@wsxjs/wsx-core 0.0.22 → 0.0.23

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.js CHANGED
@@ -633,6 +633,185 @@ function createElementWithPropsAndChildren(tag, props, children) {
633
633
  return element;
634
634
  }
635
635
 
636
+ // src/utils/update-children-helpers.ts
637
+ function collectPreservedElements(element) {
638
+ const preserved = [];
639
+ for (let i = 0; i < element.childNodes.length; i++) {
640
+ const child = element.childNodes[i];
641
+ if (shouldPreserveElement(child)) {
642
+ preserved.push(child);
643
+ }
644
+ }
645
+ return preserved;
646
+ }
647
+ function findDOMNodeByReference(oldChild, parent) {
648
+ if (oldChild.parentNode === parent && !shouldPreserveElement(oldChild)) {
649
+ return oldChild;
650
+ }
651
+ return null;
652
+ }
653
+ function findDOMNodeByCacheKey(cacheKey, parent) {
654
+ for (let i = 0; i < parent.childNodes.length; i++) {
655
+ const child = parent.childNodes[i];
656
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
657
+ if (shouldPreserveElement(child)) continue;
658
+ if (getElementCacheKey(child) === cacheKey) {
659
+ return child;
660
+ }
661
+ }
662
+ }
663
+ return null;
664
+ }
665
+ function findElementNode(oldChild, parent) {
666
+ const byRef = findDOMNodeByReference(oldChild, parent);
667
+ if (byRef) return byRef;
668
+ const cacheKey = getElementCacheKey(oldChild);
669
+ if (cacheKey) {
670
+ return findDOMNodeByCacheKey(cacheKey, parent);
671
+ }
672
+ return null;
673
+ }
674
+ function findTextNode(parent, domIndex) {
675
+ while (domIndex.value < parent.childNodes.length) {
676
+ const node = parent.childNodes[domIndex.value];
677
+ if (node.nodeType === Node.TEXT_NODE) {
678
+ const textNode = node;
679
+ domIndex.value++;
680
+ return textNode;
681
+ }
682
+ domIndex.value++;
683
+ }
684
+ return null;
685
+ }
686
+ function updateOrCreateTextNode(parent, oldNode, newText) {
687
+ if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
688
+ if (oldNode.textContent !== newText) {
689
+ oldNode.textContent = newText;
690
+ }
691
+ } else {
692
+ const newTextNode = document.createTextNode(newText);
693
+ if (oldNode && !shouldPreserveElement(oldNode)) {
694
+ parent.replaceChild(newTextNode, oldNode);
695
+ } else {
696
+ parent.insertBefore(newTextNode, oldNode || null);
697
+ }
698
+ }
699
+ }
700
+ function removeNodeIfNotPreserved(parent, node) {
701
+ if (node && !shouldPreserveElement(node) && node.parentNode === parent) {
702
+ parent.removeChild(node);
703
+ }
704
+ }
705
+ function replaceOrInsertElement(parent, newChild, oldNode) {
706
+ if (newChild.parentNode && newChild.parentNode !== parent) {
707
+ newChild.parentNode.removeChild(newChild);
708
+ }
709
+ if (oldNode && !shouldPreserveElement(oldNode)) {
710
+ if (oldNode !== newChild) {
711
+ parent.replaceChild(newChild, oldNode);
712
+ }
713
+ } else if (newChild.parentNode !== parent) {
714
+ parent.insertBefore(newChild, oldNode || null);
715
+ }
716
+ }
717
+ function appendNewChild(parent, child) {
718
+ if (child === null || child === void 0 || child === false) {
719
+ return;
720
+ }
721
+ if (typeof child === "string" || typeof child === "number") {
722
+ parent.appendChild(document.createTextNode(String(child)));
723
+ } else if (child instanceof HTMLElement || child instanceof SVGElement) {
724
+ if (child.parentNode && child.parentNode !== parent) {
725
+ child.parentNode.removeChild(child);
726
+ }
727
+ if (child.parentNode !== parent) {
728
+ parent.appendChild(child);
729
+ }
730
+ } else if (child instanceof DocumentFragment) {
731
+ parent.appendChild(child);
732
+ }
733
+ }
734
+ function buildNewChildrenMaps(flatNew) {
735
+ const elementSet = /* @__PURE__ */ new Set();
736
+ const cacheKeyMap = /* @__PURE__ */ new Map();
737
+ for (const child of flatNew) {
738
+ if (child instanceof HTMLElement || child instanceof SVGElement || child instanceof DocumentFragment) {
739
+ elementSet.add(child);
740
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
741
+ const cacheKey = getElementCacheKey(child);
742
+ if (cacheKey) {
743
+ cacheKeyMap.set(cacheKey, child);
744
+ }
745
+ }
746
+ }
747
+ }
748
+ return { elementSet, cacheKeyMap };
749
+ }
750
+ function shouldRemoveNode(node, elementSet, cacheKeyMap) {
751
+ if (shouldPreserveElement(node)) {
752
+ return false;
753
+ }
754
+ if (node instanceof HTMLElement || node instanceof SVGElement || node instanceof DocumentFragment) {
755
+ if (elementSet.has(node)) {
756
+ return false;
757
+ }
758
+ if (node instanceof HTMLElement || node instanceof SVGElement) {
759
+ const cacheKey = getElementCacheKey(node);
760
+ if (cacheKey && cacheKeyMap.has(cacheKey)) {
761
+ return false;
762
+ }
763
+ }
764
+ }
765
+ return true;
766
+ }
767
+ function deduplicateCacheKeys(parent, cacheKeyMap) {
768
+ const processedCacheKeys = /* @__PURE__ */ new Set();
769
+ for (let i = parent.childNodes.length - 1; i >= 0; i--) {
770
+ const child = parent.childNodes[i];
771
+ if (child instanceof HTMLElement || child instanceof SVGElement) {
772
+ if (shouldPreserveElement(child)) {
773
+ continue;
774
+ }
775
+ const cacheKey = getElementCacheKey(child);
776
+ if (cacheKey && cacheKeyMap.has(cacheKey) && !processedCacheKeys.has(cacheKey)) {
777
+ processedCacheKeys.add(cacheKey);
778
+ const newChild = cacheKeyMap.get(cacheKey);
779
+ if (child !== newChild) {
780
+ parent.replaceChild(newChild, child);
781
+ }
782
+ }
783
+ }
784
+ }
785
+ }
786
+ function collectNodesToRemove(parent, elementSet, cacheKeyMap) {
787
+ const nodesToRemove = [];
788
+ for (let i = 0; i < parent.childNodes.length; i++) {
789
+ const node = parent.childNodes[i];
790
+ if (shouldRemoveNode(node, elementSet, cacheKeyMap)) {
791
+ nodesToRemove.push(node);
792
+ }
793
+ }
794
+ return nodesToRemove;
795
+ }
796
+ function removeNodes(parent, nodes) {
797
+ for (let i = nodes.length - 1; i >= 0; i--) {
798
+ const node = nodes[i];
799
+ if (node.parentNode === parent) {
800
+ parent.removeChild(node);
801
+ }
802
+ }
803
+ }
804
+ function reinsertPreservedElements(parent, preservedElements) {
805
+ for (const element of preservedElements) {
806
+ if (element.parentNode !== parent) {
807
+ parent.appendChild(element);
808
+ }
809
+ }
810
+ }
811
+ function flattenChildrenSafe(children) {
812
+ return flattenChildren(children);
813
+ }
814
+
636
815
  // src/utils/element-update.ts
