@@ -28,7 +28,6 @@ type Props<T extends HTMLElement> = {
2828 onBackspaceKeyDown ?: React . KeyboardEventHandler < T > ;
2929 onInputChange ?: React . ChangeEventHandler < HTMLInputElement > ;
3030 getOptionElements : ( ) => HTMLElement [ ] ;
31- getOptionsInfo : SelectContextValue [ "getOptions" ] ;
3231 onFilteredEntities : (
3332 entities : SelectContextValue [ "filteredEntities" ] ,
3433 ) => void ;
@@ -49,7 +48,6 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
4948 onEscapeKeyDown,
5049 onBackspaceKeyDown,
5150 getOptionElements,
52- getOptionsInfo,
5351 onActiveDescendantChange,
5452 onListOpenChange,
5553 onFilteredEntities,
@@ -70,15 +68,11 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
7068 ref : focusVisibleRef ,
7169 } = useIsFocusVisible < T > ( ) ;
7270
73- const jumpToChar = useJumpToChar ( {
74- activeDescendantElement : activeDescendant ,
75- getListItems : getOptionElements ,
76- onActiveDescendantElementChange : onActiveDescendantChange ,
77- } ) ;
78-
7971 const ref = React . useRef < T > ( ) ;
8072 const handleRef = useForkedRefs ( ref , focusVisibleRef ) ;
8173
74+ const cachedOptionElementsRef = React . useRef < HTMLElement [ ] > ( [ ] ) ;
75+
8276 const isSelectOnly = ! searchable ;
8377
8478 const [ isFocusedVisible , setIsFocusedVisible ] = React . useState ( ( ) =>
@@ -97,12 +91,33 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
9791 ref . current ?. focus ( ) ;
9892 } , [ ] ) ;
9993
94+ const getCachedItems = ( ) => {
95+ if ( cachedOptionElementsRef . current . length === 0 ) {
96+ cachedOptionElementsRef . current = getOptionElements ( ) ;
97+ }
98+
99+ return cachedOptionElementsRef . current ;
100+ } ;
101+
102+ const jumpToChar = useJumpToChar ( {
103+ activeDescendantElement : activeDescendant ,
104+ getListItems : getOptionElements ,
105+ onActiveDescendantElementChange : onActiveDescendantChange ,
106+ } ) ;
107+
100108 useOnChange ( listOpenState , currentOpenState => {
101109 if ( disabled || readOnly ) return ;
102- if ( currentOpenState ) return ;
103110 if ( ! ( ref . current instanceof HTMLInputElement ) ) return ;
104111
112+ if ( currentOpenState ) {
113+ cachedOptionElementsRef . current = getOptionElements ( ) ;
114+
115+ return ;
116+ }
117+
105118 ref . current . value = "" ;
119+ cachedOptionElementsRef . current = [ ] ;
120+
106121 onFilteredEntities ( null ) ;
107122 } ) ;
108123
@@ -169,7 +184,8 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
169184 if (
170185 item . getAttribute ( "aria-disabled" ) === "true" ||
171186 item . hasAttribute ( "data-hidden" ) ||
172- item . getAttribute ( "aria-hidden" ) === "true"
187+ item . getAttribute ( "aria-hidden" ) === "true" ||
188+ item . hasAttribute ( "data-hidden" )
173189 ) {
174190 const newIdx =
175191 ( forward ? idx + 1 : idx - 1 + items . length ) % items . length ;
@@ -184,9 +200,20 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
184200 items : ( HTMLElement | null ) [ ] ,
185201 forward : boolean ,
186202 ) => {
187- const selectedItems = items . filter ( item =>
188- item ?. hasAttribute ( "data-selected" ) ,
189- ) ;
203+ const selectedItems = items . filter ( item => {
204+ if ( ! item ) return false ;
205+
206+ if (
207+ item . getAttribute ( "aria-disabled" ) === "true" ||
208+ item . hasAttribute ( "data-hidden" ) ||
209+ item . getAttribute ( "aria-hidden" ) === "true" ||
210+ item . hasAttribute ( "data-hidden" )
211+ ) {
212+ return false ;
213+ }
214+
215+ return item . hasAttribute ( "data-selected" ) ;
216+ } ) ;
190217
191218 return getAvailableItem (
192219 selectedItems . length > 0 ? selectedItems : items ,
@@ -365,15 +392,15 @@ export const useComboboxBase = <T extends HTMLElement>(props: Props<T>) => {
365392
366393 const query = target . value ;
367394
368- const options = getOptionsInfo ( ) ;
395+ const items = getCachedItems ( ) ;
369396
370- const entities = options
371- . filter ( option => {
372- const text = option . valueLabel . toLowerCase ( ) ;
397+ const entities = items
398+ . filter ( item => {
399+ const text = item . textContent ?. trim ( ) . toLowerCase ( ) ?? "" ;
373400
374401 return text . includes ( query . toLowerCase ( ) ) ;
375402 } )
376- . map ( option => option . value ) ;
403+ . map ( item => item . getAttribute ( "data-entity" ) ?? "" ) ;
377404
378405 onFilteredEntities ( entities ) ;
379406 onInputChange ?.( event ) ;
0 commit comments