@slidev/client 0.48.0-beta.9 → 0.48.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 (97) hide show
  1. package/App.vue +7 -0
  2. package/builtin/Arrow.vue +2 -4
  3. package/builtin/CodeBlockWrapper.vue +33 -28
  4. package/builtin/KaTexBlockWrapper.vue +1 -1
  5. package/builtin/Link.vue +3 -1
  6. package/builtin/Mermaid.vue +4 -3
  7. package/builtin/Monaco.vue +166 -93
  8. package/builtin/ShikiMagicMove.vue +103 -0
  9. package/builtin/SlidevVideo.vue +1 -1
  10. package/builtin/Toc.vue +1 -1
  11. package/builtin/TocList.vue +4 -3
  12. package/builtin/Tweet.vue +12 -9
  13. package/builtin/VClick.ts +2 -1
  14. package/composables/useClicks.ts +19 -32
  15. package/composables/useDarkMode.ts +9 -0
  16. package/composables/useDrawings.ts +181 -0
  17. package/composables/useNav.ts +346 -44
  18. package/{logic/note.ts → composables/useSlideInfo.ts} +13 -16
  19. package/composables/useSwipeControls.ts +43 -0
  20. package/composables/useTocTree.ts +81 -0
  21. package/composables/useViewTransition.ts +7 -4
  22. package/constants.ts +4 -3
  23. package/context.ts +13 -6
  24. package/env.ts +7 -16
  25. package/index.html +1 -0
  26. package/index.ts +12 -0
  27. package/internals/ClicksSlider.vue +97 -0
  28. package/internals/CodeRunner.vue +142 -0
  29. package/internals/Controls.vue +2 -2
  30. package/internals/DomElement.vue +18 -0
  31. package/internals/DrawingControls.vue +14 -15
  32. package/internals/DrawingLayer.vue +6 -5
  33. package/internals/DrawingPreview.vue +4 -2
  34. package/internals/Goto.vue +9 -6
  35. package/internals/IconButton.vue +3 -2
  36. package/internals/NavControls.vue +30 -11
  37. package/internals/NoteDisplay.vue +131 -8
  38. package/internals/NoteEditable.vue +129 -0
  39. package/internals/NoteStatic.vue +5 -2
  40. package/internals/PrintContainer.vue +11 -8
  41. package/internals/PrintSlide.vue +11 -12
  42. package/internals/PrintSlideClick.vue +14 -19
  43. package/internals/{SlidesOverview.vue → QuickOverview.vue} +27 -24
  44. package/internals/RecordingControls.vue +1 -1
  45. package/internals/RecordingDialog.vue +3 -3
  46. package/internals/{Editor.vue → SideEditor.vue} +24 -15
  47. package/internals/SlideContainer.vue +13 -9
  48. package/internals/SlideLoading.vue +19 -0
  49. package/internals/SlideWrapper.vue +79 -0
  50. package/internals/SlidesShow.vue +36 -22
  51. package/layouts/error.vue +5 -0
  52. package/layouts/two-cols-header.vue +9 -3
  53. package/logic/overview.ts +2 -2
  54. package/logic/route.ts +16 -5
  55. package/logic/slides.ts +20 -0
  56. package/logic/transition.ts +50 -0
  57. package/logic/utils.ts +24 -1
  58. package/main.ts +3 -15
  59. package/{setup → modules}/codemirror.ts +1 -3
  60. package/modules/context.ts +1 -46
  61. package/modules/mermaid.ts +9 -8
  62. package/package.json +21 -15
  63. package/pages/notes.vue +6 -3
  64. package/pages/overview.vue +139 -51
  65. package/pages/play.vue +16 -9
  66. package/pages/presenter/print.vue +10 -5
  67. package/pages/presenter.vue +122 -104
  68. package/pages/print.vue +4 -3
  69. package/routes.ts +8 -54
  70. package/setup/code-runners.ts +164 -0
  71. package/setup/main.ts +39 -9
  72. package/setup/mermaid.ts +5 -6
  73. package/setup/monaco.ts +114 -51
  74. package/setup/root.ts +62 -18
  75. package/setup/shortcuts.ts +15 -12
  76. package/shim-vue.d.ts +34 -0
  77. package/shim.d.ts +1 -13
  78. package/state/index.ts +2 -2
  79. package/styles/code.css +9 -5
  80. package/styles/index.css +63 -7
  81. package/styles/katex.css +1 -1
  82. package/styles/layouts-base.css +11 -8
  83. package/styles/shiki-twoslash.css +1 -1
  84. package/styles/vars.css +1 -1
  85. package/uno.config.ts +10 -1
  86. package/utils.ts +15 -2
  87. package/composables/useContext.ts +0 -17
  88. package/composables/useTweetScript.ts +0 -17
  89. package/iframes/monaco/index.css +0 -28
  90. package/iframes/monaco/index.html +0 -7
  91. package/iframes/monaco/index.ts +0 -260
  92. package/internals/NoteEditor.vue +0 -92
  93. package/internals/SlideWrapper.ts +0 -58
  94. package/logic/drawings.ts +0 -161
  95. package/logic/nav.ts +0 -278
  96. package/setup/prettier.ts +0 -43
  97. /package/{composables → logic}/hmr.ts +0 -0
