Files
DeviceManager/src/routes/(app)/PageTransition.svelte
2024-11-03 14:39:35 +01:00

64 lines
1.5 KiB
Svelte

<script lang="ts">
import { fly } from "svelte/transition";
import { afterNavigate, beforeNavigate } from "$app/navigation";
import { expoIn, expoOut } from "svelte/easing";
import type { Snippet } from "svelte";
let { children }: { children: Snippet } = $props();
let inDirection = $state(0);
let outDirection = $state(0);
let outroEnd: undefined | (() => void) = $state(undefined);
let animationDone: Promise<void>;
let isNavigating = $state(false);
const routeOrder = [
"/config",
"/learn",
"/docs",
"/editor",
"/chat",
"/plugin",
];
function routeIndex(route: string | undefined): number {
return routeOrder.findIndex((it) => route?.startsWith(it));
}
beforeNavigate((navigation) => {
const from = routeIndex(navigation.from?.url.pathname);
const to = routeIndex(navigation.to?.url.pathname);
if (from === -1 || to === -1 || from === to) return;
isNavigating = true;
inDirection = from > to ? -1 : 1;
outDirection = from > to ? 1 : -1;
animationDone = new Promise((resolve) => {
outroEnd = resolve;
});
});
afterNavigate(async () => {
await animationDone;
isNavigating = false;
});
</script>
{#if !isNavigating}
<main
in:fly={{ y: inDirection * 24, duration: 150, easing: expoOut }}
out:fly={{ y: outDirection * 24, duration: 150, easing: expoIn }}
onoutroend={outroEnd}
>
{@render children()}
</main>
{/if}
<style lang="scss">
main {
padding: 0;
}
</style>