@slidev/client 0.48.0-beta.2 → 0.48.0-beta.20

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 (78) hide show
  1. package/App.vue +7 -0
  2. package/builtin/Arrow.vue +2 -4
  3. package/builtin/CodeBlockWrapper.vue +14 -6
  4. package/builtin/KaTexBlockWrapper.vue +5 -4
  5. package/builtin/Mermaid.vue +4 -3
  6. package/builtin/Monaco.vue +109 -92
  7. package/builtin/RenderWhen.vue +3 -3
  8. package/builtin/ShikiMagicMove.vue +50 -0
  9. package/builtin/SlideCurrentNo.vue +2 -3
  10. package/builtin/SlidesTotal.vue +3 -4
  11. package/builtin/SlidevVideo.vue +8 -6
  12. package/builtin/Toc.vue +3 -3
  13. package/builtin/TocList.vue +3 -2
  14. package/builtin/Tweet.vue +3 -22
  15. package/builtin/VClick.ts +2 -1
  16. package/builtin/VClickGap.vue +3 -5
  17. package/builtin/VClicks.ts +1 -1
  18. package/composables/useClicks.ts +34 -16
  19. package/constants.ts +58 -8
  20. package/context.ts +73 -0
  21. package/env.ts +3 -12
  22. package/internals/ClicksSlider.vue +93 -0
  23. package/internals/Controls.vue +2 -2
  24. package/internals/DrawingControls.vue +39 -9
  25. package/internals/DrawingLayer.vue +3 -3
  26. package/internals/Goto.vue +5 -4
  27. package/internals/IconButton.vue +7 -3
  28. package/internals/InfoDialog.vue +1 -1
  29. package/internals/Modal.vue +1 -1
  30. package/internals/NavControls.vue +4 -5
  31. package/internals/NoteDisplay.vue +131 -8
  32. package/internals/NoteEditable.vue +128 -0
  33. package/internals/NoteStatic.vue +8 -6
  34. package/internals/PrintContainer.vue +4 -3
  35. package/internals/PrintSlide.vue +8 -2
  36. package/internals/PrintSlideClick.vue +5 -7
  37. package/internals/{SlidesOverview.vue → QuickOverview.vue} +21 -10
  38. package/internals/RecordingControls.vue +1 -1
  39. package/internals/RecordingDialog.vue +5 -6
  40. package/internals/{Editor.vue → SideEditor.vue} +7 -3
  41. package/internals/SlideContainer.vue +12 -9
  42. package/internals/SlideWrapper.ts +28 -12
  43. package/internals/SlidesShow.vue +7 -8
  44. package/layouts/two-cols-header.vue +9 -3
  45. package/logic/drawings.ts +6 -3
  46. package/logic/nav.ts +11 -8
  47. package/logic/note.ts +7 -7
  48. package/main.ts +8 -4
  49. package/modules/context.ts +4 -3
  50. package/modules/mermaid.ts +6 -7
  51. package/modules/{directives.ts → v-click.ts} +15 -15
  52. package/modules/v-mark.ts +159 -0
  53. package/package.json +26 -16
  54. package/{internals/EntrySelect.vue → pages/entry.vue} +7 -0
  55. package/{internals/NotesView.vue → pages/notes.vue} +5 -3
  56. package/pages/overview.vue +229 -0
  57. package/{internals/Play.vue → pages/play.vue} +15 -12
  58. package/{internals/PresenterPrint.vue → pages/presenter/print.vue} +12 -7
  59. package/{internals/Presenter.vue → pages/presenter.vue} +108 -100
  60. package/{internals/Print.vue → pages/print.vue} +3 -4
  61. package/routes.ts +27 -51
  62. package/setup/codemirror.ts +8 -3
  63. package/setup/monaco.ts +108 -44
  64. package/setup/root.ts +2 -2
  65. package/shim-vue.d.ts +35 -0
  66. package/shim.d.ts +1 -13
  67. package/state/index.ts +10 -10
  68. package/styles/code.css +7 -3
  69. package/styles/index.css +68 -7
  70. package/styles/katex.css +1 -1
  71. package/styles/layouts-base.css +17 -12
  72. package/styles/monaco.css +27 -0
  73. package/styles/vars.css +1 -0
  74. package/uno.config.ts +14 -2
  75. package/iframes/monaco/index.css +0 -28
  76. package/iframes/monaco/index.html +0 -7
  77. package/iframes/monaco/index.ts +0 -260
  78. package/internals/NoteEditor.vue +0 -88
