framer-motion 10.2.3 → 10.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cjs/dom-entry.js +1 -1
  2. package/dist/cjs/index.js +18 -20
  3. package/dist/cjs/{wrap-27fda06a.js → wrap-62da7859.js} +456 -437
  4. package/dist/dom-entry.d.ts +485 -37
  5. package/dist/es/animation/GroupPlaybackControls.mjs +25 -0
  6. package/dist/es/animation/animate.mjs +2 -3
  7. package/dist/es/animation/create-instant-animation.mjs +13 -3
  8. package/dist/es/animation/generators/inertia.mjs +87 -0
  9. package/dist/es/animation/{legacy-popmotion → generators}/keyframes.mjs +8 -15
  10. package/dist/es/animation/{legacy-popmotion/find-spring.mjs → generators/spring/find.mjs} +6 -5
  11. package/dist/es/animation/generators/spring/index.mjs +129 -0
  12. package/dist/es/animation/generators/utils/velocity.mjs +9 -0
  13. package/dist/es/animation/index.mjs +2 -10
  14. package/dist/es/animation/js/driver-frameloop.mjs +12 -0
  15. package/dist/es/animation/js/index.mjs +206 -0
  16. package/dist/es/animation/optimized-appear/handoff.mjs +3 -1
  17. package/dist/es/animation/waapi/create-accelerated-animation.mjs +16 -10
  18. package/dist/es/frameloop/index.mjs +3 -4
  19. package/dist/es/gestures/pan/PanSession.mjs +2 -2
  20. package/dist/es/index.mjs +2 -3
  21. package/dist/es/render/utils/motion-values.mjs +1 -1
  22. package/dist/es/utils/time-conversion.mjs +2 -1
  23. package/dist/es/value/index.mjs +3 -3
  24. package/dist/es/value/use-spring.mjs +1 -1
  25. package/dist/es/value/use-velocity.mjs +4 -6
  26. package/dist/framer-motion.dev.js +475 -458
  27. package/dist/framer-motion.js +1 -1
  28. package/dist/index.d.ts +175 -218
  29. package/dist/projection.dev.js +5849 -5830
  30. package/dist/three-entry.d.ts +62 -63
  31. package/package.json +7 -11
  32. package/dist/es/animation/legacy-popmotion/decay.mjs +0 -34
  33. package/dist/es/animation/legacy-popmotion/index.mjs +0 -163
  34. package/dist/es/animation/legacy-popmotion/inertia.mjs +0 -90
  35. package/dist/es/animation/legacy-popmotion/spring.mjs +0 -143
  36. package/dist/es/frameloop/on-next-frame.mjs +0 -12
@@ -7,8 +7,7 @@ import { isEasingArray, easingDefinitionToFunction } from '../utils/easing.mjs';
7
7
  function defaultEasing(values, easing) {
8
8
  return values.map(() => easing || easeInOut).splice(0, values.length - 1);
9
9
  }
