{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tree-view",
  "type": "registry:ui",
  "title": "Tree view",
  "description": "Nested tree view with expandable nodes, rotating chevrons, depth indentation and ARIA tree roles. Suited to file explorers and nested category lists in React.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/tree-view.tsx",
      "type": "registry:ui",
      "target": "components/ui/tree-view.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { ChevronRightIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/** A collapsible tree of nested nodes, open by default, for file browsers and org charts. */\ntype TreeNode = { id: string; label: string; children?: TreeNode[] }\n\ntype TreeViewProps = {\n  /** Root nodes. Defaults to the Lumen web app's source tree. */\n  nodes?: TreeNode[]\n  className?: string\n}\n\nconst SAMPLE_NODES: TreeNode[] = [\n  {\n    id: \"src\",\n    label: \"src\",\n    children: [\n      {\n        id: \"app\",\n        label: \"app\",\n        children: [\n          { id: \"invoices\", label: \"invoices\", children: [{ id: \"invoices-page\", label: \"page.tsx\" }] },\n          { id: \"customers\", label: \"customers\", children: [{ id: \"customers-page\", label: \"page.tsx\" }] },\n          { id: \"layout\", label: \"layout.tsx\" },\n        ],\n      },\n      {\n        id: \"components\",\n        label: \"components\",\n        children: [\n          { id: \"invoice-table\", label: \"invoice-table.tsx\" },\n          { id: \"customer-card\", label: \"customer-card.tsx\" },\n        ],\n      },\n    ],\n  },\n  { id: \"package\", label: \"package.json\" },\n  { id: \"readme\", label: \"README.md\" },\n]\n\nfunction TreeView({ nodes = SAMPLE_NODES, className }: TreeViewProps) {\n  return (\n    <ul data-slot=\"tree-view\" className={cn(\"w-full max-w-xs text-sm\", className)} role=\"tree\">\n      {nodes.map((n) => <TreeItem key={n.id} node={n} depth={0} />)}\n    </ul>\n  )\n}\n\nfunction TreeItem({ node, depth }: { node: TreeNode; depth: number }) {\n  const [open, setOpen] = React.useState(true)\n  const hasKids = !!node.children?.length\n  return (\n    <li role=\"treeitem\" aria-expanded={hasKids ? open : undefined} className=\"select-none\">\n      <button\n        type=\"button\"\n        className=\"flex w-full items-center gap-1 rounded-lg px-2 py-1.5 text-left outline-none hover:bg-sunken focus-visible:ring-2 focus-visible:ring-accent\"\n        style={{ paddingLeft: 8 + depth * 12 }}\n        onClick={() => hasKids && setOpen((v) => !v)}\n      >\n        <ChevronRightIcon className={cn(\"size-3.5 text-fg-muted transition-transform duration-[140ms]\", open && hasKids && \"rotate-90\", !hasKids && \"opacity-0\")} />\n        {node.label}\n      </button>\n      {hasKids && open ? (\n        <ul role=\"group\">\n          {node.children!.map((c) => <TreeItem key={c.id} node={c} depth={depth + 1} />)}\n        </ul>\n      ) : null}\n    </li>\n  )\n}\nexport { TreeView }\nexport type { TreeNode, TreeViewProps }\n"
    }
  ]
}
