@pierre/diffs 1.2.0-beta.3 → 1.2.0-beta.5

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 (71) hide show
  1. package/dist/components/CodeView.d.ts +18 -10
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +124 -32
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +3 -2
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +13 -4
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +3 -2
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +13 -4
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +6 -3
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  16. package/dist/components/web-components.js +4 -0
  17. package/dist/components/web-components.js.map +1 -1
  18. package/dist/constants.d.ts +6 -3
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/constants.js +11 -2
  21. package/dist/constants.js.map +1 -1
  22. package/dist/index.d.ts +5 -5
  23. package/dist/index.js +3 -3
  24. package/dist/managers/InteractionManager.d.ts +22 -10
  25. package/dist/managers/InteractionManager.d.ts.map +1 -1
  26. package/dist/managers/InteractionManager.js +223 -28
  27. package/dist/managers/InteractionManager.js.map +1 -1
  28. package/dist/react/constants.d.ts.map +1 -1
  29. package/dist/react/constants.js +3 -1
  30. package/dist/react/constants.js.map +1 -1
  31. package/dist/react/index.d.ts +2 -2
  32. package/dist/react/jsx.d.ts.map +1 -1
  33. package/dist/react/types.d.ts +2 -2
  34. package/dist/react/types.d.ts.map +1 -1
  35. package/dist/react/utils/useFileDiffInstance.d.ts +2 -2
  36. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  37. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  38. package/dist/react/utils/useFileInstance.d.ts +2 -2
  39. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  40. package/dist/react/utils/useFileInstance.js.map +1 -1
  41. package/dist/react/utils/useUnresolvedFileInstance.d.ts +2 -2
  42. package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
  43. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  44. package/dist/ssr/index.d.ts +2 -2
  45. package/dist/style.js +1 -1
  46. package/dist/style.js.map +1 -1
  47. package/dist/types.d.ts +23 -9
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/utils/areSelectionsEqual.d.ts +1 -1
  50. package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
  51. package/dist/utils/areSelectionsEqual.js.map +1 -1
  52. package/dist/utils/createGutterUtilityContentNode.js +1 -0
  53. package/dist/utils/createGutterUtilityContentNode.js.map +1 -1
  54. package/dist/utils/cssWrappers.d.ts +3 -2
  55. package/dist/utils/cssWrappers.d.ts.map +1 -1
  56. package/dist/utils/cssWrappers.js +13 -2
  57. package/dist/utils/cssWrappers.js.map +1 -1
  58. package/dist/utils/getFiletypeFromFileName.js +16 -0
  59. package/dist/utils/getFiletypeFromFileName.js.map +1 -1
  60. package/dist/utils/parsePatchFiles.js +15 -0
  61. package/dist/utils/parsePatchFiles.js.map +1 -1
  62. package/dist/utils/scrollbarGutter.d.ts +6 -0
  63. package/dist/utils/scrollbarGutter.d.ts.map +1 -0
  64. package/dist/utils/scrollbarGutter.js +28 -0
  65. package/dist/utils/scrollbarGutter.js.map +1 -0
  66. package/dist/worker/WorkerPoolManager.js.map +1 -1
  67. package/dist/worker/worker-portable.js +26 -1
  68. package/dist/worker/worker-portable.js.map +1 -1
  69. package/dist/worker/worker.js +23 -0
  70. package/dist/worker/worker.js.map +1 -1
  71. package/package.json +1 -1
