@estjs/template 0.0.15-beta.13 → 0.0.15-beta.17

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