@slidev/client 0.38.8 → 0.39.0

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/Tweet.vue CHANGED
@@ -58,7 +58,7 @@ else {
58
58
 
59
59
  <template>
60
60
  <Transform :scale="scale || 1">
61
- <div ref="tweet" class="tweet">
61
+ <div ref="tweet" class="tweet slidev-tweet">
62
62
  <div v-if="!loaded || tweetNotFound" class="w-30 h-30 my-10px bg-gray-400 bg-opacity-10 rounded-lg flex opacity-50">
63
63
  <div class="m-auto animate-pulse text-4xl">
64
64
  <carbon:logo-twitter />
@@ -68,3 +68,10 @@ else {
68
68
  </div>
69
69
  </Transform>
70
70
  </template>
71
+
72
+ <style>
73
+ .slidev-tweet iframe {
74
+ border-radius: 12px;
75
+ overflow: hidden;
76
+ }
77
+ </style>
@@ -101,8 +101,8 @@ async function start() {
101
101
 
102
102
  update = () => {
103
103
  monaco.editor.setTheme(props.dark
104
- ? theme.dark || 'vitesse-dark'
105
- : theme.light || 'vitesse-light',
104
+ ? (theme.dark || 'vitesse-dark')
105
+ : (theme.light || 'vitesse-light'),
106
106
  )
107
107
  styleObject.innerHTML = `:root { ${props.style} }`
108
108
 
@@ -1,8 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, shallowRef, watch } from 'vue'
3
- import { clicks, currentRoute, isPresenter, nextRoute, rawRoutes } from '../logic/nav'
2
+ import { TransitionGroup, computed, shallowRef, watch } from 'vue'
3
+ import { clicks, currentRoute, isPresenter, nextRoute, rawRoutes, transition } from '../logic/nav'
4
4
  import { getSlideClass } from '../utils'
5
- import { configs } from '../env'
6
5
  import SlideWrapper from './SlideWrapper'
7
6
  // @ts-expect-error virtual module
8
7
  import GlobalTop from '/@slidev/global-components/top'
@@ -24,17 +23,7 @@ const DrawingLayer = shallowRef<any>()
24
23
  if (__SLIDEV_FEATURE_DRAWINGS__ || __SLIDEV_FEATURE_DRAWINGS_PERSIST__)
25
24
  import('./DrawingLayer.vue').then(v => DrawingLayer.value = v.default)
26
25
 
27
- const routes = computed(() => rawRoutes.filter(r => r.meta?.__preloaded || r === currentRoute.value))
28
-
29
- const isLeaving = ref(false)
30
- function onBeforeLeave() {
31
- if (configs.pageTransition?.crossfade === false)
32
- isLeaving.value = true
33
- }
34
- function onAfterLeave() {
35
- if (configs.pageTransition?.crossfade === false)
36
- isLeaving.value = false
37
- }
26
+ const loadedRoutes = computed(() => rawRoutes.filter(r => r.meta?.__preloaded || r === currentRoute.value))
38
27
  </script>
39
28
 
40
29
  <template>
@@ -42,18 +31,11 @@ function onAfterLeave() {
42
31
  <GlobalBottom />
43
32
 
44
33
  <!-- Slides -->
45
- <template
46
- v-for="route of routes"
47
- :key="route.path"
48
- >
49
- <Transition
50
- v-bind="configs.pageTransition"
51
- @before-leave="onBeforeLeave()"
52
- @after-leave="onAfterLeave()"
53
- >
34
+ <TransitionGroup v-bind="transition">
35
+ <template v-for="route of loadedRoutes" :key="route.path">
54
36
  <SlideWrapper
55
37
  :is="route?.component as any"
56
- v-show="route === currentRoute && !isLeaving"
38
+ v-show="route === currentRoute"
57
39
  :clicks="route === currentRoute ? clicks : 0"
58
40
  :clicks-elements="route.meta?.__clicksElements || []"
59
41
  :clicks-disabled="false"
@@ -61,8 +43,8 @@ function onAfterLeave() {
61
43
  :route="route"
62
44
  :context="context"
63
45
  />
64
- </Transition>
65
- </template>
46
+ </template>
47
+ </TransitionGroup>
66
48
 
67
49
  <!-- Global Top -->
68
50
  <GlobalTop />
package/logic/nav.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { Ref } from 'vue'
1
+ import type { Ref, TransitionGroupProps } from 'vue'
2
2
  import type { RouteRecordRaw } from 'vue-router'
3
- import { computed, nextTick, ref } from 'vue'
3
+ import { computed, nextTick, ref, watch } from 'vue'
4
4
  import type { TocItem } from '@slidev/types'
5
5
  import { SwipeDirection, isString, timestamp, usePointerSwipe } from '@vueuse/core'
6
6
  import { rawRoutes, router } from '../routes'
@@ -18,6 +18,7 @@ nextTick(() => {
18
18
  routeForceRefresh.value += 1
19
19
  })
20
20
  })
21
+ export const navDirection = ref(0)
21
22
 
22
23
  export const route = computed(() => router.currentRoute.value)
23
24
 
@@ -40,6 +41,7 @@ export const currentSlideId = computed(() => currentRoute.value?.meta?.slide?.id
40
41
  export const currentLayout = computed(() => currentRoute.value?.meta?.layout || (currentPage.value === 1 ? 'cover' : 'default'))
41
42
 
42
43
  export const nextRoute = computed(() => rawRoutes.find(i => i.path === `${Math.min(rawRoutes.length, currentPage.value + 1)}`))
44
+ export const prevRoute = computed(() => rawRoutes.find(i => i.path === `${Math.max(1, currentPage.value - 1)}`))
43
45
 
44
46
  export const clicksElements = computed<HTMLElement[]>(() => {
45
47
  // eslint-disable-next-line no-unused-expressions
@@ -75,6 +77,12 @@ export const rawTree = computed(() => rawRoutes
75
77
  export const treeWithActiveStatuses = computed(() => getTreeWithActiveStatuses(rawTree.value, currentRoute.value))
76
78
  export const tree = computed(() => filterTree(treeWithActiveStatuses.value))
77
79
 
80
+ export const transition = computed(() => getCurrentTransition(navDirection.value, currentRoute.value, prevRoute.value))
81
+
82
+ watch(currentRoute, (next, prev) => {
83
+ navDirection.value = Number(next?.path) - Number(prev?.path)
84
+ })
85
+
78
86
  export function next() {
79
87
  if (clicksTotal.value <= clicks.value)
80
88
  nextSlide()
@@ -220,3 +228,50 @@ export function filterTree(tree: TocItem[], level = 1): TocItem[] {
220
228
  children: filterTree(item.children, level + 1),
221
229
  }))
222
230
  }
231
+
232
+ const transitionResolveMap: Record<string, string | undefined> = {
233
+ 'slide-left': 'slide-left | slide-right',
234
+ 'slide-right': 'slide-right | slide-left',
235
+ 'slide-up': 'slide-up | slide-down',
236
+ 'slide-down': 'slide-down | slide-up',
237
+ }
238
+
239
+ export function resolveTransition(transition?: string | TransitionGroupProps, isBackward = false): TransitionGroupProps | undefined {
240
+ if (!transition)
241
+ return undefined
242
+ if (typeof transition === 'string') {
243
+ transition = {
244
+ name: transition,
245
+ }
246
+ }
247
+
248
+ if (!transition.name)
249
+ return undefined
250
+
251
+ let name = transition.name.includes('|')
252
+ ? transition.name
253
+ : (transitionResolveMap[transition.name] || transition.name)
254
+
255
+ if (name.includes('|')) {
256
+ const [forward, backward] = name.split('|').map(i => i.trim())
257
+ name = isBackward ? backward : forward
258
+ }
259
+
260
+ if (!name)
261
+ return undefined
262
+
263
+ return {
264
+ ...transition,
265
+ name,
266
+ }
267
+ }
268
+
269
+ export function getCurrentTransition(direction: number, currentRoute?: RouteRecordRaw, prevRoute?: RouteRecordRaw) {
270
+ let transition = direction > 0
271
+ ? prevRoute?.meta?.transition
272
+ : currentRoute?.meta?.transition
273
+ if (!transition)
274
+ transition = configs.transition
275
+
276
+ return resolveTransition(transition, direction < 0)
277
+ }
@@ -107,7 +107,7 @@ export function useRecording() {
107
107
  return
108
108
 
109
109
  streamCamera.value = await navigator.mediaDevices.getUserMedia({
110
- video: currentCamera.value === 'none' || recordCamera.value !== true
110
+ video: (currentCamera.value === 'none' || recordCamera.value !== true)
111
111
  ? false
112
112
  : {
113
113
  deviceId: currentCamera.value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slidev/client",
3
- "version": "0.38.8",
3
+ "version": "0.39.0",
4
4
  "description": "Presentation slides for developers",
5
5
  "author": "antfu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",
@@ -16,11 +16,11 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@antfu/utils": "^0.7.2",
19
- "@unocss/reset": "^0.48.4",
19
+ "@unocss/reset": "^0.49.1",
20
20
  "@vueuse/core": "^9.11.1",
21
21
  "@vueuse/head": "^1.0.23",
22
22
  "@vueuse/math": "^9.11.1",
23
- "@vueuse/motion": "^2.0.0-beta.26",
23
+ "@vueuse/motion": "^2.0.0-beta.27",
24
24
  "codemirror": "^5.65.5",
25
25
  "defu": "^6.1.2",
26
26
  "drauu": "^0.3.2",
@@ -34,14 +34,14 @@
34
34
  "prettier": "^2.8.3",
35
35
  "recordrtc": "^5.6.2",
36
36
  "resolve": "^1.22.1",
37
- "unocss": "^0.48.4",
37
+ "unocss": "^0.49.1",
38
38
  "vite-plugin-windicss": "^1.8.10",
39
39
  "vue": "^3.2.45",
40
40
  "vue-router": "^4.1.6",
41
41
  "vue-starport": "^0.3.0",
42
42
  "windicss": "^3.5.6",
43
- "@slidev/parser": "0.38.8",
44
- "@slidev/types": "0.38.8"
43
+ "@slidev/parser": "0.39.0",
44
+ "@slidev/types": "0.39.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "vite": "^4.0.4"
package/routes.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { RouteRecordRaw } from 'vue-router'
2
+ import type { SlideTransition } from '@slidev/types'
2
3
  import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
3
4
  import Play from './internals/Play.vue'
4
5
  import Print from './internals/Print.vue'
5
6
  // @ts-expect-error missing types
6
7
  import _rawRoutes from '/@slidev/routes'
8
+ // @ts-expect-error missing types
7
9
  import _configs from '/@slidev/configs'
8
10
 
9
11
  export const rawRoutes = _rawRoutes as RouteRecordRaw[]
@@ -70,7 +72,7 @@ declare module 'vue-router' {
70
72
  title?: string
71
73
  level?: number
72
74
  }
73
-
75
+ transition?: string | SlideTransition
74
76
  // private fields
75
77
  __clicksElements: HTMLElement[]
76
78
  __preloaded?: boolean
package/styles/index.css CHANGED
@@ -51,3 +51,7 @@ html {
51
51
  vertical-align: sub;
52
52
  line-height: 1em;
53
53
  }
54
+
55
+ .slidev-page {
56
+ @apply absolute top-0 left-0 right-0 w-full relative;
57
+ }
@@ -1,3 +1,7 @@
1
+ #slide-content > div {
2
+ @apply h-full w-full absolute;
3
+ }
4
+
1
5
  .slidev-layout {
2
6
  @apply px-14 py-10 text-[1.1rem] h-full;
3
7
 
@@ -116,4 +120,4 @@
116
120
  li {
117
121
  @apply mr-1.1em pr-0.2em ml-0 pl-0;
118
122
  }
119
- }
123
+ }
@@ -0,0 +1,56 @@
1
+ /* Sliding */
2
+ .slide-left-enter-active,
3
+ .slide-left-leave-active,
4
+ .slide-right-enter-active,
5
+ .slide-right-leave-active,
6
+ .slide-up-enter-active,
7
+ .slide-up-leave-active,
8
+ .slide-down-enter-active,
9
+ .slide-down-leave-active {
10
+ transition: all var(--slidev-transition-duration) ease;
11
+ }
12
+
13
+ .slide-left-enter-from,
14
+ .slide-right-leave-to {
15
+ transform: translateX(100%);
16
+ }
17
+
18
+ .slide-left-leave-to,
19
+ .slide-right-enter-from {
20
+ transform: translateX(-100%);
21
+ }
22
+
23
+ .slide-up-enter-from,
24
+ .slide-down-leave-to {
25
+ transform: translateY(100%);
26
+ }
27
+
28
+ .slide-up-leave-to,
29
+ .slide-down-enter-from {
30
+ transform: translateY(-100%);
31
+ }
32
+
33
+ /* Fading */
34
+ .fade-enter-active,
35
+ .fade-leave-active {
36
+ transition: opacity var(--slidev-transition-duration) ease;
37
+ }
38
+
39
+ .fade-enter-from,
40
+ .fade-leave-to {
41
+ opacity: 0;
42
+ }
43
+
44
+ .fade-out-leave-active {
45
+ transition: opacity calc(var(--slidev-transition-duration) * 0.6) ease-out;
46
+ }
47
+
48
+ .fade-out-enter-active {
49
+ transition: opacity calc(var(--slidev-transition-duration) * 0.8) ease-in;
50
+ transition-delay: calc(var(--slidev-transition-duration) * 0.6);
51
+ }
52
+
53
+ .fade-out-enter-from,
54
+ .fade-out-leave-to {
55
+ opacity: 0;
56
+ }
package/styles/vars.css CHANGED
@@ -7,6 +7,8 @@
7
7
  --slidev-code-radius: 4px;
8
8
  --slidev-code-margin: 4px 0;
9
9
 
10
+ --slidev-transition-duration: 0.5s;
11
+
10
12
  --slidev-slide-container-background: black;
11
13
  --slidev-controls-foreground: white;
12
14
  }
package/utils.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import type { RouteRecordRaw } from 'vue-router'
2
2
 
3
- export function getSlideClass(route?: RouteRecordRaw) {
3
+ export function getSlideClass(route?: RouteRecordRaw, extra = '') {
4
+ const classes = ['slidev-page', extra]
5
+
4
6
  const no = route?.meta?.slide?.no
5
7
  if (no != null)
6
- return `slidev-page-${no}`
7
- return ''
8
+ classes.push(`slidev-page-${no}`)
9
+
10
+ return classes.filter(Boolean).join(' ')
8
11
  }