@pierre/diffs 1.3.0-beta.6 → 1.3.0-beta.7

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 (119) hide show
  1. package/dist/components/CodeView.d.ts +4 -1
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +45 -6
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts.map +1 -1
  6. package/dist/components/File.js +5 -2
  7. package/dist/components/File.js.map +1 -1
  8. package/dist/components/FileDiff.d.ts +36 -23
  9. package/dist/components/FileDiff.d.ts.map +1 -1
  10. package/dist/components/FileDiff.js +126 -58
  11. package/dist/components/FileDiff.js.map +1 -1
  12. package/dist/components/UnresolvedFile.d.ts +3 -2
  13. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  14. package/dist/components/UnresolvedFile.js +4 -2
  15. package/dist/components/UnresolvedFile.js.map +1 -1
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +3 -7
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +10 -4
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +178 -49
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/editor/editor.d.ts +2 -2
  24. package/dist/editor/editor.d.ts.map +1 -1
  25. package/dist/editor/editor.js +163 -106
  26. package/dist/editor/editor.js.map +1 -1
  27. package/dist/editor/editor2.js +1 -1
  28. package/dist/editor/selection.d.ts +1 -1
  29. package/dist/editor/selection.d.ts.map +1 -1
  30. package/dist/editor/selection.js +87 -37
  31. package/dist/editor/selection.js.map +1 -1
  32. package/dist/editor/textMeasure.d.ts.map +1 -1
  33. package/dist/editor/textMeasure.js +25 -7
  34. package/dist/editor/textMeasure.js.map +1 -1
  35. package/dist/editor/tokenzier.d.ts +2 -0
  36. package/dist/editor/tokenzier.d.ts.map +1 -1
  37. package/dist/editor/tokenzier.js +11 -3
  38. package/dist/editor/tokenzier.js.map +1 -1
  39. package/dist/editor/utils.d.ts +3 -1
  40. package/dist/editor/utils.d.ts.map +1 -1
  41. package/dist/editor/utils.js +14 -1
  42. package/dist/editor/utils.js.map +1 -1
  43. package/dist/index.d.ts +5 -3
  44. package/dist/index.js +3 -1
  45. package/dist/managers/InteractionManager.d.ts.map +1 -1
  46. package/dist/managers/InteractionManager.js +0 -1
  47. package/dist/managers/InteractionManager.js.map +1 -1
  48. package/dist/react/EditorContext.js.map +1 -1
  49. package/dist/react/MultiFileDiff.d.ts +3 -4
  50. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  51. package/dist/react/MultiFileDiff.js.map +1 -1
  52. package/dist/react/index.d.ts +2 -2
  53. package/dist/react/utils/useFileDiffInstance.js +14 -15
  54. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  55. package/dist/renderers/DiffHunksRenderer.d.ts +2 -2
  56. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  57. package/dist/renderers/DiffHunksRenderer.js +29 -16
  58. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  59. package/dist/renderers/FileRenderer.js.map +1 -1
  60. package/dist/ssr/index.d.ts +2 -2
  61. package/dist/ssr/preloadDiffs.d.ts +11 -10
  62. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  63. package/dist/ssr/preloadDiffs.js +14 -6
  64. package/dist/ssr/preloadDiffs.js.map +1 -1
  65. package/dist/types.d.ts +59 -5
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/utils/areHunkDataEqual.js +1 -1
  68. package/dist/utils/areHunkDataEqual.js.map +1 -1
  69. package/dist/utils/awaitWithTimeout.d.ts +5 -0
  70. package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
  71. package/dist/utils/awaitWithTimeout.js +15 -0
  72. package/dist/utils/awaitWithTimeout.js.map +1 -0
  73. package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
  74. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
  75. package/dist/utils/cloneFileDiffMetadata.js +16 -0
  76. package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
  77. package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
  78. package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
  79. package/dist/utils/computeEstimatedDiffHeights.js +8 -1
  80. package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
  81. package/dist/utils/createPreElement.js +0 -1
  82. package/dist/utils/createPreElement.js.map +1 -1
  83. package/dist/utils/getDiffFileInput.d.ts +14 -0
  84. package/dist/utils/getDiffFileInput.d.ts.map +1 -0
  85. package/dist/utils/getDiffFileInput.js +24 -0
  86. package/dist/utils/getDiffFileInput.js.map +1 -0
  87. package/dist/utils/getDiffHunksRendererOptions.js +1 -0
  88. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  89. package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
  90. package/dist/utils/getFiletypeFromFileName.js +2 -0
  91. package/dist/utils/getFiletypeFromFileName.js.map +1 -1
  92. package/dist/utils/hydratePartialDiff.d.ts +10 -0
  93. package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
  94. package/dist/utils/hydratePartialDiff.js +140 -0
  95. package/dist/utils/hydratePartialDiff.js.map +1 -0
  96. package/dist/utils/iterateOverDiff.js +3 -3
  97. package/dist/utils/iterateOverDiff.js.map +1 -1
  98. package/dist/utils/parseDiffFromFile.d.ts +1 -1
  99. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  100. package/dist/utils/parseDiffFromFile.js +26 -5
  101. package/dist/utils/parseDiffFromFile.js.map +1 -1
  102. package/dist/utils/setWrapperNodeProps.js +0 -1
  103. package/dist/utils/setWrapperNodeProps.js.map +1 -1
  104. package/dist/utils/updateDiffHunks.d.ts +5 -1
  105. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  106. package/dist/utils/updateDiffHunks.js +26 -4
  107. package/dist/utils/updateDiffHunks.js.map +1 -1
  108. package/dist/worker/WorkerPoolManager.d.ts +7 -2
  109. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  110. package/dist/worker/WorkerPoolManager.js +78 -15
  111. package/dist/worker/WorkerPoolManager.js.map +1 -1
  112. package/dist/worker/index.d.ts +2 -2
  113. package/dist/worker/types.d.ts +7 -1
  114. package/dist/worker/types.d.ts.map +1 -1
  115. package/dist/worker/worker-portable.js +5 -3
  116. package/dist/worker/worker-portable.js.map +1 -1
  117. package/dist/worker/worker.js +5 -3
  118. package/dist/worker/worker.js.map +1 -1
  119. package/package.json +1 -1
