@slidev/client 0.49.29 → 0.50.0-beta.10

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.
Files changed (93) hide show
  1. package/builtin/Arrow.vue +1 -1
  2. package/builtin/CodeBlockWrapper.vue +3 -3
  3. package/builtin/KaTexBlockWrapper.vue +3 -3
  4. package/builtin/Mermaid.vue +1 -1
  5. package/builtin/Monaco.vue +6 -5
  6. package/builtin/RenderWhen.vue +2 -2
  7. package/builtin/ShikiMagicMove.vue +5 -5
  8. package/builtin/SlidevVideo.vue +2 -2
  9. package/builtin/Toc.vue +1 -1
  10. package/builtin/TocList.vue +6 -3
  11. package/builtin/Tweet.vue +1 -1
  12. package/builtin/VAfter.ts +1 -1
  13. package/builtin/VClick.ts +1 -1
  14. package/builtin/VClickGap.vue +1 -1
  15. package/builtin/VClicks.ts +1 -1
  16. package/builtin/VDrag.vue +1 -1
  17. package/builtin/VDragArrow.vue +1 -1
  18. package/builtin/VSwitch.ts +4 -4
  19. package/composables/useClicks.ts +1 -1
  20. package/composables/useDragElements.ts +3 -3
  21. package/composables/useDrawings.ts +3 -3
  22. package/composables/useNav.ts +8 -8
  23. package/composables/useSlideInfo.ts +2 -2
  24. package/composables/useSwipeControls.ts +1 -1
  25. package/composables/useTimer.ts +20 -0
  26. package/composables/useViewTransition.ts +2 -3
  27. package/constants.ts +3 -1
  28. package/context.ts +2 -2
  29. package/env.ts +2 -2
  30. package/index.ts +23 -5
  31. package/internals/ClicksSlider.vue +1 -1
  32. package/internals/CodeRunner.vue +5 -5
  33. package/internals/ContextMenu.vue +8 -6
  34. package/internals/Controls.vue +6 -6
  35. package/internals/DevicesList.vue +2 -2
  36. package/internals/DragControl.vue +2 -2
  37. package/internals/Draggable.vue +1 -1
  38. package/internals/DrawingControls.vue +140 -139
  39. package/internals/DrawingLayer.vue +1 -1
  40. package/internals/Goto.vue +3 -3
  41. package/internals/NavControls.vue +21 -21
  42. package/internals/NoteDisplay.vue +1 -1
  43. package/internals/NoteEditable.vue +2 -2
  44. package/internals/PrintContainer.vue +4 -4
  45. package/internals/PrintSlide.vue +1 -1
  46. package/internals/PrintSlideClick.vue +3 -3
  47. package/internals/QuickOverview.vue +11 -9
  48. package/internals/RecordingControls.vue +5 -5
  49. package/internals/RecordingDialog.vue +2 -2
  50. package/internals/SelectList.vue +6 -4
  51. package/internals/Settings.vue +1 -1
  52. package/internals/ShikiEditor.vue +1 -1
  53. package/internals/SideEditor.vue +7 -7
  54. package/internals/SlideContainer.vue +31 -3
  55. package/internals/SlideWrapper.vue +5 -4
  56. package/internals/SlidesShow.vue +6 -6
  57. package/internals/WebCamera.vue +1 -1
  58. package/layouts/error.vue +5 -1
  59. package/logic/contextMenu.ts +3 -3
  60. package/logic/recording.ts +4 -4
  61. package/logic/shortcuts.ts +3 -3
  62. package/logic/slides.ts +2 -2
  63. package/logic/snapshot.ts +86 -0
  64. package/logic/utils.ts +0 -23
  65. package/main.ts +7 -3
  66. package/modules/context.ts +1 -1
  67. package/modules/mermaid.ts +3 -3
  68. package/modules/v-click.ts +1 -1
  69. package/modules/v-drag.ts +1 -1
  70. package/modules/v-mark.ts +2 -2
  71. package/modules/v-motion.ts +3 -3
  72. package/package.json +26 -25
  73. package/pages/entry.vue +4 -4
  74. package/pages/notes.vue +11 -11
  75. package/pages/overview.vue +27 -14
  76. package/pages/play.vue +14 -12
  77. package/pages/presenter/print.vue +2 -2
  78. package/pages/presenter.vue +38 -39
  79. package/pages/print.vue +3 -3
  80. package/setup/code-runners.ts +4 -4
  81. package/setup/context-menu.ts +15 -24
  82. package/setup/main.ts +4 -4
  83. package/setup/mermaid.ts +1 -1
  84. package/setup/monaco.ts +18 -18
  85. package/setup/root.ts +9 -9
  86. package/setup/shortcuts.ts +6 -7
  87. package/state/drawings.ts +1 -0
  88. package/state/index.ts +1 -1
  89. package/state/shared.ts +2 -1
  90. package/state/snapshot.ts +13 -0
  91. package/state/syncState.ts +76 -24
  92. package/styles/index.css +5 -0
  93. package/uno.config.ts +5 -2
