{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-file-tree",
  "type": "registry:component",
  "title": "File tree",
  "description": "Everything a run touched, as a tree, with the churn spelled out per file.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json",
    "https://r.assistant-ui.com/elements-range.json"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/file-tree.tsx",
      "sourcePath": "packages/ui/src/components/react/assistant-ui/elements/file-tree.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { ChevronDownIcon, FileIcon, FolderIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { mono, paper } from \"./surfaces\";\nimport { take } from \"../utils/range\";\n\nexport interface FileTreeNode {\n  path: string;\n  name: string;\n  depth: number;\n  kind: \"folder\" | \"file\";\n  additions?: number;\n  deletions?: number;\n}\n\nexport function FileTree({\n  nodes,\n  visibleCount,\n  totalAdditions,\n  totalDeletions,\n  className,\n  ...props\n}: Omit<\n  ComponentProps<\"div\">,\n  \"children\" | \"nodes\" | \"visibleCount\" | \"totalAdditions\" | \"totalDeletions\"\n> & {\n  nodes: readonly FileTreeNode[];\n  visibleCount: number;\n  totalAdditions: number;\n  totalDeletions: number;\n}) {\n  const files = nodes.filter((node) => node.kind === \"file\").length;\n\n  return (\n    <div\n      data-slot=\"file-tree\"\n      className={cn(\n        paper,\n        \"flex w-full max-w-sm flex-col gap-2 rounded-2xl p-3.5\",\n        className,\n      )}\n\n      {...props}\n    >\n      <div className=\"flex items-baseline justify-between px-1\">\n        <span className=\"text-[13.5px] font-medium\">{files} files changed</span>\n        <span className={cn(mono, \"tabular-nums\")}>\n          <span className=\"text-emerald-600 dark:text-emerald-400\">\n            +{totalAdditions}\n          </span>{\" \"}\n          <span className=\"text-red-600 dark:text-red-400\">\n            −{totalDeletions}\n          </span>\n        </span>\n      </div>\n\n      <div className=\"flex flex-col\">\n        {take(nodes, visibleCount).map((node) => (\n          <div\n            key={node.path}\n            className=\"fade-in slide-in-from-left-1 animate-in fill-mode-both hover:bg-foreground/[0.03] flex items-center gap-2 rounded-lg px-1 py-1 text-[13px] transition-colors duration-300\"\n            style={{ paddingInlineStart: `${0.25 + node.depth * 0.85}rem` }}\n          >\n            {node.kind === \"folder\" ? (\n              <>\n                <ChevronDownIcon className=\"text-foreground/25 size-3 shrink-0\" />\n                <FolderIcon className=\"text-foreground/35 size-3.5 shrink-0\" />\n                <span className=\"text-foreground/60 min-w-0 flex-1 truncate\">\n                  {node.name}\n                </span>\n              </>\n            ) : (\n              <>\n                <FileIcon className=\"text-foreground/30 ms-3 size-3.5 shrink-0\" />\n                <span className=\"text-foreground/85 min-w-0 flex-1 truncate\">\n                  {node.name}\n                </span>\n                <span className={cn(mono, \"shrink-0 tabular-nums\")}>\n                  {node.additions ? (\n                    <span className=\"text-emerald-600 dark:text-emerald-400\">\n                      +{node.additions}\n                    </span>\n                  ) : null}{\" \"}\n                  {node.deletions ? (\n                    <span className=\"text-red-600 dark:text-red-400\">\n                      −{node.deletions}\n                    </span>\n                  ) : null}\n                </span>\n              </>\n            )}\n          </div>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
    }
  ]
}