@@ -1,11 +1,15 @@
1
1
  import "../constants.js";
2
2
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
3
3
  import { areOptionsEqual } from "../utils/areOptionsEqual.js";
4
+ import { areFilesEqual } from "../utils/areFilesEqual.js";
4
5
  import { computeVirtualFileMetrics, getVirtualFileHeaderRegion, getVirtualFilePaddingBottom } from "../utils/computeVirtualFileMetrics.js";
5
6
  import { FILE_ANNOTATION_DOM_KEY, includesFileAnnotations, shouldRenderFileAnnotations } from "../utils/includesFileAnnotations.js";
6
7
  import { areDiffTargetsEqual } from "../utils/areDiffTargetsEqual.js";
8
+ import { awaitWithTimeout } from "../utils/awaitWithTimeout.js";
7
9
  import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout } from "../utils/virtualDiffLayout.js";
8
10
  import { computeEstimatedDiffHeights } from "../utils/computeEstimatedDiffHeights.js";
11
+ import { getDiffFileInput } from "../utils/getDiffFileInput.js";
12
+ import { hydratePartialDiff } from "../utils/hydratePartialDiff.js";
9
13
  import { iterateOverDiff } from "../utils/iterateOverDiff.js";
10
14
  import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
11
15
  import { FileDiff } from "./FileDiff.js";
