@neo4j-nvl/interaction-handlers 0.3.3 → 0.3.4-b33c5deb

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # Neo4j Visualization Library
2
2
 
3
- Welcome to NVL (Neo4j Visualization Library). NVL is a collection of libraries that can be used to build custom graph visualizations like [Neo4j Bloom](https://neo4j.com/product/bloom/). The NVL library is also available as a React component that can be used in React applications.
3
+ Welcome to the Neo4j Visualization Library, NVL for short. NVL is a collection of libraries that can be used to build custom graph visualizations like those used in [Neo4j Bloom and Explore(powered by Bloom)](https://neo4j.com/product/bloom/). NVL is written in TypeScript and can be used in any JavaScript project. It is also available as a React component that can be used in React applications.
4
4
 
5
- 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 more information about the NVL class in the base library documentation.
5
+ 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 more information about the NVL class in the [NVL base library](https://www.npmjs.com/package/@neo4j-nvl/base).
6
6
 
7
7
  ## Consuming the library
8
8
 
@@ -14,13 +14,12 @@ You can install the interaction handlers with your preferred package manager, fo
14
14
  npm install @neo4j-nvl/interaction-handlers
15
15
  ```
16
16
 
17
- If you are planning to use NVL in a React app, be sure to check out the NVL React wrappers.
17
+ If you are planning to use NVL in a React app, be sure to check out the [NVL React wrappers](https://www.npmjs.com/package/@neo4j-nvl/react).
18
18
 
19
19
  ### Using the library
20
20
 
21
21
  Heres is an example on how to use an interaction handler with the NVL class:
22
22
 
23
-
24
23
  ```ts
25
24
  import { ClickInteraction } from '@neo4j-nvl/interaction-handlers'
26
25
  import { NVL } from '@neo4j-nvl/base'
@@ -34,4 +33,4 @@ clickInteraction.updateCallback('onNodeClick', (node) => {
34
33
 
35
34
  If you are using React and want to add interactivity to your graph, you can also make use of the InteractiveReactWrapper.
36
35
 
37
- You can find more instructions and examples on how to use NVL interaction handlers in the [docs](https://neo4j.com/docs/nvl/current/interaction-handlers/).
36
+ You can find more instructions and examples on how to use NVL interaction handlers in the [docs](https://neo4j.com/docs/nvl/current/interaction-handlers/).
@@ -1,6 +1,6 @@
1
1
  import NVL from '@neo4j-nvl/base';
2
2
  import '@testing-library/jest-dom';
3
- import { LassoInteraction } from '../interaction-handlers/lasso-interaction';
3
+ import { LassoInteraction, checkIntersection, checkLinesCrossing, checkPointInside } from '../interaction-handlers/lasso-interaction';
4
4
  jest.mock('@neo4j-nvl/layout-workers');
5
5
  const testNodes = [
6
6
  { id: '0', x: 10, y: 10 },
@@ -64,7 +64,7 @@ describe('LassoInteraction', () => {
64
64
  createMouseEvent('mousemove', 250, 0),
65
65
  createMouseEvent('mousemove', 240, 240),
66
66
  createMouseEvent('mousemove', 100, 200),
67
- createMouseEvent('mousemove', 50, 0),
67
+ createMouseEvent('mousemove', 0, 50),
68
68
  createMouseEvent('mouseup', 0, 0)
69
69
  ];
70
70
  const container = myNVL.getContainer();
@@ -76,4 +76,49 @@ describe('LassoInteraction', () => {
76
76
  resolve();
77
77
  });
78
78
  });
79
+ test('test for line crossing utility function', () => {
80
+ const res1 = checkLinesCrossing([0, 0], [10, 10], [10, 0], [0, 10]);
81
+ expect(res1).toBeTruthy();
82
+ const res2 = checkLinesCrossing([10, 10], [227, 182], [390, 10], [100, 100]);
83
+ expect(res2).toBeTruthy();
84
+ const res3 = checkLinesCrossing([5, 5], [5, 20], [10, 10], [20, 10]);
85
+ expect(res3).toBeFalsy();
86
+ const res4 = checkLinesCrossing([10, 10], [20, 10], [15, 10], [25, 10]);
87
+ expect(res4).toBeFalsy();
88
+ const res5 = checkLinesCrossing([880, 416], [872, 404], [868, 392], [856, 378]);
89
+ expect(res5).toBeFalsy();
90
+ });
91
+ test('test for line segment crossing utility function', () => {
92
+ const res1 = checkIntersection([
93
+ [0, 0],
94
+ [10, 0],
95
+ [100, 10],
96
+ [50, 10],
97
+ [50, -10]
98
+ ]);
99
+ expect(res1).toBeTruthy();
100
+ const res2 = checkIntersection([
101
+ [10, 10],
102
+ [227, 182],
103
+ [390, 10],
104
+ [500, 100]
105
+ ]);
106
+ expect(res2).toBeFalsy();
107
+ });
108
+ test('test for point inside polygon utility function', () => {
109
+ const res1 = checkPointInside(10, 10, [
110
+ { x: 0, y: 0 },
111
+ { x: 10, y: -10 },
112
+ { x: 20, y: 0 },
113
+ { x: 10, y: 20 }
114
+ ]);
115
+ expect(res1).toBeTruthy();
116
+ const res2 = checkPointInside(10, 10, [
117
+ { x: 0, y: 0 },
118
+ { x: 10, y: -10 },
119
+ { x: 20, y: 0 },
120
+ { x: 10, y: 5 }
121
+ ]);
122
+ expect(res2).toBeFalsy();
123
+ });
79
124
  });
@@ -27,22 +27,10 @@ export type BoxSelectInteractionCallbacks = {
27
27
  }, event: MouseEvent) => void) | boolean;
28
28
  };
29
29
  /**
30
- * Interaction handler for multi-selecting nodes and relationships.
31
- * When dragging, draws a box on the canvas and selects all
32
- * nodes and relationships that are inside the box.
30
+ * An interaction handler for multi-selecting nodes and relationships.
31
+ * When dragging the cursor, it draws a box on the scene and all nodes and relationships inside the box are selected.
33
32
  *
34
- * @example
35
- * ```js
36
- * import { BoxSelectInteraction } from '@neo4j-nvl/interaction-handlers'
37
- * import { NVL } from '@neo4j-nvl/base'
38
- *
39
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
40
- * const boxSelectInteraction = new BoxSelectInteraction(nvl)
41
- *
42
- * boxSelectInteraction.updateCallback('onBoxSelect', ({ nodes, rels }) => {
43
- * console.log('Selected elements:', nodes, rels)
44
- * })
45
- * ```
33
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_boxselectinteraction Box Select Interaction documentation page}.
46
34
  */
47
35
  export declare class BoxSelectInteraction extends BaseInteraction<BoxSelectInteractionCallbacks, BoxSelectInteractionOptions> {
48
36
  private mousePosition;
@@ -3,22 +3,10 @@ import { OverlayRenderer } from '../overlay-renderer/overlay-renderer';
3
3
  import { BaseInteraction } from './base';
4
4
  import { getCanvasPosition, getWorldPosition } from './utils';
5
5
  /**
6
- * Interaction handler for multi-selecting nodes and relationships.
7
- * When dragging, draws a box on the canvas and selects all
8
- * nodes and relationships that are inside the box.
6
+ * An interaction handler for multi-selecting nodes and relationships.
7
+ * When dragging the cursor, it draws a box on the scene and all nodes and relationships inside the box are selected.
9
8
  *
10
- * @example
11
- * ```js
12
- * import { BoxSelectInteraction } from '@neo4j-nvl/interaction-handlers'
13
- * import { NVL } from '@neo4j-nvl/base'
14
- *
15
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
16
- * const boxSelectInteraction = new BoxSelectInteraction(nvl)
17
- *
18
- * boxSelectInteraction.updateCallback('onBoxSelect', ({ nodes, rels }) => {
19
- * console.log('Selected elements:', nodes, rels)
20
- * })
21
- * ```
9
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_boxselectinteraction Box Select Interaction documentation page}.
22
10
  */
23
11
  export class BoxSelectInteraction extends BaseInteraction {
24
12
  mousePosition;
@@ -74,19 +74,9 @@ export type ClickInteractionCallbacks = {
74
74
  };
75
75
  /**
76
76
  * Click interaction handler that handles click, double click and right click events on
77
- * nodes, relationships and canvas.
77
+ * nodes, relationships, and the scene.
78
78
  *
79
- * @example
80
- * ```ts
81
- * import { ClickInteraction } from '@neo4j-nvl/interaction-handlers'
82
- * import { NVL } from '@neo4j-nvl/base'
83
- *
84
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
85
- * const clickInteraction = new ClickInteraction(nvl)
86
- * clickInteraction.updateCallback('onNodeClick', (node) => {
87
- * console.log('Node clicked', node)
88
- * })
89
- * ```
79
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_clickinteraction Click Interaction documentation page}.
90
80
  */
91
81
  export declare class ClickInteraction extends BaseInteraction<ClickInteractionCallbacks, ClickInteractionOptions> {
92
82
  private moved;
@@ -2,19 +2,9 @@ import { BaseInteraction } from './base';
2
2
  import { isDraggingMovement } from './utils';
3
3
  /**
4
4
  * Click interaction handler that handles click, double click and right click events on
5
- * nodes, relationships and canvas.
5
+ * nodes, relationships, and the scene.
6
6
  *
7
- * @example
8
- * ```ts
9
- * import { ClickInteraction } from '@neo4j-nvl/interaction-handlers'
10
- * import { NVL } from '@neo4j-nvl/base'
11
- *
12
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
13
- * const clickInteraction = new ClickInteraction(nvl)
14
- * clickInteraction.updateCallback('onNodeClick', (node) => {
15
- * console.log('Node clicked', node)
16
- * })
17
- * ```
7
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_clickinteraction Click Interaction documentation page}.
18
8
  */
19
9
  export class ClickInteraction extends BaseInteraction {
20
10
  moved;
@@ -24,22 +24,11 @@ export type DragNodeInteractionCallbacks = {
24
24
  onDragEnd?: ((nodes: Node[], evt: MouseEvent) => void) | boolean;
25
25
  };
26
26
  /**
27
- * Interaction handler for dragging nodes.
28
- * Dragging is achieved by clicking and dragging on the node.
29
- * @note When more than one node is selected, all selected nodes will be dragged.
27
+ * Interaction handler for dragging nodes,
28
+ * which is achieved by clicking and moving the node.
29
+ * When multiple nodes are selected, they are all dragged.
30
30
  *
31
- * @example
32
- * ```js
33
- * import { NVL } from '@neo4j-nvl/base'
34
- * import { DragNodeInteraction } from '@neo4j-nvl/interaction-handlers'
35
- *
36
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
37
- * const dragNodeInteraction = new DragNodeInteraction(nvl)
38
- *
39
- * dragNodeInteraction.updateCallback('onDrag', (nodes) => {
40
- * console.log('Dragged nodes:', nodes)
41
- * })
42
- * ```
31
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_dragnodeinteraction Drag Node Interaction documentation page}.
43
32
  */
44
33
  export declare class DragNodeInteraction extends BaseInteraction<DragNodeInteractionCallbacks, Record<string, never>> {
45
34
  private mousePosition;
@@ -2,22 +2,11 @@ import { NODE_EDGE_WIDTH } from '../constants';
2
2
  import { BaseInteraction } from './base';
3
3
  import { isDraggingMovement } from './utils';
4
4
  /**
5
- * Interaction handler for dragging nodes.
6
- * Dragging is achieved by clicking and dragging on the node.
7
- * @note When more than one node is selected, all selected nodes will be dragged.
5
+ * Interaction handler for dragging nodes,
6
+ * which is achieved by clicking and moving the node.
7
+ * When multiple nodes are selected, they are all dragged.
8
8
  *
9
- * @example
10
- * ```js
11
- * import { NVL } from '@neo4j-nvl/base'
12
- * import { DragNodeInteraction } from '@neo4j-nvl/interaction-handlers'
13
- *
14
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
15
- * const dragNodeInteraction = new DragNodeInteraction(nvl)
16
- *
17
- * dragNodeInteraction.updateCallback('onDrag', (nodes) => {
18
- * console.log('Dragged nodes:', nodes)
19
- * })
20
- * ```
9
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_dragnodeinteraction Drag Node Interaction documentation page}.
21
10
  */
22
11
  export class DragNodeInteraction extends BaseInteraction {
23
12
  mousePosition;
@@ -2,11 +2,11 @@ import type { NVL, Node, Relationship } from '@neo4j-nvl/base';
2
2
  import { BaseInteraction } from './base';
3
3
  /**
4
4
  * @internal
5
- * @experimental
6
5
  */
7
6
  export type DrawInteractionCallbacks = {
8
7
  onHoverNodeMargin?: ((hoveredNode: Node | null, evt: MouseEvent) => void) | boolean;
9
- onDrawEnd?: ((newRelationshipToAdd: Relationship | null, newTargetNodeToAdd: Node | null, event: MouseEvent) => void) | boolean;
8
+ onDrawEnded?: ((newRelationshipToAdd: Relationship | null, newTargetNodeToAdd: Node | null, event: MouseEvent) => void) | boolean;
9
+ onDrawStarted?: ((event: MouseEvent) => void) | boolean;
10
10
  };
11
11
  export type DrawInteractionOptions = {
12
12
  ghostGraphStyling?: {
@@ -16,7 +16,6 @@ export type DrawInteractionOptions = {
16
16
  };
17
17
  /**
18
18
  * @internal
19
- * @experimental
20
19
  */
21
20
  export declare class DrawInteraction extends BaseInteraction<DrawInteractionCallbacks, DrawInteractionOptions> {
22
21
  private isMoved;
@@ -14,7 +14,6 @@ const DefaultGhostGraphStyling = {
14
14
  };
15
15
  /**
16
16
  * @internal
17
- * @experimental
18
17
  */
19
18
  export class DrawInteraction extends BaseInteraction {
20
19
  isMoved;
@@ -242,6 +241,7 @@ export class DrawInteraction extends BaseInteraction {
242
241
  };
243
242
  this.setNewRegularRelationshipToNewTempTargetNode();
244
243
  this.nvlInstance.addAndUpdateElementsInGraph([this.newTempTargetNode], this.newTempRegularRelationshipToNewTempTargetNode ? [this.newTempRegularRelationshipToNewTempTargetNode] : []);
244
+ this.callCallbackIfRegistered('onDrawStarted', event);
245
245
  }
246
246
  else {
247
247
  this.mouseDownNode = undefined;
@@ -262,7 +262,7 @@ export class DrawInteraction extends BaseInteraction {
262
262
  }
263
263
  // Avoid relationship glitch.
264
264
  this.nvlInstance.addAndUpdateElementsInGraph(this.newTargetNodeToAdd ? [{ id: this.newTargetNodeToAdd.id }] : [], this.newRelationshipToAdd ? [this.newRelationshipToAdd] : []);
265
- this.callCallbackIfRegistered('onDrawEnd', this.newRelationshipToAdd, this.newTargetNodeToAdd, event);
265
+ this.callCallbackIfRegistered('onDrawEnded', this.newRelationshipToAdd, this.newTargetNodeToAdd, event);
266
266
  }
267
267
  this.newTempTargetNode = null;
268
268
  this.newTempRegularRelationshipToNewTempTargetNode = null;
@@ -19,7 +19,7 @@ export type HoverInteractionCallbacks = {
19
19
  * @param element - The node or relationship that was hovered
20
20
  * @param hitElements - All elements that were hit by the hover
21
21
  * @param event - The original mouse event
22
- * @note This callback is called every time the mouse moves,
22
+ * This callback is called every time the mouse moves,
23
23
  * even when no element is hovered or the current element is already hovered.
24
24
  */
25
25
  onHover?: ((element: Node | Relationship, hitElements: HitTargets, event: MouseEvent) => void) | boolean;
@@ -27,20 +27,7 @@ export type HoverInteractionCallbacks = {
27
27
  /**
28
28
  * Interaction handler for hovering nodes and relationships.
29
29
  *
30
- * @example
31
- * ```ts
32
- * import { NVL } from '@neo4j-nvl/base'
33
- * import { HoverInteraction } from '@neo4j-nvl/interaction-handlers'
34
- *
35
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
36
- * const hoverInteraction = new HoverInteraction(nvl)
37
- *
38
- * hoverInteraction.updateCallback('onHover', (element, hitElements, event) => {
39
- * console.log('Hovered element:', element)
40
- * console.log('Hit elements:', hitElements)
41
- * console.log('Mouse event:', event)
42
- * })
43
- * ```
30
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_hoverinteraction Hover Interaction documentation page}.
44
31
  */
45
32
  export declare class HoverInteraction extends BaseInteraction<HoverInteractionCallbacks, HoverInteractionOptions> {
46
33
  private currentHoveredElement;
@@ -2,20 +2,7 @@ import { BaseInteraction } from './base';
2
2
  /**
3
3
  * Interaction handler for hovering nodes and relationships.
4
4
  *
5
- * @example
6
- * ```ts
7
- * import { NVL } from '@neo4j-nvl/base'
8
- * import { HoverInteraction } from '@neo4j-nvl/interaction-handlers'
9
- *
10
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
11
- * const hoverInteraction = new HoverInteraction(nvl)
12
- *
13
- * hoverInteraction.updateCallback('onHover', (element, hitElements, event) => {
14
- * console.log('Hovered element:', element)
15
- * console.log('Hit elements:', hitElements)
16
- * console.log('Mouse event:', event)
17
- * })
18
- * ```
5
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_hoverinteraction Hover Interaction documentation page}.
19
6
  */
20
7
  export class HoverInteraction extends BaseInteraction {
21
8
  currentHoveredElement;
@@ -1,4 +1,4 @@
1
- import type { NVL, Node, Relationship } from '@neo4j-nvl/base';
1
+ import type { NVL, Node, Point, Relationship } from '@neo4j-nvl/base';
2
2
  import { BaseInteraction } from './base';
3
3
  /**
4
4
  * Options for the lasso interaction handler to customize its behavior.
@@ -27,22 +27,29 @@ export type LassoInteractionCallbacks = {
27
27
  }, event: MouseEvent) => void) | boolean;
28
28
  };
29
29
  /**
30
- * Interaction handler for selecting nodes and relationships by drawing a lasso around them.
31
- * When dragging, a line is drawn in the visualisation, and when selecting all nodes inside the drawn
32
- * area will be selected.
33
- *
34
- * @example
35
- * ```ts
36
- * import { NVL } from '@neo4j-nvl/base'
37
- * import { LassoInteraction } from '@neo4j-nvl/interaction-handlers'
38
- *
39
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
40
- * const lassoInteraction = new LassoInteraction(nvl)
30
+ * @internal
31
+ */
32
+ export type Coords = [number, number];
33
+ /**
34
+ * Checks if two lines defined by p1->p2 and p3->p4 are crossing.
35
+ * @internal
36
+ */
37
+ export declare const checkLinesCrossing: (p1: Coords, p2: Coords, p3: Coords, p4: Coords) => boolean;
38
+ /**
39
+ * Checks if any line segments in the polygon intersect.
40
+ * @internal
41
+ */
42
+ export declare const checkIntersection: (polygon: Coords[]) => boolean;
43
+ /**
44
+ * Checks if the point (x, y) is inside the polygon defined by vs.
45
+ * @internal
46
+ */
47
+ export declare const checkPointInside: (x: number, y: number, vs: Point[]) => boolean;
48
+ /**
49
+ * An interaction handler that lets you select nodes and relationships by drawing a lasso around them.
50
+ * When dragging, a line is drawn on the scene and all elements inside are selected.
41
51
  *
42
- * lassoInteraction.updateCallback('onLassoSelect', ({ nodes, rels }) => {
43
- * console.log('Selected elements:', nodes, rels)
44
- * })
45
- * ```
52
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_lassointeraction Lasso Interaction documentation page}.
46
53
  */
47
54
  export declare class LassoInteraction extends BaseInteraction<LassoInteractionCallbacks, LassoInteractionOptions> {
48
55
  private active;
@@ -5,22 +5,65 @@ import { getCanvasPosition, getWorldPosition } from './utils';
5
5
  const pointDist = 10;
6
6
  const shapeShowTime = 500;
7
7
  /**
8
- * Interaction handler for selecting nodes and relationships by drawing a lasso around them.
9
- * When dragging, a line is drawn in the visualisation, and when selecting all nodes inside the drawn
10
- * area will be selected.
11
- *
12
- * @example
13
- * ```ts
14
- * import { NVL } from '@neo4j-nvl/base'
15
- * import { LassoInteraction } from '@neo4j-nvl/interaction-handlers'
16
- *
17
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
18
- * const lassoInteraction = new LassoInteraction(nvl)
8
+ * Checks if two lines defined by p1->p2 and p3->p4 are crossing.
9
+ * @internal
10
+ */
11
+ export const checkLinesCrossing = (p1, p2, p3, p4) => {
12
+ const denom = (p4[1] - p3[1]) * (p2[0] - p1[0]) - (p4[0] - p3[0]) * (p2[1] - p1[1]);
13
+ if (denom === 0) {
14
+ // This means lines are parallell
15
+ return false;
16
+ }
17
+ const t1 = ((p1[1] - p3[1]) * (p4[0] - p3[0]) - (p1[0] - p3[0]) * (p4[1] - p3[1])) / denom;
18
+ const t2 = ((p3[0] - p1[0]) * (p2[1] - p1[1]) - (p3[1] - p1[1]) * (p2[0] - p1[0])) / denom;
19
+ return t1 > 0 && t1 < 1 && t2 > 0 && t2 < 1;
20
+ };
21
+ /**
22
+ * Checks if any line segments in the polygon intersect.
23
+ * @internal
24
+ */
25
+ export const checkIntersection = (polygon) => {
26
+ for (let i = 0; i < polygon.length - 1; i++) {
27
+ for (let j = i + 2; j < polygon.length - 1; j++) {
28
+ const line1p1 = polygon[i] ?? [0, 0];
29
+ const line1p2 = polygon[i + 1] ?? [0, 0];
30
+ const line2p1 = polygon[j] ?? [0, 0];
31
+ const line2p2 = polygon[j + 1] ?? [0, 0];
32
+ if (checkLinesCrossing(line1p1, line1p2, line2p1, line2p2)) {
33
+ return true;
34
+ }
35
+ }
36
+ }
37
+ return false;
38
+ };
39
+ /**
40
+ * Checks if the point (x, y) is inside the polygon defined by vs.
41
+ * @internal
42
+ */
43
+ export const checkPointInside = (x, y, vs) => {
44
+ // ray-casting algorithm based on
45
+ // https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
46
+ let isInside = false;
47
+ for (let i = 0, j = vs.length - 1; i < vs.length; j = i, i += 1) {
48
+ const vsI = vs[i];
49
+ const vsJ = vs[j];
50
+ if (vsI === undefined || vsJ === undefined) {
51
+ continue;
52
+ }
53
+ const { x: xi, y: yi } = vsI;
54
+ const { x: xj, y: yj } = vsJ;
55
+ const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
56
+ if (intersect) {
57
+ isInside = !isInside;
58
+ }
59
+ }
60
+ return isInside;
61
+ };
62
+ /**
63
+ * An interaction handler that lets you select nodes and relationships by drawing a lasso around them.
64
+ * When dragging, a line is drawn on the scene and all elements inside are selected.
19
65
  *
20
- * lassoInteraction.updateCallback('onLassoSelect', ({ nodes, rels }) => {
21
- * console.log('Selected elements:', nodes, rels)
22
- * })
23
- * ```
66
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_lassointeraction Lasso Interaction documentation page}.
24
67
  */
25
68
  export class LassoInteraction extends BaseInteraction {
26
69
  active;
@@ -70,25 +113,6 @@ export class LassoInteraction extends BaseInteraction {
70
113
  this.endLasso(event);
71
114
  };
72
115
  getLassoItems = (points) => {
73
- const inside = (x, y, vs) => {
74
- // ray-casting algorithm based on
75
- // https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
76
- let isInside = false;
77
- for (let i = 0, j = vs.length - 1; i < vs.length; j = i, i += 1) {
78
- const vsI = vs[i];
79
- const vsJ = vs[j];
80
- if (vsI === undefined || vsJ === undefined) {
81
- continue;
82
- }
83
- const { x: xi, y: yi } = vsI;
84
- const { x: xj, y: yj } = vsJ;
85
- const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
86
- if (intersect) {
87
- isInside = !isInside;
88
- }
89
- }
90
- return isInside;
91
- };
92
116
  const worldPoints = points.map((p) => getWorldPosition(this.nvlInstance, p));
93
117
  const nodePositions = this.nvlInstance.getNodePositions();
94
118
  const hitNodes = new Set();
@@ -96,7 +120,7 @@ export class LassoInteraction extends BaseInteraction {
96
120
  if (pos.x === undefined || pos.y === undefined || pos.id === undefined) {
97
121
  continue;
98
122
  }
99
- if (inside(pos.x, pos.y, worldPoints)) {
123
+ if (checkPointInside(pos.x, pos.y, worldPoints)) {
100
124
  hitNodes.add(pos.id);
101
125
  }
102
126
  }
@@ -119,7 +143,8 @@ export class LassoInteraction extends BaseInteraction {
119
143
  }
120
144
  this.active = false;
121
145
  const pointArrays = this.points.map((p) => [p.x, p.y]);
122
- const hull = concaveman(pointArrays, 3)
146
+ const hasCrossings = checkIntersection(pointArrays);
147
+ const hull = (hasCrossings ? concaveman(pointArrays, 2) : pointArrays)
123
148
  .map((p) => ({ x: p[0], y: p[1] }))
124
149
  .filter((point) => point.x !== undefined && point.y !== undefined);
125
150
  this.overlayRenderer.drawLasso(hull, false, true);
@@ -25,21 +25,9 @@ export type PanInteractionCallbacks = {
25
25
  }, event: MouseEvent) => void) | boolean;
26
26
  };
27
27
  /**
28
- * Interaction handler for panning the canvas.
29
- * Panning is achieved by clicking and dragging on the canvas.
28
+ * Interaction handler for panning the scene, which is achieved by clicking and moving the scene.
30
29
  *
31
- * @example
32
- * ```js
33
- * import { NVL } from '@neo4j-nvl/base'
34
- * import { PanInteraction } from '@neo4j-nvl/interaction-handlers'
35
- *
36
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
37
- * const panInteraction = new PanInteraction(nvl)
38
- *
39
- * panInteraction.updateCallback('onPan', (panning) => {
40
- * console.log('Panning:', panning)
41
- * })
42
- * ```
30
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_paninteraction Pan Interaction documentation page}.
43
31
  */
44
32
  export declare class PanInteraction extends BaseInteraction<PanInteractionCallbacks, PanInteractionOptions> {
45
33
  private mousePosition;
@@ -54,7 +42,7 @@ export declare class PanInteraction extends BaseInteraction<PanInteractionCallba
54
42
  * Updates which type of graph elements should hinder panning.
55
43
  * @param targets - The graph elements that should hinder panning
56
44
  * @param excludeNodeMargin - If true, the node margin will not hinder panning
57
- * @note By default, panning is hindered by nodes and relationships.
45
+ * By default, panning is hindered by nodes and relationships.
58
46
  *
59
47
  * @example
60
48
  * ```js
@@ -2,21 +2,9 @@ import { difference } from 'lodash';
2
2
  import { NODE_EDGE_WIDTH } from '../constants';
3
3
  import { BaseInteraction } from './base';
4
4
  /**
5
- * Interaction handler for panning the canvas.
6
- * Panning is achieved by clicking and dragging on the canvas.
5
+ * Interaction handler for panning the scene, which is achieved by clicking and moving the scene.
7
6
  *
8
- * @example
9
- * ```js
10
- * import { NVL } from '@neo4j-nvl/base'
11
- * import { PanInteraction } from '@neo4j-nvl/interaction-handlers'
12
- *
13
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
14
- * const panInteraction = new PanInteraction(nvl)
15
- *
16
- * panInteraction.updateCallback('onPan', (panning) => {
17
- * console.log('Panning:', panning)
18
- * })
19
- * ```
7
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_paninteraction Pan Interaction documentation page}.
20
8
  */
21
9
  export class PanInteraction extends BaseInteraction {
22
10
  mousePosition;
@@ -39,7 +27,7 @@ export class PanInteraction extends BaseInteraction {
39
27
  * Updates which type of graph elements should hinder panning.
40
28
  * @param targets - The graph elements that should hinder panning
41
29
  * @param excludeNodeMargin - If true, the node margin will not hinder panning
42
- * @note By default, panning is hindered by nodes and relationships.
30
+ * By default, panning is hindered by nodes and relationships.
43
31
  *
44
32
  * @example
45
33
  * ```js
@@ -12,21 +12,9 @@ export type ZoomInteractionCallbacks = {
12
12
  onZoom?: ((zoomLevel: number, event: WheelEvent) => void) | boolean;
13
13
  };
14
14
  /**
15
- * Interaction handler for zooming the canvas.
16
- * Zooming is achieved by scrolling the mouse wheel on the canvas.
15
+ * Interaction handler for zooming the canvas, which is achieved by scrolling the mouse wheel on the canvas.
17
16
  *
18
- * @example
19
- * ```js
20
- * import { NVL } from '@neo4j-nvl/base'
21
- * import { ZoomInteraction } from '@neo4j-nvl/interaction-handlers'
22
- *
23
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
24
- * const zoomInteraction = new ZoomInteraction(nvl)
25
- *
26
- * zoomInteraction.updateCallback('onZoom', (zoomLevel) => {
27
- * console.log('Zoom level:', zoomLevel)
28
- * })
29
- * ```
17
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_zoominteraction Zoom Interaction documentation page}.
30
18
  */
31
19
  export declare class ZoomInteraction extends BaseInteraction<ZoomInteractionCallbacks, Record<string, never>> {
32
20
  /**
@@ -37,13 +25,13 @@ export declare class ZoomInteraction extends BaseInteraction<ZoomInteractionCall
37
25
  /**
38
26
  * Throttled zoom function to avoid events happening too fast.
39
27
  * @param event - The original mouse wheel event
40
- * @note "Wheel" with a touchpad, the wheel is triggered event a lot,
28
+ * "Wheel" with a touchpad, the wheel is triggered event a lot,
41
29
  * especially a lot of very small values.
42
30
  * However, updating values in NVL instance takes time.
43
31
  * Sometimes it lost the track of multiple events happening too soon.
44
32
  * As a result, the zoom might lose its anchor point under touch pad.
45
33
  * Therefore, the throttle is needed to avoid events happening too fast.
46
- * @note The throttle is set to 25ms.
34
+ * The throttle is set to 25ms.
47
35
  */
48
36
  private throttledZoom;
49
37
  private handleWheel;
@@ -2,21 +2,9 @@ import { throttle } from 'lodash';
2
2
  import { BaseInteraction } from './base';
3
3
  import { getCanvasCenterOffset } from './utils';
4
4
  /**
5
- * Interaction handler for zooming the canvas.
6
- * Zooming is achieved by scrolling the mouse wheel on the canvas.
5
+ * Interaction handler for zooming the canvas, which is achieved by scrolling the mouse wheel on the canvas.
7
6
  *
8
- * @example
9
- * ```js
10
- * import { NVL } from '@neo4j-nvl/base'
11
- * import { ZoomInteraction } from '@neo4j-nvl/interaction-handlers'
12
- *
13
- * const nvl = new NVL(document.createElement('div'), [{ id: '0' }], [])
14
- * const zoomInteraction = new ZoomInteraction(nvl)
15
- *
16
- * zoomInteraction.updateCallback('onZoom', (zoomLevel) => {
17
- * console.log('Zoom level:', zoomLevel)
18
- * })
19
- * ```
7
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_zoominteraction Zoom Interaction documentation page}.
20
8
  */
21
9
  export class ZoomInteraction extends BaseInteraction {
22
10
  /**
@@ -30,13 +18,13 @@ export class ZoomInteraction extends BaseInteraction {
30
18
  /**
31
19
  * Throttled zoom function to avoid events happening too fast.
32
20
  * @param event - The original mouse wheel event
33
- * @note "Wheel" with a touchpad, the wheel is triggered event a lot,
21
+ * "Wheel" with a touchpad, the wheel is triggered event a lot,
34
22
  * especially a lot of very small values.
35
23
  * However, updating values in NVL instance takes time.
36
24
  * Sometimes it lost the track of multiple events happening too soon.
37
25
  * As a result, the zoom might lose its anchor point under touch pad.
38
26
  * Therefore, the throttle is needed to avoid events happening too fast.
39
- * @note The throttle is set to 25ms.
27
+ * The throttle is set to 25ms.
40
28
  */
41
29
  throttledZoom = throttle((event) => {
42
30
  const zoom = this.nvlInstance.getScale();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo4j-nvl/interaction-handlers",
3
- "version": "0.3.3",
3
+ "version": "0.3.4-b33c5deb",
4
4
  "license": "SEE LICENSE IN 'LICENSE.txt'",
5
5
  "homepage": "https://neo4j.com/docs/nvl/current/",
6
6
  "description": "Interaction handlers for the Neo4j Visualization Library",
@@ -26,14 +26,8 @@
26
26
  "postpack": "rm LICENSE.txt",
27
27
  "eslint": "eslint ./src/"
28
28
  },
29
- "typedoc": {
30
- "entryPoint": "./src/index.ts",
31
- "readmeFile": "./README.md",
32
- "displayName": "Interaction Handlers",
33
- "tsconfig": "./tsconfig.json"
34
- },
35
29
  "dependencies": {
36
- "@neo4j-nvl/base": "0.3.3",
30
+ "@neo4j-nvl/base": "0.3.4-b33c5deb",
37
31
  "concaveman": "^1.2.1",
38
32
  "lodash": "4.17.21"
39
33
  },
@@ -50,5 +44,6 @@
50
44
  "eslint": "*",
51
45
  "jest": "*",
52
46
  "typescript": "*"
53
- }
47
+ },
48
+ "stableVersion": "0.3.4"
54
49
  }