{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "org-switcher",
  "title": "Org Switcher",
  "description": "A control for switching between organisations within the app shell.",
  "dependencies": [
    "@untitledui/icons@^0.0.22"
  ],
  "registryDependencies": [
    "@nx-ui/avatar",
    "@nx-ui/dropdown-menu",
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/blocks/org-switcher.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Check, ChevronSelectorVertical, Plus } from \"@untitledui/icons\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\n\nexport type Org = {\n  id: string\n  name: string\n  logoUrl?: string\n  /** Secondary line under the name (e.g. the viewer's role, or a plan). */\n  meta?: React.ReactNode\n}\n\nfunction initialsOf(name: string) {\n  return name\n    .split(/\\s+/)\n    .filter(Boolean)\n    .slice(0, 2)\n    .map((word) => word[0]?.toUpperCase() ?? \"\")\n    .join(\"\")\n}\n\n/** Square, rounded avatar — the org/workspace treatment (people stay circular). */\nfunction OrgAvatar({\n  org,\n  size = \"sm\",\n  className,\n}: {\n  org: Pick<Org, \"name\" | \"logoUrl\">\n  size?: \"sm\" | \"default\"\n  className?: string\n}) {\n  return (\n    <Avatar\n      size={size}\n      className={cn(\n        \"rounded-lg after:rounded-lg data-[size=sm]:rounded-md data-[size=sm]:after:rounded-md\",\n        className\n      )}\n    >\n      {org.logoUrl ? (\n        <AvatarImage src={org.logoUrl} alt={org.name} className=\"rounded-lg\" />\n      ) : null}\n      <AvatarFallback className=\"rounded-lg bg-utility-brand-100 text-featured-icon-light-fg-brand\">\n        {initialsOf(org.name)}\n      </AvatarFallback>\n    </Avatar>\n  )\n}\n\n/**\n * OrgSwitcher — a DropdownMenu that switches the active organisation. The\n * trigger shows the active org's (square) avatar, name and a chevron-selector;\n * the menu lists every org with a tick on the active one, and an optional\n * \"Create organisation\" action beneath a separator.\n */\nfunction OrgSwitcher({\n  orgs,\n  activeOrgId,\n  onOrgChange,\n  onCreateOrg,\n  className,\n}: {\n  orgs: Org[]\n  activeOrgId: string\n  onOrgChange: (orgId: string) => void\n  onCreateOrg?: () => void\n  className?: string\n}) {\n  const activeOrg = orgs.find((org) => org.id === activeOrgId) ?? orgs[0]\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        className={cn(\n          \"flex w-full items-center gap-2.5 rounded-lg p-2 text-left ring-1 ring-border ring-inset outline-none transition hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring\",\n          className\n        )}\n        aria-label=\"Switch organisation\"\n      >\n        {activeOrg ? <OrgAvatar org={activeOrg} /> : null}\n        <span className=\"flex min-w-0 flex-1 flex-col\">\n          <span className=\"truncate text-sm font-semibold text-foreground\">\n            {activeOrg?.name}\n          </span>\n          {activeOrg?.meta ? (\n            <span className=\"truncate text-xs text-muted-foreground\">\n              {activeOrg.meta}\n            </span>\n          ) : null}\n        </span>\n        <ChevronSelectorVertical className=\"size-4 shrink-0 text-fg-quaternary\" />\n      </DropdownMenuTrigger>\n\n      <DropdownMenuContent className=\"min-w-64\" align=\"start\">\n        {orgs.map((org) => {\n          const isActive = org.id === activeOrg?.id\n          return (\n            <DropdownMenuItem\n              key={org.id}\n              onClick={() => onOrgChange(org.id)}\n              className=\"gap-2.5\"\n            >\n              <OrgAvatar org={org} size=\"sm\" />\n              <span className=\"flex min-w-0 flex-1 flex-col\">\n                <span className=\"truncate text-sm font-semibold text-secondary-foreground\">\n                  {org.name}\n                </span>\n                {org.meta ? (\n                  <span className=\"truncate text-xs text-muted-foreground\">\n                    {org.meta}\n                  </span>\n                ) : null}\n              </span>\n              {isActive ? (\n                <Check className=\"size-4 shrink-0 text-fg-brand-primary\" aria-label=\"Active\" />\n              ) : null}\n            </DropdownMenuItem>\n          )\n        })}\n\n        {onCreateOrg ? (\n          <>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem onClick={onCreateOrg}>\n              <Plus className=\"size-5 text-fg-quaternary\" />\n              <span className=\"text-sm font-semibold text-secondary-foreground\">\n                Create organisation\n              </span>\n            </DropdownMenuItem>\n          </>\n        ) : null}\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n\nexport { OrgSwitcher, OrgAvatar }\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:block"
}