@slidev/client 0.48.0-beta.21 → 0.48.0-beta.23

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.
@@ -0,0 +1,139 @@
1
+ <script setup lang="ts">
2
+ import { debounce, toArray } from '@antfu/utils'
3
+ import { useVModel } from '@vueuse/core'
4
+ import type { CodeRunnerOutput } from '@slidev/types'
5
+ import { computed, ref, shallowRef, watch } from 'vue'
6
+ import { isPrintMode } from '../logic/nav'
7
+ import { useSlideContext } from '../context'
8
+ import setupCodeRunners from '../setup/code-runners'
9
+ import IconButton from './IconButton.vue'
10
+ import DomElement from './DomElement.vue'
11
+
12
+ const props = defineProps<{
13
+ modelValue: string
14
+ lang: string
15
+ autorun: boolean | 'once'
16
+ height?: string
17
+ highlightOutput: boolean
18
+ runnerOptions?: Record<string, unknown>
19
+ }>()
20
+
21
+ const emit = defineEmits(['update:modelValue'])
22
+ const code = useVModel(props, 'modelValue', emit)
23
+
24
+ const { $renderContext } = useSlideContext()
25
+ const disabled = computed(() => !['slide', 'presenter'].includes($renderContext.value))
26
+
27
+ const autorun = isPrintMode.value ? 'once' : props.autorun
28
+ const isRunning = ref(autorun)
29
+ const outputs = shallowRef<CodeRunnerOutput[]>()
30
+ const runCount = ref(0)
31
+ const highlightFn = ref<(code: string, lang: string) => string>()
32
+
33
+ const triggerRun = debounce(200, async () => {
34
+ if (disabled.value)
35
+ return
36
+
37
+ const { highlight, run } = await setupCodeRunners()
38
+ highlightFn.value = highlight
39
+
40
+ const setAsRunning = setTimeout(() => {
41
+ isRunning.value = true
42
+ }, 500)
43
+
44
+ outputs.value = toArray(await run(code.value, props.lang, props.runnerOptions ?? {}))
45
+ runCount.value += 1
46
+ isRunning.value = false
47
+
48
+ clearTimeout(setAsRunning)
49
+ })
50
+
51
+ if (autorun === 'once')
52
+ triggerRun()
53
+ else if (autorun)
54
+ watch(code, triggerRun, { immediate: true })
55
+ </script>
56
+
57
+ <template>
58
+ <div
59
+ class="relative flex flex-col rounded-b border-t border-main"
60
+ :style="{ height: props.height }"
61
+ data-waitfor=".slidev-runner-output"
62
+ >
63
+ <div v-if="disabled" class="text-sm text-center opacity-50">
64
+ Code is disabled in the "{{ $renderContext }}" mode
65
+ </div>
66
+ <div v-else-if="isRunning" class="text-sm text-center opacity-50">
67
+ Running...
68
+ </div>
69
+ <div v-else-if="!outputs?.length" class="text-sm text-center opacity-50">
70
+ Click the play button to run the code
71
+ </div>
72
+ <div v-else :key="`run-${runCount}`" class="slidev-runner-output">
73
+ <template v-for="output, _idx1 of outputs" :key="_idx1">
74
+ <div v-if="'html' in output" v-html="output.html" />
75
+ <div v-else-if="'error' in output" class="text-red-500">
76
+ {{ output.error }}
77
+ </div>
78
+ <DomElement v-else-if="'element' in output" :element="output.element" />
79
+ <div v-else class="output-line">
80
+ <template
81
+ v-for="item, idx2 in toArray(output)"
82
+ :key="idx2"
83
+ >
84
+ <span
85
+ v-if="item.highlightLang && highlightFn"
86
+ class="highlighted"
87
+ v-html="highlightFn(item.text, item.highlightLang)"
88
+ />
89
+ <span v-else :class="item.class">{{ item.text }}</span>
90
+ <span v-if="idx2 < toArray(output).length - 1" class="separator">,</span>
91
+ </template>
92
+ </div>
93
+ </template>
94
+ </div>
95
+ </div>
96
+ <div v-if="code.trim()" class="absolute right-1 top-1 max-h-full flex gap-1">
97
+ <IconButton class="w-8 h-8 max-h-full flex justify-center items-center" title="Run code" @click="triggerRun">
98
+ <carbon:play />
99
+ </IconButton>
100
+ </div>
101
+ </template>
102
+
103
+ <style lang="postcss">
104
+ .slidev-runner-output {
105
+ @apply px-5 py-3 flex-grow text-xs leading-[.8rem] font-$slidev-code-font-family select-text;
106
+ }
107
+
108
+ .slidev-runner-output .log-type {
109
+ @apply font-bold op-70;
110
+
111
+ &.DBG {
112
+ @apply text-gray-500;
113
+ }
114
+
115
+ &.LOG {
116
+ @apply text-blue-500;
117
+ }
118
+
119
+ &.WRN {
120
+ @apply text-orange-500;
121
+ }
122
+
123
+ &.ERR {
124
+ @apply text-red-500;
125
+ }
126
+ }
127
+
128
+ .slidev-runner-output .output-line {
129
+ @apply flex my-1 w-full;
130
+ }
131
+
132
+ .slidev-runner-output .separator {
133
+ @apply op-40 mr-1;
134
+ }
135
+
136
+ .slidev-runner-output .highlighted > pre {
137
+ @apply inline text-wrap !bg-transparent;
138
+ }
139
+ </style>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import { ref, watchEffect } from 'vue'
3
+
4
+ const props = defineProps<{
5
+ element: HTMLElement
6
+ }>()
7
+
8
+ const container = ref<HTMLElement>()
9
+
10
+ watchEffect(() => {
11
+ if (container.value)
12
+ container.value.appendChild(props.element)
13
+ })
14
+ </script>
15
+
16
+ <template>
17
+ <div ref="container" />
18
+ </template>
@@ -7,7 +7,7 @@ defineProps<{
7
7
  </script>
8
8
 
9
9
  <template>
10
- <component :is="as || 'button'" class="slidev-icon-btn" :title="title" v-bind="$attrs">
10
+ <component :is="as || 'button'" class="slidev-icon-btn" :title="title">
11
11
  <span class="sr-only">{{ title }}</span>
12
12
  <slot>
13
13
  <div :class="icon" />
@@ -1,14 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import type { PropType } from 'vue'
3
- import { nextTick, ref, watch, watchEffect } from 'vue'
3
+ import { nextTick, ref, toRef, watch, watchEffect } from 'vue'
4
4
  import { ignorableWatch, onClickOutside, useVModel } from '@vueuse/core'
5
5
  import type { ClicksContext } from '@slidev/types'
6
- import { useDynamicSlideInfo } from '../logic/note'
6
+ import { useDynamicSlideInfo } from '../composables/useSlideInfo'
7
7
  import NoteDisplay from './NoteDisplay.vue'
8
8
 
9
9
  const props = defineProps({
10
10
  no: {
11
11
  type: Number,
12
+ required: true,
12
13
  },
13
14
  class: {
14
15
  default: '',
@@ -38,7 +39,7 @@ const emit = defineEmits<{
38
39
 
39
40
  const editing = useVModel(props, 'editing', emit, { passive: true })
40
41
 
41
- const { info, update } = useDynamicSlideInfo(props.no)
42
+ const { info, update } = useDynamicSlideInfo(toRef(props, 'no'))
42
43
 
43
44
  const note = ref('')
44
45
  let timer: any
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import type { ClicksContext } from '@slidev/types'
3
- import { useSlideInfo } from '../logic/note'
3
+ import { useSlideInfo } from '../composables/useSlideInfo'
4
4
  import NoteDisplay from './NoteDisplay.vue'
5
5
 
6
6
  const props = defineProps<{
7
- no?: number
7
+ no: number
8
8
  class?: string
9
9
  clicksContext?: ClicksContext
10
10
  }>()
@@ -12,14 +12,14 @@ const props = defineProps<{
12
12
  }>()
13
13
 
14
14
  const width = computed(() => props.width)
15
- const height = computed(() => props.width / slideAspect)
15
+ const height = computed(() => props.width / slideAspect.value)
16
16
 
17
17
  const screenAspect = computed(() => width.value / height.value)
18
18
 
19
19
  const scale = computed(() => {
20
- if (screenAspect.value < slideAspect)
21
- return width.value / slideWidth
22
- return (height.value * slideAspect) / slideWidth
20
+ if (screenAspect.value < slideAspect.value)
21
+ return width.value / slideWidth.value
22
+ return (height.value * slideAspect.value) / slideWidth.value
23
23
  })
24
24
 
25
25
  // In print mode, the routes will never change. So we don't need reactivity here.
@@ -5,7 +5,7 @@ import { injectionSlidevContext } from '../constants'
5
5
  import { configs, slideHeight, slideWidth } from '../env'
6
6
  import { getSlideClass } from '../utils'
7
7
  import type { SlidevContextNav } from '../composables/useNav'
8
- import SlideWrapper from './SlideWrapper'
8
+ import SlideWrapper from './SlideWrapper.vue'
9
9
 
10
10
  import GlobalTop from '#slidev/global-components/top'
11
11
  import GlobalBottom from '#slidev/global-components/bottom'
@@ -17,8 +17,8 @@ const { nav } = defineProps<{
17
17
  const route = computed(() => nav.currentSlideRoute.value)
18
18
 
19
19
  const style = computed(() => ({
20
- height: `${slideHeight}px`,
21
- width: `${slideWidth}px`,
20
+ height: `${slideHeight.value}px`,
21
+ width: `${slideWidth.value}px`,
22
22
  }))
23
23
 
24
24
  const DrawingPreview = shallowRef<any>()
@@ -8,7 +8,7 @@ import { useFixedClicks } from '../composables/useClicks'
8
8
  import { getSlideClass } from '../utils'
9
9
  import { CLICKS_MAX } from '../constants'
10
10
  import SlideContainer from './SlideContainer.vue'
11
- import SlideWrapper from './SlideWrapper'
11
+ import SlideWrapper from './SlideWrapper.vue'
12
12
  import DrawingPreview from './DrawingPreview.vue'
13
13
  import IconButton from './IconButton.vue'
14
14
 
@@ -167,6 +167,7 @@ watchEffect(() => {
167
167
  <carbon:close />
168
168
  </IconButton>
169
169
  <IconButton
170
+ v-if="__DEV__"
170
171
  as="a"
171
172
  title="Slides Overview"
172
173
  target="_blank"
@@ -4,7 +4,7 @@ import { computed, nextTick, onMounted, ref, watch } from 'vue'
4
4
  import { activeElement, editorHeight, editorWidth, isInputting, showEditor, isEditorVertical as vertical } from '../state'
5
5
  import { useCodeMirror } from '../setup/codemirror'
6
6
  import { currentSlideNo, openInEditor } from '../logic/nav'
7
- import { useDynamicSlideInfo } from '../logic/note'
7
+ import { useDynamicSlideInfo } from '../composables/useSlideInfo'
8
8
  import IconButton from './IconButton.vue'
9
9
 
10
10
  const props = defineProps<{
@@ -25,7 +25,7 @@ const root = ref<HTMLDivElement>()
25
25
  const element = useElementSize(root)
26
26
 
27
27
  const width = computed(() => props.width ? props.width : element.width.value)
28
- const height = computed(() => props.width ? props.width / slideAspect : element.height.value)
28
+ const height = computed(() => props.width ? props.width / slideAspect.value : element.height.value)
29
29
 
30
30
  if (props.width) {
31
31
  watchEffect(() => {
@@ -41,14 +41,14 @@ const screenAspect = computed(() => width.value / height.value)
41
41
  const scale = computed(() => {
42
42
  if (props.scale && !isPrintMode.value)
43
43
  return props.scale
44
- if (screenAspect.value < slideAspect)
45
- return width.value / slideWidth
46
- return height.value * slideAspect / slideWidth
44
+ if (screenAspect.value < slideAspect.value)
45
+ return width.value / slideWidth.value
46
+ return height.value * slideAspect.value / slideWidth.value
47
47
  })
48
48
 
49
49
  const style = computed(() => ({
50
- 'height': `${slideHeight}px`,
51
- 'width': `${slideWidth}px`,
50
+ 'height': `${slideHeight.value}px`,
51
+ 'width': `${slideWidth.value}px`,
52
52
  'transform': `translate(-50%, -50%) scale(${scale.value})`,
53
53
  '--slidev-slide-scale': scale.value,
54
54
  }))
@@ -10,7 +10,7 @@ onMounted(() => {
10
10
  </script>
11
11
 
12
12
  <template>
13
- <div class="h-full w-full flex items-center justify-center gap-2">
13
+ <div class="h-full w-full flex items-center justify-center gap-2 slidev-slide-loading">
14
14
  <template v-if="timeout">
15
15
  <div class="i-svg-spinners-90-ring-with-bg text-xl" />
16
16
  <div>Loading slide...</div>
@@ -0,0 +1,79 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineAsyncComponent, defineComponent, h, onMounted, ref, toRef } from 'vue'
3
+ import type { PropType } from 'vue'
4
+ import { provideLocal } from '@vueuse/core'
5
+ import type { ClicksContext, RenderContext, SlideRoute } from '@slidev/types'
6
+ import { injectionActive, injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionRoute } from '../constants'
7
+ import SlideLoading from './SlideLoading.vue'
8
+
9
+ const props = defineProps({
10
+ clicksContext: {
11
+ type: Object as PropType<ClicksContext>,
12
+ required: true,
13
+ },
14
+ renderContext: {
15
+ type: String as PropType<RenderContext>,
16
+ default: 'slide',
17
+ },
18
+ active: {
19
+ type: Boolean,
20
+ default: false,
21
+ },
22
+ is: {
23
+ type: Function as PropType<() => any>,
24
+ required: true,
25
+ },
26
+ route: {
27
+ type: Object as PropType<SlideRoute>,
28
+ required: true,
29
+ },
30
+ })
31
+
32
+ provideLocal(injectionRoute, props.route)
33
+ provideLocal(injectionCurrentPage, ref(props.route.no))
34
+ provideLocal(injectionRenderContext, ref(props.renderContext as RenderContext))
35
+ provideLocal(injectionActive, toRef(props, 'active'))
36
+ provideLocal(injectionClicksContext, toRef(props, 'clicksContext'))
37
+
38
+ const style = computed(() => {
39
+ const zoom = props.route.meta?.slide?.frontmatter.zoom ?? 1
40
+ return zoom === 1
41
+ ? undefined
42
+ : {
43
+ width: `${100 / zoom}%`,
44
+ height: `${100 / zoom}%`,
45
+ transformOrigin: 'top left',
46
+ transform: `scale(${zoom})`,
47
+ }
48
+ })
49
+
50
+ const SlideComponent = defineAsyncComponent({
51
+ loader: async () => {
52
+ const component = await props.is()
53
+ return defineComponent({
54
+ setup(_, { attrs }) {
55
+ onMounted(() => {
56
+ props.clicksContext.onMounted()
57
+ })
58
+ return () => h(component.default, attrs)
59
+ },
60
+ })
61
+ },
62
+ delay: 300,
63
+ loadingComponent: SlideLoading,
64
+ })
65
+ </script>
66
+
67
+ <template>
68
+ <component
69
+ :is="SlideComponent"
70
+ :style="style"
71
+ :class="{ 'disable-view-transition': !['slide', 'presenter'].includes(props.renderContext) }"
72
+ />
73
+ </template>
74
+
75
+ <style scoped>
76
+ .disable-view-transition:deep(*) {
77
+ view-transition-name: none !important;
78
+ }
79
+ </style>
@@ -5,7 +5,7 @@ import { getSlideClass } from '../utils'
5
5
  import { useViewTransition } from '../composables/useViewTransition'
6
6
  import { skipTransition } from '../composables/hmr'
7
7
  import { usePrimaryClicks } from '../composables/useClicks'
8
- import SlideWrapper from './SlideWrapper'
8
+ import SlideWrapper from './SlideWrapper.vue'
9
9
  import PresenterMouse from './PresenterMouse.vue'
10
10
 
11
11
  import GlobalTop from '#slidev/global-components/top'
package/logic/nav.ts CHANGED
@@ -67,5 +67,5 @@ watch(
67
67
  await goLast()
68
68
  }
69
69
  },
70
- { flush: 'post', immediate: true },
70
+ { flush: 'pre', immediate: true },
71
71
  )
package/logic/route.ts CHANGED
@@ -19,7 +19,12 @@ export function useRouteQuery<T extends string | string[]>(
19
19
  },
20
20
  set(v) {
21
21
  nextTick(() => {
22
- router[unref(mode) as 'replace' | 'push']({ query: { ...router.currentRoute.value.query, [name]: v } })
22
+ router[unref(mode) as 'replace' | 'push']({
23
+ query: {
24
+ ...router.currentRoute.value.query,
25
+ [name]: `${v}` === defaultValue ? undefined : v,
26
+ },
27
+ })
23
28
  })
24
29
  },
25
30
  })
package/logic/utils.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import { parseRangeString } from '@slidev/parser/core'
1
2
  import { useTimestamp } from '@vueuse/core'
2
3
  import { computed, ref } from 'vue'
4
+ import { CLASS_VCLICK_TARGET } from '../constants'
3
5
 
4
6
  export function useTimer() {
5
7
  const tsStart = ref(Date.now())
@@ -24,7 +26,7 @@ export function useTimer() {
24
26
 
25
27
  export function makeId(length = 5) {
26
28
  const result = []
27
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
29
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
28
30
  const charactersLength = characters.length
29
31
  for (let i = 0; i < length; i++)
30
32
  result.push(characters.charAt(Math.floor(Math.random() * charactersLength)))
@@ -48,3 +50,25 @@ export function normalizeAtProp(at: string | number = '+1'): [isRelative: boolea
48
50
  n,
49
51
  ]
50
52
  }
53
+
54
+ export function updateCodeHighlightRange(
55
+ rangeStr: string,
56
+ linesCount: number,
57
+ startLine: number,
58
+ getTokenOfLine: (line: number) => Element[],
59
+ ) {
60
+ const highlights: number[] = parseRangeString(linesCount + startLine - 1, rangeStr)
61
+ for (let line = 0; line < linesCount; line++) {
62
+ const tokens = getTokenOfLine(line)
63
+ const isHighlighted = highlights.includes(line + startLine)
64
+ for (const token of tokens) {
65
+ // token.classList.toggle(CLASS_VCLICK_TARGET, true)
66
+ token.classList.toggle('slidev-code-highlighted', isHighlighted)
67
+ token.classList.toggle('slidev-code-dishonored', !isHighlighted)
68
+
69
+ // for backward compatibility
70
+ token.classList.toggle('highlighted', isHighlighted)
71
+ token.classList.toggle('dishonored', !isHighlighted)
72
+ }
73
+ }
74
+ }
package/main.ts CHANGED
@@ -10,6 +10,7 @@ import { createVMarkDirective } from './modules/v-mark'
10
10
  import { createSlidevContext } from './modules/context'
11
11
 
12
12
  import '#slidev/styles'
13
+ import 'shiki-magic-move/style.css'
13
14
 
14
15
  const app = createApp(App)
15
16
  app.use(router)
@@ -1,12 +1,13 @@
1
1
  import type { App } from 'vue'
2
- import { computed, reactive, ref } from 'vue'
2
+ import { computed, reactive, ref, shallowRef } from 'vue'
3
3
  import type { ComputedRef } from '@vue/reactivity'
4
4
  import type { configs } from '../env'
5
5
  import * as nav from '../logic/nav'
6
6
  import { isDark } from '../logic/dark'
7
- import { injectionCurrentPage, injectionRenderContext, injectionSlidevContext } from '../constants'
7
+ import { injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionSlidevContext } from '../constants'
8
8
  import { useContext } from '../composables/useContext'
9
9
  import type { SlidevContextNav } from '../composables/useNav'
10
+ import { useFixedClicks } from '../composables/useClicks'
10
11
 
11
12
  export interface SlidevContext {
12
13
  nav: SlidevContextNav
@@ -21,6 +22,7 @@ export function createSlidevContext() {
21
22
  app.provide(injectionRenderContext, ref('none'))
22
23
  app.provide(injectionSlidevContext, context)
23
24
  app.provide(injectionCurrentPage, computed(() => context.nav.currentSlideNo))
25
+ app.provide(injectionClicksContext, shallowRef(useFixedClicks()))
24
26
 
25
27
  // allows controls from postMessages
26
28
  if (__DEV__) {
@@ -8,8 +8,10 @@ mermaid.startOnLoad = false
8
8
  mermaid.initialize({ startOnLoad: false })
9
9
 
10
10
  const cache = new Map<string, string>()
11
+ let containerElement: Element | undefined
11
12
 
12
13
  export async function renderMermaid(lzEncoded: string, options: any) {
14
+ containerElement ??= document.getElementById('mermaid-rendering-container')!
13
15
  const key = lzEncoded + JSON.stringify(options)
14
16
  const _cache = cache.get(key)
15
17
  if (_cache)
@@ -22,7 +24,7 @@ export async function renderMermaid(lzEncoded: string, options: any) {
22
24
  })
23
25
  const code = lz.decompressFromBase64(lzEncoded)
24
26
  const id = makeId()
25
- const { svg } = await mermaid.render(id, code)
27
+ const { svg } = await mermaid.render(id, code, containerElement)
26
28
  cache.set(key, svg)
27
29
  return svg
28
30
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@slidev/client",
3
3
  "type": "module",
4
- "version": "0.48.0-beta.21",
4
+ "version": "0.48.0-beta.23",
5
5
  "description": "Presentation slides for developers",
6
6
  "author": "antfu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -27,14 +27,14 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@antfu/utils": "^0.7.7",
30
- "@iconify-json/carbon": "^1.1.30",
30
+ "@iconify-json/carbon": "^1.1.31",
31
31
  "@iconify-json/ph": "^1.1.11",
32
32
  "@iconify-json/svg-spinners": "^1.1.2",
33
33
  "@shikijs/monaco": "^1.1.7",
34
34
  "@shikijs/vitepress-twoslash": "^1.1.7",
35
35
  "@slidev/rough-notation": "^0.1.0",
36
36
  "@typescript/ata": "^0.9.4",
37
- "@unhead/vue": "^1.8.10",
37
+ "@unhead/vue": "^1.8.11",
38
38
  "@unocss/reset": "^0.58.5",
39
39
  "@vueuse/core": "^10.9.0",
40
40
  "@vueuse/math": "^10.9.0",
@@ -47,20 +47,21 @@
47
47
  "js-yaml": "^4.1.0",
48
48
  "katex": "^0.16.9",
49
49
  "lz-string": "^1.5.0",
50
- "mermaid": "^10.8.0",
50
+ "mermaid": "^10.9.0",
51
51
  "monaco-editor": "^0.46.0",
52
52
  "prettier": "^3.2.5",
53
53
  "recordrtc": "^5.6.2",
54
54
  "shiki": "^1.1.7",
55
- "shiki-magic-move": "^0.1.0",
56
- "typescript": "^5.3.3",
55
+ "shiki-magic-move": "^0.3.4",
56
+ "typescript": "^5.4.2",
57
57
  "unocss": "^0.58.5",
58
58
  "vue": "^3.4.21",
59
+ "vue-demi": "^0.14.7",
59
60
  "vue-router": "^4.3.0",
60
- "@slidev/types": "0.48.0-beta.21",
61
- "@slidev/parser": "0.48.0-beta.21"
61
+ "@slidev/types": "0.48.0-beta.23",
62
+ "@slidev/parser": "0.48.0-beta.23"
62
63
  },
63
64
  "devDependencies": {
64
- "vite": "^5.1.4"
65
+ "vite": "^5.1.5"
65
66
  }
66
67
  }
@@ -8,7 +8,7 @@ import { useFixedClicks } from '../composables/useClicks'
8
8
  import { isColorSchemaConfigured, isDark, toggleDark } from '../logic/dark'
9
9
  import { getSlideClass } from '../utils'
10
10
  import SlideContainer from '../internals/SlideContainer.vue'
11
- import SlideWrapper from '../internals/SlideWrapper'
11
+ import SlideWrapper from '../internals/SlideWrapper.vue'
12
12
  import DrawingPreview from '../internals/DrawingPreview.vue'
13
13
  import IconButton from '../internals/IconButton.vue'
14
14
  import NoteEditable from '../internals/NoteEditable.vue'
@@ -139,6 +139,7 @@ onMounted(() => {
139
139
  :key="route.no"
140
140
  :ref="el => blocks.set(idx, el as any)"
141
141
  class="relative border-t border-main of-hidden flex gap-4 min-h-50 group"
142
+ :class="idx === 0 ? 'pt5' : ''"
142
143
  >
143
144
  <div class="select-none w-13 text-right my4 flex flex-col gap-1 items-end">
144
145
  <div class="text-3xl op20 mb2">
@@ -192,19 +193,19 @@ onMounted(() => {
192
193
  <IconButton
193
194
  title="Edit Note"
194
195
  class="rounded-full w-9 h-9 text-sm"
195
- :class="edittingNote === idx ? 'important:op0' : ''"
196
- @click="edittingNote = idx"
196
+ :class="edittingNote === route.no ? 'important:op0' : ''"
197
+ @click="edittingNote = route.no"
197
198
  >
198
199
  <carbon:pen />
199
200
  </IconButton>
200
201
  </div>
201
202
  <NoteEditable
202
- :no="idx"
203
+ :no="route.no"
203
204
  class="max-w-250 w-250 text-lg rounded p3"
204
205
  :auto-height="true"
205
- :editing="edittingNote === idx"
206
+ :editing="edittingNote === route.no"
206
207
  :clicks-context="getClicksContext(route)"
207
- @dblclick="edittingNote !== idx ? edittingNote = idx : null"
208
+ @dblclick="edittingNote !== route.no ? edittingNote = route.no : null"
208
209
  @update:editing="edittingNote = null"
209
210
  @marker-click="(e, clicks) => onMarkerClick(e, clicks, route)"
210
211
  />
@@ -12,7 +12,7 @@ import { getSlideClass } from '../utils'
12
12
  import { useTimer } from '../logic/utils'
13
13
  import { isDrawing } from '../logic/drawings'
14
14
  import { useFixedClicks, usePrimaryClicks } from '../composables/useClicks'
15
- import SlideWrapper from '../internals/SlideWrapper'
15
+ import SlideWrapper from '../internals/SlideWrapper.vue'
16
16
  import SlideContainer from '../internals/SlideContainer.vue'
17
17
  import NavControls from '../internals/NavControls.vue'
18
18
  import QuickOverview from '../internals/QuickOverview.vue'