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

50 lines (49 loc) 2.08 kB
import { motionValue } from 'motion-dom'; import { augmentMotionValue } from './augmentMotionValue.svelte.js'; /** * Creates a tracked, mutable value backed by motion-dom's `MotionValue`. * * Use `.set(v)` to write the value imperatively, `.get()` to sample it * imperatively, and `.current` to read it inside Svelte 5 reactive scopes * (templates, `$derived`, `$effect`). The same value also implements the * Svelte readable store contract via `.subscribe(run)`, so legacy `$mv` * template syntax and `svelte/store`'s `get()` keep working. * * Returned object is a real motion-dom `MotionValue` — it composes with * `useTransform`, `useSpring`, `useVelocity`, the `animate()` driver, and * passes `isMotionValue`. Unlike `useSpring`, writes are immediate — there * is no follow source and no animation. * * Lifecycle: must be called during component initialization. Cleanup is * registered via `$effect`; motion-dom's internal listeners and animation * subscriptions are released when the surrounding component / effect tears * down. Call `.destroy()` to clean up early. * * SSR-safe: motion-dom's `motionValue` runs without DOM access; on the * server reads return the initial value and writes still work, with no * timers or listeners attached. * * @template T The value type — typically `number` or `string`. * @param initial The starting value. * @returns A `MotionValue<T>` augmented with `.current` and `.subscribe`. * * @example * ```svelte * <script lang="ts"> * import { useMotionValue, useTransform } from '@humanspeak/svelte-motion' * * const x = useMotionValue(0) * const opacity = useTransform(x, [0, 200], [0, 1]) * </script> * * <input type="range" min="0" max="200" oninput={(e) => x.set(+e.currentTarget.value)} /> * <div style="opacity: {opacity.current}">x = {x.current}</div> * ``` * * @see https://motion.dev/docs/react-motion-value */ export const useMotionValue = (initial) => { const value = motionValue(initial); $effect(() => () => value.destroy()); return augmentMotionValue(value); };