diff --git a/packages/react/src/components/form/Combobox/Combobox.stories.tsx b/packages/react/src/components/form/Combobox/Combobox.stories.tsx index ca52a22c6c..8269f0bef4 100644 --- a/packages/react/src/components/form/Combobox/Combobox.stories.tsx +++ b/packages/react/src/components/form/Combobox/Combobox.stories.tsx @@ -673,3 +673,24 @@ export const RemoveAllOptions: StoryFn = (args) => { ); }; + +export const WithNumberValues: StoryFn = () => { + return ( + + + some value + + + some other value + + + ); +}; diff --git a/packages/react/src/components/form/Combobox/Combobox.tsx b/packages/react/src/components/form/Combobox/Combobox.tsx index e4e90a7683..5111dbccd7 100644 --- a/packages/react/src/components/form/Combobox/Combobox.tsx +++ b/packages/react/src/components/form/Combobox/Combobox.tsx @@ -14,7 +14,7 @@ import { Spinner } from '../../Spinner'; import { getSize } from '../../../utilities/getSize'; import type { Option } from './useCombobox'; -import useCombobox from './useCombobox'; +import useCombobox, { prefix, removePrefix } from './useCombobox'; import ComboboxInput from './internal/ComboboxInput'; import ComboboxLabel from './internal/ComboboxLabel'; import ComboboxError from './internal/ComboboxError'; @@ -209,7 +209,7 @@ export const ComboboxComponent = forwardRef( // if value is set, set input value to the label of the value useEffect(() => { if (value && value.length > 0 && !multiple) { - const option = options[value[0]]; + const option = options[prefix(value[0])]; setInputValue(option?.label || ''); } }, [multiple, value, options]); @@ -217,7 +217,7 @@ export const ComboboxComponent = forwardRef( useEffect(() => { if (value && Object.keys(options).length >= 0) { const updatedSelectedOptions = value.map((option) => { - const value = options[option]; + const value = options[prefix(option)]; return value; }); @@ -225,7 +225,7 @@ export const ComboboxComponent = forwardRef( updatedSelectedOptions.reduce<{ [key: string]: Option; }>((acc, value) => { - acc[value.value] = value; + acc[prefix(value.value)] = value; return acc; }, {}), ); @@ -250,19 +250,21 @@ export const ComboboxComponent = forwardRef( if (remove) { const newSelectedOptions = { ...selectedOptions }; - delete newSelectedOptions[option.value]; + delete newSelectedOptions[prefix(option.value)]; setSelectedOptions(newSelectedOptions); - onValueChange?.(Object.keys(newSelectedOptions)); + onValueChange?.( + Object.keys(newSelectedOptions).map((key) => removePrefix(key)), + ); return; } const newSelectedOptions = { ...selectedOptions }; if (multiple) { - if (newSelectedOptions[option.value]) { - delete newSelectedOptions[option.value]; + if (newSelectedOptions[prefix(option.value)]) { + delete newSelectedOptions[prefix(option.value)]; } else { - newSelectedOptions[option.value] = option; + newSelectedOptions[prefix(option.value)] = option; } setInputValue(''); inputRef.current?.focus(); @@ -271,7 +273,7 @@ export const ComboboxComponent = forwardRef( Object.keys(newSelectedOptions).forEach((key) => { delete newSelectedOptions[key]; }); - newSelectedOptions[option.value] = option; + newSelectedOptions[prefix(option.value)] = option; setInputValue(option?.label || ''); // move cursor to the end of the input setTimeout(() => { @@ -283,7 +285,9 @@ export const ComboboxComponent = forwardRef( } setSelectedOptions(newSelectedOptions); - onValueChange?.(Object.keys(newSelectedOptions)); + onValueChange?.( + Object.keys(newSelectedOptions).map((key) => removePrefix(key)), + ); !multiple && setOpen(false); refs.domReference.current?.focus(); @@ -313,7 +317,7 @@ export const ComboboxComponent = forwardRef( measureElement: (elem) => { return elem.getBoundingClientRect().height; }, - overscan: 1, + overscan: 7, }); return ( @@ -342,7 +346,7 @@ export const ComboboxComponent = forwardRef( onOptionClick: (value: string) => { if (readOnly) return; if (disabled) return; - const option = options[value]; + const option = options[prefix(value)]; debouncedHandleSelectOption({ option: option }); }, handleSelectOption: debouncedHandleSelectOption, diff --git a/packages/react/src/components/form/Combobox/Option/useComboboxOption.tsx b/packages/react/src/components/form/Combobox/Option/useComboboxOption.tsx index 27fa8d380d..b5de5ec623 100644 --- a/packages/react/src/components/form/Combobox/Option/useComboboxOption.tsx +++ b/packages/react/src/components/form/Combobox/Option/useComboboxOption.tsx @@ -4,6 +4,7 @@ import { useMergeRefs } from '@floating-ui/react'; import { ComboboxContext } from '../ComboboxContext'; import useDebounce from '../../../../utilities/useDebounce'; import { useComboboxId, useComboboxIdDispatch } from '../ComboboxIdContext'; +import { prefix } from '../useCombobox'; type UseComboboxOptionProps = { id?: string; @@ -34,7 +35,7 @@ export default function useComboboxOption({ } = context; const index = useMemo( - () => filteredOptions.indexOf(value) + customIds.length, + () => filteredOptions.indexOf(prefix(String(value))) + customIds.length, [customIds.length, filteredOptions, value], ); @@ -49,7 +50,7 @@ export default function useComboboxOption({ throw new Error('Internal error: ComboboxOption did not find index'); } - const selected = selectedOptions[value]; + const selected = selectedOptions[prefix(value)]; const active = activeIndex === index; useEffect(() => { diff --git a/packages/react/src/components/form/Combobox/internal/ComboboxInput.tsx b/packages/react/src/components/form/Combobox/internal/ComboboxInput.tsx index ca12684c8d..21df5d7845 100644 --- a/packages/react/src/components/form/Combobox/internal/ComboboxInput.tsx +++ b/packages/react/src/components/form/Combobox/internal/ComboboxInput.tsx @@ -9,6 +9,7 @@ import { Box } from '../../../Box'; import { omit } from '../../../../utilities'; import { useComboboxIdDispatch } from '../ComboboxIdContext'; import type { ComboboxProps } from '../Combobox'; +import { prefix } from '../useCombobox'; import ComboboxChips from './ComboboxChips'; import ComboboxClearButton from './ComboboxClearButton'; @@ -68,9 +69,9 @@ export const ComboboxInput = ({ setActiveIndex(0); // check if input value is the same as a label, if so, select it - const option = options[value.toLowerCase()]; + const option = options[prefix(value.toLowerCase())]; if (!option) return; - if (selectedOptions[option.value]) return; + if (selectedOptions[prefix(option.value)]) return; handleSelectOption({ option: option }); }; diff --git a/packages/react/src/components/form/Combobox/internal/ComboboxNative.tsx b/packages/react/src/components/form/Combobox/internal/ComboboxNative.tsx index 621e6b7760..79ffe909bd 100644 --- a/packages/react/src/components/form/Combobox/internal/ComboboxNative.tsx +++ b/packages/react/src/components/form/Combobox/internal/ComboboxNative.tsx @@ -1,5 +1,6 @@ import type { Option } from '../useCombobox'; import type { ComboboxProps } from '../Combobox'; +import { removePrefix } from '../useCombobox'; type ComboboxNativeProps = { selectedOptions: { @@ -14,19 +15,17 @@ export const ComboboxNative = ({ multiple, name, }: ComboboxNativeProps) => { + const VALUE = Object.keys(selectedOptions).map((key) => removePrefix(key)); + return (