@estjs/template 0.0.15 → 0.0.16-beta.2

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.
@@ -1,688 +1,461 @@
1
- import { error, isHTMLElement, isPrimitive, isFalsy, isNull, isObject, isArray, isHtmlInputElement, isHtmlSelectElement, isHtmlTextAreaElement, isFunction, hasChanged, isPromise, coerceArray, startsWith, isString, isBrowser, normalizeClassName, camelCase, capitalize, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isUndefined, isNumber, isTextNode } from '@estjs/shared';
2
- import { effect, shallowReactive, isSignal, isComputed, signal, memoEffect, untrack } from '@estjs/signals';
1
+ import { getActiveScope, runWithScope, onCleanup, __objRest, createScope, disposeScope, __async } from './chunk-3E4EK64L.dev.esm.js';
2
+ import { normalizeClassName, isObject, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isString, isArray, camelCase, capitalize, isBrowser, error, isPromise, isFunction, isOn, coerceArray } from '@estjs/shared';
3
+ import { effect, shallowReactive, isSignal, isComputed, signal } from '@estjs/signals';
3
4
 
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __spreadValues = (a, b) => {
10
- for (var prop in b || (b = {}))
11
- if (__hasOwnProp.call(b, prop))
12
- __defNormalProp(a, prop, b[prop]);
13
- if (__getOwnPropSymbols)
14
- for (var prop of __getOwnPropSymbols(b)) {
15
- if (__propIsEnum.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- }
18
- return a;
19
- };
20
- var __async = (__this, __arguments, generator) => {
21
- return new Promise((resolve, reject) => {
22
- var fulfilled = (value) => {
23
- try {
24
- step(generator.next(value));
25
- } catch (e) {
26
- reject(e);
27
- }
28
- };
29
- var rejected = (value) => {
30
- try {
31
- step(generator.throw(value));
32
- } catch (e) {
33
- reject(e);
34
- }
35
- };
36
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
- step((generator = generator.apply(__this, __arguments)).next());
38
- });
39
- };
40
- var LIFECYCLE = {
41
- mount: "mount",
42
- destroy: "destroy",
43
- update: "update"
44
- };
45
- function registerScopedHook(scope, listKey, hook) {
46
- let hookList = scope[listKey];
47
- if (!hookList) {
48
- hookList = scope[listKey] = [];
49
- }
50
- if (!hookList.includes(hook)) {
51
- hookList.push(hook);
5
+ // src/constants.ts
6
+ var SPREAD_NAME = "_$spread$";
7
+ var REF_KEY = "ref";
8
+ var KEY_PROP = "key";
9
+ var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
10
+ var XLINK_NAMESPACE = "http://www.w3.org/2000/xlink";
11
+ var XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
12
+ var FRAGMENT_COMPONENT = /* @__PURE__ */ Symbol("Fragment Component" );
13
+ var PORTAL_COMPONENT = /* @__PURE__ */ Symbol("Portal Component" );
14
+ var SUSPENSE_COMPONENT = /* @__PURE__ */ Symbol("Suspense Component" );
15
+ var FOR_COMPONENT = /* @__PURE__ */ Symbol("For Component" );
16
+ function patchAttr(el, key, prev, next2) {
17
+ if (key === KEY_PROP) {
18
+ if (next2 == null) {
19
+ el.removeAttribute(key);
20
+ } else {
21
+ el.setAttribute(key, String(next2));
22
+ }
23
+ return;
52
24
  }
53
- }
54
- function executeHooks(hooks, scopeId2, phase) {
55
- const len = hooks.length;
56
- if (len === 0) return;
57
- let pending;
58
- for (let i = 0; i < len; i++) {
59
- try {
60
- const result = hooks[i]();
61
- if (isPromise(result)) {
62
- const safePromise = result.catch((error_) => {
63
- if (true) {
64
- error(`Scope(${scopeId2}): Async ${phase} hook rejected:`, error_);
65
- }
66
- });
67
- (pending != null ? pending : pending = []).push(safePromise);
25
+ if (key === SPREAD_NAME) {
26
+ const prevObj = isObject(prev) ? prev : null;
27
+ const nextObj = isObject(next2) ? next2 : null;
28
+ {
29
+ if (next2 != null && !nextObj) {
30
+ warn("spread attribute must be an object");
68
31
  }
69
- } catch (error_) {
70
- {
71
- error(`Scope(${scopeId2}): Error in ${phase} hook:`, error_);
32
+ }
33
+ if (prevObj) {
34
+ for (const attrKey in prevObj) {
35
+ if (attrKey === SPREAD_NAME) {
36
+ {
37
+ warn("nested spread attributes are ignored");
38
+ }
39
+ continue;
40
+ }
41
+ if (!nextObj || !(attrKey in nextObj)) {
42
+ patchAttr(el, attrKey, prevObj[attrKey], null);
43
+ }
72
44
  }
73
45
  }
74
- }
75
- if (!pending) return;
76
- return Promise.all(pending).then(() => void 0);
77
- }
78
- function onMount(hook) {
79
- const scope = getActiveScope();
80
- if (!scope) {
81
- error("onMount() must be called within a scope");
82
- return;
83
- }
84
- if (scope.isMounted) {
85
- try {
86
- const result = hook();
87
- if (isPromise(result)) {
88
- result.catch((error_) => {
89
- if (true) error(`Scope(${scope.id}): Async ${LIFECYCLE.mount} hook rejected:`, error_);
90
- });
46
+ if (nextObj) {
47
+ for (const attrKey in nextObj) {
48
+ if (attrKey === SPREAD_NAME) {
49
+ {
50
+ warn("nested spread attributes are ignored");
51
+ }
52
+ continue;
53
+ }
54
+ patchAttr(el, attrKey, prevObj == null ? void 0 : prevObj[attrKey], nextObj[attrKey]);
91
55
  }
92
- } catch (error_) {
93
- error(`Scope(${scope.id}): Error in ${LIFECYCLE.mount} hook:`, error_);
94
56
  }
95
57
  return;
96
58
  }
97
- registerScopedHook(scope, "onMount", hook);
98
- }
99
- function onUpdate(hook) {
100
- const scope = getActiveScope();
101
- if (!scope) {
102
- error("onUpdate() must be called within a scope");
59
+ const elementIsSVG = (el == null ? void 0 : el.namespaceURI) === SVG_NAMESPACE;
60
+ const isXlink = elementIsSVG && key.startsWith("xlink:");
61
+ const isXmlns = elementIsSVG && key.startsWith("xmlns:");
62
+ const isBoolean = isSpecialBooleanAttr(key) || isBooleanAttr(key);
63
+ if (prev === next2) {
103
64
  return;
104
65
  }
105
- registerScopedHook(scope, "onUpdate", hook);
106
- }
107
- function onDestroy(hook) {
108
- const scope = getActiveScope();
109
- if (!scope) {
110
- error("onDestroy() must be called within a scope");
66
+ if (key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110) {
111
67
  return;
112
68
  }
113
- registerScopedHook(scope, "onDestroy", hook);
114
- }
115
- function triggerMountHooks(scope) {
116
- var _a2;
117
- if (scope.isDestroyed || !((_a2 = scope.onMount) == null ? void 0 : _a2.length)) {
118
- scope.isMounted = true;
69
+ const lowerKey = key.toLowerCase();
70
+ if (lowerKey === "innerhtml" || lowerKey === "srcdoc") {
71
+ {
72
+ warn(`${key} updates are ignored by patchAttr`);
73
+ }
119
74
  return;
120
75
  }
121
- const mountHooks = scope.onMount;
122
- const result = runWithScope(scope, () => executeHooks(mountHooks, scope.id, LIFECYCLE.mount));
123
- mountHooks.length = 0;
124
- scope.isMounted = true;
125
- return result;
126
- }
127
- function triggerUpdateHooks(scope) {
128
- var _a2;
129
- if (scope.isDestroyed || !((_a2 = scope.onUpdate) == null ? void 0 : _a2.length)) return;
130
- const updateHooks = scope.onUpdate;
131
- const result = runWithScope(scope, () => executeHooks(updateHooks, scope.id, "update"));
132
- updateHooks.length = 0;
133
- return result;
134
- }
135
- function triggerDestroyHooks(scope) {
136
- var _a2;
137
- if (scope.isDestroyed || !((_a2 = scope.onDestroy) == null ? void 0 : _a2.length)) return;
138
- return runWithScope(scope, () => executeHooks(scope.onDestroy, scope.id, "destroy"));
139
- }
140
-
141
- // src/scope.ts
142
- var activeScope = null;
143
- var scopeId = 0;
144
- function getActiveScope() {
145
- return activeScope;
146
- }
147
- function setActiveScope(scope) {
148
- activeScope = scope;
149
- }
150
- function createScope(parent = activeScope) {
151
- const scope = {
152
- id: ++scopeId,
153
- parent,
154
- children: null,
155
- provides: null,
156
- cleanup: null,
157
- onMount: null,
158
- onUpdate: null,
159
- onDestroy: null,
160
- isMounted: false,
161
- isDestroyed: false
162
- };
163
- if (parent) {
164
- if (!parent.children) {
165
- parent.children = [];
76
+ if (next2 == null) {
77
+ if (isXlink) {
78
+ el.removeAttributeNS(XLINK_NAMESPACE, key.slice(6));
79
+ } else if (isXmlns) {
80
+ const localName = key.slice(6);
81
+ el.removeAttributeNS(XMLNS_NAMESPACE, localName);
82
+ } else {
83
+ el.removeAttribute(key);
166
84
  }
167
- parent.children.push(scope);
168
- }
169
- return scope;
170
- }
171
- function runWithScope(scope, fn) {
172
- const prevScope = activeScope;
173
- activeScope = scope;
174
- try {
175
- return fn();
176
- } finally {
177
- activeScope = prevScope;
85
+ return;
178
86
  }
179
- }
180
- function disposeScope(scope) {
181
- var _a2, _b, _c;
182
- if (!scope || scope.isDestroyed) {
87
+ if (isBoolean) {
88
+ if (includeBooleanAttr(next2)) {
89
+ el.setAttribute(key, "");
90
+ } else {
91
+ el.removeAttribute(key);
92
+ }
183
93
  return;
184
94
  }
185
- const parentScope = scope.parent;
186
- if (scope.children) {
187
- for (const child of scope.children) {
188
- disposeScope(child);
95
+ const attrValue = isSymbol(next2) ? String(next2) : next2;
96
+ const isUrlAttr = lowerKey === "href" || lowerKey === "src" || lowerKey === "xlink:href" || lowerKey === "action" || lowerKey === "formaction" || lowerKey === "poster";
97
+ if (isUrlAttr && isString(attrValue)) {
98
+ const v = attrValue.trim().toLowerCase();
99
+ if (v.startsWith("javascript:") || v.startsWith("data:")) {
100
+ return;
189
101
  }
190
- scope.children.length = 0;
191
102
  }
192
- if ((_a2 = scope.onDestroy) == null ? void 0 : _a2.length) {
193
- triggerDestroyHooks(scope);
194
- scope.onDestroy.length = 0;
103
+ if (isXlink) {
104
+ el.setAttributeNS(XLINK_NAMESPACE, key, String(attrValue));
105
+ return;
106
+ }
107
+ if (isXmlns) {
108
+ el.setAttributeNS(XMLNS_NAMESPACE, key, String(attrValue));
109
+ return;
195
110
  }
196
- if ((_b = scope.cleanup) == null ? void 0 : _b.length) {
197
- for (const fn of scope.cleanup) {
111
+ if (elementIsSVG) {
112
+ el.setAttribute(key, String(attrValue));
113
+ } else {
114
+ if (key in el) {
198
115
  try {
199
- fn();
200
- } catch (error_) {
201
- {
202
- error(`Scope(${scope.id}): Error in cleanup:`, error_);
203
- }
116
+ el[key] = attrValue;
117
+ } catch (e) {
118
+ el.setAttribute(key, String(attrValue));
204
119
  }
120
+ } else {
121
+ el.setAttribute(key, String(attrValue));
205
122
  }
206
- scope.cleanup.length = 0;
207
- }
208
- if (parentScope == null ? void 0 : parentScope.children) {
209
- const idx = parentScope.children.indexOf(scope);
210
- if (idx !== -1) {
211
- parentScope.children.splice(idx, 1);
212
- }
213
- }
214
- (_c = scope.provides) == null ? void 0 : _c.clear();
215
- if (scope.onMount) scope.onMount.length = 0;
216
- if (scope.onUpdate) scope.onUpdate.length = 0;
217
- scope.parent = null;
218
- scope.isDestroyed = true;
219
- if (activeScope === scope) {
220
- activeScope = parentScope;
221
123
  }
222
124
  }
223
- function onCleanup(fn) {
224
- const scope = activeScope;
225
- if (!scope) {
226
- {
227
- error("onCleanup() must be called within a scope");
228
- }
125
+ function patchClass(el, prev, next2, isSVG = false) {
126
+ if (prev === next2) {
229
127
  return;
230
128
  }
231
- if (!scope.cleanup) {
232
- scope.cleanup = [];
129
+ const normalizedNext = normalizeClass(next2);
130
+ if (!normalizedNext) {
131
+ el.removeAttribute("class");
132
+ return;
233
133
  }
234
- scope.cleanup.push(fn);
235
- }
236
-
237
- // src/constants.ts
238
- var EVENT_PREFIX = "on";
239
- var SPREAD_NAME = "_$spread$";
240
- var REF_KEY = "ref";
241
- var KEY_PROP = "key";
242
- var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
243
- var XLINK_NAMESPACE = "http://www.w3.org/2000/xlink";
244
- var XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
245
- var NORMAL_COMPONENT = /* @__PURE__ */ Symbol("Normal Component" );
246
- var FRAGMENT_COMPONENT = /* @__PURE__ */ Symbol("Fragment Component" );
247
- var PORTAL_COMPONENT = /* @__PURE__ */ Symbol("Portal Component" );
248
- var SUSPENSE_COMPONENT = /* @__PURE__ */ Symbol("Suspense Component" );
249
- var FOR_COMPONENT = /* @__PURE__ */ Symbol("For Component" );
250
- var MAX_KEY_LENGTH = 1e3;
251
- var componentKeyPrefixCache = /* @__PURE__ */ new WeakMap();
252
- function getComponentKey(type) {
253
- let prefix = componentKeyPrefixCache.get(type);
254
- if (!prefix) {
255
- const name = type.name || "anonymous";
256
- const hash = simpleHash(type.toString()).toString(36);
257
- prefix = `${name}_${hash}`;
258
- componentKeyPrefixCache.set(type, prefix);
259
- }
260
- return prefix;
261
- }
262
- function simpleHash(str) {
263
- let hash = 0;
264
- const len = str.length < 100 ? str.length : 100;
265
- for (let i = 0; i < len; i++) {
266
- hash = Math.trunc((hash << 5) - hash + str.charCodeAt(i));
134
+ const normalizedPrev = isString(prev) ? prev : normalizeClass(prev);
135
+ if (normalizedPrev === normalizedNext) {
136
+ return;
267
137
  }
268
- return hash < 0 ? -hash : hash;
269
- }
270
- var symbolIdCounter = 0;
271
- function normalizeKey(key) {
272
- if (isFalsy(key)) {
273
- return void 0;
138
+ if (isSVG) {
139
+ el.setAttribute("class", normalizedNext);
140
+ } else {
141
+ el.className = normalizedNext;
274
142
  }
275
- if (isString(key)) {
276
- if (key.length <= MAX_KEY_LENGTH) {
277
- return key;
143
+ }
144
+ var normalizeClass = normalizeClassName;
145
+ var importantRE = /\s*!important$/;
146
+ var prefixes = ["Webkit", "Moz", "ms"];
147
+ var prefixCache = {};
148
+ function patchStyle(el, prev, next2) {
149
+ const style = el.style;
150
+ if (next2 && isString(next2)) {
151
+ if (prev !== next2) {
152
+ style.cssText = next2;
278
153
  }
279
- {
280
- warn(
281
- `[Key System] Key length exceeds ${MAX_KEY_LENGTH} characters. Consider using a shorter identifier.`
282
- );
154
+ return;
155
+ }
156
+ if (!next2) {
157
+ if (prev) {
158
+ el.removeAttribute("style");
283
159
  }
284
- return `${key.slice(0, MAX_KEY_LENGTH - 10)}_${simpleHash(key).toString(36)}`;
160
+ return;
285
161
  }
286
- if (isNumber(key)) {
287
- {
288
- if (key !== key) {
289
- warn("[Key System] NaN cannot be used as a key");
290
- return void 0;
162
+ if (prev && !isString(prev)) {
163
+ const prevObj = prev;
164
+ for (const key in prevObj) {
165
+ if (!next2 || next2[key] == null) {
166
+ setStyle(style, key, "");
291
167
  }
292
- if (!Number.isFinite(key)) {
293
- warn("[Key System] Infinity cannot be used as a key");
294
- return void 0;
168
+ }
169
+ } else if (prev && isString(prev)) {
170
+ const declRE = /(?:^|;)\s*([a-z][a-z\d-]*)\s*:/gi;
171
+ let match;
172
+ while ((match = declRE.exec(prev)) !== null) {
173
+ const key = match[1].trim();
174
+ if (key && next2 && isObject(next2) && next2[key] == null) {
175
+ setStyle(style, key, "");
295
176
  }
296
177
  }
297
- return String(key);
298
178
  }
299
- if (isSymbol(key)) {
300
- const globalKey = Symbol.keyFor(key);
301
- if (globalKey) {
302
- return `_s.${globalKey}`;
179
+ if (next2 && !isString(next2)) {
180
+ const nextObj = next2;
181
+ for (const key in nextObj) {
182
+ const value = nextObj[key];
183
+ if ((!prev || isString(prev) || prev[key] !== value) && value != null) {
184
+ setStyle(style, key, value);
185
+ }
303
186
  }
304
- const desc = key.description;
305
- return desc ? `_s.${desc}` : `${symbolIdCounter++}`;
306
187
  }
307
- return String(key);
308
188
  }
309
- var NODE_KEY_SYMBOL = /* @__PURE__ */ Symbol("essor.key");
310
- function setNodeKey(node, key) {
311
- if (isComponent(node)) {
312
- return;
313
- }
314
- if (!node || node.nodeType === Node.DOCUMENT_NODE) {
315
- {
316
- warn("[Key System] Cannot set key on invalid node");
189
+ function setStyle(style, name, val) {
190
+ if (isArray(val)) {
191
+ for (const element of val) {
192
+ setStyle(style, name, element);
317
193
  }
318
194
  return;
319
195
  }
320
- const normalizedKey = normalizeKey(key);
321
- if (isFalsy(normalizedKey)) {
322
- delete node[NODE_KEY_SYMBOL];
323
- } else {
324
- node[NODE_KEY_SYMBOL] = normalizedKey;
196
+ if (val == null || val === "") {
197
+ val = "";
325
198
  }
326
- }
327
- function getNodeKey(node) {
328
- if (!node) return void 0;
329
- return isComponent(node) ? node.key : node[NODE_KEY_SYMBOL];
330
- }
331
-
332
- // src/utils/node.ts
333
- function normalizeNode(node) {
334
- if (isHTMLElement(node)) {
335
- return node;
199
+ if (name.startsWith("--")) {
200
+ style.setProperty(name, val);
201
+ return;
336
202
  }
337
- if (isPrimitive(node)) {
338
- const textContent = isFalsy(node) ? "" : String(node);
339
- return document.createTextNode(textContent);
203
+ const prefixed = autoPrefix(style, name);
204
+ if (isString(val) && importantRE.test(val)) {
205
+ style.setProperty(camelCase(prefixed), val.replace(importantRE, ""), "important");
206
+ } else {
207
+ style[prefixed] = val;
340
208
  }
341
- return node;
342
209
  }
343
- function isSameNode(a, b) {
344
- const keyA = getNodeKey(a);
345
- const keyB = getNodeKey(b);
346
- if (keyA !== keyB) {
347
- return false;
348
- }
349
- const aIsComponent = isComponent(a);
350
- const bIsComponent = isComponent(b);
351
- if (aIsComponent && bIsComponent) {
352
- return a.component === b.component;
353
- }
354
- if (aIsComponent !== bIsComponent) {
355
- return false;
356
- }
357
- if (isPrimitive(a) || isPrimitive(b)) {
358
- return a === b;
359
- }
360
- const aNode = a;
361
- const bNode = b;
362
- if (aNode.nodeType !== bNode.nodeType) {
363
- return false;
210
+ function autoPrefix(style, rawName) {
211
+ const cached = prefixCache[rawName];
212
+ if (cached) {
213
+ return cached;
364
214
  }
365
- if (aNode.nodeType === Node.ELEMENT_NODE) {
366
- return aNode.tagName === bNode.tagName;
215
+ let name = camelCase(rawName);
216
+ if (name !== "filter" && name in style) {
217
+ return prefixCache[rawName] = name;
367
218
  }
368
- return true;
369
- }
370
- function shallowCompare(a, b) {
371
- if (a === b) return true;
372
- if (isNull(a) || isNull(b)) return false;
373
- if (!isObject(a) || !isObject(b)) return false;
374
- if (isArray(a) !== isArray(b)) return false;
375
- const aRecord = a;
376
- const bRecord = b;
377
- const aKeys = Object.keys(aRecord);
378
- const bKeys = Object.keys(bRecord);
379
- if (aKeys.length !== bKeys.length) return false;
380
- for (const key of aKeys) {
381
- if (!(key in bRecord) || aRecord[key] !== bRecord[key]) {
382
- return false;
219
+ name = capitalize(name);
220
+ for (const prefix of prefixes) {
221
+ const prefixed = prefix + name;
222
+ if (prefixed in style) {
223
+ return prefixCache[rawName] = prefixed;
383
224
  }
384
225
  }
385
- return true;
386
- }
387
- function removeNode(node) {
388
- if (!node) return;
389
- if (isComponent(node)) {
390
- node.destroy();
391
- return;
392
- }
393
- const element = node;
394
- if (element.parentElement) {
395
- element.remove();
396
- }
226
+ return rawName;
397
227
  }
398
- function insertNode(parent, child, before) {
399
- if (!parent || !child) return;
400
- if (isComponent(child)) {
401
- const beforeNode2 = isComponent(before) ? before.firstChild : before;
402
- child.mount(parent, beforeNode2);
403
- return;
404
- }
405
- const beforeNode = isComponent(before) ? before.firstChild : before;
406
- if (beforeNode) {
407
- parent.insertBefore(child, beforeNode);
408
- } else {
409
- parent.appendChild(child);
410
- }
228
+
229
+ // src/hydration.ts
230
+ var _hydrationKey = 0;
231
+ function getHydrationKey() {
232
+ return String(_hydrationKey++);
411
233
  }
412
- function replaceNode(parent, newNode, oldNode) {
413
- if (!parent || !newNode || !oldNode || newNode === oldNode) return;
414
- const beforeNode = isComponent(oldNode) ? oldNode.beforeNode : oldNode.nextSibling;
415
- removeNode(oldNode);
416
- insertNode(parent, newNode, beforeNode);
234
+ function resetHydrationKey() {
235
+ _hydrationKey = 0;
417
236
  }
418
- function getFirstDOMNode(node) {
419
- if (!node) {
420
- return;
421
- }
422
- if (isComponent(node)) {
423
- return node.firstChild;
424
- }
425
- if (isPrimitive(node)) {
426
- return void 0;
427
- }
428
- return node;
237
+ var _isHydrating = false;
238
+ function isHydrating() {
239
+ return _isHydrating;
429
240
  }
430
- function transferKey(oldNode, newNode) {
431
- if (isComponent(oldNode) || isComponent(newNode)) {
432
- return;
433
- }
434
- const oldKey = getNodeKey(oldNode);
435
- if (oldKey && !getNodeKey(newNode)) {
436
- setNodeKey(newNode, oldKey);
241
+ var _registry = /* @__PURE__ */ new Map();
242
+ function gatherHydratable(root) {
243
+ const nodes = root.querySelectorAll("[data-hk]");
244
+ for (const node of nodes) {
245
+ const key = node.dataset.hk;
246
+ if (key != null && !_registry.has(key)) {
247
+ _registry.set(key, node);
248
+ }
437
249
  }
438
250
  }
439
- function patch(parent, oldNode, newNode) {
440
- if (newNode === oldNode) {
441
- return oldNode;
442
- }
443
- const oldIsElement = isHTMLElement(oldNode);
444
- const newIsElement = isHTMLElement(newNode);
445
- if (newIsElement && oldIsElement) {
446
- if (newNode.isEqualNode(oldNode)) {
447
- return oldNode;
448
- }
449
- if (oldNode.tagName === newNode.tagName) {
450
- const oldAttrs = oldNode.attributes;
451
- const newAttrs = newNode.attributes;
452
- for (let i = oldAttrs.length - 1; i >= 0; i--) {
453
- const attrName = oldAttrs[i].name;
454
- if (!newNode.hasAttribute(attrName)) {
455
- oldNode.removeAttribute(attrName);
456
- }
457
- }
458
- for (let i = 0, len = newAttrs.length; i < len; i++) {
459
- const attr = newAttrs[i];
460
- if (oldNode.getAttribute(attr.name) !== attr.value) {
461
- oldNode.setAttribute(attr.name, attr.value);
462
- }
251
+ var _teleportCallsiteAnchors = [];
252
+ var _teleportTargetStarts = /* @__PURE__ */ new Map();
253
+ function gatherTeleportAnchors() {
254
+ if (typeof document === "undefined") return;
255
+ const walker = document.createNodeIterator(document.body, NodeFilter.SHOW_COMMENT);
256
+ let node;
257
+ while (node = walker.nextNode()) {
258
+ const data = node.data;
259
+ if (data === "teleport-anchor") {
260
+ _teleportCallsiteAnchors.push(node);
261
+ } else if (data === "teleport-start") {
262
+ const parent = node.parentElement;
263
+ if (!parent) continue;
264
+ let bucket = _teleportTargetStarts.get(parent);
265
+ if (!bucket) {
266
+ bucket = [];
267
+ _teleportTargetStarts.set(parent, bucket);
463
268
  }
464
- transferKey(oldNode, newNode);
465
- return oldNode;
269
+ bucket.push(node);
466
270
  }
467
271
  }
468
- if (isTextNode(oldNode) && isTextNode(newNode)) {
469
- if (oldNode.textContent !== newNode.textContent) {
470
- oldNode.textContent = newNode.textContent;
272
+ }
273
+ function consumeTeleportAnchor() {
274
+ var _a2;
275
+ return (_a2 = _teleportCallsiteAnchors.shift()) != null ? _a2 : null;
276
+ }
277
+ function consumeTeleportBlock(target) {
278
+ const bucket = _teleportTargetStarts.get(target);
279
+ const start = bucket == null ? void 0 : bucket.shift();
280
+ if (!start) return null;
281
+ const nodes = [];
282
+ let cursor = start.nextSibling;
283
+ while (cursor) {
284
+ if (cursor.nodeType === Node.COMMENT_NODE && cursor.data === "teleport-end") {
285
+ return { start, end: cursor, nodes };
471
286
  }
472
- transferKey(oldNode, newNode);
473
- return oldNode;
287
+ nodes.push(cursor);
288
+ cursor = cursor.nextSibling;
474
289
  }
475
- const oldIsComponent = isComponent(oldNode);
476
- const newIsComponent = isComponent(newNode);
477
- if (oldIsComponent && newIsComponent) {
478
- if (oldNode.component === newNode.component) {
479
- return newNode.update(oldNode);
480
- }
290
+ {
291
+ warn("[Portal] hydration: orphaned <!--teleport-start--> without matching <!--teleport-end-->");
481
292
  }
482
- replaceNode(parent, newNode, oldNode);
483
- return newNode;
293
+ return null;
484
294
  }
485
- function patchChildren(parent, oldChildren, newChildren, anchor) {
486
- const oldLength = oldChildren.length;
487
- const newLength = newChildren.length;
488
- if (oldLength === 0 && newLength === 0) {
489
- return [];
295
+ function beginHydration(root) {
296
+ _isHydrating = true;
297
+ _hydrationKey = 0;
298
+ _registry.clear();
299
+ _teleportCallsiteAnchors.length = 0;
300
+ _teleportTargetStarts.clear();
301
+ gatherHydratable(root);
302
+ gatherTeleportAnchors();
303
+ }
304
+ function endHydration() {
305
+ _isHydrating = false;
306
+ _registry.clear();
307
+ _teleportCallsiteAnchors.length = 0;
308
+ _teleportTargetStarts.clear();
309
+ }
310
+ function getRenderedElement(html) {
311
+ if (!isBrowser()) {
312
+ return () => {
313
+ throw new Error("[essor] getRenderedElement called in non-browser environment");
314
+ };
490
315
  }
316
+ let _csrFactory = null;
317
+ return () => {
318
+ if (!_isHydrating) {
319
+ if (!_csrFactory) _csrFactory = template(html);
320
+ return _csrFactory();
321
+ }
322
+ const key = getHydrationKey();
323
+ const node = _registry.get(key);
324
+ if (node) {
325
+ _registry.delete(key);
326
+ return node;
327
+ }
328
+ warn(`[essor] hydration mismatch: no SSR element for key "${key}"`);
329
+ if (!_csrFactory) _csrFactory = template(html);
330
+ return _csrFactory();
331
+ };
332
+ }
333
+ function patchClassHydrate(el, prev, next2, isSVG) {
334
+ if (_isHydrating) return;
335
+ patchClass(el, prev, next2, isSVG);
336
+ }
337
+ function patchAttrHydrate(el, key, prev, next2) {
338
+ if (_isHydrating) return;
339
+ patchAttr(el, key, prev, next2);
340
+ }
341
+ function patchStyleHydrate(el, prev, next2) {
342
+ if (_isHydrating) return;
343
+ patchStyle(el, prev, next2);
344
+ }
345
+
346
+ // src/reconcile.ts
347
+ function resolveInsertAnchor(parent, candidate) {
348
+ return candidate && candidate.parentNode === parent ? candidate : null;
349
+ }
350
+ function reconcileArrays(parent, oldNodes, newNodes, anchor) {
351
+ const fallbackAnchor = resolveInsertAnchor(parent, anchor);
352
+ const oldLength = oldNodes.length;
353
+ const newLength = newNodes.length;
354
+ if (oldLength === 0 && newLength === 0) return newNodes;
491
355
  if (oldLength === 0) {
492
356
  for (let i = 0; i < newLength; i++) {
493
- insertNode(parent, newChildren[i], anchor);
357
+ insertNode(parent, newNodes[i], fallbackAnchor);
494
358
  }
495
- return newChildren;
359
+ return newNodes;
496
360
  }
497
361
  if (newLength === 0) {
498
362
  for (let i = 0; i < oldLength; i++) {
499
- removeNode(oldChildren[i]);
363
+ removeNode(oldNodes[i]);
500
364
  }
501
365
  return [];
502
366
  }
503
- if (oldLength === 1 && newLength === 1) {
504
- const oldNode = oldChildren[0];
505
- const newNode = newChildren[0];
506
- if (isSameNode(oldNode, newNode)) {
507
- patch(parent, oldNode, newNode);
508
- newChildren[0] = oldNode;
509
- } else {
510
- replaceNode(parent, newNode, oldNode);
511
- }
512
- return newChildren;
513
- }
514
- if (oldLength === 2 && newLength === 2) {
515
- const o0 = oldChildren[0];
516
- const o1 = oldChildren[1];
517
- const n0 = newChildren[0];
518
- const n1 = newChildren[1];
519
- if (isSameNode(o0, n0) && isSameNode(o1, n1)) {
520
- patch(parent, o0, n0);
521
- patch(parent, o1, n1);
522
- newChildren[0] = o0;
523
- newChildren[1] = o1;
524
- return newChildren;
525
- }
526
- if (isSameNode(o0, n1) && isSameNode(o1, n0)) {
527
- patch(parent, o0, n1);
528
- patch(parent, o1, n0);
529
- const dom1 = getFirstDOMNode(o1);
530
- const dom0 = getFirstDOMNode(o0);
531
- if (dom1 && dom0 && dom1.parentNode === parent) {
532
- parent.insertBefore(dom1, dom0);
533
- }
534
- newChildren[0] = o1;
535
- newChildren[1] = o0;
536
- return newChildren;
537
- }
538
- }
539
- return patchKeyedChildren(parent, oldChildren, newChildren, anchor);
540
- }
541
- function patchKeyedChildren(parent, oldChildren, newChildren, anchor) {
542
- let oldStartIdx = 0;
543
- let newStartIdx = 0;
544
- let oldEndIdx = oldChildren.length - 1;
545
- let newEndIdx = newChildren.length - 1;
546
- let oldStartNode = oldChildren[0];
547
- let oldEndNode = oldChildren[oldEndIdx];
548
- let newStartNode = newChildren[0];
549
- let newEndNode = newChildren[newEndIdx];
550
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
551
- if (!oldStartNode) {
552
- oldStartNode = oldChildren[++oldStartIdx];
553
- } else if (!oldEndNode) {
554
- oldEndNode = oldChildren[--oldEndIdx];
555
- } else if (isSameNode(oldStartNode, newStartNode)) {
556
- patch(parent, oldStartNode, newStartNode);
557
- newChildren[newStartIdx] = oldStartNode;
558
- oldStartNode = oldChildren[++oldStartIdx];
559
- newStartNode = newChildren[++newStartIdx];
367
+ let start = 0;
368
+ let oldEnd = oldLength - 1;
369
+ let newEnd = newLength - 1;
370
+ while (start <= oldEnd && start <= newEnd) {
371
+ if (oldNodes[start] === newNodes[start]) {
372
+ start++;
560
373
  } else {
561
374
  break;
562
375
  }
563
376
  }
564
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
565
- if (!oldStartNode) {
566
- oldStartNode = oldChildren[++oldStartIdx];
567
- } else if (!oldEndNode) {
568
- oldEndNode = oldChildren[--oldEndIdx];
569
- } else if (isSameNode(oldEndNode, newEndNode)) {
570
- patch(parent, oldEndNode, newEndNode);
571
- newChildren[newEndIdx] = oldEndNode;
572
- oldEndNode = oldChildren[--oldEndIdx];
573
- newEndNode = newChildren[--newEndIdx];
377
+ while (oldEnd >= start && newEnd >= start) {
378
+ if (oldNodes[oldEnd] === newNodes[newEnd]) {
379
+ oldEnd--;
380
+ newEnd--;
574
381
  } else {
575
382
  break;
576
383
  }
577
384
  }
578
- if (oldStartIdx > oldEndIdx) {
579
- if (newStartIdx <= newEndIdx) {
580
- const anchorNode = newEndIdx + 1 < newChildren.length ? getFirstDOMNode(newChildren[newEndIdx + 1]) : anchor;
581
- for (let i = newStartIdx; i <= newEndIdx; i++) {
582
- insertNode(parent, newChildren[i], anchorNode);
385
+ if (start > oldEnd) {
386
+ if (start <= newEnd) {
387
+ const nextPos = newEnd + 1;
388
+ const nextNode = resolveInsertAnchor(
389
+ parent,
390
+ nextPos < newLength ? newNodes[nextPos] : fallbackAnchor
391
+ );
392
+ for (let i = start; i <= newEnd; i++) {
393
+ insertNode(parent, newNodes[i], nextNode);
583
394
  }
584
395
  }
585
- } else if (newStartIdx > newEndIdx) {
586
- for (let i = oldStartIdx; i <= oldEndIdx; i++) {
587
- const node = oldChildren[i];
588
- if (node) {
589
- removeNode(node);
590
- }
396
+ } else if (start > newEnd) {
397
+ for (let i = start; i <= oldEnd; i++) {
398
+ removeNode(oldNodes[i]);
591
399
  }
592
400
  } else {
593
- patchUnknownSequence(
594
- parent,
595
- oldChildren,
596
- newChildren,
597
- oldStartIdx,
598
- oldEndIdx,
599
- newStartIdx,
600
- newEndIdx,
601
- anchor
602
- );
401
+ reconcileUnknownSequence(parent, oldNodes, newNodes, start, oldEnd, newEnd, fallbackAnchor);
603
402
  }
604
- return newChildren;
403
+ return newNodes;
605
404
  }
606
- function patchUnknownSequence(parent, oldChildren, newChildren, oldStartIdx, oldEndIdx, newStartIdx, newEndIdx, anchor) {
607
- const newLength = newEndIdx - newStartIdx + 1;
608
- let keyToNewIndexMap;
609
- for (let i = newStartIdx; i <= newEndIdx; i++) {
610
- const key = getNodeKey(newChildren[i]);
611
- if (key !== void 0) {
612
- if (!keyToNewIndexMap) {
613
- keyToNewIndexMap = /* @__PURE__ */ Object.create(null);
614
- }
615
- keyToNewIndexMap[key] = i;
616
- }
405
+ function reconcileUnknownSequence(parent, oldNodes, newNodes, start, oldEnd, newEnd, anchor) {
406
+ const newLength = newEnd - start + 1;
407
+ const newIndexMap = /* @__PURE__ */ new Map();
408
+ for (let i = start; i <= newEnd; i++) {
409
+ newIndexMap.set(newNodes[i], i);
617
410
  }
618
411
  const newIndexToOldIndexMap = new Int32Array(newLength);
412
+ newIndexToOldIndexMap.fill(0);
413
+ let patched = 0;
619
414
  let moved = false;
620
415
  let maxNewIndexSoFar = 0;
621
- let patched = 0;
622
- for (let i = oldStartIdx; i <= oldEndIdx; i++) {
623
- const oldNode = oldChildren[i];
624
- if (!oldNode) continue;
416
+ for (let i = start; i <= oldEnd; i++) {
417
+ const oldNode = oldNodes[i];
625
418
  if (patched >= newLength) {
626
419
  removeNode(oldNode);
627
420
  continue;
628
421
  }
629
- let newIndex;
630
- const oldKey = getNodeKey(oldNode);
631
- if (oldKey !== void 0 && keyToNewIndexMap && oldKey in keyToNewIndexMap) {
632
- newIndex = keyToNewIndexMap[oldKey];
633
- } else {
634
- for (let j2 = newStartIdx; j2 <= newEndIdx; j2++) {
635
- if (newIndexToOldIndexMap[j2 - newStartIdx] === 0 && oldKey === void 0 && getNodeKey(newChildren[j2]) === void 0 && isSameNode(oldNode, newChildren[j2])) {
636
- newIndex = j2;
637
- break;
638
- }
639
- }
640
- }
422
+ const newIndex = newIndexMap.get(oldNode);
641
423
  if (newIndex === void 0) {
642
424
  removeNode(oldNode);
643
425
  } else {
644
- newIndexToOldIndexMap[newIndex - newStartIdx] = i + 1;
426
+ newIndexToOldIndexMap[newIndex - start] = i + 1;
645
427
  if (newIndex >= maxNewIndexSoFar) {
646
428
  maxNewIndexSoFar = newIndex;
647
429
  } else {
648
430
  moved = true;
649
431
  }
650
- patch(parent, oldNode, newChildren[newIndex]);
651
- newChildren[newIndex] = oldNode;
652
432
  patched++;
653
433
  }
654
434
  }
655
435
  const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : [];
656
436
  let j = increasingNewIndexSequence.length - 1;
657
- let cachedAnchor = anchor;
658
437
  for (let i = newLength - 1; i >= 0; i--) {
659
- const nextIndex = newStartIdx + i;
660
- const nextNode = newChildren[nextIndex];
438
+ const nextIndex = start + i;
439
+ const nextNode = newNodes[nextIndex];
440
+ const anchorNode = resolveInsertAnchor(
441
+ parent,
442
+ nextIndex + 1 < newNodes.length ? newNodes[nextIndex + 1] : anchor
443
+ );
661
444
  if (newIndexToOldIndexMap[i] === 0) {
662
- insertNode(parent, nextNode, cachedAnchor);
663
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
445
+ insertNode(parent, nextNode, anchorNode);
664
446
  } else if (moved) {
665
447
  if (j < 0 || i !== increasingNewIndexSequence[j]) {
666
- const domNode = getFirstDOMNode(nextNode);
667
- if (domNode && domNode.parentNode === parent) {
668
- insertNode(parent, domNode, cachedAnchor);
669
- }
670
- cachedAnchor = domNode || cachedAnchor;
448
+ insertNode(parent, nextNode, anchorNode);
671
449
  } else {
672
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
673
450
  j--;
674
451
  }
675
- } else {
676
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
677
452
  }
678
453
  }
679
454
  }
680
455
  function getSequence(arr) {
456
+ const p = new Int32Array(arr.length);
457
+ const result = [0];
681
458
  const len = arr.length;
682
- if (len === 0) return [];
683
- if (len === 1) return arr[0] !== 0 ? [0] : [];
684
- const result = [];
685
- const p = new Int32Array(len);
686
459
  let i;
687
460
  let j;
688
461
  let u;
@@ -692,7 +465,7 @@ function getSequence(arr) {
692
465
  const arrI = arr[i];
693
466
  if (arrI !== 0) {
694
467
  j = result[result.length - 1];
695
- if (result.length === 0 || arr[j] < arrI) {
468
+ if (arr[j] < arrI) {
696
469
  p[i] = j;
697
470
  result.push(i);
698
471
  continue;
@@ -724,167 +497,261 @@ function getSequence(arr) {
724
497
  return result;
725
498
  }
726
499
 
727
- // src/binding.ts
728
- function addEventListener(element, event, handler, options) {
729
- element.addEventListener(event, handler, options);
730
- onCleanup(() => {
731
- element.removeEventListener(event, handler, options);
732
- });
733
- }
734
- function bindElement(node, key, defaultValue, setter) {
735
- if (isHtmlInputElement(node)) {
736
- bindInputElement(node, setter);
737
- } else if (isHtmlSelectElement(node)) {
738
- bindSelectElement(node, setter);
739
- } else if (isHtmlTextAreaElement(node)) {
740
- addEventListener(node, "input", () => {
741
- setter(node.value);
742
- });
500
+ // src/dom.ts
501
+ function removeNode(node) {
502
+ if (!node) return;
503
+ if (isComponent(node)) {
504
+ node.destroy();
505
+ } else {
506
+ const element = node;
507
+ if (element.parentNode) {
508
+ element.remove();
509
+ }
743
510
  }
744
511
  }
745
- function bindInputElement(node, setter) {
746
- switch (node.type) {
747
- case "checkbox":
748
- addEventListener(node, "change", () => {
749
- setter(Boolean(node.checked));
750
- });
751
- break;
752
- case "radio":
753
- addEventListener(node, "change", () => {
754
- setter(node.checked ? node.value : "");
755
- });
756
- break;
757
- case "file":
758
- addEventListener(node, "change", () => {
759
- setter(node.files);
760
- });
761
- break;
762
- case "number":
763
- case "range":
764
- addEventListener(node, "input", () => {
765
- setter(node.value || "");
766
- });
767
- break;
768
- case "date":
769
- case "datetime-local":
770
- case "month":
771
- case "time":
772
- case "week":
773
- addEventListener(node, "change", () => {
774
- setter(node.value || "");
775
- });
776
- break;
777
- default:
778
- addEventListener(node, "input", () => {
779
- setter(node.value);
780
- });
781
- break;
512
+ function insertNode(parent, child2, before) {
513
+ if (!parent || !child2) return;
514
+ const beforeNode = isComponent(before) ? before.firstChild : before;
515
+ if (isComponent(child2)) {
516
+ child2.mount(parent, beforeNode);
517
+ return;
782
518
  }
783
- }
784
- function bindSelectElement(node, setter) {
785
- addEventListener(node, "change", () => {
786
- if (node.multiple) {
787
- const values = Array.from(node.options).filter((option) => option.selected).map((option) => option.value);
788
- setter(values);
789
- } else {
790
- setter(node.value);
519
+ if (beforeNode) {
520
+ parent.insertBefore(child2, beforeNode);
521
+ } else {
522
+ {
523
+ if (!child2) {
524
+ error("insertNode: child is not a Node", child2);
525
+ }
791
526
  }
792
- });
527
+ parent.appendChild(child2);
528
+ }
529
+ }
530
+ function normalizeNode(node) {
531
+ if (node instanceof Node) return node;
532
+ if (isComponent(node)) return node;
533
+ const t = typeof node;
534
+ if (node == null || t === "string" || t === "number" || t === "boolean" || t === "symbol") {
535
+ return document.createTextNode(node === false || node == null ? "" : String(node));
536
+ }
537
+ if (isObject(node)) {
538
+ warn(
539
+ "Rendering a plain object as a node is not recommended. The object will be converted to its string representation.",
540
+ node
541
+ );
542
+ }
543
+ return document.createTextNode(String(node));
793
544
  }
794
545
  function insert(parent, nodeFactory, before) {
795
546
  if (!parent) return;
547
+ const ownerScope = getActiveScope();
796
548
  let renderedNodes = [];
797
- const currentScope = getActiveScope();
798
- const cleanup = effect(() => {
799
- const run = () => {
549
+ let isFirstRun = true;
550
+ const resolveNodes = (raw) => {
551
+ if (raw instanceof Node) return [raw];
552
+ if (isComponent(raw)) return [raw];
553
+ const t = typeof raw;
554
+ if (raw == null || t === "string" || t === "number" || t === "boolean") {
555
+ return [normalizeNode(raw)];
556
+ }
557
+ return coerceArray(raw).map((item) => isFunction(item) ? item() : item).flatMap((i) => i).map(normalizeNode);
558
+ };
559
+ const effectRunner = effect(() => {
560
+ const executeUpdate = () => {
800
561
  const rawNodes = isFunction(nodeFactory) ? nodeFactory() : nodeFactory;
801
- const nodes = coerceArray(rawNodes).map((item) => isFunction(item) ? item() : item).flatMap(normalizeNode);
802
- renderedNodes = patchChildren(parent, renderedNodes, nodes, before);
562
+ const nodes = resolveNodes(rawNodes);
563
+ if (isFirstRun && isHydrating() && nodes.every((node) => node instanceof Node && node.parentNode === parent)) {
564
+ renderedNodes = nodes;
565
+ isFirstRun = false;
566
+ return;
567
+ }
568
+ renderedNodes = reconcileArrays(parent, renderedNodes, nodes, before);
569
+ isFirstRun = false;
803
570
  };
804
- if (currentScope) {
805
- runWithScope(currentScope, run);
571
+ if (ownerScope && !ownerScope.isDestroyed) {
572
+ runWithScope(ownerScope, executeUpdate);
806
573
  } else {
807
- run();
574
+ executeUpdate();
808
575
  }
809
576
  });
810
577
  onCleanup(() => {
811
- cleanup();
812
- renderedNodes.forEach((node) => removeNode(node));
813
- renderedNodes.length = 0;
578
+ effectRunner.stop();
579
+ for (const node of renderedNodes) removeNode(node);
580
+ renderedNodes = [];
814
581
  });
815
582
  return renderedNodes;
816
583
  }
817
- function mapNodes(template2, indexes) {
818
- const len = indexes.length;
819
- const tree = new Array(len);
820
- const indexSet = new Set(indexes);
821
- let index = 1;
822
- let found = 0;
823
- const walk = (node) => {
824
- if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
825
- if (indexSet.has(index)) {
826
- tree[found++] = node;
827
- if (found === len) return true;
584
+ function child(node) {
585
+ return (node == null ? void 0 : node.firstChild) || null;
586
+ }
587
+ function next(node, step = 1) {
588
+ while (node && step > 0) {
589
+ node = node.nextSibling;
590
+ step--;
591
+ }
592
+ return node || null;
593
+ }
594
+ function nthChild(node, index) {
595
+ if (!node || index < 0) return null;
596
+ let current = node.firstChild;
597
+ while (current && index > 0) {
598
+ current = current.nextSibling;
599
+ index--;
600
+ }
601
+ return current || null;
602
+ }
603
+
604
+ // src/operations/event.ts
605
+ function addEvent(el, event, handler, options) {
606
+ if (!(options == null ? void 0 : options.delegate)) {
607
+ el.addEventListener(event, handler, options);
608
+ return () => el.removeEventListener(event, handler, options);
609
+ }
610
+ const selector = options.delegate;
611
+ const wrappedHandler = (e) => {
612
+ const target = e.target;
613
+ if (target.matches(selector) || target.closest(selector)) {
614
+ handler.call(el, e);
615
+ }
616
+ };
617
+ const _a2 = options, { delegate: _ } = _a2, nativeOptions = __objRest(_a2, ["delegate"]);
618
+ el.addEventListener(event, wrappedHandler, nativeOptions);
619
+ return () => {
620
+ el.removeEventListener(event, wrappedHandler, nativeOptions);
621
+ };
622
+ }
623
+ function registerScopedHook(scope, listKey, hook) {
624
+ let hookList = scope[listKey];
625
+ if (!hookList) {
626
+ hookList = [];
627
+ scope[listKey] = hookList;
628
+ }
629
+ hookList.push(hook);
630
+ }
631
+ function executeHooks(hooks, scopeId, phase) {
632
+ const len = hooks.length;
633
+ if (len === 0) return;
634
+ let pending;
635
+ for (let i = 0; i < len; i++) {
636
+ try {
637
+ const result = hooks[i]();
638
+ if (isPromise(result)) {
639
+ const safePromise = result.catch((error_) => {
640
+ if (true) {
641
+ error(`Scope(${scopeId}): Async ${phase} hook rejected:`, error_);
642
+ }
643
+ });
644
+ (pending || (pending = [])).push(safePromise);
645
+ }
646
+ } catch (error_) {
647
+ {
648
+ error(`Scope(${scopeId}): Error in ${phase} hook:`, error_);
828
649
  }
829
- index++;
830
650
  }
831
- let child = node.firstChild;
832
- while (child) {
833
- if (walk(child)) return true;
834
- child = child.nextSibling;
651
+ }
652
+ if (!pending) return;
653
+ return Promise.all(pending).then(() => {
654
+ });
655
+ }
656
+ function onMount(hook) {
657
+ const scope = getActiveScope();
658
+ if (!scope) {
659
+ error("onMount() must be called within a scope");
660
+ return;
661
+ }
662
+ if (scope.isMounted) {
663
+ try {
664
+ const result = hook();
665
+ if (isPromise(result)) {
666
+ result.catch((error_) => {
667
+ if (true) error(`Scope(${scope.id}): Async mount hook rejected:`, error_);
668
+ });
669
+ }
670
+ } catch (error_) {
671
+ error(`Scope(${scope.id}): Error in mount hook:`, error_);
835
672
  }
836
- return false;
837
- };
838
- walk(template2);
839
- return tree;
673
+ return;
674
+ }
675
+ registerScopedHook(scope, "onMount", hook);
676
+ }
677
+ function onUpdate(hook) {
678
+ const scope = getActiveScope();
679
+ if (!scope) {
680
+ error("onUpdate() must be called within a scope");
681
+ return;
682
+ }
683
+ registerScopedHook(scope, "onUpdate", hook);
684
+ }
685
+ function onDestroy(hook) {
686
+ const scope = getActiveScope();
687
+ if (!scope) {
688
+ error("onDestroy() must be called within a scope");
689
+ return;
690
+ }
691
+ registerScopedHook(scope, "onDestroy", hook);
692
+ }
693
+ function triggerMountHooks(scope) {
694
+ if (scope.isDestroyed) {
695
+ return;
696
+ }
697
+ if (!scope.onMount || scope.onMount.length === 0) {
698
+ scope.isMounted = true;
699
+ return;
700
+ }
701
+ const mountHooks = scope.onMount;
702
+ const result = runWithScope(scope, () => executeHooks(mountHooks, scope.id, "mount"));
703
+ mountHooks.length = 0;
704
+ scope.isMounted = true;
705
+ return result;
706
+ }
707
+ function triggerUpdateHooks(scope) {
708
+ if (scope.isDestroyed || !scope.onUpdate || scope.onUpdate.length === 0) return;
709
+ return runWithScope(scope, () => executeHooks(scope.onUpdate, scope.id, "update"));
840
710
  }
841
711
 
842
712
  // src/component.ts
713
+ function syncDescriptors(target, source, pruneMissing = false) {
714
+ const seen = pruneMissing ? /* @__PURE__ */ new Set() : null;
715
+ for (const key of Object.getOwnPropertyNames(source)) {
716
+ seen == null ? void 0 : seen.add(key);
717
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
718
+ }
719
+ if (seen) {
720
+ for (const key of Object.getOwnPropertyNames(target)) {
721
+ if (!seen.has(key)) delete target[key];
722
+ }
723
+ }
724
+ }
725
+ function readProp(source, key) {
726
+ const descriptor = Object.getOwnPropertyDescriptor(source, key);
727
+ return descriptor.get ? descriptor.get.call(source) : descriptor.value;
728
+ }
843
729
  var _a;
844
- _a = NORMAL_COMPONENT;
730
+ _a = "normal" /* NORMAL */;
845
731
  var Component = class {
846
732
  constructor(component, props = {}) {
847
733
  this.component = component;
848
734
  this.props = props;
849
- // Component rendered nodes (supports arrays and fragments)
850
- this.renderedNodes = [];
851
- // Component scope (unified context management)
735
+ this[_a] = true;
852
736
  this.scope = null;
853
- // Component parent node
854
- this.parentNode = void 0;
855
- // Component before node
856
- this.beforeNode = void 0;
857
- // Component props (reactive and snapshot)
858
- this.reactiveProps = {};
859
- this._propSnapshots = {};
860
- // Component lifecycle state
861
737
  this.state = 0 /* INITIAL */;
862
- // Parent scope captured at construction time for correct hierarchy
863
- this.parentScope = null;
864
- // @ts-ignore
865
- this[_a] = true;
866
- this.key = props.key ? normalizeKey(props.key) : getComponentKey(component);
867
- this.reactiveProps = shallowReactive(__spreadValues({}, props));
738
+ this.beforeNode = void 0;
739
+ this.renderedNodes = [];
740
+ this.firstChild = void 0;
741
+ this.parentNode = void 0;
742
+ this.rootEventCleanups = [];
868
743
  this.parentScope = getActiveScope();
869
- for (const key in props) {
870
- const val = props[key];
871
- if (isObject(val)) {
872
- this._propSnapshots[key] = isArray(val) ? [...val] : __spreadValues({}, val);
873
- }
874
- }
875
- }
876
- get isConnected() {
877
- return this.state === 2 /* MOUNTED */;
878
- }
879
- get firstChild() {
880
- for (const node of this.renderedNodes) {
881
- const dom = getFirstDOMNode(node);
882
- if (dom) return dom;
883
- }
884
- return void 0;
744
+ const container = {};
745
+ syncDescriptors(container, props);
746
+ this.reactiveProps = shallowReactive(container);
885
747
  }
748
+ /**
749
+ * Mount the component into `parentNode` (optionally before `beforeNode`).
750
+ * If already rendered, the existing DOM is re-inserted without re-running
751
+ * the component function.
752
+ */
886
753
  mount(parentNode, beforeNode) {
887
- var _a2, _b;
754
+ var _a2;
888
755
  this.parentNode = parentNode;
889
756
  this.beforeNode = beforeNode;
890
757
  this.state = 1 /* MOUNTING */;
@@ -895,177 +762,128 @@ var Component = class {
895
762
  this.state = 2 /* MOUNTED */;
896
763
  return this.renderedNodes;
897
764
  }
898
- const parentScope = (_a2 = this.parentScope) != null ? _a2 : getActiveScope();
899
- this.scope = createScope(parentScope);
900
- setActiveScope(this.scope);
901
- let result = this.component(this.reactiveProps);
902
- if (isFunction(result)) {
903
- result = result(this.reactiveProps);
904
- }
905
- if (isSignal(result) || isComputed(result)) {
906
- result = result.value;
907
- }
908
- const renderedNodes = (_b = insert(parentNode, result, beforeNode)) != null ? _b : [];
765
+ const scope = createScope((_a2 = this.parentScope) != null ? _a2 : getActiveScope());
766
+ this.scope = scope;
767
+ const renderedNodes = runWithScope(scope, () => {
768
+ var _a3;
769
+ let result = this.component(this.reactiveProps);
770
+ if (isFunction(result)) {
771
+ result = result(this.reactiveProps);
772
+ }
773
+ if (isSignal(result) || isComputed(result)) {
774
+ result = result.value;
775
+ }
776
+ return (_a3 = insert(parentNode, result, beforeNode)) != null ? _a3 : [];
777
+ });
909
778
  this.renderedNodes = renderedNodes;
910
- this.applyProps(this.props);
779
+ this.firstChild = renderedNodes[0];
780
+ this.syncSpecialProps(this.props);
911
781
  this.state = 2 /* MOUNTED */;
912
- triggerMountHooks(this.scope);
782
+ triggerMountHooks(scope);
913
783
  return this.renderedNodes;
914
784
  }
915
- update(prevNode) {
916
- if (this.key !== prevNode.key) {
917
- this.mount(prevNode.parentNode, prevNode.beforeNode);
918
- return this;
919
- }
920
- this.parentNode = prevNode.parentNode;
921
- this.beforeNode = prevNode.beforeNode;
922
- this.scope = prevNode.scope;
923
- this.parentScope = prevNode.parentScope;
924
- this.renderedNodes = prevNode.renderedNodes;
925
- this.state = prevNode.state;
926
- this.reactiveProps = prevNode.reactiveProps;
927
- this._propSnapshots = prevNode._propSnapshots;
928
- this._updateReactiveProps(this.props);
929
- if (!this.isConnected && this.parentNode) {
930
- this.mount(this.parentNode, this.beforeNode);
931
- return this;
932
- }
933
- if (this.scope) {
934
- setActiveScope(this.scope);
935
- this.applyProps(this.props);
936
- triggerUpdateHooks(this.scope);
937
- }
938
- return this;
939
- }
940
785
  /**
941
- * Update reactive props by comparing with current values
786
+ * Re-install props into the same `reactiveProps` container (preserving
787
+ * any closures already holding a reference to it) and re-apply
788
+ * refs/events against the current root element.
942
789
  */
943
- _updateReactiveProps(props) {
944
- for (const key in props) {
945
- if (key === "key") continue;
946
- const newValue = props[key];
947
- const oldValue = this.reactiveProps[key];
948
- if (newValue === oldValue && !this._propSnapshots[key]) continue;
949
- const isNewValueObject = isObject(newValue);
950
- if (isNewValueObject) {
951
- const snapshot = this._propSnapshots[key];
952
- if (snapshot && shallowCompare(newValue, snapshot)) continue;
953
- const newSnapshot = isArray(newValue) ? [...newValue] : __spreadValues({}, newValue);
954
- this.reactiveProps[key] = newSnapshot;
955
- this._propSnapshots[key] = newSnapshot;
956
- } else {
957
- if (hasChanged(newValue, oldValue)) {
958
- this.reactiveProps[key] = newValue;
959
- if (this._propSnapshots[key]) {
960
- delete this._propSnapshots[key];
961
- }
962
- }
963
- }
964
- }
965
- }
966
- unwrapRenderResult(result) {
967
- if (isFunction(result)) {
968
- result = result(this.reactiveProps);
969
- }
970
- if (isSignal(result) || isComputed(result)) {
971
- result = result.value;
972
- }
973
- if (isComponent(result)) {
974
- result = result.mount(this.parentNode, this.beforeNode);
975
- }
976
- if (isPromise(result)) {
977
- result = result.then((r) => this.unwrapRenderResult(r));
978
- }
979
- return result;
980
- }
981
- forceUpdate() {
982
- if (this.state === 5 /* DESTROYED */ || !this.parentNode || !this.scope) {
983
- return;
984
- }
985
- const originalNodes = [...this.renderedNodes];
986
- try {
987
- runWithScope(this.scope, () => {
988
- let result = this.component(this.reactiveProps);
989
- if (isFunction(result)) {
990
- result = result(this.reactiveProps);
991
- }
992
- if (isSignal(result) || isComputed(result)) {
993
- result = result.value;
994
- }
995
- const newNodes = coerceArray(result);
996
- const anchor = this._getAnchorNode();
997
- if (!this.parentNode) return;
998
- for (const node of this.renderedNodes) {
999
- removeNode(node);
1000
- }
1001
- for (const node of newNodes) {
1002
- insertNode(this.parentNode, node, anchor);
1003
- }
1004
- this.renderedNodes = newNodes;
1005
- });
1006
- if (this.scope) {
1007
- triggerUpdateHooks(this.scope);
1008
- }
1009
- } catch (error8) {
1010
- this.renderedNodes = originalNodes;
1011
- throw error8;
1012
- }
790
+ update(props) {
791
+ this.props = props;
792
+ const scope = this.scope;
793
+ if (!scope || scope.isDestroyed) return;
794
+ syncDescriptors(
795
+ this.reactiveProps,
796
+ props != null ? props : {},
797
+ /* pruneMissing */
798
+ true
799
+ );
800
+ this.syncSpecialProps(props);
801
+ triggerUpdateHooks(scope);
1013
802
  }
1014
803
  /**
1015
- * Get anchor node for insertion
804
+ * Tear down and re-mount the component at its current insertion point.
805
+ * No-op if the component has never been mounted.
1016
806
  */
1017
- _getAnchorNode() {
1018
- if (this.beforeNode) return this.beforeNode;
1019
- if (this.renderedNodes.length > 0) {
1020
- const lastNode = this.renderedNodes[this.renderedNodes.length - 1];
1021
- const lastDom = getFirstDOMNode(lastNode);
1022
- if (lastDom) {
1023
- return lastDom.nextSibling;
1024
- }
1025
- }
1026
- return void 0;
807
+ forceUpdate() {
808
+ if (!this.parentNode) return;
809
+ const parent = this.parentNode;
810
+ const before = this.beforeNode;
811
+ this.destroy();
812
+ this.mount(parent, before);
1027
813
  }
1028
814
  /**
1029
- * Destroy component
815
+ * Dispose the scope, remove all rendered nodes, and clear bookkeeping.
816
+ * Idempotent: subsequent calls are no-ops.
1030
817
  */
1031
818
  destroy() {
1032
- if (this.state === 4 /* DESTROYING */ || this.state === 5 /* DESTROYED */) {
1033
- return;
1034
- }
1035
- this.state = 4 /* DESTROYING */;
1036
- for (const node of this.renderedNodes) {
1037
- removeNode(node);
1038
- }
1039
819
  const scope = this.scope;
1040
- if (scope) {
1041
- disposeScope(scope);
1042
- this.scope = null;
1043
- }
820
+ if (!scope || scope.isDestroyed) return;
821
+ this.scope = null;
822
+ this.releaseSpecialProps();
823
+ disposeScope(scope);
824
+ for (const node of this.renderedNodes) removeNode(node);
1044
825
  this.renderedNodes = [];
826
+ this.firstChild = void 0;
1045
827
  this.parentNode = void 0;
1046
- this.beforeNode = void 0;
1047
- this.parentScope = null;
1048
- this.reactiveProps = {};
1049
- this.props = {};
1050
- this.state = 5 /* DESTROYED */;
1051
828
  }
1052
- applyProps(props) {
829
+ /**
830
+ * Apply props that bind to the root DOM element rather than flowing into
831
+ * the component body: `ref` (signal/function) and `onXxx` event handlers.
832
+ * The render-facing `reactiveProps` already has those keys; here we just
833
+ * wire them to the actual DOM node.
834
+ */
835
+ syncSpecialProps(props) {
1053
836
  if (!props) return;
1054
- const firstElement = this.firstChild;
1055
- for (const [propName, propValue] of Object.entries(props)) {
1056
- if (startsWith(propName, EVENT_PREFIX)) {
1057
- if (!firstElement || !isHTMLElement(firstElement)) return;
1058
- const eventName = propName.slice(EVENT_PREFIX.length).toLowerCase();
1059
- addEventListener(firstElement, eventName, propValue);
1060
- } else if (propName === REF_KEY && isSignal(propValue)) {
1061
- propValue.value = firstElement;
837
+ const root = this.firstChild;
838
+ if (!root) return;
839
+ this.releaseSpecialProps();
840
+ for (const key of Object.getOwnPropertyNames(props)) {
841
+ const value = readProp(props, key);
842
+ if (key === REF_KEY) {
843
+ this.rootRefCleanup = this.bindRootRef(value, root);
844
+ continue;
845
+ }
846
+ if (isOn(key) && isFunction(value)) {
847
+ const eventName = key.slice(2).toLowerCase();
848
+ this.rootEventCleanups.push(addEvent(root, eventName, value));
1062
849
  }
1063
850
  }
1064
- this.props = props;
851
+ }
852
+ /**
853
+ * Remove all listeners/ref bindings currently attached to the root element.
854
+ */
855
+ releaseSpecialProps() {
856
+ for (const cleanup of this.rootEventCleanups) {
857
+ cleanup();
858
+ }
859
+ this.rootEventCleanups.length = 0;
860
+ if (this.rootRefCleanup) {
861
+ this.rootRefCleanup();
862
+ this.rootRefCleanup = void 0;
863
+ }
864
+ }
865
+ /**
866
+ * Bind the root ref prop and return a cleanup that restores the previous ref state.
867
+ */
868
+ bindRootRef(value, root) {
869
+ if (isFunction(value)) {
870
+ value(root);
871
+ return () => value(null);
872
+ }
873
+ if (isSignal(value)) {
874
+ const previousValue = value.value;
875
+ value.value = root;
876
+ return () => {
877
+ if (value.value === root) {
878
+ value.value = previousValue;
879
+ }
880
+ };
881
+ }
882
+ return void 0;
1065
883
  }
1066
884
  };
1067
885
  function isComponent(node) {
1068
- return !!node && !!node[NORMAL_COMPONENT];
886
+ return !!node && !!node["normal" /* NORMAL */];
1069
887
  }
1070
888
  function createComponent(componentFn, props) {
1071
889
  if (isComponent(componentFn)) {
@@ -1091,17 +909,72 @@ function template(html) {
1091
909
  function createApp(component, target) {
1092
910
  const container = isString(target) ? document.querySelector(target) : target;
1093
911
  if (!container) {
1094
- error(`Target element not found: ${target}`);
912
+ {
913
+ warn(`Target element not found: ${target}`);
914
+ }
1095
915
  return;
1096
916
  }
1097
- const existingContext = container.innerHTML;
1098
- if (existingContext) {
1099
- error(`Target element is not empty, it will be delete: ${target}`);
917
+ const existingContent = container.innerHTML;
918
+ if (existingContent) {
919
+ {
920
+ warn(`Target element is not empty, it will be cleared: ${target}`);
921
+ }
1100
922
  container.innerHTML = "";
1101
923
  }
1102
- const rootComponent = isComponent(component) ? component : createComponent(component);
1103
- rootComponent.mount(container);
1104
- return rootComponent;
924
+ const scope = createScope();
925
+ let rootNode;
926
+ try {
927
+ runWithScope(scope, () => {
928
+ const mountedRoot = createComponent(component);
929
+ if (isComponent(mountedRoot)) {
930
+ rootNode = mountedRoot;
931
+ insertNode(container, mountedRoot);
932
+ }
933
+ });
934
+ } catch (error_) {
935
+ disposeScope(scope);
936
+ throw error_;
937
+ }
938
+ return {
939
+ root: rootNode,
940
+ unmount: () => {
941
+ disposeScope(scope);
942
+ rootNode == null ? void 0 : rootNode.destroy();
943
+ }
944
+ };
945
+ }
946
+ function hydrate(component, target) {
947
+ const container = isString(target) ? document.querySelector(target) : target;
948
+ if (!container) {
949
+ {
950
+ warn(`[essor] hydrate: target element not found: ${target}`);
951
+ }
952
+ return;
953
+ }
954
+ beginHydration(container);
955
+ const scope = createScope();
956
+ let rootNode;
957
+ try {
958
+ runWithScope(scope, () => {
959
+ const mountedRoot = createComponent(component);
960
+ if (isComponent(mountedRoot)) {
961
+ rootNode = mountedRoot;
962
+ insert(container, mountedRoot);
963
+ }
964
+ });
965
+ } catch (error_) {
966
+ disposeScope(scope);
967
+ throw error_;
968
+ } finally {
969
+ endHydration();
970
+ }
971
+ return {
972
+ root: rootNode,
973
+ unmount: () => {
974
+ disposeScope(scope);
975
+ rootNode == null ? void 0 : rootNode.destroy();
976
+ }
977
+ };
1105
978
  }
1106
979
  function provide(key, value) {
1107
980
  const scope = getActiveScope();
@@ -1127,68 +1000,66 @@ function inject(key, defaultValue) {
1127
1000
  let current = scope;
1128
1001
  while (current) {
1129
1002
  if (current.provides) {
1130
- const value = current.provides.get(key);
1131
- if (value) {
1132
- return value;
1003
+ if (current.provides.has(key)) {
1004
+ return current.provides.get(key);
1133
1005
  }
1134
1006
  }
1135
1007
  current = current.parent;
1136
1008
  }
1137
1009
  return defaultValue;
1138
1010
  }
1139
- function reTarget(event, value) {
1140
- Object.defineProperty(event, "target", {
1011
+ function reTargetEvent(e, value) {
1012
+ Object.defineProperty(e, "target", {
1141
1013
  configurable: true,
1142
1014
  value
1143
1015
  });
1144
1016
  }
1145
- function handleNodeEvent(node, event, key) {
1146
- const handler = node[`_$${key}`];
1147
- if (handler && isFunction(handler) && !node.disabled) {
1148
- const data = node[`${key}Data`];
1149
- data ? handler.call(node, data, event) : handler.call(node, event);
1150
- if (event.cancelBubble) return false;
1151
- }
1152
- if (node.host && !isString(node.host) && !node.host._$host && isFunction(node.contains) && node.contains(event.target)) {
1153
- reTarget(event, node.host);
1154
- }
1155
- return true;
1156
- }
1157
- function walkUpTree(startNode, event, key) {
1158
- let node = startNode;
1159
- while (handleNodeEvent(node, event, key) && (node = node._$host || node.parentNode || node.host)) ;
1160
- return node;
1161
- }
1162
- function eventHandler(event) {
1163
- let node = event.target;
1164
- const key = `${event.type}`;
1165
- const oriTarget = event.target;
1166
- const oriCurrentTarget = event.currentTarget;
1167
- Object.defineProperty(event, "currentTarget", {
1017
+ function eventHandler(e) {
1018
+ let node = e.target;
1019
+ const key = e.type;
1020
+ const oriTarget = e.target;
1021
+ const oriCurrentTarget = e.currentTarget;
1022
+ const handleNode = () => {
1023
+ const handler = node[`_$${key}`];
1024
+ if (handler && isFunction(handler) && !node.disabled) {
1025
+ const data = node[`${key}Data`];
1026
+ data ? handler.call(node, data, e) : handler.call(node, e);
1027
+ if (e.cancelBubble) return false;
1028
+ }
1029
+ if (node.host && !isString(node.host) && !node.host._$host && isFunction(node.contains) && node.contains(e.target)) {
1030
+ reTargetEvent(e, node.host);
1031
+ }
1032
+ return true;
1033
+ };
1034
+ const walkUpTree = () => {
1035
+ while (handleNode() && (node = node._$host || node.parentNode || node.host)) ;
1036
+ };
1037
+ Object.defineProperty(e, "currentTarget", {
1168
1038
  configurable: true,
1039
+ /**
1040
+ * Returns the current delegated target for the event.
1041
+ */
1169
1042
  get() {
1170
1043
  return node || document;
1171
1044
  }
1172
1045
  });
1173
- if (event.composedPath) {
1174
- const path = event.composedPath();
1175
- reTarget(event, path[0]);
1046
+ if (e.composedPath) {
1047
+ const path = e.composedPath();
1048
+ reTargetEvent(e, path[0]);
1176
1049
  for (let i = 0; i < path.length - 2; i++) {
1177
1050
  node = path[i];
1178
- if (!handleNodeEvent(node, event, key)) break;
1051
+ if (!handleNode()) break;
1179
1052
  if (node._$host) {
1180
1053
  node = node._$host;
1181
- node = walkUpTree(node, event, key);
1054
+ walkUpTree();
1182
1055
  break;
1183
1056
  }
1184
1057
  if (node.parentNode === oriCurrentTarget) {
1185
1058
  break;
1186
1059
  }
1187
1060
  }
1188
- } else {
1189
- node = walkUpTree(node, event, key);
1190
- }
1191
- reTarget(event, oriTarget);
1061
+ } else walkUpTree();
1062
+ reTargetEvent(e, oriTarget);
1192
1063
  }
1193
1064
  var $EVENTS = /* @__PURE__ */ Symbol("_$EVENTS");
1194
1065
  function delegateEvents(eventNames, document2 = window.document) {
@@ -1201,424 +1072,344 @@ function delegateEvents(eventNames, document2 = window.document) {
1201
1072
  }
1202
1073
  }
1203
1074
  }
1204
-
1205
- // src/utils/props.ts
1206
- function omitProps(target, keys) {
1207
- const excludeSet = new Set(keys);
1208
- return new Proxy(target, {
1209
- // Intercept property reads
1210
- get(obj, prop) {
1211
- if (excludeSet.has(prop)) {
1212
- return void 0;
1213
- }
1214
- return Reflect.get(obj, prop);
1215
- },
1216
- // Intercept property enumeration (for...in, Object.keys, etc.)
1217
- ownKeys(obj) {
1218
- return Reflect.ownKeys(obj).filter((key) => !excludeSet.has(key));
1219
- },
1220
- // Intercept property descriptor retrieval
1221
- getOwnPropertyDescriptor(obj, prop) {
1222
- if (excludeSet.has(prop)) {
1223
- return void 0;
1224
- }
1225
- return Reflect.getOwnPropertyDescriptor(obj, prop);
1226
- },
1227
- // Intercept the 'in' operator
1228
- has(obj, prop) {
1229
- if (excludeSet.has(prop)) {
1230
- return false;
1231
- }
1232
- return Reflect.has(obj, prop);
1233
- }
1234
- });
1235
- }
1236
-
1237
- // src/hydration/shared.ts
1238
- var isHydrationActive = false;
1239
- function startHydration() {
1240
- isHydrationActive = true;
1241
- }
1242
- function endHydration() {
1243
- isHydrationActive = false;
1244
- }
1245
- function isHydrating() {
1246
- return isHydrationActive;
1247
- }
1248
- var hydrationCounter = 0;
1249
- function getHydrationKey() {
1250
- return `${hydrationCounter++}`;
1251
- }
1252
- function resetHydrationKey() {
1253
- hydrationCounter = 0;
1254
- }
1255
-
1256
- // src/hydration/hydration.ts
1257
- var DATA_IDX_REGEX = /^\d+-\d+$/;
1258
- function getRenderedElement(temp) {
1259
- return () => {
1260
- if (!isBrowser()) {
1261
- return null;
1262
- }
1263
- const key = getHydrationKey();
1264
- const node = document.querySelector(`[data-hk="${key}"]`);
1265
- if (node) {
1266
- return node;
1267
- }
1268
- return template(temp)();
1269
- };
1270
- }
1271
- function mapSSRNodes(templateEl, idx) {
1272
- const hk = templateEl.dataset.hk;
1273
- if (!hk) {
1274
- return mapNodes(templateEl, idx);
1275
- }
1276
- const nodesList = [];
1277
- const elements = templateEl.querySelectorAll(`[data-idx^="${hk}"]`);
1278
- if (elements.length > 0) {
1279
- nodesList.push(
1280
- ...Array.from(elements).filter((item) => {
1281
- const idxAttr = item.dataset.idx;
1282
- return idxAttr !== null && DATA_IDX_REGEX.test(idxAttr);
1283
- }).map((item) => {
1284
- const idxAttr = item.dataset.idx || "";
1285
- const [hkPart, idxPart] = idxAttr.split("-");
1286
- return {
1287
- hk: hkPart,
1288
- idx: idxPart,
1289
- node: item
1290
- };
1291
- })
1292
- );
1293
- }
1294
- const commentNodes = [];
1295
- const walkNodes = (node) => {
1296
- if (node.nodeType === Node.COMMENT_NODE && node.textContent && DATA_IDX_REGEX.test(node.textContent)) {
1297
- const [hkPart, idxPart] = node.textContent.split("-");
1298
- commentNodes.push({
1299
- hk: hkPart,
1300
- idx: idxPart,
1301
- node
1302
- });
1303
- }
1304
- let child = node.firstChild;
1305
- while (child) {
1306
- walkNodes(child);
1307
- child = child.nextSibling;
1308
- }
1309
- };
1310
- walkNodes(templateEl);
1311
- nodesList.push(...commentNodes);
1312
- const nodes = [templateEl];
1313
- idx.forEach((indexValue) => {
1314
- const node = nodesList.find((item) => item.idx === String(indexValue));
1315
- if (node) {
1316
- nodes.push(node.node);
1317
- }
1318
- });
1319
- return nodes;
1320
- }
1321
- function hydrate(component, container) {
1322
- startHydration();
1323
- resetHydrationKey();
1324
- try {
1325
- const rootElement = isString(container) ? document.querySelector(container) : container;
1326
- if (!rootElement) {
1327
- error("Hydration error: Root element not found");
1328
- return void 0;
1329
- }
1330
- const rootComponent = createComponent(component);
1331
- rootComponent.mount(rootElement);
1332
- endHydration();
1333
- return rootComponent;
1334
- } catch (error_) {
1335
- error("Hydration error:", error_);
1336
- endHydration();
1337
- return void 0;
1338
- }
1339
- }
1340
- function patchClass(el, prev, next, isSVG = false) {
1341
- if (prev === next) {
1342
- return;
1343
- }
1344
- if (isHydrating()) {
1345
- return;
1346
- }
1347
- const normalizedNext = normalizeClass(next);
1348
- const normalizedPrev = normalizeClass(prev);
1349
- if (normalizedNext && normalizedPrev === normalizedNext) {
1350
- return;
1351
- }
1352
- if (!normalizedNext) {
1353
- el.removeAttribute("class");
1354
- } else if (isSVG) {
1355
- el.setAttribute("class", normalizedNext);
1356
- } else {
1357
- el.className = normalizedNext;
1358
- }
1359
- }
1360
- function normalizeClass(value) {
1361
- return normalizeClassName(value);
1362
- }
1363
- var importantRE = /\s*!important$/;
1364
- var prefixes = ["Webkit", "Moz", "ms"];
1365
- var prefixCache = {};
1366
- function patchStyle(el, prev, next) {
1367
- const style = el.style;
1368
- const isCssString = isString(next);
1369
- if (isHydrating()) {
1370
- return;
1371
- }
1372
- if (next && isCssString) {
1373
- if (prev !== next) {
1374
- style.cssText = next;
1375
- }
1376
- return;
1377
- }
1378
- if (!next) {
1379
- if (prev) {
1380
- el.removeAttribute("style");
1381
- }
1382
- return;
1383
- }
1384
- if (prev && !isString(prev)) {
1385
- for (const key in prev) {
1386
- if (!next || next[key] == null) {
1387
- setStyle(style, key, "");
1388
- }
1389
- }
1390
- } else if (prev && isString(prev)) {
1391
- const prevStyles = prev.split(";");
1392
- for (const stylePart of prevStyles) {
1393
- const colonIndex = stylePart.indexOf(":");
1394
- if (colonIndex > 0) {
1395
- const key = stylePart.slice(0, colonIndex).trim();
1396
- if (next && isObject(next) && next[key] == null) {
1397
- setStyle(style, key, "");
1398
- }
1399
- }
1400
- }
1401
- }
1402
- if (next && !isString(next)) {
1403
- for (const key in next) {
1404
- const value = next[key];
1405
- if ((!prev || isString(prev) || prev[key] !== value) && value != null) {
1406
- setStyle(style, key, value);
1407
- }
1408
- }
1409
- }
1410
- }
1411
- function setStyle(style, name, val) {
1412
- if (isArray(val)) {
1413
- for (const element of val) {
1414
- setStyle(style, name, element);
1075
+ function clearDelegatedEvents(document2 = window.document) {
1076
+ const docWithEvents = document2;
1077
+ const eventSet = docWithEvents[$EVENTS];
1078
+ if (eventSet) {
1079
+ for (const name of eventSet.keys()) {
1080
+ document2.removeEventListener(name, eventHandler);
1415
1081
  }
1416
- return;
1417
- }
1418
- if (val == null || val === "") {
1419
- val = "";
1420
- }
1421
- if (name.startsWith("--")) {
1422
- style.setProperty(name, val);
1423
- return;
1424
- }
1425
- const prefixed = autoPrefix(style, name);
1426
- if (isString(val) && importantRE.test(val)) {
1427
- style.setProperty(camelCase(prefixed), val.replace(importantRE, ""), "important");
1428
- } else {
1429
- style[prefixed] = val;
1082
+ delete docWithEvents[$EVENTS];
1430
1083
  }
1431
1084
  }
1432
- function autoPrefix(style, rawName) {
1433
- const cached = prefixCache[rawName];
1434
- if (cached) {
1435
- return cached;
1436
- }
1437
- let name = camelCase(rawName);
1438
- if (name !== "filter" && name in style) {
1439
- return prefixCache[rawName] = name;
1440
- }
1441
- name = capitalize(name);
1442
- for (const prefix of prefixes) {
1443
- const prefixed = prefix + name;
1444
- if (prefixed in style) {
1445
- return prefixCache[rawName] = prefixed;
1446
- }
1085
+ function addEventListener(element, event, handler, options) {
1086
+ const cleanup = addEvent(element, event, handler, options);
1087
+ if (getActiveScope()) {
1088
+ onCleanup(cleanup);
1447
1089
  }
1448
- return rawName;
1449
1090
  }
1450
- function patchAttr(el, key, prev, next) {
1451
- if (key === KEY_PROP) {
1452
- if (next == null) {
1453
- setNodeKey(el, void 0);
1454
- } else {
1455
- setNodeKey(el, String(next));
1456
- }
1457
- return;
1458
- }
1459
- if (key === SPREAD_NAME) {
1460
- {
1461
- if (!isObject(next)) {
1462
- warn("spread attribute must be an object");
1463
- }
1464
- }
1465
- Object.keys(next).forEach((k) => {
1466
- patchAttr(el, k, prev == null ? void 0 : prev[k], next == null ? void 0 : next[k]);
1467
- });
1468
- return;
1469
- }
1470
- if (isHydrating()) {
1471
- return;
1472
- }
1473
- const elementIsSVG = (el == null ? void 0 : el.namespaceURI) === SVG_NAMESPACE;
1474
- const isXlink = elementIsSVG && key.startsWith("xlink:");
1475
- const isXmlns = elementIsSVG && key.startsWith("xmlns:");
1476
- const isBoolean = isSpecialBooleanAttr(key) || isBooleanAttr(key);
1477
- if (prev === next) {
1478
- return;
1091
+
1092
+ // src/binding.ts
1093
+ function writeValue(el, v) {
1094
+ const target = el;
1095
+ const next2 = v == null ? "" : String(v);
1096
+ if (target.value !== next2) target.value = next2;
1097
+ }
1098
+ var CHECKBOX = {
1099
+ event: "change",
1100
+ forceChange: true,
1101
+ read: (el) => el.checked,
1102
+ write(el, v) {
1103
+ const e = el;
1104
+ const next2 = Boolean(v);
1105
+ if (e.checked !== next2) e.checked = next2;
1479
1106
  }
1480
- const lowerKey = key.toLowerCase();
1481
- if (lowerKey.length > 2 && lowerKey.charCodeAt(0) === 111 && lowerKey.charCodeAt(1) === 110) {
1482
- return;
1107
+ };
1108
+ var RADIO = {
1109
+ event: "change",
1110
+ forceChange: true,
1111
+ read(el) {
1112
+ const e = el;
1113
+ return e.checked ? e.value : "";
1114
+ },
1115
+ write(el, v) {
1116
+ const e = el;
1117
+ const next2 = String(v) === e.value;
1118
+ if (e.checked !== next2) e.checked = next2;
1483
1119
  }
1484
- if (lowerKey === "innerhtml") {
1485
- return;
1120
+ };
1121
+ var FILE = {
1122
+ event: "change",
1123
+ forceChange: true,
1124
+ read: (el) => el.files,
1125
+ write() {
1486
1126
  }
1487
- if (next == null) {
1488
- if (isXlink) {
1489
- el.removeAttributeNS(XLINK_NAMESPACE, key.slice(6));
1490
- } else if (isXmlns) {
1491
- const localName = key.slice(6);
1492
- el.removeAttributeNS(XMLNS_NAMESPACE, localName);
1127
+ // browsers forbid programmatic writes to file inputs
1128
+ };
1129
+ var TEXT = {
1130
+ event: "input",
1131
+ ime: true,
1132
+ read: (el) => el.value,
1133
+ write: writeValue
1134
+ };
1135
+ var TEXTAREA = {
1136
+ event: "input",
1137
+ ime: true,
1138
+ read: (el) => el.value,
1139
+ write: writeValue
1140
+ };
1141
+ var SELECT = {
1142
+ event: "change",
1143
+ forceChange: true,
1144
+ read(el) {
1145
+ const s = el;
1146
+ return s.multiple ? Array.from(s.selectedOptions, (o) => o.value) : s.value;
1147
+ },
1148
+ write(el, v) {
1149
+ const s = el;
1150
+ if (s.multiple) {
1151
+ const selected = new Set((Array.isArray(v) ? v : []).map(String));
1152
+ for (const opt of Array.from(s.options)) opt.selected = selected.has(opt.value);
1493
1153
  } else {
1494
- el.removeAttribute(key);
1154
+ writeValue(el, v);
1495
1155
  }
1496
- return;
1497
1156
  }
1498
- if (isXlink) {
1499
- el.setAttributeNS(XLINK_NAMESPACE, key, String(next));
1500
- return;
1157
+ };
1158
+ function resolve(node, prop) {
1159
+ switch (node.nodeName) {
1160
+ case "INPUT":
1161
+ if (prop === "checked") return node.type === "radio" ? RADIO : CHECKBOX;
1162
+ if (prop === "files") return FILE;
1163
+ return TEXT;
1164
+ case "SELECT":
1165
+ return SELECT;
1166
+ case "TEXTAREA":
1167
+ return TEXTAREA;
1168
+ default:
1169
+ return {
1170
+ event: "input",
1171
+ read: (el) => el[prop],
1172
+ write(el, v) {
1173
+ el[prop] = v;
1174
+ }
1175
+ };
1501
1176
  }
1502
- if (isXmlns) {
1503
- el.setAttributeNS(XMLNS_NAMESPACE, key, String(next));
1504
- return;
1177
+ }
1178
+ function applyModifiers(v, trim, toNum) {
1179
+ if (!isString(v)) return v;
1180
+ let s = v;
1181
+ if (trim) s = s.trim();
1182
+ if (toNum && s !== "") {
1183
+ const n = Number(s);
1184
+ if (!Number.isNaN(n)) return n;
1505
1185
  }
1506
- if (isBoolean) {
1507
- if (includeBooleanAttr(next)) {
1508
- el.setAttribute(key, "");
1509
- } else {
1510
- el.removeAttribute(key);
1511
- }
1512
- return;
1186
+ return s;
1187
+ }
1188
+ function isFocused(el) {
1189
+ const root = el.getRootNode();
1190
+ return (root instanceof Document || root instanceof ShadowRoot) && root.activeElement === el;
1191
+ }
1192
+ function bindElement(node, prop, getter, setter, modifiers = {}) {
1193
+ if (!node) return;
1194
+ const { event, read, write, forceChange, ime } = resolve(node, prop);
1195
+ const trim = modifiers.trim === true;
1196
+ const toNum = modifiers.number === true;
1197
+ const lazy = modifiers.lazy === true;
1198
+ const shouldCast = (trim || toNum) && prop !== "files";
1199
+ const getModel = isFunction(getter) ? getter : () => getter;
1200
+ const cast = shouldCast ? (v) => applyModifiers(v, trim, toNum) : (v) => v;
1201
+ let composing = false;
1202
+ const eventName = lazy || forceChange ? "change" : event;
1203
+ const syncToModel = () => {
1204
+ if (composing) return;
1205
+ const raw = read(node);
1206
+ if (raw === void 0) return;
1207
+ const next2 = cast(raw);
1208
+ if (!Object.is(getModel(), next2)) setter(next2);
1209
+ };
1210
+ addEventListener(node, eventName, syncToModel);
1211
+ if (!lazy && shouldCast && eventName !== "change") {
1212
+ addEventListener(node, "change", () => write(node, cast(read(node))));
1513
1213
  }
1514
- const attrValue = isSymbol(next) ? String(next) : next;
1515
- const isUrlAttr = lowerKey === "href" || lowerKey === "src" || lowerKey === "xlink:href";
1516
- if (isUrlAttr && isString(attrValue)) {
1517
- const v = attrValue.trim().toLowerCase();
1518
- if (v.startsWith("javascript:") || v.startsWith("data:")) {
1519
- return;
1520
- }
1214
+ if (ime && !lazy) {
1215
+ addEventListener(node, "compositionstart", () => {
1216
+ composing = true;
1217
+ });
1218
+ addEventListener(node, "compositionend", () => {
1219
+ if (!composing) return;
1220
+ composing = false;
1221
+ syncToModel();
1222
+ });
1521
1223
  }
1522
- if (elementIsSVG) {
1523
- el.setAttribute(key, String(attrValue));
1524
- } else {
1525
- if (key in el) {
1526
- try {
1527
- el[key] = attrValue;
1528
- } catch (e) {
1529
- el.setAttribute(key, String(attrValue));
1530
- }
1531
- } else {
1532
- el.setAttribute(key, String(attrValue));
1224
+ const runner = effect(() => {
1225
+ const value = getModel();
1226
+ if (ime && !lazy && isFocused(node)) {
1227
+ if (composing) return;
1228
+ if (Object.is(cast(read(node)), value)) return;
1533
1229
  }
1230
+ write(node, value);
1231
+ });
1232
+ if (getActiveScope()) {
1233
+ onCleanup(() => runner.stop());
1534
1234
  }
1535
1235
  }
1536
1236
 
1537
- // src/operations/event.ts
1538
- function addEvent(el, event, handler, options) {
1539
- if (!(options == null ? void 0 : options.delegate)) {
1540
- el.addEventListener(event, handler, options);
1541
- return () => el.removeEventListener(event, handler, options);
1542
- }
1543
- const selector = options.delegate;
1544
- const wrappedHandler = (e) => {
1545
- const target = e.target;
1546
- if (target.matches(selector) || target.closest(selector)) {
1547
- handler.call(el, e);
1237
+ // src/utils.ts
1238
+ function omitProps(target, keys) {
1239
+ const excludeSet = new Set(keys);
1240
+ return new Proxy(target, {
1241
+ /**
1242
+ * Returns a property unless it is excluded by the proxy.
1243
+ */
1244
+ get(obj, prop) {
1245
+ if (excludeSet.has(prop)) {
1246
+ return void 0;
1247
+ }
1248
+ return Reflect.get(obj, prop);
1249
+ },
1250
+ /**
1251
+ * Returns the enumerable keys that are not excluded from the proxy.
1252
+ */
1253
+ ownKeys(obj) {
1254
+ return Reflect.ownKeys(obj).filter((key) => !excludeSet.has(key));
1255
+ },
1256
+ /**
1257
+ * Returns the property descriptor unless the key is excluded.
1258
+ */
1259
+ getOwnPropertyDescriptor(obj, prop) {
1260
+ if (excludeSet.has(prop)) {
1261
+ return void 0;
1262
+ }
1263
+ return Reflect.getOwnPropertyDescriptor(obj, prop);
1264
+ },
1265
+ /**
1266
+ * Returns whether the requested value exists.
1267
+ */
1268
+ has(obj, prop) {
1269
+ if (excludeSet.has(prop)) {
1270
+ return false;
1271
+ }
1272
+ return Reflect.has(obj, prop);
1548
1273
  }
1549
- };
1550
- const cleanOptions = __spreadValues({}, options);
1551
- cleanOptions.delegate = void 0;
1552
- el.addEventListener(event, wrappedHandler, cleanOptions);
1553
- return () => {
1554
- el.removeEventListener(event, wrappedHandler, cleanOptions);
1555
- };
1274
+ });
1556
1275
  }
1276
+
1277
+ // src/components/Fragment.ts
1557
1278
  function Fragment(props) {
1558
- {
1559
- if (!props) {
1560
- error("Fragment component requires props");
1561
- return null;
1562
- }
1563
- }
1564
- if (!(props == null ? void 0 : props.children)) {
1565
- error("Fragment component requires children");
1566
- return null;
1567
- }
1568
- const { children } = props;
1569
- return children;
1279
+ if (!props || props.children == null) return null;
1280
+ return props.children;
1570
1281
  }
1571
1282
  Fragment[FRAGMENT_COMPONENT] = true;
1572
1283
  function isFragment(node) {
1573
1284
  return !!node && !!node[FRAGMENT_COMPONENT];
1574
1285
  }
1286
+ function resolveTarget(props) {
1287
+ const raw = isFunction(props.target) ? props.target() : props.target;
1288
+ if (raw == null) return null;
1289
+ if (isString(raw)) return document.querySelector(raw);
1290
+ return raw;
1291
+ }
1292
+ function evalDisabled(props) {
1293
+ return isFunction(props.disabled) ? !!props.disabled() : !!props.disabled;
1294
+ }
1575
1295
  function Portal(props) {
1296
+ if (isHydrating()) {
1297
+ const adopted = tryHydratePortal(props);
1298
+ if (adopted) return adopted;
1299
+ }
1576
1300
  const placeholder = document.createComment("portal");
1577
1301
  placeholder[PORTAL_COMPONENT] = true;
1578
- const children = props.children;
1579
- if (children) {
1580
- const childArray = isArray(children) ? children : [children];
1581
- const nodes = [];
1582
- onMount(() => {
1583
- const targetElement = isString(props.target) ? document.querySelector(props.target) : props.target;
1584
- if (!targetElement) {
1585
- if (true) {
1586
- warn(`[Portal] Target element not found: ${props.target}`);
1587
- }
1588
- return;
1302
+ const { children } = props;
1303
+ if (children == null) return placeholder;
1304
+ const ownerScope = getActiveScope();
1305
+ let innerScope = null;
1306
+ const mountAt = (parent, before) => {
1307
+ innerScope = createScope(ownerScope);
1308
+ runWithScope(innerScope, () => {
1309
+ insert(parent, () => children, before);
1310
+ });
1311
+ };
1312
+ const teardown = () => {
1313
+ if (innerScope) {
1314
+ disposeScope(innerScope);
1315
+ innerScope = null;
1316
+ }
1317
+ };
1318
+ const apply = (disabled, target) => {
1319
+ teardown();
1320
+ if (disabled) {
1321
+ const parent = placeholder.parentNode;
1322
+ if (!parent) return;
1323
+ mountAt(parent, placeholder);
1324
+ return;
1325
+ }
1326
+ if (!target) {
1327
+ {
1328
+ warn(`[Portal] Target element not found: ${String(props.target)}`);
1589
1329
  }
1590
- childArray.forEach((child) => {
1591
- if (child != null) {
1592
- const normalized = normalizeNode(child);
1593
- if (normalized) {
1594
- insertNode(targetElement, normalized);
1595
- nodes.push(normalized);
1596
- }
1597
- }
1598
- });
1599
- onCleanup(() => {
1600
- nodes.forEach((node) => {
1601
- if (!isString(node) && node.parentNode === targetElement) {
1602
- targetElement.removeChild(node);
1603
- }
1604
- });
1605
- });
1330
+ return;
1331
+ }
1332
+ mountAt(target);
1333
+ };
1334
+ let mounted = false;
1335
+ const effectRunner = effect(() => {
1336
+ const disabled = evalDisabled(props);
1337
+ const target = disabled ? null : resolveTarget(props);
1338
+ if (mounted) {
1339
+ apply(disabled, target);
1340
+ }
1341
+ });
1342
+ onMount(() => {
1343
+ mounted = true;
1344
+ const disabled = evalDisabled(props);
1345
+ const target = disabled ? null : resolveTarget(props);
1346
+ if (disabled || target) {
1347
+ apply(disabled, target);
1348
+ return;
1349
+ }
1350
+ queueMicrotask(() => {
1351
+ if (!placeholder.parentNode) return;
1352
+ apply(evalDisabled(props), resolveTarget(props));
1606
1353
  });
1607
- }
1354
+ });
1355
+ onCleanup(() => {
1356
+ effectRunner.stop();
1357
+ teardown();
1358
+ });
1608
1359
  return placeholder;
1609
1360
  }
1610
1361
  Portal[PORTAL_COMPONENT] = true;
1362
+ function tryHydratePortal(props) {
1363
+ if (evalDisabled(props)) return null;
1364
+ const anchor = consumeTeleportAnchor();
1365
+ if (!anchor) {
1366
+ {
1367
+ warn("[Portal] hydration mismatch: no <!--teleport-anchor--> at call site.");
1368
+ }
1369
+ return null;
1370
+ }
1371
+ const target = resolveTarget(props);
1372
+ if (!target) {
1373
+ {
1374
+ warn(`[Portal] hydration mismatch: target not found: ${String(props.target)}`);
1375
+ }
1376
+ return null;
1377
+ }
1378
+ const block = consumeTeleportBlock(target);
1379
+ if (!block) {
1380
+ {
1381
+ warn(
1382
+ `[Portal] hydration mismatch: no <!--teleport-start--> in target ${String(props.target)}`
1383
+ );
1384
+ }
1385
+ return null;
1386
+ }
1387
+ anchor[PORTAL_COMPONENT] = true;
1388
+ return anchor;
1389
+ }
1611
1390
  function isPortal(node) {
1612
1391
  return !!node && !!node[PORTAL_COMPONENT];
1613
1392
  }
1393
+ function clearContainer(el) {
1394
+ while (el.firstChild) {
1395
+ el.removeChild(el.firstChild);
1396
+ }
1397
+ }
1398
+ function resolveNodeValue(value) {
1399
+ let current = value;
1400
+ while (isFunction(current)) {
1401
+ current = current();
1402
+ }
1403
+ if (isSignal(current) || isComputed(current)) {
1404
+ return resolveNodeValue(current.value);
1405
+ }
1406
+ return current;
1407
+ }
1614
1408
  var SuspenseContext = /* @__PURE__ */ Symbol("SuspenseContext");
1615
1409
  function Suspense(props) {
1616
- if (isUndefined(document)) {
1617
- const fallback = props.fallback;
1618
- if (fallback) {
1619
- return String(fallback || "");
1620
- }
1621
- return "";
1410
+ var _a2;
1411
+ if (!isBrowser()) {
1412
+ return (_a2 = props.fallback) != null ? _a2 : "";
1622
1413
  }
1623
1414
  const container = document.createElement("div");
1624
1415
  container.style.display = "contents";
@@ -1626,19 +1417,42 @@ function Suspense(props) {
1626
1417
  let pendingCount = 0;
1627
1418
  let isShowingFallback = false;
1628
1419
  let resolvedChildren = null;
1629
- const showFallback = () => {
1630
- if (isShowingFallback) return;
1631
- isShowingFallback = true;
1632
- while (container.firstChild) {
1633
- container.removeChild(container.firstChild);
1420
+ const materializeChild = (value) => {
1421
+ const current = resolveNodeValue(value);
1422
+ if (isArray(current)) {
1423
+ const nodes = [];
1424
+ for (const item of current) {
1425
+ const materialized = materializeChild(item);
1426
+ if (isArray(materialized)) {
1427
+ nodes.push(...materialized);
1428
+ } else {
1429
+ nodes.push(materialized);
1430
+ }
1431
+ }
1432
+ return nodes;
1634
1433
  }
1635
- if (props.fallback != null) {
1636
- const normalized = normalizeNode(props.fallback);
1637
- if (normalized) {
1638
- insertNode(container, normalized);
1434
+ return normalizeNode(current);
1435
+ };
1436
+ const insertMaterializedChild = (value) => {
1437
+ const normalized = materializeChild(value);
1438
+ const nodes = isArray(normalized) ? normalized : [normalized];
1439
+ for (const node of nodes) {
1440
+ if (node != null) {
1441
+ insertNode(container, node);
1639
1442
  }
1640
1443
  }
1641
1444
  };
1445
+ const renderFallbackContent = () => {
1446
+ clearContainer(container);
1447
+ if (props.fallback != null) {
1448
+ insertMaterializedChild(props.fallback);
1449
+ }
1450
+ };
1451
+ const showFallback = () => {
1452
+ if (isShowingFallback) return;
1453
+ isShowingFallback = true;
1454
+ renderFallbackContent();
1455
+ };
1642
1456
  const showChildren = () => {
1643
1457
  if (!isShowingFallback) return;
1644
1458
  const hasContent = resolvedChildren || props.children != null && !isPromise(props.children);
@@ -1646,9 +1460,7 @@ function Suspense(props) {
1646
1460
  return;
1647
1461
  }
1648
1462
  isShowingFallback = false;
1649
- while (container.firstChild) {
1650
- container.removeChild(container.firstChild);
1651
- }
1463
+ clearContainer(container);
1652
1464
  if (resolvedChildren) {
1653
1465
  renderChildren(resolvedChildren);
1654
1466
  } else if (props.children != null && !isPromise(props.children)) {
@@ -1656,33 +1468,17 @@ function Suspense(props) {
1656
1468
  }
1657
1469
  };
1658
1470
  const renderChildren = (children2) => {
1659
- while (container.firstChild) {
1660
- container.removeChild(container.firstChild);
1661
- }
1471
+ if (isShowingFallback) return;
1472
+ clearContainer(container);
1662
1473
  if (children2 == null) return;
1663
- const currentScope = getActiveScope();
1664
1474
  const childArray = isArray(children2) ? children2 : [children2];
1665
- childArray.forEach((child) => {
1666
- if (child != null) {
1667
- if (isComponent(child)) {
1668
- child.parentContext = currentScope;
1669
- }
1670
- const normalized = normalizeNode(child);
1671
- if (normalized) {
1672
- insertNode(container, normalized);
1673
- }
1475
+ for (const child2 of childArray) {
1476
+ if (child2 != null) {
1477
+ insertMaterializedChild(child2);
1674
1478
  }
1675
- });
1479
+ }
1676
1480
  if (isShowingFallback) {
1677
- while (container.firstChild) {
1678
- container.removeChild(container.firstChild);
1679
- }
1680
- if (props.fallback != null) {
1681
- const normalized = normalizeNode(props.fallback);
1682
- if (normalized) {
1683
- insertNode(container, normalized);
1684
- }
1685
- }
1481
+ renderFallbackContent();
1686
1482
  }
1687
1483
  };
1688
1484
  const suspenseContext = {
@@ -1695,9 +1491,9 @@ function Suspense(props) {
1695
1491
  if (pendingCount === 0) {
1696
1492
  showChildren();
1697
1493
  }
1698
- }).catch((error8) => {
1494
+ }).catch((error4) => {
1699
1495
  {
1700
- warn("[Suspense] Resource failed:", error8);
1496
+ warn("[Suspense] Resource failed:", error4);
1701
1497
  }
1702
1498
  if (!isMounted) return;
1703
1499
  pendingCount--;
@@ -1711,7 +1507,7 @@ function Suspense(props) {
1711
1507
  showFallback();
1712
1508
  },
1713
1509
  decrement: () => {
1714
- pendingCount--;
1510
+ pendingCount = Math.max(0, pendingCount - 1);
1715
1511
  if (pendingCount === 0) {
1716
1512
  showChildren();
1717
1513
  }
@@ -1732,9 +1528,10 @@ function Suspense(props) {
1732
1528
  }
1733
1529
  onDestroy(() => {
1734
1530
  isMounted = false;
1735
- while (container.firstChild) {
1736
- container.removeChild(container.firstChild);
1737
- }
1531
+ pendingCount = 0;
1532
+ resolvedChildren = null;
1533
+ clearContainer(container);
1534
+ container.remove();
1738
1535
  });
1739
1536
  return container;
1740
1537
  }
@@ -1745,19 +1542,25 @@ function isSuspense(node) {
1745
1542
  function createResource(fetcher, options) {
1746
1543
  const value = signal(options == null ? void 0 : options.initialValue);
1747
1544
  const loading = signal(true);
1748
- const error8 = signal(null);
1545
+ const error4 = signal(null);
1749
1546
  const state = signal("pending");
1750
1547
  let fetchId = 0;
1751
1548
  let currentPromise = null;
1549
+ let suspenseRegistered = false;
1550
+ const suspenseContext = inject(SuspenseContext, null);
1752
1551
  const fetch = () => __async(null, null, function* () {
1753
1552
  const currentFetchId = ++fetchId;
1754
1553
  loading.value = true;
1755
1554
  state.value = "pending";
1756
- error8.value = null;
1555
+ error4.value = null;
1556
+ suspenseRegistered = false;
1557
+ if (suspenseContext) {
1558
+ suspenseContext.increment();
1559
+ }
1757
1560
  try {
1758
1561
  const promise = fetcher();
1759
- currentPromise = promise.then(() => {
1760
- }).catch(() => {
1562
+ currentPromise = promise;
1563
+ promise.catch(() => {
1761
1564
  });
1762
1565
  const result = yield promise;
1763
1566
  if (currentFetchId === fetchId) {
@@ -1767,31 +1570,33 @@ function createResource(fetcher, options) {
1767
1570
  }
1768
1571
  } catch (error_) {
1769
1572
  if (currentFetchId === fetchId) {
1770
- error8.value = error_ instanceof Error ? error_ : new Error(String(error_));
1573
+ error4.value = error_ instanceof Error ? error_ : new Error(String(error_));
1771
1574
  state.value = "errored";
1772
1575
  loading.value = false;
1773
1576
  }
1577
+ } finally {
1578
+ if (suspenseContext) {
1579
+ suspenseContext.decrement();
1580
+ }
1774
1581
  }
1775
1582
  });
1776
1583
  fetch();
1777
1584
  const resource = (() => {
1778
- if (loading.value && currentPromise) {
1779
- const suspenseContext = inject(SuspenseContext, null);
1780
- if (suspenseContext) {
1781
- suspenseContext.register(currentPromise);
1782
- }
1585
+ if (!suspenseRegistered && loading.value && currentPromise && suspenseContext) {
1586
+ suspenseRegistered = true;
1587
+ suspenseContext.register(currentPromise);
1783
1588
  }
1784
1589
  return value.value;
1785
1590
  });
1786
1591
  resource.loading = loading;
1787
- resource.error = error8;
1592
+ resource.error = error4;
1788
1593
  resource.state = state;
1789
1594
  const actions = {
1790
1595
  mutate: (newValue) => {
1791
1596
  value.value = newValue;
1792
1597
  state.value = "ready";
1793
1598
  loading.value = false;
1794
- error8.value = null;
1599
+ error4.value = null;
1795
1600
  },
1796
1601
  refetch: () => __async(null, null, function* () {
1797
1602
  yield fetch();
@@ -1799,89 +1604,274 @@ function createResource(fetcher, options) {
1799
1604
  };
1800
1605
  return [resource, actions];
1801
1606
  }
1607
+ function resolveModule(mod) {
1608
+ return isFunction(mod) ? mod : mod.default;
1609
+ }
1610
+ function renderInto(el, fn, props) {
1611
+ const comp = new Component(fn, props);
1612
+ comp.mount(el);
1613
+ return comp;
1614
+ }
1615
+ function defineAsyncComponent(loader, options = {}) {
1616
+ const { delay = 200, timeout, ssr = "blocking", onError } = options;
1617
+ if (typeof window === "undefined") {
1618
+ if (ssr === "client-only") {
1619
+ const placeholder = () => "";
1620
+ placeholder.__asyncLoader = loader;
1621
+ placeholder.__asyncResolved = () => null;
1622
+ return placeholder;
1623
+ }
1624
+ let ssrResolved = null;
1625
+ let ssrPromise = null;
1626
+ const ssrLoad = () => {
1627
+ if (ssrPromise) return ssrPromise;
1628
+ ssrPromise = loader().then((mod) => {
1629
+ ssrResolved = resolveModule(mod);
1630
+ }).catch(() => {
1631
+ });
1632
+ return ssrPromise;
1633
+ };
1634
+ ssrLoad();
1635
+ const ssrWrapper = (props) => {
1636
+ if (ssrResolved) {
1637
+ return ssrResolved(props);
1638
+ }
1639
+ return "";
1640
+ };
1641
+ ssrWrapper.__asyncLoader = ssrLoad;
1642
+ ssrWrapper.__asyncResolved = () => ssrResolved;
1643
+ return ssrWrapper;
1644
+ }
1645
+ let cachedComponent = null;
1646
+ let cachedError = null;
1647
+ let cachedStatus = "pending";
1648
+ let loadPromise = null;
1649
+ function load() {
1650
+ if (loadPromise) return loadPromise;
1651
+ loadPromise = loader().then((mod) => {
1652
+ cachedComponent = resolveModule(mod);
1653
+ cachedStatus = "resolved";
1654
+ }).catch((error4) => {
1655
+ cachedError = error4 instanceof Error ? error4 : new Error(String(error4));
1656
+ cachedStatus = "errored";
1657
+ loadPromise = null;
1658
+ });
1659
+ return loadPromise;
1660
+ }
1661
+ load();
1662
+ function AsyncWrapper(props) {
1663
+ var _a2;
1664
+ if (cachedStatus === "resolved" && cachedComponent) {
1665
+ const el = document.createElement("div");
1666
+ el.style.display = "contents";
1667
+ const comp = renderInto(el, cachedComponent, props);
1668
+ onCleanup(() => comp.destroy());
1669
+ return el;
1670
+ }
1671
+ if (cachedStatus === "errored" && cachedError) {
1672
+ const el = document.createElement("div");
1673
+ el.style.display = "contents";
1674
+ if (options.error) {
1675
+ let alive2 = true;
1676
+ let currentComp2 = null;
1677
+ const swap2 = (fn, swapProps) => {
1678
+ if (!alive2) return;
1679
+ currentComp2 == null ? void 0 : currentComp2.destroy();
1680
+ currentComp2 = renderInto(el, fn, swapProps);
1681
+ };
1682
+ const retry = () => {
1683
+ loadPromise = null;
1684
+ cachedStatus = "pending";
1685
+ cachedError = null;
1686
+ if (options.loading) swap2(options.loading);
1687
+ load().then(() => {
1688
+ if (!alive2) return;
1689
+ if (cachedStatus === "resolved" && cachedComponent) {
1690
+ swap2(cachedComponent, props);
1691
+ } else if (cachedStatus === "errored" && cachedError) {
1692
+ if (options.error) swap2(options.error, { error: cachedError, retry });
1693
+ }
1694
+ });
1695
+ };
1696
+ swap2(options.error, { error: cachedError, retry });
1697
+ onDestroy(() => {
1698
+ alive2 = false;
1699
+ currentComp2 == null ? void 0 : currentComp2.destroy();
1700
+ currentComp2 = null;
1701
+ });
1702
+ }
1703
+ return el;
1704
+ }
1705
+ const container = document.createElement("div");
1706
+ container.style.display = "contents";
1707
+ let alive = true;
1708
+ let currentComp = null;
1709
+ let delayTimer = null;
1710
+ let timeoutTimer = null;
1711
+ const swap = (fn, swapProps) => {
1712
+ if (!alive) return;
1713
+ currentComp == null ? void 0 : currentComp.destroy();
1714
+ currentComp = renderInto(container, fn, swapProps);
1715
+ };
1716
+ const retryWith = (retryProps) => () => {
1717
+ loadPromise = null;
1718
+ cachedStatus = "pending";
1719
+ cachedError = null;
1720
+ if (options.loading) swap(options.loading);
1721
+ load().then(() => {
1722
+ if (cachedStatus === "resolved" && cachedComponent) {
1723
+ swap(cachedComponent, retryProps);
1724
+ } else if (cachedStatus === "errored" && cachedError) {
1725
+ if (options.error) {
1726
+ swap(options.error, {
1727
+ error: cachedError,
1728
+ retry: retryWith(retryProps)
1729
+ });
1730
+ }
1731
+ }
1732
+ });
1733
+ };
1734
+ onDestroy(() => {
1735
+ alive = false;
1736
+ currentComp == null ? void 0 : currentComp.destroy();
1737
+ currentComp = null;
1738
+ if (delayTimer != null) clearTimeout(delayTimer);
1739
+ if (timeoutTimer != null) clearTimeout(timeoutTimer);
1740
+ });
1741
+ const suspenseCtx = (_a2 = inject(SuspenseContext)) != null ? _a2 : null;
1742
+ const showResolved = (compFn) => swap(compFn, props);
1743
+ const showError = (err) => {
1744
+ if (options.error) swap(options.error, { error: err, retry: retryWith(props) });
1745
+ };
1746
+ const showLoading = () => {
1747
+ if (options.loading) swap(options.loading);
1748
+ };
1749
+ const instancePromise = load().then(() => {
1750
+ if (!alive) return;
1751
+ if (cachedStatus === "resolved" && cachedComponent) {
1752
+ showResolved(cachedComponent);
1753
+ } else if (cachedStatus === "errored" && cachedError) {
1754
+ showError(cachedError);
1755
+ if (onError) onError(cachedError, retryWith(props));
1756
+ }
1757
+ if (delayTimer != null) clearTimeout(delayTimer);
1758
+ if (timeoutTimer != null) clearTimeout(timeoutTimer);
1759
+ });
1760
+ if (suspenseCtx) {
1761
+ suspenseCtx.register(instancePromise);
1762
+ }
1763
+ if (delay > 0) {
1764
+ delayTimer = setTimeout(() => {
1765
+ if (alive && cachedStatus === "pending") {
1766
+ showLoading();
1767
+ }
1768
+ }, delay);
1769
+ } else if (options.loading) {
1770
+ showLoading();
1771
+ }
1772
+ if (timeout != null) {
1773
+ timeoutTimer = setTimeout(() => {
1774
+ if (alive && cachedStatus === "pending") {
1775
+ const err = new Error(`[defineAsyncComponent] Timeout after ${timeout}ms`);
1776
+ cachedError = err;
1777
+ cachedStatus = "errored";
1778
+ showError(err);
1779
+ if (onError) onError(err, retryWith(props));
1780
+ }
1781
+ }, timeout);
1782
+ }
1783
+ return container;
1784
+ }
1785
+ AsyncWrapper.__asyncLoader = load;
1786
+ AsyncWrapper.__asyncResolved = () => cachedComponent;
1787
+ return AsyncWrapper;
1788
+ }
1802
1789
  function For(props) {
1803
1790
  const fragment = document.createDocumentFragment();
1804
1791
  const marker = document.createComment("");
1805
1792
  fragment.appendChild(marker);
1806
1793
  let entries = [];
1807
- let fallbackNode = null;
1808
- const keyFn = props.keyFn;
1794
+ let fallbackNodes = [];
1795
+ const keyFn = props.key;
1809
1796
  const renderFn = props.children;
1810
1797
  const getList = () => {
1811
1798
  var _a2, _b;
1812
1799
  const input = props.each;
1813
1800
  if (isSignal(input)) return (_a2 = input.value) != null ? _a2 : [];
1814
- if (typeof input === "function") return (_b = input()) != null ? _b : [];
1801
+ if (isFunction(input)) return (_b = input()) != null ? _b : [];
1815
1802
  return input != null ? input : [];
1816
1803
  };
1817
1804
  const getKey = (item) => keyFn ? keyFn(item) : item;
1818
- const renderItem = (item, index, parent, before) => {
1819
- var _a2;
1820
- const prevScope = getActiveScope();
1821
- const scope = createScope(prevScope);
1822
- setActiveScope(scope);
1823
- let node;
1824
- try {
1825
- const result = renderFn(item, index);
1826
- if (isComponent(result)) {
1827
- result.mount(parent, before);
1828
- node = (_a2 = result.firstChild) != null ? _a2 : document.createComment("empty");
1805
+ const normalizeNodes = (value) => {
1806
+ if (Array.isArray(value)) {
1807
+ const nodes = [];
1808
+ for (const item of value) {
1809
+ nodes.push(...normalizeNodes(item));
1810
+ }
1811
+ return nodes;
1812
+ }
1813
+ return [normalizeNode(value)];
1814
+ };
1815
+ const mountValue = (value, parent, before) => {
1816
+ const nodes = normalizeNodes(value);
1817
+ for (const node of nodes) {
1818
+ if (before) {
1819
+ parent.insertBefore(node, before);
1829
1820
  } else {
1830
- node = result;
1831
- if (!node.parentNode) {
1832
- if (before) {
1833
- parent.insertBefore(node, before);
1834
- } else {
1835
- parent.appendChild(node);
1836
- }
1837
- }
1821
+ parent.appendChild(node);
1822
+ }
1823
+ }
1824
+ return nodes;
1825
+ };
1826
+ const mountFallback = (parent, before) => {
1827
+ if (!props.fallback) return;
1828
+ const nodes = mountValue(props.fallback(), parent, before);
1829
+ fallbackNodes = nodes;
1830
+ };
1831
+ const clearFallback = () => {
1832
+ for (const node of fallbackNodes) {
1833
+ if (node.parentNode) {
1834
+ node.parentNode.removeChild(node);
1838
1835
  }
1839
- } finally {
1840
- setActiveScope(prevScope);
1841
1836
  }
1842
- return { key: getKey(item), node, scope };
1837
+ fallbackNodes = [];
1838
+ };
1839
+ const renderItem = (item, index, parent, before) => {
1840
+ const parentScope = getActiveScope();
1841
+ const scope = createScope(parentScope);
1842
+ let mountedNodes = [];
1843
+ runWithScope(scope, () => {
1844
+ mountedNodes = mountValue(renderFn(item, index), parent, before);
1845
+ });
1846
+ return { key: getKey(item), item, nodes: mountedNodes, scope };
1843
1847
  };
1844
1848
  const disposeItem = (entry) => {
1845
1849
  disposeScope(entry.scope);
1846
- if (entry.node.parentNode) {
1847
- entry.node.parentNode.removeChild(entry.node);
1850
+ for (const node of entry.nodes) {
1851
+ if (node.parentNode) {
1852
+ node.parentNode.removeChild(node);
1853
+ }
1848
1854
  }
1849
1855
  };
1850
- memoEffect(
1851
- ({ prev }) => {
1852
- var _a2;
1853
- const newItems = getList();
1854
- if (prev === newItems) return { prev: newItems };
1855
- const parent = marker.parentNode;
1856
- if (!parent) {
1857
- if (newItems.length === 0) {
1858
- if (props.fallback) {
1859
- const fb = props.fallback();
1860
- if (isComponent(fb)) {
1861
- fb.mount(fragment, marker);
1862
- fallbackNode = (_a2 = fb.firstChild) != null ? _a2 : document.createComment("empty");
1863
- } else {
1864
- fallbackNode = fb;
1865
- fragment.insertBefore(fallbackNode, marker);
1866
- }
1867
- }
1868
- return { prev: newItems };
1869
- }
1856
+ const effectRunner = effect(() => {
1857
+ const newItems = getList();
1858
+ const parent = marker.parentNode;
1859
+ if (!parent) {
1860
+ if (newItems.length === 0) {
1861
+ mountFallback(fragment, marker);
1862
+ } else {
1870
1863
  entries = new Array(newItems.length);
1871
- for (const [i, newItem] of newItems.entries()) {
1872
- entries[i] = renderItem(newItem, i, fragment, marker);
1864
+ let idx = 0;
1865
+ for (const newItem of newItems) {
1866
+ entries[idx] = renderItem(newItem, idx, fragment, marker);
1867
+ idx++;
1873
1868
  }
1874
- return { prev: newItems };
1875
1869
  }
1876
- untrack(() => reconcile(parent, newItems));
1877
- return { prev: newItems };
1878
- },
1879
- {
1880
- prev: []
1870
+ return;
1881
1871
  }
1882
- );
1872
+ reconcile(parent, newItems);
1873
+ });
1883
1874
  function reconcile(parent, newItems) {
1884
- var _a2;
1885
1875
  const oldLen = entries.length;
1886
1876
  const newLen = newItems.length;
1887
1877
  if (newLen === 0) {
@@ -1889,22 +1879,14 @@ function For(props) {
1889
1879
  disposeItem(entries[i]);
1890
1880
  }
1891
1881
  entries = [];
1892
- if (props.fallback && !fallbackNode) {
1893
- const fb = props.fallback();
1894
- if (isComponent(fb)) {
1895
- fb.mount(parent, marker);
1896
- fallbackNode = (_a2 = fb.firstChild) != null ? _a2 : document.createComment("empty");
1897
- } else {
1898
- fallbackNode = fb;
1899
- parent.insertBefore(fallbackNode, marker);
1900
- }
1882
+ if (props.fallback && fallbackNodes.length === 0) {
1883
+ mountFallback(parent, marker);
1901
1884
  }
1902
1885
  return;
1903
1886
  }
1904
- if (oldLen === 0 || fallbackNode) {
1905
- if (fallbackNode) {
1906
- if (fallbackNode.parentNode) fallbackNode.parentNode.removeChild(fallbackNode);
1907
- fallbackNode = null;
1887
+ if (oldLen === 0 || fallbackNodes.length > 0) {
1888
+ if (fallbackNodes.length > 0) {
1889
+ clearFallback();
1908
1890
  }
1909
1891
  entries = new Array(newLen);
1910
1892
  const batchFragment2 = document.createDocumentFragment();
@@ -1918,46 +1900,76 @@ function For(props) {
1918
1900
  for (let i = 0; i < oldLen; i++) {
1919
1901
  const entry = entries[i];
1920
1902
  const list = oldKeyMap.get(entry.key);
1921
- if (list) {
1922
- list.push(entry);
1923
- } else {
1924
- oldKeyMap.set(entry.key, [entry]);
1925
- }
1903
+ const pair = [entry, i];
1904
+ if (list) list.push(pair);
1905
+ else oldKeyMap.set(entry.key, [pair]);
1926
1906
  }
1927
1907
  const newEntries = new Array(newLen);
1928
1908
  const toRemove = [];
1929
- const batchFragment = document.createDocumentFragment();
1909
+ let batchFragment = null;
1910
+ const newIndexToOldIndex = new Int32Array(newLen);
1911
+ let moved = false;
1912
+ let maxOldSeen = 0;
1913
+ const newKeys = new Array(newLen);
1914
+ for (let i = 0; i < newLen; i++) {
1915
+ newKeys[i] = getKey(newItems[i]);
1916
+ }
1930
1917
  for (let i = 0; i < newLen; i++) {
1931
1918
  const item = newItems[i];
1932
- const key = getKey(item);
1919
+ const key = newKeys[i];
1933
1920
  const oldList = oldKeyMap.get(key);
1934
1921
  if (oldList && oldList.length > 0) {
1935
- newEntries[i] = oldList.shift();
1922
+ const [reused, oldIndex] = oldList.shift();
1923
+ if (Object.is(reused.item, item)) {
1924
+ reused.item = item;
1925
+ newEntries[i] = reused;
1926
+ newIndexToOldIndex[i] = oldIndex + 1;
1927
+ if (oldIndex < maxOldSeen) moved = true;
1928
+ else maxOldSeen = oldIndex;
1929
+ } else {
1930
+ if (!batchFragment) batchFragment = document.createDocumentFragment();
1931
+ disposeItem(reused);
1932
+ newEntries[i] = renderItem(item, i, batchFragment, null);
1933
+ }
1936
1934
  } else {
1935
+ if (!batchFragment) batchFragment = document.createDocumentFragment();
1937
1936
  newEntries[i] = renderItem(item, i, batchFragment, null);
1938
1937
  }
1939
1938
  }
1940
1939
  for (const list of oldKeyMap.values()) {
1941
- for (const entry of list) {
1942
- toRemove.push(entry);
1940
+ for (const [entry] of list) toRemove.push(entry);
1941
+ }
1942
+ for (const entry of toRemove) disposeItem(entry);
1943
+ const lis = moved ? getSequence(newIndexToOldIndex) : [];
1944
+ let lisCursor = lis.length - 1;
1945
+ let nextNode = marker;
1946
+ for (let i = newLen - 1; i >= 0; i--) {
1947
+ const entry = newEntries[i];
1948
+ const nodes = entry.nodes;
1949
+ const isFresh = newIndexToOldIndex[i] === 0;
1950
+ const inLis = !isFresh && moved && lisCursor >= 0 && i === lis[lisCursor];
1951
+ if (inLis) {
1952
+ lisCursor--;
1953
+ for (let j = nodes.length - 1; j >= 0; j--) nextNode = nodes[j];
1954
+ continue;
1955
+ }
1956
+ for (let j = nodes.length - 1; j >= 0; j--) {
1957
+ const node = nodes[j];
1958
+ if (node.nextSibling !== nextNode) {
1959
+ parent.insertBefore(node, nextNode);
1960
+ }
1961
+ nextNode = node;
1943
1962
  }
1944
- }
1945
- for (const entry of toRemove) {
1946
- disposeItem(entry);
1947
- }
1948
- for (let i = 0; i < newLen; i++) {
1949
- const node = newEntries[i].node;
1950
- parent.insertBefore(node, marker);
1951
1963
  }
1952
1964
  entries = newEntries;
1953
1965
  }
1954
1966
  onCleanup(() => {
1967
+ effectRunner.stop();
1955
1968
  for (const entry of entries) {
1956
1969
  disposeItem(entry);
1957
1970
  }
1958
- if (fallbackNode && fallbackNode.parentNode) {
1959
- fallbackNode.parentNode.removeChild(fallbackNode);
1960
- }
1971
+ entries = [];
1972
+ clearFallback();
1961
1973
  if (marker.parentNode) {
1962
1974
  marker.parentNode.removeChild(marker);
1963
1975
  }
@@ -1966,6 +1978,6 @@ function For(props) {
1966
1978
  }
1967
1979
  For[FOR_COMPONENT] = true;
1968
1980
 
1969
- export { Component, For, Fragment, Portal, Suspense, addEvent, addEventListener, bindElement, createApp, createComponent, createResource, createScope, delegateEvents, disposeScope, endHydration, getActiveScope, getFirstDOMNode, getHydrationKey, getRenderedElement, hydrate, inject, insert, insertNode, isComponent, isFragment, isHydrating, isPortal, isSameNode, isSuspense, mapNodes, mapSSRNodes, normalizeClass, normalizeNode, omitProps, onCleanup, onDestroy, onMount, onUpdate, patchAttr, patchClass, patchStyle, provide, removeNode, replaceNode, resetHydrationKey, runWithScope, setActiveScope, setStyle, shallowCompare, startHydration, template };
1981
+ export { Component, For, Fragment, Portal, Suspense, addEvent, addEventListener, beginHydration, bindElement, child, clearDelegatedEvents, consumeTeleportAnchor, consumeTeleportBlock, createApp, createComponent, createResource, defineAsyncComponent, delegateEvents, endHydration, getHydrationKey, getRenderedElement, hydrate, inject, insert, isComponent, isFragment, isHydrating, isPortal, isSuspense, next, normalizeClass, nthChild, omitProps, onDestroy, onMount, onUpdate, patchAttr, patchAttrHydrate, patchClass, patchClassHydrate, patchStyle, patchStyleHydrate, provide, resetHydrationKey, setStyle, template };
1970
1982
  //# sourceMappingURL=template.dev.esm.js.map
1971
1983
  //# sourceMappingURL=template.dev.esm.js.map