@elurjs/core 3.6.1 → 3.7.0-beta.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 (213) hide show
  1. package/dist/lib/async.cjs +1 -1
  2. package/dist/lib/async.js +1 -1
  3. package/dist/lib/component.cjs +1 -2
  4. package/dist/lib/component.js +2 -66
  5. package/dist/lib/context.cjs +1 -1
  6. package/dist/lib/context.js +35 -23
  7. package/dist/lib/devtools.cjs +1 -1
  8. package/dist/lib/devtools.js +1 -1
  9. package/dist/lib/elur/async.cjs +1 -1
  10. package/dist/lib/elur/async.cjs.map +1 -1
  11. package/dist/lib/elur/async.js +1 -1
  12. package/dist/lib/elur/component.cjs +1 -2
  13. package/dist/lib/elur/component.d.cts +1 -17
  14. package/dist/lib/elur/component.d.ts +1 -17
  15. package/dist/lib/elur/component.js +2 -66
  16. package/dist/lib/elur/context.cjs +1 -1
  17. package/dist/lib/elur/context.cjs.map +1 -1
  18. package/dist/lib/elur/context.d.cts +5 -0
  19. package/dist/lib/elur/context.d.ts +5 -0
  20. package/dist/lib/elur/context.js +35 -23
  21. package/dist/lib/elur/context.js.map +1 -1
  22. package/dist/lib/elur/devtools.cjs +1 -1
  23. package/dist/lib/elur/devtools.cjs.map +1 -1
  24. package/dist/lib/elur/devtools.js +1 -1
  25. package/dist/lib/elur/form.cjs +1 -1
  26. package/dist/lib/elur/form.cjs.map +1 -1
  27. package/dist/lib/elur/form.js +1 -1
  28. package/dist/lib/elur/hydrate/index.cjs +1 -2
  29. package/dist/lib/elur/hydrate/index.d.cts +1 -13
  30. package/dist/lib/elur/hydrate/index.d.ts +1 -13
  31. package/dist/lib/elur/hydrate/index.js +2 -410
  32. package/dist/lib/elur/lifecycle.cjs +1 -1
  33. package/dist/lib/elur/lifecycle.cjs.map +1 -1
  34. package/dist/lib/elur/lifecycle.d.cts +27 -0
  35. package/dist/lib/elur/lifecycle.d.ts +27 -0
  36. package/dist/lib/elur/lifecycle.js +4 -0
  37. package/dist/lib/elur/lifecycle.js.map +1 -1
  38. package/dist/lib/elur/next/component.d.cts +281 -0
  39. package/dist/lib/elur/next/component.d.ts +281 -0
  40. package/dist/lib/elur/next/dom-write.d.cts +18 -0
  41. package/dist/lib/elur/next/dom-write.d.ts +18 -0
  42. package/dist/lib/elur/next/hydrate.d.cts +14 -0
  43. package/dist/lib/elur/next/hydrate.d.ts +14 -0
  44. package/dist/lib/elur/next/keyed-diff.d.cts +46 -0
  45. package/dist/lib/elur/next/keyed-diff.d.ts +46 -0
  46. package/dist/lib/elur/next/mount-helpers.d.cts +25 -0
  47. package/dist/lib/elur/next/mount-helpers.d.ts +25 -0
  48. package/dist/lib/elur/next/mount.d.cts +29 -0
  49. package/dist/lib/elur/next/mount.d.ts +29 -0
  50. package/dist/lib/elur/next/node-binding.d.cts +6 -0
  51. package/dist/lib/elur/next/node-binding.d.ts +6 -0
  52. package/dist/lib/elur/next/reactivity.d.cts +193 -0
  53. package/dist/lib/elur/next/reactivity.d.ts +193 -0
  54. package/dist/lib/elur/next-2/component.cjs +2 -0
  55. package/dist/lib/elur/next-2/component.cjs.map +1 -0
  56. package/dist/lib/elur/next-2/component.d.cts +283 -0
  57. package/dist/lib/elur/next-2/component.d.ts +283 -0
  58. package/dist/lib/elur/next-2/component.js +340 -0
  59. package/dist/lib/elur/next-2/component.js.map +1 -0
  60. package/dist/lib/elur/next-2/dom-write.cjs +2 -0
  61. package/dist/lib/elur/next-2/dom-write.cjs.map +1 -0
  62. package/dist/lib/elur/next-2/dom-write.d.cts +18 -0
  63. package/dist/lib/elur/next-2/dom-write.d.ts +18 -0
  64. package/dist/lib/elur/next-2/dom-write.js +31 -0
  65. package/dist/lib/elur/next-2/dom-write.js.map +1 -0
  66. package/dist/lib/elur/next-2/hydrate.cjs +2 -0
  67. package/dist/lib/elur/next-2/hydrate.cjs.map +1 -0
  68. package/dist/lib/elur/next-2/hydrate.d.cts +30 -0
  69. package/dist/lib/elur/next-2/hydrate.d.ts +30 -0
  70. package/dist/lib/elur/next-2/hydrate.js +449 -0
  71. package/dist/lib/elur/next-2/hydrate.js.map +1 -0
  72. package/dist/lib/elur/next-2/keyed-diff.cjs +2 -0
  73. package/dist/lib/elur/next-2/keyed-diff.cjs.map +1 -0
  74. package/dist/lib/elur/next-2/keyed-diff.d.cts +79 -0
  75. package/dist/lib/elur/next-2/keyed-diff.d.ts +79 -0
  76. package/dist/lib/elur/next-2/keyed-diff.js +208 -0
  77. package/dist/lib/elur/next-2/keyed-diff.js.map +1 -0
  78. package/dist/lib/elur/next-2/mount-helpers.cjs +2 -0
  79. package/dist/lib/elur/next-2/mount-helpers.cjs.map +1 -0
  80. package/dist/lib/elur/next-2/mount-helpers.d.cts +25 -0
  81. package/dist/lib/elur/next-2/mount-helpers.d.ts +25 -0
  82. package/dist/lib/elur/next-2/mount-helpers.js +87 -0
  83. package/dist/lib/elur/next-2/mount-helpers.js.map +1 -0
  84. package/dist/lib/elur/next-2/mount.cjs +2 -0
  85. package/dist/lib/elur/next-2/mount.cjs.map +1 -0
  86. package/dist/lib/elur/next-2/mount.d.cts +29 -0
  87. package/dist/lib/elur/next-2/mount.d.ts +29 -0
  88. package/dist/lib/elur/next-2/mount.js +34 -0
  89. package/dist/lib/elur/next-2/mount.js.map +1 -0
  90. package/dist/lib/elur/next-2/node-binding.cjs +2 -0
  91. package/dist/lib/elur/next-2/node-binding.cjs.map +1 -0
  92. package/dist/lib/elur/next-2/node-binding.d.cts +6 -0
  93. package/dist/lib/elur/next-2/node-binding.d.ts +6 -0
  94. package/dist/lib/elur/next-2/node-binding.js +130 -0
  95. package/dist/lib/elur/next-2/node-binding.js.map +1 -0
  96. package/dist/lib/elur/next-2/reactivity.cjs +2 -0
  97. package/dist/lib/elur/next-2/reactivity.cjs.map +1 -0
  98. package/dist/lib/elur/next-2/reactivity.d.cts +220 -0
  99. package/dist/lib/elur/next-2/reactivity.d.ts +220 -0
  100. package/dist/lib/elur/next-2/reactivity.js +614 -0
  101. package/dist/lib/elur/next-2/reactivity.js.map +1 -0
  102. package/dist/lib/elur/next-2/scheduler.cjs +2 -0
  103. package/dist/lib/elur/next-2/scheduler.cjs.map +1 -0
  104. package/dist/lib/elur/next-2/scheduler.d.cts +23 -0
  105. package/dist/lib/elur/next-2/scheduler.d.ts +23 -0
  106. package/dist/lib/elur/next-2/scheduler.js +26 -0
  107. package/dist/lib/elur/next-2/scheduler.js.map +1 -0
  108. package/dist/lib/elur/plugins.cjs +1 -1
  109. package/dist/lib/elur/plugins.cjs.map +1 -1
  110. package/dist/lib/elur/plugins.js +1 -1
  111. package/dist/lib/elur/reactivity.cjs +1 -2
  112. package/dist/lib/elur/reactivity.d.cts +1 -67
  113. package/dist/lib/elur/reactivity.d.ts +1 -67
  114. package/dist/lib/elur/reactivity.js +2 -218
  115. package/dist/lib/elur/router.cjs +2 -2
  116. package/dist/lib/elur/router.cjs.map +1 -1
  117. package/dist/lib/elur/router.js +2 -2
  118. package/dist/lib/elur/router.js.map +1 -1
  119. package/dist/lib/elur/server/index.cjs +1 -1
  120. package/dist/lib/elur/server/index.cjs.map +1 -1
  121. package/dist/lib/elur/server/index.js +180 -108
  122. package/dist/lib/elur/server/index.js.map +1 -1
  123. package/dist/lib/elur/store.cjs +1 -1
  124. package/dist/lib/elur/store.cjs.map +1 -1
  125. package/dist/lib/elur/store.js +10 -4
  126. package/dist/lib/elur/store.js.map +1 -1
  127. package/dist/lib/elur/template/bindings.cjs +1 -1
  128. package/dist/lib/elur/template/bindings.cjs.map +1 -1
  129. package/dist/lib/elur/template/bindings.js +98 -84
  130. package/dist/lib/elur/template/bindings.js.map +1 -1
  131. package/dist/lib/elur/template/dom-write.d.cts +1 -5
  132. package/dist/lib/elur/template/dom-write.d.ts +1 -5
  133. package/dist/lib/elur/template/error-boundary.cjs +1 -1
  134. package/dist/lib/elur/template/error-boundary.cjs.map +1 -1
  135. package/dist/lib/elur/template/error-boundary.js +56 -50
  136. package/dist/lib/elur/template/error-boundary.js.map +1 -1
  137. package/dist/lib/elur/template/html.cjs +1 -1
  138. package/dist/lib/elur/template/html.cjs.map +1 -1
  139. package/dist/lib/elur/template/html.js +40 -37
  140. package/dist/lib/elur/template/html.js.map +1 -1
  141. package/dist/lib/elur/template/index.cjs +1 -1
  142. package/dist/lib/elur/template/index.d.cts +2 -1
  143. package/dist/lib/elur/template/index.d.ts +2 -1
  144. package/dist/lib/elur/template/index.js +13 -12
  145. package/dist/lib/elur/template/keyed-diff.d.cts +1 -32
  146. package/dist/lib/elur/template/keyed-diff.d.ts +1 -32
  147. package/dist/lib/elur/template/keyed.cjs +1 -1
  148. package/dist/lib/elur/template/keyed.cjs.map +1 -1
  149. package/dist/lib/elur/template/keyed.d.cts +10 -2
  150. package/dist/lib/elur/template/keyed.d.ts +10 -2
  151. package/dist/lib/elur/template/keyed.js +12 -1
  152. package/dist/lib/elur/template/keyed.js.map +1 -1
  153. package/dist/lib/elur/template/mount-helpers.d.cts +1 -29
  154. package/dist/lib/elur/template/mount-helpers.d.ts +1 -29
  155. package/dist/lib/elur/template/node-binding.d.cts +1 -6
  156. package/dist/lib/elur/template/node-binding.d.ts +1 -6
  157. package/dist/lib/elur/template/portal.cjs +1 -1
  158. package/dist/lib/elur/template/portal.cjs.map +1 -1
  159. package/dist/lib/elur/template/portal.js +1 -1
  160. package/dist/lib/elur/template/transitions.cjs +1 -1
  161. package/dist/lib/elur/template/transitions.cjs.map +1 -1
  162. package/dist/lib/elur/template/transitions.js +2 -2
  163. package/dist/lib/elur/template/types.cjs +1 -1
  164. package/dist/lib/elur/template/types.cjs.map +1 -1
  165. package/dist/lib/elur/template/types.d.cts +55 -0
  166. package/dist/lib/elur/template/types.d.ts +55 -0
  167. package/dist/lib/elur/template/types.js +5 -1
  168. package/dist/lib/elur/template/types.js.map +1 -1
  169. package/dist/lib/elur.cjs +1 -1
  170. package/dist/lib/elur.js +2 -2
  171. package/dist/lib/form.cjs +1 -1
  172. package/dist/lib/form.js +1 -1
  173. package/dist/lib/hydrate.cjs +1 -2
  174. package/dist/lib/hydrate.js +2 -410
  175. package/dist/lib/index.cjs +1 -1
  176. package/dist/lib/index.js +2 -2
  177. package/dist/lib/lifecycle.cjs +1 -1
  178. package/dist/lib/lifecycle.js +4 -0
  179. package/dist/lib/plugins.cjs +1 -1
  180. package/dist/lib/plugins.js +1 -1
  181. package/dist/lib/router.cjs +2 -2
  182. package/dist/lib/router.js +2 -2
  183. package/dist/lib/server.cjs +1 -1
  184. package/dist/lib/server.js +180 -108
  185. package/dist/lib/signals.cjs +1 -2
  186. package/dist/lib/signals.js +2 -218
  187. package/dist/lib/store.cjs +1 -1
  188. package/dist/lib/store.js +10 -4
  189. package/dist/lib/template.cjs +1 -1
  190. package/dist/lib/template.js +13 -12
  191. package/package.json +7 -9
  192. package/dist/lib/elur/component.cjs.map +0 -1
  193. package/dist/lib/elur/component.js.map +0 -1
  194. package/dist/lib/elur/hydrate/index.cjs.map +0 -1
  195. package/dist/lib/elur/hydrate/index.js.map +0 -1
  196. package/dist/lib/elur/reactivity.cjs.map +0 -1
  197. package/dist/lib/elur/reactivity.js.map +0 -1
  198. package/dist/lib/elur/template/dom-write.cjs +0 -2
  199. package/dist/lib/elur/template/dom-write.cjs.map +0 -1
  200. package/dist/lib/elur/template/dom-write.js +0 -16
  201. package/dist/lib/elur/template/dom-write.js.map +0 -1
  202. package/dist/lib/elur/template/keyed-diff.cjs +0 -2
  203. package/dist/lib/elur/template/keyed-diff.cjs.map +0 -1
  204. package/dist/lib/elur/template/keyed-diff.js +0 -100
  205. package/dist/lib/elur/template/keyed-diff.js.map +0 -1
  206. package/dist/lib/elur/template/mount-helpers.cjs +0 -2
  207. package/dist/lib/elur/template/mount-helpers.cjs.map +0 -1
  208. package/dist/lib/elur/template/mount-helpers.js +0 -132
  209. package/dist/lib/elur/template/mount-helpers.js.map +0 -1
  210. package/dist/lib/elur/template/node-binding.cjs +0 -2
  211. package/dist/lib/elur/template/node-binding.cjs.map +0 -1
  212. package/dist/lib/elur/template/node-binding.js +0 -95
  213. package/dist/lib/elur/template/node-binding.js.map +0 -1
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Elur "next" — kernel unificado de componentes (experimental).
3
+ *
4
+ * Implementa A.6–A.9 del PLAN_TECNICO_ELUR_NEXT sobre el ownership de
5
+ * `./reactivity.ts`:
6
+ * - Una sola `ComponentInstance` para clases y funciones (adaptadores).
7
+ * - Máquina de estados (A.7): created → initializing → rendering →
8
+ * pending-mount → mounted → disposing → disposed (o failed).
9
+ * - Mount transaccional (A.9): cualquier fallo dispara rollback —
10
+ * cleanups registrados, owner reactivo disposed, DOM insertado removido.
11
+ * - `unmount()` idempotente (A.2.10).
12
+ * - `onMount` corre DESPUÉS del commit DOM (A.2.9).
13
+ * - Todo lo creado en setup/render pertenece al owner de la instancia y
14
+ * muere con unmount (A.2.1 — no más effects huérfanos).
15
+ *
16
+ * Las invocaciones implementan `ELUR_RENDER_PROTOCOL.mountDom`, así el
17
+ * renderer existente las monta sin saber que son componentes.
18
+ */
19
+ import { Owner, Signal, type Disposable, type OwnerLike } from "./reactivity.js";
20
+ import { type ElurComponent, type ComponentController } from "../lifecycle.js";
21
+ import { ELUR_RENDER_PROTOCOL, type DomProtocolContext } from "../template/types.js";
22
+ export type ComponentState = "created" | "initializing" | "rendering" | "pending-mount" | "mounted" | "deactivated" | "disposing" | "disposed" | "failed";
23
+ /** Fase del lifecycle donde ocurrió el error. */
24
+ export type ErrorPhase = "setup" | "init" | "render" | "hydrate" | "mount" | "effect" | "activate" | "deactivate" | "cleanup" | "unmount";
25
+ /** Información estructurada del error (A.16). */
26
+ export interface ComponentErrorInfo {
27
+ phase: ErrorPhase;
28
+ /** Instancia donde ocurrió el error (no la boundary que lo maneja). */
29
+ component: ComponentInstance;
30
+ cause: unknown;
31
+ }
32
+ /** Resolución de una boundary (A.16). */
33
+ export type ErrorResolution = {
34
+ handled: false;
35
+ } | {
36
+ handled: true;
37
+ fallback?: Renderable;
38
+ } | {
39
+ handled: true;
40
+ retry: true;
41
+ };
42
+ export interface ComponentHooks {
43
+ /** Tras el commit DOM. Puede devolver cleanup (corre en unmount). */
44
+ onMount?: () => (() => void) | void;
45
+ /** Antes de remover el DOM. */
46
+ onUnmount?: () => void;
47
+ /**
48
+ * Boundary de errores (A.16): recibe info estructurada; el error burbujea
49
+ * por la cadena de instancias hasta una boundary que devuelva handled.
50
+ * `void` = manejado sin más.
51
+ */
52
+ onError?: (info: ComponentErrorInfo) => ErrorResolution | void;
53
+ /** A.17: tras setup durante SSR — nunca en cliente. */
54
+ onServerRender?: () => void;
55
+ }
56
+ /** Contexto que recibe el setup de un componente funcional. */
57
+ export interface SetupCtx {
58
+ onMount(fn: () => (() => void) | void): void;
59
+ onUnmount(fn: () => void): void;
60
+ onError(fn: (info: ComponentErrorInfo) => ErrorResolution | void): void;
61
+ /** A.17: hook server-side — corre tras setup durante SSR, nunca en cliente. */
62
+ onServerRender(fn: () => void): void;
63
+ /** Owner de la instancia — para runWithOwner/getOwner manual. */
64
+ readonly owner: OwnerLike;
65
+ /** Señal interna de una prop (A.13) — para acceso reactivo explícito. */
66
+ propSignal<K extends string>(key: K): Signal<unknown> | undefined;
67
+ /**
68
+ * A.14: renderiza el contenido de un slot (lazy — corre el render del
69
+ * slot bajo el owner del padre que lo declaró). `"default"` por defecto.
70
+ */
71
+ slot(name?: string): unknown;
72
+ /** A.14: slots declarados en la invocación. */
73
+ readonly slots: Record<string, Slot> | undefined;
74
+ }
75
+ interface RenderableValue {
76
+ _render(parent: Node, before: Node | null): () => void;
77
+ }
78
+ /** Renderable común: cualquier cosa montable en un binding. */
79
+ export type Renderable = ElurComponent | ComponentInvocation<unknown> | Slot | {
80
+ _render(parent: Node, before: Node | null): () => void;
81
+ } | string | number | bigint | false | null | undefined | Renderable[];
82
+ /**
83
+ * Slot lazy y marcado (A.14): el contenido se renderiza bajo el owner del
84
+ * padre que LO DECLARÓ (contexto léxico), aunque se monte dentro del
85
+ * componente consumidor.
86
+ */
87
+ export interface Slot {
88
+ readonly __isElurSlot: true;
89
+ /** Owner capturado en el punto de declaración (contexto léxico). */
90
+ readonly owner: OwnerLike | null;
91
+ render(): unknown;
92
+ }
93
+ export declare function slot(render: () => unknown): Slot;
94
+ export declare function isElurSlot(v: unknown): v is Slot;
95
+ export declare class ComponentInstance implements Disposable {
96
+ readonly id: number;
97
+ readonly kind: "class" | "function";
98
+ state: ComponentState;
99
+ /** Owner reactivo de la instancia — todo lo creado dentro muere con él. */
100
+ readonly owner: Owner;
101
+ /** Instancia padre (owner activo cuando se creó esta instancia). */
102
+ parent: ComponentInstance | null;
103
+ hooks: ComponentHooks;
104
+ renderable: RenderableValue | null;
105
+ /** A.12: frame de provide/inject propio de la instancia — permanente. */
106
+ readonly context: Map<unknown, unknown>;
107
+ private _inst;
108
+ private _invocation;
109
+ private _renderCleanup;
110
+ private _mountCleanups;
111
+ /** A.13: señales internas por prop + objeto live pasado al setup. */
112
+ private _propSignals;
113
+ private _liveProps;
114
+ /** A.16: fase actual del lifecycle — para el ComponentErrorInfo. */
115
+ private _phase;
116
+ /** A.16: posición de montaje — para renderizar fallback de boundary. */
117
+ private _mountParent;
118
+ private _mountBefore;
119
+ /** A.3.8: nodos DOM de la instancia — para detach/attach. */
120
+ private _domNodes;
121
+ /** A.21: controllers de ciclo de vida (Lit-style). */
122
+ private _controllers;
123
+ constructor(source: ElurComponent | ComponentInvocation<any>);
124
+ /**
125
+ * Mount transaccional (A.9). Cualquier fase que falle → rollback completo:
126
+ * owner disposed, cleanups corridos, DOM insertado removido, state=failed.
127
+ *
128
+ * Opciones:
129
+ * - `ctxSnapshot`: contexto capturado en el punto de declaración
130
+ * (mounts dentro de effects dinámicos heredan provide/inject).
131
+ * - `deferOnMount`: recibe una función `fire()` que corre onMount; el
132
+ * caller decide cuándo invocarla (fragments aún no insertados).
133
+ */
134
+ mount(parent: Node, before: Node | null, opts?: {
135
+ ctxSnapshot?: Map<unknown, unknown>[];
136
+ deferOnMount?: (fire: () => void) => void;
137
+ /** Valores a proveer en el frame de contexto de la instancia (A.12). */
138
+ provides?: Iterable<readonly [unknown, unknown]>;
139
+ /**
140
+ * A.14: owner del declarante — para contenido de slots, el owner padre
141
+ * es el del padre que declaró el contenido, no el del punto de montaje.
142
+ */
143
+ declOwner?: OwnerLike | null;
144
+ }): void;
145
+ /** A.21: registra un controller — sus hooks corren bajo este owner. */
146
+ addController(c: ComponentController): void;
147
+ /**
148
+ * A.3.8: saca el DOM de la instancia SIN disponer nada — effects, signals
149
+ * y contexto siguen vivos (página cached, Suspense, transición). No-op si
150
+ * no está montado.
151
+ */
152
+ detach(): void;
153
+ /**
154
+ * A.3.8: reinserta el DOM de una instancia detached en la posición original
155
+ * (o en parent/before dados). No-op si no está deactivated.
156
+ */
157
+ attach(parent?: Node, before?: Node | null): void;
158
+ /** Idempotente (A.2.10): disponer dos veces es seguro. */
159
+ unmount(): void;
160
+ dispose(): void;
161
+ /** @internal — corre onMount una vez; no-op si ya no está montado. */
162
+ _runOnMount(): void;
163
+ /**
164
+ * @internal A.16: intenta manejar el error con el boundary propio.
165
+ * `null` = este nodo no tiene boundary — seguir subiendo.
166
+ */
167
+ _handleError(info: ComponentErrorInfo): ErrorResolution | null;
168
+ /** A.16: errores de teardown — se reportan a la cadena; si nadie los maneja quedan registrados. */
169
+ private _reportSwallowed;
170
+ /** A.16: renderiza el fallback de una boundary en la posición del componente. */
171
+ private _renderFallback;
172
+ /** Camina la cadena de owners hasta la instancia registrada más cercana. */
173
+ private _resolveParent;
174
+ private _rollback;
175
+ private _makeSetupCtx;
176
+ /** Fases initializing+rendering: setup/onInit + render → this.renderable. */
177
+ private _initBody;
178
+ /** Corre `body` dentro del frame de contexto (snapshot o frame nuevo). */
179
+ private _withScope;
180
+ /**
181
+ * A.18 — hidratación: setup/onInit + render una sola vez, luego adopta el
182
+ * DOM SSR via ctx.render (que activa bindings dentro del owner de la
183
+ * instancia). En mismatch: rollback de la activación + remount por el mismo
184
+ * kernel REUSANDO el renderable — setup/onInit no se duplica.
185
+ */
186
+ _hydrate(ctx: {
187
+ parent: Node;
188
+ bounds: {
189
+ start: Comment;
190
+ end: Comment;
191
+ } | null;
192
+ render(value: unknown): unknown;
193
+ }): void;
194
+ /**
195
+ * A.17 — SSR: setup/onInit + onServerRender + serializar el renderable.
196
+ * NO corre onMount/onUnmount; el owner server-side se dispone al final
197
+ * (mata effects/computeds creados en setup).
198
+ */
199
+ _renderServer(sctx: {
200
+ markers?: boolean;
201
+ render(value: unknown, options?: {
202
+ markers?: boolean;
203
+ }): string | Promise<string>;
204
+ }): Promise<string>;
205
+ /**
206
+ * A.13 — crea el objeto LiveProps: propiedades readonly respaldadas por
207
+ * signals. OJO: destructurar props en setup crea snapshots no reactivos.
208
+ */
209
+ private _initProps;
210
+ /**
211
+ * A.13/A.15 — true si `inv` es la misma definición con la misma key:
212
+ * entonces el runtime debe actualizar props, no recrear el setup.
213
+ */
214
+ matches(inv: ComponentInvocation<any>): boolean;
215
+ /**
216
+ * A.13 — actualiza props sin recrear setup: escribe cada signal de prop.
217
+ * Props nuevas se añaden; props desaparecidas quedan en undefined.
218
+ */
219
+ updateProps(props: unknown): void;
220
+ }
221
+ /**
222
+ * A.16: burbujeo de errores por la cadena de instancias (padres reales del
223
+ * árbol de componentes). Devuelve la primera resolución manejada; si nadie
224
+ * maneja el error, `{ handled: false }` y el caller decide (re-lanzar o
225
+ * registrar).
226
+ */
227
+ export declare function reportError(from: ComponentInstance, info: ComponentErrorInfo): ErrorResolution;
228
+ /** Envuelve un ElurComponent de clase en el kernel unificado. */
229
+ export declare function adaptClassComponent(inst: ElurComponent): ComponentInstance;
230
+ export interface ComponentDefinition<P> {
231
+ (props?: P, slots?: Record<string, Slot>): ComponentInvocation<P>;
232
+ readonly setup: (props: P | undefined, ctx: SetupCtx) => unknown;
233
+ readonly _isComponentDefinition: true;
234
+ }
235
+ /** Invocación marcada: `Counter({ initial: 10 })` NO ejecuta setup — monta después. */
236
+ export declare class ComponentInvocation<P> {
237
+ readonly [ELUR_RENDER_PROTOCOL]: {
238
+ mountDom: (ctx: DomProtocolContext) => (() => void);
239
+ renderServer: (sctx: {
240
+ markers?: boolean;
241
+ render(value: unknown, options?: {
242
+ markers?: boolean;
243
+ }): string | Promise<string>;
244
+ }) => Promise<string>;
245
+ hydrateDom: (ctx: {
246
+ parent: Node;
247
+ bounds: {
248
+ start: Comment;
249
+ end: Comment;
250
+ } | null;
251
+ render(value: unknown): unknown;
252
+ }) => (() => void);
253
+ };
254
+ readonly definition: ComponentDefinition<P>;
255
+ readonly props: P | undefined;
256
+ /** A.14: slots declarados en la llamada — `Card(props, { default: slot(...) })`. */
257
+ readonly slots: Record<string, Slot> | undefined;
258
+ constructor(definition: ComponentDefinition<P>, props: P | undefined, slots?: Record<string, Slot>);
259
+ }
260
+ export declare function isComponentInvocation(v: unknown): v is ComponentInvocation<any>;
261
+ /**
262
+ * @internal — registra un frame de contexto para un owner raíz (mount de
263
+ * template con router, roots de app, etc).
264
+ */
265
+ export declare function _registerContextOwner(owner: OwnerLike, context: Map<unknown, unknown>): void;
266
+ /**
267
+ * Define un componente funcional de primera clase (A.5):
268
+ * `Counter(props)` retorna una invocación marcada; el runtime ejecuta el
269
+ * setup cuando monta la invocación.
270
+ */
271
+ export declare function defineComponent<P = Record<string, never>>(setup: (props: P | undefined, ctx: SetupCtx) => unknown): ComponentDefinition<P>;
272
+ /**
273
+ * Monta un componente (clase o invocación funcional) en `container` y
274
+ * devuelve el handle con `unmount()`. Todo el árbol reactivo muere con el
275
+ * unmount — sin fugas de effects/computeds.
276
+ */
277
+ export declare function mountComponent(value: ElurComponent | ComponentInvocation<any>, container: Element): {
278
+ unmount(): void;
279
+ instance: ComponentInstance;
280
+ };
281
+ export {};
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Elur "next" — kernel unificado de componentes (experimental).
3
+ *
4
+ * Implementa A.6–A.9 del PLAN_TECNICO_ELUR_NEXT sobre el ownership de
5
+ * `./reactivity.ts`:
6
+ * - Una sola `ComponentInstance` para clases y funciones (adaptadores).
7
+ * - Máquina de estados (A.7): created → initializing → rendering →
8
+ * pending-mount → mounted → disposing → disposed (o failed).
9
+ * - Mount transaccional (A.9): cualquier fallo dispara rollback —
10
+ * cleanups registrados, owner reactivo disposed, DOM insertado removido.
11
+ * - `unmount()` idempotente (A.2.10).
12
+ * - `onMount` corre DESPUÉS del commit DOM (A.2.9).
13
+ * - Todo lo creado en setup/render pertenece al owner de la instancia y
14
+ * muere con unmount (A.2.1 — no más effects huérfanos).
15
+ *
16
+ * Las invocaciones implementan `ELUR_RENDER_PROTOCOL.mountDom`, así el
17
+ * renderer existente las monta sin saber que son componentes.
18
+ */
19
+ import { Owner, Signal, type Disposable, type OwnerLike } from "./reactivity.js";
20
+ import { type ElurComponent, type ComponentController } from "../lifecycle.js";
21
+ import { ELUR_RENDER_PROTOCOL, type DomProtocolContext } from "../template/types.js";
22
+ export type ComponentState = "created" | "initializing" | "rendering" | "pending-mount" | "mounted" | "deactivated" | "disposing" | "disposed" | "failed";
23
+ /** Fase del lifecycle donde ocurrió el error. */
24
+ export type ErrorPhase = "setup" | "init" | "render" | "hydrate" | "mount" | "effect" | "activate" | "deactivate" | "cleanup" | "unmount";
25
+ /** Información estructurada del error (A.16). */
26
+ export interface ComponentErrorInfo {
27
+ phase: ErrorPhase;
28
+ /** Instancia donde ocurrió el error (no la boundary que lo maneja). */
29
+ component: ComponentInstance;
30
+ cause: unknown;
31
+ }
32
+ /** Resolución de una boundary (A.16). */
33
+ export type ErrorResolution = {
34
+ handled: false;
35
+ } | {
36
+ handled: true;
37
+ fallback?: Renderable;
38
+ } | {
39
+ handled: true;
40
+ retry: true;
41
+ };
42
+ export interface ComponentHooks {
43
+ /** Tras el commit DOM. Puede devolver cleanup (corre en unmount). */
44
+ onMount?: () => (() => void) | void;
45
+ /** Antes de remover el DOM. */
46
+ onUnmount?: () => void;
47
+ /**
48
+ * Boundary de errores (A.16): recibe info estructurada; el error burbujea
49
+ * por la cadena de instancias hasta una boundary que devuelva handled.
50
+ * `void` = manejado sin más.
51
+ */
52
+ onError?: (info: ComponentErrorInfo) => ErrorResolution | void;
53
+ /** A.17: tras setup durante SSR — nunca en cliente. */
54
+ onServerRender?: () => void;
55
+ }
56
+ /** Contexto que recibe el setup de un componente funcional. */
57
+ export interface SetupCtx {
58
+ onMount(fn: () => (() => void) | void): void;
59
+ onUnmount(fn: () => void): void;
60
+ onError(fn: (info: ComponentErrorInfo) => ErrorResolution | void): void;
61
+ /** A.17: hook server-side — corre tras setup durante SSR, nunca en cliente. */
62
+ onServerRender(fn: () => void): void;
63
+ /** Owner de la instancia — para runWithOwner/getOwner manual. */
64
+ readonly owner: OwnerLike;
65
+ /** Señal interna de una prop (A.13) — para acceso reactivo explícito. */
66
+ propSignal<K extends string>(key: K): Signal<unknown> | undefined;
67
+ /**
68
+ * A.14: renderiza el contenido de un slot (lazy — corre el render del
69
+ * slot bajo el owner del padre que lo declaró). `"default"` por defecto.
70
+ */
71
+ slot(name?: string): unknown;
72
+ /** A.14: slots declarados en la invocación. */
73
+ readonly slots: Record<string, Slot> | undefined;
74
+ }
75
+ interface RenderableValue {
76
+ _render(parent: Node, before: Node | null): () => void;
77
+ }
78
+ /** Renderable común: cualquier cosa montable en un binding. */
79
+ export type Renderable = ElurComponent | ComponentInvocation<unknown> | Slot | {
80
+ _render(parent: Node, before: Node | null): () => void;
81
+ } | string | number | bigint | false | null | undefined | Renderable[];
82
+ /**
83
+ * Slot lazy y marcado (A.14): el contenido se renderiza bajo el owner del
84
+ * padre que LO DECLARÓ (contexto léxico), aunque se monte dentro del
85
+ * componente consumidor.
86
+ */
87
+ export interface Slot {
88
+ readonly __isElurSlot: true;
89
+ /** Owner capturado en el punto de declaración (contexto léxico). */
90
+ readonly owner: OwnerLike | null;
91
+ render(): unknown;
92
+ }
93
+ export declare function slot(render: () => unknown): Slot;
94
+ export declare function isElurSlot(v: unknown): v is Slot;
95
+ export declare class ComponentInstance implements Disposable {
96
+ readonly id: number;
97
+ readonly kind: "class" | "function";
98
+ state: ComponentState;
99
+ /** Owner reactivo de la instancia — todo lo creado dentro muere con él. */
100
+ readonly owner: Owner;
101
+ /** Instancia padre (owner activo cuando se creó esta instancia). */
102
+ parent: ComponentInstance | null;
103
+ hooks: ComponentHooks;
104
+ renderable: RenderableValue | null;
105
+ /** A.12: frame de provide/inject propio de la instancia — permanente. */
106
+ readonly context: Map<unknown, unknown>;
107
+ private _inst;
108
+ private _invocation;
109
+ private _renderCleanup;
110
+ private _mountCleanups;
111
+ /** A.13: señales internas por prop + objeto live pasado al setup. */
112
+ private _propSignals;
113
+ private _liveProps;
114
+ /** A.16: fase actual del lifecycle — para el ComponentErrorInfo. */
115
+ private _phase;
116
+ /** A.16: posición de montaje — para renderizar fallback de boundary. */
117
+ private _mountParent;
118
+ private _mountBefore;
119
+ /** A.3.8: nodos DOM de la instancia — para detach/attach. */
120
+ private _domNodes;
121
+ /** A.21: controllers de ciclo de vida (Lit-style). */
122
+ private _controllers;
123
+ constructor(source: ElurComponent | ComponentInvocation<any>);
124
+ /**
125
+ * Mount transaccional (A.9). Cualquier fase que falle → rollback completo:
126
+ * owner disposed, cleanups corridos, DOM insertado removido, state=failed.
127
+ *
128
+ * Opciones:
129
+ * - `ctxSnapshot`: contexto capturado en el punto de declaración
130
+ * (mounts dentro de effects dinámicos heredan provide/inject).
131
+ * - `deferOnMount`: recibe una función `fire()` que corre onMount; el
132
+ * caller decide cuándo invocarla (fragments aún no insertados).
133
+ */
134
+ mount(parent: Node, before: Node | null, opts?: {
135
+ ctxSnapshot?: Map<unknown, unknown>[];
136
+ deferOnMount?: (fire: () => void) => void;
137
+ /** Valores a proveer en el frame de contexto de la instancia (A.12). */
138
+ provides?: Iterable<readonly [unknown, unknown]>;
139
+ /**
140
+ * A.14: owner del declarante — para contenido de slots, el owner padre
141
+ * es el del padre que declaró el contenido, no el del punto de montaje.
142
+ */
143
+ declOwner?: OwnerLike | null;
144
+ }): void;
145
+ /** A.21: registra un controller — sus hooks corren bajo este owner. */
146
+ addController(c: ComponentController): void;
147
+ /**
148
+ * A.3.8: saca el DOM de la instancia SIN disponer nada — effects, signals
149
+ * y contexto siguen vivos (página cached, Suspense, transición). No-op si
150
+ * no está montado.
151
+ */
152
+ detach(): void;
153
+ /**
154
+ * A.3.8: reinserta el DOM de una instancia detached en la posición original
155
+ * (o en parent/before dados). No-op si no está deactivated.
156
+ */
157
+ attach(parent?: Node, before?: Node | null): void;
158
+ /** Idempotente (A.2.10): disponer dos veces es seguro. */
159
+ unmount(): void;
160
+ dispose(): void;
161
+ /** @internal — corre onMount una vez; no-op si ya no está montado. */
162
+ _runOnMount(): void;
163
+ /**
164
+ * @internal A.16: intenta manejar el error con el boundary propio.
165
+ * `null` = este nodo no tiene boundary — seguir subiendo.
166
+ */
167
+ _handleError(info: ComponentErrorInfo): ErrorResolution | null;
168
+ /** A.16: errores de teardown — se reportan a la cadena; si nadie los maneja quedan registrados. */
169
+ private _reportSwallowed;
170
+ /** A.16: renderiza el fallback de una boundary en la posición del componente. */
171
+ private _renderFallback;
172
+ /** Camina la cadena de owners hasta la instancia registrada más cercana. */
173
+ private _resolveParent;
174
+ private _rollback;
175
+ private _makeSetupCtx;
176
+ /** Fases initializing+rendering: setup/onInit + render → this.renderable. */
177
+ private _initBody;
178
+ /** Corre `body` dentro del frame de contexto (snapshot o frame nuevo). */
179
+ private _withScope;
180
+ /**
181
+ * A.18 — hidratación: setup/onInit + render una sola vez, luego adopta el
182
+ * DOM SSR via ctx.render (que activa bindings dentro del owner de la
183
+ * instancia). En mismatch: rollback de la activación + remount por el mismo
184
+ * kernel REUSANDO el renderable — setup/onInit no se duplica.
185
+ */
186
+ _hydrate(ctx: {
187
+ parent: Node;
188
+ bounds: {
189
+ start: Comment;
190
+ end: Comment;
191
+ } | null;
192
+ render(value: unknown): unknown;
193
+ }): void;
194
+ /**
195
+ * A.17 — SSR: setup/onInit + onServerRender + serializar el renderable.
196
+ * NO corre onMount/onUnmount; el owner server-side se dispone al final
197
+ * (mata effects/computeds creados en setup).
198
+ */
199
+ _renderServer(sctx: {
200
+ markers?: boolean;
201
+ render(value: unknown, options?: {
202
+ markers?: boolean;
203
+ }): string | Promise<string>;
204
+ }): Promise<string>;
205
+ /**
206
+ * A.13 — crea el objeto LiveProps: propiedades readonly respaldadas por
207
+ * signals. OJO: destructurar props en setup crea snapshots no reactivos.
208
+ */
209
+ private _initProps;
210
+ /**
211
+ * A.13/A.15 — true si `inv` es la misma definición con la misma key:
212
+ * entonces el runtime debe actualizar props, no recrear el setup.
213
+ */
214
+ matches(inv: ComponentInvocation<any>): boolean;
215
+ /**
216
+ * A.13 — actualiza props sin recrear setup: escribe cada signal de prop.
217
+ * Props nuevas se añaden; props desaparecidas quedan en undefined.
218
+ */
219
+ updateProps(props: unknown): void;
220
+ }
221
+ /**
222
+ * A.16: burbujeo de errores por la cadena de instancias (padres reales del
223
+ * árbol de componentes). Devuelve la primera resolución manejada; si nadie
224
+ * maneja el error, `{ handled: false }` y el caller decide (re-lanzar o
225
+ * registrar).
226
+ */
227
+ export declare function reportError(from: ComponentInstance, info: ComponentErrorInfo): ErrorResolution;
228
+ /** Envuelve un ElurComponent de clase en el kernel unificado. */
229
+ export declare function adaptClassComponent(inst: ElurComponent): ComponentInstance;
230
+ export interface ComponentDefinition<P> {
231
+ (props?: P, slots?: Record<string, Slot>): ComponentInvocation<P>;
232
+ readonly setup: (props: P | undefined, ctx: SetupCtx) => unknown;
233
+ readonly _isComponentDefinition: true;
234
+ }
235
+ /** Invocación marcada: `Counter({ initial: 10 })` NO ejecuta setup — monta después. */
236
+ export declare class ComponentInvocation<P> {
237
+ readonly [ELUR_RENDER_PROTOCOL]: {
238
+ mountDom: (ctx: DomProtocolContext) => (() => void);
239
+ renderServer: (sctx: {
240
+ markers?: boolean;
241
+ render(value: unknown, options?: {
242
+ markers?: boolean;
243
+ }): string | Promise<string>;
244
+ }) => Promise<string>;
245
+ hydrateDom: (ctx: {
246
+ parent: Node;
247
+ bounds: {
248
+ start: Comment;
249
+ end: Comment;
250
+ } | null;
251
+ render(value: unknown): unknown;
252
+ }) => (() => void);
253
+ };
254
+ readonly definition: ComponentDefinition<P>;
255
+ readonly props: P | undefined;
256
+ /** A.14: slots declarados en la llamada — `Card(props, { default: slot(...) })`. */
257
+ readonly slots: Record<string, Slot> | undefined;
258
+ constructor(definition: ComponentDefinition<P>, props: P | undefined, slots?: Record<string, Slot>);
259
+ }
260
+ export declare function isComponentInvocation(v: unknown): v is ComponentInvocation<any>;
261
+ /**
262
+ * @internal — registra un frame de contexto para un owner raíz (mount de
263
+ * template con router, roots de app, etc).
264
+ */
265
+ export declare function _registerContextOwner(owner: OwnerLike, context: Map<unknown, unknown>): void;
266
+ /**
267
+ * Define un componente funcional de primera clase (A.5):
268
+ * `Counter(props)` retorna una invocación marcada; el runtime ejecuta el
269
+ * setup cuando monta la invocación.
270
+ */
271
+ export declare function defineComponent<P = Record<string, never>>(setup: (props: P | undefined, ctx: SetupCtx) => unknown): ComponentDefinition<P>;
272
+ /**
273
+ * Monta un componente (clase o invocación funcional) en `container` y
274
+ * devuelve el handle con `unmount()`. Todo el árbol reactivo muere con el
275
+ * unmount — sin fugas de effects/computeds.
276
+ */
277
+ export declare function mountComponent(value: ElurComponent | ComponentInvocation<any>, container: Element): {
278
+ unmount(): void;
279
+ instance: ComponentInstance;
280
+ };
281
+ export {};
@@ -0,0 +1,18 @@
1
+ export type DomWriteKind = "text" | "attr" | "prop" | "class" | "style" | "custom";
2
+ export interface DomWrite {
3
+ /** Identidad del binding — dos writes con el mismo id colapsan (último gana). */
4
+ id: unknown;
5
+ kind: DomWriteKind;
6
+ write: () => void;
7
+ }
8
+ /**
9
+ * Cola tipada: `id` identifica el binding. Si el mismo binding escribe varias
10
+ * veces antes del flush, sólo corre la última escritura — Map.set reemplaza el
11
+ * valor conservando la posición de inserción.
12
+ */
13
+ export declare function queueDomWrite(id: unknown, kind: DomWriteKind, write: () => void): void;
14
+ /**
15
+ * Compat con la API actual: deduplica por identidad del closure
16
+ * (comportamiento idéntico a la impl estable).
17
+ */
18
+ export declare function queueDOMWrite(task: () => void): void;
@@ -0,0 +1,18 @@
1
+ export type DomWriteKind = "text" | "attr" | "prop" | "class" | "style" | "custom";
2
+ export interface DomWrite {
3
+ /** Identidad del binding — dos writes con el mismo id colapsan (último gana). */
4
+ id: unknown;
5
+ kind: DomWriteKind;
6
+ write: () => void;
7
+ }
8
+ /**
9
+ * Cola tipada: `id` identifica el binding. Si el mismo binding escribe varias
10
+ * veces antes del flush, sólo corre la última escritura — Map.set reemplaza el
11
+ * valor conservando la posición de inserción.
12
+ */
13
+ export declare function queueDomWrite(id: unknown, kind: DomWriteKind, write: () => void): void;
14
+ /**
15
+ * Compat con la API actual: deduplica por identidad del closure
16
+ * (comportamiento idéntico a la impl estable).
17
+ */
18
+ export declare function queueDOMWrite(task: () => void): void;
@@ -0,0 +1,14 @@
1
+ import { type ElurComponent } from "../lifecycle.js";
2
+ import { type ComponentInvocation } from "./component.js";
3
+ import { type ElurMountHandle, type ElurTemplate } from "../template/types.js";
4
+ export interface HydrateOptions {
5
+ mismatch?: "throw" | "warn-remount" | "remount";
6
+ onMismatch?: (error: HydrationMismatch) => void;
7
+ context?: unknown;
8
+ }
9
+ export interface HydrationMismatch {
10
+ index: number;
11
+ kind: "node" | "attribute" | "event" | "descriptor" | "keyed";
12
+ message: string;
13
+ }
14
+ export declare function hydrate(value: ElurTemplate | ElurComponent | ComponentInvocation<any>, container: Element, options?: HydrateOptions): ElurMountHandle;
@@ -0,0 +1,14 @@
1
+ import { type ElurComponent } from "../lifecycle.js";
2
+ import { type ComponentInvocation } from "./component.js";
3
+ import { type ElurMountHandle, type ElurTemplate } from "../template/types.js";
4
+ export interface HydrateOptions {
5
+ mismatch?: "throw" | "warn-remount" | "remount";
6
+ onMismatch?: (error: HydrationMismatch) => void;
7
+ context?: unknown;
8
+ }
9
+ export interface HydrationMismatch {
10
+ index: number;
11
+ kind: "node" | "attribute" | "event" | "descriptor" | "keyed";
12
+ message: string;
13
+ }
14
+ export declare function hydrate(value: ElurTemplate | ElurComponent | ComponentInvocation<any>, container: Element, options?: HydrateOptions): ElurMountHandle;
@@ -0,0 +1,46 @@
1
+ import { type KEntry, type KeyedList } from "../template/types.js";
2
+ import { type RepeatKey } from "../template/keyed.js";
3
+ /**
4
+ * C.16.1: lista keyed "live" — renderItem recibe accessors (`getItem`,
5
+ * `getIndex`) en vez del item capturado. Misma key + objeto nuevo → las
6
+ * señales del item se actualizan y los bindings re-corren sin remount,
7
+ * preservando identidad de DOM y estado del item.
8
+ */
9
+ export interface LiveKeyedList<T = unknown> {
10
+ readonly __isKeyedList: true;
11
+ readonly live: true;
12
+ readonly items: T[];
13
+ readonly keyFn: (item: T, index: number) => string | number;
14
+ readonly renderItem: (getItem: () => T, getIndex: () => number) => unknown;
15
+ }
16
+ export declare function repeatLive<T>(items: T[], keyFn: (item: T, index: number) => string | number, renderItem: (getItem: () => T, getIndex: () => number) => unknown): LiveKeyedList<T>;
17
+ /**
18
+ * Mounts a single keyed item's rendered value before `endMarker` inside `parent`.
19
+ * Used by the DOM renderer and the hydration renderer so both engines share the
20
+ * exact same reconciliation semantics.
21
+ */
22
+ export declare function createKeyedMount(ctxSnapshot: Map<unknown, unknown>[]): (rendered: unknown, parent: Node, endMarker: Node) => () => void;
23
+ export interface KeyedDiffOptions {
24
+ /** Node marking the start of the keyed zone. */
25
+ zoneStart: Node;
26
+ /** End boundary; new content is inserted before this node. */
27
+ anchor: Node;
28
+ /** Live map of key → entry (start/end markers + cleanup). */
29
+ state: Map<RepeatKey, KEntry>;
30
+ /** Key order from the previous reconciliation pass. */
31
+ prevOrder: RepeatKey[];
32
+ /** The current keyed list value (clásica o live). */
33
+ list: KeyedList | LiveKeyedList;
34
+ /** Mounts a freshly rendered item into the DOM. */
35
+ mount: (rendered: unknown, parent: Node, endMarker: Node) => () => void;
36
+ /** Context snapshot for component mounts inside the effect. */
37
+ ctxSnapshot?: Map<unknown, unknown>[];
38
+ /** Called when a duplicate key is encountered. */
39
+ onDuplicateKey?: (key: RepeatKey) => void;
40
+ }
41
+ /**
42
+ * Reconciles a keyed list between `zoneStart` and `anchor` using the same LIS
43
+ * algorithm used by the DOM renderer. Total replacement (O(1)) when no key
44
+ * survives; otherwise remove/insert/move with minimal DOM operations.
45
+ */
46
+ export declare function reconcileKeyedList(opts: KeyedDiffOptions): void;