framer-motion 12.7.3 → 12.7.5-alpha.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/README.md +1 -1
- package/dist/cjs/client.js +1 -1
- package/dist/cjs/{create-DwAwaNot.js → create-C7kXmWbI.js} +99 -2828
- package/dist/cjs/dom-mini.js +82 -66
- package/dist/cjs/dom.js +264 -3000
- package/dist/cjs/index.js +163 -218
- package/dist/cjs/m.js +13 -170
- package/dist/cjs/mini.js +77 -9
- package/dist/dom-mini.js +1 -1
- package/dist/dom.d.ts +5 -94
- package/dist/dom.js +1 -1
- package/dist/es/animation/animate/sequence.mjs +1 -1
- package/dist/es/animation/animators/waapi/animate-elements.mjs +78 -10
- package/dist/es/animation/interfaces/motion-value.mjs +11 -30
- package/dist/es/animation/interfaces/visual-element-target.mjs +1 -2
- package/dist/es/animation/optimized-appear/store-id.mjs +1 -1
- package/dist/es/animation/sequence/create.mjs +2 -5
- package/dist/es/animation/sequence/utils/edit.mjs +2 -3
- package/dist/es/animation/utils/default-transitions.mjs +1 -1
- package/dist/es/animation/utils/stagger.mjs +1 -1
- package/dist/es/components/AnimatePresence/PresenceChild.mjs +26 -23
- package/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
- package/dist/es/dom.mjs +2 -18
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -3
- package/dist/es/gestures/drag/utils/constraints.mjs +2 -3
- package/dist/es/gestures/focus.mjs +1 -1
- package/dist/es/gestures/pan/PanSession.mjs +1 -2
- package/dist/es/index.mjs +3 -24
- package/dist/es/motion/utils/is-forced-motion-value.mjs +1 -1
- package/dist/es/projection/animation/mix-values.mjs +2 -4
- package/dist/es/projection/geometry/delta-apply.mjs +1 -1
- package/dist/es/projection/geometry/delta-calc.mjs +1 -1
- package/dist/es/projection/geometry/delta-remove.mjs +1 -2
- package/dist/es/projection/node/create-projection-node.mjs +3 -7
- package/dist/es/projection/styles/scale-border-radius.mjs +1 -1
- package/dist/es/projection/styles/scale-box-shadow.mjs +1 -2
- package/dist/es/projection/styles/scale-correction.mjs +1 -1
- package/dist/es/projection.mjs +1 -3
- package/dist/es/render/VisualElement.mjs +2 -9
- package/dist/es/render/dom/DOMVisualElement.mjs +1 -1
- package/dist/es/render/dom/scroll/attach-animation.mjs +17 -0
- package/dist/es/render/dom/scroll/attach-function.mjs +23 -0
- package/dist/es/render/dom/scroll/index.mjs +6 -82
- package/dist/es/render/dom/scroll/offsets/index.mjs +2 -3
- package/dist/es/render/dom/scroll/utils/get-timeline.mjs +29 -0
- package/dist/es/render/html/HTMLVisualElement.mjs +1 -3
- package/dist/es/render/html/utils/build-styles.mjs +1 -4
- package/dist/es/render/html/utils/build-transform.mjs +1 -3
- package/dist/es/render/svg/SVGVisualElement.mjs +1 -3
- package/dist/es/render/svg/config-motion.mjs +1 -2
- package/dist/es/render/svg/utils/path.mjs +1 -1
- package/dist/es/render/svg/utils/scrape-motion-values.mjs +1 -1
- package/dist/es/render/svg/utils/transform-origin.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/utils/delay.mjs +1 -1
- package/dist/es/utils/transform.mjs +1 -1
- package/dist/es/utils/use-cycle.mjs +1 -1
- package/dist/es/utils/use-instant-transition.mjs +4 -4
- package/dist/es/value/use-spring.mjs +2 -3
- package/dist/es/value/use-will-change/get-will-change-name.mjs +1 -2
- package/dist/framer-motion.dev.js +3881 -3419
- package/dist/framer-motion.js +1 -1
- package/dist/m.d.ts +3 -50
- package/dist/mini.js +1 -1
- package/dist/size-rollup-animate.js +1 -1
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/size-rollup-scroll.js +1 -1
- package/dist/size-rollup-waapi-animate.js +1 -1
- package/dist/types/client.d.ts +4 -3
- package/dist/types/index.d.ts +56 -351
- package/dist/{types.d-B50aGbjN.d.ts → types.d-B1Voffvi.d.ts} +3 -138
- package/package.json +9 -9
- package/dist/es/animation/animators/AcceleratedAnimation.mjs +0 -319
- package/dist/es/animation/animators/BaseAnimation.mjs +0 -120
- package/dist/es/animation/animators/MainThreadAnimation.mjs +0 -394
- package/dist/es/animation/animators/drivers/driver-frameloop.mjs +0 -16
- package/dist/es/animation/animators/utils/accelerated-values.mjs +0 -14
- package/dist/es/animation/animators/utils/can-animate.mjs +0 -42
- package/dist/es/animation/animators/waapi/utils/supports-waapi.mjs +0 -5
- package/dist/es/animation/generators/inertia.mjs +0 -87
- package/dist/es/animation/generators/keyframes.mjs +0 -51
- package/dist/es/animation/generators/spring/defaults.mjs +0 -27
- package/dist/es/animation/generators/spring/find.mjs +0 -85
- package/dist/es/animation/generators/spring/index.mjs +0 -174
- package/dist/es/animation/generators/utils/velocity.mjs +0 -9
- package/dist/es/animation/utils/is-animatable.mjs +0 -30
- package/dist/es/animation/utils/is-none.mjs +0 -15
- package/dist/es/easing/anticipate.mjs +0 -5
- package/dist/es/easing/back.mjs +0 -9
- package/dist/es/easing/circ.mjs +0 -8
- package/dist/es/easing/cubic-bezier.mjs +0 -51
- package/dist/es/easing/ease.mjs +0 -7
- package/dist/es/easing/modifiers/mirror.mjs +0 -5
- package/dist/es/easing/modifiers/reverse.mjs +0 -5
- package/dist/es/easing/steps.mjs +0 -15
- package/dist/es/easing/utils/get-easing-for-segment.mjs +0 -8
- package/dist/es/easing/utils/is-easing-array.mjs +0 -5
- package/dist/es/easing/utils/map.mjs +0 -37
- package/dist/es/render/dom/DOMKeyframesResolver.mjs +0 -130
- package/dist/es/render/dom/scroll/observe.mjs +0 -18
- package/dist/es/render/dom/utils/css-variables-conversion.mjs +0 -42
- package/dist/es/render/dom/utils/is-css-variable.mjs +0 -15
- package/dist/es/render/dom/utils/unit-conversion.mjs +0 -36
- package/dist/es/render/dom/value-types/animatable-none.mjs +0 -15
- package/dist/es/render/dom/value-types/defaults.mjs +0 -30
- package/dist/es/render/dom/value-types/dimensions.mjs +0 -15
- package/dist/es/render/dom/value-types/find.mjs +0 -15
- package/dist/es/render/dom/value-types/get-as-type.mjs +0 -10
- package/dist/es/render/dom/value-types/number-browser.mjs +0 -41
- package/dist/es/render/dom/value-types/number.mjs +0 -18
- package/dist/es/render/dom/value-types/test.mjs +0 -6
- package/dist/es/render/dom/value-types/transform.mjs +0 -31
- package/dist/es/render/dom/value-types/type-auto.mjs +0 -9
- package/dist/es/render/dom/value-types/type-int.mjs +0 -8
- package/dist/es/render/html/utils/keys-position.mjs +0 -13
- package/dist/es/render/html/utils/keys-transform.mjs +0 -28
- package/dist/es/render/html/utils/make-none-animatable.mjs +0 -30
- package/dist/es/render/html/utils/parse-transform.mjs +0 -83
- package/dist/es/render/utils/KeyframesResolver.mjs +0 -163
- package/dist/es/utils/clamp.mjs +0 -9
- package/dist/es/utils/hsla-to-rgba.mjs +0 -42
- package/dist/es/utils/interpolate.mjs +0 -76
- package/dist/es/utils/is-numerical-string.mjs +0 -6
- package/dist/es/utils/is-zero-value-string.mjs +0 -6
- package/dist/es/utils/mix/color.mjs +0 -47
- package/dist/es/utils/mix/complex.mjs +0 -93
- package/dist/es/utils/mix/immediate.mjs +0 -5
- package/dist/es/utils/mix/index.mjs +0 -14
- package/dist/es/utils/mix/number.mjs +0 -26
- package/dist/es/utils/mix/visibility.mjs +0 -16
- package/dist/es/utils/offsets/default.mjs +0 -9
- package/dist/es/utils/offsets/fill.mjs +0 -12
- package/dist/es/utils/offsets/time.mjs +0 -5
- package/dist/es/utils/pipe.mjs +0 -11
- package/dist/es/utils/use-instant-transition-state.mjs +0 -5
- package/dist/es/utils/wrap.mjs +0 -6
- package/dist/es/value/types/color/hex.mjs +0 -40
- package/dist/es/value/types/color/hsla.mjs +0 -22
- package/dist/es/value/types/color/index.mjs +0 -27
- package/dist/es/value/types/color/rgba.mjs +0 -25
- package/dist/es/value/types/color/utils.mjs +0 -29
- package/dist/es/value/types/complex/filter.mjs +0 -30
- package/dist/es/value/types/complex/index.mjs +0 -91
- package/dist/es/value/types/numbers/index.mjs +0 -17
- package/dist/es/value/types/numbers/units.mjs +0 -17
- package/dist/es/value/types/utils/color-regex.mjs +0 -3
- package/dist/es/value/types/utils/float-regex.mjs +0 -3
- package/dist/es/value/types/utils/is-nullish.mjs +0 -5
- package/dist/es/value/types/utils/sanitize.mjs +0 -5
- package/dist/es/value/types/utils/single-color-regex.mjs +0 -3
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
import { isGenerator, calcGeneratorDuration, activeAnimations } from 'motion-dom';
|
|
2
|
-
import { invariant, millisecondsToSeconds, secondsToMilliseconds } from 'motion-utils';
|
|
3
|
-
import { KeyframeResolver } from '../../render/utils/KeyframesResolver.mjs';
|
|
4
|
-
import { clamp } from '../../utils/clamp.mjs';
|
|
5
|
-
import { mix } from '../../utils/mix/index.mjs';
|
|
6
|
-
import { pipe } from '../../utils/pipe.mjs';
|
|
7
|
-
import { inertia } from '../generators/inertia.mjs';
|
|
8
|
-
import { keyframes } from '../generators/keyframes.mjs';
|
|
9
|
-
import { spring } from '../generators/spring/index.mjs';
|
|
10
|
-
import { BaseAnimation } from './BaseAnimation.mjs';
|
|
11
|
-
import { frameloopDriver } from './drivers/driver-frameloop.mjs';
|
|
12
|
-
import { getFinalKeyframe } from './waapi/utils/get-final-keyframe.mjs';
|
|
13
|
-
|
|
14
|
-
const generators = {
|
|
15
|
-
decay: inertia,
|
|
16
|
-
inertia,
|
|
17
|
-
tween: keyframes,
|
|
18
|
-
keyframes: keyframes,
|
|
19
|
-
spring,
|
|
20
|
-
};
|
|
21
|
-
const percentToProgress = (percent) => percent / 100;
|
|
22
|
-
/**
|
|
23
|
-
* Animation that runs on the main thread. Designed to be WAAPI-spec in the subset of
|
|
24
|
-
* features we expose publically. Mostly the compatibility is to ensure visual identity
|
|
25
|
-
* between both WAAPI and main thread animations.
|
|
26
|
-
*/
|
|
27
|
-
class MainThreadAnimation extends BaseAnimation {
|
|
28
|
-
constructor(options) {
|
|
29
|
-
super(options);
|
|
30
|
-
/**
|
|
31
|
-
* The time at which the animation was paused.
|
|
32
|
-
*/
|
|
33
|
-
this.holdTime = null;
|
|
34
|
-
/**
|
|
35
|
-
* The time at which the animation was cancelled.
|
|
36
|
-
*/
|
|
37
|
-
this.cancelTime = null;
|
|
38
|
-
/**
|
|
39
|
-
* The current time of the animation.
|
|
40
|
-
*/
|
|
41
|
-
this.currentTime = 0;
|
|
42
|
-
/**
|
|
43
|
-
* Playback speed as a factor. 0 would be stopped, -1 reverse and 2 double speed.
|
|
44
|
-
*/
|
|
45
|
-
this.playbackSpeed = 1;
|
|
46
|
-
/**
|
|
47
|
-
* The state of the animation to apply when the animation is resolved. This
|
|
48
|
-
* allows calls to the public API to control the animation before it is resolved,
|
|
49
|
-
* without us having to resolve it first.
|
|
50
|
-
*/
|
|
51
|
-
this.pendingPlayState = "running";
|
|
52
|
-
/**
|
|
53
|
-
* The time at which the animation was started.
|
|
54
|
-
*/
|
|
55
|
-
this.startTime = null;
|
|
56
|
-
this.state = "idle";
|
|
57
|
-
/**
|
|
58
|
-
* This method is bound to the instance to fix a pattern where
|
|
59
|
-
* animation.stop is returned as a reference from a useEffect.
|
|
60
|
-
*/
|
|
61
|
-
this.stop = () => {
|
|
62
|
-
this.resolver.cancel();
|
|
63
|
-
this.isStopped = true;
|
|
64
|
-
if (this.state === "idle")
|
|
65
|
-
return;
|
|
66
|
-
this.teardown();
|
|
67
|
-
const { onStop } = this.options;
|
|
68
|
-
onStop && onStop();
|
|
69
|
-
};
|
|
70
|
-
const { name, motionValue, element, keyframes } = this.options;
|
|
71
|
-
const KeyframeResolver$1 = element?.KeyframeResolver || KeyframeResolver;
|
|
72
|
-
const onResolved = (resolvedKeyframes, finalKeyframe) => this.onKeyframesResolved(resolvedKeyframes, finalKeyframe);
|
|
73
|
-
this.resolver = new KeyframeResolver$1(keyframes, onResolved, name, motionValue, element);
|
|
74
|
-
this.resolver.scheduleResolve();
|
|
75
|
-
}
|
|
76
|
-
flatten() {
|
|
77
|
-
super.flatten();
|
|
78
|
-
// If we've already resolved the animation, re-initialise it
|
|
79
|
-
if (this._resolved) {
|
|
80
|
-
Object.assign(this._resolved, this.initPlayback(this._resolved.keyframes));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
initPlayback(keyframes$1) {
|
|
84
|
-
const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = this.options;
|
|
85
|
-
const generatorFactory = isGenerator(type)
|
|
86
|
-
? type
|
|
87
|
-
: generators[type] || keyframes;
|
|
88
|
-
/**
|
|
89
|
-
* If our generator doesn't support mixing numbers, we need to replace keyframes with
|
|
90
|
-
* [0, 100] and then make a function that maps that to the actual keyframes.
|
|
91
|
-
*
|
|
92
|
-
* 100 is chosen instead of 1 as it works nicer with spring animations.
|
|
93
|
-
*/
|
|
94
|
-
let mapPercentToKeyframes;
|
|
95
|
-
let mirroredGenerator;
|
|
96
|
-
if (process.env.NODE_ENV !== "production" &&
|
|
97
|
-
generatorFactory !== keyframes) {
|
|
98
|
-
invariant(keyframes$1.length <= 2, `Only two keyframes currently supported with spring and inertia animations. Trying to animate ${keyframes$1}`);
|
|
99
|
-
}
|
|
100
|
-
if (generatorFactory !== keyframes &&
|
|
101
|
-
typeof keyframes$1[0] !== "number") {
|
|
102
|
-
mapPercentToKeyframes = pipe(percentToProgress, mix(keyframes$1[0], keyframes$1[1]));
|
|
103
|
-
keyframes$1 = [0, 100];
|
|
104
|
-
}
|
|
105
|
-
const generator = generatorFactory({ ...this.options, keyframes: keyframes$1 });
|
|
106
|
-
/**
|
|
107
|
-
* If we have a mirror repeat type we need to create a second generator that outputs the
|
|
108
|
-
* mirrored (not reversed) animation and later ping pong between the two generators.
|
|
109
|
-
*/
|
|
110
|
-
if (repeatType === "mirror") {
|
|
111
|
-
mirroredGenerator = generatorFactory({
|
|
112
|
-
...this.options,
|
|
113
|
-
keyframes: [...keyframes$1].reverse(),
|
|
114
|
-
velocity: -velocity,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* If duration is undefined and we have repeat options,
|
|
119
|
-
* we need to calculate a duration from the generator.
|
|
120
|
-
*
|
|
121
|
-
* We set it to the generator itself to cache the duration.
|
|
122
|
-
* Any timeline resolver will need to have already precalculated
|
|
123
|
-
* the duration by this step.
|
|
124
|
-
*/
|
|
125
|
-
if (generator.calculatedDuration === null) {
|
|
126
|
-
generator.calculatedDuration = calcGeneratorDuration(generator);
|
|
127
|
-
}
|
|
128
|
-
const { calculatedDuration } = generator;
|
|
129
|
-
const resolvedDuration = calculatedDuration + repeatDelay;
|
|
130
|
-
const totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
|
|
131
|
-
return {
|
|
132
|
-
generator,
|
|
133
|
-
mirroredGenerator,
|
|
134
|
-
mapPercentToKeyframes,
|
|
135
|
-
calculatedDuration,
|
|
136
|
-
resolvedDuration,
|
|
137
|
-
totalDuration,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
onPostResolved() {
|
|
141
|
-
const { autoplay = true } = this.options;
|
|
142
|
-
activeAnimations.mainThread++;
|
|
143
|
-
this.play();
|
|
144
|
-
if (this.pendingPlayState === "paused" || !autoplay) {
|
|
145
|
-
this.pause();
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
this.state = this.pendingPlayState;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
tick(timestamp, sample = false) {
|
|
152
|
-
const { resolved } = this;
|
|
153
|
-
// If the animations has failed to resolve, return the final keyframe.
|
|
154
|
-
if (!resolved) {
|
|
155
|
-
const { keyframes } = this.options;
|
|
156
|
-
return { done: true, value: keyframes[keyframes.length - 1] };
|
|
157
|
-
}
|
|
158
|
-
const { finalKeyframe, generator, mirroredGenerator, mapPercentToKeyframes, keyframes, calculatedDuration, totalDuration, resolvedDuration, } = resolved;
|
|
159
|
-
if (this.startTime === null)
|
|
160
|
-
return generator.next(0);
|
|
161
|
-
const { delay, repeat, repeatType, repeatDelay, onUpdate } = this.options;
|
|
162
|
-
/**
|
|
163
|
-
* requestAnimationFrame timestamps can come through as lower than
|
|
164
|
-
* the startTime as set by performance.now(). Here we prevent this,
|
|
165
|
-
* though in the future it could be possible to make setting startTime
|
|
166
|
-
* a pending operation that gets resolved here.
|
|
167
|
-
*/
|
|
168
|
-
if (this.speed > 0) {
|
|
169
|
-
this.startTime = Math.min(this.startTime, timestamp);
|
|
170
|
-
}
|
|
171
|
-
else if (this.speed < 0) {
|
|
172
|
-
this.startTime = Math.min(timestamp - totalDuration / this.speed, this.startTime);
|
|
173
|
-
}
|
|
174
|
-
// Update currentTime
|
|
175
|
-
if (sample) {
|
|
176
|
-
this.currentTime = timestamp;
|
|
177
|
-
}
|
|
178
|
-
else if (this.holdTime !== null) {
|
|
179
|
-
this.currentTime = this.holdTime;
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
// Rounding the time because floating point arithmetic is not always accurate, e.g. 3000.367 - 1000.367 =
|
|
183
|
-
// 2000.0000000000002. This is a problem when we are comparing the currentTime with the duration, for
|
|
184
|
-
// example.
|
|
185
|
-
this.currentTime =
|
|
186
|
-
Math.round(timestamp - this.startTime) * this.speed;
|
|
187
|
-
}
|
|
188
|
-
// Rebase on delay
|
|
189
|
-
const timeWithoutDelay = this.currentTime - delay * (this.speed >= 0 ? 1 : -1);
|
|
190
|
-
const isInDelayPhase = this.speed >= 0
|
|
191
|
-
? timeWithoutDelay < 0
|
|
192
|
-
: timeWithoutDelay > totalDuration;
|
|
193
|
-
this.currentTime = Math.max(timeWithoutDelay, 0);
|
|
194
|
-
// If this animation has finished, set the current time to the total duration.
|
|
195
|
-
if (this.state === "finished" && this.holdTime === null) {
|
|
196
|
-
this.currentTime = totalDuration;
|
|
197
|
-
}
|
|
198
|
-
let elapsed = this.currentTime;
|
|
199
|
-
let frameGenerator = generator;
|
|
200
|
-
if (repeat) {
|
|
201
|
-
/**
|
|
202
|
-
* Get the current progress (0-1) of the animation. If t is >
|
|
203
|
-
* than duration we'll get values like 2.5 (midway through the
|
|
204
|
-
* third iteration)
|
|
205
|
-
*/
|
|
206
|
-
const progress = Math.min(this.currentTime, totalDuration) / resolvedDuration;
|
|
207
|
-
/**
|
|
208
|
-
* Get the current iteration (0 indexed). For instance the floor of
|
|
209
|
-
* 2.5 is 2.
|
|
210
|
-
*/
|
|
211
|
-
let currentIteration = Math.floor(progress);
|
|
212
|
-
/**
|
|
213
|
-
* Get the current progress of the iteration by taking the remainder
|
|
214
|
-
* so 2.5 is 0.5 through iteration 2
|
|
215
|
-
*/
|
|
216
|
-
let iterationProgress = progress % 1.0;
|
|
217
|
-
/**
|
|
218
|
-
* If iteration progress is 1 we count that as the end
|
|
219
|
-
* of the previous iteration.
|
|
220
|
-
*/
|
|
221
|
-
if (!iterationProgress && progress >= 1) {
|
|
222
|
-
iterationProgress = 1;
|
|
223
|
-
}
|
|
224
|
-
iterationProgress === 1 && currentIteration--;
|
|
225
|
-
currentIteration = Math.min(currentIteration, repeat + 1);
|
|
226
|
-
/**
|
|
227
|
-
* Reverse progress if we're not running in "normal" direction
|
|
228
|
-
*/
|
|
229
|
-
const isOddIteration = Boolean(currentIteration % 2);
|
|
230
|
-
if (isOddIteration) {
|
|
231
|
-
if (repeatType === "reverse") {
|
|
232
|
-
iterationProgress = 1 - iterationProgress;
|
|
233
|
-
if (repeatDelay) {
|
|
234
|
-
iterationProgress -= repeatDelay / resolvedDuration;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
else if (repeatType === "mirror") {
|
|
238
|
-
frameGenerator = mirroredGenerator;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
elapsed = clamp(0, 1, iterationProgress) * resolvedDuration;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* If we're in negative time, set state as the initial keyframe.
|
|
245
|
-
* This prevents delay: x, duration: 0 animations from finishing
|
|
246
|
-
* instantly.
|
|
247
|
-
*/
|
|
248
|
-
const state = isInDelayPhase
|
|
249
|
-
? { done: false, value: keyframes[0] }
|
|
250
|
-
: frameGenerator.next(elapsed);
|
|
251
|
-
if (mapPercentToKeyframes) {
|
|
252
|
-
state.value = mapPercentToKeyframes(state.value);
|
|
253
|
-
}
|
|
254
|
-
let { done } = state;
|
|
255
|
-
if (!isInDelayPhase && calculatedDuration !== null) {
|
|
256
|
-
done =
|
|
257
|
-
this.speed >= 0
|
|
258
|
-
? this.currentTime >= totalDuration
|
|
259
|
-
: this.currentTime <= 0;
|
|
260
|
-
}
|
|
261
|
-
const isAnimationFinished = this.holdTime === null &&
|
|
262
|
-
(this.state === "finished" || (this.state === "running" && done));
|
|
263
|
-
if (isAnimationFinished && finalKeyframe !== undefined) {
|
|
264
|
-
state.value = getFinalKeyframe(keyframes, this.options, finalKeyframe);
|
|
265
|
-
}
|
|
266
|
-
if (onUpdate) {
|
|
267
|
-
onUpdate(state.value);
|
|
268
|
-
}
|
|
269
|
-
if (isAnimationFinished) {
|
|
270
|
-
this.finish();
|
|
271
|
-
}
|
|
272
|
-
return state;
|
|
273
|
-
}
|
|
274
|
-
get duration() {
|
|
275
|
-
const { resolved } = this;
|
|
276
|
-
return resolved ? millisecondsToSeconds(resolved.calculatedDuration) : 0;
|
|
277
|
-
}
|
|
278
|
-
get time() {
|
|
279
|
-
return millisecondsToSeconds(this.currentTime);
|
|
280
|
-
}
|
|
281
|
-
set time(newTime) {
|
|
282
|
-
newTime = secondsToMilliseconds(newTime);
|
|
283
|
-
this.currentTime = newTime;
|
|
284
|
-
if (this.holdTime !== null || this.speed === 0) {
|
|
285
|
-
this.holdTime = newTime;
|
|
286
|
-
}
|
|
287
|
-
else if (this.driver) {
|
|
288
|
-
this.startTime = this.driver.now() - newTime / this.speed;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
get speed() {
|
|
292
|
-
return this.playbackSpeed;
|
|
293
|
-
}
|
|
294
|
-
set speed(newSpeed) {
|
|
295
|
-
const hasChanged = this.playbackSpeed !== newSpeed;
|
|
296
|
-
this.playbackSpeed = newSpeed;
|
|
297
|
-
if (hasChanged) {
|
|
298
|
-
this.time = millisecondsToSeconds(this.currentTime);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
play() {
|
|
302
|
-
if (!this.resolver.isScheduled) {
|
|
303
|
-
this.resolver.resume();
|
|
304
|
-
}
|
|
305
|
-
if (!this._resolved) {
|
|
306
|
-
this.pendingPlayState = "running";
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
if (this.isStopped)
|
|
310
|
-
return;
|
|
311
|
-
const { driver = frameloopDriver, onPlay, startTime } = this.options;
|
|
312
|
-
if (!this.driver) {
|
|
313
|
-
this.driver = driver((timestamp) => this.tick(timestamp));
|
|
314
|
-
}
|
|
315
|
-
onPlay && onPlay();
|
|
316
|
-
const now = this.driver.now();
|
|
317
|
-
if (this.holdTime !== null) {
|
|
318
|
-
this.startTime = now - this.holdTime;
|
|
319
|
-
}
|
|
320
|
-
else if (!this.startTime) {
|
|
321
|
-
this.startTime = startTime ?? this.calcStartTime();
|
|
322
|
-
}
|
|
323
|
-
else if (this.state === "finished") {
|
|
324
|
-
this.startTime = now;
|
|
325
|
-
}
|
|
326
|
-
if (this.state === "finished") {
|
|
327
|
-
this.updateFinishedPromise();
|
|
328
|
-
}
|
|
329
|
-
this.cancelTime = this.startTime;
|
|
330
|
-
this.holdTime = null;
|
|
331
|
-
/**
|
|
332
|
-
* Set playState to running only after we've used it in
|
|
333
|
-
* the previous logic.
|
|
334
|
-
*/
|
|
335
|
-
this.state = "running";
|
|
336
|
-
this.driver.start();
|
|
337
|
-
}
|
|
338
|
-
pause() {
|
|
339
|
-
if (!this._resolved) {
|
|
340
|
-
this.pendingPlayState = "paused";
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
this.state = "paused";
|
|
344
|
-
this.holdTime = this.currentTime ?? 0;
|
|
345
|
-
}
|
|
346
|
-
complete() {
|
|
347
|
-
if (this.state !== "running") {
|
|
348
|
-
this.play();
|
|
349
|
-
}
|
|
350
|
-
this.pendingPlayState = this.state = "finished";
|
|
351
|
-
this.holdTime = null;
|
|
352
|
-
}
|
|
353
|
-
finish() {
|
|
354
|
-
this.teardown();
|
|
355
|
-
this.state = "finished";
|
|
356
|
-
const { onComplete } = this.options;
|
|
357
|
-
onComplete && onComplete();
|
|
358
|
-
}
|
|
359
|
-
cancel() {
|
|
360
|
-
if (this.cancelTime !== null) {
|
|
361
|
-
this.tick(this.cancelTime);
|
|
362
|
-
}
|
|
363
|
-
this.teardown();
|
|
364
|
-
this.updateFinishedPromise();
|
|
365
|
-
}
|
|
366
|
-
teardown() {
|
|
367
|
-
this.state = "idle";
|
|
368
|
-
this.stopDriver();
|
|
369
|
-
this.resolveFinishedPromise();
|
|
370
|
-
this.updateFinishedPromise();
|
|
371
|
-
this.startTime = this.cancelTime = null;
|
|
372
|
-
this.resolver.cancel();
|
|
373
|
-
activeAnimations.mainThread--;
|
|
374
|
-
}
|
|
375
|
-
stopDriver() {
|
|
376
|
-
if (!this.driver)
|
|
377
|
-
return;
|
|
378
|
-
this.driver.stop();
|
|
379
|
-
this.driver = undefined;
|
|
380
|
-
}
|
|
381
|
-
sample(time) {
|
|
382
|
-
this.startTime = 0;
|
|
383
|
-
return this.tick(time, true);
|
|
384
|
-
}
|
|
385
|
-
get finished() {
|
|
386
|
-
return this.currentFinishedPromise;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
// Legacy interface
|
|
390
|
-
function animateValue(options) {
|
|
391
|
-
return new MainThreadAnimation(options);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
export { MainThreadAnimation, animateValue };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { frame, cancelFrame, frameData, time } from 'motion-dom';
|
|
2
|
-
|
|
3
|
-
const frameloopDriver = (update) => {
|
|
4
|
-
const passTimestamp = ({ timestamp }) => update(timestamp);
|
|
5
|
-
return {
|
|
6
|
-
start: () => frame.update(passTimestamp, true),
|
|
7
|
-
stop: () => cancelFrame(passTimestamp),
|
|
8
|
-
/**
|
|
9
|
-
* If we're processing this frame we can use the
|
|
10
|
-
* framelocked timestamp to keep things in sync.
|
|
11
|
-
*/
|
|
12
|
-
now: () => (frameData.isProcessing ? frameData.timestamp : time.now()),
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export { frameloopDriver };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A list of values that can be hardware-accelerated.
|
|
3
|
-
*/
|
|
4
|
-
const acceleratedValues = new Set([
|
|
5
|
-
"opacity",
|
|
6
|
-
"clipPath",
|
|
7
|
-
"filter",
|
|
8
|
-
"transform",
|
|
9
|
-
// TODO: Can be accelerated but currently disabled until https://issues.chromium.org/issues/41491098 is resolved
|
|
10
|
-
// or until we implement support for linear() easing.
|
|
11
|
-
// "background-color"
|
|
12
|
-
]);
|
|
13
|
-
|
|
14
|
-
export { acceleratedValues };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { isGenerator } from 'motion-dom';
|
|
2
|
-
import { warning } from 'motion-utils';
|
|
3
|
-
import { isAnimatable } from '../../utils/is-animatable.mjs';
|
|
4
|
-
|
|
5
|
-
function hasKeyframesChanged(keyframes) {
|
|
6
|
-
const current = keyframes[0];
|
|
7
|
-
if (keyframes.length === 1)
|
|
8
|
-
return true;
|
|
9
|
-
for (let i = 0; i < keyframes.length; i++) {
|
|
10
|
-
if (keyframes[i] !== current)
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
function canAnimate(keyframes, name, type, velocity) {
|
|
15
|
-
/**
|
|
16
|
-
* Check if we're able to animate between the start and end keyframes,
|
|
17
|
-
* and throw a warning if we're attempting to animate between one that's
|
|
18
|
-
* animatable and another that isn't.
|
|
19
|
-
*/
|
|
20
|
-
const originKeyframe = keyframes[0];
|
|
21
|
-
if (originKeyframe === null)
|
|
22
|
-
return false;
|
|
23
|
-
/**
|
|
24
|
-
* These aren't traditionally animatable but we do support them.
|
|
25
|
-
* In future we could look into making this more generic or replacing
|
|
26
|
-
* this function with mix() === mixImmediate
|
|
27
|
-
*/
|
|
28
|
-
if (name === "display" || name === "visibility")
|
|
29
|
-
return true;
|
|
30
|
-
const targetKeyframe = keyframes[keyframes.length - 1];
|
|
31
|
-
const isOriginAnimatable = isAnimatable(originKeyframe, name);
|
|
32
|
-
const isTargetAnimatable = isAnimatable(targetKeyframe, name);
|
|
33
|
-
warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${name} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
|
|
34
|
-
// Always skip if any of these are true
|
|
35
|
-
if (!isOriginAnimatable || !isTargetAnimatable) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
return (hasKeyframesChanged(keyframes) ||
|
|
39
|
-
((type === "spring" || isGenerator(type)) && velocity));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { canAnimate };
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { spring } from './spring/index.mjs';
|
|
2
|
-
import { calcGeneratorVelocity } from './utils/velocity.mjs';
|
|
3
|
-
|
|
4
|
-
function inertia({ keyframes, velocity = 0.0, power = 0.8, timeConstant = 325, bounceDamping = 10, bounceStiffness = 500, modifyTarget, min, max, restDelta = 0.5, restSpeed, }) {
|
|
5
|
-
const origin = keyframes[0];
|
|
6
|
-
const state = {
|
|
7
|
-
done: false,
|
|
8
|
-
value: origin,
|
|
9
|
-
};
|
|
10
|
-
const isOutOfBounds = (v) => (min !== undefined && v < min) || (max !== undefined && v > max);
|
|
11
|
-
const nearestBoundary = (v) => {
|
|
12
|
-
if (min === undefined)
|
|
13
|
-
return max;
|
|
14
|
-
if (max === undefined)
|
|
15
|
-
return min;
|
|
16
|
-
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
|
|
17
|
-
};
|
|
18
|
-
let amplitude = power * velocity;
|
|
19
|
-
const ideal = origin + amplitude;
|
|
20
|
-
const target = modifyTarget === undefined ? ideal : modifyTarget(ideal);
|
|
21
|
-
/**
|
|
22
|
-
* If the target has changed we need to re-calculate the amplitude, otherwise
|
|
23
|
-
* the animation will start from the wrong position.
|
|
24
|
-
*/
|
|
25
|
-
if (target !== ideal)
|
|
26
|
-
amplitude = target - origin;
|
|
27
|
-
const calcDelta = (t) => -amplitude * Math.exp(-t / timeConstant);
|
|
28
|
-
const calcLatest = (t) => target + calcDelta(t);
|
|
29
|
-
const applyFriction = (t) => {
|
|
30
|
-
const delta = calcDelta(t);
|
|
31
|
-
const latest = calcLatest(t);
|
|
32
|
-
state.done = Math.abs(delta) <= restDelta;
|
|
33
|
-
state.value = state.done ? target : latest;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Ideally this would resolve for t in a stateless way, we could
|
|
37
|
-
* do that by always precalculating the animation but as we know
|
|
38
|
-
* this will be done anyway we can assume that spring will
|
|
39
|
-
* be discovered during that.
|
|
40
|
-
*/
|
|
41
|
-
let timeReachedBoundary;
|
|
42
|
-
let spring$1;
|
|
43
|
-
const checkCatchBoundary = (t) => {
|
|
44
|
-
if (!isOutOfBounds(state.value))
|
|
45
|
-
return;
|
|
46
|
-
timeReachedBoundary = t;
|
|
47
|
-
spring$1 = spring({
|
|
48
|
-
keyframes: [state.value, nearestBoundary(state.value)],
|
|
49
|
-
velocity: calcGeneratorVelocity(calcLatest, t, state.value), // TODO: This should be passing * 1000
|
|
50
|
-
damping: bounceDamping,
|
|
51
|
-
stiffness: bounceStiffness,
|
|
52
|
-
restDelta,
|
|
53
|
-
restSpeed,
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
checkCatchBoundary(0);
|
|
57
|
-
return {
|
|
58
|
-
calculatedDuration: null,
|
|
59
|
-
next: (t) => {
|
|
60
|
-
/**
|
|
61
|
-
* We need to resolve the friction to figure out if we need a
|
|
62
|
-
* spring but we don't want to do this twice per frame. So here
|
|
63
|
-
* we flag if we updated for this frame and later if we did
|
|
64
|
-
* we can skip doing it again.
|
|
65
|
-
*/
|
|
66
|
-
let hasUpdatedFrame = false;
|
|
67
|
-
if (!spring$1 && timeReachedBoundary === undefined) {
|
|
68
|
-
hasUpdatedFrame = true;
|
|
69
|
-
applyFriction(t);
|
|
70
|
-
checkCatchBoundary(t);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* If we have a spring and the provided t is beyond the moment the friction
|
|
74
|
-
* animation crossed the min/max boundary, use the spring.
|
|
75
|
-
*/
|
|
76
|
-
if (timeReachedBoundary !== undefined && t >= timeReachedBoundary) {
|
|
77
|
-
return spring$1.next(t - timeReachedBoundary);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
!hasUpdatedFrame && applyFriction(t);
|
|
81
|
-
return state;
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export { inertia };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { easeInOut } from '../../easing/ease.mjs';
|
|
2
|
-
import { isEasingArray } from '../../easing/utils/is-easing-array.mjs';
|
|
3
|
-
import { easingDefinitionToFunction } from '../../easing/utils/map.mjs';
|
|
4
|
-
import { interpolate } from '../../utils/interpolate.mjs';
|
|
5
|
-
import { defaultOffset } from '../../utils/offsets/default.mjs';
|
|
6
|
-
import { convertOffsetToTimes } from '../../utils/offsets/time.mjs';
|
|
7
|
-
|
|
8
|
-
function defaultEasing(values, easing) {
|
|
9
|
-
return values.map(() => easing || easeInOut).splice(0, values.length - 1);
|
|
10
|
-
}
|
|
11
|
-
function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "easeInOut", }) {
|
|
12
|
-
/**
|
|
13
|
-
* Easing functions can be externally defined as strings. Here we convert them
|
|
14
|
-
* into actual functions.
|
|
15
|
-
*/
|
|
16
|
-
const easingFunctions = isEasingArray(ease)
|
|
17
|
-
? ease.map(easingDefinitionToFunction)
|
|
18
|
-
: easingDefinitionToFunction(ease);
|
|
19
|
-
/**
|
|
20
|
-
* This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
|
|
21
|
-
* to reduce GC during animation.
|
|
22
|
-
*/
|
|
23
|
-
const state = {
|
|
24
|
-
done: false,
|
|
25
|
-
value: keyframeValues[0],
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Create a times array based on the provided 0-1 offsets
|
|
29
|
-
*/
|
|
30
|
-
const absoluteTimes = convertOffsetToTimes(
|
|
31
|
-
// Only use the provided offsets if they're the correct length
|
|
32
|
-
// TODO Maybe we should warn here if there's a length mismatch
|
|
33
|
-
times && times.length === keyframeValues.length
|
|
34
|
-
? times
|
|
35
|
-
: defaultOffset(keyframeValues), duration);
|
|
36
|
-
const mapTimeToKeyframe = interpolate(absoluteTimes, keyframeValues, {
|
|
37
|
-
ease: Array.isArray(easingFunctions)
|
|
38
|
-
? easingFunctions
|
|
39
|
-
: defaultEasing(keyframeValues, easingFunctions),
|
|
40
|
-
});
|
|
41
|
-
return {
|
|
42
|
-
calculatedDuration: duration,
|
|
43
|
-
next: (t) => {
|
|
44
|
-
state.value = mapTimeToKeyframe(t);
|
|
45
|
-
state.done = t >= duration;
|
|
46
|
-
return state;
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export { defaultEasing, keyframes };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const springDefaults = {
|
|
2
|
-
// Default spring physics
|
|
3
|
-
stiffness: 100,
|
|
4
|
-
damping: 10,
|
|
5
|
-
mass: 1.0,
|
|
6
|
-
velocity: 0.0,
|
|
7
|
-
// Default duration/bounce-based options
|
|
8
|
-
duration: 800, // in ms
|
|
9
|
-
bounce: 0.3,
|
|
10
|
-
visualDuration: 0.3, // in seconds
|
|
11
|
-
// Rest thresholds
|
|
12
|
-
restSpeed: {
|
|
13
|
-
granular: 0.01,
|
|
14
|
-
default: 2,
|
|
15
|
-
},
|
|
16
|
-
restDelta: {
|
|
17
|
-
granular: 0.005,
|
|
18
|
-
default: 0.5,
|
|
19
|
-
},
|
|
20
|
-
// Limits
|
|
21
|
-
minDuration: 0.01, // in seconds
|
|
22
|
-
maxDuration: 10.0, // in seconds
|
|
23
|
-
minDamping: 0.05,
|
|
24
|
-
maxDamping: 1,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export { springDefaults };
|