@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,12 +1,13 @@
1
1
  import { sum } from '@antfu/utils'
2
2
  import type { ClicksContext } from '@slidev/types'
3
3
  import type { Ref } from 'vue'
4
- import { ref, shallowReactive } from 'vue'
4
+ import { computed, ref, shallowReactive } from 'vue'
5
5
  import type { RouteRecordRaw } from 'vue-router'
6
6
  import { currentRoute, isPrintMode, isPrintWithClicks, queryClicks, routeForceRefresh } from '../logic/nav'
7
7
  import { normalizeAtProp } from '../logic/utils'
8
+ import { CLICKS_MAX } from '../constants'
8
9
 
9
- function useClicksContextBase(route: RouteRecordRaw | undefined, getCurrent: () => number): ClicksContext {
10
+ function useClicksContextBase(current: Ref<number>, clicksOverrides?: number): ClicksContext {
10
11
  const relativeOffsets: ClicksContext['relativeOffsets'] = new Map()
11
12
  const map: ClicksContext['map'] = shallowReactive(new Map())
12
13
 
@@ -15,7 +16,10 @@ function useClicksContextBase(route: RouteRecordRaw | undefined, getCurrent: ()
15
16
  return isPrintMode.value && !isPrintWithClicks.value
16
17
  },
17
18
  get current() {
18
- return getCurrent()
19
+ return current.value
20
+ },
21
+ set current(value) {
22
+ current.value = value
19
23
  },
20
24
  relativeOffsets,
21
25
  map,
@@ -53,7 +57,7 @@ function useClicksContextBase(route: RouteRecordRaw | undefined, getCurrent: ()
53
57
  get total() {
54
58
  // eslint-disable-next-line no-unused-expressions
55
59
  routeForceRefresh.value
56
- return route?.meta?.clicks
60
+ return clicksOverrides
57
61
  ?? Math.max(0, ...[...map.values()].map(v => v.max || 0))
58
62
  },
59
63
  }
@@ -62,22 +66,36 @@ function useClicksContextBase(route: RouteRecordRaw | undefined, getCurrent: ()
62
66
  export function usePrimaryClicks(route: RouteRecordRaw | undefined): ClicksContext {
63
67
  if (route?.meta?.__clicksContext)
64
68
  return route.meta.__clicksContext
65
- const thisPath = +(route?.path ?? 99999)
66
- const context = useClicksContextBase(route, () => {
67
- const currentPath = +(currentRoute.value?.path ?? 99999)
68
- if (currentPath === thisPath)
69
- return queryClicks.value
70
- else if (currentPath > thisPath)
71
- return 99999
72
- else
73
- return 0
69
+ const thisPath = +(route?.path ?? Number.NaN)
70
+ const current = computed({
71
+ get() {
72
+ const currentPath = +(currentRoute.value?.path ?? Number.NaN)
73
+ if (!currentPath || Number.isNaN(currentPath))
74
+ return 0
75
+ if (currentPath === thisPath)
76
+ return queryClicks.value
77
+ else if (currentPath > thisPath)
78
+ return CLICKS_MAX
79
+ else
80
+ return 0
81
+ },
82
+ set(v) {
83
+ const currentPath = +(currentRoute.value?.path ?? Number.NaN)
84
+ if (currentPath === thisPath) {
85
+ // eslint-disable-next-line ts/no-use-before-define
86
+ queryClicks.value = Math.min(v, context.total)
87
+ }
88
+ },
74
89
  })
90
+ const context = useClicksContextBase(
91
+ current,
92
+ route?.meta?.clicks,
93
+ )
75
94
  if (route?.meta)
76
95
  route.meta.__clicksContext = context
77
96
  return context
78
97
  }
79
98
 
80
- export function useFixedClicks(route: RouteRecordRaw | undefined, currentInit = 0): [Ref<number>, ClicksContext] {
81
- const current = ref(currentInit)
82
- return [current, useClicksContextBase(route, () => current.value)]
99
+ export function useFixedClicks(route?: RouteRecordRaw | undefined, currentInit = 0): ClicksContext {
100
+ return useClicksContextBase(ref(currentInit), route?.meta?.clicks)
83
101
  }
package/constants.ts CHANGED
@@ -3,14 +3,16 @@ import type { RouteRecordRaw } from 'vue-router'
3
3
  import type { ClicksContext, RenderContext } from '@slidev/types'
4
4
  import type { SlidevContext } from './modules/context'
5
5
 
6
- export const injectionClicksContext: InjectionKey<Ref<ClicksContext>> = Symbol('slidev-clicks-context')
7
- export const injectionCurrentPage: InjectionKey<Ref<number>> = Symbol('slidev-page')
8
- export const injectionSlideScale: InjectionKey<ComputedRef<number>> = Symbol('slidev-slide-scale')
9
- export const injectionSlidevContext: InjectionKey<UnwrapNestedRefs<SlidevContext>> = Symbol('slidev-slidev-context')
10
- export const injectionRoute: InjectionKey<RouteRecordRaw> = Symbol('slidev-route')
11
- export const injectionRenderContext: InjectionKey<Ref<RenderContext>> = Symbol('slidev-render-context')
12
- export const injectionActive: InjectionKey<Ref<boolean>> = Symbol('slidev-active')
13
- export const injectionFrontmatter: InjectionKey<Record<string, any>> = Symbol('slidev-fontmatter')
6
+ // Here we use string literal instead of symbols to make HMR more stable
7
+ // The value of the injections keys are implementation details, you should always use them with the reference to the constant instead of the value
8
+ export const injectionClicksContext = '$$slidev-clicks-context' as unknown as InjectionKey<Ref<ClicksContext>>
9
+ export const injectionCurrentPage = '$$slidev-page' as unknown as InjectionKey<Ref<number>>
10
+ export const injectionSlideScale = '$$slidev-slide-scale' as unknown as InjectionKey<ComputedRef<number>>
11
+ export const injectionSlidevContext = '$$slidev-context' as unknown as InjectionKey<UnwrapNestedRefs<SlidevContext>>
12
+ export const injectionRoute = '$$slidev-route' as unknown as InjectionKey<RouteRecordRaw>
13
+ export const injectionRenderContext = '$$slidev-render-context' as unknown as InjectionKey<Ref<RenderContext>>
14
+ export const injectionActive = '$$slidev-active' as unknown as InjectionKey<Ref<boolean>>
15
+ export const injectionFrontmatter = '$$slidev-fontmatter' as unknown as InjectionKey<Record<string, any>>
14
16
 
15
17
  export const CLASS_VCLICK_TARGET = 'slidev-vclick-target'
16
18
  export const CLASS_VCLICK_HIDDEN = 'slidev-vclick-hidden'
@@ -20,7 +22,55 @@ export const CLASS_VCLICK_HIDDEN_EXP = 'slidev-vclick-hidden-explicitly'
20
22
  export const CLASS_VCLICK_CURRENT = 'slidev-vclick-current'
21
23
  export const CLASS_VCLICK_PRIOR = 'slidev-vclick-prior'
22
24
 
25
+ export const CLICKS_MAX = 999999
26
+
23
27
  export const TRUST_ORIGINS = [
24
28
  'localhost',
25
29
  '127.0.0.1',
26
30
  ]
31
+
32
+ export const FRONTMATTER_FIELDS = [
33
+ 'clicks',
34
+ 'disabled',
35
+ 'hide',
36
+ 'hideInToc',
37
+ 'layout',
38
+ 'level',
39
+ 'preload',
40
+ 'routeAlias',
41
+ 'src',
42
+ 'title',
43
+ 'transition',
44
+ 'zoom',
45
+ ]
46
+
47
+ export const HEADMATTER_FIELDS = [
48
+ ...FRONTMATTER_FIELDS,
49
+ 'theme',
50
+ 'titleTemplate',
51
+ 'info',
52
+ 'author',
53
+ 'keywords',
54
+ 'presenter',
55
+ 'download',
56
+ 'exportFilename',
57
+ 'export',
58
+ 'highlighter',
59
+ 'lineNumbers',
60
+ 'monaco',
61
+ 'remoteAssets',
62
+ 'selectable',
63
+ 'record',
64
+ 'colorSchema',
65
+ 'routerMode',
66
+ 'aspectRatio',
67
+ 'canvasWidth',
68
+ 'themeConfig',
69
+ 'favicon',
70
+ 'plantUmlServer',
71
+ 'fonts',
72
+ 'defaults',
73
+ 'drawings',
74
+ 'htmlAttrs',
75
+ 'mdc',
76
+ ]
package/context.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { ref, shallowRef, toRef } from 'vue'
2
+ import { injectLocal, objectOmit, provideLocal } from '@vueuse/core'
3
+ import { useFixedClicks } from './composables/useClicks'
4
+ import {
5
+ FRONTMATTER_FIELDS,
6
+ HEADMATTER_FIELDS,
7
+ injectionClicksContext,
8
+ injectionCurrentPage,
9
+ injectionFrontmatter,
10
+ injectionRenderContext,
11
+ injectionRoute,
12
+ injectionSlideScale,
13
+ injectionSlidevContext,
14
+ } from './constants'
15
+
16
+ const clicksContextFallback = shallowRef(useFixedClicks())
17
+
18
+ /**
19
+ * Get the current slide context, should be called inside the setup function of a component inside slide
20
+ */
21
+ export function useSlideContext() {
22
+ const $slidev = injectLocal(injectionSlidevContext)!
23
+ const $nav = toRef($slidev, 'nav')
24
+ const $clicksContext = injectLocal(injectionClicksContext, clicksContextFallback)!.value
25
+ const $clicks = toRef($clicksContext, 'current')
26
+ const $page = injectLocal(injectionCurrentPage)!
27
+ const $renderContext = injectLocal(injectionRenderContext)!
28
+ const $frontmatter = injectLocal(injectionFrontmatter, {})
29
+ const $route = injectLocal(injectionRoute, undefined)
30
+ const $scale = injectLocal(injectionSlideScale, ref(1))!
31
+
32
+ return {
33
+ $slidev,
34
+ $nav,
35
+ $clicksContext,
36
+ $clicks,
37
+ $page,
38
+ $route,
39
+ $renderContext,
40
+ $frontmatter,
41
+ $scale,
42
+ }
43
+ }
44
+
45
+ export function provideFrontmatter(frontmatter: Record<string, any>) {
46
+ provideLocal(injectionFrontmatter, frontmatter)
47
+
48
+ const {
49
+ $slidev,
50
+ $page,
51
+ } = useSlideContext()
52
+
53
+ // update frontmatter in router to make HMR work better
54
+ const route = $slidev.nav.rawRoutes.find(i => i.path === String($page.value))
55
+ if (route?.meta?.slide?.frontmatter) {
56
+ for (const key of Object.keys(route.meta.slide.frontmatter)) {
57
+ if (!(key in frontmatter))
58
+ delete route.meta.slide.frontmatter[key]
59
+ }
60
+ Object.assign(route.meta.slide.frontmatter, frontmatter)
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Convert frontmatter options to props for v-bind
66
+ * It removes known options fields, and expose an extra `frontmatter` field that contains full frontmatter
67
+ */
68
+ export function frontmatterToProps(frontmatter: Record<string, any>, pageNo: number) {
69
+ return {
70
+ ...objectOmit(frontmatter, pageNo === 0 ? HEADMATTER_FIELDS : FRONTMATTER_FIELDS),
71
+ frontmatter,
72
+ }
73
+ }
package/env.ts CHANGED
@@ -1,15 +1,12 @@
1
- import type { SlidevConfig } from '@slidev/types'
2
- import type { UnwrapNestedRefs } from 'vue'
3
1
  import { computed } from 'vue'
4
2
  import { objectMap } from '@antfu/utils'
3
+ import configs from '#slidev/configs'
5
4
 
6
- // @ts-expect-error missing types
7
- import _configs from '/@slidev/configs'
8
- import type { SlidevContext } from './modules/context'
5
+ export { configs }
9
6
 
10
- export const configs = _configs as SlidevConfig
11
7
  export const slideAspect = configs.aspectRatio ?? (16 / 9)
12
8
  export const slideWidth = configs.canvasWidth ?? 980
9
+
13
10
  // To honor the aspect ratio more as possible, we need to approximate the height to the next integer.
14
11
  // Doing this, we will prevent on print, to create an additional empty white page after each page.
15
12
  export const slideHeight = Math.ceil(slideWidth / slideAspect)
@@ -17,9 +14,3 @@ export const slideHeight = Math.ceil(slideWidth / slideAspect)
17
14
  export const themeVars = computed(() => {
18
15
  return objectMap(configs.themeConfig || {}, (k, v) => [`--slidev-theme-${k}`, v])
19
16
  })
20
-
21
- declare module 'vue' {
22
- interface ComponentCustomProperties {
23
- $slidev: UnwrapNestedRefs<SlidevContext>
24
- }
25
- }
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ import type { ClicksContext } from '@slidev/types'
3
+ import { computed } from 'vue'
4
+
5
+ const props = defineProps<{
6
+ clicksContext: ClicksContext
7
+ }>()
8
+
9
+ const total = computed(() => props.clicksContext.total)
10
+ const current = computed({
11
+ get() {
12
+ return props.clicksContext.current > total.value ? -1 : props.clicksContext.current
13
+ },
14
+ set(value: number) {
15
+ // eslint-disable-next-line vue/no-mutating-props
16
+ props.clicksContext.current = value
17
+ },
18
+ })
19
+
20
+ const range = computed(() => Array.from({ length: total.value + 1 }, (_, i) => i))
21
+
22
+ function onMousedown() {
23
+ if (current.value < 0 || current.value > total.value)
24
+ current.value = 0
25
+ }
26
+ </script>
27
+
28
+ <template>
29
+ <div
30
+ class="flex gap-0.5 items-center select-none"
31
+ :title="`Clicks in this slide: ${total}`"
32
+ :class="total ? '' : 'op50'"
33
+ >
34
+ <div class="flex gap-1 items-center min-w-16">
35
+ <carbon:cursor-1 text-sm op50 />
36
+ <span text-primary>{{ current }}</span>
37
+ <span op50>/</span>
38
+ <span op50>{{ total }}</span>
39
+ </div>
40
+ <div
41
+ relative flex-auto h5 flex="~"
42
+ @dblclick="current = clicksContext.total"
43
+ >
44
+ <div
45
+ v-for="i of range" :key="i"
46
+ border="y main" of-hidden relative
47
+ :class="[
48
+ i === 0 ? 'rounded-l border-l' : '',
49
+ i === total ? 'rounded-r border-r' : '',
50
+ ]"
51
+ :style="{ width: total > 0 ? `${1 / total * 100}%` : '100%' }"
52
+ >
53
+ <div absolute inset-0 :class="i <= current ? 'bg-primary op20' : ''" />
54
+ <div
55
+ :class="[
56
+ +i === +current ? 'text-primary font-bold op100 border-primary' : 'op30 border-main',
57
+ i === 0 ? 'rounded-l' : '',
58
+ i === total ? 'rounded-r' : 'border-r-2',
59
+ ]"
60
+ w-full h-full text-xs flex items-center justify-center z-1
61
+ >
62
+ {{ i }}
63
+ </div>
64
+ </div>
65
+ <input
66
+ v-model="current"
67
+ class="range" absolute inset-0
68
+ type="range" :min="0" :max="total" :step="1" z-10 op0
69
+ :style="{ '--thumb-width': `${1 / (total + 1) * 100}%` }"
70
+ @mousedown="onMousedown"
71
+ @focus="event => (event.currentTarget as HTMLElement)?.blur()"
72
+ >
73
+ </div>
74
+ </div>
75
+ </template>
76
+
77
+ <style scoped>
78
+ .range {
79
+ -webkit-appearance: none;
80
+ appearance: none;
81
+ background: transparent;
82
+ }
83
+ .range::-webkit-slider-thumb {
84
+ -webkit-appearance: none;
85
+ height: 100%;
86
+ width: var(--thumb-width, 0.5rem);
87
+ }
88
+
89
+ .range::-moz-range-thumb {
90
+ height: 100%;
91
+ width: var(--thumb-width, 0.5rem);
92
+ }
93
+ </style>
@@ -2,7 +2,7 @@
2
2
  import { shallowRef } from 'vue'
3
3
  import { showInfoDialog, showOverview, showRecordingDialog } from '../state'
4
4
  import { configs } from '../env'
5
- import SlidesOverview from './SlidesOverview.vue'
5
+ import QuickOverview from './QuickOverview.vue'
6
6
  import InfoDialog from './InfoDialog.vue'
7
7
  import Goto from './Goto.vue'
8
8
 
@@ -15,7 +15,7 @@ if (__SLIDEV_FEATURE_RECORD__) {
15
15
  </script>
16
16
 
17
17
  <template>
18
- <SlidesOverview v-model="showOverview" />
18
+ <QuickOverview v-model="showOverview" />
19
19
  <Goto />
20
20
  <WebCamera v-if="WebCamera" />
21
21
  <RecordingDialog v-if="RecordingDialog" v-model="showRecordingDialog" />
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { Menu } from 'floating-vue'
3
+ import 'floating-vue/dist/style.css'
2
4
  import {
3
5
  brush,
4
6
  brushColors,
@@ -21,20 +23,24 @@ function undo() {
21
23
  function redo() {
22
24
  drauu.redo()
23
25
  }
26
+
27
+ let lastDrawingMode: typeof drawingMode.value = 'stylus'
24
28
  function setDrawingMode(mode: typeof drawingMode.value) {
25
29
  drawingMode.value = mode
26
30
  drawingEnabled.value = true
31
+ if (mode !== 'eraseLine')
32
+ lastDrawingMode = mode
27
33
  }
28
34
  function setBrushColor(color: typeof brush.color) {
29
35
  brush.color = color
30
36
  drawingEnabled.value = true
37
+ drawingMode.value = lastDrawingMode
31
38
  }
32
39
  </script>
33
40
 
34
41
  <template>
35
42
  <Draggable
36
- class="flex flex-wrap text-xl p-2 gap-1 rounded-md bg-main shadow transition-opacity duration-200"
37
- dark="border border-gray-400 border-opacity-10"
43
+ class="flex flex-wrap text-xl p-2 gap-1 rounded-md bg-main shadow transition-opacity duration-200 z-20 border border-main"
38
44
  :class="drawingEnabled ? '' : drawingPinned ? 'opacity-40 hover:opacity-90' : 'opacity-0 pointer-events-none'"
39
45
  storage-key="slidev-drawing-pos"
40
46
  :initial-x="10"
@@ -57,23 +63,41 @@ function setBrushColor(color: typeof brush.color) {
57
63
  <IconButton title="Draw a rectangle" :class="{ shallow: drawingMode !== 'rectangle' }" @click="setDrawingMode('rectangle')">
58
64
  <carbon:checkbox />
59
65
  </IconButton>
60
- <!-- TODO: not sure why it's not working! -->
61
- <!-- <IconButton title="Erase" :class="{ shallow: drawingMode != 'eraseLine' }" @click="setDrawingMode('eraseLine')">
66
+ <IconButton title="Erase" :class="{ shallow: drawingMode !== 'eraseLine' }" @click="setDrawingMode('eraseLine')">
62
67
  <carbon:erase />
63
- </IconButton> -->
68
+ </IconButton>
64
69
 
65
70
  <VerticalDivider />
66
71
 
72
+ <Menu>
73
+ <IconButton title="Adjust stroke width" :class="{ shallow: drawingMode === 'eraseLine' }">
74
+ <svg viewBox="0 0 32 32" width="1.2em" height="1.2em">
75
+ <line x1="2" y1="15" x2="22" y2="4" stroke="currentColor" stroke-width="1" stroke-linecap="round" />
76
+ <line x1="2" y1="24" x2="28" y2="10" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
77
+ <line x1="7" y1="31" x2="29" y2="19" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
78
+ </svg>
79
+ </IconButton>
80
+ <template #popper>
81
+ <div class="flex bg-main p-2">
82
+ <div class="inline-block w-7 text-center">
83
+ {{ brush.size }}
84
+ </div>
85
+ <div class="pt-.5">
86
+ <input v-model="brush.size" type="range" min="1" max="15" @change="drawingMode = lastDrawingMode">
87
+ </div>
88
+ </div>
89
+ </template>
90
+ </Menu>
67
91
  <IconButton
68
92
  v-for="color of brushColors"
69
93
  :key="color"
70
94
  title="Set brush color"
71
- :class="brush.color === color ? 'active' : 'shallow'"
95
+ :class="brush.color === color && drawingMode !== 'eraseLine' ? 'active' : 'shallow'"
72
96
  @click="setBrushColor(color)"
73
97
  >
74
98
  <div
75
- class="w-6 h-6 transition-all transform border border-gray-400/50"
76
- :class="brush.color !== color ? 'rounded-1/2 scale-85' : 'rounded-md'"
99
+ class="w-6 h-6 transition-all transform border"
100
+ :class="brush.color !== color ? 'rounded-1/2 scale-85 border-white' : 'rounded-md border-gray-300/50'"
77
101
  :style="drawingEnabled ? { background: color } : { borderColor: color }"
78
102
  />
79
103
  </IconButton>
@@ -87,7 +111,7 @@ function setBrushColor(color: typeof brush.color) {
87
111
  <carbon:redo />
88
112
  </IconButton>
89
113
  <IconButton title="Delete" :class="{ disabled: !canClear }" @click="clearDrauu()">
90
- <carbon:delete />
114
+ <carbon:trash-can />
91
115
  </IconButton>
92
116
 
93
117
  <VerticalDivider />
@@ -106,3 +130,9 @@ function setBrushColor(color: typeof brush.color) {
106
130
  </IconButton>
107
131
  </Draggable>
108
132
  </template>
133
+
134
+ <style>
135
+ .v-popper--theme-menu .v-popper__arrow-inner {
136
+ --uno: border-main;
137
+ }
138
+ </style>
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import { inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'
2
+ import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
3
3
  import { drauu, drawingEnabled, loadCanvas } from '../logic/drawings'
4
- import { injectionSlideScale } from '../constants'
4
+ import { useSlideContext } from '../context'
5
5
 
6
- const scale = inject(injectionSlideScale)!
6
+ const scale = useSlideContext().$scale
7
7
  const svg = ref<SVGSVGElement>()
8
8
 
9
9
  onMounted(() => {
@@ -3,7 +3,7 @@ import { computed, ref, watch } from 'vue'
3
3
  import Fuse from 'fuse.js'
4
4
  import { go, rawRoutes } from '../logic/nav'
5
5
  import { activeElement, showGotoDialog } from '../state'
6
- import Titles from '/@slidev/titles.md'
6
+ import Titles from '#slidev/titles.md'
7
7
 
8
8
  const container = ref<HTMLDivElement>()
9
9
  const input = ref<HTMLInputElement>()
@@ -165,10 +165,11 @@ watch(activeElement, () => {
165
165
  </div>
166
166
  </template>
167
167
 
168
- <style scoped lang="postcss">
168
+ <style scoped>
169
169
  .autocomplete-list {
170
- @apply bg-main transform mt-1 overflow-auto;
171
- max-height: calc( 100vh - 100px );
170
+ --uno: bg-main mt-1;
171
+ overflow: auto;
172
+ max-height: calc(100vh - 100px);
172
173
  }
173
174
 
174
175
  .autocomplete {
@@ -1,12 +1,16 @@
1
1
  <script setup lang="ts">
2
2
  defineProps<{
3
3
  title: string
4
+ icon?: string
5
+ as?: string
4
6
  }>()
5
7
  </script>
6
8
 
7
9
  <template>
8
- <button class="slidev-icon-btn" :title="title" v-bind="$attrs">
10
+ <component :is="as || 'button'" class="slidev-icon-btn" :title="title" v-bind="$attrs">
9
11
  <span class="sr-only">{{ title }}</span>
10
- <slot />
11
- </button>
12
+ <slot>
13
+ <div :class="icon" />
14
+ </slot>
15
+ </component>
12
16
  </template>
@@ -10,7 +10,7 @@ const props = defineProps({
10
10
  },
11
11
  })
12
12
 
13
- const emit = defineEmits<{ (name: 'modelValue', v: boolean): void }>()
13
+ const emit = defineEmits(['update:modelValue'])
14
14
  const value = useVModel(props, 'modelValue', emit)
15
15
  const hasInfo = computed(() => typeof configs.info === 'string')
16
16
  </script>
@@ -10,7 +10,7 @@ const props = defineProps({
10
10
  },
11
11
  })
12
12
 
13
- const emit = defineEmits<{ (name: 'modelValue', v: boolean): void }>()
13
+ const emit = defineEmits(['update:modelValue'])
14
14
  const value = useVModel(props, 'modelValue', emit)
15
15
 
16
16
  function onClick() {
@@ -10,8 +10,7 @@ import MenuButton from './MenuButton.vue'
10
10
  import VerticalDivider from './VerticalDivider.vue'
11
11
  import IconButton from './IconButton.vue'
12
12
 
13
- // @ts-expect-error virtual module
14
- import CustomNavControls from '/@slidev/custom-nav-controls'
13
+ import CustomNavControls from '#slidev/custom-nav-controls'
15
14
 
16
15
  const props = defineProps({
17
16
  persist: {
@@ -34,7 +33,7 @@ function onMouseLeave() {
34
33
 
35
34
  const barStyle = computed(() => props.persist
36
35
  ? 'text-$slidev-controls-foreground bg-transparent'
37
- : 'rounded-md bg-main shadow dark:border dark:border-gray-400 dark:border-opacity-10')
36
+ : 'rounded-md bg-main shadow dark:border dark:border-main')
38
37
 
39
38
  const RecordingControls = shallowRef<any>()
40
39
  if (__SLIDEV_FEATURE_RECORD__)
@@ -115,13 +114,13 @@ if (__SLIDEV_FEATURE_DRAWINGS__)
115
114
  <IconButton
116
115
  v-if="__DEV__ && __SLIDEV_FEATURE_EDITOR__"
117
116
  :title="showEditor ? 'Hide editor' : 'Show editor'"
118
- class="<md:hidden"
117
+ class="lt-md:hidden"
119
118
  @click="showEditor = !showEditor"
120
119
  >
121
120
  <carbon:text-annotation-toggle />
122
121
  </IconButton>
123
122
 
124
- <IconButton v-if="isPresenter" title="Toggle Presenter Layout" @click="togglePresenterLayout">
123
+ <IconButton v-if="isPresenter" title="Toggle Presenter Layout" class="aspect-ratio-initial" @click="togglePresenterLayout">
125
124
  <carbon:template />
126
125
  {{ presenterLayout }}
127
126
  </IconButton>