{"version":3,"file":"start.mjs","sources":["../../../../src/animation/optimized-appear/start.ts"],"sourcesContent":["import {\n    AnyResolvedKeyframe,\n    Batcher,\n    getOptimisedAppearId,\n    MotionValue,\n    optimizedAppearDataId,\n    startWaapiAnimation,\n    ValueAnimationTransition,\n    type WithAppearProps,\n} from \"motion-dom\"\nimport { noop } from \"motion-utils\"\nimport { handoffOptimizedAppearAnimation } from \"./handoff\"\nimport { appearAnimationStore, appearComplete, AppearStoreEntry } from \"./store\"\nimport { appearStoreId } from \"./store-id\"\n\n/**\n * A single time to use across all animations to manually set startTime\n * and ensure they're all in sync.\n */\nlet startFrameTime: number\n\n/**\n * A dummy animation to detect when Chrome is ready to start\n * painting the page and hold off from triggering the real animation\n * until then. We only need one animation to detect paint ready.\n *\n * https://bugs.chromium.org/p/chromium/issues/detail?id=1406850\n */\nlet readyAnimation: Animation\n\n/**\n * Keep track of animations that were suspended vs cancelled so we\n * can easily resume them when we're done measuring layout.\n */\nconst suspendedAnimations = new Set<AppearStoreEntry>()\n\nfunction resumeSuspendedAnimations() {\n    suspendedAnimations.forEach((data) => {\n        data.animation.play()\n        data.animation.startTime = data.startTime\n    })\n    suspendedAnimations.clear()\n}\n\nexport function startOptimizedAppearAnimation(\n    element: HTMLElement,\n    name: string,\n    keyframes: string[] | number[],\n    options: ValueAnimationTransition<number | string>,\n    onReady?: (animation: Animation) => void\n): void {\n    // Prevent optimised appear animations if Motion has already started animating.\n    if (window.MotionIsMounted) {\n        return\n    }\n\n    const id = element.dataset[optimizedAppearDataId]\n    if (!id) return\n\n    window.MotionHandoffAnimation = handoffOptimizedAppearAnimation\n\n    const storeId = appearStoreId(id, name)\n    if (!readyAnimation) {\n        readyAnimation = startWaapiAnimation(\n            element,\n            name,\n            [keyframes[0] as number, keyframes[0] as number],\n            /**\n             * 10 secs is basically just a super-safe duration to give Chrome\n             * long enough to get the animation ready.\n             */\n            { duration: 10000, ease: \"linear\" }\n        )\n\n        appearAnimationStore.set(storeId, {\n            animation: readyAnimation,\n            startTime: null,\n        })\n\n        /**\n         * If there's no readyAnimation then there's been no instantiation\n         * of handoff animations.\n         */\n        window.MotionHandoffAnimation = handoffOptimizedAppearAnimation\n\n        window.MotionHasOptimisedAnimation = (\n            elementId?: string,\n            valueName?: string\n        ) => {\n            if (!elementId) return false\n\n            /**\n             * Keep a map of elementIds that have started animating. We check\n             * via ID instead of Element because of hydration errors and\n             * pre-hydration checks. We also actively record IDs as they start\n             * animating rather than simply checking for data-appear-id as\n             * this attrbute might be present but not lead to an animation, for\n             * instance if the element's appear animation is on a different\n             * breakpoint.\n             */\n            if (!valueName) {\n                return appearComplete.has(elementId)\n            }\n\n            const animationId = appearStoreId(elementId, valueName)\n            return Boolean(appearAnimationStore.get(animationId))\n        }\n\n        window.MotionHandoffMarkAsComplete = (elementId: string): void => {\n            if (appearComplete.has(elementId)) {\n                appearComplete.set(elementId, true)\n            }\n        }\n\n        window.MotionHandoffIsComplete = (elementId: string): boolean => {\n            return appearComplete.get(elementId) === true\n        }\n\n        /**\n         * We only need to cancel transform animations as\n         * they're the ones that will interfere with the\n         * layout animation measurements.\n         */\n        window.MotionCancelOptimisedAnimation = (\n            elementId: string,\n            valueName: string,\n            frame?: Batcher,\n            canResume?: boolean\n        ) => {\n            const animationId = appearStoreId(elementId, valueName)\n            const data = appearAnimationStore.get(animationId)\n\n            if (!data) return\n\n            if (frame && canResume === undefined) {\n                /**\n                 * Wait until the end of the subsequent frame to cancel the animation\n                 * to ensure we don't remove the animation before the main thread has\n                 * had a chance to resolve keyframes and render.\n                 */\n                frame.postRender(() => {\n                    frame.postRender(() => {\n                        data.animation.cancel()\n                    })\n                })\n            } else {\n                data.animation.cancel()\n            }\n\n            if (frame && canResume) {\n                suspendedAnimations.add(data)\n                frame.render(resumeSuspendedAnimations)\n            } else {\n                appearAnimationStore.delete(animationId)\n\n                /**\n                 * If there are no more animations left, we can remove the cancel function.\n                 * This will let us know when we can stop checking for conflicting layout animations.\n                 */\n                if (!appearAnimationStore.size) {\n                    window.MotionCancelOptimisedAnimation = undefined\n                }\n            }\n        }\n\n        window.MotionCheckAppearSync = (\n            visualElement: WithAppearProps,\n            valueName: string,\n            value: MotionValue\n        ) => {\n            const appearId = getOptimisedAppearId(visualElement)\n\n            if (!appearId) return\n\n            const valueIsOptimised = window.MotionHasOptimisedAnimation?.(\n                appearId,\n                valueName\n            )\n            const externalAnimationValue =\n                visualElement.props.values?.[valueName]\n\n            if (!valueIsOptimised || !externalAnimationValue) return\n\n            const removeSyncCheck = value.on(\n                \"change\",\n                (latestValue: AnyResolvedKeyframe) => {\n                    if (externalAnimationValue.get() !== latestValue) {\n                        window.MotionCancelOptimisedAnimation?.(\n                            appearId,\n                            valueName\n                        )\n                        removeSyncCheck()\n                    }\n                }\n            )\n\n            return removeSyncCheck\n        }\n    }\n\n    const startAnimation = () => {\n        readyAnimation.cancel()\n\n        const appearAnimation = startWaapiAnimation(\n            element,\n            name,\n            keyframes,\n            options\n        )\n\n        /**\n         * Record the time of the first started animation. We call performance.now() once\n         * here and once in handoff to ensure we're getting\n         * close to a frame-locked time. This keeps all animations in sync.\n         */\n        if (startFrameTime === undefined) {\n            startFrameTime = performance.now()\n        }\n\n        appearAnimation.startTime = startFrameTime\n\n        appearAnimationStore.set(storeId, {\n            animation: appearAnimation,\n            startTime: startFrameTime,\n        })\n\n        if (onReady) onReady(appearAnimation)\n    }\n\n    appearComplete.set(id, false)\n\n    if (readyAnimation.ready) {\n        readyAnimation.ready.then(startAnimation).catch(noop)\n    } else {\n        startAnimation()\n    }\n}\n"],"names":[],"mappings":"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"}