useKeyDown.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { useCallback, useMemo } from 'react';
  2. import { Keyboard } from '$app/constants/document/keyboard';
  3. import isHotkey from 'is-hotkey';
  4. import { useAppDispatch } from '@/appflowy_app/stores/store';
  5. import {
  6. enterActionForBlockThunk,
  7. tabActionForBlockThunk,
  8. shiftTabActionForBlockThunk,
  9. } from '$app_reducers/document/async-actions';
  10. import { useTurnIntoBlockEvents } from './useTurnIntoBlockEvents';
  11. import { useCommonKeyEvents } from '../_shared/EditorHooks/useCommonKeyEvents';
  12. import { useSubscribeDocument } from '$app/components/document/_shared/SubscribeDoc.hooks';
  13. export function useKeyDown(id: string) {
  14. const { controller } = useSubscribeDocument();
  15. const dispatch = useAppDispatch();
  16. const turnIntoEvents = useTurnIntoBlockEvents(id);
  17. const commonKeyEvents = useCommonKeyEvents(id);
  18. const interceptEvents = useMemo(() => {
  19. return [
  20. ...commonKeyEvents,
  21. {
  22. // Prevent all enter key unless it be rewritten
  23. canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
  24. return e.key === Keyboard.keys.ENTER;
  25. },
  26. handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
  27. e.preventDefault();
  28. },
  29. },
  30. {
  31. // rewrite only enter key and no other key is pressed
  32. canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
  33. return isHotkey(Keyboard.keys.ENTER, e);
  34. },
  35. handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
  36. if (!controller) return;
  37. dispatch(
  38. enterActionForBlockThunk({
  39. id,
  40. controller,
  41. })
  42. );
  43. },
  44. },
  45. {
  46. // Prevent all tab key unless it be rewritten
  47. canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
  48. return e.key === Keyboard.keys.TAB;
  49. },
  50. handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
  51. e.preventDefault();
  52. },
  53. },
  54. {
  55. // rewrite only tab key and no other key is pressed
  56. canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
  57. return isHotkey(Keyboard.keys.TAB, e);
  58. },
  59. handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
  60. if (!controller) return;
  61. dispatch(
  62. tabActionForBlockThunk({
  63. id,
  64. controller,
  65. })
  66. );
  67. },
  68. },
  69. {
  70. // rewrite only shift+tab key and no other key is pressed
  71. canHandle: (e: React.KeyboardEvent<HTMLDivElement>) => {
  72. return isHotkey(Keyboard.keys.SHIFT_TAB, e);
  73. },
  74. handler: (e: React.KeyboardEvent<HTMLDivElement>) => {
  75. if (!controller) return;
  76. dispatch(
  77. shiftTabActionForBlockThunk({
  78. id,
  79. controller,
  80. })
  81. );
  82. },
  83. },
  84. ...turnIntoEvents,
  85. ];
  86. }, [commonKeyEvents, controller, dispatch, id, turnIntoEvents]);
  87. const onKeyDown = useCallback(
  88. (e: React.KeyboardEvent<HTMLDivElement>) => {
  89. const filteredEvents = interceptEvents.filter((event) => event.canHandle(e));
  90. filteredEvents.forEach((event) => {
  91. e.stopPropagation();
  92. event.handler(e);
  93. });
  94. },
  95. [interceptEvents]
  96. );
  97. return {
  98. onKeyDown,
  99. };
  100. }