@v-ibe/core 0.1.0
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/LICENSE +21 -0
- package/README.md +40 -0
- package/dist/DI/__tests__/scoped-container-dependencies.test.d.ts +1 -0
- package/dist/DI/bootstrap.d.ts +18 -0
- package/dist/DI/decorators/inject.d.ts +37 -0
- package/dist/DI/decorators/inject.js +45 -0
- package/dist/DI/decorators/service.d.ts +24 -0
- package/dist/DI/decorators/service.js +13 -0
- package/dist/DI/di-container.d.ts +53 -0
- package/dist/DI/di-container.js +158 -0
- package/dist/DI/lifecycle.d.ts +37 -0
- package/dist/DI/lifecycle.js +6 -0
- package/dist/DI/scoped-container.d.ts +68 -0
- package/dist/DI/scoped-container.js +193 -0
- package/dist/DI/service-metadata.d.ts +32 -0
- package/dist/DI/service-metadata.js +31 -0
- package/dist/DI/types.d.ts +4 -0
- package/dist/behaviors/__tests__/behavior-system.test.d.ts +1 -0
- package/dist/behaviors/behavior-manager.d.ts +60 -0
- package/dist/behaviors/behavior-manager.js +131 -0
- package/dist/behaviors/behavior-registry.d.ts +68 -0
- package/dist/behaviors/behavior-registry.js +105 -0
- package/dist/behaviors/constants.d.ts +16 -0
- package/dist/behaviors/constants.js +8 -0
- package/dist/behaviors/decorators.d.ts +87 -0
- package/dist/behaviors/decorators.js +46 -0
- package/dist/behaviors/index.d.ts +4 -0
- package/dist/components/__tests__/host.test.d.ts +1 -0
- package/dist/components/app-tree.d.ts +49 -0
- package/dist/components/app-tree.js +122 -0
- package/dist/components/base-component.d.ts +85 -0
- package/dist/components/base-component.js +438 -0
- package/dist/components/decorators/component.d.ts +27 -0
- package/dist/components/decorators/component.js +47 -0
- package/dist/components/decorators/prop.d.ts +14 -0
- package/dist/components/decorators/prop.js +37 -0
- package/dist/components/types.d.ts +26 -0
- package/dist/core.d.ts +23 -0
- package/dist/core.js +8 -0
- package/dist/custom-components/__tests__/for.test.d.ts +1 -0
- package/dist/custom-components/__tests__/show.test.d.ts +1 -0
- package/dist/custom-components/for.d.ts +58 -0
- package/dist/custom-components/for.js +313 -0
- package/dist/custom-components/index.d.ts +2 -0
- package/dist/custom-components/show.d.ts +78 -0
- package/dist/custom-components/show.js +88 -0
- package/dist/data-management/cache/cache-invalidate.decorator.d.ts +35 -0
- package/dist/data-management/cache/cache-invalidate.decorator.js +21 -0
- package/dist/data-management/cache/cache-metadata.d.ts +15 -0
- package/dist/data-management/cache/cache-provider.interface.d.ts +67 -0
- package/dist/data-management/cache/cache-tags.decorator.d.ts +52 -0
- package/dist/data-management/cache/cache-tags.decorator.js +13 -0
- package/dist/data-management/cache/cache-update.decorator.d.ts +28 -0
- package/dist/data-management/cache/cache-update.decorator.js +21 -0
- package/dist/data-management/cache/cache.decorator.d.ts +28 -0
- package/dist/data-management/cache/cache.decorator.js +13 -0
- package/dist/data-management/cache/index.d.ts +11 -0
- package/dist/data-management/cache/local-storage-cache.d.ts +40 -0
- package/dist/data-management/cache/local-storage-cache.js +268 -0
- package/dist/data-management/cache/memory-cache.d.ts +37 -0
- package/dist/data-management/cache/memory-cache.js +149 -0
- package/dist/data-management/cache/session-storage-cache.d.ts +35 -0
- package/dist/data-management/cache/session-storage-cache.js +242 -0
- package/dist/data-management/cache/ttl.decorator.d.ts +31 -0
- package/dist/data-management/cache/ttl.decorator.js +34 -0
- package/dist/data-management/decorators/consume.d.ts +29 -0
- package/dist/data-management/decorators/consume.js +28 -0
- package/dist/data-management/decorators/id.d.ts +28 -0
- package/dist/data-management/decorators/id.js +19 -0
- package/dist/data-management/decorators/model.d.ts +48 -0
- package/dist/data-management/decorators/model.js +24 -0
- package/dist/data-management/decorators/prop.d.ts +43 -0
- package/dist/data-management/decorators/prop.js +32 -0
- package/dist/data-management/index.d.ts +13 -0
- package/dist/data-management/store/json-to-model.d.ts +45 -0
- package/dist/data-management/store/json-to-model.js +36 -0
- package/dist/data-management/store/store.d.ts +108 -0
- package/dist/data-management/store/store.js +207 -0
- package/dist/data-management/store/types.d.ts +53 -0
- package/dist/events-handler/decorators/emit.d.ts +29 -0
- package/dist/events-handler/decorators/emit.js +51 -0
- package/dist/events-handler/event-decorators.d.ts +1 -0
- package/dist/events-handler/event-emitter.service.d.ts +21 -0
- package/dist/events-handler/event-emitter.service.js +85 -0
- package/dist/events-handler/event-types.d.ts +12 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +121 -0
- package/dist/jsx/dynamic/__tests__/granular-array-renderer.test.d.ts +1 -0
- package/dist/jsx/dynamic/__tests__/jsx-array-rendering.test.d.ts +1 -0
- package/dist/jsx/dynamic/array-renderer.d.ts +2 -0
- package/dist/jsx/dynamic/array-renderer.js +133 -0
- package/dist/jsx/dynamic/child-renderer.d.ts +1 -0
- package/dist/jsx/dynamic/child-renderer.js +180 -0
- package/dist/jsx/dynamic/dom-utils.d.ts +5 -0
- package/dist/jsx/dynamic/dom-utils.js +22 -0
- package/dist/jsx/dynamic/granular-array-renderer.d.ts +16 -0
- package/dist/jsx/dynamic/granular-array-renderer.js +153 -0
- package/dist/jsx/dynamic/node-renderer.d.ts +2 -0
- package/dist/jsx/dynamic/props-handler.d.ts +3 -0
- package/dist/jsx/dynamic/props-handler.js +281 -0
- package/dist/jsx/dynamic/text-renderer.d.ts +2 -0
- package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx/jsx-runtime.d.ts +3 -0
- package/dist/jsx/types.d.ts +35 -0
- package/dist/jsx/types.js +4 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +8 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +11 -0
- package/dist/reactivity/__tests__/context-stack.test.d.ts +1 -0
- package/dist/reactivity/__tests__/nested-effects-untrack.test.d.ts +22 -0
- package/dist/reactivity/context-scope.d.ts +57 -0
- package/dist/reactivity/context-scope.js +35 -0
- package/dist/reactivity/decorators/__tests__/ctx-integration.test.d.ts +5 -0
- package/dist/reactivity/decorators/__tests__/ctx-loop.test.d.ts +10 -0
- package/dist/reactivity/decorators/__tests__/state-intelligent.test.d.ts +1 -0
- package/dist/reactivity/decorators/computed.d.ts +6 -0
- package/dist/reactivity/decorators/computed.js +17 -0
- package/dist/reactivity/decorators/create-event-decorator.d.ts +5 -0
- package/dist/reactivity/decorators/create-event-decorator.js +28 -0
- package/dist/reactivity/decorators/ctx.d.ts +9 -0
- package/dist/reactivity/decorators/ctx.js +91 -0
- package/dist/reactivity/decorators/effect.d.ts +9 -0
- package/dist/reactivity/decorators/effect.js +24 -0
- package/dist/reactivity/decorators/resource.d.ts +48 -0
- package/dist/reactivity/decorators/resource.js +20 -0
- package/dist/reactivity/decorators/state.d.ts +8 -0
- package/dist/reactivity/decorators/state.js +68 -0
- package/dist/reactivity/decorators/store.d.ts +6 -0
- package/dist/reactivity/decorators/store.js +25 -0
- package/dist/reactivity/phase-scheduler.d.ts +81 -0
- package/dist/reactivity/phase-scheduler.js +88 -0
- package/dist/reactivity/phase-scheduler.test.d.ts +1 -0
- package/dist/reactivity/reactive-cache.d.ts +21 -0
- package/dist/reactivity/reactive-cache.js +31 -0
- package/dist/reactivity/reactive-cache.test.d.ts +1 -0
- package/dist/reactivity/reactive-context.d.ts +152 -0
- package/dist/reactivity/reactive-context.js +184 -0
- package/dist/reactivity/signals/__tests__/composicion-automatica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-1-estructura-basica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-2-registro-subscribers.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-3-notificaciones-basicas.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-4-comparacion-valores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-5-tracking-automatico.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-6-anti-glitch.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-7-objetos-anidados.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-8-observable-array-support.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite-shallow-tracking.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/effect.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-1-estructura-basica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-2-metodos-mutadores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-3-tracking-por-indice.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-4-tracking-length.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-5-tracking-mutation.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-6-metodos-no-mutadores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-7-composicion-bidireccional.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-8-proxies.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-9-derived-cache-optimization.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/resource.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/signal.test.d.ts +1 -0
- package/dist/reactivity/signals/array-strategies.d.ts +120 -0
- package/dist/reactivity/signals/array-strategies.js +261 -0
- package/dist/reactivity/signals/composite.d.ts +89 -0
- package/dist/reactivity/signals/composite.js +145 -0
- package/dist/reactivity/signals/computed.d.ts +61 -0
- package/dist/reactivity/signals/computed.js +107 -0
- package/dist/reactivity/signals/computed.test.d.ts +1 -0
- package/dist/reactivity/signals/derived.d.ts +10 -0
- package/dist/reactivity/signals/derived.js +24 -0
- package/dist/reactivity/signals/effect.d.ts +27 -0
- package/dist/reactivity/signals/effect.js +46 -0
- package/dist/reactivity/signals/event.d.ts +9 -0
- package/dist/reactivity/signals/event.js +15 -0
- package/dist/reactivity/signals/reactive-array.d.ts +133 -0
- package/dist/reactivity/signals/reactive-array.js +490 -0
- package/dist/reactivity/signals/reactive-proxy.d.ts +54 -0
- package/dist/reactivity/signals/reactive-proxy.js +299 -0
- package/dist/reactivity/signals/reactive-tracking.test.d.ts +1 -0
- package/dist/reactivity/signals/resource.d.ts +9 -0
- package/dist/reactivity/signals/resource.js +58 -0
- package/dist/reactivity/signals/signal.d.ts +39 -0
- package/dist/reactivity/signals/signal.js +56 -0
- package/dist/reactivity/signals/subscription-management.test.d.ts +1 -0
- package/dist/reactivity/types.d.ts +12 -0
- package/dist/router/__tests__/link-behavior-active-class.test.d.ts +1 -0
- package/dist/router/__tests__/loop-detector.test.d.ts +1 -0
- package/dist/router/__tests__/params-container-resolution.test.d.ts +1 -0
- package/dist/router/__tests__/router-generated-routes.test.d.ts +1 -0
- package/dist/router/__tests__/router-params-granular.test.d.ts +1 -0
- package/dist/router/__tests__/router-params-simple.test.d.ts +1 -0
- package/dist/router/__tests__/router-query-params.test.d.ts +1 -0
- package/dist/router/__tests__/router-route-candidates.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-app-articles.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-debug.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-integration.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-this.test.d.ts +1 -0
- package/dist/router/decorators/base-policy.d.ts +141 -0
- package/dist/router/decorators/base-policy.js +63 -0
- package/dist/router/decorators/index.d.ts +6 -0
- package/dist/router/decorators/params.d.ts +31 -0
- package/dist/router/decorators/params.js +97 -0
- package/dist/router/decorators/route-metadata.d.ts +11 -0
- package/dist/router/decorators/route-metadata.js +23 -0
- package/dist/router/decorators/route.d.ts +39 -0
- package/dist/router/decorators/route.js +7 -0
- package/dist/router/link.behavior.d.ts +87 -0
- package/dist/router/link.behavior.js +227 -0
- package/dist/router/policy-evaluator.d.ts +81 -0
- package/dist/router/policy-evaluator.js +209 -0
- package/dist/router/route-view.d.ts +56 -0
- package/dist/router/route-view.js +156 -0
- package/dist/router/router.d.ts +67 -0
- package/dist/router/router.js +308 -0
- package/dist/router/static-analysis/index.d.ts +37 -0
- package/dist/router/static-analysis/parser.d.ts +14 -0
- package/dist/router/static-analysis/parser.js +147 -0
- package/dist/router/static-analysis/scanner.d.ts +27 -0
- package/dist/router/static-analysis/scanner.js +91 -0
- package/dist/router/trie.d.ts +14 -0
- package/dist/router/trie.js +126 -0
- package/dist/router/trie.types.d.ts +36 -0
- package/dist/styles/base-style-sheet.d.ts +96 -0
- package/dist/styles/base-style-sheet.js +149 -0
- package/dist/styles/decorators/factories.d.ts +76 -0
- package/dist/styles/decorators/factories.js +11 -0
- package/dist/styles/decorators/keyframes.d.ts +238 -0
- package/dist/styles/decorators/keyframes.js +79 -0
- package/dist/styles/decorators/rule.d.ts +177 -0
- package/dist/styles/decorators/rule.js +72 -0
- package/dist/styles/decorators/scope.d.ts +66 -0
- package/dist/styles/decorators/scope.js +17 -0
- package/dist/styles/decorators/style.d.ts +1 -0
- package/dist/styles/decorators/style.js +20 -0
- package/dist/styles/decorators/useStyles.d.ts +5 -0
- package/dist/styles/decorators/useStyles.js +29 -0
- package/dist/styles/global-styles-registry.d.ts +72 -0
- package/dist/styles/global-styles-registry.js +155 -0
- package/dist/types.d.ts +1 -0
- package/dist/vite-plugins/__tests__/jsx-control-flow-transform.test.d.ts +1 -0
- package/dist/vite-plugins/index.d.ts +4 -0
- package/dist/vite-plugins/index.js +10 -0
- package/dist/vite-plugins/jsx-contextual.d.ts +7 -0
- package/dist/vite-plugins/jsx-contextual.js +53 -0
- package/dist/vite-plugins/jsx-control-flow-transform.d.ts +60 -0
- package/dist/vite-plugins/jsx-control-flow-transform.js +180 -0
- package/dist/vite-plugins/jsx-signals.d.ts +2 -0
- package/dist/vite-plugins/jsx-signals.js +124 -0
- package/dist/vite-plugins/router/route-generator-plugin.d.ts +63 -0
- package/dist/vite-plugins/router/route-generator-plugin.js +310 -0
- package/package.json +85 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { RESOURCE_PROPERTY_KEYS } from "../reactivity/decorators/resource.js";
|
|
2
|
+
import { reactiveContext } from "../reactivity/reactive-context.js";
|
|
3
|
+
import { createResource } from "../reactivity/signals/resource.js";
|
|
4
|
+
import { AppTree } from "./app-tree.js";
|
|
5
|
+
import { bindProps } from "../jsx/dynamic/props-handler.js";
|
|
6
|
+
import { renderChild } from "../jsx/dynamic/child-renderer.js";
|
|
7
|
+
import { Fragment } from "../jsx/types.js";
|
|
8
|
+
import { globalStylesheets } from "../styles/global-styles-registry.js";
|
|
9
|
+
import { BehaviorManager } from "../behaviors/behavior-manager.js";
|
|
10
|
+
import { ScopedContainer } from "../DI/scoped-container.js";
|
|
11
|
+
import { getServiceMetadata } from "../DI/service-metadata.js";
|
|
12
|
+
class BaseComponent extends HTMLElement {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
this.#isInitialized = false;
|
|
16
|
+
this.#globalStylesheetIds = [];
|
|
17
|
+
this.#documentStylesheetIds = [];
|
|
18
|
+
this._pendingContextInitializers = [];
|
|
19
|
+
this._pendingEffects = [];
|
|
20
|
+
this.behaviorManager = new BehaviorManager(this);
|
|
21
|
+
const metadata = AppTree.getMetadata(this.constructor);
|
|
22
|
+
const useShadowDOM = metadata?.useShadowDOM !== false;
|
|
23
|
+
if (useShadowDOM) {
|
|
24
|
+
this.attachShadow({ mode: "open" });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
#isInitialized;
|
|
28
|
+
#globalStylesheetIds;
|
|
29
|
+
#documentStylesheetIds;
|
|
30
|
+
/**
|
|
31
|
+
* Obtiene el root donde se renderizan los elementos.
|
|
32
|
+
* Puede ser shadowRoot o el elemento mismo si no usa shadow DOM.
|
|
33
|
+
*/
|
|
34
|
+
get renderRoot() {
|
|
35
|
+
return this.shadowRoot || this;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Registra un efecto pendiente que se ejecutará después de la inicialización
|
|
39
|
+
* Usado por el decorador @Effect para diferir la ejecución
|
|
40
|
+
*/
|
|
41
|
+
queueEffect(effectFn) {
|
|
42
|
+
if (this.#isInitialized) {
|
|
43
|
+
queueMicrotask(effectFn);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!this._pendingEffects) {
|
|
47
|
+
this._pendingEffects = [];
|
|
48
|
+
}
|
|
49
|
+
this._pendingEffects.push(effectFn);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Ejecuta todos los efectos pendientes
|
|
53
|
+
* Se llama al final de initializeForJSX()
|
|
54
|
+
*/
|
|
55
|
+
flushPendingEffects() {
|
|
56
|
+
if (this._pendingEffects && this._pendingEffects.length > 0) {
|
|
57
|
+
const effects = this._pendingEffects;
|
|
58
|
+
this._pendingEffects = [];
|
|
59
|
+
effects.forEach((effectFn) => {
|
|
60
|
+
queueMicrotask(effectFn);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Inicialización controlada por JSX
|
|
65
|
+
initializeForJSX() {
|
|
66
|
+
if (this.#isInitialized) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
reactiveContext.untrack(() => {
|
|
70
|
+
this.registerSharedStylesheetsIfNeeded();
|
|
71
|
+
this.registerDocumentStylesIfNeeded();
|
|
72
|
+
this.adoptSharedStylesheets();
|
|
73
|
+
this.adoptLocalStylesheet();
|
|
74
|
+
this.initializeContexts();
|
|
75
|
+
this.initializeResources();
|
|
76
|
+
if (typeof this.onInit === "function") {
|
|
77
|
+
this.onInit();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
this.#isInitialized = true;
|
|
81
|
+
this.flushPendingEffects();
|
|
82
|
+
}
|
|
83
|
+
connectedCallback() {
|
|
84
|
+
if (this.#isInitialized) {
|
|
85
|
+
if (typeof this.onConnected === "function") {
|
|
86
|
+
this.onConnected();
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.init().catch((error) => {
|
|
91
|
+
console.error("[BaseComponent] Error durante inicialización:", error);
|
|
92
|
+
this.renderError(error);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Bootstrap services declared in @Component({ services: [...] })
|
|
97
|
+
* for a given node. Creates a ScopedContainer with parent chain resolution.
|
|
98
|
+
* Used by both init() (DOM path) and createAndRenderComponent() (JSX path).
|
|
99
|
+
*/
|
|
100
|
+
static bootstrapServicesForNode(node, metadata, sync = false) {
|
|
101
|
+
if (!metadata.services?.length) return;
|
|
102
|
+
const parentContainer = node.parent ? AppTree.findContainerFor(node.parent) : void 0;
|
|
103
|
+
const container = new ScopedContainer(parentContainer);
|
|
104
|
+
for (const ServiceClass of metadata.services) {
|
|
105
|
+
container.register(ServiceClass);
|
|
106
|
+
}
|
|
107
|
+
for (const ServiceClass of metadata.services) {
|
|
108
|
+
const serviceMeta = getServiceMetadata(ServiceClass);
|
|
109
|
+
if (serviceMeta) {
|
|
110
|
+
for (const dep of serviceMeta.dependencies) {
|
|
111
|
+
if (metadata.services.includes(dep)) {
|
|
112
|
+
container.registerDependency(ServiceClass, dep);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (sync) {
|
|
118
|
+
container.bootstrapSync();
|
|
119
|
+
}
|
|
120
|
+
node.container = container;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Assign __container to a component instance.
|
|
124
|
+
* Uses the node's own container if it has one, otherwise walks up the tree.
|
|
125
|
+
*/
|
|
126
|
+
static assignContainer(instance, node) {
|
|
127
|
+
instance.__container = node.container ?? AppTree.findContainerFor(node) ?? void 0;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Proceso de inicialización asíncrona del componente
|
|
131
|
+
* Incluye renderizado progresivo
|
|
132
|
+
*/
|
|
133
|
+
async init() {
|
|
134
|
+
const parentNode = this.findParentNode();
|
|
135
|
+
this.appNode = AppTree.registerInstance(this, parentNode);
|
|
136
|
+
const metadata = AppTree.getMetadata(this.constructor);
|
|
137
|
+
if (metadata?.services?.length) {
|
|
138
|
+
BaseComponent.bootstrapServicesForNode(this.appNode, metadata);
|
|
139
|
+
await this.appNode.container.bootstrap();
|
|
140
|
+
}
|
|
141
|
+
BaseComponent.assignContainer(this, this.appNode);
|
|
142
|
+
this.initializeForJSX();
|
|
143
|
+
this.renderRoot.innerHTML = "";
|
|
144
|
+
if (typeof this.view === "function") {
|
|
145
|
+
const viewResult = this.view();
|
|
146
|
+
const isIterable = (value) => {
|
|
147
|
+
return value && typeof value === "object" && typeof value[Symbol.iterator] === "function";
|
|
148
|
+
};
|
|
149
|
+
if (viewResult instanceof Node) {
|
|
150
|
+
this.renderRoot.appendChild(viewResult);
|
|
151
|
+
} else if (isIterable(viewResult)) {
|
|
152
|
+
for (const child of viewResult) {
|
|
153
|
+
renderChild(this.renderRoot, child);
|
|
154
|
+
}
|
|
155
|
+
} else if (viewResult != null) {
|
|
156
|
+
renderChild(this.renderRoot, viewResult);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (typeof this.onConnected === "function") {
|
|
160
|
+
this.onConnected();
|
|
161
|
+
}
|
|
162
|
+
this.#isInitialized = true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Renderiza un estado de error si la inicialización falla
|
|
166
|
+
*/
|
|
167
|
+
renderError(error) {
|
|
168
|
+
this.renderRoot.innerHTML = `
|
|
169
|
+
<div style="padding: 20px; border: 2px solid #ff4444; background: #fff5f5; border-radius: 4px; margin: 10px;">
|
|
170
|
+
<h3 style="margin: 0 0 10px 0; color: #ff4444;">❌ Error de Inicialización</h3>
|
|
171
|
+
<p style="margin: 0 0 10px 0; color: #333;">El componente <strong>${this.constructor.name}</strong> falló al inicializar.</p>
|
|
172
|
+
<pre style="background: #f5f5f5; padding: 10px; overflow: auto; font-size: 12px; border-radius: 3px; color: #333;">${error.stack || error.message || String(error)}</pre>
|
|
173
|
+
</div>
|
|
174
|
+
`;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Encuentra el nodo padre de este componente en el AppTree.
|
|
178
|
+
*/
|
|
179
|
+
findParentNode() {
|
|
180
|
+
let currentElement = this.parentElement;
|
|
181
|
+
while (currentElement) {
|
|
182
|
+
if (currentElement instanceof BaseComponent) {
|
|
183
|
+
const parentNode = AppTree.findByInstance(currentElement);
|
|
184
|
+
if (parentNode) {
|
|
185
|
+
return parentNode;
|
|
186
|
+
}
|
|
187
|
+
if (currentElement.appNode) {
|
|
188
|
+
return currentElement.appNode;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (currentElement instanceof ShadowRoot) {
|
|
192
|
+
currentElement = currentElement.host;
|
|
193
|
+
} else {
|
|
194
|
+
currentElement = currentElement.parentElement;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return void 0;
|
|
198
|
+
}
|
|
199
|
+
disconnectedCallback() {
|
|
200
|
+
if (this.appNode?.container) {
|
|
201
|
+
this.appNode.container.dispose();
|
|
202
|
+
}
|
|
203
|
+
if (this.#globalStylesheetIds.length > 0) {
|
|
204
|
+
globalStylesheets.unregister(this.#globalStylesheetIds);
|
|
205
|
+
this.#globalStylesheetIds = [];
|
|
206
|
+
}
|
|
207
|
+
if (this.#documentStylesheetIds.length > 0) {
|
|
208
|
+
globalStylesheets.unregisterDocumentStyles(this.#documentStylesheetIds);
|
|
209
|
+
this.#documentStylesheetIds = [];
|
|
210
|
+
}
|
|
211
|
+
if (this.appNode) {
|
|
212
|
+
AppTree.unregisterInstance(this.appNode);
|
|
213
|
+
}
|
|
214
|
+
this.behaviorManager.disconnectAll();
|
|
215
|
+
if (typeof this.onDisconnected === "function") {
|
|
216
|
+
this.onDisconnected();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Registra las stylesheets @Shared si este componente las declara.
|
|
221
|
+
*/
|
|
222
|
+
registerSharedStylesheetsIfNeeded() {
|
|
223
|
+
const metadata = AppTree.getMetadata(
|
|
224
|
+
this.constructor
|
|
225
|
+
);
|
|
226
|
+
if (metadata?.sharedStylesClasses && metadata.sharedStylesClasses.length > 0) {
|
|
227
|
+
this.#globalStylesheetIds = globalStylesheets.registerShared(
|
|
228
|
+
metadata.sharedStylesClasses,
|
|
229
|
+
this
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Registra las stylesheets @ForDocument si este componente las declara.
|
|
235
|
+
*/
|
|
236
|
+
registerDocumentStylesIfNeeded() {
|
|
237
|
+
const metadata = AppTree.getMetadata(
|
|
238
|
+
this.constructor
|
|
239
|
+
);
|
|
240
|
+
if (metadata?.documentStylesClasses && metadata.documentStylesClasses.length > 0) {
|
|
241
|
+
this.#documentStylesheetIds = globalStylesheets.registerDocument(
|
|
242
|
+
metadata.documentStylesClasses,
|
|
243
|
+
this
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Adopta todas las stylesheets @Shared registradas en el shadow root.
|
|
249
|
+
*/
|
|
250
|
+
adoptSharedStylesheets() {
|
|
251
|
+
if (!this.shadowRoot) {
|
|
252
|
+
console.warn("Cannot adopt shared stylesheets: shadow root not available");
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const sharedSheets = globalStylesheets.getSharedStylesheets();
|
|
256
|
+
if (sharedSheets.length > 0) {
|
|
257
|
+
const existingSheets = this.shadowRoot.adoptedStyleSheets;
|
|
258
|
+
const existingArray = Array.from(existingSheets);
|
|
259
|
+
const sharedInExisting = sharedSheets.filter((ss) => existingArray.includes(ss));
|
|
260
|
+
if (sharedInExisting.length === sharedSheets.length) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const filteredExisting = existingArray.filter((sheet) => !sharedSheets.includes(sheet));
|
|
264
|
+
const newSheets = [...sharedSheets, ...filteredExisting];
|
|
265
|
+
this.shadowRoot.adoptedStyleSheets = newSheets;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Adopta las stylesheets LOCALES de este componente específico.
|
|
270
|
+
*/
|
|
271
|
+
adoptLocalStylesheet() {
|
|
272
|
+
if (!this.shadowRoot) {
|
|
273
|
+
console.warn("Cannot adopt local stylesheet: shadow root not available");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const metadata = AppTree.getMetadata(
|
|
277
|
+
this.constructor
|
|
278
|
+
);
|
|
279
|
+
if (metadata?.stylesClass) {
|
|
280
|
+
const stylesInstance = new metadata.stylesClass();
|
|
281
|
+
const stylesheet = stylesInstance.getStyleSheet();
|
|
282
|
+
this.shadowRoot.adoptedStyleSheets = [
|
|
283
|
+
...this.shadowRoot.adoptedStyleSheets,
|
|
284
|
+
stylesheet
|
|
285
|
+
];
|
|
286
|
+
stylesInstance.setHost(this);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
initializeContexts() {
|
|
290
|
+
if (this._pendingContextInitializers) {
|
|
291
|
+
this._pendingContextInitializers.forEach((initializer) => {
|
|
292
|
+
initializer();
|
|
293
|
+
});
|
|
294
|
+
this._pendingContextInitializers = [];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
initializeResources() {
|
|
298
|
+
const resourceInitializers = this.constructor[RESOURCE_PROPERTY_KEYS] || [];
|
|
299
|
+
for (const { key, source } of resourceInitializers) {
|
|
300
|
+
const resource = createResource(
|
|
301
|
+
(signal) => source.call(this, signal)
|
|
302
|
+
);
|
|
303
|
+
this[key] = resource;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
jsx(type, props) {
|
|
307
|
+
if (type == null) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
if (type === Fragment) {
|
|
311
|
+
return props.children;
|
|
312
|
+
}
|
|
313
|
+
const { children, ...restProps } = props || {};
|
|
314
|
+
if (typeof type === "function" && type.prototype instanceof BaseComponent) {
|
|
315
|
+
return this.createAndRenderComponent(type, restProps, children);
|
|
316
|
+
}
|
|
317
|
+
if (typeof type === "function") {
|
|
318
|
+
const result = type({ ...restProps, children });
|
|
319
|
+
if (typeof result === "function") {
|
|
320
|
+
return result();
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
if (typeof type === "string") {
|
|
325
|
+
return this.createNativeElement(
|
|
326
|
+
type,
|
|
327
|
+
restProps,
|
|
328
|
+
...this.normalizeChildren(children)
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
throw new Error(`Unknown component type: ${typeof type} - ${type}`);
|
|
332
|
+
}
|
|
333
|
+
jsxDEV(type, props) {
|
|
334
|
+
return this.jsx(type, props);
|
|
335
|
+
}
|
|
336
|
+
jsxs(type, props) {
|
|
337
|
+
return this.jsx(type, props);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Aplica className al host element del componente.
|
|
341
|
+
*/
|
|
342
|
+
applyClassNameToHost(instance, classNameValue) {
|
|
343
|
+
if (typeof classNameValue === "object" && classNameValue?.isSignal) {
|
|
344
|
+
import("../reactivity/signals/effect.js").then(({ effect }) => {
|
|
345
|
+
effect(() => {
|
|
346
|
+
const className = classNameValue.get();
|
|
347
|
+
this.setHostClassName(instance, className);
|
|
348
|
+
}, { priority: "Frame" });
|
|
349
|
+
});
|
|
350
|
+
} else if (typeof classNameValue === "function") {
|
|
351
|
+
import("../reactivity/signals/effect.js").then(({ effect }) => {
|
|
352
|
+
effect(() => {
|
|
353
|
+
const className = classNameValue();
|
|
354
|
+
this.setHostClassName(instance, className);
|
|
355
|
+
}, { priority: "Frame" });
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
this.setHostClassName(instance, classNameValue);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Establece las clases CSS en el host element.
|
|
363
|
+
*/
|
|
364
|
+
setHostClassName(instance, className) {
|
|
365
|
+
if (!className) return;
|
|
366
|
+
const classStr = Array.isArray(className) ? className.join(" ") : String(className);
|
|
367
|
+
if (classStr.trim()) {
|
|
368
|
+
instance.className = classStr.trim();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
createAndRenderComponent(ComponentClass, props, children) {
|
|
372
|
+
let instance;
|
|
373
|
+
reactiveContext.untrack(() => {
|
|
374
|
+
instance = new ComponentClass();
|
|
375
|
+
const tagName = this.convertClassNameToTagName(ComponentClass.name);
|
|
376
|
+
Object.defineProperty(instance, "tagName", {
|
|
377
|
+
value: tagName.toUpperCase(),
|
|
378
|
+
configurable: false,
|
|
379
|
+
enumerable: true
|
|
380
|
+
});
|
|
381
|
+
Object.defineProperty(instance, "nodeName", {
|
|
382
|
+
value: tagName.toUpperCase(),
|
|
383
|
+
configurable: false,
|
|
384
|
+
enumerable: true
|
|
385
|
+
});
|
|
386
|
+
const node = AppTree.registerInstance(instance, this.appNode);
|
|
387
|
+
instance.appNode = node;
|
|
388
|
+
const childMetadata = AppTree.getMetadata(ComponentClass);
|
|
389
|
+
if (childMetadata?.services?.length) {
|
|
390
|
+
BaseComponent.bootstrapServicesForNode(node, childMetadata, true);
|
|
391
|
+
}
|
|
392
|
+
BaseComponent.assignContainer(instance, node);
|
|
393
|
+
if (props) {
|
|
394
|
+
Object.keys(props).forEach((key) => {
|
|
395
|
+
if (key === "children") return;
|
|
396
|
+
if (key === "className" || key === "class") {
|
|
397
|
+
this.applyClassNameToHost(instance, props[key]);
|
|
398
|
+
} else {
|
|
399
|
+
instance[key] = props[key];
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
instance.initializeForJSX();
|
|
404
|
+
const view = instance.view();
|
|
405
|
+
if (view instanceof Node && instance.shadowRoot) {
|
|
406
|
+
instance.shadowRoot.appendChild(view);
|
|
407
|
+
} else if (Array.isArray(view) && instance.shadowRoot) {
|
|
408
|
+
view.forEach((child) => renderChild(instance.shadowRoot, child));
|
|
409
|
+
}
|
|
410
|
+
if (children) {
|
|
411
|
+
const normalizedChildren = this.normalizeChildren(children);
|
|
412
|
+
normalizedChildren.forEach((child) => {
|
|
413
|
+
renderChild(instance, child);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
return instance;
|
|
418
|
+
}
|
|
419
|
+
createNativeElement(type, props, ...children) {
|
|
420
|
+
const el = document.createElement(type);
|
|
421
|
+
if (props) {
|
|
422
|
+
bindProps(el, props, this.behaviorManager);
|
|
423
|
+
}
|
|
424
|
+
const flatChildren = children.flat();
|
|
425
|
+
flatChildren.forEach((child) => renderChild(el, child));
|
|
426
|
+
return el;
|
|
427
|
+
}
|
|
428
|
+
normalizeChildren(children) {
|
|
429
|
+
if (!children) return [];
|
|
430
|
+
return Array.isArray(children) ? children : [children];
|
|
431
|
+
}
|
|
432
|
+
convertClassNameToTagName(className) {
|
|
433
|
+
return className.replace(/_/g, "-").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
export {
|
|
437
|
+
BaseComponent
|
|
438
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseStyleSheet } from '../../styles/base-style-sheet';
|
|
2
|
+
export interface ComponentConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Clase(s) de estilos del componente.
|
|
5
|
+
* El scope se determina por el decorador de cada clase:
|
|
6
|
+
* - Sin decorador: Local
|
|
7
|
+
* - @Shared: Shadow roots
|
|
8
|
+
* - @ForDocument: Documento
|
|
9
|
+
*/
|
|
10
|
+
styles?: (new () => BaseStyleSheet) | (new () => BaseStyleSheet)[];
|
|
11
|
+
/**
|
|
12
|
+
* Si es false, el componente no usará Shadow DOM.
|
|
13
|
+
* Por defecto es true (usa Shadow DOM).
|
|
14
|
+
* Útil para componentes que necesitan heredar estilos del documento (ej: Link con activeClass).
|
|
15
|
+
*/
|
|
16
|
+
useShadowDOM?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Servicios que este componente provee a sí mismo y a sus hijos.
|
|
19
|
+
* Los hijos resuelven servicios subiendo por el árbol de componentes.
|
|
20
|
+
*/
|
|
21
|
+
services?: (new (...args: any[]) => any)[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Decorador @Component para registrar componentes web.
|
|
25
|
+
* Uso: @Component() o @Component({ styles: [MyStyles] })
|
|
26
|
+
*/
|
|
27
|
+
export declare function Component(config?: ComponentConfig): any;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { RESOURCE_PROPERTY_KEYS } from "../../reactivity/decorators/resource.js";
|
|
2
|
+
import { AppTree } from "../app-tree.js";
|
|
3
|
+
import { getStyleScope } from "../../styles/decorators/scope.js";
|
|
4
|
+
function convertClassNameToTagName(className) {
|
|
5
|
+
const kebabCase = className.replace(/_/g, "-").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
6
|
+
return `use-${kebabCase}`;
|
|
7
|
+
}
|
|
8
|
+
function Component(config = {}) {
|
|
9
|
+
return function(ComponentClass, context) {
|
|
10
|
+
const tagName = convertClassNameToTagName(ComponentClass.name);
|
|
11
|
+
const resourceKeys = context?.metadata?.resourceKeys || [];
|
|
12
|
+
ComponentClass[RESOURCE_PROPERTY_KEYS] = resourceKeys;
|
|
13
|
+
let categorizedStyles = {
|
|
14
|
+
local: [],
|
|
15
|
+
shared: [],
|
|
16
|
+
document: []
|
|
17
|
+
};
|
|
18
|
+
if (config?.styles) {
|
|
19
|
+
const stylesArray = Array.isArray(config.styles) ? config.styles : [config.styles];
|
|
20
|
+
stylesArray.forEach((StyleClass) => {
|
|
21
|
+
const scope = getStyleScope(StyleClass);
|
|
22
|
+
categorizedStyles[scope].push(StyleClass);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
AppTree.registerMetadata({
|
|
26
|
+
tagName,
|
|
27
|
+
componentClass: ComponentClass,
|
|
28
|
+
resourceKeys,
|
|
29
|
+
stylesClass: categorizedStyles.local[0],
|
|
30
|
+
localStyles: categorizedStyles.local.length > 0 ? categorizedStyles.local : void 0,
|
|
31
|
+
sharedStylesClasses: categorizedStyles.shared.length > 0 ? categorizedStyles.shared : void 0,
|
|
32
|
+
documentStylesClasses: categorizedStyles.document.length > 0 ? categorizedStyles.document : void 0,
|
|
33
|
+
useShadowDOM: config.useShadowDOM !== false,
|
|
34
|
+
// Por defecto true
|
|
35
|
+
services: config.services
|
|
36
|
+
});
|
|
37
|
+
if (!customElements.get(tagName)) {
|
|
38
|
+
customElements.define(tagName, ComponentClass);
|
|
39
|
+
} else {
|
|
40
|
+
console.warn(`[Component] ⚠ Tag "${tagName}" ya registrado`);
|
|
41
|
+
}
|
|
42
|
+
return ComponentClass;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
Component
|
|
47
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @Prop decorator for component properties that may receive reactive expressions.
|
|
3
|
+
*
|
|
4
|
+
* When a prop receives a zero-argument function (a reactive getter from the parent),
|
|
5
|
+
* this decorator automatically unwraps it on access, creating a direct reactive
|
|
6
|
+
* subscription from the child to the parent's signals.
|
|
7
|
+
*
|
|
8
|
+
* For non-function values or callback functions (with parameters), the value is
|
|
9
|
+
* returned as-is.
|
|
10
|
+
*
|
|
11
|
+
* When used in a @Behavior class, this decorator also registers the prop name
|
|
12
|
+
* in the behavior's metadata for the PropertyRegistry to resolve.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Prop<This extends object, Value>(target: undefined, context: ClassFieldDecoratorContext<This, Value>): (this: This, initialValue: Value) => Value;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BEHAVIOR_PROPS } from "../../behaviors/constants.js";
|
|
2
|
+
function Prop(target, context) {
|
|
3
|
+
if (context.kind !== "field") {
|
|
4
|
+
throw new Error("@Prop can only be applied to class fields.");
|
|
5
|
+
}
|
|
6
|
+
const storageKey = Symbol(`prop_storage_${String(context.name)}`);
|
|
7
|
+
const metadata = context.metadata;
|
|
8
|
+
if (!metadata[BEHAVIOR_PROPS]) {
|
|
9
|
+
metadata[BEHAVIOR_PROPS] = /* @__PURE__ */ new Set();
|
|
10
|
+
}
|
|
11
|
+
metadata[BEHAVIOR_PROPS].add(String(context.name));
|
|
12
|
+
return function(initialValue) {
|
|
13
|
+
this[storageKey] = initialValue;
|
|
14
|
+
Object.defineProperty(this, context.name, {
|
|
15
|
+
get: () => {
|
|
16
|
+
const storedValue = this[storageKey];
|
|
17
|
+
const propName = String(context.name);
|
|
18
|
+
if (propName.startsWith("on") && propName.length > 2) {
|
|
19
|
+
return storedValue;
|
|
20
|
+
}
|
|
21
|
+
if (typeof storedValue === "function" && storedValue.length === 0) {
|
|
22
|
+
return storedValue();
|
|
23
|
+
}
|
|
24
|
+
return storedValue;
|
|
25
|
+
},
|
|
26
|
+
set: (newValue) => {
|
|
27
|
+
this[storageKey] = newValue;
|
|
28
|
+
},
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true
|
|
31
|
+
});
|
|
32
|
+
return initialValue;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
Prop
|
|
37
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BaseComponent } from './base-component';
|
|
2
|
+
import { BaseStyleSheet } from '../styles/base-style-sheet';
|
|
3
|
+
import { ScopedContainer } from '../DI/scoped-container';
|
|
4
|
+
export type Constructor<T = {}> = new (...args: any[]) => T;
|
|
5
|
+
export type ComponentMetadata = {
|
|
6
|
+
tagName: string;
|
|
7
|
+
componentClass: Constructor<any>;
|
|
8
|
+
routePath?: string;
|
|
9
|
+
viewPropertyName?: string;
|
|
10
|
+
resourceKeys: string[];
|
|
11
|
+
stylesClass?: new () => BaseStyleSheet;
|
|
12
|
+
localStyles?: Constructor<any>[];
|
|
13
|
+
sharedStylesClasses?: Constructor<any>[];
|
|
14
|
+
documentStylesClasses?: Constructor<any>[];
|
|
15
|
+
useShadowDOM?: boolean;
|
|
16
|
+
services?: Constructor[];
|
|
17
|
+
};
|
|
18
|
+
export interface INode {
|
|
19
|
+
id: string;
|
|
20
|
+
metadata: ComponentMetadata;
|
|
21
|
+
instance: BaseComponent;
|
|
22
|
+
parent?: INode;
|
|
23
|
+
children: INode[];
|
|
24
|
+
contextStore?: object;
|
|
25
|
+
container?: ScopedContainer;
|
|
26
|
+
}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Router } from './router/router';
|
|
2
|
+
import { Trie } from './router/trie';
|
|
3
|
+
import { PolicyEvaluator } from './router/policy-evaluator';
|
|
4
|
+
import { EventEmitter } from './events-handler/event-emitter.service';
|
|
5
|
+
/**
|
|
6
|
+
* Core framework services.
|
|
7
|
+
* Include these in your root component's services array.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { BaseComponent, Component, core, RouteView } from '@v-ibe/core';
|
|
12
|
+
*
|
|
13
|
+
* @Component({
|
|
14
|
+
* services: [...core, AuthService, MyPolicy]
|
|
15
|
+
* })
|
|
16
|
+
* export class App extends BaseComponent {
|
|
17
|
+
* view() {
|
|
18
|
+
* return <RouteView />;
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const core: (typeof Trie | typeof PolicyEvaluator | typeof Router | typeof EventEmitter)[];
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Router } from "./router/router.js";
|
|
2
|
+
import { Trie } from "./router/trie.js";
|
|
3
|
+
import { PolicyEvaluator } from "./router/policy-evaluator.js";
|
|
4
|
+
import { EventEmitter } from "./events-handler/event-emitter.service.js";
|
|
5
|
+
const core = [Router, Trie, PolicyEvaluator, EventEmitter];
|
|
6
|
+
export {
|
|
7
|
+
core
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ISignal } from '../reactivity/signals/signal';
|
|
2
|
+
import { ReactiveArray } from '../reactivity/signals/reactive-array';
|
|
3
|
+
/**
|
|
4
|
+
* Props del componente For
|
|
5
|
+
*/
|
|
6
|
+
export interface ForProps<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Array de items a renderizar.
|
|
9
|
+
* Para granularidad fina óptima, debe ser un ReactiveArray (via @State).
|
|
10
|
+
* También acepta: Signal<T[]>, función, o array plano.
|
|
11
|
+
*/
|
|
12
|
+
each: T[] | (() => T[]) | ISignal<T[]> | ReactiveArray<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Función de render para cada item.
|
|
15
|
+
* IMPORTANTE: Esta función se ejecuta DENTRO de un effect individual por item.
|
|
16
|
+
* Cambios en array[i] solo re-ejecutan el effect del índice i.
|
|
17
|
+
*/
|
|
18
|
+
children: (item: T, index: number) => any;
|
|
19
|
+
/**
|
|
20
|
+
* Elemento a mostrar cuando el array está vacío.
|
|
21
|
+
*/
|
|
22
|
+
fallback?: any;
|
|
23
|
+
/**
|
|
24
|
+
* Función para extraer key única de cada item.
|
|
25
|
+
* Si no se provee, usa auto-keying (id, key, _id, uuid).
|
|
26
|
+
* Para granularidad óptima, es mejor que los items tengan IDs estables.
|
|
27
|
+
*/
|
|
28
|
+
getKey?: (item: T, index: number) => string | number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* For - Helper con granularidad fina para listas
|
|
32
|
+
*
|
|
33
|
+
* @example Granularidad fina con @State
|
|
34
|
+
* ```tsx
|
|
35
|
+
* @Component
|
|
36
|
+
* class TodoList extends BaseComponent {
|
|
37
|
+
* @State todos: Todo[] = [...];
|
|
38
|
+
*
|
|
39
|
+
* view() {
|
|
40
|
+
* return (
|
|
41
|
+
* <For each={this.todos}>
|
|
42
|
+
* {(todo) => <TodoItem key={todo.id} todo={todo} />}
|
|
43
|
+
* </For>
|
|
44
|
+
* );
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* // Solo los TodoItem que cambian se re-renderizan
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Con array plano (sin granularidad fina)
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <For each={[1, 2, 3]}>
|
|
53
|
+
* {(n) => <div>{n}</div>}
|
|
54
|
+
* </For>
|
|
55
|
+
* // Funciona, pero re-renderiza todo cuando cambia
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function For<T>(props: ForProps<T>): DocumentFragment;
|