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