index/layouts/Card.vue

70 lines
1.8 KiB
Vue

<script setup lang="ts">
import type { UseSwipeDirection } from '@vueuse/core'
import { useSwipe } from '@vueuse/core'
const router = useRouter()
const route = useRoute()
const card = ref<HTMLElement | null>(null)
const { pages, reader } = storeToRefs(usePageStore())
const swipe = useSwipe(card, {
passive: true,
onSwipeEnd: (_touch: TouchEvent, _direction: UseSwipeDirection) => {
if (reader.value) return
const currentPage = pages.value.find(
(page) => page.path === route.fullPath,
)!
const currentIndex = pages.value.indexOf(currentPage)
if (
card.value?.offsetWidth &&
Math.abs(swipe.lengthX.value) > 1.5 * Math.abs(swipe.lengthY.value) &&
Math.abs(swipe.lengthX.value) / card.value?.offsetWidth >= 0.1
) {
router.push(
toRaw(pages.value)[
swipe.lengthX.value > 0
? (currentIndex + 1) % pages.value.length
: currentIndex - 1 < 0
? pages.value.length - (currentIndex + 1)
: currentIndex - 1
].path,
)
}
},
})
const animationComplete = ref(false)
onMounted(() => {
card.value?.addEventListener(
'animationend',
() => (animationComplete.value = true),
)
})
</script>
<template>
<main
ref="card"
class="dimensions accent-background transition-ease overflow-auto flex flex-col gap-4 lm:gap-0 sm:gap-2 py-2 px-6 sm:p-4"
:class="{
'animate__animated-sm animate__delay-1-5s animate__fadeInDown':
!animationComplete,
'lm:rounded-none sm:rounded-xl sm:mt-8 lm:mt-0 lt:mt-0': !reader,
'!max-h-full h-full': reader,
}"
>
<Settings v-if="animationComplete" />
<Navigation />
<slot name="header" />
<NuxtPage
class="sm:fade-mask flex-grow overflow-y-auto h-full sm:py-4 sm:pe-4"
/>
<slot v-if="animationComplete" name="footer" />
</main>
</template>