@@ -32,6 +36,8 @@ var VirtualizedFileDiff = class extends FileDiff {
32
36
  layoutDirty = true;
33
37
  forceRenderOverride;
34
38
  currentCollapsed;
39
+ pendingHydratedDiff;
40
+ pendingExpansions;
35
41
  constructor(options, virtualizer, metrics, workerManager, isContainerManaged = false) {
36
42
  super(options, workerManager, isContainerManaged);
37
43
  this.virtualizer = virtualizer;
@@ -92,19 +98,23 @@ var VirtualizedFileDiff = class extends FileDiff {
92
98
  if (this.isAdvancedMode()) throw new Error("VirtualizedFileDiff.setThemeType cannot be used inside CodeView. Update CodeView options instead.");
93
99
  super.setThemeType(themeType);
94
100
  }
95
- resetLayoutCache({ forceSimpleRecompute = false, includeEstimatedHeights = false } = {}) {
101
+ resetLayoutCache({ forceSimpleRecompute = false, includeEstimatedHeights = false, resetRenderRange = true } = {}) {
96
102
  this.layoutDirty = true;
97
103
  this.cache.fileAnnotationHeight = 0;
98
104
  if (this.cache.heightDeltas.size > 0) this.cache.heightDeltas.clear();
99
105
  if (this.cache.measuredHeightDeltaTotal !== 0) this.cache.measuredHeightDeltaTotal = 0;
106
+ this.invalidateDerivedLayoutCache(includeEstimatedHeights, resetRenderRange);
107
+ if (forceSimpleRecompute && this.isSimpleMode()) this.computeApproximateSize();
108
+ }
109
+ invalidateDerivedLayoutCache(includeEstimatedHeights, resetRenderRange = true) {
110
+ this.layoutDirty = true;
100
111
  if (this.cache.checkpoints.length > 0) this.cache.checkpoints.length = 0;
101
112
  if (this.cache.totalLines !== 0) this.cache.totalLines = 0;
102
113
  if (includeEstimatedHeights) {
103
114
  this.cache.estimatedSplitHeight = void 0;
104
115
  this.cache.estimatedUnifiedHeight = void 0;
105
116
  }
106
- if (this.renderRange != null) this.renderRange = void 0;
107
- if (forceSimpleRecompute && this.isSimpleMode()) this.computeApproximateSize();
117
+ if (this.renderRange != null && resetRenderRange) this.renderRange = void 0;
108
118
  }
109
119
  reconcileHeights() {
110
120
  let hasHeightChange = false;
@@ -331,17 +341,88 @@ var VirtualizedFileDiff = class extends FileDiff {
331
341
  }
332
342
  cleanUp(recycle = false) {
333
343
  if (this.fileContainer != null && this.isSimpleMode()) this.getSimpleVirtualizer()?.disconnect(this.fileContainer);
334
- if (!recycle) this.resetLayoutCache({ includeEstimatedHeights: true });
344
+ if (!recycle) {
345
+ this.resetLayoutCache({ includeEstimatedHeights: true });
346
+ this.pendingExpansions = void 0;
347
+ this.pendingHydratedDiff = void 0;
348
+ }
335
349
  this.isSetup = false;
336
350
  super.cleanUp(recycle);
337
351
  }
338
352
  expandHunk = (hunkIndex, direction, expansionLineCountOverride) => {
339
- this.hunksRenderer.expandHunk(hunkIndex, direction, expansionLineCountOverride);
353
+ if (this.fileDiff == null) return;
354
+ if (this.isAdvancedMode()) {
355
+ this.pendingExpansions ??= [];
356
+ this.pendingExpansions.push({
357
+ hunkIndex,
358
+ direction,
359
+ expansionLineCountOverride
360
+ });
361
+ } else {
362
+ this.hunksRenderer.expandHunk(hunkIndex, direction, expansionLineCountOverride);
363
+ this.resetLayoutCache({ includeEstimatedHeights: true });
364
+ this.computeApproximateSize();
365
+ }
366
+ this.loadFilesIfNecessary();
340
367
  this.forceRenderOverride = true;
341
- this.resetLayoutCache({ includeEstimatedHeights: true });
342
- if (this.isSimpleMode()) this.computeApproximateSize();
343
368
  this.virtualizer.instanceChanged(this, true);
344
369
  };
370
+ async handleFilesLoaded(expectedDiff, files) {
371
+ if (this.fileDiff !== expectedDiff || !expectedDiff.isPartial) return;
372
+ if (this.isAdvancedMode()) {
373
+ const nextDiff = hydratePartialDiff("clone", expectedDiff, files);
374
+ await awaitWithTimeout(() => this.primeHighlightCache(nextDiff));
375
+ if (!this.enabled || this.fileDiff !== expectedDiff) return;
376
+ this.pendingHydratedDiff = {
377
+ expectedDiff,
378
+ nextDiff,
379
+ files
380
+ };
381
+ } else {
382
+ hydratePartialDiff("merge", expectedDiff, files);
383
+ this.setHydratedState(files);
384
+ await awaitWithTimeout(() => this.primeHighlightCache(expectedDiff));
385
+ if (!this.enabled || this.fileDiff !== expectedDiff) return;
386
+ this.resetLayoutCache({ includeEstimatedHeights: true });
387
+ this.computeApproximateSize();
388
+ }
389
+ this.forceRenderOverride = true;
390
+ this.virtualizer.instanceChanged(this, true);
391
+ }
392
+ consumeCodeViewLayoutChanges(expectedFileDiff) {
393
+ let hasLayoutChange = false;
394
+ let nextDiff;
395
+ const { pendingExpansions, pendingHydratedDiff } = this;
396
+ if (pendingExpansions != null) {
397
+ this.pendingExpansions = void 0;
398
+ for (const pendingExpansion of pendingExpansions) {
399
+ this.hunksRenderer.expandHunk(pendingExpansion.hunkIndex, pendingExpansion.direction, pendingExpansion.expansionLineCountOverride);
400
+ hasLayoutChange = true;
401
+ }
402
+ }
403
+ if (pendingHydratedDiff != null) {
404
+ this.pendingHydratedDiff = void 0;
405
+ if (pendingHydratedDiff.expectedDiff === expectedFileDiff) {
406
+ this.setHydratedState(pendingHydratedDiff.files);
407
+ nextDiff = pendingHydratedDiff.nextDiff;
408
+ }
409
+ }
410
+ if (nextDiff != null) {
411
+ this.forceRenderOverride = true;
412
+ this.resetLayoutCache({ includeEstimatedHeights: true });
413
+ } else if (hasLayoutChange) {
414
+ this.forceRenderOverride = true;
415
+ this.invalidateDerivedLayoutCache(true);
416
+ }
417
+ return nextDiff;
418
+ }
419
+ loadFilesIfNecessary() {
420
+ if (this.pendingHydratedDiff != null) {
421
+ if (this.pendingHydratedDiff.expectedDiff === this.fileDiff) return;
422
+ this.pendingHydratedDiff = void 0;
423
+ }
424
+ super.loadFilesIfNecessary();
425
+ }
345
426
  setVisibility(visible) {
346
427
  if (this.isAdvancedMode() || this.fileContainer == null) return;
347
428
  this.renderRange = void 0;
@@ -364,22 +445,24 @@ var VirtualizedFileDiff = class extends FileDiff {
364
445
  this.getSimpleVirtualizer()?.markDOMDirty();
365
446
  this.resetLayoutCache({
366
447
  forceSimpleRecompute: this.isSimpleMode(),
367
- includeEstimatedHeights: true
448
+ includeEstimatedHeights: true,
449
+ resetRenderRange: false
368
450
  });
451
+ if (!this.isSimpleMode()) this.computeApproximateSize(true);
369
452
  if (shouldUpdateBuffer && previousRenderRange !== void 0 && this.fileDiff !== void 0) {
370
453
  const windowSpecs = this.virtualizer.getWindowSpecs();
371
454
  const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, this.top ?? 0, windowSpecs);
372
455
  if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) this.updateBuffers(renderRange);
373
456
  }
374
457
  }
375
- computeApproximateSize(force = false) {
458
+ computeApproximateSize(force = false, fileDiff = this.fileDiff) {
376
459
  const shouldValidateSize = this.isResizeDebuggingEnabled();
377
460
  if (!force && !this.layoutDirty && !shouldValidateSize) return;
378
461
  const isFirstCompute = this.height === 0;
379
462
  this.height = 0;
380
463
  this.cache.checkpoints = [];
381
464
  this.cache.totalLines = 0;
382
- if (this.fileDiff == null) {
465
+ if (fileDiff == null) {
383
466
  this.layoutDirty = false;
384
467
  return;
385
468
  }
@@ -390,18 +473,18 @@ var VirtualizedFileDiff = class extends FileDiff {
390
473
  this.layoutDirty = false;
391
474
  return;
392
475
  }
393
- this.height = this.getActiveEstimatedHeight() + this.cache.measuredHeightDeltaTotal;
394
- if (shouldValidateSize && !isFirstCompute) this.validateComputedHeight();
476
+ this.height = this.getActiveEstimatedHeight(fileDiff) + this.cache.measuredHeightDeltaTotal;
477
+ if (shouldValidateSize && !isFirstCompute) this.validateComputedHeight(fileDiff);
395
478
  this.layoutDirty = false;
396
479
  }
397
- getActiveEstimatedHeight() {
398
- this.ensureEstimatedDiffHeights();
480
+ getActiveEstimatedHeight(fileDiff = this.fileDiff) {
481
+ this.ensureEstimatedDiffHeights(fileDiff);
399
482
  const estimatedHeight = this.getDiffStyle() === "split" ? this.cache.estimatedSplitHeight : this.cache.estimatedUnifiedHeight;
400
483
  if (estimatedHeight == null) throw new Error("VirtualizedFileDiff.getActiveEstimatedHeight: missing estimated height");
401
484
  return estimatedHeight;
402
485
  }
403
- ensureEstimatedDiffHeights() {
404
- if (this.fileDiff == null) {
486
+ ensureEstimatedDiffHeights(fileDiff = this.fileDiff) {
487
+ if (fileDiff == null) {
405
488
  this.cache.estimatedSplitHeight = void 0;
406
489
  this.cache.estimatedUnifiedHeight = void 0;
407
490
  return;
@@ -409,40 +492,51 @@ var VirtualizedFileDiff = class extends FileDiff {
409
492
  if (this.cache.estimatedSplitHeight != null && this.cache.estimatedUnifiedHeight != null) return;
410
493
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
411
494
  const { splitHeight, unifiedHeight } = computeEstimatedDiffHeights({
412
- fileDiff: this.fileDiff,
495
+ fileDiff,
413
496
  metrics: this.metrics,
414
497
  disableFileHeader,
415
498
  hunkSeparators: this.getHunkSeparatorType(),
416
499
  expandUnchanged,
417
500
  expandedHunks: this.hunksRenderer.getExpandedHunksMap(),
418
- collapsedContextThreshold
501
+ collapsedContextThreshold,
502
+ canHydratePartialDiff: canHydrateCollapsedContext(fileDiff, this.options.loadDiffFiles != null)
419
503
  });
420
504
  this.cache.estimatedSplitHeight = splitHeight;
421
505
  this.cache.estimatedUnifiedHeight = unifiedHeight;
422
506
  }
423
- validateComputedHeight() {
424
- if (this.fileContainer == null || this.fileDiff == null) return;
507
+ validateComputedHeight(fileDiff = this.fileDiff) {
508
+ if (this.fileContainer == null || fileDiff == null) return;
425
509
  const rect = this.fileContainer.getBoundingClientRect();
426
510
  if (rect.height !== this.height) console.log("VirtualizedFileDiff.computeApproximateSize: computed height doesnt match", {
427
- name: this.fileDiff.name,
511
+ name: fileDiff.name,
428
512
  elementHeight: rect.height,
429
513
  computedHeight: this.height
430
514
  });
431
515
  else console.log("VirtualizedFileDiff.computeApproximateSize: computed height IS CORRECT");
432
516
  }
433
- render({ fileContainer, oldFile, newFile, fileDiff, forceRender = false, lineAnnotations, ...props } = {}) {
517
+ render({ fileContainer, fileDiff, forceRender = false, lineAnnotations, ...fileInputProps } = {}) {
518
+ const fileInput = getDiffFileInput(fileInputProps, "VirtualizedFileDiff.render");
519
+ const hasFileInput = fileInput != null;
520
+ const oldFile = fileInput?.oldFile;
521
+ const newFile = fileInput?.newFile;
522
+ const filesDidChange = hasFileInput && (!areOptionalFilesEqual(oldFile, this.deletionFile) || !areOptionalFilesEqual(newFile, this.additionFile));
523
+ let nextFileDiff = fileDiff ?? this.fileDiff;
524
+ if (fileDiff == null && hasFileInput && (filesDidChange || this.fileDiff == null)) nextFileDiff = parseDiffFromFile(fileInput.oldFile, fileInput.newFile, this.options.parseDiffOptions);
434
525
  const { forceRenderOverride, isSetup } = this;
435
526
  this.forceRenderOverride = void 0;
436
527
  const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
437
528
  if (annotationsChanged) this.resetLayoutCache({ includeEstimatedHeights: false });
438
- this.fileDiff ??= fileDiff ?? (oldFile != null && newFile != null ? parseDiffFromFile(oldFile, newFile, this.options.parseDiffOptions) : void 0);
529
+ const diffInputChanged = fileDiff != null && fileDiff !== this.fileDiff;
530
+ const targetChanged = nextFileDiff != null && !areDiffTargetsEqual(this.fileDiff, nextFileDiff);
531
+ const dataChanged = diffInputChanged || filesDidChange;
532
+ if (targetChanged) this.resetLayoutCache({ includeEstimatedHeights: true });
439
533
  fileContainer = this.getOrCreateFileContainer(fileContainer);
440
- if (this.fileDiff == null) {
534
+ if (nextFileDiff == null) {
441
535
  console.error("VirtualizedFileDiff.render: attempting to virtually render when we dont have the correct data");
442
536
  return false;
443
537
  }
444
538
  if (!isSetup) {
445
- this.computeApproximateSize();
539
+ this.computeApproximateSize(false, nextFileDiff);
446
540
  const virtualizer = this.getSimpleVirtualizer();
447
541
  this.top ??= this.getVirtualizedTop();
448
542
  if (this.isAdvancedMode()) this.isVisible = true;
@@ -452,20 +546,30 @@ var VirtualizedFileDiff = class extends FileDiff {
452
546
  this.isVisible = virtualizer.isInstanceVisible(this.top ?? 0, this.height);
453
547
  }
454
548
  this.isSetup = true;
455
- } else this.top ??= this.getVirtualizedTop();
456
- if (!this.isVisible && this.isSimpleMode()) return this.renderPlaceholder(this.height);
549
+ } else {
550
+ this.top ??= this.getVirtualizedTop();
551
+ if (targetChanged) this.computeApproximateSize(false, nextFileDiff);
552
+ }
553
+ if (!this.isVisible && this.isSimpleMode() && (!dataChanged || !isSetup)) {
554
+ this.fileDiff = nextFileDiff;
555
+ if (fileInput != null) {
556
+ this.deletionFile = oldFile;
557
+ this.additionFile = newFile;
558
+ }
559
+ if (targetChanged) this.cachedHeaderHTML = void 0;
560
+ return this.renderPlaceholder(this.height);
561
+ }
457
562
  const windowSpecs = this.virtualizer.getWindowSpecs();
458
563
  const fileTop = this.top ?? 0;
459
- const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, fileTop, windowSpecs);
564
+ const renderRange = this.computeRenderRangeFromWindow(nextFileDiff, fileTop, windowSpecs);
460
565
  return super.render({
461
- fileDiff: this.fileDiff,
566
+ fileDiff: nextFileDiff,
462
567
  fileContainer,
463
568
  renderRange,
464
- oldFile,
465
- newFile,
466
569
  lineAnnotations,
467
- forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged,
468
- ...props
570
+ forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged || targetChanged,
571
+ ...fileInput,
572
+ ...fileInputProps
469
573
  });
470
574
  }
471
575
  syncVirtualizedTop() {
@@ -496,10 +600,11 @@ var VirtualizedFileDiff = class extends FileDiff {
496
600
  getHunkSeparatorType() {
497
601
  return getOptionHunkSeparatorType(this.options.hunkSeparators);
498
602
  }
499
- approximateLayoutCheckpoints() {
500
- if (this.cache.checkpoints.length > 0 || this.fileDiff == null || this.fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
603
+ approximateLayoutCheckpoints(fileDiff = this.fileDiff) {
604
+ if (!this.layoutDirty && this.cache.checkpoints.length > 0 || fileDiff == null || fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
501
605
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
502
- const finalHunkIndex = this.fileDiff.hunks.length - 1;
606
+ const finalHunkIndex = fileDiff.hunks.length - 1;
607
+ const canHydratePartialDiff = canHydrateCollapsedContext(fileDiff, this.options.loadDiffFiles != null);
503
608
  const diffStyle = this.getDiffStyle();
504
609
  const hunkSeparators = this.getHunkSeparatorType();
505
610
  const expandedHunks = expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap();
@@ -524,11 +629,11 @@ var VirtualizedFileDiff = class extends FileDiff {
524
629
  top += preSeparatorHeight + rowCount * this.metrics.lineHeight + metadataOffsets.length * this.metrics.lineHeight + sumHeightDeltas(heightDeltaPrefix, startLineIndex, startLineIndex + rowCount) + postSeparatorHeight;
525
630
  renderedLineIndex = blockEnd;
526
631
  };
527
- for (let hunkIndex = 0; hunkIndex < this.fileDiff.hunks.length; hunkIndex++) {
528
- const hunk = this.fileDiff.hunks[hunkIndex];
632
+ for (let hunkIndex = 0; hunkIndex < fileDiff.hunks.length; hunkIndex++) {
633
+ const hunk = fileDiff.hunks[hunkIndex];
529
634
  if (hunk == null) throw new Error("VirtualizedFileDiff.approximateLayoutCheckpoints: invalid hunk index");
530
635
  const leadingRegion = getExpandedRegion({
531
- isPartial: this.fileDiff.isPartial,
636
+ isPartial: fileDiff.isPartial,
532
637
  rangeSize: hunk.collapsedBefore,
533
638
  expandedHunks,
534
639
  hunkIndex,
@@ -552,7 +657,7 @@ var VirtualizedFileDiff = class extends FileDiff {
552
657
  });
553
658
  if (leadingRegion.fromEnd > 0) pendingLeadingSeparatorHeight = 0;
554
659
  const trailingRegion = hunkIndex === finalHunkIndex ? getTrailingExpandedRegion({
555
- fileDiff: this.fileDiff,
660
+ fileDiff,
556
661
  hunkIndex,
557
662
  expandedHunks,
558
663
  collapsedContextThreshold,
@@ -561,6 +666,9 @@ var VirtualizedFileDiff = class extends FileDiff {
561
666
  const trailingSeparatorHeight = trailingRegion != null && trailingRegion.collapsedLines > 0 ? getTrailingHunkSeparatorLayout({
562
667
  type: hunkSeparators,
563
668
  metrics: this.metrics
669
+ })?.totalHeight ?? 0 : hunkIndex === finalHunkIndex && canHydratePartialDiff ? getTrailingHunkSeparatorLayout({
670
+ type: hunkSeparators,
671
+ metrics: this.metrics
564
672
  })?.totalHeight ?? 0 : 0;
565
673
  const trailingExpandedCount = trailingRegion != null ? trailingRegion.fromStart + trailingRegion.fromEnd : 0;
566
674
  const hunkBodyRowCount = diffStyle === "split" ? hunk.splitLineCount : hunk.unifiedLineCount;
@@ -651,13 +759,19 @@ var VirtualizedFileDiff = class extends FileDiff {
651
759
  if (trailingRegion != null) count += trailingRegion.fromStart + trailingRegion.fromEnd;
652
760
  return count;
653
761
  }
762
+ getLayoutLineCount(fileDiff, diffStyle) {
763
+ const expandedLineCount = this.getExpandedLineCount(fileDiff, diffStyle);
764
+ const metadataLineCount = diffStyle === "split" ? fileDiff.splitLineCount : fileDiff.unifiedLineCount;
765
+ return Math.max(expandedLineCount, metadataLineCount, fileDiff.additionLines.length, fileDiff.deletionLines.length, this.cache.totalLines);
766
+ }
654
767
  computeRenderRangeFromWindow(fileDiff, fileTop, { top, bottom }) {
655
768
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
656
769
  const { hunkLineCount, lineHeight } = this.metrics;
657
770
  const diffStyle = this.getDiffStyle();
658
771
  const hunkSeparators = this.getHunkSeparatorType();
772
+ const canHydratePartialDiff = canHydrateCollapsedContext(fileDiff, this.options.loadDiffFiles != null);
659
773
  const fileHeight = this.height;
660
- let lineCount = this.cache.totalLines > 0 ? this.cache.totalLines : this.getExpandedLineCount(fileDiff, diffStyle);
774
+ let lineCount = this.getLayoutLineCount(fileDiff, diffStyle);
661
775
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
662
776
  const paddingBottom = fileDiff.hunks.length > 0 ? getVirtualFilePaddingBottom(this.metrics) : 0;
663
777
  const { fileAnnotationHeight } = this.cache;
@@ -678,8 +792,8 @@ var VirtualizedFileDiff = class extends FileDiff {
678
792
  bufferBefore: 0,
679
793
  bufferAfter: 0
680
794
  };
681
- this.approximateLayoutCheckpoints();
682
- lineCount = this.cache.totalLines > 0 ? this.cache.totalLines : lineCount;
795
+ this.approximateLayoutCheckpoints(fileDiff);
796
+ lineCount = this.getLayoutLineCount(fileDiff, diffStyle);
683
797
  const estimatedTargetLines = Math.ceil(Math.max(bottom - top, 0) / lineHeight);
684
798
  const totalLines = Math.ceil(estimatedTargetLines / hunkLineCount) * hunkLineCount + hunkLineCount;
685
799
  const totalHunks = totalLines / hunkLineCount;
@@ -702,6 +816,7 @@ var VirtualizedFileDiff = class extends FileDiff {
702
816
  const splitLineIndex = additionLine != null ? additionLine.splitLineIndex : deletionLine.splitLineIndex;
703
817
  const unifiedLineIndex = additionLine != null ? additionLine.unifiedLineIndex : deletionLine.unifiedLineIndex;
704
818
  const hasMetadata = (additionLine?.noEOFCR ?? false) || (deletionLine?.noEOFCR ?? false);
819
+ const isFinalHunkRow = hunkIndex === fileDiff.hunks.length - 1 && hunk != null && (diffStyle === "split" ? splitLineIndex === hunk.splitLineStart + hunk.splitLineCount - 1 : unifiedLineIndex === hunk.unifiedLineStart + hunk.unifiedLineCount - 1);
705
820
  const gapAdjustment = (collapsedBefore > 0 ? getLeadingHunkSeparatorLayout({
706
821
  type: hunkSeparators,
707
822
  metrics: this.metrics,
@@ -724,10 +839,17 @@ var VirtualizedFileDiff = class extends FileDiff {
724
839
  if (overflowCounter == null && absoluteLineTop >= bottom && isAtHunkBoundary) overflowCounter = overflowHunks;
725
840
  currentLine++;
726
841
  absoluteLineTop += lineHeight;
727
- if (collapsedAfter > 0) absoluteLineTop += getTrailingHunkSeparatorLayout({
728
- type: hunkSeparators,
729
- metrics: this.metrics
730
- })?.totalHeight ?? 0;
842
+ if (collapsedAfter > 0 || isFinalHunkRow && canHydratePartialDiff) {
843
+ const trailingSeparator = getTrailingHunkSeparatorLayout({
844
+ type: hunkSeparators,
845
+ metrics: this.metrics
846
+ });
847
+ if (trailingSeparator != null) {
848
+ if (absoluteLineTop < bottom && absoluteLineTop + trailingSeparator.totalHeight > top) firstVisibleHunk ??= currentHunk;
849
+ if (centerHunk == null && absoluteLineTop + trailingSeparator.totalHeight > viewportCenter) centerHunk = currentHunk;
850
+ absoluteLineTop += trailingSeparator.totalHeight;
851
+ }
852
+ }
731
853
  return false;
732
854
  }
733
855
  });
@@ -827,14 +949,21 @@ function getHunkMetadataOffsets({ diffStyle, hunk, rowCount }) {
827
949
  return offsets;
828
950
  }
829
951
  function hasDiffLayoutOptionChanged(previousOptions, nextOptions) {
830
- return (previousOptions.diffStyle ?? "split") !== (nextOptions.diffStyle ?? "split") || (previousOptions.overflow ?? "scroll") !== (nextOptions.overflow ?? "scroll") || (previousOptions.collapsed ?? false) !== (nextOptions.collapsed ?? false) || (previousOptions.disableLineNumbers ?? false) !== (nextOptions.disableLineNumbers ?? false) || (previousOptions.disableFileHeader ?? false) !== (nextOptions.disableFileHeader ?? false) || (previousOptions.diffIndicators ?? "bars") !== (nextOptions.diffIndicators ?? "bars") || (previousOptions.hunkSeparators ?? "line-info") !== (nextOptions.hunkSeparators ?? "line-info") || (previousOptions.expandUnchanged ?? false) !== (nextOptions.expandUnchanged ?? false) || (previousOptions.collapsedContextThreshold ?? 1) !== (nextOptions.collapsedContextThreshold ?? 1) || previousOptions.unsafeCSS !== nextOptions.unsafeCSS;
952
+ return (previousOptions.diffStyle ?? "split") !== (nextOptions.diffStyle ?? "split") || (previousOptions.overflow ?? "scroll") !== (nextOptions.overflow ?? "scroll") || (previousOptions.collapsed ?? false) !== (nextOptions.collapsed ?? false) || (previousOptions.disableLineNumbers ?? false) !== (nextOptions.disableLineNumbers ?? false) || (previousOptions.disableFileHeader ?? false) !== (nextOptions.disableFileHeader ?? false) || (previousOptions.diffIndicators ?? "bars") !== (nextOptions.diffIndicators ?? "bars") || (previousOptions.hunkSeparators ?? "line-info") !== (nextOptions.hunkSeparators ?? "line-info") || Boolean(previousOptions.loadDiffFiles) !== Boolean(nextOptions.loadDiffFiles) || (previousOptions.expandUnchanged ?? false) !== (nextOptions.expandUnchanged ?? false) || (previousOptions.collapsedContextThreshold ?? 1) !== (nextOptions.collapsedContextThreshold ?? 1) || previousOptions.unsafeCSS !== nextOptions.unsafeCSS;
831
953
  }
832
954
  function hasDiffEstimateOptionChanged(previousOptions, nextOptions) {
833
- return (previousOptions.disableFileHeader ?? false) !== (nextOptions.disableFileHeader ?? false) || (previousOptions.hunkSeparators ?? "line-info") !== (nextOptions.hunkSeparators ?? "line-info") || (previousOptions.expandUnchanged ?? false) !== (nextOptions.expandUnchanged ?? false) || (previousOptions.collapsedContextThreshold ?? 1) !== (nextOptions.collapsedContextThreshold ?? 1);
955
+ return (previousOptions.disableFileHeader ?? false) !== (nextOptions.disableFileHeader ?? false) || (previousOptions.hunkSeparators ?? "line-info") !== (nextOptions.hunkSeparators ?? "line-info") || Boolean(previousOptions.loadDiffFiles) !== Boolean(nextOptions.loadDiffFiles) || (previousOptions.expandUnchanged ?? false) !== (nextOptions.expandUnchanged ?? false) || (previousOptions.collapsedContextThreshold ?? 1) !== (nextOptions.collapsedContextThreshold ?? 1);
956
+ }
957
+ function canHydrateCollapsedContext(fileDiff, hasFileLoader) {
958
+ return fileDiff.isPartial && hasFileLoader && (fileDiff.type === "change" || fileDiff.type === "rename-changed");
834
959
  }
835
960
  function getOptionHunkSeparatorType(hunkSeparators) {
836
961
  return typeof hunkSeparators === "function" ? "custom" : hunkSeparators ?? "line-info";
837
962
  }
963
+ function areOptionalFilesEqual(fileA, fileB) {
964
+ if (fileA == null || fileB == null) return fileA == null && fileB == null;
965
+ return areFilesEqual(fileA, fileB);
966
+ }
838
967
  function parseLineIndex(lineIndexAttr, diffStyle) {
839
968
  const [unifiedIndex, splitIndex] = lineIndexAttr.split(",").map(Number);
840
969
  return diffStyle === "split" ? splitIndex : unifiedIndex;