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

121 lines (120 loc) 4.96 kB
import type { DragAxis, DragConstraints, DragControls, DragInfo, MotionWhileDrag } from '../types'; import { type AnimationOptions } from 'motion'; /** * Options passed to `attachDrag`. These are derived from `MotionProps` and pre-merged * with motion config in `_MotionContainer.svelte`. * * Note: `mergedTransition` should be the already-resolved transition that combines * MotionConfig context and the component's `transition` prop. */ export type AttachDragOptions = { axis: DragAxis; constraints?: DragConstraints; elastic?: number; momentum?: boolean; transition?: { bounceStiffness?: number; bounceDamping?: number; power?: number; timeConstant?: number; min?: number; max?: number; }; directionLock?: boolean; listener?: boolean; controls?: DragControls | undefined; whileDrag?: MotionWhileDrag; mergedTransition: AnimationOptions; callbacks?: { onStart?: (e: PointerEvent, info: DragInfo) => void; onMove?: (e: PointerEvent, info: DragInfo) => void; onEnd?: (e: PointerEvent, info: DragInfo) => void; onDirectionLock?: (axis: 'x' | 'y') => void; onTransitionEnd?: () => void; }; baselineSources?: { initial?: Record<string, unknown>; animate?: Record<string, unknown>; }; propagation?: boolean; snapToOrigin?: boolean; }; /** * Resolve drag constraints into pixel offsets relative to the dragged element's origin. * * - HTMLElement: Constrains the element to the bounding box of the provided element. * - Pixel object: Direct pixel limits for top/left/right/bottom. */ /** * Normalize constraints to pixel offsets relative to the dragged element's origin. * * HTMLElement constraints: allow moving within the container bounds (subtractive rect math). * Pixel object: direct min/max per side. */ export declare const resolveConstraints: (el: HTMLElement | null, constraints: DragConstraints | undefined) => { top: number; left: number; right: number; bottom: number; } | null; /** * Apply elastic overflow outside of [min, max] using a linear ratio. */ /** * Apply elastic overflow outside the [min, max] range. * When beyond bounds, the extra distance is scaled linearly by `elastic`. */ export declare const applyElastic: (value: number, min: number, max: number, elastic: number) => number; /** * Cleanup handle returned by {@link attachDrag}. Invoke it to detach the * gesture's pointer/resize listeners. It does NOT cancel an in-flight * momentum/settle animation — matching framer-motion, whose drag teardown * removes listeners only and deliberately lets motion continue across an * unmount/remount (e.g. reorder reconciliation); the animation is cleaned * up by the element/motion-value lifecycle. * * The handle also carries `adjustOrigin(dx, dy)`, which shifts the LIVE * gesture's origin + visual offset by a layout-shift delta mid-drag — used * for projection-driven cursor pinning when a layout slot moves under the * dragged element (#379 / #310). It is a no-op when not currently dragging * and compensates on both axes (mirroring upstream's per-axis `eachAxis` * compensation). */ export type AttachDragCleanup = (() => void) & { adjustOrigin: (dx: number, dy: number) => void; }; /** * Attach a drag gesture to an element. * * Captures the pointer and updates x/y transforms with axis and optional * direction lock, applies elastic overflow against constraints, emits * lifecycle callbacks with `DragInfo`, and runs a momentum animation on * release when enabled. * * Lifecycle: * - pointerdown → capture pointer, snapshot origin, start velocity history, enter whileDrag * - pointermove → compute deltas, direction lock, apply constraints + elastic, write x/y * - pointerup/cancel → either run momentum decay to a target or settle/clamp instantly * * Invariant: `applied` tracks the currently applied x/y transform — it * must stay in sync when writing transforms or finishing animations, or a * second drag "jumps" from a stale origin (commonly a missed update after * a non-zero-duration settle animation). * * @param el The element to make draggable. * @param opts Drag options — `axis`, `constraints`, `elastic`, * `momentum`, `whileDrag`, and the `onDrag*` lifecycle callbacks. * @returns A callable cleanup handle ({@link AttachDragCleanup}): call it * to detach the gesture's listeners (in-flight momentum is not * cancelled — see the type docs), or call its `adjustOrigin(dx, dy)` to * reposition the live gesture mid-drag. * @example * ```ts * const cleanup = attachDrag(el, { axis: 'x', momentum: true }) * // …when a layout swap shifts the slot under the cursor mid-drag: * cleanup.adjustOrigin(10, -5) * // on teardown: * cleanup() * ``` */ export declare const attachDrag: (el: HTMLElement, opts: AttachDragOptions) => AttachDragCleanup;