{"version":3,"file":"AsyncMotionValueAnimation.mjs","sources":["../../../src/animation/AsyncMotionValueAnimation.ts"],"sourcesContent":["import { MotionGlobalConfig } from \"motion-utils\"\nimport { time } from \"../frameloop/sync-time\"\nimport { JSAnimation } from \"./JSAnimation\"\nimport { getFinalKeyframe } from \"./keyframes/get-final\"\nimport {\n    KeyframeResolver as DefaultKeyframeResolver,\n    flushKeyframeResolvers,\n    ResolvedKeyframes,\n} from \"./keyframes/KeyframesResolver\"\nimport { NativeAnimationExtended } from \"./NativeAnimationExtended\"\nimport {\n    AnimationPlaybackControls,\n    AnyResolvedKeyframe,\n    TimelineWithFallback,\n    ValueAnimationOptions,\n} from \"./types\"\nimport { canAnimate } from \"./utils/can-animate\"\nimport { makeAnimationInstant } from \"./utils/make-animation-instant\"\nimport { resolveStartTime } from \"./utils/resolve-start-time\"\nimport { WithPromise } from \"./utils/WithPromise\"\nimport { supportsBrowserAnimation } from \"./waapi/supports/waapi\"\nimport {\n    canGroupTransform,\n    TransformAnimation,\n} from \"./waapi/transforms/TransformAnimation\"\n\ntype ResolvedOptions<T extends AnyResolvedKeyframe> =\n    ValueAnimationOptions<T> & {\n        startTime?: number\n        finalKeyframe?: T\n    }\n\nexport class AsyncMotionValueAnimation<T extends AnyResolvedKeyframe>\n    extends WithPromise\n    implements AnimationPlaybackControls\n{\n    private createdAt: number\n\n    private resolvedAt: number | undefined\n\n    private _animation: AnimationPlaybackControls | undefined\n\n    private pendingTimeline: TimelineWithFallback | undefined\n\n    private keyframeResolver: DefaultKeyframeResolver | undefined\n\n    private stopTimeline: VoidFunction | undefined\n\n    constructor(options: ValueAnimationOptions<T>) {\n        super()\n\n        this.createdAt = time.now()\n\n        const { keyframes, name, motionValue, element } = options\n\n        /**\n         * animateMotionValue builds a fresh options object per value, so\n         * it's completed in place as keyframes resolve rather than copied.\n         */\n        const optionsWithDefaults = options as ResolvedOptions<T>\n        optionsWithDefaults.autoplay ??= true\n        optionsWithDefaults.delay ??= 0\n        optionsWithDefaults.type ??= \"keyframes\"\n        optionsWithDefaults.repeat ??= 0\n        optionsWithDefaults.repeatDelay ??= 0\n        optionsWithDefaults.repeatType ??= \"loop\"\n\n        const KeyframeResolver =\n            element?.KeyframeResolver || DefaultKeyframeResolver\n\n        this.keyframeResolver = new KeyframeResolver(\n            keyframes,\n            (\n                resolvedKeyframes: ResolvedKeyframes<T>,\n                finalKeyframe: T,\n                forced: boolean\n            ) =>\n                this.onKeyframesResolved(\n                    resolvedKeyframes,\n                    finalKeyframe,\n                    optionsWithDefaults,\n                    !forced\n                ),\n            name,\n            motionValue,\n            element\n        )\n        this.keyframeResolver?.scheduleResolve()\n    }\n\n    onKeyframesResolved(\n        keyframes: ResolvedKeyframes<T>,\n        finalKeyframe: T,\n        options: ResolvedOptions<T>,\n        sync: boolean\n    ) {\n        this.keyframeResolver = undefined\n\n        const { name, type, velocity, delay, isHandoff, onUpdate } = options\n        this.resolvedAt = time.now()\n\n        /**\n         * If we can't animate this value with the resolved keyframes\n         * then we should complete it immediately.\n         */\n        let canAnimateValue = true\n        if (!canAnimate(keyframes, name, type, velocity)) {\n            canAnimateValue = false\n\n            if (MotionGlobalConfig.instantAnimations || !delay) {\n                onUpdate?.(getFinalKeyframe(keyframes, options, finalKeyframe))\n            }\n\n            keyframes[0] = keyframes[keyframes.length - 1]\n\n            makeAnimationInstant(options)\n            options.repeat = 0\n        }\n\n        const { onComplete } = options\n        options.finalKeyframe = finalKeyframe\n        options.keyframes = keyframes\n        /**\n         * JSAnimation and NativeAnimation call onComplete exactly when\n         * their own `finished` resolves, so this replaces a promise chain\n         * per value with a callback.\n         */\n        options.onComplete = () => {\n            onComplete?.()\n            this.notifyFinished()\n        }\n\n        /**\n         * Animate via WAAPI if possible. If this is a handoff animation, the optimised animation will be running via\n         * WAAPI. Therefore, this animation must be JS to ensure it runs \"under\" the\n         * optimised animation.\n         *\n         * Also skip WAAPI when keyframes aren't animatable, as the resolved\n         * values may not be valid CSS and would trigger browser warnings.\n         */\n        const useWaapi =\n            canAnimateValue && !isHandoff && supportsBrowserAnimation(options)\n\n        /**\n         * Independent transforms (x, scale etc) on an HTML element are\n         * composed into one WAAPI transform animation per element.\n         */\n        const isGroupedTransform = !useWaapi && canGroupTransform(options)\n\n        /**\n         * Resolve startTime for the animation. A startTime passed in options\n         * (an optimised appear handoff syncing to its WAAPI animation) takes\n         * precedence.\n         *\n         * *Ideally*, we would use the createdAt time as t=0 as the following\n         * frame would then be the first frame of the animation in progress,\n         * which would feel snappier. If keyframes resolved on a later frame,\n         * and long after creation, we start from then instead.\n         *\n         * If they resolved immediately, a JSAnimation picks its own start\n         * time and resolves it the same way on its first frame, so every\n         * animation started in that moment stays in sync. WAAPI has no frame\n         * of ours to do that on.\n         */\n        if (\n            sync &&\n            (useWaapi ||\n                isGroupedTransform ||\n                this.resolvedAt !== this.createdAt)\n        ) {\n            options.startTime ??= resolveStartTime(\n                this.createdAt,\n                this.resolvedAt!\n            )\n        }\n\n        let animation: AnimationPlaybackControls\n        if (useWaapi) {\n            /**\n             * The resolver needed the VisualElement, WAAPI needs the DOM\n             * element. JSAnimation reads neither, so this is safe to\n             * leave in place if we fall back to it.\n             */\n            options.element = options.motionValue?.owner?.current\n            try {\n                animation = new NativeAnimationExtended(options as any)\n            } catch {\n                animation = new JSAnimation(options)\n            }\n        } else if (isGroupedTransform) {\n            animation = new TransformAnimation(options)\n        } else {\n            animation = new JSAnimation(options)\n        }\n\n        if (this.pendingTimeline) {\n            this.stopTimeline = animation.attachTimeline(this.pendingTimeline)\n            this.pendingTimeline = undefined\n        }\n\n        this._animation = animation\n    }\n\n    get finished() {\n        return this._animation ? this._animation.finished : super.finished\n    }\n\n    then(onResolve: VoidFunction, _onReject?: VoidFunction) {\n        return this.finished.finally(onResolve).then(() => {})\n    }\n\n    /**\n     * The value now, if the animation runs on the compositor.\n     */\n    liveValue() {\n        return (\n            this._animation as { liveValue?: () => T | undefined } | undefined\n        )?.liveValue?.()\n    }\n\n    get animation(): AnimationPlaybackControls {\n        if (!this._animation) {\n            this.keyframeResolver?.resume()\n            flushKeyframeResolvers()\n        }\n\n        return this._animation!\n    }\n\n    get duration() {\n        return this.animation.duration\n    }\n\n    get iterationDuration() {\n        return this.animation.iterationDuration\n    }\n\n    get time() {\n        return this.animation.time\n    }\n\n    set time(newTime: number) {\n        this.animation.time = newTime\n    }\n\n    get speed() {\n        return this.animation.speed\n    }\n\n    get state() {\n        return this.animation.state\n    }\n\n    set speed(newSpeed: number) {\n        this.animation.speed = newSpeed\n    }\n\n    get startTime() {\n        return this.animation.startTime\n    }\n\n    attachTimeline(timeline: TimelineWithFallback) {\n        if (this._animation) {\n            this.stopTimeline = this.animation.attachTimeline(timeline)\n        } else {\n            this.pendingTimeline = timeline\n        }\n\n        return () => this.stop()\n    }\n\n    play() {\n        this.animation.play()\n    }\n\n    pause() {\n        this.animation.pause()\n    }\n\n    complete() {\n        this.animation.complete()\n    }\n\n    cancel() {\n        if (this._animation) {\n            this.animation.cancel()\n        }\n\n        this.keyframeResolver?.cancel()\n    }\n\n    /**\n     * Bound to support return animation.stop pattern\n     */\n    stop = () => {\n        if (this._animation) {\n            this._animation.stop()\n            this.stopTimeline?.()\n        }\n\n        this.keyframeResolver?.cancel()\n    }\n}\n"],"names":["KeyframeResolver","DefaultKeyframeResolver"],"mappings":"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"}