@slidev/client 0.49.0-beta.3 → 0.49.0-beta.5
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/builtin/CodeBlockWrapper.vue +2 -2
- package/builtin/KaTexBlockWrapper.vue +2 -2
- package/builtin/ShikiMagicMove.vue +2 -1
- package/builtin/VClickGap.vue +13 -15
- package/builtin/VClicks.ts +3 -3
- package/builtin/VSwitch.ts +114 -0
- package/composables/useClicks.ts +29 -10
- package/composables/useNav.ts +14 -6
- package/constants.ts +4 -1
- package/env.ts +2 -0
- package/internals/CodeRunner.vue +1 -3
- package/internals/Controls.vue +10 -2
- package/internals/DrawingControls.vue +1 -1
- package/internals/DrawingLayer.vue +1 -1
- package/internals/DrawingPreview.vue +1 -1
- package/internals/NavControls.vue +1 -5
- package/internals/NoteDisplay.vue +1 -1
- package/internals/QuickOverview.vue +8 -16
- package/internals/Settings.vue +1 -1
- package/internals/SlideContainer.vue +28 -46
- package/internals/SlideWrapper.vue +20 -28
- package/internals/SlidesShow.vue +5 -4
- package/logic/transition.ts +1 -1
- package/modules/v-click.ts +1 -3
- package/package.json +16 -17
- package/pages/entry.vue +18 -24
- package/pages/notes.vue +8 -11
- package/pages/overview.vue +4 -11
- package/pages/play.vue +9 -21
- package/pages/presenter.vue +11 -27
- package/setup/code-runners.ts +14 -25
- package/setup/root.ts +4 -6
- package/styles/index.css +8 -0
- package/uno.config.ts +4 -0
|
@@ -17,7 +17,7 @@ import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
|
17
17
|
import type { PropType } from 'vue'
|
|
18
18
|
import { configs } from '../env'
|
|
19
19
|
import { makeId, updateCodeHighlightRange } from '../logic/utils'
|
|
20
|
-
import { CLASS_VCLICK_HIDDEN } from '../constants'
|
|
20
|
+
import { CLASS_VCLICK_HIDDEN, CLICKS_MAX } from '../constants'
|
|
21
21
|
import { useSlideContext } from '../context'
|
|
22
22
|
|
|
23
23
|
const props = defineProps({
|
|
@@ -66,7 +66,7 @@ onMounted(() => {
|
|
|
66
66
|
const clicksInfo = clicks.calculateSince(props.at, props.ranges.length - 1)
|
|
67
67
|
clicks.register(id, clicksInfo)
|
|
68
68
|
|
|
69
|
-
const index = computed(() => Math.max(0, clicks.current - clicksInfo.start + 1))
|
|
69
|
+
const index = computed(() => clicksInfo ? Math.max(0, clicks.current - clicksInfo.start + 1) : CLICKS_MAX)
|
|
70
70
|
|
|
71
71
|
const finallyRange = computed(() => {
|
|
72
72
|
return props.finally === 'last' ? props.ranges.at(-1) : props.finally.toString()
|
|
@@ -23,7 +23,7 @@ Learn more: https://sli.dev/guide/syntax.html#latex-line-highlighting
|
|
|
23
23
|
import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
24
24
|
import type { PropType } from 'vue'
|
|
25
25
|
import { parseRangeString } from '@slidev/parser'
|
|
26
|
-
import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET } from '../constants'
|
|
26
|
+
import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET, CLICKS_MAX } from '../constants'
|
|
27
27
|
import { makeId } from '../logic/utils'
|
|
28
28
|
import { useSlideContext } from '../context'
|
|
29
29
|
|
|
@@ -61,7 +61,7 @@ onMounted(() => {
|
|
|
61
61
|
const clicksInfo = clicks.calculateSince(props.at, props.ranges.length - 1)
|
|
62
62
|
clicks.register(id, clicksInfo)
|
|
63
63
|
|
|
64
|
-
const index = computed(() => Math.max(0, clicks.current - clicksInfo.start + 1))
|
|
64
|
+
const index = computed(() => clicksInfo ? Math.max(0, clicks.current - clicksInfo.start + 1) : CLICKS_MAX)
|
|
65
65
|
|
|
66
66
|
const finallyRange = computed(() => {
|
|
67
67
|
return props.finally === 'last' ? props.ranges.at(-1) : props.finally.toString()
|
|
@@ -6,6 +6,7 @@ import lz from 'lz-string'
|
|
|
6
6
|
import { useSlideContext } from '../context'
|
|
7
7
|
import { makeId, updateCodeHighlightRange } from '../logic/utils'
|
|
8
8
|
import { useNav } from '../composables/useNav'
|
|
9
|
+
import { CLICKS_MAX } from '../constants'
|
|
9
10
|
|
|
10
11
|
const props = defineProps<{
|
|
11
12
|
at?: string | number
|
|
@@ -43,7 +44,7 @@ onMounted(() => {
|
|
|
43
44
|
() => clicks.current,
|
|
44
45
|
() => {
|
|
45
46
|
// Calculate the step and rangeStr based on the current click count
|
|
46
|
-
const clickCount = clicks.current - clickInfo.start
|
|
47
|
+
const clickCount = clickInfo ? clicks.current - clickInfo.start : CLICKS_MAX
|
|
47
48
|
let step = steps.length - 1
|
|
48
49
|
let currentClickSum = 0
|
|
49
50
|
let rangeStr = 'all'
|
package/builtin/VClickGap.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { Fragment, onMounted,
|
|
2
|
+
import { Fragment, onMounted, onUnmounted } from 'vue'
|
|
3
3
|
import { makeId } from '../logic/utils'
|
|
4
4
|
import { useSlideContext } from '../context'
|
|
5
5
|
|
|
@@ -11,23 +11,21 @@ const props = defineProps({
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
const { $clicksContext: clicks } = useSlideContext()
|
|
14
|
+
const id = makeId()
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
let delta = +props.size
|
|
17
|
+
if (Number.isNaN(delta)) {
|
|
18
|
+
console.warn(`[slidev] Invalid size for VClickGap: ${props.size}`)
|
|
19
|
+
delta = 1
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
const max = clicks.currentOffset + delta - 1
|
|
22
|
+
onMounted(() => {
|
|
23
|
+
const max = clicks.currentOffset + delta - 1
|
|
24
|
+
clicks.register(id, { max, delta })
|
|
25
|
+
})
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
onCleanup(() => clicks.unregister(id))
|
|
30
|
-
})
|
|
27
|
+
onUnmounted(() => {
|
|
28
|
+
clicks.unregister(id)
|
|
31
29
|
})
|
|
32
30
|
</script>
|
|
33
31
|
|
package/builtin/VClicks.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { toArray } from '@antfu/utils'
|
|
8
8
|
import type { VNode, VNodeArrayChildren } from 'vue'
|
|
9
9
|
import { Comment, createVNode, defineComponent, h, isVNode, resolveDirective, withDirectives } from 'vue'
|
|
10
|
-
import {
|
|
10
|
+
import { normalizeSingleAtValue } from '../composables/useClicks'
|
|
11
11
|
import VClickGap from './VClickGap.vue'
|
|
12
12
|
|
|
13
13
|
const listTags = ['ul', 'ol']
|
|
@@ -37,9 +37,9 @@ export default defineComponent({
|
|
|
37
37
|
},
|
|
38
38
|
render() {
|
|
39
39
|
const every = +this.every
|
|
40
|
-
const at =
|
|
40
|
+
const at = normalizeSingleAtValue(this.at)
|
|
41
41
|
const isRelative = typeof at === 'string'
|
|
42
|
-
if (
|
|
42
|
+
if (!at) {
|
|
43
43
|
console.warn('[slidev] Invalid at prop for v-clicks component:', at)
|
|
44
44
|
return
|
|
45
45
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { PropType, Ref, Slot, TransitionGroupProps, VNode } from 'vue'
|
|
2
|
+
import { TransitionGroup, defineComponent, h, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
3
|
+
import { recomputeAllPoppers } from 'floating-vue'
|
|
4
|
+
import { useSlideContext } from '../context'
|
|
5
|
+
import { makeId } from '../logic/utils'
|
|
6
|
+
import { resolveTransition } from '../logic/transition'
|
|
7
|
+
import { skipTransition } from '../logic/hmr'
|
|
8
|
+
import { CLASS_VCLICK_CURRENT, CLASS_VCLICK_DISPLAY_NONE, CLASS_VCLICK_PRIOR, CLASS_VCLICK_TARGET, CLICKS_MAX } from '../constants'
|
|
9
|
+
|
|
10
|
+
export default defineComponent({
|
|
11
|
+
props: {
|
|
12
|
+
at: {
|
|
13
|
+
type: [Number, String],
|
|
14
|
+
default: '+1',
|
|
15
|
+
},
|
|
16
|
+
/**
|
|
17
|
+
* unmount or hide the content when it's not visible
|
|
18
|
+
*/
|
|
19
|
+
unmount: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
23
|
+
transition: {
|
|
24
|
+
type: [Object, String, Boolean] as PropType<TransitionGroupProps | string | false>,
|
|
25
|
+
default: false,
|
|
26
|
+
},
|
|
27
|
+
tag: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: 'div',
|
|
30
|
+
},
|
|
31
|
+
childTag: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: 'div',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
setup({ at, unmount, transition, tag, childTag }, { slots }) {
|
|
37
|
+
const slotEntries = Object.entries(slots).sort((a, b) => -a[0].split('-')[0] + +b[0].split('-')[0])
|
|
38
|
+
const contents: [start: number, end: number, slot: Slot<any> | undefined, elRef: Ref<HTMLElement | undefined>][] = []
|
|
39
|
+
|
|
40
|
+
let lastStart: number | undefined
|
|
41
|
+
for (const [range, slot] of slotEntries) {
|
|
42
|
+
const elRef = ref<HTMLElement>()
|
|
43
|
+
if (Number.isFinite(+range)) {
|
|
44
|
+
contents.push([+range, lastStart ?? +range + 1, slot, elRef])
|
|
45
|
+
lastStart = +range
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const [start, end] = range.split('-').map(Number)
|
|
49
|
+
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
50
|
+
throw new Error(`Invalid range for v-switch: ${range}`)
|
|
51
|
+
contents.push([start, end, slot, elRef])
|
|
52
|
+
lastStart = start
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const size = Math.max(...contents.map(c => c[1])) - 1
|
|
57
|
+
const id = makeId()
|
|
58
|
+
const offset = ref(0)
|
|
59
|
+
|
|
60
|
+
const { $clicksContext: clicks, $nav: nav } = useSlideContext()
|
|
61
|
+
|
|
62
|
+
onMounted(() => {
|
|
63
|
+
const clicksInfo = clicks.calculateSince(at, size)
|
|
64
|
+
if (!clicksInfo) {
|
|
65
|
+
offset.value = CLICKS_MAX
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
clicks.register(id, clicksInfo)
|
|
69
|
+
watchEffect(() => {
|
|
70
|
+
offset.value = clicksInfo.currentOffset.value + 1
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
onUnmounted(() => {
|
|
75
|
+
clicks.unregister(id)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
function onAfterLeave() {
|
|
79
|
+
// Refer to SlidesShow.vue
|
|
80
|
+
skipTransition.value = true
|
|
81
|
+
recomputeAllPoppers()
|
|
82
|
+
}
|
|
83
|
+
const transitionProps = transition && {
|
|
84
|
+
...resolveTransition(transition, nav.value.navDirection < 0),
|
|
85
|
+
tag,
|
|
86
|
+
onAfterLeave,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return () => {
|
|
90
|
+
const children: VNode[] = []
|
|
91
|
+
for (let i = contents.length - 1; i >= 0; i--) {
|
|
92
|
+
const [start, end, slot, ref] = contents[i]
|
|
93
|
+
const visible = start <= offset.value && offset.value < end
|
|
94
|
+
if (unmount && !visible)
|
|
95
|
+
continue
|
|
96
|
+
children.push(h(childTag, {
|
|
97
|
+
'key': i,
|
|
98
|
+
ref,
|
|
99
|
+
'class': [
|
|
100
|
+
CLASS_VCLICK_TARGET,
|
|
101
|
+
offset.value === start && CLASS_VCLICK_CURRENT,
|
|
102
|
+
offset.value >= end && CLASS_VCLICK_PRIOR,
|
|
103
|
+
!visible && CLASS_VCLICK_DISPLAY_NONE,
|
|
104
|
+
].filter(Boolean),
|
|
105
|
+
'data-slidev-clicks-start': start,
|
|
106
|
+
'data-slidev-clicks-end': end,
|
|
107
|
+
}, slot?.()))
|
|
108
|
+
}
|
|
109
|
+
return transitionProps
|
|
110
|
+
? h(TransitionGroup, skipTransition.value ? {} : transitionProps, () => children)
|
|
111
|
+
: h(tag, children)
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
})
|
package/composables/useClicks.ts
CHANGED
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { clamp, sum } from '@antfu/utils'
|
|
2
|
-
import type { ClicksContext,
|
|
2
|
+
import type { ClicksContext, NormalizedRangeClickValue, NormalizedSingleClickValue, RawAtValue, RawSingleAtValue, SlideRoute } from '@slidev/types'
|
|
3
3
|
import type { Ref } from 'vue'
|
|
4
4
|
import { computed, ref, shallowReactive } from 'vue'
|
|
5
5
|
import { routeForceRefresh } from '../logic/route'
|
|
6
6
|
|
|
7
|
-
export function
|
|
7
|
+
export function normalizeSingleAtValue(at: RawSingleAtValue): NormalizedSingleClickValue {
|
|
8
8
|
if (at === false || at === 'false')
|
|
9
9
|
return null
|
|
10
10
|
if (at == null || at === true || at === 'true')
|
|
11
11
|
return '+1'
|
|
12
|
-
if (Array.isArray(at))
|
|
13
|
-
return [+at[0], +at[1]]
|
|
14
12
|
if (typeof at === 'string' && '+-'.includes(at[0]))
|
|
15
13
|
return at
|
|
16
|
-
|
|
14
|
+
const v = +at
|
|
15
|
+
if (Number.isNaN(v)) {
|
|
16
|
+
console.error(`Invalid "at" prop value: ${at}`)
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
return v
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeRangeAtValue(at: RawAtValue): NormalizedRangeClickValue {
|
|
23
|
+
if (Array.isArray(at))
|
|
24
|
+
return [normalizeSingleAtValue(at[0])!, normalizeSingleAtValue(at[1])!]
|
|
25
|
+
return null
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
export function createClicksContextBase(
|
|
@@ -33,7 +42,10 @@ export function createClicksContextBase(
|
|
|
33
42
|
relativeOffsets: new Map(),
|
|
34
43
|
maxMap: shallowReactive(new Map()),
|
|
35
44
|
onMounted() { },
|
|
36
|
-
calculateSince(
|
|
45
|
+
calculateSince(rawAt, size = 1) {
|
|
46
|
+
const at = normalizeSingleAtValue(rawAt)
|
|
47
|
+
if (at == null)
|
|
48
|
+
return null
|
|
37
49
|
let start: number, max: number, delta: number
|
|
38
50
|
if (typeof at === 'string') {
|
|
39
51
|
const offset = context.currentOffset
|
|
@@ -52,11 +64,16 @@ export function createClicksContextBase(
|
|
|
52
64
|
end: +Number.POSITIVE_INFINITY,
|
|
53
65
|
max,
|
|
54
66
|
delta,
|
|
67
|
+
currentOffset: computed(() => context.current - start),
|
|
55
68
|
isCurrent: computed(() => context.current === start),
|
|
56
69
|
isActive: computed(() => context.current >= start),
|
|
57
70
|
}
|
|
58
71
|
},
|
|
59
|
-
calculateRange(
|
|
72
|
+
calculateRange(rawAt) {
|
|
73
|
+
const at = normalizeRangeAtValue(rawAt)
|
|
74
|
+
if (at == null)
|
|
75
|
+
return null
|
|
76
|
+
const [a, b] = at
|
|
60
77
|
let start: number, end: number, delta: number
|
|
61
78
|
if (typeof a === 'string') {
|
|
62
79
|
const offset = context.currentOffset
|
|
@@ -79,18 +96,20 @@ export function createClicksContextBase(
|
|
|
79
96
|
end,
|
|
80
97
|
max: end,
|
|
81
98
|
delta,
|
|
99
|
+
currentOffset: computed(() => context.current - start),
|
|
82
100
|
isCurrent: computed(() => context.current === start),
|
|
83
101
|
isActive: computed(() => start <= context.current && context.current < end),
|
|
84
102
|
}
|
|
85
103
|
},
|
|
86
104
|
calculate(at) {
|
|
87
|
-
if (at == null)
|
|
88
|
-
return null
|
|
89
105
|
if (Array.isArray(at))
|
|
90
106
|
return context.calculateRange(at)
|
|
91
107
|
return context.calculateSince(at)
|
|
92
108
|
},
|
|
93
|
-
register(el,
|
|
109
|
+
register(el, info) {
|
|
110
|
+
if (!info)
|
|
111
|
+
return
|
|
112
|
+
const { delta, max } = info
|
|
94
113
|
context.relativeOffsets.set(el, delta)
|
|
95
114
|
context.maxMap.set(el, max)
|
|
96
115
|
},
|
package/composables/useNav.ts
CHANGED
|
@@ -55,7 +55,7 @@ export interface SlidevContextNav {
|
|
|
55
55
|
/** Go to previous slide */
|
|
56
56
|
prevSlide: (lastClicks?: boolean) => Promise<void>
|
|
57
57
|
/** Go to slide */
|
|
58
|
-
go: (page: number | string, clicks?: number) => Promise<void>
|
|
58
|
+
go: (page: number | string, clicks?: number, force?: boolean) => Promise<void>
|
|
59
59
|
/** Go to the first slide */
|
|
60
60
|
goFirst: () => Promise<void>
|
|
61
61
|
/** Go to the last slide */
|
|
@@ -181,14 +181,14 @@ export function useNavBase(
|
|
|
181
181
|
return go(total.value)
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
async function go(page: number | string, clicks: number = 0) {
|
|
184
|
+
async function go(page: number | string, clicks: number = 0, force = false) {
|
|
185
185
|
skipTransition.value = false
|
|
186
186
|
const pageChanged = currentSlideNo.value !== page
|
|
187
187
|
const clicksChanged = clicks !== queryClicks.value
|
|
188
188
|
const meta = getSlide(page)?.meta
|
|
189
189
|
const clicksStart = meta?.slide?.frontmatter.clicksStart ?? 0
|
|
190
190
|
clicks = clamp(clicks, clicksStart, meta?.__clicksContext?.total ?? CLICKS_MAX)
|
|
191
|
-
if (pageChanged || clicksChanged) {
|
|
191
|
+
if (force || pageChanged || clicksChanged) {
|
|
192
192
|
await router?.push({
|
|
193
193
|
path: getSlidePath(page, isPresenter.value),
|
|
194
194
|
query: {
|
|
@@ -301,6 +301,7 @@ const useNavState = createSharedComposable((): SlidevContextNavState => {
|
|
|
301
301
|
return v
|
|
302
302
|
},
|
|
303
303
|
set(v) {
|
|
304
|
+
skipTransition.value = false
|
|
304
305
|
queryClicksRaw.value = v.toString()
|
|
305
306
|
},
|
|
306
307
|
})
|
|
@@ -379,9 +380,16 @@ export const useNav = createSharedComposable((): SlidevContextNavFull => {
|
|
|
379
380
|
watch(
|
|
380
381
|
[nav.total, state.currentRoute],
|
|
381
382
|
async () => {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
const no = state.currentRoute.value.params.no as string
|
|
384
|
+
if (state.hasPrimarySlide.value && !getSlide(no)) {
|
|
385
|
+
if (no && no !== 'index.html') {
|
|
386
|
+
// The current slide may has been removed. Redirect to the last slide.
|
|
387
|
+
await nav.go(nav.total.value, 0, true)
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
// Redirect to the first slide
|
|
391
|
+
await nav.go(1, 0, true)
|
|
392
|
+
}
|
|
385
393
|
}
|
|
386
394
|
},
|
|
387
395
|
{ flush: 'pre', immediate: true },
|
package/constants.ts
CHANGED
|
@@ -11,7 +11,6 @@ export const injectionSlideScale = '$$slidev-slide-scale' as unknown as Injectio
|
|
|
11
11
|
export const injectionSlidevContext = '$$slidev-context' as unknown as InjectionKey<UnwrapNestedRefs<SlidevContext>>
|
|
12
12
|
export const injectionRoute = '$$slidev-route' as unknown as InjectionKey<SlideRoute>
|
|
13
13
|
export const injectionRenderContext = '$$slidev-render-context' as unknown as InjectionKey<Ref<RenderContext>>
|
|
14
|
-
export const injectionActive = '$$slidev-active' as unknown as InjectionKey<Ref<boolean>>
|
|
15
14
|
export const injectionFrontmatter = '$$slidev-fontmatter' as unknown as InjectionKey<Record<string, any>>
|
|
16
15
|
export const injectionSlideZoom = '$$slidev-slide-zoom' as unknown as InjectionKey<ComputedRef<number>>
|
|
17
16
|
|
|
@@ -22,6 +21,7 @@ export const CLASS_VCLICK_GONE = 'slidev-vclick-gone'
|
|
|
22
21
|
export const CLASS_VCLICK_HIDDEN_EXP = 'slidev-vclick-hidden-explicitly'
|
|
23
22
|
export const CLASS_VCLICK_CURRENT = 'slidev-vclick-current'
|
|
24
23
|
export const CLASS_VCLICK_PRIOR = 'slidev-vclick-prior'
|
|
24
|
+
export const CLASS_VCLICK_DISPLAY_NONE = 'slidev-vclick-display-none'
|
|
25
25
|
|
|
26
26
|
export const CLICKS_MAX = 999999
|
|
27
27
|
|
|
@@ -61,6 +61,9 @@ export const HEADMATTER_FIELDS = [
|
|
|
61
61
|
'highlighter',
|
|
62
62
|
'lineNumbers',
|
|
63
63
|
'monaco',
|
|
64
|
+
'monacoTypesSource',
|
|
65
|
+
'monacoTypesAdditionalPackages',
|
|
66
|
+
'monacoRunAdditionalDeps',
|
|
64
67
|
'remoteAssets',
|
|
65
68
|
'selectable',
|
|
66
69
|
'record',
|
package/env.ts
CHANGED
|
@@ -16,3 +16,5 @@ export const slideHeight = computed(() => Math.ceil(slideWidth.value / slideAspe
|
|
|
16
16
|
export const themeVars = computed(() => {
|
|
17
17
|
return objectMap(configs.themeConfig || {}, (k, v) => [`--slidev-theme-${k}`, v])
|
|
18
18
|
})
|
|
19
|
+
|
|
20
|
+
export const slidesTitle = configs.titleTemplate.replace('%s', configs.title || 'Slidev')
|
package/internals/CodeRunner.vue
CHANGED
|
@@ -7,7 +7,6 @@ import { useSlideContext } from '../context'
|
|
|
7
7
|
import setupCodeRunners from '../setup/code-runners'
|
|
8
8
|
import { useNav } from '../composables/useNav'
|
|
9
9
|
import { makeId } from '../logic/utils'
|
|
10
|
-
import { normalizeAtValue } from '../composables/useClicks'
|
|
11
10
|
import IconButton from './IconButton.vue'
|
|
12
11
|
import DomElement from './DomElement.vue'
|
|
13
12
|
|
|
@@ -40,8 +39,7 @@ const hidden = ref(props.showOutputAt)
|
|
|
40
39
|
if (props.showOutputAt) {
|
|
41
40
|
const id = makeId()
|
|
42
41
|
onMounted(() => {
|
|
43
|
-
const
|
|
44
|
-
const info = $clicksContext.calculate(at)
|
|
42
|
+
const info = $clicksContext.calculate(props.showOutputAt)
|
|
45
43
|
if (info) {
|
|
46
44
|
$clicksContext.register(id, info)
|
|
47
45
|
watchSyncEffect(() => {
|
package/internals/Controls.vue
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { shallowRef } from 'vue'
|
|
3
|
-
import { showInfoDialog,
|
|
3
|
+
import { showInfoDialog, showRecordingDialog } from '../state'
|
|
4
4
|
import { configs } from '../env'
|
|
5
|
+
import { useNav } from '../composables/useNav'
|
|
5
6
|
import QuickOverview from './QuickOverview.vue'
|
|
6
7
|
import InfoDialog from './InfoDialog.vue'
|
|
7
8
|
import Goto from './Goto.vue'
|
|
8
9
|
import ContextMenu from './ContextMenu.vue'
|
|
9
10
|
|
|
11
|
+
const { isEmbedded } = useNav()
|
|
12
|
+
const drawingEnabled = __SLIDEV_FEATURE_DRAWINGS__ && !configs.drawings.presenterOnly && !isEmbedded.value
|
|
13
|
+
const DrawingControls = shallowRef<any>()
|
|
14
|
+
if (drawingEnabled)
|
|
15
|
+
import('../internals/DrawingControls.vue').then(v => DrawingControls.value = v.default)
|
|
16
|
+
|
|
10
17
|
const WebCamera = shallowRef<any>()
|
|
11
18
|
const RecordingDialog = shallowRef<any>()
|
|
12
19
|
if (__SLIDEV_FEATURE_RECORD__) {
|
|
@@ -16,7 +23,8 @@ if (__SLIDEV_FEATURE_RECORD__) {
|
|
|
16
23
|
</script>
|
|
17
24
|
|
|
18
25
|
<template>
|
|
19
|
-
<
|
|
26
|
+
<DrawingControls v-if="drawingEnabled && DrawingControls" />
|
|
27
|
+
<QuickOverview />
|
|
20
28
|
<Goto />
|
|
21
29
|
<WebCamera v-if="WebCamera" />
|
|
22
30
|
<RecordingDialog v-if="RecordingDialog" v-model="showRecordingDialog" />
|
|
@@ -53,10 +53,6 @@ const barStyle = computed(() => props.persist
|
|
|
53
53
|
const RecordingControls = shallowRef<any>()
|
|
54
54
|
if (__SLIDEV_FEATURE_RECORD__)
|
|
55
55
|
import('./RecordingControls.vue').then(v => RecordingControls.value = v.default)
|
|
56
|
-
|
|
57
|
-
const DrawingControls = shallowRef<any>()
|
|
58
|
-
if (__SLIDEV_FEATURE_DRAWINGS__)
|
|
59
|
-
import('./DrawingControls.vue').then(v => DrawingControls.value = v.default)
|
|
60
56
|
</script>
|
|
61
57
|
|
|
62
58
|
<template>
|
|
@@ -179,4 +175,4 @@ if (__SLIDEV_FEATURE_DRAWINGS__)
|
|
|
179
175
|
<CustomNavControls />
|
|
180
176
|
</div>
|
|
181
177
|
</nav>
|
|
182
|
-
</template
|
|
178
|
+
</template>
|
|
@@ -17,7 +17,7 @@ const emit = defineEmits<{
|
|
|
17
17
|
(type: 'markerClick', e: MouseEvent, clicks: number): void
|
|
18
18
|
}>()
|
|
19
19
|
|
|
20
|
-
const withClicks = computed(() => props.clicksContext
|
|
20
|
+
const withClicks = computed(() => props.clicksContext != null && props.noteHtml?.includes('slidev-note-click-mark'))
|
|
21
21
|
const noteDisplay = ref<HTMLElement | null>(null)
|
|
22
22
|
|
|
23
23
|
const CLASS_FADE = 'slidev-note-fade'
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useEventListener
|
|
2
|
+
import { useEventListener } from '@vueuse/core'
|
|
3
3
|
import { computed, ref, watchEffect } from 'vue'
|
|
4
4
|
import { breakpoints, showOverview, windowSize } from '../state'
|
|
5
5
|
import { currentOverviewPage, overviewRowCount } from '../logic/overview'
|
|
6
6
|
import { createFixedClicks } from '../composables/useClicks'
|
|
7
|
-
import { getSlideClass } from '../utils'
|
|
8
7
|
import { CLICKS_MAX } from '../constants'
|
|
9
8
|
import { useNav } from '../composables/useNav'
|
|
10
9
|
import SlideContainer from './SlideContainer.vue'
|
|
@@ -12,14 +11,10 @@ import SlideWrapper from './SlideWrapper.vue'
|
|
|
12
11
|
import DrawingPreview from './DrawingPreview.vue'
|
|
13
12
|
import IconButton from './IconButton.vue'
|
|
14
13
|
|
|
15
|
-
const props = defineProps<{ modelValue: boolean }>()
|
|
16
|
-
const emit = defineEmits(['update:modelValue'])
|
|
17
|
-
const value = useVModel(props, 'modelValue', emit)
|
|
18
|
-
|
|
19
14
|
const { currentSlideNo, go: goSlide, slides } = useNav()
|
|
20
15
|
|
|
21
16
|
function close() {
|
|
22
|
-
|
|
17
|
+
showOverview.value = false
|
|
23
18
|
}
|
|
24
19
|
|
|
25
20
|
function go(page: number) {
|
|
@@ -117,10 +112,10 @@ setTimeout(() => {
|
|
|
117
112
|
leave-to-class="opacity-0 scale-102 !backdrop-blur-0px"
|
|
118
113
|
>
|
|
119
114
|
<div
|
|
120
|
-
v-if="
|
|
121
|
-
v-show="
|
|
122
|
-
class="bg-main !bg-opacity-75 p-16 py-20 overflow-y-auto backdrop-blur-5px
|
|
123
|
-
@click="close
|
|
115
|
+
v-if="showOverview || activeSlidesLoaded"
|
|
116
|
+
v-show="showOverview"
|
|
117
|
+
class="fixed left-0 right-0 top-0 h-[calc(var(--vh,1vh)*100)] z-20 bg-main !bg-opacity-75 p-16 py-20 overflow-y-auto backdrop-blur-5px"
|
|
118
|
+
@click="close"
|
|
124
119
|
>
|
|
125
120
|
<div
|
|
126
121
|
class="grid gap-y-4 gap-x-8 w-full"
|
|
@@ -142,10 +137,7 @@ setTimeout(() => {
|
|
|
142
137
|
class="pointer-events-none"
|
|
143
138
|
>
|
|
144
139
|
<SlideWrapper
|
|
145
|
-
:is="route.component"
|
|
146
|
-
v-if="route?.component"
|
|
147
140
|
:clicks-context="createFixedClicks(route, CLICKS_MAX)"
|
|
148
|
-
:class="getSlideClass(route)"
|
|
149
141
|
:route="route"
|
|
150
142
|
render-context="overview"
|
|
151
143
|
/>
|
|
@@ -168,12 +160,12 @@ setTimeout(() => {
|
|
|
168
160
|
</div>
|
|
169
161
|
</div>
|
|
170
162
|
</Transition>
|
|
171
|
-
<div v-if="
|
|
163
|
+
<div v-if="showOverview" class="fixed top-4 right-4 z-20 text-gray-400 flex flex-col items-center gap-2">
|
|
172
164
|
<IconButton title="Close" class="text-2xl" @click="close">
|
|
173
165
|
<carbon:close />
|
|
174
166
|
</IconButton>
|
|
175
167
|
<IconButton
|
|
176
|
-
v-if="
|
|
168
|
+
v-if="__SLIDEV_FEATURE_PRESENTER__"
|
|
177
169
|
as="a"
|
|
178
170
|
title="Slides Overview"
|
|
179
171
|
target="_blank"
|
package/internals/Settings.vue
CHANGED