From 85cb2753c128e74558a87cfdeba93dbecb6e61f6 Mon Sep 17 00:00:00 2001 From: Maksim Sukharev Date: Wed, 11 Dec 2024 14:56:20 +0100 Subject: [PATCH] fix(useHotKey): validate event keys as case-insensitive by default Signed-off-by: Maksim Sukharev --- docs/composables/useHotKey.md | 1 + src/composables/useHotKey/index.js | 38 ++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/composables/useHotKey.md b/docs/composables/useHotKey.md index cb750c4d8b..619ef93e78 100644 --- a/docs/composables/useHotKey.md +++ b/docs/composables/useHotKey.md @@ -28,6 +28,7 @@ where: - `ctrl`: whether the Ctrl key (Cmd key on MacOS) should be pressed (default: `false`) - `alt`: whether the Alt key should be pressed (default: `false`) - `shift`: whether the Shift key should be pressed (should be explicitly defined as `true`|`false` if needed) + - `caseSensitive`: whether specific case should be listened, e.g. only 'd' and not 'D' (default: `false`) - `stopCallback`: a callback to stop listening to the event ### Playground diff --git a/src/composables/useHotKey/index.js b/src/composables/useHotKey/index.js index 263f646797..75b3d44dee 100644 --- a/src/composables/useHotKey/index.js +++ b/src/composables/useHotKey/index.js @@ -71,14 +71,48 @@ export function useHotKey(keysOrFilter, callback = () => {}, options = {}) { return () => {} } - const stopKeyDown = onKeyStroke(keysOrFilter, eventHandler(callback, options), { + /** + * Validates event key to expected key + * FIXME should support any languages / key codes + * + * @param {KeyboardEvent} event keyboard event + * @param {string} key expected key + * @return {boolean} whether it satisfies expected value or not + */ + const validateKeyEvent = (event, key) => { + if (options.caseSensitive) { + return event.key === key + } + return event.key.toLowerCase() === key.toLowerCase() + } + + /** + * Filter function for the listener + * see https://github.com/vueuse/vueuse/blob/v11.3.0/packages/core/onKeyStroke/index.ts#L21-L32 + * + * @param {KeyboardEvent} event keyboard event + * @return {boolean} whether it satisfies expected value or not + */ + const keyFilter = (event) => { + if (typeof keysOrFilter === 'function') { + return keysOrFilter(event) + } else if (typeof keysOrFilter === 'string') { + return validateKeyEvent(event, keysOrFilter) + } else if (Array.isArray(keysOrFilter)) { + return keysOrFilter.some(key => validateKeyEvent(event, key)) + } else { + return true + } + } + + const stopKeyDown = onKeyStroke(keyFilter, eventHandler(callback, options), { eventName: 'keydown', dedupe: true, passive: !options.prevent, }) const stopKeyUp = options.push - ? onKeyStroke(keysOrFilter, eventHandler(callback, options), { + ? onKeyStroke(keyFilter, eventHandler(callback, options), { eventName: 'keyup', passive: !options.prevent, })