@pierre/diffs 1.2.0-beta.1 → 1.2.0-beta.3
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/components/CodeView.d.ts +28 -5
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +213 -87
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +1 -1
- package/dist/components/FileDiff.js +1 -1
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +3 -2
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +23 -17
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +3 -2
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +24 -20
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/react/CodeView.d.ts +5 -1
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +75 -16
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +1 -1
- package/dist/react/utils/useFileInstance.js +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +1 -1
- package/dist/renderers/FileRenderer.js +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/style.js +1 -1
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +3 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +1 -1
- package/package.json +1 -1
|
@@ -81,6 +81,11 @@ const CODE_VIEW_SELECTION_CALLBACK_KEYS = [
|
|
|
81
81
|
"onLineSelectionEnd"
|
|
82
82
|
];
|
|
83
83
|
const DEFAULT_POINTER_EVENTS_RESTORE_DELAY_MS = 120;
|
|
84
|
+
const SCROLL_REBASE_CONTAINER_HEIGHT = 12e6;
|
|
85
|
+
const SCROLL_REBASE_TRIGGER_TOP = 1e6;
|
|
86
|
+
const SCROLL_REBASE_TARGET_TOP = 2e6;
|
|
87
|
+
const SCROLL_REBASE_TARGET_BOTTOM = SCROLL_REBASE_CONTAINER_HEIGHT - SCROLL_REBASE_TARGET_TOP;
|
|
88
|
+
const SCROLL_REBASE_THRESHOLD = SCROLL_REBASE_CONTAINER_HEIGHT - SCROLL_REBASE_TRIGGER_TOP;
|
|
84
89
|
var CodeView = class CodeView {
|
|
85
90
|
static __STOP = false;
|
|
86
91
|
static __lastScrollPosition = 0;
|
|
@@ -101,6 +106,7 @@ var CodeView = class CodeView {
|
|
|
101
106
|
scrollHeight = 0;
|
|
102
107
|
containerHeight = -1;
|
|
103
108
|
scrollTop = 0;
|
|
109
|
+
scrollPageOffset = 0;
|
|
104
110
|
scrollDirty = true;
|
|
105
111
|
pointerEventsRestoreTimer;
|
|
106
112
|
pointerEventsDisabled = false;
|
|
@@ -185,7 +191,7 @@ var CodeView = class CodeView {
|
|
|
185
191
|
this.root = root;
|
|
186
192
|
this.root.style.overflowAnchor = "none";
|
|
187
193
|
this.container ??= document.createElement("div");
|
|
188
|
-
this.container.style.contain = "layout
|
|
194
|
+
this.container.style.contain = "layout style";
|
|
189
195
|
this.syncViewerMetrics();
|
|
190
196
|
this.container.appendChild(this.stickyOffset);
|
|
191
197
|
this.container.appendChild(this.stickyContainer);
|
|
@@ -227,6 +233,7 @@ var CodeView = class CodeView {
|
|
|
227
233
|
this.stickyContainer.textContent = "";
|
|
228
234
|
this.stickyOffset.style.height = "";
|
|
229
235
|
this.container?.style.removeProperty("height");
|
|
236
|
+
this.containerHeight = -1;
|
|
230
237
|
this.windowSpecs = {
|
|
231
238
|
top: 0,
|
|
232
239
|
bottom: 0
|
|
@@ -234,6 +241,7 @@ var CodeView = class CodeView {
|
|
|
234
241
|
this.pendingLayoutAnchor = void 0;
|
|
235
242
|
this.height = 0;
|
|
236
243
|
this.scrollTop = 0;
|
|
244
|
+
this.scrollPageOffset = 0;
|
|
237
245
|
this.scrollHeight = 0;
|
|
238
246
|
this.scrollDirty = true;
|
|
239
247
|
this.heightDirty = true;
|
|
@@ -296,6 +304,22 @@ var CodeView = class CodeView {
|
|
|
296
304
|
clearSelectedLines(options) {
|
|
297
305
|
this.applySelectedLines(null, options);
|
|
298
306
|
}
|
|
307
|
+
getItem(itemId) {
|
|
308
|
+
return this.idToItem.get(itemId)?.item;
|
|
309
|
+
}
|
|
310
|
+
updateItem(input) {
|
|
311
|
+
const item = this.idToItem.get(input.id);
|
|
312
|
+
if (item == null) {
|
|
313
|
+
console.error(`CodeView.updateItem: unknown item id "${input.id}"`);
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
if (!this.syncItemRecord(item, input)) return false;
|
|
317
|
+
this.markItemLayoutDirty(item);
|
|
318
|
+
this.scrollDirty = true;
|
|
319
|
+
this.render();
|
|
320
|
+
this.syncSelection();
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
299
323
|
addItem(input) {
|
|
300
324
|
this.addItems([input]);
|
|
301
325
|
this.syncSelection();
|
|
@@ -320,6 +344,7 @@ var CodeView = class CodeView {
|
|
|
320
344
|
if (inputs.length === 0) return;
|
|
321
345
|
const viewerMetrics = this.getViewerMetrics();
|
|
322
346
|
let nextTop = this.items.length === 0 ? 0 : this.scrollHeight + viewerMetrics.gap;
|
|
347
|
+
const appendedTop = nextTop;
|
|
323
348
|
for (let index = 0; index < inputs.length; index++) {
|
|
324
349
|
const input = inputs[index];
|
|
325
350
|
if (input == null) throw new Error("CodeView.appendItemsInternal: missing input item");
|
|
@@ -333,7 +358,11 @@ var CodeView = class CodeView {
|
|
|
333
358
|
}
|
|
334
359
|
this.scrollHeight = nextTop - viewerMetrics.gap;
|
|
335
360
|
this.scrollDirty = true;
|
|
336
|
-
if (render) this.
|
|
361
|
+
if (render) if (this.canSkipRenderForAppend(appendedTop)) this.syncContainerHeight();
|
|
362
|
+
else this.render();
|
|
363
|
+
}
|
|
364
|
+
canSkipRenderForAppend(appendedTop) {
|
|
365
|
+
return this.container != null && this.renderState.firstIndex !== -1 && this.pendingScrollTarget == null && this.scrollAnimation == null && this.layoutDirtyIndex == null && appendedTop > this.windowSpecs.bottom;
|
|
337
366
|
}
|
|
338
367
|
setOptions(options) {
|
|
339
368
|
if (options == null) return;
|
|
@@ -419,15 +448,15 @@ var CodeView = class CodeView {
|
|
|
419
448
|
this.scrollListeners.delete(listener);
|
|
420
449
|
};
|
|
421
450
|
}
|
|
422
|
-
|
|
451
|
+
getLocalTopForInstance(instance) {
|
|
423
452
|
const item = this.instanceToItem.get(instance);
|
|
424
|
-
if (item == null) throw new Error("CodeView.
|
|
453
|
+
if (item == null) throw new Error("CodeView.getLocalTopForInstance: unknown virtualized instance");
|
|
425
454
|
return item.top;
|
|
426
455
|
}
|
|
427
456
|
getTopForItem(id) {
|
|
428
457
|
const item = this.idToItem.get(id);
|
|
429
458
|
if (item == null) return;
|
|
430
|
-
return item.top;
|
|
459
|
+
return item.top + this.getViewerMetrics().paddingTop;
|
|
431
460
|
}
|
|
432
461
|
createItem(input, index, top) {
|
|
433
462
|
const itemMetrics = this.getItemMetrics();
|
|
@@ -638,15 +667,81 @@ var CodeView = class CodeView {
|
|
|
638
667
|
else item.instance.setOptions(this.createOptions(item.item));
|
|
639
668
|
return true;
|
|
640
669
|
}
|
|
670
|
+
getMaxScrollTopForHeight(scrollHeight) {
|
|
671
|
+
const { paddingBottom, paddingTop } = this.getViewerMetrics();
|
|
672
|
+
return Math.max(paddingTop + scrollHeight + paddingBottom - this.getHeight(), 0);
|
|
673
|
+
}
|
|
674
|
+
getMaxScrollTop() {
|
|
675
|
+
return this.getMaxScrollTopForHeight(this.getScrollHeight());
|
|
676
|
+
}
|
|
677
|
+
shouldRebaseScroll() {
|
|
678
|
+
return this.getMaxScrollTop() > SCROLL_REBASE_THRESHOLD;
|
|
679
|
+
}
|
|
680
|
+
getPagedScrollHeight() {
|
|
681
|
+
return this.shouldRebaseScroll() ? Math.min(this.getScrollHeight(), SCROLL_REBASE_CONTAINER_HEIGHT) : this.getScrollHeight();
|
|
682
|
+
}
|
|
683
|
+
getMaxPagedScrollTop() {
|
|
684
|
+
return this.getMaxScrollTopForHeight(this.getPagedScrollHeight());
|
|
685
|
+
}
|
|
686
|
+
clampPagedScrollTop(value) {
|
|
687
|
+
const maxScroll = this.getMaxPagedScrollTop();
|
|
688
|
+
return Math.max(0, Math.min(value, maxScroll));
|
|
689
|
+
}
|
|
641
690
|
/**
|
|
642
|
-
* Clamps a scroll position to the min/max allowable scroll range
|
|
643
|
-
* the computed
|
|
691
|
+
* Clamps a logical scroll position to the min/max allowable scroll range
|
|
692
|
+
* based on the full computed content height.
|
|
644
693
|
*/
|
|
645
694
|
clampScrollTop(value) {
|
|
646
|
-
const
|
|
647
|
-
const maxScroll = Math.max(paddingTop + this.getScrollHeight() + paddingBottom - this.getHeight(), 0);
|
|
695
|
+
const maxScroll = this.getMaxScrollTop();
|
|
648
696
|
return Math.max(0, Math.min(value, maxScroll));
|
|
649
697
|
}
|
|
698
|
+
getMaxScrollPageOffset() {
|
|
699
|
+
return Math.max(this.getMaxScrollTop() - this.getMaxPagedScrollTop(), 0);
|
|
700
|
+
}
|
|
701
|
+
clampScrollPageOffset(value) {
|
|
702
|
+
const maxOffset = this.getMaxScrollPageOffset();
|
|
703
|
+
return Math.max(0, Math.min(value, maxOffset));
|
|
704
|
+
}
|
|
705
|
+
resolveScrollPageWindow(scrollTop, preferredPagedScrollTop) {
|
|
706
|
+
let pagedScrollTop = roundToDevicePixel(this.clampPagedScrollTop(preferredPagedScrollTop));
|
|
707
|
+
let scrollPageOffset = this.clampScrollPageOffset(scrollTop - pagedScrollTop);
|
|
708
|
+
pagedScrollTop = roundToDevicePixel(this.clampPagedScrollTop(scrollTop - scrollPageOffset));
|
|
709
|
+
scrollPageOffset = this.clampScrollPageOffset(scrollTop - pagedScrollTop);
|
|
710
|
+
return {
|
|
711
|
+
pagedScrollTop,
|
|
712
|
+
scrollPageOffset
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Resolve how a logical scrollTop maps onto the reusable paged scroll window
|
|
717
|
+
* without mutating the current page offset.
|
|
718
|
+
*/
|
|
719
|
+
resolvePagedScrollPosition(logicalScrollTop) {
|
|
720
|
+
if (!this.shouldRebaseScroll()) return {
|
|
721
|
+
pagedScrollTop: this.clampPagedScrollTop(logicalScrollTop),
|
|
722
|
+
scrollPageOffset: 0
|
|
723
|
+
};
|
|
724
|
+
const currentPageOffset = this.clampScrollPageOffset(this.scrollPageOffset);
|
|
725
|
+
const pagedScrollTop = logicalScrollTop - currentPageOffset;
|
|
726
|
+
const pagedMaxScrollTop = this.getMaxPagedScrollTop();
|
|
727
|
+
const maxRebaseOffset = this.getMaxScrollPageOffset();
|
|
728
|
+
const shouldMoveDown = pagedScrollTop > SCROLL_REBASE_THRESHOLD && currentPageOffset < maxRebaseOffset;
|
|
729
|
+
const shouldMoveUp = pagedScrollTop < SCROLL_REBASE_TRIGGER_TOP && currentPageOffset > 0;
|
|
730
|
+
if (pagedScrollTop < 0 || pagedScrollTop > pagedMaxScrollTop || shouldMoveDown || shouldMoveUp) return this.resolveScrollPageWindow(logicalScrollTop, shouldMoveUp ? Math.min(SCROLL_REBASE_TARGET_BOTTOM, pagedMaxScrollTop) : SCROLL_REBASE_TARGET_TOP);
|
|
731
|
+
return {
|
|
732
|
+
pagedScrollTop: roundToDevicePixel(this.clampPagedScrollTop(pagedScrollTop)),
|
|
733
|
+
scrollPageOffset: currentPageOffset
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
needsScrollPageUpdate(logicalScrollTop) {
|
|
737
|
+
const roundedScrollTop = roundToDevicePixel(this.clampScrollTop(logicalScrollTop));
|
|
738
|
+
const { scrollPageOffset } = this.resolvePagedScrollPosition(roundedScrollTop);
|
|
739
|
+
return scrollPageOffset !== this.scrollPageOffset;
|
|
740
|
+
}
|
|
741
|
+
getPagedLayoutTop(logicalTop) {
|
|
742
|
+
if (!this.shouldRebaseScroll()) return logicalTop;
|
|
743
|
+
return Math.max(logicalTop - this.scrollPageOffset, 0);
|
|
744
|
+
}
|
|
650
745
|
getStickyHeaderOffset() {
|
|
651
746
|
return this.options.stickyHeaders === true && this.options.disableFileHeader !== true ? this.getItemMetrics().diffHeaderHeight : 0;
|
|
652
747
|
}
|
|
@@ -739,7 +834,7 @@ var CodeView = class CodeView {
|
|
|
739
834
|
* smooth scroll animation or not. If not just return the destination, or
|
|
740
835
|
* compute next position given the smooth scroll spring physics
|
|
741
836
|
*/
|
|
742
|
-
|
|
837
|
+
computeTargetScrollTopForFrame(scrollTop, frameTimestamp) {
|
|
743
838
|
if (this.pendingScrollTarget == null) return scrollTop;
|
|
744
839
|
const destination = this.resolveScrollTargetTop(this.pendingScrollTarget);
|
|
745
840
|
if (destination == null) return scrollTop;
|
|
@@ -798,51 +893,50 @@ var CodeView = class CodeView {
|
|
|
798
893
|
}
|
|
799
894
|
computeRenderRangeAndEmit = (timestamp = performance.now()) => {
|
|
800
895
|
if (CodeView.__STOP || this.container == null) return;
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
let
|
|
805
|
-
let
|
|
896
|
+
const viewportHeight = this.getHeight();
|
|
897
|
+
const initialScrollTop = this.getScrollTop();
|
|
898
|
+
let scrollTopAfterLayout = initialScrollTop;
|
|
899
|
+
let computeScrollCorrection = this.pendingLayoutAnchor != null;
|
|
900
|
+
let scrollAnchor = this.getScrollAnchor(scrollTopAfterLayout);
|
|
806
901
|
if (this.layoutDirtyIndex != null) {
|
|
807
902
|
this.recomputeLayout(this.layoutDirtyIndex);
|
|
808
903
|
this.layoutDirtyIndex = void 0;
|
|
809
|
-
|
|
904
|
+
computeScrollCorrection = true;
|
|
810
905
|
}
|
|
811
|
-
if (
|
|
812
|
-
const
|
|
813
|
-
if (
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
if (this.scrollAnimation != null) this.scrollAnimation.position +=
|
|
906
|
+
if (computeScrollCorrection && scrollAnchor != null) {
|
|
907
|
+
const anchoredScrollTopAfterLayout = this.resolveAnchoredScrollTop(scrollAnchor);
|
|
908
|
+
if (anchoredScrollTopAfterLayout != null) {
|
|
909
|
+
const layoutAnchorDelta = anchoredScrollTopAfterLayout - scrollTopAfterLayout;
|
|
910
|
+
scrollTopAfterLayout = anchoredScrollTopAfterLayout;
|
|
911
|
+
if (this.scrollAnimation != null) this.scrollAnimation.position += layoutAnchorDelta;
|
|
817
912
|
}
|
|
818
913
|
}
|
|
819
|
-
if (
|
|
820
|
-
|
|
914
|
+
if (computeScrollCorrection) {
|
|
915
|
+
scrollTopAfterLayout = this.clampScrollTop(scrollTopAfterLayout);
|
|
821
916
|
this.syncContainerHeight();
|
|
822
917
|
}
|
|
823
|
-
const
|
|
824
|
-
const fitPerfectly = !
|
|
825
|
-
|
|
826
|
-
if (this.pendingScrollTarget != null && frameScrollTop !== appliedScrollTop) {
|
|
827
|
-
this.applyScrollFix(frameScrollTop, appliedScrollTop);
|
|
828
|
-
appliedScrollTop = frameScrollTop;
|
|
829
|
-
}
|
|
830
|
-
if (fitPerfectly) anchor = void 0;
|
|
918
|
+
const targetScrollTop = this.computeTargetScrollTopForFrame(scrollTopAfterLayout, timestamp);
|
|
919
|
+
const fitPerfectly = !computeScrollCorrection && (this.renderState.scrollTop === -1 || Math.abs(targetScrollTop - this.renderState.scrollTop) > viewportHeight + this.config.overscrollSize * 2);
|
|
920
|
+
if (fitPerfectly) scrollAnchor = void 0;
|
|
831
921
|
this.windowSpecs = createWindowFromScrollPosition({
|
|
832
|
-
scrollTop:
|
|
833
|
-
height,
|
|
922
|
+
scrollTop: targetScrollTop,
|
|
923
|
+
height: viewportHeight,
|
|
834
924
|
scrollHeight: this.getScrollHeight(),
|
|
835
925
|
fitPerfectly,
|
|
836
926
|
fitPerfectlyOverscroll: this.getFitPerfectlyOverscroll(),
|
|
837
927
|
overscrollSize: this.config.overscrollSize
|
|
838
928
|
});
|
|
929
|
+
let syncedScrollTop = initialScrollTop;
|
|
930
|
+
if (this.pendingScrollTarget != null && targetScrollTop !== syncedScrollTop || this.needsScrollPageUpdate(targetScrollTop)) {
|
|
931
|
+
this.applyScrollFix(targetScrollTop, syncedScrollTop, this.windowSpecs);
|
|
932
|
+
syncedScrollTop = targetScrollTop;
|
|
933
|
+
}
|
|
839
934
|
const { top, bottom } = this.windowSpecs;
|
|
840
935
|
const { firstIndex, lastIndex } = this.renderState;
|
|
841
936
|
if (firstIndex >= 0) for (let index = firstIndex; index <= lastIndex; index++) {
|
|
842
937
|
const item = this.items[index];
|
|
843
938
|
if (item == null) throw new Error(`CodeView.computeRenderRangeAndEmit: No item at index: ${index}`);
|
|
844
|
-
|
|
845
|
-
if (!(renderedTop > top - item.height && renderedTop <= bottom)) cleanRenderedItem(item);
|
|
939
|
+
if (!(item.top > top - item.height && item.top <= bottom)) cleanRenderedItem(item);
|
|
846
940
|
}
|
|
847
941
|
let prevElement;
|
|
848
942
|
const updatedItems = /* @__PURE__ */ new Set();
|
|
@@ -870,25 +964,27 @@ var CodeView = class CodeView {
|
|
|
870
964
|
this.reconcileRenderedItems(updatedItems);
|
|
871
965
|
this.syncContainerHeight();
|
|
872
966
|
this.updateStickyPositioning();
|
|
873
|
-
const
|
|
874
|
-
if (
|
|
875
|
-
const
|
|
876
|
-
let
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
967
|
+
const anchoredScrollTopAfterRender = scrollAnchor != null ? this.resolveAnchoredScrollTop(scrollAnchor) : void 0;
|
|
968
|
+
if (scrollAnchor === this.pendingLayoutAnchor) this.pendingLayoutAnchor = void 0;
|
|
969
|
+
const postRenderAnchorDelta = anchoredScrollTopAfterRender != null ? anchoredScrollTopAfterRender - scrollTopAfterLayout : 0;
|
|
970
|
+
let postRenderScrollTop = targetScrollTop;
|
|
971
|
+
let shouldCheckPendingTargetSettled = false;
|
|
972
|
+
if (this.pendingScrollTarget != null) {
|
|
973
|
+
const pendingTargetScrollTop = this.advanceScrollAnimation(timestamp, postRenderAnchorDelta);
|
|
974
|
+
if (pendingTargetScrollTop != null) {
|
|
975
|
+
postRenderScrollTop = pendingTargetScrollTop;
|
|
976
|
+
shouldCheckPendingTargetSettled = true;
|
|
977
|
+
} else postRenderScrollTop = scrollTopAfterLayout;
|
|
978
|
+
} else postRenderScrollTop = anchoredScrollTopAfterRender ?? targetScrollTop;
|
|
979
|
+
if (postRenderScrollTop !== syncedScrollTop) {
|
|
980
|
+
this.applyScrollFix(postRenderScrollTop, syncedScrollTop, this.windowSpecs);
|
|
981
|
+
syncedScrollTop = postRenderScrollTop;
|
|
982
|
+
}
|
|
983
|
+
if (shouldCheckPendingTargetSettled && this.pendingScrollTarget != null && this.isPendingTargetSettled(this.pendingScrollTarget)) {
|
|
984
|
+
this.pendingScrollTarget = void 0;
|
|
985
|
+
this.scrollAnimation = void 0;
|
|
890
986
|
}
|
|
891
|
-
this.renderState.scrollTop = roundToDevicePixel(
|
|
987
|
+
this.renderState.scrollTop = roundToDevicePixel(syncedScrollTop);
|
|
892
988
|
this.flushManagers(updatedItems);
|
|
893
989
|
if (fitPerfectly || this.scrollAnimation != null) this.render();
|
|
894
990
|
};
|
|
@@ -896,10 +992,43 @@ var CodeView = class CodeView {
|
|
|
896
992
|
for (const item of updatedItems) item.instance.flushManagers();
|
|
897
993
|
}
|
|
898
994
|
syncContainerHeight() {
|
|
899
|
-
const
|
|
900
|
-
if (this.container == null || this.containerHeight ===
|
|
901
|
-
this.container.style.height = `${
|
|
902
|
-
this.containerHeight =
|
|
995
|
+
const pagedScrollHeight = this.getPagedScrollHeight();
|
|
996
|
+
if (this.container == null || this.containerHeight === pagedScrollHeight) return;
|
|
997
|
+
this.container.style.height = `${pagedScrollHeight}px`;
|
|
998
|
+
this.containerHeight = pagedScrollHeight;
|
|
999
|
+
}
|
|
1000
|
+
getStickyBounds(windowSpecs) {
|
|
1001
|
+
const { firstIndex, lastIndex } = windowSpecs != null ? {
|
|
1002
|
+
firstIndex: this.findFirstVisibleIndex(windowSpecs.top),
|
|
1003
|
+
lastIndex: this.findLastVisibleIndex(windowSpecs.bottom)
|
|
1004
|
+
} : this.renderState;
|
|
1005
|
+
if (firstIndex === -1 || lastIndex === -1 || firstIndex > lastIndex) return;
|
|
1006
|
+
const firstStickySpecs = this.items[firstIndex]?.instance.getAdvancedStickySpecs(windowSpecs);
|
|
1007
|
+
const lastStickySpecs = this.items[lastIndex]?.instance.getAdvancedStickySpecs(windowSpecs);
|
|
1008
|
+
if (firstStickySpecs == null || lastStickySpecs == null) return;
|
|
1009
|
+
return {
|
|
1010
|
+
stickyTop: this.getPagedLayoutTop(Math.max(firstStickySpecs.topOffset, 0)),
|
|
1011
|
+
stickyBottom: this.getPagedLayoutTop(lastStickySpecs.topOffset + lastStickySpecs.height)
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
applyStickyPositioning({ stickyTop, stickyBottom }) {
|
|
1015
|
+
const height = this.getHeight();
|
|
1016
|
+
const itemMetrics = this.getItemMetrics();
|
|
1017
|
+
const stickyContainerHeight = stickyBottom - stickyTop;
|
|
1018
|
+
this.renderState.stickyHeight = stickyContainerHeight;
|
|
1019
|
+
this.renderState.stickyTop = stickyTop;
|
|
1020
|
+
this.renderState.stickyBottom = stickyBottom;
|
|
1021
|
+
this.stickyOffset.style.height = `${stickyTop}px`;
|
|
1022
|
+
const randomOffset = (Math.random() * itemMetrics.lineHeight >> 0) * -1;
|
|
1023
|
+
const stickyJitter = -Math.max(stickyContainerHeight + randomOffset, 0) + height;
|
|
1024
|
+
this.stickyContainer.style.top = `${stickyJitter}px`;
|
|
1025
|
+
this.stickyContainer.style.bottom = `${stickyJitter + itemMetrics.diffHeaderHeight}px`;
|
|
1026
|
+
}
|
|
1027
|
+
syncPagedScrollScaffolding(windowSpecs) {
|
|
1028
|
+
this.syncContainerHeight();
|
|
1029
|
+
const stickyBounds = this.getStickyBounds(windowSpecs);
|
|
1030
|
+
if (stickyBounds == null) return;
|
|
1031
|
+
this.applyStickyPositioning(stickyBounds);
|
|
903
1032
|
}
|
|
904
1033
|
reconcileRenderedItems(updatedItems) {
|
|
905
1034
|
const { firstIndex, lastIndex } = this.renderState;
|
|
@@ -931,24 +1060,11 @@ var CodeView = class CodeView {
|
|
|
931
1060
|
}
|
|
932
1061
|
}
|
|
933
1062
|
updateStickyPositioning() {
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
const
|
|
937
|
-
if (
|
|
938
|
-
|
|
939
|
-
const itemMetrics = this.getItemMetrics();
|
|
940
|
-
const stickyTop = Math.max(firstStickySpecs.topOffset, 0);
|
|
941
|
-
const stickyBottom = lastStickySpecs.topOffset + lastStickySpecs.height;
|
|
942
|
-
const stickyContainerHeight = stickyBottom - stickyTop;
|
|
943
|
-
if (stickyContainerHeight === this.renderState.stickyHeight && stickyTop === this.renderState.stickyTop && stickyBottom === this.renderState.stickyBottom) return;
|
|
944
|
-
this.renderState.stickyHeight = stickyContainerHeight;
|
|
945
|
-
this.renderState.stickyTop = stickyTop;
|
|
946
|
-
this.renderState.stickyBottom = stickyBottom;
|
|
947
|
-
this.stickyOffset.style.height = `${stickyTop}px`;
|
|
948
|
-
const randomOffset = (Math.random() * itemMetrics.lineHeight >> 0) * -1;
|
|
949
|
-
const stickyJitter = -Math.max(stickyContainerHeight + randomOffset, 0) + height;
|
|
950
|
-
this.stickyContainer.style.top = `${stickyJitter}px`;
|
|
951
|
-
this.stickyContainer.style.bottom = `${stickyJitter + itemMetrics.diffHeaderHeight}px`;
|
|
1063
|
+
const stickyBounds = this.getStickyBounds();
|
|
1064
|
+
if (stickyBounds == null) return;
|
|
1065
|
+
const { stickyTop, stickyBottom } = stickyBounds;
|
|
1066
|
+
if (stickyBottom - stickyTop === this.renderState.stickyHeight && stickyTop === this.renderState.stickyTop && stickyBottom === this.renderState.stickyBottom) return;
|
|
1067
|
+
this.applyStickyPositioning(stickyBounds);
|
|
952
1068
|
}
|
|
953
1069
|
handleScroll = () => {
|
|
954
1070
|
if (CodeView.__STOP) return;
|
|
@@ -972,7 +1088,7 @@ var CodeView = class CodeView {
|
|
|
972
1088
|
const anchoredScrollTop = anchor != null ? this.resolveAnchoredScrollTop(anchor) : void 0;
|
|
973
1089
|
if (anchoredScrollTop != null) {
|
|
974
1090
|
const resizeAnchorDelta = anchoredScrollTop - currentScrollTop;
|
|
975
|
-
this.applyScrollFix(anchoredScrollTop, currentScrollTop);
|
|
1091
|
+
this.applyScrollFix(anchoredScrollTop, currentScrollTop, this.windowSpecs);
|
|
976
1092
|
if (this.scrollAnimation != null) this.scrollAnimation.position += resizeAnchorDelta;
|
|
977
1093
|
}
|
|
978
1094
|
if (this.pendingScrollTarget != null && this.isPendingTargetSettled(this.pendingScrollTarget)) {
|
|
@@ -1053,20 +1169,29 @@ var CodeView = class CodeView {
|
|
|
1053
1169
|
}
|
|
1054
1170
|
/**
|
|
1055
1171
|
* Apply a device-pixel-rounded scroll position if it differs from the last
|
|
1056
|
-
*
|
|
1172
|
+
* logical scrollTop synchronized into the paged scroll scaffold.
|
|
1057
1173
|
*/
|
|
1058
|
-
applyScrollFix(
|
|
1174
|
+
applyScrollFix(targetScrollTop, syncedScrollTop, windowSpecs) {
|
|
1059
1175
|
if (this.root == null) return;
|
|
1060
|
-
const
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1176
|
+
const roundedTargetScrollTop = roundToDevicePixel(this.clampScrollTop(targetScrollTop));
|
|
1177
|
+
const roundedSyncedScrollTop = roundToDevicePixel(syncedScrollTop);
|
|
1178
|
+
const { scrollPageOffset: previousPageOffset } = this;
|
|
1179
|
+
const syncedPagedScrollTop = roundToDevicePixel(this.clampPagedScrollTop(roundedSyncedScrollTop - previousPageOffset));
|
|
1180
|
+
const { pagedScrollTop, scrollPageOffset } = this.resolvePagedScrollPosition(roundedTargetScrollTop);
|
|
1181
|
+
const targetPagedScrollTop = pagedScrollTop;
|
|
1182
|
+
const rebaseChanged = previousPageOffset !== scrollPageOffset;
|
|
1183
|
+
if (roundedTargetScrollTop === this.renderState.scrollTop && roundedTargetScrollTop === roundedSyncedScrollTop && targetPagedScrollTop === syncedPagedScrollTop && !rebaseChanged) return;
|
|
1063
1184
|
this.suspendPointerEvents();
|
|
1064
|
-
if (
|
|
1065
|
-
|
|
1185
|
+
if (targetPagedScrollTop !== syncedPagedScrollTop || rebaseChanged) {
|
|
1186
|
+
this.scrollPageOffset = scrollPageOffset;
|
|
1187
|
+
this.syncPagedScrollScaffolding(windowSpecs);
|
|
1188
|
+
}
|
|
1189
|
+
if (targetPagedScrollTop !== syncedPagedScrollTop) this.root.scrollTo({
|
|
1190
|
+
top: targetPagedScrollTop,
|
|
1066
1191
|
behavior: "instant"
|
|
1067
1192
|
});
|
|
1068
|
-
this.renderState.scrollTop =
|
|
1069
|
-
this.scrollTop =
|
|
1193
|
+
this.renderState.scrollTop = roundedTargetScrollTop;
|
|
1194
|
+
this.scrollTop = roundedTargetScrollTop;
|
|
1070
1195
|
this.scrollDirty = false;
|
|
1071
1196
|
}
|
|
1072
1197
|
/**
|
|
@@ -1081,7 +1206,8 @@ var CodeView = class CodeView {
|
|
|
1081
1206
|
getScrollTop() {
|
|
1082
1207
|
if (!this.scrollDirty) return this.scrollTop;
|
|
1083
1208
|
this.scrollDirty = false;
|
|
1084
|
-
|
|
1209
|
+
const rootScrollTop = this.root?.scrollTop ?? 0;
|
|
1210
|
+
this.scrollTop = this.clampScrollTop(rootScrollTop + this.scrollPageOffset);
|
|
1085
1211
|
return this.scrollTop;
|
|
1086
1212
|
}
|
|
1087
1213
|
getHeight() {
|