637
816
  function removeProp(element, key, oldValue, tag) {
638
817
  const isSVG = shouldUseSVGNamespace(tag);
@@ -750,49 +929,34 @@ function updateProps(element, oldProps, newProps, tag) {
750
929
  applySingleProp2(element, key, newValue, tag, isSVG);
751
930
  }
752
931
  }
753
- function updateChildren(element, oldChildren, newChildren) {
754
- const flatOld = flattenChildren(oldChildren);
755
- const flatNew = flattenChildren(newChildren);
932
+ function updateChildren(element, oldChildren, newChildren, cacheManager) {
933
+ const flatOld = flattenChildrenSafe(oldChildren);
934
+ const flatNew = flattenChildrenSafe(newChildren);
935
+ const preservedElements = collectPreservedElements(element);
756
936
  const minLength = Math.min(flatOld.length, flatNew.length);
757
- let domIndex = 0;
937
+ const domIndex = { value: 0 };
758
938
  for (let i = 0; i < minLength; i++) {
759
939
  const oldChild = flatOld[i];
760
940
  const newChild = flatNew[i];
761
941
  let oldNode = null;
762
942
  if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
763
- if (oldChild.parentNode === element) {
764
- if (!shouldPreserveElement(oldChild)) {
765
- oldNode = oldChild;
766
- }
767
- } else {
768
- const oldCacheKey = getElementCacheKey(oldChild);
769
- if (oldCacheKey) {
770
- for (let j = 0; j < element.childNodes.length; j++) {
771
- const domChild = element.childNodes[j];
772
- if (domChild instanceof HTMLElement || domChild instanceof SVGElement) {
773
- if (shouldPreserveElement(domChild)) {
774
- continue;
775
- }
776
- const domCacheKey = getElementCacheKey(domChild);
777
- if (domCacheKey === oldCacheKey) {
778
- oldNode = domChild;
779
- break;
780
- }
781
- }
782
- }
943
+ oldNode = findElementNode(oldChild, element);
944
+ if (oldNode && oldNode.parentNode === element) {
945
+ const nodeIndex = Array.from(element.childNodes).indexOf(oldNode);
946
+ if (nodeIndex !== -1 && nodeIndex >= domIndex.value) {
947
+ domIndex.value = nodeIndex + 1;
783
948
  }
784
949
  }
785
950
  } else if (typeof oldChild === "string" || typeof oldChild === "number") {
786
- while (domIndex < element.childNodes.length) {
787
- const node = element.childNodes[domIndex];
788
- if (node.nodeType === Node.TEXT_NODE) {
789
- oldNode = node;
790
- domIndex++;
791
- break;
792
- } else if (node.nodeType === Node.ELEMENT_NODE) {
793
- domIndex++;
794
- } else {
795
- domIndex++;
951
+ oldNode = findTextNode(element, domIndex);
952
+ if (!oldNode && element.childNodes.length > 0) {
953
+ for (let j = domIndex.value; j < element.childNodes.length; j++) {
954
+ const node = element.childNodes[j];
955
+ if (node.nodeType === Node.TEXT_NODE) {
956
+ oldNode = node;
957
+ domIndex.value = j + 1;
958
+ break;
959
+ }
796
960
  }
797
961
  }
798
962
  }
@@ -801,27 +965,13 @@ function updateChildren(element, oldChildren, newChildren) {
801
965
  const oldText = String(oldChild);
802
966
  const newText = String(newChild);
803
967
  const needsUpdate = oldText !== newText || oldNode && oldNode.nodeType === Node.TEXT_NODE && oldNode.textContent !== newText;
804
- if (!needsUpdate) {
805
- continue;
806
- }
807
- if (oldNode && oldNode.nodeType === Node.TEXT_NODE) {
808
- oldNode.textContent = newText;
809
- } else {
810
- const newTextNode = document.createTextNode(newText);
811
- if (oldNode && !shouldPreserveElement(oldNode)) {
812
- element.replaceChild(newTextNode, oldNode);
813
- } else {
814
- element.insertBefore(newTextNode, oldNode || null);
815
- }
968
+ if (needsUpdate) {
969
+ updateOrCreateTextNode(element, oldNode, newText);
816
970
  }
817
971
  } else {
818
- if (oldNode && !shouldPreserveElement(oldNode)) {
819
- element.removeChild(oldNode);
820
- }
972
+ removeNodeIfNotPreserved(element, oldNode);
821
973
  if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
822
- if (newChild.parentNode !== element) {
823
- element.insertBefore(newChild, oldNode || null);
824
- }
974
+ replaceOrInsertElement(element, newChild, oldNode);
825
975
  } else if (newChild instanceof DocumentFragment) {
826
976
  element.insertBefore(newChild, oldNode || null);
827
977
  }
@@ -830,51 +980,27 @@ function updateChildren(element, oldChildren, newChildren) {
830
980
  if (oldNode && shouldPreserveElement(oldNode)) {
831
981
  continue;
832
982
  }
833
- if (newChild === oldChild) {
834
- continue;
835
- } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
836
- const oldCacheKey = oldNode && (oldNode instanceof HTMLElement || oldNode instanceof SVGElement) ? getElementCacheKey(oldNode) : null;
837
- const newCacheKey = getElementCacheKey(newChild);
838
- const hasSameCacheKey = oldCacheKey && newCacheKey && oldCacheKey === newCacheKey;
839
- if (oldNode) {
840
- if (!shouldPreserveElement(oldNode)) {
841
- if (oldNode !== newChild) {
842
- if (newChild.parentNode === element) {
843
- if (hasSameCacheKey) {
844
- if (newChild !== oldNode) {
845
- element.replaceChild(newChild, oldNode);
846
- }
847
- } else {
848
- element.removeChild(newChild);
849
- element.replaceChild(newChild, oldNode);
850
- }
851
- } else if (newChild.parentNode) {
852
- newChild.parentNode.removeChild(newChild);
853
- element.replaceChild(newChild, oldNode);
854
- } else {
855
- element.replaceChild(newChild, oldNode);
856
- }
857
- }
858
- } else {
859
- if (newChild.parentNode !== element) {
860
- if (newChild.parentNode) {
861
- newChild.parentNode.removeChild(newChild);
862
- }
863
- element.insertBefore(newChild, oldNode.nextSibling);
983
+ if (newChild === oldChild && (newChild instanceof HTMLElement || newChild instanceof SVGElement)) {
984
+ if (cacheManager) {
985
+ const childMetadata = cacheManager.getMetadata(newChild);
986
+ if (childMetadata) {
987
+ if (oldNode === newChild && newChild.parentNode === element) {
988
+ continue;
864
989
  }
865
990
  }
866
991
  } else {
867
- if (newChild.parentNode !== element) {
868
- if (newChild.parentNode) {
869
- newChild.parentNode.removeChild(newChild);
870
- }
871
- element.appendChild(newChild);
992
+ if (oldNode === newChild && newChild.parentNode === element) {
993
+ continue;
872
994
  }
873
995
  }
874
- } else {
875
- if (oldNode && !shouldPreserveElement(oldNode)) {
876
- element.removeChild(oldNode);
996
+ }
997
+ if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
998
+ if (newChild.parentNode === element && oldNode === newChild) {
999
+ continue;
877
1000
  }
1001
+ replaceOrInsertElement(element, newChild, oldNode);
1002
+ } else {
1003
+ removeNodeIfNotPreserved(element, oldNode);
878
1004
  if (typeof newChild === "string" || typeof newChild === "number") {
879
1005
  const newTextNode = document.createTextNode(String(newChild));
880
1006
  element.insertBefore(newTextNode, oldNode?.nextSibling || null);
@@ -885,98 +1011,13 @@ function updateChildren(element, oldChildren, newChildren) {
885
1011
  }
886
1012
  }
887
1013
  for (let i = minLength; i < flatNew.length; i++) {
888
- const newChild = flatNew[i];
889
- if (newChild === null || newChild === void 0 || newChild === false) {
890
- continue;
891
- }
892
- if (typeof newChild === "string" || typeof newChild === "number") {
893
- element.appendChild(document.createTextNode(String(newChild)));
894
- } else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
895
- if (newChild.parentNode === element) {
896
- const currentIndex = Array.from(element.childNodes).indexOf(newChild);
897
- const expectedIndex = element.childNodes.length - 1;
898
- if (currentIndex !== expectedIndex) {
899
- element.removeChild(newChild);
900
- element.appendChild(newChild);
901
- }
902
- continue;
903
- } else if (newChild.parentNode) {
904
- newChild.parentNode.removeChild(newChild);
905
- }
906
- element.appendChild(newChild);
907
- } else if (newChild instanceof DocumentFragment) {
908
- element.appendChild(newChild);
909
- }
910
- }
911
- const nodesToRemove = [];
912
- const newChildSet = /* @__PURE__ */ new Set();
913
- const newChildCacheKeyMap = /* @__PURE__ */ new Map();
914
- for (const child of flatNew) {
915
- if (child instanceof HTMLElement || child instanceof SVGElement || child instanceof DocumentFragment) {
916
- newChildSet.add(child);
917
- if (child instanceof HTMLElement || child instanceof SVGElement) {
918
- const cacheKey = getElementCacheKey(child);
919
- if (cacheKey) {
920
- newChildCacheKeyMap.set(cacheKey, child);
921
- }
922
- }
923
- }
924
- }
925
- const processedCacheKeys = /* @__PURE__ */ new Set();
926
- const newChildToIndexMap = /* @__PURE__ */ new Map();
927
- for (let i = 0; i < flatNew.length; i++) {
928
- const child = flatNew[i];
929
- if (child instanceof HTMLElement || child instanceof SVGElement) {
930
- newChildToIndexMap.set(child, i);
931
- }
932
- }
933
- for (let i = element.childNodes.length - 1; i >= 0; i--) {
934
- const child = element.childNodes[i];
935
- if (child instanceof HTMLElement || child instanceof SVGElement) {
936
- if (shouldPreserveElement(child)) {
937
- continue;
938
- }
939
- const cacheKey = getElementCacheKey(child);
940
- if (cacheKey && newChildCacheKeyMap.has(cacheKey) && !processedCacheKeys.has(cacheKey)) {
941
- processedCacheKeys.add(cacheKey);
942
- const newChild = newChildCacheKeyMap.get(cacheKey);
943
- if (child !== newChild) {
944
- if (newChild.parentNode === element) {
945
- element.replaceChild(newChild, child);
946
- } else {
947
- element.replaceChild(newChild, child);
948
- }
949
- } else {
950
- }
951
- }
952
- }
953
- }
954
- for (let i = 0; i < element.childNodes.length; i++) {
955
- const child = element.childNodes[i];
956
- if (shouldPreserveElement(child)) {
957
- continue;
958
- }
959
- if (child instanceof HTMLElement || child instanceof SVGElement) {
960
- if (newChildSet.has(child)) {
961
- continue;
962
- }
963
- const cacheKey = getElementCacheKey(child);
964
- if (cacheKey && newChildCacheKeyMap.has(cacheKey)) {
965
- continue;
966
- }
967
- } else if (child instanceof DocumentFragment) {
968
- if (newChildSet.has(child)) {
969
- continue;
970
- }
971
- }
972
- nodesToRemove.push(child);
973
- }
974
- for (let i = nodesToRemove.length - 1; i >= 0; i--) {
975
- const node = nodesToRemove[i];
976
- if (node.parentNode === element) {
977
- element.removeChild(node);
978
- }
1014
+ appendNewChild(element, flatNew[i]);
979
1015
  }
1016
+ const { elementSet, cacheKeyMap } = buildNewChildrenMaps(flatNew);
1017
+ deduplicateCacheKeys(element, cacheKeyMap);
1018
+ const nodesToRemove = collectNodesToRemove(element, elementSet, cacheKeyMap);
1019
+ removeNodes(element, nodesToRemove);
1020
+ reinsertPreservedElements(element, preservedElements);
980
1021
  }
981
1022
  function updateElement(element, newProps, newChildren, tag, cacheManager) {
982
1023
  const oldMetadata = cacheManager.getMetadata(element);
@@ -987,7 +1028,7 @@ function updateElement(element, newProps, newChildren, tag, cacheManager) {
987
1028
  children: newChildren
988
1029
  });
989
1030
  updateProps(element, oldProps, newProps, tag);
990
- updateChildren(element, oldChildren, newChildren);
1031
+ updateChildren(element, oldChildren, newChildren, cacheManager);
991
1032
  }
992
1033
 
993
1034
  // src/jsx-factory.ts
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createLogger,
5
5
  h,
6
6
  shouldPreserveElement
7
- } from "./chunk-OXFZ575O.mjs";
7
+ } from "./chunk-ESZYREJK.mjs";
8
8
 
9
9
  // src/styles/style-manager.ts
10
10
  var StyleManager = class {