@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/chunk-2ER76KOQ.mjs +1422 -0
- package/dist/chunk-FAPFH5ON.mjs +1372 -0
- package/dist/chunk-NEHWERG6.mjs +1424 -0
- package/dist/chunk-PIKDVFOA.mjs +1337 -0
- package/dist/chunk-PNIWQQN6.mjs +1330 -0
- package/dist/chunk-PP54HBAY.mjs +1337 -0
- package/dist/chunk-U74WFVRE.mjs +1308 -0
- package/dist/chunk-UTWWJJ4C.mjs +1360 -0
- package/dist/index.js +1767 -1906
- package/dist/index.mjs +178 -336
- package/dist/jsx-runtime.js +168 -148
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/jsx.js +168 -148
- package/dist/jsx.mjs +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/base-component.ts +8 -305
- package/src/index.ts +3 -0
- package/src/jsx-factory.ts +3 -1
- package/src/light-component.ts +117 -99
- package/src/utils/cache-key.ts +17 -2
- package/src/utils/dom-utils.ts +14 -42
- package/src/utils/element-marking.ts +5 -3
- package/src/utils/element-update.ts +108 -154
- package/src/utils/update-children-helpers.ts +99 -83
- package/src/web-component.ts +108 -96
package/dist/index.mjs
CHANGED
|
@@ -3,48 +3,11 @@ import {
|
|
|
3
3
|
RenderContext,
|
|
4
4
|
createLogger,
|
|
5
5
|
h,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
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
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
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
|
-
*
|
|
861
|
-
*
|
|
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
|
|
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
|
-
|
|
879
|
-
|
|
880
|
-
if (
|
|
881
|
-
|
|
882
|
-
|
|
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
|
-
|
|
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 (
|
|
891
|
-
|
|
892
|
-
|
|
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
|
-
|
|
897
|
-
|
|
898
|
-
|
|
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
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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.
|
|
999
|
-
(
|
|
815
|
+
const childrenToRemove = Array.from(this.childNodes).filter(
|
|
816
|
+
(node) => node !== styleElement
|
|
1000
817
|
);
|
|
1001
|
-
childrenToRemove.forEach((
|
|
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
|
|
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
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
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
|
-
|
|
1105
|
-
|
|
938
|
+
}
|
|
939
|
+
} else {
|
|
1106
940
|
oldChildren.forEach((child) => child.remove());
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
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
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
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.
|
|
1143
|
-
(
|
|
1144
|
-
|
|
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.
|
|
1156
|
-
if (
|
|
1157
|
-
|
|
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
|
};
|