@pierre/diffs 1.1.0-beta.17 → 1.1.0-beta.19

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 (65) hide show
  1. package/dist/components/File.d.ts +3 -5
  2. package/dist/components/File.d.ts.map +1 -1
  3. package/dist/components/File.js +12 -21
  4. package/dist/components/File.js.map +1 -1
  5. package/dist/components/FileDiff.d.ts +5 -6
  6. package/dist/components/FileDiff.d.ts.map +1 -1
  7. package/dist/components/FileDiff.js +21 -22
  8. package/dist/components/FileDiff.js.map +1 -1
  9. package/dist/components/VirtualizedFileDiff.d.ts +1 -0
  10. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  11. package/dist/components/VirtualizedFileDiff.js +6 -0
  12. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  13. package/dist/index.d.ts +3 -4
  14. package/dist/index.js +2 -3
  15. package/dist/managers/InteractionManager.d.ts +140 -0
  16. package/dist/managers/InteractionManager.d.ts.map +1 -0
  17. package/dist/managers/InteractionManager.js +789 -0
  18. package/dist/managers/InteractionManager.js.map +1 -0
  19. package/dist/managers/ResizeManager.d.ts +0 -2
  20. package/dist/managers/ResizeManager.d.ts.map +1 -1
  21. package/dist/managers/ResizeManager.js +43 -32
  22. package/dist/managers/ResizeManager.js.map +1 -1
  23. package/dist/react/index.d.ts +2 -2
  24. package/dist/react/jsx.d.ts.map +1 -1
  25. package/dist/react/types.d.ts +1 -2
  26. package/dist/react/types.d.ts.map +1 -1
  27. package/dist/react/utils/renderDiffChildren.d.ts +1 -1
  28. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  29. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  30. package/dist/react/utils/renderFileChildren.d.ts +1 -1
  31. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  32. package/dist/react/utils/renderFileChildren.js.map +1 -1
  33. package/dist/react/utils/useFileDiffInstance.d.ts +1 -2
  34. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  35. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  36. package/dist/react/utils/useFileInstance.d.ts +1 -2
  37. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  38. package/dist/react/utils/useFileInstance.js.map +1 -1
  39. package/dist/renderers/DiffHunksRenderer.d.ts +1 -0
  40. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  41. package/dist/renderers/DiffHunksRenderer.js +7 -0
  42. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  43. package/dist/ssr/index.d.ts +2 -2
  44. package/dist/style.js +1 -1
  45. package/dist/style.js.map +1 -1
  46. package/dist/types.d.ts +5 -1
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/utils/areSelectionPointsEqual.d.ts +7 -0
  49. package/dist/utils/areSelectionPointsEqual.d.ts.map +1 -0
  50. package/dist/utils/areSelectionPointsEqual.js +8 -0
  51. package/dist/utils/areSelectionPointsEqual.js.map +1 -0
  52. package/dist/utils/areSelectionsEqual.d.ts +1 -1
  53. package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
  54. package/dist/utils/areSelectionsEqual.js.map +1 -1
  55. package/dist/worker/worker-portable.js +9 -6
  56. package/dist/worker/worker-portable.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/managers/LineSelectionManager.d.ts +0 -64
  59. package/dist/managers/LineSelectionManager.d.ts.map +0 -1
  60. package/dist/managers/LineSelectionManager.js +0 -270
  61. package/dist/managers/LineSelectionManager.js.map +0 -1
  62. package/dist/managers/MouseEventManager.d.ts +0 -86
  63. package/dist/managers/MouseEventManager.d.ts.map +0 -1
  64. package/dist/managers/MouseEventManager.js +0 -424
  65. package/dist/managers/MouseEventManager.js.map +0 -1
