@pierre/diffs 1.1.0-beta.8 → 1.1.0

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 (217) hide show
  1. package/README.md +7 -18
  2. package/dist/components/AdvancedVirtualizedFileDiff.js +2 -7
  3. package/dist/components/AdvancedVirtualizedFileDiff.js.map +1 -1
  4. package/dist/components/AdvancedVirtualizer.js +1 -1
  5. package/dist/components/AdvancedVirtualizer.js.map +1 -1
  6. package/dist/components/File.d.ts +17 -7
  7. package/dist/components/File.d.ts.map +1 -1
  8. package/dist/components/File.js +111 -54
  9. package/dist/components/File.js.map +1 -1
  10. package/dist/components/FileDiff.d.ts +32 -14
  11. package/dist/components/FileDiff.d.ts.map +1 -1
  12. package/dist/components/FileDiff.js +156 -81
  13. package/dist/components/FileDiff.js.map +1 -1
  14. package/dist/components/UnresolvedFile.d.ts +60 -0
  15. package/dist/components/UnresolvedFile.d.ts.map +1 -0
  16. package/dist/components/UnresolvedFile.js +280 -0
  17. package/dist/components/UnresolvedFile.js.map +1 -0
  18. package/dist/components/VirtualizedFile.js +8 -5
  19. package/dist/components/VirtualizedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts +1 -1
  21. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.js +15 -11
  23. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  24. package/dist/components/Virtualizer.d.ts +3 -1
  25. package/dist/components/Virtualizer.d.ts.map +1 -1
  26. package/dist/components/Virtualizer.js +50 -24
  27. package/dist/components/Virtualizer.js.map +1 -1
  28. package/dist/constants.d.ts +3 -1
  29. package/dist/constants.d.ts.map +1 -1
  30. package/dist/constants.js +8 -1
  31. package/dist/constants.js.map +1 -1
  32. package/dist/highlighter/shared_highlighter.d.ts +4 -2
  33. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  34. package/dist/highlighter/shared_highlighter.js +15 -7
  35. package/dist/highlighter/shared_highlighter.js.map +1 -1
  36. package/dist/index.d.ts +9 -7
  37. package/dist/index.js +8 -6
  38. package/dist/managers/InteractionManager.d.ts +146 -0
  39. package/dist/managers/InteractionManager.d.ts.map +1 -0
  40. package/dist/managers/InteractionManager.js +813 -0
  41. package/dist/managers/InteractionManager.js.map +1 -0
  42. package/dist/managers/ResizeManager.d.ts +0 -2
  43. package/dist/managers/ResizeManager.d.ts.map +1 -1
  44. package/dist/managers/ResizeManager.js +43 -32
  45. package/dist/managers/ResizeManager.js.map +1 -1
  46. package/dist/react/File.d.ts +2 -0
  47. package/dist/react/File.d.ts.map +1 -1
  48. package/dist/react/File.js +3 -1
  49. package/dist/react/File.js.map +1 -1
  50. package/dist/react/FileDiff.d.ts +2 -0
  51. package/dist/react/FileDiff.d.ts.map +1 -1
  52. package/dist/react/FileDiff.js +3 -1
  53. package/dist/react/FileDiff.js.map +1 -1
  54. package/dist/react/MultiFileDiff.d.ts +2 -0
  55. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  56. package/dist/react/MultiFileDiff.js +3 -1
  57. package/dist/react/MultiFileDiff.js.map +1 -1
  58. package/dist/react/PatchDiff.d.ts +2 -0
  59. package/dist/react/PatchDiff.d.ts.map +1 -1
  60. package/dist/react/PatchDiff.js +3 -1
  61. package/dist/react/PatchDiff.js.map +1 -1
  62. package/dist/react/UnresolvedFile.d.ts +36 -0
  63. package/dist/react/UnresolvedFile.d.ts.map +1 -0
  64. package/dist/react/UnresolvedFile.js +42 -0
  65. package/dist/react/UnresolvedFile.js.map +1 -0
  66. package/dist/react/constants.d.ts +3 -2
  67. package/dist/react/constants.d.ts.map +1 -1
  68. package/dist/react/constants.js +3 -2
  69. package/dist/react/constants.js.map +1 -1
  70. package/dist/react/index.d.ts +4 -3
  71. package/dist/react/index.js +3 -2
  72. package/dist/react/types.d.ts +11 -2
  73. package/dist/react/types.d.ts.map +1 -1
  74. package/dist/react/utils/renderDiffChildren.d.ts +16 -5
  75. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  76. package/dist/react/utils/renderDiffChildren.js +34 -7
  77. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  78. package/dist/react/utils/renderFileChildren.d.ts +5 -1
  79. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  80. package/dist/react/utils/renderFileChildren.js +13 -7
  81. package/dist/react/utils/renderFileChildren.js.map +1 -1
  82. package/dist/react/utils/useFileDiffInstance.d.ts +1 -2
  83. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  84. package/dist/react/utils/useFileDiffInstance.js +2 -2
  85. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  86. package/dist/react/utils/useFileInstance.d.ts +1 -2
  87. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  88. package/dist/react/utils/useFileInstance.js.map +1 -1
  89. package/dist/react/utils/useUnresolvedFileInstance.d.ts +33 -0
  90. package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -0
  91. package/dist/react/utils/useUnresolvedFileInstance.js +87 -0
  92. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -0
  93. package/dist/renderers/DiffHunksRenderer.d.ts +50 -6
  94. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  95. package/dist/renderers/DiffHunksRenderer.js +146 -45
  96. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  97. package/dist/renderers/FileRenderer.js +1 -1
  98. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +46 -0
  99. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -0
  100. package/dist/renderers/UnresolvedFileHunksRenderer.js +207 -0
  101. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -0
  102. package/dist/shiki-stream/stream.d.ts +1 -1
  103. package/dist/shiki-stream/stream.d.ts.map +1 -1
  104. package/dist/shiki-stream/stream.js.map +1 -1
  105. package/dist/shiki-stream/tokenizer.d.ts +1 -1
  106. package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
  107. package/dist/shiki-stream/tokenizer.js.map +1 -1
  108. package/dist/shiki-stream/types.d.ts +1 -1
  109. package/dist/shiki-stream/types.d.ts.map +1 -1
  110. package/dist/sprite.d.ts +2 -2
  111. package/dist/sprite.d.ts.map +1 -1
  112. package/dist/sprite.js +3 -0
  113. package/dist/sprite.js.map +1 -1
  114. package/dist/ssr/index.d.ts +3 -3
  115. package/dist/ssr/index.js +2 -2
  116. package/dist/ssr/preloadDiffs.d.ts +23 -14
  117. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  118. package/dist/ssr/preloadDiffs.js +40 -14
  119. package/dist/ssr/preloadDiffs.js.map +1 -1
  120. package/dist/style.js +1 -1
  121. package/dist/style.js.map +1 -1
  122. package/dist/types.d.ts +29 -2
  123. package/dist/types.d.ts.map +1 -1
  124. package/dist/utils/areMergeConflictActionsEqual.d.ts +7 -0
  125. package/dist/utils/areMergeConflictActionsEqual.d.ts.map +1 -0
  126. package/dist/utils/areMergeConflictActionsEqual.js +11 -0
  127. package/dist/utils/areMergeConflictActionsEqual.js.map +1 -0
  128. package/dist/utils/arePrePropertiesEqual.js +10 -1
  129. package/dist/utils/arePrePropertiesEqual.js.map +1 -1
  130. package/dist/utils/areSelectionPointsEqual.d.ts +7 -0
  131. package/dist/utils/areSelectionPointsEqual.d.ts.map +1 -0
  132. package/dist/utils/areSelectionPointsEqual.js +8 -0
  133. package/dist/utils/areSelectionPointsEqual.js.map +1 -0
  134. package/dist/utils/areSelectionsEqual.d.ts +1 -1
  135. package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
  136. package/dist/utils/areSelectionsEqual.js.map +1 -1
  137. package/dist/utils/createFileHeaderElement.js +5 -2
  138. package/dist/utils/createFileHeaderElement.js.map +1 -1
  139. package/dist/utils/createGutterUtilityContentNode.d.ts +5 -0
  140. package/dist/utils/createGutterUtilityContentNode.d.ts.map +1 -0
  141. package/dist/utils/createGutterUtilityContentNode.js +15 -0
  142. package/dist/utils/createGutterUtilityContentNode.js.map +1 -0
  143. package/dist/utils/createGutterUtilityElement.d.ts +7 -0
  144. package/dist/utils/createGutterUtilityElement.d.ts.map +1 -0
  145. package/dist/utils/createGutterUtilityElement.js +20 -0
  146. package/dist/utils/createGutterUtilityElement.js.map +1 -0
  147. package/dist/utils/createPreElement.d.ts +2 -1
  148. package/dist/utils/createPreElement.d.ts.map +1 -1
  149. package/dist/utils/createPreElement.js +2 -1
  150. package/dist/utils/createPreElement.js.map +1 -1
  151. package/dist/utils/createSeparator.js +1 -1
  152. package/dist/utils/createSeparator.js.map +1 -1
  153. package/dist/utils/createWindowFromScrollPosition.js +12 -11
  154. package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
  155. package/dist/utils/getHighlighterOptions.d.ts +7 -2
  156. package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
  157. package/dist/utils/getHighlighterOptions.js +3 -2
  158. package/dist/utils/getHighlighterOptions.js.map +1 -1
  159. package/dist/utils/getMergeConflictActionSlotName.d.ts +16 -0
  160. package/dist/utils/getMergeConflictActionSlotName.d.ts.map +1 -0
  161. package/dist/utils/getMergeConflictActionSlotName.js +8 -0
  162. package/dist/utils/getMergeConflictActionSlotName.js.map +1 -0
  163. package/dist/utils/getMergeConflictLineTypes.d.ts +15 -0
  164. package/dist/utils/getMergeConflictLineTypes.d.ts.map +1 -0
  165. package/dist/utils/getMergeConflictLineTypes.js +81 -0
  166. package/dist/utils/getMergeConflictLineTypes.js.map +1 -0
  167. package/dist/utils/getOrCreateCodeNode.d.ts +3 -1
  168. package/dist/utils/getOrCreateCodeNode.d.ts.map +1 -1
  169. package/dist/utils/getOrCreateCodeNode.js +5 -3
  170. package/dist/utils/getOrCreateCodeNode.js.map +1 -1
  171. package/dist/utils/hast_utils.d.ts +2 -2
  172. package/dist/utils/hast_utils.d.ts.map +1 -1
  173. package/dist/utils/hast_utils.js +3 -2
  174. package/dist/utils/hast_utils.js.map +1 -1
  175. package/dist/utils/parseMergeConflictDiffFromFile.d.ts +26 -0
  176. package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -0
  177. package/dist/utils/parseMergeConflictDiffFromFile.js +143 -0
  178. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -0
  179. package/dist/utils/resolveMergeConflict.d.ts +7 -0
  180. package/dist/utils/resolveMergeConflict.d.ts.map +1 -0
  181. package/dist/utils/resolveMergeConflict.js +30 -0
  182. package/dist/utils/resolveMergeConflict.js.map +1 -0
  183. package/dist/utils/resolveVirtualFileMetrics.js +1 -0
  184. package/dist/utils/resolveVirtualFileMetrics.js.map +1 -1
  185. package/dist/utils/setWrapperNodeProps.d.ts +2 -1
  186. package/dist/utils/setWrapperNodeProps.d.ts.map +1 -1
  187. package/dist/utils/setWrapperNodeProps.js +5 -1
  188. package/dist/utils/setWrapperNodeProps.js.map +1 -1
  189. package/dist/worker/WorkerPoolManager.d.ts +4 -2
  190. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  191. package/dist/worker/WorkerPoolManager.js +16 -9
  192. package/dist/worker/WorkerPoolManager.js.map +1 -1
  193. package/dist/worker/types.d.ts +3 -1
  194. package/dist/worker/types.d.ts.map +1 -1
  195. package/dist/worker/wasm-BlUZCxHM.js +10 -0
  196. package/dist/worker/wasm-BlUZCxHM.js.map +1 -0
  197. package/dist/worker/worker-portable.js +10546 -10106
  198. package/dist/worker/worker-portable.js.map +1 -1
  199. package/dist/worker/worker.js +27 -19
  200. package/dist/worker/worker.js.map +1 -1
  201. package/package.json +3 -7
  202. package/dist/managers/LineSelectionManager.d.ts +0 -64
  203. package/dist/managers/LineSelectionManager.d.ts.map +0 -1
  204. package/dist/managers/LineSelectionManager.js +0 -270
  205. package/dist/managers/LineSelectionManager.js.map +0 -1
  206. package/dist/managers/MouseEventManager.d.ts +0 -71
  207. package/dist/managers/MouseEventManager.d.ts.map +0 -1
  208. package/dist/managers/MouseEventManager.js +0 -358
  209. package/dist/managers/MouseEventManager.js.map +0 -1
  210. package/dist/themes/pierre-dark.js +0 -1328
  211. package/dist/themes/pierre-dark.js.map +0 -1
  212. package/dist/themes/pierre-light.js +0 -1328
  213. package/dist/themes/pierre-light.js.map +0 -1
  214. package/dist/utils/createHoverContentNode.d.ts +0 -5
  215. package/dist/utils/createHoverContentNode.d.ts.map +0 -1
  216. package/dist/utils/createHoverContentNode.js +0 -15
  217. package/dist/utils/createHoverContentNode.js.map +0 -1
