{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "theme-toggler",
  "title": "Theme Toggler",
  "description": "Wipes the new theme in as a circle using View Transitions.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/theme-toggler.tsx",
      "content": "\"use client\";\n\nimport { useRef } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface ThemeTogglerProps {\n  /** Current theme; drives the icon and the accessible label */\n  isDark: boolean;\n  /** Apply the theme change. Called inside a View Transition when supported. */\n  onToggle: () => void;\n  className?: string;\n}\n\n/**\n * Light/dark switch that wipes the new theme in as an expanding circle from\n * the button itself, using the View Transitions API where it exists and\n * falling back to a plain toggle everywhere else.\n */\nexport function ThemeToggler({\n  isDark,\n  onToggle,\n  className,\n}: ThemeTogglerProps) {\n  const ref = useRef<HTMLButtonElement>(null);\n\n  const handleClick = async () => {\n    const reduced = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n    const startViewTransition = document.startViewTransition?.bind(document);\n\n    if (!startViewTransition || reduced) {\n      onToggle();\n      return;\n    }\n\n    const rect = ref.current?.getBoundingClientRect();\n    const x = rect ? rect.left + rect.width / 2 : window.innerWidth / 2;\n    const y = rect ? rect.top + rect.height / 2 : window.innerHeight / 2;\n    // Radius that reaches the furthest corner of the viewport.\n    const radius = Math.hypot(\n      Math.max(x, window.innerWidth - x),\n      Math.max(y, window.innerHeight - y)\n    );\n\n    await startViewTransition(onToggle).ready;\n\n    document.documentElement.animate(\n      {\n        clipPath: [\n          `circle(0px at ${x}px ${y}px)`,\n          `circle(${radius}px at ${x}px ${y}px)`,\n        ],\n      },\n      {\n        duration: 480,\n        easing: \"ease-in-out\",\n        pseudoElement: \"::view-transition-new(root)\",\n      }\n    );\n  };\n\n  return (\n    <button\n      ref={ref}\n      type=\"button\"\n      data-slot=\"theme-toggler\"\n      onClick={handleClick}\n      aria-label={isDark ? \"Switch to light theme\" : \"Switch to dark theme\"}\n      className={cn(\n        \"grid size-9 cursor-pointer place-items-center rounded-lg border bg-background transition-colors hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\",\n        className\n      )}\n    >\n      <svg\n        width=\"17\"\n        height=\"17\"\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.75\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        aria-hidden\n      >\n        {isDark ? (\n          <>\n            <circle cx=\"12\" cy=\"12\" r=\"4\" />\n            <path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4\" />\n          </>\n        ) : (\n          <path d=\"M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z\" />\n        )}\n      </svg>\n    </button>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/theme-toggler.tsx"
    }
  ],
  "type": "registry:ui"
}