polen
Version:
A framework for delightful GraphQL developer portals
68 lines • 2.98 kB
JavaScript
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