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

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 (110) hide show
  1. package/dist/components/CodeView.d.ts +86 -4
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +246 -32
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +1 -0
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +15 -4
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +2 -0
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +21 -6
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  14. package/dist/components/VirtualizedFile.js +3 -1
  15. package/dist/components/VirtualizedFile.js.map +1 -1
  16. package/dist/components/VirtualizedFileDiff.d.ts +3 -1
  17. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  18. package/dist/components/VirtualizedFileDiff.js +14 -6
  19. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  20. package/dist/components/Virtualizer.d.ts +2 -0
  21. package/dist/components/Virtualizer.d.ts.map +1 -1
  22. package/dist/components/Virtualizer.js +16 -3
  23. package/dist/components/Virtualizer.js.map +1 -1
  24. package/dist/constants.d.ts +3 -1
  25. package/dist/constants.d.ts.map +1 -1
  26. package/dist/constants.js +3 -1
  27. package/dist/constants.js.map +1 -1
  28. package/dist/editor/command.d.ts +1 -1
  29. package/dist/editor/command.d.ts.map +1 -1
  30. package/dist/editor/command.js +8 -0
  31. package/dist/editor/command.js.map +1 -1
  32. package/dist/editor/editor.d.ts +8 -1
  33. package/dist/editor/editor.d.ts.map +1 -1
  34. package/dist/editor/editor.js +171 -38
  35. package/dist/editor/editor.js.map +1 -1
  36. package/dist/editor/editor2.js +1 -1
  37. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  38. package/dist/editor/lineAnnotations.js +84 -12
  39. package/dist/editor/lineAnnotations.js.map +1 -1
  40. package/dist/editor/marker.d.ts +5 -3
  41. package/dist/editor/marker.d.ts.map +1 -1
  42. package/dist/editor/marker.js +35 -12
  43. package/dist/editor/marker.js.map +1 -1
  44. package/dist/editor/matchBrackets.d.ts +8 -0
  45. package/dist/editor/matchBrackets.d.ts.map +1 -0
  46. package/dist/editor/matchBrackets.js +146 -0
  47. package/dist/editor/matchBrackets.js.map +1 -0
  48. package/dist/editor/popover.d.ts +45 -0
  49. package/dist/editor/popover.d.ts.map +1 -0
  50. package/dist/editor/popover.js +145 -0
  51. package/dist/editor/popover.js.map +1 -0
  52. package/dist/editor/selection.d.ts +13 -1
  53. package/dist/editor/selection.d.ts.map +1 -1
  54. package/dist/editor/selection.js +55 -4
  55. package/dist/editor/selection.js.map +1 -1
  56. package/dist/editor/selectionAction.d.ts +20 -3
  57. package/dist/editor/selectionAction.d.ts.map +1 -1
  58. package/dist/editor/selectionAction.js +41 -10
  59. package/dist/editor/selectionAction.js.map +1 -1
  60. package/dist/editor/textDocument.d.ts +2 -0
  61. package/dist/editor/textDocument.d.ts.map +1 -1
  62. package/dist/editor/textDocument.js +22 -6
  63. package/dist/editor/textDocument.js.map +1 -1
  64. package/dist/editor/tokenzier.d.ts +4 -7
  65. package/dist/editor/tokenzier.d.ts.map +1 -1
  66. package/dist/editor/tokenzier.js +76 -35
  67. package/dist/editor/tokenzier.js.map +1 -1
  68. package/dist/index.d.ts +6 -6
  69. package/dist/index.js +4 -4
  70. package/dist/managers/ResizeManager.d.ts +10 -2
  71. package/dist/managers/ResizeManager.d.ts.map +1 -1
  72. package/dist/managers/ResizeManager.js +33 -13
  73. package/dist/managers/ResizeManager.js.map +1 -1
  74. package/dist/react/CodeView.d.ts +25 -1
  75. package/dist/react/CodeView.d.ts.map +1 -1
  76. package/dist/react/CodeView.js +76 -17
  77. package/dist/react/CodeView.js.map +1 -1
  78. package/dist/react/EditorContext.d.ts +2 -2
  79. package/dist/react/EditorContext.d.ts.map +1 -1
  80. package/dist/react/EditorContext.js.map +1 -1
  81. package/dist/react/index.d.ts +2 -2
  82. package/dist/renderers/DiffHunksRenderer.d.ts +1 -1
  83. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  84. package/dist/renderers/DiffHunksRenderer.js +24 -15
  85. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  86. package/dist/renderers/FileRenderer.d.ts +2 -1
  87. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  88. package/dist/renderers/FileRenderer.js +58 -38
  89. package/dist/renderers/FileRenderer.js.map +1 -1
  90. package/dist/ssr/index.d.ts +2 -2
  91. package/dist/types.d.ts +42 -2
  92. package/dist/types.d.ts.map +1 -1
  93. package/dist/utils/applyLineTextWithNewline.d.ts +5 -0
  94. package/dist/utils/applyLineTextWithNewline.d.ts.map +1 -0
  95. package/dist/utils/applyLineTextWithNewline.js +11 -0
  96. package/dist/utils/applyLineTextWithNewline.js.map +1 -0
  97. package/dist/utils/areManagedSnapshotsEqual.d.ts +2 -2
  98. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  99. package/dist/utils/areManagedSnapshotsEqual.js +5 -0
  100. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  101. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts +5 -0
  102. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts.map +1 -0
  103. package/dist/utils/createCodeViewHeaderFooterHostElement.js +19 -0
  104. package/dist/utils/createCodeViewHeaderFooterHostElement.js.map +1 -0
  105. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  106. package/dist/utils/updateDiffHunks.js +23 -1
  107. package/dist/utils/updateDiffHunks.js.map +1 -1
  108. package/dist/worker/worker-portable.js.map +1 -1
  109. package/dist/worker/worker.js.map +1 -1
  110. package/package.json +1 -1
