@@ -9,8 +9,7 @@ import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp
9
9
import MuiBox from '@mui/material/Box' ;
10
10
import MuiTooltip from '@mui/material/Tooltip' ;
11
11
import { SxProps } from '@mui/system' ;
12
- import { defer } from 'lodash' ;
13
- import { useEffect , useMemo , useRef , useState } from 'react' ;
12
+ import { useMemo , useState } from 'react' ;
14
13
import {
15
14
GroupedVirtuoso ,
16
15
GroupedVirtuosoHandle ,
@@ -19,16 +18,26 @@ import {
19
18
20
19
import { text } from '../../../shared/text' ;
21
20
import { OpossumColors } from '../../shared-styles' ;
21
+ import { useVirtuosoRefs } from '../../util/use-virtuoso-refs' ;
22
22
import { LoadingMask } from '../LoadingMask/LoadingMask' ;
23
23
import { NoResults } from '../NoResults/NoResults' ;
24
24
import { GroupContainer , StyledLinearProgress } from './GroupedList.style' ;
25
25
26
+ export interface GroupedListItemContentProps {
27
+ index : number ;
28
+ selected : boolean ;
29
+ focused : boolean ;
30
+ }
31
+
26
32
export interface GroupedListProps {
27
33
className ?: string ;
28
34
grouped : Record < string , ReadonlyArray < string > > | null ;
29
35
loading ?: boolean ;
30
36
renderGroupName ?: ( key : string ) => React . ReactNode ;
31
- renderItemContent : ( datum : string , index : number ) => React . ReactNode ;
37
+ renderItemContent : (
38
+ datum : string ,
39
+ props : GroupedListItemContentProps ,
40
+ ) => React . ReactNode ;
32
41
selected ?: string ;
33
42
sx ?: SxProps ;
34
43
testId ?: string ;
@@ -45,7 +54,6 @@ export function GroupedList({
45
54
testId,
46
55
...props
47
56
} : GroupedListProps & Omit < GroupedVirtuosoProps < string , unknown > , 'selected' > ) {
48
- const ref = useRef < GroupedVirtuosoHandle > ( null ) ;
49
57
const [ { startIndex, endIndex } , setRange ] = useState < {
50
58
startIndex : number ;
51
59
endIndex : number ;
@@ -62,20 +70,19 @@ export function GroupedList({
62
70
ids : flattened ,
63
71
keys : Object . keys ( grouped ) ,
64
72
counts : Object . values ( grouped ) . map ( ( group ) => group . length ) ,
65
- selectedIndex : flattened . findIndex ( ( datum ) => datum === selected ) ,
66
73
} ;
67
- } , [ grouped , selected ] ) ;
68
-
69
- useEffect ( ( ) => {
70
- if ( groups ?. selectedIndex !== undefined && groups . selectedIndex >= 0 ) {
71
- defer ( ( ) =>
72
- ref . current ?. scrollIntoView ( {
73
- index : groups . selectedIndex ,
74
- align : 'center' ,
75
- } ) ,
76
- ) ;
77
- }
78
- } , [ groups ?. selectedIndex ] ) ;
74
+ } , [ grouped ] ) ;
75
+
76
+ const {
77
+ ref ,
78
+ scrollerRef ,
79
+ focusedIndex ,
80
+ setIsVirtuosoFocused ,
81
+ selectedIndex ,
82
+ } = useVirtuosoRefs < GroupedVirtuosoHandle > ( {
83
+ data : groups ?. ids ,
84
+ selected ,
85
+ } ) ;
79
86
80
87
return (
81
88
< LoadingMask
@@ -97,10 +104,13 @@ export function GroupedList({
97
104
return (
98
105
< GroupedVirtuoso
99
106
ref = { ref }
107
+ onFocus = { ( ) => setIsVirtuosoFocused ( true ) }
108
+ onBlur = { ( ) => setIsVirtuosoFocused ( false ) }
100
109
components = { {
101
110
EmptyPlaceholder :
102
111
loading || groups . ids . length ? undefined : ( ) => < NoResults /> ,
103
112
} }
113
+ scrollerRef = { scrollerRef }
104
114
rangeChanged = { setRange }
105
115
groupCounts = { groups ?. counts }
106
116
groupContent = { ( index ) => (
@@ -114,7 +124,13 @@ export function GroupedList({
114
124
) }
115
125
</ GroupContainer >
116
126
) }
117
- itemContent = { ( index ) => renderItemContent ( groups . ids [ index ] , index ) }
127
+ itemContent = { ( index ) =>
128
+ renderItemContent ( groups . ids [ index ] , {
129
+ index,
130
+ selected : index === selectedIndex ,
131
+ focused : index === focusedIndex ,
132
+ } )
133
+ }
118
134
{ ...props }
119
135
/>
120
136
) ;
0 commit comments