@@ -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,14 @@ 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 { ref, scrollerRef, focusedIndex, setIsFocused, selectedIndex } =
77
+ useVirtuosoRefs < GroupedVirtuosoHandle > ( {
78
+ data : groups ?. ids ,
79
+ selected,
80
+ } ) ;
79
81
80
82
return (
81
83
< LoadingMask
@@ -97,10 +99,13 @@ export function GroupedList({
97
99
return (
98
100
< GroupedVirtuoso
99
101
ref = { ref }
102
+ onFocus = { ( ) => setIsFocused ( true ) }
103
+ onBlur = { ( ) => setIsFocused ( false ) }
100
104
components = { {
101
105
EmptyPlaceholder :
102
106
loading || groups . ids . length ? undefined : ( ) => < NoResults /> ,
103
107
} }
108
+ scrollerRef = { scrollerRef }
104
109
rangeChanged = { setRange }
105
110
groupCounts = { groups ?. counts }
106
111
groupContent = { ( index ) => (
@@ -114,7 +119,13 @@ export function GroupedList({
114
119
) }
115
120
</ GroupContainer >
116
121
) }
117
- itemContent = { ( index ) => renderItemContent ( groups . ids [ index ] , index ) }
122
+ itemContent = { ( index ) =>
123
+ renderItemContent ( groups . ids [ index ] , {
124
+ index,
125
+ selected : index === selectedIndex ,
126
+ focused : index === focusedIndex ,
127
+ } )
128
+ }
118
129
{ ...props }
119
130
/>
120
131
) ;
0 commit comments