{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tree-code-viewer",
  "dependencies": [
    "shiki"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/ui/tree-view-code.tsx",
      "content": "'use client';\n\nimport {\n  TreeExpander,\n  TreeIcon,\n  TreeLabel,\n  TreeNode,\n  TreeNodeContent,\n  TreeNodeTrigger,\n  TreeProvider,\n  TreeView,\n} from '@/components/ui/tree';\nimport { type TreeNodeData, buildSimpleTree, getFileIcon } from '@/lib/tree-structure';\nimport { useState } from 'react';\nimport { ClientPreCode } from '../website/code-components/client-pre-code';\n\nexport function TreeCodeViewer({\n  files,\n}: {\n  files: {\n    id: string;\n    fileName: string;\n    virtualPath: string[];\n    ext: string;\n    raw: string;\n    html: string;\n  }[];\n}) {\n  const tree = buildSimpleTree(files);\n  console.log('tree', tree);\n  const [selectedId, setSelectedId] = useState(files[0]?.id);\n  const fileMap = Object.fromEntries(files.map((f) => [f.id, f]));\n  const selectedFile = selectedId ? fileMap[selectedId] : null;\n\n  return (\n    <div className='grid grid-cols-[250px_1fr] border dark:border-neutral-800 bg-neutral-50 dark:bg-neutral-950 overflow-hidden'>\n      {/* LEFT */}\n      <TreeProvider\n        selectable\n        multiSelect={false}\n        defaultExpandedIds={[tree[0].name, 'ui', 'lib']}\n        onSelectionChange={(ids) => {\n          if (ids[0]) setSelectedId(ids[0]);\n        }}\n        className='border-r dark:border-neutral-800 bg-neutral-50 dark:bg-neutral-900'\n      >\n        <TreeView>\n          <RenderTree nodes={tree} />\n        </TreeView>\n      </TreeProvider>\n\n      {/* RIGHT */}\n      <div className='min-w-0 p-2'>\n        {selectedFile ? (\n          <ClientPreCode html={selectedFile.html} raw={selectedFile.raw} />\n        ) : (\n          <div className='p-6 text-sm text-muted-foreground'>Select a file</div>\n        )}\n      </div>\n    </div>\n  );\n}\n\nfunction RenderTree({ nodes, level = 0 }: { nodes: TreeNodeData[]; level?: number }) {\n  return (\n    <>\n      {nodes.map((node, index) => {\n        const isLast = index === nodes.length - 1;\n\n        // 📁 FOLDER\n        if (node.type === 'folder') {\n          return (\n            <TreeNode key={node.name} nodeId={node.name} level={level} isLast={isLast} isFolder>\n              <TreeNodeTrigger>\n                <TreeExpander hasChildren />\n                <TreeIcon icon={getFileIcon('folder')} />\n                <TreeLabel>{node.name}</TreeLabel>\n              </TreeNodeTrigger>\n\n              <TreeNodeContent hasChildren>\n                <RenderTree nodes={node.children} level={level + 1} />\n              </TreeNodeContent>\n            </TreeNode>\n          );\n        }\n\n        // 📄 FILE\n        return (\n          <TreeNode key={node.id} nodeId={node.id} level={level} isLast={isLast}>\n            <TreeNodeTrigger>\n              <TreeExpander />\n              <TreeIcon icon={getFileIcon('file', node.ext, node.name)} />\n              <TreeLabel>{node.name}</TreeLabel>\n            </TreeNodeTrigger>\n          </TreeNode>\n        );\n      })}\n    </>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./components/website/code-components/client-pre-code.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { CopyButton } from './copy-button';\n\nexport function ClientPreCode({\n  html,\n  raw,\n  className,\n}: {\n  html: string;\n  raw: string;\n  className?: string;\n}) {\n  return (\n    <div className={cn('relative', className)}>\n      <CopyButton code={raw} classname='right-2 top-2 bg-white dark:bg-neutral-800' />\n\n      <div\n        className='not-prose max-h-[550px] overflow-x-hidden rounded-md text-sm border dark:border-neutral-800'\n        dangerouslySetInnerHTML={{ __html: html }}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./components/website/code-components/copy-button.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { Check, CheckCheck, Copy } from 'lucide-react';\nimport { useState } from 'react';\n\nexport function CopyButton({ code, classname }: { code: string; classname?: string }) {\n  const [hasCheckIcon, setHasCheckIcon] = useState(false);\n\n  const onCopy = () => {\n    navigator.clipboard.writeText(code);\n    setHasCheckIcon(true);\n\n    setTimeout(() => {\n      setHasCheckIcon(false);\n    }, 1000);\n  };\n\n  return (\n    <>\n      <div\n        className={cn(\n          'absolute right-2 top-2 cursor-pointer dark:hover:shadow-[0px_1px_10px_5px_#3f7ef3] hover:shadow-[0px_1px_10px_5px_#9abaf7] dark:hover:border-blue-500 hover:border-blue-300  dark:bg-zinc-800 backdrop-blur-2xl bg-white rounded-md border-2',\n          classname\n        )}\n        onClick={onCopy}\n      >\n        <div\n          className={` inset-0 transform transition-all duration-300  w-9 h-8 grid place-content-center  ${\n            hasCheckIcon ? 'scale-0 opacity-0' : 'scale-100 opacity-100'\n          }`}\n        >\n          <Copy className='h-4 w-4 text-foreground/80' />\n        </div>\n        <div\n          className={`absolute inset-0 transform transition-all duration-300 w-8 h-8 grid place-content-center  ${\n            hasCheckIcon ? 'scale-100 opacity-100' : 'scale-0 opacity-0'\n          }`}\n        >\n          <CheckCheck className='h-4 w-4 text-foreground/80' />\n        </div>\n      </div>\n    </>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}