60 lines
2.4 KiB
JavaScript
60 lines
2.4 KiB
JavaScript
|
// This is the only file allowed to import directly from the package.
|
||
|
// eslint-disable-next-line no-restricted-imports
|
||
|
import Mousetrap from 'mousetrap';
|
||
|
|
||
|
const additionalStopCallbacks = [];
|
||
|
const originalStopCallback = Mousetrap.prototype.stopCallback;
|
||
|
|
||
|
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
|
||
|
for (const callback of additionalStopCallbacks) {
|
||
|
const returnValue = callback.call(this, e, element, combo);
|
||
|
if (returnValue !== undefined) return returnValue;
|
||
|
}
|
||
|
|
||
|
return originalStopCallback.call(this, e, element, combo);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Add a stop callback to Mousetrap.
|
||
|
*
|
||
|
* This allows overriding the default behaviour of Mousetrap#stopCallback,
|
||
|
* which is to stop the bound key handler/callback from being called if the key
|
||
|
* combo is pressed inside form fields (input, select, textareas, etc). See
|
||
|
* https://craig.is/killing/mice#api.stopCallback.
|
||
|
*
|
||
|
* The stopCallback registered here has the same signature as
|
||
|
* Mousetrap#stopCallback, with the one difference being that the callback
|
||
|
* should return `undefined` if it has no opinion on whether the current key
|
||
|
* combo should be stopped or not, and the next stop callback should be
|
||
|
* consulted instead. If a boolean is returned, no other stop callbacks are
|
||
|
* called.
|
||
|
*
|
||
|
* Note: This approach does not always work as expected when coupled with
|
||
|
* Mousetrap's pause plugin, which is used for enabling/disabling all keyboard
|
||
|
* shortcuts. That plugin assumes it's the first to execute and overwrite
|
||
|
* Mousetrap's `stopCallback` method, whereas to work correctly with this, it
|
||
|
* must execute last. This is not guaranteed or even attempted.
|
||
|
*
|
||
|
* To work correctly, we may need to reimplement the pause plugin here.
|
||
|
*
|
||
|
* @param {(e: Event, element: Element, combo: string) => boolean|undefined}
|
||
|
* stopCallback The additional stop callback function to add to the chain
|
||
|
* of stop callbacks.
|
||
|
* @returns {void}
|
||
|
*/
|
||
|
export const addStopCallback = (stopCallback) => {
|
||
|
// Unshift, since we want to iterate through them in reverse order, so that
|
||
|
// the most recently added handler is called first, and the original
|
||
|
// stopCallback method is called last.
|
||
|
additionalStopCallbacks.unshift(stopCallback);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Clear additionalStopCallbacks. Used only for tests.
|
||
|
*/
|
||
|
export const clearStopCallbacksForTests = () => {
|
||
|
additionalStopCallbacks.length = 0;
|
||
|
};
|
||
|
|
||
|
export { Mousetrap };
|