{"version":3,"file":"attach-animation.mjs","sources":["../../../../../src/render/dom/scroll/attach-animation.ts"],"sourcesContent":["import { AnimationPlaybackControls, resize } from \"motion-dom\"\nimport { scrollInfo } from \"./track\"\nimport { ScrollOptionsWithDefaults } from \"./types\"\nimport { canUseNativeTimeline } from \"./utils/can-use-native-timeline\"\nimport { getTimeline } from \"./utils/get-timeline\"\nimport { offsetToViewTimelineRange } from \"./utils/offset-to-range\"\n\nexport function attachToAnimation(\n    animation: AnimationPlaybackControls,\n    options: ScrollOptionsWithDefaults\n) {\n    const { target, container, axis } = options\n    const range = target && offsetToViewTimelineRange(options.offset)\n\n    /**\n     * Use native timeline when:\n     * - No target and no offset: ScrollTimeline\n     * - Target with mappable offset: ViewTimeline with named range\n     * - Otherwise: fall back to JS observe. A ScrollTimeline has no offset,\n     *   so page offsets are applied by the JS timeline.\n     */\n    const native =\n        canUseNativeTimeline(target) && (target ? !!range : !options.offset)\n    const animations = new Map<Animation, PlaybackDirection>()\n    const observed = new Set<AnimationPlaybackControls>()\n    let stopObserving: VoidFunction | undefined\n    let reverse = false\n\n    /**\n     * When an offset's second point comes first, its range is swapped and\n     * the animation played backwards. The range is set after the direction,\n     * as that's what realigns a running animation with its timeline. Chrome\n     * skips that realignment when the range changes in the frame the\n     * animation starts, leaving it offset for good, so it's replayed too.\n     */\n    const apply = (direction: PlaybackDirection, waapi: Animation) => {\n        const [start, end] = range!.points\n        waapi.effect!.updateTiming({\n            direction: reverse\n                ? direction === \"normal\"\n                    ? \"reverse\"\n                    : \"alternate-reverse\"\n                : direction,\n        })\n        Object.assign(waapi, {\n            rangeStart: reverse ? end : start,\n            rangeEnd: reverse ? start : end,\n        })\n        waapi.play()\n    }\n\n    const stops = [\n        animation.attachTimeline({\n            /**\n             * Read only by WAAPI animations, so values driven from JS don't\n             * create a native timeline they won't use.\n             */\n            get timeline() {\n                return native ? getTimeline(options) : undefined\n            },\n            onAttach:\n                range &&\n                ((waapi) => {\n                    const direction = waapi.effect!.getTiming().direction!\n                    animations.set(waapi, direction)\n                    apply(direction, waapi)\n                }),\n            /**\n             * Values driven from JS all track the offset with scrollInfo,\n             * which measures once per frame for all of them.\n             */\n            observe: (valueAnimation) => {\n                valueAnimation.pause()\n                observed.add(valueAnimation)\n\n                stopObserving ||= scrollInfo((info) => {\n                    observed.forEach((observedAnimation) => {\n                        observedAnimation.time =\n                            observedAnimation.iterationDuration *\n                            info[axis].progress\n                    })\n                }, options)\n\n                return () => observed.delete(valueAnimation)\n            },\n        }),\n    ]\n\n    if (native && range) {\n        const { a, b } = range\n        const length = axis === \"y\" ? \"clientHeight\" : \"clientWidth\"\n\n        /**\n         * Offsets like All only run forwards when the target is longer than\n         * the container, so their direction is remeasured on resize.\n         */\n        const update = () => {\n            if (\n                reverse !==\n                (reverse = a * target![length] + b * container[length] < 0)\n            ) {\n                animations.forEach(apply)\n            }\n        }\n        update()\n\n        if (a * b < 0) {\n            stops.push(resize(update), resize([target!, container], update))\n        }\n    }\n\n    return () => {\n        stops.forEach((stop) => stop())\n        stopObserving?.()\n    }\n}\n"],"names":[],"mappings":"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"}