import React, { useEffect, useMemo, useRef, useState } from "react"; import { Text } from "../Text"; import { Popover, PopoverContent, PopoverTrigger } from "../Popover"; import { Input } from "../Input"; import { cx, focusRing } from "../../lib/utils"; import { ChevronUpDownIcon } from "@heroicons/react/20/solid"; import { Checkbox } from "../Checkbox"; import { Button } from "../Button"; export const MultiSelect: React.FC<{ items: { value: string; label: string }[]; className?: string; defaultValue?: string[]; value?: string[]; placeholder?: string; footer?: boolean; onValueChange: (val: string[]) => void; container?: any; }> = ({ items, className, defaultValue, value, onValueChange, placeholder, footer, container }) => { const [open, setOpen] = useState(false); const [internalValue, setInternalValue] = useState([]); const [query, setQuery] = useState(""); const ref = useRef(); const [width, setWidth] = useState(0); useEffect(() => { if (!ref.current) return; const resizeObserver = new ResizeObserver(() => { // Do what you want to do when the size of the element changes setWidth(ref.current?.offsetWidth || 0); }); resizeObserver.observe(ref.current); return () => resizeObserver.disconnect(); // clean up }, []); let data = useMemo(() => { if (items.length === 0) return []; return items.filter((a) => { return ( a && ((a.label + "").toLowerCase().search(query.toLowerCase()) >= 0 || (a.value + "").toLowerCase().search(query.toLowerCase()) >= 0) ); }); }, [query, items]); useEffect(() => { if (value) { setInternalValue(value); return; } if (defaultValue) { setInternalValue(defaultValue); return; } setInternalValue([]); }, [defaultValue, value]); const texts = useMemo(() => { if (internalValue) { let options = items.filter((a) => internalValue.indexOf(a.value) >= 0); return options; } return []; }, [internalValue, placeholder]); return ( { setOpen(o); if (!o) { onValueChange(internalValue); } }} >
{texts.length === 0 ? ( {placeholder || "Multi select"} ) : (
{texts.map((a) => (
{a.label}
))}
)}
{ setQuery(e.target.value); e.preventDefault(); e.stopPropagation(); }} />
{data.map((item) => (
{ e.preventDefault(); e.stopPropagation(); let exists = internalValue.find((a) => a === item.value); let newValues = internalValue.filter((a) => a !== item.value); if (exists === undefined) { newValues.push(item.value); } setInternalValue(newValues); }} key={item.label} className={cx( // base "onvo-grid onvo-cursor-pointer onvo-grid-cols-[20px_1fr] onvo-gap-x-2 onvo-rounded onvo-px-3 onvo-py-2 onvo-outline-none onvo-transition-colors data-[state=checked]:onvo-font-semibold sm:onvo-text-sm", // text color "onvo-text-slate-900 dark:onvo-text-slate-50", // disabled "data-[disabled]:onvo-pointer-events-none data-[disabled]:onvo-text-slate-400 data-[disabled]:hover:onvo-bg-none dark:data-[disabled]:onvo-text-slate-600", // focus "focus-visible:onvo-bg-slate-100 focus-visible:dark:onvo-bg-slate-900", // hover "hover:onvo-bg-slate-100 hover:dark:onvo-bg-slate-900" )} > = 0} className="onvo-mt-0.5" /> {item.label}
))}
{footer && (
)}
); };