import { useState, useEffect, forwardRef } from 'react' import { useCombobox } from 'downshift' import classnames from 'classnames' type DownshiftInputProps = { items: string[] inputValue: string label: string setValue: React.Dispatch> inputRef?: React.ForwardedRef } & React.InputHTMLAttributes const filterItemsByInputValue = ( items: DownshiftInputProps['items'], inputValue: DownshiftInputProps['inputValue'] ) => items.filter(item => item.toLowerCase().includes(inputValue.toLowerCase())) function Downshift({ items, inputValue, placeholder, label, setValue, disabled, inputRef, }: DownshiftInputProps) { const [inputItems, setInputItems] = useState(items) useEffect(() => { setInputItems(items) }, [items]) const { isOpen, getLabelProps, getMenuProps, getInputProps, getComboboxProps, getItemProps, highlightedIndex, openMenu, selectedItem, } = useCombobox({ inputValue, items: inputItems, initialSelectedItem: inputValue, onSelectedItemChange: ({ selectedItem }) => { setValue(selectedItem ?? '') }, onInputValueChange: ({ inputValue = '' }) => { setInputItems(filterItemsByInputValue(items, inputValue)) }, onStateChange: ({ type }) => { if (type === useCombobox.stateChangeTypes.FunctionOpenMenu) { setInputItems(filterItemsByInputValue(items, inputValue)) } }, }) return (
{/* eslint-disable-next-line jsx-a11y/label-has-for */} ) => { setValue(event.target.value) }, onFocus: () => { if (!isOpen) { openMenu() } }, ref: inputRef, })} className="form-control" type="text" placeholder={placeholder} disabled={disabled} />
    {inputItems.map((item, index) => (
  • {item}
  • ))}
) } const DownshiftInput = forwardRef< HTMLInputElement, Omit >((props, ref) => ) DownshiftInput.displayName = 'DownshiftInput' export default DownshiftInput