import { useMemo, useState } from 'react' import { BottomDialog, Checkbox, SearchBar, p as P } from 'web-components' import { Check, ChevronDown } from 'lucide-react' export interface MultiSelectOption { label: string value: string | number disabled?: boolean } interface MultiSelectProps { label?: string topLabel?: string options: MultiSelectOption[] value: (string | number)[] onValueChange: (v: (string | number)[]) => void placeholder?: string disabled?: boolean onSearch?: (q: string) => void error?: boolean className?: string testID?: string // Tolerated for screen compatibility (RN BottomDropdown leftovers) — ignored on web multiple?: boolean triggerComponent?: any } export function MultiSelect({ label, topLabel, options, value, onValueChange, placeholder, disabled = false, onSearch, error = false, className, testID, }: MultiSelectProps) { const [open, setOpen] = useState(false) const [query, setQuery] = useState('') const selectedSet = useMemo(() => new Set(value.map((v) => String(v))), [value]) const displayText = useMemo(() => { if (value.length === 0) return placeholder ?? label ?? 'Select...' if (value.length === 1) { const found = options.find((o) => String(o.value) === String(value[0])) return found ? found.label : (placeholder ?? label ?? 'Select...') } return `${value.length} selected` }, [value, options, placeholder, label]) const filtered = useMemo(() => { const q = query.trim().toLowerCase() if (!q) return options return options.filter((o) => o.label.toLowerCase().includes(q)) }, [options, query]) const toggle = (optionValue: string | number) => { const key = String(optionValue) if (selectedSet.has(key)) { onValueChange(value.filter((v) => String(v) !== key)) } else { onValueChange([...value, optionValue]) } } const heading = topLabel ?? label return (
{heading ? (

{heading}

) : null} setOpen(false)}>

{heading ?? placeholder ?? 'Select'}

{ setQuery(q) onSearch?.(q) }} onSearch={onSearch} className="mb-3" />
{filtered.map((option) => { const checked = selectedSet.has(String(option.value)) return (
{ if (!option.disabled) toggle(option.value) }} className={`flex flex-row items-center p-3 border-b border-gray-100 ${option.disabled ? 'opacity-50' : 'cursor-pointer hover:bg-gray-50'}`} > e.stopPropagation()}> { if (!option.disabled) toggle(option.value) }} /> {option.label} {checked ? : null}
) })} {filtered.length === 0 ? (

No options found

) : null}
) } export default MultiSelect