96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import {
|
|
formatDocsShortcutBinding,
|
|
matchesDocsShortcutBinding,
|
|
normalizeDocsShortcutBinding,
|
|
} from "@/lib/drive/docs-keyboard-shortcut"
|
|
import {
|
|
DOCS_KEYBOARD_SHORTCUT_DEFINITIONS,
|
|
DOCS_KEYBOARD_SHORTCUTS_BY_ID,
|
|
type DocsKeyboardShortcutsUserConfig,
|
|
type DocsShortcutBinding,
|
|
type DocsShortcutDefinition,
|
|
type DocsShortcutId,
|
|
} from "@/lib/drive/docs-keyboard-shortcuts-config"
|
|
|
|
export function getDocsShortcutDefinition(id: DocsShortcutId): DocsShortcutDefinition {
|
|
return DOCS_KEYBOARD_SHORTCUTS_BY_ID[id]
|
|
}
|
|
|
|
export function resolveDocsShortcutBinding(
|
|
id: DocsShortcutId,
|
|
overrides: DocsKeyboardShortcutsUserConfig = {}
|
|
): DocsShortcutBinding {
|
|
return overrides[id] ?? DOCS_KEYBOARD_SHORTCUTS_BY_ID[id].defaultBinding
|
|
}
|
|
|
|
export function resolveDocsShortcutBindings(
|
|
id: DocsShortcutId,
|
|
overrides: DocsKeyboardShortcutsUserConfig = {}
|
|
): DocsShortcutBinding[] {
|
|
const definition = DOCS_KEYBOARD_SHORTCUTS_BY_ID[id]
|
|
const primary = resolveDocsShortcutBinding(id, overrides)
|
|
const alt = overrides[id] ? [] : (definition.altBindings ?? [])
|
|
return [primary, ...alt]
|
|
}
|
|
|
|
export function formatDocsShortcutId(
|
|
id: DocsShortcutId,
|
|
overrides: DocsKeyboardShortcutsUserConfig = {}
|
|
): string {
|
|
return formatDocsShortcutBinding(resolveDocsShortcutBinding(id, overrides))
|
|
}
|
|
|
|
export function matchDocsShortcutEvent(
|
|
event: KeyboardEvent,
|
|
overrides: DocsKeyboardShortcutsUserConfig = {},
|
|
filter?: (definition: DocsShortcutDefinition) => boolean
|
|
): DocsShortcutId | null {
|
|
for (const definition of DOCS_KEYBOARD_SHORTCUT_DEFINITIONS) {
|
|
if (filter && !filter(definition)) continue
|
|
const bindings = resolveDocsShortcutBindings(definition.id, overrides)
|
|
if (bindings.some((binding) => matchesDocsShortcutBinding(event, binding))) {
|
|
return definition.id
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function isValidDocsShortcutBinding(value: unknown): value is DocsShortcutBinding {
|
|
if (!value || typeof value !== "object") return false
|
|
const binding = value as DocsShortcutBinding
|
|
if (typeof binding.key !== "string" || binding.key.length === 0) return false
|
|
if (binding.mod != null && typeof binding.mod !== "boolean") return false
|
|
if (binding.shift != null && typeof binding.shift !== "boolean") return false
|
|
if (binding.alt != null && typeof binding.alt !== "boolean") return false
|
|
return true
|
|
}
|
|
|
|
export function sanitizeDocsKeyboardShortcutsUserConfig(
|
|
raw: unknown
|
|
): DocsKeyboardShortcutsUserConfig {
|
|
if (!raw || typeof raw !== "object") return {}
|
|
const input = raw as Record<string, unknown>
|
|
const output: DocsKeyboardShortcutsUserConfig = {}
|
|
|
|
for (const definition of DOCS_KEYBOARD_SHORTCUT_DEFINITIONS) {
|
|
const candidate = input[definition.id]
|
|
if (isValidDocsShortcutBinding(candidate)) {
|
|
output[definition.id] = normalizeDocsShortcutBinding(candidate)
|
|
}
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
/** Catalog for a future keyboard-shortcuts settings screen. */
|
|
export function listDocsKeyboardShortcutCatalog(
|
|
overrides: DocsKeyboardShortcutsUserConfig = {}
|
|
) {
|
|
return DOCS_KEYBOARD_SHORTCUT_DEFINITIONS.map((definition) => ({
|
|
...definition,
|
|
binding: resolveDocsShortcutBinding(definition.id, overrides),
|
|
display: formatDocsShortcutId(definition.id, overrides),
|
|
isCustomized: Boolean(overrides[definition.id]),
|
|
}))
|
|
}
|