From 5110ec8c5326f6914ff36e5a163416025e10b72a Mon Sep 17 00:00:00 2001 From: brianuribe6 Date: Wed, 7 Feb 2024 06:33:49 -0500 Subject: [PATCH] Move shortcut helpers to its own separate module --- .../src/components/Sidebar/Category.tsx | 2 +- .../front-end/src/components/Sidebar/Link.tsx | 2 +- .../src/components/Sidebar/shorcuts.ts | 2 +- apps/front-end/src/lib/hotkeys.ts | 63 ++++++++++++++++++ apps/front-end/src/utils.ts | 64 +------------------ 5 files changed, 67 insertions(+), 66 deletions(-) create mode 100644 apps/front-end/src/lib/hotkeys.ts diff --git a/apps/front-end/src/components/Sidebar/Category.tsx b/apps/front-end/src/components/Sidebar/Category.tsx index 0d5c3b7..0412913 100644 --- a/apps/front-end/src/components/Sidebar/Category.tsx +++ b/apps/front-end/src/components/Sidebar/Category.tsx @@ -20,7 +20,7 @@ import { MenuAction } from "./MenuAction"; import { EventHandlersContext } from "./Sidebar"; import { removeItem } from "./state"; import { withDeleteItemShortcut, withRenameItemShortcut } from "./shorcuts"; -import { registerShortcuts as registerShortcuts } from "@/utils"; +import { registerShortcuts } from "@/lib/hotkeys"; export type CategoryProps = { category: CategoryItem; diff --git a/apps/front-end/src/components/Sidebar/Link.tsx b/apps/front-end/src/components/Sidebar/Link.tsx index 0eaee51..b0fcd69 100644 --- a/apps/front-end/src/components/Sidebar/Link.tsx +++ b/apps/front-end/src/components/Sidebar/Link.tsx @@ -13,7 +13,7 @@ import { MenuAction } from "./MenuAction"; import { EventHandlersContext } from "./Sidebar"; import { removeItem } from "./state"; import DeleteConfirmationDialog from "./DeleteConfirmationDialog"; -import { registerShortcuts } from "@/utils"; +import { registerShortcuts } from "@/lib/hotkeys"; import { withDeleteItemShortcut, withRenameItemShortcut } from "./shorcuts"; export type LinkProps = { diff --git a/apps/front-end/src/components/Sidebar/shorcuts.ts b/apps/front-end/src/components/Sidebar/shorcuts.ts index 69edb9e..17fc8ea 100644 --- a/apps/front-end/src/components/Sidebar/shorcuts.ts +++ b/apps/front-end/src/components/Sidebar/shorcuts.ts @@ -1,4 +1,4 @@ -import { createShortcutHandler } from "@/utils"; +import { createShortcutHandler } from "@/lib/hotkeys"; export const withDeleteItemShortcut = createShortcutHandler({ key: "Delete", diff --git a/apps/front-end/src/lib/hotkeys.ts b/apps/front-end/src/lib/hotkeys.ts new file mode 100644 index 0000000..41baa7b --- /dev/null +++ b/apps/front-end/src/lib/hotkeys.ts @@ -0,0 +1,63 @@ +import { KeyboardEventHandler } from "react"; + +type ShorcutConfiguration = { + modifiers?: Partial< + Pick + >; + key: string; +}; + +export function createShortcutHandler(options: ShorcutConfiguration) { + return function handler( + callback: KeyboardEventHandler, + ): KeyboardEventHandler { + return (e) => { + if (e.repeat || isEditableElement(e.target)) { + // Either This event was already handled (user is holding the keys) + // Or the user is editing some text, so we do nothing. + return; + } + if (!options.modifiers && options.key === e.code) { + callback(e); + return; + } + + if (!options.modifiers) { + return; + } + + const modifierKeys = Object.keys(options.modifiers) as Array< + keyof typeof options.modifiers + >; + for (const key of modifierKeys) { + if (e[key] !== options.modifiers[key]) { + return; + } + } + if (options.key === e.code) { + callback(e); + } + }; + }; +} + +function isEditableElement(target: EventTarget): boolean { + if (!(target instanceof HTMLElement)) { + return false; + } + return ( + target.isContentEditable || + target.tagName === "INPUT" || + target.tagName === "TEXTAREA" + ); +} + +export function registerShortcuts( + ...handlers: KeyboardEventHandler[] +): KeyboardEventHandler { + return (e) => { + for (const handler of handlers) { + handler(e); + } + }; +} diff --git a/apps/front-end/src/utils.ts b/apps/front-end/src/utils.ts index b523521..8373d43 100644 --- a/apps/front-end/src/utils.ts +++ b/apps/front-end/src/utils.ts @@ -1,4 +1,4 @@ -import { KeyboardEventHandler, MutableRefObject, RefCallback } from "react"; +import { MutableRefObject, RefCallback } from "react"; type Ref = RefCallback | MutableRefObject | null; @@ -20,65 +20,3 @@ export function mergeRefs(...refs: Ref[]) { }); }; } - -type ShorcutConfiguration = { - modifiers?: Partial< - Pick - >; - key: string; -}; - -export function createShortcutHandler(options: ShorcutConfiguration) { - return function handler( - callback: KeyboardEventHandler, - ): KeyboardEventHandler { - return (e) => { - if (e.repeat || isEditableElement(e.target)) { - // Either This event was already handled (user is holding the keys) - // Or the user is editing some text, so we do nothing. - return; - } - if (!options.modifiers && options.key === e.code) { - callback(e); - return; - } - - if (!options.modifiers) { - return; - } - - const modifierKeys = Object.keys(options.modifiers) as Array< - keyof typeof options.modifiers - >; - for (const key of modifierKeys) { - if (e[key] !== options.modifiers[key]) { - return; - } - } - if (options.key === e.code) { - callback(e); - } - }; - }; -} - -function isEditableElement(target: EventTarget): boolean { - if (!(target instanceof HTMLElement)) { - return false; - } - return ( - target.isContentEditable || - target.tagName === "INPUT" || - target.tagName === "TEXTAREA" - ); -} - -export function registerShortcuts( - ...handlers: KeyboardEventHandler[] -): KeyboardEventHandler { - return (e) => { - for (const handler of handlers) { - handler(e); - } - }; -}