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.
- package/core/STYLES_IMPLEMENTATION.md +194 -0
- package/core/ez.ts +21 -1
- package/core/loader.ts +34 -0
- package/core/renderer.ts +11 -0
- package/core/styles.ts +137 -0
- package/islands/runtime.ts +5 -4
- package/package.json +1 -1
- package/template/ez.styles.config.js +315 -0
|
@@ -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();
|
package/islands/runtime.ts
CHANGED
|
@@ -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
|
@@ -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
|
+
// ================================================================
|