@estjs/template 0.0.14 → 0.0.15-beta.5

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