返回 slidev
RenderWhen.vue
根目录 / packages / client / builtin / RenderWhen.vue
1 <script setup lang="ts">
2 import type { RenderContext } from '@slidev/types'
3 import { useElementVisibility } from '@vueuse/core'
4 import { computed, ref } from 'vue'
5 import { useNav } from '../composables/useNav'
6 import { useSlideContext } from '../context'
7
8 type Context = 'main' | 'visible' | 'print' | RenderContext
9
10 const props = defineProps<{
11 context: Context | Context[]
12 }>()
13 const { context } = props
14 const target = ref(null)
15 const targetVisible = useElementVisibility(target)
16
17 // When context has `visible`, we need to wrap the content with a div to track the visibility
18 const needsDomWrapper = Array.isArray(context) ? context.includes('visible') : context === 'visible'
19
20 const { $renderContext: currentContext } = useSlideContext()
21 const { isPrintMode } = useNav()
22 const shouldRender = computed(() => {
23 const anyContext = Array.isArray(context) ? context.some(contextMatch) : contextMatch(context)
24 const allConditions = Array.isArray(context) ? context.every(conditionsMatch) : conditionsMatch(context)
25 return anyContext && allConditions
26 })
27
28 function contextMatch(context: Context) {
29 if (context === currentContext?.value)
30 return true
31 if (context === 'main' && (currentContext?.value === 'slide' || currentContext?.value === 'presenter'))
32 return true
33 if (context === 'visible')
34 return true
35 if (context === 'print' && isPrintMode.value)
36 return true
37 return false
38 }
39
40 function conditionsMatch(context: Context) {
41 if (context === 'visible')
42 return targetVisible.value
43 return true
44 }
45 </script>
46
47 <template>
48 <div v-if="needsDomWrapper" ref="target">
49 <slot v-if="shouldRender" />
50 <slot v-else name="fallback" />
51 </div>
52 <slot v-else-if="shouldRender" />
53 <slot v-else name="fallback" />
54 </template>
55
55 lines Plain Text