import * as React from 'react'; import { Input } from './Input'; import { cn } from '~/utils'; export type InputWithDropdownProps = React.InputHTMLAttributes & { options: string[]; onSelect?: (value: string) => void; }; const InputWithDropdown = React.forwardRef( ({ className, options, onSelect, ...props }, ref) => { const [isOpen, setIsOpen] = React.useState(false); const [inputValue, setInputValue] = React.useState((props.value as string) || ''); const [highlightedIndex, setHighlightedIndex] = React.useState(-1); const inputRef = React.useRef(null); const handleSelect = (value: string) => { setInputValue(value); setIsOpen(false); setHighlightedIndex(-1); if (onSelect) { onSelect(value); } if (props.onChange) { props.onChange({ target: { value } } as React.ChangeEvent); } }; const handleInputChange = (e: React.ChangeEvent) => { setInputValue(e.target.value); if (props.onChange) { props.onChange(e); } }; const handleKeyDown = (e: React.KeyboardEvent) => { switch (e.key) { case 'ArrowDown': e.preventDefault(); if (!isOpen) { setIsOpen(true); } else { setHighlightedIndex((prevIndex) => prevIndex < options.length - 1 ? prevIndex + 1 : prevIndex, ); } break; case 'ArrowUp': e.preventDefault(); setHighlightedIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : 0)); break; case 'Enter': e.preventDefault(); if (isOpen && highlightedIndex !== -1) { handleSelect(options[highlightedIndex]); } setIsOpen(false); break; case 'Escape': setIsOpen(false); setHighlightedIndex(-1); break; } }; React.useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (inputRef.current && !inputRef.current.contains(event.target as Node)) { setIsOpen(false); setHighlightedIndex(-1); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); return (
{isOpen && ( )}
); }, ); InputWithDropdown.displayName = 'InputWithDropdown'; export default InputWithDropdown;