slicejs-web-framework 2.2.2 → 2.2.5
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/Slice/Components/Structural/Controller/Controller.js +151 -68
- package/Slice/Components/Structural/Router/Router.js +62 -17
- package/package.json +1 -1
- package/src/App/index.js +1 -1
- package/src/Components/AppComponents/HomePage/HomePage.js +195 -195
- package/src/Components/components.js +27 -27
|
@@ -5,8 +5,13 @@ export default class Controller {
|
|
|
5
5
|
this.componentCategories = new Map(Object.entries(components));
|
|
6
6
|
this.templates = new Map();
|
|
7
7
|
this.classes = new Map();
|
|
8
|
-
this.requestedStyles = new Set();
|
|
8
|
+
this.requestedStyles = new Set(); // ✅ CRÍTICO: Para tracking de CSS cargados
|
|
9
9
|
this.activeComponents = new Map();
|
|
10
|
+
|
|
11
|
+
// 🚀 OPTIMIZACIÓN: Índice inverso para búsqueda rápida de hijos
|
|
12
|
+
// parentSliceId → Set<childSliceId>
|
|
13
|
+
this.childrenIndex = new Map();
|
|
14
|
+
|
|
10
15
|
this.idCounter = 0;
|
|
11
16
|
}
|
|
12
17
|
|
|
@@ -65,9 +70,27 @@ export default class Controller {
|
|
|
65
70
|
return true;
|
|
66
71
|
}
|
|
67
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Registra un componente y actualiza el índice de relaciones padre-hijo
|
|
75
|
+
* 🚀 OPTIMIZADO: Ahora mantiene childrenIndex y precalcula profundidad
|
|
76
|
+
*/
|
|
68
77
|
registerComponent(component, parent = null) {
|
|
69
78
|
component.parentComponent = parent;
|
|
79
|
+
|
|
80
|
+
// 🚀 OPTIMIZACIÓN: Precalcular y guardar profundidad
|
|
81
|
+
component._depth = parent ? (parent._depth || 0) + 1 : 0;
|
|
82
|
+
|
|
83
|
+
// Registrar en activeComponents
|
|
70
84
|
this.activeComponents.set(component.sliceId, component);
|
|
85
|
+
|
|
86
|
+
// 🚀 OPTIMIZACIÓN: Actualizar índice inverso de hijos
|
|
87
|
+
if (parent) {
|
|
88
|
+
if (!this.childrenIndex.has(parent.sliceId)) {
|
|
89
|
+
this.childrenIndex.set(parent.sliceId, new Set());
|
|
90
|
+
}
|
|
91
|
+
this.childrenIndex.get(parent.sliceId).add(component.sliceId);
|
|
92
|
+
}
|
|
93
|
+
|
|
71
94
|
return true;
|
|
72
95
|
}
|
|
73
96
|
|
|
@@ -92,7 +115,6 @@ export default class Controller {
|
|
|
92
115
|
return this.activeComponents.get(sliceId);
|
|
93
116
|
}
|
|
94
117
|
|
|
95
|
-
//Attach template to component
|
|
96
118
|
loadTemplateToComponent(component) {
|
|
97
119
|
const className = component.constructor.name;
|
|
98
120
|
const template = this.templates.get(className);
|
|
@@ -110,14 +132,6 @@ export default class Controller {
|
|
|
110
132
|
return this.componentCategories.get(componentSliceId);
|
|
111
133
|
}
|
|
112
134
|
|
|
113
|
-
/*
|
|
114
|
-
Fetches a text resource (HTML, CSS, theme, or styles) for a component.
|
|
115
|
-
@param {string} componentName - The name of the component.
|
|
116
|
-
@param {string} resourceType - The type of resource to fetch ('html', 'css', 'theme', or 'styles').
|
|
117
|
-
@param {string} [componentCategory] - Optional category of the component.
|
|
118
|
-
@param {string} [customPath] - Optional custom path to fetch the resource from.
|
|
119
|
-
@returns {Promise<string>} - A promise that resolves to the fetched text.
|
|
120
|
-
*/
|
|
121
135
|
async fetchText(componentName, resourceType, componentCategory, customPath) {
|
|
122
136
|
try {
|
|
123
137
|
const baseUrl = window.location.origin;
|
|
@@ -130,12 +144,10 @@ export default class Controller {
|
|
|
130
144
|
let isVisual = resourceType === 'html' || resourceType === 'css';
|
|
131
145
|
|
|
132
146
|
if (isVisual) {
|
|
133
|
-
// ✅ CORREGIDO: Verificar que la categoría existe y agregar baseUrl
|
|
134
147
|
if (slice.paths.components[componentCategory]) {
|
|
135
148
|
path = `${baseUrl}${slice.paths.components[componentCategory].path}/${componentName}`;
|
|
136
149
|
resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
|
|
137
150
|
} else {
|
|
138
|
-
// ✅ FALLBACK: Para componentes Structural o categorías no configuradas
|
|
139
151
|
if (componentCategory === 'Structural') {
|
|
140
152
|
path = `${baseUrl}/Slice/Components/Structural/${componentName}`;
|
|
141
153
|
resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
|
|
@@ -157,7 +169,6 @@ export default class Controller {
|
|
|
157
169
|
path = customPath;
|
|
158
170
|
}
|
|
159
171
|
|
|
160
|
-
// ✅ MEJORADO: Logging para debugging
|
|
161
172
|
slice.logger.logInfo('Controller', `Fetching ${resourceType} from: ${path}`);
|
|
162
173
|
|
|
163
174
|
const response = await fetch(path);
|
|
@@ -171,7 +182,6 @@ export default class Controller {
|
|
|
171
182
|
return content;
|
|
172
183
|
} catch (error) {
|
|
173
184
|
slice.logger.logError('Controller', `Error fetching ${resourceType} for component ${componentName}:`, error);
|
|
174
|
-
// ✅ CORREGIDO: Re-lanzar el error para que el debugger pueda manejarlo
|
|
175
185
|
throw error;
|
|
176
186
|
}
|
|
177
187
|
}
|
|
@@ -180,17 +190,17 @@ export default class Controller {
|
|
|
180
190
|
const ComponentClass = component.constructor;
|
|
181
191
|
const componentName = ComponentClass.name;
|
|
182
192
|
|
|
183
|
-
//
|
|
193
|
+
// Aplicar defaults si tiene static props
|
|
184
194
|
if (ComponentClass.props) {
|
|
185
195
|
this.applyDefaultProps(component, ComponentClass.props, props);
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
//
|
|
198
|
+
// Validar solo en desarrollo
|
|
189
199
|
if (ComponentClass.props && !slice.isProduction()) {
|
|
190
200
|
this.validatePropsInDevelopment(ComponentClass, props, componentName);
|
|
191
201
|
}
|
|
192
202
|
|
|
193
|
-
//
|
|
203
|
+
// Aplicar props
|
|
194
204
|
for (const prop in props) {
|
|
195
205
|
component[`_${prop}`] = null;
|
|
196
206
|
component[prop] = props[prop];
|
|
@@ -201,14 +211,12 @@ export default class Controller {
|
|
|
201
211
|
const ComponentClass = component.constructor;
|
|
202
212
|
|
|
203
213
|
if (ComponentClass.props) {
|
|
204
|
-
// Si tiene props estáticos, usar esos como referencia
|
|
205
214
|
return {
|
|
206
215
|
availableProps: Object.keys(ComponentClass.props),
|
|
207
216
|
propsConfig: ComponentClass.props,
|
|
208
217
|
usedProps: this.extractUsedProps(component, ComponentClass.props)
|
|
209
218
|
};
|
|
210
219
|
} else {
|
|
211
|
-
// Si no tiene props estáticos, usar modo legacy
|
|
212
220
|
return {
|
|
213
221
|
availableProps: this.extractUsedProps(component),
|
|
214
222
|
propsConfig: null,
|
|
@@ -257,14 +265,12 @@ export default class Controller {
|
|
|
257
265
|
const usedProps = {};
|
|
258
266
|
|
|
259
267
|
if (staticProps) {
|
|
260
|
-
// Si tiene props estáticos, buscar solo esos
|
|
261
268
|
Object.keys(staticProps).forEach(prop => {
|
|
262
269
|
if (component[prop] !== undefined) {
|
|
263
270
|
usedProps[prop] = component[prop];
|
|
264
271
|
}
|
|
265
272
|
});
|
|
266
273
|
} else {
|
|
267
|
-
// Modo legacy: buscar cualquier prop que empiece con _
|
|
268
274
|
Object.getOwnPropertyNames(component).forEach(key => {
|
|
269
275
|
if (key.startsWith('_') && key !== '_isActive') {
|
|
270
276
|
const propName = key.substring(1);
|
|
@@ -276,52 +282,135 @@ export default class Controller {
|
|
|
276
282
|
return usedProps;
|
|
277
283
|
}
|
|
278
284
|
|
|
285
|
+
// ============================================================================
|
|
286
|
+
// 🚀 MÉTODOS DE DESTRUCCIÓN OPTIMIZADOS
|
|
287
|
+
// ============================================================================
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Encuentra recursivamente todos los hijos de un componente
|
|
291
|
+
* 🚀 OPTIMIZADO: O(m) en lugar de O(n*d) - usa childrenIndex
|
|
292
|
+
* @param {string} parentSliceId - sliceId del componente padre
|
|
293
|
+
* @param {Set<string>} collected - Set de sliceIds ya recolectados
|
|
294
|
+
* @returns {Set<string>} Set de todos los sliceIds de componentes hijos
|
|
295
|
+
*/
|
|
296
|
+
findAllChildComponents(parentSliceId, collected = new Set()) {
|
|
297
|
+
// 🚀 Buscar directamente en el índice: O(1)
|
|
298
|
+
const children = this.childrenIndex.get(parentSliceId);
|
|
299
|
+
|
|
300
|
+
if (!children) return collected;
|
|
301
|
+
|
|
302
|
+
// 🚀 Iterar solo los hijos directos: O(k) donde k = número de hijos
|
|
303
|
+
for (const childSliceId of children) {
|
|
304
|
+
collected.add(childSliceId);
|
|
305
|
+
// Recursión solo sobre hijos, no todos los componentes
|
|
306
|
+
this.findAllChildComponents(childSliceId, collected);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return collected;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Encuentra recursivamente todos los componentes dentro de un contenedor DOM
|
|
314
|
+
* Útil para destroyByContainer cuando no tenemos el sliceId del padre
|
|
315
|
+
* @param {HTMLElement} container - Elemento contenedor
|
|
316
|
+
* @param {Set<string>} collected - Set de sliceIds ya recolectados
|
|
317
|
+
* @returns {Set<string>} Set de todos los sliceIds encontrados
|
|
318
|
+
*/
|
|
319
|
+
findAllNestedComponentsInContainer(container, collected = new Set()) {
|
|
320
|
+
// Buscar todos los elementos con slice-id en el contenedor
|
|
321
|
+
const sliceComponents = container.querySelectorAll('[slice-id]');
|
|
322
|
+
|
|
323
|
+
sliceComponents.forEach(element => {
|
|
324
|
+
const sliceId = element.getAttribute('slice-id') || element.sliceId;
|
|
325
|
+
if (sliceId && this.activeComponents.has(sliceId)) {
|
|
326
|
+
collected.add(sliceId);
|
|
327
|
+
// 🚀 Usar índice para buscar hijos recursivamente
|
|
328
|
+
this.findAllChildComponents(sliceId, collected);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return collected;
|
|
333
|
+
}
|
|
334
|
+
|
|
279
335
|
/**
|
|
280
|
-
* Destruye uno o múltiples componentes
|
|
336
|
+
* Destruye uno o múltiples componentes DE FORMA RECURSIVA
|
|
337
|
+
* 🚀 OPTIMIZADO: O(m log m) en lugar de O(n*d + m log m)
|
|
281
338
|
* @param {HTMLElement|Array<HTMLElement>|string|Array<string>} components
|
|
282
|
-
*
|
|
283
|
-
* - Array de componentes
|
|
284
|
-
* - sliceId individual (string)
|
|
285
|
-
* - Array de sliceIds
|
|
286
|
-
* @returns {number} Cantidad de componentes destruidos
|
|
339
|
+
* @returns {number} Cantidad de componentes destruidos (incluyendo hijos)
|
|
287
340
|
*/
|
|
288
341
|
destroyComponent(components) {
|
|
289
|
-
// Normalizar entrada a array
|
|
290
342
|
const toDestroy = Array.isArray(components) ? components : [components];
|
|
291
|
-
|
|
343
|
+
const allSliceIdsToDestroy = new Set();
|
|
292
344
|
|
|
345
|
+
// PASO 1: Recolectar todos los componentes padres y sus hijos recursivamente
|
|
293
346
|
for (const item of toDestroy) {
|
|
294
|
-
let
|
|
347
|
+
let sliceId = null;
|
|
295
348
|
|
|
296
|
-
// Si es string, buscar el componente por sliceId
|
|
297
349
|
if (typeof item === 'string') {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (!component) {
|
|
350
|
+
if (!this.activeComponents.has(item)) {
|
|
301
351
|
slice.logger.logWarning('Controller', `Component with sliceId "${item}" not found`);
|
|
302
352
|
continue;
|
|
303
353
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
354
|
+
sliceId = item;
|
|
355
|
+
} else if (item && item.sliceId) {
|
|
356
|
+
sliceId = item.sliceId;
|
|
357
|
+
} else {
|
|
310
358
|
slice.logger.logWarning('Controller', `Invalid component or sliceId provided to destroyComponent`);
|
|
311
359
|
continue;
|
|
312
360
|
}
|
|
313
361
|
|
|
362
|
+
allSliceIdsToDestroy.add(sliceId);
|
|
363
|
+
|
|
364
|
+
// 🚀 OPTIMIZADO: Usa childrenIndex en lugar de recorrer todos los componentes
|
|
365
|
+
this.findAllChildComponents(sliceId, allSliceIdsToDestroy);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// PASO 2: Ordenar por profundidad (más profundos primero)
|
|
369
|
+
// 🚀 OPTIMIZADO: Usa _depth precalculada en lugar de calcularla cada vez
|
|
370
|
+
const sortedSliceIds = Array.from(allSliceIdsToDestroy).sort((a, b) => {
|
|
371
|
+
const compA = this.activeComponents.get(a);
|
|
372
|
+
const compB = this.activeComponents.get(b);
|
|
373
|
+
|
|
374
|
+
if (!compA || !compB) return 0;
|
|
375
|
+
|
|
376
|
+
// 🚀 O(1) en lugar de O(d) - usa profundidad precalculada
|
|
377
|
+
return (compB._depth || 0) - (compA._depth || 0);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
let destroyedCount = 0;
|
|
381
|
+
|
|
382
|
+
// PASO 3: Destruir en orden correcto (hijos antes que padres)
|
|
383
|
+
for (const sliceId of sortedSliceIds) {
|
|
384
|
+
const component = this.activeComponents.get(sliceId);
|
|
385
|
+
|
|
386
|
+
if (!component) continue;
|
|
387
|
+
|
|
314
388
|
// Ejecutar hook beforeDestroy si existe
|
|
315
389
|
if (typeof component.beforeDestroy === 'function') {
|
|
316
390
|
try {
|
|
317
391
|
component.beforeDestroy();
|
|
318
392
|
} catch (error) {
|
|
319
|
-
slice.logger.logError('Controller', `Error in beforeDestroy for ${
|
|
393
|
+
slice.logger.logError('Controller', `Error in beforeDestroy for ${sliceId}`, error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// 🚀 Limpiar del índice de hijos
|
|
398
|
+
this.childrenIndex.delete(sliceId);
|
|
399
|
+
|
|
400
|
+
// Si tiene padre, remover de la lista de hijos del padre
|
|
401
|
+
if (component.parentComponent) {
|
|
402
|
+
const parentChildren = this.childrenIndex.get(component.parentComponent.sliceId);
|
|
403
|
+
if (parentChildren) {
|
|
404
|
+
parentChildren.delete(sliceId);
|
|
405
|
+
// Si el padre no tiene más hijos, eliminar entrada vacía
|
|
406
|
+
if (parentChildren.size === 0) {
|
|
407
|
+
this.childrenIndex.delete(component.parentComponent.sliceId);
|
|
408
|
+
}
|
|
320
409
|
}
|
|
321
410
|
}
|
|
322
411
|
|
|
323
412
|
// Eliminar del mapa de componentes activos
|
|
324
|
-
this.activeComponents.delete(
|
|
413
|
+
this.activeComponents.delete(sliceId);
|
|
325
414
|
|
|
326
415
|
// Remover del DOM si está conectado
|
|
327
416
|
if (component.isConnected) {
|
|
@@ -332,14 +421,15 @@ export default class Controller {
|
|
|
332
421
|
}
|
|
333
422
|
|
|
334
423
|
if (destroyedCount > 0) {
|
|
335
|
-
slice.logger.logInfo('Controller', `Destroyed ${destroyedCount} component(s)`);
|
|
424
|
+
slice.logger.logInfo('Controller', `Destroyed ${destroyedCount} component(s) recursively`);
|
|
336
425
|
}
|
|
337
426
|
|
|
338
427
|
return destroyedCount;
|
|
339
428
|
}
|
|
340
429
|
|
|
341
430
|
/**
|
|
342
|
-
* Destruye todos los componentes Slice dentro de un contenedor
|
|
431
|
+
* Destruye todos los componentes Slice dentro de un contenedor (RECURSIVO)
|
|
432
|
+
* 🚀 OPTIMIZADO: Usa el índice inverso para búsqueda rápida
|
|
343
433
|
* @param {HTMLElement} container - Elemento contenedor
|
|
344
434
|
* @returns {number} Cantidad de componentes destruidos
|
|
345
435
|
*/
|
|
@@ -349,56 +439,49 @@ export default class Controller {
|
|
|
349
439
|
return 0;
|
|
350
440
|
}
|
|
351
441
|
|
|
352
|
-
//
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (sliceId && this.activeComponents.has(sliceId)) {
|
|
359
|
-
sliceIdsToDestroy.push(sliceId);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
442
|
+
// 🚀 Recolectar componentes usando índice optimizado
|
|
443
|
+
const allSliceIds = this.findAllNestedComponentsInContainer(container);
|
|
444
|
+
|
|
445
|
+
if (allSliceIds.size === 0) {
|
|
446
|
+
return 0;
|
|
447
|
+
}
|
|
362
448
|
|
|
363
|
-
// Destruir usando el método principal
|
|
364
|
-
const count = this.destroyComponent(
|
|
449
|
+
// Destruir usando el método principal optimizado
|
|
450
|
+
const count = this.destroyComponent(Array.from(allSliceIds));
|
|
365
451
|
|
|
366
452
|
if (count > 0) {
|
|
367
|
-
slice.logger.logInfo('Controller', `Destroyed ${count} component(s) from container`);
|
|
453
|
+
slice.logger.logInfo('Controller', `Destroyed ${count} component(s) from container (including nested)`);
|
|
368
454
|
}
|
|
369
455
|
|
|
370
456
|
return count;
|
|
371
457
|
}
|
|
372
458
|
|
|
373
459
|
/**
|
|
374
|
-
* Destruye componentes cuyos sliceId coincidan con un patrón
|
|
375
|
-
*
|
|
460
|
+
* Destruye componentes cuyos sliceId coincidan con un patrón (RECURSIVO)
|
|
461
|
+
* 🚀 OPTIMIZADO: Usa destrucción optimizada
|
|
462
|
+
* @param {string|RegExp} pattern - Patrón a buscar
|
|
376
463
|
* @returns {number} Cantidad de componentes destruidos
|
|
377
464
|
*/
|
|
378
465
|
destroyByPattern(pattern) {
|
|
379
466
|
const componentsToDestroy = [];
|
|
380
|
-
|
|
381
|
-
// Convertir string a RegExp si es necesario
|
|
382
467
|
const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern);
|
|
383
468
|
|
|
384
|
-
// Buscar componentes que coincidan con el patrón
|
|
385
469
|
for (const [sliceId, component] of this.activeComponents) {
|
|
386
470
|
if (regex.test(sliceId)) {
|
|
387
471
|
componentsToDestroy.push(component);
|
|
388
472
|
}
|
|
389
473
|
}
|
|
390
474
|
|
|
391
|
-
|
|
475
|
+
if (componentsToDestroy.length === 0) {
|
|
476
|
+
return 0;
|
|
477
|
+
}
|
|
478
|
+
|
|
392
479
|
const count = this.destroyComponent(componentsToDestroy);
|
|
393
480
|
|
|
394
481
|
if (count > 0) {
|
|
395
|
-
slice.logger.logInfo('Controller', `Destroyed ${count} component(s) matching pattern: ${pattern}`);
|
|
482
|
+
slice.logger.logInfo('Controller', `Destroyed ${count} component(s) matching pattern: ${pattern} (including nested)`);
|
|
396
483
|
}
|
|
397
484
|
|
|
398
485
|
return count;
|
|
399
486
|
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function getRelativePath(levels) {
|
|
403
|
-
return '../'.repeat(levels);
|
|
404
487
|
}
|
|
@@ -139,7 +139,7 @@ export default class Router {
|
|
|
139
139
|
* Ejecuta el beforeEach guard si existe
|
|
140
140
|
* @param {Object} to - Información de ruta destino
|
|
141
141
|
* @param {Object} from - Información de ruta origen
|
|
142
|
-
* @returns {
|
|
142
|
+
* @returns {Object|null} Objeto con redirectPath y options, o null si continúa
|
|
143
143
|
*/
|
|
144
144
|
async _executeBeforeEachGuard(to, from) {
|
|
145
145
|
if (!this._beforeEachGuard) {
|
|
@@ -147,18 +147,45 @@ export default class Router {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
let redirectPath = null;
|
|
150
|
+
let redirectOptions = {};
|
|
150
151
|
let nextCalled = false;
|
|
151
152
|
|
|
152
|
-
const next = (
|
|
153
|
+
const next = (arg) => {
|
|
153
154
|
if (nextCalled) {
|
|
154
155
|
slice.logger.logWarning('Router', 'next() called multiple times in guard');
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
157
158
|
nextCalled = true;
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
// Caso 1: Sin argumentos - continuar navegación
|
|
161
|
+
if (arg === undefined) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Caso 2: false - cancelar navegación
|
|
166
|
+
if (arg === false) {
|
|
167
|
+
redirectPath = false;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Caso 3: String - redirección simple (backward compatibility)
|
|
172
|
+
if (typeof arg === 'string') {
|
|
173
|
+
redirectPath = arg;
|
|
174
|
+
redirectOptions = { replace: false };
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Caso 4: Objeto - redirección con opciones
|
|
179
|
+
if (typeof arg === 'object' && arg.path) {
|
|
180
|
+
redirectPath = arg.path;
|
|
181
|
+
redirectOptions = {
|
|
182
|
+
replace: arg.replace || false
|
|
183
|
+
};
|
|
184
|
+
return;
|
|
161
185
|
}
|
|
186
|
+
|
|
187
|
+
// Argumento inválido
|
|
188
|
+
slice.logger.logError('Router', 'Invalid argument passed to next(). Expected string, object with path, false, or undefined.');
|
|
162
189
|
};
|
|
163
190
|
|
|
164
191
|
try {
|
|
@@ -172,7 +199,8 @@ export default class Router {
|
|
|
172
199
|
);
|
|
173
200
|
}
|
|
174
201
|
|
|
175
|
-
|
|
202
|
+
// Retornar tanto el path como las opciones
|
|
203
|
+
return redirectPath ? { path: redirectPath, options: redirectOptions } : null;
|
|
176
204
|
} catch (error) {
|
|
177
205
|
slice.logger.logError('Router', 'Error in beforeEach guard', error);
|
|
178
206
|
return null; // En caso de error, continuar con la navegación
|
|
@@ -200,7 +228,7 @@ export default class Router {
|
|
|
200
228
|
// ROUTING CORE (MODIFICADO CON GUARDS)
|
|
201
229
|
// ============================================
|
|
202
230
|
|
|
203
|
-
|
|
231
|
+
async navigate(path, _redirectChain = [], _options = {}) {
|
|
204
232
|
const currentPath = window.location.pathname;
|
|
205
233
|
|
|
206
234
|
|
|
@@ -228,21 +256,32 @@ export default class Router {
|
|
|
228
256
|
|
|
229
257
|
// Obtener información de ruta destino
|
|
230
258
|
const { route: toRoute, params: toParams } = this.matchRoute(path);
|
|
231
|
-
const to = this._createRouteInfo(toRoute, toParams, path);
|
|
259
|
+
const to = this._createRouteInfo(toRoute, toParams, path);
|
|
232
260
|
|
|
233
261
|
|
|
234
262
|
// EJECUTAR BEFORE EACH GUARD
|
|
235
|
-
const
|
|
263
|
+
const guardResult = await this._executeBeforeEachGuard(to, from);
|
|
236
264
|
|
|
237
|
-
// Si el guard redirige
|
|
238
|
-
if (
|
|
265
|
+
// Si el guard redirige
|
|
266
|
+
if (guardResult && guardResult.path) {
|
|
239
267
|
const newChain = [..._redirectChain, path];
|
|
268
|
+
return this.navigate(guardResult.path, newChain, guardResult.options);
|
|
269
|
+
}
|
|
240
270
|
|
|
241
|
-
|
|
271
|
+
// Si el guard cancela la navegación (next(false))
|
|
272
|
+
if (guardResult && guardResult.path === false) {
|
|
273
|
+
slice.logger.logInfo('Router', 'Navigation cancelled by guard');
|
|
274
|
+
return;
|
|
242
275
|
}
|
|
243
276
|
|
|
244
277
|
// No hay redirección - continuar con la navegación normal
|
|
245
|
-
|
|
278
|
+
// Usar replace o push según las opciones
|
|
279
|
+
if (_options.replace) {
|
|
280
|
+
window.history.replaceState({}, path, window.location.origin + path);
|
|
281
|
+
} else {
|
|
282
|
+
window.history.pushState({}, path, window.location.origin + path);
|
|
283
|
+
}
|
|
284
|
+
|
|
246
285
|
await this._performNavigation(to, from);
|
|
247
286
|
}
|
|
248
287
|
|
|
@@ -323,19 +362,25 @@ export default class Router {
|
|
|
323
362
|
slice.router.activeRoute = route;
|
|
324
363
|
}
|
|
325
364
|
|
|
326
|
-
|
|
365
|
+
async loadInitialRoute() {
|
|
327
366
|
const path = window.location.pathname;
|
|
328
367
|
const { route, params } = this.matchRoute(path);
|
|
329
368
|
|
|
330
369
|
// Para la carga inicial, también ejecutar guards
|
|
331
370
|
const from = this._createRouteInfo(null, {}, null);
|
|
332
|
-
const to = this._createRouteInfo(route, params, path);
|
|
371
|
+
const to = this._createRouteInfo(route, params, path);
|
|
333
372
|
|
|
334
373
|
// EJECUTAR BEFORE EACH GUARD en carga inicial
|
|
335
|
-
const
|
|
374
|
+
const guardResult = await this._executeBeforeEachGuard(to, from);
|
|
336
375
|
|
|
337
|
-
if (
|
|
338
|
-
return this.navigate(
|
|
376
|
+
if (guardResult && guardResult.path) {
|
|
377
|
+
return this.navigate(guardResult.path, [], guardResult.options);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Si el guard cancela la navegación inicial (caso raro pero posible)
|
|
381
|
+
if (guardResult && guardResult.path === false) {
|
|
382
|
+
slice.logger.logWarning('Router', 'Initial route navigation cancelled by guard');
|
|
383
|
+
return;
|
|
339
384
|
}
|
|
340
385
|
|
|
341
386
|
await this.handleRoute(route, params);
|
package/package.json
CHANGED
package/src/App/index.js
CHANGED
|
@@ -7,7 +7,7 @@ slice.router.beforeEach(async (to, from, next) => {
|
|
|
7
7
|
if(to.metadata.private){
|
|
8
8
|
const isAuthenticated = await //fetchlogic for validation
|
|
9
9
|
if(!isAuthenticated){
|
|
10
|
-
return next({ path: '/login' });
|
|
10
|
+
return next({ path: '/login', replace: true });
|
|
11
11
|
}
|
|
12
12
|
return next();
|
|
13
13
|
}
|
|
@@ -1,196 +1,196 @@
|
|
|
1
|
-
export default class HomePage extends HTMLElement {
|
|
2
|
-
constructor(props) {
|
|
3
|
-
super();
|
|
4
|
-
slice.attachTemplate(this);
|
|
5
|
-
|
|
6
|
-
this.$examplesContainer = this.querySelector('.examples-container');
|
|
7
|
-
|
|
8
|
-
slice.controller.setComponentProps(this, props);
|
|
9
|
-
this.debuggerProps = [];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async init() {
|
|
13
|
-
// Crear la barra de navegación
|
|
14
|
-
const navbar = await slice.build('Navbar', {
|
|
15
|
-
position: 'fixed',
|
|
16
|
-
logo: {
|
|
17
|
-
src: '/images/Slice.js-logo.png',
|
|
18
|
-
path: '/',
|
|
19
|
-
},
|
|
20
|
-
items: [
|
|
21
|
-
{ text: 'Home', path: '/' },
|
|
22
|
-
{ text: 'Playground', path: '/Playground' },
|
|
23
|
-
|
|
24
|
-
],
|
|
25
|
-
buttons: [
|
|
26
|
-
{
|
|
27
|
-
value: 'Change Theme',
|
|
28
|
-
onClickCallback: async () => {
|
|
29
|
-
const currentTheme = slice.stylesManager.themeManager.currentTheme;
|
|
30
|
-
if (currentTheme === 'Slice') {
|
|
31
|
-
await slice.setTheme('Light');
|
|
32
|
-
} else if (currentTheme === 'Light') {
|
|
33
|
-
await slice.setTheme('Dark');
|
|
34
|
-
} else {
|
|
35
|
-
await slice.setTheme('Slice');
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
// Crear botones para la sección de llamada a la acción
|
|
43
|
-
const docsButton = await slice.build('Button', {
|
|
44
|
-
value: 'Documentation',
|
|
45
|
-
onClickCallback: () => //redirect to https://slice-js-docs.vercel.app/Documentation
|
|
46
|
-
window.open('https://slice-js-docs.vercel.app/Documentation', '_blank'),
|
|
47
|
-
customColor: {
|
|
48
|
-
button: 'var(--primary-color)',
|
|
49
|
-
label: 'var(--primary-color-contrast)'
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const componentsButton = await slice.build('Button', {
|
|
54
|
-
value: 'Components Library',
|
|
55
|
-
onClickCallback: () => window.open('https://slice-js-docs.vercel.app/Documentation/Visual', '_blank'),
|
|
56
|
-
customColor: {
|
|
57
|
-
button: 'var(--secondary-color)',
|
|
58
|
-
label: 'var(--secondary-color-contrast)'
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Añadir botones a la sección CTA
|
|
63
|
-
this.querySelector('.cta-buttons').appendChild(docsButton);
|
|
64
|
-
this.querySelector('.cta-buttons').appendChild(componentsButton);
|
|
65
|
-
|
|
66
|
-
// Crear features section con un enfoque diferente (sin usar Cards)
|
|
67
|
-
await this.createFeatures();
|
|
68
|
-
|
|
69
|
-
// Crear ejemplos de componentes
|
|
70
|
-
await this.createComponentExamples();
|
|
71
|
-
|
|
72
|
-
// Configurar la sección de código de inicio
|
|
73
|
-
await this.setupGettingStartedSection();
|
|
74
|
-
|
|
75
|
-
// Añadir la barra de navegación al inicio del componente
|
|
76
|
-
this.insertBefore(navbar, this.firstChild);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async createFeatures() {
|
|
80
|
-
// Definir características
|
|
81
|
-
const features = [
|
|
82
|
-
{
|
|
83
|
-
title: 'Component-Based',
|
|
84
|
-
description: 'Build your app using modular, reusable components following web standards.'
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
title: 'Zero Dependencies',
|
|
88
|
-
description: 'Built with vanilla JavaScript. No external libraries required.'
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
title: 'Easy Routing',
|
|
92
|
-
description: 'Simple and powerful routing system for single page applications.'
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
title: 'Theme System',
|
|
96
|
-
description: 'Built-in theme support with easy customization through CSS variables.'
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
title: 'Developer Tools',
|
|
100
|
-
description: 'Integrated debugging and logging for faster development.'
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
title: 'Performance Focused',
|
|
104
|
-
description: 'Lightweight and optimized for fast loading and execution.'
|
|
105
|
-
}
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
const featureGrid = this.querySelector('.feature-grid');
|
|
109
|
-
|
|
110
|
-
// Crear y añadir cada feature como un elemento HTML simple
|
|
111
|
-
for (const feature of features) {
|
|
112
|
-
const featureElement = document.createElement('div');
|
|
113
|
-
featureElement.classList.add('feature-item');
|
|
114
|
-
|
|
115
|
-
const featureTitle = document.createElement('h3');
|
|
116
|
-
featureTitle.textContent = feature.title;
|
|
117
|
-
featureTitle.classList.add('feature-title');
|
|
118
|
-
|
|
119
|
-
const featureDescription = document.createElement('p');
|
|
120
|
-
featureDescription.textContent = feature.description;
|
|
121
|
-
featureDescription.classList.add('feature-description');
|
|
122
|
-
|
|
123
|
-
featureElement.appendChild(featureTitle);
|
|
124
|
-
featureElement.appendChild(featureDescription);
|
|
125
|
-
|
|
126
|
-
featureGrid.appendChild(featureElement);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async createComponentExamples() {
|
|
131
|
-
// Crear ejemplos para demostrar componentes
|
|
132
|
-
const inputExample = await slice.build('Input', {
|
|
133
|
-
placeholder: 'Try typing here...',
|
|
134
|
-
type: 'text'
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const switchExample = await slice.build('Switch', {
|
|
138
|
-
label: 'Toggle me',
|
|
139
|
-
checked: true
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const checkboxExample = await slice.build('Checkbox', {
|
|
143
|
-
label: 'Check me',
|
|
144
|
-
labelPlacement: 'right'
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const detailsExample = await slice.build('Details', {
|
|
148
|
-
title: 'Click to expand',
|
|
149
|
-
text: 'This is a collapsible details component that can contain any content.'
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Crear sección para cada ejemplo
|
|
153
|
-
const exampleSections = [
|
|
154
|
-
{ title: 'Input Component', component: inputExample },
|
|
155
|
-
{ title: 'Switch Component', component: switchExample },
|
|
156
|
-
{ title: 'Checkbox Component', component: checkboxExample },
|
|
157
|
-
{ title: 'Details Component', component: detailsExample }
|
|
158
|
-
];
|
|
159
|
-
|
|
160
|
-
// Añadir cada ejemplo a la sección de ejemplos
|
|
161
|
-
for (const section of exampleSections) {
|
|
162
|
-
const container = document.createElement('div');
|
|
163
|
-
container.classList.add('example-item');
|
|
164
|
-
|
|
165
|
-
const title = document.createElement('h3');
|
|
166
|
-
title.textContent = section.title;
|
|
167
|
-
|
|
168
|
-
container.appendChild(title);
|
|
169
|
-
container.appendChild(section.component);
|
|
170
|
-
|
|
171
|
-
this.$examplesContainer.appendChild(container);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async setupGettingStartedSection() {
|
|
176
|
-
// Opcionalmente podríamos mejorar esta sección usando el CodeVisualizer component
|
|
177
|
-
// en lugar del código HTML estático en el template
|
|
178
|
-
const codeVisualizer = await slice.build('CodeVisualizer', {
|
|
179
|
-
value: `// Initialize a new Slice.js project
|
|
180
|
-
npm run slice:init
|
|
181
|
-
|
|
182
|
-
// Create a new component
|
|
183
|
-
npm run slice:create
|
|
184
|
-
|
|
185
|
-
// Start your application
|
|
186
|
-
npm run slice:start`,
|
|
187
|
-
language: 'bash'
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
const codeSample = this.querySelector('.code-sample');
|
|
191
|
-
codeSample.innerHTML = ''; // Clear the static code sample
|
|
192
|
-
codeSample.appendChild(codeVisualizer);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
1
|
+
export default class HomePage extends HTMLElement {
|
|
2
|
+
constructor(props) {
|
|
3
|
+
super();
|
|
4
|
+
slice.attachTemplate(this);
|
|
5
|
+
|
|
6
|
+
this.$examplesContainer = this.querySelector('.examples-container');
|
|
7
|
+
|
|
8
|
+
slice.controller.setComponentProps(this, props);
|
|
9
|
+
this.debuggerProps = [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async init() {
|
|
13
|
+
// Crear la barra de navegación
|
|
14
|
+
const navbar = await slice.build('Navbar', {
|
|
15
|
+
position: 'fixed',
|
|
16
|
+
logo: {
|
|
17
|
+
src: '/images/Slice.js-logo.png',
|
|
18
|
+
path: '/',
|
|
19
|
+
},
|
|
20
|
+
items: [
|
|
21
|
+
{ text: 'Home', path: '/' },
|
|
22
|
+
{ text: 'Playground', path: '/Playground' },
|
|
23
|
+
|
|
24
|
+
],
|
|
25
|
+
buttons: [
|
|
26
|
+
{
|
|
27
|
+
value: 'Change Theme',
|
|
28
|
+
onClickCallback: async () => {
|
|
29
|
+
const currentTheme = slice.stylesManager.themeManager.currentTheme;
|
|
30
|
+
if (currentTheme === 'Slice') {
|
|
31
|
+
await slice.setTheme('Light');
|
|
32
|
+
} else if (currentTheme === 'Light') {
|
|
33
|
+
await slice.setTheme('Dark');
|
|
34
|
+
} else {
|
|
35
|
+
await slice.setTheme('Slice');
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Crear botones para la sección de llamada a la acción
|
|
43
|
+
const docsButton = await slice.build('Button', {
|
|
44
|
+
value: 'Documentation',
|
|
45
|
+
onClickCallback: () => //redirect to https://slice-js-docs.vercel.app/Documentation
|
|
46
|
+
window.open('https://slice-js-docs.vercel.app/Documentation', '_blank'),
|
|
47
|
+
customColor: {
|
|
48
|
+
button: 'var(--primary-color)',
|
|
49
|
+
label: 'var(--primary-color-contrast)'
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const componentsButton = await slice.build('Button', {
|
|
54
|
+
value: 'Components Library',
|
|
55
|
+
onClickCallback: () => window.open('https://slice-js-docs.vercel.app/Documentation/Visual', '_blank'),
|
|
56
|
+
customColor: {
|
|
57
|
+
button: 'var(--secondary-color)',
|
|
58
|
+
label: 'var(--secondary-color-contrast)'
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Añadir botones a la sección CTA
|
|
63
|
+
this.querySelector('.cta-buttons').appendChild(docsButton);
|
|
64
|
+
this.querySelector('.cta-buttons').appendChild(componentsButton);
|
|
65
|
+
|
|
66
|
+
// Crear features section con un enfoque diferente (sin usar Cards)
|
|
67
|
+
await this.createFeatures();
|
|
68
|
+
|
|
69
|
+
// Crear ejemplos de componentes
|
|
70
|
+
await this.createComponentExamples();
|
|
71
|
+
|
|
72
|
+
// Configurar la sección de código de inicio
|
|
73
|
+
await this.setupGettingStartedSection();
|
|
74
|
+
|
|
75
|
+
// Añadir la barra de navegación al inicio del componente
|
|
76
|
+
this.insertBefore(navbar, this.firstChild);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async createFeatures() {
|
|
80
|
+
// Definir características
|
|
81
|
+
const features = [
|
|
82
|
+
{
|
|
83
|
+
title: 'Component-Based',
|
|
84
|
+
description: 'Build your app using modular, reusable components following web standards.'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title: 'Zero Dependencies',
|
|
88
|
+
description: 'Built with vanilla JavaScript. No external libraries required.'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
title: 'Easy Routing',
|
|
92
|
+
description: 'Simple and powerful routing system for single page applications.'
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
title: 'Theme System',
|
|
96
|
+
description: 'Built-in theme support with easy customization through CSS variables.'
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
title: 'Developer Tools',
|
|
100
|
+
description: 'Integrated debugging and logging for faster development.'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
title: 'Performance Focused',
|
|
104
|
+
description: 'Lightweight and optimized for fast loading and execution.'
|
|
105
|
+
}
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const featureGrid = this.querySelector('.feature-grid');
|
|
109
|
+
|
|
110
|
+
// Crear y añadir cada feature como un elemento HTML simple
|
|
111
|
+
for (const feature of features) {
|
|
112
|
+
const featureElement = document.createElement('div');
|
|
113
|
+
featureElement.classList.add('feature-item');
|
|
114
|
+
|
|
115
|
+
const featureTitle = document.createElement('h3');
|
|
116
|
+
featureTitle.textContent = feature.title;
|
|
117
|
+
featureTitle.classList.add('feature-title');
|
|
118
|
+
|
|
119
|
+
const featureDescription = document.createElement('p');
|
|
120
|
+
featureDescription.textContent = feature.description;
|
|
121
|
+
featureDescription.classList.add('feature-description');
|
|
122
|
+
|
|
123
|
+
featureElement.appendChild(featureTitle);
|
|
124
|
+
featureElement.appendChild(featureDescription);
|
|
125
|
+
|
|
126
|
+
featureGrid.appendChild(featureElement);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async createComponentExamples() {
|
|
131
|
+
// Crear ejemplos para demostrar componentes
|
|
132
|
+
const inputExample = await slice.build('Input', {
|
|
133
|
+
placeholder: 'Try typing here...',
|
|
134
|
+
type: 'text'
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const switchExample = await slice.build('Switch', {
|
|
138
|
+
label: 'Toggle me',
|
|
139
|
+
checked: true
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const checkboxExample = await slice.build('Checkbox', {
|
|
143
|
+
label: 'Check me',
|
|
144
|
+
labelPlacement: 'right'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const detailsExample = await slice.build('Details', {
|
|
148
|
+
title: 'Click to expand',
|
|
149
|
+
text: 'This is a collapsible details component that can contain any content.'
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Crear sección para cada ejemplo
|
|
153
|
+
const exampleSections = [
|
|
154
|
+
{ title: 'Input Component', component: inputExample },
|
|
155
|
+
{ title: 'Switch Component', component: switchExample },
|
|
156
|
+
{ title: 'Checkbox Component', component: checkboxExample },
|
|
157
|
+
{ title: 'Details Component', component: detailsExample }
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
// Añadir cada ejemplo a la sección de ejemplos
|
|
161
|
+
for (const section of exampleSections) {
|
|
162
|
+
const container = document.createElement('div');
|
|
163
|
+
container.classList.add('example-item');
|
|
164
|
+
|
|
165
|
+
const title = document.createElement('h3');
|
|
166
|
+
title.textContent = section.title;
|
|
167
|
+
|
|
168
|
+
container.appendChild(title);
|
|
169
|
+
container.appendChild(section.component);
|
|
170
|
+
|
|
171
|
+
this.$examplesContainer.appendChild(container);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async setupGettingStartedSection() {
|
|
176
|
+
// Opcionalmente podríamos mejorar esta sección usando el CodeVisualizer component
|
|
177
|
+
// en lugar del código HTML estático en el template
|
|
178
|
+
const codeVisualizer = await slice.build('CodeVisualizer', {
|
|
179
|
+
value: `// Initialize a new Slice.js project
|
|
180
|
+
npm run slice:init
|
|
181
|
+
|
|
182
|
+
// Create a new component
|
|
183
|
+
npm run slice:create
|
|
184
|
+
|
|
185
|
+
// Start your application
|
|
186
|
+
npm run slice:start`,
|
|
187
|
+
language: 'bash'
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const codeSample = this.querySelector('.code-sample');
|
|
191
|
+
codeSample.innerHTML = ''; // Clear the static code sample
|
|
192
|
+
codeSample.appendChild(codeVisualizer);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
196
|
customElements.define('slice-home-page', HomePage);
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
const components = {
|
|
2
|
-
"HomePage": "AppComponents",
|
|
3
|
-
"Playground": "AppComponents",
|
|
4
|
-
"Button": "Visual",
|
|
5
|
-
"Card": "Visual",
|
|
6
|
-
"Checkbox": "Visual",
|
|
7
|
-
"CodeVisualizer": "Visual",
|
|
8
|
-
"Details": "Visual",
|
|
9
|
-
"DropDown": "Visual",
|
|
10
|
-
"Grid": "Visual",
|
|
11
|
-
"Icon": "Visual",
|
|
12
|
-
"Input": "Visual",
|
|
13
|
-
"Layout": "Visual",
|
|
14
|
-
"Loading": "Visual",
|
|
15
|
-
"MultiRoute": "Visual",
|
|
16
|
-
"Navbar": "Visual",
|
|
17
|
-
"NotFound": "Visual",
|
|
18
|
-
"Route": "Visual",
|
|
19
|
-
"Select": "Visual",
|
|
20
|
-
"Switch": "Visual",
|
|
21
|
-
"TreeItem": "Visual",
|
|
22
|
-
"TreeView": "Visual",
|
|
23
|
-
"FetchManager": "Service",
|
|
24
|
-
"IndexedDbManager": "Service",
|
|
25
|
-
"Link": "Service",
|
|
26
|
-
"LocalStorageManager": "Service",
|
|
27
|
-
"Translator": "Service"
|
|
1
|
+
const components = {
|
|
2
|
+
"HomePage": "AppComponents",
|
|
3
|
+
"Playground": "AppComponents",
|
|
4
|
+
"Button": "Visual",
|
|
5
|
+
"Card": "Visual",
|
|
6
|
+
"Checkbox": "Visual",
|
|
7
|
+
"CodeVisualizer": "Visual",
|
|
8
|
+
"Details": "Visual",
|
|
9
|
+
"DropDown": "Visual",
|
|
10
|
+
"Grid": "Visual",
|
|
11
|
+
"Icon": "Visual",
|
|
12
|
+
"Input": "Visual",
|
|
13
|
+
"Layout": "Visual",
|
|
14
|
+
"Loading": "Visual",
|
|
15
|
+
"MultiRoute": "Visual",
|
|
16
|
+
"Navbar": "Visual",
|
|
17
|
+
"NotFound": "Visual",
|
|
18
|
+
"Route": "Visual",
|
|
19
|
+
"Select": "Visual",
|
|
20
|
+
"Switch": "Visual",
|
|
21
|
+
"TreeItem": "Visual",
|
|
22
|
+
"TreeView": "Visual",
|
|
23
|
+
"FetchManager": "Service",
|
|
24
|
+
"IndexedDbManager": "Service",
|
|
25
|
+
"Link": "Service",
|
|
26
|
+
"LocalStorageManager": "Service",
|
|
27
|
+
"Translator": "Service"
|
|
28
28
|
}; export default components;
|