@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.
- package/README.md +7 -18
- package/dist/components/AdvancedVirtualizedFileDiff.js +2 -7
- package/dist/components/AdvancedVirtualizedFileDiff.js.map +1 -1
- package/dist/components/AdvancedVirtualizer.js +1 -1
- package/dist/components/AdvancedVirtualizer.js.map +1 -1
- package/dist/components/File.d.ts +17 -7
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +111 -54
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +32 -14
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +156 -81
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +60 -0
- package/dist/components/UnresolvedFile.d.ts.map +1 -0
- package/dist/components/UnresolvedFile.js +280 -0
- package/dist/components/UnresolvedFile.js.map +1 -0
- package/dist/components/VirtualizedFile.js +8 -5
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +15 -11
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +3 -1
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +50 -24
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/constants.d.ts +3 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +8 -1
- package/dist/constants.js.map +1 -1
- package/dist/highlighter/shared_highlighter.d.ts +4 -2
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +15 -7
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.js +8 -6
- package/dist/managers/InteractionManager.d.ts +146 -0
- package/dist/managers/InteractionManager.d.ts.map +1 -0
- package/dist/managers/InteractionManager.js +813 -0
- package/dist/managers/InteractionManager.js.map +1 -0
- package/dist/managers/ResizeManager.d.ts +0 -2
- package/dist/managers/ResizeManager.d.ts.map +1 -1
- package/dist/managers/ResizeManager.js +43 -32
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/react/File.d.ts +2 -0
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +3 -1
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +2 -0
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +3 -1
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +2 -0
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +3 -1
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +2 -0
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +3 -1
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +36 -0
- package/dist/react/UnresolvedFile.d.ts.map +1 -0
- package/dist/react/UnresolvedFile.js +42 -0
- package/dist/react/UnresolvedFile.js.map +1 -0
- package/dist/react/constants.d.ts +3 -2
- package/dist/react/constants.d.ts.map +1 -1
- package/dist/react/constants.js +3 -2
- package/dist/react/constants.js.map +1 -1
- package/dist/react/index.d.ts +4 -3
- package/dist/react/index.js +3 -2
- package/dist/react/types.d.ts +11 -2
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.d.ts +16 -5
- package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +34 -7
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.d.ts +5 -1
- package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
- package/dist/react/utils/renderFileChildren.js +13 -7
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +1 -2
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +2 -2
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +1 -2
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.d.ts +33 -0
- package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -0
- package/dist/react/utils/useUnresolvedFileInstance.js +87 -0
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -0
- package/dist/renderers/DiffHunksRenderer.d.ts +50 -6
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +146 -45
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.js +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +46 -0
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -0
- package/dist/renderers/UnresolvedFileHunksRenderer.js +207 -0
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -0
- package/dist/shiki-stream/stream.d.ts +1 -1
- package/dist/shiki-stream/stream.d.ts.map +1 -1
- package/dist/shiki-stream/stream.js.map +1 -1
- package/dist/shiki-stream/tokenizer.d.ts +1 -1
- package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
- package/dist/shiki-stream/tokenizer.js.map +1 -1
- package/dist/shiki-stream/types.d.ts +1 -1
- package/dist/shiki-stream/types.d.ts.map +1 -1
- package/dist/sprite.d.ts +2 -2
- package/dist/sprite.d.ts.map +1 -1
- package/dist/sprite.js +3 -0
- package/dist/sprite.js.map +1 -1
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.js +2 -2
- package/dist/ssr/preloadDiffs.d.ts +23 -14
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +40 -14
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +29 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/areMergeConflictActionsEqual.d.ts +7 -0
- package/dist/utils/areMergeConflictActionsEqual.d.ts.map +1 -0
- package/dist/utils/areMergeConflictActionsEqual.js +11 -0
- package/dist/utils/areMergeConflictActionsEqual.js.map +1 -0
- package/dist/utils/arePrePropertiesEqual.js +10 -1
- package/dist/utils/arePrePropertiesEqual.js.map +1 -1
- package/dist/utils/areSelectionPointsEqual.d.ts +7 -0
- package/dist/utils/areSelectionPointsEqual.d.ts.map +1 -0
- package/dist/utils/areSelectionPointsEqual.js +8 -0
- package/dist/utils/areSelectionPointsEqual.js.map +1 -0
- package/dist/utils/areSelectionsEqual.d.ts +1 -1
- package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
- package/dist/utils/areSelectionsEqual.js.map +1 -1
- package/dist/utils/createFileHeaderElement.js +5 -2
- package/dist/utils/createFileHeaderElement.js.map +1 -1
- package/dist/utils/createGutterUtilityContentNode.d.ts +5 -0
- package/dist/utils/createGutterUtilityContentNode.d.ts.map +1 -0
- package/dist/utils/createGutterUtilityContentNode.js +15 -0
- package/dist/utils/createGutterUtilityContentNode.js.map +1 -0
- package/dist/utils/createGutterUtilityElement.d.ts +7 -0
- package/dist/utils/createGutterUtilityElement.d.ts.map +1 -0
- package/dist/utils/createGutterUtilityElement.js +20 -0
- package/dist/utils/createGutterUtilityElement.js.map +1 -0
- package/dist/utils/createPreElement.d.ts +2 -1
- package/dist/utils/createPreElement.d.ts.map +1 -1
- package/dist/utils/createPreElement.js +2 -1
- package/dist/utils/createPreElement.js.map +1 -1
- package/dist/utils/createSeparator.js +1 -1
- package/dist/utils/createSeparator.js.map +1 -1
- package/dist/utils/createWindowFromScrollPosition.js +12 -11
- package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
- package/dist/utils/getHighlighterOptions.d.ts +7 -2
- package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
- package/dist/utils/getHighlighterOptions.js +3 -2
- package/dist/utils/getHighlighterOptions.js.map +1 -1
- package/dist/utils/getMergeConflictActionSlotName.d.ts +16 -0
- package/dist/utils/getMergeConflictActionSlotName.d.ts.map +1 -0
- package/dist/utils/getMergeConflictActionSlotName.js +8 -0
- package/dist/utils/getMergeConflictActionSlotName.js.map +1 -0
- package/dist/utils/getMergeConflictLineTypes.d.ts +15 -0
- package/dist/utils/getMergeConflictLineTypes.d.ts.map +1 -0
- package/dist/utils/getMergeConflictLineTypes.js +81 -0
- package/dist/utils/getMergeConflictLineTypes.js.map +1 -0
- package/dist/utils/getOrCreateCodeNode.d.ts +3 -1
- package/dist/utils/getOrCreateCodeNode.d.ts.map +1 -1
- package/dist/utils/getOrCreateCodeNode.js +5 -3
- package/dist/utils/getOrCreateCodeNode.js.map +1 -1
- package/dist/utils/hast_utils.d.ts +2 -2
- package/dist/utils/hast_utils.d.ts.map +1 -1
- package/dist/utils/hast_utils.js +3 -2
- package/dist/utils/hast_utils.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts +26 -0
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js +143 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -0
- package/dist/utils/resolveMergeConflict.d.ts +7 -0
- package/dist/utils/resolveMergeConflict.d.ts.map +1 -0
- package/dist/utils/resolveMergeConflict.js +30 -0
- package/dist/utils/resolveMergeConflict.js.map +1 -0
- package/dist/utils/resolveVirtualFileMetrics.js +1 -0
- package/dist/utils/resolveVirtualFileMetrics.js.map +1 -1
- package/dist/utils/setWrapperNodeProps.d.ts +2 -1
- package/dist/utils/setWrapperNodeProps.d.ts.map +1 -1
- package/dist/utils/setWrapperNodeProps.js +5 -1
- package/dist/utils/setWrapperNodeProps.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +4 -2
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +16 -9
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/types.d.ts +3 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/wasm-BlUZCxHM.js +10 -0
- package/dist/worker/wasm-BlUZCxHM.js.map +1 -0
- package/dist/worker/worker-portable.js +10546 -10106
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +27 -19
- package/dist/worker/worker.js.map +1 -1
- package/package.json +3 -7
- package/dist/managers/LineSelectionManager.d.ts +0 -64
- package/dist/managers/LineSelectionManager.d.ts.map +0 -1
- package/dist/managers/LineSelectionManager.js +0 -270
- package/dist/managers/LineSelectionManager.js.map +0 -1
- package/dist/managers/MouseEventManager.d.ts +0 -71
- package/dist/managers/MouseEventManager.d.ts.map +0 -1
- package/dist/managers/MouseEventManager.js +0 -358
- package/dist/managers/MouseEventManager.js.map +0 -1
- package/dist/themes/pierre-dark.js +0 -1328
- package/dist/themes/pierre-dark.js.map +0 -1
- package/dist/themes/pierre-light.js +0 -1328
- package/dist/themes/pierre-light.js.map +0 -1
- package/dist/utils/createHoverContentNode.d.ts +0 -5
- package/dist/utils/createHoverContentNode.d.ts.map +0 -1
- package/dist/utils/createHoverContentNode.js +0 -15
- 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
|