@@ -1,19 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { computed, nextTick, onMounted, reactive, ref, shallowRef } from 'vue'
3
- import { useHead } from '@unhead/vue'
4
2
  import type { ClicksContext, SlideRoute } from '@slidev/types'
5
- import { pathPrefix, slidesTitle } from '../env'
6
- import { getSlidePath } from '../logic/slides'
3
+ import { useHead } from '@unhead/vue'
4
+ import { computed, nextTick, onMounted, reactive, ref, shallowRef } from 'vue'
7
5
  import { createFixedClicks } from '../composables/useClicks'
8
- import { isColorSchemaConfigured, isDark, toggleDark } from '../logic/dark'
9
- import SlideContainer from '../internals/SlideContainer.vue'
10
- import SlideWrapper from '../internals/SlideWrapper.vue'
6
+ import { useNav } from '../composables/useNav'
7
+ import { CLICKS_MAX } from '../constants'
8
+ import { pathPrefix, slidesTitle } from '../env'
9
+ import ClicksSlider from '../internals/ClicksSlider.vue'
11
10
  import DrawingPreview from '../internals/DrawingPreview.vue'
12
11
  import IconButton from '../internals/IconButton.vue'
13
12
  import NoteEditable from '../internals/NoteEditable.vue'
14
- import ClicksSlider from '../internals/ClicksSlider.vue'
15
- import { CLICKS_MAX } from '../constants'
16
- import { useNav } from '../composables/useNav'
13
+ import SlideContainer from '../internals/SlideContainer.vue'
14
+ import SlideWrapper from '../internals/SlideWrapper.vue'
15
+ import { isColorSchemaConfigured, isDark, toggleDark } from '../logic/dark'
16
+ import { getSlidePath } from '../logic/slides'
17
17
 
18
18
  const cardWidth = 450
19
19
 
@@ -49,7 +49,20 @@ function toggleRoute(route: SlideRoute) {
49
49
  }
50
50
 
