@estjs/template 0.0.15-beta.9 → 0.0.16-beta.1

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,603 +1,461 @@
1
- import { error, isHTMLElement, isPrimitive, isFalsy, isHtmlInputElement, isHtmlSelectElement, isHtmlTextAreaElement, isFunction, isObject, startsWith, isString, normalizeClassName, isArray, camelCase, capitalize, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isUndefined, isPromise, isNumber, coerceArray, isTextNode } from '@estjs/shared';
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';
2
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;
120
58
  }
121
- if ((_a2 = scope.parent) == null ? void 0 : _a2.children) {
122
- scope.parent.children.delete(scope);
59
+ const elementIsSVG = (el == null ? void 0 : el.namespaceURI) === SVG_NAMESPACE;
60
+ const isXlink = elementIsSVG && key.startsWith("xlink:");
61
+ const isXmlns = elementIsSVG && key.startsWith("xmlns:");
62
+ const isBoolean2 = isSpecialBooleanAttr(key) || isBooleanAttr(key);
63
+ if (prev === next2) {
64
+ return;
123
65
  }
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) {
66
+ if (key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110) {
67
+ return;
68
+ }
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 MAX_KEY_LENGTH = 1e3;
155
- var componentKeyPrefixCache = /* @__PURE__ */ new WeakMap();
156
- function getComponentKey(type) {
157
- let prefix = componentKeyPrefixCache.get(type);
158
- if (!prefix) {
159
- const name = type.name || "anonymous";
160
- const hash = simpleHash(type.toString()).toString(36);
161
- prefix = `${name}_${hash}`;
162
- componentKeyPrefixCache.set(type, prefix);
163
- }
164
- return prefix;
165
- }
166
- function simpleHash(str) {
167
- let hash = 0;
168
- const len = str.length < 100 ? str.length : 100;
169
- for (let i = 0; i < len; i++) {
170
- hash = Math.trunc((hash << 5) - hash + str.charCodeAt(i));
171
- }
172
- return hash < 0 ? -hash : hash;
173
- }
174
- var symbolIdCounter = 0;
175
- function normalizeKey(key) {
176
- if (isFalsy(key)) {
177
- return void 0;
178
- }
179
- if (isString(key)) {
180
- if (key.length <= MAX_KEY_LENGTH) {
181
- return key;
182
- }
183
- {
184
- warn(
185
- `[Key System] Key length exceeds ${MAX_KEY_LENGTH} characters. Consider using a shorter identifier.`
186
- );
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);
187
84
  }
188
- return `${key.slice(0, MAX_KEY_LENGTH - 10)}_${simpleHash(key).toString(36)}`;
85
+ return;
189
86
  }
190
- if (isNumber(key)) {
191
- {
192
- if (key !== key) {
193
- warn("[Key System] NaN cannot be used as a key");
194
- return void 0;
195
- }
196
- if (!Number.isFinite(key)) {
197
- warn("[Key System] Infinity cannot be used as a key");
198
- return void 0;
199
- }
87
+ if (isBoolean2) {
88
+ if (includeBooleanAttr(next2)) {
89
+ el.setAttribute(key, "");
90
+ } else {
91
+ el.removeAttribute(key);
200
92
  }
201
- return String(key);
93
+ return;
202
94
  }
203
- if (isSymbol(key)) {
204
- const globalKey = Symbol.keyFor(key);
205
- if (globalKey) {
206
- 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;
207
101
  }
208
- const desc = key.description;
209
- return desc ? `_s.${desc}` : `${symbolIdCounter++}`;
210
102
  }
211
- return String(key);
212
- }
213
- var NODE_KEY_SYMBOL = /* @__PURE__ */ Symbol("essor.key");
214
- function setNodeKey(node, key) {
215
- if (isComponent(node)) {
103
+ if (isXlink) {
104
+ el.setAttributeNS(XLINK_NAMESPACE, key, String(attrValue));
216
105
  return;
217
106
  }
218
- if (!node || node.nodeType === Node.DOCUMENT_NODE) {
219
- {
220
- warn("[Key System] Cannot set key on invalid node");
221
- }
107
+ if (isXmlns) {
108
+ el.setAttributeNS(XMLNS_NAMESPACE, key, String(attrValue));
222
109
  return;
223
110
  }
224
- const normalizedKey = normalizeKey(key);
225
- if (isFalsy(normalizedKey)) {
226
- delete node[NODE_KEY_SYMBOL];
111
+ if (elementIsSVG) {
112
+ el.setAttribute(key, String(attrValue));
227
113
  } else {
228
- node[NODE_KEY_SYMBOL] = normalizedKey;
229
- }
230
- }
231
- function getNodeKey(node) {
232
- if (!node) return void 0;
233
- return isComponent(node) ? node.key : node[NODE_KEY_SYMBOL];
234
- }
235
-
236
- // src/utils/node.ts
237
- function normalizeNode(node) {
238
- if (isHTMLElement(node)) {
239
- return node;
240
- }
241
- if (isPrimitive(node)) {
242
- const textContent = isFalsy(node) ? "" : String(node);
243
- return document.createTextNode(textContent);
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
+ }
244
123
  }
245
- return node;
246
124
  }
247
- function isSameNode(a, b) {
248
- const keyA = getNodeKey(a);
249
- const keyB = getNodeKey(b);
250
- if (keyA !== keyB) {
251
- return false;
252
- }
253
- const aIsComponent = isComponent(a);
254
- const bIsComponent = isComponent(b);
255
- if (aIsComponent && bIsComponent) {
256
- return a.component === b.component;
257
- }
258
- if (aIsComponent !== bIsComponent) {
259
- return false;
125
+ function patchClass(el, prev, next2, isSVG = false) {
126
+ if (prev === next2) {
127
+ return;
260
128
  }
261
- if (isPrimitive(a) || isPrimitive(b)) {
262
- return a === b;
129
+ const normalizedNext = normalizeClass(next2);
130
+ if (!normalizedNext) {
131
+ el.removeAttribute("class");
132
+ return;
263
133
  }
264
- const aNode = a;
265
- const bNode = b;
266
- if (aNode.nodeType !== bNode.nodeType) {
267
- return false;
134
+ const normalizedPrev = isString(prev) ? prev : normalizeClass(prev);
135
+ if (normalizedPrev === normalizedNext) {
136
+ return;
268
137
  }
269
- if (aNode.nodeType === Node.ELEMENT_NODE) {
270
- return aNode.tagName === bNode.tagName;
138
+ if (isSVG) {
139
+ el.setAttribute("class", normalizedNext);
140
+ } else {
141
+ el.className = normalizedNext;
271
142
  }
272
- return true;
273
143
  }
274
- function shallowCompare(a, b) {
275
- if (a === b) return true;
276
- if (!a || !b) return false;
277
- if (Array.isArray(a) !== Array.isArray(b)) return false;
278
- for (const key in a) {
279
- if (a[key] !== b[key]) return false;
280
- }
281
- for (const key in b) {
282
- if (!(key in a)) return false;
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;
283
155
  }
284
- return true;
285
- }
286
- function removeNode(node) {
287
- if (!node) return;
288
- try {
289
- if (isComponent(node)) {
290
- node.destroy();
291
- } else {
292
- const element = node;
293
- if (element.parentElement) {
294
- element.remove();
295
- }
156
+ if (!next2) {
157
+ if (prev) {
158
+ el.removeAttribute("style");
296
159
  }
297
- } catch (_error) {
298
- error("Failed to remove node:", _error);
160
+ return;
299
161
  }
300
- }
301
- function insertNode(parent, child, before) {
302
- if (!parent || !child) return;
303
- try {
304
- const beforeNode = isComponent(before) ? before.firstChild : before;
305
- if (isComponent(child)) {
306
- child.mount(parent, beforeNode);
307
- return;
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
+ }
308
168
  }
309
- if (beforeNode) {
310
- parent.insertBefore(child, beforeNode);
311
- } else {
312
- if (true) {
313
- if (!child) {
314
- error("insertNode: child is not a Node", child);
315
- }
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, "");
316
176
  }
317
- parent.appendChild(child);
318
177
  }
319
- } catch (_error) {
320
- error("Failed to insert node:", _error);
321
178
  }
322
- }
323
- function replaceNode(parent, newNode, oldNode) {
324
- if (!parent || !newNode || !oldNode || newNode === oldNode) return;
325
- try {
326
- const beforeNode = isComponent(oldNode) ? oldNode.beforeNode : oldNode.nextSibling;
327
- removeNode(oldNode);
328
- insertNode(parent, newNode, beforeNode);
329
- } catch (_error) {
330
- error("Failed to replace node:", _error);
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
+ }
186
+ }
331
187
  }
332
188
  }
333
- function getFirstDOMNode(node) {
334
- if (!node) {
189
+ function setStyle(style, name, val) {
190
+ if (isArray(val)) {
191
+ for (const element of val) {
192
+ setStyle(style, name, element);
193
+ }
335
194
  return;
336
195
  }
337
- if (isComponent(node)) {
338
- return node.firstChild;
339
- }
340
- if (isPrimitive(node)) {
341
- return void 0;
196
+ if (val == null || val === "") {
197
+ val = "";
342
198
  }
343
- return node;
344
- }
345
- function transferKey(oldNode, newNode) {
346
- if (isComponent(oldNode) || isComponent(newNode)) {
199
+ if (name.startsWith("--")) {
200
+ style.setProperty(name, val);
347
201
  return;
348
202
  }
349
- const oldKey = getNodeKey(oldNode);
350
- if (oldKey && !getNodeKey(newNode)) {
351
- setNodeKey(newNode, oldKey);
203
+ const prefixed = autoPrefix(style, name);
204
+ if (isString(val) && importantRE.test(val)) {
205
+ style.setProperty(camelCase(prefixed), val.replace(importantRE, ""), "important");
206
+ } else {
207
+ style[prefixed] = val;
352
208
  }
353
209
  }
354
- function patch(parent, oldNode, newNode) {
355
- if (newNode === oldNode) {
356
- return oldNode;
210
+ function autoPrefix(style, rawName) {
211
+ const cached = prefixCache[rawName];
212
+ if (cached) {
213
+ return cached;
214
+ }
215
+ let name = camelCase(rawName);
216
+ if (name !== "filter" && name in style) {
217
+ return prefixCache[rawName] = name;
218
+ }
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
+ }
357
225
  }
358
- const oldIsElement = isHTMLElement(oldNode);
359
- const newIsElement = isHTMLElement(newNode);
360
- if (newIsElement && oldIsElement) {
361
- if (newNode.isEqualNode(oldNode)) {
362
- return oldNode;
226
+ return rawName;
227
+ }
228
+
229
+ // src/hydration.ts
230
+ var _hydrationKey = 0;
231
+ function getHydrationKey() {
232
+ return String(_hydrationKey++);
233
+ }
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);
363
248
  }
364
- if (oldNode.tagName === newNode.tagName) {
365
- const oldAttrs = oldNode.attributes;
366
- const newAttrs = newNode.attributes;
367
- for (let i = oldAttrs.length - 1; i >= 0; i--) {
368
- const attrName = oldAttrs[i].name;
369
- if (!newNode.hasAttribute(attrName)) {
370
- oldNode.removeAttribute(attrName);
371
- }
372
- }
373
- for (let i = 0, len = newAttrs.length; i < len; i++) {
374
- const attr = newAttrs[i];
375
- if (oldNode.getAttribute(attr.name) !== attr.value) {
376
- oldNode.setAttribute(attr.name, attr.value);
377
- }
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);
378
268
  }
379
- transferKey(oldNode, newNode);
380
- return oldNode;
269
+ bucket.push(node);
381
270
  }
382
271
  }
383
- if (isTextNode(oldNode) && isTextNode(newNode)) {
384
- if (oldNode.textContent !== newNode.textContent) {
385
- 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 };
386
286
  }
387
- transferKey(oldNode, newNode);
388
- return oldNode;
287
+ nodes.push(cursor);
288
+ cursor = cursor.nextSibling;
389
289
  }
390
- const oldIsComponent = isComponent(oldNode);
391
- const newIsComponent = isComponent(newNode);
392
- if (oldIsComponent && newIsComponent) {
393
- if (oldNode.component === newNode.component) {
394
- return newNode.update(oldNode);
395
- }
290
+ {
291
+ warn("[Portal] hydration: orphaned <!--teleport-start--> without matching <!--teleport-end-->");
396
292
  }
397
- replaceNode(parent, newNode, oldNode);
398
- return newNode;
293
+ return null;
399
294
  }
400
- function patchChildren(parent, oldChildren, newChildren, anchor) {
401
- const oldLength = oldChildren.length;
402
- const newLength = newChildren.length;
403
- if (oldLength === 0 && newLength === 0) {
404
- 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
+ };
405
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;
406
355
  if (oldLength === 0) {
407
356
  for (let i = 0; i < newLength; i++) {
408
- insertNode(parent, newChildren[i], anchor);
357
+ insertNode(parent, newNodes[i], fallbackAnchor);
409
358
  }
410
- return newChildren;
359
+ return newNodes;
411
360
  }
412
361
  if (newLength === 0) {
413
362
  for (let i = 0; i < oldLength; i++) {
414
- removeNode(oldChildren[i]);
363
+ removeNode(oldNodes[i]);
415
364
  }
416
365
  return [];
417
366
  }
418
- if (oldLength === 1 && newLength === 1) {
419
- const oldNode = oldChildren[0];
420
- const newNode = newChildren[0];
421
- if (isSameNode(oldNode, newNode)) {
422
- patch(parent, oldNode, newNode);
423
- newChildren[0] = oldNode;
424
- } else {
425
- replaceNode(parent, newNode, oldNode);
426
- }
427
- return newChildren;
428
- }
429
- if (oldLength === 2 && newLength === 2) {
430
- const o0 = oldChildren[0];
431
- const o1 = oldChildren[1];
432
- const n0 = newChildren[0];
433
- const n1 = newChildren[1];
434
- if (isSameNode(o0, n0) && isSameNode(o1, n1)) {
435
- patch(parent, o0, n0);
436
- patch(parent, o1, n1);
437
- newChildren[0] = o0;
438
- newChildren[1] = o1;
439
- return newChildren;
440
- }
441
- if (isSameNode(o0, n1) && isSameNode(o1, n0)) {
442
- patch(parent, o0, n1);
443
- patch(parent, o1, n0);
444
- const dom1 = getFirstDOMNode(o1);
445
- const dom0 = getFirstDOMNode(o0);
446
- if (dom1 && dom0 && dom1.parentNode === parent) {
447
- parent.insertBefore(dom1, dom0);
448
- }
449
- newChildren[0] = o1;
450
- newChildren[1] = o0;
451
- return newChildren;
452
- }
453
- }
454
- return patchKeyedChildren(parent, oldChildren, newChildren, anchor);
455
- }
456
- function patchKeyedChildren(parent, oldChildren, newChildren, anchor) {
457
- let oldStartIdx = 0;
458
- let newStartIdx = 0;
459
- let oldEndIdx = oldChildren.length - 1;
460
- let newEndIdx = newChildren.length - 1;
461
- let oldStartNode = oldChildren[0];
462
- let oldEndNode = oldChildren[oldEndIdx];
463
- let newStartNode = newChildren[0];
464
- let newEndNode = newChildren[newEndIdx];
465
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
466
- if (!oldStartNode) {
467
- oldStartNode = oldChildren[++oldStartIdx];
468
- } else if (!oldEndNode) {
469
- oldEndNode = oldChildren[--oldEndIdx];
470
- } else if (isSameNode(oldStartNode, newStartNode)) {
471
- patch(parent, oldStartNode, newStartNode);
472
- newChildren[newStartIdx] = oldStartNode;
473
- oldStartNode = oldChildren[++oldStartIdx];
474
- 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++;
475
373
  } else {
476
374
  break;
477
375
  }
478
376
  }
479
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
480
- if (!oldStartNode) {
481
- oldStartNode = oldChildren[++oldStartIdx];
482
- } else if (!oldEndNode) {
483
- oldEndNode = oldChildren[--oldEndIdx];
484
- } else if (isSameNode(oldEndNode, newEndNode)) {
485
- patch(parent, oldEndNode, newEndNode);
486
- newChildren[newEndIdx] = oldEndNode;
487
- oldEndNode = oldChildren[--oldEndIdx];
488
- newEndNode = newChildren[--newEndIdx];
377
+ while (oldEnd >= start && newEnd >= start) {
378
+ if (oldNodes[oldEnd] === newNodes[newEnd]) {
379
+ oldEnd--;
380
+ newEnd--;
489
381
  } else {
490
382
  break;
491
383
  }
492
384
  }
493
- if (oldStartIdx > oldEndIdx) {
494
- if (newStartIdx <= newEndIdx) {
495
- const anchorNode = newEndIdx + 1 < newChildren.length ? getFirstDOMNode(newChildren[newEndIdx + 1]) : anchor;
496
- for (let i = newStartIdx; i <= newEndIdx; i++) {
497
- 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);
498
394
  }
499
395
  }
500
- } else if (newStartIdx > newEndIdx) {
501
- for (let i = oldStartIdx; i <= oldEndIdx; i++) {
502
- const node = oldChildren[i];
503
- if (node) {
504
- removeNode(node);
505
- }
396
+ } else if (start > newEnd) {
397
+ for (let i = start; i <= oldEnd; i++) {
398
+ removeNode(oldNodes[i]);
506
399
  }
507
400
  } else {
508
- patchUnknownSequence(
509
- parent,
510
- oldChildren,
511
- newChildren,
512
- oldStartIdx,
513
- oldEndIdx,
514
- newStartIdx,
515
- newEndIdx,
516
- anchor
517
- );
401
+ reconcileUnknownSequence(parent, oldNodes, newNodes, start, oldEnd, newEnd, fallbackAnchor);
518
402
  }
519
- return newChildren;
403
+ return newNodes;
520
404
  }
521
- function patchUnknownSequence(parent, oldChildren, newChildren, oldStartIdx, oldEndIdx, newStartIdx, newEndIdx, anchor) {
522
- const newLength = newEndIdx - newStartIdx + 1;
523
- let keyToNewIndexMap;
524
- for (let i = newStartIdx; i <= newEndIdx; i++) {
525
- const key = getNodeKey(newChildren[i]);
526
- if (key !== void 0) {
527
- if (!keyToNewIndexMap) {
528
- keyToNewIndexMap = /* @__PURE__ */ Object.create(null);
529
- }
530
- keyToNewIndexMap[key] = i;
531
- }
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);
532
410
  }
533
411
  const newIndexToOldIndexMap = new Int32Array(newLength);
412
+ newIndexToOldIndexMap.fill(0);
413
+ let patched = 0;
534
414
  let moved = false;
535
415
  let maxNewIndexSoFar = 0;
536
- let patched = 0;
537
- for (let i = oldStartIdx; i <= oldEndIdx; i++) {
538
- const oldNode = oldChildren[i];
539
- if (!oldNode) continue;
416
+ for (let i = start; i <= oldEnd; i++) {
417
+ const oldNode = oldNodes[i];
540
418
  if (patched >= newLength) {
541
419
  removeNode(oldNode);
542
420
  continue;
543
421
  }
544
- let newIndex;
545
- const oldKey = getNodeKey(oldNode);
546
- if (oldKey !== void 0 && keyToNewIndexMap && oldKey in keyToNewIndexMap) {
547
- newIndex = keyToNewIndexMap[oldKey];
548
- } else {
549
- for (let j2 = newStartIdx; j2 <= newEndIdx; j2++) {
550
- if (newIndexToOldIndexMap[j2 - newStartIdx] === 0 && oldKey === void 0 && getNodeKey(newChildren[j2]) === void 0 && isSameNode(oldNode, newChildren[j2])) {
551
- newIndex = j2;
552
- break;
553
- }
554
- }
555
- }
422
+ const newIndex = newIndexMap.get(oldNode);
556
423
  if (newIndex === void 0) {
557
424
  removeNode(oldNode);
558
425
  } else {
559
- newIndexToOldIndexMap[newIndex - newStartIdx] = i + 1;
426
+ newIndexToOldIndexMap[newIndex - start] = i + 1;
560
427
  if (newIndex >= maxNewIndexSoFar) {
561
428
  maxNewIndexSoFar = newIndex;
562
429
  } else {
563
430
  moved = true;
564
431
  }
565
- patch(parent, oldNode, newChildren[newIndex]);
566
- newChildren[newIndex] = oldNode;
567
432
  patched++;
568
433
  }
569
434
  }
570
435
  const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : [];
571
436
  let j = increasingNewIndexSequence.length - 1;
572
- let cachedAnchor = anchor;
573
437
  for (let i = newLength - 1; i >= 0; i--) {
574
- const nextIndex = newStartIdx + i;
575
- 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
+ );
576
444
  if (newIndexToOldIndexMap[i] === 0) {
577
- insertNode(parent, nextNode, cachedAnchor);
578
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
445
+ insertNode(parent, nextNode, anchorNode);
579
446
  } else if (moved) {
580
447
  if (j < 0 || i !== increasingNewIndexSequence[j]) {
581
- const domNode = getFirstDOMNode(nextNode);
582
- if (domNode && domNode.parentNode === parent) {
583
- insertNode(parent, domNode, cachedAnchor);
584
- }
585
- cachedAnchor = domNode || cachedAnchor;
448
+ insertNode(parent, nextNode, anchorNode);
586
449
  } else {
587
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
588
450
  j--;
589
451
  }
590
- } else {
591
- cachedAnchor = getFirstDOMNode(nextNode) || cachedAnchor;
592
452
  }
593
453
  }
594
454
  }
595
455
  function getSequence(arr) {
456
+ const p = new Int32Array(arr.length);
457
+ const result = [0];
596
458
  const len = arr.length;
597
- if (len === 0) return [];
598
- if (len === 1) return arr[0] !== 0 ? [0] : [];
599
- const result = [];
600
- const p = new Int32Array(len);
601
459
  let i;
602
460
  let j;
603
461
  let u;
@@ -607,7 +465,7 @@ function getSequence(arr) {
607
465
  const arrI = arr[i];
608
466
  if (arrI !== 0) {
609
467
  j = result[result.length - 1];
610
- if (result.length === 0 || arr[j] < arrI) {
468
+ if (arr[j] < arrI) {
611
469
  p[i] = j;
612
470
  result.push(i);
613
471
  continue;
@@ -639,273 +497,251 @@ function getSequence(arr) {
639
497
  return result;
640
498
  }
641
499
 
642
- // src/utils/shared.ts
643
- var isHydrationActive = false;
644
- function startHydration() {
645
- isHydrationActive = true;
646
- }
647
- function endHydration() {
648
- isHydrationActive = false;
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
+ }
510
+ }
649
511
  }
650
- function isHydrating() {
651
- return isHydrationActive;
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
+ }
526
+ }
527
+ parent.appendChild(child2);
528
+ }
652
529
  }
653
-
654
- // src/binding.ts
655
- function addEventListener(element, event, handler, options) {
656
- element.addEventListener(event, handler, options);
657
- onCleanup(() => {
658
- element.removeEventListener(event, handler, options);
659
- });
660
- }
661
- function bindElement(node, key, defaultValue, setter) {
662
- if (isHtmlInputElement(node)) {
663
- bindInputElement(node, setter);
664
- } else if (isHtmlSelectElement(node)) {
665
- bindSelectElement(node, setter);
666
- } else if (isHtmlTextAreaElement(node)) {
667
- addEventListener(node, "input", () => {
668
- setter(node.value);
669
- });
670
- }
671
- }
672
- function bindInputElement(node, setter) {
673
- switch (node.type) {
674
- case "checkbox":
675
- addEventListener(node, "change", () => {
676
- setter(Boolean(node.checked));
677
- });
678
- break;
679
- case "radio":
680
- addEventListener(node, "change", () => {
681
- setter(node.checked ? node.value : "");
682
- });
683
- break;
684
- case "file":
685
- addEventListener(node, "change", () => {
686
- setter(node.files);
687
- });
688
- break;
689
- case "number":
690
- case "range":
691
- addEventListener(node, "input", () => {
692
- setter(node.value || "");
693
- });
694
- break;
695
- case "date":
696
- case "datetime-local":
697
- case "month":
698
- case "time":
699
- case "week":
700
- addEventListener(node, "change", () => {
701
- setter(node.value || "");
702
- });
703
- break;
704
- default:
705
- addEventListener(node, "input", () => {
706
- setter(node.value);
707
- });
708
- break;
530
+ function normalizeNode(node) {
531
+ if (isHTMLElement(node)) {
532
+ return node;
709
533
  }
710
- }
711
- function bindSelectElement(node, setter) {
712
- addEventListener(node, "change", () => {
713
- if (node.multiple) {
714
- const values = Array.from(node.options).filter((option) => option.selected).map((option) => option.value);
715
- setter(values);
716
- } else {
717
- setter(node.value);
718
- }
719
- });
720
- }
721
- var isFirstRun = true;
722
- function executeReactiveUpdate(ownerScope, parent, nodeFactory, before, renderedNodes) {
723
- const executeUpdate = () => {
724
- const rawNodes = isFunction(nodeFactory) ? nodeFactory() : nodeFactory;
725
- const nodes = coerceArray(rawNodes).map((item) => isFunction(item) ? item() : item).flatMap((i) => i).map(normalizeNode);
726
- if (isFirstRun && isHydrating()) {
727
- isFirstRun = false;
728
- return renderedNodes;
729
- }
730
- return patchChildren(parent, renderedNodes, nodes, before);
731
- };
732
- if (ownerScope && !ownerScope.isDestroyed) {
733
- return runWithScope(ownerScope, executeUpdate);
534
+ if (isPrimitive(node)) {
535
+ return document.createTextNode(isFalsy(node) ? "" : String(node));
734
536
  }
735
- return executeUpdate();
537
+ return node;
736
538
  }
737
539
  function insert(parent, nodeFactory, before) {
738
540
  if (!parent) return;
739
541
  const ownerScope = getActiveScope();
740
542
  let renderedNodes = [];
741
- const cleanup = effect(() => {
742
- renderedNodes = executeReactiveUpdate(ownerScope, parent, nodeFactory, before, renderedNodes);
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 = () => {
553
+ const rawNodes = isFunction(nodeFactory) ? nodeFactory() : nodeFactory;
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;
562
+ };
563
+ if (ownerScope && !ownerScope.isDestroyed) {
564
+ runWithScope(ownerScope, executeUpdate);
565
+ } else {
566
+ executeUpdate();
567
+ }
743
568
  });
744
569
  onCleanup(() => {
745
- cleanup();
746
- renderedNodes.forEach((node) => removeNode(node));
747
- renderedNodes.length = 0;
570
+ effectRunner.stop();
571
+ for (const node of renderedNodes) removeNode(node);
572
+ renderedNodes = [];
748
573
  });
749
574
  return renderedNodes;
750
575
  }
751
- function mapNodes(template2, indexes) {
752
- const len = indexes.length;
753
- const tree = new Array(len);
754
- const indexSet = new Set(indexes);
755
- let index = 1;
756
- let found = 0;
757
- const walk = (node) => {
758
- if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
759
- if (indexSet.has(index)) {
760
- tree[found++] = node;
761
- if (found === len) return true;
762
- }
763
- index++;
764
- }
765
- let child = node.firstChild;
766
- while (child) {
767
- if (walk(child)) return true;
768
- 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);
769
607
  }
770
- return false;
771
608
  };
772
- walk(template2);
773
- 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
+ });
774
647
  }
775
- function registerMountHook(hook) {
648
+ function onMount(hook) {
776
649
  const scope = getActiveScope();
777
650
  if (!scope) {
778
- {
779
- error("onMount() must be called within a scope");
780
- }
651
+ error("onMount() must be called within a scope");
781
652
  return;
782
653
  }
783
654
  if (scope.isMounted) {
784
655
  try {
785
- hook();
786
- } catch (error_) {
787
- {
788
- 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
+ });
789
661
  }
662
+ } catch (error_) {
663
+ error(`Scope(${scope.id}): Error in mount hook:`, error_);
790
664
  }
791
665
  return;
792
666
  }
793
- if (!scope.onMount) {
794
- scope.onMount = /* @__PURE__ */ new Set();
795
- }
796
- scope.onMount.add(hook);
667
+ registerScopedHook(scope, "onMount", hook);
797
668
  }
798
- function registerUpdateHook(hook) {
669
+ function onUpdate(hook) {
799
670
  const scope = getActiveScope();
800
671
  if (!scope) {
801
- {
802
- error("onUpdate() must be called within a scope");
803
- }
672
+ error("onUpdate() must be called within a scope");
804
673
  return;
805
674
  }
806
- if (!scope.onUpdate) {
807
- scope.onUpdate = /* @__PURE__ */ new Set();
808
- }
809
- scope.onUpdate.add(hook);
675
+ registerScopedHook(scope, "onUpdate", hook);
810
676
  }
811
- function registerDestroyHook(hook) {
677
+ function onDestroy(hook) {
812
678
  const scope = getActiveScope();
813
679
  if (!scope) {
814
- {
815
- error("onDestroy() must be called within a scope");
816
- }
680
+ error("onDestroy() must be called within a scope");
817
681
  return;
818
682
  }
819
- if (!scope.onDestroy) {
820
- scope.onDestroy = /* @__PURE__ */ new Set();
821
- }
822
- scope.onDestroy.add(hook);
683
+ registerScopedHook(scope, "onDestroy", hook);
823
684
  }
824
685
  function triggerMountHooks(scope) {
825
- if (!scope || scope.isDestroyed || scope.isMounted) {
686
+ if (scope.isDestroyed) {
826
687
  return;
827
688
  }
828
- scope.isMounted = true;
829
- if (scope.onMount) {
830
- runWithScope(scope, () => {
831
- for (const hook of scope.onMount) {
832
- try {
833
- hook();
834
- } catch (error_) {
835
- if (true) {
836
- error(`Scope(${scope.id}): Error in mount hook:`, error_);
837
- }
838
- }
839
- }
840
- });
689
+ if (!scope.onMount || scope.onMount.length === 0) {
690
+ scope.isMounted = true;
691
+ return;
841
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;
842
698
  }
843
699
  function triggerUpdateHooks(scope) {
844
- if (!scope || scope.isDestroyed) {
845
- 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));
846
710
  }
847
- if (scope.onUpdate) {
848
- for (const hook of scope.onUpdate) {
849
- try {
850
- hook();
851
- } catch (error_) {
852
- {
853
- error(`Scope(${scope.id}): Error in update hook:`, error_);
854
- }
855
- }
711
+ if (seen) {
712
+ for (const key of Object.getOwnPropertyNames(target)) {
713
+ if (!seen.has(key)) delete target[key];
856
714
  }
857
715
  }
858
716
  }
859
- function onMount(hook) {
860
- registerMountHook(hook);
861
- }
862
- function onDestroy(hook) {
863
- registerDestroyHook(hook);
864
- }
865
- function onUpdate(hook) {
866
- registerUpdateHook(hook);
717
+ function readProp(source, key) {
718
+ const descriptor = Object.getOwnPropertyDescriptor(source, key);
719
+ return descriptor.get ? descriptor.get.call(source) : descriptor.value;
867
720
  }
868
-
869
- // src/component.ts
870
721
  var _a;
871
722
  _a = "normal" /* NORMAL */;
872
723
  var Component = class {
873
724
  constructor(component, props = {}) {
874
725
  this.component = component;
875
726
  this.props = props;
876
- // component rendered nodes (supports arrays and fragments)
877
- this.renderedNodes = [];
878
- // component scope (unified context management)
727
+ this[_a] = true;
879
728
  this.scope = null;
880
- // component parent node
881
- this.parentNode = void 0;
882
- // component before node
883
- this.beforeNode = void 0;
884
- // component reactive props
885
- this.reactiveProps = {};
886
- // component state
887
729
  this.state = 0 /* INITIAL */;
888
- // parent scope captured at construction time
889
- this.parentScope = null;
890
- // component type
891
- // @ts-ignore
892
- this[_a] = true;
893
- this.key = props.key ? normalizeKey(props.key) : getComponentKey(component);
894
- 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 = [];
895
735
  this.parentScope = getActiveScope();
736
+ const container = {};
737
+ syncDescriptors(container, props);
738
+ this.reactiveProps = shallowReactive(container);
896
739
  }
897
- get isConnected() {
898
- return this.state === 2 /* MOUNTED */;
899
- }
900
- get firstChild() {
901
- for (const node of this.renderedNodes) {
902
- const dom = getFirstDOMNode(node);
903
- if (dom) {
904
- return dom;
905
- }
906
- }
907
- return void 0;
908
- }
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
+ */
909
745
  mount(parentNode, beforeNode) {
910
746
  var _a2;
911
747
  this.parentNode = parentNode;
@@ -918,9 +754,9 @@ var Component = class {
918
754
  this.state = 2 /* MOUNTED */;
919
755
  return this.renderedNodes;
920
756
  }
921
- const parent = (_a2 = this.parentScope) != null ? _a2 : getActiveScope();
922
- this.scope = createScope(parent);
923
- const renderedNodes = runWithScope(this.scope, () => {
757
+ const scope = createScope((_a2 = this.parentScope) != null ? _a2 : getActiveScope());
758
+ this.scope = scope;
759
+ const renderedNodes = runWithScope(scope, () => {
924
760
  var _a3;
925
761
  let result = this.component(this.reactiveProps);
926
762
  if (isFunction(result)) {
@@ -929,157 +765,113 @@ var Component = class {
929
765
  if (isSignal(result) || isComputed(result)) {
930
766
  result = result.value;
931
767
  }
932
- const nodes = (_a3 = insert(parentNode, result, beforeNode)) != null ? _a3 : [];
933
- return nodes;
768
+ return (_a3 = insert(parentNode, result, beforeNode)) != null ? _a3 : [];
934
769
  });
935
770
  this.renderedNodes = renderedNodes;
936
- runWithScope(this.scope, () => {
937
- this.applyProps(this.props || {});
938
- });
771
+ this.firstChild = renderedNodes[0];
772
+ this.syncSpecialProps(this.props);
939
773
  this.state = 2 /* MOUNTED */;
940
- if (this.scope) {
941
- triggerMountHooks(this.scope);
942
- }
774
+ triggerMountHooks(scope);
943
775
  return this.renderedNodes;
944
776
  }
945
- update(prevNode) {
946
- if (this.key !== prevNode.key) {
947
- this.mount(prevNode.parentNode, prevNode.beforeNode);
948
- return this;
949
- }
950
- this.parentNode = prevNode.parentNode;
951
- this.beforeNode = prevNode.beforeNode;
952
- this.scope = prevNode.scope;
953
- this.parentScope = prevNode.parentScope;
954
- this.renderedNodes = prevNode.renderedNodes;
955
- this.state = prevNode.state;
956
- this.reactiveProps = prevNode.reactiveProps;
957
- if (!this.props || Object.keys(this.props).length === 0) {
958
- if (!this.isConnected && this.parentNode) {
959
- this.mount(this.parentNode, this.beforeNode);
960
- return this;
961
- }
962
- if (this.scope) {
963
- runWithScope(this.scope, () => {
964
- this.applyProps(this.props || {});
965
- });
966
- triggerUpdateHooks(this.scope);
967
- }
968
- return this;
969
- }
970
- let hasChanges = false;
971
- for (const key in this.props) {
972
- if (key === "key") continue;
973
- const newValue = this.props[key];
974
- const oldValue = this.reactiveProps[key];
975
- if (Object.is(oldValue, newValue)) {
976
- continue;
977
- }
978
- if (isObject(oldValue) && isObject(newValue)) {
979
- if (shallowCompare(oldValue, newValue)) {
980
- continue;
981
- }
982
- }
983
- this.reactiveProps[key] = newValue;
984
- hasChanges = true;
985
- }
986
- if (!this.isConnected && this.parentNode) {
987
- this.mount(this.parentNode, this.beforeNode);
988
- }
989
- if (this.scope && (hasChanges || !this.isConnected)) {
990
- runWithScope(this.scope, () => {
991
- this.applyProps(this.props || {});
992
- });
993
- if (hasChanges) {
994
- triggerUpdateHooks(this.scope);
995
- }
996
- }
997
- return this;
777
+ /**
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.
781
+ */
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);
998
794
  }
795
+ /**
796
+ * Tear down and re-mount the component at its current insertion point.
797
+ * No-op if the component has never been mounted.
798
+ */
999
799
  forceUpdate() {
1000
- return __async(this, null, function* () {
1001
- yield Promise.resolve();
1002
- if (this.state === 5 /* DESTROYED */ || !this.parentNode || !this.scope) {
1003
- return;
1004
- }
1005
- const originalNodes = [...this.renderedNodes];
1006
- try {
1007
- runWithScope(this.scope, () => {
1008
- let result = this.component(this.reactiveProps);
1009
- if (isFunction(result)) {
1010
- result = result(this.reactiveProps);
1011
- }
1012
- if (isSignal(result) || isComputed(result)) {
1013
- result = result.value;
1014
- }
1015
- const newNodes = coerceArray(result);
1016
- if (this.parentNode) {
1017
- let anchor = this.beforeNode;
1018
- if (!anchor && this.renderedNodes.length > 0) {
1019
- const lastNode = this.renderedNodes[this.renderedNodes.length - 1];
1020
- const lastDom = getFirstDOMNode(lastNode);
1021
- if (lastDom) {
1022
- anchor = lastDom.nextSibling;
1023
- }
1024
- }
1025
- for (const node of this.renderedNodes) {
1026
- removeNode(node);
1027
- }
1028
- for (const node of newNodes) {
1029
- insertNode(this.parentNode, node, anchor);
1030
- }
1031
- this.renderedNodes = newNodes;
1032
- }
1033
- });
1034
- if (this.scope) {
1035
- triggerUpdateHooks(this.scope);
1036
- }
1037
- } catch (error8) {
1038
- this.renderedNodes = originalNodes;
1039
- throw error8;
1040
- }
1041
- });
800
+ if (!this.parentNode) return;
801
+ const parent = this.parentNode;
802
+ const before = this.beforeNode;
803
+ this.destroy();
804
+ this.mount(parent, before);
1042
805
  }
1043
806
  /**
1044
- * Destroy component
807
+ * Dispose the scope, remove all rendered nodes, and clear bookkeeping.
808
+ * Idempotent: subsequent calls are no-ops.
1045
809
  */
1046
810
  destroy() {
1047
- if (this.state === 4 /* DESTROYING */ || this.state === 5 /* DESTROYED */) {
1048
- return;
1049
- }
1050
- this.state = 4 /* DESTROYING */;
1051
811
  const scope = this.scope;
1052
- if (scope) {
1053
- disposeScope(scope);
1054
- this.scope = null;
1055
- }
1056
- for (const node of this.renderedNodes) {
1057
- removeNode(node);
1058
- }
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);
1059
817
  this.renderedNodes = [];
818
+ this.firstChild = void 0;
1060
819
  this.parentNode = void 0;
1061
- this.beforeNode = void 0;
1062
- this.parentScope = null;
1063
- this.reactiveProps = {};
1064
- this.props = {};
1065
- this.state = 5 /* DESTROYED */;
1066
820
  }
1067
- applyProps(props) {
1068
- if (!props) {
1069
- return;
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) {
828
+ if (!props) return;
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));
841
+ }
842
+ }
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;
1070
855
  }
1071
- const firstElement = this.firstChild;
1072
- for (const [propName, propValue] of Object.entries(props)) {
1073
- if (startsWith(propName, EVENT_PREFIX) && firstElement) {
1074
- const eventName = propName.slice(2).toLowerCase();
1075
- if (isHTMLElement(firstElement)) {
1076
- addEventListener(firstElement, eventName, propValue);
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;
1077
871
  }
1078
- } else if (propName === REF_KEY && isSignal(propValue)) {
1079
- propValue.value = firstElement;
1080
- }
872
+ };
1081
873
  }
1082
- this.props = props;
874
+ return void 0;
1083
875
  }
1084
876
  };
1085
877
  function isComponent(node) {
@@ -1109,17 +901,72 @@ function template(html) {
1109
901
  function createApp(component, target) {
1110
902
  const container = isString(target) ? document.querySelector(target) : target;
1111
903
  if (!container) {
1112
- error(`Target element not found: ${target}`);
904
+ {
905
+ warn(`Target element not found: ${target}`);
906
+ }
1113
907
  return;
1114
908
  }
1115
- const existingContext = container.innerHTML;
1116
- if (existingContext) {
1117
- 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
+ }
1118
914
  container.innerHTML = "";
1119
915
  }
1120
- const rootComponent = createComponent(component);
1121
- rootComponent.mount(container);
1122
- 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
+ };
1123
970
  }
1124
971
  function provide(key, value) {
1125
972
  const scope = getActiveScope();
@@ -1145,24 +992,25 @@ function inject(key, defaultValue) {
1145
992
  let current = scope;
1146
993
  while (current) {
1147
994
  if (current.provides) {
1148
- const value = current.provides.get(key);
1149
- if (value) {
1150
- return value;
995
+ if (current.provides.has(key)) {
996
+ return current.provides.get(key);
1151
997
  }
1152
998
  }
1153
999
  current = current.parent;
1154
1000
  }
1155
1001
  return defaultValue;
1156
1002
  }
1003
+ function reTargetEvent(e, value) {
1004
+ Object.defineProperty(e, "target", {
1005
+ configurable: true,
1006
+ value
1007
+ });
1008
+ }
1157
1009
  function eventHandler(e) {
1158
1010
  let node = e.target;
1159
- const key = `${e.type}`;
1011
+ const key = e.type;
1160
1012
  const oriTarget = e.target;
1161
1013
  const oriCurrentTarget = e.currentTarget;
1162
- const reTarget = (value) => Object.defineProperty(e, "target", {
1163
- configurable: true,
1164
- value
1165
- });
1166
1014
  const handleNode = () => {
1167
1015
  const handler = node[`_$${key}`];
1168
1016
  if (handler && isFunction(handler) && !node.disabled) {
@@ -1171,7 +1019,7 @@ function eventHandler(e) {
1171
1019
  if (e.cancelBubble) return false;
1172
1020
  }
1173
1021
  if (node.host && !isString(node.host) && !node.host._$host && isFunction(node.contains) && node.contains(e.target)) {
1174
- reTarget(node.host);
1022
+ reTargetEvent(e, node.host);
1175
1023
  }
1176
1024
  return true;
1177
1025
  };
@@ -1180,13 +1028,16 @@ function eventHandler(e) {
1180
1028
  };
1181
1029
  Object.defineProperty(e, "currentTarget", {
1182
1030
  configurable: true,
1031
+ /**
1032
+ * Returns the current delegated target for the event.
1033
+ */
1183
1034
  get() {
1184
1035
  return node || document;
1185
1036
  }
1186
1037
  });
1187
1038
  if (e.composedPath) {
1188
1039
  const path = e.composedPath();
1189
- reTarget(path[0]);
1040
+ reTargetEvent(e, path[0]);
1190
1041
  for (let i = 0; i < path.length - 2; i++) {
1191
1042
  node = path[i];
1192
1043
  if (!handleNode()) break;
@@ -1200,7 +1051,7 @@ function eventHandler(e) {
1200
1051
  }
1201
1052
  }
1202
1053
  } else walkUpTree();
1203
- reTarget(oriTarget);
1054
+ reTargetEvent(e, oriTarget);
1204
1055
  }
1205
1056
  var $EVENTS = /* @__PURE__ */ Symbol("_$EVENTS");
1206
1057
  function delegateEvents(eventNames, document2 = window.document) {
@@ -1213,325 +1064,354 @@ function delegateEvents(eventNames, document2 = window.document) {
1213
1064
  }
1214
1065
  }
1215
1066
  }
1216
-
1217
- // src/utils/props.ts
1218
- function omitProps(target, keys) {
1219
- const excludeSet = new Set(keys);
1220
- return new Proxy(target, {
1221
- // Intercept property reads
1222
- get(obj, prop) {
1223
- if (excludeSet.has(prop)) {
1224
- return void 0;
1225
- }
1226
- return Reflect.get(obj, prop);
1227
- },
1228
- // Intercept property enumeration (for...in, Object.keys, etc.)
1229
- ownKeys(obj) {
1230
- return Reflect.ownKeys(obj).filter((key) => !excludeSet.has(key));
1231
- },
1232
- // Intercept property descriptor retrieval
1233
- getOwnPropertyDescriptor(obj, prop) {
1234
- if (excludeSet.has(prop)) {
1235
- return void 0;
1236
- }
1237
- return Reflect.getOwnPropertyDescriptor(obj, prop);
1238
- },
1239
- // Intercept the 'in' operator
1240
- has(obj, prop) {
1241
- if (excludeSet.has(prop)) {
1242
- return false;
1243
- }
1244
- return Reflect.has(obj, prop);
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);
1245
1073
  }
1246
- });
1074
+ delete docWithEvents[$EVENTS];
1075
+ }
1247
1076
  }
1248
- function patchClass(el, prev, next, isSVG = false) {
1249
- if (prev === next) {
1250
- return;
1251
- }
1252
- if (isHydrating()) {
1253
- return;
1077
+ function addEventListener(element, event, handler, options) {
1078
+ const cleanup = addEvent(element, event, handler, options);
1079
+ if (getActiveScope()) {
1080
+ onCleanup(cleanup);
1254
1081
  }
1255
- const normalizedNext = normalizeClass(next);
1256
- const normalizedPrev = normalizeClass(prev);
1257
- if (normalizedNext && normalizedPrev === normalizedNext) {
1258
- return;
1082
+ }
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;
1259
1093
  }
1260
- if (!normalizedNext) {
1261
- el.removeAttribute("class");
1262
- } else if (isSVG) {
1263
- el.setAttribute("class", normalizedNext);
1264
- } else {
1265
- el.className = normalizedNext;
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;
1266
1106
  }
1267
- }
1268
- function normalizeClass(value) {
1269
- return normalizeClassName(value);
1270
- }
1271
- var importantRE = /\s*!important$/;
1272
- var prefixes = ["Webkit", "Moz", "ms"];
1273
- var prefixCache = {};
1274
- function patchStyle(el, prev, next) {
1275
- const style = el.style;
1276
- const isCssString = isString(next);
1277
- if (isHydrating()) {
1278
- 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: () => {
1279
1114
  }
1280
- if (next && isCssString) {
1281
- if (prev !== next) {
1282
- style.cssText = next;
1283
- }
1284
- return;
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;
1285
1124
  }
1286
- if (!next) {
1287
- if (prev) {
1288
- el.removeAttribute("style");
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);
1138
+ } else {
1139
+ const next2 = v == null ? "" : String(v);
1140
+ if (s.value !== next2) s.value = next2;
1289
1141
  }
1290
- return;
1291
1142
  }
1292
- if (prev && !isString(prev)) {
1293
- for (const key in prev) {
1294
- if (!next || next[key] == null) {
1295
- setStyle(style, key, "");
1296
- }
1297
- }
1298
- } else if (prev && isString(prev)) {
1299
- const prevStyles = prev.split(";");
1300
- for (const stylePart of prevStyles) {
1301
- const colonIndex = stylePart.indexOf(":");
1302
- if (colonIndex > 0) {
1303
- const key = stylePart.slice(0, colonIndex).trim();
1304
- if (next && isObject(next) && next[key] == null) {
1305
- setStyle(style, key, "");
1306
- }
1307
- }
1308
- }
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;
1309
1152
  }
1310
- if (next && !isString(next)) {
1311
- for (const key in next) {
1312
- const value = next[key];
1313
- if ((!prev || isString(prev) || prev[key] !== value) && value != null) {
1314
- setStyle(style, key, value);
1315
- }
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;
1316
1171
  }
1317
- }
1172
+ };
1318
1173
  }
1319
- function setStyle(style, name, val) {
1320
- if (isArray(val)) {
1321
- for (const element of val) {
1322
- setStyle(style, name, element);
1323
- }
1324
- return;
1325
- }
1326
- if (val == null || val === "") {
1327
- val = "";
1328
- }
1329
- if (name.startsWith("--")) {
1330
- style.setProperty(name, val);
1331
- return;
1332
- }
1333
- const prefixed = autoPrefix(style, name);
1334
- if (typeof val === "string" && importantRE.test(val)) {
1335
- style.setProperty(camelCase(prefixed), val.replace(importantRE, ""), "important");
1336
- } else {
1337
- style[prefixed] = val;
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;
1338
1180
  }
1181
+ return val;
1339
1182
  }
1340
- function autoPrefix(style, rawName) {
1341
- const cached = prefixCache[rawName];
1342
- if (cached) {
1343
- return cached;
1344
- }
1345
- let name = camelCase(rawName);
1346
- if (name !== "filter" && name in style) {
1347
- return prefixCache[rawName] = name;
1348
- }
1349
- name = capitalize(name);
1350
- for (const prefix of prefixes) {
1351
- const prefixed = prefix + name;
1352
- if (prefixed in style) {
1353
- return prefixCache[rawName] = prefixed;
1354
- }
1355
- }
1356
- return rawName;
1183
+ function isFocused(node) {
1184
+ const root = node.getRootNode();
1185
+ return (root instanceof Document || root instanceof ShadowRoot) && root.activeElement === node;
1357
1186
  }
1358
- function patchAttr(el, key, prev, next) {
1359
- if (key === KEY_PROP) {
1360
- if (next == null) {
1361
- setNodeKey(el, void 0);
1362
- } else {
1363
- setNodeKey(el, String(next));
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);
1202
+ return;
1364
1203
  }
1365
- return;
1366
- }
1367
- if (key === SPREAD_NAME) {
1368
- {
1369
- if (!isObject(next)) {
1370
- warn("spread attribute must be an object");
1371
- }
1204
+ const next2 = transform(raw);
1205
+ if (!Object.is(readModel(), next2)) {
1206
+ setter(next2);
1372
1207
  }
1373
- Object.keys(next).forEach((k) => {
1374
- patchAttr(el, k, prev == null ? void 0 : prev[k], next == null ? void 0 : next[k]);
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)));
1375
1213
  });
1376
- return;
1377
- }
1378
- if (isHydrating()) {
1379
- return;
1380
- }
1381
- const elementIsSVG = (el == null ? void 0 : el.namespaceURI) === SVG_NAMESPACE;
1382
- const isXlink = elementIsSVG && key.startsWith("xlink:");
1383
- const isXmlns = elementIsSVG && key.startsWith("xmlns:");
1384
- const isBoolean = isSpecialBooleanAttr(key) || isBooleanAttr(key);
1385
- if (prev === next) {
1386
- return;
1387
- }
1388
- const lowerKey = key.toLowerCase();
1389
- if (lowerKey.length > 2 && lowerKey.charCodeAt(0) === 111 && lowerKey.charCodeAt(1) === 110) {
1390
- return;
1391
- }
1392
- if (lowerKey === "innerhtml") {
1393
- return;
1394
- }
1395
- if (next == null) {
1396
- if (isXlink) {
1397
- el.removeAttributeNS(XLINK_NAMESPACE, key.slice(6));
1398
- } else if (isXmlns) {
1399
- const localName = key.slice(6);
1400
- el.removeAttributeNS(XMLNS_NAMESPACE, localName);
1401
- } else {
1402
- el.removeAttribute(key);
1403
- }
1404
- return;
1405
- }
1406
- if (isXlink) {
1407
- el.setAttributeNS(XLINK_NAMESPACE, key, String(next));
1408
- return;
1409
1214
  }
1410
- if (isXmlns) {
1411
- el.setAttributeNS(XMLNS_NAMESPACE, key, String(next));
1412
- return;
1413
- }
1414
- if (isBoolean) {
1415
- if (includeBooleanAttr(next)) {
1416
- el.setAttribute(key, "");
1417
- } else {
1418
- el.removeAttribute(key);
1419
- }
1420
- return;
1421
- }
1422
- const attrValue = isSymbol(next) ? String(next) : next;
1423
- const isUrlAttr = lowerKey === "href" || lowerKey === "src" || lowerKey === "xlink:href";
1424
- if (isUrlAttr && typeof attrValue === "string") {
1425
- const v = attrValue.trim().toLowerCase();
1426
- if (v.startsWith("javascript:") || v.startsWith("data:")) {
1427
- return;
1428
- }
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
+ });
1429
1224
  }
1430
- if (elementIsSVG) {
1431
- el.setAttribute(key, String(attrValue));
1432
- } else {
1433
- if (key in el) {
1434
- try {
1435
- el[key] = attrValue;
1436
- } catch (e) {
1437
- el.setAttribute(key, String(attrValue));
1438
- }
1439
- } else {
1440
- el.setAttribute(key, String(attrValue));
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;
1441
1231
  }
1232
+ strategy.write(node, value);
1233
+ });
1234
+ if (getActiveScope()) {
1235
+ onCleanup(() => runner.stop());
1442
1236
  }
1443
1237
  }
1444
1238
 
1445
- // src/operations/event.ts
1446
- function addEvent(el, event, handler, options) {
1447
- if (!(options == null ? void 0 : options.delegate)) {
1448
- el.addEventListener(event, handler, options);
1449
- return () => el.removeEventListener(event, handler, options);
1450
- }
1451
- const selector = options.delegate;
1452
- const wrappedHandler = (e) => {
1453
- const target = e.target;
1454
- if (target.matches(selector) || target.closest(selector)) {
1455
- 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);
1456
1275
  }
1457
- };
1458
- const cleanOptions = __spreadValues({}, options);
1459
- cleanOptions.delegate = void 0;
1460
- el.addEventListener(event, wrappedHandler, cleanOptions);
1461
- return () => {
1462
- el.removeEventListener(event, wrappedHandler, cleanOptions);
1463
- };
1276
+ });
1464
1277
  }
1278
+
1279
+ // src/components/Fragment.ts
1465
1280
  function Fragment(props) {
1466
- {
1467
- if (!props) {
1468
- error("Fragment component requires props");
1469
- return null;
1470
- }
1471
- if (!props.children) {
1472
- error("Fragment component requires children");
1473
- return null;
1474
- }
1475
- }
1476
- return props == null ? void 0 : props.children;
1281
+ if (!props || props.children == null) return null;
1282
+ return props.children;
1477
1283
  }
1478
- Fragment["fragment" /* FRAGMENT */] = true;
1284
+ Fragment[FRAGMENT_COMPONENT] = true;
1479
1285
  function isFragment(node) {
1480
- return !!node && !!node["fragment" /* FRAGMENT */];
1286
+ return !!node && !!node[FRAGMENT_COMPONENT];
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;
1481
1296
  }
1482
1297
  function Portal(props) {
1483
- if (typeof document === "undefined") {
1484
- const children2 = props.children;
1485
- if (!children2) return "";
1486
- const childArray = isArray(children2) ? children2 : [children2];
1487
- return childArray.map((child) => String(child || "")).join("");
1298
+ if (isHydrating()) {
1299
+ const adopted = tryHydratePortal(props);
1300
+ if (adopted) return adopted;
1488
1301
  }
1489
1302
  const placeholder = document.createComment("portal");
1490
- placeholder["portal" /* PORTAL */] = true;
1491
- const children = props.children;
1492
- if (children) {
1493
- const childArray = isArray(children) ? children : [children];
1494
- const nodes = [];
1495
- onMount(() => {
1496
- const targetElement = isString(props.target) ? document.querySelector(props.target) : props.target;
1497
- if (!targetElement) {
1498
- {
1499
- warn(`[Portal] Target element not found: ${props.target}`);
1500
- }
1501
- return;
1303
+ placeholder[PORTAL_COMPONENT] = true;
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)}`);
1502
1331
  }
1503
- childArray.forEach((child) => {
1504
- if (child != null) {
1505
- const normalized = normalizeNode(child);
1506
- if (normalized) {
1507
- insertNode(targetElement, normalized);
1508
- nodes.push(normalized);
1509
- }
1510
- }
1511
- });
1512
- onCleanup(() => {
1513
- nodes.forEach((node) => {
1514
- if (typeof node !== "string" && node.parentNode === targetElement) {
1515
- targetElement.removeChild(node);
1516
- }
1517
- });
1518
- });
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));
1519
1355
  });
1520
- }
1356
+ });
1357
+ onCleanup(() => {
1358
+ effectRunner.stop();
1359
+ teardown();
1360
+ });
1521
1361
  return placeholder;
1522
1362
  }
1523
- Portal["portal" /* PORTAL */] = true;
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
+ }
1524
1392
  function isPortal(node) {
1525
- return !!node && !!node["portal" /* PORTAL */];
1393
+ return !!node && !!node[PORTAL_COMPONENT];
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;
1526
1409
  }
1527
1410
  var SuspenseContext = /* @__PURE__ */ Symbol("SuspenseContext");
1528
1411
  function Suspense(props) {
1529
- if (isUndefined(document)) {
1530
- const fallback = props.fallback;
1531
- if (fallback) {
1532
- return String(fallback || "");
1533
- }
1534
- return "";
1412
+ var _a2;
1413
+ if (!isBrowser()) {
1414
+ return (_a2 = props.fallback) != null ? _a2 : "";
1535
1415
  }
1536
1416
  const container = document.createElement("div");
1537
1417
  container.style.display = "contents";
@@ -1539,19 +1419,42 @@ function Suspense(props) {
1539
1419
  let pendingCount = 0;
1540
1420
  let isShowingFallback = false;
1541
1421
  let resolvedChildren = null;
1542
- const showFallback = () => {
1543
- if (isShowingFallback) return;
1544
- isShowingFallback = true;
1545
- while (container.firstChild) {
1546
- 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;
1547
1435
  }
1548
- if (props.fallback != null) {
1549
- const normalized = normalizeNode(props.fallback);
1550
- if (normalized) {
1551
- 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);
1552
1444
  }
1553
1445
  }
1554
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
+ };
1555
1458
  const showChildren = () => {
1556
1459
  if (!isShowingFallback) return;
1557
1460
  const hasContent = resolvedChildren || props.children != null && !isPromise(props.children);
@@ -1559,9 +1462,7 @@ function Suspense(props) {
1559
1462
  return;
1560
1463
  }
1561
1464
  isShowingFallback = false;
1562
- while (container.firstChild) {
1563
- container.removeChild(container.firstChild);
1564
- }
1465
+ clearContainer(container);
1565
1466
  if (resolvedChildren) {
1566
1467
  renderChildren(resolvedChildren);
1567
1468
  } else if (props.children != null && !isPromise(props.children)) {
@@ -1569,33 +1470,17 @@ function Suspense(props) {
1569
1470
  }
1570
1471
  };
1571
1472
  const renderChildren = (children2) => {
1572
- while (container.firstChild) {
1573
- container.removeChild(container.firstChild);
1574
- }
1473
+ if (isShowingFallback) return;
1474
+ clearContainer(container);
1575
1475
  if (children2 == null) return;
1576
- const currentScope = getActiveScope();
1577
1476
  const childArray = isArray(children2) ? children2 : [children2];
1578
- childArray.forEach((child) => {
1579
- if (child != null) {
1580
- if (isComponent(child)) {
1581
- child.parentContext = currentScope;
1582
- }
1583
- const normalized = normalizeNode(child);
1584
- if (normalized) {
1585
- insertNode(container, normalized);
1586
- }
1477
+ for (const child2 of childArray) {
1478
+ if (child2 != null) {
1479
+ insertMaterializedChild(child2);
1587
1480
  }
1588
- });
1481
+ }
1589
1482
  if (isShowingFallback) {
1590
- while (container.firstChild) {
1591
- container.removeChild(container.firstChild);
1592
- }
1593
- if (props.fallback != null) {
1594
- const normalized = normalizeNode(props.fallback);
1595
- if (normalized) {
1596
- insertNode(container, normalized);
1597
- }
1598
- }
1483
+ renderFallbackContent();
1599
1484
  }
1600
1485
  };
1601
1486
  const suspenseContext = {
@@ -1608,9 +1493,9 @@ function Suspense(props) {
1608
1493
  if (pendingCount === 0) {
1609
1494
  showChildren();
1610
1495
  }
1611
- }).catch((error8) => {
1496
+ }).catch((error4) => {
1612
1497
  {
1613
- warn("[Suspense] Resource failed:", error8);
1498
+ warn("[Suspense] Resource failed:", error4);
1614
1499
  }
1615
1500
  if (!isMounted) return;
1616
1501
  pendingCount--;
@@ -1624,7 +1509,7 @@ function Suspense(props) {
1624
1509
  showFallback();
1625
1510
  },
1626
1511
  decrement: () => {
1627
- pendingCount--;
1512
+ pendingCount = Math.max(0, pendingCount - 1);
1628
1513
  if (pendingCount === 0) {
1629
1514
  showChildren();
1630
1515
  }
@@ -1645,32 +1530,39 @@ function Suspense(props) {
1645
1530
  }
1646
1531
  onDestroy(() => {
1647
1532
  isMounted = false;
1648
- while (container.firstChild) {
1649
- container.removeChild(container.firstChild);
1650
- }
1533
+ pendingCount = 0;
1534
+ resolvedChildren = null;
1535
+ clearContainer(container);
1536
+ container.remove();
1651
1537
  });
1652
1538
  return container;
1653
1539
  }
1654
- Suspense["suspense" /* SUSPENSE */] = true;
1540
+ Suspense[SUSPENSE_COMPONENT] = true;
1655
1541
  function isSuspense(node) {
1656
- return !!node && !!node["suspense" /* SUSPENSE */];
1542
+ return !!node && !!node[SUSPENSE_COMPONENT];
1657
1543
  }
1658
1544
  function createResource(fetcher, options) {
1659
1545
  const value = signal(options == null ? void 0 : options.initialValue);
1660
1546
  const loading = signal(true);
1661
- const error8 = signal(null);
1547
+ const error4 = signal(null);
1662
1548
  const state = signal("pending");
1663
1549
  let fetchId = 0;
1664
1550
  let currentPromise = null;
1551
+ let suspenseRegistered = false;
1552
+ const suspenseContext = inject(SuspenseContext, null);
1665
1553
  const fetch = () => __async(null, null, function* () {
1666
1554
  const currentFetchId = ++fetchId;
1667
1555
  loading.value = true;
1668
1556
  state.value = "pending";
1669
- error8.value = null;
1557
+ error4.value = null;
1558
+ suspenseRegistered = false;
1559
+ if (suspenseContext) {
1560
+ suspenseContext.increment();
1561
+ }
1670
1562
  try {
1671
1563
  const promise = fetcher();
1672
- currentPromise = promise.then(() => {
1673
- }).catch(() => {
1564
+ currentPromise = promise;
1565
+ promise.catch(() => {
1674
1566
  });
1675
1567
  const result = yield promise;
1676
1568
  if (currentFetchId === fetchId) {
@@ -1680,31 +1572,33 @@ function createResource(fetcher, options) {
1680
1572
  }
1681
1573
  } catch (error_) {
1682
1574
  if (currentFetchId === fetchId) {
1683
- error8.value = error_ instanceof Error ? error_ : new Error(String(error_));
1575
+ error4.value = error_ instanceof Error ? error_ : new Error(String(error_));
1684
1576
  state.value = "errored";
1685
1577
  loading.value = false;
1686
1578
  }
1579
+ } finally {
1580
+ if (suspenseContext) {
1581
+ suspenseContext.decrement();
1582
+ }
1687
1583
  }
1688
1584
  });
1689
1585
  fetch();
1690
1586
  const resource = (() => {
1691
- if (loading.value && currentPromise) {
1692
- const suspenseContext = inject(SuspenseContext, null);
1693
- if (suspenseContext) {
1694
- suspenseContext.register(currentPromise);
1695
- }
1587
+ if (!suspenseRegistered && loading.value && currentPromise && suspenseContext) {
1588
+ suspenseRegistered = true;
1589
+ suspenseContext.register(currentPromise);
1696
1590
  }
1697
1591
  return value.value;
1698
1592
  });
1699
1593
  resource.loading = loading;
1700
- resource.error = error8;
1594
+ resource.error = error4;
1701
1595
  resource.state = state;
1702
1596
  const actions = {
1703
1597
  mutate: (newValue) => {
1704
1598
  value.value = newValue;
1705
1599
  state.value = "ready";
1706
1600
  loading.value = false;
1707
- error8.value = null;
1601
+ error4.value = null;
1708
1602
  },
1709
1603
  refetch: () => __async(null, null, function* () {
1710
1604
  yield fetch();
@@ -1712,7 +1606,380 @@ function createResource(fetcher, options) {
1712
1606
  };
1713
1607
  return [resource, actions];
1714
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
+ }
1791
+ function For(props) {
1792
+ const fragment = document.createDocumentFragment();
1793
+ const marker = document.createComment("");
1794
+ fragment.appendChild(marker);
1795
+ let entries = [];
1796
+ let fallbackNodes = [];
1797
+ const keyFn = props.key;
1798
+ const renderFn = props.children;
1799
+ const getList = () => {
1800
+ var _a2, _b;
1801
+ const input = props.each;
1802
+ if (isSignal(input)) return (_a2 = input.value) != null ? _a2 : [];
1803
+ if (isFunction(input)) return (_b = input()) != null ? _b : [];
1804
+ return input != null ? input : [];
1805
+ };
1806
+ const getKey = (item) => keyFn ? keyFn(item) : item;
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);
1822
+ } else {
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);
1837
+ }
1838
+ }
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 };
1849
+ };
1850
+ const disposeItem = (entry) => {
1851
+ disposeScope(entry.scope);
1852
+ for (const node of entry.nodes) {
1853
+ if (node.parentNode) {
1854
+ node.parentNode.removeChild(node);
1855
+ }
1856
+ }
1857
+ };
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 {
1865
+ entries = new Array(newItems.length);
1866
+ let idx = 0;
1867
+ for (const newItem of newItems) {
1868
+ entries[idx] = renderItem(newItem, idx, fragment, marker);
1869
+ idx++;
1870
+ }
1871
+ }
1872
+ return;
1873
+ }
1874
+ reconcile(parent, newItems);
1875
+ });
1876
+ function reconcile(parent, newItems) {
1877
+ const oldLen = entries.length;
1878
+ const newLen = newItems.length;
1879
+ if (newLen === 0) {
1880
+ for (let i = 0; i < oldLen; i++) {
1881
+ disposeItem(entries[i]);
1882
+ }
1883
+ entries = [];
1884
+ if (props.fallback && fallbackNodes.length === 0) {
1885
+ mountFallback(parent, marker);
1886
+ }
1887
+ return;
1888
+ }
1889
+ if (oldLen === 0 || fallbackNodes.length > 0) {
1890
+ if (fallbackNodes.length > 0) {
1891
+ clearFallback();
1892
+ }
1893
+ entries = new Array(newLen);
1894
+ const batchFragment2 = document.createDocumentFragment();
1895
+ for (let i = 0; i < newLen; i++) {
1896
+ entries[i] = renderItem(newItems[i], i, batchFragment2, null);
1897
+ }
1898
+ parent.insertBefore(batchFragment2, marker);
1899
+ return;
1900
+ }
1901
+ const oldKeyMap = /* @__PURE__ */ new Map();
1902
+ for (let i = 0; i < oldLen; i++) {
1903
+ const entry = entries[i];
1904
+ const list = oldKeyMap.get(entry.key);
1905
+ const pair = [entry, i];
1906
+ if (list) list.push(pair);
1907
+ else oldKeyMap.set(entry.key, [pair]);
1908
+ }
1909
+ const newEntries = new Array(newLen);
1910
+ const toRemove = [];
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
+ }
1919
+ for (let i = 0; i < newLen; i++) {
1920
+ const item = newItems[i];
1921
+ const key = newKeys[i];
1922
+ const oldList = oldKeyMap.get(key);
1923
+ if (oldList && oldList.length > 0) {
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
+ }
1936
+ } else {
1937
+ if (!batchFragment) batchFragment = document.createDocumentFragment();
1938
+ newEntries[i] = renderItem(item, i, batchFragment, null);
1939
+ }
1940
+ }
1941
+ for (const list of oldKeyMap.values()) {
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;
1964
+ }
1965
+ }
1966
+ entries = newEntries;
1967
+ }
1968
+ onCleanup(() => {
1969
+ effectRunner.stop();
1970
+ for (const entry of entries) {
1971
+ disposeItem(entry);
1972
+ }
1973
+ entries = [];
1974
+ clearFallback();
1975
+ if (marker.parentNode) {
1976
+ marker.parentNode.removeChild(marker);
1977
+ }
1978
+ });
1979
+ return fragment;
1980
+ }
1981
+ For[FOR_COMPONENT] = true;
1715
1982
 
1716
- export { Component, Fragment, Portal, Suspense, addEvent, addEventListener, bindElement, createApp, createComponent, createResource, createScope, delegateEvents, disposeScope, endHydration, getActiveScope, getFirstDOMNode, inject, insert, insertNode, isComponent, isFragment, isHydrating, isPortal, isSameNode, isSuspense, mapNodes, normalizeClass, normalizeNode, omitProps, onCleanup, onDestroy, onMount, onUpdate, patchAttr, patchClass, patchStyle, provide, removeNode, replaceNode, 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 };
1717
1984
  //# sourceMappingURL=template.dev.esm.js.map
1718
1985
  //# sourceMappingURL=template.dev.esm.js.map