'use client'; import { useState, useRef, useEffect, ReactNode } from 'react'; export interface SelectOption { value: string; label: string; sublabel?: string; } interface SelectDropdownProps { value: string; onChange: (value: string) => void; options: SelectOption[]; placeholder?: string; icon?: ReactNode; required?: boolean; id?: string; } export default function SelectDropdown({ value, onChange, options, placeholder = 'Select...', icon, required, id, }: SelectDropdownProps) { const [open, setOpen] = useState(false); const [filter, setFilter] = useState(''); const ref = useRef(null); const inputRef = useRef(null); useEffect(() => { const handleClick = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false); setFilter(''); } }; document.addEventListener('mousedown', handleClick); return () => document.removeEventListener('mousedown', handleClick); }, []); const selectedOption = options.find((o) => o.value === value); const filtered = options.filter( (o) => o.label.toLowerCase().includes(filter.toLowerCase()) || o.value.toLowerCase().includes(filter.toLowerCase()) || o.sublabel?.toLowerCase().includes(filter.toLowerCase()) ); const handleSelect = (opt: SelectOption) => { onChange(opt.value); setOpen(false); setFilter(''); }; return (
{ setOpen(true); setTimeout(() => inputRef.current?.focus(), 0); }} > {icon && {icon}} {open ? ( setFilter(e.target.value)} placeholder={placeholder} className="flex-1 bg-transparent outline-none text-sm text-[var(--text-primary)]" /> ) : ( {selectedOption ? selectedOption.label : placeholder} )}
{open && (
{filtered.length === 0 ? (
No results
) : ( filtered.map((opt) => (
handleSelect(opt)} className={`px-4 py-2 cursor-pointer transition-colors hover:bg-[var(--accent-primary-light)] ${ opt.value === value ? 'bg-[var(--accent-primary-light)]' : '' }`} >
{opt.label}
{opt.sublabel &&
{opt.sublabel}
}
)) )}
)} {required && !value && ( {}} /> )}
); }