resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
345 lines • 28.8 kB
JavaScript
/**
* Theme System
* Uses Signal<CSSVars> with functor map patterns for reactive theming
*/
import { signal, computed } from '../core/signal';
import { bindAttribute } from '../dom';
// Theme manager using functor map patterns
export class ThemeManager {
constructor(config) {
this.config = config;
this.themes = new Map();
this.currentTheme = signal(config.defaultTheme);
// this._cssVars = signal({}); // Unused for now
this.computedVars = signal({});
this.setupColorUtils();
this.setupStyleElement();
this.setupComputedVars();
this.loadPersistedTheme();
this.setupAutoDetection();
}
// Setup color manipulation utilities
setupColorUtils() {
this.colorUtils = {
lighten: (color, amount) => {
return this.adjustHSL(color, 0, 0, amount);
},
darken: (color, amount) => {
return this.adjustHSL(color, 0, 0, -amount);
},
saturate: (color, amount) => {
return this.adjustHSL(color, 0, amount, 0);
},
desaturate: (color, amount) => {
return this.adjustHSL(color, 0, -amount, 0);
},
alpha: (color, alpha) => {
const rgb = this.hexToRgb(color);
return rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : color;
},
mix: (color1, color2, weight) => {
const rgb1 = this.hexToRgb(color1);
const rgb2 = this.hexToRgb(color2);
if (!rgb1 || !rgb2)
return color1;
const w = weight / 100;
const r = Math.round(rgb1.r * (1 - w) + rgb2.r * w);
const g = Math.round(rgb1.g * (1 - w) + rgb2.g * w);
const b = Math.round(rgb1.b * (1 - w) + rgb2.b * w);
return `rgb(${r}, ${g}, ${b})`;
},
};
}
// Setup style element for CSS injection
setupStyleElement() {
this.styleElement = document.createElement('style');
this.styleElement.id = 'signal-sigma-theme';
document.head.appendChild(this.styleElement);
// Add transition styles if configured
if (this.config.transitions) {
const { duration, easing, properties } = this.config.transitions;
const transitionCSS = `
* {
transition: ${properties.join(` ${duration} ${easing}, `)} ${duration} ${easing};
}
`;
this.styleElement.textContent = transitionCSS;
}
}
// Setup computed variables using functor map
setupComputedVars() {
this.computedVars = computed(() => {
const currentThemeName = this.currentTheme.value();
const theme = this.themes.get(currentThemeName);
if (!theme)
return {};
// Apply functor map to transform CSS variables
return this.mapCSSVars(theme.variables, (cssVar) => {
// Apply transformations based on type
switch (cssVar.type) {
case 'color':
return this.processColorVar(cssVar);
case 'length':
return this.processLengthVar(cssVar);
case 'number':
return this.processNumberVar(cssVar);
default:
return cssVar;
}
});
});
// Subscribe to computed variables and update DOM
this.computedVars.subscribe((vars) => {
this.applyCSSVars(vars);
});
}
// Functor map implementation for CSS variables
mapCSSVars(vars, transform) {
const result = {};
Object.entries(vars).forEach(([key, cssVar]) => {
result[key] = transform(cssVar, key);
});
return result;
}
// Process color variables with functor transformations
processColorVar(cssVar) {
let value = cssVar.value;
// Apply color transformations based on naming conventions
if (cssVar.name.includes('light')) {
value = this.colorUtils.lighten(value, 10);
}
else if (cssVar.name.includes('dark')) {
value = this.colorUtils.darken(value, 10);
}
else if (cssVar.name.includes('muted')) {
value = this.colorUtils.desaturate(value, 20);
}
return { ...cssVar, value };
}
// Process length variables
processLengthVar(cssVar) {
// Apply responsive scaling or other transformations
return cssVar;
}
// Process number variables
processNumberVar(cssVar) {
// Apply mathematical transformations
return cssVar;
}
// Apply CSS variables to DOM
applyCSSVars(vars) {
const cssText = Object.values(vars)
.map((cssVar) => ` ${cssVar.name}: ${cssVar.value};`)
.join('\n');
const rootCSS = `:root {\n${cssText}\n}`;
// Update style element
const existingCSS = this.styleElement.textContent || '';
const rootRegex = /:root\s*{[^}]*}/;
if (rootRegex.test(existingCSS)) {
this.styleElement.textContent = existingCSS.replace(rootRegex, rootCSS);
}
else {
this.styleElement.textContent = existingCSS + '\n' + rootCSS;
}
}
// Load persisted theme
loadPersistedTheme() {
if (!this.config.persistKey)
return;
try {
const saved = localStorage.getItem(this.config.persistKey);
if (saved && this.themes.has(saved)) {
this.currentTheme._set(saved);
}
}
catch (error) {
console.warn('Failed to load persisted theme:', error);
}
}
// Setup automatic theme detection
setupAutoDetection() {
if (!this.config.autoDetect)
return;
// Listen for system theme changes
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = (e) => {
const prefersDark = e.matches;
const autoTheme = prefersDark ? 'dark' : 'light';
if (this.themes.has(autoTheme)) {
this.setTheme(autoTheme);
}
};
mediaQuery.addEventListener('change', handleChange);
// Initial detection
handleChange({ matches: mediaQuery.matches });
}
// Color utility functions
hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
adjustHSL(color, _h, _s, _l) {
// Simplified HSL adjustment - in production, use a proper color library
return color; // Placeholder implementation
}
// Public API
// Register theme
registerTheme(theme) {
// Extend base theme if specified
if (theme.extends) {
const baseTheme = this.themes.get(theme.extends);
if (baseTheme) {
theme.variables = { ...baseTheme.variables, ...theme.variables };
}
}
this.themes.set(theme.name, theme);
// Set as current if it's the default
if (theme.name === this.config.defaultTheme) {
this.currentTheme._set(theme.name);
}
}
// Set current theme
setTheme(themeName) {
if (!this.themes.has(themeName)) {
console.warn(`Theme "${themeName}" not found`);
return;
}
this.currentTheme._set(themeName);
// Persist if configured
if (this.config.persistKey) {
try {
localStorage.setItem(this.config.persistKey, themeName);
}
catch (error) {
console.warn('Failed to persist theme:', error);
}
}
}
// Get current theme signal
getCurrentTheme() {
return this.currentTheme;
}
// Get CSS variables signal
getCSSVars() {
return this.computedVars;
}
// Get available themes
getThemes() {
return Array.from(this.themes.values());
}
// Create themed signal that maps values based on current theme
createThemedSignal(mapping, fallback) {
return computed(() => {
const currentThemeName = this.currentTheme.value();
return mapping[currentThemeName] || fallback;
});
}
// Create CSS variable signal
createCSSVarSignal(varName) {
return computed(() => {
const vars = this.computedVars.value();
const cssVar = Object.values(vars).find((v) => v.name === varName);
return cssVar?.value || '';
});
}
// Apply theme to specific element
applyToElement(element, vars) {
const unsubscribers = [];
if (vars) {
// Apply specific variables
vars.forEach((varName) => {
const varSignal = this.createCSSVarSignal(varName);
const unsubscribe = bindAttribute(element, `data-${varName}`, varSignal);
unsubscribers.push(unsubscribe);
});
}
else {
// Apply theme class
const themeSignal = computed(() => `theme-${this.currentTheme.value()}`);
const unsubscribe = bindAttribute(element, 'data-theme', themeSignal);
unsubscribers.push(unsubscribe);
}
return () => {
unsubscribers.forEach((unsub) => unsub());
};
}
// Get color utilities
getColorUtils() {
return this.colorUtils;
}
// Cleanup
destroy() {
this.styleElement.remove();
}
}
// Factory function for creating theme manager
export const createThemeManager = (config) => {
return new ThemeManager(config);
};
// Predefined theme builders using functor patterns
export const createLightTheme = (overrides = {}) => ({
name: 'light',
displayName: 'Light Theme',
variables: {
primary: { name: '--color-primary', value: '#007bff', type: 'color' },
secondary: { name: '--color-secondary', value: '#6c757d', type: 'color' },
background: { name: '--color-background', value: '#ffffff', type: 'color' },
surface: { name: '--color-surface', value: '#f8f9fa', type: 'color' },
text: { name: '--color-text', value: '#212529', type: 'color' },
textMuted: { name: '--color-text-muted', value: '#6c757d', type: 'color' },
border: { name: '--color-border', value: '#dee2e6', type: 'color' },
shadow: {
name: '--shadow',
value: '0 2px 4px rgba(0,0,0,0.1)',
type: 'string',
},
borderRadius: { name: '--border-radius', value: '4px', type: 'length' },
spacing: { name: '--spacing', value: '1rem', type: 'length' },
...overrides,
},
});
export const createDarkTheme = (overrides = {}) => ({
name: 'dark',
displayName: 'Dark Theme',
variables: {
primary: { name: '--color-primary', value: '#0d6efd', type: 'color' },
secondary: { name: '--color-secondary', value: '#6c757d', type: 'color' },
background: { name: '--color-background', value: '#121212', type: 'color' },
surface: { name: '--color-surface', value: '#1e1e1e', type: 'color' },
text: { name: '--color-text', value: '#ffffff', type: 'color' },
textMuted: { name: '--color-text-muted', value: '#adb5bd', type: 'color' },
border: { name: '--color-border', value: '#495057', type: 'color' },
shadow: {
name: '--shadow',
value: '0 2px 4px rgba(0,0,0,0.3)',
type: 'string',
},
borderRadius: { name: '--border-radius', value: '4px', type: 'length' },
spacing: { name: '--spacing', value: '1rem', type: 'length' },
...overrides,
},
});
// Theme composition utilities using functor map
export const composeThemes = (base, ...overlays) => {
return overlays.reduce((result, overlay) => ({
...result,
...overlay,
variables: { ...result.variables, ...overlay.variables },
}), base);
};
export const mapThemeColors = (theme, transform) => ({
...theme,
variables: Object.fromEntries(Object.entries(theme.variables).map(([key, cssVar]) => [
key,
cssVar.type === 'color'
? { ...cssVar, value: transform(cssVar.value) }
: cssVar,
])),
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhlbWUtc3lzdGVtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2V4dGVuc2lvbnMvdGhlbWUtc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBVSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQStDdkMsMkNBQTJDO0FBQzNDLE1BQU0sT0FBTyxZQUFZO0lBUXZCLFlBQW9CLE1BQW1CO1FBQW5CLFdBQU0sR0FBTixNQUFNLENBQWE7UUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNoRCxnREFBZ0Q7UUFDaEQsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRCxxQ0FBcUM7SUFDN0IsZUFBZTtRQUNyQixJQUFJLENBQUMsVUFBVSxHQUFHO1lBQ2hCLE9BQU8sRUFBRSxDQUFDLEtBQWEsRUFBRSxNQUFjLEVBQUUsRUFBRTtnQkFDekMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzdDLENBQUM7WUFFRCxNQUFNLEVBQUUsQ0FBQyxLQUFhLEVBQUUsTUFBYyxFQUFFLEVBQUU7Z0JBQ3hDLE9BQU8s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