10
- function keyframes({ keyframes: keyframeValues, ease = easeInOut, times, duration = 300, }) {
11
- keyframeValues = [...keyframeValues];
10
+ function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "easeInOut", }) {
12
11
  /**
13
12
  * Easing functions can be externally defined as strings. Here we convert them
14
13
  * into actual functions.
@@ -33,24 +32,18 @@ function keyframes({ keyframes: keyframeValues, ease = easeInOut, times, duratio
33
32
  times && times.length === keyframeValues.length
34
33
  ? times
35
34
  : defaultOffset(keyframeValues), duration);
36
- function createInterpolator() {
37
- return interpolate(absoluteTimes, keyframeValues, {
38
- ease: Array.isArray(easingFunctions)
39
- ? easingFunctions
40
- : defaultEasing(keyframeValues, easingFunctions),
41
- });
42
- }
43
- let interpolator = createInterpolator();
35
+ const mapTimeToKeyframe = interpolate(absoluteTimes, keyframeValues, {
36
+ ease: Array.isArray(easingFunctions)
37
+ ? easingFunctions
38
+ : defaultEasing(keyframeValues, easingFunctions),
39
+ });
44
40
  return {
41
+ calculatedDuration: duration,
45
42
  next: (t) => {
46
- state.value = interpolator(t);
43
+ state.value = mapTimeToKeyframe(t);
47
44
  state.done = t >= duration;
48
45
  return state;
49
46
  },
50
- flipTarget: () => {
51
- keyframeValues.reverse();
52
- interpolator = createInterpolator();
53
- },
54
47
  };
55
48
  }
56
49
 
@@ -1,5 +1,6 @@
1
- import { warning } from '../../utils/errors.mjs';
2
- import { clamp } from '../../utils/clamp.mjs';
1
+ import { warning } from '../../../utils/errors.mjs';
2
+ import { clamp } from '../../../utils/clamp.mjs';
3
+ import { secondsToMilliseconds, millisecondsToSeconds } from '../../../utils/time-conversion.mjs';
3
4
 
4
5
  const safeMin = 0.001;
5
6
  const minDuration = 0.01;
@@ -9,13 +10,13 @@ const maxDamping = 1;
9
10
  function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }) {
10
11
  let envelope;
11
12
  let derivative;
12
- warning(duration <= maxDuration * 1000, "Spring duration must be 10 seconds or less");
13
+ warning(duration <= secondsToMilliseconds(maxDuration), "Spring duration must be 10 seconds or less");
13
14
  let dampingRatio = 1 - bounce;
14
15
  /**
15
16
  * Restrict dampingRatio and duration to within acceptable ranges.
16
17
  */
17
18
  dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
18
- duration = clamp(minDuration, maxDuration, duration / 1000);
19
+ duration = clamp(minDuration, maxDuration, millisecondsToSeconds(duration));
19
20
  if (dampingRatio < 1) {
20
21
  /**
21
22
  * Underdamped spring
@@ -56,7 +57,7 @@ function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, })
56
57
  }
57
58
  const initialGuess = 5 / duration;
58
59
  const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
59
- duration = duration * 1000;
60
+ duration = secondsToMilliseconds(duration);
60
61
  if (isNaN(undampedFreq)) {
61
62
  return {
62
63
  stiffness: 100,
@@ -0,0 +1,129 @@
1
+ import { millisecondsToSeconds } from '../../../utils/time-conversion.mjs';
2
+ import { calcGeneratorVelocity } from '../utils/velocity.mjs';
3
+ import { findSpring, calcAngularFreq } from './find.mjs';
4
+
5
+ const durationKeys = ["duration", "bounce"];
6
+ const physicsKeys = ["stiffness", "damping", "mass"];
7
+ function isSpringType(options, keys) {
8
+ return keys.some((key) => options[key] !== undefined);
9
+ }
10
+ function getSpringOptions(options) {
11
+ let springOptions = {
12
+ velocity: 0.0,
13
+ stiffness: 100,
14
+ damping: 10,
15
+ mass: 1.0,
16
+ isResolvedFromDuration: false,
17
+ ...options,
18
+ };
19
+ // stiffness/damping/mass overrides duration/bounce
20
+ if (!isSpringType(options, physicsKeys) &&
21
+ isSpringType(options, durationKeys)) {
22
+ const derived = findSpring(options);
23
+ springOptions = {
24
+ ...springOptions,
25
+ ...derived,
26
+ velocity: 0.0,
27
+ mass: 1.0,
28
+ };
29
+ springOptions.isResolvedFromDuration = true;
30
+ }
31
+ return springOptions;
32
+ }
33
+ function spring({ keyframes, restDelta, restSpeed, ...options }) {
34
+ const origin = keyframes[0];
35
+ const target = keyframes[keyframes.length - 1];
36
+ /**
37
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
38
+ * to reduce GC during animation.
39
+ */
40
+ const state = { done: false, value: origin };
41
+ const { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
42
+ const initialVelocity = velocity ? -millisecondsToSeconds(velocity) : 0.0;
43
+ const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
44
+ const initialDelta = target - origin;
45
+ const undampedAngularFreq = millisecondsToSeconds(Math.sqrt(stiffness / mass));
46
+ /**
47
+ * If we're working on a granular scale, use smaller defaults for determining
48
+ * when the spring is finished.
49
+ *
50
+ * These defaults have been selected emprically based on what strikes a good
51
+ * ratio between feeling good and finishing as soon as changes are imperceptible.
52
+ */
53
+ const isGranularScale = Math.abs(initialDelta) < 5;
54
+ restSpeed || (restSpeed = isGranularScale ? 0.01 : 2);
55
+ restDelta || (restDelta = isGranularScale ? 0.005 : 0.5);
56
+ let resolveSpring;
57
+ if (dampingRatio < 1) {
58
+ const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
59
+ // Underdamped spring
60
+ resolveSpring = (t) => {
61
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
62
+ return (target -
63
+ envelope *
64
+ (((initialVelocity +
65
+ dampingRatio * undampedAngularFreq * initialDelta) /
66
+ angularFreq) *
67
+ Math.sin(angularFreq * t) +
68
+ initialDelta * Math.cos(angularFreq * t)));
69
+ };
70
+ }
71
+ else if (dampingRatio === 1) {
72
+ // Critically damped spring
73
+ resolveSpring = (t) => target -
74
+ Math.exp(-undampedAngularFreq * t) *
75
+ (initialDelta +
76
+ (initialVelocity + undampedAngularFreq * initialDelta) * t);
77
+ }
78
+ else {
79
+ // Overdamped spring
80
+ const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
81
+ resolveSpring = (t) => {
82
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
83
+ // When performing sinh or cosh values can hit Infinity so we cap them here
84
+ const freqForT = Math.min(dampedAngularFreq * t, 300);
85
+ return (target -
86
+ (envelope *
87
+ ((initialVelocity +
88
+ dampingRatio * undampedAngularFreq * initialDelta) *
89
+ Math.sinh(freqForT) +
90
+ dampedAngularFreq *
91
+ initialDelta *
92
+ Math.cosh(freqForT))) /
93
+ dampedAngularFreq);
94
+ };
95
+ }
96
+ return {
97
+ calculatedDuration: isResolvedFromDuration ? duration || null : null,
98
+ next: (t) => {
99
+ const current = resolveSpring(t);
100
+ if (!isResolvedFromDuration) {
101
+ let currentVelocity = initialVelocity;
102
+ if (t !== 0) {
103
+ /**
104
+ * We only need to calculate velocity for under-damped springs
105
+ * as over- and critically-damped springs can't overshoot, so
106
+ * checking only for displacement is enough.
107
+ */
108
+ if (dampingRatio < 1) {
109
+ currentVelocity = calcGeneratorVelocity(resolveSpring, t, current);
110
+ }
111
+ else {
112
+ currentVelocity = 0;
113
+ }
114
+ }
115
+ const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
116
+ const isBelowDisplacementThreshold = Math.abs(target - current) <= restDelta;
117
+ state.done =
118
+ isBelowVelocityThreshold && isBelowDisplacementThreshold;
119
+ }
120
+ else {
121
+ state.done = t >= duration;
122
+ }
123
+ state.value = state.done ? target : current;
124
+ return state;
125
+ },
126
+ };
127
+ }
128
+
129
+ export { spring };
@@ -0,0 +1,9 @@
1
+ import { velocityPerSecond } from '../../../utils/velocity-per-second.mjs';
2
+
3
+ const velocitySampleDuration = 5; // ms
4
+ function calcGeneratorVelocity(resolveValue, t, current) {
5
+ const prevT = Math.max(t - velocitySampleDuration, 0);
6
+ return velocityPerSecond(current - resolveValue(prevT), t - prevT);
7
+ }
8
+
9
+ export { calcGeneratorVelocity };
@@ -3,12 +3,11 @@ import { secondsToMilliseconds } from '../utils/time-conversion.mjs';
3
3
  import { instantAnimationState } from '../utils/use-instant-transition-state.mjs';
4
4
  import { createAcceleratedAnimation } from './waapi/create-accelerated-animation.mjs';
5
5
  import { createInstantAnimation } from './create-instant-animation.mjs';
6
- import { animateValue } from './legacy-popmotion/index.mjs';
7
- import { inertia } from './legacy-popmotion/inertia.mjs';
8
6
  import { getDefaultTransition } from './utils/default-transitions.mjs';
9
7
  import { isAnimatable } from './utils/is-animatable.mjs';
10
8
  import { getKeyframes } from './utils/keyframes.mjs';
11
9
  import { getValueTransition, isTransitionDefined } from './utils/transitions.mjs';
10
+ import { animateValue } from './js/index.mjs';
12
11
 
13
12
  const createMotionValueAnimation = (valueName, value, target, transition = {}) => {
14
13
  return (onComplete) => {
@@ -40,7 +39,7 @@ const createMotionValueAnimation = (valueName, value, target, transition = {}) =
40
39
  keyframes,
41
40
  velocity: value.getVelocity(),
42
41
  ...valueTransition,
43
- elapsed,
42
+ delay: -elapsed,
44
43
  onUpdate: (v) => {
45
44
  value.set(v);
46
45
  valueTransition.onUpdate && valueTransition.onUpdate(v);
@@ -60,13 +59,6 @@ const createMotionValueAnimation = (valueName, value, target, transition = {}) =
60
59
  */
61
60
  return createInstantAnimation(options);
62
61
  }
63
- else if (valueTransition.type === "inertia") {
64
- /**
65
- * If this is an inertia animation, we currently don't support pre-generating
66
- * keyframes for this as such it must always run on the main thread.
67
- */
68
- return inertia(options);
69
- }
70
62
  /**
71
63
  * If there's no transition defined for this value, we can generate
72
64
  * unqiue transition settings for this value.
@@ -0,0 +1,12 @@
1
+ import { sync, cancelSync } from '../../frameloop/index.mjs';
2
+
3
+ const frameloopDriver = (update) => {
4
+ const passTimestamp = ({ timestamp }) => update(timestamp);
5
+ return {
6
+ start: () => sync.update(passTimestamp, true),
7
+ stop: () => cancelSync.update(passTimestamp),
8
+ now: () => performance.now(),
9
+ };
10
+ };
11
+
12
+ export { frameloopDriver };
@@ -0,0 +1,206 @@
1
+ import { keyframes } from '../generators/keyframes.mjs';
2
+ import { spring } from '../generators/spring/index.mjs';
3
+ import { inertia } from '../generators/inertia.mjs';
4
+ import { frameloopDriver } from './driver-frameloop.mjs';
5
+ import { interpolate } from '../../utils/interpolate.mjs';
6
+ import { clamp } from '../../utils/clamp.mjs';
7
+ import { millisecondsToSeconds, secondsToMilliseconds } from '../../utils/time-conversion.mjs';
8
+
9
+ const types = {
10
+ decay: inertia,
11
+ inertia,
12
+ tween: keyframes,
13
+ keyframes: keyframes,
14
+ spring,
15
+ };
16
+ /**
17
+ * Implement a practical max duration for keyframe generation
18
+ * to prevent infinite loops
19
+ */
20
+ const maxDuration = 20000;
21
+ function calculateDuration(generator) {
22
+ let duration = 0;
23
+ const timeStep = 50;
24
+ let state = generator.next(duration);
25
+ while (!state.done && duration < maxDuration) {
26
+ duration += timeStep;
27
+ state = generator.next(duration);
28
+ }
29
+ return duration;
30
+ }
31
+ function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, keyframes: keyframes$1, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", onPlay, onStop, onComplete, onUpdate, ...options }) {
32
+ let animationDriver;
33
+ const generatorFactory = types[type] || keyframes;
34
+ /**
35
+ * If this isn't the keyframes generator and we've been provided
36
+ * strings as keyframes, we need to interpolate these.
37
+ * TODO: Support velocity for units and complex value types/
38
+ */
39
+ let mapNumbersToKeyframes;
40
+ if (generatorFactory !== keyframes &&
41
+ typeof keyframes$1[0] !== "number") {
42
+ mapNumbersToKeyframes = interpolate([0, 100], keyframes$1, {
43
+ clamp: false,
44
+ });
45
+ keyframes$1 = [0, 100];
46
+ }
47
+ const generator = generatorFactory({ ...options, keyframes: keyframes$1 });
48
+ let mirroredGenerator;
49
+ if (repeatType === "mirror") {
50
+ mirroredGenerator = generatorFactory({
51
+ ...options,
52
+ keyframes: [...keyframes$1].reverse(),
53
+ velocity: -(options.velocity || 0),
54
+ });
55
+ }
56
+ let playState = "idle";
57
+ let holdTime = null;
58
+ let startTime = null;
59
+ /**
60
+ * If duration is undefined and we have repeat options,
61
+ * we need to calculate a duration from the generator.
62
+ *
63
+ * We set it to the generator itself to cache the duration.
64
+ * Any timeline resolver will need to have already precalculated
65
+ * the duration by this step.
66
+ */
67
+ if (generator.calculatedDuration === null && repeat) {
68
+ generator.calculatedDuration = calculateDuration(generator);
69
+ }
70
+ const { calculatedDuration } = generator;
71
+ let resolvedDuration = Infinity;
72
+ let totalDuration = Infinity;
73
+ if (calculatedDuration) {
74
+ resolvedDuration = calculatedDuration + repeatDelay;
75
+ totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
76
+ }
77
+ let currentTime = 0;
78
+ const tick = (timestamp) => {
79
+ if (startTime === null)
80
+ return;
81
+ if (holdTime !== null) {
82
+ currentTime = holdTime;
83
+ }
84
+ else {
85
+ currentTime = timestamp - startTime;
86
+ }
87
+ // Rebase on delay
88
+ currentTime = Math.max(currentTime - delay, 0);
89
+ /**
90
+ * If this animation has finished, set the current time
91
+ * to the total duration.
92
+ */
93
+ if (playState === "finished" && holdTime === null) {
94
+ currentTime = totalDuration;
95
+ }
96
+ let elapsed = currentTime;
97
+ let frameGenerator = generator;
98
+ if (repeat) {
99
+ /**
100
+ * Get the current progress (0-1) of the animation. If t is >
101
+ * than duration we'll get values like 2.5 (midway through the
102
+ * third iteration)
103
+ */
104
+ const progress = currentTime / resolvedDuration;
105
+ /**
106
+ * Get the current iteration (0 indexed). For instance the floor of
107
+ * 2.5 is 2.
108
+ */
109
+ let currentIteration = Math.floor(progress);
110
+ /**
111
+ * Get the current progress of the iteration by taking the remainder
112
+ * so 2.5 is 0.5 through iteration 2
113
+ */
114
+ let iterationProgress = progress % 1.0;
115
+ /**
116
+ * If iteration progress is 1 we count that as the end
117
+ * of the previous iteration.
118
+ */
119
+ if (!iterationProgress && progress >= 1) {
120
+ iterationProgress = 1;
121
+ }
122
+ iterationProgress === 1 && currentIteration--;
123
+ /**
124
+ * Reverse progress if we're not running in "normal" direction
125
+ */
126
+ const iterationIsOdd = currentIteration % 2;
127
+ if (iterationIsOdd) {
128
+ if (repeatType === "reverse") {
129
+ iterationProgress = 1 - iterationProgress;
130
+ if (repeatDelay) {
131
+ iterationProgress -= repeatDelay / resolvedDuration;
132
+ }
133
+ }
134
+ else if (repeatType === "mirror") {
135
+ frameGenerator = mirroredGenerator;
136
+ }
137
+ }
138
+ const p = currentTime >= totalDuration
139
+ ? repeatType === "reverse" && iterationIsOdd
140
+ ? 0
141
+ : 1
142
+ : clamp(0, 1, iterationProgress);
143
+ elapsed = p * resolvedDuration;
144
+ }
145
+ const state = frameGenerator.next(elapsed);
146
+ let { value, done } = state;
147
+ if (onUpdate) {
148
+ onUpdate(mapNumbersToKeyframes ? mapNumbersToKeyframes(value) : value);
149
+ }
150
+ if (calculatedDuration !== null) {
151
+ done = currentTime >= totalDuration;
152
+ }
153
+ const isAnimationFinished = holdTime === null &&
154
+ (playState === "finished" || (playState === "running" && done));
155
+ if (isAnimationFinished) {
156
+ playState = "finished";
157
+ onComplete && onComplete();
158
+ animationDriver && animationDriver.stop();
159
+ }
160
+ return state;
161
+ };
162
+ const play = () => {
163
+ animationDriver = driver(tick);
164
+ const now = animationDriver.now();
165
+ onPlay && onPlay();
166
+ playState = "running";
167
+ if (holdTime !== null) {
168
+ startTime = now - holdTime;
169
+ }
170
+ else if (!startTime) {
171
+ // TODO When implementing play/pause, check WAAPI
172
+ // logic around finished animations
173
+ startTime = now;
174
+ }
175
+ holdTime = null;
176
+ animationDriver.start();
177
+ };
178
+ if (autoplay) {
179
+ play();
180
+ }
181
+ const controls = {
182
+ get currentTime() {
183
+ return millisecondsToSeconds(currentTime);
184
+ },
185
+ set currentTime(newTime) {
186
+ if (holdTime !== null || !animationDriver) {
187
+ holdTime = 0;
188
+ }
189
+ else {
190
+ startTime =
191
+ animationDriver.now() - secondsToMilliseconds(newTime);
192
+ }
193
+ },
194
+ stop: () => {
195
+ onStop && onStop();
196
+ animationDriver && animationDriver.stop();
197
+ },
198
+ sample: (elapsed) => {
199
+ startTime = 0;
200
+ return tick(elapsed);
201
+ },
202
+ };
203
+ return controls;
204
+ }
205
+
206
+ export { animateValue };
@@ -1,4 +1,5 @@
1
1
  import { transformProps } from '../../render/html/utils/transform.mjs';
2
+ import { millisecondsToSeconds } from '../../utils/time-conversion.mjs';
2
3
  import { appearAnimationStore } from './store.mjs';
3
4
  import { appearStoreId } from './store-id.mjs';
4
5
 
@@ -41,7 +42,8 @@ sync) {
41
42
  */
42
43
  sync.update(() => {
43
44
  if (value.animation) {
44
- value.animation.currentTime = performance.now() - sampledTime;
45
+ value.animation.currentTime =
46
+ performance.now() - millisecondsToSeconds(sampledTime);
45
47
  }
46
48
  });
47
49
  /**
@@ -1,9 +1,10 @@
1
1
  import { sync } from '../../frameloop/index.mjs';
2
- import { animateValue } from '../legacy-popmotion/index.mjs';
3
2
  import { animateStyle } from './index.mjs';
4
3
  import { isWaapiSupportedEasing } from './easing.mjs';
5
4
  import { supports } from './supports.mjs';
6
5
  import { getFinalKeyframe } from './utils/get-final-keyframe.mjs';
6
+ import { animateValue } from '../js/index.mjs';
7
+ import { millisecondsToSeconds, secondsToMilliseconds } from '../../utils/time-conversion.mjs';
7
8
 
8
9
  /**
9
10
  * A list of values that can be hardware-accelerated.
@@ -21,6 +22,11 @@ const acceleratedValues = new Set([
21
22
  * keyframe quantity.
22
23
  */
23
24
  const sampleDelta = 10; //ms
25
+ /**
26
+ * Implement a practical max duration for keyframe generation
27
+ * to prevent infinite loops
28
+ */
29
+ const maxDuration = 20000;
24
30
  const requiresPregeneratedKeyframes = (valueName, options) => options.type === "spring" ||
25
31
  valueName === "backgroundColor" ||
26
32
  !isWaapiSupportedEasing(options.ease);
@@ -29,10 +35,11 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
29
35
  acceleratedValues.has(valueName) &&
30
36
  !options.repeatDelay &&
31
37
  options.repeatType !== "mirror" &&
32
- options.damping !== 0;
38
+ options.damping !== 0 &&
39
+ options.type !== "inertia";
33
40
  if (!canAccelerateAnimation)
34
41
  return false;
35
- let { keyframes, duration = 300, elapsed = 0, ease } = options;
42
+ let { keyframes, duration = 300, ease } = options;
36
43
  /**
37
44
  * If this animation needs pre-generated keyframes then generate.
38
45
  */
@@ -40,7 +47,7 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
40
47
  const sampleAnimation = animateValue({
41
48
  ...options,
42
49
  repeat: 0,
43
- elapsed: 0,
50
+ delay: 0,
44
51
  });
45
52
  let state = { done: false, value: keyframes[0] };
46
53
  const pregeneratedKeyframes = [];
@@ -49,8 +56,8 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
49
56
  * we're heading for an infinite loop.
50
57
  */
51
58
  let t = 0;
52
- while (!state.done && t < 20000) {
53
- state = sampleAnimation.sample(t, true);
59
+ while (!state.done && t < maxDuration) {
60
+ state = sampleAnimation.sample(t);
54
61
  pregeneratedKeyframes.push(state.value);
55
62
  t += sampleDelta;
56
63
  }
@@ -60,7 +67,6 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
60
67
  }
61
68
  const animation = animateStyle(value.owner.current, valueName, keyframes, {
62
69
  ...options,
63
- delay: -elapsed,
64
70
  duration,
65
71
  /**
66
72
  * This function is currently not called if ease is provided
@@ -90,10 +96,10 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
90
96
  */
91
97
  return {
92
98
  get currentTime() {
93
- return animation.currentTime || 0;
99
+ return millisecondsToSeconds(animation.currentTime || 0);
94
100
  },
95
- set currentTime(t) {
96
- animation.currentTime = t;
101
+ set currentTime(newTime) {
102
+ animation.currentTime = secondsToMilliseconds(newTime);
97
103
  },
98
104
  stop: () => {
99
105
  /**
@@ -1,4 +1,3 @@
1
- import { onNextFrame, defaultTimestep } from './on-next-frame.mjs';
2
1
  import { createRenderStep } from './create-render-step.mjs';
3
2
  import { frameData } from './data.mjs';
4
3
 
@@ -38,7 +37,7 @@ const processStep = (stepId) => steps[stepId].process(frameData);
38
37
  const processFrame = (timestamp) => {
39
38
  runNextFrame = false;
40
39
  frameData.delta = useDefaultElapsed
41
- ? defaultTimestep
40
+ ? 1000 / 60
42
41
  : Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed), 1);
43
42
  frameData.timestamp = timestamp;
44
43
  isProcessing = true;
@@ -46,14 +45,14 @@ const processFrame = (timestamp) => {
46
45
  isProcessing = false;
47
46
  if (runNextFrame) {
48
47
  useDefaultElapsed = false;
49
- onNextFrame(processFrame);
48
+ requestAnimationFrame(processFrame);
50
49
  }
51
50
  };
52
51
  const startLoop = () => {
53
52
  runNextFrame = true;
54
53
  useDefaultElapsed = true;
55
54
  if (!isProcessing)
56
- onNextFrame(processFrame);
55
+ requestAnimationFrame(processFrame);
57
56
  };
58
57
 
59
58
  export { cancelSync, flushSync, sync };
@@ -1,6 +1,6 @@
1
1
  import { extractEventInfo } from '../../events/event-info.mjs';
2
2
  import { sync, cancelSync } from '../../frameloop/index.mjs';
3
- import { secondsToMilliseconds } from '../../utils/time-conversion.mjs';
3
+ import { secondsToMilliseconds, millisecondsToSeconds } from '../../utils/time-conversion.mjs';
4
4
  import { addPointerEvent } from '../../events/add-pointer-event.mjs';
5
5
  import { pipe } from '../../utils/pipe.mjs';
6
6
  import { distance2D } from '../../utils/distance.mjs';
@@ -129,7 +129,7 @@ function getVelocity(history, timeDelta) {
129
129
  if (!timestampedPoint) {
130
130
  return { x: 0, y: 0 };
131
131
  }
132
- const time = (lastPoint.timestamp - timestampedPoint.timestamp) / 1000;
132
+ const time = millisecondsToSeconds(lastPoint.timestamp - timestampedPoint.timestamp);
133
133
  if (time === 0) {
134
134
  return { x: 0, y: 0 };
135
135
  }
package/dist/es/index.mjs CHANGED
@@ -40,14 +40,13 @@ 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/legacy-popmotion/index.mjs';
44
- export { inertia } from './animation/legacy-popmotion/inertia.mjs';
43
+ export { animateValue } from './animation/js/index.mjs';
45
44
  export { color } from './value/types/color/index.mjs';
46
45
  export { complex } from './value/types/complex/index.mjs';
47
46
  export { px } from './value/types/numbers/units.mjs';
48
47
  export { startOptimizedAppearAnimation } from './animation/optimized-appear/start.mjs';
49
48
  export { optimizedAppearDataAttribute } from './animation/optimized-appear/data-id.mjs';
50
- export { spring } from './animation/legacy-popmotion/spring.mjs';
49
+ export { spring } from './animation/generators/spring/index.mjs';
51
50
  export { MotionContext } from './context/MotionContext/index.mjs';
52
51
  export { MotionConfigContext } from './context/MotionConfigContext.mjs';
53
52
  export { PresenceContext } from './context/PresenceContext.mjs';
@@ -22,7 +22,7 @@ function updateMotionValuesFromProps(element, next, prev) {
22
22
  * and warn against mismatches.
23
23
  */
24
24
  if (process.env.NODE_ENV === "development") {
25
- warnOnce(nextValue.version === "10.2.3", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.2.3 may not work as expected.`);
25
+ warnOnce(nextValue.version === "10.2.4", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.2.4 may not work as expected.`);
26
26
  }
27
27
  }
28
28
  else if (isMotionValue(prevValue)) {
@@ -5,5 +5,6 @@
5
5
  * @return milliseconds - Converted time in milliseconds.
6
6
  */
7
7
  const secondsToMilliseconds = (seconds) => seconds * 1000;
8
+ const millisecondsToSeconds = (milliseconds) => milliseconds / 1000;
8
9
 
9
- export { secondsToMilliseconds };
10
+ export { millisecondsToSeconds, secondsToMilliseconds };