74 lines
2.1 KiB
Vue
74 lines
2.1 KiB
Vue
|
|
<script setup lang="ts">
|
||
|
|
import type { ClicksContext, RenderContext, SlideRoute } from '@slidev/types'
|
||
|
|
import type { CSSProperties, PropType } from 'vue'
|
||
|
|
import { SlideBottom, SlideTop } from '#slidev/global-layers'
|
||
|
|
import { provideLocal } from '@vueuse/core'
|
||
|
|
import { computed, ref, toRef } from 'vue'
|
||
|
|
import { injectionClicksContext, injectionCurrentPage, injectionFrontmatter, injectionRenderContext, injectionRoute, injectionSlideZoom } from '../constants'
|
||
|
|
import { configs } from '../env'
|
||
|
|
import { getSlideClass } from '../utils'
|
||
|
|
|
||
|
|
const props = defineProps({
|
||
|
|
clicksContext: {
|
||
|
|
type: Object as PropType<ClicksContext>,
|
||
|
|
required: true,
|
||
|
|
},
|
||
|
|
renderContext: {
|
||
|
|
type: String as PropType<RenderContext>,
|
||
|
|
default: 'slide',
|
||
|
|
},
|
||
|
|
route: {
|
||
|
|
type: Object as PropType<SlideRoute>,
|
||
|
|
required: true,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
const zoom = computed(() => props.route.meta?.slide?.frontmatter.zoom ?? 1)
|
||
|
|
|
||
|
|
provideLocal(injectionRoute, props.route)
|
||
|
|
provideLocal(injectionFrontmatter, props.route.meta.slide.frontmatter)
|
||
|
|
provideLocal(injectionCurrentPage, ref(props.route.no))
|
||
|
|
provideLocal(injectionRenderContext, ref(props.renderContext))
|
||
|
|
provideLocal(injectionClicksContext, toRef(props, 'clicksContext'))
|
||
|
|
provideLocal(injectionSlideZoom, zoom)
|
||
|
|
|
||
|
|
const zoomStyle = computed(() => {
|
||
|
|
return zoom.value === 1
|
||
|
|
? undefined
|
||
|
|
: {
|
||
|
|
width: `${100 / zoom.value}%`,
|
||
|
|
height: `${100 / zoom.value}%`,
|
||
|
|
transformOrigin: 'top left',
|
||
|
|
transform: `scale(${zoom.value})`,
|
||
|
|
}
|
||
|
|
})
|
||
|
|
const style = computed<CSSProperties>(() => ({
|
||
|
|
...zoomStyle.value,
|
||
|
|
'user-select': configs.selectable ? undefined : 'none',
|
||
|
|
}))
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div
|
||
|
|
:data-slidev-no="props.route.no"
|
||
|
|
:class="getSlideClass(route, ['slide', 'presenter'].includes(props.renderContext) ? '' : 'disable-view-transition')"
|
||
|
|
:style="style"
|
||
|
|
:lang="props.route.meta.slide.frontmatter.lang"
|
||
|
|
>
|
||
|
|
<SlideBottom />
|
||
|
|
<component :is="props.route.component" />
|
||
|
|
<SlideTop />
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.disable-view-transition:deep(*) {
|
||
|
|
view-transition-name: none !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.slidev-page {
|
||
|
|
position: absolute;
|
||
|
|
inset: 0;
|
||
|
|
}
|
||
|
|
</style>
|