@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
JavaScript
;
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,
};
}