react-theme-system
Version:
A comprehensive React theme management system that enforces consistency, supports dark/light mode, and eliminates hardcoded styles
132 lines (131 loc) • 4.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useThemeToggleWithSystem = exports.useThemeToggle = void 0;
const react_1 = require("react");
const ThemeProvider_1 = require("../ThemeProvider");
/**
* Headless hook for theme toggle functionality
* Decouples theme logic from presentation, enabling custom UIs without fork-modifying
*
* @example
* ```tsx
* const { isDark, toggle, setTheme } = useThemeToggle();
*
* return (
* <button onClick={toggle}>
* {isDark ? '🌙' : '☀️'}
* </button>
* );
* ```
*/
const useThemeToggle = () => {
const { currentTheme, setTheme, isHydrated } = (0, ThemeProvider_1.useTheme)();
const isDark = currentTheme === 'dark';
const isLight = currentTheme === 'light';
const toggle = (0, react_1.useCallback)(() => {
if (!isHydrated)
return;
setTheme(isDark ? 'light' : 'dark');
}, [isDark, setTheme, isHydrated]);
const setLight = (0, react_1.useCallback)(() => {
if (!isHydrated)
return;
setTheme('light');
}, [setTheme, isHydrated]);
const setDark = (0, react_1.useCallback)(() => {
if (!isHydrated)
return;
setTheme('dark');
}, [setTheme, isHydrated]);
return {
// State
isDark,
isLight,
currentTheme,
isHydrated,
// Actions
toggle,
setLight,
setDark,
setTheme,
// Utilities
nextTheme: isDark ? 'light' : 'dark',
icon: isDark ? '🌙' : '☀️',
label: isDark ? 'Switch to light mode' : 'Switch to dark mode',
ariaLabel: isDark ? 'Switch to light mode' : 'Switch to dark mode'
};
};
exports.useThemeToggle = useThemeToggle;
/**
* Enhanced theme toggle hook with system theme detection
*
* @example
* ```tsx
* const { isDark, toggle, systemTheme, isSystemTheme } = useThemeToggleWithSystem();
*
* return (
* <div>
* <button onClick={toggle}>
* {isDark ? '🌙' : '☀️'}
* </button>
* {systemTheme && <span>System: {systemTheme}</span>}
* </div>
* );
* ```
*/
const useThemeToggleWithSystem = () => {
const { currentTheme, setTheme, isHydrated, systemTheme } = (0, ThemeProvider_1.useTheme)();
const isDark = currentTheme === 'dark';
const isLight = currentTheme === 'light';
const isSystemTheme = currentTheme === systemTheme;
const toggle = (0, react_1.useCallback)(() => {
if (!isHydrated)
return;
setTheme(isDark ? 'light' : 'dark');
}, [isDark, setTheme, isHydrated]);
const setSystem = (0, react_1.useCallback)(() => {
if (!isHydrated || !systemTheme)
return;
setTheme(systemTheme);
}, [systemTheme, setTheme, isHydrated]);
const cycleTheme = (0, react_1.useCallback)(() => {
if (!isHydrated)
return;
// Cycle: light -> dark -> system -> light
if (isLight) {
setTheme('dark');
}
else if (isDark) {
setTheme(systemTheme || 'light');
}
else {
setTheme('light');
}
}, [isLight, isDark, systemTheme, setTheme, isHydrated]);
return {
// State
isDark,
isLight,
currentTheme,
isHydrated,
systemTheme,
isSystemTheme,
// Actions
toggle,
setLight: () => setTheme('light'),
setDark: () => setTheme('dark'),
setSystem,
setTheme,
cycleTheme,
// Utilities
nextTheme: isDark ? 'light' : 'dark',
icon: isDark ? '🌙' : '☀️',
label: isDark ? 'Switch to light mode' : 'Switch to dark mode',
ariaLabel: isDark ? 'Switch to light mode' : 'Switch to dark mode',
// System theme utilities
systemIcon: systemTheme === 'dark' ? '🌙' : '☀️',
systemLabel: `Use system theme (${systemTheme})`,
hasSystemTheme: !!systemTheme
};
};
exports.useThemeToggleWithSystem = useThemeToggleWithSystem;