import { useState } from 'react'; import { Check, Plus } from 'lucide-react'; import { cn } from '../../lib/cn'; export interface MultiSelectOption { value: string; label: string; } export interface MultiSelectProps { label?: string; options?: Array; /** Controlled selected values. */ value?: string[]; defaultValue?: string[]; onChange?: (next: string[]) => void; className?: string; /** Render chips as read-only (no toggling) and show `hint` instead of being editable. */ disabled?: boolean; /** Small muted helper line — used for the disabled-state explanation. */ hint?: string; } /** Chip-based multiselect. Click options to toggle; selected render as filled chips. */ export function MultiSelect({ label, options = [], value, defaultValue = [], onChange, className, disabled = false, hint, }: MultiSelectProps) { const controlled = value !== undefined; const [internal, setInternal] = useState(defaultValue); const selected = controlled ? value : internal; const set = (next: string[]) => { if (!controlled) setInternal(next); onChange?.(next); }; const toggle = (v: string) => set(selected.includes(v) ? selected.filter((x) => x !== v) : [...selected, v]); return (
{label && {label}} {disabled ? ( // Read-only: chips don't toggle and a hint explains why (no product yet, // or the plan offers no riders). Muted so it reads as inactive.
{options.length > 0 && (
{options.map((o) => { const val = typeof o === 'string' ? o : o.value; const lab = typeof o === 'string' ? o : o.label; const on = selected.includes(val); return ( {on ? : } {lab} ); })}
)} {hint && {hint}}
) : (
{options.map((o) => { const val = typeof o === 'string' ? o : o.value; const lab = typeof o === 'string' ? o : o.label; const on = selected.includes(val); return ( ); })}
)}
); }