import { UseSelectState, UseSelectStateChange, UseSelectStateChangeOptions, } from "downshift"; import { useCallback } from "react"; import { SELECT_CREATE_OPTION_VALUE } from "../shared/constants"; import { SelectOption } from "../shared/types"; interface UseDownShiftConfigProps { transformedOptions: T[]; selected: S; onChange: (newSelected: S) => void; inputHasFocus: boolean; onInputChange: ((newValue: string) => void) | undefined; } export function useDownshiftConfig({ selected, onChange, transformedOptions, onInputChange, inputHasFocus, }: UseDownShiftConfigProps) { const resetSearch = useCallback(() => { if (onInputChange) { onInputChange(""); } }, [onInputChange]); return { items: transformedOptions, selectedItem: selected, circularNavigation: true, onSelectedItemChange: ({ selectedItem: changedItem, }: { selectedItem?: S; }) => { if (changedItem !== undefined) { onChange(changedItem); } resetSearch(); }, onIsOpenChange: (newState: UseSelectStateChange) => { if (!newState.isOpen) { resetSearch(); } }, stateReducer: ( state: UseSelectState, actionAndChanges: UseSelectStateChangeOptions, ) => { const { type, changes } = actionAndChanges; switch (type) { case "__menu_keydown_enter__": case "__menu_keydown_space_button__": if ( changes.selectedItem && changes.selectedItem.value === SELECT_CREATE_OPTION_VALUE ) { // Creatable option was selected. We're handling that manually // elsewhere (useSelectLayout), so just return state return state; } if (type === "__menu_keydown_space_button__" && inputHasFocus) { // Space was pressed while the search input was focused, // and we don't want it to select and close in that case return state; } return changes; default: return changes; } }, }; }