slate-angular 20.2.0-next.2 → 20.2.0-next.4

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.
@@ -1739,6 +1739,7 @@ class BaseElementFlavour extends BaseFlavour {
1739
1739
  this.getOutletElement = () => {
1740
1740
  return this.nativeElement.querySelector('.children-outlet');
1741
1741
  };
1742
+ this.stableHeight = null;
1742
1743
  }
1743
1744
  get element() {
1744
1745
  return this._context && this._context.element;
@@ -1824,11 +1825,21 @@ class BaseElementFlavour extends BaseFlavour {
1824
1825
  readonly: this._context.readonly
1825
1826
  };
1826
1827
  }
1828
+ isStableHeight() {
1829
+ return false;
1830
+ }
1827
1831
  getRealHeight() {
1832
+ if (this.isStableHeight() && this.stableHeight !== null) {
1833
+ return this.stableHeight;
1834
+ }
1828
1835
  const blockCard = getBlockCardByNativeElement(this.nativeElement);
1829
1836
  const target = blockCard || this.nativeElement;
1830
1837
  const computedStyle = getComputedStyle(target);
1831
- return Promise.resolve(target.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom));
1838
+ const height = target.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom);
1839
+ if (this.isStableHeight()) {
1840
+ this.stableHeight = height;
1841
+ }
1842
+ return height;
1832
1843
  }
1833
1844
  }
1834
1845
 
