All files / js/components LinkWithHotkey.tsx

16.66% Statements 3/18
0% Branches 0/4
0% Functions 0/6
17.64% Lines 3/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 631x             1x 1x                                                                                                            
import React, {
  MutableRefObject,
  ReactNode,
  useCallback,
  useEffect,
  useRef,
} from "react";
import { NavLink } from "react-router-dom";
import { getKey, KeyboardShortcut, keyboardShortcutHandler } from "../utils";
 
/**
 * React hook to add a global keyboard shortcut for the given
 * key for the lifetime of the component.
 */
function useKeyboardShortcut(
  key: KeyboardShortcut,
  action: (ev: KeyboardEvent) => void
): void {
  useEffect(() => {
    const handler = keyboardShortcutHandler(key, action);
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, [key, action]);
}
 
/**
 * Add a global keyboard shortcut for the given key and simulate
 * a click on the ref'ed element.
 */
function useKeyboardShortcutRef<T extends HTMLElement>(
  key: KeyboardShortcut
): MutableRefObject<T | null> {
  const el = useRef<T | null>(null);
  const handler = useCallback(() => {
    el.current?.click();
  }, []);
  useKeyboardShortcut(key, handler);
  return el;
}
 
export default function LinkWithHotkey(props: {
  to: string;
  children: ReactNode;
  shortcut: KeyboardShortcut;
}) {
  let path = props.to;
  if (path.substr(0, 1) !== "/") {
    path = `${$LEKTOR_CONFIG.admin_root}/${path}`;
  }
  const el = useKeyboardShortcutRef<HTMLAnchorElement>(props.shortcut);
 
  return (
    <NavLink
      to={path}
      activeClassName="active"
      title={getKey(props.shortcut)}
      ref={el}
    >
      {props.children}
    </NavLink>
  );
}