@neo4j-nvl/interaction-handlers 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/README.md +8 -0
- package/lib/constants.d.ts +1 -1
- package/lib/constants.js +4 -2
- package/lib/index.d.ts +10 -20
- package/lib/index.js +10 -10
- package/lib/interaction-handlers/base.d.ts +67 -67
- package/lib/interaction-handlers/base.js +98 -104
- package/lib/interaction-handlers/box-select-interaction.d.ts +44 -44
- package/lib/interaction-handlers/box-select-interaction.js +133 -127
- package/lib/interaction-handlers/click-interaction.d.ts +111 -111
- package/lib/interaction-handlers/click-interaction.js +116 -131
- package/lib/interaction-handlers/drag-node-interaction.d.ts +40 -40
- package/lib/interaction-handlers/drag-node-interaction.js +102 -111
- package/lib/interaction-handlers/draw-interaction.d.ts +37 -37
- package/lib/interaction-handlers/draw-interaction.js +245 -278
- package/lib/interaction-handlers/hover-interaction.d.ts +34 -30
- package/lib/interaction-handlers/hover-interaction.js +83 -89
- package/lib/interaction-handlers/keyboard-interaction.d.ts +149 -97
- package/lib/interaction-handlers/keyboard-interaction.js +255 -201
- package/lib/interaction-handlers/lasso-interaction.d.ts +45 -45
- package/lib/interaction-handlers/lasso-interaction.js +174 -196
- package/lib/interaction-handlers/pan-interaction.d.ts +62 -61
- package/lib/interaction-handlers/pan-interaction.js +111 -100
- package/lib/interaction-handlers/utils.d.ts +2 -2
- package/lib/interaction-handlers/utils.js +39 -38
- package/lib/interaction-handlers/zoom-interaction.d.ts +52 -48
- package/lib/interaction-handlers/zoom-interaction.js +73 -71
- package/lib/overlay-renderer/overlay-renderer.d.ts +13 -13
- package/lib/overlay-renderer/overlay-renderer.js +96 -111
- package/package.json +19 -6
- package/lib/__tests__/box-select-interaction.test.d.ts +0 -1
- package/lib/__tests__/box-select-interaction.test.js +0 -149
- package/lib/__tests__/click-interaction.test.d.ts +0 -1
- package/lib/__tests__/click-interaction.test.js +0 -505
- package/lib/__tests__/drag-node-interaction.test.d.ts +0 -1
- package/lib/__tests__/drag-node-interaction.test.js +0 -247
- package/lib/__tests__/hover-interaction.test.d.ts +0 -1
- package/lib/__tests__/hover-interaction.test.js +0 -374
- package/lib/__tests__/keyboard-interaction.test.d.ts +0 -1
- package/lib/__tests__/keyboard-interaction.test.js +0 -322
- package/lib/__tests__/lasso-interaction.test.d.ts +0 -1
- package/lib/__tests__/lasso-interaction.test.js +0 -219
- package/lib/__tests__/pan-interaction.test.d.ts +0 -1
- package/lib/__tests__/pan-interaction.test.js +0 -223
- package/lib/__tests__/utils.test.d.ts +0 -1
- package/lib/__tests__/utils.test.js +0 -19
- package/lib/__tests__/zoom-interaction.test.d.ts +0 -1
- package/lib/__tests__/zoom-interaction.test.js +0 -185
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import NVL from '@neo4j-nvl/base';
|
|
2
|
-
import '@testing-library/jest-dom';
|
|
3
|
-
import { PanInteraction } from '../interaction-handlers/pan-interaction';
|
|
4
|
-
jest.mock('@neo4j-nvl/layout-workers');
|
|
5
|
-
const waitForAnimationFrame = async () => {
|
|
6
|
-
await new Promise((resolve) => {
|
|
7
|
-
window.requestAnimationFrame(() => resolve());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
describe('PanInteraction', () => {
|
|
11
|
-
let panInteraction;
|
|
12
|
-
let myNVL;
|
|
13
|
-
const panCallbackMock = jest.fn();
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
myNVL = new NVL(document.createElement('div'), [
|
|
16
|
-
{ id: '0', x: 10, y: 10 },
|
|
17
|
-
{ id: '1', x: 200, y: 200 }
|
|
18
|
-
], [{ id: '10', from: '0', to: '1' }], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
19
|
-
panInteraction = new PanInteraction(myNVL);
|
|
20
|
-
});
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
panInteraction.destroy();
|
|
23
|
-
myNVL.destroy();
|
|
24
|
-
panCallbackMock.mockReset();
|
|
25
|
-
});
|
|
26
|
-
test('performing a simple pan operation should invoke the expected callback', async () => {
|
|
27
|
-
panInteraction.updateCallback('onPan', panCallbackMock);
|
|
28
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
29
|
-
clientX: 100,
|
|
30
|
-
clientY: 100
|
|
31
|
-
});
|
|
32
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
33
|
-
buttons: 1,
|
|
34
|
-
clientX: 120,
|
|
35
|
-
clientY: 120
|
|
36
|
-
});
|
|
37
|
-
const mouseUpEvent = new MouseEvent('mouseup', {
|
|
38
|
-
clientX: 120,
|
|
39
|
-
clientY: 120
|
|
40
|
-
});
|
|
41
|
-
const container = myNVL.getContainer();
|
|
42
|
-
const initialPan = myNVL.getPan();
|
|
43
|
-
container.dispatchEvent(mouseDownEvent);
|
|
44
|
-
await waitForAnimationFrame();
|
|
45
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
46
|
-
await waitForAnimationFrame();
|
|
47
|
-
container.dispatchEvent(mouseUpEvent);
|
|
48
|
-
expect(panCallbackMock).toHaveBeenCalledTimes(1);
|
|
49
|
-
expect(panCallbackMock).toHaveBeenCalledWith({
|
|
50
|
-
x: initialPan.x - 20,
|
|
51
|
-
y: initialPan.y - 20
|
|
52
|
-
}, mouseMoveEvent);
|
|
53
|
-
const newPan = myNVL.getPan();
|
|
54
|
-
expect(newPan).not.toEqual(initialPan);
|
|
55
|
-
});
|
|
56
|
-
test('panning should not work when clicking on nodes by default', () => {
|
|
57
|
-
panInteraction.updateCallback('onPan', panCallbackMock);
|
|
58
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
59
|
-
clientX: 10,
|
|
60
|
-
clientY: 10
|
|
61
|
-
});
|
|
62
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
63
|
-
buttons: 1,
|
|
64
|
-
clientX: 30,
|
|
65
|
-
clientY: 30
|
|
66
|
-
});
|
|
67
|
-
const container = myNVL.getContainer();
|
|
68
|
-
container.dispatchEvent(mouseDownEvent);
|
|
69
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
70
|
-
return new Promise((resolve) => {
|
|
71
|
-
expect(panCallbackMock).not.toHaveBeenCalled();
|
|
72
|
-
resolve();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
test('should update targets to allow panning on nodes', () => {
|
|
76
|
-
panInteraction.updateCallback('onPan', panCallbackMock);
|
|
77
|
-
panInteraction.updateTargets(['node'], false);
|
|
78
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
79
|
-
clientX: 10,
|
|
80
|
-
clientY: 10
|
|
81
|
-
});
|
|
82
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
83
|
-
buttons: 1,
|
|
84
|
-
clientX: 50,
|
|
85
|
-
clientY: 50
|
|
86
|
-
});
|
|
87
|
-
const container = myNVL.getContainer();
|
|
88
|
-
const initialPan = myNVL.getPan();
|
|
89
|
-
container.dispatchEvent(mouseDownEvent);
|
|
90
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
91
|
-
return new Promise((resolve) => {
|
|
92
|
-
expect(panCallbackMock).toHaveBeenCalledTimes(1);
|
|
93
|
-
expect(panCallbackMock).toHaveBeenCalledWith({
|
|
94
|
-
x: initialPan.x - 40,
|
|
95
|
-
y: initialPan.y - 40
|
|
96
|
-
}, mouseMoveEvent);
|
|
97
|
-
resolve();
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
test('panning outside the container should disable text selection until mouse release', () => {
|
|
101
|
-
panInteraction.updateCallback('onPan', panCallbackMock);
|
|
102
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
103
|
-
clientX: 100,
|
|
104
|
-
clientY: 100
|
|
105
|
-
});
|
|
106
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
107
|
-
buttons: 1,
|
|
108
|
-
clientX: 120,
|
|
109
|
-
clientY: 120
|
|
110
|
-
});
|
|
111
|
-
const bodyMouseUpEvent = new MouseEvent('mouseup');
|
|
112
|
-
const container = myNVL.getContainer();
|
|
113
|
-
container.dispatchEvent(mouseDownEvent);
|
|
114
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
115
|
-
expect(document.body.style.getPropertyValue('user-select')).toBe('none');
|
|
116
|
-
document.body.dispatchEvent(bodyMouseUpEvent);
|
|
117
|
-
expect(document.body.style.getPropertyValue('user-select')).toBe('');
|
|
118
|
-
});
|
|
119
|
-
test('when controlledPan is true, should not update NVL instance', () => {
|
|
120
|
-
panInteraction.destroy();
|
|
121
|
-
myNVL.destroy();
|
|
122
|
-
myNVL = new NVL(document.createElement('div'), [
|
|
123
|
-
{ id: '0', x: 10, y: 10 },
|
|
124
|
-
{ id: '1', x: 200, y: 200 }
|
|
125
|
-
], [{ id: '10', from: '0', to: '1' }], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
126
|
-
const panInteractionNoUpdate = new PanInteraction(myNVL, { controlledPan: true });
|
|
127
|
-
panInteractionNoUpdate.updateCallback('onPan', panCallbackMock);
|
|
128
|
-
const initialPan = myNVL.getPan();
|
|
129
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
130
|
-
clientX: 100,
|
|
131
|
-
clientY: 100
|
|
132
|
-
});
|
|
133
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
134
|
-
buttons: 1,
|
|
135
|
-
clientX: 120,
|
|
136
|
-
clientY: 120
|
|
137
|
-
});
|
|
138
|
-
const mouseUpEvent = new MouseEvent('mouseup', {
|
|
139
|
-
clientX: 120,
|
|
140
|
-
clientY: 120
|
|
141
|
-
});
|
|
142
|
-
const container = myNVL.getContainer();
|
|
143
|
-
container.dispatchEvent(mouseDownEvent);
|
|
144
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
145
|
-
container.dispatchEvent(mouseUpEvent);
|
|
146
|
-
return new Promise((resolve) => {
|
|
147
|
-
expect(myNVL.getPan()).toEqual(initialPan);
|
|
148
|
-
expect(panCallbackMock).toHaveBeenCalledTimes(1);
|
|
149
|
-
expect(panCallbackMock).toHaveBeenCalledWith({
|
|
150
|
-
x: initialPan.x - 20,
|
|
151
|
-
y: initialPan.y - 20
|
|
152
|
-
}, mouseMoveEvent);
|
|
153
|
-
panInteractionNoUpdate.destroy();
|
|
154
|
-
resolve();
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
test('when controlledPan is false, should update NVL instance normally', async () => {
|
|
158
|
-
panInteraction.destroy();
|
|
159
|
-
myNVL.destroy();
|
|
160
|
-
myNVL = new NVL(document.createElement('div'), [
|
|
161
|
-
{ id: '0', x: 10, y: 10 },
|
|
162
|
-
{ id: '1', x: 200, y: 200 }
|
|
163
|
-
], [{ id: '10', from: '0', to: '1' }], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
164
|
-
const panInteractionWithUpdate = new PanInteraction(myNVL, { controlledPan: false });
|
|
165
|
-
panInteractionWithUpdate.updateCallback('onPan', panCallbackMock);
|
|
166
|
-
const initialPan = myNVL.getPan();
|
|
167
|
-
const mouseDownEvent = new MouseEvent('mousedown', {
|
|
168
|
-
clientX: 100,
|
|
169
|
-
clientY: 100
|
|
170
|
-
});
|
|
171
|
-
const mouseMoveEvent = new MouseEvent('mousemove', {
|
|
172
|
-
buttons: 1,
|
|
173
|
-
clientX: 120,
|
|
174
|
-
clientY: 120
|
|
175
|
-
});
|
|
176
|
-
const mouseUpEvent = new MouseEvent('mouseup');
|
|
177
|
-
const container = myNVL.getContainer();
|
|
178
|
-
container.dispatchEvent(mouseDownEvent);
|
|
179
|
-
await waitForAnimationFrame();
|
|
180
|
-
container.dispatchEvent(mouseMoveEvent);
|
|
181
|
-
await waitForAnimationFrame();
|
|
182
|
-
container.dispatchEvent(mouseUpEvent);
|
|
183
|
-
expect(myNVL.getPan()).not.toEqual(initialPan);
|
|
184
|
-
expect(myNVL.getPan()).toEqual({
|
|
185
|
-
x: initialPan.x - 20,
|
|
186
|
-
y: initialPan.y - 20
|
|
187
|
-
});
|
|
188
|
-
expect(panCallbackMock).toHaveBeenCalledTimes(1);
|
|
189
|
-
panInteractionWithUpdate.destroy();
|
|
190
|
-
});
|
|
191
|
-
test('when controlledPan is true, should provide correct callback values for multiple operations', () => {
|
|
192
|
-
panInteraction.destroy();
|
|
193
|
-
myNVL.destroy();
|
|
194
|
-
myNVL = new NVL(document.createElement('div'), [
|
|
195
|
-
{ id: '0', x: 10, y: 10 },
|
|
196
|
-
{ id: '1', x: 200, y: 200 }
|
|
197
|
-
], [{ id: '10', from: '0', to: '1' }], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
198
|
-
const panInteractionNoUpdate = new PanInteraction(myNVL, { controlledPan: true });
|
|
199
|
-
panInteractionNoUpdate.updateCallback('onPan', panCallbackMock);
|
|
200
|
-
const initialPan = myNVL.getPan();
|
|
201
|
-
const container = myNVL.getContainer();
|
|
202
|
-
container.dispatchEvent(new MouseEvent('mousedown', { clientX: 100, clientY: 100 }));
|
|
203
|
-
container.dispatchEvent(new MouseEvent('mousemove', { buttons: 1, clientX: 120, clientY: 120 }));
|
|
204
|
-
container.dispatchEvent(new MouseEvent('mouseup'));
|
|
205
|
-
container.dispatchEvent(new MouseEvent('mousedown', { clientX: 120, clientY: 120 }));
|
|
206
|
-
container.dispatchEvent(new MouseEvent('mousemove', { buttons: 1, clientX: 140, clientY: 140 }));
|
|
207
|
-
container.dispatchEvent(new MouseEvent('mouseup'));
|
|
208
|
-
return new Promise((resolve) => {
|
|
209
|
-
expect(panCallbackMock).toHaveBeenCalledTimes(2);
|
|
210
|
-
expect(panCallbackMock).toHaveBeenNthCalledWith(1, {
|
|
211
|
-
x: initialPan.x - 20,
|
|
212
|
-
y: initialPan.y - 20
|
|
213
|
-
}, expect.anything());
|
|
214
|
-
expect(panCallbackMock).toHaveBeenNthCalledWith(2, {
|
|
215
|
-
x: initialPan.x - 20,
|
|
216
|
-
y: initialPan.y - 20
|
|
217
|
-
}, expect.anything());
|
|
218
|
-
expect(myNVL.getPan()).toEqual(initialPan);
|
|
219
|
-
panInteractionNoUpdate.destroy();
|
|
220
|
-
resolve();
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { isDraggingDistance, isDraggingMovement } from '../interaction-handlers/utils';
|
|
2
|
-
describe('interaction utils', () => {
|
|
3
|
-
test('returns true when movement reaches threshold on either axis', () => {
|
|
4
|
-
expect(isDraggingDistance({ x: 0, y: 0 }, { x: 10, y: 0 })).toBe(true);
|
|
5
|
-
expect(isDraggingDistance({ x: 0, y: 0 }, { x: 0, y: 10 })).toBe(true);
|
|
6
|
-
});
|
|
7
|
-
test('returns true for diagonal movement whose combined movement reaches threshold', () => {
|
|
8
|
-
expect(isDraggingDistance({ x: 0, y: 0 }, { x: 2, y: 2 })).toBe(false);
|
|
9
|
-
expect(isDraggingDistance({ x: 0, y: 0 }, { x: 7, y: 7 })).toBe(true);
|
|
10
|
-
expect(isDraggingDistance({ x: 0, y: 0 }, { x: 8, y: 8 })).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
test('applies the same threshold logic to mouse events', () => {
|
|
13
|
-
expect(isDraggingMovement(new MouseEvent('mousemove', { clientX: 10, clientY: 0 }), { x: 0, y: 0 })).toBe(true);
|
|
14
|
-
expect(isDraggingMovement(new MouseEvent('mousemove', { clientX: 0, clientY: 10 }), { x: 0, y: 0 })).toBe(true);
|
|
15
|
-
expect(isDraggingMovement(new MouseEvent('mousemove', { clientX: 2, clientY: 2 }), { x: 0, y: 0 })).toBe(false);
|
|
16
|
-
expect(isDraggingMovement(new MouseEvent('mousemove', { clientX: 7, clientY: 7 }), { x: 0, y: 0 })).toBe(true);
|
|
17
|
-
expect(isDraggingMovement(new MouseEvent('mousemove', { clientX: 8, clientY: 8 }), { x: 0, y: 0 })).toBe(true);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import NVL from '@neo4j-nvl/base';
|
|
2
|
-
import '@testing-library/jest-dom';
|
|
3
|
-
import { ZoomInteraction } from '../interaction-handlers/zoom-interaction';
|
|
4
|
-
jest.mock('@neo4j-nvl/layout-workers');
|
|
5
|
-
describe('ZoomInteraction', () => {
|
|
6
|
-
let zoomInteraction;
|
|
7
|
-
let myNVL;
|
|
8
|
-
let myNvlContainer;
|
|
9
|
-
const zoomAndPanCallbackMock = jest.fn();
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
myNVL = new NVL(document.createElement('div'), [], [], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
12
|
-
myNvlContainer = myNVL.getContainer();
|
|
13
|
-
zoomInteraction = new ZoomInteraction(myNVL);
|
|
14
|
-
});
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
zoomInteraction.destroy();
|
|
17
|
-
myNVL.destroy();
|
|
18
|
-
zoomAndPanCallbackMock.mockReset();
|
|
19
|
-
});
|
|
20
|
-
const simulateWheelEvent = async (container, deltaY, delay = 50, eventOptions = {}) => {
|
|
21
|
-
const wheelEvent = new WheelEvent('wheel', {
|
|
22
|
-
deltaY,
|
|
23
|
-
clientX: 150,
|
|
24
|
-
clientY: 150,
|
|
25
|
-
...eventOptions
|
|
26
|
-
});
|
|
27
|
-
container.dispatchEvent(wheelEvent);
|
|
28
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
29
|
-
return wheelEvent;
|
|
30
|
-
};
|
|
31
|
-
const simulateSequentialWheelEvents = async (container, events) => {
|
|
32
|
-
for (const event of events) {
|
|
33
|
-
// eslint-disable-next-line no-await-in-loop
|
|
34
|
-
await simulateWheelEvent(container, event.deltaY, event.delay);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
describe('Scrolling', () => {
|
|
38
|
-
test('zooming in should increase the scale', async () => {
|
|
39
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
40
|
-
const initialScale = myNVL.getScale();
|
|
41
|
-
const container = myNVL.getContainer();
|
|
42
|
-
await simulateWheelEvent(container, -100);
|
|
43
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
44
|
-
const newScale = myNVL.getScale();
|
|
45
|
-
expect(newScale).toBeGreaterThan(initialScale);
|
|
46
|
-
expect(newScale).toBe(1.2);
|
|
47
|
-
});
|
|
48
|
-
test('zooming out should decrease the scale', async () => {
|
|
49
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
50
|
-
const initialScale = myNVL.getScale();
|
|
51
|
-
await simulateWheelEvent(myNvlContainer, 100);
|
|
52
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
53
|
-
const newScale = myNVL.getScale();
|
|
54
|
-
expect(newScale).toBeLessThan(initialScale);
|
|
55
|
-
expect(newScale).toBe(0.8);
|
|
56
|
-
});
|
|
57
|
-
test('zoom callback should be called with the correct zoom level and pan values', async () => {
|
|
58
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
59
|
-
const wheelEvent = await simulateWheelEvent(myNvlContainer, -100);
|
|
60
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
61
|
-
const zoomAndPanCallbackMockArguments = zoomAndPanCallbackMock.mock.calls[0] ?? [];
|
|
62
|
-
expect(zoomAndPanCallbackMockArguments[0]).toBe(1.2);
|
|
63
|
-
expect(zoomAndPanCallbackMockArguments[1]).toBe(25);
|
|
64
|
-
expect(zoomAndPanCallbackMockArguments[2]).toBe(25);
|
|
65
|
-
expect(zoomAndPanCallbackMockArguments[3]).toBe(wheelEvent);
|
|
66
|
-
});
|
|
67
|
-
test('zooming should adjust pan to mouse position', async () => {
|
|
68
|
-
const initialPan = myNVL.getPan();
|
|
69
|
-
const initialScale = myNVL.getScale();
|
|
70
|
-
await simulateWheelEvent(myNvlContainer, -100);
|
|
71
|
-
const newPan = myNVL.getPan();
|
|
72
|
-
const newScale = myNVL.getScale();
|
|
73
|
-
expect(newPan).not.toEqual(initialPan);
|
|
74
|
-
expect(newPan.x).toBe(25);
|
|
75
|
-
expect(newPan.y).toBe(25);
|
|
76
|
-
expect(newScale).toBeGreaterThan(initialScale);
|
|
77
|
-
expect(newScale).toBe(1.2);
|
|
78
|
-
});
|
|
79
|
-
test('zooming should be progressively faster at higher zoom levels', async () => {
|
|
80
|
-
const sequentialWheelEvents = Array(8).fill({ deltaY: -100 });
|
|
81
|
-
await simulateSequentialWheelEvents(myNvlContainer, sequentialWheelEvents);
|
|
82
|
-
const newScale = myNVL.getScale();
|
|
83
|
-
expect(newScale).toBeGreaterThan(3.0);
|
|
84
|
-
expect(newScale).toBeCloseTo(4.299);
|
|
85
|
-
});
|
|
86
|
-
test('handles touchpad-like small incremental scrolling', async () => {
|
|
87
|
-
const initialScale = myNVL.getScale();
|
|
88
|
-
const touchpadEvents = Array(25).fill({ deltaY: -20, delay: 25 });
|
|
89
|
-
await simulateSequentialWheelEvents(myNvlContainer, touchpadEvents);
|
|
90
|
-
const newScale = myNVL.getScale();
|
|
91
|
-
expect(newScale).toBeGreaterThan(initialScale);
|
|
92
|
-
expect(newScale).toBeGreaterThan(2.5);
|
|
93
|
-
expect(newScale).toBeLessThan(2.7);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
describe('Trackpad pinch gestures', () => {
|
|
97
|
-
test('trackpad pinch out should zoom in', async () => {
|
|
98
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
99
|
-
await simulateWheelEvent(myNvlContainer, -75, 50, { ctrlKey: true });
|
|
100
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
101
|
-
const newScale = myNVL.getScale();
|
|
102
|
-
expect(newScale).toBe(2);
|
|
103
|
-
});
|
|
104
|
-
test('trackpad pinch in should zoom out', async () => {
|
|
105
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
106
|
-
await simulateWheelEvent(myNvlContainer, 100, 50, { ctrlKey: true });
|
|
107
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
108
|
-
const newScale = myNVL.getScale();
|
|
109
|
-
expect(newScale).toBe(0.075);
|
|
110
|
-
});
|
|
111
|
-
test('trackpad pinch should work with meta key (macOS)', async () => {
|
|
112
|
-
zoomInteraction.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
113
|
-
const initialScale = myNVL.getScale();
|
|
114
|
-
await simulateWheelEvent(myNvlContainer, -50, 50, { metaKey: true });
|
|
115
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
116
|
-
const newScale = myNVL.getScale();
|
|
117
|
-
expect(newScale).toBeGreaterThan(initialScale);
|
|
118
|
-
});
|
|
119
|
-
test('trackpad pinch should adjust pan to cursor position', async () => {
|
|
120
|
-
const initialPan = myNVL.getPan();
|
|
121
|
-
const initialScale = myNVL.getScale();
|
|
122
|
-
await simulateWheelEvent(myNvlContainer, -50, 50, {
|
|
123
|
-
ctrlKey: true,
|
|
124
|
-
clientX: 200,
|
|
125
|
-
clientY: 100
|
|
126
|
-
});
|
|
127
|
-
const newPan = myNVL.getPan();
|
|
128
|
-
const newScale = myNVL.getScale();
|
|
129
|
-
expect(newPan).not.toEqual(initialPan);
|
|
130
|
-
expect(newScale).toBeGreaterThan(initialScale);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
describe('Controlled Zoom', () => {
|
|
134
|
-
test('when controlledZoom is true, should not update NVL instance', async () => {
|
|
135
|
-
zoomInteraction.destroy();
|
|
136
|
-
myNVL.destroy();
|
|
137
|
-
myNVL = new NVL(document.createElement('div'), [], [], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
138
|
-
myNvlContainer = myNVL.getContainer();
|
|
139
|
-
const zoomInteractionNoUpdate = new ZoomInteraction(myNVL, { controlledZoom: true });
|
|
140
|
-
zoomInteractionNoUpdate.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
141
|
-
const initialScale = myNVL.getScale();
|
|
142
|
-
const initialPan = myNVL.getPan();
|
|
143
|
-
await simulateWheelEvent(myNvlContainer, -100);
|
|
144
|
-
expect(myNVL.getScale()).toBe(initialScale);
|
|
145
|
-
expect(myNVL.getPan()).toEqual(initialPan);
|
|
146
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
147
|
-
const [newZoom, newPanX, newPanY, event] = zoomAndPanCallbackMock.mock.calls[0] ?? [];
|
|
148
|
-
expect(newZoom).toBe(1.2);
|
|
149
|
-
expect(newPanX).toBe(25);
|
|
150
|
-
expect(newPanY).toBe(25);
|
|
151
|
-
expect(event).toBeInstanceOf(WheelEvent);
|
|
152
|
-
zoomInteractionNoUpdate.destroy();
|
|
153
|
-
});
|
|
154
|
-
test('when controlledZoom is false, should update NVL instance normally', async () => {
|
|
155
|
-
zoomInteraction.destroy();
|
|
156
|
-
myNVL.destroy();
|
|
157
|
-
myNVL = new NVL(document.createElement('div'), [], [], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
158
|
-
myNvlContainer = myNVL.getContainer();
|
|
159
|
-
const zoomInteractionWithUpdate = new ZoomInteraction(myNVL, { controlledZoom: false });
|
|
160
|
-
zoomInteractionWithUpdate.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
161
|
-
const initialScale = myNVL.getScale();
|
|
162
|
-
await simulateWheelEvent(myNvlContainer, -100);
|
|
163
|
-
expect(myNVL.getScale()).not.toBe(initialScale);
|
|
164
|
-
expect(myNVL.getScale()).toBe(1.2);
|
|
165
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(1);
|
|
166
|
-
zoomInteractionWithUpdate.destroy();
|
|
167
|
-
});
|
|
168
|
-
test('when controlledZoom is true, should provide correct callback values for multiple operations', async () => {
|
|
169
|
-
zoomInteraction.destroy();
|
|
170
|
-
myNVL.destroy();
|
|
171
|
-
myNVL = new NVL(document.createElement('div'), [], [], { disableWebGL: true, initialZoom: 1, layout: 'free' });
|
|
172
|
-
myNvlContainer = myNVL.getContainer();
|
|
173
|
-
const zoomInteractionNoUpdate = new ZoomInteraction(myNVL, { controlledZoom: true });
|
|
174
|
-
zoomInteractionNoUpdate.updateCallback('onZoomAndPan', zoomAndPanCallbackMock);
|
|
175
|
-
await simulateWheelEvent(myNvlContainer, -100);
|
|
176
|
-
await simulateWheelEvent(myNvlContainer, 100);
|
|
177
|
-
expect(zoomAndPanCallbackMock).toHaveBeenCalledTimes(2);
|
|
178
|
-
const [zoom1] = zoomAndPanCallbackMock.mock.calls[0] ?? [];
|
|
179
|
-
expect(zoom1).toBe(1.2);
|
|
180
|
-
const [zoom2] = zoomAndPanCallbackMock.mock.calls[1] ?? [];
|
|
181
|
-
expect(zoom2).toBe(0.8);
|
|
182
|
-
zoomInteractionNoUpdate.destroy();
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
});
|