import React from 'react'; import * as Ariakit from '@ariakit/react'; import type { OptionWithIcon } from '~/common'; import { cn } from '~/utils'; type ComboboxProps = { label?: string; placeholder?: string; options: OptionWithIcon[] | string[]; className?: string; labelClassName?: string; value: string; onChange: (value: string) => void; onBlur: () => void; }; export const InputCombobox: React.FC = ({ label, labelClassName, placeholder = 'Select an option', options, className, value, onChange, onBlur, }) => { const isOptionObject = (option: unknown): option is OptionWithIcon => { return option != null && typeof option === 'object' && 'value' in option; }; const [isOpen, setIsOpen] = React.useState(false); const [inputValue, setInputValue] = React.useState(value); const [isKeyboardFocus, setIsKeyboardFocus] = React.useState(false); React.useEffect(() => { setInputValue(value); }, [value]); const handleChange = (newValue: string) => { setInputValue(newValue); onChange(newValue); }; return ( {label != null && ( {label} )}
handleChange(event.target.value)} onBlur={() => { setIsKeyboardFocus(false); onBlur(); }} onFocusVisible={() => { setIsKeyboardFocus(true); setIsOpen(true); }} onMouseDown={() => { setIsKeyboardFocus(false); }} />
setIsOpen(false)} className={cn( 'z-50 max-h-60 w-full overflow-auto rounded-md bg-surface-primary p-1 shadow-lg', 'animate-in fade-in-0 zoom-in-95', )} > {options.map((option: string | OptionWithIcon, index: number) => ( {isOptionObject(option) && option.icon != null && ( {option.icon} )} {isOptionObject(option) ? option.label : option} ))}
); };