@slidev/client 0.49.29 → 0.50.0-beta.1

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 (86) hide show
  1. package/builtin/Arrow.vue +1 -1
  2. package/builtin/CodeBlockWrapper.vue +3 -3
  3. package/builtin/KaTexBlockWrapper.vue +2 -2
  4. package/builtin/Mermaid.vue +1 -1
  5. package/builtin/Monaco.vue +5 -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 +2 -2
  11. package/builtin/VAfter.ts +1 -1
  12. package/builtin/VClick.ts +1 -1
  13. package/builtin/VClickGap.vue +1 -1
  14. package/builtin/VClicks.ts +1 -1
  15. package/builtin/VDrag.vue +1 -1
  16. package/builtin/VDragArrow.vue +1 -1
  17. package/builtin/VSwitch.ts +4 -4
  18. package/composables/useClicks.ts +1 -1
  19. package/composables/useDragElements.ts +2 -2
  20. package/composables/useDrawings.ts +3 -3
  21. package/composables/useNav.ts +8 -8
  22. package/composables/useSlideInfo.ts +2 -2
  23. package/composables/useSwipeControls.ts +1 -1
  24. package/composables/useViewTransition.ts +1 -1
  25. package/constants.ts +2 -1
  26. package/context.ts +2 -2
  27. package/env.ts +2 -2
  28. package/index.ts +23 -5
  29. package/internals/CodeRunner.vue +4 -4
  30. package/internals/ContextMenu.vue +2 -2
  31. package/internals/Controls.vue +6 -6
  32. package/internals/DevicesList.vue +2 -2
  33. package/internals/DragControl.vue +2 -2
  34. package/internals/Draggable.vue +1 -1
  35. package/internals/DrawingControls.vue +140 -139
  36. package/internals/DrawingLayer.vue +1 -1
  37. package/internals/Goto.vue +3 -3
  38. package/internals/NavControls.vue +8 -8
  39. package/internals/NoteDisplay.vue +1 -1
  40. package/internals/NoteEditable.vue +2 -2
  41. package/internals/PrintContainer.vue +3 -3
  42. package/internals/PrintSlide.vue +1 -1
  43. package/internals/PrintSlideClick.vue +3 -3
  44. package/internals/QuickOverview.vue +9 -7
  45. package/internals/RecordingControls.vue +1 -1
  46. package/internals/RecordingDialog.vue +1 -1
  47. package/internals/SelectList.vue +1 -1
  48. package/internals/Settings.vue +1 -1
  49. package/internals/ShikiEditor.vue +1 -1
  50. package/internals/SideEditor.vue +1 -1
  51. package/internals/SlideContainer.vue +32 -3
  52. package/internals/SlideWrapper.vue +4 -4
  53. package/internals/SlidesShow.vue +6 -6
  54. package/internals/WebCamera.vue +1 -1
  55. package/logic/contextMenu.ts +3 -3
  56. package/logic/recording.ts +4 -4
  57. package/logic/shortcuts.ts +3 -3
  58. package/logic/slides.ts +2 -2
  59. package/logic/snapshot.ts +86 -0
  60. package/modules/context.ts +1 -1
  61. package/modules/mermaid.ts +3 -3
  62. package/modules/v-click.ts +1 -1
  63. package/modules/v-drag.ts +1 -1
  64. package/modules/v-mark.ts +2 -2
  65. package/modules/v-motion.ts +3 -3
  66. package/package.json +23 -22
  67. package/pages/notes.vue +7 -7
  68. package/pages/overview.vue +24 -11
  69. package/pages/play.vue +10 -10
  70. package/pages/presenter/print.vue +2 -2
  71. package/pages/presenter.vue +18 -18
  72. package/pages/print.vue +3 -3
  73. package/setup/code-runners.ts +4 -4
  74. package/setup/context-menu.ts +11 -11
  75. package/setup/main.ts +4 -4
  76. package/setup/mermaid.ts +1 -1
  77. package/setup/monaco.ts +13 -9
  78. package/setup/root.ts +9 -9
  79. package/setup/shortcuts.ts +5 -5
  80. package/state/drawings.ts +1 -0
  81. package/state/index.ts +1 -1
  82. package/state/shared.ts +2 -1
  83. package/state/snapshot.ts +13 -0
  84. package/state/syncState.ts +76 -24
  85. package/styles/index.css +1 -0
  86. package/uno.config.ts +2 -2
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()
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
+ )
@@ -1,4 +1,72 @@
1
- import { reactive, toRaw, watch } from 'vue'
1
+ import { reactive, ref, toRaw, watch } from 'vue'
2
+
3
+ export type SyncWrite<State extends object> = (state: State, updating?: boolean) => void
4
+
5
+ export interface Sync {
6
+ enabled?: boolean
7
+ init: <State extends object>(channelKey: string, onUpdate: (data: Partial<State>) => void, state: State, persist?: boolean) => SyncWrite<State> | undefined
8
+ }
9
+
10
+ interface BuiltinSync extends Sync {
11
+ channels: BroadcastChannel[]
12
+ disable: () => void
13
+ listener?: (event: StorageEvent) => void
14
+ }
15
+
16
+ const builtinSync: BuiltinSync = {
17
+ channels: [],
18
+ enabled: true,
19
+ init<State extends object>(channelKey: string, onUpdate: (data: Partial<State>) => void, state: State, persist = false) {
20
+ let stateChannel: BroadcastChannel
21
+ if (!__SLIDEV_HAS_SERVER__ && !persist) {
22
+ stateChannel = new BroadcastChannel(channelKey)
23
+ stateChannel.addEventListener('message', (event: MessageEvent<Partial<State>>) => onUpdate(event.data))
24
+ this.channels.push(stateChannel)
25
+ }
26
+ else if (!__SLIDEV_HAS_SERVER__ && persist) {
27
+ this.listener = function (event: StorageEvent) {
28
+ if (event && event.key === channelKey && event.newValue)
29
+ onUpdate(JSON.parse(event.newValue) as Partial<State>)
30
+ }
31
+ window.addEventListener('storage', this.listener)
32
+ const serializedState = window.localStorage.getItem(channelKey)
33
+ if (serializedState)
34
+ onUpdate(JSON.parse(serializedState) as Partial<State>)
35
+ }
36
+ return (state: State, updating = false) => {
37
+ if (this.enabled) {
38
+ if (!persist && stateChannel && !updating)
39
+ stateChannel.postMessage(toRaw(state))
40
+ if (persist && !updating)
41
+ window.localStorage.setItem(channelKey, JSON.stringify(state))
42
+ }
43
+ }
44
+ },
45
+ disable() {
46
+ this.enabled = false
47
+ this.channels.forEach(channel => channel.close())
48
+ if (this.listener) {
49
+ window.removeEventListener('storage', this.listener)
50
+ }
51
+ },
52
+ }
53
+ const syncInterfaces: Sync[] = reactive([builtinSync])
54
+ const channels: Map<string, { onUpdate: (data: Partial<object>) => void, persist?: boolean, state: object }> = new Map()
55
+ const syncWrites = ref<Record<string, SyncWrite<object>[]>>({})
56
+
57
+ export function disableBuiltinSync() {
58
+ builtinSync.disable()
59
+ }
60
+
61
+ export function addSyncMethod(sync: Sync) {
62
+ syncInterfaces.push(sync)
63
+ for (const [channelKey, { onUpdate, persist, state }] of channels.entries()) {
64
+ const write = sync.init(channelKey, onUpdate, state, persist)
65
+ if (write) {
66
+ syncWrites.value[channelKey].push(write)
67
+ }
68
+ }
69
+ }
2
70
 
