@lytjs/common-keyboard 6.5.0 → 6.6.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/index.cjs +1 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +132 -136
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
var MODIFIER_KEYS = /* @__PURE__ */ new Set([
|
|
5
|
-
"ctrl",
|
|
6
|
-
"shift",
|
|
7
|
-
"alt",
|
|
8
|
-
"meta"
|
|
9
|
-
]);
|
|
4
|
+
var MODIFIER_KEYS = /* @__PURE__ */ new Set(["ctrl", "shift", "alt", "meta"]);
|
|
10
5
|
var SPECIAL_KEYS = {
|
|
11
6
|
enter: "Enter",
|
|
12
7
|
escape: "Escape",
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAgBO,IAAM,aAAA,uBAAiC,GAAA,CAAI
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lytjs/common-keyboard\n * 轻量级键盘快捷键工具\n */\n\ndeclare const __DEV__: boolean;\n\nexport interface ParsedShortcut {\n key: string;\n ctrl: boolean;\n shift: boolean;\n alt: boolean;\n meta: boolean;\n}\n\n/** 修饰键名称集合 */\nexport const MODIFIER_KEYS: Set<string> = new Set(['ctrl', 'shift', 'alt', 'meta']);\n\n/** 特殊键名称到 KeyboardEvent.key 的映射 */\nexport const SPECIAL_KEYS: Record<string, string> = {\n enter: 'Enter',\n escape: 'Escape',\n tab: 'Tab',\n space: ' ',\n backspace: 'Backspace',\n delete: 'Delete',\n arrowup: 'ArrowUp',\n arrowdown: 'ArrowDown',\n arrowleft: 'ArrowLeft',\n arrowright: 'ArrowRight',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n f1: 'F1',\n f2: 'F2',\n f3: 'F3',\n f4: 'F4',\n f5: 'F5',\n f6: 'F6',\n f7: 'F7',\n f8: 'F8',\n f9: 'F9',\n f10: 'F10',\n f11: 'F11',\n f12: 'F12',\n};\n\n/**\n * 解析快捷键字符串为结构化对象\n *\n * @param shortcut - 快捷键字符串,如 \"ctrl+s\", \"shift+alt+t\", \"enter\"\n * @returns 解析后的快捷键对象\n */\nexport function parseShortcut(shortcut: string): ParsedShortcut {\n const parts = shortcut\n .toLowerCase()\n .split('+')\n .map((p) => p.trim());\n const result: ParsedShortcut = {\n key: '',\n ctrl: false,\n shift: false,\n alt: false,\n meta: false,\n };\n\n for (const part of parts) {\n if (part === 'ctrl' || part === 'control') {\n result.ctrl = true;\n } else if (part === 'shift') {\n result.shift = true;\n } else if (part === 'alt') {\n result.alt = true;\n } else if (part === 'meta' || part === 'cmd' || part === 'command') {\n result.meta = true;\n } else {\n // Resolve special keys\n result.key = SPECIAL_KEYS[part] || part.toUpperCase();\n }\n }\n\n return result;\n}\n\n/**\n * 匹配快捷键字符串\n *\n * @param event - KeyboardEvent\n * @param shortcut - 快捷键字符串,如 \"ctrl+s\", \"shift+alt+t\", \"enter\"\n * @returns 是否匹配\n */\nexport function matchShortcut(event: KeyboardEvent, shortcut: string): boolean {\n const parsed = parseShortcut(shortcut);\n\n return (\n event.ctrlKey === parsed.ctrl &&\n event.shiftKey === parsed.shift &&\n event.altKey === parsed.alt &&\n event.metaKey === parsed.meta &&\n event.key.toLowerCase() === parsed.key.toLowerCase()\n );\n}\n\n/**\n * 创建一个按键序列匹配器\n *\n * @param keys - 按键序列,如 [\"ctrl\", \"k\", \"s\"] 表示先按 Ctrl+K 再按 S\n * @returns 匹配函数,每次调用传入 KeyboardEvent,按顺序匹配\n */\nexport function createKeySequence(keys: string[]): (event: KeyboardEvent) => boolean {\n let currentIndex = 0;\n\n return (event: KeyboardEvent): boolean => {\n if (currentIndex >= keys.length) {\n currentIndex = 0;\n }\n\n if (matchShortcut(event, keys[currentIndex]!)) {\n currentIndex++;\n if (currentIndex >= keys.length) {\n currentIndex = 0;\n return true;\n }\n } else {\n // Reset if the sequence is broken\n currentIndex = 0;\n }\n\n return false;\n };\n}\n"]}
|
package/dist/index.mjs
CHANGED
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAgBO,IAAM,aAAA,uBAAiC,GAAA,CAAI
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @lytjs/common-keyboard\n * 轻量级键盘快捷键工具\n */\n\ndeclare const __DEV__: boolean;\n\nexport interface ParsedShortcut {\n key: string;\n ctrl: boolean;\n shift: boolean;\n alt: boolean;\n meta: boolean;\n}\n\n/** 修饰键名称集合 */\nexport const MODIFIER_KEYS: Set<string> = new Set(['ctrl', 'shift', 'alt', 'meta']);\n\n/** 特殊键名称到 KeyboardEvent.key 的映射 */\nexport const SPECIAL_KEYS: Record<string, string> = {\n enter: 'Enter',\n escape: 'Escape',\n tab: 'Tab',\n space: ' ',\n backspace: 'Backspace',\n delete: 'Delete',\n arrowup: 'ArrowUp',\n arrowdown: 'ArrowDown',\n arrowleft: 'ArrowLeft',\n arrowright: 'ArrowRight',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n f1: 'F1',\n f2: 'F2',\n f3: 'F3',\n f4: 'F4',\n f5: 'F5',\n f6: 'F6',\n f7: 'F7',\n f8: 'F8',\n f9: 'F9',\n f10: 'F10',\n f11: 'F11',\n f12: 'F12',\n};\n\n/**\n * 解析快捷键字符串为结构化对象\n *\n * @param shortcut - 快捷键字符串,如 \"ctrl+s\", \"shift+alt+t\", \"enter\"\n * @returns 解析后的快捷键对象\n */\nexport function parseShortcut(shortcut: string): ParsedShortcut {\n const parts = shortcut\n .toLowerCase()\n .split('+')\n .map((p) => p.trim());\n const result: ParsedShortcut = {\n key: '',\n ctrl: false,\n shift: false,\n alt: false,\n meta: false,\n };\n\n for (const part of parts) {\n if (part === 'ctrl' || part === 'control') {\n result.ctrl = true;\n } else if (part === 'shift') {\n result.shift = true;\n } else if (part === 'alt') {\n result.alt = true;\n } else if (part === 'meta' || part === 'cmd' || part === 'command') {\n result.meta = true;\n } else {\n // Resolve special keys\n result.key = SPECIAL_KEYS[part] || part.toUpperCase();\n }\n }\n\n return result;\n}\n\n/**\n * 匹配快捷键字符串\n *\n * @param event - KeyboardEvent\n * @param shortcut - 快捷键字符串,如 \"ctrl+s\", \"shift+alt+t\", \"enter\"\n * @returns 是否匹配\n */\nexport function matchShortcut(event: KeyboardEvent, shortcut: string): boolean {\n const parsed = parseShortcut(shortcut);\n\n return (\n event.ctrlKey === parsed.ctrl &&\n event.shiftKey === parsed.shift &&\n event.altKey === parsed.alt &&\n event.metaKey === parsed.meta &&\n event.key.toLowerCase() === parsed.key.toLowerCase()\n );\n}\n\n/**\n * 创建一个按键序列匹配器\n *\n * @param keys - 按键序列,如 [\"ctrl\", \"k\", \"s\"] 表示先按 Ctrl+K 再按 S\n * @returns 匹配函数,每次调用传入 KeyboardEvent,按顺序匹配\n */\nexport function createKeySequence(keys: string[]): (event: KeyboardEvent) => boolean {\n let currentIndex = 0;\n\n return (event: KeyboardEvent): boolean => {\n if (currentIndex >= keys.length) {\n currentIndex = 0;\n }\n\n if (matchShortcut(event, keys[currentIndex]!)) {\n currentIndex++;\n if (currentIndex >= keys.length) {\n currentIndex = 0;\n return true;\n }\n } else {\n // Reset if the sequence is broken\n currentIndex = 0;\n }\n\n return false;\n };\n}\n"]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,136 +1,132 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @lytjs/common-keyboard
|
|
3
|
-
* 轻量级键盘快捷键工具
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
declare const __DEV__: boolean;
|
|
7
|
-
|
|
8
|
-
export interface ParsedShortcut {
|
|
9
|
-
key: string;
|
|
10
|
-
ctrl: boolean;
|
|
11
|
-
shift: boolean;
|
|
12
|
-
alt: boolean;
|
|
13
|
-
meta: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** 修饰键名称集合 */
|
|
17
|
-
export const MODIFIER_KEYS: Set<string> = new Set([
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (part === '
|
|
72
|
-
result.
|
|
73
|
-
} else if (part === '
|
|
74
|
-
result.
|
|
75
|
-
} else if (part === '
|
|
76
|
-
result.
|
|
77
|
-
} else
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* @
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
event.
|
|
100
|
-
event.
|
|
101
|
-
event.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
currentIndex
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return false;
|
|
135
|
-
};
|
|
136
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/common-keyboard
|
|
3
|
+
* 轻量级键盘快捷键工具
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
declare const __DEV__: boolean;
|
|
7
|
+
|
|
8
|
+
export interface ParsedShortcut {
|
|
9
|
+
key: string;
|
|
10
|
+
ctrl: boolean;
|
|
11
|
+
shift: boolean;
|
|
12
|
+
alt: boolean;
|
|
13
|
+
meta: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** 修饰键名称集合 */
|
|
17
|
+
export const MODIFIER_KEYS: Set<string> = new Set(['ctrl', 'shift', 'alt', 'meta']);
|
|
18
|
+
|
|
19
|
+
/** 特殊键名称到 KeyboardEvent.key 的映射 */
|
|
20
|
+
export const SPECIAL_KEYS: Record<string, string> = {
|
|
21
|
+
enter: 'Enter',
|
|
22
|
+
escape: 'Escape',
|
|
23
|
+
tab: 'Tab',
|
|
24
|
+
space: ' ',
|
|
25
|
+
backspace: 'Backspace',
|
|
26
|
+
delete: 'Delete',
|
|
27
|
+
arrowup: 'ArrowUp',
|
|
28
|
+
arrowdown: 'ArrowDown',
|
|
29
|
+
arrowleft: 'ArrowLeft',
|
|
30
|
+
arrowright: 'ArrowRight',
|
|
31
|
+
home: 'Home',
|
|
32
|
+
end: 'End',
|
|
33
|
+
pageup: 'PageUp',
|
|
34
|
+
pagedown: 'PageDown',
|
|
35
|
+
f1: 'F1',
|
|
36
|
+
f2: 'F2',
|
|
37
|
+
f3: 'F3',
|
|
38
|
+
f4: 'F4',
|
|
39
|
+
f5: 'F5',
|
|
40
|
+
f6: 'F6',
|
|
41
|
+
f7: 'F7',
|
|
42
|
+
f8: 'F8',
|
|
43
|
+
f9: 'F9',
|
|
44
|
+
f10: 'F10',
|
|
45
|
+
f11: 'F11',
|
|
46
|
+
f12: 'F12',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 解析快捷键字符串为结构化对象
|
|
51
|
+
*
|
|
52
|
+
* @param shortcut - 快捷键字符串,如 "ctrl+s", "shift+alt+t", "enter"
|
|
53
|
+
* @returns 解析后的快捷键对象
|
|
54
|
+
*/
|
|
55
|
+
export function parseShortcut(shortcut: string): ParsedShortcut {
|
|
56
|
+
const parts = shortcut
|
|
57
|
+
.toLowerCase()
|
|
58
|
+
.split('+')
|
|
59
|
+
.map((p) => p.trim());
|
|
60
|
+
const result: ParsedShortcut = {
|
|
61
|
+
key: '',
|
|
62
|
+
ctrl: false,
|
|
63
|
+
shift: false,
|
|
64
|
+
alt: false,
|
|
65
|
+
meta: false,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
for (const part of parts) {
|
|
69
|
+
if (part === 'ctrl' || part === 'control') {
|
|
70
|
+
result.ctrl = true;
|
|
71
|
+
} else if (part === 'shift') {
|
|
72
|
+
result.shift = true;
|
|
73
|
+
} else if (part === 'alt') {
|
|
74
|
+
result.alt = true;
|
|
75
|
+
} else if (part === 'meta' || part === 'cmd' || part === 'command') {
|
|
76
|
+
result.meta = true;
|
|
77
|
+
} else {
|
|
78
|
+
// Resolve special keys
|
|
79
|
+
result.key = SPECIAL_KEYS[part] || part.toUpperCase();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 匹配快捷键字符串
|
|
88
|
+
*
|
|
89
|
+
* @param event - KeyboardEvent
|
|
90
|
+
* @param shortcut - 快捷键字符串,如 "ctrl+s", "shift+alt+t", "enter"
|
|
91
|
+
* @returns 是否匹配
|
|
92
|
+
*/
|
|
93
|
+
export function matchShortcut(event: KeyboardEvent, shortcut: string): boolean {
|
|
94
|
+
const parsed = parseShortcut(shortcut);
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
event.ctrlKey === parsed.ctrl &&
|
|
98
|
+
event.shiftKey === parsed.shift &&
|
|
99
|
+
event.altKey === parsed.alt &&
|
|
100
|
+
event.metaKey === parsed.meta &&
|
|
101
|
+
event.key.toLowerCase() === parsed.key.toLowerCase()
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 创建一个按键序列匹配器
|
|
107
|
+
*
|
|
108
|
+
* @param keys - 按键序列,如 ["ctrl", "k", "s"] 表示先按 Ctrl+K 再按 S
|
|
109
|
+
* @returns 匹配函数,每次调用传入 KeyboardEvent,按顺序匹配
|
|
110
|
+
*/
|
|
111
|
+
export function createKeySequence(keys: string[]): (event: KeyboardEvent) => boolean {
|
|
112
|
+
let currentIndex = 0;
|
|
113
|
+
|
|
114
|
+
return (event: KeyboardEvent): boolean => {
|
|
115
|
+
if (currentIndex >= keys.length) {
|
|
116
|
+
currentIndex = 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (matchShortcut(event, keys[currentIndex]!)) {
|
|
120
|
+
currentIndex++;
|
|
121
|
+
if (currentIndex >= keys.length) {
|
|
122
|
+
currentIndex = 0;
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
// Reset if the sequence is broken
|
|
127
|
+
currentIndex = 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return false;
|
|
131
|
+
};
|
|
132
|
+
}
|