{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "enterprise-workspace-switcher",
  "title": "Enterprise Workspace Switcher",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/enterprise-workspace-switcher/EnterpriseWorkspaceSwitcher.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { Building2, Check, ChevronsUpDown, Globe, LogOut, Plus, Settings, UserPlus } from 'lucide-react'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { cn } from '@/lib/utils'\n\nexport interface WorkspaceItem {\n  id: string\n  name: string\n  slug?: string\n  plan: string\n  planTier: string\n  members: number\n  region: string\n  regionCode: string\n  role: 'Owner' | 'Admin' | 'Member' | 'Personal'\n  color: string\n  initials: string\n}\n\nexport interface UserInfo {\n  name: string\n  email: string\n  avatar?: string\n}\n\nexport interface EnterpriseWorkspaceSwitcherProps {\n  initialWorkspaces?: WorkspaceItem[]\n  defaultActiveId?: string\n  user?: UserInfo\n  className?: string\n  onChange?: (workspace: WorkspaceItem) => void\n  onCreate?: (workspace: WorkspaceItem) => void\n  onAction?: (key: 'settings' | 'billing' | 'invite' | 'logout') => void\n}\n\nconst DEFAULT_WORKSPACES: WorkspaceItem[] = [\n  {\n    id: 'ws-1',\n    name: 'UIPKGE Enterprise Inc.',\n    slug: 'uipkge-enterprise',\n    plan: 'Enterprise Scale',\n    planTier: 'Enterprise Plan',\n    members: 64,\n    region: 'US East (N. Virginia)',\n    regionCode: 'US-East',\n    role: 'Owner',\n    color: 'bg-primary/10 text-primary border border-primary/20',\n    initials: 'UE',\n  },\n  {\n    id: 'ws-2',\n    name: 'Acme Design Systems Lab',\n    slug: 'acme-design',\n    plan: 'Pro Team',\n    planTier: 'Pro Team',\n    members: 18,\n    region: 'EU Central (Frankfurt)',\n    regionCode: 'EU-Central',\n    role: 'Admin',\n    color: 'bg-info/10 text-info border border-info/20',\n    initials: 'AD',\n  },\n  {\n    id: 'ws-3',\n    name: 'Personal Sandbox',\n    slug: 'personal-sandbox',\n    plan: 'Developer Tier',\n    planTier: 'Free Developer Tier',\n    members: 1,\n    region: 'Global Edge',\n    regionCode: 'Global',\n    role: 'Personal',\n    color: 'bg-success/10 text-success border border-success/20',\n    initials: 'PS',\n  },\n]\n\nconst DEFAULT_USER: UserInfo = {\n  name: 'Elena Rostova',\n  email: 'elena@uipkge.dev',\n  avatar: '',\n}\n\nexport function EnterpriseWorkspaceSwitcher({\n  initialWorkspaces = DEFAULT_WORKSPACES,\n  defaultActiveId = 'ws-1',\n  user = DEFAULT_USER,\n  className,\n  onChange,\n  onCreate,\n  onAction,\n}: EnterpriseWorkspaceSwitcherProps) {\n  const [workspaces, setWorkspaces] = React.useState<WorkspaceItem[]>(initialWorkspaces)\n  const [activeWorkspaceId, setActiveWorkspaceId] = React.useState<string>(defaultActiveId)\n  const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false)\n\n  // Dialog Form State\n  const [newOrgName, setNewOrgName] = React.useState('Stripe Developer Platform')\n  const [newOrgRegion, setNewOrgRegion] = React.useState('us-east')\n  const [newOrgPlan, setNewOrgPlan] = React.useState('pro')\n\n  const activeWorkspace = React.useMemo(() => {\n    return (\n      workspaces.find((w) => w.id === activeWorkspaceId) ||\n      workspaces[0] || {\n        id: 'ws-fallback',\n        name: 'Workspace',\n        plan: 'Standard',\n        planTier: 'Standard',\n        members: 1,\n        region: 'US-East',\n        regionCode: 'US-East',\n        role: 'Owner',\n        color: 'bg-muted text-foreground border border-border',\n        initials: 'WS',\n      }\n    )\n  }, [workspaces, activeWorkspaceId])\n\n  const slugPreview = React.useMemo(() => {\n    const cleaned = newOrgName\n      .trim()\n      .toLowerCase()\n      .replace(/[^a-z0-9]+/g, '-')\n      .replace(/^-+|-+$/g, '')\n    return cleaned || 'stripe-dev'\n  }, [newOrgName])\n\n  const handleSelectWorkspace = (workspace: WorkspaceItem) => {\n    setActiveWorkspaceId(workspace.id)\n    onChange?.(workspace)\n  }\n\n  const handleCreateWorkspace = (e: React.FormEvent) => {\n    e.preventDefault()\n    if (!newOrgName.trim()) return\n\n    const regionMap: Record<string, { full: string; code: string }> = {\n      'us-east': { full: 'US East (N. Virginia)', code: 'US-East' },\n      'eu-central': { full: 'EU Central (Frankfurt)', code: 'EU-Central' },\n      'ap-south': { full: 'AP South (Mumbai)', code: 'AP-South' },\n    }\n\n    const regionInfo = regionMap[newOrgRegion] || {\n      full: 'US East (N. Virginia)',\n      code: 'US-East',\n    }\n\n    const parts = newOrgName.trim().split(/\\s+/)\n    const initials =\n      parts.length > 1\n        ? `${parts[0]?.[0] || ''}${parts[1]?.[0] || ''}`.toUpperCase()\n        : (parts[0]?.slice(0, 2) || 'WS').toUpperCase()\n\n    const newWs: WorkspaceItem = {\n      id: `ws-${Date.now()}`,\n      name: newOrgName.trim(),\n      slug: slugPreview,\n      plan: newOrgPlan === 'enterprise' ? 'Enterprise Scale' : 'Pro Team',\n      planTier: newOrgPlan === 'enterprise' ? 'Enterprise Custom' : 'Pro Team',\n      members: 1,\n      region: regionInfo.full,\n      regionCode: regionInfo.code,\n      role: 'Owner',\n      color:\n        newOrgPlan === 'enterprise'\n          ? 'bg-primary/10 text-primary border border-primary/20'\n          : 'bg-info/10 text-info border border-info/20',\n      initials,\n    }\n\n    setWorkspaces((prev) => [newWs, ...prev])\n    setActiveWorkspaceId(newWs.id)\n    onCreate?.(newWs)\n    onChange?.(newWs)\n\n    setNewOrgName('')\n    setIsCreateDialogOpen(false)\n  }\n\n  const userInitials = React.useMemo(() => {\n    return (\n      user.name\n        .split(' ')\n        .map((p) => p[0])\n        .join('')\n        .toUpperCase() || 'U'\n    )\n  }, [user.name])\n\n  return (\n    <div data-slot=\"enterprise-workspace-switcher\" className={cn('w-full', className)}>\n      <DropdownMenu>\n        <DropdownMenuTrigger asChild>\n          <button\n            type=\"button\"\n            className=\"group border-border/80 bg-card hover:bg-accent/40 focus-visible:ring-ring flex w-full items-center gap-3 rounded-xl border p-2.5 text-left shadow-xs transition-[background-color,box-shadow] duration-150 focus-visible:ring-2 focus-visible:outline-none\"\n            aria-label=\"Select organization workspace\"\n          >\n            {/* Org Avatar / Monogram with Emerald Ring */}\n            <div className=\"relative size-10 shrink-0\">\n              <div\n                className={cn(\n                  'flex size-10 items-center justify-center rounded-lg text-sm font-semibold shadow-2xs',\n                  activeWorkspace.color,\n                )}\n              >\n                {activeWorkspace.initials}\n              </div>\n              <span\n                className=\"border-card bg-success absolute -top-0.5 -right-0.5 size-2.5 rounded-full border-2\"\n                title=\"Active Organization\"\n                aria-label=\"Active workspace status: Online\"\n              />\n            </div>\n\n            {/* Active Org Info & Role Badge */}\n            <div className=\"min-w-0 flex-1\">\n              <div className=\"flex items-center gap-1.5\">\n                <span className=\"text-foreground truncate text-sm font-semibold tracking-tight\">\n                  {activeWorkspace.name}\n                </span>\n                <Badge variant=\"secondary\" className=\"shrink-0 px-1.5 py-0 text-xs font-medium\">\n                  {activeWorkspace.role}\n                </Badge>\n              </div>\n              <div className=\"text-muted-foreground mt-0.5 flex items-center gap-1.5 truncate text-xs\">\n                <span className=\"truncate font-medium\">Tier: {activeWorkspace.plan}</span>\n                <span className=\"shrink-0\">{activeWorkspace.regionCode}</span>\n              </div>\n            </div>\n\n            {/* Chevron Icon */}\n            <ChevronsUpDown className=\"text-muted-foreground/70 group-hover:text-foreground size-4 shrink-0 transition-colors\" />\n          </button>\n        </DropdownMenuTrigger>\n\n        <DropdownMenuContent\n          className=\"border-border bg-popover w-80 rounded-xl p-2 shadow-xl sm:w-96\"\n          align=\"start\"\n          sideOffset={6}\n        >\n          {/* User Header Profile Info */}\n          <DropdownMenuLabel className=\"p-0 font-normal\">\n            <div className=\"bg-muted/40 flex items-center gap-2.5 rounded-lg px-2.5 py-2 text-left\">\n              <Avatar className=\"size-8 rounded-full border\">\n                {user.avatar ? <AvatarImage src={user.avatar} alt={user.name} /> : null}\n                <AvatarFallback className=\"bg-primary/10 text-primary text-xs font-bold\">{userInitials}</AvatarFallback>\n              </Avatar>\n              <div className=\"grid min-w-0 flex-1 text-left leading-tight\">\n                <span className=\"text-muted-foreground text-xs font-medium\">Signed in as</span>\n                <span className=\"text-foreground truncate text-xs font-semibold\">{user.email}</span>\n              </div>\n              <div className=\"flex items-center gap-1\">\n                <span className=\"bg-success size-2 rounded-full\" />\n                <span className=\"text-muted-foreground text-xs font-medium\">Ready</span>\n              </div>\n            </div>\n          </DropdownMenuLabel>\n\n          <DropdownMenuSeparator className=\"my-1.5\" />\n\n          {/* Workspaces Section */}\n          <div className=\"flex items-center justify-between px-2 py-1\">\n            <span className=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Workspaces</span>\n            <span className=\"text-muted-foreground/70 text-xs\">{workspaces.length} total</span>\n          </div>\n\n          <div className=\"my-1 space-y-1\">\n            {workspaces.map((ws) => (\n              <DropdownMenuItem\n                key={ws.id}\n                className=\"hover:bg-accent focus:bg-accent flex cursor-pointer items-center gap-3 rounded-lg p-2 transition-colors\"\n                onSelect={() => handleSelectWorkspace(ws)}\n              >\n                <div\n                  className={cn(\n                    'flex size-8 shrink-0 items-center justify-center rounded-lg text-xs font-semibold shadow-2xs',\n                    ws.color,\n                  )}\n                >\n                  {ws.initials}\n                </div>\n\n                <div className=\"min-w-0 flex-1\">\n                  <div className=\"flex items-center gap-1.5\">\n                    <span\n                      className={cn(\n                        'truncate text-sm font-medium',\n                        activeWorkspaceId === ws.id ? 'text-foreground font-semibold' : 'text-foreground/90',\n                      )}\n                    >\n                      {ws.name}\n                    </span>\n                    {ws.role === 'Owner' && (\n                      <Badge variant=\"secondary\" className=\"shrink-0 px-1 py-0 text-xs font-medium\">\n                        Owner\n                      </Badge>\n                    )}\n                    {ws.role === 'Admin' && (\n                      <Badge variant=\"outline\" className=\"shrink-0 px-1 py-0 text-xs font-medium\">\n                        Admin\n                      </Badge>\n                    )}\n                  </div>\n                  <p className=\"text-muted-foreground truncate text-xs\">\n                    {ws.planTier} · {ws.members} Member{ws.members === 1 ? '' : 's'} · {ws.regionCode}\n                  </p>\n                </div>\n\n                {activeWorkspaceId === ws.id && <Check className=\"text-success size-4 shrink-0\" aria-hidden=\"true\" />}\n              </DropdownMenuItem>\n            ))}\n          </div>\n\n          <DropdownMenuSeparator className=\"my-1.5\" />\n\n          {/* Actions */}\n          <DropdownMenuGroup>\n            <DropdownMenuItem\n              className=\"text-foreground hover:bg-accent focus:bg-accent flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 text-sm transition-colors\"\n              onSelect={() => setIsCreateDialogOpen(true)}\n            >\n              <div className=\"border-primary/30 bg-primary/10 text-primary flex size-6 items-center justify-center rounded-md border\">\n                <Plus className=\"size-3.5\" />\n              </div>\n              <span className=\"font-medium\">Create New Workspace</span>\n            </DropdownMenuItem>\n\n            <DropdownMenuItem\n              className=\"text-muted-foreground hover:text-foreground hover:bg-accent focus:bg-accent flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 text-sm transition-colors\"\n              onSelect={() => onAction?.('settings')}\n            >\n              <div className=\"border-border bg-muted flex size-6 items-center justify-center rounded-md border\">\n                <Settings className=\"size-3.5\" />\n              </div>\n              <span>Organization Settings & Billing</span>\n            </DropdownMenuItem>\n\n            <DropdownMenuItem\n              className=\"text-muted-foreground hover:text-foreground hover:bg-accent focus:bg-accent flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 text-sm transition-colors\"\n              onSelect={() => onAction?.('invite')}\n            >\n              <div className=\"border-border bg-muted flex size-6 items-center justify-center rounded-md border\">\n                <UserPlus className=\"size-3.5\" />\n              </div>\n              <span>Invite Team Members</span>\n            </DropdownMenuItem>\n          </DropdownMenuGroup>\n\n          <DropdownMenuSeparator className=\"my-1.5\" />\n\n          {/* Logout */}\n          <DropdownMenuItem\n            className=\"text-destructive hover:bg-destructive/10 focus:bg-destructive/10 focus:text-destructive flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 text-sm font-medium transition-colors\"\n            onSelect={() => onAction?.('logout')}\n          >\n            <div className=\"border-destructive/20 bg-destructive/10 text-destructive flex size-6 items-center justify-center rounded-md border\">\n              <LogOut className=\"size-3.5\" />\n            </div>\n            <span>Log out</span>\n          </DropdownMenuItem>\n        </DropdownMenuContent>\n      </DropdownMenu>\n\n      {/* Create New Workspace Modal Dialog */}\n      <Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>\n        <DialogContent className=\"border-border bg-background rounded-2xl p-6 shadow-sm sm:max-w-lg\">\n          <DialogHeader className=\"space-y-2 text-left\">\n            <div className=\"border-primary/20 bg-primary/10 text-primary flex size-10 items-center justify-center rounded-xl border shadow-xs\">\n              <Building2 className=\"size-5\" />\n            </div>\n            <DialogTitle className=\"text-foreground text-lg font-bold tracking-tight\">Create New Workspace</DialogTitle>\n            <DialogDescription className=\"text-muted-foreground text-sm leading-relaxed\">\n              Spin up a dedicated organization workspace with multi-region routing and isolated billing.\n            </DialogDescription>\n          </DialogHeader>\n\n          <form className=\"space-y-4 py-2\" onSubmit={handleCreateWorkspace}>\n            {/* Workspace Name */}\n            <div className=\"space-y-1.5\">\n              <label htmlFor=\"new-workspace-name-react\" className=\"text-foreground text-sm font-medium\">\n                Workspace Name\n              </label>\n              <Input\n                id=\"new-workspace-name-react\"\n                value={newOrgName}\n                onChange={(e) => setNewOrgName(e.target.value)}\n                placeholder=\"e.g. Stripe Developer Platform\"\n                autoComplete=\"off\"\n                className=\"h-10 text-sm\"\n                required\n              />\n            </div>\n\n            {/* URL Slug Preview */}\n            <div className=\"space-y-1.5\">\n              <label className=\"text-muted-foreground text-xs font-medium\">Workspace URL Slug</label>\n              <div className=\"border-border bg-muted/40 flex items-center gap-2 rounded-lg border px-3 py-2 text-xs\">\n                <Globe className=\"text-muted-foreground size-4 shrink-0\" aria-hidden=\"true\" />\n                <span className=\"text-muted-foreground\">uipkge.dev/</span>\n                <span className=\"text-foreground truncate font-semibold\">{slugPreview}</span>\n              </div>\n            </div>\n\n            {/* Primary Region Selection */}\n            <div className=\"space-y-1.5\">\n              <label className=\"text-foreground text-sm font-medium\">Primary Region</label>\n              <Select value={newOrgRegion} onValueChange={setNewOrgRegion}>\n                <SelectTrigger className=\"h-10 w-full\">\n                  <SelectValue placeholder=\"Select primary region\" />\n                </SelectTrigger>\n                <SelectContent>\n                  <SelectItem value=\"us-east\">US East (N. Virginia)</SelectItem>\n                  <SelectItem value=\"eu-central\">EU Central (Frankfurt)</SelectItem>\n                  <SelectItem value=\"ap-south\">AP South (Mumbai)</SelectItem>\n                </SelectContent>\n              </Select>\n              <p className=\"text-muted-foreground text-xs\">\n                Primary cluster location for low-latency queries and database replication.\n              </p>\n            </div>\n\n            {/* Plan Selection Radios */}\n            <div className=\"space-y-2\">\n              <label className=\"text-foreground text-sm font-medium\">Choose Workspace Plan</label>\n              <RadioGroup\n                value={newOrgPlan}\n                onValueChange={setNewOrgPlan}\n                className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\"\n              >\n                <label\n                  htmlFor=\"plan-pro-react\"\n                  className={cn(\n                    'border-border/80 hover:border-primary/50 relative flex cursor-pointer flex-col justify-between rounded-xl border p-3.5 shadow-xs transition-colors',\n                    newOrgPlan === 'pro' && 'border-primary bg-primary/5 ring-primary/40 shadow-sm ring-1',\n                  )}\n                >\n                  <div className=\"flex items-start justify-between gap-2\">\n                    <div className=\"space-y-0.5\">\n                      <span className=\"text-foreground text-sm font-semibold\">Pro Team</span>\n                      <p className=\"text-primary text-xs font-medium\">$29 / month</p>\n                    </div>\n                    <RadioGroupItem id=\"plan-pro-react\" value=\"pro\" className=\"mt-0.5\" />\n                  </div>\n                  <p className=\"text-muted-foreground mt-2 text-xs leading-relaxed\">\n                    Up to 25 members, standard 99.9% SLA, and daily automated backups.\n                  </p>\n                </label>\n\n                <label\n                  htmlFor=\"plan-enterprise-react\"\n                  className={cn(\n                    'border-border/80 hover:border-primary/50 relative flex cursor-pointer flex-col justify-between rounded-xl border p-3.5 shadow-xs transition-colors',\n                    newOrgPlan === 'enterprise' && 'border-primary bg-primary/5 ring-primary/40 shadow-sm ring-1',\n                  )}\n                >\n                  <div className=\"flex items-start justify-between gap-2\">\n                    <div className=\"space-y-0.5\">\n                      <span className=\"text-foreground text-sm font-semibold\">Enterprise Scale</span>\n                      <p className=\"text-primary text-xs font-medium\">Custom billing</p>\n                    </div>\n                    <RadioGroupItem id=\"plan-enterprise-react\" value=\"enterprise\" className=\"mt-0.5\" />\n                  </div>\n                  <p className=\"text-muted-foreground mt-2 text-xs leading-relaxed\">\n                    Unlimited members, dedicated VPC peering, 99.99% uptime SLA & SSO.\n                  </p>\n                </label>\n              </RadioGroup>\n            </div>\n\n            <DialogFooter className=\"border-border/60 flex gap-2 border-t pt-4 sm:justify-end\">\n              <Button type=\"button\" variant=\"outline\" onClick={() => setIsCreateDialogOpen(false)}>\n                Cancel\n              </Button>\n              <Button type=\"submit\" disabled={!newOrgName.trim()}>\n                Create Workspace\n              </Button>\n            </DialogFooter>\n          </form>\n        </DialogContent>\n      </Dialog>\n    </div>\n  )\n}\n\nexport default EnterpriseWorkspaceSwitcher\n",
      "type": "registry:block",
      "target": "~/components/blocks/EnterpriseWorkspaceSwitcher.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/avatar.json",
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/dialog.json",
    "https://uipkge.dev/r/react/dropdown-menu.json",
    "https://uipkge.dev/r/react/input.json",
    "https://uipkge.dev/r/react/radio-group.json",
    "https://uipkge.dev/r/react/select.json"
  ],
  "description": "Multi-organization workspace switcher dropdown and creation modal inspired by Portico/Riter. Features active organization display with emerald ring, 3 tier levels (Enterprise Scale, Pro Team, Free Sandbox), team role badges, member counts, and an organization creation dialog with dynamic slug preview, region selector, and tier plan radios.",
  "categories": [
    "layout",
    "dashboard",
    "navigation",
    "overlay"
  ]
}