@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +8 -0
  3. package/lib/constants.d.ts +1 -1
  4. package/lib/constants.js +4 -2
  5. package/lib/index.d.ts +10 -20
  6. package/lib/index.js +10 -10
  7. package/lib/interaction-handlers/base.d.ts +67 -67
  8. package/lib/interaction-handlers/base.js +98 -104
  9. package/lib/interaction-handlers/box-select-interaction.d.ts +44 -44
  10. package/lib/interaction-handlers/box-select-interaction.js +133 -127
  11. package/lib/interaction-handlers/click-interaction.d.ts +111 -111
  12. package/lib/interaction-handlers/click-interaction.js +116 -131
  13. package/lib/interaction-handlers/drag-node-interaction.d.ts +40 -40
  14. package/lib/interaction-handlers/drag-node-interaction.js +102 -111
  15. package/lib/interaction-handlers/draw-interaction.d.ts +37 -37
  16. package/lib/interaction-handlers/draw-interaction.js +245 -278
  17. package/lib/interaction-handlers/hover-interaction.d.ts +34 -30
  18. package/lib/interaction-handlers/hover-interaction.js +83 -89
  19. package/lib/interaction-handlers/keyboard-interaction.d.ts +149 -97
  20. package/lib/interaction-handlers/keyboard-interaction.js +255 -201
  21. package/lib/interaction-handlers/lasso-interaction.d.ts +45 -45
  22. package/lib/interaction-handlers/lasso-interaction.js +174 -196
  23. package/lib/interaction-handlers/pan-interaction.d.ts +62 -61
  24. package/lib/interaction-handlers/pan-interaction.js +111 -100
  25. package/lib/interaction-handlers/utils.d.ts +2 -2
  26. package/lib/interaction-handlers/utils.js +39 -38
  27. package/lib/interaction-handlers/zoom-interaction.d.ts +52 -48
  28. package/lib/interaction-handlers/zoom-interaction.js +73 -71
  29. package/lib/overlay-renderer/overlay-renderer.d.ts +13 -13
  30. package/lib/overlay-renderer/overlay-renderer.js +96 -111
  31. package/package.json +19 -6
  32. package/lib/__tests__/box-select-interaction.test.d.ts +0 -1
  33. package/lib/__tests__/box-select-interaction.test.js +0 -149
  34. package/lib/__tests__/click-interaction.test.d.ts +0 -1
  35. package/lib/__tests__/click-interaction.test.js +0 -505
  36. package/lib/__tests__/drag-node-interaction.test.d.ts +0 -1
  37. package/lib/__tests__/drag-node-interaction.test.js +0 -247
  38. package/lib/__tests__/hover-interaction.test.d.ts +0 -1
  39. package/lib/__tests__/hover-interaction.test.js +0 -374
  40. package/lib/__tests__/keyboard-interaction.test.d.ts +0 -1
  41. package/lib/__tests__/keyboard-interaction.test.js +0 -322
  42. package/lib/__tests__/lasso-interaction.test.d.ts +0 -1
  43. package/lib/__tests__/lasso-interaction.test.js +0 -219
  44. package/lib/__tests__/pan-interaction.test.d.ts +0 -1
  45. package/lib/__tests__/pan-interaction.test.js +0 -223
  46. package/lib/__tests__/utils.test.d.ts +0 -1
  47. package/lib/__tests__/utils.test.js +0 -19
  48. package/lib/__tests__/zoom-interaction.test.d.ts +0 -1
  49. package/lib/__tests__/zoom-interaction.test.js +0 -185
@@ -1,46 +1,50 @@
1
- import type { HitTargets, NVL, Node, Relationship } from '@neo4j-nvl/base';
2
- import { BaseInteraction } from './base';
1
+ import { BaseInteraction } from "./base.js";
2
+ import { HitTargets, NVL, Node, Relationship } from "@neo4j-nvl/base";
3
3
  /**
4
4
  * Options for the hover interaction handler to customize its behavior.
5
5
  */
6
6
  export type HoverInteractionOptions = {
7
- /**
8
- * Whether to draw a shadow on hover for nodes/relationships
9
- * @default false
10
- */
11
- drawShadowOnHover?: boolean;
7
+ /**
8
+ * Whether to draw a shadow on hover for nodes/relationships
9
+ * @default false
10
+ */
11
+ drawShadowOnHover?: boolean;
12
12
  };
