{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"c-tree-7","type":"registry:block","title":"Permissions tree with checkboxes","description":"Permissions tree with checkboxes","dependencies":["@headless-tree/core","@headless-tree/react"],"registryDependencies":["checkbox","@reui/tree"],"files":[{"path":"c-tree-7.tsx","type":"registry:block","content":"\"use client\"\n\nimport { useState } from \"react\"\nimport {\n  Tree,\n  TreeItem,\n  TreeItemLabel,\n} from \"@/components/reui/tree\"\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\"\nimport { useTree } from \"@headless-tree/react\"\n\nimport { Checkbox } from \"@/components/ui/checkbox\"\n\ninterface PermissionItem {\n  name: string\n  children?: string[]\n}\n\nconst items: Record<string, PermissionItem> = {\n  permissions: {\n    name: \"All Permissions\",\n    children: [\"users\", \"content\", \"billing\", \"api\"],\n  },\n  users: {\n    name: \"User Management\",\n    children: [\"users-view\", \"users-create\", \"users-edit\", \"users-delete\"],\n  },\n  \"users-view\": { name: \"View users\" },\n  \"users-create\": { name: \"Create users\" },\n  \"users-edit\": { name: \"Edit users\" },\n  \"users-delete\": { name: \"Delete users\" },\n  content: {\n    name: \"Content Management\",\n    children: [\"content-view\", \"content-publish\", \"content-delete\"],\n  },\n  \"content-view\": { name: \"View content\" },\n  \"content-publish\": { name: \"Publish content\" },\n  \"content-delete\": { name: \"Delete content\" },\n  billing: { name: \"Billing\", children: [\"billing-view\", \"billing-manage\"] },\n  \"billing-view\": { name: \"View invoices\" },\n  \"billing-manage\": { name: \"Manage subscriptions\" },\n  api: { name: \"API Access\", children: [\"api-read\", \"api-write\"] },\n  \"api-read\": { name: \"Read access\" },\n  \"api-write\": { name: \"Write access\" },\n}\n\nconst indent = 24\n\nexport function Pattern() {\n  const [checked, setChecked] = useState<Set<string>>(\n    new Set([\n      \"users-view\",\n      \"content-view\",\n      \"content-publish\",\n      \"billing-view\",\n      \"api-read\",\n    ])\n  )\n\n  const togglePermission = (id: string) => {\n    setChecked((prev) => {\n      const next = new Set(prev)\n      if (next.has(id)) {\n        next.delete(id)\n      } else {\n        next.add(id)\n      }\n      return next\n    })\n  }\n\n  const tree = useTree<PermissionItem>({\n    initialState: {\n      expandedItems: [\"users\", \"content\"],\n    },\n    indent,\n    rootItemId: \"permissions\",\n    getItemName: (item) => item.getItemData().name,\n    isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n    dataLoader: {\n      getItem: (itemId) => items[itemId],\n      getChildren: (itemId) => items[itemId].children ?? [],\n    },\n    features: [syncDataLoaderFeature, hotkeysCoreFeature],\n  })\n\n  return (\n    <div className=\"mx-auto w-full grow place-self-start lg:w-xs\">\n      <Tree\n        indent={indent}\n        tree={tree}\n        toggleIconType=\"plus-minus\"\n        className=\"\"\n      >\n        {tree.getItems().map((item) => {\n          const id = item.getId()\n          const isLeaf = !item.isFolder()\n\n          return (\n            <TreeItem key={id} item={item}>\n              <TreeItemLabel className=\"not-in-data-[folder=true]:ps-5\">\n                <span className=\"flex items-center gap-2\">\n                  {isLeaf && (\n                    <Checkbox\n                      checked={checked.has(id)}\n                      onCheckedChange={() => togglePermission(id)}\n                      className=\"size-3.5\"\n                      onClick={(e) => e.stopPropagation()}\n                    />\n                  )}\n                  {item.getItemName()}\n                </span>\n              </TreeItemLabel>\n            </TreeItem>\n          )\n        })}\n      </Tree>\n    </div>\n  )\n}","target":"components/examples/c-tree-7.tsx"}],"meta":{"order":7,"label":"Permissions"}}