UNPKG

@humanspeak/svelte-motion

Version:

Framer Motion for Svelte 5. Declarative motion.<tag> components with AnimatePresence exit animations, gestures (hover, tap, drag, focus, in-view), variants, FLIP layout animations, shared-layout transitions, spring physics, and scroll-linked motion values

92 lines (91 loc) 4.11 kB
import { type AugmentedMotionValue } from './augmentMotionValue.svelte.js'; import { type ElementOrGetter } from './dom.js'; /** * A scroll offset edge defined as a string (e.g. `"start"`, `"end"`, * `"center"`) or a number (0–1 progress). Each offset entry is a pair of * `[target, container]`. * * Intentionally looser than motion's internal `ScrollOffset` type — that * uses template-literal types (`` `${Edge} ${Edge}` ``) we don't want to * surface to consumers. The runtime call paths through `scroll(...)` cast * `options.offset as never` to bridge the two; safe because every shape our * type allows is structurally a member of motion's union. */ type ScrollOffset = Array<[number | string, number | string]> | string[]; /** * Options accepted by {@link useScroll}. */ export type UseScrollOptions = { /** Scrollable container to track. Defaults to the page. Accepts an element or a getter function. */ container?: ElementOrGetter; /** Target element to track position of within the container. Accepts an element or a getter function. */ target?: ElementOrGetter; /** Scroll offset configuration for element position tracking. */ offset?: ScrollOffset; /** Which axis to use for the single-axis `progress` value supplied to `scroll()`. */ axis?: 'x' | 'y'; }; /** * Return type of {@link useScroll} — four motion-dom `MotionValue<number>`s * representing scroll position and normalised progress for both axes, each * augmented with `.current` + `.subscribe`. */ export type UseScrollReturn = { scrollX: AugmentedMotionValue<number>; scrollY: AugmentedMotionValue<number>; scrollXProgress: AugmentedMotionValue<number>; scrollYProgress: AugmentedMotionValue<number>; }; /** * Creates scroll-linked motion values for building scroll-driven animations * such as progress indicators and parallax effects. * * Returns four `MotionValue<number>`s: `scrollX` / `scrollY` (current * position in px) and `scrollXProgress` / `scrollYProgress` (0–1 * normalised). Each is a real motion-dom `MotionValue` augmented with a * `$state`-backed `.current` getter and a `.subscribe` shim, so they * compose with `useTransform`, `useSpring`, and the rest of the Tier 2 * surface, and they read reactively in Svelte 5 templates. * * **GPU-accelerated when supported.** On browsers that implement CSS * scroll-timeline (no `target`) or view-timeline (with a `target` and a * preset `offset`), the *Progress motion values run on the compositor * thread via WAAPI — no per-frame JS callback. The non-progress * `scrollX` / `scrollY` motion values always use the JS-driven `scroll()` * primitive since the absolute pixel offset isn't directly available from * native timelines. * * `container` and `target` accept either an `HTMLElement` directly or a * getter `() => HTMLElement | undefined`. The getter form is the right * choice with `bind:this`. Element resolution is deferred to a microtask * (matches React framer-motion 1:1, faster than rAF polling), so a getter * that hasn't hydrated yet is retried as soon as Svelte's mount tick * settles it. * * Lifecycle: the underlying `scroll()` observer and any accelerate factory * attach at mount via `$effect` and detach at unmount, regardless of how * many consumers are reading the values. The four motion values are torn * down at the same time. * * SSR-safe: returns four static `motionValue(0)`s with no scroll observer * on the server. * * @param options Optional scroll tracking configuration. * @returns Four `MotionValue<number>`s — `scrollX`, `scrollY`, `scrollXProgress`, `scrollYProgress`. * * @example * ```svelte * <script> * import { useScroll, useSpring } from '@humanspeak/svelte-motion' * * const { scrollYProgress } = useScroll() * const scaleX = useSpring(scrollYProgress) * </script> * * <div style="transform: scaleX({scaleX.current}); transform-origin: left;" /> * ``` * * @see https://motion.dev/docs/react-use-scroll */ export declare const useScroll: (options?: UseScrollOptions) => UseScrollReturn; export {};