@slidev/client 0.49.4 → 0.49.6
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.
- package/builtin/Arrow.vue +32 -15
- package/builtin/Monaco.vue +22 -1
- package/builtin/ShikiMagicMove.vue +21 -6
- package/builtin/VDrag.vue +2 -2
- package/builtin/VDragArrow.vue +36 -0
- package/composables/useDragElements.ts +41 -33
- package/env.ts +3 -1
- package/internals/DragControl.vue +36 -28
- package/internals/Goto.vue +23 -23
- package/internals/PrintSlideClick.vue +1 -3
- package/internals/QuickOverview.vue +2 -1
- package/internals/SlideWrapper.vue +7 -0
- package/internals/SlidesShow.vue +1 -3
- package/logic/slides.ts +2 -1
- package/modules/v-drag.ts +2 -2
- package/package.json +9 -9
- package/setup/monaco.ts +16 -5
- package/setup/routes.ts +1 -1
package/builtin/Arrow.vue
CHANGED
|
@@ -9,6 +9,8 @@ Simple Arrow
|
|
|
9
9
|
-->
|
|
10
10
|
|
|
11
11
|
<script setup lang="ts">
|
|
12
|
+
import { ref } from 'vue'
|
|
13
|
+
import { onClickOutside } from '@vueuse/core'
|
|
12
14
|
import { makeId } from '../logic/utils'
|
|
13
15
|
|
|
14
16
|
defineProps<{
|
|
@@ -18,38 +20,53 @@ defineProps<{
|
|
|
18
20
|
y2: number | string
|
|
19
21
|
width?: number | string
|
|
20
22
|
color?: string
|
|
23
|
+
twoWay?: boolean
|
|
21
24
|
}>()
|
|
22
25
|
|
|
26
|
+
const emit = defineEmits(['dblclick', 'clickOutside'])
|
|
27
|
+
|
|
23
28
|
const id = makeId()
|
|
29
|
+
|
|
30
|
+
const markerAttrs = {
|
|
31
|
+
markerUnits: 'strokeWidth',
|
|
32
|
+
markerHeight: 7,
|
|
33
|
+
refY: 3.5,
|
|
34
|
+
orient: 'auto',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const clickArea = ref<HTMLElement>()
|
|
38
|
+
onClickOutside(clickArea, () => emit('clickOutside'))
|
|
24
39
|
</script>
|
|
25
40
|
|
|
26
41
|
<template>
|
|
27
42
|
<svg
|
|
28
|
-
class="absolute left-0 top-0
|
|
43
|
+
class="absolute left-0 top-0"
|
|
29
44
|
:width="Math.max(+x1, +x2) + 50"
|
|
30
45
|
:height="Math.max(+y1, +y2) + 50"
|
|
31
46
|
>
|
|
32
47
|
<defs>
|
|
33
|
-
<marker
|
|
34
|
-
:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
refX="9"
|
|
39
|
-
refY="3.5"
|
|
40
|
-
orient="auto"
|
|
41
|
-
>
|
|
42
|
-
<polygon points="0 0, 10 3.5, 0 7" :fill="color || 'currentColor'" />
|
|
48
|
+
<marker :id="id" markerWidth="10" refX="9" v-bind="markerAttrs">
|
|
49
|
+
<polygon points="0 0, 10 3.5, 0 7" :fill="color || 'currentColor'" @dblclick="emit('dblclick')" />
|
|
50
|
+
</marker>
|
|
51
|
+
<marker v-if="twoWay" :id="`${id}-rev`" markerWidth="20" refX="11" v-bind="markerAttrs">
|
|
52
|
+
<polygon points="20 0, 10 3.5, 20 7" :fill="color || 'currentColor'" @dblclick="emit('dblclick')" />
|
|
43
53
|
</marker>
|
|
44
54
|
</defs>
|
|
45
55
|
<line
|
|
46
|
-
:x1
|
|
47
|
-
:y1="+y1"
|
|
48
|
-
:x2="+x2"
|
|
49
|
-
:y2="+y2"
|
|
56
|
+
:x1 :y1 :x2 :y2
|
|
50
57
|
:stroke="color || 'currentColor'"
|
|
51
58
|
:stroke-width="width || 2"
|
|
52
59
|
:marker-end="`url(#${id})`"
|
|
60
|
+
:marker-start="twoWay ? `url(#${id}-rev)` : 'none'"
|
|
61
|
+
@dblclick="emit('dblclick')"
|
|
62
|
+
/>
|
|
63
|
+
<line
|
|
64
|
+
ref="clickArea"
|
|
65
|
+
:x1 :y1 :x2 :y2
|
|
66
|
+
stroke="transparent"
|
|
67
|
+
stroke-linecap="round"
|
|
68
|
+
:stroke-width="20"
|
|
69
|
+
@dblclick="emit('dblclick')"
|
|
53
70
|
/>
|
|
54
71
|
</svg>
|
|
55
72
|
</template>
|
package/builtin/Monaco.vue
CHANGED
|
@@ -33,6 +33,7 @@ const props = withDefaults(defineProps<{
|
|
|
33
33
|
editorOptions?: monaco.editor.IEditorOptions
|
|
34
34
|
ata?: boolean
|
|
35
35
|
runnable?: boolean
|
|
36
|
+
writable?: string
|
|
36
37
|
autorun?: boolean | 'once'
|
|
37
38
|
showOutputAt?: RawAtValue
|
|
38
39
|
outputHeight?: string
|
|
@@ -52,6 +53,7 @@ const props = withDefaults(defineProps<{
|
|
|
52
53
|
|
|
53
54
|
const code = ref(lz.decompressFromBase64(props.codeLz).trimEnd())
|
|
54
55
|
const diff = props.diffLz && ref(lz.decompressFromBase64(props.diffLz).trimEnd())
|
|
56
|
+
const isWritable = computed(() => props.writable && !props.readonly && __DEV__)
|
|
55
57
|
|
|
56
58
|
const langMap: Record<string, string> = {
|
|
57
59
|
ts: 'typescript',
|
|
@@ -95,7 +97,7 @@ const stopWatchTypesLoading = whenever(
|
|
|
95
97
|
onMounted(async () => {
|
|
96
98
|
// Lazy load monaco, so it will be bundled in async chunk
|
|
97
99
|
const { default: setup } = await import('../setup/monaco')
|
|
98
|
-
const { ata, monaco } = await setup()
|
|
100
|
+
const { ata, monaco, editorOptions } = await setup()
|
|
99
101
|
const model = monaco.editor.createModel(code.value, lang, monaco.Uri.parse(`file:///${makeId()}.${ext}`))
|
|
100
102
|
model.onDidChangeContent(() => code.value = model.getValue())
|
|
101
103
|
const commonOptions = {
|
|
@@ -112,6 +114,7 @@ onMounted(async () => {
|
|
|
112
114
|
fontSize: 11.5,
|
|
113
115
|
fontFamily: 'var(--slidev-code-font-family)',
|
|
114
116
|
scrollBeyondLastLine: false,
|
|
117
|
+
...editorOptions,
|
|
115
118
|
...props.editorOptions,
|
|
116
119
|
} satisfies monaco.editor.IStandaloneEditorConstructionOptions & monaco.editor.IDiffEditorConstructionOptions
|
|
117
120
|
|
|
@@ -151,6 +154,7 @@ onMounted(async () => {
|
|
|
151
154
|
contentHeight.value = newHeight
|
|
152
155
|
nextTick(() => editableEditor.layout())
|
|
153
156
|
})
|
|
157
|
+
|
|
154
158
|
editableEditor = editor
|
|
155
159
|
}
|
|
156
160
|
loadTypes.value = () => {
|
|
@@ -173,6 +177,23 @@ onMounted(async () => {
|
|
|
173
177
|
: /* BELOW */ `` // reset
|
|
174
178
|
}
|
|
175
179
|
}
|
|
180
|
+
|
|
181
|
+
editableEditor.addAction({
|
|
182
|
+
id: 'slidev-save',
|
|
183
|
+
label: 'Save',
|
|
184
|
+
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS],
|
|
185
|
+
run: () => {
|
|
186
|
+
if (!isWritable.value || !import.meta.hot?.send) {
|
|
187
|
+
console.warn('[Slidev] this monaco editor is not writable, save action is ignored.')
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
import.meta.hot.send('slidev:monaco-write', {
|
|
191
|
+
file: props.writable!,
|
|
192
|
+
content: editableEditor.getValue(),
|
|
193
|
+
})
|
|
194
|
+
},
|
|
195
|
+
})
|
|
196
|
+
|
|
176
197
|
nextTick(() => monaco.editor.remeasureFonts())
|
|
177
198
|
})
|
|
178
199
|
</script>
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
|
|
3
3
|
import type { KeyedTokensInfo } from 'shiki-magic-move/types'
|
|
4
|
+
import type { PropType } from 'vue'
|
|
4
5
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
5
6
|
import lz from 'lz-string'
|
|
6
7
|
import { useSlideContext } from '../context'
|
|
7
8
|
import { makeId, updateCodeHighlightRange } from '../logic/utils'
|
|
8
9
|
import { useNav } from '../composables/useNav'
|
|
9
10
|
import { CLICKS_MAX } from '../constants'
|
|
11
|
+
import { configs } from '../env'
|
|
10
12
|
|
|
11
|
-
const props = defineProps
|
|
12
|
-
at
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
at: {
|
|
15
|
+
type: [String, Number],
|
|
16
|
+
default: '+1',
|
|
17
|
+
},
|
|
18
|
+
stepsLz: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
stepRanges: {
|
|
23
|
+
type: Array as PropType<string[][]>,
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
lines: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: configs.lineNumbers,
|
|
29
|
+
},
|
|
30
|
+
})
|
|
16
31
|
|
|
17
32
|
const steps = JSON.parse(lz.decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
|
|
18
33
|
const { $clicksContext: clicks, $scale: scale, $zoom: zoom } = useSlideContext()
|
|
@@ -37,7 +52,7 @@ onMounted(() => {
|
|
|
37
52
|
throw new Error('[slidev] The length of stepRanges does not match the length of steps, this is an internal error.')
|
|
38
53
|
|
|
39
54
|
const clickCounts = ranges.value.map(s => s.length).reduce((a, b) => a + b, 0)
|
|
40
|
-
const clickInfo = clicks.calculateSince(props.at
|
|
55
|
+
const clickInfo = clicks.calculateSince(props.at, clickCounts - 1)
|
|
41
56
|
clicks.register(id, clickInfo)
|
|
42
57
|
|
|
43
58
|
watch(
|
package/builtin/VDrag.vue
CHANGED
|
@@ -8,7 +8,7 @@ const props = defineProps<{
|
|
|
8
8
|
markdownSource?: DragElementMarkdownSource
|
|
9
9
|
}>()
|
|
10
10
|
|
|
11
|
-
const {
|
|
11
|
+
const { dragId, container, containerStyle, mounted, unmounted, startDragging } = useDragElement(null, props.pos, props.markdownSource)
|
|
12
12
|
|
|
13
13
|
onMounted(mounted)
|
|
14
14
|
onUnmounted(unmounted)
|
|
@@ -17,7 +17,7 @@ onUnmounted(unmounted)
|
|
|
17
17
|
<template>
|
|
18
18
|
<div
|
|
19
19
|
ref="container"
|
|
20
|
-
:data-drag-id="
|
|
20
|
+
:data-drag-id="dragId"
|
|
21
21
|
:style="containerStyle"
|
|
22
22
|
class="p-1"
|
|
23
23
|
@dblclick="startDragging"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onMounted, onUnmounted } from 'vue'
|
|
3
|
+
import type { DragElementMarkdownSource } from '../composables/useDragElements'
|
|
4
|
+
import { useDragElement } from '../composables/useDragElements'
|
|
5
|
+
import Arrow from './Arrow.vue'
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
pos?: string
|
|
9
|
+
markdownSource?: DragElementMarkdownSource
|
|
10
|
+
width?: number | string
|
|
11
|
+
color?: string
|
|
12
|
+
twoWay?: boolean
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const { dragId, mounted, unmounted, startDragging, stopDragging, x0, y0, width, height } = useDragElement(null, props.pos ?? '100,100,300,300', props.markdownSource, true)
|
|
16
|
+
|
|
17
|
+
onMounted(mounted)
|
|
18
|
+
onUnmounted(unmounted)
|
|
19
|
+
|
|
20
|
+
const x1 = computed(() => x0.value - width.value / 2)
|
|
21
|
+
const y1 = computed(() => y0.value - height.value / 2)
|
|
22
|
+
const x2 = computed(() => x0.value + width.value / 2)
|
|
23
|
+
const y2 = computed(() => y0.value + height.value / 2)
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<Arrow
|
|
28
|
+
:x1 :y1 :x2 :y2
|
|
29
|
+
:data-drag-id="dragId"
|
|
30
|
+
:width="props.width"
|
|
31
|
+
:color="props.color"
|
|
32
|
+
:two-way="props.twoWay"
|
|
33
|
+
@dblclick="startDragging"
|
|
34
|
+
@click-outside="stopDragging"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
@@ -68,7 +68,8 @@ export function useDragElementsUpdater(no: number) {
|
|
|
68
68
|
let replaced = false
|
|
69
69
|
|
|
70
70
|
section = type === 'prop'
|
|
71
|
-
|
|
71
|
+
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
72
|
+
? section.replace(/<(v-?drag-?\w*)(.*?)>/gi, (full, tag, attrs, index) => {
|
|
72
73
|
if (index === idx) {
|
|
73
74
|
replaced = true
|
|
74
75
|
const posMatch = attrs.match(/pos=".*?"/)
|
|
@@ -112,7 +113,7 @@ export function useDragElementsUpdater(no: number) {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
export function useDragElement(directive: DirectiveBinding | null, posRaw?: string | number | number[], markdownSource?: DragElementMarkdownSource) {
|
|
116
|
+
export function useDragElement(directive: DirectiveBinding | null, posRaw?: string | number | number[], markdownSource?: DragElementMarkdownSource, isArrow?: boolean) {
|
|
116
117
|
function inject<T>(key: InjectionKey<T> | string): T | undefined {
|
|
117
118
|
return directive
|
|
118
119
|
? directiveInject(directive, key)
|
|
@@ -129,7 +130,7 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
129
130
|
const enabled = ['slide', 'presenter'].includes(renderContext.value)
|
|
130
131
|
|
|
131
132
|
let dataSource: DragElementDataSource = directive ? 'directive' : 'prop'
|
|
132
|
-
let
|
|
133
|
+
let dragId: string = makeId()
|
|
133
134
|
let pos: number[] | undefined
|
|
134
135
|
if (Array.isArray(posRaw)) {
|
|
135
136
|
pos = posRaw
|
|
@@ -139,8 +140,8 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
139
140
|
}
|
|
140
141
|
else if (posRaw != null) {
|
|
141
142
|
dataSource = 'frontmatter'
|
|
142
|
-
|
|
143
|
-
posRaw = frontmatter?.dragPos?.[
|
|
143
|
+
dragId = `${posRaw}`
|
|
144
|
+
posRaw = frontmatter?.dragPos?.[dragId]
|
|
144
145
|
pos = (posRaw as string)?.split(',').map(Number)
|
|
145
146
|
}
|
|
146
147
|
|
|
@@ -149,12 +150,12 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
149
150
|
|
|
150
151
|
const watchStopHandles: WatchStopHandle[] = [stopWatchBounds]
|
|
151
152
|
|
|
152
|
-
const autoHeight = posRaw != null && !Number.isFinite(pos?.[3])
|
|
153
|
+
const autoHeight = !isArrow && posRaw != null && !Number.isFinite(pos?.[3])
|
|
153
154
|
pos ??= [Number.NaN, Number.NaN, 0]
|
|
154
155
|
const width = ref(pos[2])
|
|
155
156
|
const x0 = ref(pos[0] + pos[2] / 2)
|
|
156
157
|
|
|
157
|
-
const rotate = ref(pos[4] ?? 0)
|
|
158
|
+
const rotate = ref(isArrow ? 0 : (pos[4] ?? 0))
|
|
158
159
|
const rotateRad = computed(() => rotate.value * Math.PI / 180)
|
|
159
160
|
const rotateSin = computed(() => Math.sin(rotateRad.value))
|
|
160
161
|
const rotateCos = computed(() => Math.cos(rotateRad.value))
|
|
@@ -163,7 +164,9 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
163
164
|
const bounds = ref({ left: 0, top: 0, width: 0, height: 0 })
|
|
164
165
|
const actualHeight = ref(0)
|
|
165
166
|
function updateBounds() {
|
|
166
|
-
|
|
167
|
+
if (!container.value)
|
|
168
|
+
return
|
|
169
|
+
const rect = container.value.getBoundingClientRect()
|
|
167
170
|
bounds.value = {
|
|
168
171
|
left: rect.left / zoom.value,
|
|
169
172
|
top: rect.top / zoom.value,
|
|
@@ -175,32 +178,36 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
175
178
|
watchStopHandles.push(watch(width, updateBounds, { flush: 'post' }))
|
|
176
179
|
|
|
177
180
|
const configuredHeight = ref(pos[3] ?? 0)
|
|
178
|
-
const height =
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
181
|
+
const height = autoHeight
|
|
182
|
+
? computed({
|
|
183
|
+
get: () => (autoHeight ? actualHeight.value : configuredHeight.value) || 0,
|
|
184
|
+
set: v => !autoHeight && (configuredHeight.value = v),
|
|
185
|
+
})
|
|
186
|
+
: configuredHeight
|
|
187
|
+
const configuredY0 = autoHeight ? ref(pos[1]) : ref(pos[1] + pos[3] / 2)
|
|
188
|
+
const y0 = autoHeight
|
|
189
|
+
? computed({
|
|
190
|
+
get: () => configuredY0.value + height.value / 2,
|
|
191
|
+
set: v => configuredY0.value = v - height.value / 2,
|
|
192
|
+
})
|
|
193
|
+
: configuredY0
|
|
194
|
+
|
|
195
|
+
const containerStyle = computed(() => {
|
|
189
196
|
return Number.isFinite(x0.value)
|
|
190
197
|
? {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
position: 'absolute',
|
|
199
|
+
zIndex: 100,
|
|
200
|
+
left: `${x0.value - width.value / 2}px`,
|
|
201
|
+
top: `${y0.value - height.value / 2}px`,
|
|
202
|
+
width: `${width.value}px`,
|
|
203
|
+
height: autoHeight ? undefined : `${height.value}px`,
|
|
204
|
+
transformOrigin: 'center center',
|
|
205
|
+
transform: `rotate(${rotate.value}deg)`,
|
|
206
|
+
} satisfies CSSProperties
|
|
200
207
|
: {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
position: 'absolute',
|
|
209
|
+
zIndex: 100,
|
|
210
|
+
} satisfies CSSProperties
|
|
204
211
|
})
|
|
205
212
|
|
|
206
213
|
watchStopHandles.push(
|
|
@@ -218,15 +225,16 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
218
225
|
if (dataSource === 'directive')
|
|
219
226
|
posStr = `[${posStr}]`
|
|
220
227
|
|
|
221
|
-
updater.value(
|
|
228
|
+
updater.value(dragId, posStr, dataSource, markdownSource)
|
|
222
229
|
},
|
|
223
230
|
),
|
|
224
231
|
)
|
|
225
232
|
|
|
226
233
|
const state = {
|
|
227
|
-
|
|
234
|
+
dragId,
|
|
228
235
|
dataSource,
|
|
229
236
|
markdownSource,
|
|
237
|
+
isArrow,
|
|
230
238
|
zoom,
|
|
231
239
|
autoHeight,
|
|
232
240
|
x0,
|
package/env.ts
CHANGED
|
@@ -17,4 +17,6 @@ export const themeVars = computed(() => {
|
|
|
17
17
|
return objectMap(configs.themeConfig || {}, (k, v) => [`--slidev-theme-${k}`, v])
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
export const slidesTitle = configs.
|
|
20
|
+
export const slidesTitle = configs.slidesTitle
|
|
21
|
+
|
|
22
|
+
export const pathPrefix = import.meta.env.BASE_URL + (__SLIDEV_HASH_ROUTE__ ? '#/' : '')
|
|
@@ -10,14 +10,14 @@ import { slideHeight, slideWidth } from '../env'
|
|
|
10
10
|
import { magicKeys } from '../state'
|
|
11
11
|
|
|
12
12
|
const { data } = defineProps<{ data: DragElementState }>()
|
|
13
|
-
const {
|
|
13
|
+
const { dragId, zoom, autoHeight, x0, y0, width, height, rotate, isArrow } = data
|
|
14
14
|
|
|
15
15
|
const slideScale = inject(injectionSlideScale, ref(1))
|
|
16
16
|
const scale = computed(() => slideScale.value * zoom.value)
|
|
17
17
|
const { left: slideLeft, top: slideTop } = useSlideBounds()
|
|
18
18
|
|
|
19
19
|
const ctrlSize = 10
|
|
20
|
-
const minSize = 40
|
|
20
|
+
const minSize = isArrow ? Number.NEGATIVE_INFINITY : 40
|
|
21
21
|
const minRemain = 10
|
|
22
22
|
|
|
23
23
|
const rotateRad = computed(() => rotate.value * Math.PI / 180)
|
|
@@ -32,6 +32,9 @@ const boundingTop = computed(() => y0.value - boundingHeight.value / 2)
|
|
|
32
32
|
const boundingRight = computed(() => x0.value + boundingWidth.value / 2)
|
|
33
33
|
const boundingBottom = computed(() => y0.value + boundingHeight.value / 2)
|
|
34
34
|
|
|
35
|
+
const arrowRevX = computed(() => isArrow && width.value < 0)
|
|
36
|
+
const arrowRevY = computed(() => isArrow && height.value < 0)
|
|
37
|
+
|
|
35
38
|
let currentDrag: {
|
|
36
39
|
x0: number
|
|
37
40
|
y0: number
|
|
@@ -206,11 +209,12 @@ function getCornerProps(isLeft: boolean, isTop: boolean) {
|
|
|
206
209
|
width: `${ctrlSize}px`,
|
|
207
210
|
height: `${ctrlSize}px`,
|
|
208
211
|
margin: `-${ctrlSize / 2}px`,
|
|
209
|
-
left: isLeft ? '0' : undefined,
|
|
210
|
-
right: isLeft ? undefined : '0',
|
|
211
|
-
top: isTop ? '0' : undefined,
|
|
212
|
-
bottom: isTop ? undefined : '0',
|
|
213
|
-
cursor: +isLeft + +isTop === 1 ? 'nesw-resize' : 'nwse-resize',
|
|
212
|
+
left: isLeft !== arrowRevX.value ? '0' : undefined,
|
|
213
|
+
right: isLeft !== arrowRevX.value ? undefined : '0',
|
|
214
|
+
top: isTop !== arrowRevY.value ? '0' : undefined,
|
|
215
|
+
bottom: isTop !== arrowRevY.value ? undefined : '0',
|
|
216
|
+
cursor: isArrow ? 'move' : +isLeft + +isTop === 1 ? 'nesw-resize' : 'nwse-resize',
|
|
217
|
+
borderRadius: isArrow ? '50%' : undefined,
|
|
214
218
|
},
|
|
215
219
|
class: ctrlClasses,
|
|
216
220
|
}
|
|
@@ -356,14 +360,14 @@ watchEffect(() => {
|
|
|
356
360
|
<div
|
|
357
361
|
v-if="Number.isFinite(x0)"
|
|
358
362
|
id="drag-control-container"
|
|
359
|
-
:data-drag-id="
|
|
363
|
+
:data-drag-id="dragId"
|
|
360
364
|
:style="{
|
|
361
365
|
position: 'absolute',
|
|
362
366
|
zIndex: 100,
|
|
363
|
-
left: `${zoom * (x0 - width / 2)}px`,
|
|
364
|
-
top: `${zoom * (y0 - height / 2)}px`,
|
|
365
|
-
width: `${zoom * width}px`,
|
|
366
|
-
height: `${zoom * height}px`,
|
|
367
|
+
left: `${zoom * (x0 - Math.abs(width) / 2)}px`,
|
|
368
|
+
top: `${zoom * (y0 - Math.abs(height) / 2)}px`,
|
|
369
|
+
width: `${zoom * Math.abs(width)}px`,
|
|
370
|
+
height: `${zoom * Math.abs(height)}px`,
|
|
367
371
|
transformOrigin: 'center center',
|
|
368
372
|
transform: `rotate(${rotate}deg)`,
|
|
369
373
|
}"
|
|
@@ -371,27 +375,31 @@ watchEffect(() => {
|
|
|
371
375
|
@pointermove="onPointermove"
|
|
372
376
|
@pointerup="onPointerup"
|
|
373
377
|
>
|
|
374
|
-
<div class="absolute inset-0 z-100
|
|
378
|
+
<div class="absolute inset-0 z-100 dark:b-gray-400" :class="isArrow ? '' : 'b b-dark'">
|
|
375
379
|
<template v-if="!autoHeight">
|
|
376
380
|
<div v-bind="getCornerProps(true, true)" />
|
|
377
|
-
<div v-bind="getCornerProps(true, false)" />
|
|
378
|
-
<div v-bind="getCornerProps(false, true)" />
|
|
379
381
|
<div v-bind="getCornerProps(false, false)" />
|
|
382
|
+
<template v-if="!isArrow">
|
|
383
|
+
<div v-bind="getCornerProps(true, false)" />
|
|
384
|
+
<div v-bind="getCornerProps(false, true)" />
|
|
385
|
+
</template>
|
|
380
386
|
</template>
|
|
381
|
-
<
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
<
|
|
385
|
-
|
|
387
|
+
<template v-if="!isArrow">
|
|
388
|
+
<div v-bind="getBorderProps('l')" />
|
|
389
|
+
<div v-bind="getBorderProps('r')" />
|
|
390
|
+
<template v-if="!autoHeight">
|
|
391
|
+
<div v-bind="getBorderProps('t')" />
|
|
392
|
+
<div v-bind="getBorderProps('b')" />
|
|
393
|
+
</template>
|
|
394
|
+
<div v-bind="getRotateProps()" />
|
|
395
|
+
<div
|
|
396
|
+
class="absolute -top-15px w-0 b b-dashed b-dark dark:b-gray-400"
|
|
397
|
+
:style="{
|
|
398
|
+
left: 'calc(50% - 1px)',
|
|
399
|
+
height: autoHeight ? '14px' : '10px',
|
|
400
|
+
}"
|
|
401
|
+
/>
|
|
386
402
|
</template>
|
|
387
|
-
<div v-bind="getRotateProps()" />
|
|
388
|
-
<div
|
|
389
|
-
class="absolute -top-15px w-0 b b-dashed b-dark dark:b-gray-400"
|
|
390
|
-
:style="{
|
|
391
|
-
left: 'calc(50% - 1px)',
|
|
392
|
-
height: autoHeight ? '14px' : '10px',
|
|
393
|
-
}"
|
|
394
|
-
/>
|
|
395
403
|
</div>
|
|
396
404
|
</div>
|
|
397
405
|
</template>
|
package/internals/Goto.vue
CHANGED
|
@@ -135,35 +135,35 @@ watch(activeElement, () => {
|
|
|
135
135
|
@input="updateText"
|
|
136
136
|
>
|
|
137
137
|
</div>
|
|
138
|
-
<
|
|
138
|
+
<div
|
|
139
139
|
v-if="result.length > 0"
|
|
140
140
|
ref="list"
|
|
141
141
|
class="autocomplete-list"
|
|
142
142
|
shadow="~"
|
|
143
143
|
border="~ transparent rounded dark:main"
|
|
144
144
|
>
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
</
|
|
166
|
-
</
|
|
145
|
+
<ul table w-full border-collapse>
|
|
146
|
+
<li
|
|
147
|
+
v-for="(item, index) of result"
|
|
148
|
+
ref="items"
|
|
149
|
+
:key="item.id"
|
|
150
|
+
role="button"
|
|
151
|
+
tabindex="0"
|
|
152
|
+
cursor-pointer
|
|
153
|
+
hover="op100"
|
|
154
|
+
table-row
|
|
155
|
+
items-center
|
|
156
|
+
:border="index === 0 ? undefined : 't main'"
|
|
157
|
+
:class="selectedIndex === index ? 'bg-active op100' : 'op80'"
|
|
158
|
+
@click.stop.prevent="select(item.no)"
|
|
159
|
+
>
|
|
160
|
+
<div text-right op50 text-sm table-cell py-2 pl-4 pr-3 vertical-middle>
|
|
161
|
+
{{ item.no }}
|
|
162
|
+
</div>
|
|
163
|
+
<TitleRenderer table-cell py-2 pr-4 w-full :no="item.no" />
|
|
164
|
+
</li>
|
|
165
|
+
</ul>
|
|
166
|
+
</div>
|
|
167
167
|
</div>
|
|
168
168
|
</template>
|
|
169
169
|
|
|
@@ -6,9 +6,7 @@ import { configs, slideHeight, slideWidth } from '../env'
|
|
|
6
6
|
import { getSlideClass } from '../utils'
|
|
7
7
|
import type { SlidevContextNav } from '../composables/useNav'
|
|
8
8
|
import SlideWrapper from './SlideWrapper.vue'
|
|
9
|
-
|
|
10
|
-
import GlobalTop from '#slidev/global-components/top'
|
|
11
|
-
import GlobalBottom from '#slidev/global-components/bottom'
|
|
9
|
+
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
12
10
|
|
|
13
11
|
const { nav } = defineProps<{
|
|
14
12
|
nav: SlidevContextNav
|
|
@@ -6,6 +6,7 @@ import { currentOverviewPage, overviewRowCount } from '../logic/overview'
|
|
|
6
6
|
import { createFixedClicks } from '../composables/useClicks'
|
|
7
7
|
import { CLICKS_MAX } from '../constants'
|
|
8
8
|
import { useNav } from '../composables/useNav'
|
|
9
|
+
import { pathPrefix } from '../env'
|
|
9
10
|
import SlideContainer from './SlideContainer.vue'
|
|
10
11
|
import SlideWrapper from './SlideWrapper.vue'
|
|
11
12
|
import DrawingPreview from './DrawingPreview.vue'
|
|
@@ -169,7 +170,7 @@ setTimeout(() => {
|
|
|
169
170
|
as="a"
|
|
170
171
|
title="Slides Overview"
|
|
171
172
|
target="_blank"
|
|
172
|
-
href="
|
|
173
|
+
:href="`${pathPrefix}overview`"
|
|
173
174
|
tab-index="-1"
|
|
174
175
|
class="text-2xl"
|
|
175
176
|
>
|
|
@@ -7,6 +7,7 @@ import { injectionClicksContext, injectionCurrentPage, injectionRenderContext, i
|
|
|
7
7
|
import { getSlideClass } from '../utils'
|
|
8
8
|
import { configs } from '../env'
|
|
9
9
|
import SlideLoading from './SlideLoading.vue'
|
|
10
|
+
import { SlideBottom, SlideTop } from '#slidev/global-layers'
|
|
10
11
|
|
|
11
12
|
const props = defineProps({
|
|
12
13
|
clicksContext: {
|
|
@@ -67,7 +68,13 @@ const SlideComponent = computed(() => props.route && defineAsyncComponent({
|
|
|
67
68
|
:class="getSlideClass(route, ['slide', 'presenter'].includes(props.renderContext) ? '' : 'disable-view-transition')"
|
|
68
69
|
:style="style"
|
|
69
70
|
>
|
|
71
|
+
<div v-if="SlideBottom" class="absolute inset-0">
|
|
72
|
+
<SlideBottom />
|
|
73
|
+
</div>
|
|
70
74
|
<SlideComponent />
|
|
75
|
+
<div v-if="SlideTop" class="absolute inset-0">
|
|
76
|
+
<SlideTop />
|
|
77
|
+
</div>
|
|
71
78
|
</div>
|
|
72
79
|
</template>
|
|
73
80
|
|
package/internals/SlidesShow.vue
CHANGED
|
@@ -9,9 +9,7 @@ import { activeDragElement } from '../state'
|
|
|
9
9
|
import { CLICKS_MAX } from '../constants'
|
|
10
10
|
import SlideWrapper from './SlideWrapper.vue'
|
|
11
11
|
import DragControl from './DragControl.vue'
|
|
12
|
-
|
|
13
|
-
import GlobalTop from '#slidev/global-components/top'
|
|
14
|
-
import GlobalBottom from '#slidev/global-components/bottom'
|
|
12
|
+
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
15
13
|
|
|
16
14
|
defineProps<{
|
|
17
15
|
renderContext: 'slide' | 'presenter'
|
package/logic/slides.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SlideRoute } from '@slidev/types'
|
|
2
|
+
import { pathPrefix } from '../env'
|
|
2
3
|
import { slides } from '#slidev/slides'
|
|
3
4
|
|
|
4
5
|
export { slides }
|
|
@@ -16,5 +17,5 @@ export function getSlidePath(
|
|
|
16
17
|
if (typeof route === 'number' || typeof route === 'string')
|
|
17
18
|
route = getSlide(route)!
|
|
18
19
|
const no = route.meta.slide?.frontmatter.routeAlias ?? route.no
|
|
19
|
-
return presenter ?
|
|
20
|
+
return presenter ? `${pathPrefix}presenter/${no}` : `${pathPrefix}${no}`
|
|
20
21
|
}
|
package/modules/v-drag.ts
CHANGED
|
@@ -18,12 +18,12 @@ export function createVDragDirective() {
|
|
|
18
18
|
}
|
|
19
19
|
state.container.value = el
|
|
20
20
|
el.draggingState = state
|
|
21
|
-
el.dataset.dragId = state.
|
|
21
|
+
el.dataset.dragId = state.dragId
|
|
22
22
|
state.watchStopHandles.push(
|
|
23
23
|
watch(state.containerStyle, (style) => {
|
|
24
24
|
for (const [k, v] of Object.entries(style)) {
|
|
25
25
|
if (v)
|
|
26
|
-
el.style[k as any] = v
|
|
26
|
+
el.style[k as any] = v as any
|
|
27
27
|
}
|
|
28
28
|
}, { immediate: true }),
|
|
29
29
|
)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.49.
|
|
4
|
+
"version": "0.49.6",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"@iconify-json/carbon": "^1.1.34",
|
|
33
33
|
"@iconify-json/ph": "^1.1.13",
|
|
34
34
|
"@iconify-json/svg-spinners": "^1.1.2",
|
|
35
|
-
"@shikijs/monaco": "^1.6.
|
|
36
|
-
"@shikijs/vitepress-twoslash": "^1.6.
|
|
35
|
+
"@shikijs/monaco": "^1.6.1",
|
|
36
|
+
"@shikijs/vitepress-twoslash": "^1.6.1",
|
|
37
37
|
"@slidev/rough-notation": "^0.1.0",
|
|
38
38
|
"@typescript/ata": "^0.9.4",
|
|
39
39
|
"@unhead/vue": "^1.9.11",
|
|
40
40
|
"@unocss/reset": "^0.60.3",
|
|
41
|
-
"@vueuse/core": "^10.
|
|
42
|
-
"@vueuse/math": "^10.
|
|
41
|
+
"@vueuse/core": "^10.10.0",
|
|
42
|
+
"@vueuse/math": "^10.10.0",
|
|
43
43
|
"@vueuse/motion": "^2.1.0",
|
|
44
44
|
"codemirror": "^5.65.16",
|
|
45
45
|
"drauu": "^0.4.0",
|
|
@@ -52,17 +52,17 @@
|
|
|
52
52
|
"monaco-editor": "^0.49.0",
|
|
53
53
|
"prettier": "^3.2.5",
|
|
54
54
|
"recordrtc": "^5.6.2",
|
|
55
|
-
"shiki": "^1.6.
|
|
55
|
+
"shiki": "^1.6.1",
|
|
56
56
|
"shiki-magic-move": "^0.4.2",
|
|
57
57
|
"typescript": "^5.4.5",
|
|
58
58
|
"unocss": "^0.60.3",
|
|
59
59
|
"vue": "^3.4.27",
|
|
60
60
|
"vue-router": "^4.3.2",
|
|
61
61
|
"yaml": "^2.4.2",
|
|
62
|
-
"@slidev/
|
|
63
|
-
"@slidev/
|
|
62
|
+
"@slidev/parser": "0.49.6",
|
|
63
|
+
"@slidev/types": "0.49.6"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"vite": "^5.2.
|
|
66
|
+
"vite": "^5.2.12"
|
|
67
67
|
}
|
|
68
68
|
}
|
package/setup/monaco.ts
CHANGED
|
@@ -95,10 +95,10 @@ const setup = createSingletonPromise(async () => {
|
|
|
95
95
|
const { shiki, themes, shikiToMonaco } = await import('#slidev/shiki')
|
|
96
96
|
const highlighter = await shiki
|
|
97
97
|
|
|
98
|
-
const
|
|
98
|
+
const editorOptions: MonacoSetupReturn['editorOptions'] & object = {}
|
|
99
99
|
for (const setup of setups) {
|
|
100
100
|
const result = await setup(monaco)
|
|
101
|
-
Object.assign(
|
|
101
|
+
Object.assign(editorOptions, result?.editorOptions)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// Use Shiki to highlight Monaco
|
|
@@ -117,14 +117,25 @@ const setup = createSingletonPromise(async () => {
|
|
|
117
117
|
return {
|
|
118
118
|
monaco,
|
|
119
119
|
ata,
|
|
120
|
-
|
|
120
|
+
editorOptions,
|
|
121
121
|
}
|
|
122
122
|
})
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
async function _addFile(raw: Promise<{ default: string }>, path: string) {
|
|
125
|
+
const uri = monaco.Uri.file(path)
|
|
125
126
|
const code = (await raw).default
|
|
126
127
|
monaco.languages.typescript.typescriptDefaults.addExtraLib(code, `file:///${path}`)
|
|
127
|
-
monaco.editor.createModel(code, 'javascript',
|
|
128
|
+
monaco.editor.createModel(code, 'javascript', uri)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const addFileCache = new Map<string, Promise<void>>()
|
|
132
|
+
|
|
133
|
+
export async function addFile(raw: Promise<{ default: string }>, path: string) {
|
|
134
|
+
if (addFileCache.has(path))
|
|
135
|
+
return addFileCache.get(path)
|
|
136
|
+
const promise = _addFile(raw, path)
|
|
137
|
+
addFileCache.set(path, promise)
|
|
138
|
+
return promise
|
|
128
139
|
}
|
|
129
140
|
|
|
130
141
|
export default setup
|