51
51
  function wordCount(str: string) {
52
- return str.match(/[\w`'\-]+/g)?.length || 0
52
+ const pattern = /[\w`'\-\u0392-\u03C9\u00C0-\u00FF\u0600-\u06FF\u0400-\u04FF]+|[\u4E00-\u9FFF\u3400-\u4DBF\uF900-\uFAFF\u3040-\u309F\uAC00-\uD7AF]+/g
53
+ const m = str.match(pattern)
54
+ let count = 0
55
+ if (!m)
56
+ return 0
57
+ for (let i = 0; i < m.length; i++) {
58
+ if (m[i].charCodeAt(0) >= 0x4E00) {
59
+ count += m[i].length
60
+ }
61
+ else {
62
+ count += 1
63
+ }
64
+ }
65
+ return count
53
66
  }
54
67
 
55
68
  function isElementInViewport(el: HTMLElement) {
@@ -170,7 +183,7 @@ onMounted(() => {
170
183
  title="Play in new tab"
171
184
  @click="openSlideInNewTab(getSlidePath(route, false))"
172
185
  >
173
- <carbon:presentation-file />
186
+ <div class="i-carbon:presentation-file" />
174
187
  </IconButton>
175
188
  <IconButton
176
189
  v-if="__DEV__ && route.meta?.slide"
@@ -178,7 +191,7 @@ onMounted(() => {
178
191
  title="Open in editor"
179
192
  @click="openInEditor(`${route.meta.slide.filepath}:${route.meta.slide.start}`)"
180
193
  >
181
- <carbon:cics-program />
194
+ <div class="i-carbon:cics-program" />
182
195
  </IconButton>
183
196
  </div>
184
197
  <div class="flex flex-col gap-2 my5" :style="{ width: `${cardWidth}px` }">
@@ -215,7 +228,7 @@ onMounted(() => {
215
228
  :class="edittingNote === route.no ? 'important:op0' : ''"
216
229
  @click="edittingNote = route.no"
217
230
  >
218
- <carbon:pen />
231
+ <div class="i-carbon:pen" />
219
232
  </IconButton>
220
233
  </div>
221
234
  <NoteEditable
package/pages/play.vue CHANGED
@@ -1,19 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, shallowRef } from 'vue'
3
2
  import { useStyleTag } from '@vueuse/core'
4
- import { editorHeight, editorWidth, isEditorVertical, isScreenVertical, showEditor, windowSize } from '../state'
3
+ import { computed, ref, shallowRef } from 'vue'
4
+ import { useDrawings } from '../composables/useDrawings'
5
+ import { useNav } from '../composables/useNav'
5
6
  import { useSwipeControls } from '../composables/useSwipeControls'
6
- import { registerShortcuts } from '../logic/shortcuts'
7
+ import { useWakeLock } from '../composables/useWakeLock'
7
8
  import Controls from '../internals/Controls.vue'
8
- import SlideContainer from '../internals/SlideContainer.vue'
9
9
  import NavControls from '../internals/NavControls.vue'
10
- import SlidesShow from '../internals/SlidesShow.vue'
10
+ import PresenterMouse from '../internals/PresenterMouse.vue'
11
11
  import PrintStyle from '../internals/PrintStyle.vue'
12
+ import SlideContainer from '../internals/SlideContainer.vue'
13
+ import SlidesShow from '../internals/SlidesShow.vue'
12
14
  import { onContextMenu } from '../logic/contextMenu'
13
- import { useNav } from '../composables/useNav'
14
- import { useWakeLock } from '../composables/useWakeLock'
15
- import { useDrawings } from '../composables/useDrawings'
16
- import PresenterMouse from '../internals/PresenterMouse.vue'
15
+ import { registerShortcuts } from '../logic/shortcuts'
16
+ import { editorHeight, editorWidth, isEditorVertical, isScreenVertical, showEditor, windowSize } from '../state'
17
17
 
18
18
  const { next, prev, isPrintMode } = useNav()
19
19
  const { isDrawing } = useDrawings()
@@ -38,7 +38,8 @@ if (__SLIDEV_FEATURE_WAKE_LOCK__)
38
38
  useWakeLock()
39
39
 
40
40
  if (import.meta.hot) {
41
- useStyleTag(computed(() => `
41
+ useStyleTag(computed(() => showEditor.value
42
+ ? `
42
43
  vite-error-overlay {
43
44
  --width: calc(100vw - ${isEditorVertical.value ? 0 : editorWidth.value}px);
44
45
  --height: calc(100vh - ${isEditorVertical.value ? editorHeight.value : 0}px);
@@ -49,7 +50,8 @@ if (import.meta.hot) {
49
50
  height: calc(var(--height) / var(--slidev-slide-scale));
50
51
  transform-origin: top left;
51
52
  transform: scale(var(--slidev-slide-scale));
52
- }`,
53
+ }`
54
+ : '',
53
55
  ))
54
56
  }
55
57
 
@@ -80,7 +82,7 @@ if (__DEV__ && __SLIDEV_FEATURE_EDITOR__)
80
82
  <template #controls>
81
83
  <div
82
84
  v-if="!isPrintMode"
83
- class="absolute bottom-0 left-0 transition duration-300 opacity-0 hover:opacity-100"
85
+ class="absolute bottom-0 left-0 transition duration-300 opacity-0 hover:opacity-100 focus-within:opacity-100 focus-visible:opacity-100"
84
86
  :class="[
85
87
  persistNav ? '!opacity-100 right-0' : 'opacity-0 p-2',
86
88
  isDrawing ? 'pointer-events-none' : '',
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { useStyleTag } from '@vueuse/core'
4
2
  import { useHead } from '@unhead/vue'
3
+ import { useStyleTag } from '@vueuse/core'
4
+ import { computed } from 'vue'
5
5
  import { useNav } from '../../composables/useNav'
6
6
  import { configs } from '../../env'
7
7
  import NoteDisplay from '../../internals/NoteDisplay.vue'
@@ -1,30 +1,30 @@
1
1
  <script setup lang="ts">
2
2
  import { useHead } from '@unhead/vue'
3
- import { computed, onMounted, reactive, ref, shallowRef, watch } from 'vue'
4
3
  import { useMouse, useWindowFocus } from '@vueuse/core'
4
+ import { computed, onMounted, reactive, ref, shallowRef, watch } from 'vue'
5
+ import { createFixedClicks } from '../composables/useClicks'
6
+ import { useDrawings } from '../composables/useDrawings'
7
+ import { useNav } from '../composables/useNav'
5
8
  import { useSwipeControls } from '../composables/useSwipeControls'
6
- import { decreasePresenterFontSize, increasePresenterFontSize, presenterLayout, presenterNotesFontSize, showEditor, showPresenterCursor } from '../state'
9
+ import { useTimer } from '../composables/useTimer'
10
+ import { useWakeLock } from '../composables/useWakeLock'
7
11
  import { slidesTitle } from '../env'
8
- import { sharedState } from '../state/shared'
9
- import { registerShortcuts } from '../logic/shortcuts'
10
- import { onContextMenu } from '../logic/contextMenu'
11
- import { useTimer } from '../logic/utils'
12
- import { createFixedClicks } from '../composables/useClicks'
13
- import SlideWrapper from '../internals/SlideWrapper.vue'
14
- import SlideContainer from '../internals/SlideContainer.vue'
12
+ import ClicksSlider from '../internals/ClicksSlider.vue'
13
+ import ContextMenu from '../internals/ContextMenu.vue'
14
+ import DrawingControls from '../internals/DrawingControls.vue'
15
+ import Goto from '../internals/Goto.vue'
16
+ import IconButton from '../internals/IconButton.vue'
15
17
  import NavControls from '../internals/NavControls.vue'
16
- import QuickOverview from '../internals/QuickOverview.vue'
17
18
  import NoteEditable from '../internals/NoteEditable.vue'
18
19
  import NoteStatic from '../internals/NoteStatic.vue'
19
- import Goto from '../internals/Goto.vue'
20
+ import QuickOverview from '../internals/QuickOverview.vue'
21
+ import SlideContainer from '../internals/SlideContainer.vue'
20
22
  import SlidesShow from '../internals/SlidesShow.vue'
21
- import DrawingControls from '../internals/DrawingControls.vue'
22
- import IconButton from '../internals/IconButton.vue'
23
- import ClicksSlider from '../internals/ClicksSlider.vue'
24
- import ContextMenu from '../internals/ContextMenu.vue'
25
- import { useNav } from '../composables/useNav'
26
- import { useDrawings } from '../composables/useDrawings'
27
- import { useWakeLock } from '../composables/useWakeLock'
23
+ import SlideWrapper from '../internals/SlideWrapper.vue'
24
+ import { onContextMenu } from '../logic/contextMenu'
25
+ import { registerShortcuts } from '../logic/shortcuts'
26
+ import { decreasePresenterFontSize, increasePresenterFontSize, presenterLayout, presenterNotesFontSize, showEditor, showPresenterCursor } from '../state'
27
+ import { sharedState } from '../state/shared'
28
28
 
29
29
  const main = ref<HTMLDivElement>()
30
30
 
@@ -49,7 +49,7 @@ useHead({ title: `Presenter - ${slidesTitle}` })
49
49
 
50
50
  const notesEditing = ref(false)
51
51
 
52
- const { timer, resetTimer } = useTimer()
52
+ const { timer, isTimerAvctive, resetTimer, toggleTimer } = useTimer()
53
53
 
54
54
  const clicksCtxMap = computed(() => slides.value.map(route => createFixedClicks(route)))
55
55
  const nextFrame = computed(() => {
@@ -167,33 +167,39 @@ onMounted(() => {
167
167
  />
168
168
  <div class="border-t border-main py-1 px-2 text-sm">
169
169
  <IconButton title="Increase font size" @click="increasePresenterFontSize">
170
- <carbon:zoom-in />
170
+ <div class="i-carbon:zoom-in" />
171
171
  </IconButton>
172
172
  <IconButton title="Decrease font size" @click="decreasePresenterFontSize">
173
- <carbon:zoom-out />
173
+ <div class="i-carbon:zoom-out" />
174
174
  </IconButton>
175
175
  <IconButton
176
176
  v-if="__DEV__"
177
177
  title="Edit Notes"
178
178
  @click="notesEditing = !notesEditing"
179
179
  >
180
- <carbon:edit />
180
+ <div class="i-carbon:edit" />
181
181
  </IconButton>
182
182
  </div>
183
183
  </div>
184
184
  <div class="grid-section bottom flex">
185
185
  <NavControls :persist="true" />
186
186
  <div flex-auto />
187
- <div
188
- class="timer-btn my-auto relative w-22px h-22px cursor-pointer text-lg"
189
- opacity="50 hover:100"
190
- @click="resetTimer"
191
- >
192
- <carbon:time class="absolute" />
193
- <carbon:renew class="absolute opacity-0" />
194
- </div>
195
- <div class="text-2xl pl-2 pr-6 my-auto tabular-nums">
196
- {{ timer }}
187
+ <div class="group flex items-center justify-center pl-4 select-none">
188
+ <div class="w-22px cursor-pointer">
189
+ <div class="i-carbon:time group-hover:hidden text-xl" />
190
+ <div class="group-not-hover:hidden flex flex-col items-center">
191
+ <div class="relative op-80 hover:op-100" @click="toggleTimer">
192
+ <div v-if="isTimerAvctive" class="i-carbon:pause text-lg" />
193
+ <div v-else class="i-carbon:play" />
194
+ </div>
195
+ <div class="op-80 hover:op-100" @click="resetTimer">
196
+ <div class="i-carbon:renew" />
197
+ </div>
198
+ </div>
199
+ </div>
200
+ <div class="text-2xl px-3 my-auto tabular-nums">
201
+ {{ timer }}
202
+ </div>
197
203
  </div>
198
204
  </div>
199
205
  <DrawingControls v-if="__SLIDEV_FEATURE_DRAWINGS__" />
@@ -215,13 +221,6 @@ onMounted(() => {
215
221
  --slidev-controls-foreground: current;
216
222
  }
217
223
 
218
- .timer-btn:hover > :first-child {
219
- opacity: 0;
220
- }
221
- .timer-btn:hover > :last-child {
222
- opacity: 1;
223
- }
224
-
225
224
  .grid-container {
226
225
  --uno: bg-gray/20;
227
226
  height: 100%;
package/pages/print.vue CHANGED
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { onMounted, watchEffect } from 'vue'
3
2
  import { recomputeAllPoppers } from 'floating-vue'
4
- import { windowSize } from '../state'
3
+ import { onMounted, watchEffect } from 'vue'
4
+ import { useNav } from '../composables/useNav'
5
5
  import PrintContainer from '../internals/PrintContainer.vue'
6
6
  import PrintStyle from '../internals/PrintStyle.vue'
7
- import { useNav } from '../composables/useNav'
7
+ import { windowSize } from '../state'
8
8
 
9
9
  const { isPrintMode } = useNav()
10
10
 
@@ -1,10 +1,10 @@
1
- import { createSingletonPromise } from '@antfu/utils'
2
- import type { CodeRunner, CodeRunnerOutput, CodeRunnerOutputText, CodeRunnerOutputs } from '@slidev/types'
3
-
1
+ import type { CodeRunner, CodeRunnerOutput, CodeRunnerOutputs, CodeRunnerOutputText } from '@slidev/types'
4
2
  import type ts from 'typescript'
5
- import { ref } from 'vue'
3
+
6
4
  import deps from '#slidev/monaco-run-deps'
7
5
  import setups from '#slidev/setups/code-runners'
6
+ import { createSingletonPromise } from '@antfu/utils'
7
+ import { ref } from 'vue'
8
8
 
9
9
  export default createSingletonPromise(async () => {
10
10
  const runners: Record<string, CodeRunner> = {
@@ -1,23 +1,14 @@
1
1
  /// <reference types="unplugin-icons/types/vue3" />
2
+
3
+ import type { ContextMenuItem } from '@slidev/types'
2
4
  import type { ComputedRef } from 'vue'
5
+ import setups from '#slidev/setups/context-menu'
3
6
  import { computed } from 'vue'
4
- import type { ContextMenuItem } from '@slidev/types'
5
- import { useNav } from '../composables/useNav'
6
7
  import { useDrawings } from '../composables/useDrawings'
8
+ import { useNav } from '../composables/useNav'
7
9
  import { fullscreen, showEditor, toggleOverview } from '../state'
8
- import setups from '#slidev/setups/context-menu'
9
10
 
10
- import IconArrowLeft from '~icons/carbon/arrow-left'
11
- import IconArrowRight from '~icons/carbon/arrow-right'
12
- import IconArrowUp from '~icons/carbon/arrow-up'
13
- import IconArrowDown from '~icons/carbon/arrow-down'
14
- import IconPen from '~icons/carbon/pen'
15
- import IconTextNotationToggle from '~icons/carbon/text-annotation-toggle'
16
- import IconApps from '~icons/carbon/apps'
17
- import IconPresentationFile from '~icons/carbon/presentation-file'
18
- import IconUserSpeaker from '~icons/carbon/user-speaker'
19
- import IconMaximize from '~icons/carbon/maximize'
20
- import IconMinimize from '~icons/carbon/minimize'
11
+ // @unocss-include
21
12
 
22
13
  let items: ComputedRef<ContextMenuItem[]> | undefined
23
14
 
@@ -51,60 +42,60 @@ export default () => {
51
42
  computed(() => [
52
43
  {
53
44
  small: true,
54
- icon: IconArrowLeft,
45
+ icon: 'i-carbon:arrow-left',
55
46
  label: 'Previous Click',
56
47
  action: prev,
57
48
  disabled: !hasPrev.value,
58
49
  },
59
50
  {
60
51
  small: true,
61
- icon: IconArrowRight,
52
+ icon: 'i-carbon:arrow-right',
62
53
  label: 'Next Click',
63
54
  action: next,
64
55
  disabled: !hasNext.value,
65
56
  },
66
57
  {
67
58
  small: true,
68
- icon: IconArrowUp,
59
+ icon: 'i-carbon:arrow-up',
69
60
  label: 'Previous Slide',
70
61
  action: prevSlide,
71
62
  disabled: currentPage.value <= 1,
72
63
  },
73
64
  {
74
65
  small: true,
75
- icon: IconArrowDown,
66
+ icon: 'i-carbon:arrow-down',
76
67
  label: 'Next Slide',
77
68
  action: nextSlide,
78
69
  disabled: currentPage.value >= total.value,
79
70
  },
80
71
  'separator',
81
72
  {
82
- icon: IconTextNotationToggle,
73
+ icon: 'i-carbon:text-annotation-toggle', // IconTextNotationToggle,
83
74
  label: showEditor.value ? 'Hide editor' : 'Show editor',
84
75
  action: () => (showEditor.value = !showEditor.value),
85
76
  },
86
77
  {
87
- icon: IconPen,
78
+ icon: 'i-carbon:pen',
88
79
  label: drawingEnabled.value ? 'Hide drawing toolbar' : 'Show drawing toolbar',
89
80
  action: () => (drawingEnabled.value = !drawingEnabled.value),
90
81
  },
91
82
  {
92
- icon: IconApps,
83
+ icon: 'i-carbon:apps',
93
84
  label: 'Show slide overview',
94
85
  action: toggleOverview,
95
86
  },
96
87
  isPresenter.value && {
97
- icon: IconPresentationFile,
88
+ icon: 'i-carbon:presentation-file',
98
89
  label: 'Exit Presenter Mode',
99
90
  action: exitPresenter,
100
91
  },
101
92
  __SLIDEV_FEATURE_PRESENTER__ && isPresenterAvailable.value && {
102
- icon: IconUserSpeaker,
93
+ icon: 'i-carbon:user-speaker',
103
94
  label: 'Enter Presenter Mode',
104
95
  action: enterPresenter,
105
96
  },
106
97
  !isEmbedded.value && {
107
- icon: isFullscreen.value ? IconMinimize : IconMaximize,
98
+ icon: isFullscreen.value ? 'i-carbon:minimize' : 'i-carbon:maximize',
108
99
  label: isFullscreen.value ? 'Close fullscreen' : 'Enter fullscreen',
109
100
  action: toggleFullscreen,
110
101
  },
package/setup/main.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import type { AppContext } from '@slidev/types'
2
- import TwoSlashFloatingVue from '@shikijs/vitepress-twoslash/client'
3
2
  import type { App } from 'vue'
4
- import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
3
+ import setups from '#slidev/setups/main'
4
+ import TwoSlashFloatingVue from '@shikijs/vitepress-twoslash/client'
5
5
  import { createHead } from '@unhead/vue'
6
+ import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
6
7
  import { createVClickDirectives } from '../modules/v-click'
7
- import { createVMarkDirective } from '../modules/v-mark'
8
8
  import { createVDragDirective } from '../modules/v-drag'
9
+ import { createVMarkDirective } from '../modules/v-mark'
9
10
  import { createVMotionDirectives } from '../modules/v-motion'
10
11
  import setupRoutes from '../setup/routes'
11
- import setups from '#slidev/setups/main'
12
12
 
13
13
  import '#slidev/styles'
14
14
 
package/setup/mermaid.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { MermaidConfig } from 'mermaid'
2
- import { createSingletonPromise } from '@antfu/utils'
3
2
  import setups from '#slidev/setups/mermaid'
3
+ import { createSingletonPromise } from '@antfu/utils'
4
4
 
5
5
  export default createSingletonPromise(async () => {
6
6
  const setupReturn: MermaidConfig = {
package/setup/monaco.ts CHANGED
@@ -1,28 +1,25 @@
1
- import { createSingletonPromise } from '@antfu/utils'
2
1
  import type { MonacoSetupReturn } from '@slidev/types'
3
- import * as monaco from 'monaco-editor'
4
- import { watchEffect } from 'vue'
2
+ import configs from '#slidev/configs'
3
+ import setups from '#slidev/setups/monaco'
4
+ import { createSingletonPromise } from '@antfu/utils'
5
5
  import { setupTypeAcquisition } from '@typescript/ata'
6
- import ts from 'typescript'
6
+ import * as monaco from 'monaco-editor'
7
7
 
8
8
  import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
9
+ // @ts-expect-error missing types
10
+ import { StandaloneServices } from 'monaco-editor/esm/vs/editor/standalone/browser/standaloneServices'
9
11
  import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
10
12
  import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
11
13
  import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
12
14
  import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
13
-
14
15
  // @ts-expect-error missing types
15
16
  import { ContextViewService } from 'monaco-editor/esm/vs/platform/contextview/browser/contextViewService'
16
-
17
17
  // @ts-expect-error missing types
18
18
  import { SyncDescriptor } from 'monaco-editor/esm/vs/platform/instantiation/common/descriptors'
19
19
 
20
- // @ts-expect-error missing types
21
- import { StandaloneServices } from 'monaco-editor/esm/vs/editor/standalone/browser/standaloneServices'
22
-
20
+ import ts from 'typescript'
21
+ import { watchEffect } from 'vue'
23
22
  import { isDark } from '../logic/dark'
24
- import configs from '#slidev/configs'
25
- import setups from '#slidev/setups/monaco'
26
23
 
27
24
  window.MonacoEnvironment = {
28
25
  getWorker(_, label) {
@@ -51,14 +48,13 @@ class ContextViewService2 extends ContextViewService {
51
48
  }
52
49
  }
53
50
 
54
- const setup = createSingletonPromise(async () => {
55
- // Initialize services first, otherwise we can't override them.
56
- StandaloneServices.initialize({
57
- contextViewService: new SyncDescriptor(ContextViewService2, [], true),
58
- })
51
+ // Initialize services first, otherwise we can't override them.
52
+ StandaloneServices.initialize({
53
+ contextViewService: new SyncDescriptor(ContextViewService2, [], true),
54
+ })
59
55
 
56
+ const setup = createSingletonPromise(async () => {
60
57
  const defaults = monaco.languages.typescript.typescriptDefaults
61
-
62
58
  defaults.setCompilerOptions({
63
59
  ...defaults.getCompilerOptions(),
64
60
  strict: true,
@@ -92,7 +88,7 @@ const setup = createSingletonPromise(async () => {
92
88
  monaco.languages.register({ id: 'typescript' })
93
89
  monaco.languages.register({ id: 'javascript' })
94
90
 
95
- const { shiki, themes, shikiToMonaco } = await import('#slidev/shiki')
91
+ const { shiki, languages, themes, shikiToMonaco } = await import('#slidev/shiki')
96
92
  const highlighter = await shiki
97
93
 
98
94
  const editorOptions: MonacoSetupReturn['editorOptions'] & object = {}
@@ -113,6 +109,10 @@ const setup = createSingletonPromise(async () => {
113
109
  : themes.light || 'vitesse-light')
114
110
  })
115
111
  }
112
+ // Register all languages, otherwise Monaco will not highlight them
113
+ for (const lang of languages) {
114
+ monaco.languages.register({ id: lang })
115
+ }
116
116
 
117
117
  return {
118
118
  monaco,
package/setup/root.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { computed, getCurrentInstance, reactive, ref, shallowRef, watch } from 'vue'
1
+ import setups from '#slidev/setups/root'
2
2
  import { useHead } from '@unhead/vue'
3
+ import { computed, getCurrentInstance, reactive, ref, shallowRef, watch } from 'vue'
3
4
  import { useRouter } from 'vue-router'
5
+ import { createFixedClicks } from '../composables/useClicks'
6
+ import { useEmbeddedControl } from '../composables/useEmbeddedCtrl'
7
+ import { useNav } from '../composables/useNav'
8
+ import { injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionSlidevContext, TRUST_ORIGINS } from '../constants'
4
9
  import { configs, slidesTitle } from '../env'
5
- import { initSharedState, onPatch, patch } from '../state/shared'
6
- import { initDrawingState } from '../state/drawings'
7
- import { TRUST_ORIGINS, injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionSlidevContext } from '../constants'
8
10
  import { skipTransition } from '../logic/hmr'
9
- import { makeId } from '../logic/utils'
10
11
  import { getSlidePath } from '../logic/slides'
11
- import { createFixedClicks } from '../composables/useClicks'
12
- import { useNav } from '../composables/useNav'
13
- import { useEmbeddedControl } from '../composables/useEmbeddedCtrl'
14
- import setups from '#slidev/setups/root'
12
+ import { makeId } from '../logic/utils'
13
+ import { initDrawingState } from '../state/drawings'
14
+ import { initSharedState, onPatch, patch } from '../state/shared'
15
15
 
16
16
  export default function setupRoot() {
17
17
  const app = getCurrentInstance()!.appContext.app
@@ -1,12 +1,12 @@
1
- import { and, not, or } from '@vueuse/math'
2
1
  import type { NavOperations, ShortcutOptions } from '@slidev/types'
3
- import { downloadPDF } from '../utils'
2
+ import setups from '#slidev/setups/shortcuts'
3
+ import { and, not, or } from '@vueuse/math'
4
+ import { useDrawings } from '../composables/useDrawings'
5
+ import { useNav } from '../composables/useNav'
4
6
  import { toggleDark } from '../logic/dark'
5
7
  import { activeDragElement, magicKeys, showGotoDialog, showOverview, toggleOverview } from '../state'
6
- import { useNav } from '../composables/useNav'
7
- import { useDrawings } from '../composables/useDrawings'
8
+ import { downloadPDF } from '../utils'
8
9
  import { currentOverviewPage, downOverviewPage, nextOverviewPage, prevOverviewPage, upOverviewPage } from './../logic/overview'
9
- import setups from '#slidev/setups/shortcuts'
10
10
 
11
11
  export default function setupShortcuts() {
12
12
  const { go, goFirst, goLast, next, nextSlide, prev, prevSlide } = useNav()
@@ -63,8 +63,7 @@ export default function setupShortcuts() {
63
63
  const baseShortcutNames = new Set(shortcuts.map(s => s.name))
64
64
 
65
65
  for (const setup of setups) {
66
- const result = setup(context, shortcuts)
67
- shortcuts = shortcuts.concat(result)
66
+ shortcuts = setup(context, shortcuts)
68
67
  }
69
68
 
70
69
  const remainingBaseShortcutNames = shortcuts.filter(s => s.name && baseShortcutNames.has(s.name))
package/state/drawings.ts CHANGED
@@ -6,6 +6,7 @@ export type DrawingsState = Record<number, string | undefined>
6
6
  export const {
7
7
  init: initDrawingState,
8
8
  onPatch: onPatchDrawingState,
9
+ onUpdate: onDrawingUpdate,
9
10
  patch: patchDrawingState,
10
11
  state: drawingState,
11
12
  } = createSyncState<DrawingsState>(serverDrawingState, serverDrawingState, __SLIDEV_FEATURE_DRAWINGS_PERSIST__)
package/state/index.ts CHANGED
@@ -1,7 +1,7 @@
1
+ import type { DragElementState } from '../composables/useDragElements'
1
2
  import { breakpointsTailwind, isClient, useActiveElement, useBreakpoints, useFullscreen, useLocalStorage, useMagicKeys, useToggle, useWindowSize } from '@vueuse/core'
2
3
  import { computed, ref, shallowRef } from 'vue'
3
4
  import { slideAspect } from '../env'
4
- import type { DragElementState } from '../composables/useDragElements'
5
5
 
6
6
  export const showRecordingDialog = ref(false)
7
7
  export const showInfoDialog = ref(false)
package/state/shared.ts CHANGED
@@ -22,7 +22,7 @@ export interface SharedState {
22
22
  }
23
23
  }
24
24
 
25
- const { init, onPatch, patch, state } = createSyncState<SharedState>(serverState, {
25
+ const { init, onPatch, onUpdate, patch, state } = createSyncState<SharedState>(serverState, {
26
26
  page: 1,
27
27
  clicks: 0,
28
28
  clicksTotal: 0,
@@ -34,6 +34,7 @@ const { init, onPatch, patch, state } = createSyncState<SharedState>(serverState
34
34
  export {
35
35
  init as initSharedState,
36
36
  onPatch,
37
+ onUpdate as onSharedUpdate,
37
38
  patch,
38
39
  state as sharedState,
39
40
  }
@@ -0,0 +1,13 @@
1
+ import serverSnapshotState from 'server-reactive:snapshots?diff'
2
+ import { createSyncState } from './syncState'
3
+
4
+ export type SnapshotState = Record<number, {
5
+ revision: string
6
+ image: string
7
+ }>
8
+
9
+ export const snapshotState = createSyncState<SnapshotState>(
10
+ serverSnapshotState,
11
+ serverSnapshotState,
12
+ true,
13
+ )