UNPKG

@asgerami/zemenay-blog

Version:

Plug-and-play blog system for Next.js - Get a fully functional blog running in minutes with zero configuration

88 lines (87 loc) 3.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTheme = useTheme; const react_1 = require("react"); function useTheme() { const [theme, setThemeState] = (0, react_1.useState)("system"); const [resolvedTheme, setResolvedTheme] = (0, react_1.useState)("light"); const [mounted, setMounted] = (0, react_1.useState)(false); // Get system preference const getSystemTheme = (0, react_1.useCallback)(() => { if (typeof window === "undefined") return "light"; return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; }, []); // Resolve theme based on current setting const resolveTheme = (0, react_1.useCallback)((currentTheme) => { if (currentTheme === "system") { return getSystemTheme(); } return currentTheme; }, [getSystemTheme]); // Apply theme to document const applyTheme = (0, react_1.useCallback)((resolvedTheme) => { if (typeof window === "undefined") return; const root = document.documentElement; root.classList.remove("light", "dark"); root.classList.add(resolvedTheme); root.setAttribute("data-theme", resolvedTheme); }, []); // Set theme and persist to localStorage const setTheme = (0, react_1.useCallback)((newTheme) => { setThemeState(newTheme); if (typeof window !== "undefined") { localStorage.setItem("zemenay-blog-theme", newTheme); } const resolved = resolveTheme(newTheme); setResolvedTheme(resolved); applyTheme(resolved); }, [resolveTheme, applyTheme]); // Toggle between light and dark (ignoring system) const toggleTheme = (0, react_1.useCallback)(() => { const newTheme = resolvedTheme === "light" ? "dark" : "light"; setTheme(newTheme); }, [resolvedTheme, setTheme]); // Initialize theme on mount (0, react_1.useEffect)(() => { if (typeof window === "undefined") return; // Check if theme was already applied by the script const preAppliedTheme = window.__ZEMENAY_THEME__; if (preAppliedTheme) { // Use the theme that was already applied to prevent flash setThemeState(preAppliedTheme.theme); setResolvedTheme(preAppliedTheme.resolvedTheme); } else { // Fallback to normal initialization const savedTheme = localStorage.getItem("zemenay-blog-theme"); const initialTheme = savedTheme || "system"; setThemeState(initialTheme); const resolved = resolveTheme(initialTheme); setResolvedTheme(resolved); applyTheme(resolved); } setMounted(true); // Listen for system theme changes const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); const handleSystemThemeChange = () => { if (theme === "system") { const newResolved = getSystemTheme(); setResolvedTheme(newResolved); applyTheme(newResolved); } }; mediaQuery.addEventListener("change", handleSystemThemeChange); return () => mediaQuery.removeEventListener("change", handleSystemThemeChange); }, [theme, resolveTheme, applyTheme, getSystemTheme]); return { theme, resolvedTheme, setTheme, toggleTheme, }; }