Skip to content

Commit f27d28e

Browse files
Merge pull request #319 from reaviz/remove-hotkeys
Remove default hotkeys
2 parents e6c381b + 21602ad commit f27d28e

File tree

8 files changed

+272
-110
lines changed

8 files changed

+272
-110
lines changed

docs/Hotkeys.mdx

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,96 @@ import { Meta } from '@storybook/blocks';
44

55
# Hotkeys
66

7-
Under the hood the library uses [reakeys](https://github.com/reaviz/reakeys) for
8-
binding hotkeys.
7+
### We recommend using [reakeys](https://github.com/reaviz/reakeys) for binding hotkeys.
98

10-
### Camera Controls
9+
There are a few examples below of how to bind hotkeys via `reakeys`.
10+
Follow these steps to bind hotkeys using Reakeys:
11+
12+
### 1. Import `useHotkeys` hook from `reakeys`.
1113

1214
```ts
13-
{
14-
name: 'Zoom In',
15-
keys: 'mod+shift+i'
16-
},
17-
{
18-
name: 'Zoom Out',
19-
keys: 'mod+shift+o'
20-
},
21-
{
22-
name: 'Center',
23-
keys: ['mod+shift+c']
24-
}
15+
import { useHotkeys } from 'reakeys';
16+
```
17+
18+
### 2. Create a ref for the graph.
19+
20+
```tsx
21+
const graphRef = useRef<GraphCanvasRef | null>(null);
22+
23+
return <GraphCanvas ref={graphRef} />;
2524
```
2625

27-
### Selection
26+
### 3. Bind Hotkeys to the Graph:
2827

2928
```ts
30-
{
31-
name: 'Select All',
32-
keys: 'mod+a',
33-
},
34-
{
35-
name: 'Deselect Selections',
36-
keys: 'escape'
37-
}
29+
useHotkeys([
30+
{
31+
name: 'Zoom In',
32+
keys: 'mod+shift+i',
33+
action: 'keydown',
34+
category: 'Graph',
35+
callback: event => {
36+
event?.preventDefault();
37+
graphRef.current?.zoomIn();
38+
}
39+
},
40+
{
41+
name: 'Zoom Out',
42+
keys: 'mod+shift+o',
43+
action: 'keydown',
44+
category: 'Graph',
45+
callback: event => {
46+
event?.preventDefault();
47+
graphRef.current?.zoomOut();
48+
}
49+
},
50+
{
51+
name: 'Center',
52+
category: 'Graph',
53+
keys: 'mod+shift+c',
54+
action: 'keydown',
55+
callback: event => {
56+
event?.preventDefault();
57+
graphRef.current?.centerGraph(complexNodes.map(node => node.id));
58+
}
59+
}
60+
]);
3861
```
62+
63+
### 4. Bind Hotkeys to Selection Actions:
64+
65+
```ts
66+
const { clearSelections, setSelections } = useSelection({
67+
ref: graphRef,
68+
nodes,
69+
edges,
70+
pathSelectionType: 'all'
71+
});
72+
73+
useHotkeys([
74+
{
75+
name: 'Select All',
76+
keys: 'mod+a',
77+
action: 'keydown',
78+
category: 'Graph',
79+
description: 'Select all nodes and edges',
80+
callback: event => {
81+
event.preventDefault();
82+
setSelections(nodes.map(node => node.id));
83+
}
84+
},
85+
{
86+
name: 'Deselect Selections',
87+
category: 'Graph',
88+
description: 'Deselect selected nodes and edges',
89+
keys: 'escape',
90+
action: 'keydown',
91+
callback: event => {
92+
event.preventDefault();
93+
clearSelections();
94+
}
95+
}
96+
]);
97+
```
98+
99+
#### Note: You can bind any available Graph actions to hotkeys via reference.

docs/demos/Hotkeys.story.tsx

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import React, { useEffect, useRef, useState } from 'react';
2+
import { useHotkeys } from 'reakeys';
3+
import {
4+
GraphCanvas,
5+
GraphCanvasRef,
6+
lightTheme,
7+
useSelection
8+
} from '../../src';
9+
import { complexEdges, complexNodes } from '../assets/demo';
10+
11+
export default {
12+
title: 'Demos/Hotkeys',
13+
component: GraphCanvas
14+
};
15+
16+
export const CameraControls = () => {
17+
const graphRef = useRef<GraphCanvasRef | null>(null);
18+
19+
const { selections, onNodeClick, onCanvasClick } = useSelection({
20+
ref: graphRef,
21+
nodes: complexNodes,
22+
edges: complexEdges,
23+
type: 'multi',
24+
selections: []
25+
});
26+
27+
const hotkeys = useHotkeys([
28+
{
29+
name: 'Zoom In',
30+
keys: 'mod+shift+i',
31+
action: 'keydown',
32+
category: 'Graph',
33+
callback: event => {
34+
event?.preventDefault();
35+
graphRef.current?.zoomIn();
36+
}
37+
},
38+
{
39+
name: 'Zoom Out',
40+
keys: 'mod+shift+o',
41+
action: 'keydown',
42+
category: 'Graph',
43+
callback: event => {
44+
event?.preventDefault();
45+
graphRef.current?.zoomOut();
46+
}
47+
},
48+
{
49+
name: 'Center',
50+
category: 'Graph',
51+
keys: 'mod+shift+c',
52+
action: 'keydown',
53+
callback: event => {
54+
event?.preventDefault();
55+
graphRef.current?.centerGraph(complexNodes.map(node => node.id));
56+
}
57+
}
58+
]);
59+
60+
return (
61+
<>
62+
<GraphCanvas
63+
ref={graphRef}
64+
nodes={complexNodes}
65+
edges={complexEdges}
66+
selections={selections}
67+
onNodeClick={onNodeClick}
68+
onCanvasClick={onCanvasClick}
69+
/>
70+
<div
71+
style={{
72+
position: 'absolute',
73+
top: 0,
74+
left: 0,
75+
color: 'black',
76+
padding: '10px'
77+
}}
78+
>
79+
<h1>Hotkeys</h1>
80+
{hotkeys.map(hotkey => (
81+
<p key={hotkey.name}>
82+
{hotkey.name} - <strong>{hotkey.keys}</strong>
83+
</p>
84+
))}
85+
</div>
86+
</>
87+
);
88+
};
89+
90+
export const Selection = () => {
91+
const graphRef = useRef<GraphCanvasRef | null>(null);
92+
93+
const {
94+
selections,
95+
setSelections,
96+
clearSelections,
97+
onNodeClick,
98+
onCanvasClick
99+
} = useSelection({
100+
ref: graphRef,
101+
nodes: complexNodes,
102+
edges: complexEdges,
103+
type: 'multi',
104+
selections: [complexNodes[0].id, complexNodes[1].id]
105+
});
106+
107+
const hotkeys = useHotkeys([
108+
{
109+
name: 'Select All',
110+
keys: 'mod+a',
111+
action: 'keydown',
112+
category: 'Graph',
113+
description: 'Select all nodes and edges',
114+
callback: event => {
115+
event?.preventDefault();
116+
setSelections(complexNodes.map(node => node.id));
117+
}
118+
},
119+
{
120+
name: 'Deselect Selections',
121+
category: 'Graph',
122+
description: 'Deselect selected nodes and edges',
123+
keys: 'escape',
124+
action: 'keydown',
125+
callback: event => {
126+
event?.preventDefault();
127+
clearSelections();
128+
}
129+
}
130+
]);
131+
132+
return (
133+
<>
134+
<GraphCanvas
135+
ref={graphRef}
136+
nodes={complexNodes}
137+
edges={complexEdges}
138+
selections={selections}
139+
onNodeClick={onNodeClick}
140+
onCanvasClick={onCanvasClick}
141+
/>
142+
<div
143+
style={{
144+
position: 'absolute',
145+
top: 0,
146+
left: 0,
147+
color: 'black',
148+
padding: '10px'
149+
}}
150+
>
151+
<h1>Hotkeys</h1>
152+
{hotkeys.map(hotkey => (
153+
<p key={hotkey.name}>
154+
{hotkey.name} - <strong>{hotkey.keys}</strong>
155+
</p>
156+
))}
157+
</div>
158+
</>
159+
);
160+
};

docs/demos/MultiSelection.story.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,19 @@ export const ModifierKey = () => {
6363

6464
return (
6565
<>
66-
<div style={{ zIndex: 9, position: 'absolute', top: 0, right: 0, background: 'rgba(0, 0, 0, .5)', color: 'white' }}>
67-
<h3 style={{ margin: 5 }}>Hold Command/CTRL and Click to Select Multiples</h3>
66+
<div
67+
style={{
68+
zIndex: 9,
69+
position: 'absolute',
70+
top: 0,
71+
right: 0,
72+
background: 'rgba(0, 0, 0, .5)',
73+
color: 'white'
74+
}}
75+
>
76+
<h3 style={{ margin: 5 }}>
77+
Hold Command/CTRL and Click to Select Multiples
78+
</h3>
6879
</div>
6980
<GraphCanvas
7081
ref={graphRef}

package-lock.json

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
"graphology-metrics": "^2.1.0",
7070
"graphology-shortest-path": "^2.0.2",
7171
"hold-event": "^0.2.0",
72-
"reakeys": "^2.0.6",
7372
"three": "^0.154.0",
7473
"three-stdlib": "^2.23.13",
7574
"zustand": "4.3.9"
@@ -113,6 +112,7 @@
113112
"prettier": "^3.2.5",
114113
"react": "^18.2.0",
115114
"react-dom": "^18.2.0",
115+
"reakeys": "^2.0.6",
116116
"rollup-plugin-peer-deps-external": "2.2.4",
117117
"stats.js": "^0.17.0",
118118
"storybook": "^7.6.17",

0 commit comments

Comments
 (0)