{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comp-576",
  "type": "registry:component",
  "title": "Comp 576",
  "description": "Comp 576",
  "files": [
    {
      "path": "registry/ui-basic/comp-576.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/components/ui/tree\";\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\n\ninterface Item {\n\tname: string;\n\thref?: string;\n\tchildren?: string[];\n\tcurrent?: boolean;\n}\n\nconst items: Record<string, Item> = {\n\tmain: { name: \"Documentation\", children: [\"guides\", \"api\", \"resources\"] },\n\tguides: { name: \"User Guides\", children: [\"getting-started\", \"advanced\"] },\n\t\"getting-started\": {\n\t\tname: \"Getting Started\",\n\t\tchildren: [\"installation\", \"setup\"],\n\t},\n\tinstallation: { name: \"Installation\", href: \"#\", current: true },\n\tsetup: { name: \"Configuration\", href: \"#\" },\n\tadvanced: { name: \"Advanced Usage\", href: \"#\" },\n\tapi: { name: \"API Reference\", children: [\"endpoints\", \"models\"] },\n\tendpoints: { name: \"Endpoints\", href: \"#\" },\n\tmodels: { name: \"Data Models\", href: \"#\" },\n\tresources: { name: \"Resources\", children: [\"examples\", \"faq\"] },\n\texamples: { name: \"Code Examples\", href: \"#\" },\n\tfaq: { name: \"FAQ\", href: \"#\" },\n};\n\nconst indent = 20;\n\n// Find the path from root to the current item\nfunction findPathToCurrent(\n\titems: Record<string, Item>,\n\trootId: string\n): string[] {\n\tconst path: string[] = [];\n\n\tfunction findPath(itemId: string): boolean {\n\t\tconst item = items[itemId];\n\t\tif (!item) return false;\n\n\t\t// If this is the current item, we found the path\n\t\tif (item.current) {\n\t\t\tpath.unshift(itemId);\n\t\t\treturn true;\n\t\t}\n\n\t\t// If this item has children, search them\n\t\tif (item.children?.length) {\n\t\t\tfor (const childId of item.children) {\n\t\t\t\tif (findPath(childId)) {\n\t\t\t\t\t// If we found the path in this branch, add this item to the path\n\t\t\t\t\tpath.unshift(itemId);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfindPath(rootId);\n\treturn path;\n}\n\n// Get all parent IDs that need to be expanded\nconst pathToCurrent = findPathToCurrent(items, \"main\");\n// Remove the current item from the path if it's a leaf node\nconst expandedItems = pathToCurrent.filter((id) => items[id].children?.length);\n\nexport default function Component() {\n\tconst tree = useTree<Item>({\n\t\tinitialState: {\n\t\t\texpandedItems,\n\t\t},\n\t\tindent,\n\t\trootItemId: \"main\",\n\t\tgetItemName: (item) => item.getItemData().name,\n\t\tisItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n\t\tdataLoader: {\n\t\t\tgetItem: (itemId) => items[itemId],\n\t\t\tgetChildren: (itemId) => items[itemId].children ?? [],\n\t\t},\n\t\tfeatures: [syncDataLoaderFeature, hotkeysCoreFeature],\n\t});\n\n\treturn (\n\t\t<div className=\"flex h-full flex-col gap-2 first:*:grow\">\n\t\t\t<Tree indent={indent} tree={tree}>\n\t\t\t\t{tree.getItems().map((item) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TreeItem\n\t\t\t\t\t\t\tkey={item.getId()}\n\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\tasChild={!!item.getItemData()?.href}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.getItemData()?.href ? (\n\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\thref={item.getItemData().href}\n\t\t\t\t\t\t\t\t\tdata-current={item.getItemData().current}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TreeItemLabel className=\"in-data-[current=true]:bg-accent in-data-[current=true]:text-accent-foreground\" />\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<TreeItemLabel />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</TreeItem>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</Tree>\n\n\t\t\t<p\n\t\t\t\taria-live=\"polite\"\n\t\t\t\trole=\"region\"\n\t\t\t\tclassName=\"text-muted-foreground mt-2 text-xs\"\n\t\t\t>\n\t\t\t\tMenu navigation tree ∙{\" \"}\n\t\t\t\t<a\n\t\t\t\t\thref=\"https://headless-tree.lukasbach.com\"\n\t\t\t\t\tclassName=\"hover:text-foreground underline\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t>\n\t\t\t\t\tAPI\n\t\t\t\t</a>\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/tree.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/registry/utilities/cn\";\nimport { ItemInstance } from \"@headless-tree/core\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { Slot } from \"radix-ui\";\n\ninterface TreeContextValue<T = any> {\n\tindent: number;\n\tcurrentItem?: ItemInstance<T>;\n\ttree?: any;\n}\n\nconst TreeContext = React.createContext<TreeContextValue>({\n\tindent: 20,\n\tcurrentItem: undefined,\n\ttree: undefined,\n});\n\nfunction useTreeContext<T = any>() {\n\treturn React.useContext(TreeContext) as TreeContextValue<T>;\n}\n\ninterface TreeProps extends React.HTMLAttributes<HTMLDivElement> {\n\tindent?: number;\n\ttree?: any;\n}\n\nfunction Tree({ indent = 20, tree, className, ...props }: TreeProps) {\n\tconst containerProps =\n\t\ttree && typeof tree.getContainerProps === \"function\"\n\t\t\t? tree.getContainerProps()\n\t\t\t: {};\n\tconst mergedProps = { ...props, ...containerProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-indent\": `${indent}px`,\n\t} as React.CSSProperties;\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, tree }}>\n\t\t\t<div\n\t\t\t\tdata-slot=\"tree\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\"flex flex-col\", className)}\n\t\t\t\t{...otherProps}\n\t\t\t/>\n\t\t</TreeContext.Provider>\n\t);\n}\n\ninterface TreeItemProps<T = any>\n\textends React.HTMLAttributes<HTMLButtonElement> {\n\titem: ItemInstance<T>;\n\tindent?: number;\n\tasChild?: boolean;\n}\n\nfunction TreeItem<T = any>({\n\titem,\n\tclassName,\n\tasChild,\n\tchildren,\n\t...props\n}: Omit<TreeItemProps<T>, \"indent\">) {\n\tconst { indent } = useTreeContext<T>();\n\n\tconst itemProps = typeof item.getProps === \"function\" ? item.getProps() : {};\n\tconst mergedProps = { ...props, ...itemProps };\n\n\t// Extract style from mergedProps to merge with our custom styles\n\tconst { style: propStyle, ...otherProps } = mergedProps;\n\n\t// Merge styles\n\tconst mergedStyle = {\n\t\t...propStyle,\n\t\t\"--tree-padding\": `${item.getItemMeta().level * indent}px`,\n\t} as React.CSSProperties;\n\n\tconst Comp = asChild ? Slot.Root : \"button\";\n\n\treturn (\n\t\t<TreeContext.Provider value={{ indent, currentItem: item }}>\n\t\t\t<Comp\n\t\t\t\tdata-slot=\"tree-item\"\n\t\t\t\tstyle={mergedStyle}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"z-10 ps-(--tree-padding) outline-hidden select-none not-last:pb-0.5 focus:z-20 data-disabled:pointer-events-none data-disabled:opacity-50\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tdata-focus={\n\t\t\t\t\ttypeof item.isFocused === \"function\"\n\t\t\t\t\t\t? item.isFocused() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-folder={\n\t\t\t\t\ttypeof item.isFolder === \"function\"\n\t\t\t\t\t\t? item.isFolder() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-selected={\n\t\t\t\t\ttypeof item.isSelected === \"function\"\n\t\t\t\t\t\t? item.isSelected() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-drag-target={\n\t\t\t\t\ttypeof item.isDragTarget === \"function\"\n\t\t\t\t\t\t? item.isDragTarget() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\tdata-search-match={\n\t\t\t\t\ttypeof item.isMatchingSearch === \"function\"\n\t\t\t\t\t\t? item.isMatchingSearch() || false\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t\taria-expanded={item.isExpanded()}\n\t\t\t\t{...otherProps}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Comp>\n\t\t</TreeContext.Provider>\n\t);\n}\n\ninterface TreeItemLabelProps<T = any>\n\textends React.HTMLAttributes<HTMLSpanElement> {\n\titem?: ItemInstance<T>;\n}\n\nfunction TreeItemLabel<T = any>({\n\titem: propItem,\n\tchildren,\n\tclassName,\n\t...props\n}: TreeItemLabelProps<T>) {\n\tconst { currentItem } = useTreeContext<T>();\n\tconst item = propItem || currentItem;\n\n\tif (!item) {\n\t\tconsole.warn(\"TreeItemLabel: No item provided via props or context\");\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"tree-item-label\"\n\t\t\tclassName={cn(\n\t\t\t\t\"in-focus-visible:ring-ring/50 bg-background hover:bg-accent in-data-[selected=true]:bg-accent in-data-[selected=true]:text-accent-foreground in-data-[drag-target=true]:bg-accent flex items-center gap-1 rounded-sm px-2 py-1.5 text-sm transition-colors not-in-data-[folder=true]:ps-7 in-focus-visible:ring-[3px] in-data-[search-match=true]:bg-blue-400/20! [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{item.isFolder() && (\n\t\t\t\t<ChevronDownIcon className=\"text-muted-foreground size-4 in-aria-[expanded=false]:-rotate-90\" />\n\t\t\t)}\n\t\t\t{children ||\n\t\t\t\t(typeof item.getItemName === \"function\"\n\t\t\t\t\t? item.getItemName()\n\t\t\t\t\t: null)}\n\t\t</span>\n\t);\n}\n\nfunction TreeDragLine({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n\tconst { tree } = useTreeContext();\n\n\tif (!tree || typeof tree.getDragLineStyle !== \"function\") {\n\t\tconsole.warn(\n\t\t\t\"TreeDragLine: No tree provided via context or tree does not have getDragLineStyle method\"\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst dragLine = tree.getDragLineStyle();\n\treturn (\n\t\t<div\n\t\t\tstyle={dragLine}\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-primary before:bg-background before:border-primary absolute z-30 -mt-px h-0.5 w-[unset] before:absolute before:-top-[3px] before:left-0 before:size-2 before:rounded-full before:border-2\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Tree, TreeItem, TreeItemLabel, TreeDragLine };\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}