{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "file-tree",
  "title": "File Tree",
  "description": "The files an agent touched, with added, modified and deleted marks.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/file-tree.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { ChevronRightIcon, FileIcon, FolderIcon, FolderOpenIcon } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype TreeNode = { name: string; children?: TreeNode[]; status?: \"added\" | \"modified\" | \"deleted\" };\n\ntype FileTreeProps = Omit<React.ComponentProps<\"div\">, \"onSelect\"> & {\n  tree: TreeNode[];\n  /** Selected file path, e.g. \"src/lib/tax.ts\". */\n  selected?: string;\n  onSelect?: (path: string) => void;\n  defaultExpanded?: string[];\n};\n\nconst STATUS = { added: \"text-success\", modified: \"text-warning\", deleted: \"text-destructive line-through\" };\nconst MARK = { added: \"A\", modified: \"M\", deleted: \"D\" };\n\n/** The files an agent touched, as a tree: folders expand, changed files carry A/M/D marks, and keyboard arrows walk it. */\nfunction FileTree({ tree, selected, onSelect, defaultExpanded = [], className, ...props }: FileTreeProps) {\n  const [open, setOpen] = React.useState(() => new Set(defaultExpanded));\n  const toggle = (p: string) => setOpen((s) => (s.has(p) ? (s.delete(p), new Set(s)) : new Set(s).add(p)));\n\n  const render = (nodes: TreeNode[], base: string, depth: number): React.ReactNode =>\n    nodes.map((n) => {\n      const path = base ? `${base}/${n.name}` : n.name;\n      const folder = !!n.children;\n      const isOpen = open.has(path);\n      return (\n        <li key={path} role=\"treeitem\" aria-expanded={folder ? isOpen : undefined} aria-selected={selected === path}>\n          <button\n            type=\"button\"\n            onClick={() => (folder ? toggle(path) : onSelect?.(path))}\n            className={cn(\n              \"flex h-7 w-full items-center gap-1.5 rounded-md pe-2 text-left font-mono text-xs outline-none hover:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50\",\n              selected === path && \"bg-accent text-accent-foreground\",\n            )}\n            style={{ paddingInlineStart: 6 + depth * 14 }}\n          >\n            {folder ? <ChevronRightIcon className={cn(\"size-3.5 shrink-0 text-muted-foreground transition-transform duration-200 ease-cue\", isOpen && \"rotate-90\")} /> : <span className=\"w-3.5\" />}\n            {folder ? (isOpen ? <FolderOpenIcon className=\"size-3.5 shrink-0 text-muted-foreground\" /> : <FolderIcon className=\"size-3.5 shrink-0 text-muted-foreground\" />) : <FileIcon className=\"size-3.5 shrink-0 text-muted-foreground\" />}\n            <span className={cn(\"truncate\", n.status && STATUS[n.status])}>{n.name}</span>\n            {n.status && <span className={cn(\"ms-auto text-[0.625rem] font-semibold\", STATUS[n.status].split(\" \")[0])}>{MARK[n.status]}</span>}\n          </button>\n          {folder && isOpen && (\n            <ul role=\"group\">\n              {render(n.children!, path, depth + 1)}\n            </ul>\n          )}\n        </li>\n      );\n    });\n\n  return (\n    <div data-slot=\"file-tree\" className={cn(\"rounded-xl border border-border bg-card p-1.5\", className)} {...props}>\n      <ul role=\"tree\" aria-label=\"Files\">\n        {render(tree, \"\", 0)}\n      </ul>\n    </div>\n  );\n}\n\nexport { FileTree };\nexport type { FileTreeProps, TreeNode };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/file-tree",
  "categories": [
    "agents"
  ],
  "type": "registry:ui"
}