@estjs/template 0.0.15-beta.9 → 0.0.15

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,5 +1,5 @@
1
- import { error, isHTMLElement, isPrimitive, isFalsy, isHtmlInputElement, isHtmlSelectElement, isHtmlTextAreaElement, isFunction, isObject, startsWith, isString, normalizeClassName, isArray, camelCase, capitalize, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isUndefined, isPromise, isNumber, coerceArray, isTextNode } from '@estjs/shared';
2
- import { effect, shallowReactive, isSignal, isComputed, signal } from '@estjs/signals';
1
+ import { error, isHTMLElement, isPrimitive, isFalsy, isNull, isObject, isArray, isHtmlInputElement, isHtmlSelectElement, isHtmlTextAreaElement, isFunction, hasChanged, isPromise, coerceArray, startsWith, isString, isBrowser, normalizeClassName, camelCase, capitalize, warn, isSpecialBooleanAttr, isBooleanAttr, includeBooleanAttr, isSymbol, isUndefined, isNumber, isTextNode } from '@estjs/shared';
2
+ import { effect, shallowReactive, isSignal, isComputed, signal, memoEffect, untrack } from '@estjs/signals';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -37,6 +37,108 @@ var __async = (__this, __arguments, generator) => {
37
37
  step((generator = generator.apply(__this, __arguments)).next());
38
38
  });
39
39
  };
40
+ var LIFECYCLE = {
41
+ mount: "mount",
42
+ destroy: "destroy",
43
+ update: "update"
44
+ };
45
+ function registerScopedHook(scope, listKey, hook) {
46
+ let hookList = scope[listKey];
47
+ if (!hookList) {
48
+ hookList = scope[listKey] = [];
49
+ }
50
+ if (!hookList.includes(hook)) {
51
+ hookList.push(hook);
52
+ }
53
+ }
54
+ function executeHooks(hooks, scopeId2, phase) {
55
+ const len = hooks.length;
56
+ if (len === 0) return;
57
+ let pending;
58
+ for (let i = 0; i < len; i++) {
59
+ try {
60
+ const result = hooks[i]();
61
+ if (isPromise(result)) {
62
+ const safePromise = result.catch((error_) => {
63
+ if (true) {
64
+ error(`Scope(${scopeId2}): Async ${phase} hook rejected:`, error_);
65
+ }
66
+ });
67
+ (pending != null ? pending : pending = []).push(safePromise);
68
+ }
69
+ } catch (error_) {
70
+ {
71
+ error(`Scope(${scopeId2}): Error in ${phase} hook:`, error_);
72
+ }
73
+ }
74
+ }
75
+ if (!pending) return;
76
+ return Promise.all(pending).then(() => void 0);
77
+ }
78
+ function onMount(hook) {
79
+ const scope = getActiveScope();
80
+ if (!scope) {
81
+ error("onMount() must be called within a scope");
82
+ return;
83
+ }
84
+ if (scope.isMounted) {
85
+ try {
86
+ const result = hook();
87
+ if (isPromise(result)) {
88
+ result.catch((error_) => {
89
+ if (true) error(`Scope(${scope.id}): Async ${LIFECYCLE.mount} hook rejected:`, error_);
90
+ });
91
+ }
92
+ } catch (error_) {
93
+ error(`Scope(${scope.id}): Error in ${LIFECYCLE.mount} hook:`, error_);
94
+ }
95
+ return;
96
+ }
97
+ registerScopedHook(scope, "onMount", hook);
98
+ }
99
+ function onUpdate(hook) {
100
+ const scope = getActiveScope();
101
+ if (!scope) {
102
+ error("onUpdate() must be called within a scope");
103
+ return;
104
+ }
105
+ registerScopedHook(scope, "onUpdate", hook);
106
+ }
107
+ function onDestroy(hook) {
108
+ const scope = getActiveScope();
109
+ if (!scope) {
110
+ error("onDestroy() must be called within a scope");
111
+ return;
112
+ }
113
+ registerScopedHook(scope, "onDestroy", hook);
114
+ }
115
+ function triggerMountHooks(scope) {
116
+ var _a2;
117
+ if (scope.isDestroyed || !((_a2 = scope.onMount) == null ? void 0 : _a2.length)) {
118
+ scope.isMounted = true;
119
+ return;
120
+ }
121
+ const mountHooks = scope.onMount;
122
+ const result = runWithScope(scope, () => executeHooks(mountHooks, scope.id, LIFECYCLE.mount));
123
+ mountHooks.length = 0;
124
+ scope.isMounted = true;
125
+ return result;
126
+ }
127
+ function triggerUpdateHooks(scope) {
128
+ var _a2;
129
+ if (scope.isDestroyed || !((_a2 = scope.onUpdate) == null ? void 0 : _a2.length)) return;
130
+ const updateHooks = scope.onUpdate;
131
+ const result = runWithScope(scope, () => executeHooks(updateHooks, scope.id, "update"));
132
+ updateHooks.length = 0;
133
+ return result;
134
+ }
135
+ function triggerDestroyHooks(scope) {
136
+ var _a2;
137
+ if (scope.isDestroyed || !((_a2 = scope.onDestroy) == null ? void 0 : _a2.length)) return;
138
+ return runWithScope(scope, () => executeHooks(scope.onDestroy, scope.id, "destroy"));
139
+ }
140
+
141
+ // src/scope.ts
40
142
  var activeScope = null;
41
143
  var scopeId = 0;
42
144
  function getActiveScope() {
@@ -50,25 +152,19 @@ function createScope(parent = activeScope) {
50
152
  id: ++scopeId,
51
153
  parent,
52
154
  children: null,
53
- // Lazy initialized
54
155
  provides: null,
55
- // Lazy initialized
56
156
  cleanup: null,
57
- // Lazy initialized
58
157
  onMount: null,
59
- // Lazy initialized
60
158
  onUpdate: null,
61
- // Lazy initialized
62
159
  onDestroy: null,
63
- // Lazy initialized
64
160
  isMounted: false,
65
161
  isDestroyed: false
66
162
  };
67
163
  if (parent) {
68
164
  if (!parent.children) {
69
- parent.children = /* @__PURE__ */ new Set();
165
+ parent.children = [];
70
166
  }
71
- parent.children.add(scope);
167
+ parent.children.push(scope);
72
168
  }
73
169
  return scope;
74
170
  }
@@ -82,31 +178,22 @@ function runWithScope(scope, fn) {
82
178
  }
83
179
  }
