154 lines
2.5 KiB
TypeScript
154 lines
2.5 KiB
TypeScript
/*
|
|
* 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);
|
|
}
|
|
}
|
|
}
|