@pierre/diffs 1.3.6 → 1.4.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 (260) hide show
  1. package/dist/components/CodeView.d.ts +115 -68
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +189 -59
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +79 -15
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +244 -66
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +101 -21
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +432 -102
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +1 -1
  14. package/dist/components/UnresolvedFile.d.ts +2 -2
  15. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  16. package/dist/components/UnresolvedFile.js +2 -2
  17. package/dist/components/UnresolvedFile.js.map +1 -1
  18. package/dist/components/VirtualizedFile.d.ts +17 -7
  19. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  20. package/dist/components/VirtualizedFile.js +142 -53
  21. package/dist/components/VirtualizedFile.js.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.d.ts +15 -8
  23. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  24. package/dist/components/VirtualizedFileDiff.js +186 -96
  25. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  26. package/dist/components/VirtulizerDevelopment.d.ts +1 -1
  27. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  28. package/dist/edit/index.d.ts +7 -4
  29. package/dist/edit/index.js +5 -1
  30. package/dist/editor/EditStateManager.d.ts +56 -0
  31. package/dist/editor/EditStateManager.d.ts.map +1 -0
  32. package/dist/editor/EditStateManager.js +135 -0
  33. package/dist/editor/EditStateManager.js.map +1 -0
  34. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts +7 -0
  35. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts.map +1 -0
  36. package/dist/editor/cloneRetainedDiffSessionSnapshot.js +16 -0
  37. package/dist/editor/cloneRetainedDiffSessionSnapshot.js.map +1 -0
  38. package/dist/editor/editPrediction.d.ts +76 -0
  39. package/dist/editor/editPrediction.d.ts.map +1 -0
  40. package/dist/editor/editPrediction.js +365 -0
  41. package/dist/editor/editPrediction.js.map +1 -0
  42. package/dist/editor/editStack.d.ts +19 -40
  43. package/dist/editor/editStack.d.ts.map +1 -1
  44. package/dist/editor/editStack.js +67 -4
  45. package/dist/editor/editStack.js.map +1 -1
  46. package/dist/editor/editor.d.ts +118 -29
  47. package/dist/editor/editor.d.ts.map +1 -1
  48. package/dist/editor/editor.js +1108 -384
  49. package/dist/editor/editor.js.map +1 -1
  50. package/dist/editor/editor2.js +1 -1
  51. package/dist/editor/languages.d.ts +3 -3
  52. package/dist/editor/languages.d.ts.map +1 -1
  53. package/dist/editor/languages.js.map +1 -1
  54. package/dist/editor/lineAnnotations.d.ts +3 -3
  55. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  56. package/dist/editor/lineAnnotations.js +16 -7
  57. package/dist/editor/lineAnnotations.js.map +1 -1
  58. package/dist/editor/marker.d.ts +2 -2
  59. package/dist/editor/marker.d.ts.map +1 -1
  60. package/dist/editor/marker.js.map +1 -1
  61. package/dist/editor/matchBrackets.d.ts +2 -2
  62. package/dist/editor/matchBrackets.d.ts.map +1 -1
  63. package/dist/editor/matchBrackets.js.map +1 -1
  64. package/dist/editor/pieceTable.d.ts +1 -1
  65. package/dist/editor/pieceTable.js.map +1 -1
  66. package/dist/editor/searchPanel.d.ts +2 -2
  67. package/dist/editor/searchPanel.js +1 -1
  68. package/dist/editor/searchPanel.js.map +1 -1
  69. package/dist/editor/selection.d.ts +32 -23
  70. package/dist/editor/selection.d.ts.map +1 -1
  71. package/dist/editor/selection.js +3 -3
  72. package/dist/editor/selection.js.map +1 -1
  73. package/dist/editor/selectionAction.d.ts +3 -3
  74. package/dist/editor/selectionAction.d.ts.map +1 -1
  75. package/dist/editor/selectionAction.js.map +1 -1
  76. package/dist/editor/textDocument.d.ts +11 -8
  77. package/dist/editor/textDocument.d.ts.map +1 -1
  78. package/dist/editor/textDocument.js +28 -5
  79. package/dist/editor/textDocument.js.map +1 -1
  80. package/dist/editor/textDocumentChangeTransaction.d.ts +15 -0
  81. package/dist/editor/textDocumentChangeTransaction.d.ts.map +1 -0
  82. package/dist/editor/textDocumentChangeTransaction.js +12 -0
  83. package/dist/editor/textDocumentChangeTransaction.js.map +1 -0
  84. package/dist/editor/textMeasure.d.ts +5 -0
  85. package/dist/editor/textMeasure.d.ts.map +1 -1
  86. package/dist/editor/textMeasure.js +10 -0
  87. package/dist/editor/textMeasure.js.map +1 -1
  88. package/dist/editor/tokenizer.d.ts +1 -1
  89. package/dist/editor/tokenizer.js.map +1 -1
  90. package/dist/editor/types.d.ts +267 -0
  91. package/dist/editor/types.d.ts.map +1 -0
  92. package/dist/editor/types.js +0 -0
  93. package/dist/editor/utils.d.ts +2 -1
  94. package/dist/editor/utils.d.ts.map +1 -1
  95. package/dist/editor/utils.js +4 -1
  96. package/dist/editor/utils.js.map +1 -1
  97. package/dist/highlighter/shared_highlighter.d.ts +6 -2
  98. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  99. package/dist/highlighter/shared_highlighter.js +7 -3
  100. package/dist/highlighter/shared_highlighter.js.map +1 -1
  101. package/dist/highlighter/themes/areThemesAttached.js +1 -1
  102. package/dist/index.d.ts +8 -6
  103. package/dist/index.js +22 -21
  104. package/dist/managers/InteractionManager.d.ts.map +1 -1
  105. package/dist/managers/InteractionManager.js +7 -0
  106. package/dist/managers/InteractionManager.js.map +1 -1
  107. package/dist/react/CodeView.d.ts +36 -25
  108. package/dist/react/CodeView.d.ts.map +1 -1
  109. package/dist/react/CodeView.js +15 -14
  110. package/dist/react/CodeView.js.map +1 -1
  111. package/dist/react/EditContext.d.ts +8 -11
  112. package/dist/react/EditContext.d.ts.map +1 -1
  113. package/dist/react/EditContext.js +2 -9
  114. package/dist/react/EditContext.js.map +1 -1
  115. package/dist/react/File.d.ts +10 -6
  116. package/dist/react/File.d.ts.map +1 -1
  117. package/dist/react/File.js +8 -4
  118. package/dist/react/File.js.map +1 -1
  119. package/dist/react/FileDiff.d.ts +10 -5
  120. package/dist/react/FileDiff.d.ts.map +1 -1
  121. package/dist/react/FileDiff.js +8 -4
  122. package/dist/react/FileDiff.js.map +1 -1
  123. package/dist/react/MultiFileDiff.d.ts +8 -5
  124. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  125. package/dist/react/MultiFileDiff.js +8 -12
  126. package/dist/react/MultiFileDiff.js.map +1 -1
  127. package/dist/react/PatchDiff.d.ts +7 -4
  128. package/dist/react/PatchDiff.d.ts.map +1 -1
  129. package/dist/react/PatchDiff.js +8 -4
  130. package/dist/react/PatchDiff.js.map +1 -1
  131. package/dist/react/UnresolvedFile.d.ts +3 -3
  132. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  133. package/dist/react/UnresolvedFile.js.map +1 -1
  134. package/dist/react/index.d.ts +8 -5
  135. package/dist/react/types.d.ts +46 -9
  136. package/dist/react/types.d.ts.map +1 -1
  137. package/dist/react/utils/renderDiffChildren.d.ts +14 -12
  138. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  139. package/dist/react/utils/renderDiffChildren.js +2 -2
  140. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  141. package/dist/react/utils/renderFileChildren.d.ts +14 -12
  142. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  143. package/dist/react/utils/renderFileChildren.js +2 -2
  144. package/dist/react/utils/renderFileChildren.js.map +1 -1
  145. package/dist/react/utils/useFileDiffInstance.d.ts +22 -10
  146. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  147. package/dist/react/utils/useFileDiffInstance.js +112 -22
  148. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  149. package/dist/react/utils/useFileInstance.d.ts +15 -9
  150. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  151. package/dist/react/utils/useFileInstance.js +84 -25
  152. package/dist/react/utils/useFileInstance.js.map +1 -1
  153. package/dist/renderers/DiffHunksRenderer.d.ts +30 -15
  154. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  155. package/dist/renderers/DiffHunksRenderer.js +172 -109
  156. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  157. package/dist/renderers/FileRenderer.d.ts +27 -11
  158. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  159. package/dist/renderers/FileRenderer.js +141 -67
  160. package/dist/renderers/FileRenderer.js.map +1 -1
  161. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +2 -2
  162. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
  163. package/dist/renderers/UnresolvedFileHunksRenderer.js +2 -2
  164. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
  165. package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
  166. package/dist/shiki-stream/tokenizer.js +2 -1
  167. package/dist/shiki-stream/tokenizer.js.map +1 -1
  168. package/dist/ssr/index.d.ts +2 -2
  169. package/dist/ssr/preloadDiffs.d.ts +21 -21
  170. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  171. package/dist/ssr/preloadDiffs.js +1 -1
  172. package/dist/ssr/preloadDiffs.js.map +1 -1
  173. package/dist/ssr/preloadFile.d.ts +6 -6
  174. package/dist/ssr/preloadFile.d.ts.map +1 -1
  175. package/dist/ssr/preloadFile.js.map +1 -1
  176. package/dist/ssr/preloadPatchFile.d.ts +4 -4
  177. package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
  178. package/dist/ssr/preloadPatchFile.js.map +1 -1
  179. package/dist/style.js +1 -1
  180. package/dist/types.d.ts +13 -263
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/utils/appendItems.d.ts +5 -0
  183. package/dist/utils/appendItems.d.ts.map +1 -0
  184. package/dist/utils/appendItems.js +8 -0
  185. package/dist/utils/appendItems.js.map +1 -0
  186. package/dist/utils/areDiffTargetsEqual.js +1 -1
  187. package/dist/utils/areDiffTargetsEqual.js.map +1 -1
  188. package/dist/utils/areFileTargetsEqual.d.ts +7 -0
  189. package/dist/utils/areFileTargetsEqual.d.ts.map +1 -0
  190. package/dist/utils/areFileTargetsEqual.js +8 -0
  191. package/dist/utils/areFileTargetsEqual.js.map +1 -0
  192. package/dist/utils/areManagedSnapshotsEqual.d.ts +1 -1
  193. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  194. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  195. package/dist/utils/areOptionsEqual.d.ts +3 -3
  196. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  197. package/dist/utils/areOptionsEqual.js.map +1 -1
  198. package/dist/utils/cloneFileDiffMetadata.d.ts +3 -2
  199. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -1
  200. package/dist/utils/cloneFileDiffMetadata.js +8 -5
  201. package/dist/utils/cloneFileDiffMetadata.js.map +1 -1
  202. package/dist/utils/composeCacheKey.d.ts +6 -0
  203. package/dist/utils/composeCacheKey.d.ts.map +1 -0
  204. package/dist/utils/composeCacheKey.js +10 -0
  205. package/dist/utils/composeCacheKey.js.map +1 -0
  206. package/dist/utils/editSessionAnnotations.d.ts +69 -0
  207. package/dist/utils/editSessionAnnotations.d.ts.map +1 -0
  208. package/dist/utils/editSessionAnnotations.js +64 -0
  209. package/dist/utils/editSessionAnnotations.js.map +1 -0
  210. package/dist/utils/editSessionHunks.d.ts +5 -3
  211. package/dist/utils/editSessionHunks.d.ts.map +1 -1
  212. package/dist/utils/editSessionHunks.js +7 -5
  213. package/dist/utils/editSessionHunks.js.map +1 -1
  214. package/dist/utils/getDiffHunksRendererOptions.d.ts +1 -1
  215. package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
  216. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  217. package/dist/utils/getFileRendererOptions.d.ts +1 -1
  218. package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
  219. package/dist/utils/getFileRendererOptions.js.map +1 -1
  220. package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
  221. package/dist/utils/hydratePartialDiff.js +2 -1
  222. package/dist/utils/hydratePartialDiff.js.map +1 -1
  223. package/dist/utils/lineAnnotationIdentity.d.ts +16 -0
  224. package/dist/utils/lineAnnotationIdentity.d.ts.map +1 -0
  225. package/dist/utils/lineAnnotationIdentity.js +17 -0
  226. package/dist/utils/lineAnnotationIdentity.js.map +1 -0
  227. package/dist/utils/parseDiffFromFile.d.ts +2 -2
  228. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  229. package/dist/utils/parseDiffFromFile.js +6 -6
  230. package/dist/utils/parseDiffFromFile.js.map +1 -1
  231. package/dist/utils/parsePatchFiles.d.ts +6 -3
  232. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  233. package/dist/utils/parsePatchFiles.js +34 -9
  234. package/dist/utils/parsePatchFiles.js.map +1 -1
  235. package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
  236. package/dist/utils/renderDiffWithHighlighter.js +6 -5
  237. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  238. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  239. package/dist/utils/renderFileWithHighlighter.js +7 -4
  240. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  241. package/dist/utils/trimPatchContext.d.ts.map +1 -1
  242. package/dist/utils/trimPatchContext.js +3 -2
  243. package/dist/utils/trimPatchContext.js.map +1 -1
  244. package/dist/utils/updateDiffHunks.js +1 -1
  245. package/dist/utils/virtualDiffLayout.js +1 -1
  246. package/dist/worker/WorkerPoolManager.d.ts +4 -3
  247. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  248. package/dist/worker/WorkerPoolManager.js +44 -6
  249. package/dist/worker/WorkerPoolManager.js.map +1 -1
  250. package/dist/worker/types.d.ts +5 -0
  251. package/dist/worker/types.d.ts.map +1 -1
  252. package/dist/worker/worker-portable.js +14 -6
  253. package/dist/worker/worker-portable.js.map +1 -1
  254. package/dist/worker/worker.js +14 -6
  255. package/dist/worker/worker.js.map +1 -1
  256. package/package.json +9 -1
  257. package/dist/editor/stateStorage.d.ts +0 -15
  258. package/dist/editor/stateStorage.d.ts.map +0 -1
  259. package/dist/editor/stateStorage.js +0 -65
  260. package/dist/editor/stateStorage.js.map +0 -1
