HotkeysDetector.jsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. const eventKey = getKeyExpression(event);
  39. hotkeyStrokes.forEach((hotkeyStroke) => {
  40. // if any stroke is completed
  41. if (hotkeyStroke.evaluate(eventKey)) {
  42. // cancel the key event
  43. event.preventDefault();
  44. // invoke detected handler
  45. onDetected(hotkeyStroke.stroke);
  46. }
  47. });
  48. }, [hotkeyStrokes, getKeyExpression, onDetected]);
  49. // memorize keyMap for GlobalHotKeys
  50. const keyMap = useMemo(() => {
  51. return { check: Array.from(keySet) };
  52. }, [keySet]);
  53. // memorize handlers for GlobalHotKeys
  54. const handlers = useMemo(() => {
  55. return { check: checkHandler };
  56. }, [checkHandler]);
  57. return (
  58. <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
  59. );
  60. };
  61. HotkeysDetector.propTypes = {
  62. onDetected: PropTypes.func.isRequired,
  63. keySet: PropTypes.instanceOf(Set).isRequired,
  64. strokeSet: PropTypes.instanceOf(Set).isRequired,
  65. };
  66. export default HotkeysDetector;