diff options
| -rw-r--r-- | apps/web/src/actions/guards.ts | 29 | ||||
| -rw-r--r-- | apps/web/src/actions/index.ts | 1 | ||||
| -rw-r--r-- | apps/web/src/actions/keybinding.ts | 20 |
3 files changed, 50 insertions, 0 deletions
diff --git a/apps/web/src/actions/guards.ts b/apps/web/src/actions/guards.ts new file mode 100644 index 00000000..c4fbe8a7 --- /dev/null +++ b/apps/web/src/actions/guards.ts @@ -0,0 +1,29 @@ +import { ACTIONS } from "./definitions"; +import type { TActionArgsMap, TActionWithOptionalArgs } from "./types"; + +type TActionWithRequiredArgs = { + [K in keyof TActionArgsMap]: undefined extends TActionArgsMap[K] + ? never + : K; +}[keyof TActionArgsMap]; + +/** + * Actions that require arguments cannot be bound to a shortcut key — a key + * press has no way to supply them. Keep in sync with the required (non- + * optional) members of `TActionArgsMap`; the type annotation rejects keys + * that are not actually required-args actions. + */ +const ACTIONS_WITH_REQUIRED_ARGS: readonly TActionWithRequiredArgs[] = [ + "remove-media-asset", + "remove-media-assets", +]; + +export function isActionWithOptionalArgs( + action: unknown, +): action is TActionWithOptionalArgs { + return ( + typeof action === "string" && + action in ACTIONS && + !(ACTIONS_WITH_REQUIRED_ARGS as readonly string[]).includes(action) + ); +} diff --git a/apps/web/src/actions/index.ts b/apps/web/src/actions/index.ts index 801a846a..d74a31a5 100644 --- a/apps/web/src/actions/index.ts +++ b/apps/web/src/actions/index.ts @@ -1,3 +1,4 @@ export * from "./definitions"; export * from "./types"; export * from "./registry"; +export * from "./guards"; diff --git a/apps/web/src/actions/keybinding.ts b/apps/web/src/actions/keybinding.ts index aeec2fd6..a71b7e98 100644 --- a/apps/web/src/actions/keybinding.ts +++ b/apps/web/src/actions/keybinding.ts @@ -32,6 +32,26 @@ export function isKey(value: string): value is Key { return KEY_SET.has(value); } +const MODIFIER_KEYS: readonly ModifierKeys[] = [ + "ctrl", + "alt", + "shift", + "ctrl+shift", + "alt+shift", + "ctrl+alt", + "ctrl+alt+shift", +]; + +export function isShortcutKey(value: string): value is ShortcutKey { + if (isKey(value)) { + return true; + } + const parts = value.split("+"); + const key = parts.at(-1) ?? ""; + const modifiers = parts.slice(0, -1).join("+"); + return (MODIFIER_KEYS as readonly string[]).includes(modifiers) && isKey(key); +} + export type ModifierBasedShortcutKey = `${ModifierKeys}+${Key}`; // Singular keybindings (these will be disabled when an input-ish area has been focused) export type SingleCharacterShortcutKey = `${Key}`; |
