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.
- package/dist/cjs/dom-entry.js +1 -1
- package/dist/cjs/index.js +135 -1958
- package/dist/cjs/{wrap-196fd3c5.js → wrap-58c66ad3.js} +3790 -1847
- package/dist/dom-entry.d.ts +43 -34
- package/dist/es/animation/animate.mjs +38 -34
- package/dist/es/animation/{create-instant-animation.mjs → animators/instant.mjs} +5 -2
- package/dist/es/animation/{js → animators/js}/driver-frameloop.mjs +2 -2
- package/dist/es/animation/{js → animators/js}/index.mjs +10 -9
- package/dist/es/animation/{waapi → animators/waapi}/create-accelerated-animation.mjs +22 -3
- package/dist/es/animation/hooks/animation-controls.mjs +4 -1
- package/dist/es/animation/hooks/use-animated-state.mjs +1 -1
- package/dist/es/animation/{index.mjs → interfaces/motion-value.mjs} +12 -12
- package/dist/es/animation/interfaces/single-value.mjs +11 -0
- package/dist/es/animation/interfaces/visual-element-target.mjs +66 -0
- package/dist/es/animation/interfaces/visual-element-variant.mjs +63 -0
- package/dist/es/animation/interfaces/visual-element.mjs +24 -0
- package/dist/es/animation/optimized-appear/start.mjs +1 -1
- package/dist/es/animation/utils/create-visual-element.mjs +32 -0
- package/dist/es/animation/utils/is-dom-keyframes.mjs +5 -0
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +2 -2
- package/dist/es/index.mjs +2 -2
- package/dist/es/projection/node/create-projection-node.mjs +5 -4
- package/dist/es/render/VisualElement.mjs +3 -0
- package/dist/es/render/dom/utils/is-svg-element.mjs +5 -0
- package/dist/es/render/store.mjs +3 -0
- package/dist/es/render/utils/animation-state.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/utils/interpolate.mjs +6 -0
- package/dist/es/value/index.mjs +1 -1
- package/dist/es/value/use-spring.mjs +1 -1
- package/dist/framer-motion.dev.js +4948 -4872
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +57 -51
- package/dist/projection.dev.js +4982 -5008
- package/dist/three-entry.d.ts +6 -10
- package/package.json +5 -5
- package/dist/es/render/utils/animation.mjs +0 -145
- /package/dist/es/animation/{waapi → animators/waapi}/easing.mjs +0 -0
- /package/dist/es/animation/{waapi → animators/waapi}/index.mjs +0 -0
- /package/dist/es/animation/{waapi → animators/waapi}/supports.mjs +0 -0
- /package/dist/es/animation/{waapi → animators/waapi}/utils/get-final-keyframe.mjs +0 -0
package/dist/dom-entry.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
1009
|
+
* Animate a single value
|
|
977
1010
|
*/
|
|
978
|
-
|
|
979
|
-
|
|
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
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
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>(
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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 '
|
|
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: () =>
|
|
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 '
|
|
2
|
-
import { frameData } from '
|
|
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 '
|
|
2
|
-
import { spring } from '
|
|
3
|
-
import { inertia } from '
|
|
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 '
|
|
6
|
-
import { clamp } from '
|
|
7
|
-
import { millisecondsToSeconds, secondsToMilliseconds } from '
|
|
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
|
-
|
|
209
|
+
newTime = secondsToMilliseconds(newTime);
|
|
210
|
+
time = newTime;
|
|
210
211
|
if (holdTime !== null || !animationDriver) {
|
|
211
|
-
holdTime =
|
|
212
|
+
holdTime = newTime;
|
|
212
213
|
}
|
|
213
214
|
else {
|
|
214
|
-
startTime = animationDriver.now() -
|
|
215
|
+
startTime = animationDriver.now() - newTime;
|
|
215
216
|
}
|
|
216
217
|
},
|
|
217
218
|
play,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { sync } from '
|
|
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 '
|
|
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
|
|
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 '
|
|
2
|
-
import { secondsToMilliseconds } from '
|
|
3
|
-
import { instantAnimationState } from '
|
|
4
|
-
import { createAcceleratedAnimation } from '
|
|
5
|
-
import { createInstantAnimation } from '
|
|
6
|
-
import { getDefaultTransition } from '
|
|
7
|
-
import { isAnimatable } from '
|
|
8
|
-
import { getKeyframes } from '
|
|
9
|
-
import { getValueTransition, isTransitionDefined } from '
|
|
10
|
-
import { animateValue } from '
|
|
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
|
|
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 {
|
|
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 };
|
|
@@ -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 {
|
|
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(
|
|
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 './
|
|
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';
|