import * as React from "react" import { cn } from "lib/utils" import { Check, ChevronsUpDown, X } from "lucide-react" import { Badge } from "@/registry/default/ui/badge" import { Button } from "@/registry/default/ui/button" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, } from "@/registry/default/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/registry/default/ui/popover" export type OptionType = Record<"value" | "label", string> interface MultiSelectProps { options: Record<"value" | "label", string>[] selected: Record<"value" | "label", string>[] onChange: React.Dispatch< React.SetStateAction[]> > className?: string placeholder?: string } const MultiSelect = React.forwardRef( ({ options, selected, onChange, className, ...props }, ref) => { const [open, setOpen] = React.useState(false) const handleUnselect = (item: Record<"value" | "label", string>) => { onChange(selected.filter((i) => i.value !== item.value)) } // on delete key press, remove last selected item React.useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Backspace" && selected.length > 0) { onChange(selected.filter((_, index) => index !== selected.length - 1)) } // close on escape if (e.key === "Escape") { setOpen(false) } } document.addEventListener("keydown", handleKeyDown) return () => { document.removeEventListener("keydown", handleKeyDown) } }, [onChange, selected]) return ( ))} {selected.length === 0 && ( {props.placeholder ?? "Select ..."} )} No item found. {options.map((option) => ( { onChange( selected.some((item) => item.value === option.value) ? selected.filter((item) => item.value !== option.value) : [...selected, option] ) setOpen(true) }} > item.value === option.value) ? "opacity-100" : "opacity-0" )} /> {option.label} ))} ) } ) MultiSelect.displayName = "MultiSelect" export { MultiSelect }