import { useCallback, useState } from 'react' import type { OptionWithDescription } from './select.js' import { useSelectNavigation } from './use-select-navigation.js' export type UseSelectStateProps = { /** * Number of items to display. * * @default 5 */ visibleOptionCount?: number /** * Options. */ options: OptionWithDescription[] /** * Initially selected option's value. */ defaultValue?: T /** * Callback for selecting an option. */ onChange?: (value: T) => void /** * Callback for canceling the select. */ onCancel?: () => void /** * Callback for focusing an option. */ onFocus?: (value: T) => void /** * Value to focus */ focusValue?: T } export type SelectState = { /** * Value of the currently focused option. */ focusedValue: T | undefined /** * 1-based index of the focused option in the full list. * Returns 0 if no option is focused. */ focusedIndex: number /** * Index of the first visible option. */ visibleFromIndex: number /** * Index of the last visible option. */ visibleToIndex: number /** * Value of the selected option. */ value: T | undefined /** * All options. */ options: OptionWithDescription[] /** * Visible options. */ visibleOptions: Array & { index: number }> /** * Whether the focused option is an input type. */ isInInput: boolean /** * Focus next option and scroll the list down, if needed. */ focusNextOption: () => void /** * Focus previous option and scroll the list up, if needed. */ focusPreviousOption: () => void /** * Focus next page and scroll the list down by a page. */ focusNextPage: () => void /** * Focus previous page and scroll the list up by a page. */ focusPreviousPage: () => void /** * Focus a specific option by value. */ focusOption: (value: T | undefined) => void /** * Select currently focused option. */ selectFocusedOption: () => void /** * Callback for selecting an option. */ onChange?: (value: T) => void /** * Callback for canceling the select. */ onCancel?: () => void } export function useSelectState({ visibleOptionCount = 5, options, defaultValue, onChange, onCancel, onFocus, focusValue, }: UseSelectStateProps): SelectState { const [value, setValue] = useState(defaultValue) const navigation = useSelectNavigation({ visibleOptionCount, options, initialFocusValue: undefined, onFocus, focusValue, }) const selectFocusedOption = useCallback(() => { setValue(navigation.focusedValue) }, [navigation.focusedValue]) return { ...navigation, value, selectFocusedOption, onChange, onCancel, } }