summaryrefslogtreecommitdiff
path: root/packages/frontend/src/utility/key-event.ts
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-03-09 14:28:01 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-03-09 14:28:01 +0900
commitbe7e3b9a0cb81b78a744993fef2fa2fd2833fa9c (patch)
treec82e18ce93ec0a24c57d7e36eb54a09266b3a25b /packages/frontend/src/utility/key-event.ts
parentenhnace(frontend): 文字列比較のためのローマナイズを強化(... (diff)
downloadsharkey-be7e3b9a0cb81b78a744993fef2fa2fd2833fa9c.tar.gz
sharkey-be7e3b9a0cb81b78a744993fef2fa2fd2833fa9c.tar.bz2
sharkey-be7e3b9a0cb81b78a744993fef2fa2fd2833fa9c.zip
refactor(frontend): scripts -> utility
Diffstat (limited to 'packages/frontend/src/utility/key-event.ts')
-rw-r--r--packages/frontend/src/utility/key-event.ts153
1 files changed, 153 insertions, 0 deletions
diff --git a/packages/frontend/src/utility/key-event.ts b/packages/frontend/src/utility/key-event.ts
new file mode 100644
index 0000000000..020a6c2174
--- /dev/null
+++ b/packages/frontend/src/utility/key-event.ts
@@ -0,0 +1,153 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+/**
+ * {@link KeyboardEvent.code} の値を表す文字列。不足分は適宜追加する
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
+ */
+export type KeyCode = (
+ | 'Backspace'
+ | 'Tab'
+ | 'Enter'
+ | 'Shift'
+ | 'Control'
+ | 'Alt'
+ | 'Pause'
+ | 'CapsLock'
+ | 'Escape'
+ | 'Space'
+ | 'PageUp'
+ | 'PageDown'
+ | 'End'
+ | 'Home'
+ | 'ArrowLeft'
+ | 'ArrowUp'
+ | 'ArrowRight'
+ | 'ArrowDown'
+ | 'Insert'
+ | 'Delete'
+ | 'Digit0'
+ | 'Digit1'
+ | 'Digit2'
+ | 'Digit3'
+ | 'Digit4'
+ | 'Digit5'
+ | 'Digit6'
+ | 'Digit7'
+ | 'Digit8'
+ | 'Digit9'
+ | 'KeyA'
+ | 'KeyB'
+ | 'KeyC'
+ | 'KeyD'
+ | 'KeyE'
+ | 'KeyF'
+ | 'KeyG'
+ | 'KeyH'
+ | 'KeyI'
+ | 'KeyJ'
+ | 'KeyK'
+ | 'KeyL'
+ | 'KeyM'
+ | 'KeyN'
+ | 'KeyO'
+ | 'KeyP'
+ | 'KeyQ'
+ | 'KeyR'
+ | 'KeyS'
+ | 'KeyT'
+ | 'KeyU'
+ | 'KeyV'
+ | 'KeyW'
+ | 'KeyX'
+ | 'KeyY'
+ | 'KeyZ'
+ | 'MetaLeft'
+ | 'MetaRight'
+ | 'ContextMenu'
+ | 'F1'
+ | 'F2'
+ | 'F3'
+ | 'F4'
+ | 'F5'
+ | 'F6'
+ | 'F7'
+ | 'F8'
+ | 'F9'
+ | 'F10'
+ | 'F11'
+ | 'F12'
+ | 'NumLock'
+ | 'ScrollLock'
+ | 'Semicolon'
+ | 'Equal'
+ | 'Comma'
+ | 'Minus'
+ | 'Period'
+ | 'Slash'
+ | 'Backquote'
+ | 'BracketLeft'
+ | 'Backslash'
+ | 'BracketRight'
+ | 'Quote'
+ | 'Meta'
+ | 'AltGraph'
+);
+
+/**
+ * 修飾キーを表す文字列。不足分は適宜追加する。
+ */
+export type KeyModifier = (
+ | 'Shift'
+ | 'Control'
+ | 'Alt'
+ | 'Meta'
+);
+
+/**
+ * 押下されたキー以外の状態を表す文字列。不足分は適宜追加する。
+ */
+export type KeyState = (
+ | 'composing'
+ | 'repeat'
+);
+
+export type KeyEventHandler = {
+ modifiers?: KeyModifier[];
+ states?: KeyState[];
+ code: KeyCode | 'any';
+ handler: (event: KeyboardEvent) => void;
+};
+
+export function handleKeyEvent(event: KeyboardEvent, handlers: KeyEventHandler[]) {
+ function checkModifier(ev: KeyboardEvent, modifiers? : KeyModifier[]) {
+ if (modifiers) {
+ return modifiers.every(modifier => ev.getModifierState(modifier));
+ }
+ return true;
+ }
+
+ function checkState(ev: KeyboardEvent, states?: KeyState[]) {
+ if (states) {
+ return states.every(state => ev.getModifierState(state));
+ }
+ return true;
+ }
+
+ let hit = false;
+ for (const handler of handlers.filter(it => it.code === event.code)) {
+ if (checkModifier(event, handler.modifiers) && checkState(event, handler.states)) {
+ handler.handler(event);
+ hit = true;
+ break;
+ }
+ }
+
+ if (!hit) {
+ for (const handler of handlers.filter(it => it.code === 'any')) {
+ handler.handler(event);
+ }
+ }
+}