HotkeysDetector.jsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import React, { useMemo, useCallback } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { GlobalHotKeys } from 'react-hotkeys';
  4. import HotkeyStroke from '../../models/HotkeyStroke';
  5. const HotkeysDetector = (props) => {
  6. const { keySet, strokeSet, onDetected } = props;
  7. // memorize HotkeyStroke instances
  8. const hotkeyStrokes = useMemo(
  9. () => {
  10. const strokes = Array.from(strokeSet);
  11. return strokes.map(stroke => new HotkeyStroke(stroke));
  12. },
  13. [strokeSet],
  14. );
  15. /**
  16. * return key expression string includes modifier
  17. */
  18. const getKeyExpression = useCallback((event) => {
  19. let eventKey = event.key;
  20. if (event.ctrlKey) {
  21. eventKey += '+ctrl';
  22. }
  23. if (event.metaKey) {
  24. eventKey += '+meta';
  25. }
  26. if (event.altKey) {
  27. eventKey += '+alt';
  28. }
  29. if (event.shiftKey) {
  30. eventKey += '+shift';
  31. }
  32. return eventKey;
  33. }, []);
  34. /**
  35. * evaluate the key user pressed and trigger onDetected
  36. */
  37. const checkHandler = useCallback((event) => {
  38. event.preventDefault();
  39. const eventKey = getKeyExpression(event);
  40. hotkeyStrokes.forEach((hotkeyStroke) => {
  41. if (hotkeyStroke.evaluate(eventKey)) {
  42. onDetected(hotkeyStroke.stroke);
  43. }
  44. });
  45. }, [hotkeyStrokes, getKeyExpression, onDetected]);
  46. // memorize keyMap for GlobalHotKeys
  47. const keyMap = useMemo(() => {
  48. return { check: Array.from(keySet) };
  49. }, [keySet]);
  50. // memorize handlers for GlobalHotKeys
  51. const handlers = useMemo(() => {
  52. return { check: checkHandler };
  53. }, [checkHandler]);
  54. return (
  55. <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
  56. );
  57. };
  58. HotkeysDetector.propTypes = {
  59. onDetected: PropTypes.func.isRequired,
  60. keySet: PropTypes.instanceOf(Set).isRequired,
  61. strokeSet: PropTypes.instanceOf(Set).isRequired,
  62. };
  63. export default HotkeysDetector;