@@ -12,6 +12,7 @@ import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
1212import useDebounce from '@hooks/useDebounce' ;
1313import useKeyboardShortcut from '@hooks/useKeyboardShortcut' ;
1414import useKeyboardState from '@hooks/useKeyboardState' ;
15+ import usePrevious from '@hooks/usePrevious' ;
1516import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings' ;
1617import useScrollEnabled from '@hooks/useScrollEnabled' ;
1718import useSingleExecution from '@hooks/useSingleExecution' ;
@@ -288,7 +289,6 @@ function BaseSelectionList<TItem extends ListItem>({
288289 onFocusChange = { ( v : boolean ) => ( isTextInputFocusedRef . current = v ) }
289290 showLoadingPlaceholder = { showLoadingPlaceholder }
290291 isLoadingNewOptions = { isLoadingNewOptions }
291- setFocusedIndex = { setFocusedIndex }
292292 />
293293 ) ;
294294 } ;
@@ -392,6 +392,56 @@ function BaseSelectionList<TItem extends ListItem>({
392392 [ data . length , scrollToIndex , setFocusedIndex ] ,
393393 ) ;
394394
395+ const prevSearchValue = usePrevious ( textInputOptions ?. value ) ;
396+ const prevSelectedOptionsLength = usePrevious ( dataDetails . selectedOptions . length ) ;
397+ const prevAllOptionsLength = usePrevious ( data . length ) ;
398+
399+ useEffect ( ( ) => {
400+ const currentSearchValue = textInputOptions ?. value ;
401+ const searchChanged = prevSearchValue !== currentSearchValue ;
402+ const selectedOptionsChanged = dataDetails . selectedOptions . length !== prevSelectedOptionsLength ;
403+ // Do not change focus if:
404+ // 1. Input value is the same or
405+ // 2. Data length is 0 or
406+ // 3. shouldUpdateFocusedIndex is true => other function handles the focus
407+ if ( ( ! searchChanged && ! selectedOptionsChanged ) || data . length === 0 || shouldUpdateFocusedIndex ) {
408+ return ;
409+ }
410+
411+ const hasSearchBeenCleared = prevSearchValue && ! currentSearchValue ;
412+ if ( hasSearchBeenCleared ) {
413+ const foundSelectedItemIndex = data . findIndex ( isItemSelected ) ;
414+
415+ if ( foundSelectedItemIndex !== - 1 && ! canSelectMultiple ) {
416+ scrollToIndex ( foundSelectedItemIndex ) ;
417+ setFocusedIndex ( foundSelectedItemIndex ) ;
418+ return ;
419+ }
420+ }
421+
422+ // Remove focus (set focused index to -1) if:
423+ // 1. If the search is idle or
424+ // 2. If the user is just toggling options without changing the list content
425+ // Otherwise (e.g. when filtering/typing), focus on the first item (0)
426+ const isSearchIdle = ! prevSearchValue && ! currentSearchValue ;
427+ const newSelectedIndex = isSearchIdle || ( selectedOptionsChanged && prevAllOptionsLength === data . length ) ? - 1 : 0 ;
428+
429+ scrollToIndex ( newSelectedIndex ) ;
430+ setFocusedIndex ( newSelectedIndex ) ;
431+ } , [
432+ canSelectMultiple ,
433+ data ,
434+ dataDetails . selectedOptions . length ,
435+ isItemSelected ,
436+ prevAllOptionsLength ,
437+ prevSelectedOptionsLength ,
438+ prevSearchValue ,
439+ scrollToIndex ,
440+ setFocusedIndex ,
441+ shouldUpdateFocusedIndex ,
442+ textInputOptions ?. value ,
443+ ] ) ;
444+
395445 useEffect ( ( ) => {
396446 if ( ! itemFocusTimeoutRef . current ) {
397447 return ;
0 commit comments