slate-angular 20.2.14 → 20.2.16
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/fesm2022/slate-angular.mjs +622 -583
- package/fesm2022/slate-angular.mjs.map +1 -1
- package/index.d.ts +18 -18
- package/package.json +1 -1
|
@@ -3508,668 +3508,707 @@ class SlateEditable {
|
|
|
3508
3508
|
this.addEventListener(event.name, () => { });
|
|
3509
3509
|
});
|
|
3510
3510
|
}
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3511
|
+
isEnabledVirtualScroll() {
|
|
3512
|
+
return !!(this.virtualScrollConfig && this.virtualScrollConfig.enabled);
|
|
3513
|
+
}
|
|
3514
|
+
initializeVirtualScroll() {
|
|
3515
|
+
if (this.virtualScrollInitialized) {
|
|
3516
|
+
return;
|
|
3517
|
+
}
|
|
3518
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3519
|
+
this.virtualScrollInitialized = true;
|
|
3520
|
+
this.virtualTopHeightElement = document.createElement('div');
|
|
3521
|
+
this.virtualTopHeightElement.classList.add('virtual-top-height');
|
|
3522
|
+
this.virtualTopHeightElement.contentEditable = 'false';
|
|
3523
|
+
this.virtualBottomHeightElement = document.createElement('div');
|
|
3524
|
+
this.virtualBottomHeightElement.classList.add('virtual-bottom-height');
|
|
3525
|
+
this.virtualBottomHeightElement.contentEditable = 'false';
|
|
3526
|
+
this.virtualCenterOutlet = document.createElement('div');
|
|
3527
|
+
this.virtualCenterOutlet.classList.add('virtual-center-outlet');
|
|
3528
|
+
this.elementRef.nativeElement.appendChild(this.virtualTopHeightElement);
|
|
3529
|
+
this.elementRef.nativeElement.appendChild(this.virtualCenterOutlet);
|
|
3530
|
+
this.elementRef.nativeElement.appendChild(this.virtualBottomHeightElement);
|
|
3531
|
+
let editorResizeObserverRectWidth = this.elementRef.nativeElement.getBoundingClientRect().width;
|
|
3532
|
+
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, this.virtualTopHeightElement.offsetWidth);
|
|
3533
|
+
this.editorResizeObserver = new ResizeObserver(entries => {
|
|
3534
|
+
if (entries.length > 0 && entries[0].contentRect.width !== editorResizeObserverRectWidth) {
|
|
3535
|
+
editorResizeObserverRectWidth = entries[0].contentRect.width;
|
|
3536
|
+
this.keyHeightMap.clear();
|
|
3537
|
+
let target = this.virtualTopHeightElement;
|
|
3538
|
+
if (this.inViewportChildren[0]) {
|
|
3539
|
+
const firstElement = this.inViewportChildren[0];
|
|
3540
|
+
const firstDomElement = AngularEditor.toDOMNode(this.editor, firstElement);
|
|
3541
|
+
target = firstDomElement;
|
|
3542
|
+
}
|
|
3543
|
+
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, target.offsetWidth);
|
|
3544
|
+
updatePreRenderingElementWidth(this.editor);
|
|
3545
|
+
if (isDebug) {
|
|
3546
|
+
debugLog('log', 'editorResizeObserverRectWidth: ', editorResizeObserverRectWidth, 'EDITOR_TO_ROOT_NODE_WIDTH: ', EDITOR_TO_ROOT_NODE_WIDTH.get(this.editor));
|
|
3547
|
+
}
|
|
3531
3548
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3549
|
+
});
|
|
3550
|
+
this.editorResizeObserver.observe(this.elementRef.nativeElement);
|
|
3551
|
+
let pendingRemeasureIndics = [];
|
|
3552
|
+
this.indicsOfNeedBeMeasured$
|
|
3553
|
+
.pipe(tap((previousValue) => {
|
|
3554
|
+
previousValue.forEach((index) => {
|
|
3555
|
+
if (!pendingRemeasureIndics.includes(index)) {
|
|
3556
|
+
pendingRemeasureIndics.push(index);
|
|
3557
|
+
}
|
|
3558
|
+
});
|
|
3559
|
+
}), debounceTime(500), filter(() => pendingRemeasureIndics.length > 0))
|
|
3560
|
+
.subscribe(() => {
|
|
3561
|
+
const changed = measureHeightByIndics(this.editor, pendingRemeasureIndics, true);
|
|
3562
|
+
if (changed) {
|
|
3563
|
+
this.tryUpdateVirtualViewport();
|
|
3534
3564
|
if (isDebug) {
|
|
3535
|
-
debugLog('log',
|
|
3565
|
+
debugLog('log', 'exist pendingRemeasureIndics: ', pendingRemeasureIndics, 'will try to update virtual viewport');
|
|
3536
3566
|
}
|
|
3537
|
-
return intersectedSelection;
|
|
3538
3567
|
}
|
|
3539
|
-
|
|
3568
|
+
pendingRemeasureIndics = [];
|
|
3569
|
+
});
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
getChangedIndics(previousValue) {
|
|
3573
|
+
const remeasureIndics = [];
|
|
3574
|
+
this.inViewportChildren.forEach((child, index) => {
|
|
3575
|
+
if (previousValue.indexOf(child) === -1) {
|
|
3576
|
+
remeasureIndics.push(this.inViewportIndics[index]);
|
|
3540
3577
|
}
|
|
3578
|
+
});
|
|
3579
|
+
return remeasureIndics;
|
|
3580
|
+
}
|
|
3581
|
+
setVirtualSpaceHeight(topHeight, bottomHeight) {
|
|
3582
|
+
if (!this.virtualScrollInitialized) {
|
|
3583
|
+
return;
|
|
3584
|
+
}
|
|
3585
|
+
this.virtualTopHeightElement.style.height = `${topHeight}px`;
|
|
3586
|
+
if (bottomHeight !== undefined) {
|
|
3587
|
+
this.virtualBottomHeightElement.style.height = `${bottomHeight}px`;
|
|
3541
3588
|
}
|
|
3542
|
-
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, null);
|
|
3543
|
-
return selection;
|
|
3544
3589
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
return !anchorElement || !focusElement || !this.editor.isVisible(anchorElement) || !this.editor.isVisible(focusElement);
|
|
3590
|
+
getActualVirtualTopHeight() {
|
|
3591
|
+
if (!this.virtualScrollInitialized) {
|
|
3592
|
+
return 0;
|
|
3593
|
+
}
|
|
3594
|
+
return parseFloat(this.virtualTopHeightElement.style.height.replace('px', ''));
|
|
3551
3595
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
const
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
const hasDomSelection = domSelection.type !== 'None';
|
|
3565
|
-
// If the DOM selection is properly unset, we're done.
|
|
3566
|
-
if (!selection && !hasDomSelection) {
|
|
3567
|
-
return;
|
|
3596
|
+
handlePreRendering(visibleStates) {
|
|
3597
|
+
let preRenderingCount = 0;
|
|
3598
|
+
const childrenWithPreRendering = [...this.inViewportChildren];
|
|
3599
|
+
const childrenWithPreRenderingIndics = [...this.inViewportIndics];
|
|
3600
|
+
const firstIndex = this.inViewportIndics[0];
|
|
3601
|
+
for (let index = firstIndex - 1; index >= 0; index--) {
|
|
3602
|
+
const element = this.editor.children[index];
|
|
3603
|
+
if (visibleStates[index]) {
|
|
3604
|
+
childrenWithPreRendering.unshift(element);
|
|
3605
|
+
childrenWithPreRenderingIndics.unshift(index);
|
|
3606
|
+
preRenderingCount = 1;
|
|
3607
|
+
break;
|
|
3568
3608
|
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
if (
|
|
3574
|
-
|
|
3609
|
+
}
|
|
3610
|
+
const lastIndex = this.inViewportIndics[this.inViewportIndics.length - 1];
|
|
3611
|
+
for (let index = lastIndex + 1; index < this.editor.children.length; index++) {
|
|
3612
|
+
const element = this.editor.children[index];
|
|
3613
|
+
if (visibleStates[index]) {
|
|
3614
|
+
childrenWithPreRendering.push(element);
|
|
3615
|
+
childrenWithPreRenderingIndics.push(index);
|
|
3616
|
+
break;
|
|
3575
3617
|
}
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3618
|
+
}
|
|
3619
|
+
return { preRenderingCount, childrenWithPreRendering, childrenWithPreRenderingIndics };
|
|
3620
|
+
}
|
|
3621
|
+
tryUpdateVirtualViewport() {
|
|
3622
|
+
if (isDebug) {
|
|
3623
|
+
debugLog('log', 'tryUpdateVirtualViewport');
|
|
3624
|
+
}
|
|
3625
|
+
const isFromScrollTo = EDITOR_TO_IS_FROM_SCROLL_TO.get(this.editor);
|
|
3626
|
+
if (this.inViewportIndics.length > 0 && !isFromScrollTo) {
|
|
3627
|
+
const topHeight = this.getActualVirtualTopHeight();
|
|
3628
|
+
const visibleStates = this.editor.getAllVisibleStates();
|
|
3629
|
+
const refreshVirtualTopHeight = calculateVirtualTopHeight(this.editor, this.inViewportIndics[0], visibleStates);
|
|
3630
|
+
if (topHeight !== refreshVirtualTopHeight) {
|
|
3631
|
+
if (isDebug) {
|
|
3632
|
+
debugLog('log', 'update top height since dirty state(正数减去高度,负数代表增加高度): ', topHeight - refreshVirtualTopHeight);
|
|
3584
3633
|
}
|
|
3585
|
-
|
|
3586
|
-
// prevent updating native selection when active element is void element
|
|
3587
|
-
if (isTargetInsideVoid(this.editor, activeElement)) {
|
|
3634
|
+
this.setVirtualSpaceHeight(refreshVirtualTopHeight);
|
|
3588
3635
|
return;
|
|
3589
3636
|
}
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { exactMatch: false, suppressThrow: false });
|
|
3596
|
-
return;
|
|
3637
|
+
}
|
|
3638
|
+
this.tryUpdateVirtualViewportAnimId && cancelAnimationFrame(this.tryUpdateVirtualViewportAnimId);
|
|
3639
|
+
this.tryUpdateVirtualViewportAnimId = requestAnimationFrame(() => {
|
|
3640
|
+
if (isDebug) {
|
|
3641
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim start');
|
|
3597
3642
|
}
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
domSelection.setBaseAndExtent(newDomRange.endContainer, newDomRange.endOffset, newDomRange.startContainer, newDomRange.startOffset);
|
|
3643
|
+
const visibleStates = this.editor.getAllVisibleStates();
|
|
3644
|
+
let virtualView = this.calculateVirtualViewport(visibleStates);
|
|
3645
|
+
let diff = this.diffVirtualViewport(virtualView);
|
|
3646
|
+
if (diff.isDifferent && diff.needRemoveOnTop && !isFromScrollTo) {
|
|
3647
|
+
const remeasureIndics = diff.changedIndexesOfTop;
|
|
3648
|
+
const changed = measureHeightByIndics(this.editor, remeasureIndics);
|
|
3649
|
+
if (changed) {
|
|
3650
|
+
virtualView = this.calculateVirtualViewport(visibleStates);
|
|
3651
|
+
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
3608
3652
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3653
|
+
}
|
|
3654
|
+
if (diff.isDifferent) {
|
|
3655
|
+
this.applyVirtualView(virtualView);
|
|
3656
|
+
if (this.listRender.initialized) {
|
|
3657
|
+
const { preRenderingCount, childrenWithPreRendering, childrenWithPreRenderingIndics } = this.handlePreRendering(visibleStates);
|
|
3658
|
+
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount, childrenWithPreRenderingIndics);
|
|
3659
|
+
if (diff.needAddOnTop && !isFromScrollTo) {
|
|
3660
|
+
const remeasureAddedIndics = diff.changedIndexesOfTop;
|
|
3661
|
+
if (isDebug) {
|
|
3662
|
+
debugLog('log', 'needAddOnTop to remeasure heights: ', remeasureAddedIndics);
|
|
3663
|
+
}
|
|
3664
|
+
const startIndexBeforeAdd = diff.changedIndexesOfTop[diff.changedIndexesOfTop.length - 1] + 1;
|
|
3665
|
+
const topHeightBeforeAdd = virtualView.accumulatedHeights[startIndexBeforeAdd];
|
|
3666
|
+
const changed = measureHeightByIndics(this.editor, remeasureAddedIndics);
|
|
3667
|
+
if (changed) {
|
|
3668
|
+
const newHeights = buildHeightsAndAccumulatedHeights(this.editor, visibleStates);
|
|
3669
|
+
const actualTopHeightAfterAdd = newHeights.accumulatedHeights[startIndexBeforeAdd];
|
|
3670
|
+
const newTopHeight = virtualView.top - (actualTopHeightAfterAdd - topHeightBeforeAdd);
|
|
3671
|
+
this.setVirtualSpaceHeight(newTopHeight);
|
|
3672
|
+
if (isDebug) {
|
|
3673
|
+
debugLog('log', `update top height since will add element in top(正数减去高度,负数代表增加高度): ${actualTopHeightAfterAdd - topHeightBeforeAdd}`);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
if (this.editor.selection) {
|
|
3678
|
+
this.toNativeSelection(false);
|
|
3679
|
+
}
|
|
3612
3680
|
}
|
|
3613
3681
|
}
|
|
3614
|
-
|
|
3615
|
-
|
|
3682
|
+
if (isDebug) {
|
|
3683
|
+
debugLog('log', 'tryUpdateVirtualViewport Anim end');
|
|
3616
3684
|
}
|
|
3617
|
-
|
|
3618
|
-
if (this.isEnabledVirtualScroll() &&
|
|
3619
|
-
!selection &&
|
|
3620
|
-
this.editor.selection &&
|
|
3621
|
-
autoScroll &&
|
|
3622
|
-
this.virtualScrollConfig.scrollContainer) {
|
|
3623
|
-
this.virtualScrollConfig.scrollContainer.scrollTop = this.virtualScrollConfig.scrollContainer.scrollTop + 100;
|
|
3624
|
-
this.isUpdatingSelection = false;
|
|
3625
|
-
return;
|
|
3626
|
-
}
|
|
3627
|
-
else {
|
|
3628
|
-
// handle scrolling in setTimeout because of
|
|
3629
|
-
// dom should not have updated immediately after listRender's updating
|
|
3630
|
-
newDomRange && autoScroll && this.scrollSelectionIntoView(this.editor, newDomRange);
|
|
3631
|
-
// COMPAT: In Firefox, it's not enough to create a range, you also need
|
|
3632
|
-
// to focus the contenteditable element too. (2016/11/16)
|
|
3633
|
-
if (newDomRange && IS_FIREFOX) {
|
|
3634
|
-
el.focus();
|
|
3635
|
-
}
|
|
3636
|
-
}
|
|
3637
|
-
this.isUpdatingSelection = false;
|
|
3638
|
-
});
|
|
3639
|
-
}
|
|
3640
|
-
catch (error) {
|
|
3641
|
-
this.editor.onError({
|
|
3642
|
-
code: SlateErrorCode.ToNativeSelectionError,
|
|
3643
|
-
nativeError: error
|
|
3644
|
-
});
|
|
3645
|
-
this.isUpdatingSelection = false;
|
|
3646
|
-
}
|
|
3647
|
-
}
|
|
3648
|
-
onChange() {
|
|
3649
|
-
this.forceRender();
|
|
3650
|
-
this.onChangeCallback(this.editor.children);
|
|
3685
|
+
});
|
|
3651
3686
|
}
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3687
|
+
calculateVirtualViewport(visibleStates) {
|
|
3688
|
+
const children = (this.editor.children || []);
|
|
3689
|
+
if (!children.length || !this.isEnabledVirtualScroll()) {
|
|
3690
|
+
return {
|
|
3691
|
+
inViewportChildren: children,
|
|
3692
|
+
inViewportIndics: [],
|
|
3693
|
+
top: 0,
|
|
3694
|
+
bottom: 0,
|
|
3695
|
+
heights: []
|
|
3696
|
+
};
|
|
3658
3697
|
}
|
|
3659
|
-
|
|
3660
|
-
|
|
3698
|
+
const scrollTop = this.virtualScrollConfig.scrollTop;
|
|
3699
|
+
let viewportHeight = this.virtualScrollConfig.viewportHeight ?? 0;
|
|
3700
|
+
if (!viewportHeight) {
|
|
3701
|
+
return {
|
|
3702
|
+
inViewportChildren: [],
|
|
3703
|
+
inViewportIndics: [],
|
|
3704
|
+
top: 0,
|
|
3705
|
+
bottom: 0,
|
|
3706
|
+
heights: []
|
|
3707
|
+
};
|
|
3661
3708
|
}
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
// so isComposing needs to be corrected
|
|
3666
|
-
// need exec after this.cdr.detectChanges() to render HTML
|
|
3667
|
-
// need exec before this.toNativeSelection() to correct native selection
|
|
3668
|
-
if (this.isComposing) {
|
|
3669
|
-
// Composition input text be not rendered when user composition input with selection is expanded
|
|
3670
|
-
// At this time, the following matching conditions are met, assign isComposing to false, and the status is wrong
|
|
3671
|
-
// this time condition is true and isComposing is assigned false
|
|
3672
|
-
// Therefore, need to wait for the composition input text to be rendered before performing condition matching
|
|
3709
|
+
const elementLength = children.length;
|
|
3710
|
+
if (!EDITOR_TO_BUSINESS_TOP.has(this.editor)) {
|
|
3711
|
+
EDITOR_TO_BUSINESS_TOP.set(this.editor, 0);
|
|
3673
3712
|
setTimeout(() => {
|
|
3674
|
-
const
|
|
3675
|
-
const
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
if (text.startsWith(zeroChar)) {
|
|
3683
|
-
text = text.slice(1);
|
|
3684
|
-
}
|
|
3685
|
-
if (text.endsWith(zeroChar)) {
|
|
3686
|
-
text = text.slice(0, text.length - 1);
|
|
3687
|
-
}
|
|
3688
|
-
textContent += text;
|
|
3689
|
-
});
|
|
3690
|
-
if (Node.string(textNode).endsWith(textContent)) {
|
|
3691
|
-
this.isComposing = false;
|
|
3713
|
+
const virtualTopBoundingTop = this.virtualTopHeightElement.getBoundingClientRect()?.top ?? 0;
|
|
3714
|
+
const businessTop = Math.ceil(virtualTopBoundingTop) +
|
|
3715
|
+
Math.ceil(this.virtualScrollConfig.scrollTop) -
|
|
3716
|
+
Math.floor(this.virtualScrollConfig.viewportBoundingTop);
|
|
3717
|
+
EDITOR_TO_BUSINESS_TOP.set(this.editor, businessTop);
|
|
3718
|
+
if (isDebug) {
|
|
3719
|
+
debugLog('log', 'businessTop', businessTop);
|
|
3720
|
+
this.virtualTopHeightElement.setAttribute('data-business-top', businessTop.toString());
|
|
3692
3721
|
}
|
|
3693
|
-
},
|
|
3694
|
-
}
|
|
3695
|
-
if (this.editor.selection && this.isSelectionInvisible(this.editor.selection)) {
|
|
3696
|
-
Transforms.deselect(this.editor);
|
|
3697
|
-
return;
|
|
3722
|
+
}, 100);
|
|
3698
3723
|
}
|
|
3699
|
-
|
|
3700
|
-
|
|
3724
|
+
const businessTop = getBusinessTop(this.editor);
|
|
3725
|
+
const { heights, accumulatedHeights } = buildHeightsAndAccumulatedHeights(this.editor, visibleStates);
|
|
3726
|
+
const totalHeight = accumulatedHeights[elementLength] + businessTop;
|
|
3727
|
+
let startPosition = Math.max(scrollTop - businessTop, 0);
|
|
3728
|
+
let endPosition = startPosition + viewportHeight;
|
|
3729
|
+
if (scrollTop < businessTop) {
|
|
3730
|
+
endPosition = startPosition + viewportHeight - (businessTop - scrollTop);
|
|
3701
3731
|
}
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
const
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3732
|
+
let accumulatedOffset = 0;
|
|
3733
|
+
let inViewportStartIndex = -1;
|
|
3734
|
+
const visible = [];
|
|
3735
|
+
const inViewportIndics = [];
|
|
3736
|
+
for (let i = 0; i < elementLength && accumulatedOffset < endPosition; i++) {
|
|
3737
|
+
const currentHeight = heights[i];
|
|
3738
|
+
const nextOffset = accumulatedOffset + currentHeight;
|
|
3739
|
+
const isVisible = visibleStates[i];
|
|
3740
|
+
if (!isVisible) {
|
|
3741
|
+
accumulatedOffset = nextOffset;
|
|
3742
|
+
continue;
|
|
3708
3743
|
}
|
|
3709
|
-
|
|
3710
|
-
|
|
3744
|
+
// 可视区域有交集,加入渲染
|
|
3745
|
+
if (nextOffset > startPosition && accumulatedOffset < endPosition) {
|
|
3746
|
+
if (inViewportStartIndex === -1)
|
|
3747
|
+
inViewportStartIndex = i; // 第一个相交起始位置
|
|
3748
|
+
visible.push(children[i]);
|
|
3749
|
+
inViewportIndics.push(i);
|
|
3711
3750
|
}
|
|
3751
|
+
accumulatedOffset = nextOffset;
|
|
3712
3752
|
}
|
|
3753
|
+
const inViewportEndIndex = inViewportStartIndex === -1 ? elementLength - 1 : (inViewportIndics[inViewportIndics.length - 1] ?? inViewportStartIndex);
|
|
3754
|
+
const top = inViewportStartIndex === -1 ? 0 : accumulatedHeights[inViewportStartIndex];
|
|
3755
|
+
const bottom = totalHeight - accumulatedHeights[inViewportEndIndex + 1];
|
|
3756
|
+
return {
|
|
3757
|
+
inViewportChildren: visible.length ? visible : children,
|
|
3758
|
+
inViewportIndics,
|
|
3759
|
+
top,
|
|
3760
|
+
bottom,
|
|
3761
|
+
heights,
|
|
3762
|
+
accumulatedHeights
|
|
3763
|
+
};
|
|
3713
3764
|
}
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
virtualView = this.calculateVirtualViewport(visibleStates);
|
|
3724
|
-
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
3765
|
+
applyVirtualView(virtualView) {
|
|
3766
|
+
this.inViewportChildren = virtualView.inViewportChildren;
|
|
3767
|
+
this.setVirtualSpaceHeight(virtualView.top, virtualView.bottom);
|
|
3768
|
+
this.inViewportIndics = virtualView.inViewportIndics;
|
|
3769
|
+
}
|
|
3770
|
+
diffVirtualViewport(virtualView, stage = 'first') {
|
|
3771
|
+
if (!this.inViewportChildren.length) {
|
|
3772
|
+
if (isDebug) {
|
|
3773
|
+
debugLog('log', 'diffVirtualViewport', stage, 'empty inViewportChildren', virtualView.inViewportIndics);
|
|
3725
3774
|
}
|
|
3775
|
+
return {
|
|
3776
|
+
isDifferent: true,
|
|
3777
|
+
changedIndexesOfTop: [],
|
|
3778
|
+
changedIndexesOfBottom: []
|
|
3779
|
+
};
|
|
3726
3780
|
}
|
|
3727
|
-
this.
|
|
3728
|
-
const
|
|
3729
|
-
|
|
3730
|
-
const
|
|
3731
|
-
|
|
3732
|
-
|
|
3781
|
+
const oldIndexesInViewport = [...this.inViewportIndics];
|
|
3782
|
+
const newIndexesInViewport = [...virtualView.inViewportIndics];
|
|
3783
|
+
const firstNewIndex = newIndexesInViewport[0];
|
|
3784
|
+
const lastNewIndex = newIndexesInViewport[newIndexesInViewport.length - 1];
|
|
3785
|
+
const firstOldIndex = oldIndexesInViewport[0];
|
|
3786
|
+
const lastOldIndex = oldIndexesInViewport[oldIndexesInViewport.length - 1];
|
|
3787
|
+
const isSameViewport = oldIndexesInViewport.length === newIndexesInViewport.length &&
|
|
3788
|
+
oldIndexesInViewport.every((index, i) => index === newIndexesInViewport[i]);
|
|
3789
|
+
if (firstNewIndex === firstOldIndex && lastNewIndex === lastOldIndex) {
|
|
3790
|
+
return {
|
|
3791
|
+
isDifferent: !isSameViewport,
|
|
3792
|
+
changedIndexesOfTop: [],
|
|
3793
|
+
changedIndexesOfBottom: []
|
|
3794
|
+
};
|
|
3733
3795
|
}
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3796
|
+
if (firstNewIndex !== firstOldIndex || lastNewIndex !== lastOldIndex) {
|
|
3797
|
+
const changedIndexesOfTop = [];
|
|
3798
|
+
const changedIndexesOfBottom = [];
|
|
3799
|
+
const needRemoveOnTop = firstNewIndex !== firstOldIndex && firstNewIndex > firstOldIndex;
|
|
3800
|
+
const needAddOnTop = firstNewIndex !== firstOldIndex && firstNewIndex < firstOldIndex;
|
|
3801
|
+
const needRemoveOnBottom = lastNewIndex !== lastOldIndex && lastOldIndex > lastNewIndex;
|
|
3802
|
+
const needAddOnBottom = lastNewIndex !== lastOldIndex && lastOldIndex < lastNewIndex;
|
|
3803
|
+
if (needRemoveOnTop || needAddOnBottom) {
|
|
3804
|
+
// 向下
|
|
3805
|
+
for (let index = 0; index < oldIndexesInViewport.length; index++) {
|
|
3806
|
+
const element = oldIndexesInViewport[index];
|
|
3807
|
+
if (!newIndexesInViewport.includes(element)) {
|
|
3808
|
+
changedIndexesOfTop.push(element);
|
|
3809
|
+
}
|
|
3810
|
+
else {
|
|
3811
|
+
break;
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
for (let index = newIndexesInViewport.length - 1; index >= 0; index--) {
|
|
3815
|
+
const element = newIndexesInViewport[index];
|
|
3816
|
+
if (!oldIndexesInViewport.includes(element)) {
|
|
3817
|
+
changedIndexesOfBottom.push(element);
|
|
3818
|
+
}
|
|
3819
|
+
else {
|
|
3820
|
+
break;
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
else if (needAddOnTop || needRemoveOnBottom) {
|
|
3825
|
+
// 向上
|
|
3826
|
+
for (let index = 0; index < newIndexesInViewport.length; index++) {
|
|
3827
|
+
const element = newIndexesInViewport[index];
|
|
3828
|
+
if (!oldIndexesInViewport.includes(element)) {
|
|
3829
|
+
changedIndexesOfTop.push(element);
|
|
3830
|
+
}
|
|
3831
|
+
else {
|
|
3832
|
+
break;
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
for (let index = oldIndexesInViewport.length - 1; index >= 0; index--) {
|
|
3836
|
+
const element = oldIndexesInViewport[index];
|
|
3837
|
+
if (!newIndexesInViewport.includes(element)) {
|
|
3838
|
+
changedIndexesOfBottom.push(element);
|
|
3839
|
+
}
|
|
3840
|
+
else {
|
|
3841
|
+
break;
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
if (isDebug) {
|
|
3846
|
+
debugLog('log', `====== diffVirtualViewport stage: ${stage} ======`);
|
|
3847
|
+
debugLog('log', 'oldIndexesInViewport:', oldIndexesInViewport);
|
|
3848
|
+
debugLog('log', 'newIndexesInViewport:', newIndexesInViewport);
|
|
3849
|
+
// this.editor.children[index] will be undefined when it is removed
|
|
3850
|
+
debugLog('log', 'changedIndexesOfTop:', needRemoveOnTop ? '-' : needAddOnTop ? '+' : '-', changedIndexesOfTop, changedIndexesOfTop.map(index => (this.editor.children[index] &&
|
|
3851
|
+
getCachedHeightByElement(this.editor, this.editor.children[index])) ||
|
|
3852
|
+
0));
|
|
3853
|
+
debugLog('log', 'changedIndexesOfBottom:', needAddOnBottom ? '+' : needRemoveOnBottom ? '-' : '+', changedIndexesOfBottom, changedIndexesOfBottom.map(index => (this.editor.children[index] &&
|
|
3854
|
+
getCachedHeightByElement(this.editor, this.editor.children[index])) ||
|
|
3855
|
+
0));
|
|
3856
|
+
const needTop = virtualView.heights.slice(0, newIndexesInViewport[0]).reduce((acc, height) => acc + height, 0);
|
|
3857
|
+
const needBottom = virtualView.heights
|
|
3858
|
+
.slice(newIndexesInViewport[newIndexesInViewport.length - 1] + 1)
|
|
3859
|
+
.reduce((acc, height) => acc + height, 0);
|
|
3860
|
+
debugLog('log', needTop - parseFloat(this.virtualTopHeightElement.style.height), 'newTopHeight:', needTop, 'prevTopHeight:', parseFloat(this.virtualTopHeightElement.style.height));
|
|
3861
|
+
debugLog('log', 'newBottomHeight:', needBottom, 'prevBottomHeight:', parseFloat(this.virtualBottomHeightElement.style.height));
|
|
3862
|
+
debugLog('warn', '=========== Dividing line ===========');
|
|
3863
|
+
}
|
|
3864
|
+
return {
|
|
3865
|
+
isDifferent: true,
|
|
3866
|
+
needRemoveOnTop,
|
|
3867
|
+
needAddOnTop,
|
|
3868
|
+
needRemoveOnBottom,
|
|
3869
|
+
needAddOnBottom,
|
|
3870
|
+
changedIndexesOfTop,
|
|
3871
|
+
changedIndexesOfBottom
|
|
3747
3872
|
};
|
|
3748
|
-
return true;
|
|
3749
3873
|
}
|
|
3750
|
-
return
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
parent: this.editor,
|
|
3755
|
-
selection: this.editor.selection,
|
|
3756
|
-
decorations: this.generateDecorations(),
|
|
3757
|
-
decorate: this.decorate,
|
|
3758
|
-
readonly: this.readonly
|
|
3874
|
+
return {
|
|
3875
|
+
isDifferent: false,
|
|
3876
|
+
changedIndexesOfTop: [],
|
|
3877
|
+
changedIndexesOfBottom: []
|
|
3759
3878
|
};
|
|
3760
3879
|
}
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
};
|
|
3880
|
+
//#region event proxy
|
|
3881
|
+
addEventListener(eventName, listener, target = this.elementRef.nativeElement) {
|
|
3882
|
+
this.manualListeners.push(this.renderer2.listen(target, eventName, (event) => {
|
|
3883
|
+
const beforeInputEvent = extractBeforeInputEvent(event.type, null, event, event.target);
|
|
3884
|
+
if (beforeInputEvent) {
|
|
3885
|
+
this.onFallbackBeforeInput(beforeInputEvent);
|
|
3886
|
+
}
|
|
3887
|
+
listener(event);
|
|
3888
|
+
}));
|
|
3770
3889
|
}
|
|
3771
|
-
|
|
3772
|
-
if (
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3890
|
+
calculateVirtualScrollSelection(selection) {
|
|
3891
|
+
if (selection) {
|
|
3892
|
+
const isBlockCardCursor = AngularEditor.isBlockCardLeftCursor(this.editor) || AngularEditor.isBlockCardRightCursor(this.editor);
|
|
3893
|
+
const indics = this.inViewportIndics;
|
|
3894
|
+
if (indics.length > 0) {
|
|
3895
|
+
const currentVisibleRange = {
|
|
3896
|
+
anchor: Editor.start(this.editor, [indics[0]]),
|
|
3897
|
+
focus: Editor.end(this.editor, [indics[indics.length - 1]])
|
|
3898
|
+
};
|
|
3899
|
+
const [start, end] = Range.edges(selection);
|
|
3900
|
+
let forwardSelection = { anchor: start, focus: end };
|
|
3901
|
+
if (!isBlockCardCursor) {
|
|
3902
|
+
forwardSelection = { anchor: start, focus: end };
|
|
3782
3903
|
}
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
else {
|
|
3786
|
-
return [];
|
|
3787
|
-
}
|
|
3788
|
-
}
|
|
3789
|
-
generateDecorations() {
|
|
3790
|
-
const decorations = this.decorate([this.editor, []]);
|
|
3791
|
-
const placeholderDecorations = this.isComposing ? [] : this.composePlaceholderDecorate(this.editor);
|
|
3792
|
-
decorations.push(...placeholderDecorations);
|
|
3793
|
-
return decorations;
|
|
3794
|
-
}
|
|
3795
|
-
isEnabledVirtualScroll() {
|
|
3796
|
-
return !!(this.virtualScrollConfig && this.virtualScrollConfig.enabled);
|
|
3797
|
-
}
|
|
3798
|
-
initializeVirtualScroll() {
|
|
3799
|
-
if (this.virtualScrollInitialized) {
|
|
3800
|
-
return;
|
|
3801
|
-
}
|
|
3802
|
-
if (this.isEnabledVirtualScroll()) {
|
|
3803
|
-
this.virtualScrollInitialized = true;
|
|
3804
|
-
this.virtualTopHeightElement = document.createElement('div');
|
|
3805
|
-
this.virtualTopHeightElement.classList.add('virtual-top-height');
|
|
3806
|
-
this.virtualTopHeightElement.contentEditable = 'false';
|
|
3807
|
-
this.virtualBottomHeightElement = document.createElement('div');
|
|
3808
|
-
this.virtualBottomHeightElement.classList.add('virtual-bottom-height');
|
|
3809
|
-
this.virtualBottomHeightElement.contentEditable = 'false';
|
|
3810
|
-
this.virtualCenterOutlet = document.createElement('div');
|
|
3811
|
-
this.virtualCenterOutlet.classList.add('virtual-center-outlet');
|
|
3812
|
-
this.elementRef.nativeElement.appendChild(this.virtualTopHeightElement);
|
|
3813
|
-
this.elementRef.nativeElement.appendChild(this.virtualCenterOutlet);
|
|
3814
|
-
this.elementRef.nativeElement.appendChild(this.virtualBottomHeightElement);
|
|
3815
|
-
let editorResizeObserverRectWidth = this.elementRef.nativeElement.getBoundingClientRect().width;
|
|
3816
|
-
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, this.virtualTopHeightElement.offsetWidth);
|
|
3817
|
-
this.editorResizeObserver = new ResizeObserver(entries => {
|
|
3818
|
-
if (entries.length > 0 && entries[0].contentRect.width !== editorResizeObserverRectWidth) {
|
|
3819
|
-
editorResizeObserverRectWidth = entries[0].contentRect.width;
|
|
3820
|
-
this.keyHeightMap.clear();
|
|
3821
|
-
let target = this.virtualTopHeightElement;
|
|
3822
|
-
if (this.inViewportChildren[0]) {
|
|
3823
|
-
const firstElement = this.inViewportChildren[0];
|
|
3824
|
-
const firstDomElement = AngularEditor.toDOMNode(this.editor, firstElement);
|
|
3825
|
-
target = firstDomElement;
|
|
3826
|
-
}
|
|
3827
|
-
EDITOR_TO_ROOT_NODE_WIDTH.set(this.editor, target.offsetWidth);
|
|
3828
|
-
updatePreRenderingElementWidth(this.editor);
|
|
3829
|
-
if (isDebug) {
|
|
3830
|
-
debugLog('log', 'editorResizeObserverRectWidth: ', editorResizeObserverRectWidth, 'EDITOR_TO_ROOT_NODE_WIDTH: ', EDITOR_TO_ROOT_NODE_WIDTH.get(this.editor));
|
|
3831
|
-
}
|
|
3904
|
+
else {
|
|
3905
|
+
forwardSelection = { anchor: { path: start.path, offset: 0 }, focus: { path: end.path, offset: 0 } };
|
|
3832
3906
|
}
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
.
|
|
3838
|
-
|
|
3839
|
-
if (!pendingRemeasureIndics.includes(index)) {
|
|
3840
|
-
pendingRemeasureIndics.push(index);
|
|
3841
|
-
}
|
|
3842
|
-
});
|
|
3843
|
-
}), debounceTime(500), filter(() => pendingRemeasureIndics.length > 0))
|
|
3844
|
-
.subscribe(() => {
|
|
3845
|
-
const changed = measureHeightByIndics(this.editor, pendingRemeasureIndics, true);
|
|
3846
|
-
if (changed) {
|
|
3847
|
-
this.tryUpdateVirtualViewport();
|
|
3907
|
+
const intersectedSelection = Range.intersection(forwardSelection, currentVisibleRange);
|
|
3908
|
+
if (intersectedSelection && isBlockCardCursor) {
|
|
3909
|
+
return selection;
|
|
3910
|
+
}
|
|
3911
|
+
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, intersectedSelection);
|
|
3912
|
+
if (!intersectedSelection || !Range.equals(intersectedSelection, forwardSelection)) {
|
|
3848
3913
|
if (isDebug) {
|
|
3849
|
-
debugLog('log',
|
|
3914
|
+
debugLog('log', `selection is not in visible range, selection: ${JSON.stringify(selection)}, currentVisibleRange: ${JSON.stringify(currentVisibleRange)}, intersectedSelection: ${JSON.stringify(intersectedSelection)}`);
|
|
3850
3915
|
}
|
|
3916
|
+
return intersectedSelection;
|
|
3851
3917
|
}
|
|
3852
|
-
|
|
3853
|
-
});
|
|
3854
|
-
}
|
|
3855
|
-
}
|
|
3856
|
-
getChangedIndics(previousValue) {
|
|
3857
|
-
const remeasureIndics = [];
|
|
3858
|
-
this.inViewportChildren.forEach((child, index) => {
|
|
3859
|
-
if (previousValue.indexOf(child) === -1) {
|
|
3860
|
-
remeasureIndics.push(this.inViewportIndics[index]);
|
|
3918
|
+
return selection;
|
|
3861
3919
|
}
|
|
3862
|
-
});
|
|
3863
|
-
return remeasureIndics;
|
|
3864
|
-
}
|
|
3865
|
-
setVirtualSpaceHeight(topHeight, bottomHeight) {
|
|
3866
|
-
if (!this.virtualScrollInitialized) {
|
|
3867
|
-
return;
|
|
3868
|
-
}
|
|
3869
|
-
this.virtualTopHeightElement.style.height = `${topHeight}px`;
|
|
3870
|
-
if (bottomHeight !== undefined) {
|
|
3871
|
-
this.virtualBottomHeightElement.style.height = `${bottomHeight}px`;
|
|
3872
3920
|
}
|
|
3921
|
+
EDITOR_TO_VIRTUAL_SCROLL_SELECTION.set(this.editor, null);
|
|
3922
|
+
return selection;
|
|
3873
3923
|
}
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3924
|
+
isSelectionInvisible(selection) {
|
|
3925
|
+
const anchorIndex = selection.anchor.path[0];
|
|
3926
|
+
const focusIndex = selection.focus.path[0];
|
|
3927
|
+
const anchorElement = this.editor.children[anchorIndex];
|
|
3928
|
+
const focusElement = this.editor.children[focusIndex];
|
|
3929
|
+
return !anchorElement || !focusElement || !this.editor.isVisible(anchorElement) || !this.editor.isVisible(focusElement);
|
|
3879
3930
|
}
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
for (let index = firstIndex - 1; index >= 0; index--) {
|
|
3886
|
-
const element = this.editor.children[index];
|
|
3887
|
-
if (visibleStates[index]) {
|
|
3888
|
-
childrenWithPreRendering.unshift(element);
|
|
3889
|
-
childrenWithPreRenderingIndics.unshift(index);
|
|
3890
|
-
preRenderingCount = 1;
|
|
3891
|
-
break;
|
|
3931
|
+
toNativeSelection(autoScroll = true) {
|
|
3932
|
+
try {
|
|
3933
|
+
let { selection } = this.editor;
|
|
3934
|
+
if (this.isEnabledVirtualScroll()) {
|
|
3935
|
+
selection = this.calculateVirtualScrollSelection(selection);
|
|
3892
3936
|
}
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
childrenWithPreRendering.push(element);
|
|
3899
|
-
childrenWithPreRenderingIndics.push(index);
|
|
3900
|
-
break;
|
|
3937
|
+
const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
|
|
3938
|
+
const { activeElement } = root;
|
|
3939
|
+
const domSelection = root.getSelection();
|
|
3940
|
+
if ((this.isComposing && !IS_ANDROID) || !domSelection) {
|
|
3941
|
+
return;
|
|
3901
3942
|
}
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
tryUpdateVirtualViewport() {
|
|
3906
|
-
if (isDebug) {
|
|
3907
|
-
debugLog('log', 'tryUpdateVirtualViewport');
|
|
3908
|
-
}
|
|
3909
|
-
const isFromScrollTo = EDITOR_TO_IS_FROM_SCROLL_TO.get(this.editor);
|
|
3910
|
-
if (this.inViewportIndics.length > 0 && !isFromScrollTo) {
|
|
3911
|
-
const topHeight = this.getActualVirtualTopHeight();
|
|
3912
|
-
const visibleStates = this.editor.getAllVisibleStates();
|
|
3913
|
-
const refreshVirtualTopHeight = calculateVirtualTopHeight(this.editor, this.inViewportIndics[0], visibleStates);
|
|
3914
|
-
if (topHeight !== refreshVirtualTopHeight) {
|
|
3915
|
-
if (isDebug) {
|
|
3916
|
-
debugLog('log', 'update top height since dirty state(正数减去高度,负数代表增加高度): ', topHeight - refreshVirtualTopHeight);
|
|
3917
|
-
}
|
|
3918
|
-
this.setVirtualSpaceHeight(refreshVirtualTopHeight);
|
|
3943
|
+
const hasDomSelection = domSelection.type !== 'None';
|
|
3944
|
+
// If the DOM selection is properly unset, we're done.
|
|
3945
|
+
if (!selection && !hasDomSelection) {
|
|
3919
3946
|
return;
|
|
3920
3947
|
}
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3948
|
+
// If the DOM selection is already correct, we're done.
|
|
3949
|
+
// verify that the dom selection is in the editor
|
|
3950
|
+
const editorElement = EDITOR_TO_ELEMENT.get(this.editor);
|
|
3951
|
+
let hasDomSelectionInEditor = false;
|
|
3952
|
+
if (editorElement.contains(domSelection.anchorNode) && editorElement.contains(domSelection.focusNode)) {
|
|
3953
|
+
hasDomSelectionInEditor = true;
|
|
3926
3954
|
}
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
if (
|
|
3934
|
-
|
|
3935
|
-
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
3955
|
+
// If the DOM selection is in the editor and the editor selection is already correct, we're done.
|
|
3956
|
+
if (hasDomSelection && hasDomSelectionInEditor && selection && hasStringTarget(domSelection)) {
|
|
3957
|
+
const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, {
|
|
3958
|
+
exactMatch: false,
|
|
3959
|
+
suppressThrow: true
|
|
3960
|
+
});
|
|
3961
|
+
if (rangeFromDOMSelection && Range.equals(rangeFromDOMSelection, selection)) {
|
|
3962
|
+
return;
|
|
3936
3963
|
}
|
|
3937
3964
|
}
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3965
|
+
// prevent updating native selection when active element is void element
|
|
3966
|
+
if (isTargetInsideVoid(this.editor, activeElement)) {
|
|
3967
|
+
return;
|
|
3968
|
+
}
|
|
3969
|
+
// when <Editable/> is being controlled through external value
|
|
3970
|
+
// then its children might just change - DOM responds to it on its own
|
|
3971
|
+
// but Slate's value is not being updated through any operation
|
|
3972
|
+
// and thus it doesn't transform selection on its own
|
|
3973
|
+
if (selection && !AngularEditor.hasRange(this.editor, selection)) {
|
|
3974
|
+
this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { exactMatch: false, suppressThrow: false });
|
|
3975
|
+
return;
|
|
3976
|
+
}
|
|
3977
|
+
// Otherwise the DOM selection is out of sync, so update it.
|
|
3978
|
+
const el = AngularEditor.toDOMNode(this.editor, this.editor);
|
|
3979
|
+
this.isUpdatingSelection = true;
|
|
3980
|
+
const newDomRange = selection && AngularEditor.toDOMRange(this.editor, selection);
|
|
3981
|
+
if (newDomRange) {
|
|
3982
|
+
// COMPAT: Since the DOM range has no concept of backwards/forwards
|
|
3983
|
+
// we need to check and do the right thing here.
|
|
3984
|
+
if (Range.isBackward(selection)) {
|
|
3985
|
+
// eslint-disable-next-line max-len
|
|
3986
|
+
domSelection.setBaseAndExtent(newDomRange.endContainer, newDomRange.endOffset, newDomRange.startContainer, newDomRange.startOffset);
|
|
3987
|
+
}
|
|
3988
|
+
else {
|
|
3989
|
+
// eslint-disable-next-line max-len
|
|
3990
|
+
domSelection.setBaseAndExtent(newDomRange.startContainer, newDomRange.startOffset, newDomRange.endContainer, newDomRange.endOffset);
|
|
3964
3991
|
}
|
|
3965
3992
|
}
|
|
3966
|
-
|
|
3967
|
-
|
|
3993
|
+
else {
|
|
3994
|
+
domSelection.removeAllRanges();
|
|
3968
3995
|
}
|
|
3969
|
-
});
|
|
3970
|
-
}
|
|
3971
|
-
calculateVirtualViewport(visibleStates) {
|
|
3972
|
-
const children = (this.editor.children || []);
|
|
3973
|
-
if (!children.length || !this.isEnabledVirtualScroll()) {
|
|
3974
|
-
return {
|
|
3975
|
-
inViewportChildren: children,
|
|
3976
|
-
inViewportIndics: [],
|
|
3977
|
-
top: 0,
|
|
3978
|
-
bottom: 0,
|
|
3979
|
-
heights: []
|
|
3980
|
-
};
|
|
3981
|
-
}
|
|
3982
|
-
const scrollTop = this.virtualScrollConfig.scrollTop;
|
|
3983
|
-
let viewportHeight = this.virtualScrollConfig.viewportHeight ?? 0;
|
|
3984
|
-
if (!viewportHeight) {
|
|
3985
|
-
return {
|
|
3986
|
-
inViewportChildren: [],
|
|
3987
|
-
inViewportIndics: [],
|
|
3988
|
-
top: 0,
|
|
3989
|
-
bottom: 0,
|
|
3990
|
-
heights: []
|
|
3991
|
-
};
|
|
3992
|
-
}
|
|
3993
|
-
const elementLength = children.length;
|
|
3994
|
-
if (!EDITOR_TO_BUSINESS_TOP.has(this.editor)) {
|
|
3995
|
-
EDITOR_TO_BUSINESS_TOP.set(this.editor, 0);
|
|
3996
3996
|
setTimeout(() => {
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
3997
|
+
if (this.isEnabledVirtualScroll() &&
|
|
3998
|
+
!selection &&
|
|
3999
|
+
this.editor.selection &&
|
|
4000
|
+
autoScroll &&
|
|
4001
|
+
this.virtualScrollConfig.scrollContainer) {
|
|
4002
|
+
this.virtualScrollConfig.scrollContainer.scrollTop = this.virtualScrollConfig.scrollContainer.scrollTop + 100;
|
|
4003
|
+
this.isUpdatingSelection = false;
|
|
4004
|
+
return;
|
|
4005
4005
|
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4006
|
+
else {
|
|
4007
|
+
// handle scrolling in setTimeout because of
|
|
4008
|
+
// dom should not have updated immediately after listRender's updating
|
|
4009
|
+
newDomRange && autoScroll && this.scrollSelectionIntoView(this.editor, newDomRange);
|
|
4010
|
+
// COMPAT: In Firefox, it's not enough to create a range, you also need
|
|
4011
|
+
// to focus the contenteditable element too. (2016/11/16)
|
|
4012
|
+
if (newDomRange && IS_FIREFOX) {
|
|
4013
|
+
el.focus();
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
this.isUpdatingSelection = false;
|
|
4017
|
+
});
|
|
4015
4018
|
}
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
const nextOffset = accumulatedOffset + currentHeight;
|
|
4023
|
-
const isVisible = visibleStates[i];
|
|
4024
|
-
if (!isVisible) {
|
|
4025
|
-
accumulatedOffset = nextOffset;
|
|
4026
|
-
continue;
|
|
4027
|
-
}
|
|
4028
|
-
// 可视区域有交集,加入渲染
|
|
4029
|
-
if (nextOffset > startPosition && accumulatedOffset < endPosition) {
|
|
4030
|
-
if (inViewportStartIndex === -1)
|
|
4031
|
-
inViewportStartIndex = i; // 第一个相交起始位置
|
|
4032
|
-
visible.push(children[i]);
|
|
4033
|
-
inViewportIndics.push(i);
|
|
4034
|
-
}
|
|
4035
|
-
accumulatedOffset = nextOffset;
|
|
4019
|
+
catch (error) {
|
|
4020
|
+
this.editor.onError({
|
|
4021
|
+
code: SlateErrorCode.ToNativeSelectionError,
|
|
4022
|
+
nativeError: error
|
|
4023
|
+
});
|
|
4024
|
+
this.isUpdatingSelection = false;
|
|
4036
4025
|
}
|
|
4037
|
-
const inViewportEndIndex = inViewportStartIndex === -1 ? elementLength - 1 : (inViewportIndics[inViewportIndics.length - 1] ?? inViewportStartIndex);
|
|
4038
|
-
const top = inViewportStartIndex === -1 ? 0 : accumulatedHeights[inViewportStartIndex];
|
|
4039
|
-
const bottom = totalHeight - accumulatedHeights[inViewportEndIndex + 1];
|
|
4040
|
-
return {
|
|
4041
|
-
inViewportChildren: visible.length ? visible : children,
|
|
4042
|
-
inViewportIndics,
|
|
4043
|
-
top,
|
|
4044
|
-
bottom,
|
|
4045
|
-
heights,
|
|
4046
|
-
accumulatedHeights
|
|
4047
|
-
};
|
|
4048
4026
|
}
|
|
4049
|
-
|
|
4050
|
-
this.
|
|
4051
|
-
this.
|
|
4052
|
-
this.inViewportIndics = virtualView.inViewportIndics;
|
|
4027
|
+
onChange() {
|
|
4028
|
+
this.forceRender();
|
|
4029
|
+
this.onChangeCallback(this.editor.children);
|
|
4053
4030
|
}
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
isDifferent: true,
|
|
4061
|
-
changedIndexesOfTop: [],
|
|
4062
|
-
changedIndexesOfBottom: []
|
|
4063
|
-
};
|
|
4031
|
+
ngAfterViewChecked() { }
|
|
4032
|
+
ngDoCheck() { }
|
|
4033
|
+
forceRender() {
|
|
4034
|
+
this.updateContext();
|
|
4035
|
+
if (this.isEnabledVirtualScroll()) {
|
|
4036
|
+
this.updateListRenderAndRemeasureHeights();
|
|
4064
4037
|
}
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
const firstNewIndex = newIndexesInViewport[0];
|
|
4068
|
-
const lastNewIndex = newIndexesInViewport[newIndexesInViewport.length - 1];
|
|
4069
|
-
const firstOldIndex = oldIndexesInViewport[0];
|
|
4070
|
-
const lastOldIndex = oldIndexesInViewport[oldIndexesInViewport.length - 1];
|
|
4071
|
-
const isSameViewport = oldIndexesInViewport.length === newIndexesInViewport.length &&
|
|
4072
|
-
oldIndexesInViewport.every((index, i) => index === newIndexesInViewport[i]);
|
|
4073
|
-
if (firstNewIndex === firstOldIndex && lastNewIndex === lastOldIndex) {
|
|
4074
|
-
return {
|
|
4075
|
-
isDifferent: !isSameViewport,
|
|
4076
|
-
changedIndexesOfTop: [],
|
|
4077
|
-
changedIndexesOfBottom: []
|
|
4078
|
-
};
|
|
4038
|
+
else {
|
|
4039
|
+
this.listRender.update(this.editor.children, this.editor, this.context);
|
|
4079
4040
|
}
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
if (
|
|
4101
|
-
|
|
4041
|
+
// repair collaborative editing when Chinese input is interrupted by other users' cursors
|
|
4042
|
+
// when the DOMElement where the selection is located is removed
|
|
4043
|
+
// the compositionupdate and compositionend events will no longer be fired
|
|
4044
|
+
// so isComposing needs to be corrected
|
|
4045
|
+
// need exec after this.cdr.detectChanges() to render HTML
|
|
4046
|
+
// need exec before this.toNativeSelection() to correct native selection
|
|
4047
|
+
if (this.isComposing) {
|
|
4048
|
+
// Composition input text be not rendered when user composition input with selection is expanded
|
|
4049
|
+
// At this time, the following matching conditions are met, assign isComposing to false, and the status is wrong
|
|
4050
|
+
// this time condition is true and isComposing is assigned false
|
|
4051
|
+
// Therefore, need to wait for the composition input text to be rendered before performing condition matching
|
|
4052
|
+
setTimeout(() => {
|
|
4053
|
+
const textNode = Node.get(this.editor, this.editor.selection.anchor.path);
|
|
4054
|
+
const textDOMNode = AngularEditor.toDOMNode(this.editor, textNode);
|
|
4055
|
+
let textContent = '';
|
|
4056
|
+
// skip decorate text
|
|
4057
|
+
textDOMNode.querySelectorAll('[editable-text]').forEach(stringDOMNode => {
|
|
4058
|
+
let text = stringDOMNode.textContent;
|
|
4059
|
+
const zeroChar = '\uFEFF';
|
|
4060
|
+
// remove zero with char
|
|
4061
|
+
if (text.startsWith(zeroChar)) {
|
|
4062
|
+
text = text.slice(1);
|
|
4102
4063
|
}
|
|
4103
|
-
|
|
4104
|
-
|
|
4064
|
+
if (text.endsWith(zeroChar)) {
|
|
4065
|
+
text = text.slice(0, text.length - 1);
|
|
4105
4066
|
}
|
|
4067
|
+
textContent += text;
|
|
4068
|
+
});
|
|
4069
|
+
if (Node.string(textNode).endsWith(textContent)) {
|
|
4070
|
+
this.isComposing = false;
|
|
4106
4071
|
}
|
|
4072
|
+
}, 0);
|
|
4073
|
+
}
|
|
4074
|
+
if (this.editor.selection && this.isSelectionInvisible(this.editor.selection)) {
|
|
4075
|
+
Transforms.deselect(this.editor);
|
|
4076
|
+
return;
|
|
4077
|
+
}
|
|
4078
|
+
else {
|
|
4079
|
+
this.toNativeSelection();
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
render() {
|
|
4083
|
+
const changed = this.updateContext();
|
|
4084
|
+
if (changed) {
|
|
4085
|
+
if (this.isEnabledVirtualScroll()) {
|
|
4086
|
+
this.updateListRenderAndRemeasureHeights();
|
|
4107
4087
|
}
|
|
4108
|
-
else
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4088
|
+
else {
|
|
4089
|
+
this.listRender.update(this.editor.children, this.editor, this.context);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
updateListRenderAndRemeasureHeights() {
|
|
4094
|
+
const operations = this.editor.operations;
|
|
4095
|
+
const firstIndex = this.inViewportIndics[0];
|
|
4096
|
+
const operationsOfFirstElementMerged = operations.filter(op => op.type === 'merge_node' && op.path.length === 1 && firstIndex === op.path[0] - 1);
|
|
4097
|
+
const operationsOfFirstElementSplitted = operations.filter(op => op.type === 'split_node' && op.path.length === 1 && firstIndex === op.path[0]);
|
|
4098
|
+
const mutationOfFirstElementHeight = operationsOfFirstElementSplitted.length > 0 || operationsOfFirstElementMerged.length > 0;
|
|
4099
|
+
const visibleStates = this.editor.getAllVisibleStates();
|
|
4100
|
+
const previousInViewportChildren = [...this.inViewportChildren];
|
|
4101
|
+
// the first element height will reset to default height when split or merge
|
|
4102
|
+
// if the most top content of the first element is not in viewport, the change of height will cause the viewport to scroll
|
|
4103
|
+
// to keep viewport stable, we need to use the current inViewportIndics temporarily
|
|
4104
|
+
if (mutationOfFirstElementHeight) {
|
|
4105
|
+
const newInViewportIndics = [];
|
|
4106
|
+
const newInViewportChildren = [];
|
|
4107
|
+
this.inViewportIndics.forEach(index => {
|
|
4108
|
+
const element = this.editor.children[index];
|
|
4109
|
+
const isVisible = visibleStates[index];
|
|
4110
|
+
if (isVisible) {
|
|
4111
|
+
newInViewportIndics.push(index);
|
|
4112
|
+
newInViewportChildren.push(element);
|
|
4118
4113
|
}
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4114
|
+
});
|
|
4115
|
+
if (operationsOfFirstElementSplitted.length > 0) {
|
|
4116
|
+
const lastIndex = newInViewportIndics[newInViewportIndics.length - 1];
|
|
4117
|
+
for (let i = lastIndex + 1; i < this.editor.children.length; i++) {
|
|
4118
|
+
const element = this.editor.children[i];
|
|
4119
|
+
const isVisible = visibleStates[i];
|
|
4120
|
+
if (isVisible) {
|
|
4121
|
+
newInViewportIndics.push(i);
|
|
4122
|
+
newInViewportChildren.push(element);
|
|
4125
4123
|
break;
|
|
4126
4124
|
}
|
|
4127
4125
|
}
|
|
4128
4126
|
}
|
|
4127
|
+
this.inViewportIndics = newInViewportIndics;
|
|
4128
|
+
this.inViewportChildren = newInViewportChildren;
|
|
4129
4129
|
if (isDebug) {
|
|
4130
|
-
debugLog('log',
|
|
4131
|
-
debugLog('log', 'oldIndexesInViewport:', oldIndexesInViewport);
|
|
4132
|
-
debugLog('log', 'newIndexesInViewport:', newIndexesInViewport);
|
|
4133
|
-
// this.editor.children[index] will be undefined when it is removed
|
|
4134
|
-
debugLog('log', 'changedIndexesOfTop:', needRemoveOnTop ? '-' : needAddOnTop ? '+' : '-', changedIndexesOfTop, changedIndexesOfTop.map(index => (this.editor.children[index] &&
|
|
4135
|
-
getCachedHeightByElement(this.editor, this.editor.children[index])) ||
|
|
4136
|
-
0));
|
|
4137
|
-
debugLog('log', 'changedIndexesOfBottom:', needAddOnBottom ? '+' : needRemoveOnBottom ? '-' : '+', changedIndexesOfBottom, changedIndexesOfBottom.map(index => (this.editor.children[index] &&
|
|
4138
|
-
getCachedHeightByElement(this.editor, this.editor.children[index])) ||
|
|
4139
|
-
0));
|
|
4140
|
-
const needTop = virtualView.heights.slice(0, newIndexesInViewport[0]).reduce((acc, height) => acc + height, 0);
|
|
4141
|
-
const needBottom = virtualView.heights
|
|
4142
|
-
.slice(newIndexesInViewport[newIndexesInViewport.length - 1] + 1)
|
|
4143
|
-
.reduce((acc, height) => acc + height, 0);
|
|
4144
|
-
debugLog('log', needTop - parseFloat(this.virtualTopHeightElement.style.height), 'newTopHeight:', needTop, 'prevTopHeight:', parseFloat(this.virtualTopHeightElement.style.height));
|
|
4145
|
-
debugLog('log', 'newBottomHeight:', needBottom, 'prevBottomHeight:', parseFloat(this.virtualBottomHeightElement.style.height));
|
|
4146
|
-
debugLog('warn', '=========== Dividing line ===========');
|
|
4130
|
+
debugLog('log', 'updateListRenderAndRemeasureHeights', 'mutationOfFirstElementHeight', 'newInViewportIndics', newInViewportIndics);
|
|
4147
4131
|
}
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4132
|
+
}
|
|
4133
|
+
else {
|
|
4134
|
+
let virtualView = this.calculateVirtualViewport(visibleStates);
|
|
4135
|
+
let diff = this.diffVirtualViewport(virtualView, 'onChange');
|
|
4136
|
+
if (diff.isDifferent && diff.needRemoveOnTop) {
|
|
4137
|
+
const remeasureIndics = diff.changedIndexesOfTop;
|
|
4138
|
+
const changed = measureHeightByIndics(this.editor, remeasureIndics);
|
|
4139
|
+
if (changed) {
|
|
4140
|
+
virtualView = this.calculateVirtualViewport(visibleStates);
|
|
4141
|
+
diff = this.diffVirtualViewport(virtualView, 'second');
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
this.applyVirtualView(virtualView);
|
|
4145
|
+
}
|
|
4146
|
+
const { preRenderingCount, childrenWithPreRendering, childrenWithPreRenderingIndics } = this.handlePreRendering(visibleStates);
|
|
4147
|
+
this.listRender.update(childrenWithPreRendering, this.editor, this.context, preRenderingCount, childrenWithPreRenderingIndics);
|
|
4148
|
+
const remeasureIndics = this.getChangedIndics(previousInViewportChildren);
|
|
4149
|
+
if (remeasureIndics.length) {
|
|
4150
|
+
this.indicsOfNeedBeMeasured$.next(remeasureIndics);
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
updateContext() {
|
|
4154
|
+
const decorations = this.generateDecorations();
|
|
4155
|
+
if (this.context.selection !== this.editor.selection ||
|
|
4156
|
+
this.context.decorate !== this.decorate ||
|
|
4157
|
+
this.context.readonly !== this.readonly ||
|
|
4158
|
+
!isDecoratorRangeListEqual(this.context.decorations, decorations)) {
|
|
4159
|
+
this.context = {
|
|
4160
|
+
parent: this.editor,
|
|
4161
|
+
selection: this.editor.selection,
|
|
4162
|
+
decorations: decorations,
|
|
4163
|
+
decorate: this.decorate,
|
|
4164
|
+
readonly: this.readonly
|
|
4156
4165
|
};
|
|
4166
|
+
return true;
|
|
4157
4167
|
}
|
|
4158
|
-
return
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4168
|
+
return false;
|
|
4169
|
+
}
|
|
4170
|
+
initializeContext() {
|
|
4171
|
+
this.context = {
|
|
4172
|
+
parent: this.editor,
|
|
4173
|
+
selection: this.editor.selection,
|
|
4174
|
+
decorations: this.generateDecorations(),
|
|
4175
|
+
decorate: this.decorate,
|
|
4176
|
+
readonly: this.readonly
|
|
4162
4177
|
};
|
|
4163
4178
|
}
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
}
|
|
4179
|
+
initializeViewContext() {
|
|
4180
|
+
this.viewContext = {
|
|
4181
|
+
editor: this.editor,
|
|
4182
|
+
renderElement: this.renderElement,
|
|
4183
|
+
renderLeaf: this.renderLeaf,
|
|
4184
|
+
renderText: this.renderText,
|
|
4185
|
+
trackBy: this.trackBy,
|
|
4186
|
+
isStrictDecorate: this.isStrictDecorate
|
|
4187
|
+
};
|
|
4188
|
+
}
|
|
4189
|
+
composePlaceholderDecorate(editor) {
|
|
4190
|
+
if (this.placeholderDecorate) {
|
|
4191
|
+
return this.placeholderDecorate(editor) || [];
|
|
4192
|
+
}
|
|
4193
|
+
if (this.placeholder && editor.children.length === 1 && Array.from(Node.texts(editor)).length === 1 && Node.string(editor) === '') {
|
|
4194
|
+
const start = Editor.start(editor, []);
|
|
4195
|
+
return [
|
|
4196
|
+
{
|
|
4197
|
+
placeholder: this.placeholder,
|
|
4198
|
+
anchor: start,
|
|
4199
|
+
focus: start
|
|
4200
|
+
}
|
|
4201
|
+
];
|
|
4202
|
+
}
|
|
4203
|
+
else {
|
|
4204
|
+
return [];
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
generateDecorations() {
|
|
4208
|
+
const decorations = this.decorate([this.editor, []]);
|
|
4209
|
+
const placeholderDecorations = this.isComposing ? [] : this.composePlaceholderDecorate(this.editor);
|
|
4210
|
+
decorations.push(...placeholderDecorations);
|
|
4211
|
+
return decorations;
|
|
4173
4212
|
}
|
|
4174
4213
|
toSlateSelection() {
|
|
4175
4214
|
if ((!this.isComposing || IS_ANDROID) && !this.isUpdatingSelection && !this.isDraggingInternally) {
|