返回 slidev
shortcuts.ts
根目录 / packages / client / logic / shortcuts.ts
1 import type { ShortcutOptions } from '@slidev/types'
2 import type { Fn, KeyFilter } from '@vueuse/core'
3 import type { Ref } from 'vue'
4 import { onKeyStroke } from '@vueuse/core'
5 import { and, not } from '@vueuse/math'
6 import { watch } from 'vue'
7 import { useNav } from '../composables/useNav'
8 import setupShortcuts from '../setup/shortcuts'
9 import { fullscreen, isInputting, isOnFocus, magicKeys, shortcutsEnabled, shortcutsLocked } from '../state'
10
11 export function registerShortcuts() {
12 const { isPrintMode } = useNav()
13 const enabled = and(not(isInputting), not(isOnFocus), not(isPrintMode), shortcutsEnabled, not(shortcutsLocked))
14
15 const allShortcuts = setupShortcuts()
16 const shortcuts = new Map<string | Ref<boolean>, ShortcutOptions>(
17 allShortcuts.map((options: ShortcutOptions) => [options.key, options]),
18 )
19
20 shortcuts.forEach((options) => {
21 if (options.fn)
22 shortcut(options.key, options.fn, options.autoRepeat)
23 })
24
25 strokeShortcut('f', () => fullscreen.toggle())
26
27 function shortcut(key: string | Ref<boolean>, fn: Fn, autoRepeat = false) {
28 if (typeof key === 'string')
29 key = magicKeys[key]
30
31 const source = and(key, enabled)
32 let count = 0
33 let timer: any
34 const trigger = () => {
35 clearTimeout(timer)
36 if (!source.value) {
37 count = 0
38 return
39 }
40 if (autoRepeat) {
41 timer = setTimeout(trigger, Math.max(1000 - count * 250, 150))
42 count++
43 }
44 fn()
45 }
46
47 return watch(source, trigger, { flush: 'sync' })
48 }
49
50 function strokeShortcut(key: KeyFilter, fn: Fn) {
51 return onKeyStroke(key, (ev) => {
52 if (!enabled.value)
53 return
54 if (!ev.repeat)
55 fn()
56 })
57 }
58 }
59
59 lines TYPESCRIPT