import { createContext, useContext, useEffect, useState } from 'react' export type Theme = 'light' | 'dark' | 'system' export type ResolvedTheme = 'light' | 'dark' interface ThemeContextValue { theme: Theme resolved: ResolvedTheme setTheme: (theme: Theme) => void } const ThemeContext = createContext(null) function resolveTheme(theme: Theme): ResolvedTheme { if (theme !== 'system') return theme if (typeof window === 'undefined') return 'dark' return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } function updateMetaThemeColor(resolved: ResolvedTheme) { if (typeof document === 'undefined') return const meta = document.querySelector('meta[name="theme-color"]') if (!meta) return meta.setAttribute('content', resolved === 'dark' ? '#0A0A0B' : '#FAFAFA') } export function ThemeProvider({ children }: { children: React.ReactNode }) { const [theme, setThemeState] = useState(() => { try { const saved = localStorage.getItem('theme') if (saved === 'light' || saved === 'dark' || saved === 'system') return saved } catch {} return 'system' }) const [resolved, setResolved] = useState(() => resolveTheme(theme)) useEffect(() => { const nextResolved = resolveTheme(theme) setResolved(nextResolved) const root = document.documentElement root.classList.remove('light', 'dark') root.classList.add(nextResolved) try { localStorage.setItem('theme', theme) } catch {} updateMetaThemeColor(nextResolved) }, [theme]) useEffect(() => { if (theme !== 'system') return const media = window.matchMedia('(prefers-color-scheme: dark)') const handler = () => { const nextResolved = resolveTheme('system') setResolved(nextResolved) document.documentElement.classList.remove('light', 'dark') document.documentElement.classList.add(nextResolved) updateMetaThemeColor(nextResolved) } media.addEventListener('change', handler) return () => media.removeEventListener('change', handler) }, [theme]) const setTheme = (next: Theme) => { setThemeState(next) } return ( {children} ) } export function useTheme(): ThemeContextValue { const ctx = useContext(ThemeContext) if (!ctx) { throw new Error('useTheme must be used within ThemeProvider') } return ctx }