87 lines
No EOL
2.8 KiB
Svelte
87 lines
No EOL
2.8 KiB
Svelte
<script lang="ts">
|
|
import '$lib/styles/global.css';
|
|
import Header from '$lib/components/Header.svelte';
|
|
import Loader from '$lib/components/Loader.svelte';
|
|
import { page } from '$app/state';
|
|
import { beforeNavigate } from '$app/navigation';
|
|
import { browser } from '$app/environment';
|
|
import type { Snippet } from 'svelte';
|
|
import { onMount } from 'svelte';
|
|
|
|
interface LayoutData {
|
|
pathname: string;
|
|
}
|
|
|
|
onMount(() => {
|
|
// console.log('layout mounted');
|
|
setTheme();
|
|
});
|
|
|
|
let { children }: { children: Snippet } = $props();
|
|
|
|
let showLoader = $state(false);
|
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
let navToken = 0;
|
|
|
|
function clearTimer() {
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
timer = null;
|
|
}
|
|
}
|
|
|
|
if (browser) {
|
|
beforeNavigate((nav) => {
|
|
// token to avoid races between overlapping navigations
|
|
const token = ++navToken;
|
|
|
|
clearTimer();
|
|
showLoader = false;
|
|
|
|
// only show if navigation takes >150ms
|
|
timer = setTimeout(() => {
|
|
if (token === navToken) showLoader = true;
|
|
}, 150);
|
|
|
|
// hide loader when THIS navigation completes (even if afterNavigate timing is odd)
|
|
nav.complete.finally(() => {
|
|
if (token !== navToken) return;
|
|
clearTimer();
|
|
showLoader = false;
|
|
setTheme();
|
|
});
|
|
});
|
|
}
|
|
|
|
function setTheme() {
|
|
if (page.data.theme && page.data.theme.bg && page.data.theme.text && page.data.theme.highlight) {
|
|
document.documentElement.style.setProperty('--color-bg', page.data.theme.bg);
|
|
document.documentElement.style.setProperty('--color-text', page.data.theme.text);
|
|
document.documentElement.style.setProperty('--color-highlight', page.data.theme.highlight);
|
|
} else {
|
|
// Remove inline styles to let CSS :root defaults take effect
|
|
document.documentElement.style.removeProperty('--color-bg');
|
|
document.documentElement.style.removeProperty('--color-text');
|
|
document.documentElement.style.removeProperty('--color-highlight');
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:url" content={`https://floter.design${page.url.pathname}`} />
|
|
<meta property="og:image" content="https://floter.design/ogimage.png">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="description" content={page.data.description ? page.data.description : 'Simon Flöter is a designer and creative developer'} />
|
|
<title>{page.data.title ? page.data.title : 'Simon Flöter, Designer and Creative Developer'}</title>
|
|
<script defer data-domain="floter.design" src="https://analytics.floter.design/js/script.js"></script>
|
|
</svelte:head>
|
|
|
|
<Header />
|
|
<div class="content">
|
|
{#if showLoader}
|
|
<Loader />
|
|
{/if}
|
|
{@render children()}
|
|
</div> |