{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "multi-select",
  "type": "registry:block",
  "title": "Searchable multiselect",
  "description": "cmdk filtering and keyboard navigation, controlled selections and accessible dismissal.",
  "dependencies": [
    "cmdk@^1.1.1"
  ],
  "registryDependencies": [
    "button",
    "dialog"
  ],
  "files": [
    {
      "path": "blocks/multi-select.tsx",
      "type": "registry:component",
      "target": "components/shine/multi-select.tsx",
      "content": "\"use client\";\nimport { useState } from \"react\";\nimport { Command } from \"cmdk\";\nimport { Button } from \"@/components/ui/button\";\nimport { Dialog, DialogContent, DialogTitle, DialogDescription, DialogTrigger } from \"@/components/ui/dialog\";\nexport function MultiSelect({label,options,value,onChange,disabled=false}:{label:string;options:{value:string;label:string;disabled?:boolean}[];value:string[];onChange:(value:string[])=>void;disabled?:boolean}) {\n const [open,setOpen]=useState(false);return <div data-product-pattern=\"multi-select\" className=\"space-y-2\"><Dialog open={open} onOpenChange={setOpen}><DialogTrigger asChild><Button variant=\"outline\" disabled={disabled}>{label}: {value.length} selected</Button></DialogTrigger><DialogContent><DialogTitle>{label}</DialogTitle><DialogDescription>Search and toggle options. Your selections apply immediately.</DialogDescription><Command><Command.Input aria-label={\"Search \"+label} className=\"h-11 w-full rounded-md border border-input bg-background px-3\"/><Command.List className=\"mt-3 max-h-72 overflow-y-auto\"><Command.Empty>No matching options.</Command.Empty>{options.map(option=><Command.Item key={option.value} value={option.value} keywords={[option.label]} disabled={disabled||option.disabled} onSelect={()=>onChange(value.includes(option.value)?value.filter(item=>item!==option.value):[...value,option.value])} className=\"flex cursor-pointer items-center gap-3 rounded-md p-3 data-[selected=true]:bg-accent data-[disabled=true]:opacity-50\"><span aria-hidden=\"true\">{value.includes(option.value)?\"✓\":\"○\"}</span>{option.label}<span className=\"sr-only\">{value.includes(option.value)?\"Selected\":\"Not selected\"}</span></Command.Item>)}</Command.List></Command><div className=\"flex justify-between gap-3\"><Button variant=\"outline\" disabled={disabled||!value.length} onClick={()=>onChange([])}>Clear selections</Button><Button onClick={()=>setOpen(false)}>Done</Button></div></DialogContent></Dialog><p role=\"status\" className=\"text-sm text-muted-foreground\">{value.map(item=>options.find(option=>option.value===item)?.label||item).join(\", \")||\"None selected\"}</p></div>;\n}\n"
    }
  ]
}
