@wsxjs/wsx-core 0.0.30 → 0.1.0

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,49 +4,10 @@ import {
4
4
  createLogger,
5
5
  h,
6
6
  parseHTMLToNodes,
7
- reconcileElement,
8
- shouldPreserveElement
9
- } from "./chunk-2ER76KOQ.mjs";
10
-
11
- // src/styles/style-manager.ts
12
- var StyleManager = class {
13
- /**
14
- * Create or get a cached CSSStyleSheet for a component
15
- */
16
- static getStyleSheet(componentName, cssText) {
17
- if (this.styleSheets.has(componentName)) {
18
- return this.styleSheets.get(componentName);
19
- }
20
- if ("adoptedStyleSheets" in Document.prototype && "CSSStyleSheet" in window) {
21
- const styleSheet = new CSSStyleSheet();
22
- styleSheet.replaceSync(cssText);
23
- this.styleSheets.set(componentName, styleSheet);
24
- return styleSheet;
25
- } else {
26
- throw new Error("Constructable StyleSheets not supported. Use fallback method.");
27
- }
28
- }
29
- /**
30
- * Apply styles to a shadow root using constructable stylesheets
31
- */
32
- static applyStyles(shadowRoot, componentName, cssText) {
33
- try {
34
- const styleSheet = this.getStyleSheet(componentName, cssText);
35
- shadowRoot.adoptedStyleSheets = [styleSheet];
36
- } catch {
37
- this.applyStylesFallback(shadowRoot, cssText);
38
- }
39
- }
40
- /**
41
- * Fallback method for browsers that don't support constructable stylesheets
42
- */
43
- static applyStylesFallback(shadowRoot, cssText) {
44
- const style = document.createElement("style");
45
- style.textContent = cssText;
46
- shadowRoot.appendChild(style);
47
- }
48
- };
49
- StyleManager.styleSheets = /* @__PURE__ */ new Map();
7
+ shouldPreserveElement,
8
+ updateChildren,
9
+ updateProps
10
+ } from "./chunk-PNIWQQN6.mjs";
50
11
 
51
12
  // src/utils/reactive.ts
52
13
  import { createLogger as createLogger2 } from "@wsxjs/wsx-logger";
