import { useDisclosure, useOutsideClick, Flex, Popover, PopoverTrigger, Input, PopoverContent, Button, InputProps, } from '@chakra-ui/react' import { useState, useRef, useEffect, ChangeEvent } from 'react' import { useDebouncedCallback } from 'use-debounce' import { isEmpty } from 'utils' type Props = { selectedItem?: string items: string[] debounceTimeout?: number onValueChange?: (value: string) => void } & InputProps export const SearchableDropdown = ({ selectedItem, items, debounceTimeout = 1000, onValueChange, ...inputProps }: Props) => { const { onOpen, onClose, isOpen } = useDisclosure() const [inputValue, setInputValue] = useState(selectedItem ?? '') const debounced = useDebouncedCallback( // eslint-disable-next-line @typescript-eslint/no-empty-function onValueChange ? onValueChange : () => {}, isEmpty(process.env.NEXT_PUBLIC_E2E_TEST) ? debounceTimeout : 0 ) const [filteredItems, setFilteredItems] = useState([ ...items .filter((item) => item.toLowerCase().includes((selectedItem ?? '').toLowerCase()) ) .slice(0, 50), ]) const dropdownRef = useRef(null) const inputRef = useRef(null) useEffect( () => () => { debounced.flush() }, // eslint-disable-next-line react-hooks/exhaustive-deps [] ) useEffect(() => { if (filteredItems.length > 0) return setFilteredItems([ ...items .filter((item) => item.toLowerCase().includes((selectedItem ?? '').toLowerCase()) ) .slice(0, 50), ]) if (inputRef.current === document.activeElement) onOpen() // eslint-disable-next-line react-hooks/exhaustive-deps }, [items]) useOutsideClick({ ref: dropdownRef, handler: onClose, }) const onInputChange = (e: ChangeEvent) => { if (!isOpen) onOpen() setInputValue(e.target.value) debounced(e.target.value) if (e.target.value === '') { setFilteredItems([...items.slice(0, 50)]) return } setFilteredItems([ ...items .filter((item) => item.toLowerCase().includes((inputValue ?? '').toLowerCase()) ) .slice(0, 50), ]) } const handleItemClick = (item: string) => () => { setInputValue(item) debounced(item) onClose() } return ( {filteredItems.length > 0 && ( <> {filteredItems.map((item, idx) => { return ( ) })} )} ) }