@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
TypeScript
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 {};