package/App.vue CHANGED
@@ -1,7 +1,14 @@
1
1
  <script setup lang="ts">
2
+ import { watchEffect } from 'vue'
3
+ import { themeVars } from './env'
2
4
  import setupRoot from './setup/root'
3
5
 
4
6
  setupRoot()
7
+
8
+ watchEffect(() => {
9
+ for (const [key, value] of Object.entries(themeVars.value))
10
+ document.body.style.setProperty(key, value.toString())
11
+ })
5
12
  </script>
6
13
 
7
14
  <template>
package/builtin/Arrow.vue CHANGED
@@ -9,7 +9,7 @@ Simple Arrow
9
9
  -->
10
10
 
11
11
  <script setup lang="ts">
12
- import { customAlphabet } from 'nanoid'
12
+ import { makeId } from '../logic/utils'
13
13
 
14
14
  defineProps<{
15
15
  x1: number | string
@@ -20,9 +20,7 @@ defineProps<{
20
20
  color?: string
21
21
  }>()
22
22
 
23
- const nanoid = customAlphabet('abcedfghijklmn', 10)
24
-
25
- const id = nanoid()
23
+ const id = makeId()
26
24
  </script>
27
25
 
28
26
  <template>
@@ -14,11 +14,12 @@ Learn more: https://sli.dev/guide/syntax.html#line-highlighting
14
14
  <script setup lang="ts">
15
15
  import { parseRangeString } from '@slidev/parser/core'
16
16
  import { useClipboard } from '@vueuse/core'
17
- import { computed, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue'
17
+ import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
18
18
  import type { PropType } from 'vue'
19
19
  import { configs } from '../env'
20
20
  import { makeId } from '../logic/utils'
21
- import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET, injectionClicksContext } from '../constants'
21
+ import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET } from '../constants'
22
+ import { useSlideContext } from '../context'
22
23
 