package/styles/index.css CHANGED
@@ -16,22 +16,27 @@ html {
16
16
  }
17
17
 
18
18
  .slidev-icon-btn {
19
- @apply inline-block cursor-pointer select-none !outline-none;
19
+ aspect-ratio: 1;
20
+ display: inline-block;
21
+ user-select: none;
22
+ outline: none;
23
+ cursor: pointer;
20
24
  @apply opacity-75 transition duration-200 ease-in-out align-middle rounded p-1;
21
25
  @apply hover:(opacity-100 bg-gray-400 bg-opacity-10);
22
26
  @apply md:p-2;
23
27
  }
24
28
 
25
29
  .slidev-icon-btn.shallow {
26
- @apply opacity-30
30
+ opacity: 0.3;
27
31
  }
28
32
 
29
33
  .slidev-icon-btn.active {
30
- @apply opacity-100
34
+ opacity: 1;
31
35
  }
32
36
 
33
37
  .slidev-icon-btn.disabled {
34
- @apply opacity-25 pointer-events-none;
38
+ opacity: 0.25;
39
+ pointer-events: none;
35
40
  }
36
41
 
37
42
  .slidev-vclick-target {
@@ -39,11 +44,13 @@ html {
39
44
  }
40
45
 
41
46
  .slidev-vclick-hidden {
42
- @apply !opacity-0 !pointer-events-none;
47
+ opacity: 0 !important;
48
+ pointer-events: none !important;
49
+ user-select: none !important;
43
50
  }
44
51
 
45
52
  .slidev-vclick-fade {
46
- @apply opacity-50;
53
+ opacity: 0.5;
47
54
  }
48
55
 
49
56
  .slidev-icon {
@@ -53,7 +60,56 @@ html {
53
60
  }
54
61
 
55
62
  .slidev-page {
56
- @apply absolute top-0 left-0 right-0 w-full relative;
63
+ position: relative;
64
+ top: 0;
65
+ left: 0;
66
+ right: 0;
67
+ width: 100%;
68
+ }
69
+
70
+ /* Note Clicks */
71
+
72
+ .slidev-note-with-clicks .slidev-note-fade {
73
+ color: #888888ab;
74
+ }
75
+
76
+ .slidev-note-click-mark {
77
+ user-select: none;
78
+ font-size: 0.7em;
79
+ display: inline-flex;
80
+ --uno: text-violet bg-violet/10 px1 font-mono rounded items-center border
81
+ border-transparent;
82
+ }
83
+ .slidev-note-click-mark.slidev-note-click-mark-active {
84
+ --uno: border border-violet;
85
+ }
86
+ .slidev-note-click-mark.slidev-note-click-mark-past {
87
+ filter: saturate(0);
88
+ opacity: 0.5;
89
+ }
90
+ .slidev-note-click-mark.slidev-note-click-mark-future {
91
+ opacity: 0.5;
92
+ }
93
+
94
+ .slidev-note-click-mark::before {
95
+ content: '';
96
+ display: inline-block;
97
+ --un-icon: url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1.2em' height='1.2em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M23 28a1 1 0 0 1-.71-.29l-6.13-6.14l-3.33 5a1 1 0 0 1-1 .44a1 1 0 0 1-.81-.7l-6-20A1 1 0 0 1 6.29 5l20 6a1 1 0 0 1 .7.81a1 1 0 0 1-.44 1l-5 3.33l6.14 6.13a1 1 0 0 1 0 1.42l-4 4A1 1 0 0 1 23 28m0-2.41L25.59 23l-7.16-7.15l5.25-3.5L7.49 7.49l4.86 16.19l3.5-5.25Z'/%3E%3C/svg%3E");
98
+ -webkit-mask: var(--un-icon) no-repeat;
99
+ mask: var(--un-icon) no-repeat;
100
+ -webkit-mask-size: 100% 100%;
101
+ mask-size: 100% 100%;
102
+ background-color: currentColor;
103
+ color: inherit;
104
+ width: 1.2em;
105
+ height: 1.2em;
106
+ opacity: 0.8;
107
+ }
108
+
109
+ .slidev-note-click-mark::after {
110
+ content: attr(data-clicks);
111
+ display: inline-block;
112
+ transform: translateY(0.1em);
57
113
  }
58
114
 
59
115
  /* Transform the position back for Rough Notation (v-mark) */
package/styles/katex.css CHANGED
@@ -2,4 +2,4 @@
2
2
  }
3
3
  .slidev-katex-wrapper .mord.dishonored {
4
4
  opacity: 0.3;
5
- }
5
+ }
@@ -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
 
