"use client" import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from "react" import { useServerInsertedHTML } from "next/navigation" const STORAGE_KEY = "rl-theme" const MEDIA_QUERY = "(prefers-color-scheme: dark)" const THEMES = ["light", "dark", "system"] as const type Theme = (typeof THEMES)[number] type ResolvedTheme = "light" | "dark" const THEME_INIT_SCRIPT = `(function(){try{var k="${STORAGE_KEY}",d="dark",e=document.documentElement,t=localStorage.getItem(k)||d,s=function(){return window.matchMedia("${MEDIA_QUERY}").matches?"dark":"light"}();if(t==="system")t=s;e.classList.remove("light","dark");e.classList.add(t);e.style.colorScheme=t}catch(n){}})()` type ThemeContextValue = { theme: Theme | undefined setTheme: (theme: Theme | ((prev: Theme) => Theme)) => void resolvedTheme: ResolvedTheme | undefined systemTheme: ResolvedTheme | undefined themes: readonly Theme[] } const ThemeContext = createContext(undefined) type ThemeProviderProps = { children: ReactNode defaultTheme?: Theme enableSystem?: boolean disableTransitionOnChange?: boolean } function readStoredTheme(defaultTheme: Theme, enableSystem: boolean): Theme { try { const stored = localStorage.getItem(STORAGE_KEY) if (stored === "light" || stored === "dark") return stored if (enableSystem && stored === "system") return stored } catch { // ignore } return defaultTheme } function resolveTheme(theme: Theme, systemTheme: ResolvedTheme): ResolvedTheme { return theme === "system" ? systemTheme : theme } function applyThemeClass(resolved: ResolvedTheme, disableTransitionOnChange: boolean) { const root = document.documentElement if (disableTransitionOnChange) { const style = document.createElement("style") style.appendChild( document.createTextNode( "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}", ), ) document.head.appendChild(style) window.getComputedStyle(document.body) setTimeout(() => { document.head.removeChild(style) }, 1) } root.classList.remove("light", "dark") root.classList.add(resolved) root.style.colorScheme = resolved } export function ThemeProvider({ children, defaultTheme = "dark", enableSystem = true, disableTransitionOnChange = false, }: ThemeProviderProps) { useServerInsertedHTML(() => (