@@ -0,0 +1,813 @@
1
+ import { areSelectionPointsEqual } from "../utils/areSelectionPointsEqual.js";
2
+ import { areSelectionsEqual } from "../utils/areSelectionsEqual.js";
3
+ import { createGutterUtilityElement } from "../utils/createGutterUtilityElement.js";
4
+ import { toHtml } from "hast-util-to-html";
5
+
6
+ //#region src/managers/InteractionManager.ts
7
+ var InteractionManager = class {
8
+ hoveredLine;
9
+ pre;
10
+ gutterUtilityContainer;
11
+ gutterUtilityButton;
12
+ gutterUtilitySlot;
13
+ interactiveLinesAttr = false;
14
+ interactiveLineNumbersAttr = false;
15
+ hasPointerListeners = false;
16
+ hasDocumentPointerListeners = false;
17
+ selectedRange = null;
18
+ renderedSelectionRange;
19
+ selectionAnchor;
20
+ queuedSelectionRender;
21
+ pointerSession = { mode: "idle" };
22
+ constructor(mode, options) {
23
+ this.mode = mode;
24
+ this.options = options;
25
+ }
26
+ setOptions(options) {
27
+ this.options = options;
28
+ }
29
+ cleanUp() {
30
+ this.pre?.removeEventListener("click", this.handlePointerClick);
31
+ this.pre?.removeEventListener("pointerdown", this.handlePointerDown);
32
+ this.pre?.removeEventListener("pointermove", this.handlePointerMove);
33
+ this.pre?.removeEventListener("pointerleave", this.handlePointerLeave);
34
+ this.pre?.removeAttribute("data-interactive-lines");
35
+ this.pre?.removeAttribute("data-interactive-line-numbers");
36
+ this.pre = void 0;
37
+ this.gutterUtilityContainer?.remove();
38
+ this.gutterUtilityContainer = void 0;
39
+ this.gutterUtilityButton = void 0;
40
+ this.gutterUtilitySlot = void 0;
41
+ this.clearHoveredLine();
42
+ this.detachDocumentPointerListeners();
43
+ this.clearPointerSession();
44
+ if (this.queuedSelectionRender != null) {
45
+ cancelAnimationFrame(this.queuedSelectionRender);
46
+ this.queuedSelectionRender = void 0;
47
+ }
48
+ this.interactiveLinesAttr = false;
49
+ this.interactiveLineNumbersAttr = false;
50
+ this.hasPointerListeners = false;
51
+ }
52
+ setup(pre) {
53
+ this.setSelectionDirty();
54
+ const { usesCustomGutterUtility = false, enableGutterUtility = false } = this.options;
55
+ if (this.pre !== pre) {
56
+ this.cleanUp();
57
+ this.pre = pre;
58
+ }
59
+ if (enableGutterUtility) this.ensureGutterUtilityNode(usesCustomGutterUtility);
60
+ else if (this.gutterUtilityContainer != null) {
61
+ this.gutterUtilityContainer.remove();
62
+ this.gutterUtilityContainer = void 0;
63
+ this.gutterUtilityButton = void 0;
64
+ this.gutterUtilitySlot = void 0;
65
+ if (this.pointerSession.mode === "gutterSelecting") {
66
+ this.clearPointerSession();
67
+ this.detachDocumentPointerListeners();
68
+ }
69
+ }
70
+ this.syncPointerListeners(pre);
71
+ this.updateInteractiveLineAttributes();
72
+ this.renderSelection();
73
+ }
74
+ setSelectionDirty() {
75
+ this.renderedSelectionRange = void 0;
76
+ }
77
+ isSelectionDirty() {
78
+ return this.renderedSelectionRange === null;
79
+ }
80
+ setSelection(range) {
81
+ const isRangeChange = !(range === this.selectedRange || areSelectionsEqual(range ?? void 0, this.selectedRange ?? void 0));
82
+ if (!this.isSelectionDirty() && !isRangeChange) return;
83
+ this.selectedRange = range;
84
+ this.renderSelection();
85
+ if (isRangeChange) this.notifySelectionCommitted();
86
+ }
87
+ getSelection() {
88
+ return this.selectedRange;
89
+ }
90
+ getHoveredLine = () => {
91
+ if (this.hoveredLine != null) {
92
+ if (this.mode === "diff" && this.hoveredLine.type === "diff-line") return {
93
+ lineNumber: this.hoveredLine.lineNumber,
94
+ side: this.hoveredLine.annotationSide
95
+ };
96
+ if (this.mode === "file" && this.hoveredLine.type === "line") return { lineNumber: this.hoveredLine.lineNumber };
97
+ }
98
+ };
99
+ handlePointerClick = (event) => {
100
+ const { onHunkExpand, onLineClick, onLineNumberClick, onMergeConflictActionClick } = this.options;
101
+ if (onHunkExpand == null && onLineClick == null && onLineNumberClick == null && onMergeConflictActionClick == null) return;
102
+ if (this.options.onGutterUtilityClick != null && isGutterUtilityPointerPath(event.composedPath())) return;
103
+ debugLogIfEnabled(this.options.__debugPointerEvents, "click", "FileDiff.DEBUG.handlePointerClick:", event);
104
+ this.handlePointerEvent({
105
+ eventType: "click",
106
+ event
107
+ });
108
+ };
109
+ handlePointerMove = (event) => {
110
+ const { lineHoverHighlight = "disabled", onLineEnter, onLineLeave, enableGutterUtility = false } = this.options;
111
+ if (lineHoverHighlight === "disabled" && !enableGutterUtility && onLineEnter == null && onLineLeave == null) return;
112
+ debugLogIfEnabled(this.options.__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerMove:", event);
113
+ this.handlePointerEvent({
114
+ eventType: "move",
115
+ event
116
+ });
117
+ };
118
+ handlePointerLeave = (event) => {
119
+ const { __debugPointerEvents } = this.options;
120
+ debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: no event");
121
+ if (this.hoveredLine == null) {
122
+ debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.handlePointerLeave: returned early, no .hoveredLine");
123
+ return;
124
+ }
125
+ this.gutterUtilityContainer?.remove();
126
+ this.options.onLineLeave?.({
127
+ ...this.hoveredLine,
128
+ event
129
+ });
130
+ this.clearHoveredLine();
131
+ };
132
+ handlePointerEvent({ eventType, event }) {
133
+ const { __debugPointerEvents } = this.options;
134
+ const composedPath = event.composedPath();
135
+ debugLogIfEnabled(__debugPointerEvents, eventType, "FileDiff.DEBUG.handlePointerEvent:", {
136
+ eventType,
137
+ composedPath
138
+ });
139
+ const target = this.resolvePointerTarget(composedPath);
140
+ debugLogIfEnabled(__debugPointerEvents, eventType, "FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:", target);
141
+ const { onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onHunkExpand, onMergeConflictActionClick } = this.options;
142
+ switch (eventType) {
143
+ case "move":
144
+ if (isLinePointerTarget(target) && this.hoveredLine?.lineElement === target.lineElement) break;
145
+ if (this.hoveredLine != null) {
146
+ this.gutterUtilityContainer?.remove();
147
+ onLineLeave?.({
148
+ ...this.hoveredLine,
149
+ event
150
+ });
151
+ this.clearHoveredLine();
152
+ }
153
+ if (isLinePointerTarget(target)) {
154
+ this.setHoveredLine(this.toEventBaseProps(target));
155
+ if (this.gutterUtilityContainer != null) target.numberElement.appendChild(this.gutterUtilityContainer);
156
+ onLineEnter?.({
157
+ ...this.hoveredLine,
158
+ event
159
+ });
160
+ }
161
+ break;
162
+ case "click": {
163
+ if (target == null) break;
164
+ if (isMergeConflictActionPointerTarget(target) && onMergeConflictActionClick != null) {
165
+ onMergeConflictActionClick(target);
166
+ break;
167
+ }
168
+ if (isExpandoPointerTarget(target) && onHunkExpand != null) {
169
+ onHunkExpand(target.hunkIndex, event.shiftKey ? "both" : target.direction, event.shiftKey ? Number.POSITIVE_INFINITY : void 0);
170
+ break;
171
+ }
172
+ if (!isLinePointerTarget(target)) break;
173
+ const eventBase = this.toEventBaseProps(target);
174
+ if (onLineNumberClick != null && target.numberColumn) onLineNumberClick({
175
+ ...eventBase,
176
+ event
177
+ });
178
+ else if (onLineClick != null) onLineClick({
179
+ ...eventBase,
180
+ event
181
+ });
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ syncPointerListeners(pre) {
187
+ const { __debugPointerEvents, lineHoverHighlight = "disabled", onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onHunkExpand, onMergeConflictActionClick, enableGutterUtility = false, enableLineSelection = false, onGutterUtilityClick } = this.options;
188
+ const enableGutterSelection = onGutterUtilityClick != null;
189
+ const shouldAttachPointerListeners = lineHoverHighlight !== "disabled" || onLineClick != null || onLineNumberClick != null || onHunkExpand != null || onMergeConflictActionClick != null || onLineEnter != null || onLineLeave != null || enableGutterUtility || enableLineSelection || enableGutterSelection;
190
+ if (shouldAttachPointerListeners && !this.hasPointerListeners) {
191
+ pre.addEventListener("click", this.handlePointerClick);
192
+ pre.addEventListener("pointerdown", this.handlePointerDown);
193
+ pre.addEventListener("pointermove", this.handlePointerMove);
194
+ pre.addEventListener("pointerleave", this.handlePointerLeave);
195
+ this.hasPointerListeners = true;
196
+ debugLogIfEnabled(__debugPointerEvents, "click", "FileDiff.DEBUG.attachEventListeners: Attaching click events for:", (() => {
197
+ const reasons = [];
198
+ if (__debugPointerEvents === "both" || __debugPointerEvents === "click") {
199
+ if (onLineClick != null) reasons.push("onLineClick");
200
+ if (onLineNumberClick != null) reasons.push("onLineNumberClick");
201
+ if (onHunkExpand != null) reasons.push("expandable hunk separators");
202
+ if (onMergeConflictActionClick != null) reasons.push("merge conflict actions");
203
+ }
204
+ return reasons;
205
+ })());
206
+ debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer move event");
207
+ debugLogIfEnabled(__debugPointerEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event");
208
+ } else if (!shouldAttachPointerListeners && this.hasPointerListeners) {
209
+ pre.removeEventListener("click", this.handlePointerClick);
210
+ pre.removeEventListener("pointerdown", this.handlePointerDown);
211
+ pre.removeEventListener("pointermove", this.handlePointerMove);
212
+ pre.removeEventListener("pointerleave", this.handlePointerLeave);
213
+ this.hasPointerListeners = false;
214
+ }
215
+ const hasActiveLineSelectionSession = this.pointerSession.mode === "selecting" || this.pointerSession.mode === "pendingSingleLineUnselect";
216
+ const hasActiveGutterSelectionSession = this.pointerSession.mode === "gutterSelecting";
217
+ if (!enableLineSelection && hasActiveLineSelectionSession || !enableGutterSelection && hasActiveGutterSelectionSession) {
218
+ this.clearPointerSession();
219
+ this.detachDocumentPointerListeners();
220
+ this.selectionAnchor = void 0;
221
+ this.clearPendingSingleLineState();
222
+ }
223
+ }
224
+ updateInteractiveLineAttributes() {
225
+ if (this.pre == null) return;
226
+ const { onLineClick, onLineNumberClick, enableLineSelection = false } = this.options;
227
+ const shouldHaveInteractiveLines = onLineClick != null;
228
+ const shouldHaveInteractiveLineNumbers = onLineNumberClick != null || enableLineSelection;
229
+ if (shouldHaveInteractiveLines && !this.interactiveLinesAttr) {
230
+ this.pre.setAttribute("data-interactive-lines", "");
231
+ this.interactiveLinesAttr = true;
232
+ } else if (!shouldHaveInteractiveLines && this.interactiveLinesAttr) {
233
+ this.pre.removeAttribute("data-interactive-lines");
234
+ this.interactiveLinesAttr = false;
235
+ }
236
+ if (shouldHaveInteractiveLineNumbers && !this.interactiveLineNumbersAttr) {
237
+ this.pre.setAttribute("data-interactive-line-numbers", "");
238
+ this.interactiveLineNumbersAttr = true;
239
+ } else if (!shouldHaveInteractiveLineNumbers && this.interactiveLineNumbersAttr) {
240
+ this.pre.removeAttribute("data-interactive-line-numbers");
241
+ this.interactiveLineNumbersAttr = false;
242
+ }
243
+ }
244
+ handlePointerDown = (event) => {
245
+ if (event.pointerType === "mouse" && event.button !== 0 || this.pre == null || this.pointerSession.mode !== "idle") return;
246
+ const path = event.composedPath();
247
+ if (isGutterUtilityPointerPath(path) && this.options.onGutterUtilityClick != null) this.startGutterSelectionFromPointerDown(event, path);
248
+ else this.startLineSelectionFromPointerDown(event, path);
249
+ };
250
+ startLineSelectionFromPointerDown(event, path) {
251
+ const { enableLineSelection = false } = this.options;
252
+ if (!enableLineSelection) return;
253
+ const pointerInfo = this.getSelectionPointerInfo(path, true);
254
+ if (pointerInfo == null) return;
255
+ const { pre } = this;
256
+ if (pre == null) return;
257
+ event.preventDefault();
258
+ const { lineNumber, eventSide, lineIndex } = pointerInfo;
259
+ if (event.shiftKey && this.selectedRange != null) {
260
+ const rowRange = this.getIndexesFromSelection(this.selectedRange, pre.getAttribute("data-diff-type") === "split");
261
+ if (rowRange == null) return;
262
+ const useStart = rowRange.start <= rowRange.end ? lineIndex >= rowRange.start : lineIndex <= rowRange.end;
263
+ this.selectionAnchor = {
264
+ lineNumber: useStart ? this.selectedRange.start : this.selectedRange.end,
265
+ side: useStart ? this.selectedRange.side : this.selectedRange.endSide ?? this.selectedRange.side
266
+ };
267
+ this.updateSelection(lineNumber, eventSide, false);
268
+ this.notifySelectionStart(this.selectedRange);
269
+ this.pointerSession = {
270
+ mode: "selecting",
271
+ pointerId: event.pointerId
272
+ };
273
+ this.attachDocumentPointerListeners();
274
+ return;
275
+ }
276
+ if (this.selectedRange?.start === lineNumber && this.selectedRange?.end === lineNumber) {
277
+ const point = {
278
+ lineNumber,
279
+ side: eventSide
280
+ };
281
+ this.selectionAnchor = point;
282
+ this.pointerSession = {
283
+ mode: "pendingSingleLineUnselect",
284
+ pointerId: event.pointerId,
285
+ anchor: point,
286
+ pending: point
287
+ };
288
+ this.attachDocumentPointerListeners();
289
+ return;
290
+ }
291
+ this.selectedRange = null;
292
+ this.selectionAnchor = {
293
+ lineNumber,
294
+ side: eventSide
295
+ };
296
+ this.updateSelection(lineNumber, eventSide, false);
297
+ this.notifySelectionStart(this.selectedRange);
298
+ this.pointerSession = {
299
+ mode: "selecting",
300
+ pointerId: event.pointerId
301
+ };
302
+ this.attachDocumentPointerListeners();
303
+ }
304
+ startGutterSelectionFromPointerDown(event, path) {
305
+ const { enableLineSelection = false, onGutterUtilityClick } = this.options;
306
+ if (onGutterUtilityClick == null) return;
307
+ const point = this.getSelectionPointFromPath(path);
308
+ if (point == null) return;
309
+ event.preventDefault();
310
+ event.stopPropagation();
311
+ this.pointerSession = {
312
+ mode: "gutterSelecting",
313
+ pointerId: event.pointerId,
314
+ anchor: point,
315
+ current: point
316
+ };
317
+ if (enableLineSelection) {
318
+ this.selectionAnchor = {
319
+ lineNumber: point.lineNumber,
320
+ side: point.side
321
+ };
322
+ this.updateSelection(point.lineNumber, point.side, false);
323
+ this.notifySelectionStart(this.selectedRange);
324
+ }
325
+ this.attachDocumentPointerListeners();
326
+ }
327
+ handleDocumentPointerMove = (event) => {
328
+ const { enableLineSelection = false } = this.options;
329
+ switch (this.pointerSession.mode) {
330
+ case "idle": return;
331
+ case "gutterSelecting": {
332
+ if (event.pointerId !== this.pointerSession.pointerId) return;
333
+ const point = this.getSelectionPointFromPath(event.composedPath());
334
+ if (point == null) return;
335
+ this.pointerSession.current = point;
336
+ if (enableLineSelection === true) this.updateSelection(point.lineNumber, point.side);
337
+ return;
338
+ }
339
+ case "selecting": {
340
+ if (event.pointerId !== this.pointerSession.pointerId) return;
341
+ const pointerInfo = this.getSelectionPointerInfo(event.composedPath(), false);
342
+ if (pointerInfo == null || this.selectionAnchor == null) return;
343
+ this.updateSelection(pointerInfo.lineNumber, pointerInfo.eventSide);
344
+ return;
345
+ }
346
+ case "pendingSingleLineUnselect": {
347
+ if (event.pointerId !== this.pointerSession.pointerId) return;
348
+ const pointerInfo = this.getSelectionPointerInfo(event.composedPath(), false);
349
+ if (pointerInfo == null || this.selectionAnchor == null) return;
350
+ const point = {
351
+ lineNumber: pointerInfo.lineNumber,
352
+ side: pointerInfo.eventSide
353
+ };
354
+ if (areSelectionPointsEqual(this.pointerSession.pending, point)) return;
355
+ this.updateSelection(pointerInfo.lineNumber, pointerInfo.eventSide, false);
356
+ this.notifySelectionStart(this.selectedRange);
357
+ this.notifySelectionChangeDelta();
358
+ this.pointerSession = {
359
+ mode: "selecting",
360
+ pointerId: event.pointerId
361
+ };
362
+ return;
363
+ }
364
+ }
365
+ };
366
+ handleDocumentPointerUp = (event) => {
367
+ const { enableLineSelection = false, onGutterUtilityClick } = this.options;
368
+ switch (this.pointerSession.mode) {
369
+ case "idle": return;
370
+ case "gutterSelecting": {
371
+ if (event.pointerId !== this.pointerSession.pointerId) return;
372
+ const point = this.getSelectionPointFromPath(event.composedPath());
373
+ if (point != null) {
374
+ this.pointerSession.current = point;
375
+ if (enableLineSelection) this.updateSelection(point.lineNumber, point.side);
376
+ }
377
+ onGutterUtilityClick?.(this.buildSelectedLineRange(this.pointerSession.anchor, this.pointerSession.current));
378
+ this.selectionAnchor = void 0;
379
+ if (enableLineSelection) {
380
+ this.notifySelectionEnd(this.selectedRange);
381
+ this.notifySelectionCommitted();
382
+ }
383
+ this.clearPointerSession();
384
+ this.detachDocumentPointerListeners();
385
+ return;
386
+ }
387
+ case "pendingSingleLineUnselect":
388
+ if (event.pointerId !== this.pointerSession.pointerId) return;
389
+ this.updateSelection(null, void 0, false);
390
+ this.selectionAnchor = void 0;
391
+ this.clearPendingSingleLineState();
392
+ this.detachDocumentPointerListeners();
393
+ this.notifySelectionEnd(this.selectedRange);
394
+ this.notifySelectionCommitted();
395
+ return;
396
+ case "selecting":
397
+ if (event.pointerId !== this.pointerSession.pointerId) return;
398
+ this.selectionAnchor = void 0;
399
+ this.detachDocumentPointerListeners();
400
+ this.clearPointerSession();
401
+ this.notifySelectionEnd(this.selectedRange);
402
+ this.notifySelectionCommitted();
403
+ }
404
+ };
405
+ handleDocumentPointerCancel = (event) => {
406
+ switch (this.pointerSession.mode) {
407
+ case "idle": return;
408
+ case "gutterSelecting":
409
+ case "selecting":
410
+ case "pendingSingleLineUnselect":
411
+ if ("pointerId" in this.pointerSession) {
412
+ if (event.pointerId !== this.pointerSession.pointerId) return;
413
+ }
414
+ this.selectionAnchor = void 0;
415
+ this.clearPendingSingleLineState();
416
+ this.clearPointerSession();
417
+ this.detachDocumentPointerListeners();
418
+ }
419
+ };
420
+ clearHoveredLine() {
421
+ if (this.hoveredLine == null) return;
422
+ this.hoveredLine.lineElement.removeAttribute("data-hovered");
423
+ this.hoveredLine.numberElement.removeAttribute("data-hovered");
424
+ this.hoveredLine = void 0;
425
+ }
426
+ setHoveredLine(hoveredLine) {
427
+ const { lineHoverHighlight = "disabled" } = this.options;
428
+ if (this.hoveredLine != null) this.clearHoveredLine();
429
+ this.hoveredLine = hoveredLine;
430
+ if (lineHoverHighlight !== "disabled") {
431
+ if (lineHoverHighlight === "both" || lineHoverHighlight === "line") this.hoveredLine.lineElement.setAttribute("data-hovered", "");
432
+ if (lineHoverHighlight === "both" || lineHoverHighlight === "number") this.hoveredLine.numberElement.setAttribute("data-hovered", "");
433
+ }
434
+ }
435
+ ensureGutterUtilityNode(useCustomGutterUtility) {
436
+ if (this.gutterUtilityContainer == null) {
437
+ this.gutterUtilityContainer = document.createElement("div");
438
+ this.gutterUtilityContainer.setAttribute("data-gutter-utility-slot", "");
439
+ }
440
+ if (useCustomGutterUtility) {
441
+ if (this.gutterUtilityButton != null) {
442
+ this.gutterUtilityButton.remove();
443
+ this.gutterUtilityButton = void 0;
444
+ }
445
+ if (this.gutterUtilitySlot == null) {
446
+ this.gutterUtilitySlot = document.createElement("slot");
447
+ this.gutterUtilitySlot.name = "gutter-utility-slot";
448
+ }
449
+ if (this.gutterUtilitySlot.parentNode !== this.gutterUtilityContainer) this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);
450
+ } else {
451
+ this.gutterUtilitySlot?.remove();
452
+ this.gutterUtilitySlot = void 0;
453
+ if (this.gutterUtilityButton == null) {
454
+ const tempDiv = document.createElement("div");
455
+ tempDiv.innerHTML = toHtml(createGutterUtilityElement());
456
+ const utilityButton = tempDiv.firstElementChild;
457
+ if (!(utilityButton instanceof HTMLButtonElement)) throw new Error("InteractionManager.ensureGutterUtilityNode: Node element should be a button");
458
+ utilityButton.remove();
459
+ this.gutterUtilityButton = utilityButton;
460
+ }
461
+ if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);
462
+ }
463
+ }
464
+ attachDocumentPointerListeners() {
465
+ if (this.hasDocumentPointerListeners) return;
466
+ document.addEventListener("pointermove", this.handleDocumentPointerMove);
467
+ document.addEventListener("pointerup", this.handleDocumentPointerUp);
468
+ document.addEventListener("pointercancel", this.handleDocumentPointerCancel);
469
+ this.hasDocumentPointerListeners = true;
470
+ }
471
+ detachDocumentPointerListeners() {
472
+ if (!this.hasDocumentPointerListeners) return;
473
+ document.removeEventListener("pointermove", this.handleDocumentPointerMove);
474
+ document.removeEventListener("pointerup", this.handleDocumentPointerUp);
475
+ document.removeEventListener("pointercancel", this.handleDocumentPointerCancel);
476
+ this.hasDocumentPointerListeners = false;
477
+ }
478
+ clearPointerSession() {
479
+ this.pointerSession = { mode: "idle" };
480
+ }
481
+ clearPendingSingleLineState() {
482
+ if (this.pointerSession.mode === "pendingSingleLineUnselect") this.pointerSession = { mode: "idle" };
483
+ }
484
+ getSelectionPointerInfo(path, requireNumberColumn) {
485
+ const target = this.resolvePointerTarget(path);
486
+ if (!isLinePointerTarget(target)) return;
487
+ if (requireNumberColumn && !target.numberColumn) return;
488
+ if (target.splitLineIndex == null) return;
489
+ return {
490
+ lineIndex: target.splitLineIndex,
491
+ lineNumber: target.lineNumber,
492
+ eventSide: this.mode === "diff" ? target.side : void 0
493
+ };
494
+ }
495
+ getSelectionPointFromPath(path) {
496
+ const target = this.resolvePointerTarget(path);
497
+ if (!isLinePointerTarget(target)) return;
498
+ return {
499
+ lineNumber: target.lineNumber,
500
+ side: this.mode === "diff" ? target.side : void 0
501
+ };
502
+ }
503
+ getLineIndex(lineNumber, side) {
504
+ const { getLineIndex } = this.options;
505
+ return getLineIndex != null ? getLineIndex(lineNumber, side) : [lineNumber - 1, lineNumber - 1];
506
+ }
507
+ updateSelection(currentLine, side, emitChange = true) {
508
+ const { selectedRange: previousRange } = this;
509
+ let nextRange;
510
+ if (currentLine == null) nextRange = null;
511
+ else {
512
+ const anchorSide = this.selectionAnchor?.side ?? side;
513
+ const anchorLine = this.selectionAnchor?.lineNumber ?? currentLine;
514
+ nextRange = this.buildSelectionRange(anchorLine, currentLine, anchorSide, side);
515
+ }
516
+ if (areSelectionsEqual(previousRange ?? void 0, nextRange ?? void 0)) return;
517
+ this.selectedRange = nextRange;
518
+ if (emitChange) this.notifySelectionChangeDelta();
519
+ this.queuedSelectionRender ??= requestAnimationFrame(this.renderSelection);
520
+ }
521
+ getIndexesFromSelection(selectedRange, split) {
522
+ if (this.pre == null) return;
523
+ const startIndexes = this.getLineIndex(selectedRange.start, selectedRange.side);
524
+ const finalIndexes = this.getLineIndex(selectedRange.end, selectedRange.endSide ?? selectedRange.side);
525
+ return startIndexes != null && finalIndexes != null ? {
526
+ start: split ? startIndexes[1] : startIndexes[0],
527
+ end: split ? finalIndexes[1] : finalIndexes[0]
528
+ } : void 0;
529
+ }
530
+ renderSelection = () => {
531
+ if (this.queuedSelectionRender != null) {
532
+ cancelAnimationFrame(this.queuedSelectionRender);
533
+ this.queuedSelectionRender = void 0;
534
+ }
535
+ if (this.pre == null || this.renderedSelectionRange === this.selectedRange) return;
536
+ const allSelected = this.pre.querySelectorAll("[data-selected-line]");
537
+ for (const element of allSelected) element.removeAttribute("data-selected-line");
538
+ this.renderedSelectionRange = this.selectedRange;
539
+ if (this.selectedRange == null) return;
540
+ const { children: codeElements } = this.pre;
541
+ if (codeElements.length === 0) return;
542
+ if (codeElements.length > 2) {
543
+ console.error(codeElements);
544
+ throw new Error("InteractionManager.renderSelection: Somehow there are more than 2 code elements...");
545
+ }
546
+ const split = this.pre.getAttribute("data-diff-type") === "split";
547
+ const rowRange = this.getIndexesFromSelection(this.selectedRange, split);
548
+ if (rowRange == null) {
549
+ console.error({
550
+ rowRange,
551
+ selectedRange: this.selectedRange
552
+ });
553
+ throw new Error("InteractionManager.renderSelection: No valid rowRange");
554
+ }
555
+ const isSingle = rowRange.start === rowRange.end;
556
+ const first = Math.min(rowRange.start, rowRange.end);
557
+ const last = Math.max(rowRange.start, rowRange.end);
558
+ for (const code of codeElements) {
559
+ const [gutter, content] = code.children;
560
+ const len = content.children.length;
561
+ if (len !== gutter.children.length) throw new Error("InteractionManager.renderSelection: gutter and content children dont match, something is wrong");
562
+ for (let i = 0; i < len; i++) {
563
+ const contentElement = content.children[i];
564
+ const gutterElement = gutter.children[i];
565
+ if (!(contentElement instanceof HTMLElement) || !(gutterElement instanceof HTMLElement)) continue;
566
+ const lineIndex = this.parseLineIndex(contentElement, split);
567
+ if ((lineIndex ?? 0) > last) break;
568
+ if (lineIndex == null || lineIndex < first) continue;
569
+ let attributeValue = isSingle ? "single" : lineIndex === first ? "first" : lineIndex === last ? "last" : "";
570
+ contentElement.setAttribute("data-selected-line", attributeValue);
571
+ gutterElement.setAttribute("data-selected-line", attributeValue);
572
+ if (gutterElement.nextSibling instanceof HTMLElement && contentElement.nextSibling instanceof HTMLElement && (contentElement.nextSibling.hasAttribute("data-line-annotation") || contentElement.nextSibling.hasAttribute("data-merge-conflict-actions"))) {
573
+ if (isSingle) {
574
+ attributeValue = "last";
575
+ contentElement.setAttribute("data-selected-line", "first");
576
+ } else if (lineIndex === first) attributeValue = "";
577
+ else if (lineIndex === last) contentElement.setAttribute("data-selected-line", "");
578
+ contentElement.nextSibling.setAttribute("data-selected-line", attributeValue);
579
+ gutterElement.nextSibling.setAttribute("data-selected-line", attributeValue);
580
+ }
581
+ }
582
+ }
583
+ };
584
+ notifySelectionCommitted() {
585
+ this.options.onLineSelected?.(this.selectedRange ?? null);
586
+ }
587
+ notifySelectionChangeDelta() {
588
+ this.options.onLineSelectionChange?.(this.selectedRange ?? null);
589
+ }
590
+ notifySelectionStart(range) {
591
+ this.options.onLineSelectionStart?.(range);
592
+ }
593
+ notifySelectionEnd(range) {
594
+ this.options.onLineSelectionEnd?.(range);
595
+ }
596
+ toEventBaseProps(target) {
597
+ if (this.mode === "file") return {
598
+ type: "line",
599
+ lineElement: target.lineElement,
600
+ lineNumber: target.lineNumber,
601
+ numberColumn: target.numberColumn,
602
+ numberElement: target.numberElement
603
+ };
604
+ return {
605
+ type: "diff-line",
606
+ annotationSide: target.side,
607
+ lineType: target.lineType,
608
+ lineElement: target.lineElement,
609
+ numberElement: target.numberElement,
610
+ lineNumber: target.lineNumber,
611
+ numberColumn: target.numberColumn
612
+ };
613
+ }
614
+ buildSelectedLineRange(anchor, current) {
615
+ return this.buildSelectionRange(anchor.lineNumber, current.lineNumber, anchor.side, current.side);
616
+ }
617
+ buildSelectionRange(start, end, side, endSide) {
618
+ return {
619
+ start,
620
+ end,
621
+ ...side != null ? { side } : {},
622
+ ...side !== endSide && endSide != null ? { endSide } : {}
623
+ };
624
+ }
625
+ resolvePointerTarget(path) {
626
+ let numberColumn = false;
627
+ let lineType;
628
+ let codeElement;
629
+ let lineElement;
630
+ let lineIndexValue;
631
+ let numberElement;
632
+ let expandInfo;
633
+ let lineNumber;
634
+ let mergeConflictActionTarget;
635
+ for (const element of path) {
636
+ if (!(element instanceof HTMLElement)) continue;
637
+ if (mergeConflictActionTarget == null && element.hasAttribute("data-merge-conflict-action")) {
638
+ const resolutionValue = element.getAttribute("data-merge-conflict-action") ?? void 0;
639
+ const conflictIndexValue = element.getAttribute("data-merge-conflict-conflict-index") ?? void 0;
640
+ const conflictIndex = conflictIndexValue != null ? Number.parseInt(conflictIndexValue, 10) : NaN;
641
+ if (isMergeConflictResolution(resolutionValue) && Number.isFinite(conflictIndex)) mergeConflictActionTarget = {
642
+ kind: "merge-conflict-action",
643
+ resolution: resolutionValue,
644
+ conflictIndex
645
+ };
646
+ }
647
+ const columnNumber = numberElement == null ? element.getAttribute("data-column-number") ?? void 0 : void 0;
648
+ if (columnNumber != null) {
649
+ numberElement = element;
650
+ lineNumber = Number.parseInt(columnNumber, 10);
651
+ numberColumn = true;
652
+ lineType = getLineTypeFromElement(element);
653
+ lineIndexValue = element.getAttribute("data-line-index") ?? void 0;
654
+ continue;
655
+ }
656
+ const lineAttr = lineElement == null ? element.getAttribute("data-line") ?? void 0 : void 0;
657
+ if (lineAttr != null) {
658
+ lineElement = element;
659
+ lineNumber = Number.parseInt(lineAttr, 10);
660
+ lineType = getLineTypeFromElement(element);
661
+ lineIndexValue = element.getAttribute("data-line-index") ?? void 0;
662
+ continue;
663
+ }
664
+ if (expandInfo == null && element.hasAttribute("data-expand-button")) {
665
+ expandInfo = {
666
+ hunkIndex: void 0,
667
+ direction: (() => {
668
+ if (element.hasAttribute("data-expand-up")) return "up";
669
+ if (element.hasAttribute("data-expand-down")) return "down";
670
+ return "both";
671
+ })()
672
+ };
673
+ continue;
674
+ }
675
+ const expandIndexValue = expandInfo != null ? element.getAttribute("data-expand-index") ?? void 0 : void 0;
676
+ if (expandInfo != null && expandIndexValue != null) {
677
+ const expandIndex = Number.parseInt(expandIndexValue, 10);
678
+ if (!Number.isNaN(expandIndex)) expandInfo.hunkIndex = expandIndex;
679
+ continue;
680
+ }
681
+ if (codeElement == null && element.hasAttribute("data-code")) {
682
+ codeElement = element;
683
+ break;
684
+ }
685
+ }
686
+ if (mergeConflictActionTarget != null) return mergeConflictActionTarget;
687
+ if (expandInfo?.hunkIndex != null) return {
688
+ type: "line-info",
689
+ hunkIndex: expandInfo.hunkIndex,
690
+ direction: expandInfo.direction
691
+ };
692
+ lineElement ??= lineIndexValue != null ? queryHTMLElement(codeElement, `[data-line][data-line-index="${lineIndexValue}"]`) : void 0;
693
+ numberElement ??= lineIndexValue != null ? queryHTMLElement(codeElement, `[data-column-number][data-line-index="${lineIndexValue}"]`) : void 0;
694
+ if (codeElement == null || lineElement == null || numberElement == null || lineType == null || lineNumber == null || Number.isNaN(lineNumber)) return;
695
+ const splitLineIndex = this.parseLineIndex(lineElement, this.isSplitDiff());
696
+ if (this.mode === "file") return {
697
+ kind: "line",
698
+ lineType,
699
+ lineElement,
700
+ lineNumber,
701
+ numberColumn,
702
+ numberElement,
703
+ side: void 0,
704
+ splitLineIndex
705
+ };
706
+ const annotationSide = (() => {
707
+ switch (lineType) {
708
+ case "change-deletion": return "deletions";
709
+ case "change-addition": return "additions";
710
+ default: return codeElement.hasAttribute("data-deletions") ? "deletions" : "additions";
711
+ }
712
+ })();
713
+ return {
714
+ kind: "line",
715
+ lineType,
716
+ lineElement,
717
+ lineNumber,
718
+ numberColumn,
719
+ numberElement,
720
+ side: annotationSide,
721
+ splitLineIndex
722
+ };
723
+ }
724
+ isSplitDiff() {
725
+ return this.pre?.getAttribute("data-diff-type") === "split";
726
+ }
727
+ parseLineIndex(element, split) {
728
+ const lineIndexes = (element.getAttribute("data-line-index") ?? "").split(",").map((value) => Number.parseInt(value, 10)).filter((value) => !Number.isNaN(value));
729
+ if (split && lineIndexes.length === 2) return lineIndexes[1];
730
+ if (!split) return lineIndexes[0];
731
+ }
732
+ };
733
+ function pluckInteractionOptions({ enableGutterUtility, enableHoverUtility, lineHoverHighlight, onGutterUtilityClick, onLineClick, onLineEnter, onLineLeave, onLineNumberClick, renderGutterUtility, renderHoverUtility, __debugPointerEvents, enableLineSelection, onLineSelected, onLineSelectionStart, onLineSelectionChange, onLineSelectionEnd }, onHunkExpand, getLineIndex, onMergeConflictActionClick) {
734
+ return {
735
+ enableGutterUtility: resolveEnableGutterUtilityOption({
736
+ enableGutterUtility,
737
+ enableHoverUtility,
738
+ renderGutterUtility,
739
+ renderHoverUtility,
740
+ onGutterUtilityClick
741
+ }),
742
+ usesCustomGutterUtility: renderGutterUtility != null || renderHoverUtility != null,
743
+ lineHoverHighlight,
744
+ onGutterUtilityClick,
745
+ onHunkExpand,
746
+ onMergeConflictActionClick,
747
+ onLineClick,
748
+ onLineEnter,
749
+ onLineLeave,
750
+ onLineNumberClick,
751
+ __debugPointerEvents,
752
+ enableLineSelection,
753
+ onLineSelected,
754
+ onLineSelectionStart,
755
+ onLineSelectionChange,
756
+ onLineSelectionEnd,
757
+ getLineIndex
758
+ };
759
+ }
760
+ function resolveEnableGutterUtilityOption({ enableGutterUtility, enableHoverUtility, renderGutterUtility, renderHoverUtility, onGutterUtilityClick }) {
761
+ if (enableGutterUtility !== void 0 && enableHoverUtility !== void 0) throw new Error("Cannot use both 'enableGutterUtility' and deprecated 'enableHoverUtility'. Use only 'enableGutterUtility'.");
762
+ if (renderGutterUtility != null && renderHoverUtility != null) throw new Error("Cannot use both 'renderGutterUtility' and deprecated 'renderHoverUtility'. Use only 'renderGutterUtility'.");
763
+ if (onGutterUtilityClick != null && (renderGutterUtility != null || renderHoverUtility != null)) throw new Error("Cannot use both 'onGutterUtilityClick' and render utility callbacks ('renderGutterUtility'/'renderHoverUtility'). Use only one gutter utility API.");
764
+ return enableGutterUtility ?? enableHoverUtility ?? false;
765
+ }
766
+ function isLinePointerTarget(target) {
767
+ return target != null && "kind" in target && target.kind === "line";
768
+ }
769
+ function isExpandoPointerTarget(target) {
770
+ return "type" in target && target.type === "line-info";
771
+ }
772
+ function isMergeConflictActionPointerTarget(target) {
773
+ return "kind" in target && target.kind === "merge-conflict-action";
774
+ }
775
+ function isMergeConflictResolution(value) {
776
+ return value === "current" || value === "incoming" || value === "both";
777
+ }
778
+ function queryHTMLElement(parent, query) {
779
+ const element = parent?.querySelector(query);
780
+ return element instanceof HTMLElement ? element : void 0;
781
+ }
782
+ function getLineTypeFromElement(element) {
783
+ const lineType = element.getAttribute("data-line-type");
784
+ if (lineType == null) return;
785
+ switch (lineType) {
786
+ case "change-deletion":
787
+ case "change-addition":
788
+ case "context":
789
+ case "context-expanded": return lineType;
790
+ default: return;
791
+ }
792
+ }
793
+ function isGutterUtilityPointerPath(path) {
794
+ for (const element of path) if (element instanceof HTMLElement && element.hasAttribute("data-utility-button")) return true;
795
+ return false;
796
+ }
797
+ function debugLogIfEnabled(debugLogType = "none", logIfType, ...args) {
798
+ switch (debugLogType) {
799
+ case "none": return;
800
+ case "both": break;
801
+ case "click":
802
+ if (logIfType !== "click") return;
803
+ break;
804
+ case "move":
805
+ if (logIfType !== "move") return;
806
+ break;
807
+ }
808
+ console.log(...args);
809
+ }
810
+
811
+ //#endregion
812
+ export { InteractionManager, pluckInteractionOptions };
813
+ //# sourceMappingURL=InteractionManager.js.map