{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "enterprise-workspace-switcher",
  "title": "Enterprise Workspace Switcher",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/enterprise-workspace-switcher/EnterpriseWorkspaceSwitcher.svelte",
      "content": "<script lang=\"ts\" module>\n  export 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\n  export interface UserInfo {\n    name: string\n    email: string\n    avatar?: string\n  }\n\n  export interface EnterpriseWorkspaceSwitcherProps {\n    initialWorkspaces?: WorkspaceItem[]\n    defaultActiveId?: string\n    user?: UserInfo\n    class?: string\n    onChange?: (workspace: WorkspaceItem) => void\n    onCreate?: (workspace: WorkspaceItem) => void\n    onAction?: (key: 'settings' | 'billing' | 'invite' | 'logout') => void\n  }\n\n  const 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\n  const DEFAULT_USER: UserInfo = {\n    name: 'Elena Rostova',\n    email: 'elena@uipkge.dev',\n    avatar: '',\n  }\n</script>\n\n<script lang=\"ts\">\n  import { Building2, Check, ChevronsUpDown, Globe, LogOut, Plus, Settings, UserPlus } from '@lucide/svelte'\n  import { Avatar, AvatarFallback, AvatarImage } from '$lib/components/ui/avatar'\n  import { Badge } from '$lib/components/ui/badge'\n  import { Button } from '$lib/components/ui/button'\n  import {\n    Dialog,\n    DialogContent,\n    DialogDescription,\n    DialogFooter,\n    DialogHeader,\n    DialogTitle,\n  } from '$lib/components/ui/dialog'\n  import {\n    DropdownMenu,\n    DropdownMenuContent,\n    DropdownMenuGroup,\n    DropdownMenuItem,\n    DropdownMenuLabel,\n    DropdownMenuSeparator,\n    DropdownMenuTrigger,\n  } from '$lib/components/ui/dropdown-menu'\n  import { Input } from '$lib/components/ui/input'\n  import { RadioGroup, RadioGroupItem } from '$lib/components/ui/radio-group'\n  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '$lib/components/ui/select'\n  import { cn } from '$lib/utils'\n\n  let {\n    initialWorkspaces = DEFAULT_WORKSPACES,\n    defaultActiveId = 'ws-1',\n    user = DEFAULT_USER,\n    class: className,\n    onChange,\n    onCreate,\n    onAction,\n  }: EnterpriseWorkspaceSwitcherProps = $props()\n\n  let workspaces = $state<WorkspaceItem[]>([...initialWorkspaces])\n  let activeWorkspaceId = $state<string>(defaultActiveId)\n  let isCreateDialogOpen = $state(false)\n\n  const activeWorkspace = $derived(\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' as const,\n        color: 'bg-muted text-foreground border border-border',\n        initials: 'WS',\n      },\n  )\n\n  // Dialog Form State\n  let newOrgName = $state('Stripe Developer Platform')\n  let newOrgRegion = $state('us-east')\n  let newOrgPlan = $state('pro')\n\n  const slugPreview = $derived(\n    newOrgName\n      .trim()\n      .toLowerCase()\n      .replace(/[^a-z0-9]+/g, '-')\n      .replace(/^-+|-+$/g, '') || 'stripe-dev',\n  )\n\n  const userInitials = $derived(\n    user.name\n      .split(' ')\n      .map((p) => p[0])\n      .join('')\n      .toUpperCase() || 'U',\n  )\n\n  function selectWorkspace(workspace: WorkspaceItem) {\n    activeWorkspaceId = workspace.id\n    onChange?.(workspace)\n  }\n\n  function handleCreateWorkspace(e: SubmitEvent) {\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    workspaces = [newWs, ...workspaces]\n    activeWorkspaceId = newWs.id\n    onCreate?.(newWs)\n    onChange?.(newWs)\n\n    // Reset form\n    newOrgName = ''\n    isCreateDialogOpen = false\n  }\n</script>\n\n<div data-slot=\"enterprise-workspace-switcher\" class={cn('w-full', className)}>\n  <DropdownMenu>\n    <DropdownMenuTrigger>\n      {#snippet child({ props })}\n        <button\n          {...props}\n          type=\"button\"\n          class=\"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 class=\"relative size-10 shrink-0\">\n            <div\n              class={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              class=\"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            ></span>\n          </div>\n\n          <!-- Active Org Info & Role Badge -->\n          <div class=\"min-w-0 flex-1\">\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"text-foreground truncate text-sm font-semibold tracking-tight\">\n                {activeWorkspace.name}\n              </span>\n              <Badge variant=\"secondary\" class=\"shrink-0 px-1.5 py-0 text-xs font-medium\">\n                {activeWorkspace.role}\n              </Badge>\n            </div>\n            <div class=\"text-muted-foreground mt-0.5 flex items-center gap-1.5 truncate text-xs\">\n              <span class=\"truncate font-medium\">Tier: {activeWorkspace.plan}</span>\n              <span class=\"shrink-0\">{activeWorkspace.regionCode}</span>\n            </div>\n          </div>\n\n          <!-- Chevron Icon -->\n          <ChevronsUpDown\n            class=\"text-muted-foreground/70 group-hover:text-foreground size-4 shrink-0 transition-colors\"\n          />\n        </button>\n      {/snippet}\n    </DropdownMenuTrigger>\n\n    <DropdownMenuContent class=\"border-border bg-popover w-80 rounded-xl p-2 shadow-xl sm:w-96\" align=\"start\" sideOffset={6}>\n      <!-- User Header Profile Info -->\n      <DropdownMenuLabel class=\"p-0 font-normal\">\n        <div class=\"bg-muted/40 flex items-center gap-2.5 rounded-lg px-2.5 py-2 text-left\">\n          <Avatar class=\"size-8 rounded-full border\">\n            {#if user.avatar}\n              <AvatarImage src={user.avatar} alt={user.name} />\n            {/if}\n            <AvatarFallback class=\"bg-primary/10 text-primary text-xs font-bold\">\n              {userInitials}\n            </AvatarFallback>\n          </Avatar>\n          <div class=\"grid min-w-0 flex-1 text-left leading-tight\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Signed in as</span>\n            <span class=\"text-foreground truncate text-xs font-semibold\">{user.email}</span>\n          </div>\n          <div class=\"flex items-center gap-1\">\n            <span class=\"bg-success size-2 rounded-full\"></span>\n            <span class=\"text-muted-foreground text-xs font-medium\">Ready</span>\n          </div>\n        </div>\n      </DropdownMenuLabel>\n\n      <DropdownMenuSeparator class=\"my-1.5\" />\n\n      <!-- Workspaces Section -->\n      <div class=\"flex items-center justify-between px-2 py-1\">\n        <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\"> Workspaces </span>\n        <span class=\"text-muted-foreground/70 text-xs\">{workspaces.length} total</span>\n      </div>\n\n      <div class=\"my-1 space-y-1\">\n        {#each workspaces as ws (ws.id)}\n          <DropdownMenuItem\n            class=\"hover:bg-accent focus:bg-accent flex cursor-pointer items-center gap-3 rounded-lg p-2 transition-colors\"\n            onSelect={() => selectWorkspace(ws)}\n          >\n            <div\n              class={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 class=\"min-w-0 flex-1\">\n              <div class=\"flex items-center gap-1.5\">\n                <span\n                  class={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                {#if ws.role === 'Owner'}\n                  <Badge variant=\"secondary\" class=\"shrink-0 px-1 py-0 text-xs font-medium\">Owner</Badge>\n                {:else if ws.role === 'Admin'}\n                  <Badge variant=\"outline\" class=\"shrink-0 px-1 py-0 text-xs font-medium\">Admin</Badge>\n                {/if}\n              </div>\n              <p class=\"text-muted-foreground truncate text-xs\">\n                {ws.planTier} · {ws.members} Member{ws.members === 1 ? '' : 's'} · {ws.regionCode}\n              </p>\n            </div>\n\n            {#if activeWorkspaceId === ws.id}\n              <Check class=\"text-success size-4 shrink-0\" aria-hidden=\"true\" />\n            {/if}\n          </DropdownMenuItem>\n        {/each}\n      </div>\n\n      <DropdownMenuSeparator class=\"my-1.5\" />\n\n      <!-- Actions -->\n      <DropdownMenuGroup>\n        <DropdownMenuItem\n          class=\"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={() => (isCreateDialogOpen = true)}\n        >\n          <div\n            class=\"border-primary/30 bg-primary/10 text-primary flex size-6 items-center justify-center rounded-md border\"\n          >\n            <Plus class=\"size-3.5\" />\n          </div>\n          <span class=\"font-medium\">Create New Workspace</span>\n        </DropdownMenuItem>\n\n        <DropdownMenuItem\n          class=\"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 class=\"border-border bg-muted flex size-6 items-center justify-center rounded-md border\">\n            <Settings class=\"size-3.5\" />\n          </div>\n          <span>Organization Settings & Billing</span>\n        </DropdownMenuItem>\n\n        <DropdownMenuItem\n          class=\"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 class=\"border-border bg-muted flex size-6 items-center justify-center rounded-md border\">\n            <UserPlus class=\"size-3.5\" />\n          </div>\n          <span>Invite Team Members</span>\n        </DropdownMenuItem>\n      </DropdownMenuGroup>\n\n      <DropdownMenuSeparator class=\"my-1.5\" />\n\n      <!-- Logout -->\n      <DropdownMenuItem\n        class=\"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\n          class=\"border-destructive/20 bg-destructive/10 text-destructive flex size-6 items-center justify-center rounded-md border\"\n        >\n          <LogOut class=\"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 bind:open={isCreateDialogOpen}>\n    <DialogContent class=\"border-border bg-background rounded-2xl p-6 shadow-sm sm:max-w-lg\">\n      <DialogHeader class=\"space-y-2 text-left\">\n        <div\n          class=\"border-primary/20 bg-primary/10 text-primary flex size-10 items-center justify-center rounded-xl border shadow-xs\"\n        >\n          <Building2 class=\"size-5\" />\n        </div>\n        <DialogTitle class=\"text-foreground text-lg font-bold tracking-tight\"> Create New Workspace </DialogTitle>\n        <DialogDescription class=\"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 class=\"space-y-4 py-2\" onsubmit={handleCreateWorkspace}>\n        <!-- Workspace Name -->\n        <div class=\"space-y-1.5\">\n          <label for=\"new-workspace-name\" class=\"text-foreground text-sm font-medium\"> Workspace Name </label>\n          <Input\n            id=\"new-workspace-name\"\n            bind:value={newOrgName}\n            placeholder=\"e.g. Stripe Developer Platform\"\n            autocomplete=\"off\"\n            class=\"h-10 text-sm\"\n            required\n          />\n        </div>\n\n        <!-- URL Slug Preview -->\n        <div class=\"space-y-1.5\">\n          <span class=\"text-muted-foreground text-xs font-medium\"> Workspace URL Slug </span>\n          <div class=\"border-border bg-muted/40 flex items-center gap-2 rounded-lg border px-3 py-2 text-xs\">\n            <Globe class=\"text-muted-foreground size-4 shrink-0\" aria-hidden=\"true\" />\n            <span class=\"text-muted-foreground\">uipkge.dev/</span>\n            <span class=\"text-foreground truncate font-semibold\">{slugPreview}</span>\n          </div>\n        </div>\n\n        <!-- Primary Region Selection -->\n        <div class=\"space-y-1.5\">\n          <span class=\"text-foreground text-sm font-medium\"> Primary Region </span>\n          <Select bind:value={newOrgRegion}>\n            <SelectTrigger class=\"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 class=\"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 class=\"space-y-2\">\n          <span class=\"text-foreground text-sm font-medium\"> Choose Workspace Plan </span>\n          <RadioGroup bind:value={newOrgPlan} class=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n            <label\n              for=\"plan-pro\"\n              class={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 class=\"flex items-start justify-between gap-2\">\n                <div class=\"space-y-0.5\">\n                  <span class=\"text-foreground text-sm font-semibold\">Pro Team</span>\n                  <p class=\"text-primary text-xs font-medium\">$29 / month</p>\n                </div>\n                <RadioGroupItem id=\"plan-pro\" value=\"pro\" class=\"mt-0.5\" />\n              </div>\n              <p class=\"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              for=\"plan-enterprise\"\n              class={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 class=\"flex items-start justify-between gap-2\">\n                <div class=\"space-y-0.5\">\n                  <span class=\"text-foreground text-sm font-semibold\">Enterprise Scale</span>\n                  <p class=\"text-primary text-xs font-medium\">Custom billing</p>\n                </div>\n                <RadioGroupItem id=\"plan-enterprise\" value=\"enterprise\" class=\"mt-0.5\" />\n              </div>\n              <p class=\"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 class=\"border-border/60 flex gap-2 border-t pt-4 sm:justify-end\">\n          <Button type=\"button\" variant=\"outline\" onclick={() => (isCreateDialogOpen = false)}> Cancel </Button>\n          <Button type=\"submit\" disabled={!newOrgName.trim()}> Create Workspace </Button>\n        </DialogFooter>\n      </form>\n    </DialogContent>\n  </Dialog>\n</div>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/enterprise-workspace-switcher/EnterpriseWorkspaceSwitcher.svelte"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/avatar.json",
    "https://uipkge.dev/r/svelte/badge.json",
    "https://uipkge.dev/r/svelte/button.json",
    "https://uipkge.dev/r/svelte/dialog.json",
    "https://uipkge.dev/r/svelte/dropdown-menu.json",
    "https://uipkge.dev/r/svelte/input.json",
    "https://uipkge.dev/r/svelte/radio-group.json",
    "https://uipkge.dev/r/svelte/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"
  ]
}