"use client"; import { useCallback, useSyncExternalStore } from "react"; import { applyTheme, currentTheme, DEFAULT_THEME, THEME_KEY, type Theme } from "./theme"; const listeners = new Set<() => void>(); function subscribe(listener: () => void): () => void { listeners.add(listener); const onStorage = (event: StorageEvent) => { // Another tab changed the theme: follow it. if (event.key !== THEME_KEY) return; const next = event.newValue === "light" || event.newValue === "dark" ? event.newValue : DEFAULT_THEME; applyTheme(next, document.documentElement, null); listeners.forEach((l) => l()); }; window.addEventListener("storage", onStorage); return () => { listeners.delete(listener); window.removeEventListener("storage", onStorage); }; } const getSnapshot = (): Theme => currentTheme(document.documentElement); const getServerSnapshot = (): Theme => DEFAULT_THEME; function safeStorage(): Storage | null { try { return window.localStorage; } catch { return null; } } /** Shared theme state for every toggle: the current theme and a setter. */ export function useTheme(): { theme: Theme; setTheme: (theme: Theme) => void; toggleTheme: () => void } { const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); const setTheme = useCallback((next: Theme) => { applyTheme(next, document.documentElement, safeStorage()); listeners.forEach((l) => l()); }, []); const toggleTheme = useCallback(() => setTheme(getSnapshot() === "dark" ? "light" : "dark"), [setTheme]); return { theme, setTheme, toggleTheme }; }