@slidev/client 0.49.0-beta.4 → 0.49.0-beta.6

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.
@@ -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'
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { Fragment, onMounted, watchEffect } from 'vue'
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
- onMounted(() => {
16
- watchEffect((onCleanup) => {
17
- if (!clicks)
18
- return
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
- let delta = +props.size
21
- if (Number.isNaN(delta)) {
22
- console.warn(`[slidev] Invalid size for VClickGap: ${props.size}`)
23
- delta = 1
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
- const id = makeId()
28
- clicks.register(id, { max, delta })
29
- onCleanup(() => clicks.unregister(id))
30
- })
27
+ onUnmounted(() => {
28
+ clicks.unregister(id)
31
29
  })
32
30
  </script>
33
31
 
@@ -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 { normalizeAtValue } from '../composables/useClicks'
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 = normalizeAtValue(this.at)
40
+ const at = normalizeSingleAtValue(this.at)
41
41
  const isRelative = typeof at === 'string'
42
- if (typeof at !== 'string' && typeof at !== 'number') {
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
+ })
@@ -1,19 +1,28 @@
1
1
  import { clamp, sum } from '@antfu/utils'
2
- import type { ClicksContext, NormalizedAtValue, RawAtValue, SlideRoute } from '@slidev/types'
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 normalizeAtValue(at: RawAtValue): NormalizedAtValue {
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
- return +at
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(at, size = 1) {
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([a, b]) {
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, { delta, max }) {
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
  },
@@ -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
- if (state.hasPrimarySlide.value && !getSlide(state.currentRoute.value.params.no as string)) {
383
- // The current slide may has been removed. Redirect to the last slide.
384
- await nav.goLast()
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
 
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')
@@ -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 at = normalizeAtValue(props.showOutputAt)
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(() => {
@@ -1,12 +1,19 @@
1
1
  <script setup lang="ts">
2
2
  import { shallowRef } from 'vue'
3
- import { showInfoDialog, showOverview, showRecordingDialog } from '../state'
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
- <QuickOverview v-model="showOverview" />
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" />
@@ -136,4 +136,4 @@ function setBrushColor(color: typeof brush.color) {
136
136
  .v-popper--theme-menu .v-popper__arrow-inner {
137
137
  --uno: border-main;
138
138
  }
139
- </style>../composables/drawings
139
+ </style>
@@ -25,4 +25,4 @@ onBeforeUnmount(() => {
25
25
  class="w-full h-full absolute top-0"
26
26
  :class="{ 'pointer-events-none': !drawingEnabled, 'touch-none': drawingEnabled }"
27
27
  />
28
- </template>../composables/drawings
28
+ </template>
@@ -12,4 +12,4 @@ const { drawingState } = useDrawings()
12
12
  class="w-full h-full absolute top-0 pointer-events-none"
13
13
  v-html="drawingState[page]"
14
14
  />
15
- </template>../composables/drawings
15
+ </template>
@@ -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>../composables/drawings
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?.current != null && props.noteHtml?.includes('slidev-note-click-mark'))
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, useVModel } from '@vueuse/core'
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
- value.value = false
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="value || activeSlidesLoaded"
121
- v-show="value"
122
- class="bg-main !bg-opacity-75 p-16 py-20 overflow-y-auto backdrop-blur-5px fixed left-0 right-0 top-0 h-[calc(var(--vh,1vh)*100)]"
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="value" class="fixed top-4 right-4 text-gray-400 flex flex-col items-center gap-2">
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="__DEV__"
168
+ v-if="__SLIDEV_FEATURE_PRESENTER__"
177
169
  as="a"
178
170
  title="Slides Overview"
179
171
  target="_blank"
@@ -16,7 +16,7 @@ const items: SelectionItem<number>[] = [
16
16
  </script>
17
17
 
18
18
  <template>
19
- <div class="text-sm">
19
+ <div class="text-sm select-none">
20
20
  <SelectList v-model="slideScale" title="Scale" :items="items" />
21
21
  </div>
22
22
  </template>