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