@dxos/keyboard 0.9.1-main.c7dcc2e112 → 0.10.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/dist/lib/browser/index.mjs +6 -2
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +6 -2
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/keyboard.d.ts +7 -0
- package/dist/types/src/keyboard.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/keyboard.stories.tsx +1 -1
- package/src/keyboard.test.ts +30 -3
- package/src/keyboard.ts +18 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/keyboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Keyboard bindings",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"src"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@dxos/
|
|
30
|
-
"@dxos/
|
|
31
|
-
"@dxos/util": "0.
|
|
29
|
+
"@dxos/invariant": "0.10.0",
|
|
30
|
+
"@dxos/node-std": "0.10.0",
|
|
31
|
+
"@dxos/util": "0.10.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"react": "~19.2.
|
|
35
|
-
"react-dom": "~19.2.
|
|
36
|
-
"@dxos/storybook-utils": "0.
|
|
37
|
-
"@dxos/react-ui": "0.
|
|
38
|
-
"@dxos/ui-theme": "0.
|
|
34
|
+
"react": "~19.2.7",
|
|
35
|
+
"react-dom": "~19.2.7",
|
|
36
|
+
"@dxos/storybook-utils": "0.10.0",
|
|
37
|
+
"@dxos/react-ui": "0.10.0",
|
|
38
|
+
"@dxos/ui-theme": "0.10.0"
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
package/src/keyboard.stories.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react';
|
|
|
8
8
|
import { Input, Select } from '@dxos/react-ui';
|
|
9
9
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
10
10
|
|
|
11
|
-
import { type KeyHandler
|
|
11
|
+
import { Keyboard, type KeyHandler } from './keyboard';
|
|
12
12
|
|
|
13
13
|
const contexts = ['/', '/space/1', '/space/2', '/space/2/a', '/space/2/b'];
|
|
14
14
|
|
package/src/keyboard.test.ts
CHANGED
|
@@ -2,14 +2,41 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
6
6
|
|
|
7
|
-
import { Keyboard } from './keyboard';
|
|
7
|
+
import { Keyboard, nestKeyboardContext } from './keyboard';
|
|
8
8
|
|
|
9
9
|
describe('keyboard', () => {
|
|
10
|
-
test('
|
|
10
|
+
test('binds shortcuts on the active context', () => {
|
|
11
11
|
const keyboard = new Keyboard();
|
|
12
12
|
keyboard.bind({ shortcut: 'meta+k', handler: () => true });
|
|
13
13
|
expect(keyboard.getBindings()).to.have.length(1);
|
|
14
14
|
});
|
|
15
|
+
|
|
16
|
+
test('child context inherits root bindings', async () => {
|
|
17
|
+
const keyboard = new Keyboard();
|
|
18
|
+
const handler = vi.fn();
|
|
19
|
+
keyboard.getContext('root').bind({ shortcut: 'shift+meta+f', handler });
|
|
20
|
+
keyboard.setCurrentContext('root/plank-1');
|
|
21
|
+
|
|
22
|
+
await keyboard.handleKeyDown({
|
|
23
|
+
altKey: false,
|
|
24
|
+
ctrlKey: false,
|
|
25
|
+
metaKey: true,
|
|
26
|
+
shiftKey: true,
|
|
27
|
+
key: 'F',
|
|
28
|
+
preventDefault: vi.fn(),
|
|
29
|
+
stopPropagation: vi.fn(),
|
|
30
|
+
} as unknown as KeyboardEvent);
|
|
31
|
+
|
|
32
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('nestKeyboardContext nests attendable ids under graph root', ({ expect }) => {
|
|
36
|
+
expect(nestKeyboardContext(undefined)).to.equal('root');
|
|
37
|
+
expect(nestKeyboardContext('')).to.equal('root');
|
|
38
|
+
expect(nestKeyboardContext('root')).to.equal('root');
|
|
39
|
+
expect(nestKeyboardContext('plank-1')).to.equal('root/plank-1');
|
|
40
|
+
expect(nestKeyboardContext('root/plank-1')).to.equal('root/plank-1');
|
|
41
|
+
});
|
|
15
42
|
});
|
package/src/keyboard.ts
CHANGED
|
@@ -57,6 +57,20 @@ class KeyboardContext {
|
|
|
57
57
|
|
|
58
58
|
const ROOT = '';
|
|
59
59
|
|
|
60
|
+
/** Graph root segment; matches `@dxos/plugin-graph` `Node.RootId`. */
|
|
61
|
+
export const GRAPH_ROOT_ID = 'root';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Nest an attendable segment under the graph root so plank context inherits root-level bindings.
|
|
65
|
+
* An empty/absent segment resolves to the graph root itself.
|
|
66
|
+
*/
|
|
67
|
+
export const nestKeyboardContext = (segment?: string): string =>
|
|
68
|
+
segment
|
|
69
|
+
? segment === GRAPH_ROOT_ID || segment.startsWith(`${GRAPH_ROOT_ID}/`)
|
|
70
|
+
? segment
|
|
71
|
+
: `${GRAPH_ROOT_ID}/${segment}`
|
|
72
|
+
: GRAPH_ROOT_ID;
|
|
73
|
+
|
|
60
74
|
/**
|
|
61
75
|
* Manages context-aware key bindings.
|
|
62
76
|
*/
|
|
@@ -123,10 +137,10 @@ export class Keyboard {
|
|
|
123
137
|
const isInput =
|
|
124
138
|
tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');
|
|
125
139
|
|
|
126
|
-
// Normalized key binding (order
|
|
127
|
-
const str =
|
|
128
|
-
.filter(Boolean)
|
|
129
|
-
|
|
140
|
+
// Normalized key binding (order and case; see parseShortcut).
|
|
141
|
+
const str = parseShortcut(
|
|
142
|
+
[ctrlKey && 'ctrl', shiftKey && 'shift', altKey && 'alt', metaKey && 'meta', key].filter(Boolean).join('+'),
|
|
143
|
+
);
|
|
130
144
|
|
|
131
145
|
// Scan matching contexts.
|
|
132
146
|
for (let i = this._contexts.length - 1; i >= 0; --i) {
|