@@ -1,23 +1,25 @@
1
1
  import "../constants.js";
2
2
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
3
3
  import { areOptionsEqual } from "../utils/areOptionsEqual.js";
4
- import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
5
4
  import { computeVirtualFileMetrics, getVirtualFileHeaderRegion, getVirtualFilePaddingBottom } from "../utils/computeVirtualFileMetrics.js";
6
- import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, isAdditionLineRenderable } from "../utils/virtualDiffLayout.js";
7
- import { areFilesEqual } from "../utils/areFilesEqual.js";
8
5
  import { FILE_ANNOTATION_DOM_KEY, includesFileAnnotations, shouldRenderFileAnnotations } from "../utils/includesFileAnnotations.js";
9
6
  import { areDiffTargetsEqual } from "../utils/areDiffTargetsEqual.js";
7
+ import { areFilesEqual } from "../utils/areFilesEqual.js";
10
8
  import { awaitWithTimeout } from "../utils/awaitWithTimeout.js";
9
+ import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, isAdditionLineRenderable } from "../utils/virtualDiffLayout.js";
11
10
  import { computeEstimatedDiffHeights } from "../utils/computeEstimatedDiffHeights.js";
12
11
  import { getDiffFileInput } from "../utils/getDiffFileInput.js";
13
12
  import { hydratePartialDiff } from "../utils/hydratePartialDiff.js";
