import React from "react"; import classnames from "classnames"; import {useCombobox} from "downshift"; const MAX_HEIGHT = 140; export type InputAutocompleteProps = { value?: string options?: any[] onChange?(value: string | undefined): unknown "aria-label"?: string }; export default function InputAutocomplete({ value, options = [], onChange = () => {}, "aria-label": ariaLabel, }: InputAutocompleteProps) { const [input, setInput] = React.useState(value || ""); const menuRef = React.useRef(null); const [maxHeight, setMaxHeight] = React.useState(MAX_HEIGHT); const filteredItems = React.useMemo(() => { const lv = input.toLowerCase(); return options.filter((item) => item[0].toLowerCase().includes(lv)); }, [options, input]); const calcMaxHeight = React.useCallback(() => { if (menuRef.current) { const space = window.innerHeight - menuRef.current.getBoundingClientRect().top; setMaxHeight(Math.min(space, MAX_HEIGHT)); } }, []); const { isOpen, getMenuProps, getInputProps, getItemProps, highlightedIndex, openMenu, } = useCombobox({ items: filteredItems, inputValue: input, itemToString: (item) => (item ? item[0] : ""), stateReducer: (_state, action) => { if (action.type === useCombobox.stateChangeTypes.InputClick) { return {...action.changes, isOpen: true}; } return action.changes; }, onSelectedItemChange: ({selectedItem}) => { const v = selectedItem ? selectedItem[0] : ""; setInput(v); onChange(selectedItem ? selectedItem[0] : undefined); }, onInputValueChange: ({inputValue: v}) => { if (typeof v === "string") { setInput(v); onChange(v === "" ? undefined : v); openMenu(); } }, }); React.useEffect(() => { if (isOpen) { calcMaxHeight(); } }, [isOpen, calcMaxHeight]); React.useEffect(() => { window.addEventListener("resize", calcMaxHeight); return () => window.removeEventListener("resize", calcMaxHeight); }, [calcMaxHeight]); React.useEffect(() => { setInput(value || ""); }, [value]); return (
openMenu(), })} />
{isOpen && filteredItems.map((item, index) => (
{item[1]}
))}
); }