{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "team-permissions-matrix",
  "title": "Team Permissions Matrix",
  "description": "Manage team permissions and roles with visual matrix.",
  "registryDependencies": [
    "badge",
    "card",
    "separator",
    "toggle"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/team/team-permissions-matrix.tsx",
      "content": "\"use client\";\n\nimport { Check, Lock, X } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Badge } from \"@/registry/new-york/ui/badge\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\";\nimport { Separator } from \"@/registry/new-york/ui/separator\";\nimport { Toggle } from \"@/registry/new-york/ui/toggle\";\n\nexport type PermissionAction =\n  | \"view\"\n  | \"create\"\n  | \"edit\"\n  | \"delete\"\n  | \"manage_members\"\n  | \"manage_settings\"\n  | \"manage_billing\"\n  | \"view_analytics\"\n  | \"manage_ai_rooms\"\n  | \"manage_files\"\n  | \"manage_projects\";\n\nexport type PermissionRole = \"owner\" | \"admin\" | \"member\" | \"viewer\";\n\nexport interface Permission {\n  action: PermissionAction;\n  label: string;\n  description?: string;\n  category: string;\n}\n\nexport interface RolePermissions {\n  role: PermissionRole;\n  permissions: Record<PermissionAction, boolean>;\n}\n\nexport interface TeamPermissionsMatrixProps {\n  permissions?: Permission[];\n  rolePermissions?: RolePermissions[];\n  onPermissionChange?: (\n    role: PermissionRole,\n    action: PermissionAction,\n    enabled: boolean\n  ) => Promise<void>;\n  className?: string;\n  showPresets?: boolean;\n}\n\nconst DEFAULT_PERMISSIONS: Permission[] = [\n  {\n    action: \"view\",\n    label: \"View Content\",\n    description: \"View team content and resources\",\n    category: \"General\",\n  },\n  {\n    action: \"create\",\n    label: \"Create Content\",\n    description: \"Create new content and resources\",\n    category: \"General\",\n  },\n  {\n    action: \"edit\",\n    label: \"Edit Content\",\n    description: \"Edit existing content\",\n    category: \"General\",\n  },\n  {\n    action: \"delete\",\n    label: \"Delete Content\",\n    description: \"Delete content and resources\",\n    category: \"General\",\n  },\n  {\n    action: \"manage_members\",\n    label: \"Manage Members\",\n    description: \"Invite, remove, and change member roles\",\n    category: \"Team Management\",\n  },\n  {\n    action: \"manage_settings\",\n    label: \"Manage Settings\",\n    description: \"Change team settings and configuration\",\n    category: \"Team Management\",\n  },\n  {\n    action: \"manage_billing\",\n    label: \"Manage Billing\",\n    description: \"View and manage billing information\",\n    category: \"Team Management\",\n  },\n  {\n    action: \"view_analytics\",\n    label: \"View Analytics\",\n    description: \"View team usage and analytics\",\n    category: \"Analytics\",\n  },\n  {\n    action: \"manage_ai_rooms\",\n    label: \"Manage AI Rooms\",\n    description: \"Create and manage shared AI workspaces\",\n    category: \"AI Features\",\n  },\n  {\n    action: \"manage_files\",\n    label: \"Manage Files\",\n    description: \"Upload, organize, and delete files\",\n    category: \"Files\",\n  },\n  {\n    action: \"manage_projects\",\n    label: \"Manage Projects\",\n    description: \"Create and manage team projects\",\n    category: \"Projects\",\n  },\n];\n\nconst DEFAULT_ROLE_PERMISSIONS: RolePermissions[] = [\n  {\n    role: \"owner\",\n    permissions: {\n      view: true,\n      create: true,\n      edit: true,\n      delete: true,\n      manage_members: true,\n      manage_settings: true,\n      manage_billing: true,\n      view_analytics: true,\n      manage_ai_rooms: true,\n      manage_files: true,\n      manage_projects: true,\n    },\n  },\n  {\n    role: \"admin\",\n    permissions: {\n      view: true,\n      create: true,\n      edit: true,\n      delete: true,\n      manage_members: true,\n      manage_settings: false,\n      manage_billing: false,\n      view_analytics: true,\n      manage_ai_rooms: true,\n      manage_files: true,\n      manage_projects: true,\n    },\n  },\n  {\n    role: \"member\",\n    permissions: {\n      view: true,\n      create: true,\n      edit: true,\n      delete: false,\n      manage_members: false,\n      manage_settings: false,\n      manage_billing: false,\n      view_analytics: false,\n      manage_ai_rooms: true,\n      manage_files: true,\n      manage_projects: true,\n    },\n  },\n  {\n    role: \"viewer\",\n    permissions: {\n      view: true,\n      create: false,\n      edit: false,\n      delete: false,\n      manage_members: false,\n      manage_settings: false,\n      manage_billing: false,\n      view_analytics: false,\n      manage_ai_rooms: false,\n      manage_files: false,\n      manage_projects: false,\n    },\n  },\n];\n\nfunction getRoleLabel(role: PermissionRole): string {\n  switch (role) {\n    case \"owner\":\n      return \"Owner\";\n    case \"admin\":\n      return \"Admin\";\n    case \"member\":\n      return \"Member\";\n    case \"viewer\":\n      return \"Viewer\";\n  }\n}\n\nfunction getRoleBadgeVariant(role: PermissionRole) {\n  switch (role) {\n    case \"owner\":\n      return \"default\";\n    case \"admin\":\n      return \"secondary\";\n    default:\n      return \"outline\";\n  }\n}\n\nexport default function TeamPermissionsMatrix({\n  permissions = DEFAULT_PERMISSIONS,\n  rolePermissions = DEFAULT_ROLE_PERMISSIONS,\n  onPermissionChange,\n  className,\n  showPresets = true,\n}: TeamPermissionsMatrixProps) {\n  const [localRolePermissions, setLocalRolePermissions] =\n    useState<RolePermissions[]>(rolePermissions);\n\n  const groupedPermissions = permissions.reduce(\n    (acc, permission) => {\n      if (!acc[permission.category]) {\n        acc[permission.category] = [];\n      }\n      acc[permission.category].push(permission);\n      return acc;\n    },\n    {} as Record<string, Permission[]>\n  );\n\n  const handlePermissionToggle = async (\n    role: PermissionRole,\n    action: PermissionAction,\n    currentValue: boolean\n  ) => {\n    // Owner role cannot be modified\n    if (role === \"owner\") return;\n\n    const newValue = !currentValue;\n    setLocalRolePermissions((prev) =>\n      prev.map((rp) => {\n        if (rp.role === role) {\n          return {\n            ...rp,\n            permissions: {\n              ...rp.permissions,\n              [action]: newValue,\n            },\n          };\n        }\n        return rp;\n      })\n    );\n\n    try {\n      await onPermissionChange?.(role, action, newValue);\n    } catch {\n      // Revert on error\n      setLocalRolePermissions((prev) =>\n        prev.map((rp) => {\n          if (rp.role === role) {\n            return {\n              ...rp,\n              permissions: {\n                ...rp.permissions,\n                [action]: currentValue,\n              },\n            };\n          }\n          return rp;\n        })\n      );\n    }\n  };\n\n  return (\n    <Card className={cn(\"w-full shadow-xs\", className)}>\n      <CardHeader>\n        <div className=\"flex flex-col gap-1\">\n          <CardTitle>Permissions Matrix</CardTitle>\n          <CardDescription>\n            Manage what each role can do in your team\n          </CardDescription>\n        </div>\n      </CardHeader>\n      <CardContent>\n        <div className=\"flex flex-col gap-6\">\n          {Object.entries(groupedPermissions).map(([category, perms]) => (\n            <div className=\"flex flex-col gap-3\" key={category}>\n              <div className=\"flex items-center gap-2\">\n                <h3 className=\"font-semibold text-muted-foreground text-sm\">\n                  {category}\n                </h3>\n                <Separator className=\"flex-1\" />\n              </div>\n              <div className=\"flex flex-col gap-2\">\n                {perms.map((permission) => (\n                  <div\n                    className=\"flex flex-col gap-3 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50\"\n                    key={permission.action}\n                  >\n                    <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n                      <span className=\"wrap-break-word font-medium text-sm\">\n                        {permission.label}\n                      </span>\n                      {permission.description && (\n                        <span className=\"wrap-break-word text-muted-foreground text-xs\">\n                          {permission.description}\n                        </span>\n                      )}\n                    </div>\n                    <div className=\"flex flex-wrap items-center gap-3\">\n                      {localRolePermissions.map((rp) => {\n                        const hasPermission = rp.permissions[permission.action];\n                        const isOwner = rp.role === \"owner\";\n\n                        return (\n                          <div\n                            className=\"flex items-center gap-2\"\n                            key={rp.role}\n                          >\n                            <Badge variant={getRoleBadgeVariant(rp.role)}>\n                              {getRoleLabel(rp.role)}\n                            </Badge>\n                            {isOwner ? (\n                              <div className=\"flex items-center justify-center\">\n                                <Lock className=\"size-4 text-muted-foreground\" />\n                              </div>\n                            ) : (\n                              <Toggle\n                                aria-label={`${permission.label} for ${getRoleLabel(rp.role)}`}\n                                aria-pressed={hasPermission}\n                                onPressedChange={() =>\n                                  handlePermissionToggle(\n                                    rp.role,\n                                    permission.action,\n                                    hasPermission\n                                  )\n                                }\n                                pressed={hasPermission}\n                                size=\"sm\"\n                              >\n                                {hasPermission ? (\n                                  <Check className=\"size-4\" />\n                                ) : (\n                                  <X className=\"size-4\" />\n                                )}\n                              </Toggle>\n                            )}\n                          </div>\n                        );\n                      })}\n                    </div>\n                  </div>\n                ))}\n              </div>\n            </div>\n          ))}\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "team"
  ],
  "type": "registry:ui"
}