UNPKG

polen

Version:

A framework for delightful GraphQL developer portals

68 lines 2.98 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { createContext, useContext, useEffect, useState } from 'react'; import * as Theme from '../../lib/theme/theme.js'; const ThemeContext = createContext(undefined); // Create theme manager instance const themeManager = Theme.createThemeManager({ cookieName: `polen-theme-preference`, }); // Theme CSS component to ensure consistent CSS on server and client const ThemeCSS = () => { const css = themeManager.getCSS(); return _jsx("style", { dangerouslySetInnerHTML: { __html: css } }); }; export const ThemeProvider = ({ children }) => { const [appearance, setAppearance] = useState(() => { // Initial appearance from server or browser const serverTheme = globalThis.__POLEN__.serverContext.theme; if (serverTheme === 'system') { // During SSR, default to light for system preference // Client will detect actual preference on mount return typeof globalThis.window !== 'undefined' ? (globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : 'light'; } return serverTheme; }); const [preference, setPreference] = useState(() => { // Initial preference from server-rendered theme const serverTheme = globalThis.__POLEN__.serverContext.theme; // If server sent a specific theme (from cookie), use that as preference // Otherwise it's system preference return serverTheme; }); useEffect(() => { // Apply theme preference to DOM on mount and when it changes themeManager.applyToDOM(preference); // Update appearance based on preference if (preference === 'system') { const systemTheme = globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; setAppearance(systemTheme); // Listen for system theme changes const mediaQuery = globalThis.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e) => { if (preference === 'system') { setAppearance(e.matches ? 'dark' : 'light'); } }; mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); } else { setAppearance(preference); } }, [preference]); const toggleTheme = () => { const newPref = themeManager.toggle(); setPreference(newPref); }; return (_jsxs(ThemeContext.Provider, { value: { appearance, preference, toggleTheme }, children: [_jsx(ThemeCSS, {}), children] })); }; export const useTheme = () => { const context = useContext(ThemeContext); if (!context) { throw new Error(`useTheme must be used within a ThemeProvider`); } return context; }; //# sourceMappingURL=ThemeContext.js.map