import { createContext, type ReactNode, useContext, useEffect, useState } from 'react' export type Theme = 'dark' | 'light' | 'system' export const THEME_STORAGE_KEY = 'theme' interface ThemeProviderState { theme: Theme setTheme: (theme: Theme) => void } const ThemeProviderContext = createContext(null) const applyTheme = (theme: Theme) => { const root = document.documentElement const resolved = theme === 'system' ? window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' : theme root.classList.remove('light', 'dark') root.classList.add(resolved) } export function ThemeProvider({ children, defaultTheme = 'system', }: { children: ReactNode defaultTheme?: Theme }) { const [theme, setThemeState] = useState(defaultTheme) useEffect(() => { const stored = localStorage.getItem(THEME_STORAGE_KEY) as Theme | null if (stored) setThemeState(stored) }, []) useEffect(() => { applyTheme(theme) if (theme !== 'system') return const media = window.matchMedia('(prefers-color-scheme: dark)') const onChange = () => applyTheme('system') media.addEventListener('change', onChange) return () => media.removeEventListener('change', onChange) }, [theme]) const setTheme = (next: Theme) => { localStorage.setItem(THEME_STORAGE_KEY, next) setThemeState(next) } return ( {children} ) } export function useTheme() { const context = useContext(ThemeProviderContext) if (!context) { throw new Error('useTheme must be used within a ThemeProvider') } return context }