{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox-07",
  "title": "Nested tree",
  "description": "Multi-level file tree; parents derive checked / indeterminate from children.",
  "dependencies": [],
  "registryDependencies": [
    "checkbox",
    "label"
  ],
  "files": [
    {
      "path": "registry/patterns/checkbox/checkbox-07.tsx",
      "content": "'use client'\n\nimport { Checkbox } from '@/components/ui/checkbox'\nimport { Label } from '@/components/ui/label'\nimport { FileIcon, FolderIcon } from 'lucide-react'\nimport { useState } from 'react'\n\ntype TreeNode = {\n  id: string\n  label: string\n  children?: TreeNode[]\n}\n\nconst tree: TreeNode[] = [\n  {\n    id: 'src',\n    label: 'src',\n    children: [\n      {\n        id: 'components',\n        label: 'components',\n        children: [\n          { id: 'button', label: 'button.tsx' },\n          { id: 'input', label: 'input.tsx' },\n        ],\n      },\n      {\n        id: 'lib',\n        label: 'lib',\n        children: [{ id: 'utils', label: 'utils.ts' }],\n      },\n    ],\n  },\n  {\n    id: 'public',\n    label: 'public',\n    children: [{ id: 'logo', label: 'logo.svg' }],\n  },\n]\n\nfunction leafIds(node: TreeNode): string[] {\n  return node.children ? node.children.flatMap(leafIds) : [node.id]\n}\n\nfunction TreeItem({\n  node,\n  checked,\n  onToggle,\n  depth = 0,\n}: Readonly<{\n  node: TreeNode\n  checked: Set<string>\n  onToggle: (ids: string[], next: boolean) => void\n  depth?: number\n}>) {\n  const leaves = leafIds(node)\n  const checkedLeaves = leaves.filter((id) => checked.has(id))\n  const allLeavesChecked =\n    checkedLeaves.length > 0 && checkedLeaves.length === leaves.length\n  const someLeavesChecked =\n    checkedLeaves.length > 0 && checkedLeaves.length < leaves.length\n\n  return (\n    <div className=\"flex flex-col gap-2.5\">\n      <div\n        className=\"flex items-center gap-2.5\"\n        style={{ paddingLeft: depth * 20 }}\n      >\n        <Checkbox\n          id={`checkbox-07-${node.id}`}\n          checked={allLeavesChecked}\n          indeterminate={someLeavesChecked}\n          onCheckedChange={(value) => onToggle(leaves, value === true)}\n        />\n        {node.children ? (\n          <FolderIcon className=\"text-muted-foreground size-4\" />\n        ) : (\n          <FileIcon className=\"text-muted-foreground size-4\" />\n        )}\n        <Label htmlFor={`checkbox-07-${node.id}`} className=\"font-normal\">\n          {node.label}\n        </Label>\n      </div>\n      {node.children?.map((child) => (\n        <TreeItem\n          key={child.id}\n          node={child}\n          checked={checked}\n          onToggle={onToggle}\n          depth={depth + 1}\n        />\n      ))}\n    </div>\n  )\n}\n\nexport function Checkbox07() {\n  const [checked, setChecked] = useState<Set<string>>(\n    () => new Set(['button', 'utils']),\n  )\n\n  const toggle = (ids: string[], next: boolean) =>\n    setChecked((prev) => {\n      const draft = new Set(prev)\n      ids.forEach((id) => (next ? draft.add(id) : draft.delete(id)))\n      return draft\n    })\n\n  return (\n    <div className=\"flex w-full max-w-xs flex-col gap-2.5\">\n      {tree.map((node) => (\n        <TreeItem\n          key={node.id}\n          node={node}\n          checked={checked}\n          onToggle={toggle}\n        />\n      ))}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/flx/patterns/checkbox/checkbox-07.tsx"
    }
  ],
  "type": "registry:block"
}