@@ -383,21 +344,6 @@ var BaseComponent = class extends HTMLElement {
383
344
  * @internal
384
345
  */
385
346
  this._domCache = new DOMCacheManager();
386
- /**
387
- * 当前捕获的焦点状态(用于在 render 时使用捕获的值)
388
- * @internal - 由 rerender() 方法管理
389
- */
390
- this._pendingFocusState = null;
391
- /**
392
- * 防抖定时器,用于延迟重渲染(当用户正在输入时)
393
- * @internal
394
- */
395
- this._rerenderDebounceTimer = null;
396
- /**
397
- * 待处理的重渲染标志(当用户正在输入时,标记需要重渲染但延迟执行)
398
- * @internal
399
- */
400
- this._pendingRerender = false;
401
347
  /**
402
348
  * 正在渲染标志(防止在 _rerender() 执行期间再次触发 scheduleRerender())
403
349
  * @internal
@@ -409,29 +355,6 @@ var BaseComponent = class extends HTMLElement {
409
355
  * @internal
410
356
  */
411
357
  this._hasScheduledRender = false;
412
- /**
413
- * 处理 blur 事件,在用户停止输入时执行待处理的重渲染
414
- * @internal
415
- */
416
- this.handleGlobalBlur = (event) => {
417
- const root = this.getActiveRoot();
418
- const target = event.target;
419
- if (target && root.contains(target)) {
420
- if (this._pendingRerender && this.connected) {
421
- if (this._rerenderDebounceTimer !== null) {
422
- clearTimeout(this._rerenderDebounceTimer);
423
- this._rerenderDebounceTimer = null;
424
- }
425
- requestAnimationFrame(() => {
426
- if (this._pendingRerender && this.connected && !this._isRendering) {
427
- this._pendingRerender = false;
428
- this._isRendering = true;
429
- this._rerender();
430
- }
431
- });
432
- }
433
- }
434
- };
435
358
  this._isDebugEnabled = config.debug ?? false;
436
359
  const host = this;
437
360
  const originalStyles = config.styles;
@@ -506,10 +429,6 @@ var BaseComponent = class extends HTMLElement {
506
429
  */
507
430
  scheduleRerender() {
508
431
  if (!this.connected) {
509
- if (this._rerenderDebounceTimer !== null) {
510
- clearTimeout(this._rerenderDebounceTimer);
511
- this._rerenderDebounceTimer = null;
512
- }
513
432
  return;
514
433
  }
515
434
  if (this._isRendering) {
@@ -518,31 +437,6 @@ var BaseComponent = class extends HTMLElement {
518
437
  if (this._hasScheduledRender) {
519
438
  return;
520
439
  }
521
- const root = this.getActiveRoot();
522
- let activeElement = null;
523
- if (root instanceof ShadowRoot) {
524
- activeElement = root.activeElement;
525
- } else {
526
- const docActiveElement = document.activeElement;
527
- if (docActiveElement && root.contains(docActiveElement)) {
528
- activeElement = docActiveElement;
529
- }
530
- }
531
- if (activeElement) {
532
- const isInputElement = activeElement instanceof HTMLInputElement && activeElement.type !== "radio" && activeElement.type !== "checkbox" || activeElement instanceof HTMLTextAreaElement || activeElement instanceof HTMLSelectElement || activeElement.hasAttribute("contenteditable");
533
- const forceRender = activeElement.hasAttribute("data-wsx-force-render");
534
- if (isInputElement && !forceRender) {
535
- this._pendingRerender = true;
536
- if (this._rerenderDebounceTimer !== null) {
537
- clearTimeout(this._rerenderDebounceTimer);
538
- this._rerenderDebounceTimer = null;
539
- }
540
- return;
541
- }
542
- }
543
- if (this._pendingRerender) {
544
- this._pendingRerender = false;
545
- }
546
440
  this._hasScheduledRender = true;
547
441
  requestAnimationFrame(() => {
548
442
  this._hasScheduledRender = false;
@@ -571,21 +465,12 @@ var BaseComponent = class extends HTMLElement {
571
465
  * @internal
572
466
  */
573
467
  cleanup() {
574
- if (this._rerenderDebounceTimer !== null) {
575
- clearTimeout(this._rerenderDebounceTimer);
576
- this._rerenderDebounceTimer = null;
577
- }
578
- const root = this.getActiveRoot();
579
- root.removeEventListener("blur", this.handleGlobalBlur, true);
580
- this._pendingRerender = false;
581
468
  }
582
469
  /**
583
470
  * 初始化事件监听器(在组件连接时调用)
584
471
  * @internal
585
472
  */
586
473
  initializeEventListeners() {
587
- const root = this.getActiveRoot();
588
- root.addEventListener("blur", this.handleGlobalBlur, true);
589
474
  }
590
475
  /**
591
476
  * 获取配置值
@@ -658,119 +543,47 @@ var BaseComponent = class extends HTMLElement {
658
543
  }
659
544
  return this;
660
545
  }
546
+ };
547
+
548
+ // src/styles/style-manager.ts
549
+ var StyleManager = class {
661
550
  /**
662
- * 捕获当前焦点状态(在重渲染之前调用)
663
- * @returns 焦点状态,如果没有焦点元素则返回 null
551
+ * Create or get a cached CSSStyleSheet for a component
664
552
  */
665
- captureFocusState() {
666
- const root = this.getActiveRoot();
667
- let activeElement = null;
668
- if (root instanceof ShadowRoot) {
669
- activeElement = root.activeElement;
670
- } else {
671
- const docActiveElement = document.activeElement;
672
- if (docActiveElement && root.contains(docActiveElement)) {
673
- activeElement = docActiveElement;
674
- }
675
- }
676
- if (!activeElement || !(activeElement instanceof HTMLElement)) {
677
- return null;
678
- }
679
- const key = activeElement.getAttribute("data-wsx-key");
680
- if (!key) {
681
- return null;
553
+ static getStyleSheet(componentName, cssText) {
554
+ if (this.styleSheets.has(componentName)) {
555
+ return this.styleSheets.get(componentName);
682
556
  }
683
- const tagName = activeElement.tagName.toLowerCase();
684
- const state2 = {
685
- key,
686
- elementType: tagName
687
- };
688
- if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) {
689
- state2.value = activeElement.value;
690
- state2.selectionStart = activeElement.selectionStart ?? void 0;
691
- state2.selectionEnd = activeElement.selectionEnd ?? void 0;
692
- if (activeElement instanceof HTMLTextAreaElement) {
693
- state2.scrollTop = activeElement.scrollTop;
694
- }
695
- } else if (activeElement instanceof HTMLSelectElement) {
696
- state2.elementType = "select";
697
- state2.selectedIndex = activeElement.selectedIndex;
698
- } else if (activeElement.hasAttribute("contenteditable")) {
699
- state2.elementType = "contenteditable";
700
- const selection = window.getSelection();
701
- if (selection && selection.rangeCount > 0) {
702
- const range = selection.getRangeAt(0);
703
- state2.selectionStart = range.startOffset;
704
- state2.selectionEnd = range.endOffset;
705
- }
557
+ if ("adoptedStyleSheets" in Document.prototype && "CSSStyleSheet" in window) {
558
+ const styleSheet = new CSSStyleSheet();
559
+ styleSheet.replaceSync(cssText);
560
+ this.styleSheets.set(componentName, styleSheet);
561
+ return styleSheet;
562
+ } else {
563
+ throw new Error("Constructable StyleSheets not supported. Use fallback method.");
706
564
  }
707
- return state2;
708
565
  }
709
566
  /**
710
- * 恢复焦点状态(在重渲染之后调用)
711
- * @param state - 之前捕获的焦点状态
567
+ * Apply styles to a shadow root using constructable stylesheets
712
568
  */
713
- restoreFocusState(state2) {
714
- if (!state2 || !state2.key) {
715
- return;
716
- }
717
- const root = this.getActiveRoot();
718
- const target = root.querySelector(`[data-wsx-key="${state2.key}"]`);
719
- if (!target) {
720
- return;
721
- }
722
- if (state2.value !== void 0) {
723
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
724
- target.value = state2.value;
725
- }
726
- }
727
- if (state2.selectedIndex !== void 0 && target instanceof HTMLSelectElement) {
728
- target.selectedIndex = state2.selectedIndex;
569
+ static applyStyles(shadowRoot, componentName, cssText) {
570
+ try {
571
+ const styleSheet = this.getStyleSheet(componentName, cssText);
572
+ shadowRoot.adoptedStyleSheets = [styleSheet];
573
+ } catch {
574
+ this.applyStylesFallback(shadowRoot, cssText);
729
575
  }
730
- requestAnimationFrame(() => {
731
- const currentTarget = root.querySelector(
732
- `[data-wsx-key="${state2.key}"]`
733
- );
734
- if (!currentTarget) {
735
- return;
736
- }
737
- if (state2.value !== void 0) {
738
- if (currentTarget instanceof HTMLInputElement || currentTarget instanceof HTMLTextAreaElement) {
739
- if (currentTarget.value !== state2.value) {
740
- currentTarget.value = state2.value;
741
- }
742
- }
743
- }
744
- currentTarget.focus({ preventScroll: true });
745
- if (state2.selectionStart !== void 0) {
746
- if (currentTarget instanceof HTMLInputElement || currentTarget instanceof HTMLTextAreaElement) {
747
- const start = state2.selectionStart;
748
- const end = state2.selectionEnd ?? start;
749
- currentTarget.setSelectionRange(start, end);
750
- if (state2.scrollTop !== void 0 && currentTarget instanceof HTMLTextAreaElement) {
751
- currentTarget.scrollTop = state2.scrollTop;
752
- }
753
- } else if (currentTarget.hasAttribute("contenteditable")) {
754
- const selection = window.getSelection();
755
- if (selection) {
756
- const range = document.createRange();
757
- const textNode = currentTarget.childNodes[0];
758
- if (textNode && textNode.nodeType === Node.TEXT_NODE) {
759
- const maxPos = Math.min(
760
- state2.selectionStart,
761
- textNode.textContent?.length || 0
762
- );
763
- range.setStart(textNode, maxPos);
764
- range.setEnd(textNode, state2.selectionEnd ?? maxPos);
765
- selection.removeAllRanges();
766
- selection.addRange(range);
767
- }
768
- }
769
- }
770
- }
771
- });
576
+ }
577
+ /**
578
+ * Fallback method for browsers that don't support constructable stylesheets
579
+ */
580
+ static applyStylesFallback(shadowRoot, cssText) {
581
+ const style = document.createElement("style");
582
+ style.textContent = cssText;
583
+ shadowRoot.appendChild(style);
772
584
  }
773
585
  };
586
+ StyleManager.styleSheets = /* @__PURE__ */ new Map();
774
587
 
775
588
  // src/web-component.ts
776
589
  import { createLogger as createLogger3 } from "@wsxjs/wsx-logger";
@@ -855,8 +668,11 @@ var WebComponent = class extends BaseComponent {
855
668
  }
856
669
  /**
857
670
  * 内部重渲染实现
858
- * 包含从 rerender() 方法迁移的实际渲染逻辑
859
- * WebComponent 使用 Shadow DOM,不存在 JSX children 问题
671
+ * 使用真实 DOM 协调 (RFC 0058) 替代全量替换
672
+ *
673
+ * 策略:
674
+ * 1. 尝试原地更新 (Reconciliation)
675
+ * 2. 只有在结构完全不匹配时才回退到替更新
860
676
  *
861
677
  * @override
862
678
  */
@@ -865,64 +681,67 @@ var WebComponent = class extends BaseComponent {
865
681
  this._isRendering = false;
866
682
  return;
867
683
  }
868
- const focusState = this.captureFocusState();
869
- this._pendingFocusState = focusState;
870
- const adoptedStyleSheets = this.shadowRoot.adoptedStyleSheets || [];
871
- const hasActualAdoptedStyles = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
872
- const hasFallbackStyleElement = Array.from(this.shadowRoot.children).some(
873
- (child) => child instanceof HTMLStyleElement
874
- );
684
+ const content = RenderContext.runInContext(this, () => this.render());
875
685
  try {
876
- if (!hasActualAdoptedStyles && !hasFallbackStyleElement) {
877
- const stylesToApply = this._autoStyles || this.config.styles;
878
- if (stylesToApply) {
879
- const styleName = this.config.styleName || this.constructor.name;
880
- StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
686
+ const allChildren = Array.from(this.shadowRoot.childNodes);
687
+ const oldChildren = allChildren.filter((child) => {
688
+ if (child instanceof HTMLStyleElement) return false;
689
+ if (shouldPreserveElement(child)) return false;
690
+ return true;
691
+ });
692
+ if (oldChildren.length === 1 && oldChildren[0] instanceof HTMLElement && content instanceof HTMLElement && oldChildren[0].tagName === content.tagName) {
693
+ const oldRoot = oldChildren[0];
694
+ const newRoot = content;
695
+ if (oldRoot === newRoot) {
696
+ } else {
697
+ const cacheManager = RenderContext.getDOMCache();
698
+ if (cacheManager) {
699
+ const oldMetadata = cacheManager.getMetadata(oldRoot);
700
+ const newMetadata = cacheManager.getMetadata(newRoot);
701
+ if (oldMetadata && newMetadata) {
702
+ updateProps(
703
+ oldRoot,
704
+ oldMetadata.props,
705
+ newMetadata.props,
706
+ oldRoot.tagName
707
+ );
708
+ updateChildren(
709
+ oldRoot,
710
+ oldMetadata.children,
711
+ newMetadata.children,
712
+ cacheManager
713
+ );
714
+ } else {
715
+ oldRoot.replaceWith(newRoot);
716
+ }
717
+ } else {
718
+ oldRoot.replaceWith(newRoot);
719
+ }
881
720
  }
882
- }
883
- const content = RenderContext.runInContext(this, () => this.render());
884
- if (focusState && focusState.key && focusState.value !== void 0) {
885
- const target = content.querySelector(
886
- `[data-wsx-key="${focusState.key}"]`
721
+ const hasStylesOriginal = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0 || Array.from(this.shadowRoot.childNodes).some(
722
+ (c) => c instanceof HTMLStyleElement
887
723
  );
888
- if (target) {
889
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
890
- target.value = focusState.value;
724
+ if (!hasStylesOriginal) {
725
+ const stylesToApply = this._autoStyles || this.config.styles;
726
+ if (stylesToApply) {
727
+ const styleName = this.config.styleName || this.constructor.name;
728
+ StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
891
729
  }
892
730
  }
893
- }
894
- const isContentAlreadyInShadowRoot = content.parentNode === this.shadowRoot;
895
- if (!isContentAlreadyInShadowRoot) {
896
- this.shadowRoot.appendChild(content);
897
- }
898
- const oldNodes = Array.from(this.shadowRoot.childNodes).filter((child) => {
899
- if (child === content) {
900
- return false;
901
- }
902
- if (child instanceof HTMLStyleElement) {
903
- return false;
904
- }
905
- if (shouldPreserveElement(child)) {
906
- return false;
731
+ } else {
732
+ oldChildren.forEach((child) => child.remove());
733
+ if (content.parentNode !== this.shadowRoot) {
734
+ this.shadowRoot.appendChild(content);
907
735
  }
908
- return true;
909
- });
910
- oldNodes.forEach((node) => node.remove());
911
- const hasStylesAfterDOM = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0;
912
- const hasStyleElementAfterDOM = Array.from(this.shadowRoot.children).some(
913
- (child) => child instanceof HTMLStyleElement
914
- );
915
- if (adoptedStyleSheets.length > 0) {
916
- this.shadowRoot.adoptedStyleSheets = adoptedStyleSheets;
917
- } else if (!hasStylesAfterDOM && !hasStyleElementAfterDOM) {
918
- const stylesToApply = this._autoStyles || this.config.styles;
919
- if (stylesToApply) {
920
- const styleName = this.config.styleName || this.constructor.name;
921
- StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
736
+ const hasStylesAfter = this.shadowRoot.adoptedStyleSheets && this.shadowRoot.adoptedStyleSheets.length > 0 || Array.from(this.shadowRoot.children).some((c) => c instanceof HTMLStyleElement);
737
+ if (!hasStylesAfter) {
738
+ const stylesToApply = this._autoStyles || this.config.styles;
739
+ if (stylesToApply) {
740
+ const styleName = this.config.styleName || this.constructor.name;
741
+ StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
742
+ }
922
743
  }
923
744
  }
924
- this.restoreFocusState(focusState);
925
- this._pendingFocusState = null;
926
745
  this.onRendered?.();
927
746
  this._isRendering = false;
928
747
  } catch (error) {
@@ -993,10 +812,10 @@ var LightComponent = class extends BaseComponent {
993
812
  this.insertBefore(styleElement, this.firstChild);
994
813
  }
995
814
  } else {
996
- const childrenToRemove = Array.from(this.children).filter(
997
- (child) => child !== styleElement
815
+ const childrenToRemove = Array.from(this.childNodes).filter(
816
+ (node) => node !== styleElement
998
817
  );
999
- childrenToRemove.forEach((child) => child.remove());
818
+ childrenToRemove.forEach((node) => node.remove());
1000
819
  const content = RenderContext.runInContext(this, () => this.render());
1001
820
  this.appendChild(content);
1002
821
  if (styleElement && styleElement !== this.firstChild) {
@@ -1058,21 +877,9 @@ var LightComponent = class extends BaseComponent {
1058
877
  this._isRendering = false;
1059
878
  return;
1060
879
  }
1061
- const focusState = this.captureFocusState();
1062
- this._pendingFocusState = focusState;
1063
880
  const jsxChildren = this.getJSXChildren();
1064
881
  try {
1065
882
  const newContent = RenderContext.runInContext(this, () => this.render());
1066
- if (focusState && focusState.key && focusState.value !== void 0) {
1067
- const target = newContent.querySelector(
1068
- `[data-wsx-key="${focusState.key}"]`
1069
- );
1070
- if (target) {
1071
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
1072
- target.value = focusState.value;
1073
- }
1074
- }
1075
- }
1076
883
  const stylesToApply = this._autoStyles || this.config.styles;
1077
884
  const styleName = this.config.styleName || this.constructor.name;
1078
885
  if (stylesToApply) {
@@ -1088,60 +895,66 @@ var LightComponent = class extends BaseComponent {
1088
895
  styleElement.textContent = stylesToApply;
1089
896
  }
1090
897
  }
1091
- requestAnimationFrame(() => {
1092
- const oldChildren = Array.from(this.children).filter((child) => {
1093
- if (stylesToApply && child instanceof HTMLStyleElement && child.getAttribute("data-wsx-light-component") === styleName) {
1094
- return false;
1095
- }
1096
- if (child instanceof HTMLElement && jsxChildren.includes(child)) {
1097
- return false;
1098
- }
1099
- return true;
1100
- });
1101
- if (oldChildren.length === 1 && newContent instanceof HTMLElement) {
1102
- const oldElement = oldChildren[0];
1103
- if (oldElement instanceof HTMLElement && oldElement.tagName === newContent.tagName) {
1104
- Array.from(oldElement.attributes).forEach((attr) => {
1105
- if (!newContent.hasAttribute(attr.name)) {
1106
- oldElement.removeAttribute(attr.name);
1107
- }
1108
- });
1109
- Array.from(newContent.attributes).forEach((attr) => {
1110
- if (oldElement.getAttribute(attr.name) !== attr.value) {
1111
- oldElement.setAttribute(attr.name, attr.value);
1112
- }
1113
- });
1114
- reconcileElement(oldElement, newContent);
898
+ const allShadowChildren = Array.from(this.childNodes);
899
+ const oldChildren = allShadowChildren.filter((child) => {
900
+ if (stylesToApply && child instanceof HTMLStyleElement && child.getAttribute("data-wsx-light-component") === styleName) {
901
+ return false;
902
+ }
903
+ if (jsxChildren.includes(child)) {
904
+ return false;
905
+ }
906
+ if (shouldPreserveElement(child)) {
907
+ return false;
908
+ }
909
+ return true;
910
+ });
911
+ if (oldChildren.length === 1 && newContent instanceof HTMLElement && oldChildren[0] instanceof HTMLElement && oldChildren[0].tagName === newContent.tagName) {
912
+ const oldRoot = oldChildren[0];
913
+ const newRoot = newContent;
914
+ if (oldRoot !== newRoot) {
915
+ const cacheManager = RenderContext.getDOMCache();
916
+ if (cacheManager) {
917
+ const oldMetadata = cacheManager.getMetadata(oldRoot);
918
+ const newMetadata = cacheManager.getMetadata(newRoot);
919
+ if (oldMetadata && newMetadata) {
920
+ updateProps(
921
+ oldRoot,
922
+ oldMetadata.props,
923
+ newMetadata.props,
924
+ oldRoot.tagName
925
+ );
926
+ updateChildren(
927
+ oldRoot,
928
+ oldMetadata.children,
929
+ newMetadata.children,
930
+ cacheManager
931
+ );
932
+ } else {
933
+ oldRoot.replaceWith(newRoot);
934
+ }
1115
935
  } else {
1116
- oldElement.remove();
1117
- this.appendChild(newContent);
936
+ oldRoot.replaceWith(newRoot);
1118
937
  }
1119
- } else {
1120
- oldChildren.forEach((child) => child.remove());
1121
- this.appendChild(newContent);
1122
938
  }
1123
- if (stylesToApply) {
1124
- let styleEl = this.querySelector(
1125
- `style[data-wsx-light-component="${styleName}"]`
1126
- );
1127
- if (!styleEl) {
1128
- styleEl = document.createElement("style");
1129
- styleEl.setAttribute("data-wsx-light-component", styleName);
1130
- styleEl.textContent = stylesToApply;
1131
- this.insertBefore(styleEl, this.firstChild);
1132
- } else if (styleEl.textContent !== stylesToApply) {
1133
- styleEl.textContent = stylesToApply;
1134
- } else if (styleEl !== this.firstChild) {
1135
- this.insertBefore(styleEl, this.firstChild);
1136
- }
939
+ } else {
940
+ oldChildren.forEach((child) => child.remove());
941
+ this.appendChild(newContent);
942
+ }
943
+ if (stylesToApply) {
944
+ let styleEl = this.querySelector(
945
+ `style[data-wsx-light-component="${styleName}"]`
946
+ );
947
+ if (!styleEl) {
948
+ styleEl = document.createElement("style");
949
+ styleEl.setAttribute("data-wsx-light-component", styleName);
950
+ styleEl.textContent = stylesToApply;
951
+ this.insertBefore(styleEl, this.firstChild);
952
+ } else if (styleEl !== this.firstChild) {
953
+ this.insertBefore(styleEl, this.firstChild);
1137
954
  }
1138
- requestAnimationFrame(() => {
1139
- this.restoreFocusState(focusState);
1140
- this._pendingFocusState = null;
1141
- this.onRendered?.();
1142
- this._isRendering = false;
1143
- });
1144
- });
955
+ }
956
+ this.onRendered?.();
957
+ this._isRendering = false;
1145
958
  } catch (error) {
1146
959
  logger4.error(`[${this.constructor.name}] Error in _rerender:`, error);
1147
960
  this.renderError(error);
@@ -1155,9 +968,15 @@ var LightComponent = class extends BaseComponent {
1155
968
  * 这些 children 不是 render() 返回的内容,应该保留
1156
969
  */
1157
970
  getJSXChildren() {
1158
- const jsxChildren = Array.from(this.children).filter(
1159
- (child) => child instanceof HTMLElement && child.getAttribute("data-wsx-jsx-child") === "true"
1160
- ).map((child) => child);
971
+ const jsxChildren = Array.from(this.childNodes).filter((node) => {
972
+ if (node instanceof HTMLElement) {
973
+ return node.getAttribute("data-wsx-jsx-child") === "true";
974
+ }
975
+ if (node.nodeType === Node.TEXT_NODE) {
976
+ return node.__wsxJsxChild === true;
977
+ }
978
+ return false;
979
+ });
1161
980
  return jsxChildren;
1162
981
  }
1163
982
  /**
@@ -1168,9 +987,14 @@ var LightComponent = class extends BaseComponent {
1168
987
  const styleElement = this.querySelector(
1169
988
  `style[data-wsx-light-component="${styleName}"]`
1170
989
  );
1171
- Array.from(this.children).forEach((child) => {
1172
- if (child instanceof HTMLElement && child !== styleElement && !(child instanceof HTMLSlotElement)) {
1173
- child.setAttribute("data-wsx-jsx-child", "true");
990
+ Array.from(this.childNodes).forEach((node) => {
991
+ if (node !== styleElement && !(node instanceof HTMLSlotElement)) {
992
+ if (node instanceof HTMLElement) {
993
+ node.setAttribute("data-wsx-jsx-child", "true");
994
+ } else if (node.nodeType === Node.TEXT_NODE) {
995
+ node.__wsxManaged = true;
996
+ node.__wsxJsxChild = true;
997
+ }
1174
998
  }
1175
999
  });
1176
1000
  }
@@ -1323,6 +1147,7 @@ function state(targetOrContext, propertyKey) {
1323
1147
  throw new Error(createBabelPluginError(propertyName));
1324
1148
  }
1325
1149
  export {
1150
+ BaseComponent,
1326
1151
  Fragment,
1327
1152
  LightComponent,
1328
1153
  StyleManager,