From b3d458ad3949011acb3da3acfca8384723027976 Mon Sep 17 00:00:00 2001 From: Dmitry Lazarev Date: Thu, 17 Feb 2022 18:48:33 +0500 Subject: [PATCH 1/4] Fix pressing functional keys andd add missed chars --- .changeset/dry-ducks-remain.md | 6 + packages/globals/src/index.ts | 2 +- packages/globals/src/keyboard-layout.ts | 55 ++++++- packages/keyboard/src/keyboard.ts | 9 +- packages/keyboard/src/layout.ts | 202 +++++++++++------------- packages/keyboard/test/keyboard.test.ts | 98 ++++++------ 6 files changed, 202 insertions(+), 170 deletions(-) create mode 100644 .changeset/dry-ducks-remain.md diff --git a/.changeset/dry-ducks-remain.md b/.changeset/dry-ducks-remain.md new file mode 100644 index 00000000..b54c9d71 --- /dev/null +++ b/.changeset/dry-ducks-remain.md @@ -0,0 +1,6 @@ +--- +"@interactors/globals": patch +"@interactors/keyboard": patch +--- + +Improve keyboard layout, by adding missing chars and fix pressing functional keys diff --git a/packages/globals/src/index.ts b/packages/globals/src/index.ts index 7602e714..650ba722 100644 --- a/packages/globals/src/index.ts +++ b/packages/globals/src/index.ts @@ -1,2 +1,2 @@ export * from './globals' -export { KeyboardLayout, KeyCode } from './keyboard-layout' +export * from './keyboard-layout' diff --git a/packages/globals/src/keyboard-layout.ts b/packages/globals/src/keyboard-layout.ts index 54cfd98c..ccd949ac 100644 --- a/packages/globals/src/keyboard-layout.ts +++ b/packages/globals/src/keyboard-layout.ts @@ -99,11 +99,60 @@ export type KeyCode = | "Slash" | "Backquote" | "BracketLeft" - | "Backslack" + | "Backslash" | "BracketRight" | "Quote"; +export const FunctionalKeys: KeyCode[] = [ + "Backspace", + "Tab", + "Enter", + "ShiftLeft", + "ShiftRight", + "ControlLeft", + "ControlRight", + "AltLeft", + "AltRight", + "Pause", + "CapsLock", + "Escape", + "PageUp", + "PageDown", + "End", + "Home", + "ArrowLeft", + "ArrowUp", + "ArrowRight", + "ArrowDown", + "PrintScreen", + "Insert", + "Delete", + "MetaLeft", + "MetaRight", + "ContextMenu", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "NumLock", + "ScrollLock", +]; + +export interface Key { + code: KeyCode; + key: string; + shiftKey?: true; +} + export interface KeyboardLayout { - getKey(code: KeyCode): string | undefined; - getCode(key: string): KeyCode | undefined; + getByCode(code: KeyCode): Key | undefined; + getByKey(key: string): Key | undefined; } diff --git a/packages/keyboard/src/keyboard.ts b/packages/keyboard/src/keyboard.ts index ad4a77d7..8e48fe56 100644 --- a/packages/keyboard/src/keyboard.ts +++ b/packages/keyboard/src/keyboard.ts @@ -1,4 +1,4 @@ -import { globals, KeyCode } from '@interactors/globals'; +import { FunctionalKeys, globals, KeyCode } from '@interactors/globals'; import { createInteractor } from '@interactors/core'; import { dispatchInput, dispatchKeyDown, dispatchKeyUp } from './dispatch'; @@ -19,12 +19,13 @@ const KeyboardInteractor = createInteractor('Keyboard') await interactor.perform((element) => { let activeElement = (element.ownerDocument.activeElement || element.ownerDocument.body) as HTMLElement; if(options.key && !options.code) { - options.code = globals.keyboardLayout.getCode(options.key); + options = { ...options, ...globals.keyboardLayout.getByKey(options.key) }; } if(options.code && !options.key) { - options.key = globals.keyboardLayout.getKey(options.code); + options = { ...options, ...globals.keyboardLayout.getByCode(options.code) }; } - if(dispatchKeyDown(activeElement, options) && isTextElement(activeElement)) { + let isFunctionalKey = options.code ? FunctionalKeys.includes(options.code) : false; + if(dispatchKeyDown(activeElement, options) && isTextElement(activeElement) && !isFunctionalKey) { // don't change the value if the keydown event was stopped setValue(activeElement, activeElement.value + options.key); // input is not dispatched if the keydown event was stopped diff --git a/packages/keyboard/src/layout.ts b/packages/keyboard/src/layout.ts index 9d5f56d9..c879858f 100644 --- a/packages/keyboard/src/layout.ts +++ b/packages/keyboard/src/layout.ts @@ -1,122 +1,96 @@ -import { KeyCode, KeyboardLayout } from '@interactors/globals'; +import { Key, KeyCode, KeyboardLayout } from "@interactors/globals"; -export function createKeyboardLayout(map: Iterable<[KeyCode, string]>): KeyboardLayout { - let keyMap = new Map(map); - let codeMap = new Map(Array.from(map).map(([key, value]) => [value, key])); +export const defaultKeyMap = [ + ..."0123456789".split("").map((digit) => ({ code: `Digit${digit}`, key: digit })), + ...")!@#$%^&*(".split("").map((key, digit) => ({ code: `Digit${digit}`, key, shiftKey: true })), + ..."abcdefghijklmnopqrstuvwxyz".split("").map((key) => ({ code: `Key${key.toUpperCase()}`, key })), + ..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((key) => ({ code: `Key${key}`, key, shiftKey: true })), + ...Array.from({ length: 12 }) + .map((_, digit) => `F${digit + 1}`) + .map((key) => ({ code: key, key })), + ...[ + "Backspace", + "Tab", + "Enter", + "Pause", + "CapsLock", + "Escape", + "PageUp", + "PageDown", + "End", + "Home", + "ArrowLeft", + "ArrowUp", + "ArrowRight", + "ArrowDown", + "PrintScreen", + "Insert", + "Delete", + "ContextMenu", + "NumLock", + "ScrollLock", + ].map((code) => ({ code, key: code })), + + { code: "Space", key: " " }, + { code: "AltLeft", key: "Alt" }, + { code: "AltRight", key: "Alt" }, + { code: "ShiftLeft", key: "Shift" }, + { code: "ShiftRight", key: "Shift" }, + { code: "ControlLeft", key: "Control" }, + { code: "ControlRight", key: "Control" }, + { code: "MetaLeft", key: "Meta" }, + { code: "MetaRight", key: "Meta" }, + + { code: "Semicolon", key: ";" }, + { code: "Equal", key: "=" }, + { code: "Comma", key: "," }, + { code: "Minus", key: "-" }, + { code: "Period", key: "." }, + { code: "Slash", key: "/" }, + { code: "Backquote", key: "`" }, + { code: "BracketLeft", key: "[" }, + { code: "Backslash", key: "\\" }, + { code: "BracketRight", key: "]" }, + { code: "Quote", key: "'" }, + + { code: "Semicolon", key: ":", shiftKey: true }, + { code: "Equal", key: "+", shiftKey: true }, + { code: "Comma", key: "<", shiftKey: true }, + { code: "Minus", key: "_", shiftKey: true }, + { code: "Period", key: ">", shiftKey: true }, + { code: "Slash", key: "?", shiftKey: true }, + { code: "Backquote", key: "~", shiftKey: true }, + { code: "BracketLeft", key: "{", shiftKey: true }, + { code: "Backslash", key: "|", shiftKey: true }, + { code: "BracketRight", key: "}", shiftKey: true }, + { code: "Quote", key: '"', shiftKey: true }, + + ..."0123456789".split("").map((digit) => ({ code: `Numpad${digit}`, key: digit })), + { code: "NumpadMultiply", key: "*" }, + { code: "NumpadAdd", key: "+" }, + { code: "NumpadSubtract", key: "-" }, + { code: "NumpadDecimal", key: "." }, + { code: "NumpadDivide", key: "/" }, +] as Key[]; + +export function createKeyboardLayout(override: Key[] = []): KeyboardLayout { + let codeMap = new Map(); + let keyMap = new Map(); + + [...override, ...defaultKeyMap].forEach((key) => { + codeMap.get(key.code)?.push(key) ?? codeMap.set(key.code, [key]); + keyMap.get(key.key)?.push(key) ?? keyMap.set(key.key, [key]); + }); return { - getKey(code: KeyCode): string | undefined { - return keyMap.get(code); + getByCode(code: KeyCode): Key | undefined { + return codeMap.get(code)?.[0]; }, - getCode(key: string): KeyCode | undefined { - return codeMap.get(key); + getByKey(key: string): Key | undefined { + return keyMap.get(key)?.[0]; }, - } + }; } -export const US_INTERNATIONAL = createKeyboardLayout([ - ["Backspace", "Backspace"], - ["Tab", "Tab"], - ["Enter", "Enter"], - ["ShiftLeft", "Shift"], - ["ShiftRight", "Shift"], - ["ControlLeft", "Control"], - ["ControlRight", "Control"], - ["AltLeft", "Alt"], - ["AltRight", "Alt"], - ["Pause", "Pause"], - ["CapsLock", "CapsLock"], - ["Escape", "Escape"], - ["Space", " "], - ["PageUp", "PageUp"], - ["PageDown", "PageDown"], - ["End", "End"], - ["Home", "Home"], - ["ArrowLeft", "ArrowLeft"], - ["ArrowUp", "ArrowUp"], - ["ArrowRight", "ArrowRight"], - ["ArrowDown", "ArrowDown"], - ["PrintScreen", "PrintScreen"], - ["Insert", "Insert"], - ["Delete", "Delete"], - ["Digit0", "0"], - ["Digit1", "1"], - ["Digit2", "2"], - ["Digit3", "3"], - ["Digit4", "4"], - ["Digit5", "5"], - ["Digit6", "6"], - ["Digit7", "7"], - ["Digit8", "8"], - ["Digit9", "9"], - ["KeyA", "a"], - ["KeyB", "b"], - ["KeyC", "c"], - ["KeyD", "d"], - ["KeyE", "e"], - ["KeyF", "f"], - ["KeyG", "g"], - ["KeyH", "h"], - ["KeyI", "i"], - ["KeyJ", "j"], - ["KeyK", "k"], - ["KeyL", "l"], - ["KeyM", "m"], - ["KeyN", "n"], - ["KeyO", "o"], - ["KeyP", "p"], - ["KeyQ", "q"], - ["KeyR", "r"], - ["KeyS", "s"], - ["KeyT", "t"], - ["KeyU", "u"], - ["KeyV", "v"], - ["KeyW", "w"], - ["KeyX", "x"], - ["KeyY", "y"], - ["KeyZ", "z"], - ["MetaLeft", "Meta"], - ["MetaRight", "Meta"], - ["ContextMenu", "ContextMenu"], - ["Numpad0", "0"], - ["Numpad1", "1"], - ["Numpad2", "2"], - ["Numpad3", "3"], - ["Numpad4", "4"], - ["Numpad5", "5"], - ["Numpad6", "6"], - ["Numpad7", "7"], - ["Numpad8", "8"], - ["Numpad9", "9"], - ["NumpadMultiply", "*"], - ["NumpadAdd", "+"], - ["NumpadSubtract", "-"], - ["NumpadDecimal", "."], - ["NumpadDivide", "/"], - ["F1", "F1"], - ["F2", "F2"], - ["F3", "F3"], - ["F4", "F4"], - ["F5", "F5"], - ["F6", "F6"], - ["F7", "F7"], - ["F8", "F8"], - ["F9", "F9"], - ["F10", "F10"], - ["F11", "F11"], - ["F12", "F12"], - ["NumLock", "NumLock"], - ["ScrollLock", "ScrollLock"], - ["Semicolon", ";"], - ["Equal", "="], - ["Comma", ","], - ["Minus", "-"], - ["Period", "."], - ["Slash", "/"], - ["Backquote", "`"], - ["BracketLeft", "["], - ["Backslack", "\\"], - ["BracketRight", "]"], - ["Quote", "'"], -]); +export const US_INTERNATIONAL = createKeyboardLayout(); diff --git a/packages/keyboard/test/keyboard.test.ts b/packages/keyboard/test/keyboard.test.ts index b0ed9bef..8b08ee80 100644 --- a/packages/keyboard/test/keyboard.test.ts +++ b/packages/keyboard/test/keyboard.test.ts @@ -5,7 +5,7 @@ import { Keyboard, createKeyboardLayout } from '../src'; import { dom } from './helpers'; const TextField = createInteractor('text field') - .selector('input') + .selector('input,textarea') .filters({ id: (e) => e.id, }) @@ -22,6 +22,26 @@ const Heading = createInteractor('heading') describe('Keyboard', () => { describe('press', () => { + let domFixture = ` +

+ +

+

+

+

+ + `; + it('dispatches events with the given key to the body when no element active', async () => { dom(`

@@ -39,34 +59,14 @@ describe('Keyboard', () => { `); - globals.document.getElementById('nameField'); await Keyboard.press({ key: 'w' }); await Heading({ id: 'keydown' }).has({ text: 'success w KeyW' }); await Heading({ id: 'keyup' }).has({ text: 'success w KeyW' }); }); it('dispatches events with the given key to the active element', async () => { - dom(` -

- -

-

-

-

- - `); + dom(domFixture); - globals.document.getElementById('nameField'); await TextField({ id: 'nameField' }).focus(); await Keyboard.press({ key: 'w' }); await Heading({ id: 'keydown' }).has({ text: 'success hello w KeyW' }); @@ -75,32 +75,34 @@ describe('Keyboard', () => { }); it('dispatches events with the given code to the active element', async () => { - dom(` -

- -

-

-

-

- - `); + dom(domFixture); + + + await TextField({ id: "nameField" }).focus(); + await Keyboard.press({ code: "KeyW" }); + await Heading({ id: "keydown" }).has({ text: "success hello w KeyW" }); + await Heading({ id: "keyup" }).has({ text: "success hellow w KeyW" }); + await Heading({ id: "input" }).has({ text: "success hellow insertText w" }); + }); + + it("dispatches events with the `Enter` code to the active element", async () => { + dom(domFixture); - globals.document.getElementById('nameField'); await TextField({ id: 'nameField' }).focus(); - await Keyboard.press({ code: 'KeyW' }); - await Heading({ id: 'keydown' }).has({ text: 'success hello w KeyW' }); - await Heading({ id: 'keyup' }).has({ text: 'success hellow w KeyW' }); - await Heading({ id: 'input' }).has({ text: 'success hellow insertText w' }); + await Keyboard.press({ code: 'Home' }); + await Keyboard.press({ code: 'Enter' }); + await Heading({ id: 'keydown' }).has({ text: 'success hello Enter Enter' }); + await Heading({ id: 'keyup' }).has({ text: 'success hello Enter Enter' }); + }); + + it("dispatches events with the uppercased `w` to the active element", async () => { + dom(domFixture); + + await TextField({ id: 'nameField' }).focus(); + await Keyboard.press({ key: 'W' }); + await Heading({ id: "keydown" }).has({ text: "success hello W KeyW" }); + await Heading({ id: "keyup" }).has({ text: "success helloW W KeyW" }); + await Heading({ id: "input" }).has({ text: "success helloW insertText W" }); }); }); @@ -127,8 +129,8 @@ describe('Keyboard', () => { describe('layout', () => { it('can change keyboard layout', async () => { setKeyboardLayout(createKeyboardLayout([ - ['KeyW', 'q'], - ['KeyX', 'b'], + { code: 'KeyW', key: 'q' }, + { code: 'KeyX', key: 'b' }, ])); dom(` From d99e78c08a41262db2a2e6cb6172ffe6286d47d8 Mon Sep 17 00:00:00 2001 From: wKich Date: Thu, 10 Mar 2022 16:52:39 +0500 Subject: [PATCH 2/4] Add possible key values from MDN --- packages/globals/src/keyboard-layout.ts | 362 +++++++++++++++++++++++- packages/keyboard/src/keyboard.ts | 8 +- packages/keyboard/src/layout.ts | 2 +- 3 files changed, 366 insertions(+), 6 deletions(-) diff --git a/packages/globals/src/keyboard-layout.ts b/packages/globals/src/keyboard-layout.ts index ccd949ac..6e18554c 100644 --- a/packages/globals/src/keyboard-layout.ts +++ b/packages/globals/src/keyboard-layout.ts @@ -1,3 +1,355 @@ +// NOTE: List of keys from https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values +export type KeyValue = + // Special keys + | 'Unidentified' + // Modifier keys + | 'Alt' + | 'AltGraph' + | 'CapsLock' + | 'Control' + | 'Fn' + | 'FnLock' + | 'Hyper' + | 'Meta' + | 'NumLock' + | 'ScrollLock' + | 'Shift' + | 'Super' + | 'Symbol' + | 'SymbolLock' + // Whitespace keys + | 'Enter' + | 'Tab' + | ' ' + // Navigation keys + | 'ArrowDown' + | 'ArrowLeft' + | 'ArrowRight' + | 'ArrowUp' + | 'End' + | 'Home' + | 'PageDown' + | 'PageUp' + // Editing keys + | 'Backspace' + | 'Clear' + | 'Copy' + | 'CrSel' + | 'Cut' + | 'Delete' + | 'EraseEof' + | 'ExSel' + | 'Insert' + | 'Paste' + | 'Redo' + | 'Undo' + // UI keys + | 'Accept' + | 'Again' + | 'Attn' + | 'Cancel' + | 'ContextMenu' + | 'Escape' + | 'Execute' + | 'Find' + | 'Finish' + | 'Help' + | 'Pause' + | 'Play' + | 'Props' + | 'Select' + | 'ZoomIn' + | 'ZoomOut' + // Device keys + | 'BrightnessDown' + | 'BrightnessUp' + | 'Eject' + | 'LogOff' + | 'Power' + | 'PowerOff' + | 'PrintScreen' + | 'Hibernate' + | 'Standby' + | 'WakeUp' + // Common IME keys + | 'AllCandidates' + | 'Alphanumeric' + | 'CodeInput' + | 'Compose' + | 'Convert' + | 'Dead' + | 'FinalMode' + | 'GroupFirst' + | 'GroupLast' + | 'GroupNext' + | 'GroupPrevious' + | 'ModeChange' + | 'NextCandidate' + | 'NonConvert' + | 'PreviousCandidate' + | 'Process' + | 'SingleCandidate' + // Korean keyboards only + | 'HangulMode' + | 'HanjaMode' + | 'JunjaMode' + // Japanese keyboards only + | 'Eisu' + | 'Hankaku' + | 'Hiragana' + | 'HiraganaKatakana' + | 'KanaMode' + | 'KanjiMode' + | 'Katakana' + | 'Romaji' + | 'Zenkaku' + | 'ZenkakuHanaku' + // Function keys + | 'F1' + | 'F2' + | 'F3' + | 'F4' + | 'F5' + | 'F6' + | 'F7' + | 'F8' + | 'F9' + | 'F10' + | 'F11' + | 'F12' + | 'F13' + | 'F14' + | 'F15' + | 'F16' + | 'F17' + | 'F18' + | 'F19' + | 'F20' + | 'Soft1' + | 'Soft2' + | 'Soft3' + | 'Soft4' + // Phone keys + | 'AppSwitch' + | 'Call' + | 'Camera' + | 'CameraFocus' + | 'EndCall' + | 'GoBack' + | 'GoHome' + | 'HeadsetHook' + | 'LastNumberRedial' + | 'Notification' + | 'MannerMode' + | 'VoiceDial' + // Multimedia keys + | 'ChannelDown' + | 'ChannelUp' + | 'MediaFastForward' + | 'MediaPause' + | 'MediaPlay' + | 'MediaPlayPause' + | 'MediaRecord' + | 'MediaRewind' + | 'MediaStop' + | 'MediaTrackNext' + | 'MediaTrackPrevious' + // Audio control keys + | 'AudioBalanceLeft' + | 'AudioBalanceRight' + | 'AudioBassDown' + | 'AudioBassBoostDown' + | 'AudioBassBoostToggle' + | 'AudioBassBoostUp' + | 'AudioBassUp' + | 'AudioFaderFront' + | 'AudioFaderRear' + | 'AudioSurroundModeNext' + | 'AudioTrebleDown' + | 'AudioTrebleUp' + | 'AudioVolumeDown' + | 'AudioVolumeMute' + | 'AudioVolumeUp' + | 'MicrophoneToggle' + | 'MicrophoneVolumeDown' + | 'MicrophoneVolumeMute' + | 'MicrophoneVolumeUp' + // TV control keys + | 'TV' + | 'TV3DMode' + | 'TVAntennaCable' + | 'TVAudioDescription' + | 'TVAudioDescriptionMixDown' + | 'TVAudioDescriptionMixUp' + | 'TVContentsMenu' + | 'TVDataService' + | 'TVInput' + | 'TVInputComponent1' + | 'TVInputComponent2' + | 'TVInputComposite1' + | 'TVInputComposite2' + | 'TVInputHDMI1' + | 'TVInputHDMI2' + | 'TVInputHDMI3' + | 'TVInputHDMI4' + | 'TVInputVGA1' + | 'TVMediaContext' + | 'TVNetwork' + | 'TVNumberEntry' + | 'TVPower' + | 'TVRadioService' + | 'TVSatellite' + | 'TVSatelliteBS' + | 'TVSatelliteCS' + | 'TVSatelliteToggle' + | 'TVTerrestrialAnalog' + | 'TVTerrestrialDigital' + | 'TVTimer' + // Media controller keys + | 'AVRInput' + | 'AVRPower' + | 'ColorF0Red' + | 'ColorF1Green' + | 'ColorF2Yellow' + | 'ColorF3Blue' + | 'ColorF4Grey' + | 'ColorF5Brown' + | 'ClosedCaptionToggle' + | 'Dimmer' + | 'DisplaySwap' + | 'DVR' + | 'Exit' + | 'FavoriteClear0' + | 'FavoriteClear1' + | 'FavoriteClear2' + | 'FavoriteClear3' + | 'FavoriteRecall0' + | 'FavoriteRecall1' + | 'FavoriteRecall2' + | 'FavoriteRecall3' + | 'FavoriteStore0' + | 'FavoriteStore1' + | 'FavoriteStore2' + | 'FavoriteStore3' + | 'Guide' + | 'GuideNextDay' + | 'GuidePreviousDay' + | 'Info' + | 'InstantReplay' + | 'Link' + | 'ListProgram' + | 'LiveContent' + | 'Lock' + | 'MediaApps' + | 'MediaAudioTrack' + | 'MediaLast' + | 'MediaSkipBackward' + | 'MediaSkipForward' + | 'MediaStepBackward' + | 'MediaStepForward' + | 'MediaTopMenu' + | 'NavigateIn' + | 'NavigateNext' + | 'NavigateOut' + | 'NavigatePrevious' + | 'NextFavoriteChannel' + | 'NextUserProfile' + | 'OnDemand' + | 'Pairing' + | 'PinPDown' + | 'PinPMove' + | 'PinPToggle' + | 'PinPUp' + | 'PlaySpeedDown' + | 'PlaySpeedReset' + | 'PlaySpeedUp' + | 'RandomToggle' + | 'RcLowBattery' + | 'RecordSpeedNext' + | 'RfBypass' + | 'ScanChannelsToggle' + | 'ScreenModeNext' + | 'Settings' + | 'SplitScreenToggle' + | 'STBInput' + | 'STBPower' + | 'Subtitle' + | 'Teletext' + | 'VideoModeNext' + | 'Wink' + | 'ZoomToggle' + // Speech recognition keys + | 'SpeechCorrectionList' + | 'SpeechInputToggle' + // Document keys + | 'Close' + | 'New' + | 'Open' + | 'Print' + | 'Save' + | 'SpellCheck' + | 'MailForward' + | 'MailReply' + | 'MailSend' + // Application selector keys + | 'LaunchCalculator' + | 'LaunchCalendar' + | 'LaunchContacts' + | 'LaunchMail' + | 'LaunchMediaPlayer' + | 'LaunchMusicPlayer' + | 'LaunchMyComputer' + | 'LaunchPhone' + | 'LaunchScreenSaver' + | 'LaunchSpreadsheet' + | 'LaunchWebBrowser' + | 'LaunchWebCam' + | 'LaunchWordProcessor' + | 'LaunchApplication1' + | 'LaunchApplication2' + | 'LaunchApplication3' + | 'LaunchApplication4' + | 'LaunchApplication5' + | 'LaunchApplication6' + | 'LaunchApplication7' + | 'LaunchApplication8' + | 'LaunchApplication9' + | 'LaunchApplication10' + | 'LaunchApplication11' + | 'LaunchApplication12' + | 'LaunchApplication13' + | 'LaunchApplication14' + | 'LaunchApplication15' + | 'LaunchApplication16' + // Browser control keys + | 'BrowserBack' + | 'BrowserFavorites' + | 'BrowserForward' + | 'BrowserHome' + | 'BrowserRefresh' + | 'BrowserSearch' + | 'BrowserStop' + // Numeric keypad keys + | 'Decimal' + | 'Key11' + | 'Key12' + | 'Multiply' + | 'Add' + | 'Clear' + | 'Divide' + | 'Subtract' + | 'Separator' + | '0' + | '1' + | '2' + | '3' + | '4' + | '5' + | '6' + | '7' + | '8' + | '9' + export type KeyCode = | "Backspace" | "Tab" @@ -146,12 +498,20 @@ export const FunctionalKeys: KeyCode[] = [ "ScrollLock", ]; -export interface Key { +interface CommonKey { code: KeyCode; key: string; shiftKey?: true; } +interface SpecialKey { + code: KeyCode; + key: KeyValue; + shiftKey?: true; +} + +export type Key = CommonKey | SpecialKey + export interface KeyboardLayout { getByCode(code: KeyCode): Key | undefined; getByKey(key: string): Key | undefined; diff --git a/packages/keyboard/src/keyboard.ts b/packages/keyboard/src/keyboard.ts index 8e48fe56..e540f57e 100644 --- a/packages/keyboard/src/keyboard.ts +++ b/packages/keyboard/src/keyboard.ts @@ -1,9 +1,9 @@ -import { FunctionalKeys, globals, KeyCode } from '@interactors/globals'; +import { FunctionalKeys, globals, KeyCode, KeyValue } from '@interactors/globals'; import { createInteractor } from '@interactors/core'; import { dispatchInput, dispatchKeyDown, dispatchKeyUp } from './dispatch'; -export type KeyOptions = { - key?: string; +export interface KeyOptions { + key?: K; code?: KeyCode; ctrlKey?: boolean; shiftKey?: boolean; @@ -15,7 +15,7 @@ export type KeyOptions = { const KeyboardInteractor = createInteractor('Keyboard') .selector(':root') .actions({ - async press(interactor, options: KeyOptions = {}) { + async press(interactor, options: KeyOptions | KeyOptions = {}) { await interactor.perform((element) => { let activeElement = (element.ownerDocument.activeElement || element.ownerDocument.body) as HTMLElement; if(options.key && !options.code) { diff --git a/packages/keyboard/src/layout.ts b/packages/keyboard/src/layout.ts index c879858f..1ef090c2 100644 --- a/packages/keyboard/src/layout.ts +++ b/packages/keyboard/src/layout.ts @@ -73,7 +73,7 @@ export const defaultKeyMap = [ { code: "NumpadDivide", key: "/" }, ] as Key[]; -export function createKeyboardLayout(override: Key[] = []): KeyboardLayout { +export function createKeyboardLayout(override: (Key)[] = []): KeyboardLayout { let codeMap = new Map(); let keyMap = new Map(); From 86985eb99a799ee1945b85eeafd57fd719069570 Mon Sep 17 00:00:00 2001 From: wKich Date: Fri, 11 Mar 2022 16:37:25 +0500 Subject: [PATCH 3/4] Fix filtering non-printable keys --- packages/globals/src/keyboard-layout.ts | 382 +++++++++++++++++++++--- packages/keyboard/src/keyboard.ts | 4 +- packages/keyboard/test/keyboard.test.ts | 11 + 3 files changed, 353 insertions(+), 44 deletions(-) diff --git a/packages/globals/src/keyboard-layout.ts b/packages/globals/src/keyboard-layout.ts index 6e18554c..bf3b9035 100644 --- a/packages/globals/src/keyboard-layout.ts +++ b/packages/globals/src/keyboard-layout.ts @@ -455,48 +455,346 @@ export type KeyCode = | "BracketRight" | "Quote"; -export const FunctionalKeys: KeyCode[] = [ - "Backspace", - "Tab", - "Enter", - "ShiftLeft", - "ShiftRight", - "ControlLeft", - "ControlRight", - "AltLeft", - "AltRight", - "Pause", - "CapsLock", - "Escape", - "PageUp", - "PageDown", - "End", - "Home", - "ArrowLeft", - "ArrowUp", - "ArrowRight", - "ArrowDown", - "PrintScreen", - "Insert", - "Delete", - "MetaLeft", - "MetaRight", - "ContextMenu", - "F1", - "F2", - "F3", - "F4", - "F5", - "F6", - "F7", - "F8", - "F9", - "F10", - "F11", - "F12", - "NumLock", - "ScrollLock", -]; +export const NonPrintableKeys: Set = new Set([ + // Special keys, + 'Unidentified', + // Modifier keys + 'Alt', + 'AltGraph', + 'CapsLock', + 'Control', + 'Fn', + 'FnLock', + 'Hyper', + 'Meta', + 'NumLock', + 'ScrollLock', + 'Shift', + 'Super', + 'Symbol', + 'SymbolLock', + // Whitespace keys + 'Enter', + 'Tab', + // Navigation keys + 'ArrowDown', + 'ArrowLeft', + 'ArrowRight', + 'ArrowUp', + 'End', + 'Home', + 'PageDown', + 'PageUp', + // Editing keys + 'Backspace', + 'Clear', + 'Copy', + 'CrSel', + 'Cut', + 'Delete', + 'EraseEof', + 'ExSel', + 'Insert', + 'Paste', + 'Redo', + 'Undo', + // UI keys + 'Accept', + 'Again', + 'Attn', + 'Cancel', + 'ContextMenu', + 'Escape', + 'Execute', + 'Find', + 'Finish', + 'Help', + 'Pause', + 'Play', + 'Props', + 'Select', + 'ZoomIn', + 'ZoomOut', + // Device keys + 'BrightnessDown', + 'BrightnessUp', + 'Eject', + 'LogOff', + 'Power', + 'PowerOff', + 'PrintScreen', + 'Hibernate', + 'Standby', + 'WakeUp', + // Common IME keys + 'AllCandidates', + 'Alphanumeric', + 'CodeInput', + 'Compose', + 'Convert', + 'Dead', + 'FinalMode', + 'GroupFirst', + 'GroupLast', + 'GroupNext', + 'GroupPrevious', + 'ModeChange', + 'NextCandidate', + 'NonConvert', + 'PreviousCandidate', + 'Process', + 'SingleCandidate', + // Korean keyboards only + 'HangulMode', + 'HanjaMode', + 'JunjaMode', + // Japanese keyboards only + 'Eisu', + 'Hankaku', + 'Hiragana', + 'HiraganaKatakana', + 'KanaMode', + 'KanjiMode', + 'Katakana', + 'Romaji', + 'Zenkaku', + 'ZenkakuHanaku', + // Function keys + 'F1', + 'F2', + 'F3', + 'F4', + 'F5', + 'F6', + 'F7', + 'F8', + 'F9', + 'F10', + 'F11', + 'F12', + 'F13', + 'F14', + 'F15', + 'F16', + 'F17', + 'F18', + 'F19', + 'F20', + 'Soft1', + 'Soft2', + 'Soft3', + 'Soft4', + // Phone keys + 'AppSwitch', + 'Call', + 'Camera', + 'CameraFocus', + 'EndCall', + 'GoBack', + 'GoHome', + 'HeadsetHook', + 'LastNumberRedial', + 'Notification', + 'MannerMode', + 'VoiceDial', + // Multimedia keys + 'ChannelDown', + 'ChannelUp', + 'MediaFastForward', + 'MediaPause', + 'MediaPlay', + 'MediaPlayPause', + 'MediaRecord', + 'MediaRewind', + 'MediaStop', + 'MediaTrackNext', + 'MediaTrackPrevious', + // Audio control keys + 'AudioBalanceLeft', + 'AudioBalanceRight', + 'AudioBassDown', + 'AudioBassBoostDown', + 'AudioBassBoostToggle', + 'AudioBassBoostUp', + 'AudioBassUp', + 'AudioFaderFront', + 'AudioFaderRear', + 'AudioSurroundModeNext', + 'AudioTrebleDown', + 'AudioTrebleUp', + 'AudioVolumeDown', + 'AudioVolumeMute', + 'AudioVolumeUp', + 'MicrophoneToggle', + 'MicrophoneVolumeDown', + 'MicrophoneVolumeMute', + 'MicrophoneVolumeUp', + // TV control keys + 'TV', + 'TV3DMode', + 'TVAntennaCable', + 'TVAudioDescription', + 'TVAudioDescriptionMixDown', + 'TVAudioDescriptionMixUp', + 'TVContentsMenu', + 'TVDataService', + 'TVInput', + 'TVInputComponent1', + 'TVInputComponent2', + 'TVInputComposite1', + 'TVInputComposite2', + 'TVInputHDMI1', + 'TVInputHDMI2', + 'TVInputHDMI3', + 'TVInputHDMI4', + 'TVInputVGA1', + 'TVMediaContext', + 'TVNetwork', + 'TVNumberEntry', + 'TVPower', + 'TVRadioService', + 'TVSatellite', + 'TVSatelliteBS', + 'TVSatelliteCS', + 'TVSatelliteToggle', + 'TVTerrestrialAnalog', + 'TVTerrestrialDigital', + 'TVTimer', + // Media controller keys + 'AVRInput', + 'AVRPower', + 'ColorF0Red', + 'ColorF1Green', + 'ColorF2Yellow', + 'ColorF3Blue', + 'ColorF4Grey', + 'ColorF5Brown', + 'ClosedCaptionToggle', + 'Dimmer', + 'DisplaySwap', + 'DVR', + 'Exit', + 'FavoriteClear0', + 'FavoriteClear1', + 'FavoriteClear2', + 'FavoriteClear3', + 'FavoriteRecall0', + 'FavoriteRecall1', + 'FavoriteRecall2', + 'FavoriteRecall3', + 'FavoriteStore0', + 'FavoriteStore1', + 'FavoriteStore2', + 'FavoriteStore3', + 'Guide', + 'GuideNextDay', + 'GuidePreviousDay', + 'Info', + 'InstantReplay', + 'Link', + 'ListProgram', + 'LiveContent', + 'Lock', + 'MediaApps', + 'MediaAudioTrack', + 'MediaLast', + 'MediaSkipBackward', + 'MediaSkipForward', + 'MediaStepBackward', + 'MediaStepForward', + 'MediaTopMenu', + 'NavigateIn', + 'NavigateNext', + 'NavigateOut', + 'NavigatePrevious', + 'NextFavoriteChannel', + 'NextUserProfile', + 'OnDemand', + 'Pairing', + 'PinPDown', + 'PinPMove', + 'PinPToggle', + 'PinPUp', + 'PlaySpeedDown', + 'PlaySpeedReset', + 'PlaySpeedUp', + 'RandomToggle', + 'RcLowBattery', + 'RecordSpeedNext', + 'RfBypass', + 'ScanChannelsToggle', + 'ScreenModeNext', + 'Settings', + 'SplitScreenToggle', + 'STBInput', + 'STBPower', + 'Subtitle', + 'Teletext', + 'VideoModeNext', + 'Wink', + 'ZoomToggle', + // Speech recognition keys + 'SpeechCorrectionList', + 'SpeechInputToggle', + // Document keys + 'Close', + 'New', + 'Open', + 'Print', + 'Save', + 'SpellCheck', + 'MailForward', + 'MailReply', + 'MailSend', + // Application selector keys + 'LaunchCalculator', + 'LaunchCalendar', + 'LaunchContacts', + 'LaunchMail', + 'LaunchMediaPlayer', + 'LaunchMusicPlayer', + 'LaunchMyComputer', + 'LaunchPhone', + 'LaunchScreenSaver', + 'LaunchSpreadsheet', + 'LaunchWebBrowser', + 'LaunchWebCam', + 'LaunchWordProcessor', + 'LaunchApplication1', + 'LaunchApplication2', + 'LaunchApplication3', + 'LaunchApplication4', + 'LaunchApplication5', + 'LaunchApplication6', + 'LaunchApplication7', + 'LaunchApplication8', + 'LaunchApplication9', + 'LaunchApplication10', + 'LaunchApplication11', + 'LaunchApplication12', + 'LaunchApplication13', + 'LaunchApplication14', + 'LaunchApplication15', + 'LaunchApplication16', + // Browser control keys + 'BrowserBack', + 'BrowserFavorites', + 'BrowserForward', + 'BrowserHome', + 'BrowserRefresh', + 'BrowserSearch', + 'BrowserStop', + // Numeric keypad keys + 'Decimal', + 'Key11', + 'Key12', + 'Multiply', + 'Add', + 'Clear', + 'Divide', + 'Subtract', + 'Separator' +]); interface CommonKey { code: KeyCode; diff --git a/packages/keyboard/src/keyboard.ts b/packages/keyboard/src/keyboard.ts index e540f57e..9bf4ee56 100644 --- a/packages/keyboard/src/keyboard.ts +++ b/packages/keyboard/src/keyboard.ts @@ -1,4 +1,4 @@ -import { FunctionalKeys, globals, KeyCode, KeyValue } from '@interactors/globals'; +import { NonPrintableKeys, globals, KeyCode, KeyValue } from '@interactors/globals'; import { createInteractor } from '@interactors/core'; import { dispatchInput, dispatchKeyDown, dispatchKeyUp } from './dispatch'; @@ -24,7 +24,7 @@ const KeyboardInteractor = createInteractor('Keyboard') if(options.code && !options.key) { options = { ...options, ...globals.keyboardLayout.getByCode(options.code) }; } - let isFunctionalKey = options.code ? FunctionalKeys.includes(options.code) : false; + let isFunctionalKey = options.key ? NonPrintableKeys.has(options.key as KeyValue) : false; if(dispatchKeyDown(activeElement, options) && isTextElement(activeElement) && !isFunctionalKey) { // don't change the value if the keydown event was stopped setValue(activeElement, activeElement.value + options.key); diff --git a/packages/keyboard/test/keyboard.test.ts b/packages/keyboard/test/keyboard.test.ts index 8b08ee80..eba76b30 100644 --- a/packages/keyboard/test/keyboard.test.ts +++ b/packages/keyboard/test/keyboard.test.ts @@ -93,6 +93,17 @@ describe('Keyboard', () => { await Keyboard.press({ code: 'Enter' }); await Heading({ id: 'keydown' }).has({ text: 'success hello Enter Enter' }); await Heading({ id: 'keyup' }).has({ text: 'success hello Enter Enter' }); + await Heading({ id: "input" }).has({ text: "" }); + }); + + it("dispatches events with the `Dead` key value to the active element", async () => { + dom(domFixture); + + await TextField({ id: 'nameField' }).focus(); + await Keyboard.press({ key: 'Dead' }); + await Heading({ id: 'keydown' }).has({ text: 'success hello Dead ' }); + await Heading({ id: 'keyup' }).has({ text: 'success hello Dead ' }); + await Heading({ id: "input" }).has({ text: "" }); }); it("dispatches events with the uppercased `w` to the active element", async () => { From d93827d3dd3d3c52f5935e2c373037e8b51942cd Mon Sep 17 00:00:00 2001 From: wKich Date: Mon, 14 Mar 2022 21:03:56 +0500 Subject: [PATCH 4/4] Move non-printable keys set to the keyboard package --- packages/globals/src/keyboard-layout.ts | 341 ----------------------- packages/keyboard/src/keyboard.ts | 3 +- packages/keyboard/src/keys.ts | 342 ++++++++++++++++++++++++ 3 files changed, 344 insertions(+), 342 deletions(-) create mode 100644 packages/keyboard/src/keys.ts diff --git a/packages/globals/src/keyboard-layout.ts b/packages/globals/src/keyboard-layout.ts index bf3b9035..1d3d701c 100644 --- a/packages/globals/src/keyboard-layout.ts +++ b/packages/globals/src/keyboard-layout.ts @@ -455,347 +455,6 @@ export type KeyCode = | "BracketRight" | "Quote"; -export const NonPrintableKeys: Set = new Set([ - // Special keys, - 'Unidentified', - // Modifier keys - 'Alt', - 'AltGraph', - 'CapsLock', - 'Control', - 'Fn', - 'FnLock', - 'Hyper', - 'Meta', - 'NumLock', - 'ScrollLock', - 'Shift', - 'Super', - 'Symbol', - 'SymbolLock', - // Whitespace keys - 'Enter', - 'Tab', - // Navigation keys - 'ArrowDown', - 'ArrowLeft', - 'ArrowRight', - 'ArrowUp', - 'End', - 'Home', - 'PageDown', - 'PageUp', - // Editing keys - 'Backspace', - 'Clear', - 'Copy', - 'CrSel', - 'Cut', - 'Delete', - 'EraseEof', - 'ExSel', - 'Insert', - 'Paste', - 'Redo', - 'Undo', - // UI keys - 'Accept', - 'Again', - 'Attn', - 'Cancel', - 'ContextMenu', - 'Escape', - 'Execute', - 'Find', - 'Finish', - 'Help', - 'Pause', - 'Play', - 'Props', - 'Select', - 'ZoomIn', - 'ZoomOut', - // Device keys - 'BrightnessDown', - 'BrightnessUp', - 'Eject', - 'LogOff', - 'Power', - 'PowerOff', - 'PrintScreen', - 'Hibernate', - 'Standby', - 'WakeUp', - // Common IME keys - 'AllCandidates', - 'Alphanumeric', - 'CodeInput', - 'Compose', - 'Convert', - 'Dead', - 'FinalMode', - 'GroupFirst', - 'GroupLast', - 'GroupNext', - 'GroupPrevious', - 'ModeChange', - 'NextCandidate', - 'NonConvert', - 'PreviousCandidate', - 'Process', - 'SingleCandidate', - // Korean keyboards only - 'HangulMode', - 'HanjaMode', - 'JunjaMode', - // Japanese keyboards only - 'Eisu', - 'Hankaku', - 'Hiragana', - 'HiraganaKatakana', - 'KanaMode', - 'KanjiMode', - 'Katakana', - 'Romaji', - 'Zenkaku', - 'ZenkakuHanaku', - // Function keys - 'F1', - 'F2', - 'F3', - 'F4', - 'F5', - 'F6', - 'F7', - 'F8', - 'F9', - 'F10', - 'F11', - 'F12', - 'F13', - 'F14', - 'F15', - 'F16', - 'F17', - 'F18', - 'F19', - 'F20', - 'Soft1', - 'Soft2', - 'Soft3', - 'Soft4', - // Phone keys - 'AppSwitch', - 'Call', - 'Camera', - 'CameraFocus', - 'EndCall', - 'GoBack', - 'GoHome', - 'HeadsetHook', - 'LastNumberRedial', - 'Notification', - 'MannerMode', - 'VoiceDial', - // Multimedia keys - 'ChannelDown', - 'ChannelUp', - 'MediaFastForward', - 'MediaPause', - 'MediaPlay', - 'MediaPlayPause', - 'MediaRecord', - 'MediaRewind', - 'MediaStop', - 'MediaTrackNext', - 'MediaTrackPrevious', - // Audio control keys - 'AudioBalanceLeft', - 'AudioBalanceRight', - 'AudioBassDown', - 'AudioBassBoostDown', - 'AudioBassBoostToggle', - 'AudioBassBoostUp', - 'AudioBassUp', - 'AudioFaderFront', - 'AudioFaderRear', - 'AudioSurroundModeNext', - 'AudioTrebleDown', - 'AudioTrebleUp', - 'AudioVolumeDown', - 'AudioVolumeMute', - 'AudioVolumeUp', - 'MicrophoneToggle', - 'MicrophoneVolumeDown', - 'MicrophoneVolumeMute', - 'MicrophoneVolumeUp', - // TV control keys - 'TV', - 'TV3DMode', - 'TVAntennaCable', - 'TVAudioDescription', - 'TVAudioDescriptionMixDown', - 'TVAudioDescriptionMixUp', - 'TVContentsMenu', - 'TVDataService', - 'TVInput', - 'TVInputComponent1', - 'TVInputComponent2', - 'TVInputComposite1', - 'TVInputComposite2', - 'TVInputHDMI1', - 'TVInputHDMI2', - 'TVInputHDMI3', - 'TVInputHDMI4', - 'TVInputVGA1', - 'TVMediaContext', - 'TVNetwork', - 'TVNumberEntry', - 'TVPower', - 'TVRadioService', - 'TVSatellite', - 'TVSatelliteBS', - 'TVSatelliteCS', - 'TVSatelliteToggle', - 'TVTerrestrialAnalog', - 'TVTerrestrialDigital', - 'TVTimer', - // Media controller keys - 'AVRInput', - 'AVRPower', - 'ColorF0Red', - 'ColorF1Green', - 'ColorF2Yellow', - 'ColorF3Blue', - 'ColorF4Grey', - 'ColorF5Brown', - 'ClosedCaptionToggle', - 'Dimmer', - 'DisplaySwap', - 'DVR', - 'Exit', - 'FavoriteClear0', - 'FavoriteClear1', - 'FavoriteClear2', - 'FavoriteClear3', - 'FavoriteRecall0', - 'FavoriteRecall1', - 'FavoriteRecall2', - 'FavoriteRecall3', - 'FavoriteStore0', - 'FavoriteStore1', - 'FavoriteStore2', - 'FavoriteStore3', - 'Guide', - 'GuideNextDay', - 'GuidePreviousDay', - 'Info', - 'InstantReplay', - 'Link', - 'ListProgram', - 'LiveContent', - 'Lock', - 'MediaApps', - 'MediaAudioTrack', - 'MediaLast', - 'MediaSkipBackward', - 'MediaSkipForward', - 'MediaStepBackward', - 'MediaStepForward', - 'MediaTopMenu', - 'NavigateIn', - 'NavigateNext', - 'NavigateOut', - 'NavigatePrevious', - 'NextFavoriteChannel', - 'NextUserProfile', - 'OnDemand', - 'Pairing', - 'PinPDown', - 'PinPMove', - 'PinPToggle', - 'PinPUp', - 'PlaySpeedDown', - 'PlaySpeedReset', - 'PlaySpeedUp', - 'RandomToggle', - 'RcLowBattery', - 'RecordSpeedNext', - 'RfBypass', - 'ScanChannelsToggle', - 'ScreenModeNext', - 'Settings', - 'SplitScreenToggle', - 'STBInput', - 'STBPower', - 'Subtitle', - 'Teletext', - 'VideoModeNext', - 'Wink', - 'ZoomToggle', - // Speech recognition keys - 'SpeechCorrectionList', - 'SpeechInputToggle', - // Document keys - 'Close', - 'New', - 'Open', - 'Print', - 'Save', - 'SpellCheck', - 'MailForward', - 'MailReply', - 'MailSend', - // Application selector keys - 'LaunchCalculator', - 'LaunchCalendar', - 'LaunchContacts', - 'LaunchMail', - 'LaunchMediaPlayer', - 'LaunchMusicPlayer', - 'LaunchMyComputer', - 'LaunchPhone', - 'LaunchScreenSaver', - 'LaunchSpreadsheet', - 'LaunchWebBrowser', - 'LaunchWebCam', - 'LaunchWordProcessor', - 'LaunchApplication1', - 'LaunchApplication2', - 'LaunchApplication3', - 'LaunchApplication4', - 'LaunchApplication5', - 'LaunchApplication6', - 'LaunchApplication7', - 'LaunchApplication8', - 'LaunchApplication9', - 'LaunchApplication10', - 'LaunchApplication11', - 'LaunchApplication12', - 'LaunchApplication13', - 'LaunchApplication14', - 'LaunchApplication15', - 'LaunchApplication16', - // Browser control keys - 'BrowserBack', - 'BrowserFavorites', - 'BrowserForward', - 'BrowserHome', - 'BrowserRefresh', - 'BrowserSearch', - 'BrowserStop', - // Numeric keypad keys - 'Decimal', - 'Key11', - 'Key12', - 'Multiply', - 'Add', - 'Clear', - 'Divide', - 'Subtract', - 'Separator' -]); - interface CommonKey { code: KeyCode; key: string; diff --git a/packages/keyboard/src/keyboard.ts b/packages/keyboard/src/keyboard.ts index 9bf4ee56..9fd25613 100644 --- a/packages/keyboard/src/keyboard.ts +++ b/packages/keyboard/src/keyboard.ts @@ -1,6 +1,7 @@ -import { NonPrintableKeys, globals, KeyCode, KeyValue } from '@interactors/globals'; +import { globals, KeyCode, KeyValue } from '@interactors/globals'; import { createInteractor } from '@interactors/core'; import { dispatchInput, dispatchKeyDown, dispatchKeyUp } from './dispatch'; +import { NonPrintableKeys } from './keys'; export interface KeyOptions { key?: K; diff --git a/packages/keyboard/src/keys.ts b/packages/keyboard/src/keys.ts new file mode 100644 index 00000000..d57ee092 --- /dev/null +++ b/packages/keyboard/src/keys.ts @@ -0,0 +1,342 @@ +import { KeyValue } from '@interactors/globals'; + +export const NonPrintableKeys: Set = new Set([ + // Special keys, + 'Unidentified', + // Modifier keys + 'Alt', + 'AltGraph', + 'CapsLock', + 'Control', + 'Fn', + 'FnLock', + 'Hyper', + 'Meta', + 'NumLock', + 'ScrollLock', + 'Shift', + 'Super', + 'Symbol', + 'SymbolLock', + // Whitespace keys + 'Enter', + 'Tab', + // Navigation keys + 'ArrowDown', + 'ArrowLeft', + 'ArrowRight', + 'ArrowUp', + 'End', + 'Home', + 'PageDown', + 'PageUp', + // Editing keys + 'Backspace', + 'Clear', + 'Copy', + 'CrSel', + 'Cut', + 'Delete', + 'EraseEof', + 'ExSel', + 'Insert', + 'Paste', + 'Redo', + 'Undo', + // UI keys + 'Accept', + 'Again', + 'Attn', + 'Cancel', + 'ContextMenu', + 'Escape', + 'Execute', + 'Find', + 'Finish', + 'Help', + 'Pause', + 'Play', + 'Props', + 'Select', + 'ZoomIn', + 'ZoomOut', + // Device keys + 'BrightnessDown', + 'BrightnessUp', + 'Eject', + 'LogOff', + 'Power', + 'PowerOff', + 'PrintScreen', + 'Hibernate', + 'Standby', + 'WakeUp', + // Common IME keys + 'AllCandidates', + 'Alphanumeric', + 'CodeInput', + 'Compose', + 'Convert', + 'Dead', + 'FinalMode', + 'GroupFirst', + 'GroupLast', + 'GroupNext', + 'GroupPrevious', + 'ModeChange', + 'NextCandidate', + 'NonConvert', + 'PreviousCandidate', + 'Process', + 'SingleCandidate', + // Korean keyboards only + 'HangulMode', + 'HanjaMode', + 'JunjaMode', + // Japanese keyboards only + 'Eisu', + 'Hankaku', + 'Hiragana', + 'HiraganaKatakana', + 'KanaMode', + 'KanjiMode', + 'Katakana', + 'Romaji', + 'Zenkaku', + 'ZenkakuHanaku', + // Function keys + 'F1', + 'F2', + 'F3', + 'F4', + 'F5', + 'F6', + 'F7', + 'F8', + 'F9', + 'F10', + 'F11', + 'F12', + 'F13', + 'F14', + 'F15', + 'F16', + 'F17', + 'F18', + 'F19', + 'F20', + 'Soft1', + 'Soft2', + 'Soft3', + 'Soft4', + // Phone keys + 'AppSwitch', + 'Call', + 'Camera', + 'CameraFocus', + 'EndCall', + 'GoBack', + 'GoHome', + 'HeadsetHook', + 'LastNumberRedial', + 'Notification', + 'MannerMode', + 'VoiceDial', + // Multimedia keys + 'ChannelDown', + 'ChannelUp', + 'MediaFastForward', + 'MediaPause', + 'MediaPlay', + 'MediaPlayPause', + 'MediaRecord', + 'MediaRewind', + 'MediaStop', + 'MediaTrackNext', + 'MediaTrackPrevious', + // Audio control keys + 'AudioBalanceLeft', + 'AudioBalanceRight', + 'AudioBassDown', + 'AudioBassBoostDown', + 'AudioBassBoostToggle', + 'AudioBassBoostUp', + 'AudioBassUp', + 'AudioFaderFront', + 'AudioFaderRear', + 'AudioSurroundModeNext', + 'AudioTrebleDown', + 'AudioTrebleUp', + 'AudioVolumeDown', + 'AudioVolumeMute', + 'AudioVolumeUp', + 'MicrophoneToggle', + 'MicrophoneVolumeDown', + 'MicrophoneVolumeMute', + 'MicrophoneVolumeUp', + // TV control keys + 'TV', + 'TV3DMode', + 'TVAntennaCable', + 'TVAudioDescription', + 'TVAudioDescriptionMixDown', + 'TVAudioDescriptionMixUp', + 'TVContentsMenu', + 'TVDataService', + 'TVInput', + 'TVInputComponent1', + 'TVInputComponent2', + 'TVInputComposite1', + 'TVInputComposite2', + 'TVInputHDMI1', + 'TVInputHDMI2', + 'TVInputHDMI3', + 'TVInputHDMI4', + 'TVInputVGA1', + 'TVMediaContext', + 'TVNetwork', + 'TVNumberEntry', + 'TVPower', + 'TVRadioService', + 'TVSatellite', + 'TVSatelliteBS', + 'TVSatelliteCS', + 'TVSatelliteToggle', + 'TVTerrestrialAnalog', + 'TVTerrestrialDigital', + 'TVTimer', + // Media controller keys + 'AVRInput', + 'AVRPower', + 'ColorF0Red', + 'ColorF1Green', + 'ColorF2Yellow', + 'ColorF3Blue', + 'ColorF4Grey', + 'ColorF5Brown', + 'ClosedCaptionToggle', + 'Dimmer', + 'DisplaySwap', + 'DVR', + 'Exit', + 'FavoriteClear0', + 'FavoriteClear1', + 'FavoriteClear2', + 'FavoriteClear3', + 'FavoriteRecall0', + 'FavoriteRecall1', + 'FavoriteRecall2', + 'FavoriteRecall3', + 'FavoriteStore0', + 'FavoriteStore1', + 'FavoriteStore2', + 'FavoriteStore3', + 'Guide', + 'GuideNextDay', + 'GuidePreviousDay', + 'Info', + 'InstantReplay', + 'Link', + 'ListProgram', + 'LiveContent', + 'Lock', + 'MediaApps', + 'MediaAudioTrack', + 'MediaLast', + 'MediaSkipBackward', + 'MediaSkipForward', + 'MediaStepBackward', + 'MediaStepForward', + 'MediaTopMenu', + 'NavigateIn', + 'NavigateNext', + 'NavigateOut', + 'NavigatePrevious', + 'NextFavoriteChannel', + 'NextUserProfile', + 'OnDemand', + 'Pairing', + 'PinPDown', + 'PinPMove', + 'PinPToggle', + 'PinPUp', + 'PlaySpeedDown', + 'PlaySpeedReset', + 'PlaySpeedUp', + 'RandomToggle', + 'RcLowBattery', + 'RecordSpeedNext', + 'RfBypass', + 'ScanChannelsToggle', + 'ScreenModeNext', + 'Settings', + 'SplitScreenToggle', + 'STBInput', + 'STBPower', + 'Subtitle', + 'Teletext', + 'VideoModeNext', + 'Wink', + 'ZoomToggle', + // Speech recognition keys + 'SpeechCorrectionList', + 'SpeechInputToggle', + // Document keys + 'Close', + 'New', + 'Open', + 'Print', + 'Save', + 'SpellCheck', + 'MailForward', + 'MailReply', + 'MailSend', + // Application selector keys + 'LaunchCalculator', + 'LaunchCalendar', + 'LaunchContacts', + 'LaunchMail', + 'LaunchMediaPlayer', + 'LaunchMusicPlayer', + 'LaunchMyComputer', + 'LaunchPhone', + 'LaunchScreenSaver', + 'LaunchSpreadsheet', + 'LaunchWebBrowser', + 'LaunchWebCam', + 'LaunchWordProcessor', + 'LaunchApplication1', + 'LaunchApplication2', + 'LaunchApplication3', + 'LaunchApplication4', + 'LaunchApplication5', + 'LaunchApplication6', + 'LaunchApplication7', + 'LaunchApplication8', + 'LaunchApplication9', + 'LaunchApplication10', + 'LaunchApplication11', + 'LaunchApplication12', + 'LaunchApplication13', + 'LaunchApplication14', + 'LaunchApplication15', + 'LaunchApplication16', + // Browser control keys + 'BrowserBack', + 'BrowserFavorites', + 'BrowserForward', + 'BrowserHome', + 'BrowserRefresh', + 'BrowserSearch', + 'BrowserStop', + // Numeric keypad keys + 'Decimal', + 'Key11', + 'Key12', + 'Multiply', + 'Add', + 'Clear', + 'Divide', + 'Subtract', + 'Separator' +]);