13
13
  /**
14
14
  * Callbacks for the hover interaction handler.
15
15
  */
16
16
  export type HoverInteractionCallbacks = {
17
- /**
18
- * Called when a node or relationship is hovered.
19
- * @param element - The highest-priority node or relationship under the pointer.
20
- * @param hitElements - All nodes, relationships, and clusters under the pointer.
21
- * @param event - The original mouse event.
22
- * This callback is called every time the mouse moves,
23
- * even when no element is hovered or the current element is already hovered.
24
- */
25
- onHover?: ((element: Node | Relationship, hitElements: HitTargets, event: MouseEvent) => void) | boolean;
17
+ /**
18
+ * Called when a node or relationship is hovered.
19
+ * @param element - The highest-priority node or relationship under the pointer, or `undefined` if nothing is hovered.
20
+ * @param hitElements - All nodes, relationships, and clusters under the pointer.
21
+ * @param event - The original mouse event.
22
+ * This callback is called every time the mouse moves,
23
+ * even when no element is hovered or the current element is already hovered.
24
+ */
25
+ onHover?: ((element: Node | Relationship | undefined, hitElements: HitTargets, event: MouseEvent) => void) | boolean;
26
26
  };
27
27
  /**
28
28
  * Interaction handler for hovering nodes and relationships.
29
29
  *
30
+ * @remarks Clusters are not hoverable elements: `element` is never a cluster and no hover state is drawn
31
+ * for hulls. Read `hitElements.clusters` in {@link HoverInteractionCallbacks.onHover}, or call
32
+ * {@link NVL.getHits} with `['cluster']`, to react to the pointer being inside a cluster hull.
33
+ *
30
34
  * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_hoverinteraction Hover Interaction documentation page}.
31
35
  */
