Gitako/src/utils/keyHelper.ts
2019-11-09 01:53:59 +08:00

59 lines
1.5 KiB
TypeScript

const keyCodeArray = [
...'1234567890abcdefghijklmnopqrstuvwxyz'.split(''),
..."`[]\\;',./".split(''),
'alt',
'shift',
'ctrl',
'meta',
]
const validKeyCodes = new Set(keyCodeArray)
function isValidKey(key: string) {
return validKeyCodes.has(key)
}
/**
* parse a string representation of key combination
*
* @param {string} keysString
* @returns {string}
*/
function parse(keysString: string) {
return (
keysString
.split('+')
/* when trying to set a combination includes '+',
input should be 'shift + =' instead of 'shift + +',
thus a valid key string won't contain '++' */
.map(_ => _.trim().toLowerCase())
.filter(isValidKey)
.sort((a, b) => keyCodeArray.indexOf(b) - keyCodeArray.indexOf(a))
.join('+')
)
}
function parseKeyCode(code: string) {
return code.toLowerCase().replace(/^control$/, 'ctrl')
}
export function parseEvent(e: KeyboardEvent | React.KeyboardEvent) {
const { altKey: alt, shiftKey: shift, metaKey: meta, ctrlKey: ctrl } = e
try {
const code = parseKeyCode(e.key)
const keys = { meta, ctrl, shift, alt, [code]: true }
const combination = parse(
Object.entries(keys)
.filter(([key, pressed]) => pressed)
.map(([key, pressed]) => key)
.join('+'),
)
return combination
} catch (err) {
const serializedKeyData = JSON.stringify({
keyCode: e.keyCode,
key: e.key,
charCode: e.charCode,
})
throw new Error(`Error parse keyboard event: ${serializedKeyData}`)
}
}