Multi Select
optics/multi-selectFreeComponent
A select component for allowing multiple selections.
See it running
Open the demo on optics
optics.agusmayol.com.ar/components/multi-selectInstall it
npx shadcn@latest add https://optics.agusmayol.com.ar/r/multi-select.jsonSource
1"use client";23import * as React from "react";4import { Select as SelectPrimitive } from "@base-ui/react/select";5import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";6import { Button, buttonVariants } from "@/registry/optics/button";7import { cn } from "@/registry/optics/lib/utils";8import { Badge } from "@/registry/optics/badge";9import { Checkbox } from "@/registry/optics/checkbox";1011// Contexto para compartir el estado de selección entre todos los items12const MultiSelectContext = React.createContext({13 values: {},14 setValue: () => {},15 onValuesChange: () => {},16 itemCount: 0,17 colors: {},18 registerColor: () => {},19});2021function Select({22 onValuesChange = undefined,23 onOpenChange = undefined,24 ...props25}) {26 const [values, setValues] = React.useState({});27 const [colors, setColors] = React.useState({});28 const [open, setOpen] = React.useState(false);29 const registeredItemsRef = React.useRef(new Set());3031 // Función para registrar un item32 const registerItem = React.useCallback((value) => {33 if (value && !registeredItemsRef.current.has(value)) {34 registeredItemsRef.current.add(value);35 setValues((prev) => {36 if (!(value in prev)) {37 return { ...prev, [value]: false };38 }39 return prev;40 });41 }42 }, []);4344 // Función para registrar el color de un item45 const registerColor = React.useCallback((value, color) => {46 if (value) {47 setColors((prev) => ({ ...prev, [value]: color }));48 }49 }, []);5051 // Función para actualizar un valor52 const setValue = React.useCallback(53 (value, checked) => {54 setValues((prev) => {55 const newValues = { ...prev, [value]: checked };56 // Llamar al callback con el array de valores57 if (onValuesChange) {58 const valuesArray = Object.entries(newValues).map(([key, val]) => ({59 value: key,60 checked: val,61 }));62 onValuesChange(valuesArray);63 }64 return newValues;65 });66 },67 [onValuesChange],68 );6970 const handleOpenChange = React.useCallback(71 (newOpen) => {72 setOpen(newOpen);73 if (onOpenChange) {74 onOpenChange(newOpen);75 }76 },77 [onOpenChange],78 );7980 const contextValue = React.useMemo(81 () => ({82 values,83 setValue,84 registerItem,85 itemCount: registeredItemsRef.current.size,86 colors,87 registerColor,88 }),89 [values, setValue, registerItem, colors, registerColor],90 );9192 return (93 <MultiSelectContext.Provider value={contextValue}>94 <SelectPrimitive.Root95 data-slot="select"96 open={open}97 onOpenChange={handleOpenChange}98// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from optics
All 79 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | optics | Components | Free | 5 deps | |
| Alertalert | optics | Components | Free | 4 deps | |
| Alert Dialogalert-dialog | optics | Components | Free | 4 deps | |
| Aspect Ratioaspect-ratio | optics | Components | Free | 2 deps | |
| Auto Heightauto-height | optics | Components | Free | 3 deps | |
| Avataravatar | optics | Components | Free | 3 deps | |
| Badgebadge | optics | Components | Free | 4 deps | |
| Breadcrumbbreadcrumb | optics | Components | Free | 4 deps |
