{"version":3,"file":"effects.mjs","sources":["../../../../src/animation/animate/effects.ts"],"sourcesContent":["import { invariant, removeItem } from \"motion-utils\"\nimport { AnimateEffect } from \"../../effects/utils/create-effect\"\nimport { frame } from \"../../frameloop\"\nimport { positionalKeys } from \"../../render/utils/keys-position\"\nimport { MotionValue, motionValue } from \"../../value\"\nimport { animateMotionValue } from \"../interfaces/motion-value\"\nimport { AnimationElement } from \"../keyframes/types\"\nimport {\n AnimationPlaybackControlsWithThen,\n AnyResolvedKeyframe,\n UnresolvedValueKeyframe,\n ValueTransition,\n} from \"../types\"\n\n/**\n * Effects registered via `animate.addEffect()`, most recent first.\n */\nconst effects: AnimateEffect[] = []\n\nexport function addEffect(effect: AnimateEffect): void {\n invariant(\n typeof effect.test === \"function\" && typeof effect.read === \"function\",\n \"Effects passed to animate.addEffect() need test() and read().\",\n \"effect-missing-test\"\n )\n\n removeEffect(effect)\n effects.unshift(effect)\n}\n\nexport function removeEffect(effect: AnimateEffect): void {\n removeItem(effects, effect)\n}\n\nexport function findEffect(subject: unknown): AnimateEffect | undefined {\n return effects.find((effect) => effect.test(subject))\n}\n\nexport interface EffectKeyframes {\n [key: string]:\n | UnresolvedValueKeyframe\n | UnresolvedValueKeyframe[]\n | Record\n | undefined\n transition?: Record\n transitionEnd?: Record\n}\n\n/**\n * Effect subjects can expose any key, so per-key transition overrides\n * are keyed by arbitrary strings.\n */\nexport type EffectTransition = ValueTransition & {\n reduceMotion?: boolean\n skipAnimations?: boolean\n} & Record\n\n/**\n * Animate each key in `keyframes` on the motion value `getValue` returns\n * for it. `element` is what the keyframe resolver uses to read, render\n * and measure the subject when the effect defers resolution to it.\n */\nexport function animateValues(\n getValue: (key: string) => MotionValue,\n keyframes: EffectKeyframes,\n transition: EffectTransition = {},\n element?: AnimationElement\n): AnimationPlaybackControlsWithThen[] {\n const animations: AnimationPlaybackControlsWithThen[] = []\n const { velocity, path } = transition\n const reduceMotion = transition.reduceMotion ?? element?.shouldReduceMotion\n\n /**\n * Only elements have x/y to move along a path. path claims them by\n * deleting them, so hand it a copy.\n */\n if (path?.animateValues && element) {\n keyframes = { ...keyframes }\n path.animateValues(getValue, keyframes, transition, 0, animations)\n }\n\n for (const key in keyframes) {\n if (key === \"transition\" || key === \"transitionEnd\") continue\n\n const target = keyframes[key]\n if (target === undefined) continue\n\n const value = getValue(key)\n\n /**\n * If the value is already at the defined target, skip the animation.\n * We still re-assert the value via frame.update to take precedence\n * over any stale transitionEnd callbacks from previous animations.\n */\n const current = value.get()\n if (\n current !== undefined &&\n !value.isAnimating() &&\n !Array.isArray(target) &&\n target === current &&\n !velocity\n ) {\n frame.update(() => value.set(target))\n continue\n }\n\n value.start(\n animateMotionValue(\n key,\n value,\n target as any,\n reduceMotion && positionalKeys.has(key)\n ? { type: false }\n : transition,\n element\n )\n )\n\n value.animation &&\n animations.push(\n value.animation as AnimationPlaybackControlsWithThen\n )\n }\n\n const { transitionEnd } = keyframes\n if (transitionEnd) {\n const applyTransitionEnd = () =>\n frame.update(() => {\n for (const key in transitionEnd) {\n getValue(key).set(transitionEnd[key])\n }\n })\n\n animations.length\n ? Promise.all(animations).then(applyTransitionEnd)\n : applyTransitionEnd()\n }\n\n return animations\n}\n\n/**\n * Animate the keys of `subject` via `effect`. Motion values are created on\n * first animation and bound to the subject through the effect for the\n * rest of its life.\n *\n * Without `element`, a new value is seeded synchronously from the first\n * keyframe or `effect.read()`. With it, the value starts undefined and the\n * keyframe resolver reads the subject (batched, with unit conversion by\n * measurement) via `element`.\n */\nexport function animateEffectSubject(\n effect: AnimateEffect,\n subject: Subject,\n keyframes: EffectKeyframes,\n transition?: EffectTransition,\n element?: AnimationElement\n): AnimationPlaybackControlsWithThen[] {\n return animateValues(\n (key) => {\n let value = effect.get(subject, key)\n\n if (!value) {\n let initial: AnyResolvedKeyframe | undefined\n\n if (!element) {\n const target = keyframes[key] as\n | UnresolvedValueKeyframe\n | UnresolvedValueKeyframe[]\n initial =\n firstKeyframe(target) ??\n effect.read(subject, key, target)\n\n invariant(\n initial !== undefined,\n `\"${key}\" can't be read from the animated subject. Provide [from, to] keyframes.`,\n \"effect-unreadable-value\"\n )\n }\n\n value = motionValue(initial, { owner: element })\n effect(subject, { [key]: value })\n }\n\n return value\n },\n keyframes,\n transition,\n element\n )\n}\n\nfunction firstKeyframe(\n target: UnresolvedValueKeyframe | UnresolvedValueKeyframe[] | undefined\n) {\n const first = Array.isArray(target) ? target[0] : undefined\n return first === null ? undefined : first\n}\n"],"names":[],"mappings":"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"}