framer-motion 10.3.4 → 10.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cjs/dom-entry.js +1 -1
  2. package/dist/cjs/index.js +135 -1958
  3. package/dist/cjs/{wrap-196fd3c5.js → wrap-58c66ad3.js} +3790 -1847
  4. package/dist/dom-entry.d.ts +43 -34
  5. package/dist/es/animation/animate.mjs +38 -34
  6. package/dist/es/animation/{create-instant-animation.mjs → animators/instant.mjs} +5 -2
  7. package/dist/es/animation/{js → animators/js}/driver-frameloop.mjs +2 -2
  8. package/dist/es/animation/{js → animators/js}/index.mjs +10 -9
  9. package/dist/es/animation/{waapi → animators/waapi}/create-accelerated-animation.mjs +22 -3
  10. package/dist/es/animation/hooks/animation-controls.mjs +4 -1
  11. package/dist/es/animation/hooks/use-animated-state.mjs +1 -1
  12. package/dist/es/animation/{index.mjs → interfaces/motion-value.mjs} +12 -12
  13. package/dist/es/animation/interfaces/single-value.mjs +11 -0
  14. package/dist/es/animation/interfaces/visual-element-target.mjs +66 -0
  15. package/dist/es/animation/interfaces/visual-element-variant.mjs +63 -0
  16. package/dist/es/animation/interfaces/visual-element.mjs +24 -0
  17. package/dist/es/animation/optimized-appear/start.mjs +1 -1
  18. package/dist/es/animation/utils/create-visual-element.mjs +32 -0
  19. package/dist/es/animation/utils/is-dom-keyframes.mjs +5 -0
  20. package/dist/es/gestures/drag/VisualElementDragControls.mjs +2 -2
  21. package/dist/es/index.mjs +2 -2
  22. package/dist/es/projection/node/create-projection-node.mjs +5 -4
  23. package/dist/es/render/VisualElement.mjs +3 -0
  24. package/dist/es/render/dom/utils/is-svg-element.mjs +5 -0
  25. package/dist/es/render/store.mjs +3 -0
  26. package/dist/es/render/utils/animation-state.mjs +1 -1
  27. package/dist/es/render/utils/motion-values.mjs +1 -1
  28. package/dist/es/utils/interpolate.mjs +6 -0
  29. package/dist/es/value/index.mjs +1 -1
  30. package/dist/es/value/use-spring.mjs +1 -1
  31. package/dist/framer-motion.dev.js +4948 -4872
  32. package/dist/framer-motion.js +1 -1
  33. package/dist/index.d.ts +57 -51
  34. package/dist/projection.dev.js +4982 -5008
  35. package/dist/three-entry.d.ts +6 -10
  36. package/package.json +5 -5
  37. package/dist/es/render/utils/animation.mjs +0 -145
  38. /package/dist/es/animation/{waapi → animators/waapi}/easing.mjs +0 -0
  39. /package/dist/es/animation/{waapi → animators/waapi}/index.mjs +0 -0
  40. /package/dist/es/animation/{waapi → animators/waapi}/supports.mjs +0 -0
  41. /package/dist/es/animation/{waapi → animators/waapi}/utils/get-final-keyframe.mjs +0 -0
@@ -28,6 +28,7 @@ declare type Sync = {
28
28
  [key in StepId]: Schedule;
29
29
  };
30
30
 
31
+ declare type GenericKeyframesTarget<V> = [null, ...V[]] | V[];
31
32
  /**
32
33
  * Options for orchestrating the timing of animations.
33
34
  *
@@ -799,6 +800,15 @@ declare type TransitionMap = Orchestration & {
799
800
  */
800
801
  declare type Transition = (Orchestration & Repeat & TransitionDefinition) | (Orchestration & Repeat & TransitionMap);
801
802
 
803
+ interface AnimationPlaybackLifecycles<V> {
804
+ onUpdate?: (latest: V) => void;
805
+ onPlay?: () => void;
806
+ onComplete?: () => void;
807
+ onRepeat?: () => void;
808
+ onStop?: () => void;
809
+ }
810
+ declare type AnimateOptions<V = any> = Transition & AnimationPlaybackLifecycles<V>;
811
+ declare type ElementOrSelector$1 = Element | Element[] | NodeListOf<Element> | string;
802
812
  /**
803
813
  * @public
804
814
  */
