@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.
Files changed (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/DI/__tests__/scoped-container-dependencies.test.d.ts +1 -0
  4. package/dist/DI/bootstrap.d.ts +18 -0
  5. package/dist/DI/decorators/inject.d.ts +37 -0
  6. package/dist/DI/decorators/inject.js +45 -0
  7. package/dist/DI/decorators/service.d.ts +24 -0
  8. package/dist/DI/decorators/service.js +13 -0
  9. package/dist/DI/di-container.d.ts +53 -0
  10. package/dist/DI/di-container.js +158 -0
  11. package/dist/DI/lifecycle.d.ts +37 -0
  12. package/dist/DI/lifecycle.js +6 -0
  13. package/dist/DI/scoped-container.d.ts +68 -0
  14. package/dist/DI/scoped-container.js +193 -0
  15. package/dist/DI/service-metadata.d.ts +32 -0
  16. package/dist/DI/service-metadata.js +31 -0
  17. package/dist/DI/types.d.ts +4 -0
  18. package/dist/behaviors/__tests__/behavior-system.test.d.ts +1 -0
  19. package/dist/behaviors/behavior-manager.d.ts +60 -0
  20. package/dist/behaviors/behavior-manager.js +131 -0
  21. package/dist/behaviors/behavior-registry.d.ts +68 -0
  22. package/dist/behaviors/behavior-registry.js +105 -0
  23. package/dist/behaviors/constants.d.ts +16 -0
  24. package/dist/behaviors/constants.js +8 -0
  25. package/dist/behaviors/decorators.d.ts +87 -0
  26. package/dist/behaviors/decorators.js +46 -0
  27. package/dist/behaviors/index.d.ts +4 -0
  28. package/dist/components/__tests__/host.test.d.ts +1 -0
  29. package/dist/components/app-tree.d.ts +49 -0
  30. package/dist/components/app-tree.js +122 -0
  31. package/dist/components/base-component.d.ts +85 -0
  32. package/dist/components/base-component.js +438 -0
  33. package/dist/components/decorators/component.d.ts +27 -0
  34. package/dist/components/decorators/component.js +47 -0
  35. package/dist/components/decorators/prop.d.ts +14 -0
  36. package/dist/components/decorators/prop.js +37 -0
  37. package/dist/components/types.d.ts +26 -0
  38. package/dist/core.d.ts +23 -0
  39. package/dist/core.js +8 -0
  40. package/dist/custom-components/__tests__/for.test.d.ts +1 -0
  41. package/dist/custom-components/__tests__/show.test.d.ts +1 -0
  42. package/dist/custom-components/for.d.ts +58 -0
  43. package/dist/custom-components/for.js +313 -0
  44. package/dist/custom-components/index.d.ts +2 -0
  45. package/dist/custom-components/show.d.ts +78 -0
  46. package/dist/custom-components/show.js +88 -0
  47. package/dist/data-management/cache/cache-invalidate.decorator.d.ts +35 -0
  48. package/dist/data-management/cache/cache-invalidate.decorator.js +21 -0
  49. package/dist/data-management/cache/cache-metadata.d.ts +15 -0
  50. package/dist/data-management/cache/cache-provider.interface.d.ts +67 -0
  51. package/dist/data-management/cache/cache-tags.decorator.d.ts +52 -0
  52. package/dist/data-management/cache/cache-tags.decorator.js +13 -0
  53. package/dist/data-management/cache/cache-update.decorator.d.ts +28 -0
  54. package/dist/data-management/cache/cache-update.decorator.js +21 -0
  55. package/dist/data-management/cache/cache.decorator.d.ts +28 -0
  56. package/dist/data-management/cache/cache.decorator.js +13 -0
  57. package/dist/data-management/cache/index.d.ts +11 -0
  58. package/dist/data-management/cache/local-storage-cache.d.ts +40 -0
  59. package/dist/data-management/cache/local-storage-cache.js +268 -0
  60. package/dist/data-management/cache/memory-cache.d.ts +37 -0
  61. package/dist/data-management/cache/memory-cache.js +149 -0
  62. package/dist/data-management/cache/session-storage-cache.d.ts +35 -0
  63. package/dist/data-management/cache/session-storage-cache.js +242 -0
  64. package/dist/data-management/cache/ttl.decorator.d.ts +31 -0
  65. package/dist/data-management/cache/ttl.decorator.js +34 -0
  66. package/dist/data-management/decorators/consume.d.ts +29 -0
  67. package/dist/data-management/decorators/consume.js +28 -0
  68. package/dist/data-management/decorators/id.d.ts +28 -0
  69. package/dist/data-management/decorators/id.js +19 -0
  70. package/dist/data-management/decorators/model.d.ts +48 -0
  71. package/dist/data-management/decorators/model.js +24 -0
  72. package/dist/data-management/decorators/prop.d.ts +43 -0
  73. package/dist/data-management/decorators/prop.js +32 -0
  74. package/dist/data-management/index.d.ts +13 -0
  75. package/dist/data-management/store/json-to-model.d.ts +45 -0
  76. package/dist/data-management/store/json-to-model.js +36 -0
  77. package/dist/data-management/store/store.d.ts +108 -0
  78. package/dist/data-management/store/store.js +207 -0
  79. package/dist/data-management/store/types.d.ts +53 -0
  80. package/dist/events-handler/decorators/emit.d.ts +29 -0
  81. package/dist/events-handler/decorators/emit.js +51 -0
  82. package/dist/events-handler/event-decorators.d.ts +1 -0
  83. package/dist/events-handler/event-emitter.service.d.ts +21 -0
  84. package/dist/events-handler/event-emitter.service.js +85 -0
  85. package/dist/events-handler/event-types.d.ts +12 -0
  86. package/dist/index.d.ts +55 -0
  87. package/dist/index.js +121 -0
  88. package/dist/jsx/dynamic/__tests__/granular-array-renderer.test.d.ts +1 -0
  89. package/dist/jsx/dynamic/__tests__/jsx-array-rendering.test.d.ts +1 -0
  90. package/dist/jsx/dynamic/array-renderer.d.ts +2 -0
  91. package/dist/jsx/dynamic/array-renderer.js +133 -0
  92. package/dist/jsx/dynamic/child-renderer.d.ts +1 -0
  93. package/dist/jsx/dynamic/child-renderer.js +180 -0
  94. package/dist/jsx/dynamic/dom-utils.d.ts +5 -0
  95. package/dist/jsx/dynamic/dom-utils.js +22 -0
  96. package/dist/jsx/dynamic/granular-array-renderer.d.ts +16 -0
  97. package/dist/jsx/dynamic/granular-array-renderer.js +153 -0
  98. package/dist/jsx/dynamic/node-renderer.d.ts +2 -0
  99. package/dist/jsx/dynamic/props-handler.d.ts +3 -0
  100. package/dist/jsx/dynamic/props-handler.js +281 -0
  101. package/dist/jsx/dynamic/text-renderer.d.ts +2 -0
  102. package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
  103. package/dist/jsx/jsx-runtime.d.ts +3 -0
  104. package/dist/jsx/types.d.ts +35 -0
  105. package/dist/jsx/types.js +4 -0
  106. package/dist/jsx-dev-runtime.d.ts +2 -0
  107. package/dist/jsx-dev-runtime.js +8 -0
  108. package/dist/jsx-runtime.d.ts +2 -0
  109. package/dist/jsx-runtime.js +11 -0
  110. package/dist/reactivity/__tests__/context-stack.test.d.ts +1 -0
  111. package/dist/reactivity/__tests__/nested-effects-untrack.test.d.ts +22 -0
  112. package/dist/reactivity/context-scope.d.ts +57 -0
  113. package/dist/reactivity/context-scope.js +35 -0
  114. package/dist/reactivity/decorators/__tests__/ctx-integration.test.d.ts +5 -0
  115. package/dist/reactivity/decorators/__tests__/ctx-loop.test.d.ts +10 -0
  116. package/dist/reactivity/decorators/__tests__/state-intelligent.test.d.ts +1 -0
  117. package/dist/reactivity/decorators/computed.d.ts +6 -0
  118. package/dist/reactivity/decorators/computed.js +17 -0
  119. package/dist/reactivity/decorators/create-event-decorator.d.ts +5 -0
  120. package/dist/reactivity/decorators/create-event-decorator.js +28 -0
  121. package/dist/reactivity/decorators/ctx.d.ts +9 -0
  122. package/dist/reactivity/decorators/ctx.js +91 -0
  123. package/dist/reactivity/decorators/effect.d.ts +9 -0
  124. package/dist/reactivity/decorators/effect.js +24 -0
  125. package/dist/reactivity/decorators/resource.d.ts +48 -0
  126. package/dist/reactivity/decorators/resource.js +20 -0
  127. package/dist/reactivity/decorators/state.d.ts +8 -0
  128. package/dist/reactivity/decorators/state.js +68 -0
  129. package/dist/reactivity/decorators/store.d.ts +6 -0
  130. package/dist/reactivity/decorators/store.js +25 -0
  131. package/dist/reactivity/phase-scheduler.d.ts +81 -0
  132. package/dist/reactivity/phase-scheduler.js +88 -0
  133. package/dist/reactivity/phase-scheduler.test.d.ts +1 -0
  134. package/dist/reactivity/reactive-cache.d.ts +21 -0
  135. package/dist/reactivity/reactive-cache.js +31 -0
  136. package/dist/reactivity/reactive-cache.test.d.ts +1 -0
  137. package/dist/reactivity/reactive-context.d.ts +152 -0
  138. package/dist/reactivity/reactive-context.js +184 -0
  139. package/dist/reactivity/signals/__tests__/composicion-automatica.test.d.ts +1 -0
  140. package/dist/reactivity/signals/__tests__/composite/nivel-1-estructura-basica.test.d.ts +1 -0
  141. package/dist/reactivity/signals/__tests__/composite/nivel-2-registro-subscribers.test.d.ts +1 -0
  142. package/dist/reactivity/signals/__tests__/composite/nivel-3-notificaciones-basicas.test.d.ts +1 -0
  143. package/dist/reactivity/signals/__tests__/composite/nivel-4-comparacion-valores.test.d.ts +1 -0
  144. package/dist/reactivity/signals/__tests__/composite/nivel-5-tracking-automatico.test.d.ts +1 -0
  145. package/dist/reactivity/signals/__tests__/composite/nivel-6-anti-glitch.test.d.ts +1 -0
  146. package/dist/reactivity/signals/__tests__/composite/nivel-7-objetos-anidados.test.d.ts +1 -0
  147. package/dist/reactivity/signals/__tests__/composite/nivel-8-observable-array-support.test.d.ts +1 -0
  148. package/dist/reactivity/signals/__tests__/composite-shallow-tracking.test.d.ts +1 -0
  149. package/dist/reactivity/signals/__tests__/effect.test.d.ts +1 -0
  150. package/dist/reactivity/signals/__tests__/reactive-array/nivel-1-estructura-basica.test.d.ts +1 -0
  151. package/dist/reactivity/signals/__tests__/reactive-array/nivel-2-metodos-mutadores.test.d.ts +1 -0
  152. package/dist/reactivity/signals/__tests__/reactive-array/nivel-3-tracking-por-indice.test.d.ts +1 -0
  153. package/dist/reactivity/signals/__tests__/reactive-array/nivel-4-tracking-length.test.d.ts +1 -0
  154. package/dist/reactivity/signals/__tests__/reactive-array/nivel-5-tracking-mutation.test.d.ts +1 -0
  155. package/dist/reactivity/signals/__tests__/reactive-array/nivel-6-metodos-no-mutadores.test.d.ts +1 -0
  156. package/dist/reactivity/signals/__tests__/reactive-array/nivel-7-composicion-bidireccional.test.d.ts +1 -0
  157. package/dist/reactivity/signals/__tests__/reactive-array/nivel-8-proxies.test.d.ts +1 -0
  158. package/dist/reactivity/signals/__tests__/reactive-array/nivel-9-derived-cache-optimization.test.d.ts +1 -0
  159. package/dist/reactivity/signals/__tests__/resource.test.d.ts +1 -0
  160. package/dist/reactivity/signals/__tests__/signal.test.d.ts +1 -0
  161. package/dist/reactivity/signals/array-strategies.d.ts +120 -0
  162. package/dist/reactivity/signals/array-strategies.js +261 -0
  163. package/dist/reactivity/signals/composite.d.ts +89 -0
  164. package/dist/reactivity/signals/composite.js +145 -0
  165. package/dist/reactivity/signals/computed.d.ts +61 -0
  166. package/dist/reactivity/signals/computed.js +107 -0
  167. package/dist/reactivity/signals/computed.test.d.ts +1 -0
  168. package/dist/reactivity/signals/derived.d.ts +10 -0
  169. package/dist/reactivity/signals/derived.js +24 -0
  170. package/dist/reactivity/signals/effect.d.ts +27 -0
  171. package/dist/reactivity/signals/effect.js +46 -0
  172. package/dist/reactivity/signals/event.d.ts +9 -0
  173. package/dist/reactivity/signals/event.js +15 -0
  174. package/dist/reactivity/signals/reactive-array.d.ts +133 -0
  175. package/dist/reactivity/signals/reactive-array.js +490 -0
  176. package/dist/reactivity/signals/reactive-proxy.d.ts +54 -0
  177. package/dist/reactivity/signals/reactive-proxy.js +299 -0
  178. package/dist/reactivity/signals/reactive-tracking.test.d.ts +1 -0
  179. package/dist/reactivity/signals/resource.d.ts +9 -0
  180. package/dist/reactivity/signals/resource.js +58 -0
  181. package/dist/reactivity/signals/signal.d.ts +39 -0
  182. package/dist/reactivity/signals/signal.js +56 -0
  183. package/dist/reactivity/signals/subscription-management.test.d.ts +1 -0
  184. package/dist/reactivity/types.d.ts +12 -0
  185. package/dist/router/__tests__/link-behavior-active-class.test.d.ts +1 -0
  186. package/dist/router/__tests__/loop-detector.test.d.ts +1 -0
  187. package/dist/router/__tests__/params-container-resolution.test.d.ts +1 -0
  188. package/dist/router/__tests__/router-generated-routes.test.d.ts +1 -0
  189. package/dist/router/__tests__/router-params-granular.test.d.ts +1 -0
  190. package/dist/router/__tests__/router-params-simple.test.d.ts +1 -0
  191. package/dist/router/__tests__/router-query-params.test.d.ts +1 -0
  192. package/dist/router/__tests__/router-route-candidates.test.d.ts +1 -0
  193. package/dist/router/__tests__/routeview-app-articles.test.d.ts +1 -0
  194. package/dist/router/__tests__/routeview-debug.test.d.ts +1 -0
  195. package/dist/router/__tests__/routeview-integration.test.d.ts +1 -0
  196. package/dist/router/__tests__/routeview-this.test.d.ts +1 -0
  197. package/dist/router/decorators/base-policy.d.ts +141 -0
  198. package/dist/router/decorators/base-policy.js +63 -0
  199. package/dist/router/decorators/index.d.ts +6 -0
  200. package/dist/router/decorators/params.d.ts +31 -0
  201. package/dist/router/decorators/params.js +97 -0
  202. package/dist/router/decorators/route-metadata.d.ts +11 -0
  203. package/dist/router/decorators/route-metadata.js +23 -0
  204. package/dist/router/decorators/route.d.ts +39 -0
  205. package/dist/router/decorators/route.js +7 -0
  206. package/dist/router/link.behavior.d.ts +87 -0
  207. package/dist/router/link.behavior.js +227 -0
  208. package/dist/router/policy-evaluator.d.ts +81 -0
  209. package/dist/router/policy-evaluator.js +209 -0
  210. package/dist/router/route-view.d.ts +56 -0
  211. package/dist/router/route-view.js +156 -0
  212. package/dist/router/router.d.ts +67 -0
  213. package/dist/router/router.js +308 -0
  214. package/dist/router/static-analysis/index.d.ts +37 -0
  215. package/dist/router/static-analysis/parser.d.ts +14 -0
  216. package/dist/router/static-analysis/parser.js +147 -0
  217. package/dist/router/static-analysis/scanner.d.ts +27 -0
  218. package/dist/router/static-analysis/scanner.js +91 -0
  219. package/dist/router/trie.d.ts +14 -0
  220. package/dist/router/trie.js +126 -0
  221. package/dist/router/trie.types.d.ts +36 -0
  222. package/dist/styles/base-style-sheet.d.ts +96 -0
  223. package/dist/styles/base-style-sheet.js +149 -0
  224. package/dist/styles/decorators/factories.d.ts +76 -0
  225. package/dist/styles/decorators/factories.js +11 -0
  226. package/dist/styles/decorators/keyframes.d.ts +238 -0
  227. package/dist/styles/decorators/keyframes.js +79 -0
  228. package/dist/styles/decorators/rule.d.ts +177 -0
  229. package/dist/styles/decorators/rule.js +72 -0
  230. package/dist/styles/decorators/scope.d.ts +66 -0
  231. package/dist/styles/decorators/scope.js +17 -0
  232. package/dist/styles/decorators/style.d.ts +1 -0
  233. package/dist/styles/decorators/style.js +20 -0
  234. package/dist/styles/decorators/useStyles.d.ts +5 -0
  235. package/dist/styles/decorators/useStyles.js +29 -0
  236. package/dist/styles/global-styles-registry.d.ts +72 -0
  237. package/dist/styles/global-styles-registry.js +155 -0
  238. package/dist/types.d.ts +1 -0
  239. package/dist/vite-plugins/__tests__/jsx-control-flow-transform.test.d.ts +1 -0
  240. package/dist/vite-plugins/index.d.ts +4 -0
  241. package/dist/vite-plugins/index.js +10 -0
  242. package/dist/vite-plugins/jsx-contextual.d.ts +7 -0
  243. package/dist/vite-plugins/jsx-contextual.js +53 -0
  244. package/dist/vite-plugins/jsx-control-flow-transform.d.ts +60 -0
  245. package/dist/vite-plugins/jsx-control-flow-transform.js +180 -0
  246. package/dist/vite-plugins/jsx-signals.d.ts +2 -0
  247. package/dist/vite-plugins/jsx-signals.js +124 -0
  248. package/dist/vite-plugins/router/route-generator-plugin.d.ts +63 -0
  249. package/dist/vite-plugins/router/route-generator-plugin.js +310 -0
  250. package/package.json +85 -0
@@ -0,0 +1,89 @@
1
+ import { Subscriber } from '../types.js';
2
+ export type { Subscriber };
3
+ /**
4
+ * CompositeSignal - Con caché compartido y composición automática
5
+ *
6
+ * Soporta reactividad profunda con composición automática:
7
+ * - Objetos anidados se envuelven automáticamente en CompositeSignal
8
+ * - Arrays anidados se envuelven automáticamente en ReactiveArray
9
+ * - Usa caché compartido global para garantizar consistencia
10
+ * - El tracking funciona en cualquier nivel de profundidad
11
+ *
12
+ * IMPORTANTE: Usa el mismo tipo Subscriber que Signal, que es una función.
13
+ * Esto permite integración completa con el sistema de reactividad existente.
14
+ */
15
+ export declare class CompositeSignal<T extends object> {
16
+ private value;
17
+ private propertySubscribers;
18
+ private nestedReactives;
19
+ private onChangeCallback?;
20
+ constructor(initialValue: T);
21
+ /**
22
+ * Registra un callback que se llamará cada vez que cualquier propiedad cambie
23
+ * El callback se llama síncronamente antes de cualquier notificación a subscribers
24
+ *
25
+ * @param callback - Función que recibe (property, oldValue, newValue)
26
+ */
27
+ onChange(callback: (property: string | symbol, oldValue: any, newValue: any) => void): void;
28
+ /**
29
+ * Obtiene el objeto JavaScript plano subyacente, sin envolver en CompositeSignal
30
+ *
31
+ * @returns El objeto plano original
32
+ */
33
+ getPlainValue(): T;
34
+ /**
35
+ * Obtiene el valor de una propiedad del objeto almacenado
36
+ * Si hay un efecto activo en reactiveContext, lo registra automáticamente
37
+ * como subscriber de esta propiedad
38
+ *
39
+ * COMPOSICIÓN AUTOMÁTICA:
40
+ * - Si el valor es un objeto → devuelve CompositeSignal
41
+ * - Si el valor es un array → devuelve ReactiveArray
42
+ * - Si el valor es primitivo → devuelve el valor directo
43
+ *
44
+ * Usa caché compartido para garantizar consistencia
45
+ *
46
+ * @param property - La clave de la propiedad a leer
47
+ * @returns El valor de la propiedad (envuelto si es objeto/array)
48
+ */
49
+ get(property: string | symbol): any;
50
+ /**
51
+ * Actualiza el valor de una propiedad en el objeto almacenado y notifica a los subscribers
52
+ * Solo notifica si el valor realmente cambió (usa Object.is para comparación)
53
+ *
54
+ * IMPORTANTE: Si se reemplaza un objeto, invalida el caché del CompositeSignal anidado
55
+ *
56
+ * @param property - La clave de la propiedad a actualizar
57
+ * @param newValue - El nuevo valor para la propiedad
58
+ */
59
+ set(property: string | symbol, newValue: any): void;
60
+ /**
61
+ * Notifica a todos los subscribers de una propiedad específica
62
+ * Distingue entre Computed (síncrono) y Effect (agendado en scheduler)
63
+ * @param property - La propiedad cuyos subscribers deben ser notificados
64
+ */
65
+ private _notifyProperty;
66
+ /**
67
+ * Registra un subscriber para una propiedad específica
68
+ * @param property - La propiedad a observar
69
+ * @param subscriber - El subscriber que se ejecutará cuando la propiedad cambie
70
+ */
71
+ subscribeToProperty(property: string | symbol, subscriber: Subscriber): void;
72
+ /**
73
+ * Método helper para inspeccionar los subscribers registrados (útil para testing)
74
+ * @param property - La propiedad a inspeccionar
75
+ * @returns El Set de subscribers para esa propiedad, o undefined si no hay
76
+ */
77
+ getSubscribers(property: string | symbol): Set<Subscriber> | undefined;
78
+ /**
79
+ * Método helper para obtener todas las propiedades que tienen subscribers
80
+ * @returns Array de propiedades que tienen al menos un subscriber
81
+ */
82
+ getSubscribedProperties(): (string | symbol)[];
83
+ /**
84
+ * ✅ NUEVO: Trackea shallow (cualquier cambio en el objeto)
85
+ * Se llama cuando se itera sobre el objeto (Object.keys, for...in, etc.)
86
+ * El effect se ejecutará cuando CUALQUIER propiedad cambie
87
+ */
88
+ trackShallow(): void;
89
+ }
@@ -0,0 +1,145 @@
1
+ import { reactiveContext } from "../reactive-context.js";
2
+ import { phaseScheduler } from "../phase-scheduler.js";
3
+ import { getOrCreateReactive } from "../reactive-cache.js";
4
+ const SHALLOW_KEY = Symbol.for("__composite_shallow__");
5
+ class CompositeSignal {
6
+ constructor(initialValue) {
7
+ this.propertySubscribers = /* @__PURE__ */ new Map();
8
+ this.nestedReactives = /* @__PURE__ */ new Map();
9
+ this.value = initialValue;
10
+ }
11
+ /**
12
+ * Registra un callback que se llamará cada vez que cualquier propiedad cambie
13
+ * El callback se llama síncronamente antes de cualquier notificación a subscribers
14
+ *
15
+ * @param callback - Función que recibe (property, oldValue, newValue)
16
+ */
17
+ onChange(callback) {
18
+ this.onChangeCallback = callback;
19
+ }
20
+ /**
21
+ * Obtiene el objeto JavaScript plano subyacente, sin envolver en CompositeSignal
22
+ *
23
+ * @returns El objeto plano original
24
+ */
25
+ getPlainValue() {
26
+ return this.value;
27
+ }
28
+ /**
29
+ * Obtiene el valor de una propiedad del objeto almacenado
30
+ * Si hay un efecto activo en reactiveContext, lo registra automáticamente
31
+ * como subscriber de esta propiedad
32
+ *
33
+ * COMPOSICIÓN AUTOMÁTICA:
34
+ * - Si el valor es un objeto → devuelve CompositeSignal
35
+ * - Si el valor es un array → devuelve ReactiveArray
36
+ * - Si el valor es primitivo → devuelve el valor directo
37
+ *
38
+ * Usa caché compartido para garantizar consistencia
39
+ *
40
+ * @param property - La clave de la propiedad a leer
41
+ * @returns El valor de la propiedad (envuelto si es objeto/array)
42
+ */
43
+ get(property) {
44
+ if (reactiveContext.currentComputation && reactiveContext.isTracking) {
45
+ this.subscribeToProperty(property, reactiveContext.currentComputation);
46
+ }
47
+ const value = this.value[property];
48
+ if (value === null || typeof value !== "object") {
49
+ return value;
50
+ }
51
+ if (!this.nestedReactives.has(property)) {
52
+ const reactive = getOrCreateReactive(value);
53
+ this.nestedReactives.set(property, reactive);
54
+ }
55
+ return this.nestedReactives.get(property);
56
+ }
57
+ /**
58
+ * Actualiza el valor de una propiedad en el objeto almacenado y notifica a los subscribers
59
+ * Solo notifica si el valor realmente cambió (usa Object.is para comparación)
60
+ *
61
+ * IMPORTANTE: Si se reemplaza un objeto, invalida el caché del CompositeSignal anidado
62
+ *
63
+ * @param property - La clave de la propiedad a actualizar
64
+ * @param newValue - El nuevo valor para la propiedad
65
+ */
66
+ set(property, newValue) {
67
+ const oldValue = this.value[property];
68
+ if (!Object.is(oldValue, newValue)) {
69
+ this.value[property] = newValue;
70
+ if (this.onChangeCallback) {
71
+ this.onChangeCallback(property, oldValue, newValue);
72
+ }
73
+ if (this.nestedReactives.has(property)) {
74
+ this.nestedReactives.delete(property);
75
+ }
76
+ this._notifyProperty(property);
77
+ }
78
+ }
79
+ /**
80
+ * Notifica a todos los subscribers de una propiedad específica
81
+ * Distingue entre Computed (síncrono) y Effect (agendado en scheduler)
82
+ * @param property - La propiedad cuyos subscribers deben ser notificados
83
+ */
84
+ _notifyProperty(property) {
85
+ const subscribers = this.propertySubscribers.get(property);
86
+ if (subscribers) {
87
+ subscribers.forEach((subscriber) => {
88
+ if (subscriber._isComputation) {
89
+ subscriber();
90
+ } else {
91
+ phaseScheduler.schedule(subscriber);
92
+ }
93
+ });
94
+ }
95
+ const shallowSubscribers = this.propertySubscribers.get(SHALLOW_KEY);
96
+ if (shallowSubscribers) {
97
+ shallowSubscribers.forEach((subscriber) => {
98
+ if (subscriber._isComputation) {
99
+ subscriber();
100
+ } else {
101
+ phaseScheduler.schedule(subscriber);
102
+ }
103
+ });
104
+ }
105
+ }
106
+ /**
107
+ * Registra un subscriber para una propiedad específica
108
+ * @param property - La propiedad a observar
109
+ * @param subscriber - El subscriber que se ejecutará cuando la propiedad cambie
110
+ */
111
+ subscribeToProperty(property, subscriber) {
112
+ if (!this.propertySubscribers.has(property)) {
113
+ this.propertySubscribers.set(property, /* @__PURE__ */ new Set());
114
+ }
115
+ this.propertySubscribers.get(property).add(subscriber);
116
+ }
117
+ /**
118
+ * Método helper para inspeccionar los subscribers registrados (útil para testing)
119
+ * @param property - La propiedad a inspeccionar
120
+ * @returns El Set de subscribers para esa propiedad, o undefined si no hay
121
+ */
122
+ getSubscribers(property) {
123
+ return this.propertySubscribers.get(property);
124
+ }
125
+ /**
126
+ * Método helper para obtener todas las propiedades que tienen subscribers
127
+ * @returns Array de propiedades que tienen al menos un subscriber
128
+ */
129
+ getSubscribedProperties() {
130
+ return Array.from(this.propertySubscribers.keys());
131
+ }
132
+ /**
133
+ * ✅ NUEVO: Trackea shallow (cualquier cambio en el objeto)
134
+ * Se llama cuando se itera sobre el objeto (Object.keys, for...in, etc.)
135
+ * El effect se ejecutará cuando CUALQUIER propiedad cambie
136
+ */
137
+ trackShallow() {
138
+ if (reactiveContext.currentComputation && reactiveContext.isTracking) {
139
+ this.subscribeToProperty(SHALLOW_KEY, reactiveContext.currentComputation);
140
+ }
141
+ }
142
+ }
143
+ export {
144
+ CompositeSignal
145
+ };
@@ -0,0 +1,61 @@
1
+ import { ISignal } from './signal';
2
+ /**
3
+ * Computed Signal - Lazy evaluation with dirty flag (like Solid.js, Vue 3)
4
+ *
5
+ * Características:
6
+ * - Solo recalcula cuando se lee (lazy/pull-based)
7
+ * - Usa un flag "_isDirty" para saber si necesita recalcular
8
+ * - Recalcula SÍNCRONAMENTE cuando se lee y está dirty
9
+ * - NO usa scheduler asíncrono para recalcular (no hay glitches)
10
+ * - Trackea sus dependencias automáticamente
11
+ *
12
+ * STACK UNIFICADO:
13
+ * - Usa reactiveContext.enter() para crear su contexto de tracking
14
+ * - Garantiza limpieza correcta del contexto
15
+ */
16
+ export declare class Computed<T> implements ISignal<T> {
17
+ readonly isSignal = true;
18
+ private _value;
19
+ private _subscribers;
20
+ private _getter;
21
+ private _isDirty;
22
+ private _computation;
23
+ private _sources;
24
+ constructor(getter: () => T);
25
+ get(): T;
26
+ /**
27
+ * Recalcula el valor del computed síncronamente.
28
+ * Se ejecuta cuando:
29
+ * 1. Se lee el computed (get) y está dirty
30
+ * 2. Es la primera vez que se lee
31
+ */
32
+ private _recompute;
33
+ /**
34
+ * Notifica a los subscribers que este computed cambió.
35
+ *
36
+ * FIX: Distingue entre Computed y Effect:
37
+ * - Computed: Ejecutar síncronamente
38
+ * - Effect: Agendar en el scheduler
39
+ */
40
+ private _notify;
41
+ /**
42
+ * Limpia las suscripciones a las signals anteriores.
43
+ * Este es el patrón Solid/Vue de bi-directional tracking:
44
+ * - Signal sabe quién depende de ella (_subscribers)
45
+ * - Computed sabe de qué signals depende (_sources)
46
+ *
47
+ * Cuando recalculamos, necesitamos:
48
+ * 1. Des-suscribirnos de las signals viejas
49
+ * 2. Re-trackear las nuevas signals que leemos
50
+ *
51
+ * Esto permite dependencias dinámicas/condicionales.
52
+ */
53
+ private _cleanup;
54
+ set(newValue: T): void;
55
+ update(updater: (currentValue: T) => T): void;
56
+ /**
57
+ * Limpia los recursos del computed.
58
+ */
59
+ dispose(): void;
60
+ }
61
+ export declare function computed<T>(getter: () => T): ISignal<T>;
@@ -0,0 +1,107 @@
1
+ import { reactiveContext } from "../reactive-context.js";
2
+ import { phaseScheduler } from "../phase-scheduler.js";
3
+ class Computed {
4
+ constructor(getter) {
5
+ this.isSignal = true;
6
+ this._subscribers = /* @__PURE__ */ new Set();
7
+ this._isDirty = true;
8
+ this._sources = /* @__PURE__ */ new Set();
9
+ this._getter = getter;
10
+ this._value = void 0;
11
+ const self = this;
12
+ this._computation = () => {
13
+ self._isDirty = true;
14
+ self._notify();
15
+ };
16
+ this._computation.priority = "Sync";
17
+ this._computation._isComputation = true;
18
+ }
19
+ get() {
20
+ if (this._isDirty) {
21
+ this._recompute();
22
+ }
23
+ if (reactiveContext.currentComputation && reactiveContext.isTracking) {
24
+ this._subscribers.add(reactiveContext.currentComputation);
25
+ }
26
+ return this._value;
27
+ }
28
+ /**
29
+ * Recalcula el valor del computed síncronamente.
30
+ * Se ejecuta cuando:
31
+ * 1. Se lee el computed (get) y está dirty
32
+ * 2. Es la primera vez que se lee
33
+ */
34
+ _recompute() {
35
+ this._isDirty = false;
36
+ this._cleanup();
37
+ const previousOnTrack = reactiveContext.onTrack;
38
+ reactiveContext.onTrack = (signal) => {
39
+ this._sources.add(signal);
40
+ };
41
+ const exitContext = reactiveContext.enter(this._computation, true, "computed");
42
+ try {
43
+ const newValue = this._getter();
44
+ this._value = newValue;
45
+ } finally {
46
+ exitContext();
47
+ reactiveContext.onTrack = previousOnTrack;
48
+ }
49
+ }
50
+ /**
51
+ * Notifica a los subscribers que este computed cambió.
52
+ *
53
+ * FIX: Distingue entre Computed y Effect:
54
+ * - Computed: Ejecutar síncronamente
55
+ * - Effect: Agendar en el scheduler
56
+ */
57
+ _notify() {
58
+ this._subscribers.forEach((subscriber) => {
59
+ if (subscriber._isComputation) {
60
+ subscriber();
61
+ } else {
62
+ phaseScheduler.schedule(subscriber);
63
+ }
64
+ });
65
+ }
66
+ /**
67
+ * Limpia las suscripciones a las signals anteriores.
68
+ * Este es el patrón Solid/Vue de bi-directional tracking:
69
+ * - Signal sabe quién depende de ella (_subscribers)
70
+ * - Computed sabe de qué signals depende (_sources)
71
+ *
72
+ * Cuando recalculamos, necesitamos:
73
+ * 1. Des-suscribirnos de las signals viejas
74
+ * 2. Re-trackear las nuevas signals que leemos
75
+ *
76
+ * Esto permite dependencias dinámicas/condicionales.
77
+ */
78
+ _cleanup() {
79
+ this._sources.forEach((source) => {
80
+ if (source._unsubscribe) {
81
+ source._unsubscribe(this._computation);
82
+ }
83
+ });
84
+ this._sources.clear();
85
+ }
86
+ // Las signals computadas son de solo lectura
87
+ set(newValue) {
88
+ throw new Error("Cannot set a computed signal.");
89
+ }
90
+ update(updater) {
91
+ throw new Error("Cannot update a computed signal.");
92
+ }
93
+ /**
94
+ * Limpia los recursos del computed.
95
+ */
96
+ dispose() {
97
+ this._cleanup();
98
+ this._subscribers.clear();
99
+ }
100
+ }
101
+ function computed(getter) {
102
+ return new Computed(getter);
103
+ }
104
+ export {
105
+ Computed,
106
+ computed
107
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import { ISignal } from './signal';
2
+ export declare class Derived<T> implements ISignal<T> {
3
+ readonly isSignal = true;
4
+ private _inner;
5
+ constructor(source: ISignal<T>, mapper?: (value: T) => T);
6
+ get(): T;
7
+ set(_: T): void;
8
+ update(_: (currentValue: T) => T): void;
9
+ }
10
+ export declare function derived<T>(source: ISignal<T>, mapper?: (value: T) => T): ISignal<T>;
@@ -0,0 +1,24 @@
1
+ import { computed } from "./computed.js";
2
+ class Derived {
3
+ constructor(source, mapper) {
4
+ this.isSignal = true;
5
+ const safeMapper = mapper ?? ((v) => v);
6
+ this._inner = computed(() => safeMapper(source.get()));
7
+ }
8
+ get() {
9
+ return this._inner.get();
10
+ }
11
+ set(_) {
12
+ throw new Error("Cannot set a ContextSignal.");
13
+ }
14
+ update(_) {
15
+ throw new Error("Cannot update a ContextSignal.");
16
+ }
17
+ }
18
+ function derived(source, mapper) {
19
+ return new Derived(source, mapper);
20
+ }
21
+ export {
22
+ Derived,
23
+ derived
24
+ };
@@ -0,0 +1,27 @@
1
+ interface Computation extends Function {
2
+ }
3
+ /**
4
+ * Crea un effect reactivo que se re-ejecuta cuando sus dependencias cambian
5
+ *
6
+ * Sistema basado en fases:
7
+ * - Elimina glitches garantizando orden de ejecución consistente
8
+ * - Batching automático de actualizaciones
9
+ * - Ordenamiento topológico de dependencias
10
+ *
11
+ * IMPORTANTE (Stack Unificado):
12
+ * - Cada effect usa reactiveContext.enter() para crear su propio frame
13
+ * - Esto garantiza que el effect tenga su propio contexto incluso si
14
+ * se crea dentro de un untrack() del padre
15
+ * - Resuelve el bug de suscripciones perdidas en effects anidados
16
+ *
17
+ * @param fn - Función a ejecutar. Recibe onCleanup para registrar limpieza
18
+ * @param options - Opciones (deprecado: priority ya no se usa)
19
+ * @returns Objeto con métodos run y dispose
20
+ */
21
+ export declare function effect(fn: (onCleanup: (cb: () => void) => void) => void | Promise<void>, options?: {
22
+ priority?: string;
23
+ }): {
24
+ run: Computation;
25
+ dispose: () => void;
26
+ };
27
+ export {};
@@ -0,0 +1,46 @@
1
+ import { reactiveContext } from "../reactive-context.js";
2
+ function effect(fn, options) {
3
+ let cleanupFn = null;
4
+ let isDisposed = false;
5
+ const onCleanup = (cb) => {
6
+ cleanupFn = cb;
7
+ };
8
+ const computation = () => {
9
+ if (isDisposed) {
10
+ return;
11
+ }
12
+ if (cleanupFn) {
13
+ cleanupFn();
14
+ cleanupFn = null;
15
+ }
16
+ const exitContext = reactiveContext.enter(computation, true, "effect");
17
+ try {
18
+ const result = fn(onCleanup);
19
+ if (result && typeof result.then === "function") {
20
+ result.finally(exitContext);
21
+ } else {
22
+ exitContext();
23
+ }
24
+ } catch (error) {
25
+ exitContext();
26
+ throw error;
27
+ }
28
+ };
29
+ computation();
30
+ return {
31
+ run: computation,
32
+ dispose: () => {
33
+ if (isDisposed) {
34
+ return;
35
+ }
36
+ isDisposed = true;
37
+ if (cleanupFn) {
38
+ cleanupFn();
39
+ cleanupFn = null;
40
+ }
41
+ }
42
+ };
43
+ }
44
+ export {
45
+ effect
46
+ };
@@ -0,0 +1,9 @@
1
+ import { Signal } from './signal';
2
+ export declare function eventListener<T, K extends keyof HTMLElementEventMap>(eventTarget: EventTarget, eventType: K, valueGetter: (e: HTMLElementEventMap[K]) => T, initialValueGetter?: () => T): {
3
+ signal: Signal<T>;
4
+ cleanup: () => void;
5
+ };
6
+ export declare function eventListener<T>(eventTarget: EventTarget, eventType: string, valueGetter: (e: Event) => T, initialValueGetter?: () => T): {
7
+ signal: Signal<T>;
8
+ cleanup: () => void;
9
+ };
@@ -0,0 +1,15 @@
1
+ import { Signal } from "./signal.js";
2
+ function eventListener(eventTarget, eventType, valueGetter, initialValueGetter) {
3
+ const signal = new Signal(
4
+ valueGetter(null)
5
+ );
6
+ const updateSignal = (e) => signal.set(valueGetter(e));
7
+ eventTarget.addEventListener(eventType, updateSignal);
8
+ const cleanup = () => {
9
+ eventTarget.removeEventListener(eventType, updateSignal);
10
+ };
11
+ return { signal, cleanup };
12
+ }
13
+ export {
14
+ eventListener
15
+ };
@@ -0,0 +1,133 @@
1
+ import { Subscriber } from '../types.js';
2
+ export type { Subscriber };
3
+ export declare class ReactiveArray<T> {
4
+ private strategy;
5
+ private ownedStrategy?;
6
+ private subscribers;
7
+ private onChangeCallback?;
8
+ private mapCache;
9
+ constructor(itemsOrConfig?: T[] | {
10
+ source: ReactiveArray<any>;
11
+ transform: (value: any, index: number) => T;
12
+ } | {
13
+ source: ReactiveArray<T>;
14
+ predicate: (value: T, index: number, array: T[]) => boolean;
15
+ });
16
+ /**
17
+ * Registra un callback que se llama síncronamente antes de notificar subscribers
18
+ */
19
+ onChange(callback: (operation: string, ...args: any[]) => void): void;
20
+ /**
21
+ * Retorna el array plano subyacente (sin reactividad)
22
+ * Útil para serialización o interoperación con código no reactivo
23
+ */
24
+ getPlainValue(): T[];
25
+ /**
26
+ * Getter reactivo para la longitud del array
27
+ */
28
+ get length(): number;
29
+ /**
30
+ * Método at() reactivo que soporta índices negativos
31
+ * Similar a array.at() pero con tracking granular por índice
32
+ */
33
+ at(index: number): T | undefined;
34
+ /**
35
+ * Asegura que el array esté en modo owned (tiene datos propios)
36
+ * Lanza error si se intenta mutar un array derivado
37
+ */
38
+ private ensureOwned;
39
+ push(...items: T[]): number;
40
+ pop(): T | undefined;
41
+ shift(): T | undefined;
42
+ unshift(...items: T[]): number;
43
+ splice(start: number, deleteCount?: number, ...items: T[]): T[];
44
+ sort(compareFn?: (a: T, b: T) => number): this;
45
+ reverse(): this;
46
+ fill(value: T, start?: number, end?: number): this;
47
+ /**
48
+ * map() ahora retorna un ReactiveArray derivado, no un array plano
49
+ * Este es el corazón de tu insight: mantener la reactividad en la cadena
50
+ *
51
+ * MEMOIZACIÓN INTELIGENTE:
52
+ * - Cachea el array derivado por toString() del callback
53
+ * - Captura dependencias externas (signals que el callback lee)
54
+ * - Si las dependencias no cambiaron, retorna el MISMO array derivado
55
+ * - Esto permite granularidad: push/pop solo afectan nuevos elementos
56
+ */
57
+ map<U>(callback: (value: T, index: number, array: T[]) => U): ReactiveArray<U>;
58
+ /**
59
+ * filter() también retorna un ReactiveArray derivado
60
+ * Implementación especial que necesita manejar índices no lineales
61
+ */
62
+ filter(callback: (value: T, index: number, array: T[]) => boolean): ReactiveArray<T>;
63
+ slice(start?: number, end?: number): T[];
64
+ concat(...items: (T | T[])[]): T[];
65
+ find(callback: (value: T, index: number, array: T[]) => boolean): T | undefined;
66
+ findIndex(callback: (value: T, index: number, array: T[]) => boolean): number;
67
+ indexOf(searchElement: T, fromIndex?: number): number;
68
+ includes(searchElement: T, fromIndex?: number): boolean;
69
+ forEach(callback: (value: T, index: number, array: T[]) => void): void;
70
+ some(callback: (value: T, index: number, array: T[]) => boolean): boolean;
71
+ every(callback: (value: T, index: number, array: T[]) => boolean): boolean;
72
+ reduce<U>(callback: (accumulator: U, value: T, index: number, array: T[]) => U, initialValue: U): U;
73
+ reduceRight<U>(callback: (accumulator: U, value: T, index: number, array: T[]) => U, initialValue: U): U;
74
+ join(separator?: string): string;
75
+ toString(): string;
76
+ toLocaleString(): string;
77
+ [Symbol.iterator](): IterableIterator<T>;
78
+ entries(): IterableIterator<[number, T]>;
79
+ keys(): IterableIterator<number>;
80
+ values(): IterableIterator<T>;
81
+ /**
82
+ * Registra un subscriber para un tipo específico de cambio
83
+ */
84
+ private _subscribe;
85
+ /**
86
+ * Notifica a subscribers de un tipo específico de cambio
87
+ */
88
+ private _notify;
89
+ /**
90
+ * Notifica que el array mutó (cualquier cambio en contenido)
91
+ */
92
+ private _notifyMutation;
93
+ /**
94
+ * Notifica que la longitud cambió
95
+ */
96
+ private _notifyLength;
97
+ /**
98
+ * Notifica a todos los índices numéricos suscritos
99
+ * Se usa cuando operaciones como shift/unshift/splice afectan múltiples índices
100
+ */
101
+ private _notifyAllIndices;
102
+ /**
103
+ * Notifica todos los índices desde start hacia adelante
104
+ * Útil cuando splice/insert afecta índices posteriores
105
+ */
106
+ private _notifyIndicesFrom;
107
+ getSubscribers(key: string | number): Set<Subscriber> | undefined;
108
+ getSubscribedKeys(): (string | number)[];
109
+ }
110
+ export type ObservableArray<T> = ReactiveArray<T>;
111
+ export type Collection<T> = ReactiveArray<T>;
112
+ /**
113
+ * Factory function to create a new ReactiveArray
114
+ */
115
+ export declare function collection<T>(items?: T[]): ReactiveArray<T>;
116
+ /**
117
+ * Type guard to check if a value is a ReactiveArray
118
+ */
119
+ export declare function isObservableArray(value: any): value is ReactiveArray<any>;
120
+ /**
121
+ * Type guard to check if a value is a Collection (same as ObservableArray)
122
+ */
123
+ export declare function isCollection(value: any): value is ReactiveArray<any>;
124
+ /**
125
+ * Type guard to check if a value is a ReactiveArray OR a proxy wrapping a ReactiveArray
126
+ * This is useful in JSX rendering where arrays might be wrapped in proxies
127
+ */
128
+ export declare function isReactiveArrayLike(value: any): boolean;
129
+ /**
130
+ * Unwraps a ReactiveArray from a proxy if necessary
131
+ * Returns the underlying ReactiveArray or null if the value is not a ReactiveArray
132
+ */
133
+ export declare function unwrapReactiveArray<T = any>(value: any): ReactiveArray<T> | null;