@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
@@ -1,7 +1,8 @@
1
1
  .slidev-layout {
2
2
  @apply px-14 py-10 text-[1.1rem] h-full;
3
3
 
4
- pre, code {
4
+ pre,
5
+ code {
5
6
  @apply select-text;
6
7
  }
7
8
 
@@ -54,7 +55,9 @@
54
55
  }
55
56
 
56
57
  blockquote {
57
- @apply text-sm px-2 py-1 bg-$prism-background text-$prism-foreground border-$slidev-theme-primary border-l rounded;
58
+ background: var(--slidev-code-background);
59
+ color: var(--slidev-code-foreground);
60
+ @apply text-sm px-2 py-1 border-primary border-l rounded;
58
61
  }
59
62
 
60
63
  blockquote > * {
@@ -66,7 +69,7 @@
66
69
  }
67
70
 
68
71
  tr {
69
- @apply border-b border-gray-400 border-opacity-20;
72
+ @apply border-b border-main;
70
73
  }
71
74
 
72
75
  th {
@@ -74,26 +77,28 @@
74
77
  }
75
78
 
76
79
  a {
77
- @apply border-current border-b border-dashed hover:text-$slidev-theme-primary hover:border-solid;
80
+ @apply border-current border-b border-dashed hover:text-primary hover:border-solid;
78
81
  }
79
82
 
80
- td, th {
83
+ td,
84
+ th {
81
85
  @apply p-2 py-3;
82
86
  }
83
87
 
84
- b, strong {
88
+ b,
89
+ strong {
85
90
  @apply font-600;
86
91
  }
87
92
 
88
93
  kbd {
89
- @apply border border-gray-400 border-b-2 border-opacity-20 rounded;
94
+ @apply border border-main border-b-2 rounded;
90
95
  @apply bg-gray-400 bg-opacity-5 py-0.5 px-1 text-xs font-mono;
91
96
  }
92
97
  }
93
98
 
94
99
  .slidev-layout,
95
- [dir=ltr],
96
- .slidev-layout [dir=ltr] {
100
+ [dir='ltr'],
101
+ .slidev-layout [dir='ltr'] {
97
102
  h1 {
98
103
  @apply -ml-[0.05em] mr-0;
99
104
  }
@@ -107,10 +112,10 @@
107
112
  }
108
113
  }
109
114
 
110
- [dir=rtl],
111
- .slidev-layout [dir=rtl] {
115
+ [dir='rtl'],
116
+ .slidev-layout [dir='rtl'] {
112
117
  h1 {
113
- @apply -mr-[0.05em] ml-0;
118
+ @apply -mr-[0.05em] ml-0;
114
119
  }
115
120
 
116
121
  h6 {
@@ -0,0 +1,27 @@
1
+ div[widgetid='messageoverlay'] {
2
+ transform: translateY(calc(100% * (var(--slidev-slide-scale) - 1)));
3
+ }
4
+
5
+ .slidev-monaco-container {
6
+ position: relative;
7
+ margin: var(--slidev-code-margin);
8
+ padding: var(--slidev-code-padding);
9
+ line-height: var(--slidev-code-line-height);
10
+ border-radius: var(--slidev-code-radius);
11
+ background: var(--slidev-code-background);
12
+ }
13
+
14
+ .slidev-monaco-container .monaco-editor {
15
+ --monaco-monospace-font: var(--slidev-code-font-family);
16
+ --vscode-editor-background: var(--slidev-code-background);
17
+ --vscode-editorGutter-background: var(--slidev-code-background);
18
+ }
19
+
20
+ /** Revert styles */
21
+ .slidev-monaco-container .monaco-editor a {
22
+ border-bottom: none;
23
+ }
24
+
25
+ .slidev-monaco-container .monaco-editor a:hover {
26
+ border-bottom: none;
27
+ }
package/styles/vars.css CHANGED
@@ -7,6 +7,7 @@
7
7
  --slidev-code-line-height: 18px;
8
8
  --slidev-code-radius: 4px;
9
9
  --slidev-code-margin: 4px 0;
10
+ --slidev-theme-primary: #3ab9d5;
10
11
 
11
12
  --slidev-transition-duration: 0.5s;
12
13
  --slidev-slide-container-background: black;
package/uno.config.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  transformerDirectives,
9
9
  transformerVariantGroup,
10
10
  } from 'unocss'
11
+ import { variantMatcher } from '@unocss/preset-mini/utils'
11
12
 
12
13
  export default defineConfig({
13
14
  safelist: [
@@ -15,15 +16,26 @@ export default defineConfig({
15
16
  'prose',
16
17
  ],
17
18
  shortcuts: {
18
- 'bg-main': 'bg-white text-[#181818] dark:(bg-[#121212] text-[#ddd])',
19
+ 'bg-main': 'bg-white dark:bg-[#121212]',
19
20
  'bg-active': 'bg-gray-400/10',
20
- 'border-main': 'border-gray-400/20',
21
+ 'border-main': 'border-gray/20',
22
+ 'text-main': 'text-[#181818] dark:text-[#ddd]',
23
+ 'text-primary': 'color-$slidev-theme-primary',
24
+ 'bg-primary': 'bg-$slidev-theme-primary',
25
+ 'border-primary': 'border-$slidev-theme-primary',
21
26
  'abs-tl': 'absolute top-0 left-0',
22
27
  'abs-tr': 'absolute top-0 right-0',
23
28
  'abs-b': 'absolute bottom-0 left-0 right-0',
24
29
  'abs-bl': 'absolute bottom-0 left-0',
25
30
  'abs-br': 'absolute bottom-0 right-0',
26
31
  },
32
+ // Slidev Specific Variants, probably extrat to a preset later
33
+ variants: [
34
+ // `forward:` and `backward:` variant to selectively apply styles based on the direction of the slide
35
+ // For example, `forward:text-red` will only apply to the slides that are navigated forward
36
+ variantMatcher('forward', input => ({ prefix: `.slidev-nav-go-forward ${input.prefix}` })),
37
+ variantMatcher('backward', input => ({ prefix: `.slidev-nav-go-backward ${input.prefix}` })),
38
+ ],
27
39
  presets: [
28
40
  presetUno(),
29
41
  presetAttributify(),
@@ -1,28 +0,0 @@
1
- html,
2
- body,
3
- #container {
4
- padding: 0;
5
- margin: 0;
6
- background: var(--slidev-code-background);
7
- width: 100%;
8
- height: 200%;
9
- }
10
-
11
- #container {
12
- padding: var(--slidev-code-padding);
13
- margin: var(--slidev-code-margin);
14
- border-radius: var(--slidev-code-radius);
15
- }
16
-
17
- .monaco-editor .monaco-hover {
18
- border-radius: var(--slidev-code-radius);
19
- overflow: hidden;
20
- border: none;
21
- outline: none;
22
- }
23
-
24
- .monaco-editor .lines-content,
25
- .monaco-editor .view-line,
26
- .monaco-editor .view-lines {
27
- user-select: none;
28
- }
@@ -1,7 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <body>
4
- <div id="container"></div>
5
- <script type="module" src="./index.ts"></script>
6
- </body>
7
- </html>
@@ -1,260 +0,0 @@
1
- import '/@slidev/styles'
2
- import './index.css'
3
-
4
- import type * as monaco from 'monaco-editor'
5
- import { formatCode } from '../../setup/prettier'
6
- import setupMonaco from '../../setup/monaco'
7
- import '/@slidev/monaco-types'
8
-
9
- const url = new URL(location.href)
10
- const props = {
11
- id: url.searchParams.get('id'),
12
- code: '',
13
- diff: '',
14
- lang: url.searchParams.get('lang') ?? 'typescript',
15
- readonly: false,
16
- lineNumbers: url.searchParams.get('lineNumbers') ?? 'off',
17
- dark: false,
18
- style: '',
19
- editorOptions: {},
20
- }
21
-
22
- const styleObject = document.createElement('style')
23
- let originalEditor: monaco.editor.IStandaloneCodeEditor
24
- let modifiedEditor: monaco.editor.IStandaloneCodeEditor
25
- let format: () => void = () => { }
26
- let update: () => void = () => { }
27
-
28
- document.body.appendChild(styleObject)
29
-
30
- function lang() {
31
- switch (props.lang) {
32
- case 'ts':
33
- case 'tsx':
34
- return 'typescript'
35
- case 'jsx':
36
- case 'js':
37
- return 'javascript'
38
- default:
39
- return props.lang
40
- }
41
- }
42
-
43
- function ext() {
44
- switch (lang()) {
45
- case 'typescript':
46
- return 'ts'
47
- case 'javascript':
48
- return 'js'
49
- default:
50
- return lang()
51
- }
52
- }
53
-
54
- function post(data: any, type = 'slidev-monaco') {
55
- if (window.parent === window)
56
- return
57
-
58
- window.parent.postMessage(
59
- {
60
- type,
61
- id: props.id,
62
- data,
63
- },
64
- location.origin,
65
- )
66
- }
67
-
68
- async function start() {
69
- const { monaco, theme = {}, editorOptions = {} } = await setupMonaco()
70
-
71
- const style = getComputedStyle(document.documentElement)
72
- const container = document.getElementById('container')!
73
-
74
- const model = monaco.editor.createModel(
75
- props.code,
76
- lang(),
77
- monaco.Uri.parse(`file:///root/${Date.now()}.${ext()}`),
78
- )
79
-
80
- if (url.searchParams.get('diff')) {
81
- // Diff editor
82
- const diffModel = monaco.editor.createModel(
83
- props.diff,
84
- lang(),
85
- monaco.Uri.parse(`file:///root/${Date.now()}.${ext()}`),
86
- )
87
- const monacoEditor = monaco.editor.createDiffEditor(container, {
88
- fontSize: +style.getPropertyValue('--slidev-code-font-size').replace(/px/g, ''),
89
- fontFamily: style.getPropertyValue('--slidev-code-font-family'),
90
- lineHeight: +style.getPropertyValue('--slidev-code-line-height').replace(/px/g, ''),
91
- lineDecorationsWidth: 0,
92
- lineNumbersMinChars: 0,
93
- scrollBeyondLastLine: false,
94
- scrollBeyondLastColumn: 0,
95
- automaticLayout: true,
96
- readOnly: props.readonly,
97
- theme: 'vitesse-dark',
98
- lineNumbers: props.lineNumbers as any,
99
- glyphMargin: false,
100
- scrollbar: {
101
- useShadows: false,
102
- vertical: 'hidden',
103
- horizontal: 'hidden',
104
- },
105
- overviewRulerLanes: 0,
106
- minimap: { enabled: false },
107
- enableSplitViewResizing: false,
108
- renderOverviewRuler: false,
109
- // renderSideBySide: false,
110
- ...editorOptions,
111
- })
112
- monacoEditor.setModel({
113
- original: model,
114
- modified: diffModel,
115
- })
116
- originalEditor = monacoEditor.getOriginalEditor()
117
- modifiedEditor = monacoEditor.getModifiedEditor()
118
-
119
- format = async () => {
120
- model.setValue((await formatCode(props.code, lang())).trim())
121
- diffModel.setValue((await formatCode(props.diff, lang())).trim())
122
- }
123
-
124
- // ctrl+s to format
125
- originalEditor.onKeyDown((e) => {
126
- if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
127
- e.preventDefault()
128
- format()
129
- }
130
- })
131
- modifiedEditor.onKeyDown((e) => {
132
- if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
133
- e.preventDefault()
134
- format()
135
- }
136
- })
137
-
138
- update = () => {
139
- monaco.editor.setTheme(props.dark
140
- ? (theme.dark || 'vitesse-dark')
141
- : (theme.light || 'vitesse-light'))
142
- styleObject.innerHTML = `:root { ${props.style} }`
143
-
144
- if (originalEditor.getValue().toString() !== props.code) {
145
- const selection = originalEditor.getSelection()
146
- originalEditor.setValue(props.code)
147
- if (selection)
148
- originalEditor.setSelection(selection)
149
- }
150
- originalEditor.updateOptions(props.editorOptions)
151
-
152
- if (modifiedEditor.getValue().toString() !== props.diff) {
153
- const selection = modifiedEditor.getSelection()
154
- modifiedEditor.setValue(props.diff)
155
- if (selection)
156
- modifiedEditor.setSelection(selection)
157
- }
158
- modifiedEditor.updateOptions(props.editorOptions)
159
- }
160
-
161
- diffModel.onDidChangeContent(() => {
162
- onCodeChange(diffModel.getValue().toString())
163
- })
164
-
165
- function onCodeChange(diff: string) {
166
- props.diff = diff
167
- post({ diff })
168
- }
169
- }
170
- else {
171
- // Normal editor
172
- originalEditor = monaco.editor.create(container, {
173
- model,
174
- tabSize: 2,
175
- insertSpaces: true,
176
- detectIndentation: false,
177
- folding: false,
178
- fontSize: +style.getPropertyValue('--slidev-code-font-size').replace(/px/g, ''),
179
- fontFamily: style.getPropertyValue('--slidev-code-font-family'),
180
- lineHeight: +style.getPropertyValue('--slidev-code-line-height').replace(/px/g, ''),
181
- lineDecorationsWidth: 0,
182
- lineNumbersMinChars: 0,
183
- scrollBeyondLastLine: false,
184
- scrollBeyondLastColumn: 0,
185
- automaticLayout: true,
186
- readOnly: props.readonly,
187
- theme: 'vitesse-dark',
188
- lineNumbers: props.lineNumbers as any,
189
- glyphMargin: false,
190
- scrollbar: {
191
- useShadows: false,
192
- vertical: 'hidden',
193
- horizontal: 'hidden',
194
- },
195
- overviewRulerLanes: 0,
196
- minimap: { enabled: false },
197
- ...editorOptions,
198
- })
199
-
200
- format = async () => {
201
- model.setValue((await formatCode(props.code, lang())).trim())
202
- }
203
-
204
- // ctrl+s to format
205
- originalEditor.onKeyDown((e) => {
206
- if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') {
207
- e.preventDefault()
208
- format()
209
- }
210
- })
211
-
212
- update = () => {
213
- monaco.editor.setTheme(props.dark
214
- ? (theme.dark || 'vitesse-dark')
215
- : (theme.light || 'vitesse-light'))
216
- styleObject.innerHTML = `:root { ${props.style} }`
217
-
218
- if (originalEditor.getValue().toString() !== props.code) {
219
- const selection = originalEditor.getSelection()
220
- originalEditor.setValue(props.code)
221
- if (selection)
222
- originalEditor.setSelection(selection)
223
- }
224
- originalEditor.updateOptions(props.editorOptions)
225
- }
226
- }
227
-
228
- originalEditor.onDidContentSizeChange(() => {
229
- post({ height: Math.max(originalEditor.getContentHeight(), modifiedEditor?.getContentHeight() ?? 0) })
230
- })
231
-
232
- model.onDidChangeContent(() => {
233
- onCodeChange(model.getValue().toString())
234
- })
235
-
236
- function onCodeChange(code: string) {
237
- props.code = code
238
- post({ code })
239
- }
240
-
241
- update()
242
-
243
- post({}, 'slidev-monaco-loaded')
244
- }
245
-
246
- window.addEventListener('message', (payload) => {
247
- if (payload.source === window)
248
- return
249
- if (payload.origin !== location.origin)
250
- return
251
- if (typeof payload.data !== 'string')
252
- return
253
- const { type, data, id } = JSON.parse(payload.data)
254
- if (type === 'slidev-monaco' && id === props.id) {
255
- Object.assign(props, data)
256
- update()
257
- }
258
- })
259
-
260
- start()
@@ -1,88 +0,0 @@
1
- <script setup lang="ts">
2
- import { ignorableWatch, onClickOutside, useVModel } from '@vueuse/core'
3
- import { ref, watch, watchEffect } from 'vue'
4
- import { currentSlideId } from '../logic/nav'
5
- import { useDynamicSlideInfo } from '../logic/note'
6
- import NoteDisplay from './NoteDisplay.vue'
7
-
8
- const props = defineProps({
9
- class: {
10
- default: '',
11
- },
12
- editing: {
13
- default: false,
14
- },
15
- style: {
16
- default: () => ({}),
17
- },
18
- placeholder: {
19
- default: 'No notes for this slide',
20
- },
21
- })
22
-
23
- const emit = defineEmits([
24
- 'update:editing',
25
- ])
26
- const editing = useVModel(props, 'editing', emit, { passive: true })
27
-
28
- const { info, update } = useDynamicSlideInfo(currentSlideId)
29
-
30
- const note = ref('')
31
- let timer: any
32
-
33
- const { ignoreUpdates } = ignorableWatch(
34
- note,
35
- (v) => {
36
- const id = currentSlideId.value
37
- clearTimeout(timer)
38
- timer = setTimeout(() => {
39
- update({ raw: null!, note: v }, id)
40
- }, 500)
41
- },
42
- )
43
-
44
- watch(
45
- info,
46
- (v) => {
47
- clearTimeout(timer)
48
- ignoreUpdates(() => {
49
- note.value = v?.note || ''
50
- })
51
- },
52
- { immediate: true, flush: 'sync' },
53
- )
54
-
55
- const input = ref<HTMLTextAreaElement>()
56
-
57
- watchEffect(() => {
58
- if (editing.value)
59
- input.value?.focus()
60
- })
61
-
62
- onClickOutside(input, () => {
63
- editing.value = false
64
- })
65
- </script>
66
-
67
- <template>
68
- <NoteDisplay
69
- v-if="!editing"
70
- class="my--4 border-transparent border-2"
71
- :class="[props.class, note ? '' : 'opacity-50']"
72
- :style="props.style"
73
- :note="note || placeholder"
74
- :note-html="info?.noteHTML"
75
- />
76
- <textarea
77
- v-else
78
- ref="input"
79
- v-model="note"
80
- class="prose resize-none overflow-auto outline-none bg-transparent block border-green border-2"
81
- style="line-height: 1.75;"
82
- :style="props.style"
83
- :class="props.class"
84
- :placeholder="placeholder"
85
- @keydown.esc=" editing = false"
86
- @focus="editing = true"
87
- />
88
- </template>