14
13
  import { iterateOverDiff } from "../utils/iterateOverDiff.js";
14
+ import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
15
15
  import { FileDiff } from "./FileDiff.js";
16
16
  //#region src/components/VirtualizedFileDiff.ts
17
17
  const VIRTUALIZED_FILE_DIFF_LAYOUT_CHECKPOINT_INTERVAL = 3e3;
18
+ const NO_GHOST_TEXT_ROWS = /* @__PURE__ */ new Map();
18
19
  let instanceId = -1;
19
20
  var VirtualizedFileDiff = class extends FileDiff {
20
21
  __id = `little-virtualized-file-diff:${++instanceId}`;
22
+ renderType = "virtualized";
21
23
  top;
22
24
  height = 0;
23
25
  metrics;
@@ -28,7 +30,9 @@ var VirtualizedFileDiff = class extends FileDiff {
28
30
  estimatedUnifiedHeight: void 0,
29
31
  checkpoints: [],
30
32
  totalLines: 0,
31
- fileAnnotationHeight: 0
33
+ fileAnnotationHeight: 0,
34
+ ghostTextRows: NO_GHOST_TEXT_ROWS,
35
+ ghostTextRowsByIndex: /* @__PURE__ */ new Map()
32
36
  };
33
37
  isVisible = false;
34
38
  isSetup = false;
@@ -36,9 +40,9 @@ var VirtualizedFileDiff = class extends FileDiff {
36
40
  layoutDirty = true;
37
41
  forceRenderOverride;
38
42
  currentCollapsed;
39
- currentExpandUnchanged;
40
43
  pendingHydratedDiff;
41
44
  pendingExpansions;
45
+ pendingRender;
42
46
  constructor(options, virtualizer, metrics, workerManager, isContainerManaged = false) {
43
47
  super(options, workerManager, isContainerManaged);
44
48
  this.virtualizer = virtualizer;
@@ -54,10 +58,17 @@ var VirtualizedFileDiff = class extends FileDiff {
54
58
  if (this.syncLineAnnotations(lineAnnotations)) this.resetLayoutCache({ includeEstimatedHeights: false });
55
59
  }
56
60
  syncLineAnnotations(lineAnnotations) {
57
- if (lineAnnotations == null || lineAnnotations === this.lineAnnotations || lineAnnotations.length === 0 && this.lineAnnotations.length === 0) return false;
61
+ if (lineAnnotations == null || !this.isNewAnnotations(lineAnnotations) || lineAnnotations.length === 0 && this.getLatestAnnotations().length === 0) return false;
58
62
  super.setLineAnnotations(lineAnnotations);
59
63
  return true;
60
64
  }
65
+ syncEditSessionAnnotationsFromEditor(lineAnnotations) {
66
+ if (super.syncEditSessionAnnotationsFromEditor(lineAnnotations)) {
67
+ this.resetLayoutCache({ includeEstimatedHeights: false });
68
+ return true;
69
+ }
70
+ return false;
71
+ }
61
72
  setFileAnnotationHeight(nextHeight) {
62
73
  const previousHeight = this.cache.fileAnnotationHeight;
63
74
  if (nextHeight === previousHeight) return false;
@@ -65,9 +76,10 @@ var VirtualizedFileDiff = class extends FileDiff {
65
76
  this.cache.measuredHeightDeltaTotal += nextHeight - previousHeight;
66
77
  return true;
67
78
  }
68
- hasFileAnnotations(fileDiff = this.fileDiff) {
69
- if (fileDiff == null || !includesFileAnnotations(this.lineAnnotations)) return false;
70
- return this.lineAnnotations.some((annotation) => {
79
+ hasFileAnnotations(fileDiff) {
80
+ const lineAnnotations = this.getLatestAnnotations();
81
+ if (!includesFileAnnotations(lineAnnotations)) return false;
82
+ return lineAnnotations.some((annotation) => {
71
83
  if (annotation.lineNumber !== 0) return false;
72
84
  if (fileDiff.type === "new") return annotation.side === "additions";
73
85
  if (fileDiff.type === "deleted") return annotation.side === "deletions";
@@ -102,8 +114,10 @@ var VirtualizedFileDiff = class extends FileDiff {
102
114
  resetLayoutCache({ forceSimpleRecompute = false, includeEstimatedHeights = false, resetRenderRange = true } = {}) {
103
115
  this.layoutDirty = true;
104
116
  this.cache.fileAnnotationHeight = 0;
105
- if (this.cache.heightDeltas.size > 0) this.cache.heightDeltas.clear();
106
- if (this.cache.measuredHeightDeltaTotal !== 0) this.cache.measuredHeightDeltaTotal = 0;
117
+ this.cache.heightDeltas.clear();
118
+ this.cache.measuredHeightDeltaTotal = 0;
119
+ this.cache.ghostTextRows = NO_GHOST_TEXT_ROWS;
120
+ if (this.cache.ghostTextRowsByIndex.size > 0) this.cache.ghostTextRowsByIndex.clear();
107
121
  this.invalidateDerivedLayoutCache(includeEstimatedHeights, resetRenderRange);
108
122
  if (forceSimpleRecompute && this.isSimpleMode()) this.computeApproximateSize();
109
123
  }
@@ -117,19 +131,49 @@ var VirtualizedFileDiff = class extends FileDiff {
117
131
  }
118
132
  if (this.renderRange != null && resetRenderRange) this.renderRange = void 0;
119
133
  }
134
+ applyGhostTextRows(fileDiff, ghostTextRows) {
135
+ const { cache: { heightDeltas, ghostTextRows: folded, ghostTextRowsByIndex: previous }, metrics: { lineHeight } } = this;
136
+ if (folded === ghostTextRows) return false;
137
+ const diffStyle = this.getDiffStyle();
138
+ const next = /* @__PURE__ */ new Map();
139
+ for (const [line, rows] of ghostTextRows) {
140
+ const indexes = this.getLineIndexForDiff(fileDiff, line + 1, "additions");
141
+ if (indexes == null) continue;
142
+ next.set(diffStyle === "split" ? indexes[1] : indexes[0], rows);
143
+ }
144
+ let changed = false;
145
+ for (const rowIndex of /* @__PURE__ */ new Set([...previous.keys(), ...next.keys()])) {
146
+ const delta = ((next.get(rowIndex) ?? 0) - (previous.get(rowIndex) ?? 0)) * lineHeight;
147
+ if (delta === 0) continue;
148
+ const nextDelta = (heightDeltas.get(rowIndex) ?? 0) + delta;
149
+ if (nextDelta === 0) heightDeltas.delete(rowIndex);
150
+ else heightDeltas.set(rowIndex, nextDelta);
151
+ this.cache.measuredHeightDeltaTotal += delta;
152
+ changed = true;
153
+ }
154
+ this.cache.ghostTextRows = ghostTextRows;
155
+ this.cache.ghostTextRowsByIndex = next;
156
+ return changed;
157
+ }
120
158
  reconcileHeights() {
121
159
  let hasHeightChange = false;
122
- const { overflow = "scroll" } = this.options;
123
- if (this.fileContainer == null || this.fileDiff == null) {
160
+ const { options: { overflow = "scroll" }, cache: { ghostTextRowsByIndex }, metrics: { lineHeight } } = this;
161
+ const fileDiff = this.getRenderedDiff();
162
+ if (this.fileContainer == null || fileDiff == null) {
124
163
  if (this.height !== 0) hasHeightChange = true;
125
164
  this.height = 0;
126
165
  return hasHeightChange;
127
166
  }
128
167
  this.top = this.getVirtualizedTop();
129
- if (overflow === "scroll" && this.lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) return hasHeightChange;
168
+ hasHeightChange = this.applyGhostTextRows(fileDiff, this.editor?.__getGhostTextRows() ?? NO_GHOST_TEXT_ROWS);
169
+ const lineAnnotations = this.getLatestAnnotations();
170
+ if (overflow === "scroll" && lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) {
171
+ if (hasHeightChange) this.computeApproximateSize(true);
172
+ return hasHeightChange;
173
+ }
130
174
  const diffStyle = this.getDiffStyle();
131
175
  const codeGroups = diffStyle === "split" ? [this.codeDeletions, this.codeAdditions] : [this.codeUnified];
132
- const hasFileAnnotations = this.hasFileAnnotations(this.fileDiff);
176
+ const hasFileAnnotations = this.hasFileAnnotations(fileDiff);
133
177
  if (this.renderRange != null && hasFileAnnotations && shouldRenderFileAnnotations(this.renderRange)) {
134
178
  const nextFileAnnotationHeight = measureFileAnnotationHeight(codeGroups) ?? 0;
135
179
  if (this.setFileAnnotationHeight(nextFileAnnotationHeight)) hasHeightChange = true;
@@ -138,12 +182,15 @@ var VirtualizedFileDiff = class extends FileDiff {
138
182
  if (codeGroup == null) continue;
139
183
  const content = codeGroup.children[1];
140
184
  if (!(content instanceof HTMLElement)) continue;
185
+ const skipsGhostRows = diffStyle === "split" && codeGroup === this.codeDeletions;
141
186
  for (const line of content.children) {
142
187
  if (!(line instanceof HTMLElement)) continue;
143
188
  const lineIndexAttr = line.dataset.lineIndex;
144
189
  if (lineIndexAttr == null) continue;
145
190
  const lineIndex = parseLineIndex(lineIndexAttr, diffStyle);
146
- let measuredHeight = line.getBoundingClientRect().height;
191
+ const ghostRows = ghostTextRowsByIndex.get(lineIndex) ?? 0;
192
+ if (skipsGhostRows && ghostRows > 0) continue;
193
+ let measuredHeight = line.getBoundingClientRect().height + ghostRows * lineHeight;
147
194
  let hasMetadata = false;
148
195
  if (line.nextElementSibling instanceof HTMLElement && ("lineAnnotation" in line.nextElementSibling.dataset || "noNewline" in line.nextElementSibling.dataset)) {
149
196
  if ("noNewline" in line.nextElementSibling.dataset) hasMetadata = true;
@@ -171,41 +218,59 @@ var VirtualizedFileDiff = class extends FileDiff {
171
218
  super.flushManagers();
172
219
  if (this.lineStateRefreshPending) this.flushDeferredLineState();
173
220
  }
174
- prepareCodeViewItem(fileDiff, top, reset, lineAnnotations) {
175
- const targetChanged = !areDiffTargetsEqual(this.fileDiff, fileDiff);
176
- const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
177
- let shouldResetLayoutCache = reset?.resetDiffLayoutCache === true || targetChanged || annotationsChanged;
178
- let includeEstimatedHeights = targetChanged || reset?.resetDiffLayoutCache === true && reset.includeEstimatedDiffHeights;
221
+ updateCodeViewLayout(fileDiff, top, reset, lineAnnotations) {
222
+ let resetLayoutCache = false;
223
+ let resetEstimatedHeights = false;
224
+ const { pendingExpansions, pendingHydratedDiff, options: { collapsed = false } } = this;
225
+ if (pendingHydratedDiff != null) {
226
+ this.pendingHydratedDiff = void 0;
227
+ if (pendingHydratedDiff.expectedDiff === fileDiff) {
228
+ Object.assign(fileDiff, pendingHydratedDiff.nextDiff);
229
+ this.setHydratedState(pendingHydratedDiff.files);
230
+ this.startHydratedEditSession(fileDiff);
231
+ this.forceRenderOverride = true;
232
+ resetLayoutCache = true;
233
+ resetEstimatedHeights = true;
234
+ }
235
+ }
236
+ if (pendingExpansions != null) {
237
+ this.pendingExpansions = void 0;
238
+ for (const { hunkIndex, direction, expansionLineCountOverride } of pendingExpansions) {
239
+ this.hunksRenderer.expandHunk(hunkIndex, direction, expansionLineCountOverride);
240
+ this.forceRenderOverride = true;
241
+ resetEstimatedHeights = true;
242
+ }
243
+ }
244
+ const diffChanged = this.updateExternalDiff(fileDiff, lineAnnotations);
245
+ const { pendingRenderDiff, layoutDiffChanged, renderedDiffChanged, annotationsChanged } = this.updatePendingRender(fileDiff, lineAnnotations);
246
+ if (!this.forceRenderOverride && (diffChanged || renderedDiffChanged || annotationsChanged)) this.forceRenderOverride = true;
247
+ if (reset?.resetDiffLayoutCache === true || layoutDiffChanged || annotationsChanged) resetLayoutCache = true;
248
+ if (layoutDiffChanged || reset?.resetDiffLayoutCache === true && reset.includeEstimatedDiffHeights) resetEstimatedHeights = true;
179
249
  if (reset?.metrics != null) {
180
250
  this.metrics = computeVirtualFileMetrics(reset.metrics);
181
- shouldResetLayoutCache = true;
182
- includeEstimatedHeights = true;
251
+ resetLayoutCache = true;
252
+ resetEstimatedHeights = true;
183
253
  }
184
- const { collapsed = false, expandUnchanged = false } = this.options;
185
254
  if (this.currentCollapsed !== collapsed) {
186
255
  this.currentCollapsed = collapsed;
187
- shouldResetLayoutCache = true;
188
- }
189
- if (this.currentExpandUnchanged !== expandUnchanged) {
190
- this.currentExpandUnchanged = expandUnchanged;
191
- shouldResetLayoutCache = true;
192
- includeEstimatedHeights = true;
256
+ resetLayoutCache = true;
193
257
  }
194
- if (shouldResetLayoutCache) this.resetLayoutCache({ includeEstimatedHeights });
195
- this.fileDiff = fileDiff;
258
+ if (resetLayoutCache) this.resetLayoutCache({ includeEstimatedHeights: resetEstimatedHeights });
259
+ else if (resetEstimatedHeights) this.invalidateDerivedLayoutCache(true);
196
260
  this.top = top;
197
- this.computeApproximateSize();
261
+ this.computeApproximateSize(false, pendingRenderDiff);
198
262
  return this.height;
199
263
  }
200
264
  getLinePosition(lineNumber, side = "additions") {
201
- if (this.fileDiff == null || lineNumber < 1) return;
202
- const targetLineIndexes = this.getLineIndex(lineNumber, side);
265
+ const fileDiff = this.getLayoutDiff();
266
+ if (fileDiff == null || lineNumber < 1) return;
267
+ const targetLineIndexes = this.getLineIndexForDiff(fileDiff, lineNumber, side);
203
268
  if (targetLineIndexes == null) return;
204
269
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = 1 } = this.options;
205
270
  const diffStyle = this.getDiffStyle();
206
271
  const hunkSeparators = this.getHunkSeparatorType();
207
272
  const targetLineIndex = diffStyle === "split" ? targetLineIndexes[1] : targetLineIndexes[0];
208
- this.approximateLayoutCheckpoints();
273
+ this.approximateLayoutCheckpoints(fileDiff);
209
274
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
210
275
  const checkpoint = this.getLayoutCheckpointBeforeLineIndex(targetLineIndex);
211
276
  let top = checkpoint?.top ?? headerRegion + this.cache.fileAnnotationHeight;
@@ -215,7 +280,7 @@ var VirtualizedFileDiff = class extends FileDiff {
215
280
  };
216
281
  let position;
217
282
  iterateOverDiff({
218
- diff: this.fileDiff,
283
+ diff: fileDiff,
219
284
  diffStyle,
220
285
  startingLine: checkpoint?.renderedLineIndex ?? 0,
221
286
  expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
@@ -276,17 +341,18 @@ var VirtualizedFileDiff = class extends FileDiff {
276
341
  return this.virtualizer.type === "simple" ? this.virtualizer.getRoot() : this.virtualizer.getContainerElement();
277
342
  }
278
343
  getNumericScrollAnchor(localViewportTop) {
279
- if (this.fileDiff == null) return;
344
+ const fileDiff = this.getLayoutDiff();
345
+ if (fileDiff == null) return;
280
346
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = 1 } = this.options;
281
347
  if (collapsed) return;
282
348
  const diffStyle = this.getDiffStyle();
283
349
  const hunkSeparators = this.getHunkSeparatorType();
284
- this.approximateLayoutCheckpoints();
350
+ this.approximateLayoutCheckpoints(fileDiff);
285
351
  const checkpoint = this.getLayoutCheckpointBeforeTop(localViewportTop);
286
352
  let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader) + this.cache.fileAnnotationHeight;
287
353
  let anchor;
288
354
  iterateOverDiff({
289
- diff: this.fileDiff,
355
+ diff: fileDiff,
290
356
  diffStyle,
291
357
  startingLine: checkpoint?.renderedLineIndex ?? 0,
292
358
  expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
@@ -334,12 +400,13 @@ var VirtualizedFileDiff = class extends FileDiff {
334
400
  return this.height;
335
401
  }
336
402
  getAdvancedStickySpecs(windowSpecs) {
337
- if (this.top == null || this.fileDiff == null) return;
403
+ const fileDiff = this.getLayoutDiff();
404
+ if (this.top == null || fileDiff == null) return;
338
405
  if (this.options.collapsed === true) return {
339
406
  topOffset: this.top,
340
407
  height: this.height
341
408
  };
342
- const renderRange = windowSpecs != null ? this.computeRenderRangeFromWindow(this.fileDiff, this.top, windowSpecs) : this.renderRange;
409
+ const renderRange = windowSpecs != null ? this.computeRenderRangeFromWindow(fileDiff, this.top, windowSpecs) : this.renderRange;
343
410
  if (renderRange == null) return;
344
411
  const { bufferBefore, bufferAfter, totalLines } = renderRange;
345
412
  let headerOnlyOffset = 0;
@@ -353,14 +420,19 @@ var VirtualizedFileDiff = class extends FileDiff {
353
420
  };
354
421
  }
355
422
  cleanUp(recycle = false) {
423
+ const hadGhostTextRows = this.cache.ghostTextRows.size > 0;
424
+ if (hadGhostTextRows) this.layoutDirty = true;
425
+ const shouldRecomputeLayout = recycle && this.isAdvancedMode() && this.fileContainer != null && (hadGhostTextRows || !areDiffTargetsEqual(this.getRenderedDiff(), this.getLatestDiff()));
356
426
  if (this.fileContainer != null && this.isSimpleMode()) this.getSimpleVirtualizer()?.disconnect(this.fileContainer);
357
427
  if (!recycle) {
358
428
  this.resetLayoutCache({ includeEstimatedHeights: true });
359
429
  this.pendingExpansions = void 0;
360
430
  this.pendingHydratedDiff = void 0;
361
431
  }
432
+ this.pendingRender = void 0;
362
433
  this.isSetup = false;
363
434
  super.cleanUp(recycle);
435
+ if (shouldRecomputeLayout) this.virtualizer.instanceChanged(this, true);
364
436
  }
365
437
  expandHunk = (hunkIndex, direction, expansionLineCountOverride) => {
366
438
  if (this.fileDiff == null) return;
@@ -394,41 +466,16 @@ var VirtualizedFileDiff = class extends FileDiff {
394
466
  } else {
395
467
  hydratePartialDiff("merge", expectedDiff, files);
396
468
  this.setHydratedState(files);
397
- await awaitWithTimeout(() => this.primeHighlightCache(expectedDiff));
398
- if (!this.enabled || this.fileDiff !== expectedDiff) return;
469
+ if (!this.startHydratedEditSession(expectedDiff)) {
470
+ await awaitWithTimeout(() => this.primeHighlightCache(expectedDiff));
471
+ if (!this.enabled || this.fileDiff !== expectedDiff) return;
472
+ }
399
473
  this.resetLayoutCache({ includeEstimatedHeights: true });
400
474
  this.computeApproximateSize();
401
475
  }
402
476
  this.forceRenderOverride = true;
403
477
  this.virtualizer.instanceChanged(this, true);
404
478
  }
405
- consumeCodeViewLayoutChanges(expectedFileDiff) {
406
- let hasLayoutChange = false;
407
- let nextDiff;
408
- const { pendingExpansions, pendingHydratedDiff } = this;
409
- if (pendingExpansions != null) {
410
- this.pendingExpansions = void 0;
411
- for (const pendingExpansion of pendingExpansions) {
412
- this.hunksRenderer.expandHunk(pendingExpansion.hunkIndex, pendingExpansion.direction, pendingExpansion.expansionLineCountOverride);
413
- hasLayoutChange = true;
414
- }
415
- }
416
- if (pendingHydratedDiff != null) {
417
- this.pendingHydratedDiff = void 0;
418
- if (pendingHydratedDiff.expectedDiff === expectedFileDiff) {
419
- this.setHydratedState(pendingHydratedDiff.files);
420
- nextDiff = pendingHydratedDiff.nextDiff;
421
- }
422
- }
423
- if (nextDiff != null) {
424
- this.forceRenderOverride = true;
425
- this.resetLayoutCache({ includeEstimatedHeights: true });
426
- } else if (hasLayoutChange) {
427
- this.forceRenderOverride = true;
428
- this.invalidateDerivedLayoutCache(true);
429
- }
430
- return nextDiff;
431
- }
432
479
  loadFilesIfNecessary() {
433
480
  if (this.pendingHydratedDiff != null) {
434
481
  if (this.pendingHydratedDiff.expectedDiff === this.fileDiff) return;
@@ -439,7 +486,7 @@ var VirtualizedFileDiff = class extends FileDiff {
439
486
  isLineRenderable(lineNumber) {
440
487
  if (super.isLineRenderable(lineNumber)) return true;
441
488
  const { pendingExpansions } = this;
442
- const fileDiff = this.fileDiffCache;
489
+ const fileDiff = this.getRenderedDiff();
443
490
  if (pendingExpansions == null || pendingExpansions.length === 0 || fileDiff == null) return false;
444
491
  const { expansionLineCount = 100, collapsedContextThreshold = 1 } = this.options;
445
492
  const staged = new Map(this.hunksRenderer.getExpandedHunksMap());
@@ -500,8 +547,19 @@ var VirtualizedFileDiff = class extends FileDiff {
500
547
  }
501
548
  rerender() {
502
549
  if (!this.enabled || this.fileDiff == null && this.additionFile == null && this.deletionFile == null) return;
550
+ const latestDiff = this.getLatestDiff();
551
+ const nextRenderDiff = latestDiff == null ? void 0 : this.hunksRenderer.getDiffForNextRender(latestDiff);
552
+ if (this.isSimpleMode()) this.pendingRender = void 0;
503
553
  this.forceRenderOverride = true;
504
- this.virtualizer.instanceChanged(this, false);
554
+ this.virtualizer.instanceChanged(this, !areDiffTargetsEqual(this.getRenderedDiff(), nextRenderDiff));
555
+ }
556
+ syncGhostTextRows() {
557
+ const codeView = this.getAdvancedVirtualizer();
558
+ if (codeView != null) {
559
+ codeView.capturePendingLayoutAnchor();
560
+ this.layoutDirty = true;
561
+ codeView.instanceChanged(this, true);
562
+ } else this.getSimpleVirtualizer()?.requestHeightReconcile(this);
505
563
  }
506
564
  applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer = false) {
507
565
  const { renderRange: previousRenderRange } = this;
@@ -513,16 +571,17 @@ var VirtualizedFileDiff = class extends FileDiff {
513
571
  includeEstimatedHeights: true,
514
572
  resetRenderRange: false
515
573
  });
574
+ const fileDiff = this.getRenderedDiff();
516
575
  if (!this.isSimpleMode()) this.computeApproximateSize(true);
517
- else if (shouldUpdateBuffer && previousRenderRange !== void 0 && this.fileDiff !== void 0) {
576
+ else if (shouldUpdateBuffer && previousRenderRange != null && fileDiff != null) {
518
577
  const windowSpecs = this.virtualizer.getWindowSpecs();
519
- const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, this.top ?? 0, windowSpecs);
578
+ const renderRange = this.computeRenderRangeFromWindow(fileDiff, this.top ?? 0, windowSpecs);
520
579
  if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) this.updateBuffers(renderRange);
521
580
  }
522
581
  this.forceRenderOverride = true;
523
582
  this.virtualizer.instanceChanged(this, true);
524
583
  }
525
- computeApproximateSize(force = false, fileDiff = this.fileDiff) {
584
+ computeApproximateSize(force = false, fileDiff = this.getLayoutDiff()) {
526
585
  const shouldValidateSize = this.isResizeDebuggingEnabled();
527
586
  if (!force && !this.layoutDirty && !shouldValidateSize) return;
528
587
  const isFirstCompute = this.height === 0;
@@ -533,6 +592,7 @@ var VirtualizedFileDiff = class extends FileDiff {
533
592
  this.layoutDirty = false;
534
593
  return;
535
594
  }
595
+ this.applyGhostTextRows(fileDiff, this.editor?.__getGhostTextRows() ?? NO_GHOST_TEXT_ROWS);
536
596
  const { disableFileHeader = false, collapsed = false } = this.options;
537
597
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
538
598
  this.height += headerRegion;
@@ -544,13 +604,16 @@ var VirtualizedFileDiff = class extends FileDiff {
544
604
  if (shouldValidateSize && !isFirstCompute) this.validateComputedHeight(fileDiff);
545
605
  this.layoutDirty = false;
546
606
  }
547
- getActiveEstimatedHeight(fileDiff = this.fileDiff) {
607
+ getLayoutDiff() {
608
+ return this.pendingRender?.diff ?? this.getRenderedDiff();
609
+ }
610
+ getActiveEstimatedHeight(fileDiff = this.getLayoutDiff()) {
548
611
  this.ensureEstimatedDiffHeights(fileDiff);
549
612
  const estimatedHeight = this.getDiffStyle() === "split" ? this.cache.estimatedSplitHeight : this.cache.estimatedUnifiedHeight;
550
613
  if (estimatedHeight == null) throw new Error("VirtualizedFileDiff.getActiveEstimatedHeight: missing estimated height");
551
614
  return estimatedHeight;
552
615
  }
553
- ensureEstimatedDiffHeights(fileDiff = this.fileDiff) {
616
+ ensureEstimatedDiffHeights(fileDiff = this.getLayoutDiff()) {
554
617
  if (fileDiff == null) {
555
618
  this.cache.estimatedSplitHeight = void 0;
556
619
  this.cache.estimatedUnifiedHeight = void 0;
@@ -571,7 +634,7 @@ var VirtualizedFileDiff = class extends FileDiff {
571
634
  this.cache.estimatedSplitHeight = splitHeight;
572
635
  this.cache.estimatedUnifiedHeight = unifiedHeight;
573
636
  }
574
- validateComputedHeight(fileDiff = this.fileDiff) {
637
+ validateComputedHeight(fileDiff = this.getLayoutDiff()) {
575
638
  if (this.fileContainer == null || fileDiff == null) return;
576
639
  const rect = this.fileContainer.getBoundingClientRect();
577
640
  if (rect.height !== this.height) console.log("VirtualizedFileDiff.computeApproximateSize: computed height doesnt match", {
@@ -591,19 +654,26 @@ var VirtualizedFileDiff = class extends FileDiff {
591
654
  if (fileDiff == null && hasFileInput && (filesDidChange || this.fileDiff == null)) nextFileDiff = parseDiffFromFile(fileInput.oldFile, fileInput.newFile, this.options.parseDiffOptions);
592
655
  const { forceRenderOverride, isSetup } = this;
593
656
  this.forceRenderOverride = void 0;
594
- const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
595
- if (annotationsChanged) this.resetLayoutCache({ includeEstimatedHeights: false });
596
- const diffInputChanged = fileDiff != null && fileDiff !== this.fileDiff;
597
657
  const targetChanged = nextFileDiff != null && !areDiffTargetsEqual(this.fileDiff, nextFileDiff);
598
- const dataChanged = diffInputChanged || filesDidChange;
599
- if (targetChanged) this.resetLayoutCache({ includeEstimatedHeights: true });
658
+ const dataChanged = targetChanged || filesDidChange;
600
659
  fileContainer = this.getOrCreateFileContainer(fileContainer);
601
660
  if (nextFileDiff == null) {
602
661
  console.error("VirtualizedFileDiff.render: attempting to virtually render when we dont have the correct data");
603
662
  return false;
604
663
  }
664
+ if (targetChanged) this.updateExternalDiff(nextFileDiff, lineAnnotations);
665
+ const { pendingRenderDiff, layoutDiffChanged, renderedDiffChanged, annotationsChanged } = (() => {
666
+ if (this.pendingRender != null && this.pendingRender.latestDiff === (this.getLatestDiff(nextFileDiff) ?? nextFileDiff)) return {
667
+ pendingRenderDiff: this.pendingRender.diff,
668
+ layoutDiffChanged: false,
669
+ renderedDiffChanged: false,
670
+ annotationsChanged: false
671
+ };
672
+ return this.updatePendingRender(nextFileDiff, lineAnnotations);
673
+ })();
674
+ if (annotationsChanged || layoutDiffChanged) this.resetLayoutCache({ includeEstimatedHeights: layoutDiffChanged });
605
675
  if (!isSetup) {
606
- this.computeApproximateSize(false, nextFileDiff);
676
+ this.computeApproximateSize(false, pendingRenderDiff);
607
677
  const virtualizer = this.getSimpleVirtualizer();
608
678
  this.top ??= this.getVirtualizedTop();
609
679
  if (this.isAdvancedMode()) this.isVisible = true;
@@ -615,34 +685,54 @@ var VirtualizedFileDiff = class extends FileDiff {
615
685
  this.isSetup = true;
616
686
  } else {
617
687
  this.top ??= this.getVirtualizedTop();
618
- if (targetChanged) {
688
+ if (layoutDiffChanged) {
619
689
  this.getSimpleVirtualizer()?.markDOMDirty();
620
- this.computeApproximateSize(false, nextFileDiff);
690
+ this.computeApproximateSize(false, pendingRenderDiff);
621
691
  }
622
692
  }
623
693
  if (!this.isVisible && this.isSimpleMode() && (!dataChanged || !isSetup)) {
624
- this.fileDiff = nextFileDiff;
625
694
  if (fileInput != null) {
626
695
  this.deletionFile = oldFile;
627
696
  this.additionFile = newFile;
628
697
  }
629
- if (targetChanged) this.cachedHeaderHTML = void 0;
698
+ if (targetChanged) this.clearReusableHeader();
699
+ this.pendingRender = void 0;
630
700
  return this.renderPlaceholder(this.height);
631
701
  }
632
702
  const windowSpecs = this.virtualizer.getWindowSpecs();
633
703
  const fileTop = this.top ?? 0;
634
- const renderRange = this.computeRenderRangeFromWindow(nextFileDiff, fileTop, windowSpecs);
635
- const rendered = super.render({
704
+ const renderRange = this.computeRenderRangeFromWindow(pendingRenderDiff, fileTop, windowSpecs);
705
+ return super.render({
636
706
  fileDiff: nextFileDiff,
637
707
  fileContainer,
638
708
  renderRange,
639
709
  lineAnnotations,
640
- forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged || targetChanged,
710
+ forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged || renderedDiffChanged || targetChanged,
641
711
  ...fileInput,
642
712
  ...fileInputProps
643
713
  });
644
- if (this.isSimpleMode() && rendered) this.getSimpleVirtualizer()?.requestHeightReconcile(this);
645
- return rendered;
714
+ }
715
+ finalizeRender() {
716
+ if (this.getRenderedDiff() !== this.pendingRender?.diff) throw new Error("VirtualizedFileDiff.render: rendered a different diff than its prepared layout");
717
+ this.pendingRender = void 0;
718
+ if (this.isSimpleMode()) this.getSimpleVirtualizer()?.requestHeightReconcile(this);
719
+ }
720
+ updatePendingRender(nextFileDiff, lineAnnotations) {
721
+ const latestDiff = this.getLatestDiff(nextFileDiff) ?? nextFileDiff;
722
+ const previousRenderedDiff = this.getRenderedDiff();
723
+ const { pendingRender } = this;
724
+ const previousLayoutDiff = pendingRender?.diff ?? previousRenderedDiff;
725
+ const pendingRenderDiff = this.hunksRenderer.getDiffForNextRender(latestDiff);
726
+ this.pendingRender = {
727
+ latestDiff,
728
+ diff: pendingRenderDiff
729
+ };
730
+ return {
731
+ pendingRenderDiff,
732
+ annotationsChanged: this.syncLineAnnotations(lineAnnotations),
733
+ layoutDiffChanged: !areDiffTargetsEqual(previousLayoutDiff, pendingRenderDiff),
734
+ renderedDiffChanged: !areDiffTargetsEqual(previousRenderedDiff, pendingRenderDiff)
735
+ };
646
736
  }
647
737
  syncVirtualizedTop() {
648
738
  this.top = this.getVirtualizedTop();
@@ -678,8 +768,8 @@ var VirtualizedFileDiff = class extends FileDiff {
678
768
  getHunkSeparatorType() {
679
769
  return getOptionHunkSeparatorType(this.options.hunkSeparators);
680
770
  }
681
- approximateLayoutCheckpoints(fileDiff = this.fileDiff) {
682
- if (!this.layoutDirty && this.cache.checkpoints.length > 0 || fileDiff == null || fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
771
+ approximateLayoutCheckpoints(fileDiff) {
772
+ if (!this.layoutDirty && this.cache.checkpoints.length > 0 || fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
683
773
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
684
774
  const finalHunkIndex = fileDiff.hunks.length - 1;
685
775
  const canHydratePartialDiff = canHydrateCollapsedContext(fileDiff, this.options.loadDiffFiles != null);