@slidev/client 0.48.0-beta.2 → 0.48.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/App.vue +7 -0
- package/builtin/Arrow.vue +2 -4
- package/builtin/CodeBlockWrapper.vue +14 -6
- package/builtin/KaTexBlockWrapper.vue +5 -4
- package/builtin/Mermaid.vue +4 -3
- package/builtin/Monaco.vue +109 -92
- package/builtin/RenderWhen.vue +3 -3
- package/builtin/ShikiMagicMove.vue +50 -0
- package/builtin/SlideCurrentNo.vue +2 -3
- package/builtin/SlidesTotal.vue +3 -4
- package/builtin/SlidevVideo.vue +9 -7
- package/builtin/Toc.vue +4 -4
- package/builtin/TocList.vue +4 -3
- package/builtin/Tweet.vue +3 -22
- package/builtin/VClick.ts +2 -1
- package/builtin/VClickGap.vue +3 -5
- package/builtin/VClicks.ts +1 -1
- package/composables/useClicks.ts +39 -20
- package/composables/useContext.ts +4 -9
- package/composables/useNav.ts +182 -44
- package/composables/useSwipeControls.ts +40 -0
- package/composables/useTocTree.ts +63 -0
- package/constants.ts +59 -10
- package/context.ts +73 -0
- package/env.ts +3 -12
- package/internals/ClicksSlider.vue +93 -0
- package/internals/Controls.vue +2 -2
- package/internals/DrawingControls.vue +39 -9
- package/internals/DrawingLayer.vue +3 -3
- package/internals/Goto.vue +7 -6
- package/internals/IconButton.vue +7 -3
- package/internals/InfoDialog.vue +1 -1
- package/internals/Modal.vue +1 -1
- package/internals/NavControls.vue +11 -10
- package/internals/NoteDisplay.vue +131 -8
- package/internals/NoteEditable.vue +128 -0
- package/internals/NoteStatic.vue +8 -6
- package/internals/PrintContainer.vue +8 -6
- package/internals/PrintSlide.vue +10 -11
- package/internals/PrintSlideClick.vue +14 -18
- package/internals/{SlidesOverview.vue → QuickOverview.vue} +31 -20
- package/internals/RecordingControls.vue +1 -1
- package/internals/RecordingDialog.vue +5 -6
- package/internals/{Editor.vue → SideEditor.vue} +9 -5
- package/internals/SlideContainer.vue +12 -9
- package/internals/SlideLoading.vue +19 -0
- package/internals/SlideWrapper.ts +32 -16
- package/internals/SlidesShow.vue +20 -18
- package/layouts/error.vue +5 -0
- package/layouts/two-cols-header.vue +9 -3
- package/logic/drawings.ts +13 -10
- package/logic/nav-state.ts +20 -0
- package/logic/nav.ts +51 -258
- package/logic/note.ts +9 -9
- package/logic/overview.ts +2 -2
- package/logic/route.ts +10 -1
- package/logic/slides.ts +19 -0
- package/logic/transition.ts +50 -0
- package/main.ts +8 -4
- package/modules/context.ts +7 -13
- package/modules/mermaid.ts +6 -7
- package/modules/{directives.ts → v-click.ts} +15 -15
- package/modules/v-mark.ts +159 -0
- package/package.json +27 -16
- package/{internals/EntrySelect.vue → pages/entry.vue} +7 -0
- package/{internals/NotesView.vue → pages/notes.vue} +7 -6
- package/pages/overview.vue +227 -0
- package/{internals/Play.vue → pages/play.vue} +17 -13
- package/{internals/PresenterPrint.vue → pages/presenter/print.vue} +13 -8
- package/{internals/Presenter.vue → pages/presenter.vue} +114 -105
- package/{internals/Print.vue → pages/print.vue} +3 -4
- package/routes.ts +28 -60
- package/setup/codemirror.ts +8 -3
- package/setup/monaco.ts +108 -44
- package/setup/root.ts +8 -9
- package/setup/shortcuts.ts +2 -1
- package/shim-vue.d.ts +38 -0
- package/shim.d.ts +1 -13
- package/state/index.ts +10 -10
- package/styles/code.css +7 -3
- package/styles/index.css +68 -7
- package/styles/katex.css +1 -1
- package/styles/layouts-base.css +17 -12
- package/styles/monaco.css +27 -0
- package/styles/vars.css +1 -0
- package/uno.config.ts +14 -2
- package/utils.ts +15 -2
- package/iframes/monaco/index.css +0 -28
- package/iframes/monaco/index.html +0 -7
- package/iframes/monaco/index.ts +0 -260
- package/internals/NoteEditor.vue +0 -88
package/logic/drawings.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { createDrauu } from 'drauu'
|
|
|
4
4
|
import { toReactive, useLocalStorage } from '@vueuse/core'
|
|
5
5
|
import { drawingState, onPatch, patch } from '../state/drawings'
|
|
6
6
|
import { configs } from '../env'
|
|
7
|
-
import {
|
|
7
|
+
import { isInputting } from '../state'
|
|
8
|
+
import { currentSlideNo, isPresenter } from './nav'
|
|
8
9
|
|
|
9
10
|
export const brushColors = [
|
|
10
11
|
'#ff595e',
|
|
@@ -40,11 +41,13 @@ export const drawingMode = computed({
|
|
|
40
41
|
set(v: DrawingMode | 'arrow') {
|
|
41
42
|
_mode.value = v
|
|
42
43
|
if (v === 'arrow') {
|
|
43
|
-
|
|
44
|
+
// eslint-disable-next-line ts/no-use-before-define
|
|
45
|
+
drauu.mode = 'line'
|
|
44
46
|
brush.arrowEnd = true
|
|
45
47
|
}
|
|
46
48
|
else {
|
|
47
|
-
|
|
49
|
+
// eslint-disable-next-line ts/no-use-before-define
|
|
50
|
+
drauu.mode = v
|
|
48
51
|
brush.arrowEnd = false
|
|
49
52
|
}
|
|
50
53
|
},
|
|
@@ -60,7 +63,7 @@ export const drauu = markRaw(createDrauu(drauuOptions))
|
|
|
60
63
|
export function clearDrauu() {
|
|
61
64
|
drauu.clear()
|
|
62
65
|
if (syncUp.value)
|
|
63
|
-
patch(
|
|
66
|
+
patch(currentSlideNo.value, '')
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
export function updateState() {
|
|
@@ -71,7 +74,7 @@ export function updateState() {
|
|
|
71
74
|
|
|
72
75
|
export function loadCanvas(page?: number) {
|
|
73
76
|
disableDump = true
|
|
74
|
-
const data = drawingState[page ||
|
|
77
|
+
const data = drawingState[page || currentSlideNo.value]
|
|
75
78
|
if (data != null)
|
|
76
79
|
drauu.load(data)
|
|
77
80
|
else
|
|
@@ -84,7 +87,7 @@ drauu.on('changed', () => {
|
|
|
84
87
|
updateState()
|
|
85
88
|
if (!disableDump) {
|
|
86
89
|
const dump = drauu.dump()
|
|
87
|
-
const key =
|
|
90
|
+
const key = currentSlideNo.value
|
|
88
91
|
if ((drawingState[key] || '') !== dump && syncUp.value)
|
|
89
92
|
patch(key, drauu.dump())
|
|
90
93
|
}
|
|
@@ -92,14 +95,14 @@ drauu.on('changed', () => {
|
|
|
92
95
|
|
|
93
96
|
onPatch((state) => {
|
|
94
97
|
disableDump = true
|
|
95
|
-
if (state[
|
|
96
|
-
drauu.load(state[
|
|
98
|
+
if (state[currentSlideNo.value] != null)
|
|
99
|
+
drauu.load(state[currentSlideNo.value] || '')
|
|
97
100
|
disableDump = false
|
|
98
101
|
updateState()
|
|
99
102
|
})
|
|
100
103
|
|
|
101
104
|
nextTick(() => {
|
|
102
|
-
watch(
|
|
105
|
+
watch(currentSlideNo, () => {
|
|
103
106
|
if (!drauu.mounted)
|
|
104
107
|
return
|
|
105
108
|
loadCanvas()
|
|
@@ -110,7 +113,7 @@ drauu.on('start', () => isDrawing.value = true)
|
|
|
110
113
|
drauu.on('end', () => isDrawing.value = false)
|
|
111
114
|
|
|
112
115
|
window.addEventListener('keydown', (e) => {
|
|
113
|
-
if (!drawingEnabled.value)
|
|
116
|
+
if (!drawingEnabled.value || isInputting.value)
|
|
114
117
|
return
|
|
115
118
|
|
|
116
119
|
const noModifier = !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import { logicOr } from '@vueuse/math'
|
|
3
|
+
import { configs } from '../env'
|
|
4
|
+
import { router } from '../routes'
|
|
5
|
+
import { getSlide, slides } from './slides'
|
|
6
|
+
|
|
7
|
+
export const currentRoute = computed(() => router.currentRoute.value)
|
|
8
|
+
|
|
9
|
+
export const isPrintMode = computed(() => currentRoute.value.query.print !== undefined)
|
|
10
|
+
export const isPrintWithClicks = computed(() => currentRoute.value.query.print === 'clicks')
|
|
11
|
+
export const isEmbedded = computed(() => currentRoute.value.query.embedded !== undefined)
|
|
12
|
+
export const isPlaying = computed(() => currentRoute.value.name === 'play')
|
|
13
|
+
export const isPresenter = computed(() => currentRoute.value.name === 'presenter')
|
|
14
|
+
export const isNotesViewer = computed(() => currentRoute.value.name === 'notes')
|
|
15
|
+
export const isPresenterAvailable = computed(() => !isPresenter.value && (!configs.remote || currentRoute.value.query.password === configs.remote))
|
|
16
|
+
|
|
17
|
+
export const hasPrimarySlide = logicOr(isPlaying, isPresenter)
|
|
18
|
+
|
|
19
|
+
export const currentSlideNo = computed(() => hasPrimarySlide.value ? getSlide(currentRoute.value.params.no as string)?.no ?? 1 : 1)
|
|
20
|
+
export const currentSlideRoute = computed(() => slides.value[currentSlideNo.value - 1])
|
package/logic/nav.ts
CHANGED
|
@@ -1,44 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { computed, nextTick, ref, watch } from 'vue'
|
|
4
|
-
import type { TocItem } from '@slidev/types'
|
|
5
|
-
import { timestamp, usePointerSwipe } from '@vueuse/core'
|
|
6
|
-
import { rawRoutes, router } from '../routes'
|
|
7
|
-
import { configs } from '../env'
|
|
8
|
-
import { skipTransition } from '../composables/hmr'
|
|
1
|
+
import { computed, watch } from 'vue'
|
|
2
|
+
import { router } from '../routes'
|
|
9
3
|
import { usePrimaryClicks } from '../composables/useClicks'
|
|
4
|
+
import { CLICKS_MAX } from '../constants'
|
|
5
|
+
import { useNavBase } from '../composables/useNav'
|
|
10
6
|
import { useRouteQuery } from './route'
|
|
11
|
-
import {
|
|
7
|
+
import { currentRoute, currentSlideRoute, hasPrimarySlide } from './nav-state'
|
|
8
|
+
import { getSlide } from './slides'
|
|
12
9
|
|
|
13
|
-
export
|
|
10
|
+
export * from './slides'
|
|
11
|
+
export * from './nav-state'
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
export const routeForceRefresh = ref(0)
|
|
17
|
-
nextTick(() => {
|
|
18
|
-
router.afterEach(async () => {
|
|
19
|
-
await nextTick()
|
|
20
|
-
routeForceRefresh.value += 1
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
export const navDirection = ref(0)
|
|
25
|
-
|
|
26
|
-
export const route = computed(() => router.currentRoute.value)
|
|
27
|
-
|
|
28
|
-
export const isPrintMode = computed(() => route.value.query.print !== undefined)
|
|
29
|
-
export const isPrintWithClicks = computed(() => route.value.query.print === 'clicks')
|
|
30
|
-
export const isEmbedded = computed(() => route.value.query.embedded !== undefined)
|
|
31
|
-
export const isPresenter = computed(() => route.value.path.startsWith('/presenter'))
|
|
32
|
-
export const isNotesViewer = computed(() => route.value.path.startsWith('/notes'))
|
|
33
|
-
export const presenterPassword = computed(() => route.value.query.password)
|
|
34
|
-
export const showPresenter = computed(() => !isPresenter.value && (!configs.remote || presenterPassword.value === configs.remote))
|
|
13
|
+
export const clicksContext = computed(() => usePrimaryClicks(currentSlideRoute.value))
|
|
35
14
|
|
|
36
15
|
const queryClicksRaw = useRouteQuery('clicks', '0')
|
|
37
16
|
export const queryClicks = computed({
|
|
38
17
|
get() {
|
|
39
|
-
// eslint-disable-next-line ts/no-use-before-define
|
|
40
18
|
if (clicksContext.value.disabled)
|
|
41
|
-
return
|
|
19
|
+
return CLICKS_MAX
|
|
42
20
|
let v = +(queryClicksRaw.value || 0)
|
|
43
21
|
if (Number.isNaN(v))
|
|
44
22
|
v = 0
|
|
@@ -49,230 +27,45 @@ export const queryClicks = computed({
|
|
|
49
27
|
},
|
|
50
28
|
})
|
|
51
29
|
|
|
52
|
-
export const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
queryClicks.value += 1
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function prev() {
|
|
94
|
-
if (queryClicks.value <= 0)
|
|
95
|
-
await prevSlide()
|
|
96
|
-
else
|
|
97
|
-
queryClicks.value -= 1
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function getPath(no: number | string) {
|
|
101
|
-
return isPresenter.value ? `/presenter/${no}` : `/${no}`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function nextSlide() {
|
|
105
|
-
if (currentPage.value < rawRoutes.length)
|
|
106
|
-
await go(currentPage.value + 1)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export async function prevSlide(lastClicks = true) {
|
|
110
|
-
const next = Math.max(1, currentPage.value - 1)
|
|
111
|
-
await go(next)
|
|
112
|
-
if (lastClicks && clicksTotal.value)
|
|
113
|
-
router.replace({ query: { ...route.value.query, clicks: clicksTotal.value } })
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function goFirst() {
|
|
117
|
-
return go(1)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function goLast() {
|
|
121
|
-
return go(total.value)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function go(page: number | string, clicks?: number) {
|
|
125
|
-
skipTransition.value = false
|
|
126
|
-
return router.push({ path: getPath(page), query: { ...route.value.query, clicks } })
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function useSwipeControls(root: Ref<HTMLElement | undefined>) {
|
|
130
|
-
const swipeBegin = ref(0)
|
|
131
|
-
const { direction, distanceX, distanceY } = usePointerSwipe(root, {
|
|
132
|
-
onSwipeStart(e) {
|
|
133
|
-
if (e.pointerType !== 'touch')
|
|
134
|
-
return
|
|
135
|
-
if (isDrawing.value)
|
|
136
|
-
return
|
|
137
|
-
swipeBegin.value = timestamp()
|
|
138
|
-
},
|
|
139
|
-
onSwipeEnd(e) {
|
|
140
|
-
if (e.pointerType !== 'touch')
|
|
141
|
-
return
|
|
142
|
-
if (!swipeBegin.value)
|
|
143
|
-
return
|
|
144
|
-
if (isDrawing.value)
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
const x = Math.abs(distanceX.value)
|
|
148
|
-
const y = Math.abs(distanceY.value)
|
|
149
|
-
if (x / window.innerWidth > 0.3 || x > 75) {
|
|
150
|
-
if (direction.value === 'left')
|
|
151
|
-
next()
|
|
152
|
-
else
|
|
153
|
-
prev()
|
|
154
|
-
}
|
|
155
|
-
else if (y / window.innerHeight > 0.4 || y > 200) {
|
|
156
|
-
if (direction.value === 'down')
|
|
157
|
-
prevSlide()
|
|
158
|
-
else
|
|
159
|
-
nextSlide()
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export async function downloadPDF() {
|
|
166
|
-
const { saveAs } = await import('file-saver')
|
|
167
|
-
saveAs(
|
|
168
|
-
typeof configs.download === 'string'
|
|
169
|
-
? configs.download
|
|
170
|
-
: configs.exportFilename
|
|
171
|
-
? `${configs.exportFilename}.pdf`
|
|
172
|
-
: `${import.meta.env.BASE_URL}slidev-exported.pdf`,
|
|
173
|
-
`${configs.title}.pdf`,
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export async function openInEditor(url?: string) {
|
|
178
|
-
if (url == null) {
|
|
179
|
-
const slide = currentRoute.value?.meta?.slide
|
|
180
|
-
if (!slide?.filepath)
|
|
181
|
-
return false
|
|
182
|
-
url = `${slide.filepath}:${slide.start}`
|
|
183
|
-
}
|
|
184
|
-
await fetch(`/__open-in-editor?file=${encodeURIComponent(url)}`)
|
|
185
|
-
return true
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export function addToTree(tree: TocItem[], route: RouteRecordRaw, level = 1) {
|
|
189
|
-
const titleLevel = route.meta?.slide?.level
|
|
190
|
-
if (titleLevel && titleLevel > level && tree.length > 0) {
|
|
191
|
-
addToTree(tree[tree.length - 1].children, route, level + 1)
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
tree.push({
|
|
195
|
-
children: [],
|
|
196
|
-
level,
|
|
197
|
-
path: route.path,
|
|
198
|
-
hideInToc: Boolean(route.meta?.slide?.frontmatter?.hideInToc),
|
|
199
|
-
title: route.meta?.slide?.title,
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export function getTreeWithActiveStatuses(
|
|
205
|
-
tree: TocItem[],
|
|
206
|
-
currentRoute?: RouteRecordRaw,
|
|
207
|
-
hasActiveParent = false,
|
|
208
|
-
parent?: TocItem,
|
|
209
|
-
): TocItem[] {
|
|
210
|
-
return tree.map((item: TocItem) => {
|
|
211
|
-
const clone = {
|
|
212
|
-
...item,
|
|
213
|
-
active: item.path === currentRoute?.path,
|
|
214
|
-
hasActiveParent,
|
|
30
|
+
export const {
|
|
31
|
+
slides,
|
|
32
|
+
total,
|
|
33
|
+
currentPath,
|
|
34
|
+
currentSlideNo,
|
|
35
|
+
currentPage,
|
|
36
|
+
currentLayout,
|
|
37
|
+
currentTransition,
|
|
38
|
+
clicksDirection,
|
|
39
|
+
nextRoute,
|
|
40
|
+
prevRoute,
|
|
41
|
+
clicks,
|
|
42
|
+
clicksTotal,
|
|
43
|
+
hasNext,
|
|
44
|
+
hasPrev,
|
|
45
|
+
tocTree,
|
|
46
|
+
navDirection,
|
|
47
|
+
openInEditor,
|
|
48
|
+
next,
|
|
49
|
+
prev,
|
|
50
|
+
go,
|
|
51
|
+
goLast,
|
|
52
|
+
goFirst,
|
|
53
|
+
nextSlide,
|
|
54
|
+
prevSlide,
|
|
55
|
+
} = useNavBase(
|
|
56
|
+
currentSlideRoute,
|
|
57
|
+
clicksContext,
|
|
58
|
+
queryClicks,
|
|
59
|
+
router,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
watch(
|
|
63
|
+
[total, currentRoute],
|
|
64
|
+
async () => {
|
|
65
|
+
if (hasPrimarySlide.value && !getSlide(currentRoute.value.params.no as string)) {
|
|
66
|
+
// The current slide may has been removed. Redirect to the last slide.
|
|
67
|
+
await goLast()
|
|
215
68
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
parent.activeParent = true
|
|
220
|
-
return clone
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function filterTree(tree: TocItem[], level = 1): TocItem[] {
|
|
225
|
-
return tree
|
|
226
|
-
.filter((item: TocItem) => !item.hideInToc)
|
|
227
|
-
.map((item: TocItem) => ({
|
|
228
|
-
...item,
|
|
229
|
-
children: filterTree(item.children, level + 1),
|
|
230
|
-
}))
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const transitionResolveMap: Record<string, string | undefined> = {
|
|
234
|
-
'slide-left': 'slide-left | slide-right',
|
|
235
|
-
'slide-right': 'slide-right | slide-left',
|
|
236
|
-
'slide-up': 'slide-up | slide-down',
|
|
237
|
-
'slide-down': 'slide-down | slide-up',
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export function resolveTransition(transition?: string | TransitionGroupProps, isBackward = false): TransitionGroupProps | undefined {
|
|
241
|
-
if (!transition)
|
|
242
|
-
return undefined
|
|
243
|
-
if (typeof transition === 'string') {
|
|
244
|
-
transition = {
|
|
245
|
-
name: transition,
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (!transition.name)
|
|
250
|
-
return undefined
|
|
251
|
-
|
|
252
|
-
let name = transition.name.includes('|')
|
|
253
|
-
? transition.name
|
|
254
|
-
: (transitionResolveMap[transition.name] || transition.name)
|
|
255
|
-
|
|
256
|
-
if (name.includes('|')) {
|
|
257
|
-
const [forward, backward] = name.split('|').map(i => i.trim())
|
|
258
|
-
name = isBackward ? backward : forward
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (!name)
|
|
262
|
-
return undefined
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
...transition,
|
|
266
|
-
name,
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export function getCurrentTransition(direction: number, currentRoute?: RouteRecordRaw, prevRoute?: RouteRecordRaw) {
|
|
271
|
-
let transition = direction > 0
|
|
272
|
-
? prevRoute?.meta?.transition
|
|
273
|
-
: currentRoute?.meta?.transition
|
|
274
|
-
if (!transition)
|
|
275
|
-
transition = configs.transition
|
|
276
|
-
|
|
277
|
-
return resolveTransition(transition, direction < 0)
|
|
278
|
-
}
|
|
69
|
+
},
|
|
70
|
+
{ flush: 'post', immediate: true },
|
|
71
|
+
)
|
package/logic/note.ts
CHANGED
|
@@ -2,17 +2,17 @@ import type { MaybeRef } from '@vueuse/core'
|
|
|
2
2
|
import { useFetch } from '@vueuse/core'
|
|
3
3
|
import type { Ref } from 'vue'
|
|
4
4
|
import { computed, ref, unref } from 'vue'
|
|
5
|
-
import type { SlideInfo,
|
|
5
|
+
import type { SlideInfo, SlidePatch } from '@slidev/types'
|
|
6
6
|
|
|
7
7
|
export interface UseSlideInfo {
|
|
8
|
-
info: Ref<
|
|
9
|
-
update: (data:
|
|
8
|
+
info: Ref<SlideInfo | undefined>
|
|
9
|
+
update: (data: SlidePatch) => Promise<SlideInfo | void>
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function useSlideInfo(id: number | undefined): UseSlideInfo {
|
|
13
13
|
if (id == null) {
|
|
14
14
|
return {
|
|
15
|
-
info: ref() as Ref<
|
|
15
|
+
info: ref() as Ref<SlideInfo | undefined>,
|
|
16
16
|
update: async () => {},
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -21,7 +21,7 @@ export function useSlideInfo(id: number | undefined): UseSlideInfo {
|
|
|
21
21
|
|
|
22
22
|
execute()
|
|
23
23
|
|
|
24
|
-
const update = async (data:
|
|
24
|
+
const update = async (data: SlidePatch) => {
|
|
25
25
|
return await fetch(
|
|
26
26
|
url,
|
|
27
27
|
{
|
|
@@ -36,12 +36,12 @@ export function useSlideInfo(id: number | undefined): UseSlideInfo {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
if (__DEV__) {
|
|
39
|
-
import.meta.hot?.on('slidev-
|
|
39
|
+
import.meta.hot?.on('slidev:update-slide', (payload) => {
|
|
40
40
|
if (payload.id === id)
|
|
41
41
|
info.value = payload.data
|
|
42
42
|
})
|
|
43
|
-
import.meta.hot?.on('slidev
|
|
44
|
-
if (payload.id === id && info.value.note
|
|
43
|
+
import.meta.hot?.on('slidev:update-note', (payload) => {
|
|
44
|
+
if (payload.id === id && info.value.note?.trim() !== payload.note?.trim())
|
|
45
45
|
info.value = { ...info.value, ...payload }
|
|
46
46
|
})
|
|
47
47
|
}
|
|
@@ -64,7 +64,7 @@ export function useDynamicSlideInfo(id: MaybeRef<number | undefined>) {
|
|
|
64
64
|
|
|
65
65
|
return {
|
|
66
66
|
info: computed(() => get(unref(id)).info.value),
|
|
67
|
-
update: async (data:
|
|
67
|
+
update: async (data: SlidePatch, newId?: number) => {
|
|
68
68
|
const info = get(newId ?? unref(id))
|
|
69
69
|
const newData = await info.update(data)
|
|
70
70
|
if (newData)
|
package/logic/overview.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { computed, ref } from 'vue'
|
|
2
|
-
import {
|
|
2
|
+
import { slides } from './nav'
|
|
3
3
|
|
|
4
4
|
// To have same format(.value) as max, wrap it with ref.
|
|
5
5
|
const min = ref(1)
|
|
6
|
-
const max = computed(() =>
|
|
6
|
+
const max = computed(() => slides.value.length)
|
|
7
7
|
|
|
8
8
|
export const currentOverviewPage = ref(0)
|
|
9
9
|
export const overviewRowCount = ref(0)
|
package/logic/route.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, nextTick, unref } from 'vue'
|
|
1
|
+
import { computed, nextTick, ref, unref } from 'vue'
|
|
2
2
|
import { router } from '../routes'
|
|
3
3
|
|
|
4
4
|
export function useRouteQuery<T extends string | string[]>(
|
|
@@ -24,3 +24,12 @@ export function useRouteQuery<T extends string | string[]>(
|
|
|
24
24
|
},
|
|
25
25
|
})
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
// force update collected elements when the route is fully resolved
|
|
29
|
+
export const routeForceRefresh = ref(0)
|
|
30
|
+
nextTick(() => {
|
|
31
|
+
router.afterEach(async () => {
|
|
32
|
+
await nextTick()
|
|
33
|
+
routeForceRefresh.value += 1
|
|
34
|
+
})
|
|
35
|
+
})
|
package/logic/slides.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SlideRoute } from '@slidev/types'
|
|
2
|
+
import { router } from '../routes'
|
|
3
|
+
import { isPresenter } from './nav-state'
|
|
4
|
+
import { slides } from '#slidev/slides'
|
|
5
|
+
|
|
6
|
+
export { slides, router }
|
|
7
|
+
|
|
8
|
+
export function getSlide(no: number | string) {
|
|
9
|
+
return slides.value.find(
|
|
10
|
+
s => (s.no === +no || s.meta.slide?.frontmatter.routeAlias === no),
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getSlidePath(route: SlideRoute | number | string, presenter = isPresenter.value) {
|
|
15
|
+
if (typeof route === 'number' || typeof route === 'string')
|
|
16
|
+
route = getSlide(route)!
|
|
17
|
+
const no = route.meta.slide?.frontmatter.routeAlias ?? route.no
|
|
18
|
+
return presenter ? `/presenter/${no}` : `/${no}`
|
|
19
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { SlideRoute } from '@slidev/types'
|
|
2
|
+
import type { TransitionGroupProps } from 'vue'
|
|
3
|
+
import { configs } from '../env'
|
|
4
|
+
|
|
5
|
+
const transitionResolveMap: Record<string, string | undefined> = {
|
|
6
|
+
'slide-left': 'slide-left | slide-right',
|
|
7
|
+
'slide-right': 'slide-right | slide-left',
|
|
8
|
+
'slide-up': 'slide-up | slide-down',
|
|
9
|
+
'slide-down': 'slide-down | slide-up',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function resolveTransition(transition?: string | TransitionGroupProps, isBackward = false): TransitionGroupProps | undefined {
|
|
13
|
+
if (!transition)
|
|
14
|
+
return undefined
|
|
15
|
+
if (typeof transition === 'string') {
|
|
16
|
+
transition = {
|
|
17
|
+
name: transition,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!transition.name)
|
|
22
|
+
return undefined
|
|
23
|
+
|
|
24
|
+
let name = transition.name.includes('|')
|
|
25
|
+
? transition.name
|
|
26
|
+
: (transitionResolveMap[transition.name] || transition.name)
|
|
27
|
+
|
|
28
|
+
if (name.includes('|')) {
|
|
29
|
+
const [forward, backward] = name.split('|').map(i => i.trim())
|
|
30
|
+
name = isBackward ? backward : forward
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!name)
|
|
34
|
+
return undefined
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
...transition,
|
|
38
|
+
name,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getCurrentTransition(direction: number, currentRoute?: SlideRoute, prevRoute?: SlideRoute) {
|
|
43
|
+
let transition = direction > 0
|
|
44
|
+
? prevRoute?.meta?.transition
|
|
45
|
+
: currentRoute?.meta?.transition
|
|
46
|
+
if (!transition)
|
|
47
|
+
transition = configs.transition
|
|
48
|
+
|
|
49
|
+
return resolveTransition(transition, direction < 0)
|
|
50
|
+
}
|
package/main.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
/// <reference types="@slidev/types/client" />
|
|
2
|
+
|
|
1
3
|
import { createApp } from 'vue'
|
|
2
4
|
import { createHead } from '@unhead/vue'
|
|
3
5
|
import App from './App.vue'
|
|
4
6
|
import setupMain from './setup/main'
|
|
5
7
|
import { router } from './routes'
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
+
import { createVClickDirectives } from './modules/v-click'
|
|
9
|
+
import { createVMarkDirective } from './modules/v-mark'
|
|
10
|
+
import { createSlidevContext } from './modules/context'
|
|
8
11
|
|
|
9
|
-
import '
|
|
12
|
+
import '#slidev/styles'
|
|
10
13
|
|
|
11
14
|
const app = createApp(App)
|
|
12
15
|
app.use(router)
|
|
13
16
|
app.use(createHead())
|
|
14
|
-
app.use(
|
|
17
|
+
app.use(createVClickDirectives())
|
|
18
|
+
app.use(createVMarkDirective())
|
|
15
19
|
app.use(createSlidevContext())
|
|
16
20
|
|
|
17
21
|
setupMain({ app, router })
|
package/modules/context.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import type { App } from 'vue'
|
|
2
|
-
import { computed, reactive } from 'vue'
|
|
3
|
-
import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router'
|
|
2
|
+
import { computed, reactive, ref } from 'vue'
|
|
4
3
|
import type { ComputedRef } from '@vue/reactivity'
|
|
5
4
|
import type { configs } from '../env'
|
|
6
5
|
import * as nav from '../logic/nav'
|
|
7
|
-
import { route } from '../logic/nav'
|
|
8
6
|
import { isDark } from '../logic/dark'
|
|
9
|
-
import { injectionCurrentPage, injectionSlidevContext } from '../constants'
|
|
7
|
+
import { injectionCurrentPage, injectionRenderContext, injectionSlidevContext } from '../constants'
|
|
10
8
|
import { useContext } from '../composables/useContext'
|
|
11
|
-
|
|
12
|
-
export type SlidevContextNavKey = 'path' | 'total' | 'clicksContext' | 'clicks' | 'clicksTotal' | 'currentPage' | 'currentPath' | 'currentRoute' | 'currentSlideId' | 'currentLayout' | 'nextRoute' | 'rawTree' | 'treeWithActiveStatuses' | 'tree' | 'downloadPDF' | 'next' | 'nextSlide' | 'openInEditor' | 'prev' | 'prevSlide' | 'rawRoutes' | 'go'
|
|
13
|
-
|
|
14
|
-
export interface SlidevContextNav extends Pick<typeof nav, SlidevContextNavKey> {
|
|
15
|
-
route: ComputedRef<RouteRecordRaw | RouteLocationNormalizedLoaded>
|
|
16
|
-
}
|
|
9
|
+
import type { SlidevContextNav } from '../composables/useNav'
|
|
17
10
|
|
|
18
11
|
export interface SlidevContext {
|
|
19
12
|
nav: SlidevContextNav
|
|
@@ -21,12 +14,13 @@ export interface SlidevContext {
|
|
|
21
14
|
themeConfigs: ComputedRef<typeof configs['themeConfig']>
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
export
|
|
17
|
+
export function createSlidevContext() {
|
|
25
18
|
return {
|
|
26
19
|
install(app: App) {
|
|
27
|
-
const context = reactive(useContext(
|
|
20
|
+
const context = reactive(useContext())
|
|
21
|
+
app.provide(injectionRenderContext, ref('none'))
|
|
28
22
|
app.provide(injectionSlidevContext, context)
|
|
29
|
-
app.provide(injectionCurrentPage, computed(() => context.nav.
|
|
23
|
+
app.provide(injectionCurrentPage, computed(() => context.nav.currentSlideNo))
|
|
30
24
|
|
|
31
25
|
// allows controls from postMessages
|
|
32
26
|
if (__DEV__) {
|