@pierre/diffs 1.1.20 → 1.2.0-beta.1

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.
Files changed (146) hide show
  1. package/dist/components/CodeView.d.ts +325 -0
  2. package/dist/components/CodeView.d.ts.map +1 -0
  3. package/dist/components/CodeView.js +1252 -0
  4. package/dist/components/CodeView.js.map +1 -0
  5. package/dist/components/File.d.ts +13 -12
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +68 -28
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +9 -10
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +57 -30
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +9 -3
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/components/VirtualizedFile.d.ts +28 -5
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +225 -45
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +28 -5
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +285 -49
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/components/Virtualizer.d.ts +6 -3
  24. package/dist/components/Virtualizer.d.ts.map +1 -1
  25. package/dist/components/Virtualizer.js +4 -6
  26. package/dist/components/Virtualizer.js.map +1 -1
  27. package/dist/components/VirtulizerDevelopment.d.ts +2 -2
  28. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  29. package/dist/constants.d.ts +6 -2
  30. package/dist/constants.d.ts.map +1 -1
  31. package/dist/constants.js +17 -2
  32. package/dist/constants.js.map +1 -1
  33. package/dist/index.d.ts +6 -5
  34. package/dist/index.js +11 -10
  35. package/dist/managers/InteractionManager.d.ts +11 -7
  36. package/dist/managers/InteractionManager.d.ts.map +1 -1
  37. package/dist/managers/InteractionManager.js +38 -25
  38. package/dist/managers/InteractionManager.js.map +1 -1
  39. package/dist/managers/ResizeManager.d.ts +4 -4
  40. package/dist/managers/ResizeManager.d.ts.map +1 -1
  41. package/dist/managers/ResizeManager.js +89 -54
  42. package/dist/managers/ResizeManager.js.map +1 -1
  43. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  44. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  45. package/dist/managers/UniversalRenderingManager.js +13 -16
  46. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  47. package/dist/react/CodeView.d.ts +45 -0
  48. package/dist/react/CodeView.d.ts.map +1 -0
  49. package/dist/react/CodeView.js +241 -0
  50. package/dist/react/CodeView.js.map +1 -0
  51. package/dist/react/File.d.ts +0 -1
  52. package/dist/react/File.d.ts.map +1 -1
  53. package/dist/react/File.js +2 -3
  54. package/dist/react/File.js.map +1 -1
  55. package/dist/react/FileDiff.d.ts +0 -1
  56. package/dist/react/FileDiff.d.ts.map +1 -1
  57. package/dist/react/FileDiff.js +3 -4
  58. package/dist/react/FileDiff.js.map +1 -1
  59. package/dist/react/MultiFileDiff.d.ts +0 -1
  60. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  61. package/dist/react/MultiFileDiff.js +3 -4
  62. package/dist/react/MultiFileDiff.js.map +1 -1
  63. package/dist/react/PatchDiff.d.ts +0 -1
  64. package/dist/react/PatchDiff.d.ts.map +1 -1
  65. package/dist/react/PatchDiff.js +3 -4
  66. package/dist/react/PatchDiff.js.map +1 -1
  67. package/dist/react/UnresolvedFile.d.ts +0 -1
  68. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  69. package/dist/react/UnresolvedFile.js +3 -4
  70. package/dist/react/UnresolvedFile.js.map +1 -1
  71. package/dist/react/constants.d.ts.map +1 -1
  72. package/dist/react/index.d.ts +3 -2
  73. package/dist/react/index.js +5 -4
  74. package/dist/react/jsx.d.ts.map +1 -1
  75. package/dist/react/types.d.ts +0 -8
  76. package/dist/react/types.d.ts.map +1 -1
  77. package/dist/react/utils/renderDiffChildren.d.ts +0 -2
  78. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  79. package/dist/react/utils/renderDiffChildren.js +3 -4
  80. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  81. package/dist/react/utils/renderFileChildren.d.ts +0 -2
  82. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  83. package/dist/react/utils/renderFileChildren.js +3 -4
  84. package/dist/react/utils/renderFileChildren.js.map +1 -1
  85. package/dist/react/utils/useFileDiffInstance.js +12 -7
  86. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  87. package/dist/react/utils/useFileInstance.js +12 -7
  88. package/dist/react/utils/useFileInstance.js.map +1 -1
  89. package/dist/react/utils/useUnresolvedFileInstance.js +6 -2
  90. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  91. package/dist/renderers/DiffHunksRenderer.d.ts +2 -1
  92. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  93. package/dist/renderers/DiffHunksRenderer.js +35 -20
  94. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  95. package/dist/renderers/FileRenderer.d.ts +2 -1
  96. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  97. package/dist/renderers/FileRenderer.js +34 -20
  98. package/dist/renderers/FileRenderer.js.map +1 -1
  99. package/dist/ssr/index.d.ts +2 -2
  100. package/dist/ssr/preloadDiffs.js +1 -1
  101. package/dist/style.js +1 -1
  102. package/dist/style.js.map +1 -1
  103. package/dist/types.d.ts +98 -3
  104. package/dist/types.d.ts.map +1 -1
  105. package/dist/utils/areManagedSnapshotsEqual.d.ts +7 -0
  106. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -0
  107. package/dist/utils/areManagedSnapshotsEqual.js +15 -0
  108. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -0
  109. package/dist/utils/areOptionsEqual.d.ts +2 -1
  110. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  111. package/dist/utils/areOptionsEqual.js +1 -1
  112. package/dist/utils/areOptionsEqual.js.map +1 -1
  113. package/dist/utils/createFileHeaderElement.d.ts +3 -1
  114. package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
  115. package/dist/utils/createFileHeaderElement.js +3 -2
  116. package/dist/utils/createFileHeaderElement.js.map +1 -1
  117. package/dist/utils/createWindowFromScrollPosition.d.ts +3 -3
  118. package/dist/utils/createWindowFromScrollPosition.d.ts.map +1 -1
  119. package/dist/utils/createWindowFromScrollPosition.js +6 -6
  120. package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
  121. package/dist/utils/iterateOverDiff.d.ts +2 -1
  122. package/dist/utils/iterateOverDiff.d.ts.map +1 -1
  123. package/dist/utils/iterateOverDiff.js +135 -7
  124. package/dist/utils/iterateOverDiff.js.map +1 -1
  125. package/dist/utils/renderFileWithHighlighter.js +1 -1
  126. package/dist/utils/resolveVirtualFileMetrics.d.ts +4 -1
  127. package/dist/utils/resolveVirtualFileMetrics.d.ts.map +1 -1
  128. package/dist/utils/resolveVirtualFileMetrics.js +11 -1
  129. package/dist/utils/resolveVirtualFileMetrics.js.map +1 -1
  130. package/dist/utils/roundToDevicePixel.d.ts +14 -0
  131. package/dist/utils/roundToDevicePixel.d.ts.map +1 -0
  132. package/dist/utils/roundToDevicePixel.js +18 -0
  133. package/dist/utils/roundToDevicePixel.js.map +1 -0
  134. package/dist/worker/worker-portable.js +195 -14
  135. package/dist/worker/worker-portable.js.map +1 -1
  136. package/dist/worker/worker.js +146 -7
  137. package/dist/worker/worker.js.map +1 -1
  138. package/package.json +7 -1
  139. package/dist/components/AdvancedVirtualizedFileDiff.d.ts +0 -40
  140. package/dist/components/AdvancedVirtualizedFileDiff.d.ts.map +0 -1
  141. package/dist/components/AdvancedVirtualizedFileDiff.js +0 -140
  142. package/dist/components/AdvancedVirtualizedFileDiff.js.map +0 -1
  143. package/dist/components/AdvancedVirtualizer.d.ts +0 -38
  144. package/dist/components/AdvancedVirtualizer.d.ts.map +0 -1
  145. package/dist/components/AdvancedVirtualizer.js +0 -201
  146. package/dist/components/AdvancedVirtualizer.js.map +0 -1
