{"version":3,"file":"ThemeProvider.mjs","sources":["../../../src/lib/theme/ThemeProvider.tsx"],"sourcesContent":["import React, {\n  useContext,\n  useState,\n  useEffect,\n  useCallback,\n  useMemo,\n  type ReactNode,\n} from 'react';\nimport { ThemeContext, type ThemeContextValue } from '../contexts/ThemeContext';\nimport { lightPalette } from './palettes/light';\nimport { darkPalette } from './palettes/dark';\nimport { tokens } from './tokens';\nimport { useFeatureFlag } from '../flags/useFeatureFlag';\nimport { flagKeys } from '../flags/flag-keys';\n\ntype Theme = 'light' | 'dark' | 'system';\n\nconst THEME_STORAGE_KEY = 'app-theme';\n\nfunction getSystemTheme(): 'light' | 'dark' {\n  if (typeof window === 'undefined') return 'light';\n  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nfunction getStoredTheme(): Theme {\n  if (typeof window === 'undefined') return 'system';\n  const stored = localStorage.getItem(THEME_STORAGE_KEY);\n  if (stored === 'light' || stored === 'dark' || stored === 'system') {\n    return stored;\n  }\n  return 'system';\n}\n\ninterface ThemeProviderProps {\n  children: ReactNode;\n  defaultTheme?: Theme;\n}\n\n/**\n * Global theme context with persistence + dark/light mode.\n * Respects the 'dark-mode' feature flag - when disabled, forces light mode only.\n */\nexport function ThemeProvider({ children, defaultTheme }: ThemeProviderProps): React.ReactElement {\n  // Check if dark mode toggle is enabled via feature flag\n  const darkModeEnabled = useFeatureFlag(flagKeys.DARK_MODE);\n\n  const [theme, setThemeState] = useState<Theme>(() => {\n    // If dark mode is disabled, always use light theme\n    if (!darkModeEnabled) return 'light';\n    return defaultTheme ?? getStoredTheme();\n  });\n  const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>(() => {\n    // If dark mode is disabled, always resolve to light\n    if (!darkModeEnabled) return 'light';\n    const initial = defaultTheme ?? getStoredTheme();\n    return initial === 'system' ? getSystemTheme() : initial;\n  });\n\n  // Update resolved theme when theme or system preference changes\n  useEffect(() => {\n    const resolved = theme === 'system' ? getSystemTheme() : theme;\n\n    // Apply theme to document and update state\n    queueMicrotask(() => {\n      document.documentElement.classList.remove('light', 'dark');\n      document.documentElement.classList.add(resolved);\n      document.documentElement.setAttribute('data-theme', resolved);\n      setResolvedTheme(resolved);\n    });\n  }, [theme]);\n\n  // Listen for system theme changes\n  useEffect(() => {\n    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n\n    const handleChange = (): void => {\n      if (theme === 'system') {\n        const newResolved = getSystemTheme();\n        setResolvedTheme(newResolved);\n        document.documentElement.classList.remove('light', 'dark');\n        document.documentElement.classList.add(newResolved);\n        document.documentElement.setAttribute('data-theme', newResolved);\n      }\n    };\n\n    mediaQuery.addEventListener('change', handleChange);\n    return () => mediaQuery.removeEventListener('change', handleChange);\n  }, [theme]);\n\n  const setTheme = useCallback(\n    (newTheme: Theme) => {\n      // If dark mode is disabled, ignore attempts to set dark/system themes\n      if (!darkModeEnabled && (newTheme === 'dark' || newTheme === 'system')) {\n        console.warn(\n          '[ThemeProvider] Dark mode is disabled via feature flag. Ignoring theme change.'\n        );\n        return;\n      }\n      setThemeState(newTheme);\n      localStorage.setItem(THEME_STORAGE_KEY, newTheme);\n    },\n    [darkModeEnabled]\n  );\n\n  const toggleTheme = useCallback(() => {\n    // If dark mode is disabled, do nothing\n    if (!darkModeEnabled) {\n      console.warn(\n        '[ThemeProvider] Dark mode is disabled via feature flag. Theme toggle is disabled.'\n      );\n      return;\n    }\n    setTheme(resolvedTheme === 'light' ? 'dark' : 'light');\n  }, [darkModeEnabled, resolvedTheme, setTheme]);\n\n  const palette = useMemo(\n    () => (resolvedTheme === 'dark' ? darkPalette : lightPalette),\n    [resolvedTheme]\n  );\n\n  // PERFORMANCE: Memoize context value to prevent unnecessary re-renders\n  const value: ThemeContextValue = useMemo(\n    () => ({\n      theme,\n      resolvedTheme,\n      setTheme,\n      toggleTheme,\n      palette,\n      tokens,\n      darkModeEnabled,\n    }),\n    [theme, resolvedTheme, setTheme, toggleTheme, palette, darkModeEnabled]\n  );\n\n  return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\n/**\n * Hook to access the theme context.\n */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useThemeContext(): ThemeContextValue {\n  const context = useContext(ThemeContext);\n  if (!context) {\n    throw new Error('useThemeContext must be used within a ThemeProvider');\n  }\n  return context;\n}\n"],"names":["THEME_STORAGE_KEY","getSystemTheme","getStoredTheme","stored","ThemeProvider","children","defaultTheme","darkModeEnabled","useFeatureFlag","flagKeys","theme","setThemeState","useState","resolvedTheme","setResolvedTheme","initial","useEffect","resolved","mediaQuery","handleChange","newResolved","setTheme","useCallback","newTheme","toggleTheme","palette","useMemo","darkPalette","lightPalette","value","tokens","jsx","ThemeContext","useThemeContext","context","useContext"],"mappings":"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"}