import { DeesElement, type TemplateResult, property, customElement, html, css, cssManager, } from '@design.estate/dees-element'; import { type ITheme, type IThemeColors, type IThemeSpacing, type IThemeRadius, type IThemeShadows, type IThemeTransitions, type IThemeControlHeights, themeDefaults, themeDefaultStyles, } from '../00theme.js'; import { demoFunc } from './dees-theme.demo.js'; /** * A theme provider component that wraps children and provides CSS custom properties. * Can be used at the app root or around specific sections to customize theming. * * Usage: * ```html * * * * ``` * * With custom overrides: * ```html * * * * ``` */ @customElement('dees-theme') export class DeesTheme extends DeesElement { public static demo = demoFunc; // ============================================ // Properties for theme overrides // ============================================ @property({ type: Object }) accessor customSpacing: Partial | null = null; @property({ type: Object }) accessor customRadius: Partial | null = null; @property({ type: Object }) accessor customShadows: Partial | null = null; @property({ type: Object }) accessor customTransitions: Partial | null = null; @property({ type: Object }) accessor customControlHeights: Partial | null = null; // ============================================ // Styles // ============================================ public static styles = [ themeDefaultStyles, cssManager.defaultStyles, css` :host { display: contents; } `, ]; // ============================================ // Render // ============================================ public render(): TemplateResult { return html` `; } // ============================================ // Private Methods // ============================================ private generateCustomStyles(): string { const styles: string[] = [':host {']; // Custom spacing if (this.customSpacing) { for (const [key, value] of Object.entries(this.customSpacing)) { if (value) { styles.push(` --dees-spacing-${key}: ${value};`); } } } // Custom radius if (this.customRadius) { for (const [key, value] of Object.entries(this.customRadius)) { if (value) { styles.push(` --dees-radius-${key}: ${value};`); } } } // Custom shadows if (this.customShadows) { for (const [key, value] of Object.entries(this.customShadows)) { if (value) { styles.push(` --dees-shadow-${key}: ${value};`); } } } // Custom transitions if (this.customTransitions) { for (const [key, value] of Object.entries(this.customTransitions)) { if (value) { const cssKey = key === 'default' ? 'default' : key; styles.push(` --dees-transition-${cssKey}: ${value};`); } } } // Custom control heights if (this.customControlHeights) { for (const [key, value] of Object.entries(this.customControlHeights)) { if (value) { styles.push(` --dees-control-height-${key}: ${value};`); } } } styles.push('}'); return styles.join('\n'); } // ============================================ // Public API Methods // ============================================ /** * Set a spacing value dynamically */ public setSpacing(key: keyof IThemeSpacing, value: string): void { this.customSpacing = { ...this.customSpacing, [key]: value }; } /** * Set a radius value dynamically */ public setRadius(key: keyof IThemeRadius, value: string): void { this.customRadius = { ...this.customRadius, [key]: value }; } /** * Set a shadow value dynamically */ public setShadow(key: keyof IThemeShadows, value: string): void { this.customShadows = { ...this.customShadows, [key]: value }; } /** * Set a transition value dynamically */ public setTransition(key: keyof IThemeTransitions, value: string): void { this.customTransitions = { ...this.customTransitions, [key]: value }; } /** * Set a control height value dynamically */ public setControlHeight(key: keyof IThemeControlHeights, value: string): void { this.customControlHeights = { ...this.customControlHeights, [key]: value }; } /** * Get the current theme configuration (defaults + overrides) */ public getTheme(): ITheme { return { colors: themeDefaults.colors, spacing: { ...themeDefaults.spacing, ...this.customSpacing }, radius: { ...themeDefaults.radius, ...this.customRadius }, shadows: { ...themeDefaults.shadows, ...this.customShadows }, transitions: { ...themeDefaults.transitions, ...this.customTransitions }, controlHeights: { ...themeDefaults.controlHeights, ...this.customControlHeights }, }; } /** * Reset all custom overrides to defaults */ public resetToDefaults(): void { this.customSpacing = null; this.customRadius = null; this.customShadows = null; this.customTransitions = null; this.customControlHeights = null; } /** * Apply a complete theme object */ public applyTheme(theme: Partial): void { if (theme.spacing) this.customSpacing = theme.spacing; if (theme.radius) this.customRadius = theme.radius; if (theme.shadows) this.customShadows = theme.shadows; if (theme.transitions) this.customTransitions = theme.transitions; if (theme.controlHeights) this.customControlHeights = theme.controlHeights; } }