<script setup lang="ts">
import { nextTick, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import Loading from './Loading.vue'

// Reset the scroll position on every route change. The app's scroll container is
// the inner `.pageContent` element in AppContent (the window itself doesn't
// scroll), so a plain vue-router `scrollBehavior` wouldn't help. We scroll the
// nearest `.pageContent` ancestor back to the top after the new view mounts.
const anchor = ref<HTMLElement | null>(null)
const route = useRoute()

watch(
	() => route.fullPath,
	async () => {
		await nextTick()
		const container = anchor.value?.closest('.pageContent') as HTMLElement | null
		if (container) container.scrollTop = 0
		// Fallback: also reset the window in case a view scrolls the page itself.
		else window.scrollTo({ top: 0 })
	},
)
</script>

<template>
	<!-- Zero-size anchor used to locate the scrolling `.pageContent` ancestor. -->
	<span ref="anchor" aria-hidden="true" style="display: none" />
	<RouterView v-slot="{ Component, route }">
		<slot v-if="!Component">
			<div class="w-100p h-100vh flex justify-content-center">
				<Loading />
			</div>
		</slot>
		<transition v-else :duration="300" name="slide-fade" mode="out-in" appear>
			<component :is="Component" :key="route?.params.itemID" />
		</transition>
	</RouterView>
</template>

<style scoped>

.slide-fade-enter-active,
.slide-fade-leave-active {
overflow: hidden;
}

</style>
