motion 12.7.4 → 12.7.5-alpha.1
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/README.md +1 -1
- package/dist/cjs/debug.js +22 -14
- package/dist/cjs/index.js +4123 -3634
- package/dist/cjs/mini.js +403 -324
- package/dist/cjs/react-client.js +3150 -3245
- package/dist/cjs/react-m.js +169 -166
- package/dist/cjs/react-mini.js +330 -251
- package/dist/es/framer-motion/dist/es/animation/animate/sequence.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/animate-elements.mjs +81 -9
- package/dist/es/framer-motion/dist/es/animation/interfaces/motion-value.mjs +11 -30
- package/dist/es/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/store-id.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/sequence/create.mjs +3 -3
- package/dist/es/framer-motion/dist/es/animation/sequence/utils/edit.mjs +2 -2
- package/dist/es/framer-motion/dist/es/animation/utils/default-transitions.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/utils/stagger.mjs +1 -1
- package/dist/es/framer-motion/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
- package/dist/es/framer-motion/dist/es/gestures/drag/VisualElementDragControls.mjs +2 -2
- package/dist/es/framer-motion/dist/es/gestures/drag/utils/constraints.mjs +2 -2
- package/dist/es/framer-motion/dist/es/gestures/focus.mjs +1 -1
- package/dist/es/framer-motion/dist/es/gestures/pan/PanSession.mjs +1 -1
- package/dist/es/framer-motion/dist/es/motion/utils/is-forced-motion-value.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/animation/mix-values.mjs +3 -3
- package/dist/es/framer-motion/dist/es/projection/geometry/delta-apply.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/geometry/delta-calc.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/geometry/delta-remove.mjs +2 -2
- package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +3 -5
- package/dist/es/framer-motion/dist/es/projection/styles/scale-border-radius.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/styles/scale-box-shadow.mjs +2 -2
- package/dist/es/framer-motion/dist/es/projection/styles/scale-correction.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +7 -7
- package/dist/es/framer-motion/dist/es/render/dom/DOMVisualElement.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/dom/scroll/attach-animation.mjs +17 -0
- package/dist/es/framer-motion/dist/es/render/dom/scroll/attach-function.mjs +23 -0
- package/dist/es/framer-motion/dist/es/render/dom/scroll/index.mjs +6 -82
- package/dist/es/framer-motion/dist/es/render/dom/scroll/offsets/index.mjs +3 -3
- package/dist/es/framer-motion/dist/es/render/dom/scroll/utils/get-timeline.mjs +30 -0
- package/dist/es/framer-motion/dist/es/render/html/HTMLVisualElement.mjs +3 -3
- package/dist/es/framer-motion/dist/es/render/html/utils/build-styles.mjs +4 -4
- package/dist/es/framer-motion/dist/es/render/html/utils/build-transform.mjs +3 -3
- package/dist/es/framer-motion/dist/es/render/svg/SVGVisualElement.mjs +2 -2
- package/dist/es/framer-motion/dist/es/render/svg/config-motion.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/svg/utils/path.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/svg/utils/scrape-motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/svg/utils/transform-origin.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/delay.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/transform.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/use-cycle.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/use-instant-transition.mjs +4 -4
- package/dist/es/framer-motion/dist/es/value/use-spring.mjs +2 -2
- package/dist/es/framer-motion/dist/es/value/use-will-change/get-will-change-name.mjs +2 -2
- package/dist/es/motion/lib/index.mjs +109 -26
- package/dist/es/motion/lib/react.mjs +108 -32
- package/dist/es/motion-dom/dist/es/animation/AsyncMotionValueAnimation.mjs +179 -0
- package/dist/es/motion-dom/dist/es/animation/GroupAnimation.mjs +6 -15
- package/dist/es/{framer-motion/dist/es/animation/animators/MainThreadAnimation.mjs → motion-dom/dist/es/animation/JSAnimation.mjs} +107 -156
- package/dist/es/motion-dom/dist/es/animation/NativeAnimation.mjs +64 -67
- package/dist/es/motion-dom/dist/es/animation/NativeAnimationExtended.mjs +65 -0
- package/dist/es/motion-dom/dist/es/animation/NativeAnimationWrapper.mjs +14 -0
- package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation}/drivers/driver-frameloop.mjs +2 -2
- package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/keyframes.mjs +5 -5
- package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/find.mjs +1 -1
- package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/index.mjs +5 -6
- package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation/keyframes}/DOMKeyframesResolver.mjs +9 -8
- package/dist/es/{framer-motion/dist/es/render/utils → motion-dom/dist/es/animation/keyframes}/KeyframesResolver.mjs +28 -35
- package/dist/es/motion-dom/dist/es/animation/keyframes/get-final.mjs +3 -4
- package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/fill.mjs +2 -2
- package/dist/es/motion-dom/dist/es/animation/keyframes/utils/apply-px-defaults.mjs +11 -0
- package/dist/es/motion-dom/dist/es/animation/keyframes/utils/fill-wildcards.mjs +7 -0
- package/dist/es/{framer-motion/dist/es/animation → motion-dom/dist/es/animation/keyframes}/utils/is-none.mjs +1 -1
- package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/animation/keyframes}/utils/make-none-animatable.mjs +1 -1
- package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation/keyframes}/utils/unit-conversion.mjs +2 -2
- package/dist/es/motion-dom/dist/es/animation/utils/WithPromise.mjs +28 -0
- package/dist/es/motion-dom/dist/es/animation/utils/active-animations.mjs +9 -0
- package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation}/utils/can-animate.mjs +3 -3
- package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation}/utils/css-variables-conversion.mjs +2 -2
- package/dist/es/motion-dom/dist/es/animation/utils/replace-transition-type.mjs +18 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/is-supported.mjs +1 -1
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/map-easing.mjs +5 -3
- package/dist/es/motion-dom/dist/es/animation/waapi/start-waapi-animation.mjs +6 -4
- package/dist/es/motion-dom/dist/es/animation/waapi/supports/waapi.mjs +39 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/apply-generator.mjs +2 -1
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/unsupported-easing.mjs +20 -0
- package/dist/es/motion-dom/dist/es/frameloop/batcher.mjs +2 -1
- package/dist/es/motion-dom/dist/es/frameloop/order.mjs +1 -0
- package/dist/es/motion-dom/dist/es/render/dom/is-css-var.mjs +3 -0
- package/dist/es/motion-dom/dist/es/render/dom/style-computed.mjs +10 -0
- package/dist/es/motion-dom/dist/es/render/dom/style-set.mjs +9 -0
- package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/render}/utils/keys-transform.mjs +1 -1
- package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es}/scroll/observe.mjs +1 -1
- package/dist/es/motion-dom/dist/es/stats/index.mjs +2 -0
- package/dist/es/{framer-motion → motion-dom}/dist/es/utils/interpolate.mjs +4 -3
- package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/color.mjs +3 -3
- package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/complex.mjs +5 -5
- package/dist/es/motion-dom/dist/es/value/index.mjs +3 -1
- package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/rgba.mjs +2 -2
- package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types}/dimensions.mjs +3 -3
- package/dist/es/{framer-motion/dist/es/render/dom/value-types/type-int.mjs → motion-dom/dist/es/value/types/int.mjs} +1 -1
- package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/maps}/defaults.mjs +2 -2
- package/dist/es/{framer-motion/dist/es/render/dom/value-types/number-browser.mjs → motion-dom/dist/es/value/types/maps/number.mjs} +13 -3
- package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/maps}/transform.mjs +2 -2
- package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/numbers/index.mjs +1 -1
- package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/numbers/units.mjs +3 -2
- package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/animatable-none.mjs +4 -4
- package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/find.mjs +4 -4
- package/dist/es/motion-dom/dist/es/view/index.mjs +64 -0
- package/dist/es/motion-dom/dist/es/view/queue.mjs +52 -0
- package/dist/es/motion-dom/dist/es/view/start.mjs +155 -0
- package/dist/es/motion-dom/dist/es/view/utils/choose-layer-type.mjs +11 -0
- package/dist/es/motion-dom/dist/es/view/utils/css.mjs +32 -0
- package/dist/es/motion-dom/dist/es/view/utils/get-layer-name.mjs +8 -0
- package/dist/es/motion-dom/dist/es/view/utils/get-view-animations.mjs +12 -0
- package/dist/es/motion-dom/dist/es/view/utils/has-target.mjs +5 -0
- package/dist/es/{framer-motion → motion-utils}/dist/es/easing/cubic-bezier.mjs +1 -1
- package/dist/es/{framer-motion → motion-utils}/dist/es/easing/steps.mjs +1 -1
- package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/get-easing-for-segment.mjs +1 -1
- package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/map.mjs +7 -4
- package/dist/es/motion-utils/dist/es/global-config.mjs +1 -4
- package/dist/es/motion-utils/dist/es/warn-once.mjs +4 -1
- package/dist/motion.dev.js +4122 -3633
- package/dist/motion.js +1 -1
- package/package.json +3 -3
- package/dist/es/framer-motion/dist/es/animation/animators/AcceleratedAnimation.mjs +0 -324
- package/dist/es/framer-motion/dist/es/animation/animators/BaseAnimation.mjs +0 -120
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/utils/supports-waapi.mjs +0 -5
- package/dist/es/framer-motion/dist/es/render/dom/value-types/number.mjs +0 -18
- package/dist/es/framer-motion/dist/es/utils/use-instant-transition-state.mjs +0 -5
- package/dist/es/motion-dom/dist/es/animation/keyframes/hydrate.mjs +0 -26
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/attach-timeline.mjs +0 -6
- package/dist/es/motion-dom/dist/es/render/dom/style.mjs +0 -15
- /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/inertia.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/defaults.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/utils/velocity.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/default.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/time.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/utils/is-animatable.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation}/utils/is-css-variable.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation/waapi}/utils/accelerated-values.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/html/utils → motion-dom/dist/es/render/dom}/parse-transform.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/render}/utils/keys-position.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/immediate.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/index.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/number.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/visibility.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/dom/value-types/type-auto.mjs → motion-dom/dist/es/value/types/auto.mjs} +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/hex.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/value/types/color}/hsla-to-rgba.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/hsla.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/index.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/utils.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/complex/filter.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/complex/index.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types}/test.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/color-regex.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/float-regex.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/get-as-type.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/is-nullish.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/sanitize.mjs +0 -0
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/single-color-regex.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/clamp.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/anticipate.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/back.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/circ.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/ease.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/modifiers/mirror.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/modifiers/reverse.mjs +0 -0
- /package/dist/es/{motion-dom/dist/es → motion-utils/dist/es/easing}/utils/is-bezier-definition.mjs +0 -0
- /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/is-easing-array.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/is-numerical-string.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/is-zero-value-string.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/pipe.mjs +0 -0
- /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/wrap.mjs +0 -0
package/dist/cjs/mini.js
CHANGED
|
@@ -59,187 +59,154 @@ const secondsToMilliseconds = (seconds) => seconds * 1000;
|
|
|
59
59
|
/*#__NO_SIDE_EFFECTS__*/
|
|
60
60
|
const millisecondsToSeconds = (milliseconds) => milliseconds / 1000;
|
|
61
61
|
|
|
62
|
-
const
|
|
62
|
+
const wrap = (min, max, v) => {
|
|
63
|
+
const rangeSize = max - min;
|
|
64
|
+
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
|
|
65
|
+
};
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
get speed() {
|
|
107
|
-
return this.getAll("speed");
|
|
108
|
-
}
|
|
109
|
-
set speed(speed) {
|
|
110
|
-
this.setAll("speed", speed);
|
|
111
|
-
}
|
|
112
|
-
get startTime() {
|
|
113
|
-
return this.getAll("startTime");
|
|
114
|
-
}
|
|
115
|
-
get duration() {
|
|
116
|
-
let max = 0;
|
|
117
|
-
for (let i = 0; i < this.animations.length; i++) {
|
|
118
|
-
max = Math.max(max, this.animations[i].duration);
|
|
119
|
-
}
|
|
120
|
-
return max;
|
|
121
|
-
}
|
|
122
|
-
runAll(methodName) {
|
|
123
|
-
this.animations.forEach((controls) => controls[methodName]());
|
|
124
|
-
}
|
|
125
|
-
flatten() {
|
|
126
|
-
this.runAll("flatten");
|
|
127
|
-
}
|
|
128
|
-
play() {
|
|
129
|
-
this.runAll("play");
|
|
130
|
-
}
|
|
131
|
-
pause() {
|
|
132
|
-
this.runAll("pause");
|
|
133
|
-
}
|
|
134
|
-
cancel() {
|
|
135
|
-
this.runAll("cancel");
|
|
67
|
+
const isEasingArray = (ease) => {
|
|
68
|
+
return Array.isArray(ease) && typeof ease[0] !== "number";
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function getEasingForSegment(easing, i) {
|
|
72
|
+
return isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
Value in range from progress
|
|
79
|
+
|
|
80
|
+
Given a lower limit and an upper limit, we return the value within
|
|
81
|
+
that range as expressed by progress (usually a number from 0 to 1)
|
|
82
|
+
|
|
83
|
+
So progress = 0.5 would change
|
|
84
|
+
|
|
85
|
+
from -------- to
|
|
86
|
+
|
|
87
|
+
to
|
|
88
|
+
|
|
89
|
+
from ---- to
|
|
90
|
+
|
|
91
|
+
E.g. from = 10, to = 20, progress = 0.5 => 15
|
|
92
|
+
|
|
93
|
+
@param [number]: Lower limit of range
|
|
94
|
+
@param [number]: Upper limit of range
|
|
95
|
+
@param [number]: The progress between lower and upper limits expressed 0-1
|
|
96
|
+
@return [number]: Value as calculated from progress within range (not limited within range)
|
|
97
|
+
*/
|
|
98
|
+
const mixNumber = (from, to, progress) => {
|
|
99
|
+
return from + (to - from) * progress;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const generateLinearEasing = (easing, duration, // as milliseconds
|
|
103
|
+
resolution = 10 // as milliseconds
|
|
104
|
+
) => {
|
|
105
|
+
let points = "";
|
|
106
|
+
const numPoints = Math.max(Math.round(duration / resolution), 2);
|
|
107
|
+
for (let i = 0; i < numPoints; i++) {
|
|
108
|
+
points += easing(i / (numPoints - 1)) + ", ";
|
|
136
109
|
}
|
|
137
|
-
|
|
138
|
-
|
|
110
|
+
return `linear(${points.substring(0, points.length - 2)})`;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Implement a practical max duration for keyframe generation
|
|
115
|
+
* to prevent infinite loops
|
|
116
|
+
*/
|
|
117
|
+
const maxGeneratorDuration = 20000;
|
|
118
|
+
function calcGeneratorDuration(generator) {
|
|
119
|
+
let duration = 0;
|
|
120
|
+
const timeStep = 50;
|
|
121
|
+
let state = generator.next(duration);
|
|
122
|
+
while (!state.done && duration < maxGeneratorDuration) {
|
|
123
|
+
duration += timeStep;
|
|
124
|
+
state = generator.next(duration);
|
|
139
125
|
}
|
|
126
|
+
return duration >= maxGeneratorDuration ? Infinity : duration;
|
|
140
127
|
}
|
|
141
128
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Create a progress => progress easing function from a generator.
|
|
131
|
+
*/
|
|
132
|
+
function createGeneratorEasing(options, scale = 100, createGenerator) {
|
|
133
|
+
const generator = createGenerator({ ...options, keyframes: [0, scale] });
|
|
134
|
+
const duration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
135
|
+
return {
|
|
136
|
+
type: "keyframes",
|
|
137
|
+
ease: (progress) => {
|
|
138
|
+
return generator.next(duration * progress).value / scale;
|
|
139
|
+
},
|
|
140
|
+
duration: millisecondsToSeconds(duration),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function fillOffset(offset, remaining) {
|
|
145
|
+
const min = offset[offset.length - 1];
|
|
146
|
+
for (let i = 1; i <= remaining; i++) {
|
|
147
|
+
const offsetProgress = progress(0, remaining, i);
|
|
148
|
+
offset.push(mixNumber(min, 1, offsetProgress));
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
: (element.style[name] = value);
|
|
154
|
-
},
|
|
155
|
-
get: (element, name) => {
|
|
156
|
-
return isCSSVar(name)
|
|
157
|
-
? element.style.getPropertyValue(name)
|
|
158
|
-
: element.style[name];
|
|
159
|
-
},
|
|
160
|
-
};
|
|
152
|
+
function defaultOffset(arr) {
|
|
153
|
+
const offset = [0];
|
|
154
|
+
fillOffset(offset, arr.length - 1);
|
|
155
|
+
return offset;
|
|
156
|
+
}
|
|
161
157
|
|
|
162
158
|
const isNotNull = (value) => value !== null;
|
|
163
|
-
function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe) {
|
|
159
|
+
function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe, speed = 1) {
|
|
164
160
|
const resolvedKeyframes = keyframes.filter(isNotNull);
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
: resolvedKeyframes.length - 1;
|
|
161
|
+
const useFirstKeyframe = speed < 0 || (repeat && repeatType !== "loop" && repeat % 2 === 1);
|
|
162
|
+
const index = useFirstKeyframe ? 0 : resolvedKeyframes.length - 1;
|
|
168
163
|
return !index || finalKeyframe === undefined
|
|
169
164
|
? resolvedKeyframes[index]
|
|
170
165
|
: finalKeyframe;
|
|
171
166
|
}
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
class WithPromise {
|
|
169
|
+
constructor() {
|
|
170
|
+
this.count = 0;
|
|
171
|
+
this.updateFinished();
|
|
176
172
|
}
|
|
177
|
-
|
|
178
|
-
return
|
|
173
|
+
get finished() {
|
|
174
|
+
return this._finished;
|
|
179
175
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
"borderWidth",
|
|
186
|
-
"borderTopWidth",
|
|
187
|
-
"borderRightWidth",
|
|
188
|
-
"borderBottomWidth",
|
|
189
|
-
"borderLeftWidth",
|
|
190
|
-
"borderRadius",
|
|
191
|
-
"radius",
|
|
192
|
-
"borderTopLeftRadius",
|
|
193
|
-
"borderTopRightRadius",
|
|
194
|
-
"borderBottomRightRadius",
|
|
195
|
-
"borderBottomLeftRadius",
|
|
196
|
-
// Positioning props
|
|
197
|
-
"width",
|
|
198
|
-
"maxWidth",
|
|
199
|
-
"height",
|
|
200
|
-
"maxHeight",
|
|
201
|
-
"top",
|
|
202
|
-
"right",
|
|
203
|
-
"bottom",
|
|
204
|
-
"left",
|
|
205
|
-
// Spacing props
|
|
206
|
-
"padding",
|
|
207
|
-
"paddingTop",
|
|
208
|
-
"paddingRight",
|
|
209
|
-
"paddingBottom",
|
|
210
|
-
"paddingLeft",
|
|
211
|
-
"margin",
|
|
212
|
-
"marginTop",
|
|
213
|
-
"marginRight",
|
|
214
|
-
"marginBottom",
|
|
215
|
-
"marginLeft",
|
|
216
|
-
// Misc
|
|
217
|
-
"backgroundPositionX",
|
|
218
|
-
"backgroundPositionY",
|
|
219
|
-
]);
|
|
220
|
-
|
|
221
|
-
function hydrateKeyframes(element, name, keyframes, pseudoElement) {
|
|
222
|
-
if (!Array.isArray(keyframes)) {
|
|
223
|
-
keyframes = [keyframes];
|
|
176
|
+
updateFinished() {
|
|
177
|
+
this.count++;
|
|
178
|
+
this._finished = new Promise((resolve) => {
|
|
179
|
+
this.resolve = resolve;
|
|
180
|
+
});
|
|
224
181
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
keyframes[i] =
|
|
228
|
-
i === 0 && !pseudoElement
|
|
229
|
-
? style.get(element, name)
|
|
230
|
-
: keyframes[i - 1];
|
|
231
|
-
}
|
|
232
|
-
if (typeof keyframes[i] === "number" && pxValues.has(name)) {
|
|
233
|
-
keyframes[i] = keyframes[i] + "px";
|
|
234
|
-
}
|
|
182
|
+
notifyFinished() {
|
|
183
|
+
this.resolve();
|
|
235
184
|
}
|
|
236
|
-
|
|
237
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Allows the animation to be awaited.
|
|
187
|
+
*
|
|
188
|
+
* @deprecated Use `finished` instead.
|
|
189
|
+
*/
|
|
190
|
+
then(onResolve, onReject) {
|
|
191
|
+
return this.finished.then(onResolve, onReject);
|
|
238
192
|
}
|
|
239
|
-
return keyframes;
|
|
240
193
|
}
|
|
241
194
|
|
|
242
|
-
|
|
195
|
+
function fillWildcards(keyframes) {
|
|
196
|
+
for (let i = 1; i < keyframes.length; i++) {
|
|
197
|
+
keyframes[i] ?? (keyframes[i] = keyframes[i - 1]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const isCSSVar = (name) => name.startsWith("--");
|
|
202
|
+
|
|
203
|
+
function setStyle(element, name, value) {
|
|
204
|
+
isCSSVar(name)
|
|
205
|
+
? element.style.setProperty(name, value)
|
|
206
|
+
: (element.style[name] = value);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const supportsScrollTimeline = /* @__PURE__ */ memo(() => window.ScrollTimeline !== undefined);
|
|
243
210
|
|
|
244
211
|
/**
|
|
245
212
|
* Add the ability for test suites to manually set support flags
|
|
@@ -264,17 +231,6 @@ const supportsLinearEasing = /*@__PURE__*/ memoSupports(() => {
|
|
|
264
231
|
return true;
|
|
265
232
|
}, "linearEasing");
|
|
266
233
|
|
|
267
|
-
const generateLinearEasing = (easing, duration, // as milliseconds
|
|
268
|
-
resolution = 10 // as milliseconds
|
|
269
|
-
) => {
|
|
270
|
-
let points = "";
|
|
271
|
-
const numPoints = Math.max(Math.round(duration / resolution), 2);
|
|
272
|
-
for (let i = 0; i < numPoints; i++) {
|
|
273
|
-
points += easing(i / (numPoints - 1)) + ", ";
|
|
274
|
-
}
|
|
275
|
-
return `linear(${points.substring(0, points.length - 2)})`;
|
|
276
|
-
};
|
|
277
|
-
|
|
278
234
|
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
279
235
|
|
|
280
236
|
const supportedWaapiEasing = {
|
|
@@ -293,8 +249,10 @@ function mapEasingToNativeEasing(easing, duration) {
|
|
|
293
249
|
if (!easing) {
|
|
294
250
|
return undefined;
|
|
295
251
|
}
|
|
296
|
-
else if (typeof easing === "function"
|
|
297
|
-
return
|
|
252
|
+
else if (typeof easing === "function") {
|
|
253
|
+
return supportsLinearEasing()
|
|
254
|
+
? generateLinearEasing(easing, duration)
|
|
255
|
+
: "ease-out";
|
|
298
256
|
}
|
|
299
257
|
else if (isBezierDefinition(easing)) {
|
|
300
258
|
return cubicBezierAsString(easing);
|
|
@@ -308,7 +266,7 @@ function mapEasingToNativeEasing(easing, duration) {
|
|
|
308
266
|
}
|
|
309
267
|
}
|
|
310
268
|
|
|
311
|
-
function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "
|
|
269
|
+
function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "easeOut", times, } = {}, pseudoElement = undefined) {
|
|
312
270
|
const keyframeOptions = {
|
|
313
271
|
[valueName]: keyframes,
|
|
314
272
|
};
|
|
@@ -320,15 +278,17 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
|
|
|
320
278
|
*/
|
|
321
279
|
if (Array.isArray(easing))
|
|
322
280
|
keyframeOptions.easing = easing;
|
|
323
|
-
const
|
|
281
|
+
const options = {
|
|
324
282
|
delay,
|
|
325
283
|
duration,
|
|
326
284
|
easing: !Array.isArray(easing) ? easing : "linear",
|
|
327
285
|
fill: "both",
|
|
328
286
|
iterations: repeat + 1,
|
|
329
287
|
direction: repeatType === "reverse" ? "alternate" : "normal",
|
|
330
|
-
|
|
331
|
-
|
|
288
|
+
};
|
|
289
|
+
if (pseudoElement)
|
|
290
|
+
options.pseudoElement = pseudoElement;
|
|
291
|
+
const animation = element.animate(keyframeOptions, options);
|
|
332
292
|
return animation;
|
|
333
293
|
}
|
|
334
294
|
|
|
@@ -337,7 +297,7 @@ function isGenerator(type) {
|
|
|
337
297
|
}
|
|
338
298
|
|
|
339
299
|
function applyGeneratorOptions({ type, ...options }) {
|
|
340
|
-
if (isGenerator(type)) {
|
|
300
|
+
if (isGenerator(type) && supportsLinearEasing()) {
|
|
341
301
|
return type.applyToOptions(options);
|
|
342
302
|
}
|
|
343
303
|
else {
|
|
@@ -347,86 +307,81 @@ function applyGeneratorOptions({ type, ...options }) {
|
|
|
347
307
|
return options;
|
|
348
308
|
}
|
|
349
309
|
|
|
350
|
-
const animationMaps = new WeakMap();
|
|
351
|
-
const animationMapKey = (name, pseudoElement) => `${name}:${pseudoElement}`;
|
|
352
|
-
function getAnimationMap(element) {
|
|
353
|
-
const map = animationMaps.get(element) || new Map();
|
|
354
|
-
animationMaps.set(element, map);
|
|
355
|
-
return map;
|
|
356
|
-
}
|
|
357
310
|
/**
|
|
358
311
|
* NativeAnimation implements AnimationPlaybackControls for the browser's Web Animations API.
|
|
359
312
|
*/
|
|
360
|
-
class NativeAnimation {
|
|
313
|
+
class NativeAnimation extends WithPromise {
|
|
361
314
|
constructor(options) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if ("animation" in options) {
|
|
367
|
-
this.animation = options.animation;
|
|
315
|
+
super();
|
|
316
|
+
this.finishedTime = null;
|
|
317
|
+
this.isStopped = false;
|
|
318
|
+
if (!options)
|
|
368
319
|
return;
|
|
369
|
-
}
|
|
370
|
-
const { element, name, keyframes: unresolvedKeyframes, pseudoElement, allowFlatten = false, } = options;
|
|
371
|
-
let { transition } = options;
|
|
320
|
+
const { element, name, keyframes, pseudoElement, allowFlatten = false, finalKeyframe, } = options;
|
|
372
321
|
this.isPseudoElement = Boolean(pseudoElement);
|
|
373
322
|
this.allowFlatten = allowFlatten;
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
* TODO: Check for VisualElement before using animation state. This is a fallback
|
|
378
|
-
* for mini animate(). Do this when implementing NativeAnimationExtended.
|
|
379
|
-
*/
|
|
380
|
-
const animationMap = getAnimationMap(element);
|
|
381
|
-
const key = animationMapKey(name, pseudoElement || "");
|
|
382
|
-
const currentAnimation = animationMap.get(key);
|
|
383
|
-
currentAnimation && currentAnimation.stop();
|
|
384
|
-
/**
|
|
385
|
-
* TODO: If these keyframes aren't correctly hydrated then we want to throw
|
|
386
|
-
* run an instant animation.
|
|
387
|
-
*/
|
|
388
|
-
const keyframes = hydrateKeyframes(element, name, unresolvedKeyframes, pseudoElement);
|
|
389
|
-
invariant(typeof transition.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "motion"?`);
|
|
390
|
-
transition = applyGeneratorOptions(transition);
|
|
323
|
+
this.options = options;
|
|
324
|
+
invariant(typeof options.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "motion"?`);
|
|
325
|
+
const transition = applyGeneratorOptions(options);
|
|
391
326
|
this.animation = startWaapiAnimation(element, name, keyframes, transition, pseudoElement);
|
|
392
327
|
if (transition.autoplay === false) {
|
|
393
328
|
this.animation.pause();
|
|
394
329
|
}
|
|
395
|
-
this.removeAnimation = () => animationMap.delete(key);
|
|
396
330
|
this.animation.onfinish = () => {
|
|
331
|
+
this.finishedTime = this.time;
|
|
397
332
|
if (!pseudoElement) {
|
|
398
|
-
|
|
399
|
-
this.
|
|
333
|
+
const keyframe = getFinalKeyframe(keyframes, this.options, finalKeyframe, this.speed);
|
|
334
|
+
if (this.updateMotionValue) {
|
|
335
|
+
this.updateMotionValue(keyframe);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
/**
|
|
339
|
+
* If we can, we want to commit the final style as set by the user,
|
|
340
|
+
* rather than the computed keyframe value supplied by the animation.
|
|
341
|
+
*/
|
|
342
|
+
setStyle(element, name, keyframe);
|
|
343
|
+
}
|
|
344
|
+
this.animation.cancel();
|
|
400
345
|
}
|
|
346
|
+
this.notifyFinished();
|
|
401
347
|
};
|
|
402
|
-
/**
|
|
403
|
-
* TODO: Check for VisualElement before using animation state.
|
|
404
|
-
*/
|
|
405
|
-
animationMap.set(key, this);
|
|
406
348
|
}
|
|
407
349
|
play() {
|
|
350
|
+
if (this.isStopped)
|
|
351
|
+
return;
|
|
408
352
|
this.animation.play();
|
|
353
|
+
if (this.state === "finished") {
|
|
354
|
+
this.updateFinished();
|
|
355
|
+
}
|
|
409
356
|
}
|
|
410
357
|
pause() {
|
|
411
358
|
this.animation.pause();
|
|
412
359
|
}
|
|
413
360
|
complete() {
|
|
414
|
-
this.animation.finish();
|
|
361
|
+
this.animation.finish?.();
|
|
415
362
|
}
|
|
416
363
|
cancel() {
|
|
417
364
|
try {
|
|
418
365
|
this.animation.cancel();
|
|
419
366
|
}
|
|
420
367
|
catch (e) { }
|
|
421
|
-
this.removeAnimation();
|
|
422
368
|
}
|
|
423
369
|
stop() {
|
|
370
|
+
if (this.isStopped)
|
|
371
|
+
return;
|
|
372
|
+
this.isStopped = true;
|
|
424
373
|
const { state } = this;
|
|
425
374
|
if (state === "idle" || state === "finished") {
|
|
426
375
|
return;
|
|
427
376
|
}
|
|
428
|
-
this.
|
|
429
|
-
|
|
377
|
+
if (this.updateMotionValue) {
|
|
378
|
+
this.updateMotionValue();
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
this.commitStyles();
|
|
382
|
+
}
|
|
383
|
+
if (!this.isPseudoElement)
|
|
384
|
+
this.cancel();
|
|
430
385
|
}
|
|
431
386
|
/**
|
|
432
387
|
* WAAPI doesn't natively have any interruption capabilities.
|
|
@@ -446,13 +401,14 @@ class NativeAnimation {
|
|
|
446
401
|
}
|
|
447
402
|
}
|
|
448
403
|
get duration() {
|
|
449
|
-
const duration = this.animation.effect?.getComputedTiming().duration || 0;
|
|
404
|
+
const duration = this.animation.effect?.getComputedTiming?.().duration || 0;
|
|
450
405
|
return millisecondsToSeconds(Number(duration));
|
|
451
406
|
}
|
|
452
407
|
get time() {
|
|
453
408
|
return millisecondsToSeconds(Number(this.animation.currentTime) || 0);
|
|
454
409
|
}
|
|
455
410
|
set time(newTime) {
|
|
411
|
+
this.finishedTime = null;
|
|
456
412
|
this.animation.currentTime = secondsToMilliseconds(newTime);
|
|
457
413
|
}
|
|
458
414
|
/**
|
|
@@ -463,75 +419,175 @@ class NativeAnimation {
|
|
|
463
419
|
return this.animation.playbackRate;
|
|
464
420
|
}
|
|
465
421
|
set speed(newSpeed) {
|
|
422
|
+
// Allow backwards playback after finishing
|
|
423
|
+
if (newSpeed < 0)
|
|
424
|
+
this.finishedTime = null;
|
|
466
425
|
this.animation.playbackRate = newSpeed;
|
|
467
426
|
}
|
|
468
427
|
get state() {
|
|
469
|
-
return this.
|
|
428
|
+
return this.finishedTime !== null
|
|
429
|
+
? "finished"
|
|
430
|
+
: this.animation.playState;
|
|
470
431
|
}
|
|
471
432
|
get startTime() {
|
|
472
433
|
return Number(this.animation.startTime);
|
|
473
434
|
}
|
|
474
|
-
|
|
475
|
-
|
|
435
|
+
set startTime(newStartTime) {
|
|
436
|
+
this.animation.startTime = newStartTime;
|
|
476
437
|
}
|
|
477
|
-
|
|
438
|
+
/**
|
|
439
|
+
* Attaches a timeline to the animation, for instance the `ScrollTimeline`.
|
|
440
|
+
*/
|
|
441
|
+
attachTimeline({ timeline, observe }) {
|
|
478
442
|
if (this.allowFlatten) {
|
|
479
443
|
this.animation.effect?.updateTiming({ easing: "linear" });
|
|
480
444
|
}
|
|
445
|
+
this.animation.onfinish = null;
|
|
446
|
+
if (timeline && supportsScrollTimeline()) {
|
|
447
|
+
this.animation.timeline = timeline;
|
|
448
|
+
return noop;
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
return observe(this);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
class GroupAnimation {
|
|
457
|
+
constructor(animations) {
|
|
458
|
+
// Bound to accomadate common `return animation.stop` pattern
|
|
459
|
+
this.stop = () => this.runAll("stop");
|
|
460
|
+
this.animations = animations.filter(Boolean);
|
|
461
|
+
}
|
|
462
|
+
get finished() {
|
|
463
|
+
return Promise.all(this.animations.map((animation) => animation.finished));
|
|
481
464
|
}
|
|
482
465
|
/**
|
|
483
|
-
*
|
|
466
|
+
* TODO: Filter out cancelled or stopped animations before returning
|
|
484
467
|
*/
|
|
468
|
+
getAll(propName) {
|
|
469
|
+
return this.animations[0][propName];
|
|
470
|
+
}
|
|
471
|
+
setAll(propName, newValue) {
|
|
472
|
+
for (let i = 0; i < this.animations.length; i++) {
|
|
473
|
+
this.animations[i][propName] = newValue;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
485
476
|
attachTimeline(timeline) {
|
|
486
|
-
this.animation
|
|
487
|
-
|
|
488
|
-
|
|
477
|
+
const subscriptions = this.animations.map((animation) => animation.attachTimeline(timeline));
|
|
478
|
+
return () => {
|
|
479
|
+
subscriptions.forEach((cancel, i) => {
|
|
480
|
+
cancel && cancel();
|
|
481
|
+
this.animations[i].stop();
|
|
482
|
+
});
|
|
483
|
+
};
|
|
489
484
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
485
|
+
get time() {
|
|
486
|
+
return this.getAll("time");
|
|
487
|
+
}
|
|
488
|
+
set time(time) {
|
|
489
|
+
this.setAll("time", time);
|
|
490
|
+
}
|
|
491
|
+
get speed() {
|
|
492
|
+
return this.getAll("speed");
|
|
493
|
+
}
|
|
494
|
+
set speed(speed) {
|
|
495
|
+
this.setAll("speed", speed);
|
|
496
|
+
}
|
|
497
|
+
get state() {
|
|
498
|
+
return this.getAll("state");
|
|
499
|
+
}
|
|
500
|
+
get startTime() {
|
|
501
|
+
return this.getAll("startTime");
|
|
502
|
+
}
|
|
503
|
+
get duration() {
|
|
504
|
+
let max = 0;
|
|
505
|
+
for (let i = 0; i < this.animations.length; i++) {
|
|
506
|
+
max = Math.max(max, this.animations[i].duration);
|
|
507
|
+
}
|
|
508
|
+
return max;
|
|
509
|
+
}
|
|
510
|
+
runAll(methodName) {
|
|
511
|
+
this.animations.forEach((controls) => controls[methodName]());
|
|
512
|
+
}
|
|
513
|
+
play() {
|
|
514
|
+
this.runAll("play");
|
|
515
|
+
}
|
|
516
|
+
pause() {
|
|
517
|
+
this.runAll("pause");
|
|
518
|
+
}
|
|
519
|
+
cancel() {
|
|
520
|
+
this.runAll("cancel");
|
|
521
|
+
}
|
|
522
|
+
complete() {
|
|
523
|
+
this.runAll("complete");
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
class GroupAnimationWithThen extends GroupAnimation {
|
|
528
|
+
then(onResolve, _onReject) {
|
|
529
|
+
return this.finished.finally(onResolve).then(() => { });
|
|
497
530
|
}
|
|
498
531
|
}
|
|
499
532
|
|
|
533
|
+
const animationMaps = new WeakMap();
|
|
534
|
+
const animationMapKey = (name, pseudoElement = "") => `${name}:${pseudoElement}`;
|
|
535
|
+
function getAnimationMap(element) {
|
|
536
|
+
const map = animationMaps.get(element) || new Map();
|
|
537
|
+
animationMaps.set(element, map);
|
|
538
|
+
return map;
|
|
539
|
+
}
|
|
540
|
+
|
|
500
541
|
function getValueTransition$1(transition, key) {
|
|
501
542
|
return (transition?.[key] ??
|
|
502
543
|
transition?.["default"] ??
|
|
503
544
|
transition);
|
|
504
545
|
}
|
|
505
546
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
547
|
+
const pxValues = new Set([
|
|
548
|
+
// Border props
|
|
549
|
+
"borderWidth",
|
|
550
|
+
"borderTopWidth",
|
|
551
|
+
"borderRightWidth",
|
|
552
|
+
"borderBottomWidth",
|
|
553
|
+
"borderLeftWidth",
|
|
554
|
+
"borderRadius",
|
|
555
|
+
"radius",
|
|
556
|
+
"borderTopLeftRadius",
|
|
557
|
+
"borderTopRightRadius",
|
|
558
|
+
"borderBottomRightRadius",
|
|
559
|
+
"borderBottomLeftRadius",
|
|
560
|
+
// Positioning props
|
|
561
|
+
"width",
|
|
562
|
+
"maxWidth",
|
|
563
|
+
"height",
|
|
564
|
+
"maxHeight",
|
|
565
|
+
"top",
|
|
566
|
+
"right",
|
|
567
|
+
"bottom",
|
|
568
|
+
"left",
|
|
569
|
+
// Spacing props
|
|
570
|
+
"padding",
|
|
571
|
+
"paddingTop",
|
|
572
|
+
"paddingRight",
|
|
573
|
+
"paddingBottom",
|
|
574
|
+
"paddingLeft",
|
|
575
|
+
"margin",
|
|
576
|
+
"marginTop",
|
|
577
|
+
"marginRight",
|
|
578
|
+
"marginBottom",
|
|
579
|
+
"marginLeft",
|
|
580
|
+
// Misc
|
|
581
|
+
"backgroundPositionX",
|
|
582
|
+
"backgroundPositionY",
|
|
583
|
+
]);
|
|
521
584
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
return {
|
|
529
|
-
type: "keyframes",
|
|
530
|
-
ease: (progress) => {
|
|
531
|
-
return generator.next(duration * progress).value / scale;
|
|
532
|
-
},
|
|
533
|
-
duration: millisecondsToSeconds(duration),
|
|
534
|
-
};
|
|
585
|
+
function applyPxDefaults(keyframes, name) {
|
|
586
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
587
|
+
if (typeof keyframes[i] === "number" && pxValues.has(name)) {
|
|
588
|
+
keyframes[i] = keyframes[i] + "px";
|
|
589
|
+
}
|
|
590
|
+
}
|
|
535
591
|
}
|
|
536
592
|
|
|
537
593
|
function resolveElements(elementOrSelector, scope, selectorCache) {
|
|
@@ -550,56 +606,11 @@ function resolveElements(elementOrSelector, scope, selectorCache) {
|
|
|
550
606
|
return Array.from(elementOrSelector);
|
|
551
607
|
}
|
|
552
608
|
|
|
553
|
-
|
|
554
|
-
const
|
|
555
|
-
return (
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const isEasingArray = (ease) => {
|
|
559
|
-
return Array.isArray(ease) && typeof ease[0] !== "number";
|
|
560
|
-
};
|
|
561
|
-
|
|
562
|
-
function getEasingForSegment(easing, i) {
|
|
563
|
-
return isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
/*
|
|
567
|
-
Value in range from progress
|
|
568
|
-
|
|
569
|
-
Given a lower limit and an upper limit, we return the value within
|
|
570
|
-
that range as expressed by progress (usually a number from 0 to 1)
|
|
571
|
-
|
|
572
|
-
So progress = 0.5 would change
|
|
573
|
-
|
|
574
|
-
from -------- to
|
|
575
|
-
|
|
576
|
-
to
|
|
577
|
-
|
|
578
|
-
from ---- to
|
|
579
|
-
|
|
580
|
-
E.g. from = 10, to = 20, progress = 0.5 => 15
|
|
581
|
-
|
|
582
|
-
@param [number]: Lower limit of range
|
|
583
|
-
@param [number]: Upper limit of range
|
|
584
|
-
@param [number]: The progress between lower and upper limits expressed 0-1
|
|
585
|
-
@return [number]: Value as calculated from progress within range (not limited within range)
|
|
586
|
-
*/
|
|
587
|
-
const mixNumber = (from, to, progress) => {
|
|
588
|
-
return from + (to - from) * progress;
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
function fillOffset(offset, remaining) {
|
|
592
|
-
const min = offset[offset.length - 1];
|
|
593
|
-
for (let i = 1; i <= remaining; i++) {
|
|
594
|
-
const offsetProgress = progress(0, remaining, i);
|
|
595
|
-
offset.push(mixNumber(min, 1, offsetProgress));
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
function defaultOffset(arr) {
|
|
600
|
-
const offset = [0];
|
|
601
|
-
fillOffset(offset, arr.length - 1);
|
|
602
|
-
return offset;
|
|
609
|
+
function getComputedStyle(element, name) {
|
|
610
|
+
const computedStyle = window.getComputedStyle(element);
|
|
611
|
+
return isCSSVar(name)
|
|
612
|
+
? computedStyle.getPropertyValue(name)
|
|
613
|
+
: computedStyle[name];
|
|
603
614
|
}
|
|
604
615
|
|
|
605
616
|
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
@@ -940,7 +951,27 @@ function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
|
940
951
|
const elements = resolveElements(elementOrSelector, scope);
|
|
941
952
|
const numElements = elements.length;
|
|
942
953
|
invariant(Boolean(numElements), "No valid element provided.");
|
|
943
|
-
|
|
954
|
+
/**
|
|
955
|
+
* WAAPI doesn't support interrupting animations.
|
|
956
|
+
*
|
|
957
|
+
* Therefore, starting animations requires a three-step process:
|
|
958
|
+
* 1. Stop existing animations (write styles to DOM)
|
|
959
|
+
* 2. Resolve keyframes (read styles from DOM)
|
|
960
|
+
* 3. Create new animations (write styles to DOM)
|
|
961
|
+
*
|
|
962
|
+
* The hybrid `animate()` function uses AsyncAnimation to resolve
|
|
963
|
+
* keyframes before creating new animations, which removes style
|
|
964
|
+
* thrashing. Here, we have much stricter filesize constraints.
|
|
965
|
+
* Therefore we do this in a synchronous way that ensures that
|
|
966
|
+
* at least within `animate()` calls there is no style thrashing.
|
|
967
|
+
*
|
|
968
|
+
* In the motion-native-animate-mini-interrupt benchmark this
|
|
969
|
+
* was 80% faster than a single loop.
|
|
970
|
+
*/
|
|
971
|
+
const animationDefinitions = [];
|
|
972
|
+
/**
|
|
973
|
+
* Step 1: Build options and stop existing animations (write)
|
|
974
|
+
*/
|
|
944
975
|
for (let i = 0; i < numElements; i++) {
|
|
945
976
|
const element = elements[i];
|
|
946
977
|
const elementTransition = { ...options };
|
|
@@ -951,20 +982,68 @@ function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
|
951
982
|
elementTransition.delay = elementTransition.delay(i, numElements);
|
|
952
983
|
}
|
|
953
984
|
for (const valueName in keyframes) {
|
|
954
|
-
|
|
985
|
+
let valueKeyframes = keyframes[valueName];
|
|
986
|
+
if (!Array.isArray(valueKeyframes)) {
|
|
987
|
+
valueKeyframes = [valueKeyframes];
|
|
988
|
+
}
|
|
955
989
|
const valueOptions = {
|
|
956
990
|
...getValueTransition$1(elementTransition, valueName),
|
|
957
991
|
};
|
|
958
992
|
valueOptions.duration && (valueOptions.duration = secondsToMilliseconds(valueOptions.duration));
|
|
959
993
|
valueOptions.delay && (valueOptions.delay = secondsToMilliseconds(valueOptions.delay));
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
994
|
+
/**
|
|
995
|
+
* If there's an existing animation playing on this element then stop it
|
|
996
|
+
* before creating a new one.
|
|
997
|
+
*/
|
|
998
|
+
const map = getAnimationMap(element);
|
|
999
|
+
const key = animationMapKey(valueName, valueOptions.pseudoElement || "");
|
|
1000
|
+
const currentAnimation = map.get(key);
|
|
1001
|
+
currentAnimation && currentAnimation.stop();
|
|
1002
|
+
animationDefinitions.push({
|
|
1003
|
+
map,
|
|
1004
|
+
key,
|
|
1005
|
+
unresolvedKeyframes: valueKeyframes,
|
|
1006
|
+
options: {
|
|
1007
|
+
...valueOptions,
|
|
1008
|
+
element,
|
|
1009
|
+
name: valueName,
|
|
1010
|
+
allowFlatten: !elementTransition.type && !elementTransition.ease,
|
|
1011
|
+
},
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Step 2: Resolve keyframes (read)
|
|
1017
|
+
*/
|
|
1018
|
+
for (let i = 0; i < animationDefinitions.length; i++) {
|
|
1019
|
+
const { unresolvedKeyframes, options: animationOptions } = animationDefinitions[i];
|
|
1020
|
+
const { element, name, pseudoElement } = animationOptions;
|
|
1021
|
+
if (!pseudoElement && unresolvedKeyframes[0] === null) {
|
|
1022
|
+
unresolvedKeyframes[0] = getComputedStyle(element, name);
|
|
967
1023
|
}
|
|
1024
|
+
fillWildcards(unresolvedKeyframes);
|
|
1025
|
+
applyPxDefaults(unresolvedKeyframes, name);
|
|
1026
|
+
/**
|
|
1027
|
+
* If we only have one keyframe, explicitly read the initial keyframe
|
|
1028
|
+
* from the computed style. This is to ensure consistency with WAAPI behaviour
|
|
1029
|
+
* for restarting animations, for instance .play() after finish, when it
|
|
1030
|
+
* has one vs two keyframes.
|
|
1031
|
+
*/
|
|
1032
|
+
if (!pseudoElement && unresolvedKeyframes.length < 2) {
|
|
1033
|
+
unresolvedKeyframes.unshift(getComputedStyle(element, name));
|
|
1034
|
+
}
|
|
1035
|
+
animationOptions.keyframes = unresolvedKeyframes;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Step 3: Create new animations (write)
|
|
1039
|
+
*/
|
|
1040
|
+
const animations = [];
|
|
1041
|
+
for (let i = 0; i < animationDefinitions.length; i++) {
|
|
1042
|
+
const { map, key, options: animationOptions } = animationDefinitions[i];
|
|
1043
|
+
const animation = new NativeAnimation(animationOptions);
|
|
1044
|
+
map.set(key, animation);
|
|
1045
|
+
animation.finished.finally(() => map.delete(key));
|
|
1046
|
+
animations.push(animation);
|
|
968
1047
|
}
|
|
969
1048
|
return animations;
|
|
970
1049
|
}
|