'use client' import { ChevronsUpDown } from 'lucide-react' import * as React from 'react' import { Button } from '@/components/ui/button' import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { cn } from '@/lib/utils' export type ComboBoxOption = { value: string label: React.ReactNode keywords: string } export type ComboBoxProps = { className?: string triggerClassName?: string onSelect?: (value: string | undefined) => void options: ComboBoxOption[] placeholder?: string defaultValue?: string deselectable?: boolean disabled?: boolean children?: never emptyText?: React.ReactNode } export function ComboBox({ className, triggerClassName, onSelect, options = [], deselectable, defaultValue, disabled, emptyText = 'No results found.', placeholder = 'Select an option', }: ComboBoxProps) { const [open, setOpen] = React.useState(false) const [value, setValue] = React.useState(defaultValue) React.useEffect(() => { if (defaultValue) { setValue(defaultValue) } }, [defaultValue]) const selectedOption = value ? options.find((opt) => opt.value === value) : undefined const label = selectedOption?.label ?? placeholder const labelText = selectedOption?.keywords ?? placeholder return ( { const extendValue = `${value} ${(keywords ?? []).join(' ')}`.toLowerCase().replace(/[\s]/g, '') if (extendValue.includes(search.toLowerCase().replace(/[\s]/g, ''))) return 1 return 0 }} onValueChange={(newValue) => { const deselectableValue = newValue === value ? undefined : newValue const actualValue = deselectable ? deselectableValue : newValue setValue(actualValue) setOpen(false) onSelect?.(actualValue) }} defaultValue={defaultValue} > {emptyText} {options.map((opt) => ( { const deselectableValue = currentValue === value ? undefined : currentValue const actualValue = deselectable ? deselectableValue : currentValue setValue(actualValue) setOpen(false) onSelect?.(actualValue) }} > {opt.label} ))} ) }