@@ -1,8 +1,9 @@
1
- import { ExpansionDirections, VirtualFileMetrics } from "../types.js";
1
+ import { ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, SelectionSide, StickySpecs, VirtualFileMetrics } from "../types.js";
2
2
  import { WorkerPoolManager } from "../worker/WorkerPoolManager.js";
3
3
  import "../worker/index.js";
4
4
  import { Virtualizer } from "./Virtualizer.js";
5
5
  import { FileDiff, FileDiffOptions, FileDiffRenderProps } from "./FileDiff.js";
6
+ import { CodeView } from "./CodeView.js";
6
7
 
7
8
  //#region src/components/VirtualizedFileDiff.d.ts
8
9
  declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {
@@ -10,27 +11,49 @@ declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnn
10
11
  top: number | undefined;
11
12
  height: number;
12
13
  private metrics;
13
- private heightCache;
14
+ private cache;
14
15
  private isVisible;
15
16
  private isSetup;
16
17
  private virtualizer;
17
- constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);
18
+ private forceRenderOverride;
19
+ constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer | CodeView<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);
20
+ setMetrics(metrics?: Partial<VirtualFileMetrics>, force?: boolean): void;
18
21
  private getLineHeight;
19
22
  setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;
20
- reconcileHeights(): void;
23
+ reconcileHeights(): boolean;
21
24
  onRender: (dirty: boolean) => boolean;
22
- cleanUp(): void;
25
+ prepareVirtualizedItem(fileDiff: FileDiffMetadata): number;
26
+ getLinePosition(lineNumber: number, side?: SelectionSide): {
27
+ top: number;
28
+ height: number;
29
+ } | undefined;
30
+ getNumericScrollAnchor(localViewportTop: number): NumericScrollLineAnchor | undefined;
31
+ getVirtualizedHeight(): number;
32
+ getAdvancedStickySpecs(): StickySpecs | undefined;
33
+ cleanUp(recycle?: boolean): void;
23
34
  expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;
24
35
  setVisibility(visible: boolean): void;
36
+ rerender(): void;
25
37
  private computeApproximateSize;
26
38
  render({
27
39
  fileContainer,
28
40
  oldFile,
29
41
  newFile,
30
42
  fileDiff,
43
+ forceRender,
31
44
  ...props
32
45
  }?: FileDiffRenderProps<LAnnotation>): boolean;
46
+ syncVirtualizedTop(): void;
47
+ protected shouldDisableVirtualizationBuffers(): boolean;
48
+ private isSimpleMode;
49
+ private isAdvancedMode;
50
+ private getVirtualizedTop;
51
+ private getSimpleVirtualizer;
52
+ private isResizeDebuggingEnabled;
33
53
  private getDiffStyle;
54
+ private addLayoutCheckpoint;
55
+ private getLayoutCheckpointBeforeLineIndex;
56
+ private getLayoutCheckpointBeforeTop;
34
57
  private getExpandedRegion;
35
58
  private getExpandedLineCount;
