ezfw-core 1.0.84 → 1.0.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ # EzStyles - Sistema de Override de Estilos
2
+
3
+ ## Resumen
4
+
5
+ Sistema para permitir override de CSS variables por componente sin modificar el framework.
6
+ El usuario define variantes de estilo en `ez.styles.config.js` y las usa directamente como `eztype`.
7
+
8
+ ## API Final
9
+
10
+ ```javascript
11
+ // ez.styles.config.js (root del proyecto)
12
+ export default {
13
+ // Variables globales → se aplican a :root
14
+ theme: {
15
+ '--ez-primary': '#8b5cf6',
16
+ '--ez-radius-md': '12px',
17
+ },
18
+
19
+ // Variantes de componentes → se aplican inline al elemento
20
+ EzButton: {
21
+ ToolButton: {
22
+ '--ez-primary': '#10b981',
23
+ '--ez-primary-hover': '#059669',
24
+ },
25
+ CancelButton: {
26
+ '--ez-primary': '#ef4444',
27
+ },
28
+ },
29
+
30
+ EzInput: {
31
+ SearchInput: {
32
+ '--ez-radius-md': '9999px',
33
+ },
34
+ },
35
+ };
36
+ ```
37
+
38
+ ```javascript
39
+ // Uso - directo como eztype
40
+ { eztype: 'ToolButton', text: 'Tool' } // ← No necesita variant prop
41
+ { eztype: 'CancelButton', text: 'Cancel' }
42
+ { eztype: 'SearchInput', placeholder: 'Buscar...' }
43
+
44
+ // También funciona el componente base
45
+ { eztype: 'EzButton', text: 'Normal' }
46
+ ```
47
+
48
+ ## Decisiones de Diseño
49
+
50
+ ### ¿Por qué no `variant` prop?
51
+ - Más verboso: `{ eztype: 'EzButton', variant: 'ToolButton' }`
52
+ - El usuario pidió poder usar `eztype: 'ToolButton'` directamente
53
+
54
+ ### ¿Por qué solo CSS variables, no CSS crudo?
55
+ - Los componentes ya usan variables del theme (`--ez-primary`, etc.)
56
+ - Cambiar la variable cambia el estilo sin tocar CSS
57
+ - Más simple, menos propenso a errores
58
+
59
+ ### ¿Por qué config síncrono?
60
+ - Los aliases deben existir ANTES de que el loader intente resolver componentes
61
+ - El config es pequeño (~1-2KB), impacto mínimo
62
+ - "Mal necesario" aceptado por el usuario
63
+
64
+ ### Separación de registries
65
+ - `ez._registry` → Componentes reales (archivos .js)
66
+ - `ez.styles` → Variantes de estilo (virtuales, solo CSS vars)
67
+ - No mezclamos "componentes fake" en el registry principal
68
+
69
+ ## Flujo de Resolución
70
+
71
+ ```
72
+ 1. Usuario escribe: { eztype: 'ToolButton' }
73
+
74
+ 2. loader.resolve('ToolButton')
75
+
76
+ 3. ¿ez.styles.getVariant('ToolButton')?
77
+ → SÍ: { base: 'EzButton', vars: { '--ez-primary': '#10b981' } }
78
+
79
+ 4. loader.load('EzButton') ← lazy load normal del componente base
80
+
81
+ 5. renderer crea instancia de EzButton
82
+
83
+ 6. renderer aplica vars inline: style="--ez-primary: #10b981;"
84
+
85
+ 7. Elemento final con estilos custom
86
+ ```
87
+
88
+ ## Consideraciones SSR
89
+
90
+ ### Theme variables
91
+ - NO usar `document.documentElement.style.setProperty()` en SSR
92
+ - Generar `<style id="ez-theme-vars">:root { ... }</style>` en el HTML
93
+
94
+ ### Inline vars (variantes)
95
+ - Funcionan sin cambios: `style="--ez-primary: #10b981;"` se serializa normal
96
+
97
+ ### Aliases en SSR
98
+ - El config debe cargarse antes del render SSR
99
+ - Vite plugin debe procesar `ez.styles.config.js` en buildStart
100
+
101
+ ### Hydration
102
+ - Cliente debe importar mismo config síncronamente
103
+ - Evita mismatch entre server HTML y client render
104
+
105
+ ---
106
+
107
+ ## TODO - Implementación
108
+
109
+ ### Fase 1: Core (styles.ts) ✅
110
+ - [x] Crear `ez/core/styles.ts`
111
+ - [x] Implementar clase `EzStyles`:
112
+ ```typescript
113
+ class EzStyles {
114
+ private variants: Map<string, { base: string; vars: Record<string, string> }>;
115
+ private theme: Record<string, string>;
116
+
117
+ define(config): void // Procesa el config
118
+ getVariant(name): Variant // Retorna variante o undefined
119
+ getTheme(): Record // Retorna theme vars
120
+ applyTheme(): void // Aplica a :root (solo cliente)
121
+ }
122
+ ```
123
+ - [x] Exportar instancia singleton
124
+
125
+ ### Fase 2: Integración ez.ts ✅
126
+ - [x] Importar `EzStyles` en `ez.ts`
127
+ - [x] Exponer `ez.styles` (instancia)
128
+ - [x] Exponer `ez.defineStyles(config)` como shorthand
129
+
130
+ ### Fase 3: Integración loader.ts ✅
131
+ - [x] Modificar método de resolución
132
+ - [x] Antes de buscar archivo, checar `ez.styles.getVariant(name)`
133
+ - [x] Si es variante: retornar `{ component: base, styleVars: vars }`
134
+ - [x] Si no: continuar flujo normal de lazy loading
135
+ - [x] Pasar `styleVars` al renderer via `_resolvedStyleVariants` Map
136
+ - [x] Método `getStyleVars(eztype)` para obtener vars de una variante
137
+
138
+ ### Fase 4: Integración renderer.ts ✅
139
+ - [x] Recibir `styleVars` del loader
140
+ - [x] Después de crear elemento, aplicar vars como inline styles:
141
+ ```typescript
142
+ if (styleVars) {
143
+ for (const [key, value] of Object.entries(styleVars)) {
144
+ el.style.setProperty(key, value);
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### Fase 5: SSR Support
150
+ - [ ] Modificar `StaticHtmlRenderer.ts` o Vite plugin
151
+ - [ ] Cargar `ez.styles.config.js` en buildStart
152
+ - [ ] Generar `<style>` tag con theme vars en HTML output
153
+ - [ ] Asegurar que variantes se resuelven correctamente en SSR
154
+
155
+ ### Fase 6: Template del config ✅
156
+ - [x] Crear template `template/ez.styles.config.js`
157
+ - [x] Incluir todos los componentes (vacíos)
158
+ - [x] Incluir comentario con TODAS las variables disponibles del theme
159
+ - [ ] El CLI `npx ezfw init` debería copiar este template
160
+
161
+ ### Fase 7: Documentación
162
+ - [ ] Documentar en CLAUDE.md o docs
163
+ - [ ] Ejemplos de uso
164
+ - [ ] Lista de variables por componente
165
+
166
+ ---
167
+
168
+ ## Estado Actual
169
+
170
+ **Fase:** Implementación client-side completada
171
+ **Último paso:** Crear template `ez.styles.config.js`
172
+ **Siguiente paso:** SSR support (Fase 5) o publicar versión actual
173
+
174
+ ---
175
+
176
+ ## Archivos a Modificar/Crear
177
+
178
+ | Archivo | Acción | Descripción |
179
+ |---------|--------|-------------|
180
+ | `ez/core/styles.ts` | CREAR | Clase EzStyles |
181
+ | `ez/core/ez.ts` | MODIFICAR | Exponer ez.styles |
182
+ | `ez/core/loader.ts` | MODIFICAR | Checar variantes antes de load |
183
+ | `ez/core/renderer.ts` | MODIFICAR | Aplicar styleVars inline |
184
+ | `islands/StaticHtmlRenderer.ts` | MODIFICAR | SSR support |
185
+ | `islands/ViteIslandsPlugin.ts` | MODIFICAR | Cargar config en build |
186
+
187
+ ---
188
+
189
+ ## Notas Adicionales
190
+
191
+ - El config NO puede ser lazy loaded - debe estar en bundle inicial
192
+ - Las variantes NO son componentes reales, no tienen archivo .js
193
+ - El theme se aplica a :root, las variantes se aplican inline (mayor especificidad)
194
+ - Inline styles con CSS vars funcionan: `style="--ez-primary: red"` override :root
package/core/ez.ts CHANGED
@@ -6,6 +6,7 @@ import { EzState, ControllerDefinition, GridControllerDefinition, GridBehaviorDe
6
6
  import { EzModel, ModelDefinition, Model } from './EzModel.js';
7
7
  import { EzServices } from './services.js';
8
8
  import { EzEventBus, EventHandler } from './eventBus.js';
9
+ import { ezStyles, StylesConfig, StyleVariant } from './styles.js';
9
10
  import { deepSignal } from 'deepsignal';
10
11
  import * as EzGridQuery from '../components/grid/query/EzGridQuery.js';
11
12
  import dayjs from 'dayjs';
@@ -249,6 +250,19 @@ export interface EzFramework {
249
250
  truncate(str: string, length: number, suffix?: string): string;
250
251
  pluralize(count: number, singular: string, plural?: string): string;
251
252
  utils: typeof EzUtils;
253
+
254
+ // Style overrides system
255
+ styles: {
256
+ define(config: StylesConfig): void;
257
+ getVariant(name: string): StyleVariant | undefined;
258
+ hasVariant(name: string): boolean;
259
+ getTheme(): Record<string, string>;
260
+ applyTheme(): void;
261
+ getThemeStyleTag(): string;
262
+ list(): Map<string, StyleVariant>;
263
+ isInitialized(): boolean;
264
+ };
265
+ defineStyles(config: StylesConfig): void;
252
266
  }
253
267
 
254
268
  const ez: EzFramework = {
@@ -740,7 +754,13 @@ const ez: EzFramework = {
740
754
  capitalizeWords,
741
755
  truncate,
742
756
  pluralize,
743
- utils: EzUtils
757
+ utils: EzUtils,
758
+
759
+ // Style overrides system
760
+ styles: ezStyles,
761
+ defineStyles(config: StylesConfig): void {
762
+ ezStyles.define(config);
763
+ }
744
764
  };
745
765
 
746
766
  // Initialize framework
package/core/loader.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { EzError } from './EzError.js';
2
+ import { ezStyles, StyleVariant } from './styles.js';
2
3
 
3
4
  export interface ModuleMeta {
4
5
  path: string;
@@ -109,6 +110,8 @@ export class EzLoader {
109
110
  };
110
111
  private _retryAttempts: Map<string, number> = new Map();
111
112
  private _failedModules: Set<string> = new Set();
113
+ // Track style variants that have been resolved (name -> styleVars)
114
+ private _resolvedStyleVariants: Map<string, Record<string, string>> = new Map();
112
115
 
113
116
  constructor(ez: EzInstance) {
114
117
  this.ez = ez;
@@ -331,6 +334,22 @@ export class EzLoader {
331
334
  async resolveEzType(eztype: string): Promise<void> {
332
335
  if (this.ez._registry[eztype]) return;
333
336
 
337
+ // Check if this is a style variant first
338
+ const styleVariant = ezStyles.getVariant(eztype);
339
+ if (styleVariant) {
340
+ // Resolve the base component
341
+ await this.resolveEzType(styleVariant.base);
342
+
343
+ // Register variant as alias to base component
344
+ const baseComponent = this.ez._registry[styleVariant.base];
345
+ if (baseComponent) {
346
+ this.ez._registry[eztype] = baseComponent;
347
+ // Store the styleVars for this variant
348
+ this._resolvedStyleVariants.set(eztype, styleVariant.vars);
349
+ }
350
+ return;
351
+ }
352
+
334
353
  const lowerEztype = eztype.toLowerCase();
335
354
  const breakpoint = this.ez._currentBreakpoint;
336
355
 
@@ -418,6 +437,21 @@ export class EzLoader {
418
437
  return this.ez._internal.variants[componentName] || [];
419
438
  }
420
439
 
440
+ /**
441
+ * Get style vars for a resolved style variant
442
+ * Returns the CSS variables to apply inline, or null if not a style variant
443
+ */
444
+ getStyleVars(eztype: string): Record<string, string> | null {
445
+ return this._resolvedStyleVariants.get(eztype) || null;
446
+ }
447
+
448
+ /**
449
+ * Check if an eztype is a style variant
450
+ */
451
+ isStyleVariant(eztype: string): boolean {
452
+ return this._resolvedStyleVariants.has(eztype) || ezStyles.hasVariant(eztype);
453
+ }
454
+
421
455
  async resolveController(name: string | object | null): Promise<unknown> {
422
456
  if (!name) return null;
423
457
 
package/core/renderer.ts CHANGED
@@ -171,6 +171,7 @@ interface EzInstance {
171
171
  loadWithPriority(name: string, priority: string): Promise<void>;
172
172
  getCurrentModulePath(): string | null;
173
173
  hasVariants(name: string): boolean;
174
+ getStyleVars(eztype: string): Record<string, string> | null;
174
175
  };
175
176
  getController(name: string): Promise<ControllerInstance>;
176
177
  getStore(name: string): unknown;
@@ -1066,6 +1067,16 @@ export class EzRenderer {
1066
1067
  this._setupRepaintEffect(el, eztype, config, instance);
1067
1068
  }
1068
1069
 
1070
+ // Apply style variant CSS variables if this is a style variant
1071
+ if (el instanceof HTMLElement && eztype) {
1072
+ const styleVars = this.ez._loader?.getStyleVars(eztype);
1073
+ if (styleVars) {
1074
+ for (const [key, value] of Object.entries(styleVars)) {
1075
+ el.style.setProperty(key, value);
1076
+ }
1077
+ }
1078
+ }
1079
+
1069
1080
  return el;
1070
1081
  }
1071
1082
 
package/core/styles.ts ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * EzStyles - Sistema de Override de Estilos
3
+ *
4
+ * Permite definir variantes de estilo para componentes del framework
5
+ * sin modificar el código fuente. Las variantes se definen en
6
+ * ez.styles.config.js y se usan directamente como eztype.
7
+ *
8
+ * @see STYLES_IMPLEMENTATION.md para documentación completa
9
+ */
10
+
11
+ export interface StyleVariant {
12
+ base: string;
13
+ vars: Record<string, string>;
14
+ }
15
+
16
+ export interface StylesConfig {
17
+ theme?: Record<string, string>;
18
+ [component: string]: Record<string, Record<string, string> | string> | undefined;
19
+ }
20
+
21
+ class EzStyles {
22
+ private variants: Map<string, StyleVariant> = new Map();
23
+ private theme: Record<string, string> = {};
24
+ private _initialized = false;
25
+
26
+ /**
27
+ * Define estilos desde el config
28
+ *
29
+ * @example
30
+ * ez.defineStyles({
31
+ * theme: { '--ez-primary': '#8b5cf6' },
32
+ * EzButton: {
33
+ * ToolButton: { '--ez-primary': '#10b981' }
34
+ * }
35
+ * });
36
+ */
37
+ define(config: StylesConfig): void {
38
+ // Theme → guardar y aplicar a :root
39
+ if (config.theme) {
40
+ this.theme = { ...this.theme, ...config.theme };
41
+ this.applyTheme();
42
+ }
43
+
44
+ // Procesar variantes de componentes
45
+ for (const [component, variants] of Object.entries(config)) {
46
+ if (component === 'theme' || !variants) continue;
47
+
48
+ for (const [variantName, vars] of Object.entries(variants)) {
49
+ // Solo procesar si es un objeto (variante), no string
50
+ if (typeof vars === 'object') {
51
+ this.variants.set(variantName, {
52
+ base: component,
53
+ vars: vars as Record<string, string>
54
+ });
55
+ }
56
+ }
57
+ }
58
+
59
+ this._initialized = true;
60
+ }
61
+
62
+ /**
63
+ * Obtiene una variante por nombre
64
+ *
65
+ * @returns La variante o undefined si no existe
66
+ */
67
+ getVariant(name: string): StyleVariant | undefined {
68
+ return this.variants.get(name);
69
+ }
70
+
71
+ /**
72
+ * Verifica si un nombre es una variante de estilo
73
+ */
74
+ hasVariant(name: string): boolean {
75
+ return this.variants.has(name);
76
+ }
77
+
78
+ /**
79
+ * Obtiene las variables del theme
80
+ */
81
+ getTheme(): Record<string, string> {
82
+ return { ...this.theme };
83
+ }
84
+
85
+ /**
86
+ * Aplica las variables del theme a :root
87
+ * Solo funciona en cliente (browser)
88
+ */
89
+ applyTheme(): void {
90
+ if (typeof document === 'undefined') return;
91
+
92
+ const root = document.documentElement;
93
+ for (const [key, value] of Object.entries(this.theme)) {
94
+ root.style.setProperty(key, value);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Genera CSS string para SSR
100
+ * Retorna el contenido para un <style> tag
101
+ */
102
+ getThemeStyleTag(): string {
103
+ if (Object.keys(this.theme).length === 0) return '';
104
+
105
+ const vars = Object.entries(this.theme)
106
+ .map(([key, value]) => ` ${key}: ${value};`)
107
+ .join('\n');
108
+
109
+ return `:root {\n${vars}\n}`;
110
+ }
111
+
112
+ /**
113
+ * Lista todas las variantes registradas (para debug)
114
+ */
115
+ list(): Map<string, StyleVariant> {
116
+ return new Map(this.variants);
117
+ }
118
+
119
+ /**
120
+ * Verifica si el sistema fue inicializado
121
+ */
122
+ isInitialized(): boolean {
123
+ return this._initialized;
124
+ }
125
+
126
+ /**
127
+ * Limpia todas las variantes y theme (para testing)
128
+ */
129
+ reset(): void {
130
+ this.variants.clear();
131
+ this.theme = {};
132
+ this._initialized = false;
133
+ }
134
+ }
135
+
136
+ // Singleton
137
+ export const ezStyles = new EzStyles();
@@ -137,8 +137,8 @@ async function hydrateIsland(instance: IslandInstance): Promise<void> {
137
137
  const startTime = performance.now();
138
138
 
139
139
  try {
140
- // Load the island module (plain object export)
141
- const componentDef = await loadIslandModule(instance.name) as IslandDefinition | null;
140
+ // Load the island module (plain object export or class component)
141
+ const componentDef = await loadIslandModule(instance.name) as IslandDefinition | (new () => unknown) | null;
142
142
 
143
143
  if (!componentDef) {
144
144
  console.error(`[Ez Islands] Failed to load module: ${instance.name}`);
@@ -158,9 +158,10 @@ async function hydrateIsland(instance: IslandInstance): Promise<void> {
158
158
  instance.element.classList.remove('ez-island-loading');
159
159
 
160
160
  // Check if it's a class component (has prototype with render method)
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
162
  const isClassComponent = typeof componentDef === 'function' &&
162
- componentDef.prototype &&
163
- typeof componentDef.prototype.render === 'function';
163
+ (componentDef as any).prototype &&
164
+ typeof (componentDef as any).prototype.render === 'function';
164
165
 
165
166
  if (isClassComponent) {
166
167
  // Class components: register directly, no preparation needed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezfw-core",
3
- "version": "1.0.84",
3
+ "version": "1.0.85",
4
4
  "description": "Ez Framework - A declarative component framework for building modern web applications",
5
5
  "type": "module",
6
6
  "main": "./core/ez.ts",
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Ez Framework - Style Overrides Configuration
3
+ *
4
+ * This file allows you to customize component styles without modifying the framework.
5
+ * Define variants by specifying CSS variables that will be applied inline to elements.
6
+ *
7
+ * Usage:
8
+ * 1. Define variants under each component name
9
+ * 2. Use the variant name directly as eztype: { eztype: 'ToolButton', text: 'Tool' }
10
+ *
11
+ * @see https://ezfw.dev/docs/styles for full documentation
12
+ */
13
+
14
+ export default {
15
+ // ================================================================
16
+ // Global Theme Variables
17
+ // Applied to :root - affects all components
18
+ // ================================================================
19
+ theme: {
20
+ // '--ez-primary': '#8b5cf6',
21
+ // '--ez-radius-md': '12px',
22
+ },
23
+
24
+ // ================================================================
25
+ // Component Variants
26
+ // Each variant becomes usable as an eztype
27
+ // ================================================================
28
+
29
+ // Buttons
30
+ EzButton: {
31
+ // Example:
32
+ // ToolButton: {
33
+ // '--ez-btn-primary-bg': '#10b981',
34
+ // '--ez-btn-primary-bg-hover': '#059669',
35
+ // },
36
+ // DangerButton: {
37
+ // '--ez-btn-primary-bg': '#ef4444',
38
+ // '--ez-btn-primary-bg-hover': '#dc2626',
39
+ // },
40
+ },
41
+
42
+ EzButtonGroup: {
43
+ //
44
+ },
45
+
46
+ // Inputs & Forms
47
+ EzInput: {
48
+ // Example:
49
+ // SearchInput: {
50
+ // '--ez-radius-md': '9999px',
51
+ // },
52
+ },
53
+
54
+ EzTextarea: {
55
+ //
56
+ },
57
+
58
+ EzSelect: {
59
+ //
60
+ },
61
+
62
+ EzCheckbox: {
63
+ //
64
+ },
65
+
66
+ EzRadio: {
67
+ //
68
+ },
69
+
70
+ EzSwitch: {
71
+ //
72
+ },
73
+
74
+ EzDatePicker: {
75
+ //
76
+ },
77
+
78
+ EzTimePicker: {
79
+ //
80
+ },
81
+
82
+ EzPicker: {
83
+ //
84
+ },
85
+
86
+ EzDropdown: {
87
+ //
88
+ },
89
+
90
+ EzForm: {
91
+ //
92
+ },
93
+
94
+ // Layout & Containers
95
+ EzCard: {
96
+ //
97
+ },
98
+
99
+ EzPanel: {
100
+ //
101
+ },
102
+
103
+ EzPaper: {
104
+ //
105
+ },
106
+
107
+ EzTabPanel: {
108
+ //
109
+ },
110
+
111
+ EzDialog: {
112
+ //
113
+ },
114
+
115
+ EzDrawer: {
116
+ //
117
+ },
118
+
119
+ // Data Display
120
+ EzGrid: {
121
+ //
122
+ },
123
+
124
+ EzDataView: {
125
+ //
126
+ },
127
+
128
+ EzKanban: {
129
+ //
130
+ },
131
+
132
+ EzTree: {
133
+ //
134
+ },
135
+
136
+ EzChart: {
137
+ //
138
+ },
139
+
140
+ // Feedback & Status
141
+ EzBadge: {
142
+ //
143
+ },
144
+
145
+ EzAvatar: {
146
+ //
147
+ },
148
+
149
+ EzSkeleton: {
150
+ //
151
+ },
152
+
153
+ EzTooltip: {
154
+ //
155
+ },
156
+
157
+ EzActivityFeed: {
158
+ //
159
+ },
160
+
161
+ // Organization
162
+ EzOrgChart: {
163
+ //
164
+ },
165
+ };
166
+
167
+ // ================================================================
168
+ // AVAILABLE CSS VARIABLES REFERENCE
169
+ // ================================================================
170
+ // Copy any of these variables into your variants to override them.
171
+ //
172
+ // ======================== BRAND COLORS ========================
173
+ // --ez-primary Primary brand color
174
+ // --ez-primary-hover Primary hover state
175
+ // --ez-primary-active Primary active/pressed state
176
+ // --ez-primary-light Light primary (for backgrounds)
177
+ // --ez-primary-subtle Subtle primary tint
178
+ // --ez-secondary Secondary brand color
179
+ // --ez-secondary-hover Secondary hover state
180
+ // --ez-accent Accent color for special elements
181
+ // --ez-accent-hover Accent hover state
182
+ //
183
+ // ===================== SEMANTIC COLORS =======================
184
+ // --ez-success Success state color
185
+ // --ez-success-hover Success hover state
186
+ // --ez-success-light Light success background
187
+ // --ez-warning Warning state color
188
+ // --ez-warning-hover Warning hover state
189
+ // --ez-warning-light Light warning background
190
+ // --ez-danger Danger/error state color
191
+ // --ez-danger-hover Danger hover state
192
+ // --ez-danger-light Light danger background
193
+ // --ez-info Info state color
194
+ // --ez-info-hover Info hover state
195
+ // --ez-info-light Light info background
196
+ //
197
+ // ===================== SURFACE COLORS ========================
198
+ // --ez-bg Main page background
199
+ // --ez-surface Cards, panels background
200
+ // --ez-surface-hover Surface hover state
201
+ // --ez-surface-active Surface active/pressed state
202
+ // --ez-overlay Modal/dialog overlay
203
+ //
204
+ // ======================== TEXT COLORS ========================
205
+ // --ez-text Primary text color
206
+ // --ez-text-secondary Secondary text color
207
+ // --ez-text-tertiary Tertiary/subtle text
208
+ // --ez-text-muted Muted/disabled text
209
+ // --ez-text-placeholder Input placeholder text
210
+ // --ez-text-inverse Inverse text (on dark bg)
211
+ // --ez-text-on-primary Text on primary colored bg
212
+ //
213
+ // ======================= BORDER COLORS =======================
214
+ // --ez-border Default border color
215
+ // --ez-border-light Subtle/light border
216
+ // --ez-border-strong Strong/emphasis border
217
+ // --ez-border-focus Focus ring color
218
+ //
219
+ // ====================== INPUT VARIABLES ======================
220
+ // --ez-input-bg Input background
221
+ // --ez-input-bg-disabled Disabled input background
222
+ // --ez-input-border Input border color
223
+ // --ez-input-border-hover Input border on hover
224
+ // --ez-input-border-focus Input border on focus
225
+ // --ez-input-text Input text color
226
+ // --ez-input-placeholder Input placeholder color
227
+ // --ez-input-shadow-focus Input focus shadow
228
+ //
229
+ // ====================== BUTTON VARIABLES =====================
230
+ // --ez-btn-primary-bg Primary button background
231
+ // --ez-btn-primary-bg-hover Primary button hover bg
232
+ // --ez-btn-primary-text Primary button text
233
+ // --ez-btn-primary-shadow Primary button shadow
234
+ // --ez-btn-secondary-bg Secondary button background
235
+ // --ez-btn-secondary-bg-hover Secondary button hover bg
236
+ // --ez-btn-secondary-text Secondary button text
237
+ // --ez-btn-secondary-border Secondary button border
238
+ // --ez-btn-ghost-bg Ghost button background
239
+ // --ez-btn-ghost-bg-hover Ghost button hover bg
240
+ // --ez-btn-ghost-text Ghost button text
241
+ // --ez-btn-danger-bg Danger button background
242
+ // --ez-btn-danger-bg-hover Danger button hover bg
243
+ // --ez-btn-danger-text Danger button text
244
+ //
245
+ // ======================= TABLE/GRID ==========================
246
+ // --ez-table-header-bg Table header background
247
+ // --ez-table-header-text Table header text
248
+ // --ez-table-row-bg Table row background
249
+ // --ez-table-row-alt-bg Alternate row background
250
+ // --ez-table-row-hover Row hover background
251
+ // --ez-table-row-selected Selected row background
252
+ // --ez-table-border Table border color
253
+ //
254
+ // ========================= CARDS =============================
255
+ // --ez-card-bg Card background
256
+ // --ez-card-border Card border color
257
+ // --ez-card-shadow Card box shadow
258
+ // --ez-card-shadow-hover Card hover shadow
259
+ // --ez-card-header-bg Card header background
260
+ //
261
+ // ========================= BADGES ============================
262
+ // --ez-badge-primary-bg Primary badge background
263
+ // --ez-badge-primary-text Primary badge text
264
+ // --ez-badge-secondary-bg Secondary badge background
265
+ // --ez-badge-secondary-text Secondary badge text
266
+ // --ez-badge-success-bg Success badge background
267
+ // --ez-badge-success-text Success badge text
268
+ // --ez-badge-warning-bg Warning badge background
269
+ // --ez-badge-warning-text Warning badge text
270
+ // --ez-badge-danger-bg Danger badge background
271
+ // --ez-badge-danger-text Danger badge text
272
+ //
273
+ // ======================== DROPDOWN ===========================
274
+ // --ez-dropdown-bg Dropdown background
275
+ // --ez-dropdown-border Dropdown border
276
+ // --ez-dropdown-shadow Dropdown box shadow
277
+ // --ez-dropdown-item-hover Dropdown item hover bg
278
+ // --ez-dropdown-divider Dropdown divider color
279
+ //
280
+ // ========================= DIALOG ============================
281
+ // --ez-dialog-bg Dialog background
282
+ // --ez-dialog-border Dialog border
283
+ // --ez-dialog-shadow Dialog box shadow
284
+ // --ez-dialog-header-bg Dialog header background
285
+ // --ez-dialog-footer-bg Dialog footer background
286
+ //
287
+ // ======================== TOOLTIP ============================
288
+ // --ez-tooltip-bg Tooltip background
289
+ // --ez-tooltip-text Tooltip text color
290
+ // --ez-tooltip-shadow Tooltip box shadow
291
+ //
292
+ // ========================= SPACING ===========================
293
+ // --ez-radius-sm Small border radius (4px)
294
+ // --ez-radius-md Medium border radius (8px)
295
+ // --ez-radius-lg Large border radius (12px)
296
+ // --ez-radius-xl Extra large radius (16px)
297
+ // --ez-radius-full Full/pill radius (9999px)
298
+ //
299
+ // ======================= TYPOGRAPHY ==========================
300
+ // --ez-font-family Base font family
301
+ // --ez-font-mono Monospace font family
302
+ // --ez-text-xs Extra small text (0.75rem)
303
+ // --ez-text-sm Small text (0.875rem)
304
+ // --ez-text-base Base text (1rem)
305
+ // --ez-text-lg Large text (1.125rem)
306
+ // --ez-text-xl Extra large text (1.25rem)
307
+ //
308
+ // ======================== SHADOWS ============================
309
+ // --ez-shadow-sm Small shadow
310
+ // --ez-shadow-md Medium shadow
311
+ // --ez-shadow-lg Large shadow
312
+ // --ez-shadow-xl Extra large shadow
313
+ // --ez-focus-ring Focus ring shadow
314
+ //
315
+ // ================================================================