'use client'; import * as React from 'react'; import { Check, ChevronsUpDown } from 'lucide-react'; import { Button } from './button'; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from './command'; import { Popover, PopoverContent, PopoverTrigger } from './popover'; import { cn } from './utils'; export interface MultiSelectOption { value: string; label: string; depth?: number; // 트리 구조 들여쓰기용 } interface MultiSelectComboboxProps { options: MultiSelectOption[]; value: string[]; onChange: (value: string[]) => void; placeholder?: string; searchPlaceholder?: string; emptyText?: string; disabled?: boolean; className?: string; } export function MultiSelectCombobox({ options, value, onChange, placeholder = '선택하세요', searchPlaceholder = '검색...', emptyText = '결과가 없습니다.', disabled = false, className, }: MultiSelectComboboxProps) { const [open, setOpen] = React.useState(false); const handleSelect = (selectedValue: string) => { if (value.includes(selectedValue)) { onChange(value.filter((v) => v !== selectedValue)); } else { onChange([...value, selectedValue]); } }; const handleSelectAll = () => { if (value.length === options.length) { onChange([]); } else { onChange(options.map((opt) => opt.value)); } }; const getDisplayText = () => { if (value.length === 0) return placeholder; if (value.length === options.length) return '전체'; const firstItem = options.find((opt) => opt.value === value[0]); if (value.length === 1) return firstItem?.label || ''; return `${firstItem?.label} 외 ${value.length - 1}`; }; return ( { e.preventDefault(); setOpen(false); }} onInteractOutside={(e) => { e.preventDefault(); setOpen(false); }} > {emptyText} {/* 전체 선택 */} 전체 {/* 개별 옵션 */} {options.map((option) => ( handleSelect(option.value)} className="cursor-pointer" style={{ paddingLeft: option.depth ? `${(option.depth * 16) + 8}px` : undefined }} > {option.label} ))} ); }