import { useState, useRef, useEffect, type CSSProperties, type ReactNode } from 'react' type DropdownItem = { value: T label: string description?: string icon?: ReactNode } type DropdownProps = { items: DropdownItem[] value: T onChange: (value: T) => void trigger: ReactNode width?: CSSProperties['width'] maxHeight?: CSSProperties['maxHeight'] align?: 'left' | 'right' className?: string } export function Dropdown({ items, value, onChange, trigger, width = 320, maxHeight, align = 'left', className = '', }: DropdownProps) { const [open, setOpen] = useState(false) const ref = useRef(null) useEffect(() => { if (!open) return const handleClick = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false) } } const handleEsc = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) } document.addEventListener('mousedown', handleClick) document.addEventListener('keydown', handleEsc) return () => { document.removeEventListener('mousedown', handleClick) document.removeEventListener('keydown', handleEsc) } }, [open]) return (
setOpen(!open)} className="cursor-pointer"> {trigger}
{open && (
{items.map((item, i) => ( ))}
)}
) }