@dxos/keyboard 0.3.11-main.d7d4c52 → 0.3.11-main.d8b8a39
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/README.md +159 -24
- package/dist/lib/browser/index.mjs +52 -16
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +52 -16
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/keyboard.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/keyboard.ts +4 -3
- package/src/util.ts +56 -14
package/README.md
CHANGED
|
@@ -1,28 +1,163 @@
|
|
|
1
|
-
##
|
|
1
|
+
## @dxos/keyboard
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utility for managing contextual keyboard bindings.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Common Shortcuts
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"jsdom": true,
|
|
11
|
-
"testingFramework": "mocha"
|
|
12
|
-
}
|
|
13
|
-
```
|
|
7
|
+
- Meta => Command (macos), Windows (Windows), Super (Linux)
|
|
8
|
+
- Alt => Option (macos)
|
|
9
|
+
- Tip: Use https://tableconvert.com/markdown-to-markdown to edit the table.
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
11
|
+
| | macos | windows | chrome (macos) | chrome (windows) |
|
|
12
|
+
|-------------------|------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------|-----------------------------------------------------------------------------------|
|
|
13
|
+
| | https://support.apple.com/en-us/HT201236 | https://support.microsoft.com/en-us/windows/keyboard-shortcuts-in-windows-dcc61a57-8ff0-cffe-9796-cb9706c75eec | | https://support.google.com/chrome/answer/157179?hl=en&co=GENIE.Platform%3DDesktop |
|
|
14
|
+
| Alt-Tab | | x | | |
|
|
15
|
+
| Alt-F4 | | x | | |
|
|
16
|
+
| Alt-F8 | | x | | |
|
|
17
|
+
| Alt-Esc | | x | | |
|
|
18
|
+
| Alt-Enter | | x | | |
|
|
19
|
+
| Alt-Space | | x | | |
|
|
20
|
+
| Alt-A | | x | | |
|
|
21
|
+
| Alt-E | | | | x |
|
|
22
|
+
| Alt-F | | | | x |
|
|
23
|
+
| Alt-Meta-Esc | x | | | |
|
|
24
|
+
| Alt-Meta-Enter | | x | | |
|
|
25
|
+
| Alt-Meta-B | | x | x | |
|
|
26
|
+
| Alt-Meta-F | | | x | |
|
|
27
|
+
| Alt-Meta-I | | | x | |
|
|
28
|
+
| Alt-Meta-J | | | x | |
|
|
29
|
+
| Alt-Meta-K | | x | | |
|
|
30
|
+
| Alt-Meta-P | | | x | |
|
|
31
|
+
| Alt-Meta-R | | x | | |
|
|
32
|
+
| Alt-Meta-U | | | x | |
|
|
33
|
+
| Alt-Meta-Shift-A | | | x | |
|
|
34
|
+
| Alt-Meta-Shift-I | | | x | |
|
|
35
|
+
| "Alt-Ctrl-Meta-," | x | | | |
|
|
36
|
+
| Alt-Ctrl-Meta-. | x | | | |
|
|
37
|
+
| Alt-Ctrl-Meta-8 | x | | | |
|
|
38
|
+
| Alt-Ctrl-Tab | | x | | |
|
|
39
|
+
| Alt-Shift-A | | | | x |
|
|
40
|
+
| Alt-Shift-I | | | | x |
|
|
41
|
+
| Alt-Shift-T | | | | x |
|
|
42
|
+
| Ctrl-Esc | | x | | |
|
|
43
|
+
| Ctrl-Backspace | | | | x |
|
|
44
|
+
| Ctrl-Space | | x | | |
|
|
45
|
+
| Ctrl-Tab | | | | x |
|
|
46
|
+
| Ctrl-+ | | | | x |
|
|
47
|
+
| Ctrl-- | | | | x |
|
|
48
|
+
| Ctrl-F2 | x | | x | |
|
|
49
|
+
| Ctrl-F3 | x | | | |
|
|
50
|
+
| Ctrl-F4 | x | | | |
|
|
51
|
+
| Ctrl-F5 | x | | | x |
|
|
52
|
+
| Ctrl-F6 | x | | | x |
|
|
53
|
+
| Ctrl-F7 | x | | | |
|
|
54
|
+
| Ctrl-F8 | x | | | |
|
|
55
|
+
| Ctrl-F4 | | x | | |
|
|
56
|
+
| Ctrl-A | x | x | | |
|
|
57
|
+
| Ctrl-B | x | | | |
|
|
58
|
+
| Ctrl-C | | x | | |
|
|
59
|
+
| Ctrl-D | | x | | x |
|
|
60
|
+
| Ctrl-E | x | | | x |
|
|
61
|
+
| Ctrl-F | x | | | x |
|
|
62
|
+
| Ctrl-G | | | | x |
|
|
63
|
+
| Ctrl-H | | | | x |
|
|
64
|
+
| Ctrl-J | | | | x |
|
|
65
|
+
| Ctrl-K | | | | x |
|
|
66
|
+
| Ctrl-L | x | | | x |
|
|
67
|
+
| Ctrl-N | x | | | x |
|
|
68
|
+
| Ctrl-O | x | | | x |
|
|
69
|
+
| Ctrl-P | x | | | x |
|
|
70
|
+
| Ctrl-R | | x | | x |
|
|
71
|
+
| Ctrl-S | | | | x |
|
|
72
|
+
| Ctrl-T | x | | | x |
|
|
73
|
+
| Ctrl-U | | | | x |
|
|
74
|
+
| Ctrl-V | | x | | |
|
|
75
|
+
| Ctrl-W | | | | x |
|
|
76
|
+
| Ctrl-X | | x | | |
|
|
77
|
+
| Ctrl-Y | | x | | |
|
|
78
|
+
| Ctrl-Z | | x | | |
|
|
79
|
+
| Ctrl-Meta-Enter | | | | |
|
|
80
|
+
| Ctrl-Meta-Space | x | | | |
|
|
81
|
+
| Ctrl-Meta-C | | x | | |
|
|
82
|
+
| Ctrl-Meta-Q | x | x | | |
|
|
83
|
+
| Ctrl-Meta-F | x | x | x | |
|
|
84
|
+
| Ctrl-Meta-Shift-B | | x | | |
|
|
85
|
+
| Ctrl-Shift-F6 | x | | | |
|
|
86
|
+
| Ctrl-Shift-Esc | | x | | |
|
|
87
|
+
| Ctrl-Shift-Delete | | | | x |
|
|
88
|
+
| Ctrl-Shift-B | | | | x |
|
|
89
|
+
| Ctrl-Shift-D | | | | x |
|
|
90
|
+
| Ctrl-Shift-G | | | | x |
|
|
91
|
+
| Ctrl-Shift-J | | | | x |
|
|
92
|
+
| Ctrl-Shift-M | | | | |
|
|
93
|
+
| Ctrl-Shift-N | | | | x |
|
|
94
|
+
| Ctrl-Shift-O | | | | x |
|
|
95
|
+
| Ctrl-Shift-R | | | | x |
|
|
96
|
+
| Ctrl-Shift-T | | | | x |
|
|
97
|
+
| Ctrl-Shift-V | | x | | |
|
|
98
|
+
| Meta-. | | x | | |
|
|
99
|
+
| Meta-; | | x | | |
|
|
100
|
+
| "Meta-," | | x | x | |
|
|
101
|
+
| Meta-` | x | | | |
|
|
102
|
+
| Meta-+ | | x | x | |
|
|
103
|
+
| Meta-- | | x | x | |
|
|
104
|
+
| Meta-/ | | x | | |
|
|
105
|
+
| Meta-[ | | | x | |
|
|
106
|
+
| Meta-] | | | x | |
|
|
107
|
+
| Meta-Backspace | x | | | |
|
|
108
|
+
| Meta-Esc | | x | | |
|
|
109
|
+
| Meta-Space | x | x | | |
|
|
110
|
+
| Meta-Tab | x | x | | |
|
|
111
|
+
| Meta-A | x | x | | |
|
|
112
|
+
| Meta-B | | x | | |
|
|
113
|
+
| Meta-C | x | x | | |
|
|
114
|
+
| Meta-D | | x | x | |
|
|
115
|
+
| Meta-E | | x | x | |
|
|
116
|
+
| Meta-F | x | x | x | |
|
|
117
|
+
| Meta-G | x | x | x | |
|
|
118
|
+
| Meta-H | x | x | x | |
|
|
119
|
+
| Meta-I | | x | | |
|
|
120
|
+
| Meta-J | | x | | |
|
|
121
|
+
| Meta-K | | x | | |
|
|
122
|
+
| Meta-L | | x | x | |
|
|
123
|
+
| Meta-M | x | x | x | |
|
|
124
|
+
| Meta-N | | x | x | |
|
|
125
|
+
| Meta-O | x | x | x | |
|
|
126
|
+
| Meta-P | x | x | x | |
|
|
127
|
+
| Meta-Q | x | x | x | |
|
|
128
|
+
| Meta-R | | x | | |
|
|
129
|
+
| Meta-S | x | x | x | |
|
|
130
|
+
| Meta-T | x | x | x | |
|
|
131
|
+
| Meta-U | | x | | |
|
|
132
|
+
| Meta-V | x | x | | |
|
|
133
|
+
| Meta-W | x | x | x | |
|
|
134
|
+
| Meta-X | x | x | | |
|
|
135
|
+
| Meta-Y | | x | x | |
|
|
136
|
+
| Meta-Z | x | x | | |
|
|
137
|
+
| Meta-Shift-Space | | x | | |
|
|
138
|
+
| Meta-Shift-Delete | | | x | |
|
|
139
|
+
| Meta-Shift-+ | x | | | |
|
|
140
|
+
| Meta-Shift-- | x | | | |
|
|
141
|
+
| Meta-Shift-? | x | | | |
|
|
142
|
+
| Meta-Shift-3 | x | | | |
|
|
143
|
+
| Meta-Shift-4 | x | | | |
|
|
144
|
+
| Meta-Shift-5 | x | | | |
|
|
145
|
+
| Meta-Shift-B | | | x | |
|
|
146
|
+
| Meta-Shift-C | | x | | |
|
|
147
|
+
| Meta-Shift-D | | | x | |
|
|
148
|
+
| Meta-Shift-G | | | x | |
|
|
149
|
+
| Meta-Shift-H | | | x | |
|
|
150
|
+
| Meta-Shift-I | | | x | |
|
|
151
|
+
| Meta-Shift-J | | | x | |
|
|
152
|
+
| Meta-Shift-M | | x | x | |
|
|
153
|
+
| Meta-Shift-N | | | x | |
|
|
154
|
+
| Meta-Shift-R | | | | |
|
|
155
|
+
| Meta-Shift-S | x | x | | |
|
|
156
|
+
| Meta-Shift-T | | | x | |
|
|
157
|
+
| Meta-Shift-V | | x | | |
|
|
158
|
+
| Meta-Shift-W | | | x | |
|
|
159
|
+
| Meta-Shift-Q | x | | | |
|
|
160
|
+
| Meta-Shift-` | x | | | |
|
|
161
|
+
| Alt-Meta-` | x | | | |
|
|
162
|
+
| Ctrl-Tab | x | | | |
|
|
163
|
+
| Ctrl-Shift-Tab | x | | | |
|
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
import { invariant } from "@dxos/invariant";
|
|
12
12
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keyboard/src/keyboard.ts";
|
|
13
13
|
var modifiers = [
|
|
14
|
-
"alt",
|
|
15
14
|
"ctrl",
|
|
16
15
|
"shift",
|
|
16
|
+
"alt",
|
|
17
17
|
"meta"
|
|
18
18
|
];
|
|
19
19
|
var parseShortcut = (shortcut, delimiter = /[+-]/) => {
|
|
20
|
-
const parts = shortcut.split(delimiter);
|
|
20
|
+
const parts = shortcut.toLowerCase().split(delimiter);
|
|
21
21
|
const mods = modifiers.filter((key) => parts.includes(key));
|
|
22
22
|
invariant(mods.length === 0 || mods.length === parts.length - 1, void 0, {
|
|
23
23
|
F: __dxlog_file,
|
|
24
|
-
L:
|
|
24
|
+
L: 29,
|
|
25
25
|
S: void 0,
|
|
26
26
|
A: [
|
|
27
27
|
"mods.length === 0 || mods.length === parts.length - 1",
|
|
@@ -142,22 +142,58 @@ var Keyboard = class _Keyboard {
|
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
// packages/common/keyboard/src/util.ts
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
145
|
+
import { getHostPlatform } from "@dxos/util";
|
|
146
|
+
var ctrl = {
|
|
147
|
+
macos: "\u2303",
|
|
148
|
+
ios: "\u2303",
|
|
149
|
+
windows: "Ctrl",
|
|
150
|
+
linux: "Ctrl",
|
|
151
|
+
unknown: "Ctrl"
|
|
152
|
+
};
|
|
153
|
+
var alt = {
|
|
154
|
+
macos: "\u2325",
|
|
155
|
+
ios: "\u2325",
|
|
156
|
+
windows: "Alt",
|
|
157
|
+
linux: "Alt",
|
|
158
|
+
unknown: "Alt"
|
|
159
|
+
};
|
|
160
|
+
var meta = {
|
|
161
|
+
macos: "\u2318",
|
|
162
|
+
ios: "\u2318",
|
|
163
|
+
windows: "\u229E",
|
|
164
|
+
// TODO(wittjosiah): Use ⌘ or ⊞ instead? Wait for user feedback.
|
|
165
|
+
// From https://en.wikipedia.org/wiki/Super_key_(keyboard_button).
|
|
166
|
+
linux: "\u2756",
|
|
167
|
+
unknown: "\u2756"
|
|
168
|
+
};
|
|
169
|
+
var getSymbol = (part) => {
|
|
170
|
+
const platform = getHostPlatform();
|
|
171
|
+
switch (part.toLowerCase()) {
|
|
172
|
+
case "alt":
|
|
173
|
+
return alt[platform];
|
|
174
|
+
case "ctrl":
|
|
175
|
+
return ctrl[platform];
|
|
176
|
+
case "meta":
|
|
177
|
+
return meta[platform];
|
|
178
|
+
case "shift":
|
|
179
|
+
return "\u21E7";
|
|
180
|
+
case "backspace":
|
|
181
|
+
return "\u232B";
|
|
182
|
+
case "enter":
|
|
183
|
+
return "\u23CE";
|
|
184
|
+
case "escape":
|
|
185
|
+
return "\u238B";
|
|
186
|
+
case "space":
|
|
187
|
+
return "\u2423";
|
|
188
|
+
case "tab":
|
|
189
|
+
return "\u21E5";
|
|
190
|
+
default:
|
|
191
|
+
return part.toUpperCase();
|
|
192
|
+
}
|
|
157
193
|
};
|
|
158
194
|
var keySymbols = (keyBinding) => {
|
|
159
195
|
const parts = keyBinding.split("+");
|
|
160
|
-
return parts.map(
|
|
196
|
+
return parts.map(getSymbol);
|
|
161
197
|
};
|
|
162
198
|
export {
|
|
163
199
|
Keyboard,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/keyboard.ts", "../../../src/util.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n shortcut: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n shortcut: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\n// Keybinding is normalized to this order.\nconst modifiers = ['
|
|
5
|
-
"mappings": ";;;;;;;;;;AAIA,SAASA,iBAAiB;;
|
|
6
|
-
"names": ["invariant", "modifiers", "parseShortcut", "shortcut", "delimiter", "parts", "split", "mods", "filter", "key", "includes", "length", "join", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "sort", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n shortcut: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n shortcut: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\n// Keybinding is normalized to this order.\n// https://support.apple.com/en-us/HT201236\nconst modifiers = ['ctrl', 'shift', 'alt', 'meta'];\n\n// Normalize order and case of modifiers.\nexport const parseShortcut = (shortcut: string, delimiter = /[+-]/): string => {\n const parts = shortcut.toLowerCase().split(delimiter);\n const mods = modifiers.filter((key) => parts.includes(key));\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n // Assume single natural key.\n return mods.length ? [...mods, parts[parts.length - 1]].join('+') : shortcut;\n};\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n config.shortcut = parseShortcut(config.shortcut);\n this._keyMap.set(config.shortcut, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setCurrentContext(path = ROOT) {\n this._path = path;\n }\n\n getCurrentContext() {\n return this._path;\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.shortcut, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // Binding option to check for input or contenteditable.\n const tagName = (event.target as any)?.tagName;\n const isInput =\n tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');\n\n // Normalized key binding.\n const str = [altKey && 'alt', ctrlKey && 'ctrl', shiftKey && 'shift', metaKey && 'meta', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};\n if (handler && (!isInput || !disableInput)) {\n const result = handler({ context: path, shortcut: str, data, event });\n if (result !== false) {\n // TODO(burdon): This doesn't prevent actions in markdown editor.\n // Reference: https://codemirror.net/docs/ref/#view.KeyBinding\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { getHostPlatform } from '@dxos/util';\n\n// Resources.\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://developer.apple.com/design/human-interface-guidelines/designing-for-macos\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\nconst ctrl: Record<string, string> = {\n macos: '⌃',\n ios: '⌃',\n windows: 'Ctrl',\n linux: 'Ctrl',\n unknown: 'Ctrl',\n};\n\nconst alt: Record<string, string> = {\n macos: '⌥',\n ios: '⌥',\n windows: 'Alt',\n linux: 'Alt',\n unknown: 'Alt',\n};\n\nconst meta: Record<string, string> = {\n macos: '⌘',\n ios: '⌘',\n windows: '⊞',\n // TODO(wittjosiah): Use ⌘ or ⊞ instead? Wait for user feedback.\n // From https://en.wikipedia.org/wiki/Super_key_(keyboard_button).\n linux: '❖',\n unknown: '❖',\n};\n\nconst getSymbol = (part: string) => {\n const platform = getHostPlatform();\n switch (part.toLowerCase()) {\n // Mods.\n case 'alt':\n return alt[platform];\n case 'ctrl':\n return ctrl[platform];\n case 'meta':\n return meta[platform];\n case 'shift':\n return '⇧';\n // Special keys.\n case 'backspace':\n return '⌫';\n case 'enter':\n return '⏎';\n case 'escape':\n return '⎋';\n case 'space':\n return '␣';\n case 'tab':\n return '⇥';\n default:\n return part.toUpperCase();\n }\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map(getSymbol);\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["invariant", "modifiers", "parseShortcut", "shortcut", "delimiter", "parts", "toLowerCase", "split", "mods", "filter", "key", "includes", "length", "join", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "sort", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "getHostPlatform", "ctrl", "macos", "ios", "windows", "linux", "unknown", "alt", "meta", "getSymbol", "part", "platform", "getHostPlatform", "toLowerCase", "toUpperCase", "keySymbols", "keyBinding", "parts", "split", "map"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/keyboard.ts":{"bytes":
|
|
1
|
+
{"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/keyboard.ts":{"bytes":15618,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":5668,"imports":[{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":10471},"packages/common/keyboard/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols","parseShortcut"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"inject-globals:@inject-globals":{"bytesInOutput":79},"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3637},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":1150}},"bytes":5109}}}
|
package/dist/lib/node/index.cjs
CHANGED
|
@@ -24,19 +24,20 @@ __export(node_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(node_exports);
|
|
26
26
|
var import_invariant = require("@dxos/invariant");
|
|
27
|
+
var import_util = require("@dxos/util");
|
|
27
28
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keyboard/src/keyboard.ts";
|
|
28
29
|
var modifiers = [
|
|
29
|
-
"alt",
|
|
30
30
|
"ctrl",
|
|
31
31
|
"shift",
|
|
32
|
+
"alt",
|
|
32
33
|
"meta"
|
|
33
34
|
];
|
|
34
35
|
var parseShortcut = (shortcut, delimiter = /[+-]/) => {
|
|
35
|
-
const parts = shortcut.split(delimiter);
|
|
36
|
+
const parts = shortcut.toLowerCase().split(delimiter);
|
|
36
37
|
const mods = modifiers.filter((key) => parts.includes(key));
|
|
37
38
|
(0, import_invariant.invariant)(mods.length === 0 || mods.length === parts.length - 1, void 0, {
|
|
38
39
|
F: __dxlog_file,
|
|
39
|
-
L:
|
|
40
|
+
L: 29,
|
|
40
41
|
S: void 0,
|
|
41
42
|
A: [
|
|
42
43
|
"mods.length === 0 || mods.length === parts.length - 1",
|
|
@@ -155,22 +156,57 @@ var Keyboard = class _Keyboard {
|
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
};
|
|
158
|
-
var
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
var ctrl = {
|
|
160
|
+
macos: "\u2303",
|
|
161
|
+
ios: "\u2303",
|
|
162
|
+
windows: "Ctrl",
|
|
163
|
+
linux: "Ctrl",
|
|
164
|
+
unknown: "Ctrl"
|
|
165
|
+
};
|
|
166
|
+
var alt = {
|
|
167
|
+
macos: "\u2325",
|
|
168
|
+
ios: "\u2325",
|
|
169
|
+
windows: "Alt",
|
|
170
|
+
linux: "Alt",
|
|
171
|
+
unknown: "Alt"
|
|
172
|
+
};
|
|
173
|
+
var meta = {
|
|
174
|
+
macos: "\u2318",
|
|
175
|
+
ios: "\u2318",
|
|
176
|
+
windows: "\u229E",
|
|
177
|
+
// TODO(wittjosiah): Use ⌘ or ⊞ instead? Wait for user feedback.
|
|
178
|
+
// From https://en.wikipedia.org/wiki/Super_key_(keyboard_button).
|
|
179
|
+
linux: "\u2756",
|
|
180
|
+
unknown: "\u2756"
|
|
181
|
+
};
|
|
182
|
+
var getSymbol = (part) => {
|
|
183
|
+
const platform = (0, import_util.getHostPlatform)();
|
|
184
|
+
switch (part.toLowerCase()) {
|
|
185
|
+
case "alt":
|
|
186
|
+
return alt[platform];
|
|
187
|
+
case "ctrl":
|
|
188
|
+
return ctrl[platform];
|
|
189
|
+
case "meta":
|
|
190
|
+
return meta[platform];
|
|
191
|
+
case "shift":
|
|
192
|
+
return "\u21E7";
|
|
193
|
+
case "backspace":
|
|
194
|
+
return "\u232B";
|
|
195
|
+
case "enter":
|
|
196
|
+
return "\u23CE";
|
|
197
|
+
case "escape":
|
|
198
|
+
return "\u238B";
|
|
199
|
+
case "space":
|
|
200
|
+
return "\u2423";
|
|
201
|
+
case "tab":
|
|
202
|
+
return "\u21E5";
|
|
203
|
+
default:
|
|
204
|
+
return part.toUpperCase();
|
|
205
|
+
}
|
|
170
206
|
};
|
|
171
207
|
var keySymbols = (keyBinding) => {
|
|
172
208
|
const parts = keyBinding.split("+");
|
|
173
|
-
return parts.map(
|
|
209
|
+
return parts.map(getSymbol);
|
|
174
210
|
};
|
|
175
211
|
// Annotate the CommonJS export names for ESM import in node:
|
|
176
212
|
0 && (module.exports = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/keyboard.ts", "../../../src/util.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n shortcut: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n shortcut: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\n// Keybinding is normalized to this order.\nconst modifiers = ['
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAIA,uBAA0B;;
|
|
6
|
-
"names": ["modifiers", "parseShortcut", "shortcut", "delimiter", "parts", "split", "mods", "filter", "key", "includes", "invariant", "length", "join", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "sort", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\n\nexport type KeyHandler = (props: {\n context: string;\n shortcut: string;\n data?: any;\n event: KeyboardEvent;\n}) => boolean | void;\n\nexport type KeyBinding = {\n shortcut: string;\n handler: KeyHandler;\n disableInput?: boolean;\n data?: any;\n};\n\n// Keybinding is normalized to this order.\n// https://support.apple.com/en-us/HT201236\nconst modifiers = ['ctrl', 'shift', 'alt', 'meta'];\n\n// Normalize order and case of modifiers.\nexport const parseShortcut = (shortcut: string, delimiter = /[+-]/): string => {\n const parts = shortcut.toLowerCase().split(delimiter);\n const mods = modifiers.filter((key) => parts.includes(key));\n invariant(mods.length === 0 || mods.length === parts.length - 1);\n // Assume single natural key.\n return mods.length ? [...mods, parts[parts.length - 1]].join('+') : shortcut;\n};\n\nclass KeyboardContext {\n readonly _keyMap = new Map<string, KeyBinding>();\n\n get bindings() {\n return Array.from(this._keyMap.values());\n }\n\n get(binding: string) {\n return this._keyMap.get(binding);\n }\n\n bind(config: KeyBinding) {\n config.shortcut = parseShortcut(config.shortcut);\n this._keyMap.set(config.shortcut, config);\n }\n\n unbind(binding: string) {\n this._keyMap.delete(binding);\n }\n}\n\nconst ROOT = '';\n\n/**\n * Manages context-aware key bindings.\n */\nexport class Keyboard {\n static singleton = new Keyboard();\n\n private readonly _root = new KeyboardContext();\n private readonly _keyMap = new Map<string, KeyboardContext>([[ROOT, this._root]]);\n private readonly _contexts: string[] = [ROOT];\n private readonly _keyHandler = this.handleKeyDown.bind(this);\n private _path = ROOT;\n\n initialize() {\n document.addEventListener('keydown', this._keyHandler);\n }\n\n destroy() {\n document.removeEventListener('keydown', this._keyHandler);\n }\n\n bind = this._root.bind.bind(this._root);\n unbind = this._root.unbind.bind(this._root);\n\n setCurrentContext(path = ROOT) {\n this._path = path;\n }\n\n getCurrentContext() {\n return this._path;\n }\n\n getContext(path = ROOT): KeyboardContext {\n let context = this._keyMap.get(path);\n if (!context) {\n context = new KeyboardContext();\n this._keyMap.set(path, context);\n this._contexts.push(path);\n this._contexts.sort();\n }\n\n return context;\n }\n\n getBindings() {\n const bindings = new Map<string, KeyBinding>();\n for (let i = 0; i < this._contexts.length; ++i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n this.getContext(path).bindings.forEach((binding) => {\n bindings.set(binding.shortcut, binding);\n });\n }\n }\n\n return Array.from(bindings.values());\n }\n\n handleKeyDown(event: KeyboardEvent) {\n const { altKey, ctrlKey, metaKey, shiftKey, key } = event;\n\n if (key !== 'Alt' && key !== 'Control' && key !== 'Meta' && key !== 'Shift') {\n // Binding option to check for input or contenteditable.\n const tagName = (event.target as any)?.tagName;\n const isInput =\n tagName === 'INPUT' || tagName === 'TEXTAREA' || (event.target as any)?.getAttribute('contenteditable');\n\n // Normalized key binding.\n const str = [altKey && 'alt', ctrlKey && 'ctrl', shiftKey && 'shift', metaKey && 'meta', key]\n .filter(Boolean)\n .join('+');\n\n // Scan matching contexts.\n for (let i = this._contexts.length - 1; i >= 0; --i) {\n const path = this._contexts[i];\n if (this._path.startsWith(path)) {\n const { data, handler, disableInput } = this.getContext(path).get(str) ?? {};\n if (handler && (!isInput || !disableInput)) {\n const result = handler({ context: path, shortcut: str, data, event });\n if (result !== false) {\n // TODO(burdon): This doesn't prevent actions in markdown editor.\n // Reference: https://codemirror.net/docs/ref/#view.KeyBinding\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n }\n }\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { getHostPlatform } from '@dxos/util';\n\n// Resources.\n// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents\n// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n// https://developer.apple.com/design/human-interface-guidelines/designing-for-macos\n// https://support.apple.com/en-us/HT201236\n// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac\n\nconst ctrl: Record<string, string> = {\n macos: '⌃',\n ios: '⌃',\n windows: 'Ctrl',\n linux: 'Ctrl',\n unknown: 'Ctrl',\n};\n\nconst alt: Record<string, string> = {\n macos: '⌥',\n ios: '⌥',\n windows: 'Alt',\n linux: 'Alt',\n unknown: 'Alt',\n};\n\nconst meta: Record<string, string> = {\n macos: '⌘',\n ios: '⌘',\n windows: '⊞',\n // TODO(wittjosiah): Use ⌘ or ⊞ instead? Wait for user feedback.\n // From https://en.wikipedia.org/wiki/Super_key_(keyboard_button).\n linux: '❖',\n unknown: '❖',\n};\n\nconst getSymbol = (part: string) => {\n const platform = getHostPlatform();\n switch (part.toLowerCase()) {\n // Mods.\n case 'alt':\n return alt[platform];\n case 'ctrl':\n return ctrl[platform];\n case 'meta':\n return meta[platform];\n case 'shift':\n return '⇧';\n // Special keys.\n case 'backspace':\n return '⌫';\n case 'enter':\n return '⏎';\n case 'escape':\n return '⎋';\n case 'space':\n return '␣';\n case 'tab':\n return '⇥';\n default:\n return part.toUpperCase();\n }\n};\n\nexport const keySymbols = (keyBinding: string): string[] => {\n const parts = keyBinding.split('+');\n return parts.map(getSymbol);\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["modifiers", "parseShortcut", "shortcut", "delimiter", "parts", "toLowerCase", "split", "mods", "filter", "key", "includes", "invariant", "length", "join", "KeyboardContext", "_keyMap", "Map", "bindings", "Array", "from", "values", "get", "binding", "bind", "config", "set", "unbind", "delete", "ROOT", "Keyboard", "_root", "_contexts", "_keyHandler", "handleKeyDown", "_path", "singleton", "initialize", "document", "addEventListener", "destroy", "removeEventListener", "setCurrentContext", "path", "getCurrentContext", "getContext", "context", "push", "sort", "getBindings", "i", "startsWith", "forEach", "event", "altKey", "ctrlKey", "metaKey", "shiftKey", "tagName", "target", "isInput", "getAttribute", "str", "Boolean", "data", "handler", "disableInput", "result", "preventDefault", "stopPropagation", "ctrl", "macos", "ios", "windows", "linux", "unknown", "alt", "meta", "getSymbol", "part", "platform", "getHostPlatform", "toUpperCase", "keySymbols", "keyBinding", "map"]
|
|
7
7
|
}
|
package/dist/lib/node/meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytes":15618,"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/util.ts":{"bytes":5668,"imports":[{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/common/keyboard/src/index.ts":{"bytes":544,"imports":[{"path":"packages/common/keyboard/src/keyboard.ts","kind":"import-statement","original":"./keyboard"},{"path":"packages/common/keyboard/src/util.ts","kind":"import-statement","original":"./util"}],"format":"esm"}},"outputs":{"packages/common/keyboard/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":10462},"packages/common/keyboard/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["Keyboard","keySymbols","parseShortcut"],"entryPoint":"packages/common/keyboard/src/index.ts","inputs":{"packages/common/keyboard/src/keyboard.ts":{"bytesInOutput":3637},"packages/common/keyboard/src/index.ts":{"bytesInOutput":0},"packages/common/keyboard/src/util.ts":{"bytesInOutput":1150}},"bytes":4961}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/keyboard.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,aAAa,CAAC;CACtB,KAAK,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/keyboard.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,aAAa,CAAC;CACtB,KAAK,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;AAOF,eAAO,MAAM,aAAa,aAAc,MAAM,yBAAuB,MAMpE,CAAC;AAEF,cAAM,eAAe;IACnB,QAAQ,CAAC,OAAO,0BAAiC;IAEjD,IAAI,QAAQ,iBAEX;IAED,GAAG,CAAC,OAAO,EAAE,MAAM;IAInB,IAAI,CAAC,MAAM,EAAE,UAAU;IAKvB,MAAM,CAAC,OAAO,EAAE,MAAM;CAGvB;AAID;;GAEG;AACH,qBAAa,QAAQ;IACnB,MAAM,CAAC,SAAS,WAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0D;IAClF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAC7D,OAAO,CAAC,KAAK,CAAQ;IAErB,UAAU;IAIV,OAAO;IAIP,IAAI,+BAAoC;IACxC,MAAM,4BAAsC;IAE5C,iBAAiB,CAAC,IAAI,SAAO;IAI7B,iBAAiB;IAIjB,UAAU,CAAC,IAAI,SAAO,GAAG,eAAe;IAYxC,WAAW;IAcX,aAAa,CAAC,KAAK,EAAE,aAAa;CAkCnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"AAmEA,eAAO,MAAM,UAAU,eAAgB,MAAM,KAAG,MAAM,EAGrD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/keyboard",
|
|
3
|
-
"version": "0.3.11-main.
|
|
3
|
+
"version": "0.3.11-main.d8b8a39",
|
|
4
4
|
"description": "Keyboard bindings",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
"src"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@dxos/invariant": "0.3.11-main.
|
|
20
|
-
"@dxos/
|
|
19
|
+
"@dxos/invariant": "0.3.11-main.d8b8a39",
|
|
20
|
+
"@dxos/util": "0.3.11-main.d8b8a39",
|
|
21
|
+
"@dxos/node-std": "0.3.11-main.d8b8a39"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"react": "^18.2.0",
|
|
24
25
|
"react-dom": "^18.2.0",
|
|
25
|
-
"@dxos/react-ui": "0.3.11-main.
|
|
26
|
-
"@dxos/
|
|
27
|
-
"@dxos/
|
|
26
|
+
"@dxos/react-ui": "0.3.11-main.d8b8a39",
|
|
27
|
+
"@dxos/react-ui-theme": "0.3.11-main.d8b8a39",
|
|
28
|
+
"@dxos/storybook-utils": "0.3.11-main.d8b8a39"
|
|
28
29
|
},
|
|
29
30
|
"publishConfig": {
|
|
30
31
|
"access": "public"
|
package/src/keyboard.ts
CHANGED
|
@@ -19,11 +19,12 @@ export type KeyBinding = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
// Keybinding is normalized to this order.
|
|
22
|
-
|
|
22
|
+
// https://support.apple.com/en-us/HT201236
|
|
23
|
+
const modifiers = ['ctrl', 'shift', 'alt', 'meta'];
|
|
23
24
|
|
|
24
|
-
// Normalize order of modifiers.
|
|
25
|
+
// Normalize order and case of modifiers.
|
|
25
26
|
export const parseShortcut = (shortcut: string, delimiter = /[+-]/): string => {
|
|
26
|
-
const parts = shortcut.split(delimiter);
|
|
27
|
+
const parts = shortcut.toLowerCase().split(delimiter);
|
|
27
28
|
const mods = modifiers.filter((key) => parts.includes(key));
|
|
28
29
|
invariant(mods.length === 0 || mods.length === parts.length - 1);
|
|
29
30
|
// Assume single natural key.
|
package/src/util.ts
CHANGED
|
@@ -2,28 +2,70 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { getHostPlatform } from '@dxos/util';
|
|
6
|
+
|
|
7
|
+
// Resources.
|
|
5
8
|
// https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
|
|
6
9
|
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
|
10
|
+
// https://developer.apple.com/design/human-interface-guidelines/designing-for-macos
|
|
7
11
|
// https://support.apple.com/en-us/HT201236
|
|
8
12
|
// https://support.apple.com/guide/mac-help/what-are-those-symbols-shown-in-menus-cpmh0011/mac
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const ctrl: Record<string, string> = {
|
|
15
|
+
macos: '⌃',
|
|
16
|
+
ios: '⌃',
|
|
17
|
+
windows: 'Ctrl',
|
|
18
|
+
linux: 'Ctrl',
|
|
19
|
+
unknown: 'Ctrl',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const alt: Record<string, string> = {
|
|
23
|
+
macos: '⌥',
|
|
24
|
+
ios: '⌥',
|
|
25
|
+
windows: 'Alt',
|
|
26
|
+
linux: 'Alt',
|
|
27
|
+
unknown: 'Alt',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const meta: Record<string, string> = {
|
|
31
|
+
macos: '⌘',
|
|
32
|
+
ios: '⌘',
|
|
33
|
+
windows: '⊞',
|
|
34
|
+
// TODO(wittjosiah): Use ⌘ or ⊞ instead? Wait for user feedback.
|
|
35
|
+
// From https://en.wikipedia.org/wiki/Super_key_(keyboard_button).
|
|
36
|
+
linux: '❖',
|
|
37
|
+
unknown: '❖',
|
|
38
|
+
};
|
|
17
39
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
const getSymbol = (part: string) => {
|
|
41
|
+
const platform = getHostPlatform();
|
|
42
|
+
switch (part.toLowerCase()) {
|
|
43
|
+
// Mods.
|
|
44
|
+
case 'alt':
|
|
45
|
+
return alt[platform];
|
|
46
|
+
case 'ctrl':
|
|
47
|
+
return ctrl[platform];
|
|
48
|
+
case 'meta':
|
|
49
|
+
return meta[platform];
|
|
50
|
+
case 'shift':
|
|
51
|
+
return '⇧';
|
|
52
|
+
// Special keys.
|
|
53
|
+
case 'backspace':
|
|
54
|
+
return '⌫';
|
|
55
|
+
case 'enter':
|
|
56
|
+
return '⏎';
|
|
57
|
+
case 'escape':
|
|
58
|
+
return '⎋';
|
|
59
|
+
case 'space':
|
|
60
|
+
return '␣';
|
|
61
|
+
case 'tab':
|
|
62
|
+
return '⇥';
|
|
63
|
+
default:
|
|
64
|
+
return part.toUpperCase();
|
|
65
|
+
}
|
|
24
66
|
};
|
|
25
67
|
|
|
26
68
|
export const keySymbols = (keyBinding: string): string[] => {
|
|
27
69
|
const parts = keyBinding.split('+');
|
|
28
|
-
return parts.map(
|
|
70
|
+
return parts.map(getSymbol);
|
|
29
71
|
};
|