79 lines
1.8 KiB
Svelte
79 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
import {
|
|
createLenisContext,
|
|
setLenisContext,
|
|
} from '$shared/lib';
|
|
import Lenis from 'lenis';
|
|
import type { LenisOptions } from 'lenis';
|
|
import { onMount } from 'svelte';
|
|
|
|
interface Props {
|
|
children?: import('svelte').Snippet;
|
|
// Lenis options - all optional with sensible defaults
|
|
duration?: number;
|
|
easing?: (t: number) => number;
|
|
smoothWheel?: boolean;
|
|
wheelMultiplier?: number;
|
|
touchMultiplier?: number;
|
|
infinite?: boolean;
|
|
orientation?: 'vertical' | 'horizontal';
|
|
gestureOrientation?: 'vertical' | 'horizontal' | 'both';
|
|
}
|
|
|
|
let {
|
|
children,
|
|
duration = 1.2,
|
|
easing = t => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
|
|
smoothWheel = true,
|
|
wheelMultiplier = 1,
|
|
touchMultiplier = 2,
|
|
infinite = false,
|
|
orientation = 'vertical',
|
|
gestureOrientation = 'vertical',
|
|
}: Props = $props();
|
|
|
|
const lenisContext = createLenisContext();
|
|
setLenisContext(lenisContext);
|
|
|
|
onMount(() => {
|
|
const lenisOptions: LenisOptions = {
|
|
duration,
|
|
easing,
|
|
smoothWheel,
|
|
wheelMultiplier,
|
|
touchMultiplier,
|
|
infinite,
|
|
orientation,
|
|
gestureOrientation,
|
|
// Prevent jitter with virtual scroll
|
|
prevent: (node: HTMLElement) => {
|
|
// Don't smooth scroll inside elements with data-lenis-prevent
|
|
return node.hasAttribute('data-lenis-prevent');
|
|
},
|
|
};
|
|
|
|
const lenis = new Lenis(lenisOptions);
|
|
|
|
lenisContext.setLenis(lenis);
|
|
|
|
// RAF loop
|
|
function raf(time: number) {
|
|
lenis.raf(time);
|
|
requestAnimationFrame(raf);
|
|
}
|
|
|
|
requestAnimationFrame(raf);
|
|
|
|
// Expose to window for debugging (only in dev)
|
|
if (import.meta.env?.DEV) {
|
|
(window as any).lenis = lenis;
|
|
}
|
|
|
|
return () => {
|
|
lenisContext.destroyLenis();
|
|
};
|
|
});
|
|
</script>
|
|
|
|
{@render children?.()}
|