use-keyboard-shortcut
Advanced tools
Comparing version 1.1.3 to 1.1.4
export default useKeyboardShortcut; | ||
type callbackFn = (heldKeys: string[]) => void; | ||
type callbackFn = (shortcutKeys: string[]) => void; | ||
type flushHeldKeys = () => void; | ||
declare function useKeyboardShortcut( | ||
@@ -12,2 +13,2 @@ shortcutKeys: string[], | ||
} | ||
): void; | ||
): { flushHeldKeys }; |
@@ -16,8 +16,4 @@ import { useEffect, useCallback, useRef, useMemo } from "react"; | ||
const useKeyboardShortcut = ( | ||
shortcutKeys, | ||
callback, | ||
userOptions | ||
) => { | ||
const options = {...DEFAULT_OPTIONS, ...userOptions} | ||
const useKeyboardShortcut = (shortcutKeys, callback, userOptions) => { | ||
const options = { ...DEFAULT_OPTIONS, ...userOptions }; | ||
if (!Array.isArray(shortcutKeys)) | ||
@@ -38,10 +34,12 @@ throw new Error( | ||
const shortcutKeysId = useMemo(() => shortcutKeys.join(), [shortcutKeys]); | ||
// Normalizes the shortcut keys a deduplicated array of lowercased keys. | ||
const shortcutArray = useMemo( | ||
() => uniq_fast(shortcutKeys).map((key) => String(key).toLowerCase()), | ||
// While using JSON.stringify() is bad for most larger objects, this shortcut | ||
// While using .join() is bad for most larger objects, this shortcut | ||
// array is fine as it's small, according to the answer below. | ||
// https://github.com/facebook/react/issues/14476#issuecomment-471199055 | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[JSON.stringify(shortcutKeys)] | ||
[shortcutKeysId] | ||
); | ||
@@ -58,2 +56,13 @@ // useRef to avoid a constant re-render on keydown and keyup. | ||
if (options.overrideSystem) { | ||
overrideSystemHandling(keydownEvent); | ||
} | ||
if ( | ||
options.ignoreInputFields && | ||
BLACKLISTED_DOM_TARGETS.indexOf(keydownEvent.target.tagName) >= 0 | ||
) { | ||
return; | ||
} | ||
// This needs to be checked as soon as possible to avoid | ||
@@ -77,16 +86,6 @@ // all option checks that might prevent default behavior | ||
if ( | ||
options.ignoreInputFields && | ||
BLACKLISTED_DOM_TARGETS.indexOf(keydownEvent.target.tagName) >= 0 | ||
) { | ||
return; | ||
} | ||
if (options.overrideSystem) { | ||
overrideSystemHandling(keydownEvent); | ||
} | ||
const nextHeldKeys = [...heldKeys.current, loweredKey]; | ||
if (nextHeldKeys.length === shortcutArray.length) { | ||
if (nextHeldKeys.join() === shortcutArray.join()) { | ||
callback(shortcutKeys); | ||
return false | ||
return false; | ||
} | ||
@@ -99,3 +98,8 @@ | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[shortcutArray, callback, options.overrideSystem, options.ignoreInputFields] | ||
[ | ||
shortcutKeysId, | ||
callback, | ||
options.overrideSystem, | ||
options.ignoreInputFields, | ||
] | ||
); | ||
@@ -111,12 +115,2 @@ | ||
if ( | ||
options.ignoreInputFields && | ||
BLACKLISTED_DOM_TARGETS.indexOf(keyupEvent.target.tagName) >= 0 | ||
) { | ||
return; | ||
} | ||
if (options.overrideSystem) { | ||
overrideSystemHandling(keyupEvent); | ||
} | ||
let nextHeldKeys = []; | ||
@@ -133,5 +127,10 @@ let loopIndex; | ||
}, | ||
[shortcutArray, options.overrideSystem, options.ignoreInputFields] | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
[shortcutKeysId] | ||
); | ||
const flushHeldKeys = useCallback(() => { | ||
heldKeys.current = []; | ||
}, []); | ||
useEffect(() => { | ||
@@ -145,11 +144,15 @@ window.addEventListener("keydown", keydownListener); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [keydownListener, keyupListener, shortcutArray]); | ||
}, [keydownListener, keyupListener, shortcutKeysId]); | ||
// Resets the held keys array if the shortcut keys are changed. | ||
useEffect(() => { | ||
heldKeys.current = []; | ||
flushHeldKeys(); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [shortcutArray]); | ||
}, [shortcutKeysId, flushHeldKeys]); | ||
return { | ||
flushHeldKeys, | ||
}; | ||
}; | ||
export default useKeyboardShortcut; |
{ | ||
"name": "use-keyboard-shortcut", | ||
"version": "1.1.3", | ||
"version": "1.1.4", | ||
"description": "A custom React hook for adding keyboard shortcuts to your application", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -5,3 +5,3 @@ ## useKeyboardShortcut | ||
[Click here for a small demo!](https://use-keyboard-shortcut.tyukayev.com/) | ||
[Documentation | Live Example](https://use-keyboard-shortcut.tyukayev.com/) | ||
@@ -15,3 +15,11 @@ A custom React hook that allows adding keyboard shortcuts to a React application. | ||
const App = () => { | ||
useKeyboardShortcut(['Shift', 'H'], () => console.log('Shift + H has been pressed.'), { overrideSystem: false }) | ||
const { flushHeldKeys } = useKeyboardShortcut( | ||
["Shift", "H"], | ||
shortcutKeys => console.log("Shift + H has been pressed."), | ||
{ | ||
overrideSystem: false, | ||
ignoreInputFields: false, | ||
repeatOnHold: false | ||
} | ||
); | ||
@@ -26,6 +34,9 @@ return ( | ||
```javascript | ||
useKeyboardShortcut(shortcutArray, callback, options) | ||
const { flushHeldKeys } = useKeyboardShortcut(shortcutArray, callback, options) | ||
``` | ||
| Hook Return | Type | Description | | ||
|--------------|-----------|------------| | ||
| `flushHeldKeys` | `Function` | Function to flush the array of held keys used for keydown tracking. This can help fixing "stuck" keys. | | ||
| Parameter | Type | Description | | ||
| Hook Parameter | Type | Description | | ||
|--------------|-----------|------------| | ||
@@ -51,5 +62,7 @@ | `shortcutArray` | `Array` | Array of `KeyboardEvent.key` strings. A full list of strings can be seen [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) | | ||
Some browsers just simply ignore `Event.preventDefault()` when it comes to specific browser actions. For example, on Chrome the shortcut `Meta + S` can be prevented *sometimes* from opening the Save Dialog, however the shortcut `Meta + T` cannot be prevented from opening a new tab. Results may vary depending on the browser. | ||
Some browsers just simply ignore `Event.preventDefault()` when it comes to specific browser actions. For example, on Chrome the shortcut `Meta + S` can be prevented *sometimes* from opening the Save Dialog, however the shortcut `Meta + T` cannot be prevented from opening a new tab. _Results may vary depending on the browser._ | ||
Callback behavior or browser behavior that causes a system dialog to appear might perform poorly. During testing, the keyup listener doesn't fire in some browsers if the callback or overriden shortcut resulted in a dialog appearing. For example, creating a shortcut such as `Meta + A` that opens an `alert()`, may sometimes cause the keyup listener to not fire and cause keys to be "stuck". | ||
## Bugs / Problems | ||
[Please create an issue](https://github.com/arthurtyukayev/use-keyboard-shortcut/issues/new). |
14147
228
65