@@ -79,11 +80,13 @@
79
80
  @apply border-current border-b border-dashed hover:text-primary hover:border-solid;
80
81
  }
81
82
 
82
- td, th {
83
+ td,
84
+ th {
83
85
  @apply p-2 py-3;
84
86
  }
85
87
 
86
- b, strong {
88
+ b,
89
+ strong {
87
90
  @apply font-600;
88
91
  }
89
92
 
@@ -94,8 +97,8 @@
94
97
  }
95
98
 
96
99
  .slidev-layout,
97
- [dir=ltr],
98
- .slidev-layout [dir=ltr] {
100
+ [dir='ltr'],
101
+ .slidev-layout [dir='ltr'] {
99
102
  h1 {
100
103
  @apply -ml-[0.05em] mr-0;
101
104
  }
@@ -109,10 +112,10 @@
109
112
  }
110
113
  }
111
114
 
112
- [dir=rtl],
113
- .slidev-layout [dir=rtl] {
115
+ [dir='rtl'],
116
+ .slidev-layout [dir='rtl'] {
114
117
  h1 {
115
- @apply -mr-[0.05em] ml-0;
118
+ @apply -mr-[0.05em] ml-0;
116
119
  }
117
120
 
118
121
  h6 {
@@ -11,7 +11,7 @@
11
11
  }
12
12
 
13
13
  .twoslash-popup-container {
14
- font-size: calc(13px * var(--slidev-slide-scale, 1));
14
+ font-size: 13px;
15
15
  }
16
16
 
17
17
  .twoslash-popup-container .twoslash-popup-code {
package/styles/vars.css CHANGED
@@ -7,7 +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
+ --slidev-theme-primary: #3ab9d5;
11
11
 
12
12
  --slidev-transition-duration: 0.5s;
13
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,9 +16,10 @@ 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
21
  'border-main': 'border-gray/20',
22
+ 'text-main': 'text-[#181818] dark:text-[#ddd]',
21
23
  'text-primary': 'color-$slidev-theme-primary',
22
24
  'bg-primary': 'bg-$slidev-theme-primary',
23
25
  'border-primary': 'border-$slidev-theme-primary',
@@ -27,6 +29,13 @@ export default defineConfig({
27
29
  'abs-bl': 'absolute bottom-0 left-0',
28
30
  'abs-br': 'absolute bottom-0 right-0',
29
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
+ ],
30
39
  presets: [
31
40
  presetUno(),
32
41
  presetAttributify(),
package/utils.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { RouteRecordRaw } from 'vue-router'
1
+ import type { SlideRoute } from '@slidev/types'
2
+ import { configs } from './env'
2
3
 
3
- export function getSlideClass(route?: RouteRecordRaw, extra = '') {
4
+ export function getSlideClass(route?: SlideRoute, extra = '') {
4
5
  const classes = ['slidev-page', extra]
5
6
 
6
7
  const no = route?.meta?.slide?.no
@@ -9,3 +10,15 @@ export function getSlideClass(route?: RouteRecordRaw, extra = '') {
9
10
 
10
11
  return classes.filter(Boolean).join(' ')
11
12
  }
13
+
14
+ export async function downloadPDF() {
15
+ const { saveAs } = await import('file-saver')
16
+ saveAs(
17
+ typeof configs.download === 'string'
18
+ ? configs.download
19
+ : configs.exportFilename
20
+ ? `${configs.exportFilename}.pdf`
21
+ : `${import.meta.env.BASE_URL}slidev-exported.pdf`,
22
+ `${configs.title}.pdf`,
23
+ )
24
+ }
@@ -1,17 +0,0 @@
1
- import type { ComputedRef } from 'vue'
2
- import { computed } from 'vue'
3
- import type { RouteLocationNormalizedLoaded } from 'vue-router'
4
- import type { SlidevContext } from '../modules/context'
5
- import { configs } from '../env'
6
- import { useNav } from './useNav'
7
-
8
- export function useContext(
9
- route: ComputedRef<RouteLocationNormalizedLoaded>,
10
- ): SlidevContext {
11
- const nav = useNav(route)
12
- return {
13
- nav,
14
- configs,
15
- themeConfigs: computed(() => configs.themeConfig),
16
- }
17
- }
@@ -1,17 +0,0 @@
1
- import { createSharedComposable, useScriptTag } from '@vueuse/core'
2
- import type { ComponentInternalInstance } from 'vue'
3
- import { onMounted } from 'vue'
4
-
5
- export const useTweetScript = createSharedComposable(
6
- (vm: ComponentInternalInstance, create: () => void) =>
7
- useScriptTag(
8
- 'https://platform.twitter.com/widgets.js',
9
- () => {
10
- if (vm.isMounted)
11
- create()
12
- else
13
- onMounted(create, vm)
14
- },
15
- { async: true },
16
- ),
17
- )
@@ -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,92 +0,0 @@
1
- <script setup lang="ts">
2
- import { ignorableWatch, onClickOutside, useVModel } from '@vueuse/core'
3
- import { ref, watch, watchEffect } from 'vue'
4
- import { useDynamicSlideInfo } from '../logic/note'
5
- import NoteDisplay from './NoteDisplay.vue'
6
-
7
- const props = defineProps({
8
- no: {
9
- type: Number,
10
- },
11
- class: {
12
- default: '',
13
- },
14
- editing: {
15
- default: false,
16
- },
17
- style: {
18
- default: () => ({}),
19
- },
20
- placeholder: {
21
- default: 'No notes for this slide',
22
- },
23
- })
24
-
25
- const emit = defineEmits([
26
- 'update:editing',
27
- ])
28
- const editing = useVModel(props, 'editing', emit, { passive: true })
29
-
30
- const { info, update } = useDynamicSlideInfo(props.no)
31
-
32
- const note = ref('')
33
- let timer: any
34
-
35
- const { ignoreUpdates } = ignorableWatch(
36
- note,
37
- (v) => {
38
- const id = props.no
39
- clearTimeout(timer)
40
- timer = setTimeout(() => {
41
- update({ note: v }, id)
42
- }, 500)
43
- },
44
- )
45
-
46
- watch(
47
- info,
48
- (v) => {
49
- if (editing.value)
50
- return
51
- clearTimeout(timer)
52
- ignoreUpdates(() => {
53
- note.value = v?.note || ''
54
- })
55
- },
56
- { immediate: true, flush: 'sync' },
57
- )
58
-
59
- const input = ref<HTMLTextAreaElement>()
60
-
61
- watchEffect(() => {
62
- if (editing.value)
63
- input.value?.focus()
64
- })
65
-
66
- onClickOutside(input, () => {
67
- editing.value = false
68
- })
69
- </script>
70
-
71
- <template>
72
- <NoteDisplay
73
- v-if="!editing"
74
- class="my--4 border-transparent border-2"
75
- :class="[props.class, note ? '' : 'opacity-25 italic select-none']"
76
- :style="props.style"
77
- :note="note || placeholder"
78
- :note-html="info?.noteHTML"
79
- />
80
- <textarea
81
- v-else
82
- ref="input"
83
- v-model="note"
84
- class="prose resize-none overflow-auto outline-none bg-transparent block border-primary border-2"
85
- style="line-height: 1.75;"
86
- :style="props.style"
87
- :class="props.class"
88
- :placeholder="placeholder"
89
- @keydown.esc=" editing = false"
90
- @focus="editing = true"
91
- />
92
- </template>