{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "status-theme-switcher",
  "title": "Status Theme Switcher",
  "description": "Agnostic light/dark/system theme switcher. Caller owns the value and onValueChange wiring (next-themes, form state, etc.)",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://openstatus.dev/r/status-i18n.json",
    "https://openstatus.dev/r/status-types.json",
    "button",
    "dropdown-menu",
    "skeleton"
  ],
  "files": [
    {
      "path": "src/components/blocks/status-theme-switcher.tsx",
      "content": "\"use client\";\n\nimport { useStatusBlocksLabels } from \"@/components/blocks/status-i18n\";\nimport {\n  THEME_VALUES,\n  type ThemeValue,\n} from \"@/components/blocks/status.types\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport { cn } from \"@/lib/utils\";\nimport { Laptop, Moon, Sun } from \"lucide-react\";\n\nexport type { ThemeValue };\n\nfunction ThemeIcon({\n  value,\n  className,\n}: {\n  value: ThemeValue;\n  className?: string;\n}) {\n  const Icon = value === \"light\" ? Sun : value === \"dark\" ? Moon : Laptop;\n  return <Icon className={cn(\"h-4 w-4\", className)} />;\n}\n\n/**\n * StatusThemeSwitcher — agnostic light/dark/system switcher.\n *\n * Pure presentation: caller owns the value and onValueChange wiring (next-themes,\n * form state, etc.). The block does no hydration handling — render a Skeleton\n * yourself before the active theme is known.\n */\nexport function StatusThemeSwitcher({\n  value,\n  onValueChange,\n  className,\n  ...props\n}: Omit<\n  React.ComponentProps<typeof DropdownMenuTrigger>,\n  \"value\" | \"onValueChange\"\n> & {\n  value: ThemeValue;\n  onValueChange: (value: ThemeValue) => void;\n}) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild className={className} {...props}>\n        <Button data-slot=\"status-theme-switcher\" variant=\"ghost\" size=\"icon\">\n          <ThemeIcon value={value} />\n          <span className=\"sr-only\">{labels.ariaToggleTheme}</span>\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\" alignOffset={-4}>\n        {THEME_VALUES.map((v) => {\n          const isActive = v === value;\n          return (\n            <DropdownMenuItem\n              data-slot=\"status-theme-switcher-item\"\n              key={v}\n              onClick={() => onValueChange(v)}\n            >\n              <span>{labels.themeNames[v]}</span>\n              <span className=\"ml-auto\">\n                <ThemeIcon\n                  value={v}\n                  className={\n                    isActive ? \"text-foreground\" : \"text-muted-foreground\"\n                  }\n                />\n              </span>\n            </DropdownMenuItem>\n          );\n        })}\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n\n/**\n * StatusThemeSwitcherSkeleton — same footprint as the trigger button.\n * Render while the active theme isn't known yet (e.g. before next-themes\n * hydrates) so the surrounding layout doesn't shift.\n */\nexport function StatusThemeSwitcherSkeleton({\n  className,\n  ...props\n}: React.ComponentProps<typeof Skeleton>) {\n  return (\n    <Skeleton\n      data-slot=\"status-theme-switcher-skeleton\"\n      className={cn(\"size-9\", className)}\n      {...props}\n    />\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/blocks/status-theme-switcher.tsx"
    }
  ],
  "type": "registry:block"
}