Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions ui/lib/src/keyboardRemapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
export type KeyboardMapping = 'NONE' | 'QWERTY';

interface Mapping {
key: string;
code: string;
shiftKey: boolean;
}

export class KeyboardRemapper {
mapping: KeyboardMapping = 'NONE';

constructor(mapping?: KeyboardMapping) {
if (mapping !== undefined) this.mapping = mapping;
}

map(e: KeyboardEvent): { mapped: boolean; key: string } {
let mappingFound: Mapping | undefined = undefined;
if (this.mapping === 'QWERTY') {
mappingFound = qwertyMappings.find(item => item.code === e.code && item.shiftKey === e.shiftKey);
}
if (mappingFound != undefined) return { mapped: true, key: mappingFound.key };
else return { mapped: false, key: e.key };
}
}

const alphabet: string[] = Array.from(
{ length: 26 },
(_, i) => String.fromCharCode(97 + i), // 'a' is char code 97
);

const digits: string[] = Array.from(
{ length: 10 },
(_, i) => String.fromCharCode(48 + i), // '0' is char code 48
);

const qwertyMapLowerCaseLetters: Mapping[] = alphabet.map(
(letter: string) => <Mapping>{ key: letter, code: 'Key' + letter.toUpperCase(), shiftKey: false },
);

const qwertyMapUpperCaseLetters: Mapping[] = alphabet.map(
(letter: string) =>
<Mapping>{ key: letter.toUpperCase(), code: 'Key' + letter.toUpperCase(), shiftKey: true },
);

const qwertyMapDigits: Mapping[] = digits.map(
(letter: string) => <Mapping>{ key: letter, code: 'Digit' + letter.toUpperCase(), shiftKey: false },
);

const qwertyMappings: Mapping[] = [
...qwertyMapUpperCaseLetters,
...qwertyMapLowerCaseLetters,
...qwertyMapDigits,
{
key: '?',
code: 'Slash',
shiftKey: true,
},
{
key: '=',
code: 'Equal',
shiftKey: false,
},
{
key: '-',
code: 'Minus',
shiftKey: false,
},
{
key: '+',
code: 'Equal',
shiftKey: true,
},
{
key: '#',
code: 'Digit3 ',
shiftKey: true,
},
];
7 changes: 6 additions & 1 deletion ui/site/src/mousetrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* limitations under the License.
*/

import { KeyboardRemapper } from 'lib/keyboardRemapper';

type Action = 'keypress' | 'keydown' | 'keyup';

type Callback = (e: KeyboardEvent) => void;
Expand All @@ -32,6 +34,8 @@ interface Binding {
action: Action;
}

const qwertyRemapper = new KeyboardRemapper('QWERTY');

const MAP: Record<string, string> = {
8: 'backspace',
9: 'tab',
Expand Down Expand Up @@ -209,10 +213,11 @@ export default class Mousetrap {
};

private getMatches = (e: KeyboardEvent): Binding[] => {
const { mapped: mapped, key: mappedKey } = qwertyRemapper.map(e);
const key = keyFromEvent(e);
const action = e.type;
const modifiers = action === 'keyup' && isModifier(key) ? [key] : eventModifiers(e);
return (this.bindings[key] || []).filter(
return (this.bindings[key] || (mapped && this.bindings[mappedKey]) || []).filter(
binding =>
action === binding.action &&
// Chrome will not fire a keypress if meta or control is down,
Expand Down