@elurjs/core 3.5.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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/dist/lib/async.cjs +16 -0
  4. package/dist/lib/async.js +123 -0
  5. package/dist/lib/component.cjs +2 -0
  6. package/dist/lib/component.js +66 -0
  7. package/dist/lib/context.cjs +2 -0
  8. package/dist/lib/context.js +52 -0
  9. package/dist/lib/devtools.cjs +59 -0
  10. package/dist/lib/devtools.js +419 -0
  11. package/dist/lib/elur/async.cjs +16 -0
  12. package/dist/lib/elur/async.cjs.map +1 -0
  13. package/dist/lib/elur/async.d.cts +32 -0
  14. package/dist/lib/elur/async.d.ts +32 -0
  15. package/dist/lib/elur/async.js +123 -0
  16. package/dist/lib/elur/async.js.map +1 -0
  17. package/dist/lib/elur/component.cjs +2 -0
  18. package/dist/lib/elur/component.cjs.map +1 -0
  19. package/dist/lib/elur/component.d.cts +17 -0
  20. package/dist/lib/elur/component.d.ts +17 -0
  21. package/dist/lib/elur/component.js +66 -0
  22. package/dist/lib/elur/component.js.map +1 -0
  23. package/dist/lib/elur/context.cjs +2 -0
  24. package/dist/lib/elur/context.cjs.map +1 -0
  25. package/dist/lib/elur/context.d.cts +29 -0
  26. package/dist/lib/elur/context.d.ts +29 -0
  27. package/dist/lib/elur/context.js +52 -0
  28. package/dist/lib/elur/context.js.map +1 -0
  29. package/dist/lib/elur/devtools.cjs +59 -0
  30. package/dist/lib/elur/devtools.cjs.map +1 -0
  31. package/dist/lib/elur/devtools.d.cts +24 -0
  32. package/dist/lib/elur/devtools.d.ts +24 -0
  33. package/dist/lib/elur/devtools.js +419 -0
  34. package/dist/lib/elur/devtools.js.map +1 -0
  35. package/dist/lib/elur/form.cjs +2 -0
  36. package/dist/lib/elur/form.cjs.map +1 -0
  37. package/dist/lib/elur/form.d.cts +283 -0
  38. package/dist/lib/elur/form.d.ts +283 -0
  39. package/dist/lib/elur/form.js +315 -0
  40. package/dist/lib/elur/form.js.map +1 -0
  41. package/dist/lib/elur/hydrate/index.cjs +2 -0
  42. package/dist/lib/elur/hydrate/index.cjs.map +1 -0
  43. package/dist/lib/elur/hydrate/index.d.cts +13 -0
  44. package/dist/lib/elur/hydrate/index.d.ts +13 -0
  45. package/dist/lib/elur/hydrate/index.js +410 -0
  46. package/dist/lib/elur/hydrate/index.js.map +1 -0
  47. package/dist/lib/elur/index.d.cts +19 -0
  48. package/dist/lib/elur/index.d.ts +19 -0
  49. package/dist/lib/elur/lifecycle.cjs +2 -0
  50. package/dist/lib/elur/lifecycle.cjs.map +1 -0
  51. package/dist/lib/elur/lifecycle.d.cts +45 -0
  52. package/dist/lib/elur/lifecycle.d.ts +45 -0
  53. package/dist/lib/elur/lifecycle.js +39 -0
  54. package/dist/lib/elur/lifecycle.js.map +1 -0
  55. package/dist/lib/elur/plugins.cjs +2 -0
  56. package/dist/lib/elur/plugins.cjs.map +1 -0
  57. package/dist/lib/elur/plugins.d.cts +48 -0
  58. package/dist/lib/elur/plugins.d.ts +48 -0
  59. package/dist/lib/elur/plugins.js +59 -0
  60. package/dist/lib/elur/plugins.js.map +1 -0
  61. package/dist/lib/elur/reactivity.cjs +2 -0
  62. package/dist/lib/elur/reactivity.cjs.map +1 -0
  63. package/dist/lib/elur/reactivity.d.cts +60 -0
  64. package/dist/lib/elur/reactivity.d.ts +60 -0
  65. package/dist/lib/elur/reactivity.js +188 -0
  66. package/dist/lib/elur/reactivity.js.map +1 -0
  67. package/dist/lib/elur/router.cjs +12 -0
  68. package/dist/lib/elur/router.cjs.map +1 -0
  69. package/dist/lib/elur/router.d.cts +137 -0
  70. package/dist/lib/elur/router.d.ts +137 -0
  71. package/dist/lib/elur/router.js +513 -0
  72. package/dist/lib/elur/router.js.map +1 -0
  73. package/dist/lib/elur/server/index.cjs +2 -0
  74. package/dist/lib/elur/server/index.cjs.map +1 -0
  75. package/dist/lib/elur/server/index.d.cts +44 -0
  76. package/dist/lib/elur/server/index.d.ts +44 -0
  77. package/dist/lib/elur/server/index.js +307 -0
  78. package/dist/lib/elur/server/index.js.map +1 -0
  79. package/dist/lib/elur/store.cjs +2 -0
  80. package/dist/lib/elur/store.cjs.map +1 -0
  81. package/dist/lib/elur/store.d.cts +137 -0
  82. package/dist/lib/elur/store.d.ts +137 -0
  83. package/dist/lib/elur/store.js +143 -0
  84. package/dist/lib/elur/store.js.map +1 -0
  85. package/dist/lib/elur/template/bindings.cjs +2 -0
  86. package/dist/lib/elur/template/bindings.cjs.map +1 -0
  87. package/dist/lib/elur/template/bindings.d.cts +40 -0
  88. package/dist/lib/elur/template/bindings.d.ts +40 -0
  89. package/dist/lib/elur/template/bindings.js +214 -0
  90. package/dist/lib/elur/template/bindings.js.map +1 -0
  91. package/dist/lib/elur/template/dom-write.cjs +2 -0
  92. package/dist/lib/elur/template/dom-write.cjs.map +1 -0
  93. package/dist/lib/elur/template/dom-write.d.cts +5 -0
  94. package/dist/lib/elur/template/dom-write.d.ts +5 -0
  95. package/dist/lib/elur/template/dom-write.js +16 -0
  96. package/dist/lib/elur/template/dom-write.js.map +1 -0
  97. package/dist/lib/elur/template/error-boundary.cjs +2 -0
  98. package/dist/lib/elur/template/error-boundary.cjs.map +1 -0
  99. package/dist/lib/elur/template/error-boundary.d.cts +7 -0
  100. package/dist/lib/elur/template/error-boundary.d.ts +7 -0
  101. package/dist/lib/elur/template/error-boundary.js +90 -0
  102. package/dist/lib/elur/template/error-boundary.js.map +1 -0
  103. package/dist/lib/elur/template/html.cjs +2 -0
  104. package/dist/lib/elur/template/html.cjs.map +1 -0
  105. package/dist/lib/elur/template/html.d.cts +8 -0
  106. package/dist/lib/elur/template/html.d.ts +8 -0
  107. package/dist/lib/elur/template/html.js +104 -0
  108. package/dist/lib/elur/template/html.js.map +1 -0
  109. package/dist/lib/elur/template/index.cjs +1 -0
  110. package/dist/lib/elur/template/index.d.cts +15 -0
  111. package/dist/lib/elur/template/index.d.ts +15 -0
  112. package/dist/lib/elur/template/index.js +13 -0
  113. package/dist/lib/elur/template/keyed-diff.cjs +2 -0
  114. package/dist/lib/elur/template/keyed-diff.cjs.map +1 -0
  115. package/dist/lib/elur/template/keyed-diff.d.cts +32 -0
  116. package/dist/lib/elur/template/keyed-diff.d.ts +32 -0
  117. package/dist/lib/elur/template/keyed-diff.js +100 -0
  118. package/dist/lib/elur/template/keyed-diff.js.map +1 -0
  119. package/dist/lib/elur/template/keyed.cjs +2 -0
  120. package/dist/lib/elur/template/keyed.cjs.map +1 -0
  121. package/dist/lib/elur/template/keyed.d.cts +27 -0
  122. package/dist/lib/elur/template/keyed.d.ts +27 -0
  123. package/dist/lib/elur/template/keyed.js +52 -0
  124. package/dist/lib/elur/template/keyed.js.map +1 -0
  125. package/dist/lib/elur/template/mount-helpers.cjs +2 -0
  126. package/dist/lib/elur/template/mount-helpers.cjs.map +1 -0
  127. package/dist/lib/elur/template/mount-helpers.d.cts +29 -0
  128. package/dist/lib/elur/template/mount-helpers.d.ts +29 -0
  129. package/dist/lib/elur/template/mount-helpers.js +132 -0
  130. package/dist/lib/elur/template/mount-helpers.js.map +1 -0
  131. package/dist/lib/elur/template/node-binding.cjs +2 -0
  132. package/dist/lib/elur/template/node-binding.cjs.map +1 -0
  133. package/dist/lib/elur/template/node-binding.d.cts +6 -0
  134. package/dist/lib/elur/template/node-binding.d.ts +6 -0
  135. package/dist/lib/elur/template/node-binding.js +95 -0
  136. package/dist/lib/elur/template/node-binding.js.map +1 -0
  137. package/dist/lib/elur/template/portal.cjs +2 -0
  138. package/dist/lib/elur/template/portal.cjs.map +1 -0
  139. package/dist/lib/elur/template/portal.d.cts +19 -0
  140. package/dist/lib/elur/template/portal.d.ts +19 -0
  141. package/dist/lib/elur/template/portal.js +49 -0
  142. package/dist/lib/elur/template/portal.js.map +1 -0
  143. package/dist/lib/elur/template/raw.cjs +2 -0
  144. package/dist/lib/elur/template/raw.cjs.map +1 -0
  145. package/dist/lib/elur/template/raw.d.cts +9 -0
  146. package/dist/lib/elur/template/raw.d.ts +9 -0
  147. package/dist/lib/elur/template/raw.js +29 -0
  148. package/dist/lib/elur/template/raw.js.map +1 -0
  149. package/dist/lib/elur/template/sanitize.cjs +2 -0
  150. package/dist/lib/elur/template/sanitize.cjs.map +1 -0
  151. package/dist/lib/elur/template/sanitize.d.cts +16 -0
  152. package/dist/lib/elur/template/sanitize.d.ts +16 -0
  153. package/dist/lib/elur/template/sanitize.js +29 -0
  154. package/dist/lib/elur/template/sanitize.js.map +1 -0
  155. package/dist/lib/elur/template/transitions.cjs +2 -0
  156. package/dist/lib/elur/template/transitions.cjs.map +1 -0
  157. package/dist/lib/elur/template/transitions.d.cts +43 -0
  158. package/dist/lib/elur/template/transitions.d.ts +43 -0
  159. package/dist/lib/elur/template/transitions.js +96 -0
  160. package/dist/lib/elur/template/transitions.js.map +1 -0
  161. package/dist/lib/elur/template/types.cjs +2 -0
  162. package/dist/lib/elur/template/types.cjs.map +1 -0
  163. package/dist/lib/elur/template/types.d.cts +114 -0
  164. package/dist/lib/elur/template/types.d.ts +114 -0
  165. package/dist/lib/elur/template/types.js +23 -0
  166. package/dist/lib/elur/template/types.js.map +1 -0
  167. package/dist/lib/elur.cjs +1 -0
  168. package/dist/lib/elur.js +18 -0
  169. package/dist/lib/form.cjs +2 -0
  170. package/dist/lib/form.js +315 -0
  171. package/dist/lib/hydrate.cjs +2 -0
  172. package/dist/lib/hydrate.js +410 -0
  173. package/dist/lib/index.cjs +1 -0
  174. package/dist/lib/index.d.cts +2 -0
  175. package/dist/lib/index.d.ts +2 -0
  176. package/dist/lib/index.js +18 -0
  177. package/dist/lib/lifecycle.cjs +2 -0
  178. package/dist/lib/lifecycle.js +39 -0
  179. package/dist/lib/plugins.cjs +2 -0
  180. package/dist/lib/plugins.js +59 -0
  181. package/dist/lib/router.cjs +12 -0
  182. package/dist/lib/router.js +513 -0
  183. package/dist/lib/server.cjs +2 -0
  184. package/dist/lib/server.js +307 -0
  185. package/dist/lib/signals.cjs +2 -0
  186. package/dist/lib/signals.js +188 -0
  187. package/dist/lib/store.cjs +2 -0
  188. package/dist/lib/store.js +143 -0
  189. package/dist/lib/template.cjs +1 -0
  190. package/dist/lib/template.js +13 -0
  191. package/package.json +216 -0
