{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comp-570",
  "type": "registry:component",
  "title": "Comp 570",
  "description": "Comp 570",
  "files": [
    {
      "path": "registry/ui-basic/comp-570.tsx",
      "content": "\"use client\";\n\nimport React, { useState } from \"react\";\n\nimport { Input } from \"@/components/ui/input\";\nimport { Tree, TreeItem, TreeItemLabel } from \"@/components/ui/tree\";\nimport {\n\thotkeysCoreFeature,\n\trenamingFeature,\n\tselectionFeature,\n\tsyncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FileIcon, FolderIcon, FolderOpenIcon } from \"lucide-react\";\n\ninterface Item {\n\tname: string;\n\tchildren?: string[];\n}\n\n// Initial data\nconst initialItems: Record<string, Item> = {\n\tcompany: {\n\t\tname: \"Company\",\n\t\tchildren: [\"engineering\", \"marketing\", \"operations\"],\n\t},\n\tengineering: {\n\t\tname: \"Engineering\",\n\t\tchildren: [\"frontend\", \"backend\", \"platform-team\"],\n\t},\n\tfrontend: { name: \"Frontend\", children: [\"design-system\", \"web-platform\"] },\n\t\"design-system\": {\n\t\tname: \"Design System\",\n\t\tchildren: [\"components\", \"tokens\", \"guidelines\"],\n\t},\n\tcomponents: { name: \"Components\" },\n\ttokens: { name: \"Tokens\" },\n\tguidelines: { name: \"Guidelines\" },\n\t\"web-platform\": { name: \"Web Platform\" },\n\tbackend: { name: \"Backend\", children: [\"apis\", \"infrastructure\"] },\n\tapis: { name: \"APIs\" },\n\tinfrastructure: { name: \"Infrastructure\" },\n\t\"platform-team\": { name: \"Platform Team\" },\n\tmarketing: { name: \"Marketing\", children: [\"content\", \"seo\"] },\n\tcontent: { name: \"Content\" },\n\tseo: { name: \"SEO\" },\n\toperations: { name: \"Operations\", children: [\"hr\", \"finance\"] },\n\thr: { name: \"HR\" },\n\tfinance: { name: \"Finance\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n\tconst [items, setItems] = useState(initialItems);\n\n\tconst tree = useTree<Item>({\n\t\tinitialState: {\n\t\t\texpandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n\t\t},\n\t\tindent,\n\t\trootItemId: \"company\",\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\tonRename: (item, newName) => {\n\t\t\t// Update the item name in our state\n\t\t\tconst itemId = item.getId();\n\t\t\tsetItems((prevItems) => ({\n\t\t\t\t...prevItems,\n\t\t\t\t[itemId]: {\n\t\t\t\t\t...prevItems[itemId],\n\t\t\t\t\tname: newName,\n\t\t\t\t},\n\t\t\t}));\n\t\t},\n\t\tfeatures: [\n\t\t\tsyncDataLoaderFeature,\n\t\t\thotkeysCoreFeature,\n\t\t\trenamingFeature,\n\t\t\tselectionFeature,\n\t\t],\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 key={item.getId()} item={item}>\n\t\t\t\t\t\t\t<TreeItemLabel>\n\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t{item.isFolder() ? (\n\t\t\t\t\t\t\t\t\t\titem.isExpanded() ? (\n\t\t\t\t\t\t\t\t\t\t\t<FolderOpenIcon className=\"text-muted-foreground pointer-events-none size-4\" />\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<FolderIcon className=\"text-muted-foreground pointer-events-none size-4\" />\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<FileIcon className=\"text-muted-foreground pointer-events-none size-4\" />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{item.isRenaming() ? (\n\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t{...item.getRenameInputProps()}\n\t\t\t\t\t\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"-my-0.5 h-6 px-1\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\titem.getItemName()\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</TreeItemLabel>\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\tTree with renaming (press F2 to rename) ∙{\" \"}\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/input.tsx",
      "content": "// SHADCN UI GENERATED CODE\n\nimport React from \"react\";\n\nimport { cn } from \"@/registry/utilities/cn\";\n\nexport interface InputProps\n\textends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n\t({ className, type, ...props }, ref) => {\n\t\treturn (\n\t\t\t<input\n\t\t\t\ttype={type}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t}\n);\nInput.displayName = \"Input\";\n\nexport { Input };\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"
    },
    {
      "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"
    }
  ]
}