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