vim.ts 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { useThrottleCallback } from '@react-hook/throttle';
  2. import { Dispatch, useCallback, useEffect } from 'react';
  3. export const Keys = {
  4. tab: 'Tab',
  5. enter: 'Enter',
  6. esc: 'Escape',
  7. space: ' ',
  8. colon: ':',
  9. question: '?',
  10. pageDown: 'PageDown',
  11. pageUp: 'PageUp',
  12. '1': '1',
  13. '2': '2',
  14. C: 'c',
  15. J: 'j',
  16. K: 'k',
  17. };
  18. const availableKeys = Object.values(Keys);
  19. export const ActionTypeKeyPressed = '@@vim/KEY_PRESSED';
  20. export type ActionKeyPressed = {
  21. type: typeof ActionTypeKeyPressed;
  22. key: string;
  23. };
  24. export function useVimBindings(dispatch: Dispatch<ActionKeyPressed>, skip = false): void {
  25. const listener = useCallback(
  26. (event: KeyboardEvent): void => {
  27. if (!availableKeys.includes(event.key)) {
  28. return;
  29. }
  30. event.preventDefault();
  31. const action: ActionKeyPressed = { type: ActionTypeKeyPressed, key: event.key };
  32. dispatch(action);
  33. },
  34. [dispatch],
  35. );
  36. const listenerThrottled = useThrottleCallback(listener, 20, true);
  37. useEffect(() => {
  38. if (skip) {
  39. return (): void => {
  40. // pass
  41. };
  42. }
  43. window.addEventListener('keydown', listenerThrottled);
  44. return (): void => {
  45. window.removeEventListener('keydown', listenerThrottled);
  46. };
  47. }, [skip, listenerThrottled]);
  48. }