@@ -1,9 +1,11 @@
1
1
  import { DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DIFFS_DEVELOPMENT_BUILD, DIFFS_TAG_NAME } from "../constants.js";
2
2
  import { dequeueRender, queueRender } from "../managers/UniversalRenderingManager.js";
3
+ import { areManagedSnapshotsEqual } from "../utils/areManagedSnapshotsEqual.js";
3
4
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
4
5
  import { areThemesEqual } from "../utils/areThemesEqual.js";
5
6
  import { areOptionsEqual } from "../utils/areOptionsEqual.js";
6
7
  import { areSelectionsEqual } from "../utils/areSelectionsEqual.js";
8
+ import { createCodeViewHeaderFooterHostElement } from "../utils/createCodeViewHeaderFooterHostElement.js";
7
9
  import { createWindowFromScrollPosition } from "../utils/createWindowFromScrollPosition.js";
8
10
  import { isStyleNode } from "../utils/isStyleNode.js";
9
11
  import { prefersReducedMotion } from "../utils/prefersReducedMotion.js";
@@ -62,6 +64,13 @@ const CODE_VIEW_FILE_OPTION_KEYS = [
62
64
  "controlledSelection",
63
65
  "disableErrorHandling"
64
66
  ];
67
+ const CODE_VIEW_EDIT_FORCED_OPTION_KEYS = /* @__PURE__ */ new Set([
68
+ "useTokenTransformer",
69
+ "enableGutterUtility",
70
+ "enableLineSelection",
71
+ "lineHoverHighlight",
72
+ "expandUnchanged"
73
+ ]);
65
74
  const CODE_VIEW_SHARED_CALLBACK_KEYS = [
66
75
  "renderCustomHeader",
67
76
  "renderHeaderPrefix",
@@ -131,6 +140,8 @@ var CodeView = class CodeView {
131
140
  items = [];
132
141
  idToItem = /* @__PURE__ */ new Map();
133
142
  selectedLines = null;
143
+ itemEditors = /* @__PURE__ */ new Map();
144
+ attachedEditors = /* @__PURE__ */ new Set();
134
145
  instanceToItem = /* @__PURE__ */ new Map();
135
146
  layoutDirtyIndex;
136
147
  pendingLayoutReset;
@@ -172,6 +183,16 @@ var CodeView = class CodeView {
172
183
  container = document.createElement("div");
173
184
  stickyContainer = document.createElement("div");
174
185
  stickyOffset = document.createElement("div");
186
+ header = {
187
+ element: void 0,
188
+ render: void 0,
189
+ height: 0
190
+ };
191
+ footer = {
192
+ element: void 0,
193
+ render: void 0,
194
+ height: 0
195
+ };
175
196
  elementPool = [];
176
197
  elementPoolVersion = 0;
177
198
  elementPoolTracker = /* @__PURE__ */ new WeakMap();
@@ -198,6 +219,9 @@ var CodeView = class CodeView {
198
219
  getLayout() {
199
220
  return this.options.layout ?? DEFAULT_CODE_VIEW_LAYOUT;
200
221
  }
222
+ getItemTopOffset() {
223
+ return this.getLayout().paddingTop + this.header.height;
224
+ }
201
225
  computeMetricsCache(itemMetrics) {
202
226
  this.itemMetricsCache = {
203
227
  hunkLineCount: itemMetrics?.hunkLineCount ?? DEFAULT_CODE_VIEW_FILE_METRICS.hunkLineCount,
@@ -300,6 +324,43 @@ var CodeView = class CodeView {
300
324
  this.container?.style.setProperty("margin-top", `${paddingTop}px`);
301
325
  this.container?.style.setProperty("margin-bottom", `${paddingBottom}px`);
302
326
  }
327
+ reconcileHeaderFooterHosts() {
328
+ const headerChanged = this.reconcileHost("header");
329
+ const footerChanged = this.reconcileHost("footer");
330
+ return headerChanged || footerChanged;
331
+ }
332
+ reconcileHost(type) {
333
+ const { root, container } = this;
334
+ if (root == null || container == null) return false;
335
+ const host = type === "header" ? this.header : this.footer;
336
+ const render = type === "header" ? this.options.renderCodeViewHeader : this.options.renderCodeViewFooter;
337
+ if (render == null) {
338
+ if (host.element == null) return false;
339
+ this.resizeObserver?.unobserve(host.element);
340
+ host.element.remove();
341
+ host.element = void 0;
342
+ host.render = void 0;
343
+ this.setHostHeight(host, 0);
344
+ return false;
345
+ }
346
+ if (host.element != null && render === host.render) return false;
347
+ const element = host.element ?? createCodeViewHeaderFooterHostElement(type, container, this.resizeObserver);
348
+ host.element = element;
349
+ const content = render();
350
+ if (content != null) element.replaceChildren(content);
351
+ else if (!this.isContainerManaged && element.children.length > 0) element.textContent = "";
352
+ host.render = render;
353
+ return true;
354
+ }
355
+ setHostHeight(host, height) {
356
+ if (host.height === height) return;
357
+ host.height = height;
358
+ this.scrollDirty = true;
359
+ }
360
+ measureMountedHosts() {
361
+ if (this.header.element != null) this.setHostHeight(this.header, this.header.element.getBoundingClientRect().height);
362
+ if (this.footer.element != null) this.setHostHeight(this.footer, this.footer.element.getBoundingClientRect().height);
363
+ }
303
364
  setup(root) {
304
365
  if (this.root != null) throw new Error("CodeView.setup: already setup");
305
366
  this.workerManager?.subscribeToThemeChanges(this);
@@ -342,6 +403,9 @@ var CodeView = class CodeView {
342
403
  this.clearReadySubscription();
343
404
  this.restoreScrollInteractions();
344
405
  this.cleanAllRenderedItems();
406
+ for (const record of this.itemEditors.values()) record.editor.cleanUp();
407
+ this.itemEditors.clear();
408
+ this.attachedEditors.clear();
345
409
  this.selectedLines = null;
346
410
  this.items.length = 0;
347
411
  this.idToItem.clear();
@@ -384,6 +448,14 @@ var CodeView = class CodeView {
384
448
  this.stickyOffset.remove();
385
449
  this.stickyContainer.remove();
386
450
  this.stickyContainer.textContent = "";
451
+ this.header.element?.remove();
452
+ this.header.element = void 0;
453
+ this.header.render = void 0;
454
+ this.header.height = 0;
455
+ this.footer.element?.remove();
456
+ this.footer.element = void 0;
457
+ this.footer.render = void 0;
458
+ this.footer.height = 0;
387
459
  this.root = void 0;
388
460
  this.container = void 0;
389
461
  }
@@ -418,6 +490,7 @@ var CodeView = class CodeView {
418
490
  const { element } = item;
419
491
  if (element != null && this.renderedItemOwnsFocus(element)) this.shouldFixContainerFocus = true;
420
492
  item.instance.cleanUp(true);
493
+ this.attachedEditors.delete(item.item.id);
421
494
  item.element = void 0;
422
495
  if (element == null) return;
423
496
  element.remove();
@@ -510,6 +583,14 @@ var CodeView = class CodeView {
510
583
  getItem(itemId) {
511
584
  return this.idToItem.get(itemId)?.item;
512
585
  }
586
+ /**
587
+ * Get the live editor for an item currently in edit mode. Use this to drive
588
+ * editor APIs CodeView does not wrap (applyEdits, undo, setMarkers, …).
589
+ * Returns undefined once the item leaves edit mode.
590
+ */
591
+ getEditor(itemId) {
592
+ return this.itemEditors.get(itemId)?.editor;
593
+ }
513
594
  updateItem(input) {
514
595
  const item = this.idToItem.get(input.id);
515
596
  if (item == null) {
@@ -521,6 +602,7 @@ var CodeView = class CodeView {
521
602
  this.scrollDirty = true;
522
603
  this.render();
523
604
  this.syncSelection();
605
+ this.syncItemEditors();
524
606
  return true;
525
607
  }
526
608
  updateItemId(oldId, newId) {
@@ -545,6 +627,13 @@ var CodeView = class CodeView {
545
627
  };
546
628
  this.options.onSelectedLinesChange?.(this.selectedLines);
547
629
  }
630
+ const editorRecord = this.itemEditors.get(oldId);
631
+ if (editorRecord != null) {
632
+ editorRecord.state.id = newId;
633
+ this.itemEditors.delete(oldId);
634
+ this.itemEditors.set(newId, editorRecord);
635
+ if (this.attachedEditors.delete(oldId)) this.attachedEditors.add(newId);
636
+ }
548
637
  this.renamePendingScrollTarget(oldId, newId);
549
638
  this.renamePendingLayoutAnchor(oldId, newId);
550
639
  this.render();
@@ -552,17 +641,25 @@ var CodeView = class CodeView {
552
641
  }
553
642
  addItem(input) {
554
643
  this.addItems([input]);
555
- this.syncSelection();
556
644
  }
557
645
  addItems(inputs) {
558
646
  this.appendItemsInternal(inputs);
559
647
  this.syncSelection();
648
+ this.syncItemEditors();
560
649
  }
561
650
  setItems(items) {
562
- if (items.length === 0) this.reset();
563
- else if (this.items.length === 0) this.appendItemsInternal(items);
651
+ if (items.length === 0) {
652
+ const completions = [];
653
+ for (const record of this.itemEditors.values()) {
654
+ const { lastChange } = record.state;
655
+ if (lastChange != null) completions.push(lastChange);
656
+ }
657
+ this.reset();
658
+ for (const { item, file, lineAnnotations } of completions) this.options.onItemEditComplete?.(item, file, lineAnnotations);
659
+ } else if (this.items.length === 0) this.appendItemsInternal(items);
564
660
  else if (!this.tryAppendItems(items)) this.reconcileItems(items);
565
661
  this.syncSelection();
662
+ this.syncItemEditors();
566
663
  }
567
664
  /**
568
665
  * Append new records to the viewer while preserving existing layout state.
@@ -624,7 +721,9 @@ var CodeView = class CodeView {
624
721
  this.scrollDirty = true;
625
722
  }
626
723
  if (!areOptionsEqual(prevOptions, options)) this.renderOptionsRevision++;
627
- if (!this.isContainerManaged && this.items.length > 0) this.render();
724
+ this.syncItemEditors();
725
+ const headerFooterChanged = prevOptions.renderCodeViewHeader !== options.renderCodeViewHeader || prevOptions.renderCodeViewFooter !== options.renderCodeViewFooter;
726
+ if (!this.isContainerManaged && (this.items.length > 0 || headerFooterChanged)) this.render();
628
727
  }
629
728
  capturePendingLayoutAnchor() {
630
729
  if (this.root == null || this.items.length === 0 || this.pendingScrollTarget != null) return;
@@ -668,6 +767,12 @@ var CodeView = class CodeView {
668
767
  getContainerElement() {
669
768
  return this.root;
670
769
  }
770
+ getHeaderElement() {
771
+ return this.header.element;
772
+ }
773
+ getFooterElement() {
774
+ return this.footer.element;
775
+ }
671
776
  getRenderedItems() {
672
777
  const { firstIndex, lastIndex } = this.renderState;
673
778
  if (firstIndex === -1 || lastIndex === -1 || lastIndex < firstIndex) return [];
@@ -701,7 +806,18 @@ var CodeView = class CodeView {
701
806
  return true;
702
807
  }
703
808
  getSlotSnapshot(coordinator) {
704
- return getSlotSnapshot(this.getRenderedItems(), coordinator);
809
+ return this.buildSlotSnapshot(coordinator);
810
+ }
811
+ buildSlotSnapshot(coordinator) {
812
+ const items = getSlotItems(this.getRenderedItems(), coordinator);
813
+ const { element: header } = this.header;
814
+ const { element: footer } = this.footer;
815
+ if (items == null && header == null && footer == null) return;
816
+ return {
817
+ items,
818
+ header,
819
+ footer
820
+ };
705
821
  }
706
822
  subscribeToScroll(listener) {
707
823
  this.scrollListeners.add(listener);
@@ -717,7 +833,7 @@ var CodeView = class CodeView {
717
833
  getTopForItem(id) {
718
834
  const item = this.idToItem.get(id);
719
835
  if (item == null) return;
720
- return item.top + this.getLayout().paddingTop;
836
+ return item.top + this.getItemTopOffset();
721
837
  }
722
838
  createItem(input, index, top) {
723
839
  const { itemMetricsCache: itemMetrics } = this;
@@ -764,6 +880,75 @@ var CodeView = class CodeView {
764
880
  }
765
881
  item.instance.setSelectedLines(this.selectedLines.range, { notify: false });
766
882
  }
883
+ isItemInEditMode(item) {
884
+ return this.options.createEditor != null && item.item.edit === true && item.item.collapsed !== true;
885
+ }
886
+ isReceiverEdited(receiver, mode) {
887
+ const state = getItemOptionsState(receiver);
888
+ if (state == null) return false;
889
+ const item = this.getItemOptions(state, mode);
890
+ return item != null && this.isItemInEditMode(item);
891
+ }
892
+ /**
893
+ * Attach (or lazily create) the editor for a mounted edit-mode item. Called
894
+ * from the render loop so every mounted item passes through it: fresh
895
+ * mounts, remounts after virtualization released the item, and items whose
896
+ * edit flag was just turned on. Editors persist across unmounts, so a
897
+ * remounted item re-attaches its existing editor and resumes the retained
898
+ * document; the renderers keep the host's file/diff data in sync with the
899
+ * session so the remount paints the edited text.
900
+ */
901
+ attachItemEditor(item) {
902
+ const { id } = item.item;
903
+ const { createEditor } = this.options;
904
+ if (createEditor == null || item.element == null || this.attachedEditors.has(id) || !this.isItemInEditMode(item)) return;
905
+ let record = this.itemEditors.get(id);
906
+ if (record == null) {
907
+ const state = { id };
908
+ const editor = createEditor({ onChange: (file, lineAnnotations) => {
909
+ const latest = this.idToItem.get(state.id);
910
+ if (latest == null) return;
911
+ state.lastChange = {
912
+ item: latest.item,
913
+ file,
914
+ lineAnnotations
915
+ };
916
+ this.options.onItemEditChange?.(latest.item, file, lineAnnotations);
917
+ } });
918
+ if (editor == null) return;
919
+ record = {
920
+ editor,
921
+ state
922
+ };
923
+ this.itemEditors.set(id, record);
924
+ }
925
+ if (this.selectedLines?.id === id) this.applySelectedLines(null, { notify: false });
926
+ record.editor.edit(item.instance);
927
+ this.attachedEditors.add(id);
928
+ }
929
+ /**
930
+ * Drop editors for items that can no longer be edited: removed, edit turned
931
+ * off, collapsed, or the createEditor option was unset. Attachment happens
932
+ * in the render loop via attachItemEditor, so this only reconciles editors
933
+ * CodeView is already holding.
934
+ */
935
+ syncItemEditors() {
936
+ if (this.itemEditors.size === 0) return;
937
+ const completions = [];
938
+ for (const [id, record] of this.itemEditors) {
939
+ const item = this.idToItem.get(id);
940
+ if (item != null && this.isItemInEditMode(item)) continue;
941
+ record.editor.cleanUp();
942
+ this.itemEditors.delete(id);
943
+ this.attachedEditors.delete(id);
944
+ const { lastChange } = record.state;
945
+ if (lastChange != null) completions.push(item == null ? lastChange : {
946
+ ...lastChange,
947
+ item: item.item
948
+ });
949
+ }
950
+ for (const { item, file, lineAnnotations } of completions) this.options.onItemEditComplete?.(item, file, lineAnnotations);
951
+ }
767
952
  renamePendingScrollTarget(oldId, newId) {
768
953
  const { pendingScrollTarget } = this;
769
954
  if (pendingScrollTarget == null || pendingScrollTarget.type === "position" || pendingScrollTarget.id !== oldId) return;
@@ -777,7 +962,14 @@ var CodeView = class CodeView {
777
962
  }
778
963
  createFileOptionsPrototype() {
779
964
  const prototype = {};
780
- for (const key of CODE_VIEW_FILE_OPTION_KEYS) defineItemOption(prototype, key, () => this.options[key]);
965
+ for (const key of CODE_VIEW_FILE_OPTION_KEYS) {
966
+ if (CODE_VIEW_EDIT_FORCED_OPTION_KEYS.has(key)) continue;
967
+ defineItemOption(prototype, key, () => this.options[key]);
968
+ }
969
+ defineItemOption(prototype, "useTokenTransformer", (receiver) => this.isReceiverEdited(receiver, "file") ? true : this.options.useTokenTransformer);
970
+ defineItemOption(prototype, "enableGutterUtility", (receiver) => this.isReceiverEdited(receiver, "file") ? false : this.options.enableGutterUtility);
971
+ defineItemOption(prototype, "enableLineSelection", (receiver) => this.isReceiverEdited(receiver, "file") ? false : this.options.enableLineSelection);
972
+ defineItemOption(prototype, "lineHoverHighlight", (receiver) => this.isReceiverEdited(receiver, "file") ? "disabled" : this.options.lineHoverHighlight);
781
973
  defineItemOption(prototype, "stickyHeader", () => this.options.stickyHeaders);
782
974
  defineItemOption(prototype, "collapsed", (receiver) => {
783
975
  const state = getItemOptionsState(receiver);
@@ -790,7 +982,15 @@ var CodeView = class CodeView {
790
982
  }
791
983
  createDiffOptionsPrototype() {
792
984
  const prototype = {};
793
- for (const key of CODE_VIEW_DIFF_OPTION_KEYS) defineItemOption(prototype, key, () => this.options[key]);
985
+ for (const key of CODE_VIEW_DIFF_OPTION_KEYS) {
986
+ if (CODE_VIEW_EDIT_FORCED_OPTION_KEYS.has(key)) continue;
987
+ defineItemOption(prototype, key, () => this.options[key]);
988
+ }
989
+ defineItemOption(prototype, "useTokenTransformer", (receiver) => this.isReceiverEdited(receiver, "diff") ? true : this.options.useTokenTransformer);
990
+ defineItemOption(prototype, "enableGutterUtility", (receiver) => this.isReceiverEdited(receiver, "diff") ? false : this.options.enableGutterUtility);
991
+ defineItemOption(prototype, "enableLineSelection", (receiver) => this.isReceiverEdited(receiver, "diff") ? false : this.options.enableLineSelection);
992
+ defineItemOption(prototype, "lineHoverHighlight", (receiver) => this.isReceiverEdited(receiver, "diff") ? "disabled" : this.options.lineHoverHighlight);
993
+ defineItemOption(prototype, "expandUnchanged", (receiver) => this.isReceiverEdited(receiver, "diff") ? true : this.options.expandUnchanged);
794
994
  defineItemOption(prototype, "stickyHeader", () => this.options.stickyHeaders);
795
995
  defineItemOption(prototype, "hunkSeparators", () => this.options.hunkSeparators);
796
996
  defineItemOption(prototype, "collapsed", (receiver) => {
@@ -846,6 +1046,8 @@ var CodeView = class CodeView {
846
1046
  if (this.options.enableLineSelection !== true) return;
847
1047
  const state = getItemOptionsState(receiver);
848
1048
  if (state == null) return;
1049
+ const item = this.getItemOptions(state, mode);
1050
+ if (item != null && this.isItemInEditMode(item)) return;
849
1051
  const callbackCache = state.callbackCache ??= {};
850
1052
  let wrapped = callbackCache[key];
851
1053
  if (wrapped == null) {
@@ -973,7 +1175,7 @@ var CodeView = class CodeView {
973
1175
  }
974
1176
  getMaxScrollTopForHeight(scrollHeight) {
975
1177
  const { paddingBottom, paddingTop } = this.getLayout();
976
- return Math.max(paddingTop + scrollHeight + paddingBottom - this.getHeight(), 0);
1178
+ return Math.max(paddingTop + this.header.height + scrollHeight + this.footer.height + paddingBottom - this.getHeight(), 0);
977
1179
  }
978
1180
  getMaxScrollTop() {
979
1181
  return this.getMaxScrollTopForHeight(this.getScrollHeight());
@@ -1085,7 +1287,7 @@ var CodeView = class CodeView {
1085
1287
  const rect = this.getScrollTargetRect(target);
1086
1288
  if (rect == null) return;
1087
1289
  const offset = target.offset ?? 0;
1088
- const targetTop = this.getLayout().paddingTop + rect.top;
1290
+ const targetTop = this.getItemTopOffset() + rect.top;
1089
1291
  const targetBottom = targetTop + rect.height;
1090
1292
  const currentTop = this.getScrollTop();
1091
1293
  const visibleTop = currentTop + (target.type === "line" || target.type === "range" ? this.getStickyHeaderOffset() : 0);
@@ -1137,7 +1339,7 @@ var CodeView = class CodeView {
1137
1339
  * and stickyOffset if necessary
1138
1340
  */
1139
1341
  resolveAlignedScrollPosition(targetTop, targetHeight, align, offset = 0, stickyOffset = 0) {
1140
- targetTop += this.getLayout().paddingTop;
1342
+ targetTop += this.getItemTopOffset();
1141
1343
  const viewportHeight = this.getHeight();
1142
1344
  if (align === "center" && targetHeight + offset < viewportHeight) return targetTop - (viewportHeight - targetHeight) / 2 + offset;
1143
1345
  if (align === "end") return targetTop - (viewportHeight - targetHeight) + offset;
@@ -1269,7 +1471,7 @@ var CodeView = class CodeView {
1269
1471
  const fitPerfectly = !computeScrollCorrection && (this.renderState.scrollTop === -1 || Math.abs(targetScrollTop - this.renderState.scrollTop) > viewportHeight + this.config.overscrollSize * 2);
1270
1472
  if (fitPerfectly) scrollAnchor = void 0;
1271
1473
  this.windowSpecs = createWindowFromScrollPosition({
1272
- scrollTop: targetScrollTop,
1474
+ scrollTop: targetScrollTop - this.header.height,
1273
1475
  height: viewportHeight,
1274
1476
  scrollHeight: this.getScrollHeight(),
1275
1477
  fitPerfectly,
@@ -1288,6 +1490,7 @@ var CodeView = class CodeView {
1288
1490
  if (item == null) throw new Error(`CodeView.computeRenderRangeAndEmit: No item at index: ${index}`);
1289
1491
  if (!(item.top > top - item.height && item.top <= bottom)) this.releaseRenderedItem(item);
1290
1492
  }
1493
+ const hostsChanged = this.reconcileHeaderFooterHosts();
1291
1494
  let prevElement;
1292
1495
  const updatedItems = /* @__PURE__ */ new Set();
1293
1496
  const startingIndex = this.findFirstVisibleIndex(top);
@@ -1313,11 +1516,13 @@ var CodeView = class CodeView {
1313
1516
  }
1314
1517
  prevElement = item.element;
1315
1518
  }
1519
+ if (item.item.edit === true) this.attachItemEditor(item);
1316
1520
  }
1317
1521
  this.renderState.firstIndex = startingIndex <= lastRenderedIndex ? startingIndex : -1;
1318
1522
  this.renderState.lastIndex = lastRenderedIndex;
1319
1523
  this.flushSlotCoordinator();
1320
1524
  this.flushManagers(updatedItems);
1525
+ if (hostsChanged) this.measureMountedHosts();
1321
1526
  this.reconcileRenderedItems(updatedItems);
1322
1527
  this.syncContainerHeight();
1323
1528
  this.updateStickyPositioning();
@@ -1456,6 +1661,25 @@ var CodeView = class CodeView {
1456
1661
  this.scrollAnimation = void 0;
1457
1662
  }
1458
1663
  }
1664
+ } else if (entry.target === this.header.element || entry.target === this.footer.element) {
1665
+ const host = entry.target === this.header.element ? this.header : this.footer;
1666
+ const blockSize = entry.borderBoxSize[0].blockSize;
1667
+ if (blockSize !== host.height) {
1668
+ const currentScrollTop = this.getScrollTop();
1669
+ const anchor = this.getScrollAnchor(currentScrollTop);
1670
+ this.setHostHeight(host, blockSize);
1671
+ const anchoredScrollTop = anchor != null ? this.resolveAnchoredScrollTop(anchor) : void 0;
1672
+ if (anchoredScrollTop != null) {
1673
+ const resizeAnchorDelta = anchoredScrollTop - currentScrollTop;
1674
+ this.applyScrollFix(anchoredScrollTop, currentScrollTop, this.windowSpecs);
1675
+ if (this.scrollAnimation != null) this.scrollAnimation.position += resizeAnchorDelta;
1676
+ }
1677
+ if (this.pendingScrollTarget != null && this.isPendingTargetSettled(this.pendingScrollTarget)) {
1678
+ this.pendingScrollTarget = void 0;
1679
+ this.scrollAnimation = void 0;
1680
+ }
1681
+ this.render();
1682
+ }
1459
1683
  } else {
1460
1684
  this.scrollDirty = true;
1461
1685
  this.heightDirty = true;
@@ -1478,6 +1702,7 @@ var CodeView = class CodeView {
1478
1702
  */
1479
1703
  getScrollAnchor(scrollTop) {
1480
1704
  if (this.pendingLayoutAnchor != null) return this.pendingLayoutAnchor;
1705
+ if (scrollTop <= 0) return;
1481
1706
  const { firstIndex, lastIndex, stickyTop, stickyBottom } = this.renderState;
1482
1707
  if (firstIndex === -1 || lastIndex === -1) return;
1483
1708
  const viewportHeight = this.getHeight();
@@ -1485,7 +1710,7 @@ var CodeView = class CodeView {
1485
1710
  for (let index = firstIndex; index <= lastIndex; index++) {
1486
1711
  const item = this.items[index];
1487
1712
  if (item == null) continue;
1488
- const absoluteItemTop = this.getLayout().paddingTop + item.top;
1713
+ const absoluteItemTop = this.getItemTopOffset() + item.top;
1489
1714
  if (absoluteItemTop + item.height <= scrollTop) continue;
1490
1715
  if (absoluteItemTop >= scrollTop + viewportHeight) break;
1491
1716
  if (absoluteItemTop >= scrollTop) return {
@@ -1517,14 +1742,14 @@ var CodeView = class CodeView {
1517
1742
  resolveAnchoredScrollTop(anchor) {
1518
1743
  const item = this.idToItem.get(anchor.id);
1519
1744
  if (item == null) return;
1520
- const { paddingTop } = this.getLayout();
1745
+ const itemTopOffset = this.getItemTopOffset();
1521
1746
  if (anchor.type === "item") {
1522
- const absoluteItemTop = paddingTop + item.top;
1747
+ const absoluteItemTop = itemTopOffset + item.top;
1523
1748
  return this.clampScrollTop(absoluteItemTop - anchor.viewportOffset);
1524
1749
  }
1525
1750
  const linePosition = item.type === "diff" ? item.instance.getLinePosition(anchor.lineNumber, anchor.side) : item.instance.getLinePosition(anchor.lineNumber);
1526
1751
  if (linePosition == null) return;
1527
- const absoluteLineTop = paddingTop + item.top + linePosition.top;
1752
+ const absoluteLineTop = itemTopOffset + item.top + linePosition.top;
1528
1753
  return this.clampScrollTop(absoluteLineTop - anchor.viewportOffset);
1529
1754
  }
1530
1755
  /**
@@ -1581,11 +1806,10 @@ var CodeView = class CodeView {
1581
1806
  }
1582
1807
  flushSlotCoordinator() {
1583
1808
  if (this.slotCoordinator == null) return;
1584
- const { onSnapshotChange } = this.slotCoordinator;
1585
- const slotSnapshot = getSlotSnapshot(this.getRenderedItems(), this.slotCoordinator);
1586
- if (areSlotSnapshotsEqual(this.slotSnapshot, slotSnapshot)) return;
1809
+ const slotSnapshot = this.buildSlotSnapshot(this.slotCoordinator);
1810
+ if (areManagedSnapshotsEqual(this.slotSnapshot, slotSnapshot)) return;
1587
1811
  this.slotSnapshot = slotSnapshot;
1588
- onSnapshotChange(slotSnapshot);
1812
+ this.slotCoordinator.onSnapshotChange(slotSnapshot);
1589
1813
  }
1590
1814
  notifyScroll() {
1591
1815
  if (this.scrollListeners.size === 0) return;
@@ -1736,7 +1960,7 @@ function syncRenderedItemOrder(container, element, prevElement) {
1736
1960
  function hasAnnotations(item) {
1737
1961
  return (item.annotations?.length ?? 0) > 0;
1738
1962
  }
1739
- function getSlotSnapshot(renderedItems, { hasHeaderRenderers, hasAnnotationRenderer, hasGutterRenderer }) {
1963
+ function getSlotItems(renderedItems, { hasHeaderRenderers, hasAnnotationRenderer, hasGutterRenderer }) {
1740
1964
  if (renderedItems.length === 0) return;
1741
1965
  if (hasHeaderRenderers || hasGutterRenderer) return renderedItems;
1742
1966
  if (!hasAnnotationRenderer) return;
@@ -1744,17 +1968,7 @@ function getSlotSnapshot(renderedItems, { hasHeaderRenderers, hasAnnotationRende
1744
1968
  for (const renderedItem of renderedItems) if (hasAnnotations(renderedItem.item)) slotSnapshot.push(renderedItem);
1745
1969
  return slotSnapshot.length > 0 ? slotSnapshot : void 0;
1746
1970
  }
1747
- function areSlotSnapshotsEqual(previous, next) {
1748
- if (previous == null || next == null) return previous === next;
1749
- if (previous.length !== next.length) return false;
1750
- for (let index = 0; index < previous.length; index++) {
1751
- const previousItem = previous[index];
1752
- const nextItem = next[index];
1753
- if (previousItem == null || nextItem == null || previousItem.id !== nextItem.id || previousItem.type !== nextItem.type || previousItem.element !== nextItem.element || previousItem.version !== nextItem.version) return false;
1754
- }
1755
- return true;
1756
- }
1757
1971
  //#endregion
1758
- export { CodeView };
1972
+ export { CODE_VIEW_DIFF_OPTION_KEYS, CODE_VIEW_FILE_OPTION_KEYS, CodeView };
1759
1973
 
1760
1974
  //# sourceMappingURL=CodeView.js.map