@wsxjs/wsx-core 0.0.23 → 0.0.25

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.
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createLogger,
5
5
  h,
6
6
  shouldPreserveElement
7
- } from "./chunk-ESZYREJK.mjs";
7
+ } from "./chunk-5Q2VEEUH.mjs";
8
8
 
9
9
  // src/styles/style-manager.ts
10
10
  var StyleManager = class {
@@ -401,6 +401,12 @@ var BaseComponent = class extends HTMLElement {
401
401
  * @internal
402
402
  */
403
403
  this._isRendering = false;
404
+ /**
405
+ * 已调度渲染标志(防止在同一事件循环中重复注册 requestAnimationFrame)
406
+ * 用于批量更新:同一事件循环中的多个状态变化只触发一次渲染
407
+ * @internal
408
+ */
409
+ this._hasScheduledRender = false;
404
410
  /**
405
411
  * 处理 blur 事件,在用户停止输入时执行待处理的重渲染
406
412
  * @internal
@@ -507,6 +513,9 @@ var BaseComponent = class extends HTMLElement {
507
513
  if (this._isRendering) {
508
514
  return;
509
515
  }
516
+ if (this._hasScheduledRender) {
517
+ return;
518
+ }
510
519
  const root = this.getActiveRoot();
511
520
  let activeElement = null;
512
521
  if (root instanceof ShadowRoot) {
@@ -532,8 +541,16 @@ var BaseComponent = class extends HTMLElement {
532
541
  if (this._pendingRerender) {
533
542
  this._pendingRerender = false;
534
543
  }
544
+ this._hasScheduledRender = true;
535
545
  requestAnimationFrame(() => {
546
+ console.warn("[scheduleRerender] RAF callback:", {
547
+ component: this.constructor.name,
548
+ connected: this.connected,
549
+ isRendering: this._isRendering
550
+ });
551
+ this._hasScheduledRender = false;
536
552
  if (this.connected && !this._isRendering) {
553
+ console.warn("[scheduleRerender] calling _rerender()");
537
554
  this._isRendering = true;
538
555
  this._rerender();
539
556
  } else if (!this.connected) {
@@ -790,6 +807,7 @@ var WebComponent = class extends BaseComponent {
790
807
  (child) => child instanceof HTMLElement && child.style.color === "red" && child.textContent?.includes("Component Error")
791
808
  );
792
809
  const hasActualContent = allChildren.length > styleElements.length + slotElements.length;
810
+ this.onConnected?.();
793
811
  if (hasActualContent && !hasErrorElement) {
794
812
  } else {
795
813
  this.shadowRoot.innerHTML = "";
@@ -801,7 +819,6 @@ var WebComponent = class extends BaseComponent {
801
819
  this.shadowRoot.appendChild(content);
802
820
  }
803
821
  this.initializeEventListeners();
804
- this.onConnected?.();
805
822
  if (hasActualContent === false || hasErrorElement) {
806
823
  requestAnimationFrame(() => {
807
824
  this.onRendered?.();
@@ -853,8 +870,12 @@ var WebComponent = class extends BaseComponent {
853
870
  const focusState = this.captureFocusState();
854
871
  this._pendingFocusState = focusState;
855
872
  const adoptedStyleSheets = this.shadowRoot.adoptedStyleSheets || [];
873
+ const hasActualAdoptedStyles = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
874
+ const hasFallbackStyleElement = Array.from(this.shadowRoot.children).some(
875
+ (child) => child instanceof HTMLStyleElement
876
+ );
856
877
  try {
857
- if (adoptedStyleSheets.length === 0) {
878
+ if (!hasActualAdoptedStyles && !hasFallbackStyleElement) {
858
879
  const stylesToApply = this._autoStyles || this.config.styles;
859
880
  if (stylesToApply) {
860
881
  const styleName = this.config.styleName || this.constructor.name;
@@ -872,31 +893,40 @@ var WebComponent = class extends BaseComponent {
872
893
  }
873
894
  }
874
895
  }
875
- if (this.shadowRoot.adoptedStyleSheets) {
876
- this.shadowRoot.adoptedStyleSheets = adoptedStyleSheets;
877
- }
878
- requestAnimationFrame(() => {
896
+ const isContentAlreadyInShadowRoot = content.parentNode === this.shadowRoot;
897
+ if (!isContentAlreadyInShadowRoot) {
879
898
  this.shadowRoot.appendChild(content);
880
- const oldChildren = Array.from(this.shadowRoot.children).filter((child) => {
881
- if (child === content) {
882
- return false;
883
- }
884
- if (child instanceof HTMLStyleElement) {
885
- return false;
886
- }
887
- if (shouldPreserveElement(child)) {
888
- return false;
889
- }
890
- return true;
891
- });
892
- oldChildren.forEach((child) => child.remove());
893
- requestAnimationFrame(() => {
894
- this.restoreFocusState(focusState);
895
- this._pendingFocusState = null;
896
- this.onRendered?.();
897
- this._isRendering = false;
898
- });
899
+ }
900
+ const oldChildren = Array.from(this.shadowRoot.children).filter((child) => {
901
+ if (child === content) {
902
+ return false;
903
+ }
904
+ if (child instanceof HTMLStyleElement) {
905
+ return false;
906
+ }
907
+ if (shouldPreserveElement(child)) {
908
+ return false;
909
+ }
910
+ return true;
899
911
  });
912
+ oldChildren.forEach((child) => child.remove());
913
+ const hasStylesAfterDOM = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
914
+ const hasStyleElementAfterDOM = Array.from(this.shadowRoot.children).some(
915
+ (child) => child instanceof HTMLStyleElement
916
+ );
917
+ if (adoptedStyleSheets.length > 0) {
918
+ this.shadowRoot.adoptedStyleSheets = adoptedStyleSheets;
919
+ } else if (!hasStylesAfterDOM && !hasStyleElementAfterDOM) {
920
+ const stylesToApply = this._autoStyles || this.config.styles;
921
+ if (stylesToApply) {
922
+ const styleName = this.config.styleName || this.constructor.name;
923
+ StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
924
+ }
925
+ }
926
+ this.restoreFocusState(focusState);
927
+ this._pendingFocusState = null;
928
+ this.onRendered?.();
929
+ this._isRendering = false;
900
930
  } catch (error) {
901
931
  logger3.error("Error in _rerender:", error);
902
932
  this.renderError(error);
@@ -958,6 +988,7 @@ var LightComponent = class extends BaseComponent {
958
988
  const hasActualContent = Array.from(this.children).some(
959
989
  (child) => child !== styleElement && !(child instanceof HTMLSlotElement)
960
990
  );
991
+ this.onConnected?.();
961
992
  if (hasActualContent && !hasErrorElement) {
962
993
  this.markJSXChildren();
963
994
  if (styleElement && styleElement !== this.firstChild) {
@@ -975,7 +1006,6 @@ var LightComponent = class extends BaseComponent {
975
1006
  }
976
1007
  }
977
1008
  this.initializeEventListeners();
978
- this.onConnected?.();
979
1009
  if (hasActualContent === false || hasErrorElement) {
980
1010
  requestAnimationFrame(() => {
981
1011
  this.onRendered?.();
@@ -1074,11 +1104,18 @@ var LightComponent = class extends BaseComponent {
1074
1104
  return true;
1075
1105
  });
1076
1106
  oldChildren.forEach((child) => child.remove());
1077
- if (stylesToApply && this.children.length > 1) {
1078
- const styleElement = this.querySelector(
1107
+ if (stylesToApply) {
1108
+ let styleElement = this.querySelector(
1079
1109
  `style[data-wsx-light-component="${styleName}"]`
1080
1110
  );
1081
- if (styleElement && styleElement !== this.firstChild) {
1111
+ if (!styleElement) {
1112
+ styleElement = document.createElement("style");
1113
+ styleElement.setAttribute("data-wsx-light-component", styleName);
1114
+ styleElement.textContent = stylesToApply;
1115
+ this.insertBefore(styleElement, this.firstChild);
1116
+ } else if (styleElement.textContent !== stylesToApply) {
1117
+ styleElement.textContent = stylesToApply;
1118
+ } else if (styleElement !== this.firstChild) {
1082
1119
  this.insertBefore(styleElement, this.firstChild);
1083
1120
  }
1084
1121
  }
@@ -101,6 +101,7 @@ var _RenderContext = class _RenderContext {
101
101
  * @param fn The function to execute (usually the render method).
102
102
  */
103
103
  static runInContext(component, fn) {
104
+ resetCounterForNewRenderCycle(component);
104
105
  const prev = _RenderContext.current;
105
106
  _RenderContext.current = component;
106
107
  try {
@@ -126,21 +127,20 @@ _RenderContext.current = null;
126
127
  var RenderContext = _RenderContext;
127
128
 
128
129
  // src/utils/cache-key.ts
129
- var POSITION_ID_KEY = "__wsxPositionId";
130
130
  var INDEX_KEY = "__wsxIndex";
131
131
  var componentElementCounters = /* @__PURE__ */ new WeakMap();
132
132
  var componentIdCache = /* @__PURE__ */ new WeakMap();
133
133
  function generateCacheKey(tag, props, componentId, component) {
134
- const positionId = props?.[POSITION_ID_KEY];
135
134
  const userKey = props?.key;
136
135
  const index = props?.[INDEX_KEY];
136
+ const positionId = props?.__wsxPositionId;
137
137
  if (userKey !== void 0 && userKey !== null) {
138
138
  return `${componentId}:${tag}:key-${String(userKey)}`;
139
139
  }
140
140
  if (index !== void 0 && index !== null) {
141
141
  return `${componentId}:${tag}:idx-${String(index)}`;
142
142
  }
143
- if (positionId !== void 0 && positionId !== null && positionId !== "no-id") {
143
+ if (positionId !== void 0 && positionId !== null) {
144
144
  return `${componentId}:${tag}:${String(positionId)}`;
145
145
  }
146
146
  if (component) {
@@ -151,6 +151,9 @@ function generateCacheKey(tag, props, componentId, component) {
151
151
  }
152
152
  return `${componentId}:${tag}:fallback-${Date.now()}-${Math.random()}`;
153
153
  }
154
+ function resetCounterForNewRenderCycle(component) {
155
+ componentElementCounters.set(component, 0);
156
+ }
154
157
  function getComponentId() {
155
158
  const component = RenderContext.getCurrentComponent();
156
159
  if (component) {
@@ -568,7 +571,9 @@ function applySingleProp(element, key, value, tag, isSVG) {
568
571
  }
569
572
  if (key.startsWith("on") && typeof value === "function") {
570
573
  const eventName = key.slice(2).toLowerCase();
574
+ const listenerKey = `__wsxListener_${eventName}`;
571
575
  element.addEventListener(eventName, value);
576
+ element[listenerKey] = value;
572
577
  return;
573
578
  }
574
579
  if (typeof value === "boolean") {
@@ -663,7 +668,7 @@ function findElementNode(oldChild, parent) {
663
668
  function findTextNode(parent, domIndex) {
664
669
  while (domIndex.value < parent.childNodes.length) {
665
670
  const node = parent.childNodes[domIndex.value];
666
- if (node.nodeType === Node.TEXT_NODE) {
671
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent) {
667
672
  const textNode = node;
668
673
  domIndex.value++;
669
674
  return textNode;
@@ -677,13 +682,23 @@ function updateOrCreateTextNode(parent, oldNode, newText) {
677
682
  if (oldNode.textContent !== newText) {
678
683
  oldNode.textContent = newText;
679
684
  }
685
+ return oldNode;
680
686
  } else {
687
+ if (!oldNode) {
688
+ for (let i = 0; i < parent.childNodes.length; i++) {
689
+ const node = parent.childNodes[i];
690
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === parent && node.textContent === newText) {
691
+ return node;
692
+ }
693
+ }
694
+ }
681
695
  const newTextNode = document.createTextNode(newText);
682
696
  if (oldNode && !shouldPreserveElement(oldNode)) {
683
697
  parent.replaceChild(newTextNode, oldNode);
684
698
  } else {
685
699
  parent.insertBefore(newTextNode, oldNode || null);
686
700
  }
701
+ return newTextNode;
687
702
  }
688
703
  }
689
704
  function removeNodeIfNotPreserved(parent, node) {
@@ -692,29 +707,66 @@ function removeNodeIfNotPreserved(parent, node) {
692
707
  }
693
708
  }
694
709
  function replaceOrInsertElement(parent, newChild, oldNode) {
710
+ const targetNextSibling = oldNode && shouldPreserveElement(oldNode) ? oldNode : oldNode?.nextSibling || null;
711
+ replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling);
712
+ }
713
+ function replaceOrInsertElementAtPosition(parent, newChild, oldNode, targetNextSibling) {
695
714
  if (newChild.parentNode && newChild.parentNode !== parent) {
696
715
  newChild.parentNode.removeChild(newChild);
697
716
  }
698
- if (oldNode && !shouldPreserveElement(oldNode)) {
717
+ const isInCorrectPosition = newChild.parentNode === parent && newChild.nextSibling === targetNextSibling;
718
+ if (isInCorrectPosition) {
719
+ return;
720
+ }
721
+ if (newChild.parentNode === parent) {
722
+ parent.insertBefore(newChild, targetNextSibling);
723
+ return;
724
+ }
725
+ if (oldNode && oldNode.parentNode === parent && !shouldPreserveElement(oldNode)) {
699
726
  if (oldNode !== newChild) {
700
727
  parent.replaceChild(newChild, oldNode);
701
728
  }
702
- } else if (newChild.parentNode !== parent) {
703
- parent.insertBefore(newChild, oldNode || null);
729
+ } else {
730
+ if (newChild.parentNode === parent) {
731
+ return;
732
+ }
733
+ const newChildCacheKey = getElementCacheKey(newChild);
734
+ if (!newChildCacheKey) {
735
+ const newChildContent = newChild.textContent || "";
736
+ const newChildTag = newChild.tagName.toLowerCase();
737
+ for (let i = 0; i < parent.childNodes.length; i++) {
738
+ const existingNode = parent.childNodes[i];
739
+ if (existingNode instanceof HTMLElement || existingNode instanceof SVGElement) {
740
+ const existingCacheKey = getElementCacheKey(existingNode);
741
+ if (!existingCacheKey && existingNode.tagName.toLowerCase() === newChildTag && existingNode.textContent === newChildContent && existingNode !== newChild) {
742
+ return;
743
+ }
744
+ }
745
+ }
746
+ }
747
+ parent.insertBefore(newChild, targetNextSibling);
704
748
  }
705
749
  }
706
- function appendNewChild(parent, child) {
750
+ function appendNewChild(parent, child, processedNodes) {
707
751
  if (child === null || child === void 0 || child === false) {
708
752
  return;
709
753
  }
710
754
  if (typeof child === "string" || typeof child === "number") {
711
- parent.appendChild(document.createTextNode(String(child)));
755
+ const newTextNode = document.createTextNode(String(child));
756
+ parent.appendChild(newTextNode);
757
+ if (processedNodes) {
758
+ processedNodes.add(newTextNode);
759
+ }
712
760
  } else if (child instanceof HTMLElement || child instanceof SVGElement) {
761
+ if (child.parentNode === parent) {
762
+ return;
763
+ }
713
764
  if (child.parentNode && child.parentNode !== parent) {
714
765
  child.parentNode.removeChild(child);
715
766
  }
716
- if (child.parentNode !== parent) {
717
- parent.appendChild(child);
767
+ parent.appendChild(child);
768
+ if (processedNodes) {
769
+ processedNodes.add(child);
718
770
  }
719
771
  } else if (child instanceof DocumentFragment) {
720
772
  parent.appendChild(child);
@@ -736,10 +788,22 @@ function buildNewChildrenMaps(flatNew) {
736
788
  }
737
789
  return { elementSet, cacheKeyMap };
738
790
  }
739
- function shouldRemoveNode(node, elementSet, cacheKeyMap) {
791
+ function shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes) {
740
792
  if (shouldPreserveElement(node)) {
741
793
  return false;
742
794
  }
795
+ if (node.nodeType === Node.TEXT_NODE && processedNodes && processedNodes.has(node)) {
796
+ return false;
797
+ }
798
+ if (node.nodeType === Node.TEXT_NODE && processedNodes) {
799
+ let parent = node.parentNode;
800
+ while (parent) {
801
+ if (processedNodes.has(parent) && parent.parentNode) {
802
+ return false;
803
+ }
804
+ parent = parent.parentNode;
805
+ }
806
+ }
743
807
  if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
744
808
  if (elementSet.has(node)) {
745
809
  return false;
@@ -768,24 +832,39 @@ function deduplicateCacheKeys(parent, cacheKeyMap) {
768
832
  if (child !== newChild) {
769
833
  parent.replaceChild(newChild, child);
770
834
  }
835
+ } else if (cacheKey && cacheKeyMap.has(cacheKey) && processedCacheKeys.has(cacheKey)) {
836
+ const newChild = cacheKeyMap.get(cacheKey);
837
+ if (child !== newChild) {
838
+ parent.removeChild(child);
839
+ }
771
840
  }
772
841
  }
773
842
  }
774
843
  }
775
- function collectNodesToRemove(parent, elementSet, cacheKeyMap) {
844
+ function collectNodesToRemove(parent, elementSet, cacheKeyMap, processedNodes) {
776
845
  const nodesToRemove = [];
777
846
  for (let i = 0; i < parent.childNodes.length; i++) {
778
847
  const node = parent.childNodes[i];
779
- if (shouldRemoveNode(node, elementSet, cacheKeyMap)) {
848
+ if (shouldRemoveNode(node, elementSet, cacheKeyMap, processedNodes)) {
780
849
  nodesToRemove.push(node);
781
850
  }
782
851
  }
783
852
  return nodesToRemove;
784
853
  }
785
- function removeNodes(parent, nodes) {
854
+ function removeNodes(parent, nodes, cacheManager) {
786
855
  for (let i = nodes.length - 1; i >= 0; i--) {
787
856
  const node = nodes[i];
788
857
  if (node.parentNode === parent) {
858
+ if (cacheManager && (node instanceof HTMLElement || node instanceof SVGElement)) {
859
+ const metadata = cacheManager.getMetadata(node);
860
+ const refCallback = metadata?.ref;
861
+ if (typeof refCallback === "function") {
862
+ try {
863
+ refCallback(null);
864
+ } catch {
865
+ }
866
+ }
867
+ }
789
868
  parent.removeChild(node);
790
869
  }
791
870
  }
@@ -805,6 +884,12 @@ function flattenChildrenSafe(children) {
805
884
  function removeProp(element, key, oldValue, tag) {
806
885
  const isSVG = shouldUseSVGNamespace(tag);
807
886
  if (key === "ref") {
887
+ if (typeof oldValue === "function") {
888
+ try {
889
+ oldValue(null);
890
+ } catch {
891
+ }
892
+ }
808
893
  return;
809
894
  }
810
895
  if (key === "className" || key === "class") {
@@ -820,6 +905,13 @@ function removeProp(element, key, oldValue, tag) {
820
905
  return;
821
906
  }
822
907
  if (key.startsWith("on") && typeof oldValue === "function") {
908
+ const eventName = key.slice(2).toLowerCase();
909
+ const listenerKey = `__wsxListener_${eventName}`;
910
+ const savedListener = element[listenerKey];
911
+ if (savedListener) {
912
+ element.removeEventListener(eventName, savedListener);
913
+ delete element[listenerKey];
914
+ }
823
915
  return;
824
916
  }
825
917
  if (key === "value") {
@@ -863,7 +955,13 @@ function applySingleProp2(element, key, value, tag, isSVG) {
863
955
  }
864
956
  if (key.startsWith("on") && typeof value === "function") {
865
957
  const eventName = key.slice(2).toLowerCase();
958
+ const listenerKey = `__wsxListener_${eventName}`;
959
+ const oldListener = element[listenerKey];
960
+ if (oldListener) {
961
+ element.removeEventListener(eventName, oldListener);
962
+ }
866
963
  element.addEventListener(eventName, value);
964
+ element[listenerKey] = value;
867
965
  return;
868
966
  }
869
967
  if (typeof value === "boolean") {
@@ -918,12 +1016,13 @@ function updateProps(element, oldProps, newProps, tag) {
918
1016
  applySingleProp2(element, key, newValue, tag, isSVG);
919
1017
  }
920
1018
  }
921
- function updateChildren(element, oldChildren, newChildren, cacheManager) {
1019
+ function updateChildren(element, oldChildren, newChildren, _cacheManager) {
922
1020
  const flatOld = flattenChildrenSafe(oldChildren);
923
1021
  const flatNew = flattenChildrenSafe(newChildren);
924
1022
  const preservedElements = collectPreservedElements(element);
925
1023
  const minLength = Math.min(flatOld.length, flatNew.length);
926
1024
  const domIndex = { value: 0 };
1025
+ const processedNodes = /* @__PURE__ */ new Set();
927
1026
  for (let i = 0; i < minLength; i++) {
928
1027
  const oldChild = flatOld[i];
929
1028
  const newChild = flatNew[i];
@@ -939,9 +1038,10 @@ function updateChildren(element, oldChildren, newChildren, cacheManager) {
939
1038
  } else if (typeof oldChild === "string" || typeof oldChild === "number") {
940
1039
  oldNode = findTextNode(element, domIndex);
941
1040
  if (!oldNode && element.childNodes.length > 0) {
1041
+ const oldText = String(oldChild);
942
1042
  for (let j = domIndex.value; j < element.childNodes.length; j++) {
943
1043
  const node = element.childNodes[j];
944
- if (node.nodeType === Node.TEXT_NODE) {
1044
+ if (node.nodeType === Node.TEXT_NODE && node.parentNode === element && node.textContent === oldText) {
945
1045
  oldNode = node;
946
1046
  domIndex.value = j + 1;
947
1047
  break;
@@ -955,7 +1055,14 @@ function updateChildren(element, oldChildren, newChildren, cacheManager) {
955
1055
  const newText = String(newChild);
956
1056
  const needsUpdate = oldText !== newText || oldNode && oldNode.nodeType === Node.TEXT_NODE && oldNode.textContent !== newText;
957
1057
  if (needsUpdate) {
958
- updateOrCreateTextNode(element, oldNode, newText);
1058
+ const updatedNode = updateOrCreateTextNode(element, oldNode, newText);
1059
+ if (updatedNode && !processedNodes.has(updatedNode)) {
1060
+ processedNodes.add(updatedNode);
1061
+ }
1062
+ } else {
1063
+ if (oldNode && oldNode.parentNode === element) {
1064
+ processedNodes.add(oldNode);
1065
+ }
959
1066
  }
960
1067
  } else {
961
1068
  removeNodeIfNotPreserved(element, oldNode);
@@ -969,30 +1076,48 @@ function updateChildren(element, oldChildren, newChildren, cacheManager) {
969
1076
  if (oldNode && shouldPreserveElement(oldNode)) {
970
1077
  continue;
971
1078
  }
972
- if (newChild === oldChild && (newChild instanceof HTMLElement || newChild instanceof SVGElement)) {
973
- if (cacheManager) {
974
- const childMetadata = cacheManager.getMetadata(newChild);
975
- if (childMetadata) {
976
- if (oldNode === newChild && newChild.parentNode === element) {
977
- continue;
1079
+ if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
1080
+ let targetNextSibling = null;
1081
+ let foundPreviousElement = false;
1082
+ for (let j = i - 1; j >= 0; j--) {
1083
+ const prevChild = flatNew[j];
1084
+ if (prevChild instanceof HTMLElement || prevChild instanceof SVGElement) {
1085
+ if (prevChild.parentNode === element) {
1086
+ targetNextSibling = prevChild.nextSibling;
1087
+ foundPreviousElement = true;
1088
+ break;
978
1089
  }
979
1090
  }
980
- } else {
981
- if (oldNode === newChild && newChild.parentNode === element) {
982
- continue;
983
- }
984
1091
  }
985
- }
986
- if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
987
- if (newChild.parentNode === element && oldNode === newChild) {
1092
+ if (!foundPreviousElement) {
1093
+ const firstChild = Array.from(element.childNodes).find(
1094
+ (node) => !shouldPreserveElement(node) && !processedNodes.has(node)
1095
+ );
1096
+ targetNextSibling = firstChild || null;
1097
+ }
1098
+ const isInCorrectPosition = newChild.parentNode === element && newChild.nextSibling === targetNextSibling;
1099
+ if (newChild === oldChild && isInCorrectPosition) {
1100
+ if (oldNode) processedNodes.add(oldNode);
1101
+ processedNodes.add(newChild);
988
1102
  continue;
989
1103
  }
990
- replaceOrInsertElement(element, newChild, oldNode);
1104
+ const referenceNode = oldNode && oldNode.parentNode === element ? oldNode : null;
1105
+ replaceOrInsertElementAtPosition(
1106
+ element,
1107
+ newChild,
1108
+ referenceNode,
1109
+ targetNextSibling
1110
+ );
1111
+ if (oldNode && oldNode !== newChild) {
1112
+ processedNodes.delete(oldNode);
1113
+ }
1114
+ processedNodes.add(newChild);
991
1115
  } else {
992
1116
  removeNodeIfNotPreserved(element, oldNode);
993
1117
  if (typeof newChild === "string" || typeof newChild === "number") {
994
1118
  const newTextNode = document.createTextNode(String(newChild));
995
1119
  element.insertBefore(newTextNode, oldNode?.nextSibling || null);
1120
+ processedNodes.add(newTextNode);
996
1121
  } else if (newChild instanceof DocumentFragment) {
997
1122
  element.insertBefore(newChild, oldNode?.nextSibling || null);
998
1123
  }
@@ -1000,12 +1125,12 @@ function updateChildren(element, oldChildren, newChildren, cacheManager) {
1000
1125
  }
1001
1126
  }
1002
1127
  for (let i = minLength; i < flatNew.length; i++) {
1003
- appendNewChild(element, flatNew[i]);
1128
+ appendNewChild(element, flatNew[i], processedNodes);
1004
1129
  }
1005
1130
  const { elementSet, cacheKeyMap } = buildNewChildrenMaps(flatNew);
1006
1131
  deduplicateCacheKeys(element, cacheKeyMap);
1007
- const nodesToRemove = collectNodesToRemove(element, elementSet, cacheKeyMap);
1008
- removeNodes(element, nodesToRemove);
1132
+ const nodesToRemove = collectNodesToRemove(element, elementSet, cacheKeyMap, processedNodes);
1133
+ removeNodes(element, nodesToRemove, _cacheManager);
1009
1134
  reinsertPreservedElements(element, preservedElements);
1010
1135
  }
1011
1136
  function updateElement(element, newProps, newChildren, tag, cacheManager) {
@@ -2,7 +2,7 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-ESZYREJK.mjs";
5
+ } from "./chunk-5Q2VEEUH.mjs";
6
6
  export {
7
7
  Fragment,
8
8
  jsx,