@@ -2562,29 +2573,26 @@ class SlateEditable {
2562
2573
  this.virtualConfig = config;
2563
2574
  this.refreshVirtualViewAnimId && cancelAnimationFrame(this.refreshVirtualViewAnimId);
2564
2575
  this.refreshVirtualViewAnimId = requestAnimationFrame(() => {
2565
- const virtualView = this.refreshVirtualView();
2566
- const diff = this.diffVirtualView(virtualView);
2567
- if (diff.isDiff) {
2568
- if (diff.isMissingTop || diff.isMissingBottom) {
2569
- this.measureHeightByIndexes([...diff.diffTopRenderedIndexes, ...diff.diffBottomRenderedIndexes], true).then(result => {
2570
- if (isDebug) {
2571
- console.log('async measureHeightByIndexes:', result);
2572
- }
2573
- this.applyVirtualView(result || virtualView);
2574
- if (this.listRender.initialized) {
2575
- this.listRender.update(this.renderedChildren, this.editor, this.context);
2576
- }
2577
- this.scheduleMeasureVisibleHeights();
2578
- });
2579
- }
2580
- else {
2581
- this.applyVirtualView(virtualView);
2582
- if (this.listRender.initialized) {
2583
- this.listRender.update(virtualView.renderedChildren, this.editor, this.context);
2576
+ let virtualView = this.refreshVirtualView();
2577
+ let diff = this.diffVirtualView(virtualView);
2578
+ if (!diff.isDiff) {
2579
+ return;
2580
+ }
2581
+ if (diff.isMissingTop) {
2582
+ const result = this.remeasureHeightByIndics([...diff.diffTopRenderedIndexes]);
2583
+ if (result) {
2584
+ virtualView = this.refreshVirtualView();
2585
+ diff = this.diffVirtualView(virtualView, 'second');
2586
+ if (!diff.isDiff) {
2587
+ return;
2584
2588
  }
2585
- this.scheduleMeasureVisibleHeights();
2586
2589
  }
2587
2590
  }
2591
+ this.applyVirtualView(virtualView);
2592
+ if (this.listRender.initialized) {
2593
+ this.listRender.update(virtualView.renderedChildren, this.editor, this.context);
2594
+ }
2595
+ this.scheduleMeasureVisibleHeights();
2588
2596
  });
2589
2597
  }
2590
2598
  get hasBeforeInputSupport() {
@@ -2639,6 +2647,8 @@ class SlateEditable {
2639
2647
  this.virtualVisibleIndexes = new Set();
2640
2648
  this.measuredHeights = new Map();
2641
2649
  this.measurePending = false;
2650
+ // the height from scroll container top to editor top height element
2651
+ this.businessHeight = 0;
2642
2652
  this.virtualScrollInitialized = false;
2643
2653
  }
2644
2654
  ngOnInit() {
@@ -2951,6 +2961,7 @@ class SlateEditable {
2951
2961
  this.elementRef.nativeElement.appendChild(this.virtualTopHeightElement);
2952
2962
  this.elementRef.nativeElement.appendChild(this.virtualCenterOutlet);
2953
2963
  this.elementRef.nativeElement.appendChild(this.virtualBottomHeightElement);
2964
+ this.businessHeight = this.virtualTopHeightElement.getBoundingClientRect()?.top ?? 0;
2954
2965
  }
2955
2966
  }
2956
2967
  changeVirtualHeight(topHeight, bottomHeight) {
@@ -2971,10 +2982,9 @@ class SlateEditable {
2971
2982
  heights: []
2972
2983
  };
2973
2984
  }
2974
- const scrollTop = this.virtualConfig.scrollTop ?? 0;
2985
+ const scrollTop = this.virtualConfig.scrollTop;
2975
2986
  const viewportHeight = this.virtualConfig.viewportHeight ?? 0;
2976
2987
  if (!viewportHeight) {
2977
- // 已经启用虚拟滚动,但可视区域高度还未获取到,先置空不渲染
2978
2988
  return {
2979
2989
  renderedChildren: [],
2980
2990
  visibleIndexes: new Set(),
@@ -2983,36 +2993,33 @@ class SlateEditable {
2983
2993
  heights: []
2984
2994
  };
2985
2995
  }
2986
- const bufferCount = this.virtualConfig.bufferCount ?? VIRTUAL_SCROLL_DEFAULT_BUFFER_COUNT;
2987
- const heights = children.map((_, idx) => this.getBlockHeight(idx));
2988
- const accumulatedHeights = this.buildAccumulatedHeight(heights);
2989
- let visibleStart = 0;
2990
- // 按真实或估算高度往后累加,找到滚动起点所在块
2991
- while (visibleStart < heights.length && accumulatedHeights[visibleStart + 1] <= scrollTop) {
2992
- visibleStart++;
2993
- }
2994
- // 向上预留 bufferCount 块
2995
- const startIndex = Math.max(0, visibleStart - bufferCount);
2996
- const top = accumulatedHeights[startIndex];
2997
- const bufferBelowHeight = this.getBufferBelowHeight(viewportHeight, visibleStart, bufferCount);
2998
- const targetHeight = accumulatedHeights[visibleStart] - top + viewportHeight + bufferBelowHeight;
2996
+ const elementLength = children.length;
2997
+ const adjustedScrollTop = Math.max(0, scrollTop - this.businessHeight);
2998
+ const viewBottom = scrollTop + viewportHeight;
2999
+ let accumulatedOffset = 0;
3000
+ let visibleStartIndex = -1;
2999
3001
  const visible = [];
3000
3002
  const visibleIndexes = [];
3001
- let accumulated = 0;
3002
- let cursor = startIndex;
3003
- // 循环累计高度超出目标高度(可视高度 + 上下 buffer)
3004
- while (cursor < children.length && accumulated < targetHeight) {
3005
- visible.push(children[cursor]);
3006
- visibleIndexes.push(cursor);
3007
- accumulated += this.getBlockHeight(cursor);
3008
- cursor++;
3009
- }
3010
- const bottom = heights.slice(cursor).reduce((acc, height) => acc + height, 0);
3011
- const renderedChildren = visible.length ? visible : children;
3012
- const visibleIndexesSet = new Set(visibleIndexes);
3003
+ for (let i = 0; i < elementLength && accumulatedOffset < viewBottom; i++) {
3004
+ const currentHeight = this.getBlockHeight(i);
3005
+ const nextOffset = accumulatedOffset + currentHeight;
3006
+ // 可视区域有交集,加入渲染
3007
+ if (nextOffset > adjustedScrollTop && accumulatedOffset < viewBottom) {
3008
+ if (visibleStartIndex === -1)
3009
+ visibleStartIndex = i; // 第一个相交起始位置
3010
+ visible.push(children[i]);
3011
+ visibleIndexes.push(i);
3012
+ }
3013
+ accumulatedOffset = nextOffset;
3014
+ }
3015
+ const visibleEndIndex = visibleStartIndex === -1 ? elementLength - 1 : visibleIndexes.length - 1;
3016
+ const heights = children.map((_, idx) => this.getBlockHeight(idx));
3017
+ const accumulatedHeights = this.buildAccumulatedHeight(heights);
3018
+ const top = visibleStartIndex === -1 ? 0 : accumulatedHeights[visibleStartIndex];
3019
+ const bottom = accumulatedHeights[elementLength] - accumulatedHeights[visibleEndIndex];
3013
3020
  return {
3014
- renderedChildren,
3015
- visibleIndexes: visibleIndexesSet,
3021
+ renderedChildren: visible.length ? visible : children,
3022
+ visibleIndexes: new Set(visibleIndexes),
3016
3023
  top,
3017
3024
  bottom,
3018
3025
  heights
@@ -3023,7 +3030,7 @@ class SlateEditable {
3023
3030
  this.changeVirtualHeight(virtualView.top, virtualView.bottom);
3024
3031
  this.virtualVisibleIndexes = virtualView.visibleIndexes;
3025
3032
  }
3026
- diffVirtualView(virtualView) {
3033
+ diffVirtualView(virtualView, stage = 'first') {
3027
3034
  if (!this.renderedChildren.length) {
3028
3035
  return {
3029
3036
  isDiff: true,
@@ -3087,6 +3094,7 @@ class SlateEditable {
3087
3094
  }
3088
3095
  }
3089
3096
  if (isDebug) {
3097
+ console.log(`====== diffVirtualView stage: ${stage} ======`);
3090
3098
  console.log('oldVisibleIndexes:', oldVisibleIndexes);
3091
3099
  console.log('newVisibleIndexes:', newVisibleIndexes);
3092
3100
  console.log('diffTopRenderedIndexes:', isMissingTop ? '-' : isAddedTop ? '+' : '-', diffTopRenderedIndexes, diffTopRenderedIndexes.map(index => this.getBlockHeight(index, 0)));
@@ -3149,14 +3157,9 @@ class SlateEditable {
3149
3157
  if (!this.shouldUseVirtual()) {
3150
3158
  return;
3151
3159
  }
3152
- if (this.measurePending) {
3153
- return;
3154
- }
3155
- this.measurePending = true;
3156
3160
  this.measureVisibleHeightsAnimId && cancelAnimationFrame(this.measureVisibleHeightsAnimId);
3157
3161
  this.measureVisibleHeightsAnimId = requestAnimationFrame(() => {
3158
3162
  this.measureVisibleHeights();
3159
- this.measurePending = false;
3160
3163
  });
3161
3164
  }
3162
3165
  measureVisibleHeights() {
@@ -3175,16 +3178,21 @@ class SlateEditable {
3175
3178
  if (!view) {
3176
3179
  return;
3177
3180
  }
3178
- view.getRealHeight()?.then(height => {
3179
- this.measuredHeights.set(key.id, height);
3180
- });
3181
+ const ret = view.getRealHeight();
3182
+ if (ret instanceof Promise) {
3183
+ ret.then(height => {
3184
+ this.measuredHeights.set(key.id, height);
3185
+ });
3186
+ }
3187
+ else {
3188
+ this.measuredHeights.set(key.id, ret);
3189
+ }
3181
3190
  });
3182
3191
  }
3183
- async measureHeightByIndexes(indexes, isRefresh = false) {
3192
+ remeasureHeightByIndics(indics) {
3184
3193
  const children = (this.editor.children || []);
3185
3194
  let isHeightChanged = false;
3186
- const promises = [];
3187
- indexes.forEach(index => {
3195
+ indics.forEach(index => {
3188
3196
  const node = children[index];
3189
3197
  if (!node) {
3190
3198
  return;
@@ -3194,27 +3202,30 @@ class SlateEditable {
3194
3202
  if (!view) {
3195
3203
  return;
3196
3204
  }
3197
- const promise = view.getRealHeight()?.then(height => {
3198
- const prevHeight = this.measuredHeights.get(key.id);
3199
- if (isDebug) {
3200
- console.log('measureHeightByIndexes: get index:', index, 'prevHeight:', prevHeight, 'newHeight:', height);
3201
- }
3202
- if (prevHeight && height !== prevHeight) {
3203
- this.measuredHeights.set(key.id, height);
3205
+ const prevHeight = this.measuredHeights.get(key.id);
3206
+ const ret = view.getRealHeight();
3207
+ if (ret instanceof Promise) {
3208
+ ret.then(height => {
3209
+ if (height !== prevHeight) {
3210
+ this.measuredHeights.set(key.id, height);
3211
+ isHeightChanged = true;
3212
+ if (isDebug) {
3213
+ console.log(`remeasureHeightByIndics, index: ${index} prevHeight: ${prevHeight} newHeight: ${height}`);
3214
+ }
3215
+ }
3216
+ });
3217
+ }
3218
+ else {
3219
+ if (ret !== prevHeight) {
3220
+ this.measuredHeights.set(key.id, ret);
3204
3221
  isHeightChanged = true;
3222
+ if (isDebug) {
3223
+ console.log(`remeasureHeightByIndics, index: ${index} prevHeight: ${prevHeight} newHeight: ${ret}`);
3224
+ }
3205
3225
  }
3206
- });
3207
- if (promise) {
3208
- promises.push(promise);
3209
3226
  }
3210
3227
  });
3211
- if (promises.length > 0) {
3212
- await Promise.all(promises);
3213
- if (isHeightChanged && isRefresh) {
3214
- return this.refreshVirtualView();
3215
- }
3216
- }
3217
- return null;
3228
+ return isHeightChanged;
3218
3229
  }
3219
3230
  //#region event proxy
3220
3231
  addEventListener(eventName, listener, target = this.elementRef.nativeElement) {
@@ -4166,6 +4177,7 @@ class BaseElementComponent extends BaseComponent {
4166
4177
  }
4167
4178
  return null;
4168
4179
  };
4180
+ this.stableHeight = null;
4169
4181
  }
4170
4182
  get element() {
4171
4183
  return this._context && this._context.element;
@@ -4247,11 +4259,21 @@ class BaseElementComponent extends BaseComponent {
4247
4259
  readonly: this._context.readonly
4248
4260
  };
4249
4261
  }
4262
+ isStableHeight() {
4263
+ return false;
4264
+ }
4250
4265
  getRealHeight() {
4266
+ if (this.isStableHeight() && this.stableHeight !== null) {
4267
+ return this.stableHeight;
4268
+ }
4251
4269
  const blockCard = getBlockCardByNativeElement(this.nativeElement);
4252
4270
  const target = blockCard || this.nativeElement;
4253
4271
  const computedStyle = getComputedStyle(target);
4254
- return Promise.resolve(target.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom));
4272
+ const height = target.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom);
4273
+ if (this.isStableHeight()) {
4274
+ this.stableHeight = height;
4275
+ }
4276
+ return height;
4255
4277
  }
4256
4278
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: BaseElementComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
4257
4279
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: BaseElementComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }