Untitled
unknown
plain_text
7 months ago
3.7 kB
8
Indexable
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 "@/utilities/cn";
import { useState } from "react";
import { Check, ChevronsUpDown, X } from "lucide-react";
import { UseFieldArrayAppend, UseFieldArrayRemove } from "react-hook-form";
type Props = {
data: { value: string; label: string; id: string }[];
name: string;
notFoundMessage?: string;
inDialog?: boolean;
onAppend: UseFieldArrayAppend<any>;
onRemove: UseFieldArrayRemove;
};
export function MultiSelectCombobox({
data,
name,
notFoundMessage,
inDialog,
onAppend,
onRemove,
}: Props) {
const [open, setOpen] = useState(false);
const [selectedItemsIds, setSelectedItemsIds] = useState<string[]>([]);
const handleSetValue = (id: string) => {
const existingIndex = selectedItemsIds.findIndex((item) => item === id);
if (existingIndex > -1) {
onRemove(existingIndex);
setSelectedItemsIds((prev) => prev.filter((item) => item !== id));
} else {
const item = data.find((item) => item.id === id)!;
onAppend({
title: item.value,
id: item.id,
});
setSelectedItemsIds((prev) => [...prev, id]);
}
};
return (
<Popover modal={true} open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="h-fit w-full justify-between"
>
<div className="flex flex-wrap justify-start gap-2">
{selectedItemsIds?.length
? selectedItemsIds.map((id, i) => (
<div
key={i}
className=" flex h-auto items-center gap-x-2 rounded-md bg-foreground px-2 py-1 text-xs font-medium text-background"
>
{data.find((item) => item.id === id)?.label}
<X
size={13}
className="hover:text-destructive"
onClick={() => handleSetValue(id)}
/>
</div>
))
: `Select one or more ${name}...`}
</div>
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className={`combobox-width p-0 ${inDialog && "z-[200]"}`}>
<Command>
<CommandInput placeholder={`Search ${name}...`} className="h-9" />
<CommandEmpty>
{notFoundMessage ? notFoundMessage : `No ${name} found.`}
</CommandEmpty>
<CommandGroup>
<CommandList>
{data.map((item) => (
<CommandItem
isMultiSelect={true}
key={item.id}
value={item.id}
onSelect={() => {
handleSetValue(item.id);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
selectedItemsIds.includes(item.id)
? "opacity-100"
: "opacity-0",
)}
/>
{item.label}
</CommandItem>
))}
</CommandList>
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
);
}
Editor is loading...
Leave a Comment