@neo4j-nvl/interaction-handlers 2.0.0 → 2.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/CHANGELOG.md +25 -1
- package/README.md +8 -0
- package/lib/constants.d.ts +1 -1
- package/lib/constants.js +4 -2
- package/lib/index.d.ts +10 -20
- package/lib/index.js +10 -10
- package/lib/interaction-handlers/base.d.ts +67 -67
- package/lib/interaction-handlers/base.js +98 -104
- package/lib/interaction-handlers/box-select-interaction.d.ts +44 -44
- package/lib/interaction-handlers/box-select-interaction.js +133 -127
- package/lib/interaction-handlers/click-interaction.d.ts +111 -111
- package/lib/interaction-handlers/click-interaction.js +116 -131
- package/lib/interaction-handlers/drag-node-interaction.d.ts +40 -40
- package/lib/interaction-handlers/drag-node-interaction.js +102 -111
- package/lib/interaction-handlers/draw-interaction.d.ts +37 -37
- package/lib/interaction-handlers/draw-interaction.js +245 -278
- package/lib/interaction-handlers/hover-interaction.d.ts +34 -30
- package/lib/interaction-handlers/hover-interaction.js +83 -89
- package/lib/interaction-handlers/keyboard-interaction.d.ts +149 -97
- package/lib/interaction-handlers/keyboard-interaction.js +255 -201
- package/lib/interaction-handlers/lasso-interaction.d.ts +45 -45
- package/lib/interaction-handlers/lasso-interaction.js +174 -196
- package/lib/interaction-handlers/pan-interaction.d.ts +62 -61
- package/lib/interaction-handlers/pan-interaction.js +111 -100
- package/lib/interaction-handlers/utils.d.ts +2 -2
- package/lib/interaction-handlers/utils.js +39 -38
- package/lib/interaction-handlers/zoom-interaction.d.ts +52 -48
- package/lib/interaction-handlers/zoom-interaction.js +73 -71
- package/lib/overlay-renderer/overlay-renderer.d.ts +13 -13
- package/lib/overlay-renderer/overlay-renderer.js +96 -111
- package/package.json +19 -6
- package/lib/__tests__/box-select-interaction.test.d.ts +0 -1
- package/lib/__tests__/box-select-interaction.test.js +0 -149
- package/lib/__tests__/click-interaction.test.d.ts +0 -1
- package/lib/__tests__/click-interaction.test.js +0 -505
- package/lib/__tests__/drag-node-interaction.test.d.ts +0 -1
- package/lib/__tests__/drag-node-interaction.test.js +0 -247
- package/lib/__tests__/hover-interaction.test.d.ts +0 -1
- package/lib/__tests__/hover-interaction.test.js +0 -374
- package/lib/__tests__/keyboard-interaction.test.d.ts +0 -1
- package/lib/__tests__/keyboard-interaction.test.js +0 -322
- package/lib/__tests__/lasso-interaction.test.d.ts +0 -1
- package/lib/__tests__/lasso-interaction.test.js +0 -219
- package/lib/__tests__/pan-interaction.test.d.ts +0 -1
- package/lib/__tests__/pan-interaction.test.js +0 -223
- package/lib/__tests__/utils.test.d.ts +0 -1
- package/lib/__tests__/utils.test.js +0 -19
- package/lib/__tests__/zoom-interaction.test.d.ts +0 -1
- package/lib/__tests__/zoom-interaction.test.js +0 -185
|
@@ -1,207 +1,261 @@
|
|
|
1
|
-
import { BaseInteraction } from
|
|
1
|
+
import { BaseInteraction } from "./base.js";
|
|
2
|
+
// src/interaction-handlers/keyboard-interaction.ts
|
|
2
3
|
const DEFAULT_OPTIONS = {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
enterGraphKey: ["Enter"],
|
|
5
|
+
navigateForwardKey: ["Tab"],
|
|
6
|
+
navigateBackwardKey: ["Shift", "Tab"],
|
|
7
|
+
exitGraphKey: ["Escape"],
|
|
8
|
+
contextMenuKey: ["Shift", "F10"],
|
|
9
|
+
moveUpKey: ["ArrowUp"],
|
|
10
|
+
moveDownKey: ["ArrowDown"],
|
|
11
|
+
moveLeftKey: ["ArrowLeft"],
|
|
12
|
+
moveRightKey: ["ArrowRight"],
|
|
13
|
+
moveStep: 5,
|
|
14
|
+
largeMoveStep: 50,
|
|
15
|
+
largeMoveStepModifier: "Shift",
|
|
16
|
+
canvasOutlineColor: "#30839D"
|
|
9
17
|
};
|
|
10
18
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
* Checks whether a keyboard event matches a key combo array.
|
|
20
|
+
* The last element is the primary key (`event.key`), preceding elements are modifiers.
|
|
21
|
+
* Examples: `['Tab']`, `['Shift', 'Tab']`, `['Shift', 'F10']`
|
|
22
|
+
*/
|
|
15
23
|
const matchesKeyCombo = (event, keyCombo) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
event.shiftKey === requireShift &&
|
|
23
|
-
event.ctrlKey === requireCtrl &&
|
|
24
|
-
event.altKey === requireAlt &&
|
|
25
|
-
event.metaKey === requireMeta);
|
|
24
|
+
const key = keyCombo[keyCombo.length - 1];
|
|
25
|
+
const requireShift = keyCombo.includes("Shift");
|
|
26
|
+
const requireCtrl = keyCombo.includes("Ctrl");
|
|
27
|
+
const requireAlt = keyCombo.includes("Alt");
|
|
28
|
+
const requireMeta = keyCombo.includes("Meta");
|
|
29
|
+
return event.key === key && event.shiftKey === requireShift && event.ctrlKey === requireCtrl && event.altKey === requireAlt && event.metaKey === requireMeta;
|
|
26
30
|
};
|
|
27
31
|
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
32
|
+
* Nodes without layout coordinates cannot be moved by a relative offset.
|
|
33
|
+
*/
|
|
34
|
+
const hasPosition = (node) => node.x !== void 0 && node.y !== void 0;
|
|
35
|
+
/**
|
|
36
|
+
* Opinionated interaction handler for keyboard-driven focus navigation
|
|
37
|
+
* through graph elements (nodes and relationships).
|
|
38
|
+
*
|
|
39
|
+
* By default, Tab / Shift+Tab cycle focus through elements, Escape exits the
|
|
40
|
+
* graph, and Shift+F10 call the `onContextMenu` callback with the focused element.
|
|
41
|
+
* While a node is focused, the arrow keys move the selected node(s), or the focused
|
|
42
|
+
* node when nothing is selected, by `moveStep` screen pixels - or by `largeMoveStep`
|
|
43
|
+
* while the large step modifier (Shift by default) is held.
|
|
44
|
+
* All keys can be reconfigured via {@link KeyboardInteractionOptions}.
|
|
45
|
+
*
|
|
46
|
+
* Callbacks are fired for focus/blur transitions and context-menu activation,
|
|
47
|
+
* following the same one-way data-flow pattern as the other interaction handlers.
|
|
48
|
+
*/
|
|
49
|
+
var KeyboardInteraction = class extends BaseInteraction {
|
|
50
|
+
focusedElementId = void 0;
|
|
51
|
+
focusedElementIsNode = void 0;
|
|
52
|
+
focusableElements = [];
|
|
53
|
+
addedTabindex = false;
|
|
54
|
+
resolvedOptions;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new keyboard interaction handler.
|
|
57
|
+
* @param nvl - The NVL instance to attach the interaction handler to.
|
|
58
|
+
* @param options - Options for the keyboard interaction handler.
|
|
59
|
+
*/
|
|
60
|
+
constructor(nvl, options = {}) {
|
|
61
|
+
super(nvl, options);
|
|
62
|
+
this.resolvedOptions = {
|
|
63
|
+
...DEFAULT_OPTIONS,
|
|
64
|
+
...options
|
|
65
|
+
};
|
|
66
|
+
const tabindex = this.containerInstance.getAttribute("tabindex");
|
|
67
|
+
if (tabindex === null || tabindex === "") {
|
|
68
|
+
this.containerInstance.setAttribute("tabindex", "0");
|
|
69
|
+
this.addedTabindex = true;
|
|
70
|
+
}
|
|
71
|
+
this.addEventListener("keydown", this.handleKeyDown);
|
|
72
|
+
this.addEventListener("keyup", this.handleKeyUp);
|
|
73
|
+
this.addEventListener("focusin", this.handleFocusIn);
|
|
74
|
+
this.addEventListener("focusout", this.handleFocusOut);
|
|
75
|
+
}
|
|
76
|
+
buildFocusableElements() {
|
|
77
|
+
const nodes = this.nvlInstance.getNodes();
|
|
78
|
+
const relationships = this.nvlInstance.getRelationships();
|
|
79
|
+
this.focusableElements = [...nodes.map((node) => ({
|
|
80
|
+
id: node.id,
|
|
81
|
+
isNode: true
|
|
82
|
+
})), ...relationships.map((rel) => ({
|
|
83
|
+
id: rel.id,
|
|
84
|
+
isNode: false
|
|
85
|
+
}))];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns the currently focused element, if any.
|
|
89
|
+
*/
|
|
90
|
+
getFocused() {
|
|
91
|
+
if (this.focusedElementId === void 0) return;
|
|
92
|
+
if (this.focusedElementIsNode === true) return this.nvlInstance.getNodes().find((n) => n.id === this.focusedElementId);
|
|
93
|
+
return this.nvlInstance.getRelationships().find((r) => r.id === this.focusedElementId);
|
|
94
|
+
}
|
|
95
|
+
setCanvasOutline() {
|
|
96
|
+
const container = this.containerInstance;
|
|
97
|
+
if (container.matches(":focus-visible")) {
|
|
98
|
+
container.style.outline = `2px solid ${this.resolvedOptions.canvasOutlineColor}`;
|
|
99
|
+
container.style.outlineOffset = "-2px";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
clearCanvasOutline() {
|
|
103
|
+
const container = this.containerInstance;
|
|
104
|
+
container.style.outline = "none";
|
|
105
|
+
container.style.outlineOffset = "";
|
|
106
|
+
}
|
|
107
|
+
handleFocusIn = (event) => {
|
|
108
|
+
this.setCanvasOutline();
|
|
109
|
+
this.callCallbackIfRegistered("onCanvasFocus", event);
|
|
110
|
+
};
|
|
111
|
+
handleFocusOut = (event) => {
|
|
112
|
+
this.callCallbackIfRegistered("onCanvasBlur", event);
|
|
113
|
+
this.clearCanvasOutline();
|
|
114
|
+
};
|
|
115
|
+
handleKeyDown = (event) => {
|
|
116
|
+
const focusedElement = this.getFocused();
|
|
117
|
+
this.callCallbackIfRegistered("onKeyDown", event, focusedElement);
|
|
118
|
+
const { enterGraphKey, navigateForwardKey, navigateBackwardKey, exitGraphKey, contextMenuKey } = this.resolvedOptions;
|
|
119
|
+
if (matchesKeyCombo(event, enterGraphKey)) {
|
|
120
|
+
if (focusedElement === void 0) {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
this.navigateFocus(1, event);
|
|
123
|
+
}
|
|
124
|
+
} else if (matchesKeyCombo(event, navigateForwardKey)) {
|
|
125
|
+
if (focusedElement !== void 0) {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
this.navigateFocus(1, event);
|
|
128
|
+
}
|
|
129
|
+
} else if (matchesKeyCombo(event, navigateBackwardKey)) {
|
|
130
|
+
if (focusedElement !== void 0) {
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
this.navigateFocus(-1, event);
|
|
133
|
+
}
|
|
134
|
+
} else if (matchesKeyCombo(event, exitGraphKey)) {
|
|
135
|
+
this.setCanvasOutline();
|
|
136
|
+
if (focusedElement !== void 0) {
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
this.clearFocus(event);
|
|
139
|
+
}
|
|
140
|
+
} else if (matchesKeyCombo(event, contextMenuKey)) {
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
this.callCallbackIfRegistered("onContextMenu", focusedElement, event);
|
|
143
|
+
} else this.handleMoveKeys(event);
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Moves the nodes to be moved when the event matches one of the move key combos,
|
|
147
|
+
* either by `moveStep` or, with the large step modifier held, by `largeMoveStep`.
|
|
148
|
+
*
|
|
149
|
+
* The step is given in screen pixels and converted to graph coordinates using the
|
|
150
|
+
* current zoom level, the same way the drag interaction converts pointer
|
|
151
|
+
* movement, so keyboard and pointer moves cover the same visible distance.
|
|
152
|
+
*/
|
|
153
|
+
handleMoveKeys(event) {
|
|
154
|
+
const { moveUpKey, moveDownKey, moveLeftKey, moveRightKey, moveStep, largeMoveStep, largeMoveStepModifier } = this.resolvedOptions;
|
|
155
|
+
const direction = [
|
|
156
|
+
{
|
|
157
|
+
keyCombo: moveUpKey,
|
|
158
|
+
x: 0,
|
|
159
|
+
y: -1
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
keyCombo: moveDownKey,
|
|
163
|
+
x: 0,
|
|
164
|
+
y: 1
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
keyCombo: moveLeftKey,
|
|
168
|
+
x: -1,
|
|
169
|
+
y: 0
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
keyCombo: moveRightKey,
|
|
173
|
+
x: 1,
|
|
174
|
+
y: 0
|
|
175
|
+
}
|
|
176
|
+
].find(({ keyCombo }) => matchesKeyCombo(event, keyCombo) || matchesKeyCombo(event, [largeMoveStepModifier, ...keyCombo]));
|
|
177
|
+
if (direction === void 0) return;
|
|
178
|
+
const graphStep = (matchesKeyCombo(event, direction.keyCombo) ? moveStep : largeMoveStep) / this.nvlInstance.getScale() * window.devicePixelRatio;
|
|
179
|
+
this.moveNodes(direction.x * graphStep, direction.y * graphStep, event);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Returns the nodes a move key applies to: the selected nodes, or the focused
|
|
183
|
+
* node when nothing is selected.
|
|
184
|
+
*
|
|
185
|
+
* A node must be focused for any of them to move, so move keys are inert until
|
|
186
|
+
* the graph has been entered, and a focused relationship blocks moving entirely.
|
|
187
|
+
*/
|
|
188
|
+
getNodesToMove() {
|
|
189
|
+
if (this.focusedElementId === void 0 || this.focusedElementIsNode !== true) return [];
|
|
190
|
+
const selectedNodes = this.nvlInstance.getSelectedNodes();
|
|
191
|
+
if (selectedNodes.length > 0) return selectedNodes.filter(hasPosition);
|
|
192
|
+
return this.nvlInstance.getNodes().filter((node) => node.id === this.focusedElementId).filter(hasPosition);
|
|
193
|
+
}
|
|
194
|
+
moveNodes(dx, dy, event) {
|
|
195
|
+
const nodesToMove = this.getNodesToMove();
|
|
196
|
+
if (nodesToMove.length === 0) return;
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
const movedNodes = nodesToMove.map((node) => ({
|
|
199
|
+
...node,
|
|
200
|
+
x: node.x + dx,
|
|
201
|
+
y: node.y + dy,
|
|
202
|
+
pinned: true
|
|
203
|
+
}));
|
|
204
|
+
this.nvlInstance.setNodePositions(movedNodes.map(({ id, x, y, pinned }) => ({
|
|
205
|
+
id,
|
|
206
|
+
x,
|
|
207
|
+
y,
|
|
208
|
+
pinned
|
|
209
|
+
})), true);
|
|
210
|
+
this.callCallbackIfRegistered("onNodeMove", movedNodes, event);
|
|
211
|
+
}
|
|
212
|
+
handleKeyUp = (event) => {
|
|
213
|
+
const focusedElement = this.getFocused();
|
|
214
|
+
this.callCallbackIfRegistered("onKeyUp", event, focusedElement);
|
|
215
|
+
};
|
|
216
|
+
navigateFocus(direction, event) {
|
|
217
|
+
this.buildFocusableElements();
|
|
218
|
+
if (this.focusableElements.length === 0) return;
|
|
219
|
+
const currentIndex = this.focusedElementId !== void 0 ? this.focusableElements.findIndex((el) => el.id === this.focusedElementId && el.isNode === this.focusedElementIsNode) : -1;
|
|
220
|
+
let nextIndex;
|
|
221
|
+
if (currentIndex === -1) nextIndex = direction === 1 ? 0 : this.focusableElements.length - 1;
|
|
222
|
+
else nextIndex = (currentIndex + direction + this.focusableElements.length) % this.focusableElements.length;
|
|
223
|
+
const nextElement = this.focusableElements[nextIndex];
|
|
224
|
+
if (nextElement) this.setFocus(nextElement.id, nextElement.isNode, event);
|
|
225
|
+
}
|
|
226
|
+
setFocus(elementId, isNode, event) {
|
|
227
|
+
this.clearFocus(event);
|
|
228
|
+
this.focusedElementId = elementId;
|
|
229
|
+
this.focusedElementIsNode = isNode;
|
|
230
|
+
const newElement = this.getFocused();
|
|
231
|
+
if (newElement !== void 0) {
|
|
232
|
+
this.clearCanvasOutline();
|
|
233
|
+
if (isNode) this.callCallbackIfRegistered("onNodeFocus", newElement, event);
|
|
234
|
+
else this.callCallbackIfRegistered("onRelationshipFocus", newElement, event);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
clearFocus(event) {
|
|
238
|
+
const previousElement = this.getFocused();
|
|
239
|
+
if (previousElement !== void 0) {
|
|
240
|
+
if (this.focusedElementIsNode === true) this.callCallbackIfRegistered("onNodeBlur", previousElement, event);
|
|
241
|
+
else this.callCallbackIfRegistered("onRelationshipBlur", previousElement, event);
|
|
242
|
+
}
|
|
243
|
+
this.focusedElementId = void 0;
|
|
244
|
+
this.focusedElementIsNode = void 0;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Removes all related event listeners from the container.
|
|
248
|
+
*/
|
|
249
|
+
destroy() {
|
|
250
|
+
this.removeEventListener("keydown", this.handleKeyDown);
|
|
251
|
+
this.removeEventListener("keyup", this.handleKeyUp);
|
|
252
|
+
this.removeEventListener("focusin", this.handleFocusIn);
|
|
253
|
+
this.removeEventListener("focusout", this.handleFocusOut);
|
|
254
|
+
this.clearCanvasOutline();
|
|
255
|
+
if (this.addedTabindex) this.containerInstance.removeAttribute("tabindex");
|
|
256
|
+
this.focusedElementId = void 0;
|
|
257
|
+
this.focusedElementIsNode = void 0;
|
|
258
|
+
this.focusableElements = [];
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
export { KeyboardInteraction };
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { BaseInteraction } from "./base.js";
|
|
2
|
+
import { NVL, Node, Point, Relationship } from "@neo4j-nvl/base";
|
|
3
3
|
/**
|
|
4
4
|
* Options for the lasso interaction handler to customize its behavior.
|
|
5
5
|
*/
|
|
6
6
|
export type LassoInteractionOptions = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
/**
|
|
8
|
+
* If true, the selected items will be automatically selected when the gesture is finished.
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
selectOnRelease?: boolean;
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Callbacks for the lasso interaction handler.
|
|
15
15
|
*/
|
|
16
16
|
export type LassoInteractionCallbacks = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Called once when the user presses the mouse on the canvas, starting the lasso.
|
|
19
|
+
* @param event - The original mouse event.
|
|
20
|
+
*/
|
|
21
|
+
onLassoStarted?: ((event: MouseEvent) => void) | boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Called once when the user releases the mouse after lasso selecting.
|
|
24
|
+
* @param selectionObject - The selected nodes and relationships.
|
|
25
|
+
* @param event - The original mouse event.
|
|
26
|
+
*/
|
|
27
|
+
onLassoSelect?: (({ nodes, rels }: {
|
|
28
|
+
nodes: Node[];
|
|
29
|
+
rels: Relationship[];
|
|
30
|
+
}, event: MouseEvent) => void) | boolean;
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
33
|
* @internal
|
|
@@ -59,27 +59,27 @@ export declare const checkPointInside: (x: number, y: number, vs: Point[]) => bo
|
|
|
59
59
|
* For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_lassointeraction Lasso Interaction documentation page}.
|
|
60
60
|
*/
|
|
61
61
|
export declare class LassoInteraction extends BaseInteraction<LassoInteractionOptions> {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
62
|
+
private active;
|
|
63
|
+
private lassoPending;
|
|
64
|
+
private startClientPosition;
|
|
65
|
+
private pendingPointerCanvas;
|
|
66
|
+
private points;
|
|
67
|
+
private overlayRenderer;
|
|
68
|
+
/**
|
|
69
|
+
* Creates a new instance of the lasso interaction handler.
|
|
70
|
+
* @param nvl - The NVL instance to attach the interaction handler to.
|
|
71
|
+
* @param options - Options for the lasso interaction handler to customize its behavior.
|
|
72
|
+
*/
|
|
73
|
+
constructor(nvl: NVL, options?: LassoInteractionOptions);
|
|
74
|
+
private startLasso;
|
|
75
|
+
private handleMouseDown;
|
|
76
|
+
private handleDrag;
|
|
77
|
+
private activateLasso;
|
|
78
|
+
private handleMouseUp;
|
|
79
|
+
private getLassoItems;
|
|
80
|
+
private endLasso;
|
|
81
|
+
/**
|
|
82
|
+
* Removes all related event listeners and the overlay renderer for the box.
|
|
83
|
+
*/
|
|
84
|
+
destroy(): void;
|
|
85
|
+
}
|