UNPKG

framer-motion

Version:

An open source and production-ready motion library for React on the web

64 lines (56 loc) • 2.15 kB
import { useRef, useMemo, useContext } from "react" import { animate, PlaybackControls, SpringOptions } from "popmotion" import { MotionValue } from "../value" import { isMotionValue } from "./utils/is-motion-value" import { useMotionValue } from "./use-motion-value" import { useOnChange } from "./use-on-change" import { MotionConfigContext } from "../motion/context/MotionConfigContext" /** * Creates a `MotionValue` that, when `set`, will use a spring animation to animate to its new state. * * It can either work as a stand-alone `MotionValue` by initialising it with a value, or as a subscriber * to another `MotionValue`. * * @remarks * * ```jsx * const x = useSpring(0, { stiffness: 300 }) * const y = useSpring(x, { damping: 10 }) * ``` * * @param inputValue - `MotionValue` or number. If provided a `MotionValue`, when the input `MotionValue` changes, the created `MotionValue` will spring towards that value. * @param springConfig - Configuration options for the spring. * @returns `MotionValue` * * @public */ export function useSpring( source: MotionValue | number, config: SpringOptions = {} ) { const { isStatic } = useContext(MotionConfigContext) const activeSpringAnimation = useRef<PlaybackControls | null>(null) const value = useMotionValue(isMotionValue(source) ? source.get() : source) useMemo(() => { return value.attach((v, set) => { /** * A more hollistic approach to this might be to use isStatic to fix VisualElement animations * at that level, but this will work for now */ if (isStatic) return set(v) if (activeSpringAnimation.current) { activeSpringAnimation.current.stop() } activeSpringAnimation.current = animate({ from: value.get(), to: v, velocity: value.getVelocity(), ...config, onUpdate: set, }) return value.get() }) }, Object.values(config)) useOnChange(source, (v) => value.set(parseFloat(v))) return value }