36
59
  private computeRenderRangeFromWindow;
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualizedFileDiff.d.ts","names":["ExpansionDirections","VirtualFileMetrics","WorkerPoolManager","FileDiff","FileDiffOptions","FileDiffRenderProps","Virtualizer","VirtualizedFileDiff","LAnnotation","Partial","fileContainer","oldFile","newFile","fileDiff"],"sources":["../../src/components/VirtualizedFileDiff.d.ts"],"sourcesContent":["import type { ExpansionDirections, VirtualFileMetrics } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport { FileDiff, type FileDiffOptions, type FileDiffRenderProps } from './FileDiff';\nimport type { Virtualizer } from './Virtualizer';\nexport declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {\n readonly __id: string;\n top: number | undefined;\n height: number;\n private metrics;\n private heightCache;\n private isVisible;\n private isSetup;\n private virtualizer;\n constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);\n private getLineHeight;\n setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;\n reconcileHeights(): void;\n onRender: (dirty: boolean) => boolean;\n cleanUp(): void;\n expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;\n setVisibility(visible: boolean): void;\n private computeApproximateSize;\n render({ fileContainer, oldFile, newFile, fileDiff, ...props }?: FileDiffRenderProps<LAnnotation>): boolean;\n private getDiffStyle;\n private getExpandedRegion;\n private getExpandedLineCount;\n private computeRenderRangeFromWindow;\n}\n//# sourceMappingURL=VirtualizedFileDiff.d.ts.map"],"mappings":";;;;;;;cAIqBO,qDAAqDJ,SAASK;;;EAA9DD,MAAAA,EAAAA,MAAAA;EAA8DC,QAAAA,OAAAA;EAS1CA,QAAAA,WAAAA;EAAhBJ,QAAAA,SAAAA;EAAuDE,QAAAA,OAAAA;EAA+BL,QAAAA,WAAAA;EAARQ,WAAAA,CAAAA,OAAAA,EAA9EL,eAA8EK,CAA9DD,WAA8DC,CAAAA,GAAAA,SAAAA,EAAAA,WAAAA,EAAvBH,WAAuBG,EAAAA,OAAAA,CAAAA,EAAAA,OAAAA,CAAQR,kBAARQ,CAAAA,EAAAA,aAAAA,CAAAA,EAA6CP,iBAA7CO,EAAAA,kBAAAA,CAAAA,EAAAA,OAAAA;EAA6CP,QAAAA,aAAAA;EAE5GM,UAAAA,CAAAA,OAAAA,EAAhBJ,eAAgBI,CAAAA,WAAAA,CAAAA,GAAAA,SAAAA,CAAAA,EAAAA,IAAAA;EAAhBJ,gBAAAA,CAAAA,CAAAA,EAAAA,IAAAA;EAIuBJ,QAAAA,EAAAA,CAAAA,KAAAA,EAAAA,OAAAA,EAAAA,GAAAA,OAAAA;EAGlCU,OAAAA,CAAAA,CAAAA,EAAAA,IAAAA;EAAeC,UAAAA,EAAAA,CAAAA,SAAAA,EAAAA,MAAAA,EAAAA,SAAAA,EAHmBX,mBAGnBW,EAAAA,0BAAAA,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA,EAAAA,GAAAA,IAAAA;EAASC,aAAAA,CAAAA,OAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAASC,QAAAA,sBAAAA;EAA2CL,MAAAA,CAAAA;IAAAA,aAAAA;IAAAA,OAAAA;IAAAA,OAAAA;IAAAA,QAAAA;IAAAA,GAAAA;EAAAA,CAAAA,CAAAA,EAApBH,mBAAoBG,CAAAA,WAAAA,CAAAA,CAAAA,EAAAA,OAAAA;EAApBH,QAAAA,YAAAA;EAlBKF,QAAAA,iBAAAA;EAAQ,QAAA,oBAAA"}
1
+ {"version":3,"file":"VirtualizedFileDiff.d.ts","names":["ExpansionDirections","FileDiffMetadata","NumericScrollLineAnchor","SelectionSide","StickySpecs","VirtualFileMetrics","WorkerPoolManager","CodeView","FileDiff","FileDiffOptions","FileDiffRenderProps","Virtualizer","VirtualizedFileDiff","LAnnotation","Partial","fileContainer","oldFile","newFile","fileDiff","forceRender"],"sources":["../../src/components/VirtualizedFileDiff.d.ts"],"sourcesContent":["import type { ExpansionDirections, FileDiffMetadata, NumericScrollLineAnchor, SelectionSide, StickySpecs, VirtualFileMetrics } from '../types';\nimport type { WorkerPoolManager } from '../worker';\nimport type { CodeView } from './CodeView';\nimport { FileDiff, type FileDiffOptions, type FileDiffRenderProps } from './FileDiff';\nimport type { Virtualizer } from './Virtualizer';\nexport declare class VirtualizedFileDiff<LAnnotation = undefined> extends FileDiff<LAnnotation> {\n readonly __id: string;\n top: number | undefined;\n height: number;\n private metrics;\n private cache;\n private isVisible;\n private isSetup;\n private virtualizer;\n private forceRenderOverride;\n constructor(options: FileDiffOptions<LAnnotation> | undefined, virtualizer: Virtualizer | CodeView<LAnnotation>, metrics?: Partial<VirtualFileMetrics>, workerManager?: WorkerPoolManager, isContainerManaged?: boolean);\n setMetrics(metrics?: Partial<VirtualFileMetrics>, force?: boolean): void;\n private getLineHeight;\n setOptions(options: FileDiffOptions<LAnnotation> | undefined): void;\n reconcileHeights(): boolean;\n onRender: (dirty: boolean) => boolean;\n prepareVirtualizedItem(fileDiff: FileDiffMetadata): number;\n getLinePosition(lineNumber: number, side?: SelectionSide): {\n top: number;\n height: number;\n } | undefined;\n getNumericScrollAnchor(localViewportTop: number): NumericScrollLineAnchor | undefined;\n getVirtualizedHeight(): number;\n getAdvancedStickySpecs(): StickySpecs | undefined;\n cleanUp(recycle?: boolean): void;\n expandHunk: (hunkIndex: number, direction: ExpansionDirections, expansionLineCountOverride?: number | undefined) => void;\n setVisibility(visible: boolean): void;\n rerender(): void;\n private computeApproximateSize;\n render({ fileContainer, oldFile, newFile, fileDiff, forceRender, ...props }?: FileDiffRenderProps<LAnnotation>): boolean;\n syncVirtualizedTop(): void;\n protected shouldDisableVirtualizationBuffers(): boolean;\n private isSimpleMode;\n private isAdvancedMode;\n private getVirtualizedTop;\n private getSimpleVirtualizer;\n private isResizeDebuggingEnabled;\n private getDiffStyle;\n private addLayoutCheckpoint;\n private getLayoutCheckpointBeforeLineIndex;\n private getLayoutCheckpointBeforeTop;\n private getExpandedRegion;\n private getExpandedLineCount;\n private computeRenderRangeFromWindow;\n}\n//# sourceMappingURL=VirtualizedFileDiff.d.ts.map"],"mappings":";;;;;;;;cAKqBY,qDAAqDJ,SAASK;;;EAA9DD,MAAAA,EAAAA,MAAAA;EAA8DC,QAAAA,OAAAA;EAU1CA,QAAAA,KAAAA;EAAhBJ,QAAAA,SAAAA;EAAuDE,QAAAA,OAAAA;EAAuBE,QAAAA,WAAAA;EAATN,QAAAA,mBAAAA;EAAyCF,WAAAA,CAAAA,OAAAA,EAA9GI,eAA8GJ,CAA9FQ,WAA8FR,CAAAA,GAAAA,SAAAA,EAAAA,WAAAA,EAAvDM,WAAuDN,GAAzCE,QAAyCF,CAAhCQ,WAAgCR,CAAAA,EAAAA,OAAAA,CAAAA,EAARS,OAAQT,CAAAA,kBAAAA,CAAAA,EAAAA,aAAAA,CAAAA,EAAqCC,iBAArCD,EAAAA,kBAAAA,CAAAA,EAAAA,OAAAA;EAARS,UAAAA,CAAAA,OAAAA,CAAAA,EACtGA,OADsGA,CAC9FT,kBAD8FS,CAAAA,EAAAA,KAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAA6CR,QAAAA,aAAAA;EAC3ID,UAAAA,CAAAA,OAAAA,EAETI,eAFSJ,CAEOQ,WAFPR,CAAAA,GAAAA,SAAAA,CAAAA,EAAAA,IAAAA;EAARS,gBAAAA,CAAAA,CAAAA,EAAAA,OAAAA;EAEeD,QAAAA,EAAAA,CAAAA,KAAAA,EAAAA,OAAAA,EAAAA,GAAAA,OAAAA;EAAhBJ,sBAAAA,CAAAA,QAAAA,EAGaR,gBAHbQ,CAAAA,EAAAA,MAAAA;EAGaR,eAAAA,CAAAA,UAAAA,EAAAA,MAAAA,EAAAA,IAAAA,CAAAA,EACUE,aADVF,CAAAA,EAAAA;IACUE,GAAAA,EAAAA,MAAAA;IAIOD,MAAAA,EAAAA,MAAAA;EAExBE,CAAAA,GAAAA,SAAAA;EAEiBJ,sBAAAA,CAAAA,gBAAAA,EAAAA,MAAAA,CAAAA,EAJOE,uBAIPF,GAAAA,SAAAA;EAIlCe,oBAAAA,CAAAA,CAAAA,EAAAA,MAAAA;EAAeC,sBAAAA,CAAAA,CAAAA,EANEZ,WAMFY,GAAAA,SAAAA;EAASC,OAAAA,CAAAA,OAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAASC,UAAAA,EAAAA,CAAAA,SAAAA,EAAAA,MAAAA,EAAAA,SAAAA,EAJClB,mBAIDkB,EAAAA,0BAAAA,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA,EAAAA,GAAAA,IAAAA;EAAUC,aAAAA,CAAAA,OAAAA,EAAAA,OAAAA,CAAAA,EAAAA,IAAAA;EAA8CN,QAAAA,CAAAA,CAAAA,EAAAA,IAAAA;EAApBH,QAAAA,sBAAAA;EA7BRF,MAAAA,CAAAA;IAAAA,aAAAA;IAAAA,OAAAA;IAAAA,OAAAA;IAAAA,QAAAA;IAAAA,WAAAA;IAAAA,GAAAA;EAAAA,CAAAA,CAAAA,EA6BQE,mBA7BRF,CA6B4BK,WA7B5BL,CAAAA,CAAAA,EAAAA,OAAAA;EAAQ,kBAAA,CAAA,CAAA,EAAA,IAAA"}
@@ -1,28 +1,45 @@
1
1
  import { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from "../constants.js";
2
+ import { areObjectsEqual } from "../utils/areObjectsEqual.js";
3
+ import { getVirtualFileHeaderRegion, getVirtualFilePaddingBottom, resolveVirtualFileMetrics } from "../utils/resolveVirtualFileMetrics.js";
2
4
  import { iterateOverDiff } from "../utils/iterateOverDiff.js";
3
5
  import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
4
6
  import { FileDiff } from "./FileDiff.js";
5
- import { resolveVirtualFileMetrics } from "../utils/resolveVirtualFileMetrics.js";
6
7
 
7
8
  //#region src/components/VirtualizedFileDiff.ts
9
+ const LAYOUT_CHECKPOINT_INTERVAL = 5e3;
8
10
  let instanceId = -1;
9
11
  var VirtualizedFileDiff = class extends FileDiff {
10
12
  __id = `little-virtualized-file-diff:${++instanceId}`;
11
13
  top;
12
14
  height = 0;
13
15
  metrics;
14
- heightCache = /* @__PURE__ */ new Map();
16
+ cache = {
17
+ heights: /* @__PURE__ */ new Map(),
18
+ checkpoints: [],
19
+ totalLines: 0
20
+ };
15
21
  isVisible = false;
16
22
  isSetup = false;
17
23
  virtualizer;
24
+ forceRenderOverride;
18
25
  constructor(options, virtualizer, metrics, workerManager, isContainerManaged = false) {
19
26
  super(options, workerManager, isContainerManaged);
20
27
  const { hunkSeparators = "line-info" } = this.options;
21
28
  this.virtualizer = virtualizer;
22
29
  this.metrics = resolveVirtualFileMetrics(typeof hunkSeparators === "function" ? "custom" : hunkSeparators, metrics);
23
30
  }
31
+ setMetrics(metrics, force = false) {
32
+ const { hunkSeparators = "line-info" } = this.options;
33
+ const nextMetrics = resolveVirtualFileMetrics(typeof hunkSeparators === "function" ? "custom" : hunkSeparators, metrics);
34
+ if (!force && areObjectsEqual(this.metrics, nextMetrics)) return;
35
+ this.metrics = nextMetrics;
36
+ this.cache.heights.clear();
37
+ this.cache.checkpoints = [];
38
+ this.cache.totalLines = 0;
39
+ this.renderRange = void 0;
40
+ }
24
41
  getLineHeight(lineIndex, hasMetadataLine = false) {
25
- const cached = this.heightCache.get(lineIndex);
42
+ const cached = this.cache.heights.get(lineIndex);
26
43
  if (cached != null) return cached;
27
44
  const multiplier = hasMetadataLine ? 2 : 1;
28
45
  return this.metrics.lineHeight * multiplier;
@@ -34,22 +51,25 @@ var VirtualizedFileDiff = class extends FileDiff {
34
51
  const previousCollapsed = this.options.collapsed;
35
52
  super.setOptions(options);
36
53
  if (previousDiffStyle !== this.options.diffStyle || previousOverflow !== this.options.overflow || previousCollapsed !== this.options.collapsed) {
37
- this.heightCache.clear();
38
- this.computeApproximateSize();
54
+ this.cache.heights.clear();
55
+ this.cache.checkpoints = [];
56
+ this.cache.totalLines = 0;
57
+ if (this.isSimpleMode()) this.computeApproximateSize();
39
58
  this.renderRange = void 0;
40
59
  }
41
- this.virtualizer.instanceChanged(this);
60
+ if (this.isSimpleMode()) this.virtualizer.instanceChanged(this, true);
42
61
  }
43
62
  reconcileHeights() {
63
+ let hasHeightChange = false;
44
64
  const { overflow = "scroll" } = this.options;
45
- if (this.fileContainer != null) this.top = this.virtualizer.getOffsetInScrollContainer(this.fileContainer);
46
65
  if (this.fileContainer == null || this.fileDiff == null) {
66
+ if (this.height !== 0) hasHeightChange = true;
47
67
  this.height = 0;
48
- return;
68
+ return hasHeightChange;
49
69
  }
50
- if (overflow === "scroll" && this.lineAnnotations.length === 0 && !this.virtualizer.config.resizeDebugging) return;
70
+ this.top = this.getVirtualizedTop();
71
+ if (overflow === "scroll" && this.lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) return hasHeightChange;
51
72
  const diffStyle = this.getDiffStyle();
52
- let hasLineHeightChange = false;
53
73
  const codeGroups = diffStyle === "split" ? [this.codeDeletions, this.codeAdditions] : [this.codeUnified];
54
74
  for (const codeGroup of codeGroups) {
55
75
  if (codeGroup == null) continue;
@@ -68,51 +88,187 @@ var VirtualizedFileDiff = class extends FileDiff {
68
88
  }
69
89
  const expectedHeight = this.getLineHeight(lineIndex, hasMetadata);
70
90
  if (measuredHeight === expectedHeight) continue;
71
- hasLineHeightChange = true;
72
- if (measuredHeight === this.metrics.lineHeight * (hasMetadata ? 2 : 1)) this.heightCache.delete(lineIndex);
73
- else this.heightCache.set(lineIndex, measuredHeight);
91
+ hasHeightChange = true;
92
+ if (measuredHeight === this.metrics.lineHeight * (hasMetadata ? 2 : 1)) this.cache.heights.delete(lineIndex);
93
+ else this.cache.heights.set(lineIndex, measuredHeight);
74
94
  }
75
95
  }
76
- if (hasLineHeightChange || this.virtualizer.config.resizeDebugging) this.computeApproximateSize();
96
+ if (hasHeightChange || this.isResizeDebuggingEnabled()) this.computeApproximateSize();
97
+ return hasHeightChange;
77
98
  }
78
99
  onRender = (dirty) => {
79
100
  if (this.fileContainer == null) return false;
80
- if (dirty) this.top = this.virtualizer.getOffsetInScrollContainer(this.fileContainer);
101
+ if (dirty) this.top = this.getVirtualizedTop();
81
102
  return this.render();
82
103
  };
83
- cleanUp() {
84
- if (this.fileContainer != null) this.virtualizer.disconnect(this.fileContainer);
104
+ prepareVirtualizedItem(fileDiff) {
105
+ this.fileDiff = fileDiff;
106
+ this.top = this.getVirtualizedTop();
107
+ this.computeApproximateSize();
108
+ return this.height;
109
+ }
110
+ getLinePosition(lineNumber, side = "additions") {
111
+ if (this.fileDiff == null) return;
112
+ const targetLineIndexes = this.getLineIndex(lineNumber, side);
113
+ if (targetLineIndexes == null) return;
114
+ const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, hunkSeparators = "line-info" } = this.options;
115
+ const { hunkSeparatorHeight, spacing } = this.metrics;
116
+ const diffStyle = this.getDiffStyle();
117
+ const separatorGap = hunkSeparators !== "simple" && hunkSeparators !== "metadata" && hunkSeparators !== "line-info-basic" ? spacing : 0;
118
+ const targetLineIndex = diffStyle === "split" ? targetLineIndexes[1] : targetLineIndexes[0];
119
+ const checkpoint = this.getLayoutCheckpointBeforeLineIndex(targetLineIndex);
120
+ let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
121
+ if (collapsed) return {
122
+ top,
123
+ height: 0
124
+ };
125
+ let position;
126
+ iterateOverDiff({
127
+ diff: this.fileDiff,
128
+ diffStyle,
129
+ startingLine: checkpoint?.renderedLineIndex ?? 0,
130
+ expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
131
+ collapsedContextThreshold,
132
+ callback: ({ hunkIndex, collapsedBefore, collapsedAfter, deletionLine, additionLine }) => {
133
+ const lineIndex = diffStyle === "split" ? additionLine?.splitLineIndex ?? deletionLine?.splitLineIndex : additionLine?.unifiedLineIndex ?? deletionLine?.unifiedLineIndex;
134
+ if (lineIndex == null) throw new Error("VirtualizedFileDiff.getLinePosition: missing line index data");
135
+ if (collapsedBefore > 0) {
136
+ if (hunkIndex > 0) top += separatorGap;
137
+ if (targetLineIndex >= lineIndex - collapsedBefore && targetLineIndex < lineIndex) {
138
+ position = {
139
+ top,
140
+ height: hunkSeparatorHeight
141
+ };
142
+ return true;
143
+ }
144
+ top += hunkSeparatorHeight + separatorGap;
145
+ }
146
+ const lineHeight = this.getLineHeight(lineIndex, (additionLine?.noEOFCR ?? false) || (deletionLine?.noEOFCR ?? false));
147
+ if (lineIndex === targetLineIndex) {
148
+ position = {
149
+ top,
150
+ height: lineHeight
151
+ };
152
+ return true;
153
+ }
154
+ top += lineHeight;
155
+ if (collapsedAfter > 0 && hunkSeparators !== "simple") {
156
+ if (targetLineIndex > lineIndex && targetLineIndex <= lineIndex + collapsedAfter) {
157
+ position = {
158
+ top: top + separatorGap,
159
+ height: hunkSeparatorHeight
160
+ };
161
+ return true;
162
+ }
163
+ top += separatorGap + hunkSeparatorHeight;
164
+ }
165
+ return false;
166
+ }
167
+ });
168
+ return position;
169
+ }
170
+ getNumericScrollAnchor(localViewportTop) {
171
+ if (this.fileDiff == null) return;
172
+ const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, hunkSeparators = "line-info" } = this.options;
173
+ if (collapsed) return;
174
+ const { hunkSeparatorHeight, spacing } = this.metrics;
175
+ const diffStyle = this.getDiffStyle();
176
+ const separatorGap = hunkSeparators !== "simple" && hunkSeparators !== "metadata" && hunkSeparators !== "line-info-basic" ? spacing : 0;
177
+ const checkpoint = this.getLayoutCheckpointBeforeTop(localViewportTop);
178
+ let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
179
+ let anchor;
180
+ iterateOverDiff({
181
+ diff: this.fileDiff,
182
+ diffStyle,
183
+ startingLine: checkpoint?.renderedLineIndex ?? 0,
184
+ expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
185
+ collapsedContextThreshold,
186
+ callback: ({ hunkIndex, collapsedBefore, collapsedAfter, deletionLine, additionLine }) => {
187
+ const lineIndex = diffStyle === "split" ? additionLine?.splitLineIndex ?? deletionLine?.splitLineIndex : additionLine?.unifiedLineIndex ?? deletionLine?.unifiedLineIndex;
188
+ if (lineIndex == null) throw new Error("VirtualizedFileDiff.getNumericScrollAnchor: missing line index data");
189
+ if (collapsedBefore > 0) {
190
+ if (hunkIndex > 0) top += separatorGap;
191
+ top += hunkSeparatorHeight + separatorGap;
192
+ }
193
+ if (top >= localViewportTop) {
194
+ if (deletionLine != null) anchor = {
195
+ lineNumber: deletionLine.lineNumber,
196
+ side: "deletions",
197
+ top
198
+ };
199
+ else if (additionLine != null) anchor = {
200
+ lineNumber: additionLine.lineNumber,
201
+ side: "additions",
202
+ top
203
+ };
204
+ if (anchor != null) return true;
205
+ }
206
+ const lineHeight = this.getLineHeight(lineIndex, (additionLine?.noEOFCR ?? false) || (deletionLine?.noEOFCR ?? false));
207
+ top += lineHeight;
208
+ if (collapsedAfter > 0 && hunkSeparators !== "simple") top += separatorGap + hunkSeparatorHeight;
209
+ return false;
210
+ }
211
+ });
212
+ return anchor;
213
+ }
214
+ getVirtualizedHeight() {
215
+ return this.height;
216
+ }
217
+ getAdvancedStickySpecs() {
218
+ if (this.top == null) return;
219
+ if (this.options.collapsed === true) return {
220
+ topOffset: this.top,
221
+ height: this.height
222
+ };
223
+ if (this.renderRange == null) return;
224
+ const { bufferBefore, bufferAfter, totalLines } = this.renderRange;
225
+ return {
226
+ topOffset: this.top + bufferBefore + (totalLines === 0 ? bufferAfter : 0),
227
+ height: this.height - (bufferBefore + bufferAfter)
228
+ };
229
+ }
230
+ cleanUp(recycle = false) {
231
+ if (this.fileContainer != null && this.isSimpleMode()) this.getSimpleVirtualizer()?.disconnect(this.fileContainer);
85
232
  this.isSetup = false;
86
- super.cleanUp();
233
+ super.cleanUp(recycle);
87
234
  }
88
235
  expandHunk = (hunkIndex, direction, expansionLineCountOverride) => {
89
236
  this.hunksRenderer.expandHunk(hunkIndex, direction, expansionLineCountOverride);
90
237
  this.computeApproximateSize();
91
238
  this.renderRange = void 0;
92
- this.virtualizer.instanceChanged(this);
239
+ this.virtualizer.instanceChanged(this, true);
93
240
  };
94
241
  setVisibility(visible) {
95
- if (this.fileContainer == null) return;
242
+ if (this.isAdvancedMode() || this.fileContainer == null) return;
96
243
  this.renderRange = void 0;
97
244
  if (visible && !this.isVisible) {
98
- this.top = this.virtualizer.getOffsetInScrollContainer(this.fileContainer);
245
+ this.top = this.getVirtualizedTop();
99
246
  this.isVisible = true;
100
247
  } else if (!visible && this.isVisible) {
101
248
  this.isVisible = false;
102
249
  this.rerender();
103
250
  }
104
251
  }
252
+ rerender() {
253
+ if (!this.enabled || this.fileDiff == null && this.additionFile == null && this.deletionFile == null) return;
254
+ this.forceRenderOverride = true;
255
+ this.virtualizer.instanceChanged(this, false);
256
+ }
105
257
  computeApproximateSize() {
106
258
  const isFirstCompute = this.height === 0;
107
259
  this.height = 0;
260
+ this.cache.checkpoints = [];
261
+ this.cache.totalLines = 0;
108
262
  if (this.fileDiff == null) return;
109
263
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, hunkSeparators = "line-info" } = this.options;
110
- const { diffHeaderHeight, fileGap, hunkSeparatorHeight } = this.metrics;
264
+ const { spacing, hunkSeparatorHeight } = this.metrics;
111
265
  const diffStyle = this.getDiffStyle();
112
- const separatorGap = hunkSeparators !== "simple" && hunkSeparators !== "metadata" && hunkSeparators !== "line-info-basic" ? fileGap : 0;
113
- if (!disableFileHeader) this.height += diffHeaderHeight;
114
- else if (hunkSeparators !== "simple" && hunkSeparators !== "metadata") this.height += fileGap;
266
+ const separatorGap = hunkSeparators !== "simple" && hunkSeparators !== "metadata" && hunkSeparators !== "line-info-basic" ? spacing : 0;
267
+ const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
268
+ const paddingBottom = getVirtualFilePaddingBottom(this.metrics);
269
+ this.height += headerRegion;
115
270
  if (collapsed) return;
271
+ let renderedLineIndex = 0;
116
272
  iterateOverDiff({
117
273
  diff: this.fileDiff,
118
274
  diffStyle,
@@ -122,16 +278,20 @@ var VirtualizedFileDiff = class extends FileDiff {
122
278
  const splitLineIndex = additionLine != null ? additionLine.splitLineIndex : deletionLine.splitLineIndex;
123
279
  const unifiedLineIndex = additionLine != null ? additionLine.unifiedLineIndex : deletionLine.unifiedLineIndex;
124
280
  const hasMetadata = (additionLine?.noEOFCR ?? false) || (deletionLine?.noEOFCR ?? false);
281
+ const lineIndex = diffStyle === "split" ? splitLineIndex : unifiedLineIndex;
282
+ this.addLayoutCheckpoint(renderedLineIndex, lineIndex, this.height);
125
283
  if (collapsedBefore > 0) {
126
284
  if (hunkIndex > 0) this.height += separatorGap;
127
285
  this.height += hunkSeparatorHeight + separatorGap;
128
286
  }
129
- this.height += this.getLineHeight(diffStyle === "split" ? splitLineIndex : unifiedLineIndex, hasMetadata);
287
+ this.height += this.getLineHeight(lineIndex, hasMetadata);
130
288
  if (collapsedAfter > 0 && hunkSeparators !== "simple") this.height += separatorGap + hunkSeparatorHeight;
289
+ renderedLineIndex++;
131
290
  }
132
291
  });
133
- if (this.fileDiff.hunks.length > 0) this.height += fileGap;
134
- if (this.fileContainer != null && this.virtualizer.config.resizeDebugging && !isFirstCompute) {
292
+ this.cache.totalLines = renderedLineIndex;
293
+ if (this.fileDiff.hunks.length > 0) this.height += paddingBottom;
294
+ if (this.fileContainer != null && this.isResizeDebuggingEnabled() && !isFirstCompute) {
135
295
  const rect = this.fileContainer.getBoundingClientRect();
136
296
  if (rect.height !== this.height) console.log("VirtualizedFileDiff.computeApproximateSize: computed height doesnt match", {
137
297
  name: this.fileDiff.name,
@@ -141,8 +301,9 @@ var VirtualizedFileDiff = class extends FileDiff {
141
301
  else console.log("VirtualizedFileDiff.computeApproximateSize: computed height IS CORRECT");
142
302
  }
143
303
  }
144
- render({ fileContainer, oldFile, newFile, fileDiff,...props } = {}) {
145
- const { isSetup } = this;
304
+ render({ fileContainer, oldFile, newFile, fileDiff, forceRender = false,...props } = {}) {
305
+ const { forceRenderOverride, isSetup } = this;
306
+ this.forceRenderOverride = void 0;
146
307
  this.fileDiff ??= fileDiff ?? (oldFile != null && newFile != null ? parseDiffFromFile(oldFile, newFile, this.options.parseDiffOptions) : void 0);
147
308
  fileContainer = this.getOrCreateFileContainer(fileContainer);
148
309
  if (this.fileDiff == null) {
@@ -151,26 +312,99 @@ var VirtualizedFileDiff = class extends FileDiff {
151
312
  }
152
313
  if (!isSetup) {
153
314
  this.computeApproximateSize();
154
- this.virtualizer.connect(fileContainer, this);
155
- this.top ??= this.virtualizer.getOffsetInScrollContainer(fileContainer);
156
- this.isVisible = this.virtualizer.isInstanceVisible(this.top, this.height);
315
+ const virtualizer = this.getSimpleVirtualizer();
316
+ this.top ??= this.getVirtualizedTop();
317
+ if (this.isAdvancedMode()) this.isVisible = true;
318
+ else {
319
+ if (virtualizer == null) throw new Error("VirtualizedFileDiff.render: simple virtualizer is not available");
320
+ virtualizer.connect(fileContainer, this);
321
+ this.isVisible = virtualizer.isInstanceVisible(this.top ?? 0, this.height);
322
+ }
157
323
  this.isSetup = true;
158
- } else this.top ??= this.virtualizer.getOffsetInScrollContainer(fileContainer);
159
- if (!this.isVisible) return this.renderPlaceholder(this.height);
324
+ } else this.top ??= this.getVirtualizedTop();
325
+ if (!this.isVisible && this.isSimpleMode()) return this.renderPlaceholder(this.height);
160
326
  const windowSpecs = this.virtualizer.getWindowSpecs();
161
- const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, this.top, windowSpecs);
327
+ const fileTop = this.top ?? 0;
328
+ const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, fileTop, windowSpecs);
162
329
  return super.render({
163
330
  fileDiff: this.fileDiff,
164
331
  fileContainer,
165
332
  renderRange,
166
333
  oldFile,
167
334
  newFile,
335
+ forceRender: forceRenderOverride ?? forceRender,
168
336
  ...props
169
337
  });
170
338
  }
339
+ syncVirtualizedTop() {
340
+ this.top = this.getVirtualizedTop();
341
+ }
342
+ shouldDisableVirtualizationBuffers() {
343
+ return this.isAdvancedMode() || super.shouldDisableVirtualizationBuffers();
344
+ }
345
+ isSimpleMode() {
346
+ return this.virtualizer.type === "simple";
347
+ }
348
+ isAdvancedMode() {
349
+ return this.virtualizer.type === "advanced";
350
+ }
351
+ getVirtualizedTop() {
352
+ if (this.virtualizer.type === "advanced") return this.virtualizer.getTopForInstance(this);
353
+ return this.fileContainer != null ? this.virtualizer.getOffsetInScrollContainer(this.fileContainer) : 0;
354
+ }
355
+ getSimpleVirtualizer() {
356
+ return this.virtualizer.type === "simple" ? this.virtualizer : void 0;
357
+ }
358
+ isResizeDebuggingEnabled() {
359
+ return this.getSimpleVirtualizer()?.config.resizeDebugging ?? false;
360
+ }
171
361
  getDiffStyle() {
172
362
  return this.options.diffStyle ?? "split";
173
363
  }
364
+ addLayoutCheckpoint(renderedLineIndex, lineIndex, top) {
365
+ if (renderedLineIndex % LAYOUT_CHECKPOINT_INTERVAL !== 0) return;
366
+ this.cache.checkpoints.push({
367
+ renderedLineIndex,
368
+ lineIndex,
369
+ top
370
+ });
371
+ }
372
+ getLayoutCheckpointBeforeLineIndex(lineIndex) {
373
+ if (lineIndex <= 0 || this.cache.checkpoints.length === 0) return;
374
+ let low = 0;
375
+ let high = this.cache.checkpoints.length - 1;
376
+ let result;
377
+ while (low <= high) {
378
+ const mid = low + high >> 1;
379
+ const checkpoint = this.cache.checkpoints[mid];
380
+ if (checkpoint == null) throw new Error("VirtualizedFileDiff: invalid checkpoint index");
381
+ if (checkpoint.lineIndex <= lineIndex) {
382
+ result = checkpoint;
383
+ low = mid + 1;
384
+ } else high = mid - 1;
385
+ }
386
+ return result;
387
+ }
388
+ getLayoutCheckpointBeforeTop(top, hunkLineCount) {
389
+ let low = 0;
390
+ let high = this.cache.checkpoints.length - 1;
391
+ let resultIndex = -1;
392
+ while (low <= high) {
393
+ const mid = low + high >> 1;
394
+ const checkpoint = this.cache.checkpoints[mid];
395
+ if (checkpoint == null) throw new Error("VirtualizedFileDiff: invalid checkpoint index");
396
+ if (checkpoint.top <= top) {
397
+ resultIndex = mid;
398
+ low = mid + 1;
399
+ } else high = mid - 1;
400
+ }
401
+ if (hunkLineCount == null) return resultIndex >= 0 ? this.cache.checkpoints[resultIndex] : void 0;
402
+ for (let index = resultIndex; index >= 0; index--) {
403
+ const checkpoint = this.cache.checkpoints[index];
404
+ if (checkpoint == null) throw new Error("VirtualizedFileDiff: invalid checkpoint index");
405
+ if (checkpoint.renderedLineIndex % hunkLineCount === 0) return checkpoint;
406
+ }
407
+ }
174
408
  getExpandedRegion(isPartial, hunkIndex, rangeSize) {
175
409
  if (rangeSize <= 0 || isPartial) return {
176
410
  fromStart: 0,
@@ -225,16 +459,17 @@ var VirtualizedFileDiff = class extends FileDiff {
225
459
  }
226
460
  computeRenderRangeFromWindow(fileDiff, fileTop, { top, bottom }) {
227
461
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, hunkSeparators = "line-info" } = this.options;
228
- const { diffHeaderHeight, fileGap, hunkLineCount, hunkSeparatorHeight, lineHeight } = this.metrics;
462
+ const { spacing, hunkLineCount, hunkSeparatorHeight, lineHeight } = this.metrics;
229
463
  const diffStyle = this.getDiffStyle();
230
464
  const fileHeight = this.height;
231
- const lineCount = this.getExpandedLineCount(fileDiff, diffStyle);
232
- const headerRegion = disableFileHeader ? fileGap : diffHeaderHeight;
465
+ const lineCount = this.cache.totalLines > 0 ? this.cache.totalLines : this.getExpandedLineCount(fileDiff, diffStyle);
466
+ const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
467
+ const paddingBottom = fileDiff.hunks.length > 0 ? getVirtualFilePaddingBottom(this.metrics) : 0;
233
468
  if (fileTop < top - fileHeight || fileTop > bottom) return {
234
469
  startingLine: 0,
235
470
  totalLines: 0,
236
471
  bufferBefore: 0,
237
- bufferAfter: fileHeight - headerRegion - fileGap
472
+ bufferAfter: fileHeight - headerRegion - paddingBottom
238
473
  };
239
474
  if (lineCount <= hunkLineCount || fileDiff.hunks.length === 0) return {
240
475
  startingLine: 0,
@@ -248,15 +483,17 @@ var VirtualizedFileDiff = class extends FileDiff {
248
483
  const overflowHunks = totalHunks;
249
484
  const hunkOffsets = [];
250
485
  const viewportCenter = (top + bottom) / 2;
251
- const separatorGap = hunkSeparators === "simple" || hunkSeparators === "metadata" || hunkSeparators === "line-info-basic" ? 0 : fileGap;
252
- let absoluteLineTop = fileTop + headerRegion;
253
- let currentLine = 0;
486
+ const separatorGap = hunkSeparators === "simple" || hunkSeparators === "metadata" || hunkSeparators === "line-info-basic" ? 0 : spacing;
487
+ const checkpoint = this.getLayoutCheckpointBeforeTop(Math.max(0, top - fileTop - totalLines * lineHeight * 2), hunkLineCount);
488
+ let absoluteLineTop = fileTop + (checkpoint?.top ?? headerRegion);
489
+ let currentLine = checkpoint?.renderedLineIndex ?? 0;
254
490
  let firstVisibleHunk;
255
491
  let centerHunk;
256
492
  let overflowCounter;
257
493
  iterateOverDiff({
258
494
  diff: fileDiff,
259
495
  diffStyle,
496
+ startingLine: checkpoint?.renderedLineIndex ?? 0,
260
497
  expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
261
498
  collapsedContextThreshold,
262
499
  callback: ({ hunkIndex, collapsedBefore, collapsedAfter, deletionLine, additionLine }) => {
@@ -267,15 +504,15 @@ var VirtualizedFileDiff = class extends FileDiff {
267
504
  if (hunkIndex === 0 && hunkSeparators === "simple") gapAdjustment = 0;
268
505
  absoluteLineTop += gapAdjustment;
269
506
  const isAtHunkBoundary = currentLine % hunkLineCount === 0;
507
+ const currentHunk = Math.floor(currentLine / hunkLineCount);
270
508
  if (isAtHunkBoundary) {
271
- hunkOffsets.push(absoluteLineTop - (fileTop + headerRegion + gapAdjustment));
509
+ hunkOffsets[currentHunk] = absoluteLineTop - (fileTop + headerRegion + gapAdjustment);
272
510
  if (overflowCounter != null) {
273
511
  if (overflowCounter <= 0) return true;
274
512
  overflowCounter--;
275
513
  }
276
514
  }
277
515
  const lineHeight$1 = this.getLineHeight(diffStyle === "split" ? splitLineIndex : unifiedLineIndex, hasMetadata);
278
- const currentHunk = Math.floor(currentLine / hunkLineCount);
279
516
  if (absoluteLineTop > top - lineHeight$1 && absoluteLineTop < bottom) firstVisibleHunk ??= currentHunk;
280
517
  if (centerHunk == null && absoluteLineTop + lineHeight$1 > viewportCenter) centerHunk = currentHunk;
281
518
  if (overflowCounter == null && absoluteLineTop >= bottom && isAtHunkBoundary) overflowCounter = overflowHunks;
@@ -289,12 +526,11 @@ var VirtualizedFileDiff = class extends FileDiff {
289
526
  startingLine: 0,
290
527
  totalLines: 0,
291
528
  bufferBefore: 0,
292
- bufferAfter: fileHeight - headerRegion - fileGap
529
+ bufferAfter: fileHeight - headerRegion - paddingBottom
293
530
  };
294
- const collectedHunks = hunkOffsets.length;
295
531
  centerHunk ??= firstVisibleHunk;
296
532
  const idealStartHunk = Math.round(centerHunk - totalHunks / 2);
297
- const maxStartHunk = Math.max(0, collectedHunks - totalHunks);
533
+ const maxStartHunk = Math.max(0, Math.ceil(lineCount / hunkLineCount) - totalHunks);
298
534
  const startHunk = Math.max(0, Math.min(idealStartHunk, maxStartHunk));
299
535
  const startingLine = startHunk * hunkLineCount;
300
536
  const clampedTotalLines = idealStartHunk < 0 ? totalLines + idealStartHunk * hunkLineCount : totalLines;
@@ -304,7 +540,7 @@ var VirtualizedFileDiff = class extends FileDiff {
304
540
  startingLine,
305
541
  totalLines: clampedTotalLines,
306
542
  bufferBefore,
307
- bufferAfter: finalHunkIndex < hunkOffsets.length ? fileHeight - headerRegion - hunkOffsets[finalHunkIndex] - fileGap : fileHeight - (absoluteLineTop - fileTop) - fileGap
543
+ bufferAfter: finalHunkIndex < hunkOffsets.length ? fileHeight - headerRegion - hunkOffsets[finalHunkIndex] - paddingBottom : fileHeight - (absoluteLineTop - fileTop) - paddingBottom
308
544
  };
309
545
  }
310
546
  };