export type KeyCode = '' | 'Again' | 'AltLeft' | 'AltRight' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'AudioVolumeDown' | 'AudioVolumeMute' | 'AudioVolumeUp' | 'Backquote' | 'Backslash' | 'Backspace' | 'BracketLeft' | 'BracketRight' | 'BrowserBack' | 'BrowserFavorites' | 'BrowserForward' | 'BrowserHome' | 'BrowserRefresh' | 'BrowserSearch' | 'BrowserStop' | 'CapsLock' | 'Comma' | 'ContextMenu' | 'ControlLeft' | 'ControlRight' | 'Convert' | 'Copy' | 'Cut' | 'Delete' | 'Digit0' | 'Digit1' | 'Digit2' | 'Digit3' | 'Digit4' | 'Digit5' | 'Digit6' | 'Digit7' | 'Digit8' | 'Digit9' | 'Eject' | 'End' | 'Enter' | 'Equal' | 'F1' | 'F10' | 'F11' | 'F12' | 'F13' | 'F14' | 'F15' | 'F16' | 'F17' | 'F18' | 'F19' | 'F2' | 'F20' | 'F21' | 'F22' | 'F23' | 'F24' | 'F3' | 'F4' | 'F5' | 'F6' | 'F7' | 'F8' | 'F9' | 'Find' | 'Help' | 'Home' | 'Insert' | 'IntlBackslash' | 'IntlRo' | 'IntlYen' | 'KanaMode' | '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' | 'Lang1' | 'Lang2' | 'Lang3' | 'Lang4' | 'Lang5' | 'LaunchApp1' | 'LaunchApp2' | 'LaunchMail' | 'MediaPlayPause' | 'MediaSelect' | 'MediaStop' | 'MediaTrackNext' | 'MediaTrackPrevious' | 'MetaLeft' | 'MetaRight' | 'Minus' | 'NonConvert' | 'NumLock' | 'Numpad0' | 'Numpad1' | 'Numpad2' | 'Numpad3' | 'Numpad4' | 'Numpad5' | 'Numpad6' | 'Numpad7' | 'Numpad8' | 'Numpad9' | 'NumpadAdd' | 'NumpadComma' | 'NumpadDecimal' | 'NumpadDivide' | 'NumpadEnter' | 'NumpadEqual' | 'NumpadMultiply' | 'NumpadParenLeft' | 'NumpadParenRight' | 'NumpadSubtract' | 'Open' | 'PageDown' | 'PageUp' | 'Paste' | 'Pause' | 'Period' | 'Power' | 'PrintScreen' | 'Quote' | 'ScrollLock' | 'Select' | 'Semicolon' | 'ShiftLeft' | 'ShiftRight' | 'Slash' | 'Sleep' | 'Space' | 'Tab' | 'Undo' | 'WakeUp' | 'Escape' declare class KeyboardLayoutMap extends Map { } interface Keyboard { getLayoutMap: () => Promise onlayoutchange: ((this: Keyboard, ev: Event) => void) | null } declare global { interface Navigator { keyboard?: Keyboard } } // Risky as objects dont guarantee order export const keys: Partial> = { Escape: { dark: true, name: 'Escape' }, Digit1: { name: 'Digit1' }, Digit2: { name: 'Digit2' }, Digit3: { name: 'Digit3' }, Digit4: { name: 'Digit4' }, Digit5: { name: 'Digit5' }, Digit6: { name: 'Digit6' }, Digit7: { name: 'Digit7' }, Digit8: { name: 'Digit8' }, Digit9: { name: 'Digit9' }, Digit0: { name: 'Digit0' }, Minus: { name: 'Minus' }, Equal: { name: 'Equal' }, Backspace: { dark: true, size: 100, name: 'Backspace' }, Delete: { dark: true, name: 'Delete' }, Tab: { dark: true, size: 75, name: 'Tab' }, KeyQ: { name: 'KeyQ' }, KeyW: { name: 'KeyW' }, KeyE: { name: 'KeyE' }, KeyR: { name: 'KeyR' }, KeyT: { name: 'KeyT' }, KeyY: { name: 'KeyY' }, KeyU: { name: 'KeyU' }, KeyI: { name: 'KeyI' }, KeyO: { name: 'KeyO' }, KeyP: { name: 'KeyP' }, BracketLeft: { name: 'BracketLeft' }, BracketRight: { name: 'BracketRight' }, Backslash: { dark: true, size: 75, name: 'Backslash' }, Home: { dark: true, name: 'Home' }, CapsLock: { dark: true, size: 90, name: 'CapsLock' }, KeyA: { name: 'KeyA' }, KeyS: { name: 'KeyS' }, KeyD: { name: 'KeyD' }, KeyF: { name: 'KeyF' }, KeyG: { name: 'KeyG' }, KeyH: { name: 'KeyH' }, KeyJ: { name: 'KeyJ' }, KeyK: { name: 'KeyK' }, KeyL: { name: 'KeyL' }, Semicolon: { name: 'Semicolon' }, Quote: { name: 'Quote' }, Enter: { dark: true, size: 110, name: 'Enter' }, PageUp: { dark: true, name: 'PageUp' }, ShiftLeft: { dark: true, size: 115, name: 'ShiftLeft' }, KeyZ: { name: 'KeyZ' }, KeyX: { name: 'KeyX' }, KeyC: { name: 'KeyC' }, KeyV: { name: 'KeyV' }, KeyB: { name: 'KeyB' }, KeyN: { name: 'KeyN' }, KeyM: { name: 'KeyM' }, Comma: { name: 'Comma' }, Period: { name: 'Period' }, Slash: { name: 'Slash' }, ShiftRight: { dark: true, size: 85, name: 'ShiftRight' }, ArrowUp: { dark: true, name: 'ArrowUp' }, PageDown: { dark: true, name: 'PageDown' }, ControlLeft: { dark: true, size: 75, name: 'ControlLeft' }, MetaLeft: { dark: true, name: 'MetaLeft' }, AltLeft: { dark: true, size: 75, name: 'AltLeft' }, Space: { dark: true, size: 300, name: 'Space' }, AltRight: { dark: true, size: 75, name: 'AltRight' }, ContextMenu: { dark: true, size: 75, name: 'ContextMenu' }, ArrowLeft: { dark: true, name: 'ArrowLeft' }, ArrowDown: { dark: true, name: 'ArrowDown' }, ArrowRight: { dark: true, name: 'ArrowRight' } } // char => code for navigator.keyboard API export const codeMap: Record = { 0: 'Digit0', 1: 'Digit1', 2: 'Digit2', 3: 'Digit3', 4: 'Digit4', 5: 'Digit5', 6: 'Digit6', 7: 'Digit7', 8: 'Digit8', 9: 'Digit9', e: 'KeyE', d: 'KeyD', '-': 'Minus', h: 'KeyH', z: 'KeyZ', '=': 'Equal', n: 'KeyN', p: 'KeyP', ']': 'BracketRight', '[': 'BracketLeft', s: 'KeyS', ';': 'Semicolon', q: 'KeyQ', o: 'KeyO', '.': 'Period', v: 'KeyV', l: 'KeyL', '`': 'Backquote', g: 'KeyG', j: 'KeyJ', t: 'KeyT', "'": 'Quote', y: 'KeyY', '\\': 'Backslash', r: 'KeyR', u: 'KeyU', k: 'KeyK', '/': 'Slash', f: 'KeyF', i: 'KeyI', x: 'KeyX', a: 'KeyA', m: 'KeyM', w: 'KeyW', b: 'KeyB', c: 'KeyC', ',': 'Comma' } export const layout: Partial> = {} if (navigator.keyboard) { navigator.keyboard.getLayoutMap().then((map) => { for (const [key, value] of map.entries()) { layout[key] = codeMap[value] } }) }