import * as React from 'react'; import { Badge } from '@/components/ui/badge'; import { Command, CommandInput, CommandItem } from '@/components/ui/command'; import { cn } from '@/utils/cn'; import { ChevronsUpDownIcon } from 'lucide-react'; import VirtualList from 'rc-virtual-list'; import { useOnClickOutside } from 'usehooks-ts'; import { Button } from './button'; import { Checkbox } from './checkbox'; import { Popover, PopoverContent, PopoverTrigger } from './popover'; type IValue = any; type IItem = Record<'value' | 'label', IValue>; interface ComboboxAdvancedProps { value: IValue[]; onChange: (value: IValue[]) => void; items: IItem[]; placeholder: string; className?: string; } export function ComboboxAdvanced({ items, value, onChange, placeholder, className, }: ComboboxAdvancedProps) { const [open, setOpen] = React.useState(false); const [inputValue, setInputValue] = React.useState(''); const ref = React.useRef(null); useOnClickOutside(ref, () => setOpen(false)); const selectables = items .filter((item) => !value.find((s) => s === item.value)) .filter( (item) => (typeof item.label === 'string' && item.label.toLowerCase().includes(inputValue.toLowerCase())) || (typeof item.value === 'string' && item.value.toLowerCase().includes(inputValue.toLowerCase())) ); const renderItem = (item: IItem) => { const checked = !!value.find((s) => s === item.value); return ( { e.preventDefault(); e.stopPropagation(); }} onSelect={() => { setInputValue(''); onChange( value.includes(item.value) ? value.filter((s) => s !== item.value) : [...value, item.value] ); }} className={'flex cursor-pointer items-center gap-2'} > {item?.label ?? item?.value} ); }; const data = React.useMemo(() => { return [ ...(inputValue === '' ? [] : [ { value: inputValue, label: `Pick '${inputValue}'`, }, ]), ...value.map((val) => { const item = items.find((item) => item.value === val); return item ? { value: val, label: item.label, } : { value: val, label: val, }; }), ...selectables, ].filter((item) => item.value); }, [inputValue, selectables, items]); return ( {renderItem} ); }