@neo4j-nvl/react 0.3.8-d30e7f77 → 0.3.8-d40957ab
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 +24 -0
- package/lib/__tests__/InteractiveNvlWrapper.test.js +65 -20
- package/lib/interactive-nvl-wrapper/InteractionHandlers.d.ts +10 -0
- package/lib/interactive-nvl-wrapper/InteractionHandlers.js +45 -0
- package/lib/interactive-nvl-wrapper/InteractiveNvlWrapper.js +22 -44
- package/lib/interactive-nvl-wrapper/hooks.js +4 -4
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to NVL will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
|
|
5
|
+
## [0.3.9] - 2025-07-23
|
|
6
|
+
|
|
7
|
+
The 0.3.9 release contains several fixes for NVL's interaction handler and adds a new method to NVL to directly extract image data from an NVL instance:
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* new export method for image data url called `.getImageDataUrl`
|
|
12
|
+
* new callback triggered when NVL is fully initialized called `onInitialization`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
* updated license agreement in `LICENSE.txt`.
|
|
17
|
+
* prevent zoom interaction handler to zoom in NVL when ctrl or meta key is pressed.
|
|
18
|
+
* improve handling of leaving NVL container while performing selection using the lasso and box interaction handlers.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
* fix error on onDragEnd callback.
|
|
23
|
+
* fix race condition when hovering over an element that is being dismissed.
|
|
24
|
+
* fix nodes moving on clicks.
|
|
25
|
+
* prevent crash when providing non-existent node ids to `.setNodePositions` method.
|
|
26
|
+
* fix slow zoom speed for touchpads in zoom interaction handler.
|
|
27
|
+
* Ensure interaction handlers in react component waits for NVL to be initialised first.
|
|
28
|
+
|
|
5
29
|
## [0.3.8] - 2025-03-18
|
|
6
30
|
|
|
7
31
|
This release contains a fix for the [NVL result transformer](https://neo4j.com/docs/api/nvl/current/functions/_neo4j_nvl_base.nvlResultTransformer.html).
|
|
@@ -2,38 +2,70 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import NVL, { HierarchicalLayoutType } from '@neo4j-nvl/base';
|
|
3
3
|
import { BoxSelectInteraction, ClickInteraction, DragNodeInteraction, DrawInteraction, HoverInteraction, LassoInteraction, PanInteraction, ZoomInteraction } from '@neo4j-nvl/interaction-handlers';
|
|
4
4
|
import '@testing-library/jest-dom';
|
|
5
|
-
import { render } from '@testing-library/react';
|
|
5
|
+
import { act, render } from '@testing-library/react';
|
|
6
6
|
import React, { createRef } from 'react';
|
|
7
7
|
import { InteractiveNvlWrapper } from '../interactive-nvl-wrapper/InteractiveNvlWrapper';
|
|
8
8
|
jest.mock('@neo4j-nvl/base');
|
|
9
9
|
jest.mock('@neo4j-nvl/layout-workers');
|
|
10
10
|
jest.mock('@neo4j-nvl/interaction-handlers');
|
|
11
|
+
let mockOnInitialization;
|
|
11
12
|
HoverInteraction.prototype.callbackMap = new Map();
|
|
12
13
|
PanInteraction.prototype.callbackMap = new Map();
|
|
14
|
+
let mockDestroy;
|
|
15
|
+
let destroyHoverInteraction;
|
|
16
|
+
let destroyPanInteraction;
|
|
13
17
|
describe('InteractiveNvlWrapper', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
jest.spyOn(NVL.prototype, 'getContainer').mockImplementation(() => document.createElement('div'));
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
21
|
+
// @ts-expect-error
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
23
|
+
NVL.mockImplementation((_container, _nodes, _rels, _options, callbacks) => {
|
|
24
|
+
mockOnInitialization = callbacks.onInitialization;
|
|
25
|
+
return {
|
|
26
|
+
getContainer: () => document.createElement('div'),
|
|
27
|
+
destroy: mockDestroy,
|
|
28
|
+
setLayout: jest.fn(),
|
|
29
|
+
setLayoutOptions: jest.fn(),
|
|
30
|
+
setRenderer: jest.fn()
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
mockDestroy = jest.fn();
|
|
34
|
+
destroyHoverInteraction = jest.fn();
|
|
35
|
+
destroyPanInteraction = jest.fn();
|
|
36
|
+
jest.spyOn(NVL.prototype, 'destroy').mockImplementation(mockDestroy);
|
|
37
|
+
jest.spyOn(HoverInteraction.prototype, 'destroy').mockImplementation(destroyHoverInteraction);
|
|
38
|
+
jest.spyOn(PanInteraction.prototype, 'destroy').mockImplementation(destroyPanInteraction);
|
|
39
|
+
});
|
|
14
40
|
afterEach(() => {
|
|
15
41
|
jest.clearAllMocks();
|
|
16
42
|
});
|
|
17
43
|
test('initialises NVL expectedly with an empty graph object and no other properties', () => {
|
|
18
44
|
render(_jsx("div", { children: _jsx(InteractiveNvlWrapper, { nodes: [], rels: [] }) }));
|
|
19
|
-
expect(NVL).toHaveBeenCalledWith(expect.any(HTMLDivElement), [], [], {}, {});
|
|
45
|
+
expect(NVL).toHaveBeenCalledWith(expect.any(HTMLDivElement), [], [], {}, { onInitialization: expect.any(Function) });
|
|
20
46
|
});
|
|
21
47
|
test('initialises NVL expectedly with a graph object and properties', () => {
|
|
22
48
|
const mockLayoutDoneFunction = jest.fn();
|
|
23
49
|
render(_jsx(InteractiveNvlWrapper, { nodes: [{ id: '1' }, { id: '2' }], rels: [{ id: '12', from: '1', to: '2' }], layout: HierarchicalLayoutType, layoutOptions: { enableCytoscape: true }, nvlOptions: { renderer: 'canvas' }, nvlCallbacks: { onLayoutDone: mockLayoutDoneFunction } }));
|
|
50
|
+
act(() => {
|
|
51
|
+
mockOnInitialization?.();
|
|
52
|
+
});
|
|
24
53
|
expect(NVL).toHaveBeenCalledWith(expect.any(HTMLDivElement), [{ id: '1' }, { id: '2' }], [{ id: '12', from: '1', to: '2' }], { renderer: 'canvas', layout: HierarchicalLayoutType, layoutOptions: { enableCytoscape: true } }, {
|
|
25
|
-
onLayoutDone: mockLayoutDoneFunction
|
|
54
|
+
onLayoutDone: mockLayoutDoneFunction,
|
|
55
|
+
onInitialization: expect.any(Function)
|
|
26
56
|
});
|
|
27
57
|
});
|
|
28
58
|
test('initialises expected interaction handlers with correct options', () => {
|
|
29
59
|
const myNvlRef = createRef();
|
|
30
|
-
jest.spyOn(NVL.prototype, 'getContainer').mockImplementation(() => document.createElement('div'));
|
|
31
60
|
render(_jsx(InteractiveNvlWrapper, { nodes: [], rels: [], ref: myNvlRef, mouseEventCallbacks: {
|
|
32
61
|
onHover: true,
|
|
33
62
|
onPan: true
|
|
34
63
|
}, interactionOptions: {
|
|
35
64
|
drawShadowOnHover: true
|
|
36
65
|
} }));
|
|
66
|
+
act(() => {
|
|
67
|
+
mockOnInitialization?.();
|
|
68
|
+
});
|
|
37
69
|
expect(HoverInteraction).toHaveBeenCalledWith(myNvlRef.current, { drawShadowOnHover: true });
|
|
38
70
|
expect(PanInteraction).toHaveBeenCalledWith(myNvlRef.current, { drawShadowOnHover: true });
|
|
39
71
|
expect(HoverInteraction).toHaveBeenCalledTimes(1);
|
|
@@ -45,40 +77,45 @@ describe('InteractiveNvlWrapper', () => {
|
|
|
45
77
|
expect(BoxSelectInteraction).not.toHaveBeenCalled();
|
|
46
78
|
expect(LassoInteraction).not.toHaveBeenCalled();
|
|
47
79
|
});
|
|
80
|
+
test('does not attempt to initialize interaction handlers if NVL container is not available', () => {
|
|
81
|
+
const myNvlRef = createRef();
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
83
|
+
// @ts-expect-error
|
|
84
|
+
jest.spyOn(NVL.prototype, 'getContainer').mockImplementation(() => null);
|
|
85
|
+
render(_jsx(InteractiveNvlWrapper, { nodes: [], rels: [], ref: myNvlRef, mouseEventCallbacks: {
|
|
86
|
+
onHover: true
|
|
87
|
+
}, interactionOptions: {
|
|
88
|
+
drawShadowOnHover: true
|
|
89
|
+
} }));
|
|
90
|
+
expect(HoverInteraction).not.toHaveBeenCalled();
|
|
91
|
+
expect(NVL).toHaveBeenCalledTimes(1);
|
|
92
|
+
});
|
|
48
93
|
test('destroys NVL and active interaction handlers on unmount', () => {
|
|
49
|
-
const destroy = jest.fn();
|
|
50
|
-
jest.spyOn(NVL.prototype, 'destroy').mockImplementation(destroy);
|
|
51
|
-
const destroyHoverInteraction = jest.fn();
|
|
52
|
-
jest.spyOn(HoverInteraction.prototype, 'destroy').mockImplementation(destroyHoverInteraction);
|
|
53
|
-
const destroyPanInteraction = jest.fn();
|
|
54
|
-
jest.spyOn(PanInteraction.prototype, 'destroy').mockImplementation(destroyPanInteraction);
|
|
55
|
-
jest.spyOn(NVL.prototype, 'getContainer').mockImplementation(() => document.createElement('div'));
|
|
56
94
|
const { unmount } = render(_jsx(InteractiveNvlWrapper, { nodes: [], rels: [], mouseEventCallbacks: {
|
|
57
95
|
onHover: true
|
|
58
96
|
} }));
|
|
97
|
+
act(() => {
|
|
98
|
+
mockOnInitialization?.();
|
|
99
|
+
});
|
|
59
100
|
unmount();
|
|
60
|
-
expect(
|
|
101
|
+
expect(mockDestroy).toHaveBeenCalledTimes(1);
|
|
61
102
|
expect(destroyHoverInteraction).toHaveBeenCalledTimes(1);
|
|
62
103
|
expect(destroyPanInteraction).not.toHaveBeenCalled();
|
|
63
104
|
});
|
|
64
105
|
test('successfully re-initialises NVL and active interaction handlers when using React StrictMode', () => {
|
|
65
|
-
const destroy = jest.fn();
|
|
66
|
-
jest.spyOn(NVL.prototype, 'destroy').mockImplementation(destroy);
|
|
67
|
-
const destroyHoverInteraction = jest.fn();
|
|
68
|
-
jest.spyOn(HoverInteraction.prototype, 'destroy').mockImplementation(destroyHoverInteraction);
|
|
69
|
-
const destroyPanInteraction = jest.fn();
|
|
70
|
-
jest.spyOn(PanInteraction.prototype, 'destroy').mockImplementation(destroyPanInteraction);
|
|
71
|
-
jest.spyOn(NVL.prototype, 'getContainer').mockImplementation(() => document.createElement('div'));
|
|
72
106
|
const myNvlRef = createRef();
|
|
73
107
|
render(_jsx(React.StrictMode, { children: _jsx(InteractiveNvlWrapper, { nodes: [], rels: [], ref: myNvlRef, mouseEventCallbacks: {
|
|
74
108
|
onHover: true
|
|
75
109
|
}, interactionOptions: {
|
|
76
110
|
drawShadowOnHover: true
|
|
77
111
|
} }) }));
|
|
112
|
+
act(() => {
|
|
113
|
+
mockOnInitialization?.();
|
|
114
|
+
});
|
|
78
115
|
expect(NVL).toHaveBeenCalledTimes(2);
|
|
79
116
|
expect(HoverInteraction).toHaveBeenCalledTimes(2);
|
|
80
117
|
expect(HoverInteraction).toHaveBeenCalledWith(myNvlRef.current, { drawShadowOnHover: true });
|
|
81
|
-
expect(
|
|
118
|
+
expect(mockDestroy).toHaveBeenCalledTimes(1);
|
|
82
119
|
expect(destroyHoverInteraction).toHaveBeenCalledTimes(1);
|
|
83
120
|
expect(destroyPanInteraction).not.toHaveBeenCalled();
|
|
84
121
|
expect(DragNodeInteraction).not.toHaveBeenCalled();
|
|
@@ -87,4 +124,12 @@ describe('InteractiveNvlWrapper', () => {
|
|
|
87
124
|
expect(BoxSelectInteraction).not.toHaveBeenCalled();
|
|
88
125
|
expect(LassoInteraction).not.toHaveBeenCalled();
|
|
89
126
|
});
|
|
127
|
+
test('also calls custom callbacks on initialization', () => {
|
|
128
|
+
const customOnInitializationCallback = jest.fn();
|
|
129
|
+
render(_jsx(InteractiveNvlWrapper, { nodes: [], rels: [], nvlCallbacks: { onInitialization: customOnInitializationCallback } }));
|
|
130
|
+
act(() => {
|
|
131
|
+
mockOnInitialization?.();
|
|
132
|
+
});
|
|
133
|
+
expect(customOnInitializationCallback).toHaveBeenCalledTimes(1);
|
|
134
|
+
});
|
|
90
135
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type NVL from '@neo4j-nvl/base';
|
|
2
|
+
import type { MutableRefObject } from 'react';
|
|
3
|
+
import type { InteractionOptions, MouseEventCallbacks } from './types';
|
|
4
|
+
interface InteractionHandlersProps {
|
|
5
|
+
nvlRef: MutableRefObject<NVL | null>;
|
|
6
|
+
mouseEventCallbacks: MouseEventCallbacks;
|
|
7
|
+
interactionOptions: InteractionOptions;
|
|
8
|
+
}
|
|
9
|
+
export declare const InteractionHandlers: React.FC<InteractionHandlersProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BoxSelectInteraction, ClickInteraction, DragNodeInteraction, DrawInteraction, HoverInteraction, LassoInteraction, PanInteraction, ZoomInteraction } from '@neo4j-nvl/interaction-handlers';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { destroyInteraction, useInteraction } from './hooks';
|
|
4
|
+
export const InteractionHandlers = ({ nvlRef, mouseEventCallbacks, interactionOptions }) => {
|
|
5
|
+
const hoverInteraction = useRef(null);
|
|
6
|
+
const clickInteraction = useRef(null);
|
|
7
|
+
const panInteraction = useRef(null);
|
|
8
|
+
const zoomInteraction = useRef(null);
|
|
9
|
+
const dragNodeInteraction = useRef(null);
|
|
10
|
+
const drawInteraction = useRef(null);
|
|
11
|
+
const multiSelectInteraction = useRef(null);
|
|
12
|
+
const lassoInteraction = useRef(null);
|
|
13
|
+
useInteraction(HoverInteraction, hoverInteraction, mouseEventCallbacks.onHover, 'onHover', nvlRef, interactionOptions);
|
|
14
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onNodeClick, 'onNodeClick', nvlRef, interactionOptions);
|
|
15
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onNodeDoubleClick, 'onNodeDoubleClick', nvlRef, interactionOptions);
|
|
16
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onNodeRightClick, 'onNodeRightClick', nvlRef, interactionOptions);
|
|
17
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onRelationshipClick, 'onRelationshipClick', nvlRef, interactionOptions);
|
|
18
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onRelationshipDoubleClick, 'onRelationshipDoubleClick', nvlRef, interactionOptions);
|
|
19
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onRelationshipRightClick, 'onRelationshipRightClick', nvlRef, interactionOptions);
|
|
20
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onCanvasClick, 'onCanvasClick', nvlRef, interactionOptions);
|
|
21
|
+
useInteraction(ClickInteraction, clickInteraction, mouseEventCallbacks.onCanvasRightClick, 'onCanvasRightClick', nvlRef, interactionOptions);
|
|
22
|
+
useInteraction(PanInteraction, panInteraction, mouseEventCallbacks.onPan, 'onPan', nvlRef, interactionOptions);
|
|
23
|
+
useInteraction(ZoomInteraction, zoomInteraction, mouseEventCallbacks.onZoom, 'onZoom', nvlRef, interactionOptions);
|
|
24
|
+
useInteraction(DragNodeInteraction, dragNodeInteraction, mouseEventCallbacks.onDrag, 'onDrag', nvlRef, interactionOptions);
|
|
25
|
+
useInteraction(DragNodeInteraction, dragNodeInteraction, mouseEventCallbacks.onDragStart, 'onDragStart', nvlRef, interactionOptions);
|
|
26
|
+
useInteraction(DragNodeInteraction, dragNodeInteraction, mouseEventCallbacks.onDragEnd, 'onDragEnd', nvlRef, interactionOptions);
|
|
27
|
+
useInteraction(DrawInteraction, drawInteraction, mouseEventCallbacks.onHoverNodeMargin, 'onHoverNodeMargin', nvlRef, interactionOptions);
|
|
28
|
+
useInteraction(DrawInteraction, drawInteraction, mouseEventCallbacks.onDrawStarted, 'onDrawStarted', nvlRef, interactionOptions);
|
|
29
|
+
useInteraction(DrawInteraction, drawInteraction, mouseEventCallbacks.onDrawEnded, 'onDrawEnded', nvlRef, interactionOptions);
|
|
30
|
+
useInteraction(BoxSelectInteraction, multiSelectInteraction, mouseEventCallbacks.onBoxStarted, 'onBoxStarted', nvlRef, interactionOptions);
|
|
31
|
+
useInteraction(BoxSelectInteraction, multiSelectInteraction, mouseEventCallbacks.onBoxSelect, 'onBoxSelect', nvlRef, interactionOptions);
|
|
32
|
+
useInteraction(LassoInteraction, lassoInteraction, mouseEventCallbacks.onLassoStarted, 'onLassoStarted', nvlRef, interactionOptions);
|
|
33
|
+
useInteraction(LassoInteraction, lassoInteraction, mouseEventCallbacks.onLassoSelect, 'onLassoSelect', nvlRef, interactionOptions);
|
|
34
|
+
useEffect(() => () => {
|
|
35
|
+
destroyInteraction(hoverInteraction);
|
|
36
|
+
destroyInteraction(clickInteraction);
|
|
37
|
+
destroyInteraction(panInteraction);
|
|
38
|
+
destroyInteraction(zoomInteraction);
|
|
39
|
+
destroyInteraction(dragNodeInteraction);
|
|
40
|
+
destroyInteraction(drawInteraction);
|
|
41
|
+
destroyInteraction(multiSelectInteraction);
|
|
42
|
+
destroyInteraction(lassoInteraction);
|
|
43
|
+
}, []);
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import { forwardRef, memo, useEffect, useRef } from 'react';
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, memo, useCallback, useRef, useState } from 'react';
|
|
4
3
|
import { BasicNvlWrapper } from '../basic-wrapper/BasicNvlWrapper';
|
|
5
4
|
import { INTERACTIVE_WRAPPER_ID } from '../utils/constants';
|
|
6
|
-
import {
|
|
5
|
+
import { InteractionHandlers } from './InteractionHandlers';
|
|
7
6
|
const options = {
|
|
8
7
|
selectOnClick: false,
|
|
9
8
|
drawShadowOnHover: true,
|
|
@@ -24,45 +23,24 @@ const options = {
|
|
|
24
23
|
export const InteractiveNvlWrapper = memo(forwardRef(({ nodes, rels, layout, layoutOptions, onInitializationError, mouseEventCallbacks = {}, nvlCallbacks = {}, nvlOptions = {}, interactionOptions = options, ...nvlEvents }, nvlRef) => {
|
|
25
24
|
const newNvlRef = useRef(null);
|
|
26
25
|
const myNvlRef = nvlRef ?? newNvlRef;
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const panInteraction = useRef(null);
|
|
31
|
-
const zoomInteraction = useRef(null);
|
|
32
|
-
const dragNodeInteraction = useRef(null);
|
|
33
|
-
const drawInteraction = useRef(null);
|
|
34
|
-
const multiSelectInteraction = useRef(null);
|
|
35
|
-
const lassoInteraction = useRef(null);
|
|
36
|
-
useInteraction(HoverInteraction, hoverInteraction, onHover, 'onHover', myNvlRef, interactionOptions);
|
|
37
|
-
useInteraction(ClickInteraction, clickInteraction, onNodeClick, 'onNodeClick', myNvlRef, interactionOptions);
|
|
38
|
-
useInteraction(ClickInteraction, clickInteraction, onNodeDoubleClick, 'onNodeDoubleClick', myNvlRef, interactionOptions);
|
|
39
|
-
useInteraction(ClickInteraction, clickInteraction, onNodeRightClick, 'onNodeRightClick', myNvlRef, interactionOptions);
|
|
40
|
-
useInteraction(ClickInteraction, clickInteraction, onRelationshipClick, 'onRelationshipClick', myNvlRef, interactionOptions);
|
|
41
|
-
useInteraction(ClickInteraction, clickInteraction, onRelationshipDoubleClick, 'onRelationshipDoubleClick', myNvlRef, interactionOptions);
|
|
42
|
-
useInteraction(ClickInteraction, clickInteraction, onRelationshipRightClick, 'onRelationshipRightClick', myNvlRef, interactionOptions);
|
|
43
|
-
useInteraction(ClickInteraction, clickInteraction, onCanvasClick, 'onCanvasClick', myNvlRef, interactionOptions);
|
|
44
|
-
useInteraction(ClickInteraction, clickInteraction, onCanvasRightClick, 'onCanvasRightClick', myNvlRef, interactionOptions);
|
|
45
|
-
useInteraction(PanInteraction, panInteraction, onPan, 'onPan', myNvlRef, interactionOptions);
|
|
46
|
-
useInteraction(ZoomInteraction, zoomInteraction, onZoom, 'onZoom', myNvlRef, interactionOptions);
|
|
47
|
-
useInteraction(DragNodeInteraction, dragNodeInteraction, onDrag, 'onDrag', myNvlRef, interactionOptions);
|
|
48
|
-
useInteraction(DragNodeInteraction, dragNodeInteraction, onDragStart, 'onDragStart', myNvlRef, interactionOptions);
|
|
49
|
-
useInteraction(DragNodeInteraction, dragNodeInteraction, onDragEnd, 'onDragEnd', myNvlRef, interactionOptions);
|
|
50
|
-
useInteraction(DrawInteraction, drawInteraction, onHoverNodeMargin, 'onHoverNodeMargin', myNvlRef, interactionOptions);
|
|
51
|
-
useInteraction(DrawInteraction, drawInteraction, onDrawStarted, 'onDrawStarted', myNvlRef, interactionOptions);
|
|
52
|
-
useInteraction(DrawInteraction, drawInteraction, onDrawEnded, 'onDrawEnded', myNvlRef, interactionOptions);
|
|
53
|
-
useInteraction(BoxSelectInteraction, multiSelectInteraction, onBoxStarted, 'onBoxStarted', myNvlRef, interactionOptions);
|
|
54
|
-
useInteraction(BoxSelectInteraction, multiSelectInteraction, onBoxSelect, 'onBoxSelect', myNvlRef, interactionOptions);
|
|
55
|
-
useInteraction(LassoInteraction, lassoInteraction, onLassoStarted, 'onLassoStarted', myNvlRef, interactionOptions);
|
|
56
|
-
useInteraction(LassoInteraction, lassoInteraction, onLassoSelect, 'onLassoSelect', myNvlRef, interactionOptions);
|
|
57
|
-
useEffect(() => () => {
|
|
58
|
-
destroyInteraction(hoverInteraction);
|
|
59
|
-
destroyInteraction(clickInteraction);
|
|
60
|
-
destroyInteraction(panInteraction);
|
|
61
|
-
destroyInteraction(zoomInteraction);
|
|
62
|
-
destroyInteraction(dragNodeInteraction);
|
|
63
|
-
destroyInteraction(drawInteraction);
|
|
64
|
-
destroyInteraction(multiSelectInteraction);
|
|
65
|
-
destroyInteraction(lassoInteraction);
|
|
26
|
+
const [isNvlInitialized, setIsNvlInitialized] = useState(false);
|
|
27
|
+
const handleInitialization = useCallback(() => {
|
|
28
|
+
setIsNvlInitialized(true);
|
|
66
29
|
}, []);
|
|
67
|
-
|
|
30
|
+
const handleInitializationError = useCallback((error) => {
|
|
31
|
+
setIsNvlInitialized(false);
|
|
32
|
+
if (onInitializationError) {
|
|
33
|
+
onInitializationError(error);
|
|
34
|
+
}
|
|
35
|
+
}, [onInitializationError]);
|
|
36
|
+
const setupInteractions = isNvlInitialized && myNvlRef.current !== null;
|
|
37
|
+
return (_jsxs(_Fragment, { children: [_jsx(BasicNvlWrapper, { ref: myNvlRef, nodes: nodes, id: INTERACTIVE_WRAPPER_ID, rels: rels, nvlOptions: nvlOptions, nvlCallbacks: {
|
|
38
|
+
...nvlCallbacks,
|
|
39
|
+
onInitialization: () => {
|
|
40
|
+
if (nvlCallbacks.onInitialization !== undefined) {
|
|
41
|
+
nvlCallbacks.onInitialization();
|
|
42
|
+
}
|
|
43
|
+
handleInitialization();
|
|
44
|
+
}
|
|
45
|
+
}, layout: layout, layoutOptions: layoutOptions, onInitializationError: handleInitializationError, ...nvlEvents }), setupInteractions && (_jsx(InteractionHandlers, { nvlRef: myNvlRef, mouseEventCallbacks: mouseEventCallbacks, interactionOptions: interactionOptions }))] }));
|
|
68
46
|
}));
|
|
@@ -6,14 +6,14 @@ export const destroyInteraction = (interactionRef) => {
|
|
|
6
6
|
};
|
|
7
7
|
export const useInteraction = (Interaction, interactionRef, callback, eventName, nvlRef, interactionOptions) => {
|
|
8
8
|
useEffect(() => {
|
|
9
|
-
const
|
|
9
|
+
const nvl = nvlRef.current;
|
|
10
10
|
// Make sure we are not mounting interaction handlers when there is NVL setup
|
|
11
|
-
if (isNil(
|
|
11
|
+
if (isNil(nvl) || isNil(nvl.getContainer())) {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
if (
|
|
14
|
+
if (callback === true || typeof callback === 'function') {
|
|
15
15
|
if (isNil(interactionRef.current)) {
|
|
16
|
-
interactionRef.current = new Interaction(
|
|
16
|
+
interactionRef.current = new Interaction(nvl, interactionOptions);
|
|
17
17
|
}
|
|
18
18
|
if (typeof callback === 'function') {
|
|
19
19
|
interactionRef.current.updateCallback(eventName, callback);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neo4j-nvl/react",
|
|
3
|
-
"version": "0.3.8-
|
|
3
|
+
"version": "0.3.8-d40957ab",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"homepage": "https://neo4j.com/docs/nvl/current/",
|
|
6
6
|
"license": "SEE LICENSE IN 'LICENSE.txt'",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"@testing-library/jest-dom": "^5.16.5",
|
|
31
31
|
"@testing-library/react": "^13.4.0",
|
|
32
32
|
"@types/lodash": "4.14.202",
|
|
33
|
-
"@types/react": "18.2.58",
|
|
33
|
+
"@types/react": "^18.2.58",
|
|
34
34
|
"babel-eslint": "^10.1.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@neo4j-nvl/base": "0.3.8-
|
|
38
|
-
"@neo4j-nvl/interaction-handlers": "0.3.8-
|
|
37
|
+
"@neo4j-nvl/base": "0.3.8-d40957ab",
|
|
38
|
+
"@neo4j-nvl/interaction-handlers": "0.3.8-d40957ab",
|
|
39
39
|
"lodash": "4.17.21",
|
|
40
40
|
"react": "^18.2.0",
|
|
41
41
|
"react-dom": "^18.2.0"
|