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