{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "collapsible",
  "title": "Collapsible",
  "author": "AlgorizeTech",
  "description": "A minimal show/hide disclosure with controlled and uncontrolled modes. Use it for a single expandable region where a full accordion is overkill.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/custom/blocks/CollapsibleBlock.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport React, { createContext, forwardRef, useContext, useState } from \"react\";\n\n// ==========================================\n// 1. CONTEXT\n// ==========================================\ninterface CollapsibleContextType {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  disabled?: boolean;\n}\n\nconst CollapsibleContext = createContext<CollapsibleContextType | undefined>(\n  undefined,\n);\n\nfunction useCollapsible() {\n  const context = useContext(CollapsibleContext);\n  if (!context)\n    throw new Error(\n      \"Collapsible components must be used within a <Collapsible> root.\",\n    );\n  return context;\n}\n\n// ==========================================\n// 2. ROOT COMPONENT\n// ==========================================\nexport interface CollapsibleProps extends React.HTMLAttributes<HTMLDivElement> {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  disabled?: boolean;\n}\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(\n  (\n    {\n      className,\n      open: controlledOpen,\n      defaultOpen = false,\n      onOpenChange,\n      disabled = false,\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    const isControlled = controlledOpen !== undefined;\n    const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n    const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n    const handleOpenChange = (newOpen: boolean) => {\n      if (disabled) return;\n      if (!isControlled) setUncontrolledOpen(newOpen);\n      onOpenChange?.(newOpen);\n    };\n\n    return (\n      <CollapsibleContext.Provider\n        value={{ open: isOpen, onOpenChange: handleOpenChange, disabled }}\n      >\n        <div\n          ref={ref}\n          data-state={isOpen ? \"open\" : \"closed\"}\n          data-disabled={disabled ? \"\" : undefined}\n          className={className}\n          {...props}\n        >\n          {children}\n        </div>\n      </CollapsibleContext.Provider>\n    );\n  },\n);\nCollapsible.displayName = \"Collapsible\";\n\n// ==========================================\n// 3. TRIGGER\n// ==========================================\nexport type CollapsibleTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>\n\nexport const CollapsibleTrigger = forwardRef<\n  HTMLButtonElement,\n  CollapsibleTriggerProps\n>(({ className, onClick, children, ...props }, ref) => {\n  const { open, onOpenChange, disabled } = useCollapsible();\n\n  return (\n    <button\n      ref={ref}\n      type=\"button\"\n      disabled={disabled}\n      aria-expanded={open}\n      data-state={open ? \"open\" : \"closed\"}\n      data-disabled={disabled ? \"\" : undefined}\n      onClick={(e) => {\n        onOpenChange(!open);\n        onClick?.(e);\n      }}\n      className={cn(\n        \"flex items-center justify-between outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </button>\n  );\n});\nCollapsibleTrigger.displayName = \"CollapsibleTrigger\";\n\n// ==========================================\n// 4. CONTENT (Animated CSS Grid Engine)\n// ==========================================\nexport type CollapsibleContentProps = React.HTMLAttributes<HTMLDivElement>\n\nexport const CollapsibleContent = forwardRef<\n  HTMLDivElement,\n  CollapsibleContentProps\n>(({ className, children, ...props }, ref) => {\n  const { open } = useCollapsible();\n\n  return (\n    <div\n      ref={ref}\n      data-state={open ? \"open\" : \"closed\"}\n      aria-hidden={!open}\n      className={cn(\n        \"grid transition-all duration-200 ease-in-out\",\n        // The CSS Grid 0fr to 1fr trick handles smooth dynamic height animation natively!\n        open ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n        className,\n      )}\n      {...props}\n    >\n      {/* We need an inner wrapper with overflow-hidden for the grid trick to work perfectly */}\n      <div className=\"overflow-hidden\">{children}</div>\n    </div>\n  );\n});\nCollapsibleContent.displayName = \"CollapsibleContent\";\n",
      "type": "registry:component",
      "target": "components/custom/blocks/CollapsibleBlock.tsx"
    }
  ],
  "docs": "Named exports: Collapsible, CollapsibleTrigger, CollapsibleContent. Use `defaultOpen` for uncontrolled, or `open` with `onOpenChange` to drive it yourself. For several linked sections, use `accordion`.",
  "categories": [
    "layout"
  ],
  "type": "registry:component"
}