@@ -809,6 +819,29 @@ interface AnimationPlaybackControls {
809
819
  pause: () => void;
810
820
  then: (onResolve: VoidFunction, onReject?: VoidFunction) => Promise<void>;
811
821
  }
822
+ interface CSSStyleDeclarationWithTransform extends Omit<CSSStyleDeclaration, "direction" | "transition"> {
823
+ x: number | string;
824
+ y: number | string;
825
+ z: number | string;
826
+ rotateX: number | string;
827
+ rotateY: number | string;
828
+ rotateZ: number | string;
829
+ scaleX: number;
830
+ scaleY: number;
831
+ scaleZ: number;
832
+ skewX: number | string;
833
+ skewY: number | string;
834
+ }
835
+ declare type ValueKeyframe = string | number;
836
+ declare type UnresolvedValueKeyframe = ValueKeyframe | null;
837
+ declare type ValueKeyframesDefinition = ValueKeyframe | ValueKeyframe[] | UnresolvedValueKeyframe[];
838
+ declare type StyleKeyframesDefinition = {
839
+ [K in keyof CSSStyleDeclarationWithTransform]?: ValueKeyframesDefinition;
840
+ };
841
+ declare type VariableKeyframesDefinition = {
842
+ [key: `--${string}`]: ValueKeyframesDefinition;
843
+ };
844
+ declare type DOMKeyframesDefinition = StyleKeyframesDefinition & VariableKeyframesDefinition;
812
845
 
813
846
  /**
814
847
  * @public
@@ -973,43 +1006,19 @@ declare class MotionValue<V = any> {
973
1006
  declare function motionValue<V>(init: V, options?: MotionValueOptions): MotionValue<V>;
974
1007
 
975
1008
  /**
976
- * @public
1009
+ * Animate a single value
977
1010
  */
978
- interface AnimationPlaybackLifecycles<V> {
979
- onUpdate?: (latest: V) => void;
980
- onPlay?: () => void;
981
- onComplete?: () => void;
982
- onRepeat?: () => void;
983
- onStop?: () => void;
984
- }
1011
+ declare function animate(from: string, to: string | GenericKeyframesTarget<string>, options?: AnimateOptions<string>): AnimationPlaybackControls;
1012
+ declare function animate(from: number, to: number | GenericKeyframesTarget<number>, options?: AnimateOptions<number>): AnimationPlaybackControls;
985
1013
  /**
986
- * Animate a single value or a `MotionValue`.
987
- *
988
- * The first argument is either a `MotionValue` to animate, or an initial animation value.
989
- *
990
- * The second is either a value to animate to, or an array of keyframes to animate through.
991
- *
992
- * The third argument can be either tween or spring options, and optional lifecycle methods: `onUpdate`, `onPlay`, `onComplete`, `onRepeat` and `onStop`.
993
- *
994
- * Returns `AnimationPlaybackControls`, currently just a `stop` method.
995
- *
996
- * ```javascript
997
- * const x = useMotionValue(0)
998
- *
999
- * useEffect(() => {
1000
- * const controls = animate(x, 100, {
1001
- * type: "spring",
1002
- * stiffness: 2000,
1003
- * onComplete: v => {}
1004
- * })
1005
- *
1006
- * return controls.stop
1007
- * })
1008
- * ```
1009
- *
1010
- * @public
1014
+ * Animate a MotionValue
1015
+ */
1016
+ declare function animate(value: MotionValue<string>, keyframes: string | GenericKeyframesTarget<string>, options?: AnimateOptions<string>): AnimationPlaybackControls;
1017
+ declare function animate(value: MotionValue<number>, keyframes: number | GenericKeyframesTarget<number>, options?: AnimateOptions<number>): AnimationPlaybackControls;
1018
+ /**
1019
+ * Animate DOM
1011
1020
  */
