framer-motion 12.3.1 → 12.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var create = require('./create-CfaH3l7_.js');
5
+ var create = require('./create-BUi_omOK.js');
6
6
  require('motion-dom');
7
7
  require('motion-utils');
8
8
  require('react/jsx-runtime');
@@ -58,7 +58,21 @@ const MotionGlobalConfig = {
58
58
  useManualTiming: false,
59
59
  };
60
60
 
61
- function createRenderStep(runNextFrame) {
61
+ const stepsOrder = [
62
+ "read", // Read
63
+ "resolveKeyframes", // Write/Read/Write/Read
64
+ "update", // Compute
65
+ "preRender", // Compute
66
+ "render", // Write
67
+ "postRender", // Compute
68
+ ];
69
+
70
+ const statsBuffer = {
71
+ value: null,
72
+ addProjectionMetrics: null,
73
+ };
74
+
75
+ function createRenderStep(runNextFrame, stepName) {
62
76
  /**
63
77
  * We create and reuse two queues, one to queue jobs for the current frame
64
78
  * and one for the next. We reuse to avoid triggering GC after x frames.
@@ -80,11 +94,13 @@ function createRenderStep(runNextFrame) {
80
94
  timestamp: 0.0,
81
95
  isProcessing: false,
82
96
  };
97
+ let numCalls = 0;
83
98
  function triggerCallback(callback) {
84
99
  if (toKeepAlive.has(callback)) {
85
100
  step.schedule(callback);
86
101
  runNextFrame();
87
102
  }
103
+ numCalls++;
88
104
  callback(latestFrameData);
89
105
  }
90
106
  const step = {
@@ -125,6 +141,13 @@ function createRenderStep(runNextFrame) {
125
141
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
126
142
  // Execute this frame
127
143
  thisFrame.forEach(triggerCallback);
144
+ /**
145
+ * If we're recording stats then
146
+ */
147
+ if (stepName && statsBuffer.value) {
148
+ statsBuffer.value.frameloop[stepName].push(numCalls);
149
+ }
150
+ numCalls = 0;
128
151
  // Clear the frame so no callbacks remain. This is to avoid
129
152
  // memory leaks should this render step not run for a while.
130
153
  thisFrame.clear();
@@ -138,14 +161,6 @@ function createRenderStep(runNextFrame) {
138
161
  return step;
139
162
  }
140
163
 
141
- const stepsOrder = [
142
- "read", // Read
143
- "resolveKeyframes", // Write/Read/Write/Read
144
- "update", // Compute
145
- "preRender", // Compute
146
- "render", // Write
147
- "postRender", // Compute
148
- ];
149
164
  const maxElapsed = 40;
150
165
  function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
151
166
  let runNextFrame = false;
@@ -157,7 +172,7 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
157
172
  };
158
173
  const flagRunNextFrame = () => (runNextFrame = true);
159
174
  const steps = stepsOrder.reduce((acc, key) => {
160
- acc[key] = createRenderStep(flagRunNextFrame);
175
+ acc[key] = createRenderStep(flagRunNextFrame, allowKeepAlive ? key : undefined);
161
176
  return acc;
162
177
  }, {});
163
178
  const { read, resolveKeyframes, update, preRender, render, postRender } = steps;
@@ -166,9 +181,11 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
166
181
  ? state.timestamp
167
182
  : performance.now();
168
183
  runNextFrame = false;
169
- state.delta = useDefaultElapsed
170
- ? 1000 / 60
171
- : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
184
+ if (!MotionGlobalConfig.useManualTiming) {
185
+ state.delta = useDefaultElapsed
186
+ ? 1000 / 60
187
+ : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
188
+ }
172
189
  state.timestamp = timestamp;
173
190
  state.isProcessing = true;
174
191
  // Unrolled render loop for better per-frame performance
@@ -393,7 +410,7 @@ class MotionValue {
393
410
  * This will be replaced by the build step with the latest version number.
394
411
  * When MotionValues are provided to motion components, warn if versions are mixed.
395
412
  */
396
- this.version = "12.3.1";
413
+ this.version = "12.4.0";
397
414
  /**
398
415
  * Tracks whether this value can output a velocity. Currently this is only true
399
416
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -2986,7 +3003,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
2986
3003
  */
2987
3004
  if (Array.isArray(easing))
2988
3005
  keyframeOptions.easing = easing;
2989
- return element.animate(keyframeOptions, {
3006
+ const animation = element.animate(keyframeOptions, {
2990
3007
  delay,
2991
3008
  duration,
2992
3009
  easing: !Array.isArray(easing) ? easing : "linear",
@@ -2994,6 +3011,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
2994
3011
  iterations: repeat + 1,
2995
3012
  direction: repeatType === "reverse" ? "alternate" : "normal",
2996
3013
  });
3014
+ return animation;
2997
3015
  }
2998
3016
 
2999
3017
  const supportsWaapi = /*@__PURE__*/ motionUtils.memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
@@ -4538,7 +4556,7 @@ function updateMotionValuesFromProps(element, next, prev) {
4538
4556
  * and warn against mismatches.
4539
4557
  */
4540
4558
  if (process.env.NODE_ENV === "development") {
4541
- warnOnce(nextValue.version === "12.3.1", `Attempting to mix Motion versions ${nextValue.version} with 12.3.1 may not work as expected.`);
4559
+ warnOnce(nextValue.version === "12.4.0", `Attempting to mix Motion versions ${nextValue.version} with 12.4.0 may not work as expected.`);
4542
4560
  }
4543
4561
  }
4544
4562
  else if (isMotionValue(prevValue)) {
@@ -6080,13 +6098,6 @@ const globalProjectionState = {
6080
6098
  hasEverUpdated: false,
6081
6099
  };
6082
6100
 
6083
- const metrics = {
6084
- type: "projectionFrame",
6085
- totalNodes: 0,
6086
- resolvedTargetDeltas: 0,
6087
- recalculatedProjection: 0,
6088
- };
6089
- const isDebug = typeof window !== "undefined" && window.MotionDebug !== undefined;
6090
6101
  const transformAxes = ["", "X", "Y", "Z"];
6091
6102
  const hiddenVisibility = { visibility: "hidden" };
6092
6103
  /**
@@ -6236,23 +6247,10 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
6236
6247
  */
6237
6248
  this.updateProjection = () => {
6238
6249
  this.projectionUpdateScheduled = false;
6239
- /**
6240
- * Reset debug counts. Manually resetting rather than creating a new
6241
- * object each frame.
6242
- */
6243
- if (isDebug) {
6244
- metrics.totalNodes =
6245
- metrics.resolvedTargetDeltas =
6246
- metrics.recalculatedProjection =
6247
- 0;
6248
- }
6249
6250
  this.nodes.forEach(propagateDirtyNodes);
6250
6251
  this.nodes.forEach(resolveTargetDelta);
6251
6252
  this.nodes.forEach(calcProjection);
6252
6253
  this.nodes.forEach(cleanDirtyNodes);
6253
- if (isDebug) {
6254
- window.MotionDebug.record(metrics);
6255
- }
6256
6254
  };
6257
6255
  /**
6258
6256
  * Frame calculations
@@ -6895,12 +6893,6 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
6895
6893
  this.relativeParent = this.relativeTarget = undefined;
6896
6894
  }
6897
6895
  }
6898
- /**
6899
- * Increase debug counter for resolved target deltas
6900
- */
6901
- if (isDebug) {
6902
- metrics.resolvedTargetDeltas++;
6903
- }
6904
6896
  }
6905
6897
  getClosestProjectingParent() {
6906
6898
  if (!this.parent ||
@@ -7026,12 +7018,6 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
7026
7018
  this.scheduleRender();
7027
7019
  this.notifyListeners("projectionUpdate", target);
7028
7020
  }
7029
- /**
7030
- * Increase debug counter for recalculated projections
7031
- */
7032
- if (isDebug) {
7033
- metrics.recalculatedProjection++;
7034
- }
7035
7021
  }
7036
7022
  hide() {
7037
7023
  this.isVisible = false;
@@ -7138,6 +7124,8 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
7138
7124
  this.mixTargetDelta(latest);
7139
7125
  options.onUpdate && options.onUpdate(latest);
7140
7126
  },
7127
+ onStop: () => {
7128
+ },
7141
7129
  onComplete: () => {
7142
7130
  options.onComplete && options.onComplete();
7143
7131
  this.completeAnimation();
@@ -7535,12 +7523,6 @@ function notifyLayoutUpdate(node) {
7535
7523
  node.options.transition = undefined;
7536
7524
  }
7537
7525
  function propagateDirtyNodes(node) {
7538
- /**
7539
- * Increase debug counter for nodes encountered this frame
7540
- */
7541
- if (isDebug) {
7542
- metrics.totalNodes++;
7543
- }
7544
7526
  if (!node.parent)
7545
7527
  return;
7546
7528
  /**
@@ -0,0 +1,288 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var motionUtils = require('motion-utils');
6
+
7
+ const stepsOrder = [
8
+ "read", // Read
9
+ "resolveKeyframes", // Write/Read/Write/Read
10
+ "update", // Compute
11
+ "preRender", // Compute
12
+ "render", // Write
13
+ "postRender", // Compute
14
+ ];
15
+
16
+ const statsBuffer = {
17
+ value: null,
18
+ addProjectionMetrics: null,
19
+ };
20
+
21
+ function createRenderStep(runNextFrame, stepName) {
22
+ /**
23
+ * We create and reuse two queues, one to queue jobs for the current frame
24
+ * and one for the next. We reuse to avoid triggering GC after x frames.
25
+ */
26
+ let thisFrame = new Set();
27
+ let nextFrame = new Set();
28
+ /**
29
+ * Track whether we're currently processing jobs in this step. This way
30
+ * we can decide whether to schedule new jobs for this frame or next.
31
+ */
32
+ let isProcessing = false;
33
+ let flushNextFrame = false;
34
+ /**
35
+ * A set of processes which were marked keepAlive when scheduled.
36
+ */
37
+ const toKeepAlive = new WeakSet();
38
+ let latestFrameData = {
39
+ delta: 0.0,
40
+ timestamp: 0.0,
41
+ isProcessing: false,
42
+ };
43
+ let numCalls = 0;
44
+ function triggerCallback(callback) {
45
+ if (toKeepAlive.has(callback)) {
46
+ step.schedule(callback);
47
+ runNextFrame();
48
+ }
49
+ numCalls++;
50
+ callback(latestFrameData);
51
+ }
52
+ const step = {
53
+ /**
54
+ * Schedule a process to run on the next frame.
55
+ */
56
+ schedule: (callback, keepAlive = false, immediate = false) => {
57
+ const addToCurrentFrame = immediate && isProcessing;
58
+ const queue = addToCurrentFrame ? thisFrame : nextFrame;
59
+ if (keepAlive)
60
+ toKeepAlive.add(callback);
61
+ if (!queue.has(callback))
62
+ queue.add(callback);
63
+ return callback;
64
+ },
65
+ /**
66
+ * Cancel the provided callback from running on the next frame.
67
+ */
68
+ cancel: (callback) => {
69
+ nextFrame.delete(callback);
70
+ toKeepAlive.delete(callback);
71
+ },
72
+ /**
73
+ * Execute all schedule callbacks.
74
+ */
75
+ process: (frameData) => {
76
+ latestFrameData = frameData;
77
+ /**
78
+ * If we're already processing we've probably been triggered by a flushSync
79
+ * inside an existing process. Instead of executing, mark flushNextFrame
80
+ * as true and ensure we flush the following frame at the end of this one.
81
+ */
82
+ if (isProcessing) {
83
+ flushNextFrame = true;
84
+ return;
85
+ }
86
+ isProcessing = true;
87
+ [thisFrame, nextFrame] = [nextFrame, thisFrame];
88
+ // Execute this frame
89
+ thisFrame.forEach(triggerCallback);
90
+ /**
91
+ * If we're recording stats then
92
+ */
93
+ if (stepName && statsBuffer.value) {
94
+ statsBuffer.value.frameloop[stepName].push(numCalls);
95
+ }
96
+ numCalls = 0;
97
+ // Clear the frame so no callbacks remain. This is to avoid
98
+ // memory leaks should this render step not run for a while.
99
+ thisFrame.clear();
100
+ isProcessing = false;
101
+ if (flushNextFrame) {
102
+ flushNextFrame = false;
103
+ step.process(frameData);
104
+ }
105
+ },
106
+ };
107
+ return step;
108
+ }
109
+
110
+ const maxElapsed = 40;
111
+ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
112
+ let runNextFrame = false;
113
+ let useDefaultElapsed = true;
114
+ const state = {
115
+ delta: 0.0,
116
+ timestamp: 0.0,
117
+ isProcessing: false,
118
+ };
119
+ const flagRunNextFrame = () => (runNextFrame = true);
120
+ const steps = stepsOrder.reduce((acc, key) => {
121
+ acc[key] = createRenderStep(flagRunNextFrame, allowKeepAlive ? key : undefined);
122
+ return acc;
123
+ }, {});
124
+ const { read, resolveKeyframes, update, preRender, render, postRender } = steps;
125
+ const processBatch = () => {
126
+ const timestamp = performance.now();
127
+ runNextFrame = false;
128
+ {
129
+ state.delta = useDefaultElapsed
130
+ ? 1000 / 60
131
+ : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
132
+ }
133
+ state.timestamp = timestamp;
134
+ state.isProcessing = true;
135
+ // Unrolled render loop for better per-frame performance
136
+ read.process(state);
137
+ resolveKeyframes.process(state);
138
+ update.process(state);
139
+ preRender.process(state);
140
+ render.process(state);
141
+ postRender.process(state);
142
+ state.isProcessing = false;
143
+ if (runNextFrame && allowKeepAlive) {
144
+ useDefaultElapsed = false;
145
+ scheduleNextBatch(processBatch);
146
+ }
147
+ };
148
+ const wake = () => {
149
+ runNextFrame = true;
150
+ useDefaultElapsed = true;
151
+ if (!state.isProcessing) {
152
+ scheduleNextBatch(processBatch);
153
+ }
154
+ };
155
+ const schedule = stepsOrder.reduce((acc, key) => {
156
+ const step = steps[key];
157
+ acc[key] = (process, keepAlive = false, immediate = false) => {
158
+ if (!runNextFrame)
159
+ wake();
160
+ return step.schedule(process, keepAlive, immediate);
161
+ };
162
+ return acc;
163
+ }, {});
164
+ const cancel = (process) => {
165
+ for (let i = 0; i < stepsOrder.length; i++) {
166
+ steps[stepsOrder[i]].cancel(process);
167
+ }
168
+ };
169
+ return { schedule, cancel, state, steps };
170
+ }
171
+
172
+ const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : motionUtils.noop, true);
173
+
174
+ const activeAnimations = {
175
+ layout: 0,
176
+ mainThread: 0,
177
+ waapi: 0,
178
+ };
179
+
180
+ function record() {
181
+ const { value } = statsBuffer;
182
+ if (value === null) {
183
+ cancelFrame(record);
184
+ return;
185
+ }
186
+ value.frameloop.rate.push(frameData.delta);
187
+ value.animations.mainThread.push(activeAnimations.mainThread);
188
+ value.animations.waapi.push(activeAnimations.waapi);
189
+ value.animations.layout.push(activeAnimations.layout);
190
+ }
191
+ function mean(values) {
192
+ return values.reduce((acc, value) => acc + value, 0) / values.length;
193
+ }
194
+ function summarise(values, calcAverage = mean) {
195
+ if (values.length === 0) {
196
+ return {
197
+ min: 0,
198
+ max: 0,
199
+ avg: 0,
200
+ };
201
+ }
202
+ return {
203
+ min: Math.min(...values),
204
+ max: Math.max(...values),
205
+ avg: calcAverage(values),
206
+ };
207
+ }
208
+ const msToFps = (ms) => Math.round(1000 / ms);
209
+ function clearStatsBuffer() {
210
+ statsBuffer.value = null;
211
+ statsBuffer.addProjectionMetrics = null;
212
+ }
213
+ function reportStats() {
214
+ const { value } = statsBuffer;
215
+ if (!value) {
216
+ throw new Error("Stats are not being measured");
217
+ }
218
+ clearStatsBuffer();
219
+ cancelFrame(record);
220
+ const summary = {
221
+ frameloop: {
222
+ rate: summarise(value.frameloop.rate),
223
+ read: summarise(value.frameloop.read),
224
+ resolveKeyframes: summarise(value.frameloop.resolveKeyframes),
225
+ update: summarise(value.frameloop.update),
226
+ preRender: summarise(value.frameloop.preRender),
227
+ render: summarise(value.frameloop.render),
228
+ postRender: summarise(value.frameloop.postRender),
229
+ },
230
+ animations: {
231
+ mainThread: summarise(value.animations.mainThread),
232
+ waapi: summarise(value.animations.waapi),
233
+ layout: summarise(value.animations.layout),
234
+ },
235
+ layoutProjection: {
236
+ nodes: summarise(value.layoutProjection.nodes),
237
+ calculatedTargetDeltas: summarise(value.layoutProjection.calculatedTargetDeltas),
238
+ calculatedProjections: summarise(value.layoutProjection.calculatedProjections),
239
+ },
240
+ };
241
+ /**
242
+ * Convert the rate to FPS
243
+ */
244
+ const { rate } = summary.frameloop;
245
+ rate.min = msToFps(rate.min);
246
+ rate.max = msToFps(rate.max);
247
+ rate.avg = msToFps(rate.avg);
248
+ [rate.min, rate.max] = [rate.max, rate.min];
249
+ return summary;
250
+ }
251
+ function recordStats() {
252
+ if (statsBuffer.value) {
253
+ clearStatsBuffer();
254
+ throw new Error("Stats are already being measured");
255
+ }
256
+ const newStatsBuffer = statsBuffer;
257
+ newStatsBuffer.value = {
258
+ frameloop: {
259
+ rate: [],
260
+ read: [],
261
+ resolveKeyframes: [],
262
+ update: [],
263
+ preRender: [],
264
+ render: [],
265
+ postRender: [],
266
+ },
267
+ animations: {
268
+ mainThread: [],
269
+ waapi: [],
270
+ layout: [],
271
+ },
272
+ layoutProjection: {
273
+ nodes: [],
274
+ calculatedTargetDeltas: [],
275
+ calculatedProjections: [],
276
+ },
277
+ };
278
+ newStatsBuffer.addProjectionMetrics = (metrics) => {
279
+ const { layoutProjection } = newStatsBuffer.value;
280
+ layoutProjection.nodes.push(metrics.nodes);
281
+ layoutProjection.calculatedTargetDeltas.push(metrics.calculatedTargetDeltas);
282
+ layoutProjection.calculatedProjections.push(metrics.calculatedProjections);
283
+ };
284
+ frame.postRender(record, true);
285
+ return reportStats;
286
+ }
287
+
288
+ exports.recordStats = recordStats;
@@ -408,7 +408,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
408
408
  */
409
409
  if (Array.isArray(easing))
410
410
  keyframeOptions.easing = easing;
411
- return element.animate(keyframeOptions, {
411
+ const animation = element.animate(keyframeOptions, {
412
412
  delay,
413
413
  duration,
414
414
  easing: !Array.isArray(easing) ? easing : "linear",
@@ -416,6 +416,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
416
416
  iterations: repeat + 1,
417
417
  direction: repeatType === "reverse" ? "alternate" : "normal",
418
418
  });
419
+ return animation;
419
420
  }
420
421
 
421
422
  const createUnitType = (unit) => ({
package/dist/cjs/dom.js CHANGED
@@ -697,7 +697,21 @@ const MotionGlobalConfig = {
697
697
  useManualTiming: false,
698
698
  };
699
699
 
700
- function createRenderStep(runNextFrame) {
700
+ const stepsOrder = [
701
+ "read", // Read
702
+ "resolveKeyframes", // Write/Read/Write/Read
703
+ "update", // Compute
704
+ "preRender", // Compute
705
+ "render", // Write
706
+ "postRender", // Compute
707
+ ];
708
+
709
+ const statsBuffer = {
710
+ value: null,
711
+ addProjectionMetrics: null,
712
+ };
713
+
714
+ function createRenderStep(runNextFrame, stepName) {
701
715
  /**
702
716
  * We create and reuse two queues, one to queue jobs for the current frame
703
717
  * and one for the next. We reuse to avoid triggering GC after x frames.
@@ -719,11 +733,13 @@ function createRenderStep(runNextFrame) {
719
733
  timestamp: 0.0,
720
734
  isProcessing: false,
721
735
  };
736
+ let numCalls = 0;
722
737
  function triggerCallback(callback) {
723
738
  if (toKeepAlive.has(callback)) {
724
739
  step.schedule(callback);
725
740
  runNextFrame();
726
741
  }
742
+ numCalls++;
727
743
  callback(latestFrameData);
728
744
  }
729
745
  const step = {
@@ -764,6 +780,13 @@ function createRenderStep(runNextFrame) {
764
780
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
765
781
  // Execute this frame
766
782
  thisFrame.forEach(triggerCallback);
783
+ /**
784
+ * If we're recording stats then
785
+ */
786
+ if (stepName && statsBuffer.value) {
787
+ statsBuffer.value.frameloop[stepName].push(numCalls);
788
+ }
789
+ numCalls = 0;
767
790
  // Clear the frame so no callbacks remain. This is to avoid
768
791
  // memory leaks should this render step not run for a while.
769
792
  thisFrame.clear();
@@ -777,14 +800,6 @@ function createRenderStep(runNextFrame) {
777
800
  return step;
778
801
  }
779
802
 
780
- const stepsOrder = [
781
- "read", // Read
782
- "resolveKeyframes", // Write/Read/Write/Read
783
- "update", // Compute
784
- "preRender", // Compute
785
- "render", // Write
786
- "postRender", // Compute
787
- ];
788
803
  const maxElapsed$1 = 40;
789
804
  function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
790
805
  let runNextFrame = false;
@@ -796,16 +811,18 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
796
811
  };
797
812
  const flagRunNextFrame = () => (runNextFrame = true);
798
813
  const steps = stepsOrder.reduce((acc, key) => {
799
- acc[key] = createRenderStep(flagRunNextFrame);
814
+ acc[key] = createRenderStep(flagRunNextFrame, allowKeepAlive ? key : undefined);
800
815
  return acc;
801
816
  }, {});
802
817
  const { read, resolveKeyframes, update, preRender, render, postRender } = steps;
803
818
  const processBatch = () => {
804
819
  const timestamp = performance.now();
805
820
  runNextFrame = false;
806
- state.delta = useDefaultElapsed
807
- ? 1000 / 60
808
- : Math.max(Math.min(timestamp - state.timestamp, maxElapsed$1), 1);
821
+ {
822
+ state.delta = useDefaultElapsed
823
+ ? 1000 / 60
824
+ : Math.max(Math.min(timestamp - state.timestamp, maxElapsed$1), 1);
825
+ }
809
826
  state.timestamp = timestamp;
810
827
  state.isProcessing = true;
811
828
  // Unrolled render loop for better per-frame performance
@@ -994,7 +1011,7 @@ class MotionValue {
994
1011
  * This will be replaced by the build step with the latest version number.
995
1012
  * When MotionValues are provided to motion components, warn if versions are mixed.
996
1013
  */
997
- this.version = "12.3.1";
1014
+ this.version = "12.4.0";
998
1015
  /**
999
1016
  * Tracks whether this value can output a velocity. Currently this is only true
1000
1017
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -3293,7 +3310,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
3293
3310
  */
3294
3311
  if (Array.isArray(easing))
3295
3312
  keyframeOptions.easing = easing;
3296
- return element.animate(keyframeOptions, {
3313
+ const animation = element.animate(keyframeOptions, {
3297
3314
  delay,
3298
3315
  duration,
3299
3316
  easing: !Array.isArray(easing) ? easing : "linear",
@@ -3301,6 +3318,7 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
3301
3318
  iterations: repeat + 1,
3302
3319
  direction: repeatType === "reverse" ? "alternate" : "normal",
3303
3320
  });
3321
+ return animation;
3304
3322
  }
3305
3323
 
3306
3324
  const supportsWaapi = /*@__PURE__*/ motionUtils.memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
@@ -3928,7 +3946,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3928
3946
  * and warn against mismatches.
3929
3947
  */
3930
3948
  if (process.env.NODE_ENV === "development") {
3931
- warnOnce(nextValue.version === "12.3.1", `Attempting to mix Motion versions ${nextValue.version} with 12.3.1 may not work as expected.`);
3949
+ warnOnce(nextValue.version === "12.4.0", `Attempting to mix Motion versions ${nextValue.version} with 12.4.0 may not work as expected.`);
3932
3950
  }
3933
3951
  }
3934
3952
  else if (isMotionValue(prevValue)) {