import type {HTMLProps, ReactNode} from 'react' import {useMemo, useState} from 'react' import {Label} from '@/components/ui/label' import {Input} from '@/components/ui/input' import {Checkbox} from '@/components/ui/checkbox' import {Controller, useFormContext, useWatch} from 'react-hook-form' import FormError from '@/components/form/formError' interface FormMultiselectProps extends HTMLProps { options: T[] filterPredicate?: (option: T, filter: string) => boolean valueExtractor: (option: T) => string labelExtractor: (option: T) => string descriptionExtractor?: (option: T) => string name: string label?: string } function FormMultiselect({ options, filterPredicate, valueExtractor, labelExtractor, descriptionExtractor, name, label, }: FormMultiselectProps) { const [filter, setFilter] = useState('') const form = useFormContext() const filteredOptions = useMemo( () => (filterPredicate ? options.filter(t => filterPredicate(t, filter)) : options), [options, filter, filterPredicate], ) const checkboxIds = (useWatch({control: form.control, name: name}) as string[]) || [] return (
{filterPredicate && ( setFilter(e.target.value)} /> )}
{filteredOptions.length === 0 ? (

{filter ? 'No options match your search' : 'No options available'}

) : ( { const output: ReactNode[] = [] for (const option of filteredOptions) { const value = valueExtractor(option) const isChecked = checkboxIds.includes(value) output.push(
field.onChange(isChecked ? checkboxIds.filter(x => x != value) : [...checkboxIds, value]) } />
{descriptionExtractor && (

{descriptionExtractor(option)}

)}
, ) } return <>{output} }} /> )}
) } export default FormMultiselect