1012
- declare function animate<V>(from: MotionValue<V> | V, to: V | V[], transition?: Transition & AnimationPlaybackLifecycles<V>): AnimationPlaybackControls;
1021
+ declare function animate<V>(value: ElementOrSelector$1, keyframes: DOMKeyframesDefinition, options?: AnimateOptions<V>): AnimationPlaybackControls;
1013
1022
 
1014
1023
  interface AxisScrollInfo {
1015
1024
  current: number;
@@ -1,39 +1,43 @@
1
- import { createMotionValueAnimation } from './index.mjs';
2
- import { motionValue } from '../value/index.mjs';
3
- import { isMotionValue } from '../value/utils/is-motion-value.mjs';
1
+ import { resolveElements } from '../render/dom/utils/resolve-element.mjs';
2
+ import { visualElementStore } from '../render/store.mjs';
3
+ import { invariant } from '../utils/errors.mjs';
4
4
  import { GroupPlaybackControls } from './GroupPlaybackControls.mjs';
5
+ import { isDOMKeyframes } from './utils/is-dom-keyframes.mjs';
6
+ import { animateTarget } from './interfaces/visual-element-target.mjs';
7
+ import { createVisualElement } from './utils/create-visual-element.mjs';
8
+ import { animateSingleValue } from './interfaces/single-value.mjs';
5
9
 
6
- /**
7
- * Animate a single value or a `MotionValue`.
8
- *
9
- * The first argument is either a `MotionValue` to animate, or an initial animation value.
10
- *
11
- * The second is either a value to animate to, or an array of keyframes to animate through.
12
- *
13
- * The third argument can be either tween or spring options, and optional lifecycle methods: `onUpdate`, `onPlay`, `onComplete`, `onRepeat` and `onStop`.
14
- *
15
- * Returns `AnimationPlaybackControls`, currently just a `stop` method.
16
- *
17
- * ```javascript
18
- * const x = useMotionValue(0)
19
- *
20
- * useEffect(() => {
21
- * const controls = animate(x, 100, {
22
- * type: "spring",
23
- * stiffness: 2000,
24
- * onComplete: v => {}
25
- * })
26
- *
27
- * return controls.stop
28
- * })
29
- * ```
30
- *
31
- * @public
32
- */
33
- function animate(from, to, transition = {}) {
34
- const value = isMotionValue(from) ? from : motionValue(from);
35
- value.start(createMotionValueAnimation("", value, to, transition));
36
- return value.animation || new GroupPlaybackControls([]);
10
+ function animateElements(elementOrSelector, keyframes, options) {
11
+ const elements = resolveElements(elementOrSelector);
12
+ const numElements = elements.length;
13
+ invariant(Boolean(numElements), "No valid element provided.");
14
+ const animations = [];
15
+ for (let i = 0; i < numElements; i++) {
16
+ const element = elements[i];
17
+ /**
18
+ * Check each element for an associated VisualElement. If none exists,
19
+ * we need to create one.
20
+ */
21
+ if (!visualElementStore.has(element)) {
22
+ /**
23
+ * TODO: We only need render-specific parts of the VisualElement.
24
+ * With some additional work the size of the animate() function
25
+ * could be reduced significantly.
26
+ */
27
+ createVisualElement(element);
28
+ }
29
+ const visualElement = visualElementStore.get(element);
30
+ animations.push(...animateTarget(visualElement, { ...keyframes, transition: options }, {}));
31
+ }
32
+ return new GroupPlaybackControls(animations);
33
+ }
34
+ function animate(valueOrElement, keyframes, options = {}) {
35
+ if (isDOMKeyframes(keyframes)) {
36
+ return animateElements(valueOrElement, keyframes, options);
37
+ }
38
+ else {
39
+ return animateSingleValue(valueOrElement, keyframes, options);
40
+ }
37
41
  }
38
42
 
39
43
  export { animate };
@@ -1,5 +1,5 @@
1
1
  import { animateValue } from './js/index.mjs';
2
- import { noop } from '../utils/noop.mjs';
2
+ import { noop } from '../../utils/noop.mjs';
3
3
 
4
4
  function createInstantAnimation({ keyframes, delay: delayBy, onUpdate, onComplete, }) {
5
5
  const setValue = () => {
@@ -10,7 +10,10 @@ function createInstantAnimation({ keyframes, delay: delayBy, onUpdate, onComplet
10
10
  play: (noop),
11
11
  pause: (noop),
12
12
  stop: (noop),
13
- then: () => Promise.resolve(),
13
+ then: (resolve) => {
14
+ resolve();
15
+ return Promise.resolve();
16
+ },
14
17
  };
15
18
  };
16
19
  return delayBy
@@ -1,5 +1,5 @@
1
- import { sync, cancelSync } from '../../frameloop/index.mjs';
2
- import { frameData } from '../../frameloop/data.mjs';
1
+ import { sync, cancelSync } from '../../../frameloop/index.mjs';
2
+ import { frameData } from '../../../frameloop/data.mjs';
3
3
 
4
4
  const frameloopDriver = (update) => {
5
5
  const passTimestamp = ({ timestamp }) => update(timestamp);
@@ -1,10 +1,10 @@
1
- import { keyframes } from '../generators/keyframes.mjs';
2
- import { spring } from '../generators/spring/index.mjs';
3
- import { inertia } from '../generators/inertia.mjs';
1
+ import { keyframes } from '../../generators/keyframes.mjs';
2
+ import { spring } from '../../generators/spring/index.mjs';
3
+ import { inertia } from '../../generators/inertia.mjs';
4
4
  import { frameloopDriver } from './driver-frameloop.mjs';
5
- import { interpolate } from '../../utils/interpolate.mjs';
6
- import { clamp } from '../../utils/clamp.mjs';
7
- import { millisecondsToSeconds, secondsToMilliseconds } from '../../utils/time-conversion.mjs';
5
+ import { interpolate } from '../../../utils/interpolate.mjs';
6
+ import { clamp } from '../../../utils/clamp.mjs';
7
+ import { millisecondsToSeconds, secondsToMilliseconds } from '../../../utils/time-conversion.mjs';
8
8
 
9
9
  const types = {
10
10
  decay: inertia,
@@ -206,12 +206,13 @@ function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, ke
206
206
  return millisecondsToSeconds(time);
207
207
  },
208
208
  set time(newTime) {
209
- const timeInMs = secondsToMilliseconds(newTime);
209
+ newTime = secondsToMilliseconds(newTime);
210
+ time = newTime;
210
211
  if (holdTime !== null || !animationDriver) {
211
- holdTime = timeInMs;
212
+ holdTime = newTime;
212
213
  }
213
214
  else {
214
- startTime = animationDriver.now() - timeInMs;
215
+ startTime = animationDriver.now() - newTime;
215
216
  }
216
217
  },
217
218
  play,
@@ -1,10 +1,10 @@
1
- import { sync } from '../../frameloop/index.mjs';
1
+ import { sync } from '../../../frameloop/index.mjs';
2
2
  import { animateStyle } from './index.mjs';
3
3
  import { isWaapiSupportedEasing } from './easing.mjs';
4
4
  import { supports } from './supports.mjs';
5
5
  import { getFinalKeyframe } from './utils/get-final-keyframe.mjs';
6
6
  import { animateValue } from '../js/index.mjs';
7
- import { millisecondsToSeconds, secondsToMilliseconds } from '../../utils/time-conversion.mjs';
7
+ import { millisecondsToSeconds, secondsToMilliseconds } from '../../../utils/time-conversion.mjs';
8
8
 
9
9
  /**
10
10
  * A list of values that can be hardware-accelerated.
@@ -39,6 +39,23 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
39
39
  options.type !== "inertia";
40
40
  if (!canAccelerateAnimation)
41
41
  return false;
42
+ /**
43
+ * TODO: Unify with js/index
44
+ */
45
+ let resolveFinishedPromise;
46
+ let currentFinishedPromise;
47
+ /**
48
+ * Create a new finished Promise every time we enter the
49
+ * finished state and resolve the old Promise. This is
50
+ * WAAPI-compatible behaviour.
51
+ */
52
+ const updateFinishedPromise = () => {
53
+ currentFinishedPromise = new Promise((resolve) => {
54
+ resolveFinishedPromise = resolve;
55
+ });
56
+ };
57
+ // Create the first finished promise
58
+ updateFinishedPromise();
42
59
  let { keyframes, duration = 300, ease } = options;
43
60
  /**
44
61
  * If this animation needs pre-generated keyframes then generate.
@@ -90,13 +107,15 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
90
107
  value.set(getFinalKeyframe(keyframes, options));
91
108
  sync.update(() => animation.cancel());
92
109
  onComplete && onComplete();
110
+ resolveFinishedPromise();
111
+ updateFinishedPromise();
93
112
  };
94
113
  /**
95
114
  * Animation interrupt callback.
96
115
  */
97
116
  return {
98
117
  then(resolve, reject) {
99
- return animation.finished.then(resolve, reject);
118
+ return currentFinishedPromise.then(resolve, reject);
100
119
  },
101
120
  get time() {
102
121
  return millisecondsToSeconds(animation.currentTime || 0);
@@ -1,7 +1,10 @@
1
1
  import { invariant } from '../../utils/errors.mjs';
2
- import { animateVisualElement, stopAnimation } from '../../render/utils/animation.mjs';
3
2
  import { setValues } from '../../render/utils/setters.mjs';
3
+ import { animateVisualElement } from '../interfaces/visual-element.mjs';
4
4
 
5
+ function stopAnimation(visualElement) {
6
+ visualElement.values.forEach((value) => value.stop());
7
+ }
5
8
  /**
6
9
  * @public
7
10
  */
@@ -1,10 +1,10 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import { useConstant } from '../../utils/use-constant.mjs';
3
3
  import { getOrigin, checkTargetForNewValues } from '../../render/utils/setters.mjs';
4
- import { animateVisualElement } from '../../render/utils/animation.mjs';
5
4
  import { makeUseVisualState } from '../../motion/utils/use-visual-state.mjs';
6
5
  import { createBox } from '../../projection/geometry/models.mjs';
7
6
  import { VisualElement } from '../../render/VisualElement.mjs';
7
+ import { animateVisualElement } from '../interfaces/visual-element.mjs';
8
8
 
9
9
  const createObject = () => ({});
10
10
  class StateVisualElement extends VisualElement {
@@ -1,15 +1,15 @@
1
- import { warning } from '../utils/errors.mjs';
2
- import { secondsToMilliseconds } from '../utils/time-conversion.mjs';
3
- import { instantAnimationState } from '../utils/use-instant-transition-state.mjs';
4
- import { createAcceleratedAnimation } from './waapi/create-accelerated-animation.mjs';
5
- import { createInstantAnimation } from './create-instant-animation.mjs';
6
- import { getDefaultTransition } from './utils/default-transitions.mjs';
7
- import { isAnimatable } from './utils/is-animatable.mjs';
8
- import { getKeyframes } from './utils/keyframes.mjs';
9
- import { getValueTransition, isTransitionDefined } from './utils/transitions.mjs';
10
- import { animateValue } from './js/index.mjs';
1
+ import { warning } from '../../utils/errors.mjs';
2
+ import { secondsToMilliseconds } from '../../utils/time-conversion.mjs';
3
+ import { instantAnimationState } from '../../utils/use-instant-transition-state.mjs';
4
+ import { createAcceleratedAnimation } from '../animators/waapi/create-accelerated-animation.mjs';
5
+ import { createInstantAnimation } from '../animators/instant.mjs';
6
+ import { getDefaultTransition } from '../utils/default-transitions.mjs';
7
+ import { isAnimatable } from '../utils/is-animatable.mjs';
8
+ import { getKeyframes } from '../utils/keyframes.mjs';
9
+ import { getValueTransition, isTransitionDefined } from '../utils/transitions.mjs';
10
+ import { animateValue } from '../animators/js/index.mjs';
11
11
 
12
- const createMotionValueAnimation = (valueName, value, target, transition = {}) => {
12
+ const animateMotionValue = (valueName, value, target, transition = {}) => {
13
13
  return (onComplete) => {
14
14
  const valueTransition = getValueTransition(transition, valueName) || {};
15
15
  /**
@@ -97,4 +97,4 @@ const createMotionValueAnimation = (valueName, value, target, transition = {}) =
97
97
  };
98
98
  };
99
99
 
100
- export { createMotionValueAnimation };
100
+ export { animateMotionValue };
@@ -0,0 +1,11 @@
1
+ import { animateMotionValue } from './motion-value.mjs';
2
+ import { motionValue } from '../../value/index.mjs';
3
+ import { isMotionValue } from '../../value/utils/is-motion-value.mjs';
4
+
5
+ function animateSingleValue(value, keyframes, options) {
6
+ const motionValue$1 = isMotionValue(value) ? value : motionValue(value);
7
+ motionValue$1.start(animateMotionValue("", motionValue$1, keyframes, options));
8
+ return motionValue$1.animation;
9
+ }
10
+
11
+ export { animateSingleValue };
@@ -0,0 +1,66 @@
1
+ import { sync } from '../../frameloop/index.mjs';
2
+ import { transformProps } from '../../render/html/utils/transform.mjs';
3
+ import { optimizedAppearDataAttribute } from '../optimized-appear/data-id.mjs';
4
+ import { animateMotionValue } from './motion-value.mjs';
5
+ import { isWillChangeMotionValue } from '../../value/use-will-change/is.mjs';
6
+ import { setTarget } from '../../render/utils/setters.mjs';
7
+
8
+ /**
9
+ * Decide whether we should block this animation. Previously, we achieved this
10
+ * just by checking whether the key was listed in protectedKeys, but this
11
+ * posed problems if an animation was triggered by afterChildren and protectedKeys
12
+ * had been set to true in the meantime.
13
+ */
14
+ function shouldBlockAnimation({ protectedKeys, needsAnimating }, key) {
15
+ const shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
16
+ needsAnimating[key] = false;
17
+ return shouldBlock;
18
+ }
19
+ function animateTarget(visualElement, definition, { delay = 0, transitionOverride, type } = {}) {
20
+ let { transition = visualElement.getDefaultTransition(), transitionEnd, ...target } = visualElement.makeTargetAnimatable(definition);
21
+ const willChange = visualElement.getValue("willChange");
22
+ if (transitionOverride)
23
+ transition = transitionOverride;
24
+ const animations = [];
25
+ const animationTypeState = type &&
26
+ visualElement.animationState &&
27
+ visualElement.animationState.getState()[type];
28
+ for (const key in target) {
29
+ const value = visualElement.getValue(key);
30
+ const valueTarget = target[key];
31
+ if (!value ||
32
+ valueTarget === undefined ||
33
+ (animationTypeState &&
34
+ shouldBlockAnimation(animationTypeState, key))) {
35
+ continue;
36
+ }
37
+ const valueTransition = { delay, elapsed: 0, ...transition };
38
+ /**
39
+ * If this is the first time a value is being animated, check
40
+ * to see if we're handling off from an existing animation.
41
+ */
42
+ if (window.HandoffAppearAnimations && !value.hasAnimated) {
43
+ const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
44
+ if (appearId) {
45
+ valueTransition.elapsed = window.HandoffAppearAnimations(appearId, key, value, sync);
46
+ }
47
+ }
48
+ value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
49
+ ? { type: false }
50
+ : valueTransition));
51
+ const animation = value.animation;
52
+ if (isWillChangeMotionValue(willChange)) {
53
+ willChange.add(key);
54
+ animation.then(() => willChange.remove(key));
55
+ }
56
+ animations.push(animation);
57
+ }
58
+ if (transitionEnd) {
59
+ Promise.all(animations).then(() => {
60
+ transitionEnd && setTarget(visualElement, transitionEnd);
61
+ });
62
+ }
63
+ return animations;
64
+ }
65
+
66
+ export { animateTarget };
@@ -0,0 +1,63 @@
1
+ import { resolveVariant } from '../../render/utils/resolve-dynamic-variants.mjs';
2
+ import { animateTarget } from './visual-element-target.mjs';
3
+
4
+ function animateVariant(visualElement, variant, options = {}) {
5
+ const resolved = resolveVariant(visualElement, variant, options.custom);
6
+ let { transition = visualElement.getDefaultTransition() || {} } = resolved || {};
7
+ if (options.transitionOverride) {
8
+ transition = options.transitionOverride;
9
+ }
10
+ /**
11
+ * If we have a variant, create a callback that runs it as an animation.
12
+ * Otherwise, we resolve a Promise immediately for a composable no-op.
13
+ */
14
+ const getAnimation = resolved
15
+ ? () => Promise.all(animateTarget(visualElement, resolved, options))
16
+ : () => Promise.resolve();
17
+ /**
18
+ * If we have children, create a callback that runs all their animations.
19
+ * Otherwise, we resolve a Promise immediately for a composable no-op.
20
+ */
21
+ const getChildAnimations = visualElement.variantChildren && visualElement.variantChildren.size
22
+ ? (forwardDelay = 0) => {
23
+ const { delayChildren = 0, staggerChildren, staggerDirection, } = transition;
24
+ return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
25
+ }
26
+ : () => Promise.resolve();
27
+ /**
28
+ * If the transition explicitly defines a "when" option, we need to resolve either
29
+ * this animation or all children animations before playing the other.
30
+ */
31
+ const { when } = transition;
32
+ if (when) {
33
+ const [first, last] = when === "beforeChildren"
34
+ ? [getAnimation, getChildAnimations]
35
+ : [getChildAnimations, getAnimation];
36
+ return first().then(() => last());
37
+ }
38
+ else {
39
+ return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
40
+ }
41
+ }
42
+ function animateChildren(visualElement, variant, delayChildren = 0, staggerChildren = 0, staggerDirection = 1, options) {
43
+ const animations = [];
44
+ const maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
45
+ const generateStaggerDuration = staggerDirection === 1
46
+ ? (i = 0) => i * staggerChildren
47
+ : (i = 0) => maxStaggerDuration - i * staggerChildren;
48
+ Array.from(visualElement.variantChildren)
49
+ .sort(sortByTreeOrder)
50
+ .forEach((child, i) => {
51
+ child.notify("AnimationStart", variant);
52
+ animations.push(animateVariant(child, variant, {
53
+ ...options,
54
+ delay: delayChildren + generateStaggerDuration(i),
55
+ }).then(() => child.notify("AnimationComplete", variant)));
56
+ });
57
+ return Promise.all(animations);
58
+ }
59
+ function sortByTreeOrder(a, b) {
60
+ return a.sortNodePosition(b);
61
+ }
62
+
63
+ export { animateVariant, sortByTreeOrder };
@@ -0,0 +1,24 @@
1
+ import { resolveVariant } from '../../render/utils/resolve-dynamic-variants.mjs';
2
+ import { animateTarget } from './visual-element-target.mjs';
3
+ import { animateVariant } from './visual-element-variant.mjs';
4
+
5
+ function animateVisualElement(visualElement, definition, options = {}) {
6
+ visualElement.notify("AnimationStart", definition);
7
+ let animation;
8
+ if (Array.isArray(definition)) {
9
+ const animations = definition.map((variant) => animateVariant(visualElement, variant, options));
10
+ animation = Promise.all(animations);
11
+ }
12
+ else if (typeof definition === "string") {
13
+ animation = animateVariant(visualElement, definition, options);
14
+ }
15
+ else {
16
+ const resolvedDefinition = typeof definition === "function"
17
+ ? resolveVariant(visualElement, definition, options.custom)
18
+ : definition;
19
+ animation = Promise.all(animateTarget(visualElement, resolvedDefinition, options));
20
+ }
21
+ return animation.then(() => visualElement.notify("AnimationComplete", definition));
22
+ }
23
+
24
+ export { animateVisualElement };
@@ -1,5 +1,5 @@
1
1
  import { appearStoreId } from './store-id.mjs';
2
- import { animateStyle } from '../waapi/index.mjs';
2
+ import { animateStyle } from '../animators/waapi/index.mjs';
3
3
  import { optimizedAppearDataId } from './data-id.mjs';
4
4
  import { handoffOptimizedAppearAnimation } from './handoff.mjs';
5
5
  import { appearAnimationStore } from './store.mjs';
@@ -0,0 +1,32 @@
1
+ import { isSVGElement } from '../../render/dom/utils/is-svg-element.mjs';
2
+ import { SVGVisualElement } from '../../render/svg/SVGVisualElement.mjs';
3
+ import { HTMLVisualElement } from '../../render/html/HTMLVisualElement.mjs';
4
+ import { visualElementStore } from '../../render/store.mjs';
5
+
6
+ function createVisualElement(element) {
7
+ const options = {
8
+ presenceContext: null,
9
+ props: {},
10
+ visualState: {
11
+ renderState: {
12
+ transform: {},
13
+ transformOrigin: {},
14
+ style: {},
15
+ vars: {},
16
+ attrs: {},
17
+ },
18
+ latestValues: {},
19
+ },
20
+ };
21
+ const node = isSVGElement(element)
22
+ ? new SVGVisualElement(options, {
23
+ enableHardwareAcceleration: false,
24
+ })
25
+ : new HTMLVisualElement(options, {
26
+ enableHardwareAcceleration: true,
27
+ });
28
+ node.mount(element);
29
+ visualElementStore.set(element, node);
30
+ }
31
+
32
+ export { createVisualElement };
@@ -0,0 +1,5 @@
1
+ function isDOMKeyframes(keyframes) {
2
+ return typeof keyframes === "object" && !Array.isArray(keyframes);
3
+ }
4
+
5
+ export { isDOMKeyframes };
@@ -13,7 +13,7 @@ import { addDomEvent } from '../../events/add-dom-event.mjs';
13
13
  import { calcLength } from '../../projection/geometry/delta-calc.mjs';
14
14
  import { mix } from '../../utils/mix.mjs';
15
15
  import { percent } from '../../value/types/numbers/units.mjs';
16
- import { createMotionValueAnimation } from '../../animation/index.mjs';
16
+ import { animateMotionValue } from '../../animation/interfaces/motion-value.mjs';
17
17
  import { sync } from '../../frameloop/index.mjs';
18
18
 
19
19
  const elementDragControls = new WeakMap();
@@ -278,7 +278,7 @@ class VisualElementDragControls {
278
278
  }
279
279
  startAxisValueAnimation(axis, transition) {
280
280
  const axisValue = this.getAxisMotionValue(axis);
281
- return axisValue.start(createMotionValueAnimation(axis, axisValue, 0, transition));
281
+ return axisValue.start(animateMotionValue(axis, axisValue, 0, transition));
282
282
  }
283
283
  stopAnimation() {
284
284
  eachAxis((axis) => this.getAxisMotionValue(axis).stop());
package/dist/es/index.mjs CHANGED
@@ -24,7 +24,7 @@ export { useReducedMotionConfig } from './utils/reduced-motion/use-reduced-motio
24
24
  export { animationControls } from './animation/hooks/animation-controls.mjs';
25
25
  export { useAnimation, useAnimationControls } from './animation/hooks/use-animation.mjs';
26
26
  export { useAnimationFrame } from './utils/use-animation-frame.mjs';
27
- export { animateVisualElement } from './render/utils/animation.mjs';
27
+ export { animateVisualElement } from './animation/interfaces/visual-element.mjs';
28
28
  export { useCycle } from './utils/use-cycle.mjs';
29
29
  export { isValidMotionProp } from './motion/utils/valid-prop.mjs';
30
30
  export { useIsPresent, usePresence } from './components/AnimatePresence/use-presence.mjs';
@@ -40,7 +40,7 @@ export { useInstantTransition } from './utils/use-instant-transition.mjs';
40
40
  export { useInstantLayoutTransition } from './projection/use-instant-layout-transition.mjs';
41
41
  export { useResetProjection } from './projection/use-reset-projection.mjs';
42
42
  export { buildTransform } from './render/html/utils/build-transform.mjs';
43
- export { animateValue } from './animation/js/index.mjs';
43
+ export { animateValue } from './animation/animators/js/index.mjs';
44
44
  export { color } from './value/types/color/index.mjs';
45
45
  export { complex } from './value/types/complex/index.mjs';
46
46
  export { px } from './value/types/numbers/units.mjs';