'use client'; import { useEffect, useRef, useState } from 'react'; import clsx from 'clsx'; import { ChevronDownIcon } from 'lucide-react'; import { IconRemove } from '../icons'; import { type Styling } from '../props'; import { cn } from '../utils'; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from './command'; import { Popover, PopoverContent, PopoverTrigger } from './popover'; interface ComboMultiProps extends Styling { id?: string; items?: Option[]; value: Option[]; onChange: (newValue: Option[]) => void; idFunc: (item: Option) => string; labelValueFunc: (item: Option) => string; labelOptionFunc: (item: Option) => string; placeholder?: string; noSearch?: boolean; } /** * Displays a combo-box component with multiple selection. */ export function ComboMulti({ id, items, value, onChange, labelValueFunc, labelOptionFunc, idFunc, placeholder, className, style, noSearch }: ComboMultiProps) { const [open, setOpen] = useState(false); const [popoverWidth, setPopoverWidth] = useState(undefined); const triggerRef = useRef(null); useEffect(() => { if (triggerRef.current) { setPopoverWidth(triggerRef.current.offsetWidth); } }, [open]); function handleAddValue(newValue: Option) { if (value.includes(newValue)) { handleRemoveValue(newValue); } else { onChange([...value, newValue]); setOpen(false); } } function handleRemoveValue(delValue: Option) { onChange(value.filter(v => v !== delValue)); setOpen(false); } function handleClear(event: React.MouseEvent) { event.stopPropagation(); onChange([]); setOpen(false); } return ( {value.length === 0 ? {placeholder} : null} {value.map(item => ( {labelValueFunc(item)} { event.stopPropagation(); handleRemoveValue(item); }} /> ))} {!!value ? ( ) : null} {!noSearch ? : null} Список пуст {items?.map(item => ( handleAddValue(item)} className={cn(value === item && 'bg-selected text-selected-foreground')} > {labelOptionFunc(item)} ))} ); }