23
24
  const props = defineProps({
24
25
  ranges: {
@@ -47,7 +48,7 @@ const props = defineProps({
47
48
  },
48
49
  })
49
50
 
50
- const clicks = inject(injectionClicksContext)?.value
51
+ const { $clicksContext: clicks } = useSlideContext()
51
52
  const el = ref<HTMLDivElement>()
52
53
  const id = makeId()
53
54
 
@@ -55,8 +56,12 @@ onUnmounted(() => {
55
56
  clicks!.unregister(id)
56
57
  })
57
58
 
59
+ watchEffect(() => {
60
+ el.value?.classList.toggle('slidev-code-line-numbers', props.lines)
61
+ })
62
+
58
63
  onMounted(() => {
59
- if (!clicks || clicks.disabled)
64
+ if (!clicks || clicks.disabled || !props.ranges?.length)
60
65
  return
61
66
 
62
67
  const { start, end, delta } = clicks.resolve(props.at, props.ranges.length - 1)
@@ -120,9 +125,12 @@ function copyCode() {
120
125
 
121
126
  <template>
122
127
  <div
123
- ref="el" class="slidev-code-wrapper relative group" :class="{
128
+ ref="el"
129
+ class="slidev-code-wrapper relative group"
130
+ :class="{
124
131
  'slidev-code-line-numbers': props.lines,
125
- }" :style="{
132
+ }"
133
+ :style="{
126
134
  'max-height': props.maxHeight,
127
135
  'overflow-y': props.maxHeight ? 'scroll' : undefined,
128
136
  '--start': props.startLine,
@@ -20,11 +20,12 @@ Learn more: https://sli.dev/guide/syntax.html#latex-line-highlighting
20
20
  -->
21
21
 
22
22
  <script setup lang="ts">
23
- import { computed, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue'
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, injectionClicksContext } from '../constants'
26
+ import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET } from '../constants'
27
27
  import { makeId } from '../logic/utils'
28
+ import { useSlideContext } from '../context'
28
29
 
29
30
  const props = defineProps({
30
31
  ranges: {
@@ -45,7 +46,7 @@ const props = defineProps({
45
46
  },
46
47
  })
47
48
 
48
- const clicks = inject(injectionClicksContext)?.value
49
+ const { $clicksContext: clicks } = useSlideContext()
49
50
  const el = ref<HTMLDivElement>()
50
51
  const id = makeId()
51
52
 
@@ -54,7 +55,7 @@ onUnmounted(() => {
54
55
  })
55
56
 
56
57
  onMounted(() => {
57
- if (!clicks || clicks.disabled)
58
+ if (!clicks || clicks.disabled || !props.ranges?.length)
58
59
  return
59
60
 
60
61
  const { start, end, delta } = clicks.resolve(props.at, props.ranges.length - 1)
@@ -19,7 +19,7 @@ import ShadowRoot from '../internals/ShadowRoot.vue'
19
19
  import { isDark } from '../logic/dark'
20
20
 
21
21
  const props = defineProps<{
22
- code: string
22
+ codeLz: string
23
23
  scale?: number
24
24
  theme?: string
25
25
  }>()
@@ -37,7 +37,7 @@ watchEffect(async (onCleanup) => {
37
37
  error.value = null
38
38
  try {
39
39
  const svg = await renderMermaid(
40
- props.code || '',
40
+ props.codeLz || '',
41
41
  {
42
42
  theme: props.theme || (isDark.value ? 'dark' : undefined),
43
43
  ...vm!.attrs,
@@ -48,6 +48,7 @@ watchEffect(async (onCleanup) => {
48
48
  }
49
49
  catch (e) {
50
50
  error.value = `${e}`
51
+ console.warn(e)
51
52
  }
52
53
  })
53
54
 
@@ -76,6 +77,6 @@ watchEffect(() => {
76
77
  </script>
77
78
 
78
79
  <template>
79
- <pre v-if="error" border="1 red rounded" class="pa-3">{{ error }}</pre>
80
+ <pre v-if="error" border="1 red rounded" class="pa-3 text-wrap">{{ error }}</pre>
80
81
  <ShadowRoot v-else class="mermaid" :inner-html="html" @shadow="el = $event" />
81
82
  </template>
@@ -12,122 +12,139 @@ Learn more: https://sli.dev/guide/syntax.html#monaco-editor
12
12
  -->
13
13
 
14
14
  <script setup lang="ts">
15
- import { computed, onMounted, ref } from 'vue'
16
- import { useEventListener } from '@vueuse/core'
17
- import { decode } from 'js-base64'
18
- import { nanoid } from 'nanoid'
19
15
  import type * as monaco from 'monaco-editor'
20
- import { isDark } from '../logic/dark'
16
+ import { computed, nextTick, onMounted, ref } from 'vue'
17
+ import { debounce } from '@antfu/utils'
18
+ import lz from 'lz-string'
19
+ import { makeId } from '../logic/utils'
21
20
 
22
21
  const props = withDefaults(defineProps<{
23
- code: string
24
- diff?: string
22
+ codeLz: string
23
+ diffLz?: string
25
24
  lang?: string
26
25
  readonly?: boolean
27
26
  lineNumbers?: 'on' | 'off' | 'relative' | 'interval'
28
- height?: number | string
27
+ height?: number | string // Posible values: 'initial', 'auto', '100%', '200px', etc.
29
28
  editorOptions?: monaco.editor.IEditorOptions
29
+ ata?: boolean
30
30
  }>(), {
31
- code: '',
31
+ codeLz: '',
32
32
  lang: 'typescript',
33
33
  readonly: false,
34
34
  lineNumbers: 'off',
35
- height: 'auto',
35
+ height: 'initial',
36
+ ata: true,
36
37
  })
37
38
 
38
- const id = nanoid()
39
- const code = ref(decode(props.code).trimEnd())
40
- const diff = ref(props.diff ? decode(props.diff).trimEnd() : null)
41
- const lineHeight = +(getComputedStyle(document.body).getPropertyValue('--slidev-code-line-height') || '18').replace('px', '') || 18
42
- const editorHeight = ref(0)
43
- const calculatedHeight = computed(() => code.value.split(/\r?\n/g).length * lineHeight)
44
- const height = computed(() => {
45
- return props.height === 'auto' ? `${Math.max(calculatedHeight.value, editorHeight.value) + 20}px` : props.height
46
- })
47
-
48
- const iframe = ref<HTMLIFrameElement>()
39
+ const code = lz.decompressFromBase64(props.codeLz).trimEnd()
40
+ const diff = props.diffLz && lz.decompressFromBase64(props.diffLz).trimEnd()
49
41
 
50
- const cssVars = [
51
- '--slidev-code-font-size',
52
- '--slidev-code-font-family',
53
- '--slidev-code-background',
54
- '--slidev-code-line-height',
55
- '--slidev-code-padding',
56
- '--slidev-code-margin',
57
- '--slidev-code-radius',
58
- ]
59
-
60
- function getStyleObject(el: Element) {
61
- const object: Record<string, string> = {}
62
- const style = getComputedStyle(el)
63
- for (const v of cssVars)
64
- object[v] = style.getPropertyValue(v)
65
- return object
42
+ const langMap: Record<string, string> = {
43
+ ts: 'typescript',
44
+ js: 'javascript',
66
45
  }
46
+ const lang = langMap[props.lang] ?? props.lang
47
+ const extMap: Record<string, string> = {
48
+ typescript: 'mts',
49
+ javascript: 'mjs',
50
+ ts: 'mts',
51
+ js: 'mjs',
52
+ }
53
+ const ext = extMap[props.lang] ?? props.lang
67
54
 
68
- onMounted(() => {
69
- const frame = iframe.value!
70
- frame.setAttribute('sandbox', [
71
- 'allow-forms',
72
- 'allow-modals',
73
- 'allow-pointer-lock',
74
- 'allow-popups',
75
- 'allow-same-origin',
76
- 'allow-scripts',
77
- 'allow-top-navigation-by-user-activation',
78
- ].join(' '))
79
-
80
- let src = __DEV__
81
- ? `${location.origin}${__SLIDEV_CLIENT_ROOT__}/`
82
- : import.meta.env.BASE_URL
83
- src += `iframes/monaco/index.html?id=${id}&lineNumbers=${props.lineNumbers}&lang=${props.lang}`
84
- if (diff.value)
85
- src += '&diff=1'
86
- frame.src = src
55
+ const outer = ref<HTMLDivElement>()
56
+ const container = ref<HTMLDivElement>()
87
57
 
88
- frame.style.backgroundColor = 'transparent'
58
+ const contentHeight = ref(0)
59
+ const initialHeight = ref<number>()
60
+ const height = computed(() => {
61
+ if (props.height === 'auto')
62
+ return `${contentHeight.value}px`
63
+ if (props.height === 'initial')
64
+ return `${initialHeight.value}px`
65
+ return props.height
89
66
  })
90
67
 
91
- function post(payload: any) {
92
- iframe.value?.contentWindow?.postMessage(
93
- JSON.stringify({
94
- type: 'slidev-monaco',
95
- data: payload,
96
- id,
97
- }),
98
- location.origin,
99
- )
100
- }
68
+ onMounted(async () => {
69
+ // Lazy load monaco, so it will be bundled in async chunk
70
+ const { default: setup } = await import('../setup/monaco')
71
+ const { ata, monaco } = await setup()
72
+ const model = monaco.editor.createModel(code, lang, monaco.Uri.parse(`file:///${makeId()}.${ext}`))
73
+ const commonOptions = {
74
+ automaticLayout: true,
75
+ readOnly: props.readonly,
76
+ lineNumbers: props.lineNumbers,
77
+ minimap: { enabled: false },
78
+ overviewRulerBorder: false,
79
+ overviewRulerLanes: 0,
80
+ padding: { top: 10, bottom: 10 },
81
+ lineNumbersMinChars: 3,
82
+ bracketPairColorization: { enabled: false },
83
+ tabSize: 2,
84
+ fontSize: 11.5,
85
+ fontFamily: 'var(--slidev-code-font-family)',
86
+ scrollBeyondLastLine: false,
87
+ ...props.editorOptions,
88
+ } satisfies monaco.editor.IStandaloneEditorConstructionOptions & monaco.editor.IDiffEditorConstructionOptions
101
89
 
102
- useEventListener(window, 'message', ({ data: payload }) => {
103
- if (payload.id !== id)
104
- return
105
- if (payload.type === 'slidev-monaco-loaded') {
106
- if (iframe.value) {
107
- post({
108
- code: code.value,
109
- diff: diff.value,
110
- lang: props.lang,
111
- readonly: props.readonly,
112
- lineNumbers: props.lineNumbers,
113
- editorOptions: props.editorOptions,
114
- dark: isDark.value,
115
- style: Object.entries(getStyleObject(iframe.value)).map(([k, v]) => `${k}: ${v};`).join(''),
116
- })
90
+ let editableEditor: monaco.editor.IStandaloneCodeEditor
91
+ if (diff) {
92
+ const diffModel = monaco.editor.createModel(diff, lang, monaco.Uri.parse(`file:///${makeId()}.${ext}`))
93
+ const editor = monaco.editor.createDiffEditor(container.value!, {
94
+ renderOverviewRuler: false,
95
+ ...commonOptions,
96
+ })
97
+ editor.setModel({
98
+ original: model,
99
+ modified: diffModel,
100
+ })
101
+ const originalEditor = editor.getOriginalEditor()
102
+ const modifiedEditor = editor.getModifiedEditor()
103
+ const onContentSizeChange = () => {
104
+ const newHeight = Math.max(originalEditor.getContentHeight(), modifiedEditor.getContentHeight()) + 4
105
+ initialHeight.value ??= newHeight
106
+ contentHeight.value = newHeight
107
+ nextTick(() => editor.layout())
108
+ }
109
+ originalEditor.onDidContentSizeChange(onContentSizeChange)
110
+ modifiedEditor.onDidContentSizeChange(onContentSizeChange)
111
+ editableEditor = modifiedEditor
112
+ }
113
+ else {
114
+ const editor = monaco.editor.create(container.value!, {
115
+ model,
116
+ lineDecorationsWidth: 0,
117
+ ...commonOptions,
118
+ })
119
+ editor.onDidContentSizeChange((e) => {
120
+ const newHeight = e.contentHeight + 4
121
+ initialHeight.value ??= newHeight
122
+ contentHeight.value = newHeight
123
+ nextTick(() => editableEditor.layout())
124
+ })
125
+ editableEditor = editor
126
+ }
127
+ if (props.ata) {
128
+ ata(editableEditor.getValue())
129
+ editableEditor.onDidChangeModelContent(debounce(1000, () => {
130
+ ata(editableEditor.getValue())
131
+ }))
132
+ }
133
+ const originalLayoutContentWidget = editableEditor.layoutContentWidget.bind(editableEditor)
134
+ editableEditor.layoutContentWidget = (widget: any) => {
135
+ originalLayoutContentWidget(widget)
136
+ const id = widget.getId()
137
+ if (id === 'editor.contrib.resizableContentHoverWidget') {
138
+ widget._resizableNode.domNode.style.transform = widget._positionPreference === 1
139
+ ? /* ABOVE */ `translateY(calc(100% * (var(--slidev-slide-scale) - 1)))`
140
+ : /* BELOW */ `` // reset
117
141
  }
118
- return
119
142
  }
120
- if (payload.type !== 'slidev-monaco')
121
- return
122
- if (payload.data?.height)
123
- editorHeight.value = payload.data?.height
124
- if (payload?.data?.code && code.value !== payload.data.code)
125
- code.value = payload.data.code
126
- if (payload?.data?.diff && diff.value !== payload.data.diff)
127
- diff.value = payload.data.diff
128
143
  })
129
144
  </script>
130
145
 
131
146
  <template>
132
- <iframe ref="iframe" class="text-base w-full rounded" :style="{ height }" />
147
+ <div ref="outer" class="slidev-monaco-container" :style="{ height }">
148
+ <div ref="container" class="absolute inset-0.5" />
149
+ </div>
133
150
  </template>
@@ -1,8 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import type { RenderContext } from '@slidev/types'
3
- import { computed, inject, ref } from 'vue'
3
+ import { computed, ref } from 'vue'
4
4
  import { useElementVisibility } from '@vueuse/core'
5
- import { injectionRenderContext } from '../constants'
5
+ import { useSlideContext } from '../context'
6
6
 
7
7
  type Context = 'main' | 'visible' | RenderContext
8
8
 
@@ -16,7 +16,7 @@ const targetVisible = useElementVisibility(target)
16
16
  // When context has `visible`, we need to wrap the content with a div to track the visibility
17
17
  const needsDomWrapper = Array.isArray(context) ? context.includes('visible') : context === 'visible'
18
18
 
19
- const currentContext = inject(injectionRenderContext)
19
+ const { $renderContext: currentContext } = useSlideContext()
20
20
  const shouldRender = computed(() => {
21
21
  const anyContext = Array.isArray(context) ? context.some(contextMatch) : contextMatch(context)
22
22
  const allConditions = Array.isArray(context) ? context.every(conditionsMatch) : conditionsMatch(context)
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
3
+ import type { KeyedTokensInfo } from 'shiki-magic-move/types'
4
+ import { onMounted, onUnmounted, ref, watchEffect } from 'vue'
5
+ import lz from 'lz-string'
6
+ import { useSlideContext } from '../context'
7
+ import { makeId } from '../logic/utils'
8
+
9
+ import 'shiki-magic-move/style.css'
10
+
11
+ const props = defineProps<{
12
+ stepsLz: string
13
+ at?: string | number
14
+ }>()
15
+
16
+ const steps = JSON.parse(lz.decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
17
+ const { $clicksContext: clicks, $scale: scale } = useSlideContext()
18
+ const id = makeId()
19
+ const index = ref(0)
20
+
21
+ onUnmounted(() => {
22
+ clicks!.unregister(id)
23
+ })
24
+
25
+ onMounted(() => {
26
+ if (!clicks || clicks.disabled)
27
+ return
28
+
29
+ const { start, end, delta } = clicks.resolve(props.at || '+1', steps.length - 1)
30
+ clicks.register(id, { max: end, delta })
31
+
32
+ watchEffect(() => {
33
+ if (clicks.disabled)
34
+ index.value = steps.length - 1
35
+ else
36
+ index.value = Math.min(Math.max(0, clicks.current - start + 1), steps.length - 1)
37
+ })
38
+ })
39
+ </script>
40
+
41
+ <template>
42
+ <div class="slidev-code-wrapper slidev-code-magic-move">
43
+ <ShikiMagicMovePrecompiled
44
+ class="slidev-code relative shiki overflow-visible"
45
+ :steps="steps"
46
+ :step="index"
47
+ :options="{ globalScale: scale }"
48
+ />
49
+ </div>
50
+ </template>
@@ -1,8 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { inject } from 'vue'
3
- import { injectionCurrentPage } from '../constants'
2
+ import { useSlideContext } from '../context'
4
3
 
5
- const $page = inject(injectionCurrentPage)
4
+ const { $page } = useSlideContext()
6
5
  </script>
7
6
 
8
7
  <template>
@@ -1,10 +1,9 @@
1
1
  <script setup lang="ts">
2
- import { inject } from 'vue'
3
- import { injectionSlidevContext } from '../constants'
2
+ import { useSlideContext } from '../context'
4
3
 
5
- const $slidev = inject(injectionSlidevContext)
4
+ const { $nav } = useSlideContext()
6
5
  </script>
7
6
 
8
7
  <template>
9
- <span>{{ $slidev.nav.total }}</span>
8
+ <span>{{ $nav.total }}</span>
10
9
  </template>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue'
3
- import { injectionClicksContext, injectionRenderContext, injectionRoute, injectionSlidevContext } from '../constants'
2
+ import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
3
+ import { useSlideContext } from '../context'
4
4
 
5
5
  const props = defineProps<{
6
6
  autoPlay?: boolean | 'once' | 'resume' | 'resumeOnce'
@@ -8,10 +8,12 @@ const props = defineProps<{
8
8
  autoReset?: 'slide' | 'click'
9
9
  }>()
10
10
 
11
- const $slidev = inject(injectionSlidevContext)
12
- const route = inject(injectionRoute)
13
- const currentContext = inject(injectionRenderContext)
14
- const clicks = inject(injectionClicksContext)?.value
11
+ const {
12
+ $slidev,
13
+ $clicksContext: clicks,
14
+ $renderContext: currentContext,
15
+ $route: route,
16
+ } = useSlideContext()
15
17
 
16
18
  const video = ref<HTMLMediaElement>()
17
19
  const played = ref(false)
package/builtin/Toc.vue CHANGED
@@ -8,9 +8,9 @@ Usage:
8
8
  <Toc columns='2' maxDepth='3' mode='onlySiblings'/>
9
9
  -->
10
10
  <script setup lang='ts'>
11
- import { computed, inject } from 'vue'
11
+ import { computed } from 'vue'
12
12
  import type { TocItem } from '@slidev/types'
13
- import { injectionSlidevContext } from '../constants'
13
+ import { useSlideContext } from '../context'
14
14
 
15
15
  const props = withDefaults(
16
16
  defineProps<{
@@ -33,7 +33,7 @@ const props = withDefaults(
33
33
  },
34
34
  )
35
35
 
36
- const $slidev = inject(injectionSlidevContext)
36
+ const { $slidev } = useSlideContext()
37
37
 
38
38
  function filterTreeDepth(tree: TocItem[], level = 1): TocItem[] {
39
39
  if (level > Number(props.maxDepth)) {
@@ -10,7 +10,7 @@ Usage:
10
10
  import { computed } from 'vue'
11
11
  import { toArray } from '@antfu/utils'
12
12
  import type { TocItem } from '@slidev/types'
13
- import Titles from '/@slidev/titles.md'
13
+ import Titles from '#slidev/titles.md'
14
14
 
15
15
  const props = withDefaults(defineProps<{
16
16
  level: number
@@ -65,7 +65,8 @@ const styles = computed(() => {
65
65
  .slidev-layout .slidev-toc-item p {
66
66
  margin: 0;
67
67
  }
68
- .slidev-layout .slidev-toc-item div, .slidev-layout .slidev-toc-item div p {
68
+ .slidev-layout .slidev-toc-item div,
69
+ .slidev-layout .slidev-toc-item div p {
69
70
  display: initial;
70
71
  }
71
72
  </style>
package/builtin/Tweet.vue CHANGED
@@ -7,8 +7,7 @@ Usage:
7
7
  -->
8
8
 
9
9
  <script setup lang="ts">
10
- import { useScriptTag } from '@vueuse/core'
11
- import { getCurrentInstance, onMounted, ref } from 'vue'
10
+ import { onMounted, ref } from 'vue'
12
11
  import { isDark } from '../logic/dark'
13
12
 
14
13
  const props = defineProps<{
@@ -20,11 +19,10 @@ const props = defineProps<{
20
19
 
21
20
  const tweet = ref<HTMLElement | null>()
22
21
 
23
- const vm = getCurrentInstance()!
24
22
  const loaded = ref(false)
25
23
  const tweetNotFound = ref(false)
26
24
 
27
- async function create() {
25
+ onMounted(async () => {
28
26
  // @ts-expect-error global
29
27
  const element = await window.twttr.widgets.createTweet(
30
28
  props.id.toString(),
@@ -38,24 +36,7 @@ async function create() {
38
36
  loaded.value = true
39
37
  if (element === undefined)
40
38
  tweetNotFound.value = true
41
- }
42
-
43
- // @ts-expect-error global
44
- if (window?.twttr?.widgets) {
45
- onMounted(create)
46
- }
47
- else {
48
- useScriptTag(
49
- 'https://platform.twitter.com/widgets.js',
50
- () => {
51
- if (vm.isMounted)
52
- create()
53
- else
54
- onMounted(create, vm)
55
- },
56
- { async: true },
57
- )
58
- }
39
+ })
59
40
  </script>
60
41
 
61
42
  <template>
package/builtin/VClick.ts CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  import type { PropType, VNode } from 'vue'
8
8
  import { Text, defineComponent, h } from 'vue'
9
+ import { CLICKS_MAX } from '../constants'
9
10
  import VClicks from './VClicks'
10
11
 
11
12
  export default defineComponent({
@@ -31,7 +32,7 @@ export default defineComponent({
31
32
  return h(
32
33
  VClicks,
33
34
  {
34
- every: 99999,
35
+ every: CLICKS_MAX,
35
36
  at: this.at,
36
37
  hide: this.hide,
37
38
  fade: this.fade,
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { Fragment, inject, onMounted, watchEffect } from 'vue'
3
- import { injectionClicksContext } from '../constants'
2
+ import { Fragment, onMounted, watchEffect } from 'vue'
4
3
  import { makeId } from '../logic/utils'
4
+ import { useSlideContext } from '../context'
5
5
 
6
6
  const props = defineProps({
7
7
  size: {
@@ -10,12 +10,10 @@ const props = defineProps({
10
10
  },
11
11
  })
12
12
 
13
- const clicksRef = inject(injectionClicksContext)
13
+ const { $clicksContext: clicks } = useSlideContext()
14
14
 
15
15
  onMounted(() => {
16
16
  watchEffect((onCleanup) => {
17
- const clicks = clicksRef?.value
18
-
19
17
  if (!clicks || clicks.disabled)
20
18
  return
21
19
 
@@ -96,7 +96,7 @@ export default defineComponent({
96
96
  if (depth < +this.depth && Array.isArray(i.children))
97
97
  vNode = h(i, {}, mapSubList(i.children, depth))
98
98
  else
99
- vNode = i
99
+ vNode = h(i)
100
100
 
101
101
  const delta = thisShowIdx - execIdx
102
102
  execIdx = thisShowIdx