diff --git a/packages/combobox/src/types.ts b/packages/combobox/src/types.ts index e8c544355..4501760a1 100644 --- a/packages/combobox/src/types.ts +++ b/packages/combobox/src/types.ts @@ -8,8 +8,10 @@ import { IUseFieldReturnValue } from '@zendeskgarden/container-field'; import { HTMLProps, ReactNode, RefObject } from 'react'; +export type OptionValue = string; + interface ISelectedOption { - value: string; + value: OptionValue; label?: string; disabled?: boolean; hidden?: boolean; @@ -43,7 +45,7 @@ export interface IUseComboboxProps { /** * Provides an ordered list of option groups and options * - * @param {string} option.value Unique option value + * @param {OptionValue} option.value Unique option value * @param {string} option.label Optional human-readable text (defaults to `option.value`) * @param {boolean} option.selected Sets initial selection for the option * @param {boolean} option.disabled Indicates that the option is not interactive @@ -53,7 +55,7 @@ export interface IUseComboboxProps { /** Sets the input value in a controlled combobox */ inputValue?: string; /** Sets the selection value (or `isMultiselectable` values) in a controlled combobox */ - selectionValue?: string | string[] | null; + selectionValue?: OptionValue | OptionValue[] | null; /** Determines listbox expansion in a controlled combobox */ isExpanded?: boolean; /** Determines default listbox expansion in an uncontrolled combobox */ @@ -71,14 +73,14 @@ export interface IUseComboboxProps { * * @param {string} changes.type The event type that triggered the change * @param {boolean} [changes.isExpanded] The updated listbox expansion - * @param {string|string[]} [changes.selectionValue] The updated selection value(s) + * @param {OptionValue|OptionValue[]} [changes.selectionValue] The updated selection value(s) * @param {string} [changes.inputValue] The updated input value * @param {number} [changes.activeIndex] The updated active option index */ onChange?: (changes: { type: string; isExpanded?: boolean; - selectionValue?: string | string[] | null; + selectionValue?: OptionValue | OptionValue[] | null; inputValue?: string; activeIndex?: number; }) => void; @@ -88,7 +90,7 @@ export interface IUseComboboxProps { export interface IUseComboboxReturnValue { isExpanded: boolean; - activeValue?: string; + activeValue?: OptionValue; selection: ISelectedOption | ISelectedOption[] | null; inputValue?: string; getLabelProps: IUseFieldReturnValue['getLabelProps']; @@ -124,7 +126,7 @@ export interface IUseComboboxReturnValue { } ) => HTMLProps; getMessageProps: IUseFieldReturnValue['getMessageProps']; - removeSelection: (value?: ISelectedOption | string) => void; + removeSelection: (value?: ISelectedOption | OptionValue) => void; } export interface IComboboxContainerProps @@ -142,7 +144,7 @@ export interface IComboboxContainerProps * @param {function} [options.getOptionProps] Option props getter * @param {function} [options.getMessageProps] Message props getter * @param {boolean} options.isExpanded Current listbox expansion - * @param {string} [options.activeValue] Current active option value + * @param {OptionValue} [options.activeValue] Current active option value * @param {object|object[]} options.selection Current selection * @param {string} [options.inputValue] Current input value * @param {function} [options.removeSelection] Remove the specified selection value or all values if unspecified diff --git a/packages/combobox/src/useCombobox.ts b/packages/combobox/src/useCombobox.ts index 97281ac2a..46a9e94df 100644 --- a/packages/combobox/src/useCombobox.ts +++ b/packages/combobox/src/useCombobox.ts @@ -26,7 +26,7 @@ import { UseComboboxState as IDownshiftState, UseComboboxStateChangeTypes as IDownshiftStateChangeType } from 'downshift'; -import { IOption, IUseComboboxProps, IUseComboboxReturnValue } from './types'; +import { IOption, IUseComboboxProps, IUseComboboxReturnValue, OptionValue } from './types'; import { toLabel, toType } from './utils'; export const useCombobox = < @@ -61,7 +61,7 @@ export const useCombobox = < * State */ - interface IPreviousState extends IDownshiftState { + interface IPreviousState extends IDownshiftState { type: IDownshiftStateChangeType; altKey?: boolean; } @@ -84,11 +84,11 @@ export const useCombobox = < `${prefix}--option${isDisabled ? '-disabled' : ''}${isHidden ? '-hidden' : ''}-${index}` }); const labels: Record = useMemo(() => ({}), []); - const selectedValues: string[] = useMemo(() => [], []); - const disabledValues: string[] = useMemo(() => [], []); - const hiddenValues: string[] = useMemo(() => [], []); + const selectedValues: OptionValue[] = useMemo(() => [], []); + const disabledValues: OptionValue[] = useMemo(() => [], []); + const hiddenValues: OptionValue[] = useMemo(() => [], []); const values = useMemo(() => { - const retVal: string[] = []; + const retVal: OptionValue[] = []; const setValues = (option: IOption) => { if (option.disabled || option.hidden) { if (option.disabled && !disabledValues.includes(option.value)) { @@ -175,7 +175,7 @@ export const useCombobox = < */ const handleDownshiftStateChange = useCallback< - NonNullable['onStateChange']> + NonNullable['onStateChange']> >( ({ type, isOpen, selectedItem, inputValue: _inputValue, highlightedIndex }) => onChange({ @@ -279,7 +279,7 @@ export const useCombobox = < changes.selectedItem !== null ) { if (state.selectedItem.includes(changes.selectedItem)) { - changes.selectedItem = (state.selectedItem as string[]).filter( + changes.selectedItem = (state.selectedItem as OptionValue[]).filter( value => value !== changes.selectedItem ); } else { @@ -297,7 +297,7 @@ export const useCombobox = < return changes; }; - const transformValue = (value: string | null) => (value ? toLabel(labels, value) : ''); + const transformValue = (value: OptionValue | null) => (value ? toLabel(labels, value) : ''); /** Hooks */ @@ -314,7 +314,7 @@ export const useCombobox = < openMenu, setHighlightedIndex, selectItem - } = useDownshift({ + } = useDownshift({ toggleButtonId: idRef.current.trigger, menuId: idRef.current.listbox, getItemId: idRef.current.getOptionId, @@ -357,7 +357,7 @@ export const useCombobox = < ); const setDownshiftSelection = useCallback( - (value: string | string[] | null) => { + (value: OptionValue | OptionValue[] | null) => { selectItem(value); onChange({ type: toType(useDownshift.stateChangeTypes.FunctionSelectItem), @@ -875,7 +875,7 @@ export const useCombobox = < 'aria-hidden': undefined, 'aria-selected': ariaSelected, ...optionProps - } as IDownshiftOptionProps); + } as IDownshiftOptionProps); }, [getDownshiftOptionProps, disabledValues, hiddenValues, values, _selectionValue] ); diff --git a/packages/combobox/src/utils.ts b/packages/combobox/src/utils.ts index 5267bccb0..ebfa3e870 100644 --- a/packages/combobox/src/utils.ts +++ b/packages/combobox/src/utils.ts @@ -7,6 +7,7 @@ import { KEYS } from '@zendeskgarden/container-utilities'; import { useCombobox as useDownshift } from 'downshift'; +import { OptionValue } from './types'; /** Map Downshift to Garden state change types */ const typeMap: Record = { @@ -53,7 +54,7 @@ export const toType = (downshiftType: string) => { * * @returns A label from the `labels` record based on the given value. */ -export const toLabel = (labels: Record, value?: string) => { +export const toLabel = (labels: Record, value?: OptionValue) => { if (value === undefined) { return ''; }