{"version":3,"sources":["../src/index.ts","../src/ThemeProvider.tsx","../src/useDarkMode.tsx","../src/ThemeScript.tsx","../src/ThemeToggle.tsx"],"sourcesContent":["export { ThemeProvider, useTheme } from \"./ThemeProvider\";\r\nexport { ThemeScript } from \"./ThemeScript\";\r\nexport { ThemeToggle } from \"./ThemeToggle\";\r\nexport type { Theme, ThemeContextValue } from \"./types\";\r\n","\"use client\";\r\n\r\nimport React, { createContext, useContext } from \"react\";\r\nimport type { Theme, ThemeContextValue } from \"./types\";\r\nimport { useDarkMode } from \"./useDarkMode\";\r\n\r\nconst ThemeCtx = createContext<ThemeContextValue | null>(null);\r\n\r\nexport function ThemeProvider({\r\n  children,\r\n  defaultTheme = \"system\"\r\n}: {\r\n  children: React.ReactNode;\r\n  defaultTheme?: Theme;\r\n}) {\r\n  const value = useDarkMode(defaultTheme);\r\n  return <ThemeCtx.Provider value={value}>{children}</ThemeCtx.Provider>;\r\n}\r\n\r\nexport function useTheme() {\r\n  const ctx = useContext(ThemeCtx);\r\n  if (!ctx) throw new Error(\"useTheme must be used within ThemeProvider\");\r\n  return ctx;\r\n}\r\n","\"use client\";\r\n\r\nimport { useEffect, useMemo, useState } from \"react\";\r\nimport type { Theme } from \"./types\";\r\n\r\nconst THEME_KEY = \"theme\";\r\n\r\nfunction getSystemTheme(): \"light\" | \"dark\" {\r\n  if (typeof window === \"undefined\") return \"light\";\r\n  return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\r\n}\r\n\r\nfunction applyThemeToDocument(resolved: \"light\" | \"dark\") {\r\n  if (typeof document === \"undefined\") return;\r\n  const root = document.documentElement;\r\n  root.dataset.theme = resolved;\r\n  if (resolved === \"dark\") root.classList.add(\"dark\");\r\n  else root.classList.remove(\"dark\");\r\n}\r\n\r\nexport function useDarkMode(initial: Theme = \"system\") {\r\n  const [theme, setTheme] = useState<Theme>(initial);\r\n  const resolvedTheme = useMemo(\r\n    () => (theme === \"system\" ? getSystemTheme() : theme),\r\n    [theme]\r\n  );\r\n  const isDark = resolvedTheme === \"dark\";\r\n\r\n  // load stored theme on mount\r\n  useEffect(() => {\r\n    try {\r\n      const stored = localStorage.getItem(THEME_KEY) as Theme | null;\r\n      if (stored === \"light\" || stored === \"dark\" || stored === \"system\") {\r\n        setTheme(stored);\r\n      }\r\n    } catch {}\r\n    // react to system changes\r\n    const mql = window.matchMedia(\"(prefers-color-scheme: dark)\");\r\n    const handler = () => {\r\n      if (theme === \"system\") applyThemeToDocument(getSystemTheme());\r\n    };\r\n    mql.addEventListener?.(\"change\", handler);\r\n    return () => mql.removeEventListener?.(\"change\", handler);\r\n    // eslint-disable-next-line react-hooks/exhaustive-deps\r\n  }, []);\r\n\r\n  // apply + persist\r\n  useEffect(() => {\r\n    try {\r\n      localStorage.setItem(THEME_KEY, theme);\r\n    } catch {}\r\n    applyThemeToDocument(resolvedTheme);\r\n  }, [theme, resolvedTheme]);\r\n\r\n  const toggle = () =>\r\n    setTheme((prev) =>\r\n      prev === \"light\" ? \"dark\" : prev === \"dark\" ? \"system\" : \"light\"\r\n    );\r\n\r\n  return { theme, resolvedTheme, isDark, setTheme, toggle } as const;\r\n}\r\n","import React from \"react\";\r\n\r\n/**\r\n * Inline script to apply the correct theme BEFORE React hydration,\r\n * avoiding flash of wrong theme.\r\n */\r\nexport function ThemeScript() {\r\n  const code = `\r\n  (() => {\r\n    try {\r\n      const key = 'theme';\r\n      const stored = localStorage.getItem(key);\r\n      const isValid = v => v === 'light' || v === 'dark' || v === 'system';\r\n      const mql = window.matchMedia('(prefers-color-scheme: dark)');\r\n      const system = mql.matches ? 'dark' : 'light';\r\n      const theme = isValid(stored) ? stored : 'system';\r\n      const resolved = theme === 'system' ? system : theme;\r\n      const root = document.documentElement;\r\n      root.dataset.theme = resolved;\r\n      if (resolved === 'dark') root.classList.add('dark'); else root.classList.remove('dark');\r\n    } catch {}\r\n  })();\r\n  `;\r\n  // biome-ignore lint/security/noDangerouslySetInnerHtml: needed here\r\n  return <script dangerouslySetInnerHTML={{ __html: code }} />;\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { useTheme } from \"./ThemeProvider\";\r\n\r\nconst LABEL = {\r\n  light: \"🌞 light\",\r\n  dark: \"🌜 dark\",\r\n  system: \"🖥️ system\"\r\n} as const;\r\n\r\nexport function ThemeToggle() {\r\n  const { theme, resolvedTheme, toggle, setTheme } = useTheme();\r\n\r\n  return (\r\n    <div style={{ display: \"inline-flex\", gap: 8, alignItems: \"center\" }}>\r\n      <button onClick={toggle} aria-label=\"Toggle theme\"\r\n        style={{ padding: \"6px 10px\", borderRadius: 8, border: \"1px solid currentColor\" }}>\r\n        toggle ({LABEL[theme]}) → {resolvedTheme}\r\n      </button>\r\n\r\n      {/* quick set */}\r\n      <select\r\n        value={theme}\r\n        onChange={(e) => setTheme(e.target.value as any)}\r\n        style={{ padding: \"6px 10px\", borderRadius: 8 }}>\r\n        <option value=\"system\">system</option>\r\n        <option value=\"light\">light</option>\r\n        <option value=\"dark\">dark</option>\r\n      </select>\r\n    </div>\r\n  )\r\n}\r\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime"]}