{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion-multiselect",
  "type": "registry:component",
  "title": "Accordion Multiselect",
  "description": "An accordion multiselect component with categories and services.",
  "dependencies": ["@radix-ui/react-accordion", "@radix-ui/react-checkbox", "lucide-react"],
  "files": [
    {
      "path": "registry/abui/ui/accordion-multiselect.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\"\nimport { Check, ChevronDown } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\n\n// --- Architecture: Primitives (Unstyled but behaving) ---\n// We are using Radix UI Accordion and Checkbox primitives directly.\n// This component acts as a \"Component\" layer in the architecture:\n// - Wraps primitives with styling\n// - Supports controlled/uncontrolled usage\n// - Uses data-attributes for state and slots for targeting\n\n// --- Context ---\n// We use a context to share selection state between the root and items/checkboxes\n// This allows for the Compound Component pattern.\ninterface AccordionMultiselectContextValue {\n  selectedValues: string[]\n  onSelectionChange: (value: string, checked: boolean) => void\n}\n\nconst AccordionMultiselectContext = React.createContext<AccordionMultiselectContextValue | null>(null)\n\nfunction useAccordionMultiselect() {\n  const context = React.useContext(AccordionMultiselectContext)\n  if (!context) {\n    throw new Error(\"AccordionMultiselect subcomponents must be used within AccordionMultiselect\")\n  }\n  return context\n}\n\n// --- Components ---\n\n// We can't directly extend AccordionPrimitive.Root because it has specific props that might conflict or be typed in a way TS doesn't like for intersection\n// Instead, we'll define our props and intersect with the primitive's props, excluding what we override/don't need if necessary\ntype AccordionRootProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root>\n\ninterface AccordionMultiselectProps\n  extends Omit<AccordionRootProps, \"type\" | \"value\" | \"defaultValue\" | \"onValueChange\"> {\n  value?: string[]\n  onValueChange?: (value: string[]) => void\n  defaultValue?: string[]\n}\n\nfunction AccordionMultiselect({\n  value: controlledValue,\n  onValueChange,\n  defaultValue = [],\n  className,\n  children,\n  ...props\n}: AccordionMultiselectProps) {\n  // Controlled/Uncontrolled pattern\n  const [internalValue, setInternalValue] = React.useState<string[]>(defaultValue)\n  const isControlled = controlledValue !== undefined\n  const selectedValues = isControlled ? controlledValue : internalValue\n\n  const handleSelectionChange = React.useCallback(\n    (value: string, checked: boolean) => {\n      let newValues: string[]\n      if (checked) {\n        newValues = [...selectedValues, value]\n      } else {\n        newValues = selectedValues.filter(id => id !== value)\n      }\n\n      if (!isControlled) {\n        setInternalValue(newValues)\n      }\n      onValueChange?.(newValues)\n    },\n    [selectedValues, isControlled, onValueChange],\n  )\n\n  return (\n    <AccordionMultiselectContext.Provider value={{ selectedValues, onSelectionChange: handleSelectionChange }}>\n      <AccordionPrimitive.Root\n        type=\"multiple\"\n        data-slot=\"accordion-multiselect-root\"\n        className={cn(\"w-full space-y-4\", className)}\n        {...props}\n      >\n        {children}\n      </AccordionPrimitive.Root>\n    </AccordionMultiselectContext.Provider>\n  )\n}\n\nfunction AccordionMultiselectItem({\n  className,\n  ...props\n}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>) {\n  return (\n    <AccordionPrimitive.Item\n      data-slot=\"accordion-multiselect-item\"\n      className={cn(\"border-b-0\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction AccordionMultiselectTrigger({\n  className,\n  children,\n  ...props\n}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>) {\n  return (\n    <AccordionPrimitive.Header className=\"flex\">\n      <AccordionPrimitive.Trigger\n        data-slot=\"accordion-multiselect-trigger\"\n        className={cn(\n          \"flex flex-1 items-center justify-between py-2 font-semibold text-base transition-all hover:no-underline [&[data-state=open]>svg]:rotate-180 cursor-pointer\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n        <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200 text-muted-foreground\" />\n      </AccordionPrimitive.Trigger>\n    </AccordionPrimitive.Header>\n  )\n}\n\nfunction AccordionMultiselectContent({\n  className,\n  children,\n  ...props\n}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>) {\n  return (\n    <AccordionPrimitive.Content\n      data-slot=\"accordion-multiselect-content\"\n      className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n      {...props}\n    >\n      <div className={cn(\"pt-2 pb-4 flex flex-col gap-2\", className)}>{children}</div>\n    </AccordionPrimitive.Content>\n  )\n}\n\n// --- Sub-components for Item Options ---\n\ninterface AccordionMultiselectOptionProps extends React.HTMLAttributes<HTMLDivElement> {\n  value: string\n  showCheckbox?: boolean\n  children: React.ReactNode\n}\n\nfunction AccordionMultiselectOption({\n  value,\n  showCheckbox = false,\n  className,\n  onClick,\n  children,\n  ...props\n}: AccordionMultiselectOptionProps) {\n  const { selectedValues, onSelectionChange } = useAccordionMultiselect()\n  const isSelected = selectedValues.includes(value)\n\n  const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n    onSelectionChange(value, !isSelected)\n    onClick?.(e)\n  }\n\n  return (\n    <div\n      data-slot=\"accordion-multiselect-option\"\n      data-state={isSelected ? \"checked\" : \"unchecked\"}\n      className={cn(\n        \"flex items-start space-x-3 rounded-md group cursor-pointer transition-all border border-transparent\",\n        \"hover:border-foreground/10 data-[state=checked]:bg-foreground/6\",\n        className,\n      )}\n      onClick={handleClick}\n      {...props}\n    >\n      {showCheckbox && (\n        <div className=\"flex items-center h-5 mt-1\">\n          <CheckboxPrimitive.Root\n            id={value}\n            checked={isSelected}\n            onCheckedChange={checked => onSelectionChange(value, checked as boolean)}\n            onClick={e => e.stopPropagation()}\n            className={cn(\n              \"peer h-4 w-4 shrink-0 rounded-[3px] border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n            )}\n          >\n            <CheckboxPrimitive.Indicator className={cn(\"flex items-center justify-center text-current\")}>\n              <Check className=\"h-4 w-4\" />\n            </CheckboxPrimitive.Indicator>\n          </CheckboxPrimitive.Root>\n        </div>\n      )}\n      <div className=\"flex-1\">{children}</div>\n    </div>\n  )\n}\n\nexport {\n  AccordionMultiselect,\n  AccordionMultiselectItem,\n  AccordionMultiselectTrigger,\n  AccordionMultiselectContent,\n  AccordionMultiselectOption,\n}\n",
      "type": "registry:component"
    }
  ]
}