@@ -0,0 +1,315 @@
1
+ import { batch as e, computed as t, effect as n, signal as r } from "./signals.js";
2
+ //#region src/elur/form.ts
3
+ function i(e = "Required") {
4
+ return (t) => t == null || t === "" || Array.isArray(t) && t.length === 0 ? e : null;
5
+ }
6
+ function a(e, t) {
7
+ return (n) => typeof n == "string" && n.length < e ? t ?? `Minimum ${e} characters` : null;
8
+ }
9
+ function o(e, t) {
10
+ return (n) => typeof n == "string" && n.length > e ? t ?? `Maximum ${e} characters` : null;
11
+ }
12
+ function s(e, t = "Invalid format") {
13
+ return (n) => typeof n == "string" && !e.test(n) ? t : null;
14
+ }
15
+ function c(e = "Invalid email") {
16
+ return s(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, e);
17
+ }
18
+ function l(e, t) {
19
+ return (n) => typeof n == "number" && n < e ? t ?? `Minimum value is ${e}` : null;
20
+ }
21
+ function u(e, t) {
22
+ return (n) => typeof n == "number" && n > e ? t ?? `Maximum value is ${e}` : null;
23
+ }
24
+ function d(e) {
25
+ return e;
26
+ }
27
+ var f = {
28
+ required: i,
29
+ minLength: a,
30
+ maxLength: o,
31
+ email: c,
32
+ pattern: s,
33
+ min: l,
34
+ max: u
35
+ };
36
+ function p(e, t) {
37
+ return {
38
+ ...e,
39
+ ...t
40
+ };
41
+ }
42
+ function m(i, a = [], o = "blur", s) {
43
+ let c = r(i), l = r(!1), u = r(!1), d = r(null), f = r(!1), p = i, m = !0, h = n(() => {
44
+ if (c.value, m) {
45
+ m = !1;
46
+ return;
47
+ }
48
+ d.peek() !== null && (d.value = null);
49
+ }), g = t(() => {
50
+ if (d.value) return d.value;
51
+ let e = s?.();
52
+ for (let t of a) {
53
+ let n = t(c.value, e);
54
+ if (n) return n;
55
+ }
56
+ return null;
57
+ }), _ = t(() => (o === "input" ? u.value || l.value : o === "submit" ? f.value : l.value) ? g.value : null);
58
+ function v(e) {
59
+ return e.type === "checkbox" || e.type === "radio";
60
+ }
61
+ function y(e) {
62
+ if (!e || !("value" in e)) return i;
63
+ let t = e, n = t.value;
64
+ return typeof i == "boolean" ? t.checked === !0 ? !0 : v(t) ? !1 : n === "true" || n === "1" ? !0 : n === "false" || n === "0" || n === "" ? !1 : i : typeof i == "number" ? n === "" ? NaN : Number(n) : n;
65
+ }
66
+ let b = (e) => {
67
+ c.value = y(e.target), u.value = !0;
68
+ }, x = () => {
69
+ l.value = !0;
70
+ };
71
+ function S() {
72
+ e(() => {
73
+ c.value = p, l.value = !1, u.value = !1, d.value = null, f.value = !1;
74
+ });
75
+ }
76
+ function C(t, n = {}) {
77
+ let { shouldTouch: r = !1, shouldDirty: i = !0, shouldValidate: a = !0 } = n;
78
+ e(() => {
79
+ c.value = t, i && (u.value = !0), r && (l.value = !0), a && (f.value = !0);
80
+ });
81
+ }
82
+ function w(e) {
83
+ d.value = e, e && (l.value = !0);
84
+ }
85
+ function T() {
86
+ l.value = !0, f.value = !0;
87
+ }
88
+ function E(e) {
89
+ p = e;
90
+ }
91
+ function D() {
92
+ h(), _.dispose(), g.dispose();
93
+ }
94
+ return {
95
+ value: c,
96
+ error: _,
97
+ rawError: g,
98
+ touched: l,
99
+ dirty: u,
100
+ onInput: b,
101
+ onBlur: x,
102
+ reset: S,
103
+ setValue: C,
104
+ _setExternalError: w,
105
+ _forceVisible: T,
106
+ _setInitialValue: E,
107
+ _dispose: D
108
+ };
109
+ }
110
+ function h(e, n = {}, i = "blur") {
111
+ function a(e) {
112
+ let t = {};
113
+ for (let r in e) {
114
+ let a = n[r] ?? [];
115
+ t[r] = m(e[r], a, i);
116
+ }
117
+ return t;
118
+ }
119
+ let o = r(e.map(a)), s = e, c = t(() => o.value.length);
120
+ function l(e) {
121
+ o.value = [...o.value, a(e)];
122
+ }
123
+ function u(e) {
124
+ let t = o.value;
125
+ if (!(e < 0 || e >= t.length)) {
126
+ for (let n in t[e]) t[e][n]._dispose();
127
+ o.value = t.filter((t, n) => n !== e);
128
+ }
129
+ }
130
+ function d(e, t) {
131
+ let n = [...o.value];
132
+ if (e < 0 || e >= n.length || t < 0 || t >= n.length || e === t) return;
133
+ let [r] = n.splice(e, 1);
134
+ n.splice(t, 0, r), o.value = n;
135
+ }
136
+ function f(e, t) {
137
+ let n = [...o.value];
138
+ if (!(e < 0 || e >= n.length)) {
139
+ for (let t in n[e]) n[e][t]._dispose();
140
+ n[e] = a(t), o.value = n;
141
+ }
142
+ }
143
+ function p(e) {
144
+ for (let e of o.value) for (let t in e) e[t]._dispose();
145
+ o.value = e.map(a);
146
+ }
147
+ function h(e) {
148
+ let t = [...o.value];
149
+ for (let n = 0; n < e.length; n++) {
150
+ let r = e[n];
151
+ if (n >= t.length) {
152
+ t.push(a(r));
153
+ continue;
154
+ }
155
+ let i = t[n];
156
+ for (let [e, t] of Object.entries(r)) i[e] && i[e].setValue(t, {
157
+ shouldDirty: !1,
158
+ shouldTouch: !1,
159
+ shouldValidate: !1
160
+ });
161
+ }
162
+ o.value = t;
163
+ }
164
+ function g(e) {
165
+ e && (s = e);
166
+ for (let e of o.value) for (let t in e) e[t]._dispose();
167
+ o.value = s.map(a);
168
+ }
169
+ function _() {
170
+ for (let e of o.value) for (let t in e) e[t]._dispose();
171
+ c.dispose();
172
+ }
173
+ return {
174
+ fields: o,
175
+ append: l,
176
+ remove: u,
177
+ move: d,
178
+ replace: f,
179
+ length: c,
180
+ setValues: p,
181
+ patchValues: h,
182
+ reset: g,
183
+ _dispose: _
184
+ };
185
+ }
186
+ function g(e) {
187
+ return typeof e == "object" && !!e && !Array.isArray(e);
188
+ }
189
+ function _(e, t = "", n = []) {
190
+ for (let [r, i] of Object.entries(e)) {
191
+ let e = t ? `${t}.${r}` : r;
192
+ if (g(i) && Object.keys(i).length > 0) {
193
+ _(i, e, n);
194
+ continue;
195
+ }
196
+ n.push([e, i]);
197
+ }
198
+ return n;
199
+ }
200
+ function v(e, t, n) {
201
+ let r = t.split("."), i = e;
202
+ for (let e = 0; e < r.length - 1; e++) {
203
+ let t = r[e], n = i[t];
204
+ g(n) || (i[t] = {}), i = i[t];
205
+ }
206
+ i[r[r.length - 1]] = n;
207
+ }
208
+ function y(n, i = {}) {
209
+ let a = i.validateOn ?? "blur", o = {}, s = i.validators;
210
+ function c() {
211
+ let e = {};
212
+ for (let t in o) v(e, t, o[t].value.value);
213
+ return e;
214
+ }
215
+ for (let [e, t] of _(n)) o[e] = m(t, s?.[e] ?? [], a, c);
216
+ let l = r(!1), u = r(0), d = t(() => c()), f = t(() => {
217
+ let e = {};
218
+ for (let t in o) {
219
+ let n = o[t].error.value;
220
+ n && (e[t] = n);
221
+ }
222
+ return e;
223
+ }), p = t(() => {
224
+ for (let e in o) if (o[e].rawError.value) return !1;
225
+ return !0;
226
+ }), h = t(() => {
227
+ for (let e in o) if (o[e].error.value) return !1;
228
+ return !0;
229
+ }), g = t(() => {
230
+ for (let e in o) if (o[e].dirty.value) return !0;
231
+ return !1;
232
+ }), y = t(() => {
233
+ for (let e in o) if (o[e].touched.value) return !0;
234
+ return !1;
235
+ });
236
+ function b(e) {
237
+ for (let t in e) o[t]?._setExternalError(e[t] ?? null);
238
+ }
239
+ function x(e, t, n = {}) {
240
+ let r = o[e];
241
+ r && r.setValue(t, n);
242
+ }
243
+ function S(t, n = {}) {
244
+ let { keepDirty: r = !1, keepTouched: i = !1, keepErrors: a = !0 } = n;
245
+ e(() => {
246
+ for (let [e, n] of _(t)) {
247
+ let t = o[e];
248
+ t && (t.setValue(n, {
249
+ shouldDirty: !r,
250
+ shouldTouch: !1,
251
+ shouldValidate: !a
252
+ }), i || (t.touched.value = !1));
253
+ }
254
+ });
255
+ }
256
+ function C(e) {
257
+ if (e) for (let [t, n] of _(e)) {
258
+ let e = o[t];
259
+ e && e._setInitialValue(n);
260
+ }
261
+ for (let e in o) o[e].reset();
262
+ l.value = !1, u.value = 0;
263
+ }
264
+ function w() {
265
+ d.dispose(), f.dispose(), p.dispose(), h.dispose(), g.dispose(), y.dispose();
266
+ for (let e in o) o[e]._dispose();
267
+ }
268
+ function T(e) {
269
+ return (t) => {
270
+ t.preventDefault(), u.value++;
271
+ for (let e in o) o[e]._forceVisible();
272
+ let n = d.value;
273
+ if (i.validate) {
274
+ let e = i.validate(n);
275
+ if (e) {
276
+ let t = {}, n = !1;
277
+ for (let r in e) {
278
+ let i = e[r], a = Array.isArray(i) ? i[0] ?? null : i ?? null;
279
+ a && (t[r] = a, n = !0);
280
+ }
281
+ if (n) {
282
+ b(t);
283
+ return;
284
+ }
285
+ }
286
+ }
287
+ for (let e in o) if (o[e].rawError.value) return;
288
+ let r = e(n);
289
+ r instanceof Promise && (l.value = !0, r.finally(() => {
290
+ l.value = !1;
291
+ }).catch(() => {}));
292
+ };
293
+ }
294
+ return {
295
+ fields: o,
296
+ values: d,
297
+ errors: f,
298
+ canSubmit: p,
299
+ valid: h,
300
+ dirty: g,
301
+ touched: y,
302
+ isSubmitting: l,
303
+ submitCount: u,
304
+ handleSubmit: T,
305
+ reset: C,
306
+ setValue: x,
307
+ setValues: S,
308
+ setErrors: b,
309
+ dispose: w
310
+ };
311
+ }
312
+ //#endregion
313
+ export { y as createForm, d as createValidator, m as elurField, h as elurFieldArray, c as email, p as extendValidators, u as max, o as maxLength, l as min, a as minLength, s as pattern, i as required, f as validators };
314
+
315
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../src/elur/form.ts"],"sourcesContent":["import { signal, computed, effect, batch } from \"./reactivity.js\";\nimport type { Signal } from \"./reactivity.js\";\n\n// --- Validator ---\n\n/**\n * A validator function. Return an error string when invalid, or `null` /\n * `undefined` when valid.\n *\n * `allValues` is provided when the validator runs inside `createForm`, enabling\n * cross-field validation (e.g., \"confirm password matches password\").\n *\n * **Validators must be pure.** They are invoked reactively whenever the field\n * value changes — potentially many times per keystroke in forms with\n * cross-field rules — and may run inside computed signals that assume\n * deterministic output. Do not perform I/O, mutate external state, or rely on\n * `Date.now()` / `Math.random()` inside a validator. For asynchronous checks\n * (uniqueness, server-side rules), submit the form and inject the result via\n * {@link FormState.setErrors}.\n */\nexport type Validator<T, AllValues = unknown> = (\n value: T,\n allValues?: AllValues,\n) => string | null | undefined;\n\n// --- Built-in validators ---\n\nexport function required(message = \"Required\"): Validator<unknown> {\n return (v) =>\n v == null || v === \"\" || (Array.isArray(v) && v.length === 0)\n ? message\n : null;\n}\n\nexport function minLength(n: number, message?: string): Validator<string> {\n return (v) =>\n typeof v === \"string\" && v.length < n\n ? (message ?? `Minimum ${n} characters`)\n : null;\n}\n\nexport function maxLength(n: number, message?: string): Validator<string> {\n return (v) =>\n typeof v === \"string\" && v.length > n\n ? (message ?? `Maximum ${n} characters`)\n : null;\n}\n\nexport function pattern(regex: RegExp, message = \"Invalid format\"): Validator<string> {\n return (v) => (typeof v === \"string\" && !regex.test(v) ? message : null);\n}\n\nexport function email(message = \"Invalid email\"): Validator<string> {\n return pattern(/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/, message);\n}\n\nexport function min(n: number, message?: string): Validator<number> {\n return (v) =>\n typeof v === \"number\" && v < n\n ? (message ?? `Minimum value is ${n}`)\n : null;\n}\n\nexport function max(n: number, message?: string): Validator<number> {\n return (v) =>\n typeof v === \"number\" && v > n\n ? (message ?? `Maximum value is ${n}`)\n : null;\n}\n\n// --- Custom validator API ---\n\n/** Creates a typed custom validator compatible with `elurField` and `createForm`. */\nexport function createValidator<T, AllValues = unknown>(\n fn: (value: T, allValues?: AllValues) => string | null | undefined\n): Validator<T, AllValues> {\n return fn;\n}\n\n/** All built-in validators grouped as a namespace. Extensible via `extendValidators`. */\nexport const validators = {\n required,\n minLength,\n maxLength,\n email,\n pattern,\n min,\n max,\n} as const;\n\n/** Shape of the built-in `validators` namespace. Used as the base type for `extendValidators`. */\nexport type ValidatorsBase = typeof validators;\n\n/**\n * Merges custom validator factories into the built-in namespace.\n * Returns a new object — the original is never mutated.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function extendValidators<E extends Record<string, (...args: any[]) => Validator<any>>>(\n base: ValidatorsBase,\n extensions: E\n): ValidatorsBase & E {\n return { ...base, ...extensions };\n}\n\n// --- validateOn ---\n\n/**\n * Controls when validation errors become visible.\n * - `\"blur\"` — after the field loses focus (default)\n * - `\"input\"` — as soon as the user types\n * - `\"submit\"` — only after the first submit attempt\n */\nexport type ValidateOn = \"blur\" | \"input\" | \"submit\";\n\n// --- FieldState ---\n\n/** Public state of a single form field. */\nexport interface FieldState<T> {\n /** Current value — read/write signal. */\n value: Signal<T>;\n /** Error visible según validateOn. Para UI. */\n readonly error: Signal<string | null>;\n /**\n * Error real, ignorando validateOn/touched/dirty.\n * Para lógica de habilitación de botones, validez global, etc.\n */\n readonly rawError: Signal<string | null>;\n /** True after the input has lost focus at least once. */\n touched: Signal<boolean>;\n /** True after the user has typed at least once. */\n dirty: Signal<boolean>;\n /** Attach to `@input` on any `<input>`, `<select>`, `<textarea>`. */\n readonly onInput: (e: Event) => void;\n /** Attach to `@blur`. */\n readonly onBlur: () => void;\n /** Reset to initial value and clear touched/dirty/error state. */\n reset(): void;\n /**\n * Set the field value programmatically.\n *\n * @param value — new value for the field.\n * @param options — control whether to touch/dirty the field and whether to force\n * validation visibility.\n */\n setValue(\n value: T,\n options?: { shouldTouch?: boolean; shouldDirty?: boolean; shouldValidate?: boolean },\n ): void;\n /**\n * @internal — inject an external error message (server / schema validator).\n * The error clears automatically when the user next edits the field.\n */\n _setExternalError(msg: string | null): void;\n /** @internal — force error visibility (e.g., on submit). */\n _forceVisible(): void;\n /** @internal — update the stored initial value so a later reset() returns here. */\n _setInitialValue(value: T): void;\n /** @internal — dispose computed signals. */\n _dispose(): void;\n}\n\n// --- elurField ---\n\n/** Creates a standalone reactive form field with optional validators. */\nexport function elurField<T, AllValues = unknown>(\n initialValue: T,\n fieldValidators: Validator<T, AllValues>[] = [],\n validateOn: ValidateOn = \"blur\",\n getAllValues?: () => AllValues,\n): FieldState<T> {\n const value = signal(initialValue);\n const touched = signal(false);\n const dirty = signal(false);\n const _ext = signal<string | null>(null);\n // Tracks whether the form has been submitted at least once (injected externally)\n const _submitted = signal(false);\n // Mutable reference so that reset() can be redirected by createForm.reset(newValues).\n let currentInitialValue = initialValue;\n\n let _skipFirstClear = true;\n const _disposeExtCleanup = effect(() => {\n value.value; // subscribe to value changes\n if (_skipFirstClear) {\n _skipFirstClear = false;\n return;\n }\n if (_ext.peek() !== null) {\n _ext.value = null;\n }\n });\n\n const rawError = computed<string | null>(() => {\n if (_ext.value) return _ext.value;\n const allValues = getAllValues?.();\n for (const v of fieldValidators) {\n const e = v(value.value, allValues);\n if (e) return e;\n }\n return null;\n });\n\n const error = computed<string | null>(() => {\n const isVisible =\n validateOn === \"input\" ? dirty.value || touched.value :\n validateOn === \"submit\" ? _submitted.value :\n touched.value;\n if (!isVisible) return null;\n return rawError.value;\n });\n\n function isCheckable(input: HTMLInputElement): boolean {\n return input.type === \"checkbox\" || input.type === \"radio\";\n }\n\n function coerce(target: EventTarget | null): T {\n if (!target || !(\"value\" in target)) return initialValue;\n const t = target as HTMLInputElement;\n const value = t.value;\n\n if (typeof initialValue === \"boolean\") {\n const checked = t.checked;\n if (checked === true) return true as unknown as T;\n if (isCheckable(t)) return false as unknown as T;\n if (value === \"true\" || value === \"1\") return true as unknown as T;\n if (value === \"false\" || value === \"0\" || value === \"\") return false as unknown as T;\n return initialValue;\n }\n\n if (typeof initialValue === \"number\") {\n if (value === \"\") return NaN as unknown as T;\n return Number(value) as unknown as T;\n }\n\n return value as unknown as T;\n }\n\n const onInput = (e: Event): void => {\n value.value = coerce(e.target);\n dirty.value = true;\n };\n\n const onBlur = (): void => { touched.value = true; };\n\n function reset(): void {\n batch(() => {\n value.value = currentInitialValue;\n touched.value = false;\n dirty.value = false;\n _ext.value = null;\n _submitted.value = false;\n });\n }\n\n function setValue(\n next: T,\n options: { shouldTouch?: boolean; shouldDirty?: boolean; shouldValidate?: boolean } = {},\n ): void {\n const { shouldTouch = false, shouldDirty = true, shouldValidate = true } = options;\n batch(() => {\n value.value = next;\n if (shouldDirty) dirty.value = true;\n if (shouldTouch) touched.value = true;\n if (shouldValidate) _submitted.value = true;\n });\n }\n\n function _setExternalError(msg: string | null): void {\n _ext.value = msg;\n if (msg) touched.value = true;\n }\n\n function _forceVisible(): void {\n touched.value = true;\n _submitted.value = true;\n }\n\n function _setInitialValue(next: T): void {\n currentInitialValue = next;\n }\n\n function _dispose(): void {\n _disposeExtCleanup();\n error.dispose();\n rawError.dispose();\n }\n\n return { value, error, rawError, touched, dirty, onInput, onBlur, reset, setValue, _setExternalError, _forceVisible, _setInitialValue, _dispose };\n}\n\n// --- FieldArrayState ---\n\n/** Public state of a field array (dynamic list of field groups). */\nexport interface FieldArrayState<T extends Record<string, unknown>> {\n /** Reactive list of field group states. */\n readonly fields: Signal<Array<{ [K in keyof T]: FieldState<T[K]> }>>;\n /** Appends a new item to the end of the array. */\n append(value: T): void;\n /** Removes the item at the given index. */\n remove(index: number): void;\n /**\n * Moves an item from `from` to `to` index.\n * Items between the two positions shift to fill the gap.\n */\n move(from: number, to: number): void;\n /** Replaces the item at the given index with new values. */\n replace(index: number, value: T): void;\n /** Number of items in the array. Reactive. */\n readonly length: Signal<number>;\n /** Replaces the whole array with a new list of items. */\n setValues(items: T[]): void;\n /** Patches existing items and appends any extras without touching untouched items. */\n patchValues(items: Partial<T>[]): void;\n /** Resets the array to its initial value, optionally updating that initial value. */\n reset(items?: T[]): void;\n /** @internal */\n _dispose(): void;\n}\n\n/**\n * Creates a reactive array of field groups for dynamic list forms.\n *\n * @example\n * const items = elurFieldArray([{ name: \"\" }], {\n * name: [required()],\n * });\n * items.append({ name: \"nuevo\" });\n * items.remove(0);\n */\nexport function elurFieldArray<T extends Record<string, unknown>>(\n initialItems: T[],\n fieldValidators: { [K in keyof T]?: Validator<T[K], unknown>[] } = {},\n validateOn: ValidateOn = \"blur\",\n): FieldArrayState<T> {\n function makeGroup(item: T): { [K in keyof T]: FieldState<T[K]> } {\n const group = {} as { [K in keyof T]: FieldState<T[K]> };\n for (const key in item) {\n const vs = (fieldValidators[key] ?? []) as Validator<T[typeof key], unknown>[];\n (group as Record<string, unknown>)[key] = elurField(item[key], vs, validateOn);\n }\n return group;\n }\n\n const fields = signal<Array<{ [K in keyof T]: FieldState<T[K]> }>>(\n initialItems.map(makeGroup)\n );\n // Mutable so that reset(newItems) can redirect the baseline.\n let currentInitialItems = initialItems;\n\n const length = computed(() => fields.value.length);\n\n function append(value: T): void {\n fields.value = [...fields.value, makeGroup(value)];\n }\n\n function remove(index: number): void {\n const current = fields.value;\n if (index < 0 || index >= current.length) return;\n // Dispose computed signals of the removed group before discarding\n for (const key in current[index]) {\n current[index][key]._dispose();\n }\n fields.value = current.filter((_, i) => i !== index);\n }\n\n function move(from: number, to: number): void {\n const current = [...fields.value];\n if (\n from < 0 || from >= current.length ||\n to < 0 || to >= current.length ||\n from === to\n ) return;\n const [item] = current.splice(from, 1);\n current.splice(to, 0, item);\n fields.value = current;\n }\n\n function replace(index: number, value: T): void {\n const current = [...fields.value];\n if (index < 0 || index >= current.length) return;\n // Dispose old group before replacing\n for (const key in current[index]) {\n current[index][key]._dispose();\n }\n current[index] = makeGroup(value);\n fields.value = current;\n }\n\n function setValues(items: T[]): void {\n for (const group of fields.value) {\n for (const key in group) group[key]._dispose();\n }\n fields.value = items.map(makeGroup);\n }\n\n function patchValues(items: Partial<T>[]): void {\n const current = [...fields.value];\n for (let i = 0; i < items.length; i++) {\n const patch = items[i] as Record<string, unknown>;\n if (i >= current.length) {\n current.push(makeGroup(patch as T));\n continue;\n }\n const group = current[i] as Record<string, FieldState<unknown>>;\n for (const [key, val] of Object.entries(patch)) {\n if (group[key]) {\n group[key].setValue(val, { shouldDirty: false, shouldTouch: false, shouldValidate: false });\n }\n }\n }\n fields.value = current;\n }\n\n function reset(items?: T[]): void {\n if (items) currentInitialItems = items;\n for (const group of fields.value) {\n for (const key in group) group[key]._dispose();\n }\n fields.value = currentInitialItems.map(makeGroup);\n }\n\n function _dispose(): void {\n for (const group of fields.value) {\n for (const key in group) group[key]._dispose();\n }\n length.dispose();\n }\n\n return { fields, append, remove, move, replace, length, setValues, patchValues, reset, _dispose };\n}\n\n// --- FormState ---\n\n/** Field-name map that supports top-level keys and dot-path nested keys. */\nexport type FormFields<T extends Record<string, unknown>> =\n { [K in keyof T]: FieldState<T[K]> } & Record<string, FieldState<unknown>>;\n\n/** Map of field-name → error message for external validation results. */\nexport type FieldErrors<T extends Record<string, unknown>> =\n { [K in keyof T]?: string | null } & Record<string, string | null | undefined>;\n\n/** Validators map supporting both top-level and dot-path keys. */\nexport type FormValidators<T extends Record<string, unknown>> =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n { [K in keyof T]?: Validator<T[K], T>[] } & Record<string, Validator<any, any>[] | undefined>;\n\n// Utility used by setValues so callers can patch nested objects (e.g. { address: { city: \"Lima\" } }).\nexport type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]> } : T;\n\nexport interface FormState<T extends Record<string, unknown>> {\n /** Individual field states — access value, error, event handlers. */\n fields: FormFields<T>;\n /** Computed snapshot of all current field values. */\n readonly values: Signal<T>;\n /** Computed map of all currently visible field errors. */\n readonly errors: Signal<FieldErrors<T>>;\n /**\n * True when no field has a *visible* error.\n *\n * Visibility follows `validateOn`, so this signal reflects what the user\n * currently sees in the UI — not the underlying validity of the data.\n * Use it to drive error summaries, banners, or any UI that should only\n * react to errors the user has been shown.\n *\n * For enabling or disabling submit buttons, use {@link canSubmit} instead.\n */\n readonly valid: Signal<boolean>;\n /**\n * True when every per-field validator passes against the current values,\n * regardless of `touched`, `dirty`, or `validateOn`.\n *\n * This is the signal to bind to submit buttons:\n *\n * ```ts\n * <button disabled=${() => !form.canSubmit.value || form.isSubmitting.value}>\n * Save\n * </button>\n * ```\n *\n * Unlike {@link valid}, `canSubmit` does not depend on whether errors are\n * currently visible — a pristine form with empty required fields starts\n * as `false` and flips to `true` the moment all validators pass.\n *\n * External errors injected via {@link setErrors} also flip `canSubmit` to\n * `false` until the user edits the affected field.\n *\n * **Note:** `canSubmit` does not execute `options.validate` (schema-level\n * validators such as Zod). Schema validation runs only on submit, by design,\n * to keep per-keystroke cost predictable. If you need a schema rule to\n * affect `canSubmit` reactively, express it as a per-field validator in\n * `options.validators` instead.\n */\n readonly canSubmit: Signal<boolean>;\n /** True when at least one field has been modified. */\n readonly dirty: Signal<boolean>;\n /** True when at least one field has been touched (lost focus). */\n readonly touched: Signal<boolean>;\n /** True while the submit callback is executing (async-safe). */\n readonly isSubmitting: Signal<boolean>;\n /** Number of times the form has been submitted (including failed validations). */\n readonly submitCount: Signal<number>;\n /**\n * Wraps a submit callback. Returned handler:\n * 1. Calls `e.preventDefault()`\n * 2. Increments `submitCount` and marks all fields as visible\n * 3. Runs `options.validate` if provided (Zod, etc.)\n * 4. Only calls `fn(values)` if all validations pass\n * 5. Manages `isSubmitting` across async callbacks\n */\n handleSubmit(fn: (values: T) => void | Promise<void>): (e: Event) => void;\n /**\n * Reset all fields to their initial values. If `newInitialValues` is provided,\n * it becomes the new baseline and subsequent reset() calls will use it.\n */\n reset(newInitialValues?: T): void;\n /**\n * Set a single field value by its path (top-level or nested dot-path).\n */\n setValue(\n path: string,\n value: unknown,\n options?: { shouldTouch?: boolean; shouldDirty?: boolean; shouldValidate?: boolean },\n ): void;\n /**\n * Set multiple field values at once.\n *\n * @param values — partial object with top-level and/or nested values.\n * @param options — control whether to preserve existing touched/dirty/error state.\n */\n setValues(\n values: DeepPartial<T>,\n options?: { keepDirty?: boolean; keepTouched?: boolean; keepErrors?: boolean },\n ): void;\n /**\n * Inject external errors (e.g., from a server response) into specific fields.\n * Each field's error clears automatically the next time the user edits it.\n */\n setErrors(errors: FieldErrors<T>): void;\n /**\n * Disposes all internal computed signals.\n * Call in `onUnmount` when the form lives inside a component.\n */\n dispose(): void;\n}\n\nexport interface FormOptions<T extends Record<string, unknown>> {\n /** Per-field validators. Each validator receives `(value, allValues?)`. */\n validators?: FormValidators<T>;\n /**\n * Controls when validation errors become visible.\n * - `\"blur\"` — after the field loses focus (default)\n * - `\"input\"` — as soon as the user types\n * - `\"submit\"` — only after the first submit attempt\n */\n validateOn?: ValidateOn;\n /**\n * Optional schema-level validator — runs on submit after built-in validators pass.\n * Return `null` / `undefined` if valid, or a field→error map if not.\n * String arrays are accepted (first element shown per field).\n *\n * @example Zod interop\n * ```typescript\n * validate(values) {\n * const r = schema.safeParse(values);\n * if (r.success) return null;\n * return Object.fromEntries(\n * Object.entries(r.error.flatten().fieldErrors)\n * .map(([k, v]) => [k, v?.[0]])\n * );\n * }\n * ```\n */\n validate?: (\n values: T\n ) => Record<string, string | string[] | null | undefined> | null | undefined;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction flattenValuePaths(\n value: Record<string, unknown>,\n prefix = \"\",\n out: Array<[string, unknown]> = [],\n): Array<[string, unknown]> {\n for (const [key, next] of Object.entries(value)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (isPlainRecord(next) && Object.keys(next).length > 0) {\n flattenValuePaths(next, path, out);\n continue;\n }\n out.push([path, next]);\n }\n return out;\n}\n\nfunction setAtPath(target: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split(\".\");\n let current: Record<string, unknown> = target;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n const child = current[part];\n if (!isPlainRecord(child)) {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n\n current[parts[parts.length - 1]] = value;\n}\n\n// --- createForm ---\n\n/**\n * Creates a managed form with reactive fields, built-in validation,\n * schema-level validation (Zod/Valibot/Yup/custom), and submit handling.\n */\nexport function createForm<T extends Record<string, unknown>>(\n initialValues: T,\n options: FormOptions<T> = {}\n): FormState<T> {\n const validateOn: ValidateOn = options.validateOn ?? \"blur\";\n\n const fields = {} as Record<string, FieldState<unknown>>;\n const validatorsByPath = options.validators as\n | Record<string, Validator<unknown, T>[] | undefined>\n | undefined;\n\n function snapshotValues(): T {\n const r: Record<string, unknown> = {};\n for (const k in fields) setAtPath(r, k, fields[k].value.value);\n return r as T;\n }\n\n for (const [path, initialValue] of flattenValuePaths(initialValues)) {\n const vs = validatorsByPath?.[path] ?? [];\n fields[path] = elurField<unknown, T>(initialValue, vs, validateOn, snapshotValues);\n }\n\n const isSubmitting = signal(false);\n const submitCount = signal(0);\n\n const values = computed<T>(() => {\n return snapshotValues();\n });\n\n const errors = computed<FieldErrors<T>>(() => {\n const r: FieldErrors<T> = {};\n for (const k in fields) {\n const e = fields[k].error.value;\n if (e) (r as Record<string, unknown>)[k] = e;\n }\n return r;\n });\n\n const canSubmit = computed<boolean>(() => {\n for (const k in fields) {\n if (fields[k].rawError.value) return false;\n }\n return true;\n });\n\n const valid = computed<boolean>(() => {\n for (const k in fields) if (fields[k].error.value) return false;\n return true;\n });\n\n const dirty = computed<boolean>(() => {\n for (const k in fields) if (fields[k].dirty.value) return true;\n return false;\n });\n\n const touched = computed<boolean>(() => {\n for (const k in fields) if (fields[k].touched.value) return true;\n return false;\n });\n\n function setErrors(errs: FieldErrors<T>): void {\n for (const k in errs) fields[k]?._setExternalError(errs[k] ?? null);\n }\n\n function setValue(\n path: string,\n value: unknown,\n options: { shouldTouch?: boolean; shouldDirty?: boolean; shouldValidate?: boolean } = {},\n ): void {\n const field = fields[path];\n if (!field) return;\n field.setValue(value, options);\n }\n\n function setValues(\n values: DeepPartial<T>,\n options: { keepDirty?: boolean; keepTouched?: boolean; keepErrors?: boolean } = {},\n ): void {\n const { keepDirty = false, keepTouched = false, keepErrors = true } = options;\n batch(() => {\n for (const [path, v] of flattenValuePaths(values as Record<string, unknown>)) {\n const field = fields[path];\n if (!field) continue;\n field.setValue(v, {\n shouldDirty: !keepDirty,\n shouldTouch: false,\n shouldValidate: !keepErrors,\n });\n if (!keepTouched) field.touched.value = false;\n }\n });\n }\n\n function reset(newInitialValues?: T): void {\n if (newInitialValues) {\n for (const [path, v] of flattenValuePaths(newInitialValues)) {\n const field = fields[path];\n if (field) field._setInitialValue(v);\n }\n }\n for (const k in fields) fields[k].reset();\n isSubmitting.value = false;\n submitCount.value = 0;\n }\n\n function dispose(): void {\n values.dispose();\n errors.dispose();\n canSubmit.dispose();\n valid.dispose();\n dirty.dispose();\n touched.dispose();\n for (const k in fields) fields[k]._dispose();\n }\n\n function handleSubmit(fn: (values: T) => void | Promise<void>) {\n return (e: Event): void => {\n e.preventDefault();\n\n submitCount.value++;\n\n for (const k in fields) fields[k]._forceVisible();\n\n const currentValues = values.value;\n\n // Run schema-level validator (Zod, Valibot, etc.)\n if (options.validate) {\n const ext = options.validate(currentValues);\n if (ext) {\n const mapped: FieldErrors<T> = {};\n let hasAny = false;\n for (const k in ext) {\n const v = ext[k];\n const msg = Array.isArray(v) ? (v[0] ?? null) : (v ?? null);\n if (msg) {\n (mapped as Record<string, unknown>)[k] = msg;\n hasAny = true;\n }\n }\n if (hasAny) { setErrors(mapped); return; }\n }\n }\n\n // Check built-in validators\n for (const k in fields) if (fields[k].rawError.value) return;\n\n const result = fn(currentValues);\n\n if (result instanceof Promise) {\n isSubmitting.value = true;\n\n result\n .finally(() => {\n isSubmitting.value = false;\n })\n .catch(() => { });\n }\n };\n }\n\n return {\n fields: fields as FormFields<T>,\n values,\n errors,\n canSubmit,\n valid,\n dirty,\n touched,\n isSubmitting,\n submitCount,\n handleSubmit,\n reset,\n setValue,\n setValues,\n setErrors,\n dispose,\n };\n}"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`),t=require(`./elur/template/types.cjs`),n=require(`./lifecycle.cjs`),r=require(`./context.cjs`),i=require(`./elur/template/keyed.cjs`),a=require(`./elur/template/keyed-diff.cjs`),o=require(`./elur/template/sanitize.cjs`),s=require(`./elur/template/bindings.cjs`);function c(e,r,i={}){try{if(n.isElurComponent(e))return l(e,r,i);let a=e[t.ELUR_TEMPLATE_DESCRIPTOR];return a||S(i,-1,`descriptor`,`Template has no hydration descriptor`),{unmount:u(a,r,i)}}catch(t){if(i.mismatch===`throw`)throw t;return i.mismatch!==`remount`&&console.warn(`[elur] Hydration mismatch; remounting root:`,t),r.replaceChildren(),{unmount:n.isElurComponent(e)?e.render()._render(r,null):e._render(r,null)}}}function l(e,n,i){r._pushComponentContext();let a=()=>{};try{try{e.onInit?.()}catch(t){if(e.onError)e.onError(t);else throw t}let r=e.render()[t.ELUR_TEMPLATE_DESCRIPTOR];r||S(i,-1,`descriptor`,`Component template has no hydration descriptor`),a=u(r,n,i)}finally{r._popComponentContext()}let o=e.onMount?.();return{unmount(){e.onUnmount?.(),typeof o==`function`&&o(),a()}}}function u(e,t,n,r){let i=d(t,r),a=[];for(let t=0;t<e.contexts.length;t++){let r=e.contexts[t],o=e.values[t];if(r.type===`event`){let e=i.events.get(t);e||S(n,t,`event`,`Missing event marker ${t}`),e.removeAttribute(`data-elur-e-${t}`),a.push(p(e,r.eventName,r.modifiers,o));continue}if(r.type===`attr`){let e=i.attributes.get(t);e||S(n,t,`attribute`,`Missing attribute marker ${t}`),e.removeAttribute(`data-elur-a-${t}`),a.push(m(e,r.attrName,r.url===!0,o));continue}let s=i.nodes.get(t);s||S(n,t,`node`,`Missing node marker ${t}`);let c=h(s,o,n,i.keyed.get(t),i.arrayItems.get(t));c&&a.push(c)}return()=>{for(let e=a.length-1;e>=0;e--)a[e]()}}function d(e,t){let n=new Map,r=new Map,i=new Map,a=new Map,o=new Map,s=new Map,c=[],l=[],u=[],d=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT),p;for(;p=d.nextNode();){if(t&&!f(p,t))continue;if(p.nodeType===Node.COMMENT_NODE){let e=p,t=/^elur-(\d+)$/.exec(e.data);if(t){let n=Number(t[1]);c.length===0&&r.set(n,e),c.push(n);continue}let i=/^elur-end-(\d+)$/.exec(e.data);if(i){let t=Number(i[1]);if(c.pop()===t&&c.length===0){let i=r.get(t);i&&n.set(t,{start:i,end:e})}continue}let a=/^elur-ki:(.+)$/.exec(e.data);if(a){let t=a[1];l.length===0&&c.length===1?l.push({start:e,serializedKey:t,parentIndex:c[c.length-1]}):l.push({start:e,serializedKey:t,parentIndex:-1});continue}if(e.data===`elur-ke`){let t=l.pop();if(t){if(t.parentIndex>=0){let n=o.get(t.parentIndex)??[];n.push({start:t.start,end:e,serializedKey:t.serializedKey}),o.set(t.parentIndex,n)}}else throw Error(`[elur] Hydration marker mismatch: orphan keyed end marker (elur-ke)`);continue}if(e.data===`elur-ai`){u.length===0&&c.length===1?u.push({start:e,parentIndex:c[c.length-1]}):u.push({start:e,parentIndex:-1});continue}if(e.data===`elur-aiend`){let t=u.pop();if(t&&t.parentIndex>=0){let n=s.get(t.parentIndex)??[];n.push({start:t.start,end:e}),s.set(t.parentIndex,n)}continue}continue}if(c.length>0)continue;let e=p;for(let t of Array.from(e.attributes)){let n=/^data-elur-e-(\d+)$/.exec(t.name);n&&a.set(Number(n[1]),e);let r=/^data-elur-a-(\d+)$/.exec(t.name);r&&i.set(Number(r[1]),e)}}return{nodes:n,attributes:i,events:a,keyed:o,arrayItems:s}}function f(e,t){let n=document.createRange();return n.setStartAfter(t.start),n.setEndBefore(t.end),n.intersectsNode(e)}function p(e,t,n,r){if(typeof r!=`function`)throw TypeError(`Event "${t}" requires a function`);let i=r;if(s.isDelegableEvent(t)&&!n.includes(`capture`)&&!n.includes(`once`)&&document.body.contains(e))return s.activateDelegatedEvent(e,t,n,i);let a={once:n.includes(`once`),capture:n.includes(`capture`),passive:n.includes(`passive`)},o=e=>{n.includes(`prevent`)&&e.preventDefault(),n.includes(`stop`)&&e.stopPropagation(),!(n.includes(`self`)&&e.target!==e.currentTarget)&&i(e)};return e.addEventListener(t,o,a),()=>e.removeEventListener(t,o,a)}function m(t,n,r,i){if(n===`ref`){let e=i;return e.el=t,()=>{e.el=null}}let a=(n===`value`||n===`checked`||n===`selected`)&&n in t,s=!0,c=!1,l=e=>{if(a)if(!s)t[n]=e??``;else{let r=t[n];if(String(r)!==String(e??``)&&!c){c=!0;let e=n===`checked`||n===`selected`?`change`:`input`;queueMicrotask(()=>{c=!1,t.dispatchEvent(new Event(e,{bubbles:!0}))})}}else if(e==null||e===!1)t.removeAttribute(n);else{let i=r?o.sanitizeUrl(String(e)):String(e);t.setAttribute(n,i)}s=!1};return typeof i==`function`?e.effect(()=>l(i())):(l(i),()=>{})}function h(n,i,o,s,c){if(typeof i!=`function`)return g(n,i,o,s,c);let l=!0,u,d=b(n),f=null,p=r._captureContextSnapshot(),m=a.createKeyedMount(p),h=e=>{console.warn(`[elur] repeat(): duplicate key "${e}". Keys must be unique; the previous entry leaks (orphaned nodes + live effects).`)},v=e.effect(()=>{let e=i();if(t.isKeyedList(e)){if(l&&!f){let t=_(e,s,o);f={state:t.state,prevOrder:t.prevOrder},u=t.cleanup,a.reconcileKeyedList({zoneStart:n.start,anchor:n.end,state:f.state,prevOrder:f.prevOrder,list:e,mount:m,ctxSnapshot:p,onDuplicateKey:h}),d=null,l=!1;return}f||(u?.(),x(n),f={state:new Map,prevOrder:[]},u=()=>{for(let e of f.state.values())e.cleanup()}),a.reconcileKeyedList({zoneStart:n.start,anchor:n.end,state:f.state,prevOrder:f.prevOrder,list:e,mount:m,ctxSnapshot:p,onDuplicateKey:h}),d=null,l=!1;return}f&&(u?.(),x(n),f=null,u=void 0),typeof e==`string`||typeof e==`number`||typeof e==`bigint`?d?d.nodeValue!==String(e)&&(d.nodeValue=String(e)):(d=document.createTextNode(String(e)),n.end.parentNode.insertBefore(d,n.end)):l?u=g(n,e,o,s,c):(u?.(),x(n),u=y(n,e),d=b(n)),l=!1});return()=>{v(),u?.()}}function g(e,i,o,s,c){if(t.isKeyedList(i)){let t=r._captureContextSnapshot(),n=_(i,s,o);return a.reconcileKeyedList({zoneStart:e.start,anchor:e.end,state:n.state,prevOrder:n.prevOrder,list:i,mount:a.createKeyedMount(t),ctxSnapshot:t,onDuplicateKey:e=>{console.warn(`[elur] repeat(): duplicate key "${e}". Keys must be unique; the previous entry leaks (orphaned nodes + live effects).`)}}),n.cleanup}if(Array.isArray(i)){let t=[],n=c!==void 0&&c.length>0;for(let r=0;r<i.length;r++){let a=i[r],s=c?.[r];if(n&&s){let e=g(s,a,o);e&&t.push(e)}else if(n){let n=y(e,a);n&&t.push(n)}else{let n=g(e,a,o);n&&t.push(n)}}return t.length?()=>{for(let e=t.length-1;e>=0;e--)t[e]()}:void 0}if(t.isElurTemplate(i)){let n=i[t.ELUR_TEMPLATE_DESCRIPTOR];return n||S(o,-1,`descriptor`,`Nested template has no hydration descriptor`),u(n,e.start.parentNode,o,e)}if(n.isElurComponent(i)){r._pushComponentContext();let n;try{try{i.onInit?.()}catch(e){if(i.onError)i.onError(e);else throw e}let r=i.render()[t.ELUR_TEMPLATE_DESCRIPTOR];r||S(o,-1,`descriptor`,`Nested component has no hydration descriptor`);let a=u(r,e.start.parentNode,o,e),s=i.onMount?.();n=()=>{i.onUnmount?.(),typeof s==`function`&&s(),a()}}finally{r._popComponentContext()}return n}if(typeof i==`object`&&i){let n=i[t.ELUR_RENDER_PROTOCOL];if(n?.hydrateDom)return n.hydrateDom({parent:e.start.parentNode,bounds:e,context:o.context,render:t=>g(e,t,o)})??void 0}}function _(e,t,n){let r=new Map,a=[];if(!t||t.length===0)return{state:r,prevOrder:a,cleanup:()=>{}};let o=new Map;for(let t=0;t<e.items.length;t++){let n=i.normalizeRepeatKey(e.keyFn(e.items[t],t),t),r=i.serializeRepeatKey(n);o.has(r)&&console.warn(`[elur] repeat(): duplicate client key "${n}" during hydration. Keys must be unique; entries after the first leak.`),o.set(r,t)}for(let s of t){let t=o.get(s.serializedKey);if(t===void 0){v(s);continue}let c=e.items[t],l=i.normalizeRepeatKey(e.keyFn(c,t),t);if(i.serializeRepeatKey(l)!==s.serializedKey&&console.warn(`[elur] repeat(): hydration key mismatch at index ${t} (${i.deserializeRepeatKey(s.serializedKey)} != ${l}). The SSR item is adopted by position.`),r.has(l)){console.warn(`[elur] repeat(): duplicate key "${l}" during hydration; removing duplicate SSR node.`),v(s);continue}let u=e.renderFn(c,t),d=g({start:s.start,end:s.end},u,n);r.set(l,{start:s.start,end:s.end,cleanup:d??(()=>{})}),a.push(l)}return{state:r,prevOrder:a,cleanup:()=>{for(let e of r.values())e.cleanup()}}}function v(e){let t=e.start.nextSibling;for(;t&&t!==e.end;){let e=t.nextSibling;t.parentNode?.removeChild(t),t=e}e.start.parentNode?.removeChild(e.start),e.end.parentNode?.removeChild(e.end)}function y(e,r){if(r==null||r===!1||r===!0)return;if(Array.isArray(r)){let t=[];for(let n of r){let r=y(e,n);r&&t.push(r)}return t.length?()=>{for(let e=t.length-1;e>=0;e--)t[e]()}:void 0}if(t.isElurTemplate(r))return r._render(e.end.parentNode,e.end);if(n.isElurComponent(r))return r.render()._render(e.end.parentNode,e.end);let i=document.createTextNode(String(r));return e.end.parentNode.insertBefore(i,e.end),()=>i.parentNode?.removeChild(i)}function b(e){let t=e.start.nextSibling;for(;t&&t!==e.end;){if(t.nodeType===Node.TEXT_NODE)return t;t=t.nextSibling}return null}function x(e){let t=e.start.nextSibling;for(;t&&t!==e.end;){let e=t.nextSibling;t.parentNode?.removeChild(t),t=e}}function S(e,t,n,r){let i={index:t,kind:n,message:r};e.onMismatch?.(i);let a=Error(`[elur] Hydration marker mismatch: ${r}`);throw Object.assign(a,{mismatch:i}),a}exports.hydrate=c;
2
+ //# sourceMappingURL=hydrate.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydrate.cjs","names":[],"sources":["../../src/elur/hydrate/index.ts"],"sourcesContent":["import { _captureContextSnapshot, _popComponentContext, _pushComponentContext } from \"../context.js\";\nimport { isElurComponent, type ElurComponent } from \"../lifecycle.js\";\nimport { effect } from \"../reactivity.js\";\nimport { sanitizeUrl } from \"../template/sanitize.js\";\nimport { activateDelegatedEvent, isDelegableEvent } from \"../template/bindings.js\";\nimport {\n isKeyedList,\n isElurTemplate,\n ELUR_RENDER_PROTOCOL,\n ELUR_TEMPLATE_DESCRIPTOR,\n type KEntry,\n type ElurMountHandle,\n type ElurRef,\n type ElurTemplate,\n type TemplateDescriptor,\n} from \"../template/types.js\";\nimport {\n deserializeRepeatKey,\n normalizeRepeatKey,\n serializeRepeatKey,\n type RepeatKey,\n} from \"../template/keyed.js\";\nimport { createKeyedMount, reconcileKeyedList } from \"../template/keyed-diff.js\";\n\nexport interface HydrateOptions {\n mismatch?: \"throw\" | \"warn-remount\" | \"remount\";\n onMismatch?: (error: HydrationMismatch) => void;\n context?: unknown;\n}\n\nexport interface HydrationMismatch {\n index: number;\n kind: \"node\" | \"attribute\" | \"event\" | \"descriptor\" | \"keyed\";\n message: string;\n}\n\ninterface MarkerRange {\n start: Comment;\n end: Comment;\n}\n\ninterface KeyedMarkerRange {\n start: Comment;\n end: Comment;\n serializedKey: string;\n}\n\ninterface ScannedMarkers {\n nodes: Map<number, MarkerRange>;\n attributes: Map<number, Element>;\n events: Map<number, Element>;\n keyed: Map<number, KeyedMarkerRange[]>;\n arrayItems: Map<number, MarkerRange[]>;\n}\n\nexport function hydrate(\n value: ElurTemplate | ElurComponent,\n container: Element,\n options: HydrateOptions = {},\n): ElurMountHandle {\n try {\n if (isElurComponent(value)) return hydrateComponent(value, container, options);\n const descriptor = value[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throwMismatch(options, -1, \"descriptor\", \"Template has no hydration descriptor\");\n const cleanup = hydrateDescriptor(descriptor!, container, options);\n return { unmount: cleanup };\n } catch (error) {\n if (options.mismatch === \"throw\") throw error;\n if (options.mismatch !== \"remount\") console.warn(\"[elur] Hydration mismatch; remounting root:\", error);\n container.replaceChildren();\n const cleanup = isElurComponent(value)\n ? value.render()._render(container, null)\n : value._render(container, null);\n return { unmount: cleanup };\n }\n}\n\nfunction hydrateComponent(\n component: ElurComponent,\n container: Element,\n options: HydrateOptions,\n): ElurMountHandle {\n _pushComponentContext();\n let cleanup = () => { };\n try {\n try {\n component.onInit?.();\n } catch (error) {\n if (component.onError) component.onError(error);\n else throw error;\n }\n const template = component.render();\n const descriptor = template[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throwMismatch(options, -1, \"descriptor\", \"Component template has no hydration descriptor\");\n cleanup = hydrateDescriptor(descriptor!, container, options);\n } finally {\n _popComponentContext();\n }\n const mountCleanup = component.onMount?.();\n return {\n unmount() {\n component.onUnmount?.();\n if (typeof mountCleanup === \"function\") mountCleanup();\n cleanup();\n },\n };\n}\n\nfunction hydrateDescriptor(\n descriptor: TemplateDescriptor,\n root: ParentNode,\n options: HydrateOptions,\n bounds?: MarkerRange,\n): () => void {\n const markers = scanMarkers(root, bounds);\n const cleanups: Array<() => void> = [];\n\n for (let index = 0; index < descriptor.contexts.length; index++) {\n const context = descriptor.contexts[index];\n const value = descriptor.values[index];\n if (context.type === \"event\") {\n const element = markers.events.get(index);\n if (!element) throwMismatch(options, index, \"event\", `Missing event marker ${index}`);\n element!.removeAttribute(`data-elur-e-${index}`);\n cleanups.push(activateEvent(element!, context.eventName, context.modifiers, value));\n continue;\n }\n if (context.type === \"attr\") {\n const element = markers.attributes.get(index);\n if (!element) throwMismatch(options, index, \"attribute\", `Missing attribute marker ${index}`);\n element!.removeAttribute(`data-elur-a-${index}`);\n cleanups.push(activateAttribute(element!, context.attrName, context.url === true, value));\n continue;\n }\n\n const range = markers.nodes.get(index);\n if (!range) throwMismatch(options, index, \"node\", `Missing node marker ${index}`);\n const cleanup = activateNode(range!, value, options, markers.keyed.get(index), markers.arrayItems.get(index));\n if (cleanup) cleanups.push(cleanup);\n }\n\n return () => {\n for (let index = cleanups.length - 1; index >= 0; index--) cleanups[index]();\n };\n}\n\nfunction scanMarkers(root: ParentNode, bounds?: MarkerRange): ScannedMarkers {\n const nodes = new Map<number, MarkerRange>();\n const starts = new Map<number, Comment>();\n const attributes = new Map<number, Element>();\n const events = new Map<number, Element>();\n const keyed = new Map<number, KeyedMarkerRange[]>();\n const arrayItems = new Map<number, MarkerRange[]>();\n const stack: number[] = [];\n const keyedStack: Array<{ start: Comment; serializedKey: string; parentIndex: number }> = [];\n const arrayStack: Array<{ start: Comment; parentIndex: number }> = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);\n let current: Node | null;\n\n while ((current = walker.nextNode())) {\n if (bounds && !isInsideRange(current, bounds)) continue;\n if (current.nodeType === Node.COMMENT_NODE) {\n const comment = current as Comment;\n const startMatch = /^elur-(\\d+)$/.exec(comment.data);\n if (startMatch) {\n const index = Number(startMatch[1]);\n if (stack.length === 0) starts.set(index, comment);\n stack.push(index);\n continue;\n }\n const endMatch = /^elur-end-(\\d+)$/.exec(comment.data);\n if (endMatch) {\n const index = Number(endMatch[1]);\n const active = stack.pop();\n if (active === index && stack.length === 0) {\n const start = starts.get(index);\n if (start) nodes.set(index, { start, end: comment });\n }\n continue;\n }\n const keyedStartMatch = /^elur-ki:(.+)$/.exec(comment.data);\n if (keyedStartMatch) {\n const serializedKey = keyedStartMatch[1];\n if (keyedStack.length === 0 && stack.length === 1) {\n keyedStack.push({ start: comment, serializedKey, parentIndex: stack[stack.length - 1] });\n } else {\n keyedStack.push({ start: comment, serializedKey, parentIndex: -1 });\n }\n continue;\n }\n if (comment.data === \"elur-ke\") {\n const active = keyedStack.pop();\n if (active) {\n if (active.parentIndex >= 0) {\n const list = keyed.get(active.parentIndex) ?? [];\n list.push({ start: active.start, end: comment, serializedKey: active.serializedKey });\n keyed.set(active.parentIndex, list);\n }\n } else {\n throw new Error(\"[elur] Hydration marker mismatch: orphan keyed end marker (elur-ke)\");\n }\n continue;\n }\n if (comment.data === \"elur-ai\") {\n if (arrayStack.length === 0 && stack.length === 1) {\n arrayStack.push({ start: comment, parentIndex: stack[stack.length - 1] });\n } else {\n arrayStack.push({ start: comment, parentIndex: -1 });\n }\n continue;\n }\n if (comment.data === \"elur-aiend\") {\n const active = arrayStack.pop();\n if (active && active.parentIndex >= 0) {\n const list = arrayItems.get(active.parentIndex) ?? [];\n list.push({ start: active.start, end: comment });\n arrayItems.set(active.parentIndex, list);\n }\n continue;\n }\n continue;\n }\n if (stack.length > 0) continue;\n const element = current as Element;\n for (const attribute of Array.from(element.attributes)) {\n const eventMatch = /^data-elur-e-(\\d+)$/.exec(attribute.name);\n if (eventMatch) events.set(Number(eventMatch[1]), element);\n const attributeMatch = /^data-elur-a-(\\d+)$/.exec(attribute.name);\n if (attributeMatch) attributes.set(Number(attributeMatch[1]), element);\n }\n }\n\n return { nodes, attributes, events, keyed, arrayItems };\n}\n\nfunction isInsideRange(node: Node, range: MarkerRange): boolean {\n const domRange = document.createRange();\n domRange.setStartAfter(range.start);\n domRange.setEndBefore(range.end);\n return domRange.intersectsNode(node);\n}\n\nfunction activateEvent(\n element: Element,\n eventName: string,\n modifiers: readonly string[],\n value: unknown,\n): () => void {\n if (typeof value !== \"function\") throw new TypeError(`Event \"${eventName}\" requires a function`);\n const rawHandler = value as EventListener;\n\n // Use global delegation for delegable events without capture/once mods,\n // matching the mount-time behavior in bindings.ts. The element must be\n // connected to the document for delegation to work (events bubble to\n // document where the delegated listener is registered).\n const canDelegate =\n isDelegableEvent(eventName) &&\n !modifiers.includes(\"capture\") &&\n !modifiers.includes(\"once\") &&\n document.body.contains(element);\n\n if (canDelegate) {\n return activateDelegatedEvent(element, eventName, modifiers, rawHandler);\n }\n\n // Non-delegable events or disconnected elements: use addEventListener directly.\n const options: AddEventListenerOptions = {\n once: modifiers.includes(\"once\"),\n capture: modifiers.includes(\"capture\"),\n passive: modifiers.includes(\"passive\"),\n };\n const listener = (event: Event) => {\n if (modifiers.includes(\"prevent\")) event.preventDefault();\n if (modifiers.includes(\"stop\")) event.stopPropagation();\n if (modifiers.includes(\"self\") && event.target !== event.currentTarget) return;\n rawHandler(event);\n };\n element.addEventListener(eventName, listener, options);\n return () => element.removeEventListener(eventName, listener, options);\n}\n\nfunction activateAttribute(\n element: Element,\n name: string,\n url: boolean,\n value: unknown,\n): () => void {\n if (name === \"ref\") {\n const reference = value as ElurRef<Element>;\n reference.el = element;\n return () => { reference.el = null; };\n }\n\n const isProperty = (name === \"value\" || name === \"checked\" || name === \"selected\") && name in element;\n let firstRun = true;\n let pendingSync = false;\n const update = (resolved: unknown) => {\n if (isProperty) {\n if (!firstRun) {\n (element as any)[name] = resolved ?? \"\";\n } else {\n // Interaction before hydration: the DOM may hold a value the\n // user (or a hydration race with lazy island directives like\n // \"visible\") wrote before the binding activated. The DOM is\n // authoritative; keep it and propagate it to reactive model\n // sources once every handler is attached (microtask) so a\n // late @input/@change listener picks up the real value.\n const current = (element as any)[name];\n const model = resolved ?? \"\";\n if (String(current) !== String(model) && !pendingSync) {\n pendingSync = true;\n const eventName = name === \"checked\" || name === \"selected\" ? \"change\" : \"input\";\n queueMicrotask(() => {\n pendingSync = false;\n element.dispatchEvent(new Event(eventName, { bubbles: true }));\n });\n }\n }\n } else if (resolved === null || resolved === undefined || resolved === false) {\n element.removeAttribute(name);\n } else {\n const serialized = url ? sanitizeUrl(String(resolved)) : String(resolved);\n element.setAttribute(name, serialized);\n }\n firstRun = false;\n };\n\n if (typeof value === \"function\") {\n return effect(() => update((value as () => unknown)()));\n }\n update(value);\n return () => { };\n}\n\nfunction activateNode(\n range: MarkerRange,\n value: unknown,\n options: HydrateOptions,\n keyedItems?: KeyedMarkerRange[],\n arrayItems?: MarkerRange[],\n): (() => void) | undefined {\n if (typeof value !== \"function\") return hydrateNodeValue(range, value, options, keyedItems, arrayItems);\n\n let firstRun = true;\n let nestedCleanup: (() => void) | undefined;\n let textNode = findTextNode(range);\n let keyed: { state: Map<RepeatKey, KEntry>; prevOrder: RepeatKey[] } | null = null;\n const ctxSnapshot = _captureContextSnapshot();\n const keyedMount = createKeyedMount(ctxSnapshot);\n\n const warnDuplicate = (key: RepeatKey) => {\n console.warn(`[elur] repeat(): duplicate key \"${key}\". Keys must be unique; the previous entry leaks (orphaned nodes + live effects).`);\n };\n\n const dispose = effect(() => {\n const resolved = (value as () => unknown)();\n\n if (isKeyedList(resolved)) {\n if (firstRun && !keyed) {\n // First resolution is a keyed list: adopt the SSR markers when\n // present. Afterwards we converge with the current model, which\n // handles count/ordering drift without recreating surviving nodes.\n const adopted = adoptKeyedRange(resolved, keyedItems, options);\n keyed = { state: adopted.state, prevOrder: adopted.prevOrder };\n nestedCleanup = adopted.cleanup;\n reconcileKeyedList({\n zoneStart: range.start,\n anchor: range.end,\n state: keyed.state,\n prevOrder: keyed.prevOrder,\n list: resolved,\n mount: keyedMount,\n ctxSnapshot,\n onDuplicateKey: warnDuplicate,\n });\n textNode = null;\n firstRun = false;\n return;\n }\n if (!keyed) {\n // The binding became keyed after another value: the SSR markers\n // were already consumed (or never existed), so mount fresh.\n nestedCleanup?.();\n clearRange(range);\n keyed = { state: new Map(), prevOrder: [] };\n nestedCleanup = () => {\n for (const entry of keyed!.state.values()) entry.cleanup();\n };\n }\n reconcileKeyedList({\n zoneStart: range.start,\n anchor: range.end,\n state: keyed.state,\n prevOrder: keyed.prevOrder,\n list: resolved,\n mount: keyedMount,\n ctxSnapshot,\n onDuplicateKey: warnDuplicate,\n });\n textNode = null;\n firstRun = false;\n return;\n }\n\n // Non-keyed value: tear down any keyed zone first.\n if (keyed) {\n nestedCleanup?.();\n clearRange(range);\n keyed = null;\n nestedCleanup = undefined;\n }\n\n if (typeof resolved === \"string\" || typeof resolved === \"number\" || typeof resolved === \"bigint\") {\n if (!textNode) {\n textNode = document.createTextNode(String(resolved));\n range.end.parentNode!.insertBefore(textNode, range.end);\n } else if (textNode.nodeValue !== String(resolved)) {\n textNode.nodeValue = String(resolved);\n }\n } else if (firstRun) {\n nestedCleanup = hydrateNodeValue(range, resolved, options, keyedItems, arrayItems);\n } else {\n nestedCleanup?.();\n clearRange(range);\n nestedCleanup = mountNodeValue(range, resolved);\n textNode = findTextNode(range);\n }\n firstRun = false;\n });\n\n return () => {\n dispose();\n nestedCleanup?.();\n };\n}\n\nfunction hydrateNodeValue(\n range: MarkerRange,\n value: unknown,\n options: HydrateOptions,\n keyedItems?: KeyedMarkerRange[],\n arrayItems?: MarkerRange[],\n): (() => void) | undefined {\n if (isKeyedList(value)) {\n const ctxSnapshot = _captureContextSnapshot();\n const adopted = adoptKeyedRange(value, keyedItems, options);\n reconcileKeyedList({\n zoneStart: range.start,\n anchor: range.end,\n state: adopted.state,\n prevOrder: adopted.prevOrder,\n list: value,\n mount: createKeyedMount(ctxSnapshot),\n ctxSnapshot,\n onDuplicateKey: (key) => {\n console.warn(`[elur] repeat(): duplicate key \"${key}\". Keys must be unique; the previous entry leaks (orphaned nodes + live effects).`);\n },\n });\n return adopted.cleanup;\n }\n if (Array.isArray(value)) {\n const cleanups: Array<() => void> = [];\n const hasMarkers = arrayItems !== undefined && arrayItems.length > 0;\n for (let index = 0; index < value.length; index++) {\n const item = value[index];\n const itemBounds = arrayItems?.[index];\n if (hasMarkers && itemBounds) {\n // Hydrate each item within its own SSR-delimited range so\n // repeated marker indices across items never collide.\n const cleanup = hydrateNodeValue(itemBounds, item, options);\n if (cleanup) cleanups.push(cleanup);\n } else if (hasMarkers) {\n // Client item with no SSR slot: mount it fresh at the end.\n const cleanup = mountNodeValue(range, item);\n if (cleanup) cleanups.push(cleanup);\n } else {\n const cleanup = hydrateNodeValue(range, item, options);\n if (cleanup) cleanups.push(cleanup);\n }\n }\n return cleanups.length ? () => { for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i](); } : undefined;\n }\n if (isElurTemplate(value)) {\n const descriptor = value[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throwMismatch(options, -1, \"descriptor\", \"Nested template has no hydration descriptor\");\n return hydrateDescriptor(descriptor!, range.start.parentNode as ParentNode, options, range);\n }\n if (isElurComponent(value)) {\n _pushComponentContext();\n let result: (() => void) | undefined;\n try {\n try {\n value.onInit?.();\n } catch (error) {\n if (value.onError) value.onError(error);\n else throw error;\n }\n const template = value.render();\n const descriptor = template[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throwMismatch(options, -1, \"descriptor\", \"Nested component has no hydration descriptor\");\n const cleanup = hydrateDescriptor(descriptor!, range.start.parentNode as ParentNode, options, range);\n const mountCleanup = value.onMount?.();\n result = () => {\n value.onUnmount?.();\n if (typeof mountCleanup === \"function\") mountCleanup();\n cleanup();\n };\n } finally {\n _popComponentContext();\n }\n return result;\n }\n if (value != null && typeof value === \"object\") {\n const protocol = (value as Record<PropertyKey, unknown>)[ELUR_RENDER_PROTOCOL] as\n | { hydrateDom?: (ctx: import(\"../template/types.js\").HydrationProtocolContext) => (() => void) | void }\n | undefined;\n if (protocol?.hydrateDom) {\n return protocol.hydrateDom({\n parent: range.start.parentNode!,\n bounds: range,\n context: options.context,\n render: (nested) => hydrateNodeValue(range, nested, options),\n }) ?? undefined;\n }\n }\n return undefined;\n}\n\nfunction adoptKeyedRange(\n list: import(\"../template/types.js\").KeyedList,\n keyedItems: KeyedMarkerRange[] | undefined,\n options: HydrateOptions,\n): { state: Map<RepeatKey, KEntry>; prevOrder: RepeatKey[]; cleanup: () => void } {\n const state = new Map<RepeatKey, KEntry>();\n const prevOrder: RepeatKey[] = [];\n\n if (!keyedItems || keyedItems.length === 0) {\n return { state, prevOrder, cleanup: () => { } };\n }\n\n const clientByKey = new Map<string, number>();\n for (let j = 0; j < list.items.length; j++) {\n const key = normalizeRepeatKey(list.keyFn(list.items[j], j), j);\n const serialized = serializeRepeatKey(key);\n if (clientByKey.has(serialized)) {\n console.warn(\n `[elur] repeat(): duplicate client key \"${key}\" during hydration. ` +\n \"Keys must be unique; entries after the first leak.\",\n );\n }\n clientByKey.set(serialized, j);\n }\n\n for (const marker of keyedItems) {\n const clientIndex = clientByKey.get(marker.serializedKey);\n if (clientIndex === undefined) {\n // SSR item not present in the client model → remove its DOM.\n removeKeyedMarker(marker);\n continue;\n }\n const item = list.items[clientIndex];\n const key = normalizeRepeatKey(list.keyFn(item, clientIndex), clientIndex);\n if (serializeRepeatKey(key) !== marker.serializedKey) {\n console.warn(\n `[elur] repeat(): hydration key mismatch at index ${clientIndex} ` +\n `(${deserializeRepeatKey(marker.serializedKey)} != ${key}). The SSR item is adopted by position.`,\n );\n }\n if (state.has(key)) {\n console.warn(`[elur] repeat(): duplicate key \"${key}\" during hydration; removing duplicate SSR node.`);\n removeKeyedMarker(marker);\n continue;\n }\n const rendered = list.renderFn(item, clientIndex);\n const cleanup = hydrateNodeValue(\n { start: marker.start, end: marker.end },\n rendered,\n options,\n );\n state.set(key, { start: marker.start, end: marker.end, cleanup: cleanup ?? (() => { }) });\n prevOrder.push(key);\n }\n\n return {\n state,\n prevOrder,\n cleanup: () => {\n for (const entry of state.values()) entry.cleanup();\n },\n };\n}\n\nfunction removeKeyedMarker(marker: KeyedMarkerRange): void {\n let node: Node | null = marker.start.nextSibling;\n while (node && node !== marker.end) {\n const next = node.nextSibling;\n node.parentNode?.removeChild(node);\n node = next;\n }\n marker.start.parentNode?.removeChild(marker.start);\n marker.end.parentNode?.removeChild(marker.end);\n}\n\nfunction mountNodeValue(range: MarkerRange, value: unknown): (() => void) | undefined {\n if (value === null || value === undefined || value === false || value === true) return undefined;\n if (Array.isArray(value)) {\n const cleanups: Array<() => void> = [];\n for (const item of value) {\n const cleanup = mountNodeValue(range, item);\n if (cleanup) cleanups.push(cleanup);\n }\n return cleanups.length ? () => { for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i](); } : undefined;\n }\n if (isElurTemplate(value)) return value._render(range.end.parentNode!, range.end);\n if (isElurComponent(value)) return value.render()._render(range.end.parentNode!, range.end);\n const node = document.createTextNode(String(value));\n range.end.parentNode!.insertBefore(node, range.end);\n return () => node.parentNode?.removeChild(node);\n}\n\nfunction findTextNode(range: MarkerRange): Text | null {\n let node = range.start.nextSibling;\n while (node && node !== range.end) {\n if (node.nodeType === Node.TEXT_NODE) return node as Text;\n node = node.nextSibling;\n }\n return null;\n}\n\nfunction clearRange(range: MarkerRange): void {\n let node = range.start.nextSibling;\n while (node && node !== range.end) {\n const next = node.nextSibling;\n node.parentNode?.removeChild(node);\n node = next;\n }\n}\n\nfunction throwMismatch(\n options: HydrateOptions,\n index: number,\n kind: HydrationMismatch[\"kind\"],\n message: string,\n): never {\n const mismatch = { index, kind, message } satisfies HydrationMismatch;\n options.onMismatch?.(mismatch);\n const error = new Error(`[elur] Hydration marker mismatch: ${message}`);\n Object.assign(error, { mismatch });\n throw error;\n}"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type ElurComponent } from "../lifecycle.js";
2
+ import { type ElurMountHandle, type ElurTemplate } from "../template/types.js";
3
+ export interface HydrateOptions {
4
+ mismatch?: "throw" | "warn-remount" | "remount";
5
+ onMismatch?: (error: HydrationMismatch) => void;
6
+ context?: unknown;
7
+ }
8
+ export interface HydrationMismatch {
9
+ index: number;
10
+ kind: "node" | "attribute" | "event" | "descriptor" | "keyed";
11
+ message: string;
12
+ }
13
+ export declare function hydrate(value: ElurTemplate | ElurComponent, container: Element, options?: HydrateOptions): ElurMountHandle;
@@ -0,0 +1,13 @@
1
+ import { type ElurComponent } from "../lifecycle.js";
2
+ import { type ElurMountHandle, type ElurTemplate } from "../template/types.js";
3
+ export interface HydrateOptions {
4
+ mismatch?: "throw" | "warn-remount" | "remount";
5
+ onMismatch?: (error: HydrationMismatch) => void;
6
+ context?: unknown;
7
+ }
8
+ export interface HydrationMismatch {
9
+ index: number;
10
+ kind: "node" | "attribute" | "event" | "descriptor" | "keyed";
11
+ message: string;
12
+ }
13
+ export declare function hydrate(value: ElurTemplate | ElurComponent, container: Element, options?: HydrateOptions): ElurMountHandle;