import { createContext, createEffect, createSignal, ParentComponent, useContext, } from "solid-js"; type Theme = "light" | "dark" | "system"; const STORAGE_KEY = "bookra-theme"; function getInitialTheme(): Theme { if (typeof window === "undefined") return "system"; const stored = localStorage.getItem(STORAGE_KEY) as Theme | null; return stored ?? "system"; } function getResolvedTheme(theme: Theme): "light" | "dark" { if (theme === "system") { return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; } return theme; } type ThemeContextValue = { theme: () => Theme; resolvedTheme: () => "light" | "dark"; setTheme: (theme: Theme) => void; toggle: () => void; }; const ThemeContext = createContext(); export const ThemeProvider: ParentComponent = (props) => { const [theme, setThemeSignal] = createSignal(getInitialTheme()); const [resolvedTheme, setResolvedTheme] = createSignal<"light" | "dark">( getResolvedTheme(getInitialTheme()) ); const applyTheme = (t: Theme) => { const resolved = getResolvedTheme(t); setResolvedTheme(resolved); const root = document.documentElement; root.classList.remove("light", "dark"); root.classList.add(resolved); root.setAttribute("data-theme", resolved); }; createEffect(() => { const t = theme(); localStorage.setItem(STORAGE_KEY, t); applyTheme(t); }); if (typeof window !== "undefined") { const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); mediaQuery.addEventListener("change", () => { if (theme() === "system") { applyTheme("system"); } }); } const setTheme = (t: Theme) => setThemeSignal(t); const toggle = () => { const current = resolvedTheme(); setTheme(current === "light" ? "dark" : "light"); }; return ( {props.children} ); }; export function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error("ThemeProvider is missing from the component tree."); } return context; }