Skip to content

Commit d0f4bd9

Browse files
authored
Merge pull request #6301 from nextcloud-libraries/fix/5899/usehotkey-fixups
2 parents 9d271dc + 85cb275 commit d0f4bd9

File tree

2 files changed

+63
-16
lines changed

2 files changed

+63
-16
lines changed

docs/composables/useHotKey.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,22 @@ import { useHotKey } from '@nextcloud/vue/dist/Composables/useHotKey/index.js'
1313
const stopCallback = useHotKey(key, callback, options)
1414
```
1515
where:
16-
- `key`: string representing the keyboard key to listen to
16+
- `keysOrFilter`: one of following:
17+
- `string`: representing the keyboard key to listen to
18+
- `Array<string>`: representing any of keys to listen to
19+
- `Function`: custom filter function to validate event key
20+
- `true`: to listen for all events
1721

18-
See [KeyboardEvent.key Value column](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values) for possible values
22+
See [KeyboardEvent.key Value column](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values) for possible values
1923
- `callback`: a function to be called when the key is pressed. Before called, it will be checked whether keyboard shortcuts are disabled, or interactive element is currently focused, or whether options should be applied
2024
- `options`: options to be applied to the shortcut:
21-
- `push`: whether the event should be triggered on both keydown and keyup
22-
- `prevent`: prevents the default action of the event
23-
- `stop`: prevents propagation of the event in the capturing and bubbling phases
24-
- `ctrl`: whether the Ctrl key should be pressed (Cmd key on MacOS)
25-
- `alt`: whether the Alt key should be pressed
26-
- `shift`: whether the Shift key should be pressed
25+
- `push`: whether the event should be triggered on both keydown and keyup (default: `false`)
26+
- `prevent`: prevents the default action of the event (default: `false`)
27+
- `stop`: prevents propagation of the event in the capturing and bubbling phases (default: `false`)
28+
- `ctrl`: whether the Ctrl key (Cmd key on MacOS) should be pressed (default: `false`)
29+
- `alt`: whether the Alt key should be pressed (default: `false`)
30+
- `shift`: whether the Shift key should be pressed (should be explicitly defined as `true`|`false` if needed)
31+
- `caseSensitive`: whether specific case should be listened, e.g. only 'd' and not 'D' (default: `false`)
2732
- `stopCallback`: a callback to stop listening to the event
2833

2934
### Playground

src/composables/useHotKey/index.js

+50-8
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,21 @@ function shouldIgnoreEvent(event) {
2929
const eventHandler = (callback, options) => (event) => {
3030
const ctrlKeyPressed = isMac ? event.metaKey : event.ctrlKey
3131
if (ctrlKeyPressed !== Boolean(options.ctrl)) {
32-
// Ctrl is required and not pressed, or the opposite
32+
/**
33+
* Ctrl is required and not pressed, or the opposite
34+
* As on macOS 'cmd' key is used instead of 'ctrl' key for most key combinations,
35+
* 'event.metaKey' should be checked
36+
*/
3337
return
34-
} else if (!!options.alt !== event.altKey) {
38+
} else if (event.altKey !== Boolean(options.alt)) {
3539
// Alt is required and not pressed, or the opposite
3640
return
37-
} else if (!!options.shift !== event.shiftKey) {
38-
// Shift is required and not pressed, or the opposite
41+
} else if (options.shift !== undefined && event.shiftKey !== Boolean(options.shift)) {
42+
/**
43+
* Shift is required and not pressed, or the opposite
44+
* As shift key is used to type capital letters and alternate characters,
45+
* option should be explicitly defined
46+
*/
3947
return
4048
} else if (shouldIgnoreEvent(event)) {
4149
// Keyboard shortcuts are disabled, because active element assumes input
@@ -52,25 +60,59 @@ const eventHandler = (callback, options) => (event) => {
5260
}
5361

5462
/**
55-
* @param {string} key - keyboard key or keys to listen to
63+
* @param {true|string|string[]|Function} keysOrFilter - keyboard key or keys to listen to, or filter function
5664
* @param {Function} callback - callback function
5765
* @param {object} options - composable options
5866
* @see docs/composables/usekeystroke.md
5967
*/
60-
export function useHotKey(key, callback = () => {}, options = {}) {
68+
export function useHotKey(keysOrFilter, callback = () => {}, options = {}) {
6169
if (disableKeyboardShortcuts) {
6270
// Keyboard shortcuts are disabled
6371
return () => {}
6472
}
6573

66-
const stopKeyDown = onKeyStroke(key, eventHandler(callback, options), {
74+
/**
75+
* Validates event key to expected key
76+
* FIXME should support any languages / key codes
77+
*
78+
* @param {KeyboardEvent} event keyboard event
79+
* @param {string} key expected key
80+
* @return {boolean} whether it satisfies expected value or not
81+
*/
82+
const validateKeyEvent = (event, key) => {
83+
if (options.caseSensitive) {
84+
return event.key === key
85+
}
86+
return event.key.toLowerCase() === key.toLowerCase()
87+
}
88+
89+
/**
90+
* Filter function for the listener
91+
* see https://github.com/vueuse/vueuse/blob/v11.3.0/packages/core/onKeyStroke/index.ts#L21-L32
92+
*
93+
* @param {KeyboardEvent} event keyboard event
94+
* @return {boolean} whether it satisfies expected value or not
95+
*/
96+
const keyFilter = (event) => {
97+
if (typeof keysOrFilter === 'function') {
98+
return keysOrFilter(event)
99+
} else if (typeof keysOrFilter === 'string') {
100+
return validateKeyEvent(event, keysOrFilter)
101+
} else if (Array.isArray(keysOrFilter)) {
102+
return keysOrFilter.some(key => validateKeyEvent(event, key))
103+
} else {
104+
return true
105+
}
106+
}
107+
108+
const stopKeyDown = onKeyStroke(keyFilter, eventHandler(callback, options), {
67109
eventName: 'keydown',
68110
dedupe: true,
69111
passive: !options.prevent,
70112
})
71113

72114
const stopKeyUp = options.push
73-
? onKeyStroke(key, eventHandler(callback, options), {
115+
? onKeyStroke(keyFilter, eventHandler(callback, options), {
74116
eventName: 'keyup',
75117
passive: !options.prevent,
76118
})

0 commit comments

Comments
 (0)