3
71
  export function createSyncState<State extends object>(serverState: State, defaultState: State, persist = false) {
4
72
  const onPatchCallbacks: ((state: State) => void)[] = []
@@ -36,35 +104,19 @@ export function createSyncState<State extends object>(serverState: State, defaul
36
104
  }
37
105
 
38
106
  function init(channelKey: string) {
39
- let stateChannel: BroadcastChannel
40
- if (!__SLIDEV_HAS_SERVER__ && !persist) {
41
- stateChannel = new BroadcastChannel(channelKey)
42
- stateChannel.addEventListener('message', (event: MessageEvent<Partial<State>>) => onUpdate(event.data))
43
- }
44
- else if (!__SLIDEV_HAS_SERVER__ && persist) {
45
- window.addEventListener('storage', (event) => {
46
- if (event && event.key === channelKey && event.newValue)
47
- onUpdate(JSON.parse(event.newValue) as Partial<State>)
48
- })
49
- }
107
+ channels.set(channelKey, { onUpdate, persist, state })
108
+ syncWrites.value[channelKey] = syncInterfaces
109
+ .map(sync => sync.init<State>(channelKey, onUpdate, state, persist))
110
+ .filter((x): x is SyncWrite<object> => Boolean(x))
50
111
 
51
112
  function onStateChanged() {
52
- if (!persist && stateChannel && !updating)
53
- stateChannel.postMessage(toRaw(state))
54
- else if (persist && !updating)
55
- window.localStorage.setItem(channelKey, JSON.stringify(state))
113
+ syncWrites.value[channelKey].forEach(write => write?.(toRaw(state), updating))
56
114
  if (!patching)
57
115
  onPatchCallbacks.forEach((fn: (state: State) => void) => fn(state))
58
116
  }
59
117
 
60
- watch(state, onStateChanged, { deep: true, flush: 'sync' })
61
-
62
- if (!__SLIDEV_HAS_SERVER__ && persist) {
63
- const serialzedState = window.localStorage.getItem(channelKey)
64
- if (serialzedState)
65
- onUpdate(JSON.parse(serialzedState) as Partial<State>)
66
- }
118
+ watch(state, onStateChanged, { deep: true })
67
119
  }
68
120
 
69
- return { init, onPatch, patch, state }
121
+ return { init, onPatch, onUpdate, patch, state }
70
122
  }
package/styles/index.css CHANGED
@@ -23,6 +23,7 @@ html {
23
23
  cursor: pointer;
24
24
  @apply opacity-75 transition duration-200 ease-in-out align-middle rounded p-1;
25
25
  @apply hover:(opacity-100 bg-gray-400 bg-opacity-10);
26
+ @apply focus-visible:(opacity-100 outline outline-2 outline-offset-2 outline-black dark:outline-white);
26
27
  @apply md:p-2;
27
28
  }
28
29
 
package/uno.config.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import extractorMdc from '@unocss/extractor-mdc'
2
+ import { variantMatcher } from '@unocss/preset-mini/utils'
1
3
  import {
2
4
  defineConfig,
3
5
  presetAttributify,
@@ -6,8 +8,6 @@ import {
6
8
  transformerDirectives,
7
9
  transformerVariantGroup,
8
10
  } from 'unocss'
9
- import { variantMatcher } from '@unocss/preset-mini/utils'
10
- import extractorMdc from '@unocss/extractor-mdc'
11
11
 
12
12
  export default defineConfig({
13
13
  safelist: [