{"version":3,"file":"follow.mjs","sources":["../../../../src/value/utils/follow.ts"],"sourcesContent":["import type { MotionValue } from \"..\"\nimport { FollowAnimation } from \"../../animation/FollowAnimation\"\nimport type {\n AnyResolvedKeyframe,\n GeneratorFactory,\n ValueAnimationOptions,\n} from \"../../animation/types\"\nimport type { FollowValueOptions } from \"../follow-value\"\nimport { asNumber } from \"./as-number\"\nimport { isMotionValue } from \"./is-motion-value\"\n\nexport type FollowOptions = FollowValueOptions & { type: GeneratorFactory }\n\n/**\n * Animate `value` to its latest value with the generator in\n * `options.type`, tracking `source` if it's a `MotionValue`. Takes a\n * generator rather than a type name, so spring-only callers don't\n * bundle every generator.\n */\nexport function follow(\n value: MotionValue,\n source: T | MotionValue,\n options: FollowOptions\n): VoidFunction {\n const initialValue = value.get()\n\n let activeAnimation: FollowAnimation | null = null\n let set: (v: T) => void\n\n const unit =\n typeof initialValue === \"string\"\n ? initialValue.replace(/[\\d.-]/g, \"\")\n : undefined\n\n const onUpdate = (v: number) => set((unit ? v + unit : v) as T)\n\n const onPlay = () => value[\"events\"].animationStart?.notify()\n\n const stopAnimation = () => {\n if (activeAnimation) {\n activeAnimation.stop()\n activeAnimation = null\n }\n value.animation = undefined\n }\n\n value.attach((v, safeSet) => {\n set = safeSet\n const target = asNumber(v)\n\n if (activeAnimation?.state === \"running\") {\n /**\n * Steer the running animation rather than replacing it. This\n * keeps its completion promise and uses its analytical velocity\n * for accuracy, preventing systematic velocity loss at high\n * frame rates (240hz+).\n */\n activeAnimation.setTarget(target, options.velocity)\n return\n }\n\n const current = asNumber(value.get())\n const velocity = activeAnimation\n ? activeAnimation.getGeneratorVelocity()\n : value.getVelocity()\n\n stopAnimation()\n\n // Don't animate if we're already at the target\n if (current === target) return\n\n const animationOptions: ValueAnimationOptions = {\n keyframes: [current, target],\n velocity,\n restDelta: 0.001,\n restSpeed: 0.01,\n ...options,\n onUpdate,\n }\n\n const animation = (activeAnimation = new FollowAnimation({\n ...animationOptions,\n onPlay,\n }))\n\n value.animation = animation\n\n animation.then(() => {\n // Ignore if this animation has since been replaced\n if (activeAnimation !== animation) return\n activeAnimation = null\n value.animation = undefined\n value[\"events\"].animationComplete?.notify()\n })\n }, stopAnimation)\n\n if (isMotionValue(source)) {\n let skipNextAnimation = options.skipInitialAnimation === true\n\n const onSourceChange = (v: T) => {\n if (skipNextAnimation) {\n skipNextAnimation = false\n value.jump(parseValue(v, unit) as T, false)\n } else {\n value.set(parseValue(v, unit) as T)\n }\n }\n\n const removeSourceOnChange = source.on(\"change\", onSourceChange)\n\n /**\n * Catch up on a change made before we subscribed, for instance\n * between a React render reading the source and the effect\n * attaching to it. Subtracting is falsy for equal or non-numeric\n * (NaN) values.\n */\n const latest = source.get()\n if (asNumber(latest) - asNumber(value.get())) onSourceChange(latest)\n\n const removeValueOnDestroy = value.on(\"destroy\", removeSourceOnChange)\n\n /**\n * Stop our animation on detach, otherwise a re-attach (new\n * options, Strict Mode) starts a second animation that fights\n * this orphaned one. The catch-up above resumes from the\n * current value and velocity.\n */\n return () => {\n removeSourceOnChange()\n removeValueOnDestroy()\n stopAnimation()\n }\n }\n\n return stopAnimation\n}\n\nfunction parseValue(v: AnyResolvedKeyframe, unit?: string) {\n return unit ? v + unit : v\n}\n"],"names":[],"mappings":"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"}