84
180
  function disposeScope(scope) {
85
- var _a2, _b, _c, _d, _e;
181
+ var _a2, _b, _c;
86
182
  if (!scope || scope.isDestroyed) {
87
183
  return;
88
184
  }
185
+ const parentScope = scope.parent;
89
186
  if (scope.children) {
90
- while (scope.children.size > 0) {
91
- const child = scope.children.values().next().value;
92
- if (child) {
93
- disposeScope(child);
94
- }
187
+ for (const child of scope.children) {
188
+ disposeScope(child);
95
189
  }
190
+ scope.children.length = 0;
96
191
  }
97
- if (scope.onDestroy) {
98
- for (const hook of scope.onDestroy) {
99
- try {
100
- hook();
101
- } catch (error_) {
102
- {
103
- error(`Scope(${scope.id}): Error in destroy hook:`, error_);
104
- }
105
- }
106
- }
107
- scope.onDestroy.clear();
192
+ if ((_a2 = scope.onDestroy) == null ? void 0 : _a2.length) {
193
+ triggerDestroyHooks(scope);
194
+ scope.onDestroy.length = 0;
108
195
  }
109
- if (scope.cleanup) {
196
+ if ((_b = scope.cleanup) == null ? void 0 : _b.length) {
110
197
  for (const fn of scope.cleanup) {
111
198
  try {
112
199
  fn();
@@ -116,18 +203,22 @@ function disposeScope(scope) {
116
203
  }
117
204
  }
118
205
  }
119
- scope.cleanup.clear();
206
+ scope.cleanup.length = 0;
120
207
  }
121
- if ((_a2 = scope.parent) == null ? void 0 : _a2.children) {
122
- scope.parent.children.delete(scope);
208
+ if (parentScope == null ? void 0 : parentScope.children) {
209
+ const idx = parentScope.children.indexOf(scope);
210
+ if (idx !== -1) {
211
+ parentScope.children.splice(idx, 1);
212
+ }
123
213
  }
124
- (_b = scope.children) == null ? void 0 : _b.clear();
125
214
  (_c = scope.provides) == null ? void 0 : _c.clear();
126
- (_d = scope.onMount) == null ? void 0 : _d.clear();
127
- (_e = scope.onUpdate) == null ? void 0 : _e.clear();
128
- setActiveScope(scope.parent);
215
+ if (scope.onMount) scope.onMount.length = 0;
216
+ if (scope.onUpdate) scope.onUpdate.length = 0;
129
217
  scope.parent = null;
130
218
  scope.isDestroyed = true;
219
+ if (activeScope === scope) {
220
+ activeScope = parentScope;
221
+ }
131
222
  }
132
223
  function onCleanup(fn) {
133
224
  const scope = activeScope;
@@ -138,9 +229,9 @@ function onCleanup(fn) {
138
229
  return;
139
230
  }
140
231
  if (!scope.cleanup) {
141
- scope.cleanup = /* @__PURE__ */ new Set();
232
+ scope.cleanup = [];
142
233
  }
143
- scope.cleanup.add(fn);
234
+ scope.cleanup.push(fn);
144
235
  }
145
236
 
146
237
  // src/constants.ts
@@ -151,6 +242,11 @@ var KEY_PROP = "key";
151
242
  var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
152
243
  var XLINK_NAMESPACE = "http://www.w3.org/2000/xlink";
153
244
  var XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
245
+ var NORMAL_COMPONENT = /* @__PURE__ */ Symbol("Normal Component" );
246
+ var FRAGMENT_COMPONENT = /* @__PURE__ */ Symbol("Fragment Component" );
247
+ var PORTAL_COMPONENT = /* @__PURE__ */ Symbol("Portal Component" );
248
+ var SUSPENSE_COMPONENT = /* @__PURE__ */ Symbol("Suspense Component" );
249
+ var FOR_COMPONENT = /* @__PURE__ */ Symbol("For Component" );
154
250
  var MAX_KEY_LENGTH = 1e3;
155
251
  var componentKeyPrefixCache = /* @__PURE__ */ new WeakMap();
156
252
  function getComponentKey(type) {
@@ -273,62 +369,51 @@ function isSameNode(a, b) {
273
369
  }
274
370
  function shallowCompare(a, b) {
275
371
  if (a === b) return true;
276
- if (!a || !b) return false;
277
- if (Array.isArray(a) !== Array.isArray(b)) return false;
278
- for (const key in a) {
279
- if (a[key] !== b[key]) return false;
280
- }
281
- for (const key in b) {
282
- if (!(key in a)) return false;
372
+ if (isNull(a) || isNull(b)) return false;
373
+ if (!isObject(a) || !isObject(b)) return false;
374
+ if (isArray(a) !== isArray(b)) return false;
375
+ const aRecord = a;
376
+ const bRecord = b;
377
+ const aKeys = Object.keys(aRecord);
378
+ const bKeys = Object.keys(bRecord);
379
+ if (aKeys.length !== bKeys.length) return false;
380
+ for (const key of aKeys) {
381
+ if (!(key in bRecord) || aRecord[key] !== bRecord[key]) {
382
+ return false;
383
+ }
283
384
  }
284
385
  return true;
285
386
  }
286
387
  function removeNode(node) {
287
388
  if (!node) return;
288
- try {
289
- if (isComponent(node)) {
290
- node.destroy();
291
- } else {
292
- const element = node;
293
- if (element.parentElement) {
294
- element.remove();
295
- }
296
- }
297
- } catch (_error) {
298
- error("Failed to remove node:", _error);
389
+ if (isComponent(node)) {
390
+ node.destroy();
391
+ return;
392
+ }
393
+ const element = node;
394
+ if (element.parentElement) {
395
+ element.remove();
299
396
  }
300
397
  }
301
398
  function insertNode(parent, child, before) {
302
399
  if (!parent || !child) return;
303
- try {
304
- const beforeNode = isComponent(before) ? before.firstChild : before;
305
- if (isComponent(child)) {
306
- child.mount(parent, beforeNode);
307
- return;
308
- }
309
- if (beforeNode) {
310
- parent.insertBefore(child, beforeNode);
311
- } else {
312
- if (true) {
313
- if (!child) {
314
- error("insertNode: child is not a Node", child);
315
- }
316
- }
317
- parent.appendChild(child);
318
- }
319
- } catch (_error) {
320
- error("Failed to insert node:", _error);
400
+ if (isComponent(child)) {
401
+ const beforeNode2 = isComponent(before) ? before.firstChild : before;
402
+ child.mount(parent, beforeNode2);
403
+ return;
404
+ }
405
+ const beforeNode = isComponent(before) ? before.firstChild : before;
406
+ if (beforeNode) {
407
+ parent.insertBefore(child, beforeNode);
408
+ } else {
409
+ parent.appendChild(child);
321
410
  }
322
411
  }
323
412
  function replaceNode(parent, newNode, oldNode) {
324
413
  if (!parent || !newNode || !oldNode || newNode === oldNode) return;
325
- try {
326
- const beforeNode = isComponent(oldNode) ? oldNode.beforeNode : oldNode.nextSibling;
327
- removeNode(oldNode);
328
- insertNode(parent, newNode, beforeNode);
329
- } catch (_error) {
330
- error("Failed to replace node:", _error);
331
- }
414
+ const beforeNode = isComponent(oldNode) ? oldNode.beforeNode : oldNode.nextSibling;
415
+ removeNode(oldNode);
416
+ insertNode(parent, newNode, beforeNode);
332
417
  }
333
418
  function getFirstDOMNode(node) {
334
419
  if (!node) {
@@ -639,18 +724,6 @@ function getSequence(arr) {
639
724
  return result;
640
725
  }
641
726
 
642
- // src/utils/shared.ts
643
- var isHydrationActive = false;
644
- function startHydration() {
645
- isHydrationActive = true;
646
- }
647
- function endHydration() {
648
- isHydrationActive = false;
649
- }
650
- function isHydrating() {
651
- return isHydrationActive;
652
- }
653
-
654
727
  // src/binding.ts
655
728
  function addEventListener(element, event, handler, options) {
656
729
  element.addEventListener(event, handler, options);
@@ -718,28 +791,21 @@ function bindSelectElement(node, setter) {
718
791
  }
719
792
  });
720
793
  }
721
- var isFirstRun = true;
722
- function executeReactiveUpdate(ownerScope, parent, nodeFactory, before, renderedNodes) {
723
- const executeUpdate = () => {
724
- const rawNodes = isFunction(nodeFactory) ? nodeFactory() : nodeFactory;
725
- const nodes = coerceArray(rawNodes).map((item) => isFunction(item) ? item() : item).flatMap((i) => i).map(normalizeNode);
726
- if (isFirstRun && isHydrating()) {
727
- isFirstRun = false;
728
- return renderedNodes;
729
- }
730
- return patchChildren(parent, renderedNodes, nodes, before);
731
- };
732
- if (ownerScope && !ownerScope.isDestroyed) {
733
- return runWithScope(ownerScope, executeUpdate);
734
- }
735
- return executeUpdate();
736
- }
737
794
  function insert(parent, nodeFactory, before) {
738
795
  if (!parent) return;
739
- const ownerScope = getActiveScope();
740
796
  let renderedNodes = [];
797
+ const currentScope = getActiveScope();
741
798
  const cleanup = effect(() => {
742
- renderedNodes = executeReactiveUpdate(ownerScope, parent, nodeFactory, before, renderedNodes);
799
+ const run = () => {
800
+ const rawNodes = isFunction(nodeFactory) ? nodeFactory() : nodeFactory;
801
+ const nodes = coerceArray(rawNodes).map((item) => isFunction(item) ? item() : item).flatMap(normalizeNode);
802
+ renderedNodes = patchChildren(parent, renderedNodes, nodes, before);
803
+ };
804
+ if (currentScope) {
805
+ runWithScope(currentScope, run);
806
+ } else {
807
+ run();
808
+ }
743
809
  });
744
810
  onCleanup(() => {
745
811
  cleanup();
@@ -772,127 +838,40 @@ function mapNodes(template2, indexes) {
772
838
  walk(template2);
773
839
  return tree;
774
840
  }
775
- function registerMountHook(hook) {
776
- const scope = getActiveScope();
777
- if (!scope) {
778
- {
779
- error("onMount() must be called within a scope");
780
- }
781
- return;
782
- }
783
- if (scope.isMounted) {
784
- try {
785
- hook();
786
- } catch (error_) {
787
- {
788
- error(`Scope(${scope.id}): Error in mount hook:`, error_);
789
- }
790
- }
791
- return;
792
- }
793
- if (!scope.onMount) {
794
- scope.onMount = /* @__PURE__ */ new Set();
795
- }
796
- scope.onMount.add(hook);
797
- }
798
- function registerUpdateHook(hook) {
799
- const scope = getActiveScope();
800
- if (!scope) {
801
- {
802
- error("onUpdate() must be called within a scope");
803
- }
804
- return;
805
- }
806
- if (!scope.onUpdate) {
807
- scope.onUpdate = /* @__PURE__ */ new Set();
808
- }
809
- scope.onUpdate.add(hook);
810
- }
811
- function registerDestroyHook(hook) {
812
- const scope = getActiveScope();
813
- if (!scope) {
814
- {
815
- error("onDestroy() must be called within a scope");
816
- }
817
- return;
818
- }
819
- if (!scope.onDestroy) {
820
- scope.onDestroy = /* @__PURE__ */ new Set();
821
- }
822
- scope.onDestroy.add(hook);
823
- }
824
- function triggerMountHooks(scope) {
825
- if (!scope || scope.isDestroyed || scope.isMounted) {
826
- return;
827
- }
828
- scope.isMounted = true;
829
- if (scope.onMount) {
830
- runWithScope(scope, () => {
831
- for (const hook of scope.onMount) {
832
- try {
833
- hook();
834
- } catch (error_) {
835
- if (true) {
836
- error(`Scope(${scope.id}): Error in mount hook:`, error_);
837
- }
838
- }
839
- }
840
- });
841
- }
842
- }
843
- function triggerUpdateHooks(scope) {
844
- if (!scope || scope.isDestroyed) {
845
- return;
846
- }
847
- if (scope.onUpdate) {
848
- for (const hook of scope.onUpdate) {
849
- try {
850
- hook();
851
- } catch (error_) {
852
- {
853
- error(`Scope(${scope.id}): Error in update hook:`, error_);
854
- }
855
- }
856
- }
857
- }
858
- }
859
- function onMount(hook) {
860
- registerMountHook(hook);
861
- }
862
- function onDestroy(hook) {
863
- registerDestroyHook(hook);
864
- }
865
- function onUpdate(hook) {
866
- registerUpdateHook(hook);
867
- }
868
841
 
869
842
  // src/component.ts
870
843
  var _a;
871
- _a = "normal" /* NORMAL */;
844
+ _a = NORMAL_COMPONENT;
872
845
  var Component = class {
873
846
  constructor(component, props = {}) {
874
847
  this.component = component;
875
848
  this.props = props;
876
- // component rendered nodes (supports arrays and fragments)
849
+ // Component rendered nodes (supports arrays and fragments)
877
850
  this.renderedNodes = [];
878
- // component scope (unified context management)
851
+ // Component scope (unified context management)
879
852
  this.scope = null;
880
- // component parent node
853
+ // Component parent node
881
854
  this.parentNode = void 0;
882
- // component before node
855
+ // Component before node
883
856
  this.beforeNode = void 0;
884
- // component reactive props
857
+ // Component props (reactive and snapshot)
885
858
  this.reactiveProps = {};
886
- // component state
859
+ this._propSnapshots = {};
860
+ // Component lifecycle state
887
861
  this.state = 0 /* INITIAL */;
888
- // parent scope captured at construction time
862
+ // Parent scope captured at construction time for correct hierarchy
889
863
  this.parentScope = null;
890
- // component type
891
864
  // @ts-ignore
892
865
  this[_a] = true;
893
866
  this.key = props.key ? normalizeKey(props.key) : getComponentKey(component);
894
- this.reactiveProps = shallowReactive(__spreadValues({}, props || {}));
867
+ this.reactiveProps = shallowReactive(__spreadValues({}, props));
895
868
  this.parentScope = getActiveScope();
869
+ for (const key in props) {
870
+ const val = props[key];
871
+ if (isObject(val)) {
872
+ this._propSnapshots[key] = isArray(val) ? [...val] : __spreadValues({}, val);
873
+ }
874
+ }
896
875
  }
897
876
  get isConnected() {
898
877
  return this.state === 2 /* MOUNTED */;
@@ -900,14 +879,12 @@ var Component = class {
900
879
  get firstChild() {
901
880
  for (const node of this.renderedNodes) {
902
881
  const dom = getFirstDOMNode(node);
903
- if (dom) {
904
- return dom;
905
- }
882
+ if (dom) return dom;
906
883
  }
907
884
  return void 0;
908
885
  }
909
886
  mount(parentNode, beforeNode) {
910
- var _a2;
887
+ var _a2, _b;
911
888
  this.parentNode = parentNode;
912
889
  this.beforeNode = beforeNode;
913
890
  this.state = 1 /* MOUNTING */;
@@ -918,28 +895,21 @@ var Component = class {
918
895
  this.state = 2 /* MOUNTED */;
919
896
  return this.renderedNodes;
920
897
  }
921
- const parent = (_a2 = this.parentScope) != null ? _a2 : getActiveScope();
922
- this.scope = createScope(parent);
923
- const renderedNodes = runWithScope(this.scope, () => {
924
- var _a3;
925
- let result = this.component(this.reactiveProps);
926
- if (isFunction(result)) {
927
- result = result(this.reactiveProps);
928
- }
929
- if (isSignal(result) || isComputed(result)) {
930
- result = result.value;
931
- }
932
- const nodes = (_a3 = insert(parentNode, result, beforeNode)) != null ? _a3 : [];
933
- return nodes;
934
- });
898
+ const parentScope = (_a2 = this.parentScope) != null ? _a2 : getActiveScope();
899
+ this.scope = createScope(parentScope);
900
+ setActiveScope(this.scope);
901
+ let result = this.component(this.reactiveProps);
902
+ if (isFunction(result)) {
903
+ result = result(this.reactiveProps);
904
+ }
905
+ if (isSignal(result) || isComputed(result)) {
906
+ result = result.value;
907
+ }
908
+ const renderedNodes = (_b = insert(parentNode, result, beforeNode)) != null ? _b : [];
935
909
  this.renderedNodes = renderedNodes;
936
- runWithScope(this.scope, () => {
937
- this.applyProps(this.props || {});
938
- });
910
+ this.applyProps(this.props);
939
911
  this.state = 2 /* MOUNTED */;
940
- if (this.scope) {
941
- triggerMountHooks(this.scope);
942
- }
912
+ triggerMountHooks(this.scope);
943
913
  return this.renderedNodes;
944
914
  }
945
915
  update(prevNode) {
@@ -954,91 +924,106 @@ var Component = class {
954
924
  this.renderedNodes = prevNode.renderedNodes;
955
925
  this.state = prevNode.state;
956
926
  this.reactiveProps = prevNode.reactiveProps;
957
- if (!this.props || Object.keys(this.props).length === 0) {
958
- if (!this.isConnected && this.parentNode) {
959
- this.mount(this.parentNode, this.beforeNode);
960
- return this;
961
- }
962
- if (this.scope) {
963
- runWithScope(this.scope, () => {
964
- this.applyProps(this.props || {});
965
- });
966
- triggerUpdateHooks(this.scope);
967
- }
927
+ this._propSnapshots = prevNode._propSnapshots;
928
+ this._updateReactiveProps(this.props);
929
+ if (!this.isConnected && this.parentNode) {
930
+ this.mount(this.parentNode, this.beforeNode);
968
931
  return this;
969
932
  }
970
- let hasChanges = false;
971
- for (const key in this.props) {
933
+ if (this.scope) {
934
+ setActiveScope(this.scope);
935
+ this.applyProps(this.props);
936
+ triggerUpdateHooks(this.scope);
937
+ }
938
+ return this;
939
+ }
940
+ /**
941
+ * Update reactive props by comparing with current values
942
+ */
943
+ _updateReactiveProps(props) {
944
+ for (const key in props) {
972
945
  if (key === "key") continue;
973
- const newValue = this.props[key];
946
+ const newValue = props[key];
974
947
  const oldValue = this.reactiveProps[key];
975
- if (Object.is(oldValue, newValue)) {
976
- continue;
977
- }
978
- if (isObject(oldValue) && isObject(newValue)) {
979
- if (shallowCompare(oldValue, newValue)) {
980
- continue;
948
+ if (newValue === oldValue && !this._propSnapshots[key]) continue;
949
+ const isNewValueObject = isObject(newValue);
950
+ if (isNewValueObject) {
951
+ const snapshot = this._propSnapshots[key];
952
+ if (snapshot && shallowCompare(newValue, snapshot)) continue;
953
+ const newSnapshot = isArray(newValue) ? [...newValue] : __spreadValues({}, newValue);
954
+ this.reactiveProps[key] = newSnapshot;
955
+ this._propSnapshots[key] = newSnapshot;
956
+ } else {
957
+ if (hasChanged(newValue, oldValue)) {
958
+ this.reactiveProps[key] = newValue;
959
+ if (this._propSnapshots[key]) {
960
+ delete this._propSnapshots[key];
961
+ }
981
962
  }
982
963
  }
983
- this.reactiveProps[key] = newValue;
984
- hasChanges = true;
985
964
  }
986
- if (!this.isConnected && this.parentNode) {
987
- this.mount(this.parentNode, this.beforeNode);
965
+ }
966
+ unwrapRenderResult(result) {
967
+ if (isFunction(result)) {
968
+ result = result(this.reactiveProps);
969
+ }
970
+ if (isSignal(result) || isComputed(result)) {
971
+ result = result.value;
972
+ }
973
+ if (isComponent(result)) {
974
+ result = result.mount(this.parentNode, this.beforeNode);
975
+ }
976
+ if (isPromise(result)) {
977
+ result = result.then((r) => this.unwrapRenderResult(r));
988
978
  }
989
- if (this.scope && (hasChanges || !this.isConnected)) {
979
+ return result;
980
+ }
981
+ forceUpdate() {
982
+ if (this.state === 5 /* DESTROYED */ || !this.parentNode || !this.scope) {
983
+ return;
984
+ }
985
+ const originalNodes = [...this.renderedNodes];
986
+ try {
990
987
  runWithScope(this.scope, () => {
991
- this.applyProps(this.props || {});
988
+ let result = this.component(this.reactiveProps);
989
+ if (isFunction(result)) {
990
+ result = result(this.reactiveProps);
991
+ }
992
+ if (isSignal(result) || isComputed(result)) {
993
+ result = result.value;
994
+ }
995
+ const newNodes = coerceArray(result);
996
+ const anchor = this._getAnchorNode();
997
+ if (!this.parentNode) return;
998
+ for (const node of this.renderedNodes) {
999
+ removeNode(node);
1000
+ }
1001
+ for (const node of newNodes) {
1002
+ insertNode(this.parentNode, node, anchor);
1003
+ }
1004
+ this.renderedNodes = newNodes;
992
1005
  });
993
- if (hasChanges) {
1006
+ if (this.scope) {
994
1007
  triggerUpdateHooks(this.scope);
995
1008
  }
1009
+ } catch (error8) {
1010
+ this.renderedNodes = originalNodes;
1011
+ throw error8;
996
1012
  }
997
- return this;
998
1013
  }
999
- forceUpdate() {
1000
- return __async(this, null, function* () {
1001
- yield Promise.resolve();
1002
- if (this.state === 5 /* DESTROYED */ || !this.parentNode || !this.scope) {
1003
- return;
1004
- }
1005
- const originalNodes = [...this.renderedNodes];
1006
- try {
1007
- runWithScope(this.scope, () => {
1008
- let result = this.component(this.reactiveProps);
1009
- if (isFunction(result)) {
1010
- result = result(this.reactiveProps);
1011
- }
1012
- if (isSignal(result) || isComputed(result)) {
1013
- result = result.value;
1014
- }
1015
- const newNodes = coerceArray(result);
1016
- if (this.parentNode) {
1017
- let anchor = this.beforeNode;
1018
- if (!anchor && this.renderedNodes.length > 0) {
1019
- const lastNode = this.renderedNodes[this.renderedNodes.length - 1];
1020
- const lastDom = getFirstDOMNode(lastNode);
1021
- if (lastDom) {
1022
- anchor = lastDom.nextSibling;
1023
- }
1024
- }
1025
- for (const node of this.renderedNodes) {
1026
- removeNode(node);
1027
- }
1028
- for (const node of newNodes) {
1029
- insertNode(this.parentNode, node, anchor);
1030
- }
1031
- this.renderedNodes = newNodes;
1032
- }
1033
- });
1034
- if (this.scope) {
1035
- triggerUpdateHooks(this.scope);
1036
- }
1037
- } catch (error8) {
1038
- this.renderedNodes = originalNodes;
1039
- throw error8;
1014
+ /**
1015
+ * Get anchor node for insertion
1016
+ */
1017
+ _getAnchorNode() {
1018
+ if (this.beforeNode) return this.beforeNode;
1019
+ if (this.renderedNodes.length > 0) {
1020
+ const lastNode = this.renderedNodes[this.renderedNodes.length - 1];
1021
+ const lastDom = getFirstDOMNode(lastNode);
1022
+ if (lastDom) {
1023
+ return lastDom.nextSibling;
1040
1024
  }
1041
- });
1025
+ }
1026
+ return void 0;
1042
1027
  }
1043
1028
  /**
1044
1029
  * Destroy component
@@ -1048,14 +1033,14 @@ var Component = class {
1048
1033
  return;
1049
1034
  }
1050
1035
  this.state = 4 /* DESTROYING */;
1036
+ for (const node of this.renderedNodes) {
1037
+ removeNode(node);
1038
+ }
1051
1039
  const scope = this.scope;
1052
1040
  if (scope) {
1053
1041
  disposeScope(scope);
1054
1042
  this.scope = null;
1055
1043
  }
1056
- for (const node of this.renderedNodes) {
1057
- removeNode(node);
1058
- }
1059
1044
  this.renderedNodes = [];
1060
1045
  this.parentNode = void 0;
1061
1046
  this.beforeNode = void 0;
@@ -1065,16 +1050,13 @@ var Component = class {
1065
1050
  this.state = 5 /* DESTROYED */;
1066
1051
  }
1067
1052
  applyProps(props) {
1068
- if (!props) {
1069
- return;
1070
- }
1053
+ if (!props) return;
1071
1054
  const firstElement = this.firstChild;
1072
1055
  for (const [propName, propValue] of Object.entries(props)) {
1073
- if (startsWith(propName, EVENT_PREFIX) && firstElement) {
1074
- const eventName = propName.slice(2).toLowerCase();
1075
- if (isHTMLElement(firstElement)) {
1076
- addEventListener(firstElement, eventName, propValue);
1077
- }
1056
+ if (startsWith(propName, EVENT_PREFIX)) {
1057
+ if (!firstElement || !isHTMLElement(firstElement)) return;
1058
+ const eventName = propName.slice(EVENT_PREFIX.length).toLowerCase();
1059
+ addEventListener(firstElement, eventName, propValue);
1078
1060
  } else if (propName === REF_KEY && isSignal(propValue)) {
1079
1061
  propValue.value = firstElement;
1080
1062
  }
@@ -1083,7 +1065,7 @@ var Component = class {
1083
1065
  }
1084
1066
  };
1085
1067
  function isComponent(node) {
1086
- return !!node && !!node["normal" /* NORMAL */];
1068
+ return !!node && !!node[NORMAL_COMPONENT];
1087
1069
  }
1088
1070
  function createComponent(componentFn, props) {
1089
1071
  if (isComponent(componentFn)) {
@@ -1117,7 +1099,7 @@ function createApp(component, target) {
1117
1099
  error(`Target element is not empty, it will be delete: ${target}`);
1118
1100
  container.innerHTML = "";
1119
1101
  }
1120
- const rootComponent = createComponent(component);
1102
+ const rootComponent = isComponent(component) ? component : createComponent(component);
1121
1103
  rootComponent.mount(container);
1122
1104
  return rootComponent;
1123
1105
  }
@@ -1154,53 +1136,59 @@ function inject(key, defaultValue) {
1154
1136
  }
1155
1137
  return defaultValue;
1156
1138
  }
1157
- function eventHandler(e) {
1158
- let node = e.target;
1159
- const key = `${e.type}`;
1160
- const oriTarget = e.target;
1161
- const oriCurrentTarget = e.currentTarget;
1162
- const reTarget = (value) => Object.defineProperty(e, "target", {
1139
+ function reTarget(event, value) {
1140
+ Object.defineProperty(event, "target", {
1163
1141
  configurable: true,
1164
1142
  value
1165
1143
  });
1166
- const handleNode = () => {
1167
- const handler = node[`_$${key}`];
1168
- if (handler && isFunction(handler) && !node.disabled) {
1169
- const data = node[`${key}Data`];
1170
- data ? handler.call(node, data, e) : handler.call(node, e);
1171
- if (e.cancelBubble) return false;
1172
- }
1173
- if (node.host && !isString(node.host) && !node.host._$host && isFunction(node.contains) && node.contains(e.target)) {
1174
- reTarget(node.host);
1175
- }
1176
- return true;
1177
- };
1178
- const walkUpTree = () => {
1179
- while (handleNode() && (node = node._$host || node.parentNode || node.host)) ;
1180
- };
1181
- Object.defineProperty(e, "currentTarget", {
1144
+ }
1145
+ function handleNodeEvent(node, event, key) {
1146
+ const handler = node[`_$${key}`];
1147
+ if (handler && isFunction(handler) && !node.disabled) {
1148
+ const data = node[`${key}Data`];
1149
+ data ? handler.call(node, data, event) : handler.call(node, event);
1150
+ if (event.cancelBubble) return false;
1151
+ }
1152
+ if (node.host && !isString(node.host) && !node.host._$host && isFunction(node.contains) && node.contains(event.target)) {
1153
+ reTarget(event, node.host);
1154
+ }
1155
+ return true;
1156
+ }
1157
+ function walkUpTree(startNode, event, key) {
1158
+ let node = startNode;
1159
+ while (handleNodeEvent(node, event, key) && (node = node._$host || node.parentNode || node.host)) ;
1160
+ return node;
1161
+ }
1162
+ function eventHandler(event) {
1163
+ let node = event.target;
1164
+ const key = `${event.type}`;
1165
+ const oriTarget = event.target;
1166
+ const oriCurrentTarget = event.currentTarget;
1167
+ Object.defineProperty(event, "currentTarget", {
1182
1168
  configurable: true,
1183
1169
  get() {
1184
1170
  return node || document;
1185
1171
  }
1186
1172
  });
1187
- if (e.composedPath) {
1188
- const path = e.composedPath();
1189
- reTarget(path[0]);
1173
+ if (event.composedPath) {
1174
+ const path = event.composedPath();
1175
+ reTarget(event, path[0]);
1190
1176
  for (let i = 0; i < path.length - 2; i++) {
1191
1177
  node = path[i];
1192
- if (!handleNode()) break;
1178
+ if (!handleNodeEvent(node, event, key)) break;
1193
1179
  if (node._$host) {
1194
1180
  node = node._$host;
1195
- walkUpTree();
1181
+ node = walkUpTree(node, event, key);
1196
1182
  break;
1197
1183
  }
1198
1184
  if (node.parentNode === oriCurrentTarget) {
1199
1185
  break;
1200
1186
  }
1201
1187
  }
1202
- } else walkUpTree();
1203
- reTarget(oriTarget);
1188
+ } else {
1189
+ node = walkUpTree(node, event, key);
1190
+ }
1191
+ reTarget(event, oriTarget);
1204
1192
  }
1205
1193
  var $EVENTS = /* @__PURE__ */ Symbol("_$EVENTS");
1206
1194
  function delegateEvents(eventNames, document2 = window.document) {
@@ -1245,6 +1233,110 @@ function omitProps(target, keys) {
1245
1233
  }
1246
1234
  });
1247
1235
  }
1236
+
1237
+ // src/hydration/shared.ts
1238
+ var isHydrationActive = false;
1239
+ function startHydration() {
1240
+ isHydrationActive = true;
1241
+ }
1242
+ function endHydration() {
1243
+ isHydrationActive = false;
1244
+ }
1245
+ function isHydrating() {
1246
+ return isHydrationActive;
1247
+ }
1248
+ var hydrationCounter = 0;
1249
+ function getHydrationKey() {
1250
+ return `${hydrationCounter++}`;
1251
+ }
1252
+ function resetHydrationKey() {
1253
+ hydrationCounter = 0;
1254
+ }
1255
+
1256
+ // src/hydration/hydration.ts
1257
+ var DATA_IDX_REGEX = /^\d+-\d+$/;
1258
+ function getRenderedElement(temp) {
1259
+ return () => {
1260
+ if (!isBrowser()) {
1261
+ return null;
1262
+ }
1263
+ const key = getHydrationKey();
1264
+ const node = document.querySelector(`[data-hk="${key}"]`);
1265
+ if (node) {
1266
+ return node;
1267
+ }
1268
+ return template(temp)();
1269
+ };
1270
+ }
1271
+ function mapSSRNodes(templateEl, idx) {
1272
+ const hk = templateEl.dataset.hk;
1273
+ if (!hk) {
1274
+ return mapNodes(templateEl, idx);
1275
+ }
1276
+ const nodesList = [];
1277
+ const elements = templateEl.querySelectorAll(`[data-idx^="${hk}"]`);
1278
+ if (elements.length > 0) {
1279
+ nodesList.push(
1280
+ ...Array.from(elements).filter((item) => {
1281
+ const idxAttr = item.dataset.idx;
1282
+ return idxAttr !== null && DATA_IDX_REGEX.test(idxAttr);
1283
+ }).map((item) => {
1284
+ const idxAttr = item.dataset.idx || "";
1285
+ const [hkPart, idxPart] = idxAttr.split("-");
1286
+ return {
1287
+ hk: hkPart,
1288
+ idx: idxPart,
1289
+ node: item
1290
+ };
1291
+ })
1292
+ );
1293
+ }
1294
+ const commentNodes = [];
1295
+ const walkNodes = (node) => {
1296
+ if (node.nodeType === Node.COMMENT_NODE && node.textContent && DATA_IDX_REGEX.test(node.textContent)) {
1297
+ const [hkPart, idxPart] = node.textContent.split("-");
1298
+ commentNodes.push({
1299
+ hk: hkPart,
1300
+ idx: idxPart,
1301
+ node
1302
+ });
1303
+ }
1304
+ let child = node.firstChild;
1305
+ while (child) {
1306
+ walkNodes(child);
1307
+ child = child.nextSibling;
1308
+ }
1309
+ };
1310
+ walkNodes(templateEl);
1311
+ nodesList.push(...commentNodes);
1312
+ const nodes = [templateEl];
1313
+ idx.forEach((indexValue) => {
1314
+ const node = nodesList.find((item) => item.idx === String(indexValue));
1315
+ if (node) {
1316
+ nodes.push(node.node);
1317
+ }
1318
+ });
1319
+ return nodes;
1320
+ }
1321
+ function hydrate(component, container) {
1322
+ startHydration();
1323
+ resetHydrationKey();
1324
+ try {
1325
+ const rootElement = isString(container) ? document.querySelector(container) : container;
1326
+ if (!rootElement) {
1327
+ error("Hydration error: Root element not found");
1328
+ return void 0;
1329
+ }
1330
+ const rootComponent = createComponent(component);
1331
+ rootComponent.mount(rootElement);
1332
+ endHydration();
1333
+ return rootComponent;
1334
+ } catch (error_) {
1335
+ error("Hydration error:", error_);
1336
+ endHydration();
1337
+ return void 0;
1338
+ }
1339
+ }
1248
1340
  function patchClass(el, prev, next, isSVG = false) {
1249
1341
  if (prev === next) {
1250
1342
  return;
@@ -1331,7 +1423,7 @@ function setStyle(style, name, val) {
1331
1423
  return;
1332
1424
  }
1333
1425
  const prefixed = autoPrefix(style, name);
1334
- if (typeof val === "string" && importantRE.test(val)) {
1426
+ if (isString(val) && importantRE.test(val)) {
1335
1427
  style.setProperty(camelCase(prefixed), val.replace(importantRE, ""), "important");
1336
1428
  } else {
1337
1429
  style[prefixed] = val;
@@ -1421,7 +1513,7 @@ function patchAttr(el, key, prev, next) {
1421
1513
  }
1422
1514
  const attrValue = isSymbol(next) ? String(next) : next;
1423
1515
  const isUrlAttr = lowerKey === "href" || lowerKey === "src" || lowerKey === "xlink:href";
1424
- if (isUrlAttr && typeof attrValue === "string") {
1516
+ if (isUrlAttr && isString(attrValue)) {
1425
1517
  const v = attrValue.trim().toLowerCase();
1426
1518
  if (v.startsWith("javascript:") || v.startsWith("data:")) {
1427
1519
  return;
@@ -1468,26 +1560,21 @@ function Fragment(props) {
1468
1560
  error("Fragment component requires props");
1469
1561
  return null;
1470
1562
  }
1471
- if (!props.children) {
1472
- error("Fragment component requires children");
1473
- return null;
1474
- }
1475
1563
  }
1476
- return props == null ? void 0 : props.children;
1564
+ if (!(props == null ? void 0 : props.children)) {
1565
+ error("Fragment component requires children");
1566
+ return null;
1567
+ }
1568
+ const { children } = props;
1569
+ return children;
1477
1570
  }
1478
- Fragment["fragment" /* FRAGMENT */] = true;
1571
+ Fragment[FRAGMENT_COMPONENT] = true;
1479
1572
  function isFragment(node) {
1480
- return !!node && !!node["fragment" /* FRAGMENT */];
1573
+ return !!node && !!node[FRAGMENT_COMPONENT];
1481
1574
  }
1482
1575
  function Portal(props) {
1483
- if (typeof document === "undefined") {
1484
- const children2 = props.children;
1485
- if (!children2) return "";
1486
- const childArray = isArray(children2) ? children2 : [children2];
1487
- return childArray.map((child) => String(child || "")).join("");
1488
- }
1489
1576
  const placeholder = document.createComment("portal");
1490
- placeholder["portal" /* PORTAL */] = true;
1577
+ placeholder[PORTAL_COMPONENT] = true;
1491
1578
  const children = props.children;
1492
1579
  if (children) {
1493
1580
  const childArray = isArray(children) ? children : [children];
@@ -1495,7 +1582,7 @@ function Portal(props) {
1495
1582
  onMount(() => {
1496
1583
  const targetElement = isString(props.target) ? document.querySelector(props.target) : props.target;
1497
1584
  if (!targetElement) {
1498
- {
1585
+ if (true) {
1499
1586
  warn(`[Portal] Target element not found: ${props.target}`);
1500
1587
  }
1501
1588
  return;
@@ -1511,7 +1598,7 @@ function Portal(props) {
1511
1598
  });
1512
1599
  onCleanup(() => {
1513
1600
  nodes.forEach((node) => {
1514
- if (typeof node !== "string" && node.parentNode === targetElement) {
1601
+ if (!isString(node) && node.parentNode === targetElement) {
1515
1602
  targetElement.removeChild(node);
1516
1603
  }
1517
1604
  });
@@ -1520,9 +1607,9 @@ function Portal(props) {
1520
1607
  }
1521
1608
  return placeholder;
1522
1609
  }
1523
- Portal["portal" /* PORTAL */] = true;
1610
+ Portal[PORTAL_COMPONENT] = true;
1524
1611
  function isPortal(node) {
1525
- return !!node && !!node["portal" /* PORTAL */];
1612
+ return !!node && !!node[PORTAL_COMPONENT];
1526
1613
  }
1527
1614
  var SuspenseContext = /* @__PURE__ */ Symbol("SuspenseContext");
1528
1615
  function Suspense(props) {
@@ -1651,9 +1738,9 @@ function Suspense(props) {
1651
1738
  });
1652
1739
  return container;
1653
1740
  }
1654
- Suspense["suspense" /* SUSPENSE */] = true;
1741
+ Suspense[SUSPENSE_COMPONENT] = true;
1655
1742
  function isSuspense(node) {
1656
- return !!node && !!node["suspense" /* SUSPENSE */];
1743
+ return !!node && !!node[SUSPENSE_COMPONENT];
1657
1744
  }
1658
1745
  function createResource(fetcher, options) {
1659
1746
  const value = signal(options == null ? void 0 : options.initialValue);
@@ -1712,7 +1799,173 @@ function createResource(fetcher, options) {
1712
1799
  };
1713
1800
  return [resource, actions];
1714
1801
  }
1802
+ function For(props) {
1803
+ const fragment = document.createDocumentFragment();
1804
+ const marker = document.createComment("");
1805
+ fragment.appendChild(marker);
1806
+ let entries = [];
1807
+ let fallbackNode = null;
1808
+ const keyFn = props.keyFn;
1809
+ const renderFn = props.children;
1810
+ const getList = () => {
1811
+ var _a2, _b;
1812
+ const input = props.each;
1813
+ if (isSignal(input)) return (_a2 = input.value) != null ? _a2 : [];
1814
+ if (typeof input === "function") return (_b = input()) != null ? _b : [];
1815
+ return input != null ? input : [];
1816
+ };
1817
+ const getKey = (item) => keyFn ? keyFn(item) : item;
1818
+ const renderItem = (item, index, parent, before) => {
1819
+ var _a2;
1820
+ const prevScope = getActiveScope();
1821
+ const scope = createScope(prevScope);
1822
+ setActiveScope(scope);
1823
+ let node;
1824
+ try {
1825
+ const result = renderFn(item, index);
1826
+ if (isComponent(result)) {
1827
+ result.mount(parent, before);
1828
+ node = (_a2 = result.firstChild) != null ? _a2 : document.createComment("empty");
1829
+ } else {
1830
+ node = result;
1831
+ if (!node.parentNode) {
1832
+ if (before) {
1833
+ parent.insertBefore(node, before);
1834
+ } else {
1835
+ parent.appendChild(node);
1836
+ }
1837
+ }
1838
+ }
1839
+ } finally {
1840
+ setActiveScope(prevScope);
1841
+ }
1842
+ return { key: getKey(item), node, scope };
1843
+ };
1844
+ const disposeItem = (entry) => {
1845
+ disposeScope(entry.scope);
1846
+ if (entry.node.parentNode) {
1847
+ entry.node.parentNode.removeChild(entry.node);
1848
+ }
1849
+ };
1850
+ memoEffect(
1851
+ ({ prev }) => {
1852
+ var _a2;
1853
+ const newItems = getList();
1854
+ if (prev === newItems) return { prev: newItems };
1855
+ const parent = marker.parentNode;
1856
+ if (!parent) {
1857
+ if (newItems.length === 0) {
1858
+ if (props.fallback) {
1859
+ const fb = props.fallback();
1860
+ if (isComponent(fb)) {
1861
+ fb.mount(fragment, marker);
1862
+ fallbackNode = (_a2 = fb.firstChild) != null ? _a2 : document.createComment("empty");
1863
+ } else {
1864
+ fallbackNode = fb;
1865
+ fragment.insertBefore(fallbackNode, marker);
1866
+ }
1867
+ }
1868
+ return { prev: newItems };
1869
+ }
1870
+ entries = new Array(newItems.length);
1871
+ for (const [i, newItem] of newItems.entries()) {
1872
+ entries[i] = renderItem(newItem, i, fragment, marker);
1873
+ }
1874
+ return { prev: newItems };
1875
+ }
1876
+ untrack(() => reconcile(parent, newItems));
1877
+ return { prev: newItems };
1878
+ },
1879
+ {
1880
+ prev: []
1881
+ }
1882
+ );
1883
+ function reconcile(parent, newItems) {
1884
+ var _a2;
1885
+ const oldLen = entries.length;
1886
+ const newLen = newItems.length;
1887
+ if (newLen === 0) {
1888
+ for (let i = 0; i < oldLen; i++) {
1889
+ disposeItem(entries[i]);
1890
+ }
1891
+ entries = [];
1892
+ if (props.fallback && !fallbackNode) {
1893
+ const fb = props.fallback();
1894
+ if (isComponent(fb)) {
1895
+ fb.mount(parent, marker);
1896
+ fallbackNode = (_a2 = fb.firstChild) != null ? _a2 : document.createComment("empty");
1897
+ } else {
1898
+ fallbackNode = fb;
1899
+ parent.insertBefore(fallbackNode, marker);
1900
+ }
1901
+ }
1902
+ return;
1903
+ }
1904
+ if (oldLen === 0 || fallbackNode) {
1905
+ if (fallbackNode) {
1906
+ if (fallbackNode.parentNode) fallbackNode.parentNode.removeChild(fallbackNode);
1907
+ fallbackNode = null;
1908
+ }
1909
+ entries = new Array(newLen);
1910
+ const batchFragment2 = document.createDocumentFragment();
1911
+ for (let i = 0; i < newLen; i++) {
1912
+ entries[i] = renderItem(newItems[i], i, batchFragment2, null);
1913
+ }
1914
+ parent.insertBefore(batchFragment2, marker);
1915
+ return;
1916
+ }
1917
+ const oldKeyMap = /* @__PURE__ */ new Map();
1918
+ for (let i = 0; i < oldLen; i++) {
1919
+ const entry = entries[i];
1920
+ const list = oldKeyMap.get(entry.key);
1921
+ if (list) {
1922
+ list.push(entry);
1923
+ } else {
1924
+ oldKeyMap.set(entry.key, [entry]);
1925
+ }
1926
+ }
1927
+ const newEntries = new Array(newLen);
1928
+ const toRemove = [];
1929
+ const batchFragment = document.createDocumentFragment();
1930
+ for (let i = 0; i < newLen; i++) {
1931
+ const item = newItems[i];
1932
+ const key = getKey(item);
1933
+ const oldList = oldKeyMap.get(key);
1934
+ if (oldList && oldList.length > 0) {
1935
+ newEntries[i] = oldList.shift();
1936
+ } else {
1937
+ newEntries[i] = renderItem(item, i, batchFragment, null);
1938
+ }
1939
+ }
1940
+ for (const list of oldKeyMap.values()) {
1941
+ for (const entry of list) {
1942
+ toRemove.push(entry);
1943
+ }
1944
+ }
1945
+ for (const entry of toRemove) {
1946
+ disposeItem(entry);
1947
+ }
1948
+ for (let i = 0; i < newLen; i++) {
1949
+ const node = newEntries[i].node;
1950
+ parent.insertBefore(node, marker);
1951
+ }
1952
+ entries = newEntries;
1953
+ }
1954
+ onCleanup(() => {
1955
+ for (const entry of entries) {
1956
+ disposeItem(entry);
1957
+ }
1958
+ if (fallbackNode && fallbackNode.parentNode) {
1959
+ fallbackNode.parentNode.removeChild(fallbackNode);
1960
+ }
1961
+ if (marker.parentNode) {
1962
+ marker.parentNode.removeChild(marker);
1963
+ }
1964
+ });
1965
+ return fragment;
1966
+ }
1967
+ For[FOR_COMPONENT] = true;
1715
1968
 
1716
- export { Component, Fragment, Portal, Suspense, addEvent, addEventListener, bindElement, createApp, createComponent, createResource, createScope, delegateEvents, disposeScope, endHydration, getActiveScope, getFirstDOMNode, inject, insert, insertNode, isComponent, isFragment, isHydrating, isPortal, isSameNode, isSuspense, mapNodes, normalizeClass, normalizeNode, omitProps, onCleanup, onDestroy, onMount, onUpdate, patchAttr, patchClass, patchStyle, provide, removeNode, replaceNode, runWithScope, setActiveScope, setStyle, shallowCompare, startHydration, template };
1969
+ export { Component, For, Fragment, Portal, Suspense, addEvent, addEventListener, bindElement, createApp, createComponent, createResource, createScope, delegateEvents, disposeScope, endHydration, getActiveScope, getFirstDOMNode, getHydrationKey, getRenderedElement, hydrate, inject, insert, insertNode, isComponent, isFragment, isHydrating, isPortal, isSameNode, isSuspense, mapNodes, mapSSRNodes, normalizeClass, normalizeNode, omitProps, onCleanup, onDestroy, onMount, onUpdate, patchAttr, patchClass, patchStyle, provide, removeNode, replaceNode, resetHydrationKey, runWithScope, setActiveScope, setStyle, shallowCompare, startHydration, template };
1717
1970
  //# sourceMappingURL=template.dev.esm.js.map
1718
1971
  //# sourceMappingURL=template.dev.esm.js.map