{"version":3,"file":"follow-value.mjs","sources":["../../../src/value/follow-value.ts"],"sourcesContent":["import { MotionValue, motionValue } from \".\"\nimport { JSAnimation } from \"../animation/JSAnimation\"\nimport { AnyResolvedKeyframe, ValueAnimationTransition } from \"../animation/types\"\nimport { frame } from \"../frameloop\"\nimport { isMotionValue } from \"./utils/is-motion-value\"\n\n/**\n * Options for useFollowValue hook, extending ValueAnimationTransition\n * but excluding lifecycle callbacks that don't make sense for the hook pattern.\n */\nexport type FollowValueOptions = Omit<\n    ValueAnimationTransition,\n    \"onUpdate\" | \"onComplete\" | \"onPlay\" | \"onRepeat\" | \"onStop\"\n>\n\n/**\n * Create a `MotionValue` that animates to its latest value using any transition type.\n * Can either be a value or track another `MotionValue`.\n *\n * ```jsx\n * const x = motionValue(0)\n * const y = followValue(x, { type: \"spring\", stiffness: 300 })\n * // or with tween\n * const z = followValue(x, { type: \"tween\", duration: 0.5, ease: \"easeOut\" })\n * ```\n *\n * @param source - Initial value or MotionValue to track\n * @param options - Animation transition options\n * @returns `MotionValue`\n *\n * @public\n */\nexport function followValue<T extends AnyResolvedKeyframe>(\n    source: T | MotionValue<T>,\n    options?: FollowValueOptions\n) {\n    const initialValue = isMotionValue(source) ? source.get() : source\n    const value = motionValue(initialValue)\n\n    attachFollow(value, source, options)\n\n    return value\n}\n\n/**\n * Attach an animation to a MotionValue that will animate whenever the value changes.\n * Similar to attachSpring but supports any transition type (spring, tween, inertia, etc.)\n *\n * @param value - The MotionValue to animate\n * @param source - Initial value or MotionValue to track\n * @param options - Animation transition options\n * @returns Cleanup function\n *\n * @public\n */\nexport function attachFollow<T extends AnyResolvedKeyframe>(\n    value: MotionValue<T>,\n    source: T | MotionValue<T>,\n    options: FollowValueOptions = {}\n): VoidFunction {\n    const initialValue = value.get()\n\n    let activeAnimation: JSAnimation<number> | null = null\n    let latestValue = initialValue\n    let latestSetter: (v: T) => void\n\n    const unit =\n        typeof initialValue === \"string\"\n            ? initialValue.replace(/[\\d.-]/g, \"\")\n            : undefined\n\n    const stopAnimation = () => {\n        if (activeAnimation) {\n            activeAnimation.stop()\n            activeAnimation = null\n        }\n    }\n\n    const startAnimation = () => {\n        stopAnimation()\n\n        const currentValue = asNumber(value.get())\n        const targetValue = asNumber(latestValue)\n\n        // Don't animate if we're already at the target\n        if (currentValue === targetValue) {\n            return\n        }\n\n        activeAnimation = new JSAnimation({\n            keyframes: [currentValue, targetValue],\n            velocity: value.getVelocity(),\n            // Default to spring if no type specified (matches useSpring behavior)\n            type: \"spring\",\n            restDelta: 0.001,\n            restSpeed: 0.01,\n            ...options,\n            onUpdate: latestSetter,\n        })\n    }\n\n    value.attach((v, set) => {\n        latestValue = v\n        latestSetter = (latest) => set(parseValue(latest, unit) as T)\n\n        frame.postRender(() => {\n            startAnimation()\n            value[\"events\"].animationStart?.notify()\n            activeAnimation?.then(() => {\n                value[\"events\"].animationComplete?.notify()\n            })\n        })\n    }, stopAnimation)\n\n    if (isMotionValue(source)) {\n        const removeSourceOnChange = source.on(\"change\", (v) =>\n            value.set(parseValue(v, unit) as T)\n        )\n\n        const removeValueOnDestroy = value.on(\"destroy\", removeSourceOnChange)\n\n        return () => {\n            removeSourceOnChange()\n            removeValueOnDestroy()\n        }\n    }\n\n    return stopAnimation\n}\n\nfunction parseValue(v: AnyResolvedKeyframe, unit?: string) {\n    return unit ? v + unit : v\n}\n\nfunction asNumber(v: AnyResolvedKeyframe) {\n    return typeof v === \"number\" ? v : parseFloat(v)\n}\n"],"names":[],"mappings":"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"}