ultisuite-client/lib/drive/docs-keyboard-shortcut.ts
R3D347HR4Y 79bb6193fc
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
menus1
2026-06-09 18:27:10 +02:00

89 lines
2.7 KiB
TypeScript

import type { DocsShortcutBinding } from "@/lib/drive/docs-keyboard-shortcuts-config"
export type { DocsShortcutBinding }
export function isMacPlatform(): boolean {
if (typeof navigator === "undefined") return false
return (
/Mac|iPhone|iPad|iPod/.test(navigator.platform) ||
(navigator.userAgent.includes("Mac") && "ontouchend" in document)
)
}
export function docsModKeyLabel(): string {
return isMacPlatform() ? "⌘" : "Ctrl"
}
export function normalizeDocsShortcutBinding(
binding: DocsShortcutBinding
): Required<Pick<DocsShortcutBinding, "key">> & {
mod: boolean
shift: boolean
alt: boolean
} {
return {
key: binding.key.length === 1 ? binding.key.toLowerCase() : binding.key,
mod: binding.mod ?? true,
shift: binding.shift ?? false,
alt: binding.alt ?? false,
}
}
/** Display label, e.g. ⌘Z or Ctrl+Shift+V */
export function formatDocsShortcutBinding(binding: DocsShortcutBinding): string {
const normalized = normalizeDocsShortcutBinding(binding)
const mod = docsModKeyLabel()
const isMac = isMacPlatform()
const keyLabel =
normalized.key.length === 1 ? normalized.key.toUpperCase() : normalized.key
if (isMac) {
const parts: string[] = []
if (normalized.shift) parts.push("Maj")
if (normalized.alt) parts.push("⌥")
if (parts.length > 0) {
return `${mod}+${parts.join("+")}+${keyLabel}`
}
return normalized.mod ? `${mod}${keyLabel}` : keyLabel
}
const parts: string[] = []
if (normalized.shift) parts.push("Shift")
if (normalized.alt) parts.push("Alt")
if (normalized.mod) parts.push(mod)
parts.push(keyLabel)
return parts.join("+")
}
export function matchesDocsShortcutBinding(
event: KeyboardEvent,
binding: DocsShortcutBinding
): boolean {
const normalized = normalizeDocsShortcutBinding(binding)
const modPressed = isMacPlatform() ? event.metaKey : event.ctrlKey
if (normalized.mod && !modPressed) return false
if (!normalized.mod && modPressed) return false
const eventKey =
event.key.length === 1 ? event.key.toLowerCase() : event.key
if (eventKey !== normalized.key) return false
if (normalized.shift !== event.shiftKey) return false
if (normalized.alt !== event.altKey) return false
return true
}
/** TipTap key string, e.g. Mod-Shift-h */
export function docsShortcutBindingToTipTapKey(binding: DocsShortcutBinding): string {
const normalized = normalizeDocsShortcutBinding(binding)
const parts: string[] = []
if (normalized.mod) parts.push("Mod")
if (normalized.shift) parts.push("Shift")
if (normalized.alt) parts.push("Alt")
parts.push(
normalized.key.length === 1 ? normalized.key.toLowerCase() : normalized.key
)
return parts.join("-")
}