{"version":3,"file":"inertia.mjs","sources":["../../../../src/animation/generators/inertia.ts"],"sourcesContent":["import {\n AnimationState,\n KeyframeGenerator,\n ValueAnimationOptions,\n} from \"../types\"\nimport { spring as createSpring } from \"./spring\"\nimport { calcGeneratorVelocity } from \"./utils/velocity\"\n\nexport function inertia({\n keyframes,\n velocity = 0.0,\n power = 0.8,\n timeConstant = 325,\n bounceDamping = 10,\n bounceStiffness = 500,\n modifyTarget,\n min,\n max,\n restDelta = 0.5,\n restSpeed,\n}: ValueAnimationOptions): KeyframeGenerator {\n const origin = keyframes[0]\n\n const state: AnimationState = {\n done: false,\n value: origin,\n }\n\n const isOutOfBounds = (v: number) =>\n (min !== undefined && v < min) || (max !== undefined && v > max)\n\n const nearestBoundary = (v: number) => {\n if (min === undefined) return max\n if (max === undefined) return min\n\n return Math.abs(min - v) < Math.abs(max - v) ? min : max\n }\n\n let amplitude = power * velocity\n const ideal = origin + amplitude\n const target = modifyTarget === undefined ? ideal : modifyTarget(ideal)\n\n /**\n * If the target has changed we need to re-calculate the amplitude, otherwise\n * the animation will start from the wrong position.\n */\n if (target !== ideal) amplitude = target - origin\n\n const calcDelta = (t: number) => -amplitude * Math.exp(-t / timeConstant)\n\n const calcLatest = (t: number) => target + calcDelta(t)\n\n const applyFriction = (t: number) => {\n const delta = calcDelta(t)\n const latest = calcLatest(t)\n state.done = Math.abs(delta) <= restDelta\n state.value = state.done ? target : latest\n }\n\n /**\n * Ideally this would resolve for t in a stateless way, we could\n * do that by always precalculating the animation but as we know\n * this will be done anyway we can assume that spring will\n * be discovered during that.\n */\n let timeReachedBoundary: number | undefined\n let spring: KeyframeGenerator | undefined\n\n const checkCatchBoundary = (t: number) => {\n if (!isOutOfBounds(state.value)) return\n\n timeReachedBoundary = t\n\n spring = createSpring({\n keyframes: [state.value, nearestBoundary(state.value)!],\n velocity: calcGeneratorVelocity(calcLatest, t, state.value), // TODO: This should be passing * 1000\n damping: bounceDamping,\n stiffness: bounceStiffness,\n restDelta,\n restSpeed,\n })\n }\n\n checkCatchBoundary(0)\n\n return {\n calculatedDuration: null,\n next: (t: number) => {\n /**\n * We need to resolve the friction to figure out if we need a\n * spring but we don't want to do this twice per frame. So here\n * we flag if we updated for this frame and later if we did\n * we can skip doing it again.\n */\n let hasUpdatedFrame = false\n if (!spring && timeReachedBoundary === undefined) {\n hasUpdatedFrame = true\n applyFriction(t)\n checkCatchBoundary(t)\n }\n\n /**\n * If we have a spring and the provided t is beyond the moment the friction\n * animation crossed the min/max boundary, use the spring.\n */\n if (timeReachedBoundary !== undefined && t >= timeReachedBoundary) {\n return spring!.next(t - timeReachedBoundary)\n } else {\n !hasUpdatedFrame && applyFriction(t)\n return state\n }\n },\n }\n}\n"],"names":["spring","createSpring"],"mappings":"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"}