"use client"; import { Moon, Sun } from "lucide-react"; import { createContext, type ReactNode, useContext, useMemo, useSyncExternalStore, } from "react"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; type DashboardTheme = "light" | "dark"; type DashboardThemeContextValue = { theme: DashboardTheme; toggleTheme: () => void; }; const storageKey = "webdev-dashboard-theme"; const themeChangeEvent = "webdev-dashboard-theme-change"; const DashboardThemeContext = createContext(null); function isDashboardTheme(value: string | null): value is DashboardTheme { return value === "dark" || value === "light"; } function getStoredDashboardTheme(): DashboardTheme { const storedTheme = window.localStorage.getItem(storageKey); return isDashboardTheme(storedTheme) ? storedTheme : "light"; } function getServerDashboardTheme(): DashboardTheme { return "light"; } function subscribeToDashboardTheme(onStoreChange: () => void) { window.addEventListener("storage", onStoreChange); window.addEventListener(themeChangeEvent, onStoreChange); return () => { window.removeEventListener("storage", onStoreChange); window.removeEventListener(themeChangeEvent, onStoreChange); }; } export function DashboardThemeProvider({ children }: { children: ReactNode }) { const theme = useSyncExternalStore( subscribeToDashboardTheme, getStoredDashboardTheme, getServerDashboardTheme, ); const value = useMemo( () => ({ theme, toggleTheme: () => { const nextTheme = theme === "dark" ? "light" : "dark"; window.localStorage.setItem(storageKey, nextTheme); window.dispatchEvent(new Event(themeChangeEvent)); }, }), [theme], ); return (
{children}
); } export function DashboardThemeToggle() { const context = useContext(DashboardThemeContext); if (!context) { return null; } const isDark = context.theme === "dark"; const Icon = isDark ? Sun : Moon; return ( ); }