import React, { useState, useRef, useEffect } from 'react'; interface DropdownProps { options: { value: string; label: string }[]; value: string | string[]; onChange: (e: { target: { name: string; value: string | string[] } }) => void; name?: string; multiple?: boolean; } const Dropdown: React.FC = ({ options, value, onChange, name, multiple = false, ...rest }) => { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); const handleOptionClick = (optionValue: string) => { let newValue: string | string[]; if (multiple) { const currentValues = Array.isArray(value) ? value : []; if (currentValues.includes(optionValue)) { newValue = currentValues.filter((v) => v !== optionValue); } else { newValue = [...currentValues, optionValue]; } } else { newValue = optionValue; setIsOpen(false); } const syntheticEvent = { target: { name: name || '', value: newValue, }, }; onChange(syntheticEvent as any); }; const selectedOptionLabel = (() => { if (multiple) { if (Array.isArray(value) && value.length > 0) { if (value.length === 1) { return options.find((o) => o.value === value[0])?.label || ''; } return `${value.length} selected`; } return 'Select...'; } return options.find((option) => option.value === value)?.label || 'Select...'; })(); const isSelected = (optionValue: string) => { if (multiple && Array.isArray(value)) { return value.includes(optionValue); } return optionValue === value; }; return (
{isOpen && (
    {options.map((option) => (
  • handleOptionClick(option.value)} className={`h-10 px-3 text-white cursor-pointer transition-all duration-150 ease-in-out flex items-center ${ isSelected(option.value) ? 'bg-cyan-500/20 text-cyan-300' : 'hover:bg-white/20 hover:text-white hover:shadow-lg' }`} role="option" aria-selected={isSelected(option.value)} > {option.label}
  • ))}
)} {/* Hidden input to mimic native select behavior for forms */} {name && !multiple && }
); }; export default Dropdown;