32
36
  export declare class HoverInteraction extends BaseInteraction<HoverInteractionOptions> {
33
- private currentHoveredElementId;
34
- private currentHoveredElementIsNode;
35
- private readonly updates;
36
- constructor(nvl: NVL, options?: HoverInteractionOptions);
37
- /**
38
- * Handle mouse hover events
39
- * @param event - The mouse event.
40
- */
41
- handleHover: (event: MouseEvent) => void;
42
- private updateElementsInNVL;
43
- private clearUpdates;
44
- private unHoverCurrentElement;
45
- destroy(): void;
46
- }
37
+ private currentHoveredElementId;
38
+ private currentHoveredElementIsNode;
39
+ private readonly updates;
40
+ constructor(nvl: NVL, options?: HoverInteractionOptions);
41
+ /**
42
+ * Handle mouse hover events
43
+ * @param event - The mouse event.
44
+ */
45
+ handleHover: (event: MouseEvent) => void;
46
+ private updateElementsInNVL;
47
+ private clearUpdates;
48
+ private unHoverCurrentElement;
49
+ destroy(): void;
50
+ }
@@ -1,90 +1,84 @@
1
- import { BaseInteraction } from './base';
1
+ import { BaseInteraction } from "./base.js";
2
+ // src/interaction-handlers/hover-interaction.ts
2
3
  /**
3
- * Interaction handler for hovering nodes and relationships.
4
- *
5
- * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_hoverinteraction Hover Interaction documentation page}.
6
- */
7
- export class HoverInteraction extends BaseInteraction {
8
- currentHoveredElementId = undefined;
9
- currentHoveredElementIsNode = undefined;
10
- updates = {
11
- nodes: [],
12
- relationships: []
13
- };
14
- constructor(nvl, options = { drawShadowOnHover: false }) {
15
- super(nvl, options);
16
- this.addEventListener('mousemove', this.handleHover, true);
17
- }
18
- /**
19
- * Handle mouse hover events
20
- * @param event - The mouse event.
21
- */
22
- handleHover = (event) => {
23
- const { nvlTargets } = this.nvlInstance.getHits(event);
24
- const { nodes = [], relationships = [] } = nvlTargets;
25
- const mainTarget = nodes[0] ?? relationships[0];
26
- const hoveredElement = mainTarget?.data;
27
- const newHoveredElementIsNode = hoveredElement !== undefined && nodes[0] !== undefined;
28
- const nothingHasBeenHoveredOrUnHovered = this.currentHoveredElementId === undefined && hoveredElement === undefined;
29
- const newHoveredElementIsTheSameAsCurrent = hoveredElement?.id !== undefined &&
30
- this.currentHoveredElementId === hoveredElement.id &&
31
- newHoveredElementIsNode === this.currentHoveredElementIsNode;
32
- if (nothingHasBeenHoveredOrUnHovered || newHoveredElementIsTheSameAsCurrent) {
33
- this.callCallbackIfRegistered('onHover', hoveredElement, nvlTargets, event);
34
- return;
35
- }
36
- const currentElementNeedsUnHover = this.currentHoveredElementId !== undefined && this.currentHoveredElementId !== hoveredElement?.id;
37
- if (currentElementNeedsUnHover) {
38
- this.unHoverCurrentElement();
39
- }
40
- if (newHoveredElementIsNode) {
41
- this.updates.nodes.push({ id: hoveredElement.id, hovered: true });
42
- this.currentHoveredElementId = hoveredElement.id;
43
- this.currentHoveredElementIsNode = true;
44
- }
45
- else if (hoveredElement !== undefined) {
46
- const { id } = hoveredElement;
47
- this.updates.relationships.push({ id, hovered: true });
48
- this.currentHoveredElementId = hoveredElement.id;
49
- this.currentHoveredElementIsNode = false;
50
- }
51
- else {
52
- this.currentHoveredElementId = undefined;
53
- this.currentHoveredElementIsNode = undefined;
54
- }
55
- this.callCallbackIfRegistered('onHover', hoveredElement, nvlTargets, event);
56
- this.updateElementsInNVL();
57
- this.clearUpdates();
58
- };
59
- updateElementsInNVL() {
60
- // Use pure update API to avoid the previous removed node to be re-added to the scene.
61
- if (this.currentOptions.drawShadowOnHover === true) {
62
- const currentNodes = this.nvlInstance.getNodes();
63
- if (currentNodes.length > 0) {
64
- this.nvlInstance.updateElementsInGraph(this.updates.nodes, this.updates.relationships);
65
- }
66
- }
67
- }
68
- clearUpdates() {
69
- this.updates.nodes = [];
70
- this.updates.relationships = [];
71
- }
72
- unHoverCurrentElement() {
73
- if (this.currentHoveredElementId === undefined) {
74
- return;
75
- }
76
- const update = {
77
- id: this.currentHoveredElementId,
78
- hovered: false
79
- };
80
- if (this.currentHoveredElementIsNode === true) {
81
- this.updates.nodes.push(update);
82
- }
83
- else {
84
- this.updates.relationships.push({ ...update });
85
- }
86
- }
87
- destroy() {
88
- this.removeEventListener('mousemove', this.handleHover, true);
89
- }
90
- }
4
+ * Interaction handler for hovering nodes and relationships.
5
+ *
6
+ * @remarks Clusters are not hoverable elements: `element` is never a cluster and no hover state is drawn
7
+ * for hulls. Read `hitElements.clusters` in {@link HoverInteractionCallbacks.onHover}, or call
8
+ * {@link NVL.getHits} with `['cluster']`, to react to the pointer being inside a cluster hull.
9
+ *
10
+ * For examples, head to the {@link https://neo4j.com/docs/nvl/current/interaction-handlers/#_hoverinteraction Hover Interaction documentation page}.
11
+ */
12
+ var HoverInteraction = class extends BaseInteraction {
13
+ currentHoveredElementId = void 0;
14
+ currentHoveredElementIsNode = void 0;
15
+ updates = {
16
+ nodes: [],
17
+ relationships: []
18
+ };
19
+ constructor(nvl, options = { drawShadowOnHover: false }) {
20
+ super(nvl, options);
21
+ this.addEventListener("mousemove", this.handleHover, true);
22
+ }
23
+ /**
24
+ * Handle mouse hover events
25
+ * @param event - The mouse event.
26
+ */
27
+ handleHover = (event) => {
28
+ const { nvlTargets } = this.nvlInstance.getHits(event);
29
+ const { nodes = [], relationships = [] } = nvlTargets;
30
+ const hoveredElement = (nodes[0] ?? relationships[0])?.data;
31
+ const newHoveredElementIsNode = hoveredElement !== void 0 && nodes[0] !== void 0;
32
+ const nothingHasBeenHoveredOrUnHovered = this.currentHoveredElementId === void 0 && hoveredElement === void 0;
33
+ const newHoveredElementIsTheSameAsCurrent = hoveredElement?.id !== void 0 && this.currentHoveredElementId === hoveredElement.id && newHoveredElementIsNode === this.currentHoveredElementIsNode;
34
+ if (nothingHasBeenHoveredOrUnHovered || newHoveredElementIsTheSameAsCurrent) {
35
+ this.callCallbackIfRegistered("onHover", hoveredElement, nvlTargets, event);
36
+ return;
37
+ }
38
+ if (this.currentHoveredElementId !== void 0 && this.currentHoveredElementId !== hoveredElement?.id) this.unHoverCurrentElement();
39
+ if (newHoveredElementIsNode) {
40
+ this.updates.nodes.push({
41
+ id: hoveredElement.id,
42
+ hovered: true
43
+ });
44
+ this.currentHoveredElementId = hoveredElement.id;
45
+ this.currentHoveredElementIsNode = true;
46
+ } else if (hoveredElement !== void 0) {
47
+ const { id } = hoveredElement;
48
+ this.updates.relationships.push({
49
+ id,
50
+ hovered: true
51
+ });
52
+ this.currentHoveredElementId = hoveredElement.id;
53
+ this.currentHoveredElementIsNode = false;
54
+ } else {
55
+ this.currentHoveredElementId = void 0;
56
+ this.currentHoveredElementIsNode = void 0;
57
+ }
58
+ this.callCallbackIfRegistered("onHover", hoveredElement, nvlTargets, event);
59
+ this.updateElementsInNVL();
60
+ this.clearUpdates();
61
+ };
62
+ updateElementsInNVL() {
63
+ if (this.currentOptions.drawShadowOnHover === true) {
64
+ if (this.nvlInstance.getNodes().length > 0) this.nvlInstance.updateElementsInGraph(this.updates.nodes, this.updates.relationships);
65
+ }
66
+ }
67
+ clearUpdates() {
68
+ this.updates.nodes = [];
69
+ this.updates.relationships = [];
70
+ }
71
+ unHoverCurrentElement() {
72
+ if (this.currentHoveredElementId === void 0) return;
73
+ const update = {
74
+ id: this.currentHoveredElementId,
75
+ hovered: false
76
+ };
77
+ if (this.currentHoveredElementIsNode === true) this.updates.nodes.push(update);
78
+ else this.updates.relationships.push({ ...update });
79
+ }
80
+ destroy() {
81
+ this.removeEventListener("mousemove", this.handleHover, true);
82
+ }
83
+ };
84
+ export { HoverInteraction };
@@ -1,5 +1,5 @@
1
- import type { NVL, Node, Relationship } from '@neo4j-nvl/base';
2
- import { BaseInteraction } from './base';
1
+ import { BaseInteraction } from "./base.js";
2
+ import { NVL, Node, Point, Relationship } from "@neo4j-nvl/base";
3
3
  /**
4
4
  * Options for the keyboard interaction handler.
5
5
  * Allows configuring which keys trigger specific navigation actions.
@@ -17,76 +17,107 @@ import { BaseInteraction } from './base';
17
17
  * ```
18
18
  */
19
19
  export type KeyboardInteractionOptions = {
20
- /** Key combo for entering the graph and focusing the first element. Default: `['Enter']` */
21
- enterGraphKey?: string[];
22
- /** Key combo for navigating focus to the next element. Default: `['Tab']` */
23
- navigateForwardKey?: string[];
24
- /** Key combo for navigating focus to the previous element. Default: `['Shift', 'Tab']` */
25
- navigateBackwardKey?: string[];
26
- /** Key combo for exiting the graph (blur focused element and container). Default: `['Escape']` */
27
- exitGraphKey?: string[];
28
- /** Key combo for opening the context menu on the focused element. Default: `['Shift', 'F10']` */
29
- contextMenuKey?: string[];
30
- /** The color of the outline shown when the canvas receives keyboard focus. Default: `'#30839D'` */
31
- canvasOutlineColor?: string;
20
+ /** Key combo for entering the graph and focusing the first element. Default: `['Enter']` */
21
+ enterGraphKey?: string[];
22
+ /** Key combo for navigating focus to the next element. Default: `['Tab']` */
23
+ navigateForwardKey?: string[];
24
+ /** Key combo for navigating focus to the previous element. Default: `['Shift', 'Tab']` */
25
+ navigateBackwardKey?: string[];
26
+ /** Key combo for exiting the graph (blur focused element and container). Default: `['Escape']` */
27
+ exitGraphKey?: string[];
28
+ /** Key combo for opening the context menu on the focused element. Default: `['Shift', 'F10']` */
29
+ contextMenuKey?: string[];
30
+ /** Key combo for moving the selected (or focused) node(s) up. Default: `['ArrowUp']` */
31
+ moveUpKey?: string[];
32
+ /** Key combo for moving the selected (or focused) node(s) down. Default: `['ArrowDown']` */
33
+ moveDownKey?: string[];
34
+ /** Key combo for moving the selected (or focused) node(s) left. Default: `['ArrowLeft']` */
35
+ moveLeftKey?: string[];
36
+ /** Key combo for moving the selected (or focused) node(s) right. Default: `['ArrowRight']` */
37
+ moveRightKey?: string[];
38
+ /**
39
+ * Distance in screen pixels the node(s) are moved per key press. Converted to graph
40
+ * coordinates using the current zoom level, so the node travels the same visible
41
+ * distance however far the graph is zoomed in or out. Default: `5`
42
+ */
43
+ moveStep?: number;
44
+ /**
45
+ * Distance in screen pixels the node(s) are moved per key press while
46
+ * {@link KeyboardInteractionOptions.largeMoveStepModifier} is held. Default: `50`
47
+ */
48
+ largeMoveStep?: number;
49
+ /**
50
+ * Modifier key that, held together with a move key, applies
51
+ * {@link KeyboardInteractionOptions.largeMoveStep} instead of
52
+ * {@link KeyboardInteractionOptions.moveStep}. Default: `'Shift'`
53
+ */
54
+ largeMoveStepModifier?: 'Shift' | 'Ctrl' | 'Alt' | 'Meta';
55
+ /** The color of the outline shown when the canvas receives keyboard focus. Default: `'#30839D'` */
56
+ canvasOutlineColor?: string;
32
57
  };
33
58
  /**
34
59
  * Callbacks for the keyboard interaction handler.
35
60
  */
36
61
  export type KeyboardInteractionCallbacks = {
37
- /**
38
- * Called when a key is pressed while the NVL container is focused.
39
- * Fires for all key events, including those handled by the built-in navigation.
40
- * @param event - The original keyboard event.
41
- * @param focusedElement - The currently focused node or relationship, if any.
42
- */
43
- onKeyDown?: ((event: KeyboardEvent, focusedElement?: Node | Relationship) => void) | boolean;
44
- /**
45
- * Called when a key is released while the NVL container is focused
46
- * @param event - The original keyboard event.
47
- * @param focusedElement - The currently focused node or relationship, if any.
48
- */
49
- onKeyUp?: ((event: KeyboardEvent, focusedElement?: Node | Relationship) => void) | boolean;
50
- /**
51
- * Called when a node receives focus (via keyboard navigation)
52
- * @param node - The node that received focus.
53
- * @param event - The original keyboard event that triggered the focus change.
54
- */
55
- onNodeFocus?: ((node: Node, event: KeyboardEvent) => void) | boolean;
56
- /**
57
- * Called when a node loses focus (via keyboard navigation)
58
- * @param node - The node that lost focus.
59
- * @param event - The original keyboard event that triggered the focus change.
60
- */
61
- onNodeBlur?: ((node: Node, event: KeyboardEvent) => void) | boolean;
62
- /**
63
- * Called when a relationship receives focus (via keyboard navigation)
64
- * @param relationship - The relationship that received focus.
65
- * @param event - The original keyboard event that triggered the focus change.
66
- */
67
- onRelationshipFocus?: ((relationship: Relationship, event: KeyboardEvent) => void) | boolean;
68
- /**
69
- * Called when a relationship loses focus (via keyboard navigation)
70
- * @param relationship - The relationship that lost focus.
71
- * @param event - The original keyboard event that triggered the focus change.
72
- */
73
- onRelationshipBlur?: ((relationship: Relationship, event: KeyboardEvent) => void) | boolean;
74
- /**
75
- * Called when the NVL canvas container receives DOM focus
76
- * @param event - The original focus event.
77
- */
78
- onCanvasFocus?: ((event: FocusEvent) => void) | boolean;
79
- /**
80
- * Called when the NVL canvas container loses DOM focus
81
- * @param event - The original focus event.
82
- */
83
- onCanvasBlur?: ((event: FocusEvent) => void) | boolean;
84
- /**
85
- * Called when the context menu key is pressed while the NVL container is focused.
86
- * @param element - The focused node or relationship, or undefined if the canvas itself is focused.
87
- * @param event - The original keyboard event.
88
- */
89
- onContextMenu?: ((element: Node | Relationship | undefined, event: KeyboardEvent) => void) | boolean;
62
+ /**
63
+ * Called when a key is pressed while the NVL container is focused.
64
+ * Fires for all key events, including those handled by the built-in navigation.
65
+ * @param event - The original keyboard event.
66
+ * @param focusedElement - The currently focused node or relationship, if any.
67
+ */
68
+ onKeyDown?: ((event: KeyboardEvent, focusedElement?: Node | Relationship) => void) | boolean;
69
+ /**
70
+ * Called when a key is released while the NVL container is focused
71
+ * @param event - The original keyboard event.
72
+ * @param focusedElement - The currently focused node or relationship, if any.
73
+ */
74
+ onKeyUp?: ((event: KeyboardEvent, focusedElement?: Node | Relationship) => void) | boolean;
75
+ /**
76
+ * Called when a node receives focus (via keyboard navigation)
77
+ * @param node - The node that received focus.
78
+ * @param event - The original keyboard event that triggered the focus change.
79
+ */
80
+ onNodeFocus?: ((node: Node, event: KeyboardEvent) => void) | boolean;
81
+ /**
82
+ * Called when a node loses focus (via keyboard navigation)
83
+ * @param node - The node that lost focus.
84
+ * @param event - The original keyboard event that triggered the focus change.
85
+ */
86
+ onNodeBlur?: ((node: Node, event: KeyboardEvent) => void) | boolean;
87
+ /**
88
+ * Called when a relationship receives focus (via keyboard navigation)
89
+ * @param relationship - The relationship that received focus.
90
+ * @param event - The original keyboard event that triggered the focus change.
91
+ */
92
+ onRelationshipFocus?: ((relationship: Relationship, event: KeyboardEvent) => void) | boolean;
93
+ /**
94
+ * Called when a relationship loses focus (via keyboard navigation)
95
+ * @param relationship - The relationship that lost focus.
96
+ * @param event - The original keyboard event that triggered the focus change.
97
+ */
98
+ onRelationshipBlur?: ((relationship: Relationship, event: KeyboardEvent) => void) | boolean;
99
+ /**
100
+ * Called when the NVL canvas container receives DOM focus
101
+ * @param event - The original focus event.
102
+ */
103
+ onCanvasFocus?: ((event: FocusEvent) => void) | boolean;
104
+ /**
105
+ * Called when the NVL canvas container loses DOM focus
106
+ * @param event - The original focus event.
107
+ */
108
+ onCanvasBlur?: ((event: FocusEvent) => void) | boolean;
109
+ /**
110
+ * Called when the context menu key is pressed while the NVL container is focused.
111
+ * @param element - The focused node or relationship, or undefined if the canvas itself is focused.
112
+ * @param event - The original keyboard event.
113
+ */
114
+ onContextMenu?: ((element: Node | Relationship | undefined, event: KeyboardEvent) => void) | boolean;
115
+ /**
116
+ * Called when node(s) are moved with the keyboard.
117
+ * @param nodes - The moved node(s), with their updated positions.
118
+ * @param event - The original keyboard event.
119
+ */
120
+ onNodeMove?: ((nodes: (Node & Point)[], event: KeyboardEvent) => void) | boolean;
90
121
  };
91
122
  /**
92
123
  * Opinionated interaction handler for keyboard-driven focus navigation
@@ -94,39 +125,60 @@ export type KeyboardInteractionCallbacks = {
94
125
  *
95
126
  * By default, Tab / Shift+Tab cycle focus through elements, Escape exits the
96
127
  * graph, and Shift+F10 call the `onContextMenu` callback with the focused element.
128
+ * While a node is focused, the arrow keys move the selected node(s), or the focused
129
+ * node when nothing is selected, by `moveStep` screen pixels - or by `largeMoveStep`
130
+ * while the large step modifier (Shift by default) is held.
97
131
  * All keys can be reconfigured via {@link KeyboardInteractionOptions}.
98
132
  *
99
133
  * Callbacks are fired for focus/blur transitions and context-menu activation,
100
134
  * following the same one-way data-flow pattern as the other interaction handlers.
101
135
  */
102
136
  export declare class KeyboardInteraction extends BaseInteraction<KeyboardInteractionOptions> {
103
- private focusedElementId;
104
- private focusedElementIsNode;
105
- private focusableElements;
106
- private addedTabindex;
107
- private resolvedOptions;
108
- /**
109
- * Creates a new keyboard interaction handler.
110
- * @param nvl - The NVL instance to attach the interaction handler to.
111
- * @param options - Options for the keyboard interaction handler.
112
- */
113
- constructor(nvl: NVL, options?: KeyboardInteractionOptions);
114
- private buildFocusableElements;
115
- /**
116
- * Returns the currently focused element, if any.
117
- */
118
- getFocused(): Node | Relationship | undefined;
119
- private setCanvasOutline;
120
- private clearCanvasOutline;
121
- private handleFocusIn;
122
- private handleFocusOut;
123
- private handleKeyDown;
124
- private handleKeyUp;
125
- private navigateFocus;
126
- private setFocus;
127
- private clearFocus;
128
- /**
129
- * Removes all related event listeners from the container.
130
- */
131
- destroy(): void;
132
- }
137
+ private focusedElementId;
138
+ private focusedElementIsNode;
139
+ private focusableElements;
140
+ private addedTabindex;
141
+ private resolvedOptions;
142
+ /**
143
+ * Creates a new keyboard interaction handler.
144
+ * @param nvl - The NVL instance to attach the interaction handler to.
145
+ * @param options - Options for the keyboard interaction handler.
146
+ */
147
+ constructor(nvl: NVL, options?: KeyboardInteractionOptions);
148
+ private buildFocusableElements;
149
+ /**
150
+ * Returns the currently focused element, if any.
151
+ */
152
+ getFocused(): Node | Relationship | undefined;
153
+ private setCanvasOutline;
154
+ private clearCanvasOutline;
155
+ private handleFocusIn;
156
+ private handleFocusOut;
157
+ private handleKeyDown;
158
+ /**
159
+ * Moves the nodes to be moved when the event matches one of the move key combos,
160
+ * either by `moveStep` or, with the large step modifier held, by `largeMoveStep`.
161
+ *
162
+ * The step is given in screen pixels and converted to graph coordinates using the
163
+ * current zoom level, the same way the drag interaction converts pointer
164
+ * movement, so keyboard and pointer moves cover the same visible distance.
165
+ */
166
+ private handleMoveKeys;
167
+ /**
168
+ * Returns the nodes a move key applies to: the selected nodes, or the focused
169
+ * node when nothing is selected.
170
+ *
171
+ * A node must be focused for any of them to move, so move keys are inert until
172
+ * the graph has been entered, and a focused relationship blocks moving entirely.
173
+ */
174
+ private getNodesToMove;
175
+ private moveNodes;
176
+ private handleKeyUp;
177
+ private navigateFocus;
178
+ private setFocus;
179
+ private clearFocus;
180
+ /**
181
+ * Removes all related event listeners from the container.
182
+ */
183
+ destroy(): void;
184
+ }