ezfw-core 1.0.63 → 1.0.65
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/islands/StaticHtmlRenderer.ts +3 -3
- package/islands/ssrShim.js +864 -33
- package/package.json +1 -1
|
@@ -271,9 +271,9 @@ export class StaticHtmlRenderer {
|
|
|
271
271
|
|
|
272
272
|
// Check if it's a registered component
|
|
273
273
|
if (ctx.registry.has(eztype)) {
|
|
274
|
-
// Pass the entire config as props (
|
|
275
|
-
//
|
|
276
|
-
const { eztype: _,
|
|
274
|
+
// Pass the entire config as props (including items - components handle their own structure)
|
|
275
|
+
// In SPA mode, components receive full config via constructor, SSR should match
|
|
276
|
+
const { eztype: _, ...configProps } = config;
|
|
277
277
|
const mergedProps = { ...configProps, ...(config.props || {}) };
|
|
278
278
|
return this.renderComponent(eztype, ctx, mergedProps);
|
|
279
279
|
}
|
package/islands/ssrShim.js
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* Uses a SINGLETON pattern - registry persists across module reloads.
|
|
6
6
|
* Components can use ez.define() normally and definitions
|
|
7
7
|
* are stored in the registry for SSR to access.
|
|
8
|
+
*
|
|
9
|
+
* ALL framework components have SSR templates here that render
|
|
10
|
+
* reasonable static HTML. Interactive features activate on hydration.
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
13
|
// Use globalThis to store the singleton registry (persists across module reloads)
|
|
@@ -18,8 +21,29 @@ if (!globalThis.__ezSSRControllers) {
|
|
|
18
21
|
const ssrRegistry = globalThis.__ezSSRRegistry;
|
|
19
22
|
const ssrControllers = globalThis.__ezSSRControllers;
|
|
20
23
|
|
|
21
|
-
//
|
|
24
|
+
// Helper: semantic color map
|
|
25
|
+
const semanticColors = {
|
|
26
|
+
primary: 'var(--ez-primary)', secondary: 'var(--ez-secondary)',
|
|
27
|
+
success: 'var(--ez-success)', danger: 'var(--ez-danger)',
|
|
28
|
+
warning: 'var(--ez-warning)', info: 'var(--ez-info)',
|
|
29
|
+
muted: 'var(--ez-muted)', light: 'var(--ez-light)', dark: 'var(--ez-dark)'
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Helper: size map for icons
|
|
33
|
+
const sizeMap = {
|
|
34
|
+
xxs: '0.65em', xs: '0.75em', sm: '0.875em',
|
|
35
|
+
lg: '1.25em', xl: '1.5em', '2x': '2em',
|
|
36
|
+
'3x': '3em', '4x': '4em', '5x': '5em'
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Register ALL framework components for SSR
|
|
41
|
+
* Each component has a template() that returns static HTML config
|
|
42
|
+
*/
|
|
22
43
|
function registerFrameworkComponents() {
|
|
44
|
+
// ==================== BASIC COMPONENTS ====================
|
|
45
|
+
|
|
46
|
+
// EzIcon - Font Awesome icon
|
|
23
47
|
ssrRegistry['EzIcon'] = {
|
|
24
48
|
template(props) {
|
|
25
49
|
const type = props.type || 'solid';
|
|
@@ -29,18 +53,6 @@ function registerFrameworkComponents() {
|
|
|
29
53
|
if (props.pulse) classes.push('fa-pulse');
|
|
30
54
|
if (props.bounce) classes.push('fa-bounce');
|
|
31
55
|
|
|
32
|
-
const sizeMap = {
|
|
33
|
-
xxs: '0.65em', xs: '0.75em', sm: '0.875em',
|
|
34
|
-
lg: '1.25em', xl: '1.5em', '2x': '2em',
|
|
35
|
-
'3x': '3em', '4x': '4em', '5x': '5em'
|
|
36
|
-
};
|
|
37
|
-
const semanticColors = {
|
|
38
|
-
primary: 'var(--ez-primary)', secondary: 'var(--ez-secondary)',
|
|
39
|
-
success: 'var(--ez-success)', danger: 'var(--ez-danger)',
|
|
40
|
-
warning: 'var(--ez-warning)', info: 'var(--ez-info)',
|
|
41
|
-
muted: 'var(--ez-muted)', light: 'var(--ez-light)', dark: 'var(--ez-dark)'
|
|
42
|
-
};
|
|
43
|
-
|
|
44
56
|
return {
|
|
45
57
|
eztype: 'i',
|
|
46
58
|
cls: classes.join(' '),
|
|
@@ -52,6 +64,7 @@ function registerFrameworkComponents() {
|
|
|
52
64
|
}
|
|
53
65
|
};
|
|
54
66
|
|
|
67
|
+
// EzLabel - Simple text label
|
|
55
68
|
ssrRegistry['EzLabel'] = {
|
|
56
69
|
template(props) {
|
|
57
70
|
return {
|
|
@@ -63,25 +76,857 @@ function registerFrameworkComponents() {
|
|
|
63
76
|
}
|
|
64
77
|
};
|
|
65
78
|
|
|
79
|
+
// EzButton - Button with optional icon
|
|
66
80
|
ssrRegistry['EzButton'] = {
|
|
67
81
|
template(props) {
|
|
68
82
|
const items = [];
|
|
69
83
|
if (props.iconCls) {
|
|
70
84
|
items.push({ eztype: 'i', cls: props.iconCls });
|
|
71
85
|
}
|
|
86
|
+
if (props.icon) {
|
|
87
|
+
items.push({ eztype: 'EzIcon', fa: props.icon, type: props.iconType });
|
|
88
|
+
}
|
|
72
89
|
if (props.text) {
|
|
73
90
|
items.push({ eztype: 'span', text: props.text });
|
|
74
91
|
}
|
|
92
|
+
|
|
93
|
+
const variantStyles = {
|
|
94
|
+
primary: { background: 'var(--ez-primary)', color: 'white' },
|
|
95
|
+
secondary: { background: 'var(--ez-secondary)', color: 'white' },
|
|
96
|
+
success: { background: 'var(--ez-success)', color: 'white' },
|
|
97
|
+
danger: { background: 'var(--ez-danger)', color: 'white' },
|
|
98
|
+
warning: { background: 'var(--ez-warning)', color: 'black' },
|
|
99
|
+
outline: { background: 'transparent', border: '1px solid var(--ez-border)' },
|
|
100
|
+
ghost: { background: 'transparent' },
|
|
101
|
+
link: { background: 'transparent', color: 'var(--ez-primary)' }
|
|
102
|
+
};
|
|
103
|
+
|
|
75
104
|
return {
|
|
76
105
|
eztype: 'button',
|
|
77
|
-
cls: props.cls,
|
|
78
|
-
style: props.style,
|
|
106
|
+
cls: `ez-button ${props.variant || ''} ${props.cls || ''}`.trim(),
|
|
107
|
+
style: { ...variantStyles[props.variant], ...props.style },
|
|
79
108
|
attr: { type: props.type || 'button', disabled: props.disabled },
|
|
80
109
|
items: items.length > 0 ? items : undefined,
|
|
81
110
|
text: items.length === 0 ? props.text : undefined
|
|
82
111
|
};
|
|
83
112
|
}
|
|
84
113
|
};
|
|
114
|
+
|
|
115
|
+
// EzButtonGroup - Group of buttons
|
|
116
|
+
ssrRegistry['EzButtonGroup'] = {
|
|
117
|
+
template(props) {
|
|
118
|
+
return {
|
|
119
|
+
eztype: 'div',
|
|
120
|
+
cls: 'ez-button-group',
|
|
121
|
+
layout: 'hbox',
|
|
122
|
+
gap: 1,
|
|
123
|
+
style: props.style,
|
|
124
|
+
items: props.items || []
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// ==================== FORM INPUTS ====================
|
|
130
|
+
|
|
131
|
+
// EzInput - Text input field
|
|
132
|
+
ssrRegistry['EzInput'] = {
|
|
133
|
+
template(props) {
|
|
134
|
+
const items = [];
|
|
135
|
+
|
|
136
|
+
if (props.label) {
|
|
137
|
+
items.push({
|
|
138
|
+
eztype: 'label',
|
|
139
|
+
cls: 'ez-input-label',
|
|
140
|
+
text: props.label,
|
|
141
|
+
items: props.required ? [{ eztype: 'span', text: ' *', style: { color: 'var(--ez-danger)' } }] : undefined
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
items.push({
|
|
146
|
+
eztype: 'input',
|
|
147
|
+
cls: 'ez-input',
|
|
148
|
+
attr: {
|
|
149
|
+
type: props.inputType || 'text',
|
|
150
|
+
placeholder: props.placeholder,
|
|
151
|
+
disabled: props.disabled,
|
|
152
|
+
readonly: props.readonly,
|
|
153
|
+
value: props.value || ''
|
|
154
|
+
},
|
|
155
|
+
style: props.style
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
eztype: 'div',
|
|
160
|
+
cls: 'ez-input-wrapper',
|
|
161
|
+
layout: 'vbox',
|
|
162
|
+
gap: 0.5,
|
|
163
|
+
items
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// EzTextarea - Multi-line text input
|
|
169
|
+
ssrRegistry['EzTextarea'] = {
|
|
170
|
+
template(props) {
|
|
171
|
+
const items = [];
|
|
172
|
+
|
|
173
|
+
if (props.label) {
|
|
174
|
+
items.push({
|
|
175
|
+
eztype: 'label',
|
|
176
|
+
cls: 'ez-textarea-label',
|
|
177
|
+
text: props.label
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
items.push({
|
|
182
|
+
eztype: 'textarea',
|
|
183
|
+
cls: 'ez-textarea',
|
|
184
|
+
attr: {
|
|
185
|
+
placeholder: props.placeholder,
|
|
186
|
+
disabled: props.disabled,
|
|
187
|
+
rows: props.rows || 4
|
|
188
|
+
},
|
|
189
|
+
text: props.value || '',
|
|
190
|
+
style: props.style
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
eztype: 'div',
|
|
195
|
+
cls: 'ez-textarea-wrapper',
|
|
196
|
+
layout: 'vbox',
|
|
197
|
+
gap: 0.5,
|
|
198
|
+
items
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// EzSelect - Dropdown select
|
|
204
|
+
ssrRegistry['EzSelect'] = {
|
|
205
|
+
template(props) {
|
|
206
|
+
const options = (props.options || []).map(opt => ({
|
|
207
|
+
eztype: 'option',
|
|
208
|
+
attr: { value: opt.value || opt },
|
|
209
|
+
text: opt.label || opt.text || opt
|
|
210
|
+
}));
|
|
211
|
+
|
|
212
|
+
const items = [];
|
|
213
|
+
if (props.label) {
|
|
214
|
+
items.push({ eztype: 'label', cls: 'ez-select-label', text: props.label });
|
|
215
|
+
}
|
|
216
|
+
items.push({
|
|
217
|
+
eztype: 'select',
|
|
218
|
+
cls: 'ez-select',
|
|
219
|
+
attr: { disabled: props.disabled },
|
|
220
|
+
style: props.style,
|
|
221
|
+
items: options
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
eztype: 'div',
|
|
226
|
+
cls: 'ez-select-wrapper',
|
|
227
|
+
layout: 'vbox',
|
|
228
|
+
gap: 0.5,
|
|
229
|
+
items
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// EzCheckbox - Checkbox input
|
|
235
|
+
ssrRegistry['EzCheckbox'] = {
|
|
236
|
+
template(props) {
|
|
237
|
+
return {
|
|
238
|
+
eztype: 'label',
|
|
239
|
+
cls: 'ez-checkbox',
|
|
240
|
+
layout: 'hbox',
|
|
241
|
+
gap: 1,
|
|
242
|
+
style: { alignItems: 'center', cursor: 'pointer', ...props.style },
|
|
243
|
+
items: [
|
|
244
|
+
{
|
|
245
|
+
eztype: 'input',
|
|
246
|
+
attr: { type: 'checkbox', checked: props.checked, disabled: props.disabled }
|
|
247
|
+
},
|
|
248
|
+
{ eztype: 'span', text: props.label || props.text || '' }
|
|
249
|
+
]
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// EzRadio - Radio button group
|
|
255
|
+
ssrRegistry['EzRadio'] = {
|
|
256
|
+
template(props) {
|
|
257
|
+
const options = (props.options || []).map(opt => ({
|
|
258
|
+
eztype: 'label',
|
|
259
|
+
cls: 'ez-radio-option',
|
|
260
|
+
layout: 'hbox',
|
|
261
|
+
gap: 1,
|
|
262
|
+
style: { alignItems: 'center', cursor: 'pointer' },
|
|
263
|
+
items: [
|
|
264
|
+
{
|
|
265
|
+
eztype: 'input',
|
|
266
|
+
attr: { type: 'radio', name: props.name, value: opt.value || opt, checked: props.value === (opt.value || opt) }
|
|
267
|
+
},
|
|
268
|
+
{ eztype: 'span', text: opt.label || opt }
|
|
269
|
+
]
|
|
270
|
+
}));
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
eztype: 'div',
|
|
274
|
+
cls: 'ez-radio-group',
|
|
275
|
+
layout: props.horizontal ? 'hbox' : 'vbox',
|
|
276
|
+
gap: 1,
|
|
277
|
+
style: props.style,
|
|
278
|
+
items: options
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// EzSwitch - Toggle switch
|
|
284
|
+
ssrRegistry['EzSwitch'] = {
|
|
285
|
+
template(props) {
|
|
286
|
+
return {
|
|
287
|
+
eztype: 'label',
|
|
288
|
+
cls: 'ez-switch',
|
|
289
|
+
layout: 'hbox',
|
|
290
|
+
gap: 1,
|
|
291
|
+
style: { alignItems: 'center', cursor: 'pointer', ...props.style },
|
|
292
|
+
items: [
|
|
293
|
+
{
|
|
294
|
+
eztype: 'div',
|
|
295
|
+
cls: `ez-switch-track ${props.checked ? 'checked' : ''}`,
|
|
296
|
+
style: {
|
|
297
|
+
width: '40px', height: '20px', borderRadius: '10px',
|
|
298
|
+
background: props.checked ? 'var(--ez-primary)' : 'var(--ez-border)',
|
|
299
|
+
position: 'relative'
|
|
300
|
+
},
|
|
301
|
+
items: [{
|
|
302
|
+
eztype: 'div',
|
|
303
|
+
cls: 'ez-switch-thumb',
|
|
304
|
+
style: {
|
|
305
|
+
width: '16px', height: '16px', borderRadius: '50%',
|
|
306
|
+
background: 'white', position: 'absolute', top: '2px',
|
|
307
|
+
left: props.checked ? '22px' : '2px',
|
|
308
|
+
transition: 'left 0.2s'
|
|
309
|
+
}
|
|
310
|
+
}]
|
|
311
|
+
},
|
|
312
|
+
props.label ? { eztype: 'span', text: props.label } : null
|
|
313
|
+
].filter(Boolean)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// EzForm - Form container
|
|
319
|
+
ssrRegistry['EzForm'] = {
|
|
320
|
+
template(props) {
|
|
321
|
+
return {
|
|
322
|
+
eztype: 'form',
|
|
323
|
+
cls: 'ez-form',
|
|
324
|
+
layout: 'vbox',
|
|
325
|
+
gap: 2,
|
|
326
|
+
style: props.style,
|
|
327
|
+
items: props.items || []
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// ==================== DATE/TIME ====================
|
|
333
|
+
|
|
334
|
+
// EzDatePicker - Date picker
|
|
335
|
+
ssrRegistry['EzDatePicker'] = {
|
|
336
|
+
template(props) {
|
|
337
|
+
const items = [];
|
|
338
|
+
if (props.label) {
|
|
339
|
+
items.push({ eztype: 'label', cls: 'ez-datepicker-label', text: props.label });
|
|
340
|
+
}
|
|
341
|
+
items.push({
|
|
342
|
+
eztype: 'input',
|
|
343
|
+
cls: 'ez-datepicker',
|
|
344
|
+
attr: { type: 'date', value: props.value, disabled: props.disabled },
|
|
345
|
+
style: props.style
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
eztype: 'div',
|
|
350
|
+
cls: 'ez-datepicker-wrapper',
|
|
351
|
+
layout: 'vbox',
|
|
352
|
+
gap: 0.5,
|
|
353
|
+
items
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// EzTimePicker - Time picker
|
|
359
|
+
ssrRegistry['EzTimePicker'] = {
|
|
360
|
+
template(props) {
|
|
361
|
+
const items = [];
|
|
362
|
+
if (props.label) {
|
|
363
|
+
items.push({ eztype: 'label', cls: 'ez-timepicker-label', text: props.label });
|
|
364
|
+
}
|
|
365
|
+
items.push({
|
|
366
|
+
eztype: 'input',
|
|
367
|
+
cls: 'ez-timepicker',
|
|
368
|
+
attr: { type: 'time', value: props.value, disabled: props.disabled },
|
|
369
|
+
style: props.style
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
eztype: 'div',
|
|
374
|
+
cls: 'ez-timepicker-wrapper',
|
|
375
|
+
layout: 'vbox',
|
|
376
|
+
gap: 0.5,
|
|
377
|
+
items
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// ==================== DISPLAY COMPONENTS ====================
|
|
383
|
+
|
|
384
|
+
// EzAvatar - User avatar
|
|
385
|
+
ssrRegistry['EzAvatar'] = {
|
|
386
|
+
template(props) {
|
|
387
|
+
const size = props.size || 40;
|
|
388
|
+
const initials = (props.name || '??').split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase();
|
|
389
|
+
|
|
390
|
+
if (props.src) {
|
|
391
|
+
return {
|
|
392
|
+
eztype: 'img',
|
|
393
|
+
cls: 'ez-avatar',
|
|
394
|
+
attr: { src: props.src, alt: props.name || 'Avatar' },
|
|
395
|
+
style: {
|
|
396
|
+
width: `${size}px`, height: `${size}px`,
|
|
397
|
+
borderRadius: props.rounded ? '50%' : '8px',
|
|
398
|
+
objectFit: 'cover',
|
|
399
|
+
...props.style
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return {
|
|
405
|
+
eztype: 'div',
|
|
406
|
+
cls: 'ez-avatar',
|
|
407
|
+
text: initials,
|
|
408
|
+
style: {
|
|
409
|
+
width: `${size}px`, height: `${size}px`,
|
|
410
|
+
borderRadius: props.rounded !== false ? '50%' : '8px',
|
|
411
|
+
background: props.color || 'var(--ez-primary)',
|
|
412
|
+
color: 'white',
|
|
413
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
414
|
+
fontWeight: '600', fontSize: `${size * 0.4}px`,
|
|
415
|
+
...props.style
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// EzBadge - Status badge
|
|
422
|
+
ssrRegistry['EzBadge'] = {
|
|
423
|
+
template(props) {
|
|
424
|
+
const colorMap = {
|
|
425
|
+
primary: { bg: 'var(--ez-primary)', color: 'white' },
|
|
426
|
+
secondary: { bg: 'var(--ez-secondary)', color: 'white' },
|
|
427
|
+
success: { bg: 'var(--ez-success)', color: 'white' },
|
|
428
|
+
danger: { bg: 'var(--ez-danger)', color: 'white' },
|
|
429
|
+
warning: { bg: 'var(--ez-warning)', color: 'black' },
|
|
430
|
+
info: { bg: 'var(--ez-info)', color: 'white' }
|
|
431
|
+
};
|
|
432
|
+
const colors = colorMap[props.variant] || colorMap.primary;
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
eztype: 'span',
|
|
436
|
+
cls: 'ez-badge',
|
|
437
|
+
text: props.text || props.label || '',
|
|
438
|
+
style: {
|
|
439
|
+
display: 'inline-flex', alignItems: 'center',
|
|
440
|
+
padding: '2px 8px', borderRadius: '12px',
|
|
441
|
+
fontSize: '12px', fontWeight: '500',
|
|
442
|
+
background: colors.bg, color: colors.color,
|
|
443
|
+
...props.style
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// EzCard - Card container
|
|
450
|
+
ssrRegistry['EzCard'] = {
|
|
451
|
+
template(props) {
|
|
452
|
+
const items = [];
|
|
453
|
+
|
|
454
|
+
if (props.title || props.subtitle) {
|
|
455
|
+
items.push({
|
|
456
|
+
eztype: 'div',
|
|
457
|
+
cls: 'ez-card-header',
|
|
458
|
+
layout: 'vbox',
|
|
459
|
+
style: { padding: '16px', borderBottom: '1px solid var(--ez-border)' },
|
|
460
|
+
items: [
|
|
461
|
+
props.title ? { eztype: 'h3', text: props.title, style: { margin: 0, fontWeight: '600' } } : null,
|
|
462
|
+
props.subtitle ? { eztype: 'p', text: props.subtitle, style: { margin: '4px 0 0', color: 'var(--ez-muted)' } } : null
|
|
463
|
+
].filter(Boolean)
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
items.push({
|
|
468
|
+
eztype: 'div',
|
|
469
|
+
cls: 'ez-card-body',
|
|
470
|
+
style: { padding: '16px' },
|
|
471
|
+
items: props.items || []
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
return {
|
|
475
|
+
eztype: 'div',
|
|
476
|
+
cls: 'ez-card',
|
|
477
|
+
style: {
|
|
478
|
+
background: 'var(--ez-surface)',
|
|
479
|
+
border: '1px solid var(--ez-border)',
|
|
480
|
+
borderRadius: '8px',
|
|
481
|
+
...props.style
|
|
482
|
+
},
|
|
483
|
+
items
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// EzPanel - Collapsible panel
|
|
489
|
+
ssrRegistry['EzPanel'] = {
|
|
490
|
+
template(props) {
|
|
491
|
+
return {
|
|
492
|
+
eztype: 'div',
|
|
493
|
+
cls: 'ez-panel',
|
|
494
|
+
style: {
|
|
495
|
+
border: '1px solid var(--ez-border)',
|
|
496
|
+
borderRadius: '4px',
|
|
497
|
+
...props.style
|
|
498
|
+
},
|
|
499
|
+
items: [
|
|
500
|
+
{
|
|
501
|
+
eztype: 'div',
|
|
502
|
+
cls: 'ez-panel-header',
|
|
503
|
+
layout: 'hbox',
|
|
504
|
+
style: {
|
|
505
|
+
padding: '12px 16px',
|
|
506
|
+
background: 'var(--ez-surface)',
|
|
507
|
+
borderBottom: props.collapsed ? 'none' : '1px solid var(--ez-border)',
|
|
508
|
+
cursor: 'pointer'
|
|
509
|
+
},
|
|
510
|
+
items: [
|
|
511
|
+
{ eztype: 'span', text: props.title || '', style: { fontWeight: '600', flex: 1 } },
|
|
512
|
+
{ eztype: 'EzIcon', fa: props.collapsed ? 'chevron-down' : 'chevron-up' }
|
|
513
|
+
]
|
|
514
|
+
},
|
|
515
|
+
!props.collapsed ? {
|
|
516
|
+
eztype: 'div',
|
|
517
|
+
cls: 'ez-panel-body',
|
|
518
|
+
style: { padding: '16px' },
|
|
519
|
+
items: props.items || []
|
|
520
|
+
} : null
|
|
521
|
+
].filter(Boolean)
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// EzPaper - Paper surface
|
|
527
|
+
ssrRegistry['EzPaper'] = {
|
|
528
|
+
template(props) {
|
|
529
|
+
return {
|
|
530
|
+
eztype: 'div',
|
|
531
|
+
cls: 'ez-paper',
|
|
532
|
+
style: {
|
|
533
|
+
background: 'var(--ez-surface)',
|
|
534
|
+
borderRadius: '8px',
|
|
535
|
+
boxShadow: props.elevation ? `0 ${props.elevation * 2}px ${props.elevation * 4}px rgba(0,0,0,0.1)` : undefined,
|
|
536
|
+
padding: '16px',
|
|
537
|
+
...props.style
|
|
538
|
+
},
|
|
539
|
+
items: props.items || []
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// EzSkeleton - Loading skeleton
|
|
545
|
+
ssrRegistry['EzSkeleton'] = {
|
|
546
|
+
template(props) {
|
|
547
|
+
return {
|
|
548
|
+
eztype: 'div',
|
|
549
|
+
cls: 'ez-skeleton',
|
|
550
|
+
style: {
|
|
551
|
+
background: 'linear-gradient(90deg, var(--ez-border) 25%, var(--ez-surface) 50%, var(--ez-border) 75%)',
|
|
552
|
+
backgroundSize: '200% 100%',
|
|
553
|
+
animation: 'skeleton-loading 1.5s infinite',
|
|
554
|
+
borderRadius: props.variant === 'circle' ? '50%' : '4px',
|
|
555
|
+
width: props.width || '100%',
|
|
556
|
+
height: props.height || '20px',
|
|
557
|
+
...props.style
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// EzTooltip - Tooltip wrapper (renders children only in SSR)
|
|
564
|
+
ssrRegistry['EzTooltip'] = {
|
|
565
|
+
template(props) {
|
|
566
|
+
return {
|
|
567
|
+
eztype: 'div',
|
|
568
|
+
cls: 'ez-tooltip-wrapper',
|
|
569
|
+
attr: { title: props.text || props.content },
|
|
570
|
+
items: props.items || []
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// ==================== TABS & NAVIGATION ====================
|
|
576
|
+
|
|
577
|
+
// EzTabPanel - Tabbed content (renders first/active tab in SSR)
|
|
578
|
+
ssrRegistry['EzTabPanel'] = {
|
|
579
|
+
template(props) {
|
|
580
|
+
const tabs = props.items || [];
|
|
581
|
+
const activeId = props.activeTab || props.active || (tabs[0]?.id);
|
|
582
|
+
const activeTab = tabs.find(t => t.id === activeId) || tabs[0];
|
|
583
|
+
|
|
584
|
+
// Tab headers
|
|
585
|
+
const tabHeaders = tabs.map(tab => ({
|
|
586
|
+
eztype: 'div',
|
|
587
|
+
cls: `ez-tab ${tab.id === activeId ? 'active' : ''}`,
|
|
588
|
+
text: tab.title || tab.label || tab.id,
|
|
589
|
+
style: {
|
|
590
|
+
padding: '8px 16px',
|
|
591
|
+
cursor: 'pointer',
|
|
592
|
+
borderBottom: tab.id === activeId ? '2px solid var(--ez-primary)' : '2px solid transparent',
|
|
593
|
+
color: tab.id === activeId ? 'var(--ez-primary)' : 'inherit'
|
|
594
|
+
}
|
|
595
|
+
}));
|
|
596
|
+
|
|
597
|
+
return {
|
|
598
|
+
eztype: 'div',
|
|
599
|
+
cls: 'ez-tab-panel',
|
|
600
|
+
style: props.style,
|
|
601
|
+
items: [
|
|
602
|
+
{
|
|
603
|
+
eztype: 'div',
|
|
604
|
+
cls: 'ez-tab-headers',
|
|
605
|
+
layout: 'hbox',
|
|
606
|
+
style: { borderBottom: '1px solid var(--ez-border)' },
|
|
607
|
+
items: tabHeaders
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
eztype: 'div',
|
|
611
|
+
cls: 'ez-tab-content',
|
|
612
|
+
style: { padding: '16px' },
|
|
613
|
+
items: activeTab?.items || []
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
// ==================== DATA DISPLAY ====================
|
|
621
|
+
|
|
622
|
+
// EzGrid - Data grid (renders simple table in SSR)
|
|
623
|
+
ssrRegistry['EzGrid'] = {
|
|
624
|
+
template(props) {
|
|
625
|
+
const columns = props.columns || [];
|
|
626
|
+
const data = props.data || [];
|
|
627
|
+
|
|
628
|
+
const headerCells = columns.map(col => ({
|
|
629
|
+
eztype: 'th',
|
|
630
|
+
text: col.text || col.header || col.index,
|
|
631
|
+
style: { padding: '12px', textAlign: 'left', fontWeight: '600', borderBottom: '2px solid var(--ez-border)' }
|
|
632
|
+
}));
|
|
633
|
+
|
|
634
|
+
const rows = data.slice(0, 20).map(row => ({
|
|
635
|
+
eztype: 'tr',
|
|
636
|
+
items: columns.map(col => ({
|
|
637
|
+
eztype: 'td',
|
|
638
|
+
text: String(row[col.index] ?? ''),
|
|
639
|
+
style: { padding: '12px', borderBottom: '1px solid var(--ez-border)' }
|
|
640
|
+
}))
|
|
641
|
+
}));
|
|
642
|
+
|
|
643
|
+
return {
|
|
644
|
+
eztype: 'div',
|
|
645
|
+
cls: 'ez-grid',
|
|
646
|
+
style: { overflow: 'auto', ...props.style },
|
|
647
|
+
items: [{
|
|
648
|
+
eztype: 'table',
|
|
649
|
+
style: { width: '100%', borderCollapse: 'collapse' },
|
|
650
|
+
items: [
|
|
651
|
+
{ eztype: 'thead', items: [{ eztype: 'tr', items: headerCells }] },
|
|
652
|
+
{ eztype: 'tbody', items: rows }
|
|
653
|
+
]
|
|
654
|
+
}]
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// EzDataView - Data view (cards/grid/list modes)
|
|
660
|
+
ssrRegistry['EzDataView'] = {
|
|
661
|
+
template(props) {
|
|
662
|
+
return {
|
|
663
|
+
eztype: 'div',
|
|
664
|
+
cls: 'ez-dataview',
|
|
665
|
+
style: props.style,
|
|
666
|
+
items: props.items || [{ eztype: 'div', text: 'Loading...', cls: 'ez-dataview-empty' }]
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// EzTree - Tree view
|
|
672
|
+
ssrRegistry['EzTree'] = {
|
|
673
|
+
template(props) {
|
|
674
|
+
function renderNode(node, level = 0) {
|
|
675
|
+
const hasChildren = node.children && node.children.length > 0;
|
|
676
|
+
return {
|
|
677
|
+
eztype: 'div',
|
|
678
|
+
cls: 'ez-tree-node',
|
|
679
|
+
style: { paddingLeft: `${level * 20}px` },
|
|
680
|
+
items: [
|
|
681
|
+
{
|
|
682
|
+
eztype: 'div',
|
|
683
|
+
cls: 'ez-tree-node-content',
|
|
684
|
+
layout: 'hbox',
|
|
685
|
+
gap: 1,
|
|
686
|
+
style: { padding: '4px 8px', cursor: 'pointer' },
|
|
687
|
+
items: [
|
|
688
|
+
hasChildren ? { eztype: 'EzIcon', fa: 'chevron-right', size: 'sm' } : { eztype: 'span', style: { width: '14px' } },
|
|
689
|
+
node.icon ? { eztype: 'EzIcon', fa: node.icon } : null,
|
|
690
|
+
{ eztype: 'span', text: node.text || node.label || node.name || '' }
|
|
691
|
+
].filter(Boolean)
|
|
692
|
+
},
|
|
693
|
+
...(hasChildren ? node.children.map(child => renderNode(child, level + 1)) : [])
|
|
694
|
+
]
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const data = props.data || [];
|
|
699
|
+
return {
|
|
700
|
+
eztype: 'div',
|
|
701
|
+
cls: 'ez-tree',
|
|
702
|
+
style: props.style,
|
|
703
|
+
items: data.map(node => renderNode(node))
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// EzKanban - Kanban board
|
|
709
|
+
ssrRegistry['EzKanban'] = {
|
|
710
|
+
template(props) {
|
|
711
|
+
const columns = props.columns || [];
|
|
712
|
+
return {
|
|
713
|
+
eztype: 'div',
|
|
714
|
+
cls: 'ez-kanban',
|
|
715
|
+
layout: 'hbox',
|
|
716
|
+
gap: 2,
|
|
717
|
+
style: { overflow: 'auto', ...props.style },
|
|
718
|
+
items: columns.map(col => ({
|
|
719
|
+
eztype: 'div',
|
|
720
|
+
cls: 'ez-kanban-column',
|
|
721
|
+
style: {
|
|
722
|
+
minWidth: '280px', background: 'var(--ez-surface)',
|
|
723
|
+
borderRadius: '8px', padding: '12px'
|
|
724
|
+
},
|
|
725
|
+
items: [
|
|
726
|
+
{ eztype: 'h4', text: col.title || col.name, style: { margin: '0 0 12px' } },
|
|
727
|
+
{
|
|
728
|
+
eztype: 'div',
|
|
729
|
+
cls: 'ez-kanban-cards',
|
|
730
|
+
layout: 'vbox',
|
|
731
|
+
gap: 1,
|
|
732
|
+
items: (col.cards || col.items || []).map(card => ({
|
|
733
|
+
eztype: 'div',
|
|
734
|
+
cls: 'ez-kanban-card',
|
|
735
|
+
style: {
|
|
736
|
+
background: 'var(--ez-background)',
|
|
737
|
+
border: '1px solid var(--ez-border)',
|
|
738
|
+
borderRadius: '4px', padding: '12px'
|
|
739
|
+
},
|
|
740
|
+
text: card.title || card.text || ''
|
|
741
|
+
}))
|
|
742
|
+
}
|
|
743
|
+
]
|
|
744
|
+
}))
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
// EzActivityFeed - Activity feed
|
|
750
|
+
ssrRegistry['EzActivityFeed'] = {
|
|
751
|
+
template(props) {
|
|
752
|
+
const items = (props.items || []).map(item => ({
|
|
753
|
+
eztype: 'div',
|
|
754
|
+
cls: 'ez-activity-item',
|
|
755
|
+
layout: 'hbox',
|
|
756
|
+
gap: 2,
|
|
757
|
+
style: { padding: '12px 0', borderBottom: '1px solid var(--ez-border)' },
|
|
758
|
+
items: [
|
|
759
|
+
item.avatar ? { eztype: 'EzAvatar', ...item.avatar, size: 32 } : null,
|
|
760
|
+
{
|
|
761
|
+
eztype: 'div',
|
|
762
|
+
flex: 1,
|
|
763
|
+
items: [
|
|
764
|
+
{ eztype: 'div', text: item.title || item.text },
|
|
765
|
+
item.time ? { eztype: 'div', text: item.time, style: { fontSize: '12px', color: 'var(--ez-muted)' } } : null
|
|
766
|
+
].filter(Boolean)
|
|
767
|
+
}
|
|
768
|
+
].filter(Boolean)
|
|
769
|
+
}));
|
|
770
|
+
|
|
771
|
+
return {
|
|
772
|
+
eztype: 'div',
|
|
773
|
+
cls: 'ez-activity-feed',
|
|
774
|
+
style: props.style,
|
|
775
|
+
items
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
// ==================== OVERLAYS ====================
|
|
781
|
+
|
|
782
|
+
// EzDialog - Dialog/Modal (renders hidden in SSR)
|
|
783
|
+
ssrRegistry['EzDialog'] = {
|
|
784
|
+
template(props) {
|
|
785
|
+
// Don't render dialog content in SSR - it's an overlay
|
|
786
|
+
return { eztype: 'div', cls: 'ez-dialog-placeholder', style: { display: 'none' } };
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// EzDrawer - Side drawer (renders hidden in SSR)
|
|
791
|
+
ssrRegistry['EzDrawer'] = {
|
|
792
|
+
template(props) {
|
|
793
|
+
return { eztype: 'div', cls: 'ez-drawer-placeholder', style: { display: 'none' } };
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
// EzDropdown - Dropdown menu
|
|
798
|
+
ssrRegistry['EzDropdown'] = {
|
|
799
|
+
template(props) {
|
|
800
|
+
// Just render the trigger, dropdown opens on interaction
|
|
801
|
+
return {
|
|
802
|
+
eztype: 'div',
|
|
803
|
+
cls: 'ez-dropdown',
|
|
804
|
+
style: { position: 'relative', display: 'inline-block', ...props.style },
|
|
805
|
+
items: props.trigger ? [props.trigger] : [{ eztype: 'EzButton', text: props.text || 'Dropdown' }]
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
// EzPicker - Item picker
|
|
811
|
+
ssrRegistry['EzPicker'] = {
|
|
812
|
+
template(props) {
|
|
813
|
+
return {
|
|
814
|
+
eztype: 'div',
|
|
815
|
+
cls: 'ez-picker',
|
|
816
|
+
style: {
|
|
817
|
+
border: '1px solid var(--ez-border)',
|
|
818
|
+
borderRadius: '4px', padding: '8px',
|
|
819
|
+
...props.style
|
|
820
|
+
},
|
|
821
|
+
text: props.placeholder || 'Select...'
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
// EzSearchFilter - Search with filters
|
|
827
|
+
ssrRegistry['EzSearchFilter'] = {
|
|
828
|
+
template(props) {
|
|
829
|
+
return {
|
|
830
|
+
eztype: 'div',
|
|
831
|
+
cls: 'ez-search-filter',
|
|
832
|
+
layout: 'hbox',
|
|
833
|
+
gap: 1,
|
|
834
|
+
style: props.style,
|
|
835
|
+
items: [
|
|
836
|
+
{
|
|
837
|
+
eztype: 'EzInput',
|
|
838
|
+
placeholder: props.placeholder || 'Search...',
|
|
839
|
+
flex: 1
|
|
840
|
+
}
|
|
841
|
+
]
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
// ==================== CHARTS ====================
|
|
847
|
+
|
|
848
|
+
// EzChart - Chart container (placeholder in SSR)
|
|
849
|
+
ssrRegistry['EzChart'] = {
|
|
850
|
+
template(props) {
|
|
851
|
+
return {
|
|
852
|
+
eztype: 'div',
|
|
853
|
+
cls: 'ez-chart',
|
|
854
|
+
style: {
|
|
855
|
+
height: props.height || '300px',
|
|
856
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
857
|
+
background: 'var(--ez-surface)', borderRadius: '8px',
|
|
858
|
+
...props.style
|
|
859
|
+
},
|
|
860
|
+
text: 'Chart loading...'
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
ssrRegistry['EzLineChart'] = ssrRegistry['EzChart'];
|
|
866
|
+
ssrRegistry['EzBarChart'] = ssrRegistry['EzChart'];
|
|
867
|
+
ssrRegistry['EzDoughnutChart'] = ssrRegistry['EzChart'];
|
|
868
|
+
|
|
869
|
+
// ==================== LAYOUT ====================
|
|
870
|
+
|
|
871
|
+
// EzLayout - Layout container
|
|
872
|
+
ssrRegistry['EzLayout'] = {
|
|
873
|
+
template(props) {
|
|
874
|
+
return {
|
|
875
|
+
eztype: 'div',
|
|
876
|
+
cls: 'ez-layout',
|
|
877
|
+
layout: props.layout || 'vbox',
|
|
878
|
+
flex: props.flex,
|
|
879
|
+
gap: props.gap,
|
|
880
|
+
style: props.style,
|
|
881
|
+
items: props.items || []
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
// EzMask - Loading mask (renders hidden in SSR)
|
|
887
|
+
ssrRegistry['EzMask'] = {
|
|
888
|
+
template(props) {
|
|
889
|
+
return { eztype: 'div', cls: 'ez-mask-placeholder', style: { display: 'none' } };
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
// EzOrgChart - Org chart
|
|
894
|
+
ssrRegistry['EzOrgChart'] = {
|
|
895
|
+
template(props) {
|
|
896
|
+
return {
|
|
897
|
+
eztype: 'div',
|
|
898
|
+
cls: 'ez-orgchart',
|
|
899
|
+
style: {
|
|
900
|
+
padding: '20px',
|
|
901
|
+
background: 'var(--ez-surface)',
|
|
902
|
+
borderRadius: '8px',
|
|
903
|
+
...props.style
|
|
904
|
+
},
|
|
905
|
+
text: 'Organization Chart'
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
// EzOutlet - Router outlet
|
|
911
|
+
ssrRegistry['EzOutlet'] = {
|
|
912
|
+
template(props) {
|
|
913
|
+
return {
|
|
914
|
+
eztype: 'div',
|
|
915
|
+
cls: 'ez-outlet',
|
|
916
|
+
style: props.style,
|
|
917
|
+
items: props.items || []
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// EzToast - Toast notifications (handled by service, not rendered)
|
|
923
|
+
ssrRegistry['EzToast'] = {
|
|
924
|
+
template(props) {
|
|
925
|
+
return { eztype: 'div', cls: 'ez-toast-placeholder', style: { display: 'none' } };
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
console.log('[SSR Shim] Framework components registered:', Object.keys(ssrRegistry).filter(k => k.startsWith('Ez')).join(', '));
|
|
85
930
|
}
|
|
86
931
|
|
|
87
932
|
const ezSSR = {
|
|
@@ -99,17 +944,9 @@ const ezSSR = {
|
|
|
99
944
|
},
|
|
100
945
|
|
|
101
946
|
// Mock getControllerSync to return controller state for SSR
|
|
102
|
-
// Handles both "MyController" and "My" (framework adds "Controller" suffix)
|
|
103
947
|
getControllerSync(name) {
|
|
104
|
-
// Try exact match first
|
|
105
948
|
let ctrl = ssrControllers[name];
|
|
106
|
-
|
|
107
|
-
// Try with Controller suffix
|
|
108
|
-
if (!ctrl) {
|
|
109
|
-
ctrl = ssrControllers[name + 'Controller'];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Try removing Controller suffix
|
|
949
|
+
if (!ctrl) ctrl = ssrControllers[name + 'Controller'];
|
|
113
950
|
if (!ctrl && name.endsWith('Controller')) {
|
|
114
951
|
ctrl = ssrControllers[name.replace('Controller', '')];
|
|
115
952
|
}
|
|
@@ -118,12 +955,9 @@ const ezSSR = {
|
|
|
118
955
|
return { state: ctrl.state || {} };
|
|
119
956
|
}
|
|
120
957
|
|
|
121
|
-
console.warn(`[SSR Shim] Controller not found: ${name}`);
|
|
122
|
-
console.warn(`[SSR Shim] Available controllers: ${Object.keys(ssrControllers).join(', ')}`);
|
|
123
958
|
return { state: {} };
|
|
124
959
|
},
|
|
125
960
|
|
|
126
|
-
// Mock getController (async version)
|
|
127
961
|
getController(name) {
|
|
128
962
|
return this.getControllerSync(name);
|
|
129
963
|
},
|
|
@@ -132,26 +966,23 @@ const ezSSR = {
|
|
|
132
966
|
return ssrRegistry[name];
|
|
133
967
|
},
|
|
134
968
|
|
|
135
|
-
// Clear registry (useful between renders) - preserves framework components
|
|
136
969
|
_clear() {
|
|
137
970
|
Object.keys(ssrRegistry).forEach(k => delete ssrRegistry[k]);
|
|
138
971
|
Object.keys(ssrControllers).forEach(k => delete ssrControllers[k]);
|
|
139
|
-
// Re-register framework components after clear
|
|
140
972
|
registerFrameworkComponents();
|
|
141
973
|
}
|
|
142
974
|
};
|
|
143
975
|
|
|
144
|
-
// Make available globally
|
|
976
|
+
// Make available globally
|
|
145
977
|
globalThis.ez = ezSSR;
|
|
146
978
|
if (typeof global !== 'undefined') {
|
|
147
979
|
global.ez = ezSSR;
|
|
148
980
|
}
|
|
149
981
|
|
|
150
|
-
// Register
|
|
982
|
+
// Register all components
|
|
151
983
|
registerFrameworkComponents();
|
|
152
984
|
|
|
153
|
-
console.log('[SSR Shim] Initialized
|
|
154
|
-
console.log('[SSR Shim] Framework components registered: EzIcon, EzLabel, EzButton');
|
|
985
|
+
console.log('[SSR Shim] Initialized with all framework components');
|
|
155
986
|
|
|
156
987
|
export { ezSSR as ez };
|
|
157
988
|
export default ezSSR;
|