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