index/components/animations/AClientOnly.vue

106 lines
2.0 KiB
Vue

<script setup lang="ts">
import type { PropType } from 'vue'
type ModeOptions = 'in-out' | 'out-in' | 'default' | undefined
type RenderOptions =
| 'never'
| 'always'
| 'xs'
| 'sm'
| 'sm-down'
| 'sm-up'
| 'md'
| 'md-down'
| 'md-up'
| 'lg'
| 'lg-down'
| 'lg-up'
| 'xl'
| 'xl-down'
| 'xl-up'
| 'xxl'
| undefined
const vdisp = ref(useVDisplay())
const props = defineProps({
fallback: {
type: String,
default: '',
},
render: {
type: String as PropType<RenderOptions>,
default: 'always',
},
appear: {
type: Boolean,
default: false,
},
mode: {
type: String as PropType<ModeOptions>,
default: 'out-in',
},
enter: {
type: String,
default: 'animate__fadeIn',
},
leave: {
type: String,
default: 'animate__fadeOut',
},
})
const render = computed(() => {
switch (props.render) {
case 'never':
return false
case 'always':
return true
case 'xs':
return vdisp.value.xs
case 'sm':
return vdisp.value.sm
case 'sm-down':
return vdisp.value.smAndDown
case 'sm-up':
return vdisp.value.smAndUp
case 'md':
return vdisp.value.md
case 'md-down':
return vdisp.value.mdAndDown
case 'md-up':
return vdisp.value.mdAndUp
case 'lg':
return vdisp.value.lg
case 'lg-down':
return vdisp.value.lgAndDown
case 'lg-up':
return vdisp.value.lgAndUp
case 'xl':
return vdisp.value.xl
case 'xl-down':
return vdisp.value.xlAndDown
case 'xl-up':
return vdisp.value.xlAndUp
case 'xxl':
return vdisp.value.xxl
default:
return false
}
})
</script>
<template>
<ClientOnly>
<template #fallback>{{ props.fallback }}</template>
<Transition
:appear="props.appear"
:mode="props.mode"
:enter-active-class="`animate__animated ${props.enter}`"
:leave-active-class="`animate__animated ${props.leave}`"
>
<slot v-if="render" />
</Transition>
</ClientOnly>
</template>