{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comp-566",
  "type": "registry:component",
  "title": "Comp 566",
  "description": "Comp 566",
  "files": [
    {
      "path": "registry/ui-basic/comp-566.tsx",
      "content": "\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport { Tree, TreeItem, TreeItemLabel } from \"@/components/ui/tree\";\r\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\r\nimport { useTree } from \"@headless-tree/react\";\r\n\r\ninterface Item {\r\n\tname: string;\r\n\tchildren?: string[];\r\n}\r\n\r\nconst items: Record<string, Item> = {\r\n\tcompany: {\r\n\t\tname: \"Company\",\r\n\t\tchildren: [\"engineering\", \"marketing\", \"operations\"],\r\n\t},\r\n\tengineering: {\r\n\t\tname: \"Engineering\",\r\n\t\tchildren: [\"frontend\", \"backend\", \"platform-team\"],\r\n\t},\r\n\tfrontend: { name: \"Frontend\", children: [\"design-system\", \"web-platform\"] },\r\n\t\"design-system\": {\r\n\t\tname: \"Design System\",\r\n\t\tchildren: [\"components\", \"tokens\", \"guidelines\"],\r\n\t},\r\n\tcomponents: { name: \"Components\" },\r\n\ttokens: { name: \"Tokens\" },\r\n\tguidelines: { name: \"Guidelines\" },\r\n\t\"web-platform\": { name: \"Web Platform\" },\r\n\tbackend: { name: \"Backend\", children: [\"apis\", \"infrastructure\"] },\r\n\tapis: { name: \"APIs\" },\r\n\tinfrastructure: { name: \"Infrastructure\" },\r\n\t\"platform-team\": { name: \"Platform Team\" },\r\n\tmarketing: { name: \"Marketing\", children: [\"content\", \"seo\"] },\r\n\tcontent: { name: \"Content\" },\r\n\tseo: { name: \"SEO\" },\r\n\toperations: { name: \"Operations\", children: [\"hr\", \"finance\"] },\r\n\thr: { name: \"HR\" },\r\n\tfinance: { name: \"Finance\" },\r\n};\r\n\r\nconst indent = 20;\r\n\r\nexport default function Component() {\r\n\tconst tree = useTree<Item>({\r\n\t\tinitialState: {\r\n\t\t\texpandedItems: [\"engineering\", \"frontend\", \"design-system\"],\r\n\t\t},\r\n\t\tindent,\r\n\t\trootItemId: \"company\",\r\n\t\tgetItemName: (item) => item.getItemData().name,\r\n\t\tisItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\r\n\t\tdataLoader: {\r\n\t\t\tgetItem: (itemId) => items[itemId],\r\n\t\t\tgetChildren: (itemId) => items[itemId].children ?? [],\r\n\t\t},\r\n\t\tfeatures: [syncDataLoaderFeature, hotkeysCoreFeature],\r\n\t});\r\n\r\n\treturn (\r\n\t\t<div className=\"flex h-full flex-col gap-2 first:*:grow\">\r\n\t\t\t<div>\r\n\t\t\t\t<Tree\r\n\t\t\t\t\tclassName=\"relative before:absolute before:inset-0 before:-ms-1 before:bg-[repeating-linear-gradient(to_right,transparent_0,transparent_calc(var(--tree-indent)-1px),var(--border)_calc(var(--tree-indent)-1px),var(--border)_calc(var(--tree-indent)))]\"\r\n\t\t\t\t\tindent={indent}\r\n\t\t\t\t\ttree={tree}\r\n\t\t\t\t>\r\n\t\t\t\t\t{tree.getItems().map((item) => {\r\n\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t<TreeItem key={item.getId()} item={item}>\r\n\t\t\t\t\t\t\t\t<TreeItemLabel className=\"before:bg-background relative before:absolute before:inset-x-0 before:-inset-y-0.5 before:-z-10\" />\r\n\t\t\t\t\t\t\t</TreeItem>\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t})}\r\n\t\t\t\t</Tree>\r\n\t\t\t</div>\r\n\r\n\t\t\t<p\r\n\t\t\t\taria-live=\"polite\"\r\n\t\t\t\trole=\"region\"\r\n\t\t\t\tclassName=\"text-muted-foreground mt-2 text-xs\"\r\n\t\t\t>\r\n\t\t\t\tBasic tree with vertical lines ∙{\" \"}\r\n\t\t\t\t<a\r\n\t\t\t\t\thref=\"https://headless-tree.lukasbach.com\"\r\n\t\t\t\t\tclassName=\"hover:text-foreground underline\"\r\n\t\t\t\t\ttarget=\"_blank\"\r\n\t\t\t\t\trel=\"noopener noreferrer\"\r\n\t\t\t\t>\r\n\t\t\t\t\tAPI\r\n\t\t\t\t</a>\r\n\t\t\t</p>\r\n\t\t</div>\r\n\t);\r\n}\r\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"
    }
  ]
}