UNPKG

handsontable

Version:

Handsontable is a JavaScript Spreadsheet Component available for React, Angular and Vue.

171 lines (141 loc) 5.25 kB
import "core-js/modules/es.array.includes.js"; import "core-js/modules/es.array.concat.js"; import "core-js/modules/es.string.includes.js"; import { createKeysObserver } from "./keyObserver.mjs"; import { normalizeEventKey } from "./utils.mjs"; import { isImmediatePropagationStopped } from "../helpers/dom/event.mjs"; import { isMacOS } from "../helpers/browser.mjs"; var MODIFIER_KEYS = ['meta', 'alt', 'shift', 'control']; var modifierKeysObserver = createKeysObserver(); /* eslint-disable jsdoc/require-description-complete-sentence */ /** * A key recorder, used for tracking key events. * * @param {EventTarget} ownerWindow A starting `window` element * @param {Function} beforeKeyDown A hook fired before the `keydown` event is handled. You can use it to [block a keyboard shortcut's actions](@/guides/accessories-and-menus/keyboard-shortcuts.md#blocking-a-keyboard-shortcut-s-actions). * @param {Function} afterKeyDown A hook fired after the `keydown` event is handled * @param {Function} callback `KeyEvent`'s listener's callback function * @returns {object} */ export function useRecorder(ownerWindow, beforeKeyDown, afterKeyDown, callback) { /** * Check if a pressed key is tracked or not. * * @param {string} pressedKey A pressed key * @returns {boolean} */ var isModifierKey = function isModifierKey(pressedKey) { return MODIFIER_KEYS.includes(pressedKey); }; /** * Get every pressed modifier key from the performed `KeyboardEvent`. * * @private * @param {KeyboardEvent} event The event object. * @param {boolean} [mergeMetaKeys=false] If `true,` the function will return the "control" and "meta" * modifiers keys as the "control/meta" name. This allows creating * keyboard shortcuts with modifier key that trigger the shortcut * actions depend on the OS keyboard layout (the Meta key for macOS * and Control for non macOS system). * @returns {string[]} */ var getPressedModifierKeys = function getPressedModifierKeys(event) { var mergeMetaKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var pressedModifierKeys = []; if (event.altKey) { pressedModifierKeys.push('alt'); } if (mergeMetaKeys && (event.ctrlKey || event.metaKey)) { pressedModifierKeys.push('control/meta'); } else { if (event.ctrlKey) { pressedModifierKeys.push('control'); } if (event.metaKey) { pressedModifierKeys.push('meta'); } } if (event.shiftKey) { pressedModifierKeys.push('shift'); } return pressedModifierKeys; }; /** * `KeyboardEvent`'s callback function * * @private * @param {KeyboardEvent} event The event object */ var onkeydown = function onkeydown(event) { var result = beforeKeyDown(event); if (result === false || isImmediatePropagationStopped(event)) { return; } var pressedKey = normalizeEventKey(event.key); var extraModifierKeys = []; if (isModifierKey(pressedKey)) { modifierKeysObserver.press(pressedKey); } else { extraModifierKeys = getPressedModifierKeys(event); } var pressedKeys = [pressedKey].concat(extraModifierKeys); var isExecutionCancelled = callback(event, pressedKeys); if (!isExecutionCancelled && (isMacOS() && extraModifierKeys.includes('meta') || !isMacOS() && extraModifierKeys.includes('control'))) { // Trigger the callback for the virtual OS-dependent "control/meta" key callback(event, [pressedKey].concat(getPressedModifierKeys(event, true))); } afterKeyDown(event); }; /** * `KeyboardEvent`'s callback function * * @private * @param {KeyboardEvent} event The event object */ var onkeyup = function onkeyup(event) { var pressedKey = normalizeEventKey(event.key); if (isModifierKey(pressedKey) === false) { return; } modifierKeysObserver.release(pressedKey); }; /** * `FocusEvent`'s callback function * * @private */ var onblur = function onblur() { modifierKeysObserver.releaseAll(); }; /** * Add event listeners to the starting window and its parents' windows. */ var mount = function mount() { var eventTarget = ownerWindow; while (eventTarget) { eventTarget.addEventListener('keydown', onkeydown); eventTarget.addEventListener('keyup', onkeyup); eventTarget.addEventListener('blur', onblur); eventTarget = eventTarget.frameElement; } }; /** * Remove event listeners from the starting window and its parents' windows. */ var unmount = function unmount() { var eventTarget = ownerWindow; while (eventTarget) { eventTarget.removeEventListener('keydown', onkeydown); eventTarget.removeEventListener('keyup', onkeyup); eventTarget.removeEventListener('blur', onblur); eventTarget = eventTarget.frameElement; } }; return { mount: mount, unmount: unmount, isPressed: function isPressed(key) { return modifierKeysObserver.isPressed(key); } }; }