@portabletext/editor 1.12.2 → 1.13.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/lib/index.d.mts +234 -14
- package/lib/index.d.ts +234 -14
- package/lib/index.esm.js +361 -81
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +364 -83
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +361 -81
- package/lib/index.mjs.map +1 -1
- package/package.json +10 -7
- package/src/editor/Editable.tsx +60 -5
- package/src/editor/behavior/behavior.action.insert-break.ts +21 -24
- package/src/editor/behavior/behavior.actions.ts +125 -3
- package/src/editor/behavior/behavior.code-editor.ts +86 -0
- package/src/editor/behavior/behavior.core.block-objects.ts +34 -1
- package/src/editor/behavior/behavior.core.ts +2 -0
- package/src/editor/behavior/behavior.links.ts +2 -2
- package/src/editor/behavior/behavior.markdown.ts +1 -1
- package/src/editor/behavior/behavior.types.ts +37 -2
- package/src/editor/behavior/behavior.utils.ts +2 -2
- package/src/editor/editor-machine.ts +5 -2
- package/src/editor/plugins/createWithHotKeys.ts +2 -49
- package/src/index.ts +4 -0
- package/src/utils/is-hotkey.test.ts +112 -0
- package/src/utils/is-hotkey.ts +209 -0
|
@@ -16,8 +16,8 @@ import type {BehaviorContext} from './behavior.types'
|
|
|
16
16
|
|
|
17
17
|
export function selectionIsCollapsed(context: BehaviorContext) {
|
|
18
18
|
return (
|
|
19
|
-
context.selection?.anchor.path
|
|
20
|
-
context.selection?.focus.path
|
|
19
|
+
JSON.stringify(context.selection?.anchor.path) ===
|
|
20
|
+
JSON.stringify(context.selection?.focus.path) &&
|
|
21
21
|
context.selection?.anchor.offset === context.selection?.focus.offset
|
|
22
22
|
)
|
|
23
23
|
}
|
|
@@ -71,6 +71,7 @@ export type InternalEditorEvent =
|
|
|
71
71
|
type: 'behavior event'
|
|
72
72
|
behaviorEvent: BehaviorEvent
|
|
73
73
|
editor: PortableTextSlateEditor
|
|
74
|
+
nativeEvent?: {preventDefault: () => void}
|
|
74
75
|
}
|
|
75
76
|
| {
|
|
76
77
|
type: 'behavior action intends'
|
|
@@ -271,10 +272,11 @@ export const editorMachine = setup({
|
|
|
271
272
|
|
|
272
273
|
for (const eventBehavior of eventBehaviors) {
|
|
273
274
|
const shouldRun =
|
|
274
|
-
eventBehavior.guard
|
|
275
|
+
eventBehavior.guard === undefined ||
|
|
276
|
+
eventBehavior.guard({
|
|
275
277
|
context: behaviorContext,
|
|
276
278
|
event: event.behaviorEvent,
|
|
277
|
-
})
|
|
279
|
+
})
|
|
278
280
|
|
|
279
281
|
if (!shouldRun) {
|
|
280
282
|
continue
|
|
@@ -303,6 +305,7 @@ export const editorMachine = setup({
|
|
|
303
305
|
}
|
|
304
306
|
|
|
305
307
|
if (behaviorOverwritten) {
|
|
308
|
+
event.nativeEvent?.preventDefault()
|
|
306
309
|
break
|
|
307
310
|
}
|
|
308
311
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'
|
|
2
|
-
import {isHotkey} from 'is-hotkey-esm'
|
|
3
2
|
import type {KeyboardEvent} from 'react'
|
|
4
|
-
import {Editor, Node,
|
|
3
|
+
import {Editor, Node, Range} from 'slate'
|
|
5
4
|
import type {ReactEditor} from 'slate-react'
|
|
6
5
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
7
6
|
import type {HotkeyOptions} from '../../types/options'
|
|
8
7
|
import type {SlateTextBlock, VoidElement} from '../../types/slate'
|
|
9
8
|
import {debugWithName} from '../../utils/debug'
|
|
9
|
+
import {isHotkey} from '../../utils/is-hotkey'
|
|
10
10
|
import type {EditorActor} from '../editor-machine'
|
|
11
11
|
import type {PortableTextEditor} from '../PortableTextEditor'
|
|
12
12
|
|
|
@@ -80,53 +80,6 @@ export function createWithHotkeys(
|
|
|
80
80
|
const isTab = isHotkey('tab', event.nativeEvent)
|
|
81
81
|
const isShiftEnter = isHotkey('shift+enter', event.nativeEvent)
|
|
82
82
|
const isShiftTab = isHotkey('shift+tab', event.nativeEvent)
|
|
83
|
-
const isArrowDown = isHotkey('down', event.nativeEvent)
|
|
84
|
-
const isArrowUp = isHotkey('up', event.nativeEvent)
|
|
85
|
-
|
|
86
|
-
// Check if the user is in a void block, in that case, add an empty text block below if there is no next block
|
|
87
|
-
if (isArrowDown && editor.selection) {
|
|
88
|
-
const focusBlock = Node.descendant(
|
|
89
|
-
editor,
|
|
90
|
-
editor.selection.focus.path.slice(0, 1),
|
|
91
|
-
) as SlateTextBlock | VoidElement
|
|
92
|
-
|
|
93
|
-
if (focusBlock && Editor.isVoid(editor, focusBlock)) {
|
|
94
|
-
const nextPath = Path.next(editor.selection.focus.path.slice(0, 1))
|
|
95
|
-
const nextBlock = Node.has(editor, nextPath)
|
|
96
|
-
if (!nextBlock) {
|
|
97
|
-
Transforms.insertNodes(
|
|
98
|
-
editor,
|
|
99
|
-
editor.pteCreateTextBlock({decorators: []}),
|
|
100
|
-
{
|
|
101
|
-
at: nextPath,
|
|
102
|
-
},
|
|
103
|
-
)
|
|
104
|
-
Transforms.select(editor, {path: [...nextPath, 0], offset: 0})
|
|
105
|
-
editor.onChange()
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (isArrowUp && editor.selection) {
|
|
111
|
-
const isFirstBlock = editor.selection.focus.path[0] === 0
|
|
112
|
-
const focusBlock = Node.descendant(
|
|
113
|
-
editor,
|
|
114
|
-
editor.selection.focus.path.slice(0, 1),
|
|
115
|
-
) as SlateTextBlock | VoidElement
|
|
116
|
-
|
|
117
|
-
if (isFirstBlock && focusBlock && Editor.isVoid(editor, focusBlock)) {
|
|
118
|
-
Transforms.insertNodes(
|
|
119
|
-
editor,
|
|
120
|
-
editor.pteCreateTextBlock({decorators: []}),
|
|
121
|
-
{
|
|
122
|
-
at: [0],
|
|
123
|
-
},
|
|
124
|
-
)
|
|
125
|
-
Transforms.select(editor, {path: [0, 0], offset: 0})
|
|
126
|
-
editor.onChange()
|
|
127
|
-
return
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
83
|
|
|
131
84
|
// Tab for lists
|
|
132
85
|
// Only steal tab when we are on a plain text span or we are at the start of the line (fallback if the whole block is annotated or contains a single inline object)
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,10 @@ export {
|
|
|
9
9
|
createMarkdownBehaviors,
|
|
10
10
|
type MarkdownBehaviorsConfig,
|
|
11
11
|
} from './editor/behavior/behavior.markdown'
|
|
12
|
+
export {
|
|
13
|
+
createCodeEditorBehaviors,
|
|
14
|
+
type CodeEditorBehaviorsConfig,
|
|
15
|
+
} from './editor/behavior/behavior.code-editor'
|
|
12
16
|
export {
|
|
13
17
|
defineBehavior,
|
|
14
18
|
type Behavior,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {expect, test} from 'vitest'
|
|
2
|
+
import {isHotkey, type KeyboardEventLike} from './is-hotkey'
|
|
3
|
+
|
|
4
|
+
function e(
|
|
5
|
+
value: string | number,
|
|
6
|
+
modifiers: Array<'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'> = [],
|
|
7
|
+
) {
|
|
8
|
+
return {
|
|
9
|
+
...(typeof value === 'string' ? {key: value} : {keyCode: value}),
|
|
10
|
+
altKey: modifiers.includes('altKey'),
|
|
11
|
+
ctrlKey: modifiers.includes('ctrlKey'),
|
|
12
|
+
metaKey: modifiers.includes('metaKey'),
|
|
13
|
+
shiftKey: modifiers.includes('shiftKey'),
|
|
14
|
+
} as KeyboardEventLike
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type TestCase = [string, KeyboardEventLike, boolean]
|
|
18
|
+
|
|
19
|
+
const testCases: TestCase[] = [
|
|
20
|
+
['meta', e('Meta', ['metaKey']), true],
|
|
21
|
+
['Meta', e('Meta', ['metaKey']), true],
|
|
22
|
+
['meta', e(93, ['metaKey']), true],
|
|
23
|
+
['Meta', e(93, ['metaKey']), true],
|
|
24
|
+
|
|
25
|
+
['meta+s', e('s', ['metaKey']), true],
|
|
26
|
+
['Meta+S', e('s', ['metaKey']), true],
|
|
27
|
+
['meta+s', e(83, ['metaKey']), true],
|
|
28
|
+
['Meta+S', e(83, ['metaKey']), true],
|
|
29
|
+
|
|
30
|
+
['cmd+space', e(' ', ['metaKey']), true],
|
|
31
|
+
['Cmd+Space', e(' ', ['metaKey']), true],
|
|
32
|
+
['cmd+space', e(32, ['metaKey']), true],
|
|
33
|
+
['Cmd+Space', e(32, ['metaKey']), true],
|
|
34
|
+
|
|
35
|
+
['cmd+alt?+s', e('s', ['metaKey']), true],
|
|
36
|
+
['cmd+alt?+s', e('s', ['metaKey', 'altKey']), true],
|
|
37
|
+
['cmd+alt?+s', e(83, ['metaKey']), true],
|
|
38
|
+
['cmd+alt?+s', e(83, ['metaKey', 'altKey']), true],
|
|
39
|
+
|
|
40
|
+
['Cmd+Alt?+S', e('s', ['metaKey']), true],
|
|
41
|
+
['Cmd+Alt?+S', e('s', ['metaKey', 'altKey']), true],
|
|
42
|
+
['Cmd+Alt?+S', e(83, ['metaKey']), true],
|
|
43
|
+
['Cmd+Alt?+S', e(83, ['metaKey', 'altKey']), true],
|
|
44
|
+
|
|
45
|
+
['cmd+s', e('s', ['metaKey', 'altKey']), false],
|
|
46
|
+
['Cmd+S', e('s', ['metaKey', 'altKey']), false],
|
|
47
|
+
['cmd+s', e(83, ['metaKey', 'altKey']), false],
|
|
48
|
+
['Cmd+S', e(83, ['metaKey', 'altKey']), false],
|
|
49
|
+
|
|
50
|
+
['cmd+s', e('s', ['metaKey']), true],
|
|
51
|
+
['Cmd+s', e('s', ['metaKey']), true],
|
|
52
|
+
['cmd+s', e(83, ['metaKey']), true],
|
|
53
|
+
['Cmd+s', e(83, ['metaKey']), true],
|
|
54
|
+
|
|
55
|
+
['mod+s', e('s', ['ctrlKey']), true],
|
|
56
|
+
['Mod+S', e('s', ['ctrlKey']), true],
|
|
57
|
+
['mod+s', e(83, ['ctrlKey']), true],
|
|
58
|
+
['Mod+S', e(83, ['ctrlKey']), true],
|
|
59
|
+
|
|
60
|
+
['meta+alt+s', e('s', ['metaKey', 'altKey']), true],
|
|
61
|
+
['Meta+Alt+S', e('s', ['metaKey', 'altKey']), true],
|
|
62
|
+
['meta+alt+s', e(83, ['metaKey', 'altKey']), true],
|
|
63
|
+
['Meta+Alt+S', e(83, ['metaKey', 'altKey']), true],
|
|
64
|
+
|
|
65
|
+
['?', e('?'), true],
|
|
66
|
+
['?', e('?', ['altKey']), false],
|
|
67
|
+
|
|
68
|
+
['a', e('a'), true],
|
|
69
|
+
['a', e('A'), true],
|
|
70
|
+
['A', e('a'), true],
|
|
71
|
+
['A', e('A'), true],
|
|
72
|
+
['a', e(65), true],
|
|
73
|
+
['A', e(65), true],
|
|
74
|
+
|
|
75
|
+
['a', e('a', ['ctrlKey']), false],
|
|
76
|
+
['A', e('a', ['ctrlKey']), false],
|
|
77
|
+
['a', e(65, ['ctrlKey']), false],
|
|
78
|
+
['A', e(65, ['ctrlKey']), false],
|
|
79
|
+
|
|
80
|
+
['shift', e('Shift', ['shiftKey']), true],
|
|
81
|
+
['Shift', e('Shift', ['shiftKey']), true],
|
|
82
|
+
['shift', e(16, ['shiftKey']), true],
|
|
83
|
+
['Shift', e(16, ['shiftKey']), true],
|
|
84
|
+
|
|
85
|
+
['meta+a', e('a', ['metaKey']), true],
|
|
86
|
+
['Meta+A', e('a', ['metaKey']), true],
|
|
87
|
+
['cmd+a', e(65, ['metaKey']), true],
|
|
88
|
+
['Cmd+A', e(65, ['metaKey']), true],
|
|
89
|
+
|
|
90
|
+
['enter', e('Enter'), true],
|
|
91
|
+
['Enter', e('Enter'), true],
|
|
92
|
+
['enter', e(13), true],
|
|
93
|
+
['Enter', e(13), true],
|
|
94
|
+
|
|
95
|
+
['cmd+=', e(187, ['metaKey']), true],
|
|
96
|
+
['Cmd+=', e(187, ['metaKey']), true],
|
|
97
|
+
['cmd++', e('+', ['metaKey']), true],
|
|
98
|
+
['Cmd++', e('+', ['metaKey']), true],
|
|
99
|
+
|
|
100
|
+
['meta+alt+ß', e('ß', ['metaKey', 'altKey']), true],
|
|
101
|
+
['Meta+Alt+ß', e('ß', ['metaKey', 'altKey']), true],
|
|
102
|
+
] satisfies Array<TestCase>
|
|
103
|
+
|
|
104
|
+
test(isHotkey.name, () => {
|
|
105
|
+
for (const testCase of testCases) {
|
|
106
|
+
expect(isHotkey(testCase[0], testCase[1])).toBe(testCase[2])
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
expect(() =>
|
|
110
|
+
isHotkey('ctrlalt+k', e('k', ['ctrlKey', 'altKey'])),
|
|
111
|
+
).toThrowError('Unknown modifier: "ctrlalt"')
|
|
112
|
+
})
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
export interface KeyboardEventLike {
|
|
2
|
+
key: string
|
|
3
|
+
keyCode?: number
|
|
4
|
+
altKey: boolean
|
|
5
|
+
ctrlKey: boolean
|
|
6
|
+
metaKey: boolean
|
|
7
|
+
shiftKey: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface HotKey {
|
|
11
|
+
keyCode?: number | undefined
|
|
12
|
+
key?: string | undefined
|
|
13
|
+
altKey: boolean | null
|
|
14
|
+
ctrlKey: boolean | null
|
|
15
|
+
metaKey: boolean | null
|
|
16
|
+
shiftKey: boolean | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const IS_MAC =
|
|
20
|
+
typeof window !== 'undefined' &&
|
|
21
|
+
/Mac|iPod|iPhone|iPad/.test(window.navigator.userAgent)
|
|
22
|
+
|
|
23
|
+
type Modifier = 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
|
|
24
|
+
|
|
25
|
+
const modifiers: Record<string, Modifier | undefined> = {
|
|
26
|
+
alt: 'altKey',
|
|
27
|
+
control: 'ctrlKey',
|
|
28
|
+
meta: 'metaKey',
|
|
29
|
+
shift: 'shiftKey',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const aliases: Record<string, string | undefined> = {
|
|
33
|
+
add: '+',
|
|
34
|
+
break: 'pause',
|
|
35
|
+
cmd: 'meta',
|
|
36
|
+
command: 'meta',
|
|
37
|
+
ctl: 'control',
|
|
38
|
+
ctrl: 'control',
|
|
39
|
+
del: 'delete',
|
|
40
|
+
down: 'arrowdown',
|
|
41
|
+
esc: 'escape',
|
|
42
|
+
ins: 'insert',
|
|
43
|
+
left: 'arrowleft',
|
|
44
|
+
mod: IS_MAC ? 'meta' : 'control',
|
|
45
|
+
opt: 'alt',
|
|
46
|
+
option: 'alt',
|
|
47
|
+
return: 'enter',
|
|
48
|
+
right: 'arrowright',
|
|
49
|
+
space: ' ',
|
|
50
|
+
spacebar: ' ',
|
|
51
|
+
up: 'arrowup',
|
|
52
|
+
win: 'meta',
|
|
53
|
+
windows: 'meta',
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const keyCodes: Record<string, number | undefined> = {
|
|
57
|
+
'backspace': 8,
|
|
58
|
+
'tab': 9,
|
|
59
|
+
'enter': 13,
|
|
60
|
+
'shift': 16,
|
|
61
|
+
'control': 17,
|
|
62
|
+
'alt': 18,
|
|
63
|
+
'pause': 19,
|
|
64
|
+
'capslock': 20,
|
|
65
|
+
'escape': 27,
|
|
66
|
+
' ': 32,
|
|
67
|
+
'pageup': 33,
|
|
68
|
+
'pagedown': 34,
|
|
69
|
+
'end': 35,
|
|
70
|
+
'home': 36,
|
|
71
|
+
'arrowleft': 37,
|
|
72
|
+
'arrowup': 38,
|
|
73
|
+
'arrowright': 39,
|
|
74
|
+
'arrowdown': 40,
|
|
75
|
+
'insert': 45,
|
|
76
|
+
'delete': 46,
|
|
77
|
+
'meta': 91,
|
|
78
|
+
'numlock': 144,
|
|
79
|
+
'scrolllock': 145,
|
|
80
|
+
';': 186,
|
|
81
|
+
'=': 187,
|
|
82
|
+
',': 188,
|
|
83
|
+
'-': 189,
|
|
84
|
+
'.': 190,
|
|
85
|
+
'/': 191,
|
|
86
|
+
'`': 192,
|
|
87
|
+
'[': 219,
|
|
88
|
+
'\\': 220,
|
|
89
|
+
']': 221,
|
|
90
|
+
"'": 222,
|
|
91
|
+
'f1': 112,
|
|
92
|
+
'f2': 113,
|
|
93
|
+
'f3': 114,
|
|
94
|
+
'f4': 115,
|
|
95
|
+
'f5': 116,
|
|
96
|
+
'f6': 117,
|
|
97
|
+
'f7': 118,
|
|
98
|
+
'f8': 119,
|
|
99
|
+
'f9': 120,
|
|
100
|
+
'f10': 121,
|
|
101
|
+
'f11': 122,
|
|
102
|
+
'f12': 123,
|
|
103
|
+
'f13': 124,
|
|
104
|
+
'f14': 125,
|
|
105
|
+
'f15': 126,
|
|
106
|
+
'f16': 127,
|
|
107
|
+
'f17': 128,
|
|
108
|
+
'f18': 129,
|
|
109
|
+
'f19': 130,
|
|
110
|
+
'f20': 131,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function isHotkey(hotkey: string, event: KeyboardEventLike): boolean {
|
|
114
|
+
return compareHotkey(parseHotkey(hotkey), event)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function parseHotkey(hotkey: string): HotKey {
|
|
118
|
+
// Ensure that all the modifiers are set to false unless the hotkey has them.
|
|
119
|
+
const parsedHotkey: HotKey = {
|
|
120
|
+
altKey: false,
|
|
121
|
+
ctrlKey: false,
|
|
122
|
+
metaKey: false,
|
|
123
|
+
shiftKey: false,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Special case to handle the `+` key since we use it as a separator.
|
|
127
|
+
const hotkeySegments = hotkey.replace('++', '+add').split('+')
|
|
128
|
+
|
|
129
|
+
for (const rawHotkeySegment of hotkeySegments) {
|
|
130
|
+
const optional =
|
|
131
|
+
rawHotkeySegment.endsWith('?') && rawHotkeySegment.length > 1
|
|
132
|
+
const hotkeySegment = optional
|
|
133
|
+
? rawHotkeySegment.slice(0, -1)
|
|
134
|
+
: rawHotkeySegment
|
|
135
|
+
const keyName = toKeyName(hotkeySegment)
|
|
136
|
+
const modifier = modifiers[keyName]
|
|
137
|
+
const alias = aliases[hotkeySegment]
|
|
138
|
+
const code = keyCodes[keyName]
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
hotkeySegment.length > 1 &&
|
|
142
|
+
modifier === undefined &&
|
|
143
|
+
alias === undefined &&
|
|
144
|
+
code === undefined
|
|
145
|
+
) {
|
|
146
|
+
throw new TypeError(`Unknown modifier: "${hotkeySegment}"`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (hotkeySegments.length === 1 || modifier === undefined) {
|
|
150
|
+
parsedHotkey.key = keyName
|
|
151
|
+
parsedHotkey.keyCode = toKeyCode(hotkeySegment)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (modifier !== undefined) {
|
|
155
|
+
parsedHotkey[modifier] = optional ? null : true
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return parsedHotkey
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function compareHotkey(
|
|
163
|
+
parsedHotkey: HotKey,
|
|
164
|
+
event: KeyboardEventLike,
|
|
165
|
+
): boolean {
|
|
166
|
+
const matchingModifiers =
|
|
167
|
+
(parsedHotkey.altKey != null
|
|
168
|
+
? parsedHotkey.altKey === event.altKey
|
|
169
|
+
: true) &&
|
|
170
|
+
(parsedHotkey.ctrlKey != null
|
|
171
|
+
? parsedHotkey.ctrlKey === event.ctrlKey
|
|
172
|
+
: true) &&
|
|
173
|
+
(parsedHotkey.metaKey != null
|
|
174
|
+
? parsedHotkey.metaKey === event.metaKey
|
|
175
|
+
: true) &&
|
|
176
|
+
(parsedHotkey.shiftKey != null
|
|
177
|
+
? parsedHotkey.shiftKey === event.shiftKey
|
|
178
|
+
: true)
|
|
179
|
+
|
|
180
|
+
if (!matchingModifiers) {
|
|
181
|
+
return false
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (parsedHotkey.keyCode !== undefined && event.keyCode !== undefined) {
|
|
185
|
+
if (parsedHotkey.keyCode === 91 && event.keyCode === 93) {
|
|
186
|
+
return true
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return parsedHotkey.keyCode === event.keyCode
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
parsedHotkey.keyCode === event.keyCode ||
|
|
194
|
+
parsedHotkey.key === event.key.toLowerCase()
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function toKeyCode(name: string): number {
|
|
199
|
+
const keyName = toKeyName(name)
|
|
200
|
+
const keyCode = keyCodes[keyName] ?? keyName.toUpperCase().charCodeAt(0)
|
|
201
|
+
|
|
202
|
+
return keyCode
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function toKeyName(name: string): string {
|
|
206
|
+
const keyName = name.toLowerCase()
|
|
207
|
+
|
|
208
|
+
return aliases[keyName] ?? keyName
|
|
209
|
+
}
|