slicejs-web-framework 2.2.13 → 2.3.1
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/README.md +155 -156
- package/Slice/Components/Structural/ContextManager/ContextManager.js +361 -0
- package/Slice/Components/Structural/Controller/Controller.js +131 -96
- package/Slice/Components/Structural/EventManager/EventManager.js +329 -0
- package/Slice/Components/Structural/Router/Router.js +112 -103
- package/Slice/Slice.js +83 -35
- package/package.json +1 -1
- package/src/Components/AppComponents/HomePage/HomePage.js +195 -195
- package/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +3 -4
- package/src/Components/components.js +1 -2
- package/src/sliceConfig.json +59 -53
- package/src/Components/Service/Translator/Translator.js +0 -45
- package/src/Components/Service/Translator/messages.json +0 -58
|
@@ -3,20 +3,20 @@ export default class Router {
|
|
|
3
3
|
this.routes = routes;
|
|
4
4
|
this.activeRoute = null;
|
|
5
5
|
this.pathToRouteMap = this.createPathToRouteMap(routes);
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
// Navigation Guards
|
|
8
8
|
this._beforeEachGuard = null;
|
|
9
9
|
this._afterEachGuard = null;
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
// Router state
|
|
12
12
|
this._started = false;
|
|
13
13
|
this._autoStartTimeout = null;
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
// Sistema de caché optimizado
|
|
16
16
|
this.routeContainersCache = new Map();
|
|
17
17
|
this.lastCacheUpdate = 0;
|
|
18
18
|
this.CACHE_DURATION = 100; // ms - caché muy corto pero efectivo
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
// Observer para invalidar caché automáticamente
|
|
21
21
|
this.setupMutationObserver();
|
|
22
22
|
}
|
|
@@ -27,7 +27,7 @@ export default class Router {
|
|
|
27
27
|
*/
|
|
28
28
|
init() {
|
|
29
29
|
window.addEventListener('popstate', this.onRouteChange.bind(this));
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
// Auto-start después de 50ms si el usuario no llama start() manualmente
|
|
32
32
|
// Esto da tiempo para que el usuario configure guards si lo necesita
|
|
33
33
|
this._autoStartTimeout = setTimeout(async () => {
|
|
@@ -49,13 +49,13 @@ export default class Router {
|
|
|
49
49
|
slice.logger.logWarning('Router', 'start() already called');
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
// Cancelar auto-start si existe
|
|
54
54
|
if (this._autoStartTimeout) {
|
|
55
55
|
clearTimeout(this._autoStartTimeout);
|
|
56
56
|
this._autoStartTimeout = null;
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
this._started = true;
|
|
60
60
|
await this.loadInitialRoute();
|
|
61
61
|
}
|
|
@@ -104,7 +104,7 @@ export default class Router {
|
|
|
104
104
|
component: 'NotFound',
|
|
105
105
|
params: {},
|
|
106
106
|
query: this._parseQueryParams(),
|
|
107
|
-
metadata: {}
|
|
107
|
+
metadata: {},
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
|
|
@@ -113,7 +113,7 @@ export default class Router {
|
|
|
113
113
|
component: route.parentRoute ? route.parentRoute.component : route.component,
|
|
114
114
|
params: params,
|
|
115
115
|
query: this._parseQueryParams(),
|
|
116
|
-
metadata: route.metadata || {}
|
|
116
|
+
metadata: route.metadata || {},
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -127,11 +127,11 @@ export default class Router {
|
|
|
127
127
|
|
|
128
128
|
const params = {};
|
|
129
129
|
const urlParams = new URLSearchParams(queryString);
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
for (const [key, value] of urlParams) {
|
|
132
132
|
params[key] = value;
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
|
|
135
135
|
return params;
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -179,13 +179,16 @@ export default class Router {
|
|
|
179
179
|
if (typeof arg === 'object' && arg.path) {
|
|
180
180
|
redirectPath = arg.path;
|
|
181
181
|
redirectOptions = {
|
|
182
|
-
replace: arg.replace || false
|
|
182
|
+
replace: arg.replace || false,
|
|
183
183
|
};
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
// Argumento inválido
|
|
188
|
-
slice.logger.logError(
|
|
188
|
+
slice.logger.logError(
|
|
189
|
+
'Router',
|
|
190
|
+
'Invalid argument passed to next(). Expected string, object with path, false, or undefined.'
|
|
191
|
+
);
|
|
189
192
|
};
|
|
190
193
|
|
|
191
194
|
try {
|
|
@@ -193,10 +196,7 @@ export default class Router {
|
|
|
193
196
|
|
|
194
197
|
// Si no se llamó next(), loguear advertencia pero continuar
|
|
195
198
|
if (!nextCalled) {
|
|
196
|
-
slice.logger.logWarning(
|
|
197
|
-
'Router',
|
|
198
|
-
'beforeEach guard did not call next(). Navigation will continue.'
|
|
199
|
-
);
|
|
199
|
+
slice.logger.logWarning('Router', 'beforeEach guard did not call next(). Navigation will continue.');
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// Retornar tanto el path como las opciones
|
|
@@ -228,28 +228,21 @@ export default class Router {
|
|
|
228
228
|
// ROUTING CORE (MODIFICADO CON GUARDS)
|
|
229
229
|
// ============================================
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
async navigate(path, _redirectChain = [], _options = {}) {
|
|
232
232
|
const currentPath = window.location.pathname;
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
|
|
235
234
|
// Detectar loops infinitos: si ya visitamos esta ruta en la cadena de redirecciones
|
|
236
235
|
if (_redirectChain.includes(path)) {
|
|
237
|
-
slice.logger.logError(
|
|
238
|
-
'Router',
|
|
239
|
-
`Guard redirection loop detected: ${_redirectChain.join(' → ')} → ${path}`
|
|
240
|
-
);
|
|
236
|
+
slice.logger.logError('Router', `Guard redirection loop detected: ${_redirectChain.join(' → ')} → ${path}`);
|
|
241
237
|
return;
|
|
242
238
|
}
|
|
243
|
-
|
|
239
|
+
|
|
244
240
|
// Límite de seguridad: máximo 10 redirecciones
|
|
245
241
|
if (_redirectChain.length >= 10) {
|
|
246
|
-
slice.logger.logError(
|
|
247
|
-
'Router',
|
|
248
|
-
`Too many redirections: ${_redirectChain.join(' → ')} → ${path}`
|
|
249
|
-
);
|
|
242
|
+
slice.logger.logError('Router', `Too many redirections: ${_redirectChain.join(' → ')} → ${path}`);
|
|
250
243
|
return;
|
|
251
244
|
}
|
|
252
|
-
|
|
245
|
+
|
|
253
246
|
// Obtener información de ruta actual
|
|
254
247
|
const { route: fromRoute, params: fromParams } = this.matchRoute(currentPath);
|
|
255
248
|
const from = this._createRouteInfo(fromRoute, fromParams, currentPath);
|
|
@@ -258,7 +251,6 @@ export default class Router {
|
|
|
258
251
|
const { route: toRoute, params: toParams } = this.matchRoute(path);
|
|
259
252
|
const to = this._createRouteInfo(toRoute, toParams, path);
|
|
260
253
|
|
|
261
|
-
|
|
262
254
|
// EJECUTAR BEFORE EACH GUARD
|
|
263
255
|
const guardResult = await this._executeBeforeEachGuard(to, from);
|
|
264
256
|
|
|
@@ -281,7 +273,7 @@ export default class Router {
|
|
|
281
273
|
} else {
|
|
282
274
|
window.history.pushState({}, path, window.location.origin + path);
|
|
283
275
|
}
|
|
284
|
-
|
|
276
|
+
|
|
285
277
|
await this._performNavigation(to, from);
|
|
286
278
|
}
|
|
287
279
|
|
|
@@ -296,6 +288,9 @@ export default class Router {
|
|
|
296
288
|
|
|
297
289
|
// EJECUTAR AFTER EACH GUARD
|
|
298
290
|
this._executeAfterEachGuard(to, from);
|
|
291
|
+
|
|
292
|
+
// Emitir evento de cambio de ruta
|
|
293
|
+
this._emitRouteChange(to, from);
|
|
299
294
|
}
|
|
300
295
|
|
|
301
296
|
async onRouteChange() {
|
|
@@ -322,10 +317,10 @@ export default class Router {
|
|
|
322
317
|
|
|
323
318
|
async handleRoute(route, params) {
|
|
324
319
|
const targetElement = document.querySelector('#app');
|
|
325
|
-
|
|
320
|
+
|
|
326
321
|
const componentName = route.parentRoute ? route.parentRoute.component : route.component;
|
|
327
322
|
const sliceId = `route-${componentName}`;
|
|
328
|
-
|
|
323
|
+
|
|
329
324
|
const existingComponent = slice.controller.getComponent(sliceId);
|
|
330
325
|
|
|
331
326
|
if (slice.loading) {
|
|
@@ -348,7 +343,7 @@ export default class Router {
|
|
|
348
343
|
|
|
349
344
|
targetElement.innerHTML = '';
|
|
350
345
|
targetElement.appendChild(component);
|
|
351
|
-
|
|
346
|
+
|
|
352
347
|
await this.renderRoutesInComponent(component);
|
|
353
348
|
}
|
|
354
349
|
|
|
@@ -362,7 +357,7 @@ export default class Router {
|
|
|
362
357
|
slice.router.activeRoute = route;
|
|
363
358
|
}
|
|
364
359
|
|
|
365
|
-
|
|
360
|
+
async loadInitialRoute() {
|
|
366
361
|
const path = window.location.pathname;
|
|
367
362
|
const { route, params } = this.matchRoute(path);
|
|
368
363
|
|
|
@@ -387,6 +382,25 @@ export default class Router {
|
|
|
387
382
|
|
|
388
383
|
// EJECUTAR AFTER EACH GUARD en carga inicial
|
|
389
384
|
this._executeAfterEachGuard(to, from);
|
|
385
|
+
|
|
386
|
+
// Emitir evento de cambio de ruta
|
|
387
|
+
this._emitRouteChange(to, from);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Emitir evento de cambio de ruta
|
|
392
|
+
* @param {Object} to
|
|
393
|
+
* @param {Object} from
|
|
394
|
+
*/
|
|
395
|
+
_emitRouteChange(to, from) {
|
|
396
|
+
const payload = { to, from };
|
|
397
|
+
|
|
398
|
+
if (slice.eventsConfig?.enabled && slice.events && typeof slice.events.emit === 'function') {
|
|
399
|
+
slice.events.emit('router:change', payload);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
window.dispatchEvent(new CustomEvent('router:change', { detail: payload }));
|
|
390
404
|
}
|
|
391
405
|
|
|
392
406
|
// ============================================
|
|
@@ -397,33 +411,34 @@ export default class Router {
|
|
|
397
411
|
if (typeof MutationObserver !== 'undefined') {
|
|
398
412
|
this.observer = new MutationObserver((mutations) => {
|
|
399
413
|
let shouldInvalidateCache = false;
|
|
400
|
-
|
|
414
|
+
|
|
401
415
|
mutations.forEach((mutation) => {
|
|
402
416
|
if (mutation.type === 'childList') {
|
|
403
417
|
const addedNodes = Array.from(mutation.addedNodes);
|
|
404
418
|
const removedNodes = Array.from(mutation.removedNodes);
|
|
405
|
-
|
|
406
|
-
const hasRouteNodes = [...addedNodes, ...removedNodes].some(
|
|
407
|
-
node
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
419
|
+
|
|
420
|
+
const hasRouteNodes = [...addedNodes, ...removedNodes].some(
|
|
421
|
+
(node) =>
|
|
422
|
+
node.nodeType === Node.ELEMENT_NODE &&
|
|
423
|
+
(node.tagName === 'SLICE-ROUTE' ||
|
|
424
|
+
node.tagName === 'SLICE-MULTI-ROUTE' ||
|
|
425
|
+
node.querySelector?.('slice-route, slice-multi-route'))
|
|
411
426
|
);
|
|
412
|
-
|
|
427
|
+
|
|
413
428
|
if (hasRouteNodes) {
|
|
414
429
|
shouldInvalidateCache = true;
|
|
415
430
|
}
|
|
416
431
|
}
|
|
417
432
|
});
|
|
418
|
-
|
|
433
|
+
|
|
419
434
|
if (shouldInvalidateCache) {
|
|
420
435
|
this.invalidateCache();
|
|
421
436
|
}
|
|
422
437
|
});
|
|
423
|
-
|
|
438
|
+
|
|
424
439
|
this.observer.observe(document.body, {
|
|
425
440
|
childList: true,
|
|
426
|
-
subtree: true
|
|
441
|
+
subtree: true,
|
|
427
442
|
});
|
|
428
443
|
}
|
|
429
444
|
}
|
|
@@ -435,32 +450,28 @@ export default class Router {
|
|
|
435
450
|
|
|
436
451
|
createPathToRouteMap(routes, basePath = '', parentRoute = null) {
|
|
437
452
|
const pathToRouteMap = new Map();
|
|
438
|
-
|
|
453
|
+
|
|
439
454
|
for (const route of routes) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
for (const [childPath, childRoute] of childPathToRouteMap.entries()) {
|
|
459
|
-
pathToRouteMap.set(childPath, childRoute);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
455
|
+
const fullPath = `${basePath}${route.path}`.replace(/\/+/g, '/');
|
|
456
|
+
|
|
457
|
+
const routeWithParent = {
|
|
458
|
+
...route,
|
|
459
|
+
fullPath,
|
|
460
|
+
parentPath: parentRoute ? parentRoute.fullPath : null,
|
|
461
|
+
parentRoute: parentRoute,
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
pathToRouteMap.set(fullPath, routeWithParent);
|
|
465
|
+
|
|
466
|
+
if (route.children) {
|
|
467
|
+
const childPathToRouteMap = this.createPathToRouteMap(route.children, fullPath, routeWithParent);
|
|
468
|
+
|
|
469
|
+
for (const [childPath, childRoute] of childPathToRouteMap.entries()) {
|
|
470
|
+
pathToRouteMap.set(childPath, childRoute);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
462
473
|
}
|
|
463
|
-
|
|
474
|
+
|
|
464
475
|
return pathToRouteMap;
|
|
465
476
|
}
|
|
466
477
|
|
|
@@ -491,37 +502,32 @@ export default class Router {
|
|
|
491
502
|
getCachedRouteContainers(container) {
|
|
492
503
|
const containerKey = container === document ? 'document' : container.sliceId || 'anonymous';
|
|
493
504
|
const now = Date.now();
|
|
494
|
-
|
|
495
|
-
if (this.routeContainersCache.has(containerKey) &&
|
|
496
|
-
(now - this.lastCacheUpdate) < this.CACHE_DURATION) {
|
|
505
|
+
|
|
506
|
+
if (this.routeContainersCache.has(containerKey) && now - this.lastCacheUpdate < this.CACHE_DURATION) {
|
|
497
507
|
return this.routeContainersCache.get(containerKey);
|
|
498
508
|
}
|
|
499
509
|
|
|
500
510
|
const routeContainers = this.findAllRouteContainersOptimized(container);
|
|
501
511
|
this.routeContainersCache.set(containerKey, routeContainers);
|
|
502
512
|
this.lastCacheUpdate = now;
|
|
503
|
-
|
|
513
|
+
|
|
504
514
|
return routeContainers;
|
|
505
515
|
}
|
|
506
516
|
|
|
507
517
|
findAllRouteContainersOptimized(container) {
|
|
508
518
|
const routeContainers = [];
|
|
509
|
-
|
|
510
|
-
const walker = document.createTreeWalker(
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
acceptNode: (node) => {
|
|
515
|
-
if (node.tagName === 'SLICE-ROUTE' || node.tagName === 'SLICE-MULTI-ROUTE') {
|
|
516
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
517
|
-
}
|
|
518
|
-
return NodeFilter.FILTER_SKIP;
|
|
519
|
+
|
|
520
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
521
|
+
acceptNode: (node) => {
|
|
522
|
+
if (node.tagName === 'SLICE-ROUTE' || node.tagName === 'SLICE-MULTI-ROUTE') {
|
|
523
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
519
524
|
}
|
|
520
|
-
|
|
521
|
-
|
|
525
|
+
return NodeFilter.FILTER_SKIP;
|
|
526
|
+
},
|
|
527
|
+
});
|
|
522
528
|
|
|
523
529
|
let node;
|
|
524
|
-
while (node = walker.nextNode()) {
|
|
530
|
+
while ((node = walker.nextNode())) {
|
|
525
531
|
routeContainers.push(node);
|
|
526
532
|
}
|
|
527
533
|
|
|
@@ -541,15 +547,15 @@ export default class Router {
|
|
|
541
547
|
const exactMatch = this.pathToRouteMap.get(path);
|
|
542
548
|
if (exactMatch) {
|
|
543
549
|
if (exactMatch.parentRoute) {
|
|
544
|
-
return {
|
|
545
|
-
route: exactMatch.parentRoute,
|
|
550
|
+
return {
|
|
551
|
+
route: exactMatch.parentRoute,
|
|
546
552
|
params: {},
|
|
547
|
-
childRoute: exactMatch
|
|
553
|
+
childRoute: exactMatch,
|
|
548
554
|
};
|
|
549
555
|
}
|
|
550
556
|
return { route: exactMatch, params: {} };
|
|
551
557
|
}
|
|
552
|
-
|
|
558
|
+
|
|
553
559
|
for (const [routePattern, route] of this.pathToRouteMap.entries()) {
|
|
554
560
|
if (routePattern.includes('${')) {
|
|
555
561
|
const { regex, paramNames } = this.compilePathPattern(routePattern);
|
|
@@ -559,31 +565,34 @@ export default class Router {
|
|
|
559
565
|
paramNames.forEach((name, i) => {
|
|
560
566
|
params[name] = match[i + 1];
|
|
561
567
|
});
|
|
562
|
-
|
|
568
|
+
|
|
563
569
|
if (route.parentRoute) {
|
|
564
|
-
return {
|
|
565
|
-
route: route.parentRoute,
|
|
570
|
+
return {
|
|
571
|
+
route: route.parentRoute,
|
|
566
572
|
params: params,
|
|
567
|
-
childRoute: route
|
|
573
|
+
childRoute: route,
|
|
568
574
|
};
|
|
569
575
|
}
|
|
570
|
-
|
|
576
|
+
|
|
571
577
|
return { route, params };
|
|
572
578
|
}
|
|
573
579
|
}
|
|
574
580
|
}
|
|
575
|
-
|
|
581
|
+
|
|
576
582
|
const notFoundRoute = this.pathToRouteMap.get('/404');
|
|
577
583
|
return { route: notFoundRoute, params: {} };
|
|
578
584
|
}
|
|
579
585
|
|
|
580
586
|
compilePathPattern(pattern) {
|
|
581
587
|
const paramNames = [];
|
|
582
|
-
const regexPattern =
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
588
|
+
const regexPattern =
|
|
589
|
+
'^' +
|
|
590
|
+
pattern.replace(/\$\{([^}]+)\}/g, (_, paramName) => {
|
|
591
|
+
paramNames.push(paramName);
|
|
592
|
+
return '([^/]+)';
|
|
593
|
+
}) +
|
|
594
|
+
'$';
|
|
586
595
|
|
|
587
596
|
return { regex: new RegExp(regexPattern), paramNames };
|
|
588
597
|
}
|
|
589
|
-
}
|
|
598
|
+
}
|
package/Slice/Slice.js
CHANGED
|
@@ -11,6 +11,7 @@ export default class Slice {
|
|
|
11
11
|
this.loggerConfig = sliceConfig.logger;
|
|
12
12
|
this.debuggerConfig = sliceConfig.debugger;
|
|
13
13
|
this.loadingConfig = sliceConfig.loading;
|
|
14
|
+
this.eventsConfig = sliceConfig.events;
|
|
14
15
|
|
|
15
16
|
// 📦 Bundle system is initialized automatically via import in index.js
|
|
16
17
|
}
|
|
@@ -24,7 +25,7 @@ export default class Slice {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
isProduction(){
|
|
28
|
+
isProduction() {
|
|
28
29
|
return true;
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -68,23 +69,26 @@ export default class Slice {
|
|
|
68
69
|
return null;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
let isVisual = slice.paths.components[componentCategory].type ===
|
|
72
|
+
let isVisual = slice.paths.components[componentCategory].type === 'Visual';
|
|
72
73
|
let modulePath = `${slice.paths.components[componentCategory].path}/${componentName}/${componentName}.js`;
|
|
73
74
|
|
|
74
75
|
// Load template, class, and CSS concurrently if needed
|
|
75
76
|
try {
|
|
76
77
|
// 📦 Skip individual loading if component is available from bundles
|
|
77
|
-
const loadTemplate =
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
const loadTemplate =
|
|
79
|
+
isFromBundle || !isVisual || this.controller.templates.has(componentName)
|
|
80
|
+
? Promise.resolve(null)
|
|
81
|
+
: this.controller.fetchText(componentName, 'html', componentCategory);
|
|
80
82
|
|
|
81
|
-
const loadClass =
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
const loadClass =
|
|
84
|
+
isFromBundle || this.controller.classes.has(componentName)
|
|
85
|
+
? Promise.resolve(null)
|
|
86
|
+
: this.getClass(modulePath);
|
|
84
87
|
|
|
85
|
-
const loadCSS =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
const loadCSS =
|
|
89
|
+
isFromBundle || !isVisual || this.controller.requestedStyles.has(componentName)
|
|
90
|
+
? Promise.resolve(null)
|
|
91
|
+
: this.controller.fetchText(componentName, 'css', componentCategory);
|
|
88
92
|
|
|
89
93
|
const [html, ComponentClass, css] = await Promise.all([loadTemplate, loadClass, loadCSS]);
|
|
90
94
|
|
|
@@ -142,7 +146,7 @@ export default class Slice {
|
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
this.controller.registerComponent(componentInstance);
|
|
145
|
-
if(isVisual){
|
|
149
|
+
if (isVisual) {
|
|
146
150
|
this.controller.registerComponentsRecursively(componentInstance);
|
|
147
151
|
}
|
|
148
152
|
|
|
@@ -166,26 +170,22 @@ export default class Slice {
|
|
|
166
170
|
attachTemplate(componentInstance) {
|
|
167
171
|
this.controller.loadTemplateToComponent(componentInstance);
|
|
168
172
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
173
|
}
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
async function loadConfig(){
|
|
175
|
+
async function loadConfig() {
|
|
175
176
|
try {
|
|
176
177
|
const response = await fetch('/sliceConfig.json'); // 🔹 Express lo sirve desde `src/`
|
|
177
178
|
if (!response.ok) throw new Error('Error loading sliceConfig.json');
|
|
178
179
|
const json = await response.json();
|
|
179
|
-
console.log(json)
|
|
180
|
+
console.log(json);
|
|
180
181
|
return json;
|
|
181
|
-
|
|
182
|
+
} catch (error) {
|
|
182
183
|
console.error(`Error loading config file: ${error.message}`);
|
|
183
184
|
return null;
|
|
184
|
-
|
|
185
|
+
}
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
async function init() {
|
|
188
|
-
|
|
189
189
|
const sliceConfig = await loadConfig();
|
|
190
190
|
if (!sliceConfig) {
|
|
191
191
|
//Display error message in console with colors and alert in english
|
|
@@ -193,11 +193,10 @@ async function init() {
|
|
|
193
193
|
alert('Error loading Slice configuration');
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
|
-
|
|
197
196
|
|
|
198
197
|
window.slice = new Slice(sliceConfig);
|
|
199
198
|
|
|
200
|
-
slice.paths.structuralComponentFolderPath =
|
|
199
|
+
slice.paths.structuralComponentFolderPath = '/Slice/Components/Structural';
|
|
201
200
|
|
|
202
201
|
if (sliceConfig.logger.enabled) {
|
|
203
202
|
const LoggerModule = await window.slice.getClass(`${slice.paths.structuralComponentFolderPath}/Logger/Logger.js`);
|
|
@@ -219,31 +218,80 @@ async function init() {
|
|
|
219
218
|
document.body.appendChild(window.slice.debugger);
|
|
220
219
|
}
|
|
221
220
|
|
|
221
|
+
if (sliceConfig.events?.enabled) {
|
|
222
|
+
const EventManagerModule = await window.slice.getClass(
|
|
223
|
+
`${slice.paths.structuralComponentFolderPath}/EventManager/EventManager.js`
|
|
224
|
+
);
|
|
225
|
+
window.slice.events = new EventManagerModule();
|
|
226
|
+
if (typeof window.slice.events.init === 'function') {
|
|
227
|
+
await window.slice.events.init();
|
|
228
|
+
}
|
|
229
|
+
window.slice.logger.logError('Slice', 'EventManager enabled');
|
|
230
|
+
} else {
|
|
231
|
+
window.slice.events = {
|
|
232
|
+
subscribe: () => null,
|
|
233
|
+
subscribeOnce: () => null,
|
|
234
|
+
unsubscribe: () => false,
|
|
235
|
+
emit: () => {},
|
|
236
|
+
bind: () => ({
|
|
237
|
+
subscribe: () => null,
|
|
238
|
+
subscribeOnce: () => null,
|
|
239
|
+
emit: () => {},
|
|
240
|
+
}),
|
|
241
|
+
cleanupComponent: () => 0,
|
|
242
|
+
hasSubscribers: () => false,
|
|
243
|
+
subscriberCount: () => 0,
|
|
244
|
+
clear: () => {},
|
|
245
|
+
};
|
|
246
|
+
window.slice.logger.logError('Slice', 'EventManager disabled');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (sliceConfig.context?.enabled) {
|
|
250
|
+
const ContextManagerModule = await window.slice.getClass(
|
|
251
|
+
`${slice.paths.structuralComponentFolderPath}/ContextManager/ContextManager.js`
|
|
252
|
+
);
|
|
253
|
+
window.slice.context = new ContextManagerModule();
|
|
254
|
+
if (typeof window.slice.context.init === 'function') {
|
|
255
|
+
await window.slice.context.init();
|
|
256
|
+
}
|
|
257
|
+
window.slice.logger.logError('Slice', 'ContextManager enabled');
|
|
258
|
+
} else {
|
|
259
|
+
window.slice.context = {
|
|
260
|
+
create: () => false,
|
|
261
|
+
getState: () => null,
|
|
262
|
+
setState: () => {},
|
|
263
|
+
watch: () => null,
|
|
264
|
+
has: () => false,
|
|
265
|
+
destroy: () => false,
|
|
266
|
+
list: () => [],
|
|
267
|
+
};
|
|
268
|
+
window.slice.logger.logError('Slice', 'ContextManager disabled');
|
|
269
|
+
}
|
|
270
|
+
|
|
222
271
|
if (sliceConfig.loading.enabled) {
|
|
223
272
|
const loading = await window.slice.build('Loading', {});
|
|
224
273
|
window.slice.loading = loading;
|
|
225
274
|
}
|
|
226
|
-
await window.slice.stylesManager.init();
|
|
227
275
|
|
|
276
|
+
await window.slice.stylesManager.init();
|
|
228
277
|
|
|
229
278
|
const routesModule = await import(slice.paths.routesFile);
|
|
230
279
|
const routes = routesModule.default;
|
|
231
280
|
const RouterModule = await window.slice.getClass(`${slice.paths.structuralComponentFolderPath}/Router/Router.js`);
|
|
232
281
|
window.slice.router = new RouterModule(routes);
|
|
233
282
|
await window.slice.router.init();
|
|
234
|
-
|
|
235
283
|
}
|
|
236
284
|
|
|
237
|
-
|
|
285
|
+
await init();
|
|
238
286
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
} catch (error) {
|
|
247
|
-
// Bundles not available, continue with individual component loading
|
|
248
|
-
console.log('📄 Using individual component loading (no bundles found)');
|
|
287
|
+
// Initialize bundles if available
|
|
288
|
+
try {
|
|
289
|
+
const { initializeBundles } = await import('/bundles/bundle.config.js');
|
|
290
|
+
if (initializeBundles) {
|
|
291
|
+
await initializeBundles(window.slice);
|
|
292
|
+
console.log('📦 Bundles initialized automatically');
|
|
249
293
|
}
|
|
294
|
+
} catch (error) {
|
|
295
|
+
// Bundles not available, continue with individual component loading
|
|
296
|
+
console.log('📄 Using individual component loading (no bundles found)');
|
|
297
|
+
}
|