@neo4j-nvl/interaction-handlers 0.2.51 → 0.2.52
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/lib/interaction-handlers/base.d.ts +5 -3
- package/lib/interaction-handlers/base.js +11 -1
- package/lib/interaction-handlers/box-select-interaction.d.ts +2 -3
- package/lib/interaction-handlers/box-select-interaction.js +3 -10
- package/lib/interaction-handlers/click-interaction.d.ts +1 -2
- package/lib/interaction-handlers/click-interaction.js +4 -11
- package/lib/interaction-handlers/drag-node-interaction.d.ts +4 -4
- package/lib/interaction-handlers/drag-node-interaction.js +2 -2
- package/lib/interaction-handlers/draw-interaction.d.ts +3 -4
- package/lib/interaction-handlers/draw-interaction.js +16 -33
- package/lib/interaction-handlers/hover-interaction.d.ts +1 -2
- package/lib/interaction-handlers/hover-interaction.js +4 -9
- package/lib/interaction-handlers/lasso-interaction.d.ts +2 -3
- package/lib/interaction-handlers/lasso-interaction.js +2 -9
- package/lib/interaction-handlers/pan-interaction.d.ts +1 -2
- package/lib/interaction-handlers/pan-interaction.js +3 -10
- package/lib/interaction-handlers/zoom-interaction.d.ts +2 -2
- package/lib/interaction-handlers/zoom-interaction.js +2 -2
- package/lib/overlay-renderer/overlay-renderer.d.ts +0 -2
- package/lib/overlay-renderer/overlay-renderer.js +0 -24
- package/package.json +1 -1
|
@@ -4,8 +4,9 @@ import type { NVL } from '@neo4j-nvl/core';
|
|
|
4
4
|
* @abstract
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
declare abstract class BaseInteraction<T extends Record<string, ((...args: unknown[]) => void) | boolean>> {
|
|
7
|
+
declare abstract class BaseInteraction<T extends Record<string, ((...args: unknown[]) => void) | boolean>, P extends Record<string, unknown>> {
|
|
8
8
|
private readonly nvl;
|
|
9
|
+
private readonly options;
|
|
9
10
|
private readonly container;
|
|
10
11
|
/**
|
|
11
12
|
* @internal
|
|
@@ -14,11 +15,12 @@ declare abstract class BaseInteraction<T extends Record<string, ((...args: unkno
|
|
|
14
15
|
/**
|
|
15
16
|
* @internal
|
|
16
17
|
*/
|
|
17
|
-
constructor(nvl: NVL);
|
|
18
|
+
constructor(nvl: NVL, options: P);
|
|
18
19
|
/**
|
|
19
20
|
* @internal
|
|
20
21
|
*/
|
|
21
22
|
get nvlInstance(): NVL;
|
|
23
|
+
get currentOptions(): P;
|
|
22
24
|
/**
|
|
23
25
|
* @internal
|
|
24
26
|
*/
|
|
@@ -34,7 +36,7 @@ declare abstract class BaseInteraction<T extends Record<string, ((...args: unkno
|
|
|
34
36
|
/**
|
|
35
37
|
* @internal
|
|
36
38
|
*/
|
|
37
|
-
callCallbackIfRegistered: (name: keyof T
|
|
39
|
+
callCallbackIfRegistered: (name: keyof T, ...args: unknown[]) => void;
|
|
38
40
|
/**
|
|
39
41
|
* Add or update a callback for a given event of type.
|
|
40
42
|
* @param name - The name of the event
|
|
@@ -7,13 +7,19 @@ class BaseInteraction {
|
|
|
7
7
|
/**
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
constructor(nvl) {
|
|
10
|
+
constructor(nvl, options) {
|
|
11
11
|
Object.defineProperty(this, "nvl", {
|
|
12
12
|
enumerable: true,
|
|
13
13
|
configurable: true,
|
|
14
14
|
writable: true,
|
|
15
15
|
value: void 0
|
|
16
16
|
});
|
|
17
|
+
Object.defineProperty(this, "options", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
17
23
|
Object.defineProperty(this, "container", {
|
|
18
24
|
enumerable: true,
|
|
19
25
|
configurable: true,
|
|
@@ -91,6 +97,7 @@ class BaseInteraction {
|
|
|
91
97
|
}
|
|
92
98
|
});
|
|
93
99
|
this.nvl = nvl;
|
|
100
|
+
this.options = options;
|
|
94
101
|
this.container = this.nvl.getContainer();
|
|
95
102
|
this.callbackMap = new Map();
|
|
96
103
|
}
|
|
@@ -100,6 +107,9 @@ class BaseInteraction {
|
|
|
100
107
|
get nvlInstance() {
|
|
101
108
|
return this.nvl;
|
|
102
109
|
}
|
|
110
|
+
get currentOptions() {
|
|
111
|
+
return this.options;
|
|
112
|
+
}
|
|
103
113
|
/**
|
|
104
114
|
* @internal
|
|
105
115
|
*/
|
|
@@ -15,7 +15,7 @@ export type BoxSelectInteractionCallbacks = {
|
|
|
15
15
|
* Called once when the user presses the mouse on the canvas, starting the box selection.
|
|
16
16
|
* @param event - The original mouse event
|
|
17
17
|
*/
|
|
18
|
-
onBoxStarted?: (event: MouseEvent) => void;
|
|
18
|
+
onBoxStarted?: ((event: MouseEvent) => void) | boolean;
|
|
19
19
|
/**
|
|
20
20
|
* Called after once the user releases the mouse after multi-selecting.
|
|
21
21
|
* @param selectionObject - The selected nodes and relationships
|
|
@@ -40,12 +40,11 @@ export type BoxSelectInteractionCallbacks = {
|
|
|
40
40
|
* console.log('Selected elements:', nodes, rels)
|
|
41
41
|
* })
|
|
42
42
|
*/
|
|
43
|
-
export declare class BoxSelectInteraction extends BaseInteraction<BoxSelectInteractionCallbacks> {
|
|
43
|
+
export declare class BoxSelectInteraction extends BaseInteraction<BoxSelectInteractionCallbacks, BoxSelectInteractionOptions> {
|
|
44
44
|
private mousePosition;
|
|
45
45
|
private startWorldPosition;
|
|
46
46
|
private overlayRenderer;
|
|
47
47
|
private isBoxSelecting;
|
|
48
|
-
private readonly options;
|
|
49
48
|
/**
|
|
50
49
|
* Creates a new instance of the multi-select interaction handler.
|
|
51
50
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
@@ -23,7 +23,7 @@ export class BoxSelectInteraction extends BaseInteraction {
|
|
|
23
23
|
* @param options - Options for the multi-select interaction handler to customize its behavior
|
|
24
24
|
*/
|
|
25
25
|
constructor(nvl, options = { selectOnRelease: false }) {
|
|
26
|
-
super(nvl);
|
|
26
|
+
super(nvl, options);
|
|
27
27
|
Object.defineProperty(this, "mousePosition", {
|
|
28
28
|
enumerable: true,
|
|
29
29
|
configurable: true,
|
|
@@ -48,12 +48,6 @@ export class BoxSelectInteraction extends BaseInteraction {
|
|
|
48
48
|
writable: true,
|
|
49
49
|
value: void 0
|
|
50
50
|
});
|
|
51
|
-
Object.defineProperty(this, "options", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
configurable: true,
|
|
54
|
-
writable: true,
|
|
55
|
-
value: void 0
|
|
56
|
-
});
|
|
57
51
|
Object.defineProperty(this, "handleMouseDown", {
|
|
58
52
|
enumerable: true,
|
|
59
53
|
configurable: true,
|
|
@@ -129,7 +123,7 @@ export class BoxSelectInteraction extends BaseInteraction {
|
|
|
129
123
|
const endPosition = getCanvasPosition(this.containerInstance, event);
|
|
130
124
|
const endWorldPosition = getWorldPosition(this.nvlInstance, endPosition);
|
|
131
125
|
const { nodes, rels } = this.getHitsInBox(this.startWorldPosition, endWorldPosition);
|
|
132
|
-
if (this.
|
|
126
|
+
if (this.currentOptions.selectOnRelease) {
|
|
133
127
|
this.nvlInstance.updateElementsInGraph(nodes.map((node) => ({ id: node.id, selected: true })), rels.map((rel) => ({ id: rel.id, selected: true })));
|
|
134
128
|
}
|
|
135
129
|
this.callCallbackIfRegistered('onBoxSelect', { nodes, rels }, event);
|
|
@@ -139,7 +133,6 @@ export class BoxSelectInteraction extends BaseInteraction {
|
|
|
139
133
|
this.startWorldPosition = { x: 0, y: 0 };
|
|
140
134
|
this.overlayRenderer = new OverlayRenderer(this.containerInstance);
|
|
141
135
|
this.isBoxSelecting = false;
|
|
142
|
-
this.options = options;
|
|
143
136
|
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
144
137
|
this.addEventListener('mousemove', this.handleDrag, true);
|
|
145
138
|
this.addEventListener('mouseup', this.endBoxSelect, true);
|
|
@@ -164,7 +157,7 @@ export class BoxSelectInteraction extends BaseInteraction {
|
|
|
164
157
|
}
|
|
165
158
|
else {
|
|
166
159
|
this.isBoxSelecting = true;
|
|
167
|
-
if (this.
|
|
160
|
+
if (this.currentOptions.selectOnRelease) {
|
|
168
161
|
this.nvlInstance.deselectAll();
|
|
169
162
|
}
|
|
170
163
|
}
|
|
@@ -88,9 +88,8 @@ export type ClickInteractionCallbacks = {
|
|
|
88
88
|
* })
|
|
89
89
|
* ```
|
|
90
90
|
*/
|
|
91
|
-
export declare class ClickInteraction extends BaseInteraction<ClickInteractionCallbacks> {
|
|
91
|
+
export declare class ClickInteraction extends BaseInteraction<ClickInteractionCallbacks, ClickInteractionOptions> {
|
|
92
92
|
private moved;
|
|
93
|
-
private readonly options;
|
|
94
93
|
private mousePosition;
|
|
95
94
|
/**
|
|
96
95
|
* Creates a new click interaction handler.
|
|
@@ -23,19 +23,13 @@ export class ClickInteraction extends BaseInteraction {
|
|
|
23
23
|
* @param options - Options for the click interaction handler
|
|
24
24
|
*/
|
|
25
25
|
constructor(nvl, options = { selectOnClick: false }) {
|
|
26
|
-
super(nvl);
|
|
26
|
+
super(nvl, options);
|
|
27
27
|
Object.defineProperty(this, "moved", {
|
|
28
28
|
enumerable: true,
|
|
29
29
|
configurable: true,
|
|
30
30
|
writable: true,
|
|
31
31
|
value: void 0
|
|
32
32
|
});
|
|
33
|
-
Object.defineProperty(this, "options", {
|
|
34
|
-
enumerable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
writable: true,
|
|
37
|
-
value: void 0
|
|
38
|
-
});
|
|
39
33
|
Object.defineProperty(this, "mousePosition", {
|
|
40
34
|
enumerable: true,
|
|
41
35
|
configurable: true,
|
|
@@ -100,7 +94,7 @@ export class ClickInteraction extends BaseInteraction {
|
|
|
100
94
|
const { nvlTargets } = this.nvlInstance.getHits(event);
|
|
101
95
|
const { nodes = [], relationships = [] } = nvlTargets;
|
|
102
96
|
if (nodes.length === 0 && relationships.length === 0) {
|
|
103
|
-
if (this.
|
|
97
|
+
if (this.currentOptions.selectOnClick) {
|
|
104
98
|
this.nvlInstance.deselectAll();
|
|
105
99
|
}
|
|
106
100
|
this.callCallbackIfRegistered('onCanvasClick', event);
|
|
@@ -108,7 +102,7 @@ export class ClickInteraction extends BaseInteraction {
|
|
|
108
102
|
}
|
|
109
103
|
if (nodes.length > 0) {
|
|
110
104
|
const hitNodeData = nodes.map((node) => node.data);
|
|
111
|
-
if (this.
|
|
105
|
+
if (this.currentOptions.selectOnClick) {
|
|
112
106
|
const selectedNodes = this.nvlInstance.getSelectedNodes();
|
|
113
107
|
const selectedRelationships = this.nvlInstance.getSelectedRelationships();
|
|
114
108
|
const nodeUpdates = [
|
|
@@ -122,7 +116,7 @@ export class ClickInteraction extends BaseInteraction {
|
|
|
122
116
|
}
|
|
123
117
|
else if (relationships.length > 0) {
|
|
124
118
|
const hitRelationshipData = relationships.map((relationship) => relationship.data);
|
|
125
|
-
if (this.
|
|
119
|
+
if (this.currentOptions.selectOnClick) {
|
|
126
120
|
const selectedNodes = this.nvlInstance.getSelectedNodes();
|
|
127
121
|
const selectedRelationships = this.nvlInstance.getSelectedRelationships();
|
|
128
122
|
const nodeUpdates = selectedNodes.map((node) => ({ id: node.id, selected: false }));
|
|
@@ -150,7 +144,6 @@ export class ClickInteraction extends BaseInteraction {
|
|
|
150
144
|
this.removeEventListener('contextmenu', this.handleRightClick, true);
|
|
151
145
|
}
|
|
152
146
|
});
|
|
153
|
-
this.options = options;
|
|
154
147
|
this.mousePosition = { x: 0, y: 0 };
|
|
155
148
|
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
156
149
|
this.addEventListener('click', this.handleClick, true);
|
|
@@ -15,13 +15,13 @@ export type DragNodeInteractionCallbacks = {
|
|
|
15
15
|
* @param nodes - The node(s) being dragged
|
|
16
16
|
* @param event - The original mouse event
|
|
17
17
|
*/
|
|
18
|
-
onDragStart?: (nodes: Node[], evt: MouseEvent) => void;
|
|
18
|
+
onDragStart?: ((nodes: Node[], evt: MouseEvent) => void) | boolean;
|
|
19
19
|
/**
|
|
20
20
|
* Called once when node(s) are finished being dragged
|
|
21
21
|
* @param nodes - The node(s) being dragged
|
|
22
22
|
* @param event - The original mouse event
|
|
23
23
|
*/
|
|
24
|
-
onDragEnd?: (nodes: Node[], evt: MouseEvent) => void;
|
|
24
|
+
onDragEnd?: ((nodes: Node[], evt: MouseEvent) => void) | boolean;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
27
|
* Interaction handler for dragging nodes.
|
|
@@ -38,7 +38,7 @@ export type DragNodeInteractionCallbacks = {
|
|
|
38
38
|
* })
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
export declare class DragNodeInteraction extends BaseInteraction<DragNodeInteractionCallbacks
|
|
41
|
+
export declare class DragNodeInteraction extends BaseInteraction<DragNodeInteractionCallbacks, Record<string, never>> {
|
|
42
42
|
private mousePosition;
|
|
43
43
|
private mouseDownNode;
|
|
44
44
|
private isDragging;
|
|
@@ -49,7 +49,7 @@ export declare class DragNodeInteraction extends BaseInteraction<DragNodeInterac
|
|
|
49
49
|
* Creates a new instance of the drag node interaction handler.
|
|
50
50
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
51
51
|
*/
|
|
52
|
-
constructor(nvl: NVL);
|
|
52
|
+
constructor(nvl: NVL, options?: {});
|
|
53
53
|
private handleMouseDown;
|
|
54
54
|
private handleMouseMove;
|
|
55
55
|
private handleMouseUp;
|
|
@@ -21,8 +21,8 @@ export class DragNodeInteraction extends BaseInteraction {
|
|
|
21
21
|
* Creates a new instance of the drag node interaction handler.
|
|
22
22
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
23
23
|
*/
|
|
24
|
-
constructor(nvl) {
|
|
25
|
-
super(nvl);
|
|
24
|
+
constructor(nvl, options = {}) {
|
|
25
|
+
super(nvl, options);
|
|
26
26
|
Object.defineProperty(this, "mousePosition", {
|
|
27
27
|
enumerable: true,
|
|
28
28
|
configurable: true,
|
|
@@ -5,14 +5,14 @@ import { BaseInteraction } from './base';
|
|
|
5
5
|
* @experimental
|
|
6
6
|
*/
|
|
7
7
|
export type DrawInteractionCallbacks = {
|
|
8
|
+
onHoverNodeMargin?: ((hoveredNode: Node | null, evt: MouseEvent) => void) | boolean;
|
|
8
9
|
onDrawEnd?: ((newRelationshipToAdd: Relationship | null, newTargetNodeToAdd: Node | null, event: MouseEvent) => void) | boolean;
|
|
9
10
|
};
|
|
10
11
|
/**
|
|
11
12
|
* @internal
|
|
12
13
|
* @experimental
|
|
13
14
|
*/
|
|
14
|
-
export declare class DrawInteraction extends BaseInteraction<DrawInteractionCallbacks
|
|
15
|
-
private overlayRenderer;
|
|
15
|
+
export declare class DrawInteraction extends BaseInteraction<DrawInteractionCallbacks, Record<string, never>> {
|
|
16
16
|
private isMoved;
|
|
17
17
|
private isDrawing;
|
|
18
18
|
private isDraggingNode;
|
|
@@ -23,9 +23,8 @@ export declare class DrawInteraction extends BaseInteraction<DrawInteractionCall
|
|
|
23
23
|
private newTempSelfReferredRelationship;
|
|
24
24
|
private newTargetNodeToAdd;
|
|
25
25
|
private newRelationshipToAdd;
|
|
26
|
-
constructor(nvl: NVL);
|
|
26
|
+
constructor(nvl: NVL, options?: {});
|
|
27
27
|
private handleMouseMove;
|
|
28
|
-
private handleWheel;
|
|
29
28
|
private setNewRegularRelationship;
|
|
30
29
|
private setNewRegularRelationshipToNewTempTargetNode;
|
|
31
30
|
private setNewRegularRelationshipToExistingNode;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
1
2
|
import { NODE_EDGE_WIDTH } from '../constants';
|
|
2
|
-
import { OverlayRenderer } from '../overlay-renderer/overlay-renderer';
|
|
3
3
|
import { BaseInteraction } from './base';
|
|
4
4
|
import { generateUniqueId, getCanvasPosition, getWorldPosition } from './utils';
|
|
5
5
|
/**
|
|
@@ -7,14 +7,8 @@ import { generateUniqueId, getCanvasPosition, getWorldPosition } from './utils';
|
|
|
7
7
|
* @experimental
|
|
8
8
|
*/
|
|
9
9
|
export class DrawInteraction extends BaseInteraction {
|
|
10
|
-
constructor(nvl) {
|
|
11
|
-
super(nvl);
|
|
12
|
-
Object.defineProperty(this, "overlayRenderer", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
configurable: true,
|
|
15
|
-
writable: true,
|
|
16
|
-
value: void 0
|
|
17
|
-
});
|
|
10
|
+
constructor(nvl, options = {}) {
|
|
11
|
+
super(nvl, options);
|
|
18
12
|
Object.defineProperty(this, "isMoved", {
|
|
19
13
|
enumerable: true,
|
|
20
14
|
configurable: true,
|
|
@@ -83,11 +77,10 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
83
77
|
var _a, _b, _c, _d, _e, _f;
|
|
84
78
|
this.isMoved = true;
|
|
85
79
|
if (this.isDrawing) {
|
|
86
|
-
this.overlayRenderer.clear();
|
|
87
80
|
const canvasPos = getCanvasPosition(this.containerInstance, event);
|
|
88
81
|
const pos = getWorldPosition(this.nvlInstance, canvasPos);
|
|
89
82
|
const hits = this.nvlInstance.getHits(event, ['node']);
|
|
90
|
-
const hitNode = hits.nvlTargets.nodes.filter((n) => n.data.id !== this.newTempTargetNode.id)
|
|
83
|
+
const [hitNode] = hits.nvlTargets.nodes.filter((n) => n.data.id !== this.newTempTargetNode.id);
|
|
91
84
|
const targetNode = hitNode
|
|
92
85
|
? {
|
|
93
86
|
id: hitNode.data.id,
|
|
@@ -96,7 +89,9 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
96
89
|
size: hitNode.data.size
|
|
97
90
|
}
|
|
98
91
|
: undefined;
|
|
99
|
-
// ArrowBundler has race-condition to update the dataset,
|
|
92
|
+
// ArrowBundler has race-condition to update the dataset,
|
|
93
|
+
// if we remove the node with the same ID after mouse releases,
|
|
94
|
+
// the same node will be removed then be added again, which will cause the issue.
|
|
100
95
|
// So always make sure the new node id to be added to the dataset after mouse releasing is a new id.
|
|
101
96
|
const newTargetNodeId = generateUniqueId(13);
|
|
102
97
|
const newTargetNode = targetNode ? null : { id: newTargetNodeId, size: 25, selected: false, x: pos.x, y: pos.y };
|
|
@@ -155,30 +150,21 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
155
150
|
const hits = this.nvlInstance.getHits(event, ['node'], { hitNodeMarginWidth: NODE_EDGE_WIDTH });
|
|
156
151
|
const hitNodeEdges = hits.nvlTargets.nodes.filter((node) => !node.insideNode);
|
|
157
152
|
if (hitNodeEdges.length > 0) {
|
|
158
|
-
const node = hitNodeEdges
|
|
159
|
-
|
|
160
|
-
const { x, y } = this.nvlInstance.getPan();
|
|
161
|
-
this.overlayRenderer.drawNodeRing(node.targetCoordinates.x, node.targetCoordinates.y, node.data.size, zoom, x, y);
|
|
153
|
+
const [node] = hitNodeEdges;
|
|
154
|
+
this.callCallbackIfRegistered('onHoverNodeMargin', node.data);
|
|
162
155
|
}
|
|
163
156
|
else {
|
|
164
|
-
this.
|
|
157
|
+
this.callCallbackIfRegistered('onHoverNodeMargin', null);
|
|
165
158
|
}
|
|
166
159
|
}
|
|
167
160
|
}
|
|
168
161
|
});
|
|
169
|
-
Object.defineProperty(this, "handleWheel", {
|
|
170
|
-
enumerable: true,
|
|
171
|
-
configurable: true,
|
|
172
|
-
writable: true,
|
|
173
|
-
value: () => {
|
|
174
|
-
this.overlayRenderer.clear();
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
162
|
Object.defineProperty(this, "handleMouseDown", {
|
|
178
163
|
enumerable: true,
|
|
179
164
|
configurable: true,
|
|
180
165
|
writable: true,
|
|
181
166
|
value: (event) => {
|
|
167
|
+
this.callCallbackIfRegistered('onHoverNodeMargin', null);
|
|
182
168
|
this.isMoved = false;
|
|
183
169
|
this.newRelationshipToAdd = null;
|
|
184
170
|
this.newTargetNodeToAdd = null;
|
|
@@ -226,8 +212,10 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
226
212
|
]);
|
|
227
213
|
this.nvlInstance.removeNodesWithIds([(_d = this.newTempTargetNode) === null || _d === void 0 ? void 0 : _d.id]);
|
|
228
214
|
if (this.isDrawing && this.isMoved) {
|
|
229
|
-
|
|
230
|
-
|
|
215
|
+
if (this.newTargetNodeToAdd) {
|
|
216
|
+
this.nvlInstance.setNodePositions([this.newTargetNodeToAdd]);
|
|
217
|
+
}
|
|
218
|
+
// Avoid relationship glitch.
|
|
231
219
|
this.nvlInstance.addAndUpdateElementsInGraph(this.newTargetNodeToAdd ? [{ id: this.newTargetNodeToAdd.id }] : [], [this.newRelationshipToAdd]);
|
|
232
220
|
this.callCallbackIfRegistered('onDrawEnd', this.newRelationshipToAdd, this.newTargetNodeToAdd, event);
|
|
233
221
|
}
|
|
@@ -238,7 +226,6 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
238
226
|
this.isMoved = false;
|
|
239
227
|
this.isDrawing = false;
|
|
240
228
|
this.isDraggingNode = false;
|
|
241
|
-
this.overlayRenderer.clear();
|
|
242
229
|
}
|
|
243
230
|
});
|
|
244
231
|
Object.defineProperty(this, "destroy", {
|
|
@@ -247,25 +234,21 @@ export class DrawInteraction extends BaseInteraction {
|
|
|
247
234
|
writable: true,
|
|
248
235
|
value: () => {
|
|
249
236
|
this.removeEventListener('mousemove', this.handleMouseMove, true);
|
|
250
|
-
this.removeEventListener('wheel', this.handleWheel, true);
|
|
251
237
|
this.removeEventListener('mousedown', this.handleMouseDown, true);
|
|
252
238
|
this.removeEventListener('mouseup', this.handleMouseUp, true);
|
|
253
|
-
this.overlayRenderer.destroy();
|
|
254
239
|
}
|
|
255
240
|
});
|
|
256
|
-
this.overlayRenderer = new OverlayRenderer(this.containerInstance);
|
|
257
241
|
this.isMoved = false;
|
|
258
242
|
this.isDrawing = false;
|
|
259
243
|
this.isDraggingNode = false;
|
|
260
244
|
this.nvlInstance.setLayout('free');
|
|
261
245
|
this.addEventListener('mousemove', this.handleMouseMove, true);
|
|
262
|
-
this.addEventListener('wheel', this.handleWheel, true);
|
|
263
246
|
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
264
247
|
this.addEventListener('mouseup', this.handleMouseUp, true);
|
|
265
248
|
}
|
|
266
249
|
setNewRegularRelationship(targetId) {
|
|
267
250
|
if (!this.mouseDownNode) {
|
|
268
|
-
return;
|
|
251
|
+
return null;
|
|
269
252
|
}
|
|
270
253
|
return {
|
|
271
254
|
id: generateUniqueId(13),
|
|
@@ -39,11 +39,10 @@ export type HoverInteractionCallbacks = {
|
|
|
39
39
|
* })
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
|
-
export declare class HoverInteraction extends BaseInteraction<HoverInteractionCallbacks> {
|
|
42
|
+
export declare class HoverInteraction extends BaseInteraction<HoverInteractionCallbacks, HoverInteractionOptions> {
|
|
43
43
|
private currentHoveredElement;
|
|
44
44
|
private currentHoveredElementIsNode;
|
|
45
45
|
private readonly updates;
|
|
46
|
-
private readonly options;
|
|
47
46
|
constructor(nvl: NVL, options?: HoverInteractionOptions);
|
|
48
47
|
/**
|
|
49
48
|
* Handle mouse hover events
|
|
@@ -16,7 +16,7 @@ import { BaseInteraction } from './base';
|
|
|
16
16
|
*/
|
|
17
17
|
export class HoverInteraction extends BaseInteraction {
|
|
18
18
|
constructor(nvl, options = { drawShadowOnHover: false }) {
|
|
19
|
-
super(nvl);
|
|
19
|
+
super(nvl, options);
|
|
20
20
|
Object.defineProperty(this, "currentHoveredElement", {
|
|
21
21
|
enumerable: true,
|
|
22
22
|
configurable: true,
|
|
@@ -35,12 +35,6 @@ export class HoverInteraction extends BaseInteraction {
|
|
|
35
35
|
writable: true,
|
|
36
36
|
value: void 0
|
|
37
37
|
});
|
|
38
|
-
Object.defineProperty(this, "options", {
|
|
39
|
-
enumerable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
writable: true,
|
|
42
|
-
value: void 0
|
|
43
|
-
});
|
|
44
38
|
/**
|
|
45
39
|
* Handle mouse hover events
|
|
46
40
|
* @param {MouseEvent} event - The mouse event
|
|
@@ -64,6 +58,7 @@ export class HoverInteraction extends BaseInteraction {
|
|
|
64
58
|
this.currentHoveredElementIsNode = true;
|
|
65
59
|
}
|
|
66
60
|
else if (mainTarget !== undefined) {
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
67
62
|
const { id, from, to } = hoveredElement;
|
|
68
63
|
this.updates.relationships.push({ id, from, to, hovered: true });
|
|
69
64
|
this.currentHoveredElement = hoveredElement;
|
|
@@ -75,7 +70,7 @@ export class HoverInteraction extends BaseInteraction {
|
|
|
75
70
|
}
|
|
76
71
|
this.callCallbackIfRegistered('onHover', this.currentHoveredElement, nvlTargets, event);
|
|
77
72
|
// Use pure update API to avoid the previous removed node to be re-added to the scene.
|
|
78
|
-
if (this.
|
|
73
|
+
if (this.currentOptions.drawShadowOnHover) {
|
|
79
74
|
const currentNodes = this.nvlInstance.getNodes();
|
|
80
75
|
if (currentNodes.length > 0) {
|
|
81
76
|
this.nvlInstance.updateElementsInGraph(this.updates.nodes, this.updates.relationships);
|
|
@@ -88,7 +83,6 @@ export class HoverInteraction extends BaseInteraction {
|
|
|
88
83
|
nodes: [],
|
|
89
84
|
relationships: []
|
|
90
85
|
};
|
|
91
|
-
this.options = options;
|
|
92
86
|
this.addEventListener('mousemove', this.handleHover, true);
|
|
93
87
|
}
|
|
94
88
|
clearUpdates() {
|
|
@@ -107,6 +101,7 @@ export class HoverInteraction extends BaseInteraction {
|
|
|
107
101
|
this.updates.nodes.push(update);
|
|
108
102
|
}
|
|
109
103
|
else {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
110
105
|
const { from, to } = this.currentHoveredElement;
|
|
111
106
|
this.updates.relationships.push(Object.assign(Object.assign({}, update), { from, to }));
|
|
112
107
|
}
|
|
@@ -15,7 +15,7 @@ export type LassoInteractionCallbacks = {
|
|
|
15
15
|
* Called once when the user presses the mouse on the canvas, starting the lasso.
|
|
16
16
|
* @param event - The original mouse event
|
|
17
17
|
*/
|
|
18
|
-
onLassoStarted?: (event: MouseEvent) => void;
|
|
18
|
+
onLassoStarted?: ((event: MouseEvent) => void) | boolean;
|
|
19
19
|
/**
|
|
20
20
|
* Called once when the user releases the mouse after lasso selecting.
|
|
21
21
|
* @param selectionObject - The selected node and relationship ids
|
|
@@ -40,11 +40,10 @@ export type LassoInteractionCallbacks = {
|
|
|
40
40
|
* console.log('Selected elements:', nodes, rels)
|
|
41
41
|
* })
|
|
42
42
|
*/
|
|
43
|
-
export declare class LassoInteraction extends BaseInteraction<LassoInteractionCallbacks> {
|
|
43
|
+
export declare class LassoInteraction extends BaseInteraction<LassoInteractionCallbacks, LassoInteractionOptions> {
|
|
44
44
|
private active;
|
|
45
45
|
private points;
|
|
46
46
|
private overlayRenderer;
|
|
47
|
-
private readonly options;
|
|
48
47
|
/**
|
|
49
48
|
* Creates a new instance of the lasso interaction handler.
|
|
50
49
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
@@ -25,7 +25,7 @@ export class LassoInteraction extends BaseInteraction {
|
|
|
25
25
|
* @param options - Options for the lasso interaction handler to customize its behavior
|
|
26
26
|
*/
|
|
27
27
|
constructor(nvl, options = { selectOnRelease: false }) {
|
|
28
|
-
super(nvl);
|
|
28
|
+
super(nvl, options);
|
|
29
29
|
Object.defineProperty(this, "active", {
|
|
30
30
|
enumerable: true,
|
|
31
31
|
configurable: true,
|
|
@@ -44,12 +44,6 @@ export class LassoInteraction extends BaseInteraction {
|
|
|
44
44
|
writable: true,
|
|
45
45
|
value: void 0
|
|
46
46
|
});
|
|
47
|
-
Object.defineProperty(this, "options", {
|
|
48
|
-
enumerable: true,
|
|
49
|
-
configurable: true,
|
|
50
|
-
writable: true,
|
|
51
|
-
value: void 0
|
|
52
|
-
});
|
|
53
47
|
Object.defineProperty(this, "startLasso", {
|
|
54
48
|
enumerable: true,
|
|
55
49
|
configurable: true,
|
|
@@ -154,7 +148,7 @@ export class LassoInteraction extends BaseInteraction {
|
|
|
154
148
|
this.overlayRenderer.drawLasso(hull, false, true);
|
|
155
149
|
setTimeout(() => this.overlayRenderer.clear(), shapeShowTime);
|
|
156
150
|
const hitItems = this.getLassoItems(hull);
|
|
157
|
-
if (this.
|
|
151
|
+
if (this.currentOptions.selectOnRelease) {
|
|
158
152
|
this.nvlInstance.updateElementsInGraph(hitItems.nodes.map((node) => ({ id: node.id, selected: true })), hitItems.rels.map((rel) => ({ id: rel.id, selected: true })));
|
|
159
153
|
}
|
|
160
154
|
this.callCallbackIfRegistered('onLassoSelect', hitItems, event);
|
|
@@ -162,7 +156,6 @@ export class LassoInteraction extends BaseInteraction {
|
|
|
162
156
|
});
|
|
163
157
|
this.overlayRenderer = new OverlayRenderer(this.containerInstance);
|
|
164
158
|
this.active = false;
|
|
165
|
-
this.options = options;
|
|
166
159
|
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
167
160
|
this.addEventListener('mousemove', this.handleDrag, true);
|
|
168
161
|
this.addEventListener('mouseup', this.handleMouseUp, true);
|
|
@@ -37,10 +37,9 @@ export type PanInteractionCallbacks = {
|
|
|
37
37
|
* console.log('Panning:', panning)
|
|
38
38
|
* })
|
|
39
39
|
*/
|
|
40
|
-
export declare class PanInteraction extends BaseInteraction<PanInteractionCallbacks> {
|
|
40
|
+
export declare class PanInteraction extends BaseInteraction<PanInteractionCallbacks, PanInteractionOptions> {
|
|
41
41
|
private mousePosition;
|
|
42
42
|
private targets;
|
|
43
|
-
private readonly options;
|
|
44
43
|
private shouldPan;
|
|
45
44
|
/**
|
|
46
45
|
* Creates a new instance of the pan interaction handler.
|
|
@@ -20,7 +20,7 @@ export class PanInteraction extends BaseInteraction {
|
|
|
20
20
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
21
21
|
*/
|
|
22
22
|
constructor(nvl, options = { excludeNodeMargin: false }) {
|
|
23
|
-
super(nvl);
|
|
23
|
+
super(nvl, options);
|
|
24
24
|
Object.defineProperty(this, "mousePosition", {
|
|
25
25
|
enumerable: true,
|
|
26
26
|
configurable: true,
|
|
@@ -33,12 +33,6 @@ export class PanInteraction extends BaseInteraction {
|
|
|
33
33
|
writable: true,
|
|
34
34
|
value: void 0
|
|
35
35
|
});
|
|
36
|
-
Object.defineProperty(this, "options", {
|
|
37
|
-
enumerable: true,
|
|
38
|
-
configurable: true,
|
|
39
|
-
writable: true,
|
|
40
|
-
value: void 0
|
|
41
|
-
});
|
|
42
36
|
Object.defineProperty(this, "shouldPan", {
|
|
43
37
|
enumerable: true,
|
|
44
38
|
configurable: true,
|
|
@@ -63,7 +57,7 @@ export class PanInteraction extends BaseInteraction {
|
|
|
63
57
|
writable: true,
|
|
64
58
|
value: (targets, excludeNodeMargin) => {
|
|
65
59
|
this.targets = targets;
|
|
66
|
-
this.
|
|
60
|
+
this.currentOptions.excludeNodeMargin = excludeNodeMargin;
|
|
67
61
|
}
|
|
68
62
|
});
|
|
69
63
|
Object.defineProperty(this, "handleMouseDown", {
|
|
@@ -72,7 +66,7 @@ export class PanInteraction extends BaseInteraction {
|
|
|
72
66
|
writable: true,
|
|
73
67
|
value: (event) => {
|
|
74
68
|
const hits = this.nvlInstance.getHits(event, difference(['node', 'relationship'], this.targets), {
|
|
75
|
-
hitNodeMarginWidth: this.
|
|
69
|
+
hitNodeMarginWidth: this.currentOptions.excludeNodeMargin ? NODE_EDGE_WIDTH : 0
|
|
76
70
|
});
|
|
77
71
|
if (hits.nvlTargets.nodes.length > 0 || hits.nvlTargets.relationships.length > 0) {
|
|
78
72
|
this.shouldPan = false;
|
|
@@ -110,7 +104,6 @@ export class PanInteraction extends BaseInteraction {
|
|
|
110
104
|
});
|
|
111
105
|
this.mousePosition = { x: 0, y: 0 };
|
|
112
106
|
this.targets = [];
|
|
113
|
-
this.options = options;
|
|
114
107
|
this.shouldPan = false;
|
|
115
108
|
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
116
109
|
this.addEventListener('mousemove', this.handleMouseMove, true);
|
|
@@ -25,12 +25,12 @@ export type ZoomInteractionCallbacks = {
|
|
|
25
25
|
* })
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
export declare class ZoomInteraction extends BaseInteraction<ZoomInteractionCallbacks
|
|
28
|
+
export declare class ZoomInteraction extends BaseInteraction<ZoomInteractionCallbacks, Record<string, never>> {
|
|
29
29
|
/**
|
|
30
30
|
* Creates a new instance of the zoom interaction handler.
|
|
31
31
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
32
32
|
*/
|
|
33
|
-
constructor(nvl: NVL);
|
|
33
|
+
constructor(nvl: NVL, options?: {});
|
|
34
34
|
/**
|
|
35
35
|
* Throttled zoom function to avoid events happening too fast.
|
|
36
36
|
* @param event - The original mouse wheel event
|
|
@@ -20,8 +20,8 @@ export class ZoomInteraction extends BaseInteraction {
|
|
|
20
20
|
* Creates a new instance of the zoom interaction handler.
|
|
21
21
|
* @param nvl - The NVL instance to attach the interaction handler to
|
|
22
22
|
*/
|
|
23
|
-
constructor(nvl) {
|
|
24
|
-
super(nvl);
|
|
23
|
+
constructor(nvl, options = {}) {
|
|
24
|
+
super(nvl, options);
|
|
25
25
|
/**
|
|
26
26
|
* Throttled zoom function to avoid events happening too fast.
|
|
27
27
|
* @param event - The original mouse wheel event
|
|
@@ -4,13 +4,11 @@ export declare class OverlayRenderer {
|
|
|
4
4
|
private removeResizeListener;
|
|
5
5
|
constructor(canvasParent: HTMLElement);
|
|
6
6
|
private fixCanvasSize;
|
|
7
|
-
private zoomAndPan;
|
|
8
7
|
drawBox(startX: number, startY: number, endX: number, endY: number): void;
|
|
9
8
|
drawLasso(points: {
|
|
10
9
|
x: number;
|
|
11
10
|
y: number;
|
|
12
11
|
}[], stroke: boolean, fill: boolean): void;
|
|
13
|
-
drawNodeRing(x: number, y: number, radius: number, zoom: number, panX: number, panY: number): void;
|
|
14
12
|
clear(): void;
|
|
15
13
|
destroy(): void;
|
|
16
14
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { drawCircleBand } from '@neo4j-nvl/core';
|
|
2
1
|
import onResize from 'resizelistener';
|
|
3
2
|
const marquee = {
|
|
4
3
|
frameWidth: 2,
|
|
@@ -35,8 +34,6 @@ export class OverlayRenderer {
|
|
|
35
34
|
canvas.style.right = '0';
|
|
36
35
|
// These are needed for touchpad zoom on Edge
|
|
37
36
|
canvas.style.touchAction = 'none';
|
|
38
|
-
// @ts-expect-error revisit later
|
|
39
|
-
canvas.style.msTouchAction = 'none';
|
|
40
37
|
canvasParent.appendChild(canvas);
|
|
41
38
|
const context = canvas.getContext('2d');
|
|
42
39
|
this.ctx = context;
|
|
@@ -57,16 +54,6 @@ export class OverlayRenderer {
|
|
|
57
54
|
canvas.style.width = `${width}px`;
|
|
58
55
|
canvas.style.height = `${height}px`;
|
|
59
56
|
}
|
|
60
|
-
// Can be extracted as a util
|
|
61
|
-
zoomAndPan(zoom, panX, panY) {
|
|
62
|
-
const { ctx, canvas } = this;
|
|
63
|
-
const { width, height } = canvas;
|
|
64
|
-
ctx.translate((-width / 2) * zoom, (-height / 2) * zoom);
|
|
65
|
-
ctx.translate(-panX * zoom, -panY * zoom);
|
|
66
|
-
ctx.scale(zoom, zoom);
|
|
67
|
-
ctx.translate(width / 2 / zoom, height / 2 / zoom);
|
|
68
|
-
ctx.translate(width / 2, height / 2);
|
|
69
|
-
}
|
|
70
57
|
drawBox(startX, startY, endX, endY) {
|
|
71
58
|
const { ctx } = this;
|
|
72
59
|
if (ctx === null) {
|
|
@@ -116,17 +103,6 @@ export class OverlayRenderer {
|
|
|
116
103
|
}
|
|
117
104
|
ctx.restore();
|
|
118
105
|
}
|
|
119
|
-
drawNodeRing(x, y, radius, zoom, panX, panY) {
|
|
120
|
-
const { ctx } = this;
|
|
121
|
-
this.clear();
|
|
122
|
-
ctx.save();
|
|
123
|
-
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
124
|
-
this.zoomAndPan(zoom, panX, panY);
|
|
125
|
-
// TODO: make 0.2 configurable from state and same as colour
|
|
126
|
-
const width = (radius !== null && radius !== void 0 ? radius : 25) * devicePixelRatio * 0.2;
|
|
127
|
-
drawCircleBand(ctx, x, y, (radius !== null && radius !== void 0 ? radius : 25) * devicePixelRatio, [{ width, color: 'blue' }]);
|
|
128
|
-
ctx.restore();
|
|
129
|
-
}
|
|
130
106
|
clear() {
|
|
131
107
|
const { ctx, canvas } = this;
|
|
132
108
|
if (ctx === null) {
|