react-hotkeys-hook 4.0.0-2 → 4.0.0-5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HotkeysProvider.d.ts +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +3 -3
- package/dist/useDeepEqualMemo.d.ts +1 -0
- package/package.json +5 -2
- package/src/HotkeysProvider.tsx +1 -1
- package/src/index.ts +2 -0
- package/src/parseHotkeys.ts +3 -1
- package/src/useDeepEqualMemo.ts +12 -0
- package/src/useHotkeys.ts +24 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function useDeepEqualMemo<T>(value: T): T | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-hotkeys-hook",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-5",
|
|
4
4
|
"repository": "https://JohannesKlauss@github.com/JohannesKlauss/react-keymap-hook.git",
|
|
5
5
|
"homepage": "https://johannesklauss.github.io/react-hotkeys-hook/",
|
|
6
6
|
"author": "Johannes Klauss",
|
|
@@ -68,8 +68,11 @@
|
|
|
68
68
|
"tslib": "2.4.0",
|
|
69
69
|
"typescript": "4.7.4"
|
|
70
70
|
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"lodash": "4.17.11"
|
|
73
|
+
},
|
|
71
74
|
"peerDependencies": {
|
|
72
|
-
"lodash": ">=4.17.
|
|
75
|
+
"lodash": ">=4.17.0",
|
|
73
76
|
"react": ">=16.8.1",
|
|
74
77
|
"react-dom": ">=16.8.1"
|
|
75
78
|
}
|
package/src/HotkeysProvider.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { Hotkey } from './types'
|
|
|
2
2
|
import { createContext, ReactNode, useMemo, useState, useContext } from 'react'
|
|
3
3
|
import BoundHotkeysProxyProviderProvider from './BoundHotkeysProxyProvider'
|
|
4
4
|
|
|
5
|
-
type HotkeysContextType = {
|
|
5
|
+
export type HotkeysContextType = {
|
|
6
6
|
hotkeys: ReadonlyArray<Hotkey>
|
|
7
7
|
activeScopes: string[]
|
|
8
8
|
toggleScope: (scope: string) => void
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import useHotkeys from './useHotkeys'
|
|
2
2
|
import type { Options } from './types'
|
|
3
3
|
import { HotkeysProvider, useHotkeysContext } from './HotkeysProvider'
|
|
4
|
+
import { isHotkeyPressed } from './isHotkeyPressed'
|
|
4
5
|
|
|
5
6
|
export {
|
|
6
7
|
useHotkeys,
|
|
7
8
|
useHotkeysContext,
|
|
9
|
+
isHotkeyPressed,
|
|
8
10
|
HotkeysProvider,
|
|
9
11
|
Options,
|
|
10
12
|
}
|
package/src/parseHotkeys.ts
CHANGED
|
@@ -14,7 +14,9 @@ export function parseHotkey(hotkey: string, combinationKey: string = '+'): Hotke
|
|
|
14
14
|
const keys = hotkey
|
|
15
15
|
.toLocaleLowerCase()
|
|
16
16
|
.split(combinationKey)
|
|
17
|
-
.map(
|
|
17
|
+
.map(k => k.trim())
|
|
18
|
+
.map(k => k === 'esc' ? 'escape' : k)
|
|
19
|
+
.map(k => k === 'return' ? 'enter' : k)
|
|
18
20
|
|
|
19
21
|
const modifiers: KeyboardModifiers = {
|
|
20
22
|
alt: keys.includes('alt'),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
2
|
+
import { isEqual } from 'lodash'
|
|
3
|
+
|
|
4
|
+
export default function useDeepEqualMemo<T>(value: T) {
|
|
5
|
+
const ref = useRef<T | undefined>(undefined)
|
|
6
|
+
|
|
7
|
+
if (!isEqual(ref.current, value)) {
|
|
8
|
+
ref.current = value
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return ref.current
|
|
12
|
+
}
|
package/src/useHotkeys.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from './validators'
|
|
12
12
|
import { useHotkeysContext } from './HotkeysProvider'
|
|
13
13
|
import { useBoundHotkeysProxy } from './BoundHotkeysProxyProvider'
|
|
14
|
+
import useDeepEqualMemo from './useDeepEqualMemo'
|
|
14
15
|
|
|
15
16
|
const stopPropagation = (e: KeyboardEvent): void => {
|
|
16
17
|
e.stopPropagation()
|
|
@@ -31,37 +32,41 @@ export default function useHotkeys<T extends HTMLElement>(
|
|
|
31
32
|
const _deps = options instanceof Array ? options : dependencies instanceof Array ? dependencies : []
|
|
32
33
|
|
|
33
34
|
const cb = useCallback(callback, [..._deps])
|
|
34
|
-
const
|
|
35
|
+
const memoisedOptions = useDeepEqualMemo(_options)
|
|
35
36
|
|
|
37
|
+
const { activeScopes } = useHotkeysContext()
|
|
36
38
|
const proxy = useBoundHotkeysProxy()
|
|
37
39
|
|
|
38
40
|
useLayoutEffect(() => {
|
|
39
|
-
if (
|
|
41
|
+
if (memoisedOptions?.enabled === false || !isScopeActive(activeScopes, memoisedOptions?.scopes)) {
|
|
40
42
|
return
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
const listener = (e: KeyboardEvent) => {
|
|
44
|
-
if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e,
|
|
46
|
+
if (isKeyboardEventTriggeredByInput(e) && !isHotkeyEnabledOnTag(e, memoisedOptions?.enableOnFormTags)) {
|
|
45
47
|
return
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
// TODO: SINCE THE EVENT IS NOW ATTACHED TO THE REF, THE ACTIVE ELEMENT CAN NEVER BE INSIDE THE REF. THE HOTKEY ONLY TRIGGERS IF THE
|
|
51
|
+
// REF IS THE ACTIVE ELEMENT. THIS IS A PROBLEM SINCE FOCUSED SUB COMPONENTS WONT TRIGGER THE HOTKEY.
|
|
52
|
+
|
|
48
53
|
if (ref.current !== null && document.activeElement !== ref.current && !ref.current.contains(document.activeElement)) {
|
|
49
54
|
stopPropagation(e)
|
|
50
55
|
|
|
51
56
|
return
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
if (((e.target as HTMLElement)?.isContentEditable && !
|
|
59
|
+
if (((e.target as HTMLElement)?.isContentEditable && !memoisedOptions?.enableOnContentEditable)) {
|
|
55
60
|
return
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
parseKeysHookInput(keys,
|
|
59
|
-
const hotkey = parseHotkey(key,
|
|
63
|
+
parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => {
|
|
64
|
+
const hotkey = parseHotkey(key, memoisedOptions?.combinationKey)
|
|
60
65
|
|
|
61
66
|
if (isHotkeyMatchingKeyboardEvent(e, hotkey, pressedDownKeys) || hotkey.keys?.includes('*')) {
|
|
62
|
-
maybePreventDefault(e, hotkey,
|
|
67
|
+
maybePreventDefault(e, hotkey, memoisedOptions?.preventDefault)
|
|
63
68
|
|
|
64
|
-
if (!isHotkeyEnabled(e, hotkey,
|
|
69
|
+
if (!isHotkeyEnabled(e, hotkey, memoisedOptions?.enabled)) {
|
|
65
70
|
stopPropagation(e)
|
|
66
71
|
|
|
67
72
|
return
|
|
@@ -75,15 +80,20 @@ export default function useHotkeys<T extends HTMLElement>(
|
|
|
75
80
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
76
81
|
pressedDownKeys.add(event.key.toLowerCase())
|
|
77
82
|
|
|
78
|
-
if ((
|
|
83
|
+
if ((memoisedOptions?.keydown === undefined && memoisedOptions?.keyup !== true) || memoisedOptions?.keydown) {
|
|
79
84
|
listener(event)
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
const handleKeyUp = (event: KeyboardEvent) => {
|
|
84
|
-
|
|
89
|
+
if (event.key.toLowerCase() !== 'meta') {
|
|
90
|
+
pressedDownKeys.delete(event.key.toLowerCase())
|
|
91
|
+
} else {
|
|
92
|
+
// On macOS pressing down the meta key prevents triggering the keyup event for any other key https://stackoverflow.com/a/57153300/735226.
|
|
93
|
+
pressedDownKeys.clear()
|
|
94
|
+
}
|
|
85
95
|
|
|
86
|
-
if (
|
|
96
|
+
if (memoisedOptions?.keyup) {
|
|
87
97
|
listener(event)
|
|
88
98
|
}
|
|
89
99
|
}
|
|
@@ -94,7 +104,7 @@ export default function useHotkeys<T extends HTMLElement>(
|
|
|
94
104
|
(ref.current || document).addEventListener('keydown', handleKeyDown)
|
|
95
105
|
|
|
96
106
|
if (proxy) {
|
|
97
|
-
parseKeysHookInput(keys,
|
|
107
|
+
parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.addHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
return () => {
|
|
@@ -104,10 +114,10 @@ export default function useHotkeys<T extends HTMLElement>(
|
|
|
104
114
|
(ref.current || document).removeEventListener('keydown', handleKeyDown)
|
|
105
115
|
|
|
106
116
|
if (proxy) {
|
|
107
|
-
parseKeysHookInput(keys,
|
|
117
|
+
parseKeysHookInput(keys, memoisedOptions?.splitKey).forEach((key) => proxy.removeHotkey(parseHotkey(key, memoisedOptions?.combinationKey)))
|
|
108
118
|
}
|
|
109
119
|
}
|
|
110
|
-
}, [keys, cb,
|
|
120
|
+
}, [keys, cb, memoisedOptions, activeScopes])
|
|
111
121
|
|
|
112
122
|
return ref
|
|
113
123
|
}
|