@neo4j-nvl/interaction-handlers 0.2.1

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 ADDED
@@ -0,0 +1 @@
1
+ This module is a collection of decorator classes that can be used to add interaction events to an NVL instance. The decorators are applied to the NVL class. You can find documentation for the decorators in the usage documentation of each class.
@@ -0,0 +1 @@
1
+ export declare const NODE_EDGE_WIDTH = 10;
@@ -0,0 +1 @@
1
+ export const NODE_EDGE_WIDTH = 10;
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { ClickInteractionCallbacks, ClickInteractionOptions } from './interaction-handlers/click-interaction';
2
+ import { ClickInteraction } from './interaction-handlers/click-interaction';
3
+ import { DragNodeInteraction } from './interaction-handlers/drag-node-interaction';
4
+ import type { DragNodeInteractionCallbacks } from './interaction-handlers/drag-node-interaction';
5
+ import { DrawInteraction } from './interaction-handlers/draw-interaction';
6
+ import type { HoverInteractionOptions, HoverInteractionCallbacks } from './interaction-handlers/hover-interaction';
7
+ import { HoverInteraction } from './interaction-handlers/hover-interaction';
8
+ import type { MultiSelectInteractionOptions } from './interaction-handlers/multi-select-interaction';
9
+ import { MultiSelectInteraction } from './interaction-handlers/multi-select-interaction';
10
+ import type { PanInteractionCallbacks } from './interaction-handlers/pan-interaction';
11
+ import { PanInteraction } from './interaction-handlers/pan-interaction';
12
+ import type { ZoomInteractionCallbacks } from './interaction-handlers/zoom-interaction';
13
+ import { ZoomInteraction } from './interaction-handlers/zoom-interaction';
14
+ export type { MultiSelectInteractionOptions, ClickInteractionOptions, HoverInteractionOptions, HoverInteractionCallbacks, DragNodeInteractionCallbacks, ClickInteractionCallbacks, PanInteractionCallbacks, ZoomInteractionCallbacks };
15
+ export { ZoomInteraction, PanInteraction, MultiSelectInteraction, ClickInteraction, HoverInteraction, DragNodeInteraction, DrawInteraction };
package/lib/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { ClickInteraction } from './interaction-handlers/click-interaction';
2
+ import { DragNodeInteraction } from './interaction-handlers/drag-node-interaction';
3
+ import { DrawInteraction } from './interaction-handlers/draw-interaction';
4
+ import { HoverInteraction } from './interaction-handlers/hover-interaction';
5
+ import { MultiSelectInteraction } from './interaction-handlers/multi-select-interaction';
6
+ import { PanInteraction } from './interaction-handlers/pan-interaction';
7
+ import { ZoomInteraction } from './interaction-handlers/zoom-interaction';
8
+ export { ZoomInteraction, PanInteraction, MultiSelectInteraction, ClickInteraction, HoverInteraction, DragNodeInteraction, DrawInteraction };
@@ -0,0 +1,54 @@
1
+ import { NVL } from '@neo4j-nvl/core';
2
+ /**
3
+ * Base class for all interactions.
4
+ * @abstract
5
+ * @internal
6
+ */
7
+ declare abstract class BaseInteraction<T extends Record<string, (...args: unknown[]) => void>> {
8
+ private readonly nvl;
9
+ private readonly container;
10
+ /**
11
+ * @internal
12
+ */
13
+ callbackMap: Map<keyof T, T[keyof T]>;
14
+ /**
15
+ * @internal
16
+ */
17
+ constructor(nvl: NVL);
18
+ /**
19
+ * @internal
20
+ */
21
+ get nvlInstance(): NVL;
22
+ /**
23
+ * @internal
24
+ */
25
+ get containerInstance(): HTMLElement;
26
+ /**
27
+ * @internal
28
+ */
29
+ addEventListener: (type: keyof HTMLElementEventMap, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions) => void;
30
+ /**
31
+ * @internal
32
+ */
33
+ removeEventListener: (type: keyof HTMLElementEventMap, listener: (event: Event) => void, options?: boolean | EventListenerOptions) => void;
34
+ /**
35
+ * @internal
36
+ */
37
+ callCallbackIfRegistered: (name: keyof T, ...args: Parameters<T[keyof T]>) => void;
38
+ /**
39
+ * Add or update a callback for a given event of type.
40
+ * @param name - The name of the event
41
+ * @param callback - The callback to be called when the event is triggered
42
+ */
43
+ updateCallback: (name: keyof T, callback: T[keyof T]) => void;
44
+ /**
45
+ * Remove a callback for a given event of type.
46
+ * @param name - The name of the event
47
+ */
48
+ removeCallback: (name: keyof T) => void;
49
+ /**
50
+ * @internal
51
+ */
52
+ abstract destroy(): void;
53
+ }
54
+ export { BaseInteraction };
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Base class for all interactions.
3
+ * @abstract
4
+ * @internal
5
+ */
6
+ class BaseInteraction {
7
+ /**
8
+ * @internal
9
+ */
10
+ constructor(nvl) {
11
+ Object.defineProperty(this, "nvl", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ Object.defineProperty(this, "container", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ /**
24
+ * @internal
25
+ */
26
+ Object.defineProperty(this, "callbackMap", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: void 0
31
+ });
32
+ /**
33
+ * @internal
34
+ */
35
+ Object.defineProperty(this, "addEventListener", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: (type, listener, options) => {
40
+ this.container.addEventListener(type, listener, options);
41
+ }
42
+ });
43
+ /**
44
+ * @internal
45
+ */
46
+ Object.defineProperty(this, "removeEventListener", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: (type, listener, options) => {
51
+ this.container.removeEventListener(type, listener, options);
52
+ }
53
+ });
54
+ /**
55
+ * @internal
56
+ */
57
+ Object.defineProperty(this, "callCallbackIfRegistered", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: (name, ...args) => {
62
+ const callback = this.callbackMap.get(name);
63
+ if (callback) {
64
+ callback(...args);
65
+ }
66
+ }
67
+ });
68
+ /**
69
+ * Add or update a callback for a given event of type.
70
+ * @param name - The name of the event
71
+ * @param callback - The callback to be called when the event is triggered
72
+ */
73
+ Object.defineProperty(this, "updateCallback", {
74
+ enumerable: true,
75
+ configurable: true,
76
+ writable: true,
77
+ value: (name, callback) => {
78
+ this.callbackMap.set(name, callback);
79
+ }
80
+ });
81
+ /**
82
+ * Remove a callback for a given event of type.
83
+ * @param name - The name of the event
84
+ */
85
+ Object.defineProperty(this, "removeCallback", {
86
+ enumerable: true,
87
+ configurable: true,
88
+ writable: true,
89
+ value: (name) => {
90
+ this.callbackMap.delete(name);
91
+ }
92
+ });
93
+ this.nvl = nvl;
94
+ this.container = this.nvl.getContainer();
95
+ this.callbackMap = new Map();
96
+ }
97
+ /**
98
+ * @internal
99
+ */
100
+ get nvlInstance() {
101
+ return this.nvl;
102
+ }
103
+ /**
104
+ * @internal
105
+ */
106
+ get containerInstance() {
107
+ return this.container;
108
+ }
109
+ }
110
+ export { BaseInteraction };
@@ -0,0 +1,109 @@
1
+ import type { HitTargets, NVL, Node, Relationship } from '@neo4j-nvl/core';
2
+ import { BaseInteraction } from './base';
3
+ /**
4
+ * Options for the click interaction handler to customize its behavior.
5
+ */
6
+ export type ClickInteractionOptions = {
7
+ /**
8
+ * Whether to select the node or relationship on click
9
+ * @defaultValue false
10
+ */
11
+ selectOnClick?: boolean;
12
+ };
13
+ /**
14
+ * Callbacks for the click interaction handler.
15
+ */
16
+ export type ClickInteractionCallbacks = {
17
+ /**
18
+ * Called when a node is clicked
19
+ * @param nodes - The node that was clicked
20
+ * @param hitElements - All elements that were hit by the click
21
+ * @param event - The original mouse event
22
+ */
23
+ onNodeClick: (nodes: Node, hitElements: HitTargets, event: MouseEvent) => void;
24
+ /**
25
+ * Called when a relationship is clicked
26
+ * @param relationship - The relationship that was clicked
27
+ * @param hitElements - All elements that were hit by the click
28
+ * @param event - The original mouse event
29
+ */
30
+ onRelationshipClick: (relationship: Relationship, hitElements: HitTargets, event: MouseEvent) => void;
31
+ /**
32
+ * Called when the canvas is clicked
33
+ * @param event - The original mouse event
34
+ */
35
+ onCanvasClick: (event: MouseEvent) => void;
36
+ /**
37
+ * Called when a node is double clicked
38
+ * @param event - The original mouse event
39
+ */
40
+ onCanvasDoubleClick: (event: MouseEvent) => void;
41
+ /**
42
+ * Called when a relationship is right-clicked
43
+ * @param event - The original mouse event
44
+ */
45
+ onCanvasRightClick: (event: MouseEvent) => void;
46
+ /**
47
+ * Called when a node is double-clicked
48
+ * @param nodes - The node that was double-clicked
49
+ * @param hitElements - All elements that were hit by the double-click
50
+ * @param event - The original mouse event
51
+ */
52
+ onNodeDoubleClick: (node: Node, hitElements: HitTargets, event: MouseEvent) => void;
53
+ /**
54
+ * Called when a node is right-clicked
55
+ * @param nodes - The node that was right-clicked
56
+ * @param hitElements - All elements that were hit by the right-click
57
+ * @param event - The original mouse event
58
+ */
59
+ onNodeRightClick: (node: Node, hitElements: HitTargets, event: MouseEvent) => void;
60
+ /**
61
+ * Called when a relationship is double-clicked
62
+ * @param relationship - The relationship that was double-clicked
63
+ * @param hitElements - All elements that were hit by the double-click
64
+ * @param event - The original mouse event
65
+ */
66
+ onRelationshipDoubleClick: (relationship: Relationship, hitElements: HitTargets, event: MouseEvent) => void;
67
+ /**
68
+ * Called when a relationship is right-clicked
69
+ * @param relationship - The relationship that was right-clicked
70
+ * @param hitElements - All elements that were hit by the right-click
71
+ * @param event - The original mouse event
72
+ */
73
+ onRelationshipRightClick: (relationship: Relationship, hitElements: HitTargets, event: MouseEvent) => void;
74
+ };
75
+ /**
76
+ * Click interaction handler that handles click, double click and right click events on
77
+ * nodes, relationships and canvas.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * import { ClickInteraction } from '@neo4j-nvl/interaction-handlers'
82
+ * import { NVL } from '@neo4j-nvl/core'
83
+ *
84
+ * const nvl = new NVL(nodes, relationships, options)
85
+ * const clickInteraction = new ClickInteraction(nvl)
86
+ * clickInteraction.updateCallback('onNodeClick', (node) => {
87
+ * console.log('Node clicked', node)
88
+ * })
89
+ * ```
90
+ */
91
+ export declare class ClickInteraction extends BaseInteraction<ClickInteractionCallbacks> {
92
+ private moved;
93
+ private readonly options;
94
+ /**
95
+ * Creates a new click interaction handler.
96
+ * @param nvl - The NVL instance to attach the interaction handler to
97
+ * @param options - Options for the click interaction handler
98
+ */
99
+ constructor(nvl: NVL, options?: ClickInteractionOptions);
100
+ private handleMouseDown;
101
+ private handleMouseMove;
102
+ private handleRightClick;
103
+ private handleDoubleClick;
104
+ private handleMouseUp;
105
+ /**
106
+ * Removes all related event listeners from the container.
107
+ */
108
+ destroy: () => void;
109
+ }
@@ -0,0 +1,162 @@
1
+ import { BaseInteraction } from './base';
2
+ /**
3
+ * Click interaction handler that handles click, double click and right click events on
4
+ * nodes, relationships and canvas.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { ClickInteraction } from '@neo4j-nvl/interaction-handlers'
9
+ * import { NVL } from '@neo4j-nvl/core'
10
+ *
11
+ * const nvl = new NVL(nodes, relationships, options)
12
+ * const clickInteraction = new ClickInteraction(nvl)
13
+ * clickInteraction.updateCallback('onNodeClick', (node) => {
14
+ * console.log('Node clicked', node)
15
+ * })
16
+ * ```
17
+ */
18
+ export class ClickInteraction extends BaseInteraction {
19
+ /**
20
+ * Creates a new click interaction handler.
21
+ * @param nvl - The NVL instance to attach the interaction handler to
22
+ * @param options - Options for the click interaction handler
23
+ */
24
+ constructor(nvl, options = { selectOnClick: false }) {
25
+ super(nvl);
26
+ Object.defineProperty(this, "moved", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: void 0
31
+ });
32
+ Object.defineProperty(this, "options", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+ Object.defineProperty(this, "handleMouseDown", {
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true,
42
+ value: () => {
43
+ this.moved = false;
44
+ }
45
+ });
46
+ Object.defineProperty(this, "handleMouseMove", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: () => {
51
+ this.moved = true;
52
+ }
53
+ });
54
+ Object.defineProperty(this, "handleRightClick", {
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true,
58
+ value: (event) => {
59
+ event.preventDefault();
60
+ const { nvlTargets } = this.nvlInstance.getHits(event);
61
+ const { nodes = [], relationships = [] } = nvlTargets;
62
+ if (nodes.length === 0 && relationships.length === 0) {
63
+ this.callCallbackIfRegistered('onCanvasRightClick', event);
64
+ return;
65
+ }
66
+ if (nodes.length > 0) {
67
+ this.callCallbackIfRegistered('onNodeRightClick', nodes[0].data, nvlTargets, event);
68
+ }
69
+ else if (relationships.length > 0) {
70
+ this.callCallbackIfRegistered('onRelationshipRightClick', relationships[0].data, nvlTargets, event);
71
+ }
72
+ }
73
+ });
74
+ Object.defineProperty(this, "handleDoubleClick", {
75
+ enumerable: true,
76
+ configurable: true,
77
+ writable: true,
78
+ value: (event) => {
79
+ const { nvlTargets } = this.nvlInstance.getHits(event);
80
+ const { nodes = [], relationships = [] } = nvlTargets;
81
+ if (nodes.length === 0 && relationships.length === 0) {
82
+ this.callCallbackIfRegistered('onCanvasDoubleClick', event);
83
+ return;
84
+ }
85
+ if (nodes.length > 0) {
86
+ this.callCallbackIfRegistered('onNodeDoubleClick', nodes[0].data, nvlTargets, event);
87
+ }
88
+ else if (relationships.length > 0) {
89
+ this.callCallbackIfRegistered('onRelationshipDoubleClick', relationships[0].data, nvlTargets, event);
90
+ }
91
+ }
92
+ });
93
+ Object.defineProperty(this, "handleMouseUp", {
94
+ enumerable: true,
95
+ configurable: true,
96
+ writable: true,
97
+ value: (event) => {
98
+ if (this.moved) {
99
+ return;
100
+ }
101
+ const { nvlTargets } = this.nvlInstance.getHits(event);
102
+ const { nodes = [], relationships = [] } = nvlTargets;
103
+ if (nodes.length === 0 && relationships.length === 0) {
104
+ if (this.options.selectOnClick) {
105
+ this.nvlInstance.deselectAll();
106
+ }
107
+ this.callCallbackIfRegistered('onCanvasClick', event);
108
+ return;
109
+ }
110
+ if (nodes.length > 0) {
111
+ const hitNodeData = nodes.map((node) => node.data);
112
+ if (this.options.selectOnClick) {
113
+ const selectedNodes = this.nvlInstance.getSelectedNodes();
114
+ const selectedRelationships = this.nvlInstance.getSelectedRelationships();
115
+ const nodeUpdates = [
116
+ ...selectedNodes.map((node) => ({ id: node.id, selected: false })),
117
+ { id: hitNodeData[0].id, selected: true }
118
+ ];
119
+ const relationshipUpdates = selectedRelationships.map((relationship) => (Object.assign(Object.assign({}, relationship), { selected: false })));
120
+ this.nvlInstance.updateElementsInGraph(nodeUpdates, relationshipUpdates);
121
+ }
122
+ this.callCallbackIfRegistered('onNodeClick', nodes[0].data, nvlTargets, event);
123
+ }
124
+ else if (relationships.length > 0) {
125
+ const hitRelationshipData = relationships.map((relationship) => relationship.data);
126
+ if (this.options.selectOnClick) {
127
+ const selectedNodes = this.nvlInstance.getSelectedNodes();
128
+ const selectedRelationships = this.nvlInstance.getSelectedRelationships();
129
+ const nodeUpdates = selectedNodes.map((node) => ({ id: node.id, selected: false }));
130
+ const relationshipUpdates = [
131
+ { id: hitRelationshipData[0].id, selected: true },
132
+ ...selectedRelationships.map((relationship) => (Object.assign(Object.assign({}, relationship), { selected: false })))
133
+ ];
134
+ this.nvlInstance.updateElementsInGraph(nodeUpdates, relationshipUpdates);
135
+ }
136
+ this.callCallbackIfRegistered('onRelationshipClick', relationships[0].data, nvlTargets, event);
137
+ }
138
+ }
139
+ });
140
+ /**
141
+ * Removes all related event listeners from the container.
142
+ */
143
+ Object.defineProperty(this, "destroy", {
144
+ enumerable: true,
145
+ configurable: true,
146
+ writable: true,
147
+ value: () => {
148
+ this.removeEventListener('mousedown', this.handleMouseDown, true);
149
+ this.removeEventListener('mousemove', this.handleMouseMove, true);
150
+ this.removeEventListener('mouseup', this.handleMouseUp, true);
151
+ this.removeEventListener('dblclick', this.handleMouseUp, true);
152
+ this.removeEventListener('contextmenu', this.handleRightClick, true);
153
+ }
154
+ });
155
+ this.options = options;
156
+ this.addEventListener('mousedown', this.handleMouseDown, true);
157
+ this.addEventListener('mousemove', this.handleMouseMove, true);
158
+ this.addEventListener('mouseup', this.handleMouseUp, true);
159
+ this.addEventListener('dblclick', this.handleDoubleClick, true);
160
+ this.addEventListener('contextmenu', this.handleRightClick, true);
161
+ }
162
+ }
@@ -0,0 +1,46 @@
1
+ import type { NVL, Node } from '@neo4j-nvl/core';
2
+ import { BaseInteraction } from './base';
3
+ /**
4
+ * Callbacks for the drag node interaction handler.
5
+ */
6
+ export type DragNodeInteractionCallbacks = {
7
+ /**
8
+ * Called when node(s) are dragged
9
+ * @param nodes - The node(s) being dragged
10
+ */
11
+ onDrag: (nodes: Node[]) => void;
12
+ };
13
+ /**
14
+ * Interaction handler for dragging nodes.
15
+ * Dragging is achieved by clicking and dragging on the node.
16
+ * @note When more than one node is selected, all selected nodes will be dragged.
17
+ *
18
+ * @example
19
+ * ```js
20
+ * const nvl = new NVL(container, nodes, relationships)
21
+ * const dragNodeInteraction = new DragNodeInteraction(nvl)
22
+ *
23
+ * dragNodeInteraction.updateCallback('onDrag', (nodes) => {
24
+ * console.log('Dragged nodes:', nodes)
25
+ * })
26
+ * ```
27
+ */
28
+ export declare class DragNodeInteraction extends BaseInteraction<DragNodeInteractionCallbacks> {
29
+ private mousePosition;
30
+ private mouseDownNode;
31
+ private isDrawing;
32
+ private selectedNodes;
33
+ private moveSelectedNodes;
34
+ /**
35
+ * Creates a new instance of the drag node interaction handler.
36
+ * @param nvl - The NVL instance to attach the interaction handler to
37
+ */
38
+ constructor(nvl: NVL);
39
+ private handleMouseDown;
40
+ private handleMouseMove;
41
+ private handleMouseUp;
42
+ /**
43
+ * Removes all related event listeners from the container.
44
+ */
45
+ destroy: () => void;
46
+ }
@@ -0,0 +1,137 @@
1
+ import { NODE_EDGE_WIDTH } from '../constants';
2
+ import { BaseInteraction } from './base';
3
+ /**
4
+ * Interaction handler for dragging nodes.
5
+ * Dragging is achieved by clicking and dragging on the node.
6
+ * @note When more than one node is selected, all selected nodes will be dragged.
7
+ *
8
+ * @example
9
+ * ```js
10
+ * const nvl = new NVL(container, nodes, relationships)
11
+ * const dragNodeInteraction = new DragNodeInteraction(nvl)
12
+ *
13
+ * dragNodeInteraction.updateCallback('onDrag', (nodes) => {
14
+ * console.log('Dragged nodes:', nodes)
15
+ * })
16
+ * ```
17
+ */
18
+ export class DragNodeInteraction extends BaseInteraction {
19
+ /**
20
+ * Creates a new instance of the drag node interaction handler.
21
+ * @param nvl - The NVL instance to attach the interaction handler to
22
+ */
23
+ constructor(nvl) {
24
+ super(nvl);
25
+ Object.defineProperty(this, "mousePosition", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: void 0
30
+ });
31
+ Object.defineProperty(this, "mouseDownNode", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ Object.defineProperty(this, "isDrawing", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: void 0
42
+ });
43
+ Object.defineProperty(this, "selectedNodes", {
44
+ enumerable: true,
45
+ configurable: true,
46
+ writable: true,
47
+ value: void 0
48
+ });
49
+ Object.defineProperty(this, "moveSelectedNodes", {
50
+ enumerable: true,
51
+ configurable: true,
52
+ writable: true,
53
+ value: void 0
54
+ });
55
+ Object.defineProperty(this, "handleMouseDown", {
56
+ enumerable: true,
57
+ configurable: true,
58
+ writable: true,
59
+ value: (event) => {
60
+ this.mousePosition = { x: event.clientX, y: event.clientY };
61
+ const hits = this.nvlInstance.getHits(event, ['node'], { hitNodeMarginWidth: NODE_EDGE_WIDTH });
62
+ const hitNodes = hits.nvlTargets.nodes.filter(node => node.insideNode);
63
+ const hitNodeEdges = hits.nvlTargets.nodes.filter(node => !node.insideNode);
64
+ if (hitNodeEdges.length > 0) {
65
+ this.isDrawing = true;
66
+ this.mouseDownNode = null;
67
+ }
68
+ else if (hitNodes.length > 0) {
69
+ this.mouseDownNode = hits.nvlTargets.nodes[0];
70
+ }
71
+ else {
72
+ this.mouseDownNode = null;
73
+ }
74
+ this.selectedNodes = this.nvlInstance.getSelectedNodes();
75
+ if (this.mouseDownNode && this.selectedNodes.map(node => node.id).includes(this.mouseDownNode.data.id)) {
76
+ this.moveSelectedNodes = true;
77
+ }
78
+ else {
79
+ this.moveSelectedNodes = false;
80
+ }
81
+ }
82
+ });
83
+ Object.defineProperty(this, "handleMouseMove", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: (event) => {
88
+ // Avoid conflicts on moving node position in drawing process.
89
+ if (!this.mouseDownNode || event.buttons !== 1 || this.isDrawing)
90
+ return;
91
+ const zoom = this.nvlInstance.getScale();
92
+ const dx = (event.clientX - this.mousePosition.x) / zoom * window.devicePixelRatio;
93
+ const dy = (event.clientY - this.mousePosition.y) / zoom * window.devicePixelRatio;
94
+ if (this.moveSelectedNodes) {
95
+ this.nvlInstance.setNodePositions(this.selectedNodes.map((node) => ({ id: node.id, x: node.x +
96
+ dx, y: node.y + dy, pinned: true })), true);
97
+ this.callCallbackIfRegistered('onDrag', this.selectedNodes);
98
+ }
99
+ else {
100
+ this.nvlInstance.setNodePositions([{ id: this.mouseDownNode.data.id, x: this.mouseDownNode.targetCoordinates.x + dx, y: this.mouseDownNode.targetCoordinates.y + dy, pinned: true }], true);
101
+ this.callCallbackIfRegistered('onDrag', [this.mouseDownNode.data]);
102
+ }
103
+ }
104
+ });
105
+ Object.defineProperty(this, "handleMouseUp", {
106
+ enumerable: true,
107
+ configurable: true,
108
+ writable: true,
109
+ value: () => {
110
+ this.mouseDownNode = null;
111
+ this.isDrawing = false;
112
+ this.selectedNodes = [];
113
+ this.moveSelectedNodes = false;
114
+ }
115
+ });
116
+ /**
117
+ * Removes all related event listeners from the container.
118
+ */
119
+ Object.defineProperty(this, "destroy", {
120
+ enumerable: true,
121
+ configurable: true,
122
+ writable: true,
123
+ value: () => {
124
+ this.removeEventListener('mousedown', this.handleMouseDown);
125
+ this.removeEventListener('mousemove', this.handleMouseMove);
126
+ this.removeEventListener('mouseup', this.handleMouseUp);
127
+ }
128
+ });
129
+ this.mousePosition = { x: 0, y: 0 };
130
+ this.isDrawing = false;
131
+ this.selectedNodes = [];
132
+ this.moveSelectedNodes = false;
133
+ this.addEventListener('mousedown', this.handleMouseDown);
134
+ this.addEventListener('mousemove', this.handleMouseMove);
135
+ this.addEventListener('mouseup', this.handleMouseUp);
136
+ }
137
+ }