| 1 | import type { NavOperations, ShortcutOptions } from '@slidev/types' |
| 2 | import { and, not, or } from '@vueuse/math' |
| 3 | import setups from '#slidev/setups/shortcuts' |
| 4 | import { useDrawings } from '../composables/useDrawings' |
| 5 | import { useNav } from '../composables/useNav' |
| 6 | import { toggleDark } from '../logic/dark' |
| 7 | import { activeDragElement, magicKeys, showGotoDialog, showOverview, toggleOverview } from '../state' |
| 8 | import { downloadPDF } from '../utils' |
| 9 | import { currentOverviewPage, downOverviewPage, nextOverviewPage, prevOverviewPage, upOverviewPage } from './../logic/overview' |
| 10 | |
| 11 | export default function setupShortcuts() { |
| 12 | const { go, goFirst, goLast, next, nextSlide, prev, prevSlide } = useNav() |
| 13 | const { drawingEnabled } = useDrawings() |
| 14 | const { escape, space, shift, left, right, up, down, enter, d, g, o, '`': backtick } = magicKeys |
| 15 | |
| 16 | const context: NavOperations = { |
| 17 | next, |
| 18 | prev, |
| 19 | nextSlide, |
| 20 | prevSlide, |
| 21 | go, |
| 22 | goFirst, |
| 23 | goLast, |
| 24 | downloadPDF, |
| 25 | toggleDark, |
| 26 | toggleOverview, |
| 27 | toggleDrawing: () => drawingEnabled.value = !drawingEnabled.value, |
| 28 | escapeOverview: () => showOverview.value = false, |
| 29 | showGotoDialog: () => showGotoDialog.value = !showGotoDialog.value, |
| 30 | } |
| 31 | |
| 32 | const navViaArrowKeys = and(not(showOverview), not(activeDragElement)) |
| 33 | |
| 34 | let shortcuts: ShortcutOptions[] = [ |
| 35 | { name: 'next_space', key: and(space, not(shift)), fn: next, autoRepeat: true }, |
| 36 | { name: 'prev_space', key: and(space, shift), fn: prev, autoRepeat: true }, |
| 37 | { name: 'next_right', key: and(right, not(shift), navViaArrowKeys), fn: next, autoRepeat: true }, |
| 38 | { name: 'prev_left', key: and(left, not(shift), navViaArrowKeys), fn: prev, autoRepeat: true }, |
| 39 | { name: 'next_page_key', key: 'pageDown', fn: next, autoRepeat: true }, |
| 40 | { name: 'prev_page_key', key: 'pageUp', fn: prev, autoRepeat: true }, |
| 41 | { name: 'next_down', key: and(down, navViaArrowKeys), fn: nextSlide, autoRepeat: true }, |
| 42 | { name: 'prev_up', key: and(up, navViaArrowKeys), fn: prevSlide, autoRepeat: true }, |
| 43 | { name: 'next_shift', key: and(right, shift), fn: nextSlide, autoRepeat: true }, |
| 44 | { name: 'prev_shift', key: and(left, shift), fn: prevSlide, autoRepeat: true }, |
| 45 | { name: 'toggle_dark', key: and(d, not(drawingEnabled)), fn: toggleDark }, |
| 46 | { name: 'toggle_overview', key: and(or(o, backtick), not(drawingEnabled)), fn: toggleOverview }, |
| 47 | { name: 'hide_overview', key: and(escape, not(drawingEnabled)), fn: () => showOverview.value = false }, |
| 48 | { name: 'goto', key: and(g, not(drawingEnabled)), fn: () => showGotoDialog.value = !showGotoDialog.value }, |
| 49 | { name: 'next_overview', key: and(right, showOverview), fn: nextOverviewPage }, |
| 50 | { name: 'prev_overview', key: and(left, showOverview), fn: prevOverviewPage }, |
| 51 | { name: 'up_overview', key: and(up, showOverview), fn: upOverviewPage }, |
| 52 | { name: 'down_overview', key: and(down, showOverview), fn: downOverviewPage }, |
| 53 | { |
| 54 | name: 'goto_from_overview', |
| 55 | key: and(enter, showOverview), |
| 56 | fn: () => { |
| 57 | go(currentOverviewPage.value) |
| 58 | showOverview.value = false |
| 59 | }, |
| 60 | }, |
| 61 | ] |
| 62 | |
| 63 | const baseShortcutNames = new Set(shortcuts.map(s => s.name)) |
| 64 | |
| 65 | for (const setup of setups) { |
| 66 | shortcuts = setup(context, shortcuts) |
| 67 | } |
| 68 | |
| 69 | const remainingBaseShortcutNames = shortcuts.filter(s => s.name && baseShortcutNames.has(s.name)) |
| 70 | if (remainingBaseShortcutNames.length === 0) { |
| 71 | const message = [ |
| 72 | '========== WARNING ==========', |
| 73 | 'defineShortcutsSetup did not return any of the base shortcuts.', |
| 74 | 'See https://sli.dev/custom/config-shortcuts.html for migration.', |
| 75 | 'If it is intentional, return at least one shortcut with one of the base names (e.g. name:"goto").', |
| 76 | ].join('\n\n') |
| 77 | // eslint-disable-next-line no-alert |
| 78 | alert(message) |
| 79 | |
| 80 | console.warn(message) |
| 81 | } |
| 82 | |
| 83 | return shortcuts |
| 84 | } |
| 85 |