@@ -8,6 +8,7 @@ var InteractionManager = class {
8
8
  hoveredLine;
9
9
  hoveredToken;
10
10
  pre;
11
+ gutterUtilityLine;
11
12
  gutterUtilityContainer;
12
13
  gutterUtilityButton;
13
14
  gutterUtilitySlot;
@@ -37,6 +38,7 @@ var InteractionManager = class {
37
38
  this.pre?.removeAttribute("data-interactive-line-numbers");
38
39
  this.pre = void 0;
39
40
  this.gutterUtilityContainer?.remove();
41
+ this.gutterUtilityLine = void 0;
40
42
  this.gutterUtilityContainer = void 0;
41
43
  this.gutterUtilityButton = void 0;
42
44
  this.gutterUtilitySlot = void 0;
@@ -62,6 +64,7 @@ var InteractionManager = class {
62
64
  if (enableGutterUtility) this.ensureGutterUtilityNode(usesCustomGutterUtility);
63
65
  else if (this.gutterUtilityContainer != null) {
64
66
  this.gutterUtilityContainer.remove();
67
+ this.gutterUtilityLine = void 0;
65
68
  this.gutterUtilityContainer = void 0;
66
69
  this.gutterUtilityButton = void 0;
67
70
  this.gutterUtilitySlot = void 0;
@@ -73,6 +76,7 @@ var InteractionManager = class {
73
76
  this.syncPointerListeners(pre);
74
77
  this.updateInteractiveLineAttributes();
75
78
  this.renderSelection();
79
+ this.placeUtility();
76
80
  }
77
81
  setSelectionDirty() {
78
82
  this.renderedSelectionRange = void 0;
@@ -86,24 +90,26 @@ var InteractionManager = class {
86
90
  this.proposedSelectedRange = void 0;
87
91
  this.selectedRange = range;
88
92
  this.renderSelection();
93
+ this.placeUtility();
89
94
  if (isRangeChange && options?.notify !== false) this.notifySelectionCommitted();
90
95
  }
91
96
  getSelection() {
92
97
  return this.selectedRange;
93
98
  }
94
99
  getHoveredLine = () => {
95
- if (this.hoveredLine != null) {
96
- if (this.mode === "diff" && this.hoveredLine.type === "diff-line") return {
97
- lineNumber: this.hoveredLine.lineNumber,
98
- side: this.hoveredLine.annotationSide
100
+ const gutterUtilityLine = this.gutterUtilityLine ?? this.hoveredLine;
101
+ if (gutterUtilityLine != null) {
102
+ if (this.mode === "diff" && gutterUtilityLine.type === "diff-line") return {
103
+ lineNumber: gutterUtilityLine.lineNumber,
104
+ side: gutterUtilityLine.annotationSide
99
105
  };
100
- if (this.mode === "file" && this.hoveredLine.type === "line") return { lineNumber: this.hoveredLine.lineNumber };
106
+ if (this.mode === "file" && gutterUtilityLine.type === "line") return { lineNumber: gutterUtilityLine.lineNumber };
101
107
  }
102
108
  };
103
109
  handlePointerClick = (event) => {
104
110
  const { onHunkExpand, onLineClick, onLineNumberClick, onTokenClick, onMergeConflictActionClick } = this.options;
105
111
  if (onHunkExpand == null && onLineClick == null && onLineNumberClick == null && onMergeConflictActionClick == null && onTokenClick == null) return;
106
- if (this.options.onGutterUtilityClick != null && isGutterUtilityPointerPath(event.composedPath())) return;
112
+ if (this.options.onGutterUtilityClick != null && isGutterUtilityPath(event.composedPath())) return;
107
113
  debugLogIfEnabled(this.options.__debugPointerEvents, "click", "FileDiff.DEBUG.handlePointerClick:", event);
108
114
  this.handlePointerEvent({
109
115
  eventType: "click",
@@ -111,6 +117,7 @@ var InteractionManager = class {
111
117
  });
112
118
  };
113
119
  handlePointerMove = (event) => {
120
+ if (event.pointerType !== "mouse") return;
114
121
  const { lineHoverHighlight = "disabled", onLineEnter, onLineLeave, onTokenEnter, onTokenLeave, enableGutterUtility = false } = this.options;
115
122
  if (lineHoverHighlight === "disabled" && !enableGutterUtility && onLineEnter == null && onLineLeave == null && onTokenEnter == null && onTokenLeave == null) return;
116
123
  debugLogIfEnabled(this.options.__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerMove:", event);
@@ -126,7 +133,6 @@ var InteractionManager = class {
126
133
  debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token");
127
134
  return;
128
135
  }
129
- this.gutterUtilityContainer?.remove();
130
136
  if (this.hoveredToken != null) {
131
137
  this.options.onTokenLeave?.(this.hoveredToken, event);
132
138
  this.clearHoveredToken();
@@ -138,6 +144,7 @@ var InteractionManager = class {
138
144
  });
139
145
  this.clearHoveredLine();
140
146
  }
147
+ this.placeUtility();
141
148
  };
142
149
  handlePointerEvent({ eventType, event }) {
143
150
  const { __debugPointerEvents } = this.options;
@@ -164,7 +171,6 @@ var InteractionManager = class {
164
171
  }
165
172
  if (!sameLine) {
166
173
  if (this.hoveredLine != null) {
167
- this.gutterUtilityContainer?.remove();
168
174
  onLineLeave?.({
169
175
  ...this.hoveredLine,
170
176
  event
@@ -173,12 +179,12 @@ var InteractionManager = class {
173
179
  }
174
180
  if (isHoverableLinePointerTarget(target)) {
175
181
  this.setHoveredLine(this.toEventBaseProps(target));
176
- if (this.gutterUtilityContainer != null) target.numberElement.appendChild(this.gutterUtilityContainer);
182
+ this.placeUtility();
177
183
  onLineEnter?.({
178
184
  ...this.hoveredLine,
179
185
  event
180
186
  });
181
- }
187
+ } else this.placeUtility();
182
188
  }
183
189
  break;
184
190
  }
@@ -268,13 +274,19 @@ var InteractionManager = class {
268
274
  handlePointerDown = (event) => {
269
275
  if (event.pointerType === "mouse" && event.button !== 0 || this.pre == null || this.pointerSession.mode !== "idle") return;
270
276
  const path = event.composedPath();
271
- if (isGutterUtilityPointerPath(path) && this.options.onGutterUtilityClick != null) this.startGutterSelectionFromPointerDown(event, path);
272
- else this.startLineSelectionFromPointerDown(event, path);
277
+ if (isGutterUtilityPath(path) && this.options.onGutterUtilityClick != null) this.startGutterSelectionFromPointerDown(event);
278
+ else {
279
+ if (event.pointerType !== "mouse") this.revealUtilityFromGutterPath(path);
280
+ this.startLineSelectionFromPointerDown(event);
281
+ }
273
282
  };
274
- startLineSelectionFromPointerDown(event, path) {
283
+ startLineSelectionFromPointerDown(event) {
275
284
  const { enableLineSelection = false } = this.options;
276
285
  if (!enableLineSelection) return;
277
- const pointerInfo = this.getSelectionPointerInfo(path, true);
286
+ const pointerInfo = this.resolveSelectionInfo(event, {
287
+ source: "event-path",
288
+ requireNumberColumn: true
289
+ });
278
290
  if (pointerInfo == null) return;
279
291
  const { pre } = this;
280
292
  if (pre == null) return;
@@ -314,6 +326,7 @@ var InteractionManager = class {
314
326
  }
315
327
  if (this.options.controlledSelection === true) this.proposedSelectedRange = null;
316
328
  else this.selectedRange = null;
329
+ this.placeUtility();
317
330
  this.selectionAnchor = {
318
331
  lineNumber,
319
332
  side: eventSide
@@ -326,23 +339,28 @@ var InteractionManager = class {
326
339
  };
327
340
  this.attachDocumentPointerListeners();
328
341
  }
329
- startGutterSelectionFromPointerDown(event, path) {
342
+ startGutterSelectionFromPointerDown(event) {
330
343
  const { enableLineSelection = false, onGutterUtilityClick } = this.options;
331
344
  if (onGutterUtilityClick == null) return;
332
- const point = this.getSelectionPointFromPath(path);
333
- if (point == null) return;
345
+ const selectedEndpoints = this.currentSelectionEnds();
346
+ const point = selectedEndpoints?.bottom ?? this.resolveSelectionPoint(event, {
347
+ source: "event-path",
348
+ excludeUtility: false
349
+ });
350
+ const anchor = selectedEndpoints?.top ?? point;
351
+ if (point == null || anchor == null) return;
334
352
  event.preventDefault();
335
353
  event.stopPropagation();
336
354
  this.pointerSession = {
337
355
  mode: "gutterSelecting",
338
356
  pointerId: event.pointerId,
339
- anchor: point,
357
+ anchor,
340
358
  current: point
341
359
  };
342
360
  if (enableLineSelection) {
343
361
  this.selectionAnchor = {
344
- lineNumber: point.lineNumber,
345
- side: point.side
362
+ lineNumber: anchor.lineNumber,
363
+ side: anchor.side
346
364
  };
347
365
  this.updateSelection(point.lineNumber, point.side, false);
348
366
  this.notifySelectionStart(this.getCurrentSelectionRange());
@@ -355,7 +373,8 @@ var InteractionManager = class {
355
373
  case "idle": return;
356
374
  case "gutterSelecting": {
357
375
  if (event.pointerId !== this.pointerSession.pointerId) return;
358
- const point = this.getSelectionPointFromPath(event.composedPath());
376
+ event.preventDefault();
377
+ const point = this.resolveSelectionPoint(event, { source: "coordinates-first" });
359
378
  if (point == null) return;
360
379
  this.pointerSession.current = point;
361
380
  if (enableLineSelection === true) this.updateSelection(point.lineNumber, point.side);
@@ -363,14 +382,22 @@ var InteractionManager = class {
363
382
  }
364
383
  case "selecting": {
365
384
  if (event.pointerId !== this.pointerSession.pointerId) return;
366
- const pointerInfo = this.getSelectionPointerInfo(event.composedPath(), false);
385
+ event.preventDefault();
386
+ const pointerInfo = this.resolveSelectionInfo(event, {
387
+ source: "coordinates-first",
388
+ requireNumberColumn: false
389
+ });
367
390
  if (pointerInfo == null || this.selectionAnchor == null) return;
368
391
  this.updateSelection(pointerInfo.lineNumber, pointerInfo.eventSide);
369
392
  return;
370
393
  }
371
394
  case "pendingSingleLineUnselect": {
372
395
  if (event.pointerId !== this.pointerSession.pointerId) return;
373
- const pointerInfo = this.getSelectionPointerInfo(event.composedPath(), false);
396
+ event.preventDefault();
397
+ const pointerInfo = this.resolveSelectionInfo(event, {
398
+ source: "coordinates-first",
399
+ requireNumberColumn: false
400
+ });
374
401
  if (pointerInfo == null || this.selectionAnchor == null) return;
375
402
  const point = {
376
403
  lineNumber: pointerInfo.lineNumber,
@@ -394,7 +421,8 @@ var InteractionManager = class {
394
421
  case "idle": return;
395
422
  case "gutterSelecting": {
396
423
  if (event.pointerId !== this.pointerSession.pointerId) return;
397
- const point = this.getSelectionPointFromPath(event.composedPath());
424
+ event.preventDefault();
425
+ const point = this.resolveSelectionPoint(event, { source: "coordinates-first" });
398
426
  if (point != null) {
399
427
  this.pointerSession.current = point;
400
428
  if (enableLineSelection) this.updateSelection(point.lineNumber, point.side);
@@ -412,6 +440,7 @@ var InteractionManager = class {
412
440
  }
413
441
  case "pendingSingleLineUnselect":
414
442
  if (event.pointerId !== this.pointerSession.pointerId) return;
443
+ event.preventDefault();
415
444
  this.updateSelection(null, void 0, false);
416
445
  this.selectionAnchor = void 0;
417
446
  this.clearPendingSingleLineState();
@@ -422,6 +451,7 @@ var InteractionManager = class {
422
451
  return;
423
452
  case "selecting":
424
453
  if (event.pointerId !== this.pointerSession.pointerId) return;
454
+ event.preventDefault();
425
455
  this.selectionAnchor = void 0;
426
456
  this.detachDocumentPointerListeners();
427
457
  this.clearPointerSession();
@@ -498,6 +528,79 @@ var InteractionManager = class {
498
528
  if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);
499
529
  }
500
530
  }
531
+ revealUtilityFromGutterPath(path) {
532
+ if (this.placeUtilityFromSelection()) return;
533
+ const target = this.resolvePointerTarget(path);
534
+ if (isLinePointerTarget(target) && target.numberColumn) this.showUtilityOnLine(this.toEventBaseProps(target));
535
+ }
536
+ placeUtility() {
537
+ if (this.placeUtilityFromSelection()) return;
538
+ if (this.hoveredLine != null) {
539
+ this.showUtilityOnLine(this.hoveredLine);
540
+ return;
541
+ }
542
+ this.hideUtility();
543
+ }
544
+ placeUtilityFromSelection() {
545
+ const endpoints = this.currentSelectionEnds();
546
+ if (endpoints == null) return false;
547
+ const target = this.targetForSelectionPoint(endpoints.bottom);
548
+ if (target == null) this.hideUtility();
549
+ else this.showUtilityOnLine(this.toEventBaseProps(target));
550
+ return true;
551
+ }
552
+ showUtilityOnLine(line) {
553
+ if (this.gutterUtilityContainer == null) return;
554
+ this.gutterUtilityLine = line;
555
+ line.numberElement.appendChild(this.gutterUtilityContainer);
556
+ }
557
+ hideUtility() {
558
+ this.gutterUtilityContainer?.remove();
559
+ this.gutterUtilityLine = void 0;
560
+ }
561
+ currentSelectionEnds() {
562
+ const range = this.getCurrentSelectionRange();
563
+ return range == null ? void 0 : this.selectionEnds(range);
564
+ }
565
+ selectionEnds(range) {
566
+ const start = {
567
+ lineNumber: range.start,
568
+ side: range.side
569
+ };
570
+ const end = {
571
+ lineNumber: range.end,
572
+ side: range.endSide ?? range.side
573
+ };
574
+ const startIndex = this.selectionPointRowIndex(start);
575
+ const endIndex = this.selectionPointRowIndex(end);
576
+ if (startIndex == null || endIndex == null) return;
577
+ return startIndex > endIndex ? {
578
+ top: end,
579
+ bottom: start
580
+ } : {
581
+ top: start,
582
+ bottom: end
583
+ };
584
+ }
585
+ selectionPointRowIndex(point) {
586
+ const indexes = this.getLineIndex(point.lineNumber, point.side);
587
+ if (indexes == null) return;
588
+ return this.isSplitDiff() ? indexes[1] : indexes[0];
589
+ }
590
+ targetForSelectionPoint(point) {
591
+ if (this.pre == null) return;
592
+ const indexes = this.getLineIndex(point.lineNumber, point.side);
593
+ if (indexes == null) return;
594
+ const lineIndex = this.mode === "diff" ? `${indexes[0]},${indexes[1]}` : `${indexes[0]}`;
595
+ const candidates = this.pre.querySelectorAll(`[data-column-number="${point.lineNumber}"][data-line-index="${lineIndex}"]`);
596
+ for (const element of candidates) {
597
+ if (!(element instanceof HTMLElement)) continue;
598
+ const target = this.resolvePointerTarget(getElementPath(element));
599
+ if (!isLinePointerTarget(target)) continue;
600
+ if (this.mode === "diff" && point.side != null && target.side !== point.side) continue;
601
+ return target;
602
+ }
603
+ }
501
604
  attachDocumentPointerListeners() {
502
605
  if (this.hasDocumentPointerListeners) return;
503
606
  document.addEventListener("pointermove", this.handleDocumentPointerMove);
@@ -518,7 +621,7 @@ var InteractionManager = class {
518
621
  clearPendingSingleLineState() {
519
622
  if (this.pointerSession.mode === "pendingSingleLineUnselect") this.pointerSession = { mode: "idle" };
520
623
  }
521
- getSelectionPointerInfo(path, requireNumberColumn) {
624
+ selectionInfoFromPath(path, requireNumberColumn) {
522
625
  const target = this.resolvePointerTarget(path);
523
626
  if (!isLinePointerTarget(target)) return;
524
627
  if (requireNumberColumn && !target.numberColumn) return;
@@ -529,7 +632,11 @@ var InteractionManager = class {
529
632
  eventSide: this.mode === "diff" ? target.side : void 0
530
633
  };
531
634
  }
532
- getSelectionPointFromPath(path) {
635
+ resolveSelectionInfo(event, options) {
636
+ const path = this.resolveSelectionPath(event, options);
637
+ return path != null ? this.selectionInfoFromPath(path, options.requireNumberColumn) : void 0;
638
+ }
639
+ selectionPointFromPath(path) {
533
640
  const target = this.resolvePointerTarget(path);
534
641
  if (!isLinePointerTarget(target)) return;
535
642
  return {
@@ -537,6 +644,51 @@ var InteractionManager = class {
537
644
  side: this.mode === "diff" ? target.side : void 0
538
645
  };
539
646
  }
647
+ resolveSelectionPoint(event, options) {
648
+ const path = this.resolveSelectionPath(event, options);
649
+ return path != null ? this.selectionPointFromPath(path) : void 0;
650
+ }
651
+ resolveSelectionPath(event, options) {
652
+ const excludeUtility = options.excludeUtility !== false;
653
+ switch (options.source) {
654
+ case "event-path": return this.pathFromEventPath(event.composedPath(), excludeUtility);
655
+ case "coordinates-first": {
656
+ const coordinatePath = this.pathFromCoordinates(event, excludeUtility);
657
+ if (coordinatePath !== void 0) return coordinatePath ?? void 0;
658
+ return this.pathFromEventPath(event.composedPath(), excludeUtility);
659
+ }
660
+ }
661
+ }
662
+ pathFromCoordinates(event, excludeUtility) {
663
+ const coordinateTarget = this.hitTest(event);
664
+ if (coordinateTarget === void 0) return;
665
+ if (coordinateTarget === null) return null;
666
+ return this.pathFromElement(coordinateTarget, excludeUtility) ?? null;
667
+ }
668
+ pathFromEventPath(path, excludeUtility) {
669
+ if (excludeUtility && isGutterUtilityPath(path)) return;
670
+ for (const element of path) if (element instanceof Element) return this.pathFromElement(element, excludeUtility);
671
+ }
672
+ pathFromElement(element, excludeUtility) {
673
+ const path = getElementPath(element);
674
+ if (excludeUtility && isGutterUtilityPath(path)) return;
675
+ const row = closestSelectableRow(element);
676
+ if (row != null) return getElementPath(row);
677
+ return this.pathFromAnnotationSlot(element);
678
+ }
679
+ pathFromAnnotationSlot(element) {
680
+ const point = selectionPointFromAnnotationSlotName(getAnnotationSlotName(element));
681
+ if (point == null) return;
682
+ const target = this.targetForSelectionPoint(point);
683
+ return target != null ? getElementPath(target.lineElement) : void 0;
684
+ }
685
+ hitTest(event) {
686
+ if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) return;
687
+ const root = this.pre?.getRootNode();
688
+ const elementFromPointRoot = hasElementFromPoint(root) ? root : hasElementFromPoint(document) ? document : void 0;
689
+ if (elementFromPointRoot == null) return;
690
+ return elementFromPointRoot.elementFromPoint(event.clientX, event.clientY);
691
+ }
540
692
  getLineIndex(lineNumber, side) {
541
693
  const { getLineIndex } = this.options;
542
694
  return getLineIndex != null ? getLineIndex(lineNumber, side) : [lineNumber - 1, lineNumber - 1];
@@ -562,6 +714,7 @@ var InteractionManager = class {
562
714
  this.selectedRange = nextRange;
563
715
  this.queuedSelectionRender ??= requestAnimationFrame(this.renderSelection);
564
716
  }
717
+ this.placeUtility();
565
718
  if (emitChange) this.notifySelectionChangeDelta();
566
719
  }
567
720
  getIndexesFromSelection(selectedRange, split) {
@@ -890,6 +1043,45 @@ function queryHTMLElement(parent, query) {
890
1043
  const element = parent?.querySelector(query);
891
1044
  return element instanceof HTMLElement ? element : void 0;
892
1045
  }
1046
+ function getElementPath(element) {
1047
+ const path = [];
1048
+ let current = element;
1049
+ while (current != null) {
1050
+ path.push(current);
1051
+ current = current.parentNode;
1052
+ }
1053
+ return path;
1054
+ }
1055
+ function closestSelectableRow(element) {
1056
+ const row = element.closest("[data-line], [data-column-number]");
1057
+ if (row instanceof HTMLElement) return row;
1058
+ const annotationRow = element.closest("[data-line-annotation], [data-gutter-buffer=\"annotation\"]");
1059
+ if (!(annotationRow instanceof HTMLElement)) return;
1060
+ const previousRow = annotationRow.previousElementSibling;
1061
+ return previousRow instanceof HTMLElement && (previousRow.hasAttribute("data-line") || previousRow.hasAttribute("data-column-number")) ? previousRow : void 0;
1062
+ }
1063
+ function getAnnotationSlotName(element) {
1064
+ const slottedElement = element.closest("[slot^=\"annotation-\"]");
1065
+ if (slottedElement instanceof HTMLElement) return slottedElement.getAttribute("slot") ?? void 0;
1066
+ if (element instanceof HTMLElement) {
1067
+ const slotName = element.getAttribute("name") ?? void 0;
1068
+ return slotName != null && slotName.startsWith("annotation-") ? slotName : void 0;
1069
+ }
1070
+ }
1071
+ function selectionPointFromAnnotationSlotName(slotName) {
1072
+ if (slotName == null) return;
1073
+ const match = /^annotation-(?:(additions|deletions)-)?(\d+)$/.exec(slotName);
1074
+ if (match == null) return;
1075
+ const lineNumber = Number.parseInt(match[2], 10);
1076
+ if (!Number.isFinite(lineNumber)) return;
1077
+ return {
1078
+ lineNumber,
1079
+ side: match[1]
1080
+ };
1081
+ }
1082
+ function hasElementFromPoint(value) {
1083
+ return value != null && typeof value.elementFromPoint === "function";
1084
+ }
893
1085
  function getAnnotationSide(lineType, codeElement) {
894
1086
  switch (lineType) {
895
1087
  case "change-deletion": return "deletions";
@@ -908,8 +1100,11 @@ function getLineTypeFromElement(element) {
908
1100
  default: return;
909
1101
  }
910
1102
  }
911
- function isGutterUtilityPointerPath(path) {
912
- for (const element of path) if (element instanceof HTMLElement && element.hasAttribute("data-utility-button")) return true;
1103
+ function isGutterUtilityPath(path) {
1104
+ for (const element of path) {
1105
+ if (!(element instanceof HTMLElement)) continue;
1106
+ if (element.hasAttribute("data-utility-button") || element.hasAttribute("data-gutter-utility-slot") || element.getAttribute("slot") === "gutter-utility-slot" || element.getAttribute("name") === "gutter-utility-slot") return true;
1107
+ }
913
1108
  return false;
914
1109
  }
915
1110
  function debugLogIfEnabled(debugLogType = "none", logIfType, ...args) {