'use client' import React, { createContext, useContext, useEffect, useState } from 'react' export type Theme = 'dark' | 'light' | 'system' export type ResolvedTheme = 'dark' | 'light' interface ThemeContextValue { theme: Theme resolvedTheme: ResolvedTheme setTheme: (theme: Theme) => void } const ThemeContext = createContext(null) export function ThemeProvider({ children, defaultTheme = 'dark', storageKey = 'ui-theme', }: { children: React.ReactNode defaultTheme?: Theme storageKey?: string }) { const [theme, setThemeState] = useState(defaultTheme) const [resolvedTheme, setResolvedTheme] = useState('dark') useEffect(() => { const stored = localStorage.getItem(storageKey) as Theme | null if (stored && ['dark', 'light', 'system'].includes(stored)) { setThemeState(stored) } }, [storageKey]) useEffect(() => { const root = document.documentElement const apply = (resolved: ResolvedTheme) => { setResolvedTheme(resolved) if (resolved === 'light') { root.classList.add('light') } else { root.classList.remove('light') } } if (theme === 'system') { const mq = window.matchMedia('(prefers-color-scheme: light)') apply(mq.matches ? 'light' : 'dark') const handler = (e: MediaQueryListEvent) => apply(e.matches ? 'light' : 'dark') mq.addEventListener('change', handler) return () => mq.removeEventListener('change', handler) } else { apply(theme) } }, [theme]) const setTheme = (t: Theme) => { setThemeState(t) localStorage.setItem(storageKey, t) } return ( {children} ) } export function useTheme(): ThemeContextValue { const ctx = useContext(ThemeContext) if (!ctx) throw new Error('useTheme must be used within a ThemeProvider') return ctx }