@@ -1,424 +0,0 @@
1
- import { createGutterUtilityElement } from "../utils/createGutterUtilityElement.js";
2
- import { toHtml } from "hast-util-to-html";
3
-
4
- //#region src/managers/MouseEventManager.ts
5
- function isLineEventData(data, mode) {
6
- if (data == null) return false;
7
- if (mode === "file") return data.type === "line";
8
- else return data.type === "diff-line";
9
- }
10
- function isExpandoEventData(data) {
11
- return data?.type === "line-info";
12
- }
13
- var MouseEventManager = class {
14
- hoveredLine;
15
- pre;
16
- gutterUtilityContainer;
17
- gutterUtilityButton;
18
- gutterUtilitySlot;
19
- interactiveLinesAttr = false;
20
- interactiveLineNumbersAttr = false;
21
- hasEventListeners = false;
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.handleMouseClick);
31
- this.pre?.removeEventListener("pointermove", this.handleMouseMove);
32
- this.pre?.removeEventListener("pointerleave", this.handleMouseLeave);
33
- this.pre?.removeAttribute("data-interactive-lines");
34
- this.pre?.removeAttribute("data-interactive-line-numbers");
35
- this.gutterUtilityContainer?.remove();
36
- this.gutterUtilityContainer = void 0;
37
- this.gutterUtilityButton?.removeEventListener("pointerdown", this.handleGutterUtilityPointerDown);
38
- this.gutterUtilityButton = void 0;
39
- this.gutterUtilitySlot = void 0;
40
- this.clearHoveredLine();
41
- this.interactiveLinesAttr = false;
42
- this.interactiveLineNumbersAttr = false;
43
- this.hasEventListeners = false;
44
- this.pre = void 0;
45
- }
46
- setup(pre) {
47
- const { __debugMouseEvents, onLineClick, onLineNumberClick, onLineEnter, onLineLeave, usesCustomGutterUtility = false, onHunkExpand, enableGutterUtility = false, lineHoverHighlight = "disabled" } = this.options;
48
- const newContainer = this.pre !== pre;
49
- if (newContainer) {
50
- this.cleanUp();
51
- this.pre = pre;
52
- this.hasEventListeners = false;
53
- }
54
- if (enableGutterUtility) this.ensureGutterUtilityNode(usesCustomGutterUtility);
55
- else if (this.gutterUtilityContainer != null) {
56
- this.gutterUtilityContainer.remove();
57
- this.gutterUtilityContainer = void 0;
58
- this.gutterUtilityButton?.removeEventListener("pointerdown", this.handleGutterUtilityPointerDown);
59
- this.gutterUtilityButton = void 0;
60
- this.gutterUtilitySlot = void 0;
61
- }
62
- const requiresEventListeners = lineHoverHighlight !== "disabled" || onLineClick != null || onLineNumberClick != null || onHunkExpand != null || onLineEnter != null || onLineLeave != null || enableGutterUtility;
63
- if ((newContainer || !this.hasEventListeners) && requiresEventListeners) {
64
- this.hasEventListeners = true;
65
- pre.addEventListener("click", this.handleMouseClick);
66
- if (onLineClick != null) {
67
- pre.setAttribute("data-interactive-lines", "");
68
- this.interactiveLinesAttr = true;
69
- this.interactiveLineNumbersAttr = false;
70
- } else if (onLineNumberClick != null) {
71
- pre.setAttribute("data-interactive-line-numbers", "");
72
- this.interactiveLinesAttr = false;
73
- this.interactiveLineNumbersAttr = true;
74
- }
75
- debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.attachEventListeners: Attaching click events for:", (() => {
76
- const reasons = [];
77
- if (__debugMouseEvents === "both" || __debugMouseEvents === "click") {
78
- if (onLineClick != null) reasons.push("onLineClick");
79
- if (onLineNumberClick != null) reasons.push("onLineNumberClick");
80
- if (onHunkExpand != null) reasons.push("expandable hunk separators");
81
- }
82
- return reasons;
83
- })());
84
- pre.addEventListener("pointermove", this.handleMouseMove);
85
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer move event");
86
- pre.addEventListener("pointerleave", this.handleMouseLeave);
87
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event");
88
- } else if (!requiresEventListeners && this.hasEventListeners) {
89
- this.pre?.removeEventListener("click", this.handleMouseClick);
90
- this.pre?.removeEventListener("pointermove", this.handleMouseMove);
91
- this.pre?.removeEventListener("pointerleave", this.handleMouseLeave);
92
- this.hasEventListeners = false;
93
- }
94
- if (!newContainer) if (onLineClick != null) {
95
- if (this.interactiveLineNumbersAttr) {
96
- pre.removeAttribute("data-interactive-line-numbers");
97
- this.interactiveLineNumbersAttr = false;
98
- }
99
- if (!this.interactiveLinesAttr) {
100
- pre.setAttribute("data-interactive-lines", "");
101
- this.interactiveLinesAttr = true;
102
- }
103
- } else if (onLineNumberClick != null) {
104
- if (this.interactiveLinesAttr) {
105
- pre.removeAttribute("data-interactive-lines");
106
- this.interactiveLinesAttr = false;
107
- }
108
- if (!this.interactiveLineNumbersAttr) {
109
- pre.setAttribute("data-interactive-line-numbers", "");
110
- this.interactiveLineNumbersAttr = true;
111
- }
112
- } else {
113
- if (this.interactiveLinesAttr) {
114
- pre.removeAttribute("data-interactive-lines");
115
- this.interactiveLinesAttr = false;
116
- }
117
- if (this.interactiveLineNumbersAttr) {
118
- pre.removeAttribute("data-interactive-line-numbers");
119
- this.interactiveLineNumbersAttr = false;
120
- }
121
- }
122
- }
123
- getHoveredLine = () => {
124
- if (this.hoveredLine != null) {
125
- if (this.mode === "diff" && this.hoveredLine.type === "diff-line") return {
126
- lineNumber: this.hoveredLine.lineNumber,
127
- side: this.hoveredLine.annotationSide
128
- };
129
- if (this.mode === "file" && this.hoveredLine.type === "line") return { lineNumber: this.hoveredLine.lineNumber };
130
- }
131
- };
132
- handleMouseClick = (event) => {
133
- const { onGutterUtilityClick, onHunkExpand, onLineClick, onLineNumberClick } = this.options;
134
- if (onGutterUtilityClick == null && onHunkExpand == null && onLineClick == null && onLineNumberClick == null) return;
135
- debugLogIfEnabled(this.options.__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseClick:", event);
136
- this.handleMouseEvent({
137
- eventType: "click",
138
- event
139
- });
140
- };
141
- handleMouseMove = (event) => {
142
- const { lineHoverHighlight = "disabled", onLineEnter, onLineLeave, enableGutterUtility = false } = this.options;
143
- if (lineHoverHighlight === "disabled" && !enableGutterUtility && onLineEnter == null && onLineLeave == null) return;
144
- debugLogIfEnabled(this.options.__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseMove:", event);
145
- this.handleMouseEvent({
146
- eventType: "move",
147
- event
148
- });
149
- };
150
- handleMouseLeave = (event) => {
151
- const { __debugMouseEvents } = this.options;
152
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseLeave: no event");
153
- if (this.hoveredLine == null) {
154
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseLeave: returned early, no .hoveredLine");
155
- return;
156
- }
157
- this.gutterUtilityContainer?.remove();
158
- this.options.onLineLeave?.({
159
- ...this.hoveredLine,
160
- event
161
- });
162
- this.clearHoveredLine();
163
- };
164
- handleMouseEvent({ eventType, event }) {
165
- const { __debugMouseEvents } = this.options;
166
- const composedPath = event.composedPath();
167
- debugLogIfEnabled(__debugMouseEvents, eventType, "FileDiff.DEBUG.handleMouseEvent:", {
168
- eventType,
169
- composedPath
170
- });
171
- const data = this.getLineData(composedPath);
172
- debugLogIfEnabled(__debugMouseEvents, eventType, "FileDiff.DEBUG.handleMouseEvent: getLineData result:", data);
173
- const { onLineClick, onLineNumberClick, onLineEnter, onLineLeave, onGutterUtilityClick, onHunkExpand } = this.options;
174
- switch (eventType) {
175
- case "move":
176
- if (isLineEventData(data, this.mode) && this.hoveredLine?.lineElement === data.lineElement) {
177
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseEvent: switch, 'move', returned early because same line");
178
- break;
179
- }
180
- if (this.hoveredLine != null) {
181
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseEvent: switch, 'move', clearing an existing hovered line and firing onLineLeave");
182
- this.gutterUtilityContainer?.remove();
183
- onLineLeave?.({
184
- ...this.hoveredLine,
185
- event
186
- });
187
- this.clearHoveredLine();
188
- }
189
- if (isLineEventData(data, this.mode)) {
190
- debugLogIfEnabled(__debugMouseEvents, "move", "FileDiff.DEBUG.handleMouseEvent: switch, 'move', setting up a new hoveredLine and firing onLineEnter");
191
- this.setHoveredLine(data);
192
- if (this.gutterUtilityContainer != null) data.numberElement.appendChild(this.gutterUtilityContainer);
193
- onLineEnter?.({
194
- ...this.hoveredLine,
195
- event
196
- });
197
- }
198
- break;
199
- case "click":
200
- debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseEvent: switch, 'click', with data:", data);
201
- if (onGutterUtilityClick != null && this.gutterUtilityButton != null && composedPathIncludesElement(composedPath, this.gutterUtilityButton)) {
202
- event.stopPropagation();
203
- const hoveredLine = this.getHoveredLine();
204
- if (hoveredLine != null) onGutterUtilityClick(hoveredLine);
205
- break;
206
- }
207
- if (data == null) break;
208
- if (isExpandoEventData(data) && onHunkExpand != null) {
209
- debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseEvent: switch, 'click', expanding a hunk");
210
- onHunkExpand(data.hunkIndex, data.direction);
211
- break;
212
- }
213
- if (isLineEventData(data, this.mode)) if (onLineNumberClick != null && data.numberColumn) {
214
- debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineNumberClick'");
215
- onLineNumberClick({
216
- ...data,
217
- event
218
- });
219
- } else if (onLineClick != null) {
220
- debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineClick'");
221
- onLineClick({
222
- ...data,
223
- event
224
- });
225
- } else debugLogIfEnabled(__debugMouseEvents, "click", "FileDiff.DEBUG.handleMouseEvent: switch, 'click', fell through, no event to fire");
226
- break;
227
- }
228
- }
229
- clearHoveredLine() {
230
- if (this.hoveredLine == null) return;
231
- this.hoveredLine.lineElement.removeAttribute("data-hovered");
232
- this.hoveredLine.numberElement.removeAttribute("data-hovered");
233
- this.hoveredLine = void 0;
234
- }
235
- setHoveredLine(hoveredLine) {
236
- const { lineHoverHighlight = "disabled" } = this.options;
237
- if (this.hoveredLine != null) this.clearHoveredLine();
238
- this.hoveredLine = hoveredLine;
239
- if (lineHoverHighlight !== "disabled") {
240
- if (lineHoverHighlight === "both" || lineHoverHighlight === "line") this.hoveredLine.lineElement.setAttribute("data-hovered", "");
241
- if (lineHoverHighlight === "both" || lineHoverHighlight === "number") this.hoveredLine.numberElement.setAttribute("data-hovered", "");
242
- }
243
- }
244
- ensureGutterUtilityNode(useCustomGutterUtility) {
245
- if (this.gutterUtilityContainer == null) {
246
- this.gutterUtilityContainer = document.createElement("div");
247
- this.gutterUtilityContainer.setAttribute("data-gutter-utility-slot", "");
248
- }
249
- if (useCustomGutterUtility) {
250
- if (this.gutterUtilityButton != null) {
251
- this.gutterUtilityButton.removeEventListener("pointerdown", this.handleGutterUtilityPointerDown);
252
- this.gutterUtilityButton.remove();
253
- this.gutterUtilityButton = void 0;
254
- }
255
- if (this.gutterUtilitySlot == null) {
256
- this.gutterUtilitySlot = document.createElement("slot");
257
- this.gutterUtilitySlot.name = "gutter-utility-slot";
258
- }
259
- if (this.gutterUtilitySlot.parentNode !== this.gutterUtilityContainer) this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);
260
- } else {
261
- this.gutterUtilitySlot?.remove();
262
- this.gutterUtilitySlot = void 0;
263
- if (this.gutterUtilityButton == null) {
264
- const tempDiv = document.createElement("div");
265
- tempDiv.innerHTML = toHtml(createGutterUtilityElement());
266
- const utilityButton = tempDiv.firstElementChild;
267
- if (!(utilityButton instanceof HTMLButtonElement)) throw new Error("MouseEventManager.ensureGutterUtilityNode: Node element should be a button");
268
- utilityButton.remove();
269
- this.gutterUtilityButton = utilityButton;
270
- this.gutterUtilityButton.addEventListener("pointerdown", this.handleGutterUtilityPointerDown);
271
- }
272
- if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);
273
- }
274
- }
275
- handleGutterUtilityPointerDown = (event) => {
276
- if (this.options.onGutterUtilityClick != null) event.stopPropagation();
277
- };
278
- getLineData(path) {
279
- let numberColumn = false;
280
- let lineType;
281
- let codeElement;
282
- let lineElement;
283
- let lineIndex;
284
- let numberElement;
285
- let expandInfo;
286
- let lineNumber;
287
- for (const element of path) {
288
- if (!(element instanceof HTMLElement)) continue;
289
- const _columnNumber = numberElement == null ? element.getAttribute("data-column-number") ?? void 0 : void 0;
290
- if (_columnNumber) {
291
- numberElement = element;
292
- lineNumber = Number.parseInt(_columnNumber, 10);
293
- numberColumn = true;
294
- lineType = getLineTypeFromElement(element);
295
- lineIndex = element.getAttribute("data-line-index") ?? void 0;
296
- continue;
297
- }
298
- const _lineNumber = lineElement == null ? element.getAttribute("data-line") ?? void 0 : void 0;
299
- if (_lineNumber) {
300
- lineElement = element;
301
- lineNumber = Number.parseInt(_lineNumber, 10);
302
- lineType = getLineTypeFromElement(element);
303
- lineIndex = element.getAttribute("data-line-index") ?? void 0;
304
- continue;
305
- }
306
- if (expandInfo == null && element.hasAttribute("data-expand-button")) {
307
- expandInfo = {
308
- hunkIndex: void 0,
309
- direction: (() => {
310
- if (element.hasAttribute("data-expand-up")) return "up";
311
- if (element.hasAttribute("data-expand-down")) return "down";
312
- return "both";
313
- })()
314
- };
315
- continue;
316
- }
317
- const _expandIndex = expandInfo != null ? element.getAttribute("data-expand-index") ?? void 0 : void 0;
318
- if (expandInfo != null && _expandIndex != null) {
319
- const expandIndex = Number.parseInt(_expandIndex, 10);
320
- if (!Number.isNaN(expandIndex)) expandInfo.hunkIndex = expandIndex;
321
- continue;
322
- }
323
- if (codeElement == null && element.hasAttribute("data-code")) {
324
- codeElement = element;
325
- break;
326
- }
327
- }
328
- if (expandInfo?.hunkIndex != null) {
329
- const { hunkIndex, direction } = expandInfo;
330
- return {
331
- type: "line-info",
332
- hunkIndex,
333
- direction
334
- };
335
- }
336
- lineElement ??= lineIndex != null ? queryHTMLElement(codeElement, `[data-line][data-line-index="${lineIndex}"]`) : void 0;
337
- numberElement ??= lineIndex != null ? queryHTMLElement(codeElement, `[data-column-number][data-line-index="${lineIndex}"]`) : void 0;
338
- if (codeElement == null || lineElement == null || numberElement == null || lineType == null) return;
339
- if (this.mode === "file") return {
340
- type: "line",
341
- lineElement,
342
- lineNumber,
343
- numberElement,
344
- numberColumn
345
- };
346
- return {
347
- type: "diff-line",
348
- annotationSide: (() => {
349
- switch (lineType) {
350
- case "change-deletion": return "deletions";
351
- case "change-addition": return "additions";
352
- default: return codeElement.hasAttribute("data-deletions") ? "deletions" : "additions";
353
- }
354
- })(),
355
- lineType,
356
- lineElement,
357
- numberElement,
358
- lineNumber,
359
- numberColumn
360
- };
361
- }
362
- };
363
- function debugLogIfEnabled(debugLogType = "none", logIfType, ...args) {
364
- switch (debugLogType) {
365
- case "none": return;
366
- case "both": break;
367
- case "click":
368
- if (logIfType !== "click") return;
369
- break;
370
- case "move":
371
- if (logIfType !== "move") return;
372
- break;
373
- }
374
- console.log(...args);
375
- }
376
- function pluckMouseEventOptions({ enableGutterUtility, enableHoverUtility, lineHoverHighlight, onGutterUtilityClick, onLineClick, onLineEnter, onLineLeave, onLineNumberClick, renderGutterUtility, renderHoverUtility, __debugMouseEvents }, onHunkExpand) {
377
- return {
378
- enableGutterUtility: resolveEnableGutterUtilityOption({
379
- enableGutterUtility,
380
- enableHoverUtility,
381
- renderGutterUtility,
382
- renderHoverUtility,
383
- onGutterUtilityClick
384
- }),
385
- lineHoverHighlight,
386
- onGutterUtilityClick,
387
- usesCustomGutterUtility: renderGutterUtility != null || renderHoverUtility != null,
388
- onHunkExpand,
389
- onLineClick,
390
- onLineEnter,
391
- onLineLeave,
392
- onLineNumberClick,
393
- __debugMouseEvents
394
- };
395
- }
396
- function resolveEnableGutterUtilityOption({ enableGutterUtility, enableHoverUtility, renderGutterUtility, renderHoverUtility, onGutterUtilityClick }) {
397
- if (enableGutterUtility !== void 0 && enableHoverUtility !== void 0) throw new Error("Cannot use both 'enableGutterUtility' and deprecated 'enableHoverUtility'. Use only 'enableGutterUtility'.");
398
- if (renderGutterUtility != null && renderHoverUtility != null) throw new Error("Cannot use both 'renderGutterUtility' and deprecated 'renderHoverUtility'. Use only 'renderGutterUtility'.");
399
- 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.");
400
- return enableGutterUtility ?? enableHoverUtility ?? false;
401
- }
402
- function queryHTMLElement(parent, query) {
403
- const element = parent?.querySelector(query);
404
- return element instanceof HTMLElement ? element : void 0;
405
- }
406
- function composedPathIncludesElement(path, element) {
407
- for (const pathElement of path) if (pathElement === element) return true;
408
- return false;
409
- }
410
- function getLineTypeFromElement(element) {
411
- const lineType = element.getAttribute("data-line-type");
412
- if (lineType == null) return;
413
- switch (lineType) {
414
- case "change-deletion":
415
- case "change-addition":
416
- case "context":
417
- case "context-expanded": return lineType;
418
- default: return;
419
- }
420
- }
421
-
422
- //#endregion
423
- export { MouseEventManager, pluckMouseEventOptions };
424
- //# sourceMappingURL=MouseEventManager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MouseEventManager.js","names":["mode: TMode","options: MouseEventManagerOptions<TMode>","reasons: string[]","lineType: LineTypes | undefined","codeElement: HTMLElement | undefined","lineElement: HTMLElement | undefined","lineIndex: string | undefined","numberElement: HTMLElement | undefined","expandInfo:\n | {\n hunkIndex: number | undefined;\n direction: 'up' | 'down' | 'both';\n }\n | undefined","lineNumber: number | undefined"],"sources":["../../src/managers/MouseEventManager.ts"],"sourcesContent":["import { toHtml } from 'hast-util-to-html';\n\nimport type {\n AnnotationSide,\n DiffLineEventBaseProps,\n ExpansionDirections,\n LineEventBaseProps,\n LineTypes,\n} from '../types';\nimport { createGutterUtilityElement } from '../utils/createGutterUtilityElement';\n\nexport type LogTypes = 'click' | 'move' | 'both' | 'none';\n\nexport type MouseEventManagerMode = 'file' | 'diff';\n\nexport interface OnLineClickProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnLineEnterLeaveProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineClickProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\ntype HandleMouseEventProps =\n | { eventType: 'click'; event: PointerEvent | MouseEvent }\n | { eventType: 'move'; event: PointerEvent };\n\ntype EventClickProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? OnLineClickProps\n : OnDiffLineClickProps;\n\ntype MouseEventEnterLeaveProps<TMode extends MouseEventManagerMode> =\n TMode extends 'file' ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;\n\ntype EventBaseProps<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\ninterface ExpandoEventProps {\n type: 'line-info';\n hunkIndex: number;\n direction: ExpansionDirections;\n}\n\nexport type GetHoveredLineResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? { lineNumber: number }\n : { lineNumber: number; side: AnnotationSide };\n\ntype GetLineDataResult<TMode extends MouseEventManagerMode> =\n TMode extends 'file'\n ? LineEventBaseProps | ExpandoEventProps | undefined\n : DiffLineEventBaseProps | ExpandoEventProps | undefined;\n\ntype LineEventData<TMode extends MouseEventManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\nfunction isLineEventData<TMode extends MouseEventManagerMode>(\n data: GetLineDataResult<TMode>,\n mode: TMode\n): data is LineEventData<TMode> {\n if (data == null) return false;\n if (mode === 'file') {\n return data.type === 'line';\n } else {\n return data.type === 'diff-line';\n }\n}\n\nfunction isExpandoEventData(\n data:\n | LineEventBaseProps\n | DiffLineEventBaseProps\n | ExpandoEventProps\n | undefined\n): data is ExpandoEventProps {\n return data?.type === 'line-info';\n}\n\nexport interface MouseEventManagerBaseOptions<\n TMode extends MouseEventManagerMode,\n> {\n lineHoverHighlight?: 'disabled' | 'both' | 'number' | 'line';\n enableGutterUtility?: boolean;\n onGutterUtilityClick?(props: GetHoveredLineResult<TMode>): unknown;\n onLineClick?(props: EventClickProps<TMode>): unknown;\n onLineNumberClick?(props: EventClickProps<TMode>): unknown;\n onLineEnter?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n onLineLeave?(props: MouseEventEnterLeaveProps<TMode>): unknown;\n __debugMouseEvents?: LogTypes;\n}\n\nexport interface MouseEventManagerOptions<\n TMode extends MouseEventManagerMode,\n> extends MouseEventManagerBaseOptions<TMode> {\n usesCustomGutterUtility?: boolean;\n onHunkExpand?(hunkIndex: number, direction: ExpansionDirections): unknown;\n}\n\nexport class MouseEventManager<TMode extends MouseEventManagerMode> {\n private hoveredLine: EventBaseProps<TMode> | undefined;\n private pre: HTMLPreElement | undefined;\n private gutterUtilityContainer: HTMLDivElement | undefined;\n private gutterUtilityButton: HTMLButtonElement | undefined;\n private gutterUtilitySlot: HTMLSlotElement | undefined;\n private interactiveLinesAttr = false;\n private interactiveLineNumbersAttr = false;\n private hasEventListeners = false;\n\n constructor(\n private mode: TMode,\n private options: MouseEventManagerOptions<TMode>\n ) {}\n\n setOptions(options: MouseEventManagerOptions<TMode>): void {\n this.options = options;\n }\n\n cleanUp(): void {\n this.pre?.removeEventListener('click', this.handleMouseClick);\n this.pre?.removeEventListener('pointermove', this.handleMouseMove);\n this.pre?.removeEventListener('pointerleave', this.handleMouseLeave);\n this.pre?.removeAttribute('data-interactive-lines');\n this.pre?.removeAttribute('data-interactive-line-numbers');\n this.gutterUtilityContainer?.remove();\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton?.removeEventListener(\n 'pointerdown',\n this.handleGutterUtilityPointerDown\n );\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n this.clearHoveredLine();\n this.interactiveLinesAttr = false;\n this.interactiveLineNumbersAttr = false;\n this.hasEventListeners = false;\n this.pre = undefined;\n }\n\n setup(pre: HTMLPreElement): void {\n const {\n __debugMouseEvents,\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n usesCustomGutterUtility = false,\n onHunkExpand,\n enableGutterUtility = false,\n lineHoverHighlight = 'disabled',\n } = this.options;\n\n const newContainer = this.pre !== pre;\n if (newContainer) {\n this.cleanUp();\n this.pre = pre;\n this.hasEventListeners = false;\n }\n\n if (enableGutterUtility) {\n this.ensureGutterUtilityNode(usesCustomGutterUtility);\n } else if (this.gutterUtilityContainer != null) {\n this.gutterUtilityContainer.remove();\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton?.removeEventListener(\n 'pointerdown',\n this.handleGutterUtilityPointerDown\n );\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n }\n\n const requiresEventListeners =\n lineHoverHighlight !== 'disabled' ||\n onLineClick != null ||\n onLineNumberClick != null ||\n onHunkExpand != null ||\n onLineEnter != null ||\n onLineLeave != null ||\n enableGutterUtility;\n\n if ((newContainer || !this.hasEventListeners) && requiresEventListeners) {\n this.hasEventListeners = true;\n pre.addEventListener('click', this.handleMouseClick);\n if (onLineClick != null) {\n pre.setAttribute('data-interactive-lines', '');\n this.interactiveLinesAttr = true;\n this.interactiveLineNumbersAttr = false;\n } else if (onLineNumberClick != null) {\n pre.setAttribute('data-interactive-line-numbers', '');\n this.interactiveLinesAttr = false;\n this.interactiveLineNumbersAttr = true;\n }\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.attachEventListeners: Attaching click events for:',\n (() => {\n const reasons: string[] = [];\n if (__debugMouseEvents === 'both' || __debugMouseEvents === 'click') {\n if (onLineClick != null) {\n reasons.push('onLineClick');\n }\n if (onLineNumberClick != null) {\n reasons.push('onLineNumberClick');\n }\n if (onHunkExpand != null) {\n reasons.push('expandable hunk separators');\n }\n }\n return reasons;\n })()\n );\n pre.addEventListener('pointermove', this.handleMouseMove);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer move event'\n );\n pre.addEventListener('pointerleave', this.handleMouseLeave);\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event'\n );\n } else if (!requiresEventListeners && this.hasEventListeners) {\n this.pre?.removeEventListener('click', this.handleMouseClick);\n this.pre?.removeEventListener('pointermove', this.handleMouseMove);\n this.pre?.removeEventListener('pointerleave', this.handleMouseLeave);\n this.hasEventListeners = false;\n }\n\n if (!newContainer) {\n if (onLineClick != null) {\n if (this.interactiveLineNumbersAttr) {\n pre.removeAttribute('data-interactive-line-numbers');\n this.interactiveLineNumbersAttr = false;\n }\n if (!this.interactiveLinesAttr) {\n pre.setAttribute('data-interactive-lines', '');\n this.interactiveLinesAttr = true;\n }\n } else if (onLineNumberClick != null) {\n if (this.interactiveLinesAttr) {\n pre.removeAttribute('data-interactive-lines');\n this.interactiveLinesAttr = false;\n }\n if (!this.interactiveLineNumbersAttr) {\n pre.setAttribute('data-interactive-line-numbers', '');\n this.interactiveLineNumbersAttr = true;\n }\n } else {\n if (this.interactiveLinesAttr) {\n pre.removeAttribute('data-interactive-lines');\n this.interactiveLinesAttr = false;\n }\n if (this.interactiveLineNumbersAttr) {\n pre.removeAttribute('data-interactive-line-numbers');\n this.interactiveLineNumbersAttr = false;\n }\n }\n }\n }\n\n getHoveredLine = (): GetHoveredLineResult<TMode> | undefined => {\n if (this.hoveredLine != null) {\n if (this.mode === 'diff' && this.hoveredLine.type === 'diff-line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n side: this.hoveredLine.annotationSide,\n } as GetHoveredLineResult<TMode>;\n }\n if (this.mode === 'file' && this.hoveredLine.type === 'line') {\n return {\n lineNumber: this.hoveredLine.lineNumber,\n } as GetHoveredLineResult<TMode>;\n }\n }\n return undefined;\n };\n\n handleMouseClick = (event: MouseEvent): void => {\n const {\n onGutterUtilityClick,\n onHunkExpand,\n onLineClick,\n onLineNumberClick,\n } = this.options;\n if (\n onGutterUtilityClick == null &&\n onHunkExpand == null &&\n onLineClick == null &&\n onLineNumberClick == null\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'click',\n 'FileDiff.DEBUG.handleMouseClick:',\n event\n );\n this.handleMouseEvent({ eventType: 'click', event });\n };\n\n handleMouseMove = (event: PointerEvent): void => {\n const {\n lineHoverHighlight = 'disabled',\n onLineEnter,\n onLineLeave,\n enableGutterUtility = false,\n } = this.options;\n if (\n lineHoverHighlight === 'disabled' &&\n !enableGutterUtility &&\n onLineEnter == null &&\n onLineLeave == null\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseMove:',\n event\n );\n this.handleMouseEvent({ eventType: 'move', event });\n };\n\n handleMouseLeave = (event: PointerEvent): void => {\n const { __debugMouseEvents } = this.options;\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: no event'\n );\n if (this.hoveredLine == null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n 'FileDiff.DEBUG.handleMouseLeave: returned early, no .hoveredLine'\n );\n return;\n }\n this.gutterUtilityContainer?.remove();\n this.options.onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n };\n\n private handleMouseEvent({ eventType, event }: HandleMouseEventProps) {\n const { __debugMouseEvents } = this.options;\n const composedPath = event.composedPath();\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent:',\n { eventType, composedPath }\n );\n const data = this.getLineData(composedPath);\n debugLogIfEnabled(\n __debugMouseEvents,\n eventType,\n 'FileDiff.DEBUG.handleMouseEvent: getLineData result:',\n data\n );\n const {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onGutterUtilityClick,\n onHunkExpand,\n } = this.options;\n switch (eventType) {\n case 'move': {\n if (\n isLineEventData(data, this.mode) &&\n this.hoveredLine?.lineElement === data.lineElement\n ) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', returned early because same line\"\n );\n break;\n }\n if (this.hoveredLine != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', clearing an existing hovered line and firing onLineLeave\"\n );\n this.gutterUtilityContainer?.remove();\n onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n }\n if (isLineEventData(data, this.mode)) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'move',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'move', setting up a new hoveredLine and firing onLineEnter\"\n );\n this.setHoveredLine(data);\n if (this.gutterUtilityContainer != null) {\n data.numberElement.appendChild(this.gutterUtilityContainer);\n }\n onLineEnter?.({\n ...this.hoveredLine,\n event,\n } as MouseEventEnterLeaveProps<TMode>);\n }\n break;\n }\n case 'click':\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', with data:\",\n data\n );\n if (\n onGutterUtilityClick != null &&\n this.gutterUtilityButton != null &&\n composedPathIncludesElement(composedPath, this.gutterUtilityButton)\n ) {\n event.stopPropagation();\n const hoveredLine = this.getHoveredLine();\n if (hoveredLine != null) {\n onGutterUtilityClick(hoveredLine);\n }\n break;\n }\n if (data == null) break;\n if (isExpandoEventData(data) && onHunkExpand != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', expanding a hunk\"\n );\n onHunkExpand(data.hunkIndex, data.direction);\n break;\n }\n if (isLineEventData(data, this.mode)) {\n if (onLineNumberClick != null && data.numberColumn) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineNumberClick'\"\n );\n onLineNumberClick({ ...data, event } as EventClickProps<TMode>);\n } else if (onLineClick != null) {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', firing 'onLineClick'\"\n );\n onLineClick({ ...data, event } as EventClickProps<TMode>);\n } else {\n debugLogIfEnabled(\n __debugMouseEvents,\n 'click',\n \"FileDiff.DEBUG.handleMouseEvent: switch, 'click', fell through, no event to fire\"\n );\n }\n }\n break;\n }\n }\n\n private clearHoveredLine() {\n if (this.hoveredLine == null) {\n return;\n }\n this.hoveredLine.lineElement.removeAttribute('data-hovered');\n this.hoveredLine.numberElement.removeAttribute('data-hovered');\n this.hoveredLine = undefined;\n }\n\n private setHoveredLine(hoveredLine: EventBaseProps<TMode>) {\n const { lineHoverHighlight = 'disabled' } = this.options;\n if (this.hoveredLine != null) {\n this.clearHoveredLine();\n }\n this.hoveredLine = hoveredLine;\n if (lineHoverHighlight !== 'disabled') {\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'line') {\n this.hoveredLine.lineElement.setAttribute('data-hovered', '');\n }\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'number') {\n this.hoveredLine.numberElement.setAttribute('data-hovered', '');\n }\n }\n }\n\n private ensureGutterUtilityNode(useCustomGutterUtility: boolean): void {\n if (this.gutterUtilityContainer == null) {\n this.gutterUtilityContainer = document.createElement('div');\n this.gutterUtilityContainer.setAttribute('data-gutter-utility-slot', '');\n }\n if (useCustomGutterUtility) {\n if (this.gutterUtilityButton != null) {\n this.gutterUtilityButton.removeEventListener(\n 'pointerdown',\n this.handleGutterUtilityPointerDown\n );\n this.gutterUtilityButton.remove();\n this.gutterUtilityButton = undefined;\n }\n if (this.gutterUtilitySlot == null) {\n this.gutterUtilitySlot = document.createElement('slot');\n this.gutterUtilitySlot.name = 'gutter-utility-slot';\n }\n if (this.gutterUtilitySlot.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);\n }\n } else {\n this.gutterUtilitySlot?.remove();\n this.gutterUtilitySlot = undefined;\n if (this.gutterUtilityButton == null) {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = toHtml(createGutterUtilityElement());\n const utilityButton = tempDiv.firstElementChild;\n if (!(utilityButton instanceof HTMLButtonElement)) {\n throw new Error(\n 'MouseEventManager.ensureGutterUtilityNode: Node element should be a button'\n );\n }\n utilityButton.remove();\n this.gutterUtilityButton = utilityButton;\n this.gutterUtilityButton.addEventListener(\n 'pointerdown',\n this.handleGutterUtilityPointerDown\n );\n }\n if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);\n }\n }\n }\n\n private handleGutterUtilityPointerDown = (event: PointerEvent): void => {\n if (this.options.onGutterUtilityClick != null) {\n event.stopPropagation();\n }\n };\n\n private getLineData(\n path: (EventTarget | undefined)[]\n ): GetLineDataResult<TMode> {\n let numberColumn = false;\n let lineType: LineTypes | undefined;\n let codeElement: HTMLElement | undefined;\n let lineElement: HTMLElement | undefined;\n let lineIndex: string | undefined;\n let numberElement: HTMLElement | undefined;\n let expandInfo:\n | {\n hunkIndex: number | undefined;\n direction: 'up' | 'down' | 'both';\n }\n | undefined;\n let lineNumber: number | undefined;\n\n for (const element of path) {\n if (!(element instanceof HTMLElement)) continue;\n // If we've click on a number column line, lets grab the relevant\n // line info\n const _columnNumber =\n numberElement == null\n ? (element.getAttribute('data-column-number') ?? undefined)\n : undefined;\n if (_columnNumber) {\n numberElement = element;\n lineNumber = Number.parseInt(_columnNumber, 10);\n numberColumn = true;\n lineType = getLineTypeFromElement(element);\n lineIndex = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n // If we've clicked on a code column line, lets grab the relevant\n // line info\n const _lineNumber =\n lineElement == null\n ? (element.getAttribute('data-line') ?? undefined)\n : undefined;\n if (_lineNumber) {\n lineElement = element;\n lineNumber = Number.parseInt(_lineNumber, 10);\n lineType = getLineTypeFromElement(element);\n lineIndex = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n // If we've clicked on an expand button, lets grab the relevant info\n if (expandInfo == null && element.hasAttribute('data-expand-button')) {\n expandInfo = {\n hunkIndex: undefined,\n direction: (() => {\n if (element.hasAttribute('data-expand-up')) {\n return 'up';\n }\n if (element.hasAttribute('data-expand-down')) {\n return 'down';\n }\n return 'both';\n })(),\n };\n continue;\n }\n // If we've clicked on an expand container, lets grab the index off of it\n // FIXME(amadeus): Might be worth stuffing the expand index into the\n // buttons themselves? Requires a small HTML change tho...\n const _expandIndex =\n expandInfo != null\n ? (element.getAttribute('data-expand-index') ?? undefined)\n : undefined;\n if (expandInfo != null && _expandIndex != null) {\n const expandIndex = Number.parseInt(_expandIndex, 10);\n if (!Number.isNaN(expandIndex)) {\n expandInfo.hunkIndex = expandIndex;\n }\n continue;\n }\n // And finally, if we managed to get to the code element, then we either\n // have the necessary info, or we don't, so we can stop iterating through\n // the path\n if (codeElement == null && element.hasAttribute('data-code')) {\n codeElement = element;\n // Once we've found the code parent, there's no more travesial necessary\n break;\n }\n }\n\n // If we are handling expansion, lets do that\n if (expandInfo?.hunkIndex != null) {\n const { hunkIndex, direction } = expandInfo;\n return { type: 'line-info', hunkIndex, direction };\n }\n\n lineElement ??=\n lineIndex != null\n ? queryHTMLElement(\n codeElement,\n `[data-line][data-line-index=\"${lineIndex}\"]`\n )\n : undefined;\n numberElement ??=\n lineIndex != null\n ? queryHTMLElement(\n codeElement,\n `[data-column-number][data-line-index=\"${lineIndex}\"]`\n )\n : undefined;\n\n // If we were unable to find the necessary elements, we out.\n if (\n codeElement == null ||\n lineElement == null ||\n numberElement == null ||\n lineType == null\n ) {\n return undefined;\n }\n\n if (this.mode === 'file') {\n return {\n type: 'line',\n lineElement,\n lineNumber,\n numberElement,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n\n return {\n type: 'diff-line',\n annotationSide: (() => {\n switch (lineType) {\n case 'change-deletion':\n return 'deletions';\n case 'change-addition':\n return 'additions';\n default:\n return codeElement.hasAttribute('data-deletions')\n ? 'deletions'\n : 'additions';\n }\n })(),\n lineType,\n lineElement,\n numberElement,\n lineNumber,\n numberColumn,\n } as GetLineDataResult<TMode>;\n }\n}\n\nfunction debugLogIfEnabled(\n debugLogType: LogTypes | undefined = 'none',\n logIfType: 'move' | 'click',\n ...args: unknown[]\n) {\n switch (debugLogType) {\n case 'none':\n return;\n case 'both':\n break;\n case 'click':\n if (logIfType !== 'click') {\n return;\n }\n break;\n case 'move':\n if (logIfType !== 'move') {\n return;\n }\n break;\n }\n console.log(...args);\n}\n\ntype MouseEventPluckOptions<TMode extends MouseEventManagerMode> =\n MouseEventManagerBaseOptions<TMode> & {\n enableHoverUtility?: boolean;\n renderGutterUtility?(\n getHoveredRow: () => GetHoveredLineResult<TMode> | undefined\n ): HTMLElement | null;\n renderHoverUtility?(\n getHoveredRow: () => GetHoveredLineResult<TMode> | undefined\n ): HTMLElement | null;\n };\n\nexport function pluckMouseEventOptions<TMode extends MouseEventManagerMode>(\n {\n enableGutterUtility,\n enableHoverUtility,\n lineHoverHighlight,\n onGutterUtilityClick,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n renderGutterUtility,\n renderHoverUtility,\n __debugMouseEvents,\n }: MouseEventPluckOptions<TMode>,\n onHunkExpand?: (hunkIndex: number, direction: ExpansionDirections) => unknown\n): MouseEventManagerOptions<TMode> {\n return {\n enableGutterUtility: resolveEnableGutterUtilityOption({\n enableGutterUtility,\n enableHoverUtility,\n renderGutterUtility,\n renderHoverUtility,\n onGutterUtilityClick,\n }),\n lineHoverHighlight,\n onGutterUtilityClick,\n usesCustomGutterUtility:\n renderGutterUtility != null || renderHoverUtility != null,\n onHunkExpand,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n __debugMouseEvents,\n };\n}\n\nfunction resolveEnableGutterUtilityOption<TMode extends MouseEventManagerMode>({\n enableGutterUtility,\n enableHoverUtility,\n renderGutterUtility,\n renderHoverUtility,\n onGutterUtilityClick,\n}: Pick<\n MouseEventPluckOptions<TMode>,\n | 'enableGutterUtility'\n | 'enableHoverUtility'\n | 'renderGutterUtility'\n | 'renderHoverUtility'\n | 'onGutterUtilityClick'\n>): boolean {\n if (enableGutterUtility !== undefined && enableHoverUtility !== undefined) {\n throw new Error(\n \"Cannot use both 'enableGutterUtility' and deprecated 'enableHoverUtility'. Use only 'enableGutterUtility'.\"\n );\n }\n if (renderGutterUtility != null && renderHoverUtility != null) {\n throw new Error(\n \"Cannot use both 'renderGutterUtility' and deprecated 'renderHoverUtility'. Use only 'renderGutterUtility'.\"\n );\n }\n if (\n onGutterUtilityClick != null &&\n (renderGutterUtility != null || renderHoverUtility != null)\n ) {\n throw new Error(\n \"Cannot use both 'onGutterUtilityClick' and render utility callbacks ('renderGutterUtility'/'renderHoverUtility'). Use only one gutter utility API.\"\n );\n }\n return enableGutterUtility ?? enableHoverUtility ?? false;\n}\n\nfunction queryHTMLElement(\n parent: HTMLElement | undefined,\n query: string\n): HTMLElement | undefined {\n const element = parent?.querySelector(query);\n return element instanceof HTMLElement ? element : undefined;\n}\n\nfunction composedPathIncludesElement(\n path: (EventTarget | undefined)[],\n element: Element\n): boolean {\n for (const pathElement of path) {\n if (pathElement === element) {\n return true;\n }\n }\n return false;\n}\n\nfunction getLineTypeFromElement(element: HTMLElement): LineTypes | undefined {\n const lineType = element.getAttribute('data-line-type');\n if (lineType == null) {\n return undefined;\n }\n switch (lineType) {\n case 'change-deletion':\n case 'change-addition':\n case 'context':\n case 'context-expanded':\n return lineType;\n default:\n return undefined;\n }\n}\n"],"mappings":"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"}