framer-motion 11.14.3 → 11.15.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.
@@ -250,10 +250,11 @@ function createRenderStep(runNextFrame) {
250
250
  }
251
251
  isProcessing = true;
252
252
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
253
- // Clear the next frame queue
254
- nextFrame.clear();
255
253
  // Execute this frame
256
254
  thisFrame.forEach(triggerCallback);
255
+ // Clear the frame so no callbacks remain. This is to avoid
256
+ // memory leaks should this render step not run for a while.
257
+ thisFrame.clear();
257
258
  isProcessing = false;
258
259
  if (flushNextFrame) {
259
260
  flushNextFrame = false;
@@ -3333,7 +3334,7 @@ class MotionValue {
3333
3334
  * This will be replaced by the build step with the latest version number.
3334
3335
  * When MotionValues are provided to motion components, warn if versions are mixed.
3335
3336
  */
3336
- this.version = "11.14.3";
3337
+ this.version = "11.15.0";
3337
3338
  /**
3338
3339
  * Tracks whether this value can output a velocity. Currently this is only true
3339
3340
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -5840,7 +5841,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5840
5841
  * and warn against mismatches.
5841
5842
  */
5842
5843
  if (process.env.NODE_ENV === "development") {
5843
- warnOnce(nextValue.version === "11.14.3", `Attempting to mix Motion versions ${nextValue.version} with 11.14.3 may not work as expected.`);
5844
+ warnOnce(nextValue.version === "11.15.0", `Attempting to mix Motion versions ${nextValue.version} with 11.15.0 may not work as expected.`);
5844
5845
  }
5845
5846
  }
5846
5847
  else if (isMotionValue(prevValue)) {
package/dist/cjs/dom.js CHANGED
@@ -75,10 +75,11 @@ function createRenderStep(runNextFrame) {
75
75
  }
76
76
  isProcessing = true;
77
77
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
78
- // Clear the next frame queue
79
- nextFrame.clear();
80
78
  // Execute this frame
81
79
  thisFrame.forEach(triggerCallback);
80
+ // Clear the frame so no callbacks remain. This is to avoid
81
+ // memory leaks should this render step not run for a while.
82
+ thisFrame.clear();
82
83
  isProcessing = false;
83
84
  if (flushNextFrame) {
84
85
  flushNextFrame = false;
@@ -280,7 +281,7 @@ class MotionValue {
280
281
  * This will be replaced by the build step with the latest version number.
281
282
  * When MotionValues are provided to motion components, warn if versions are mixed.
282
283
  */
283
- this.version = "11.14.3";
284
+ this.version = "11.15.0";
284
285
  /**
285
286
  * Tracks whether this value can output a velocity. Currently this is only true
286
287
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -1126,7 +1127,24 @@ function compareByTime(a, b) {
1126
1127
  }
1127
1128
  }
1128
1129
 
1130
+ /**
1131
+ * Take an array of times that represent repeated keyframes. For instance
1132
+ * if we have original times of [0, 0.5, 1] then our repeated times will
1133
+ * be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
1134
+ * down to a 0-1 scale.
1135
+ */
1136
+ function normalizeTimes(times, repeat) {
1137
+ for (let i = 0; i < times.length; i++) {
1138
+ times[i] = times[i] / (repeat + 1);
1139
+ }
1140
+ }
1141
+
1142
+ function calculateRepeatDuration(duration, repeat, _repeatDelay) {
1143
+ return duration * (repeat + 1);
1144
+ }
1145
+
1129
1146
  const defaultSegmentEasing = "easeInOut";
1147
+ const MAX_REPEAT = 20;
1130
1148
  function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
1131
1149
  const defaultDuration = defaultTransition.duration || 0.3;
1132
1150
  const animationDefinitions = new Map();
@@ -1169,7 +1187,7 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
1169
1187
  let maxDuration = 0;
1170
1188
  const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
1171
1189
  const valueKeyframesAsList = keyframesAsList(valueKeyframes);
1172
- const { delay = 0, times = defaultOffset$1(valueKeyframesAsList), type = "keyframes", ...remainingTransition } = valueTransition;
1190
+ const { delay = 0, times = defaultOffset$1(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
1173
1191
  let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
1174
1192
  /**
1175
1193
  * Resolve stagger() if defined.
@@ -1207,7 +1225,6 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
1207
1225
  }
1208
1226
  duration !== null && duration !== void 0 ? duration : (duration = defaultDuration);
1209
1227
  const startTime = currentTime + calculatedDelay;
1210
- const targetTime = startTime + duration;
1211
1228
  /**
1212
1229
  * If there's only one time offset of 0, fill in a second with length 1
1213
1230
  */
@@ -1226,6 +1243,28 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
1226
1243
  */
1227
1244
  valueKeyframesAsList.length === 1 &&
1228
1245
  valueKeyframesAsList.unshift(null);
1246
+ /**
1247
+ * Handle repeat options
1248
+ */
1249
+ if (repeat) {
1250
+ motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
1251
+ duration = calculateRepeatDuration(duration, repeat);
1252
+ const originalKeyframes = [...valueKeyframesAsList];
1253
+ const originalTimes = [...times];
1254
+ ease = Array.isArray(ease) ? [...ease] : [ease];
1255
+ const originalEase = [...ease];
1256
+ for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
1257
+ valueKeyframesAsList.push(...originalKeyframes);
1258
+ for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
1259
+ times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
1260
+ ease.push(keyframeIndex === 0
1261
+ ? "linear"
1262
+ : getEasingForSegment(originalEase, keyframeIndex - 1));
1263
+ }
1264
+ }
1265
+ normalizeTimes(times, repeat);
1266
+ }
1267
+ const targetTime = startTime + duration;
1229
1268
  /**
1230
1269
  * Add keyframes, mapping offsets to absolute time.
1231
1270
  */
@@ -4117,7 +4156,7 @@ function updateMotionValuesFromProps(element, next, prev) {
4117
4156
  * and warn against mismatches.
4118
4157
  */
4119
4158
  if (process.env.NODE_ENV === "development") {
4120
- warnOnce(nextValue.version === "11.14.3", `Attempting to mix Motion versions ${nextValue.version} with 11.14.3 may not work as expected.`);
4159
+ warnOnce(nextValue.version === "11.15.0", `Attempting to mix Motion versions ${nextValue.version} with 11.15.0 may not work as expected.`);
4121
4160
  }
4122
4161
  }
4123
4162
  else if (isMotionValue(prevValue)) {
package/dist/cjs/index.js CHANGED
@@ -318,10 +318,11 @@ function createRenderStep(runNextFrame) {
318
318
  }
319
319
  isProcessing = true;
320
320
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
321
- // Clear the next frame queue
322
- nextFrame.clear();
323
321
  // Execute this frame
324
322
  thisFrame.forEach(triggerCallback);
323
+ // Clear the frame so no callbacks remain. This is to avoid
324
+ // memory leaks should this render step not run for a while.
325
+ thisFrame.clear();
325
326
  isProcessing = false;
326
327
  if (flushNextFrame) {
327
328
  flushNextFrame = false;
@@ -3416,7 +3417,7 @@ class MotionValue {
3416
3417
  * This will be replaced by the build step with the latest version number.
3417
3418
  * When MotionValues are provided to motion components, warn if versions are mixed.
3418
3419
  */
3419
- this.version = "11.14.3";
3420
+ this.version = "11.15.0";
3420
3421
  /**
3421
3422
  * Tracks whether this value can output a velocity. Currently this is only true
3422
3423
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -5939,7 +5940,24 @@ function compareByTime(a, b) {
5939
5940
  }
5940
5941
  }
5941
5942
 
5943
+ /**
5944
+ * Take an array of times that represent repeated keyframes. For instance
5945
+ * if we have original times of [0, 0.5, 1] then our repeated times will
5946
+ * be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
5947
+ * down to a 0-1 scale.
5948
+ */
5949
+ function normalizeTimes(times, repeat) {
5950
+ for (let i = 0; i < times.length; i++) {
5951
+ times[i] = times[i] / (repeat + 1);
5952
+ }
5953
+ }
5954
+
5955
+ function calculateRepeatDuration(duration, repeat, _repeatDelay) {
5956
+ return duration * (repeat + 1);
5957
+ }
5958
+
5942
5959
  const defaultSegmentEasing = "easeInOut";
5960
+ const MAX_REPEAT = 20;
5943
5961
  function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
5944
5962
  const defaultDuration = defaultTransition.duration || 0.3;
5945
5963
  const animationDefinitions = new Map();
@@ -5982,7 +6000,7 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
5982
6000
  let maxDuration = 0;
5983
6001
  const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
5984
6002
  const valueKeyframesAsList = keyframesAsList(valueKeyframes);
5985
- const { delay = 0, times = defaultOffset$1(valueKeyframesAsList), type = "keyframes", ...remainingTransition } = valueTransition;
6003
+ const { delay = 0, times = defaultOffset$1(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
5986
6004
  let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
5987
6005
  /**
5988
6006
  * Resolve stagger() if defined.
@@ -6020,7 +6038,6 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
6020
6038
  }
6021
6039
  duration !== null && duration !== void 0 ? duration : (duration = defaultDuration);
6022
6040
  const startTime = currentTime + calculatedDelay;
6023
- const targetTime = startTime + duration;
6024
6041
  /**
6025
6042
  * If there's only one time offset of 0, fill in a second with length 1
6026
6043
  */
@@ -6039,6 +6056,28 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
6039
6056
  */
6040
6057
  valueKeyframesAsList.length === 1 &&
6041
6058
  valueKeyframesAsList.unshift(null);
6059
+ /**
6060
+ * Handle repeat options
6061
+ */
6062
+ if (repeat) {
6063
+ motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
6064
+ duration = calculateRepeatDuration(duration, repeat);
6065
+ const originalKeyframes = [...valueKeyframesAsList];
6066
+ const originalTimes = [...times];
6067
+ ease = Array.isArray(ease) ? [...ease] : [ease];
6068
+ const originalEase = [...ease];
6069
+ for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
6070
+ valueKeyframesAsList.push(...originalKeyframes);
6071
+ for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
6072
+ times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
6073
+ ease.push(keyframeIndex === 0
6074
+ ? "linear"
6075
+ : getEasingForSegment(originalEase, keyframeIndex - 1));
6076
+ }
6077
+ }
6078
+ normalizeTimes(times, repeat);
6079
+ }
6080
+ const targetTime = startTime + duration;
6042
6081
  /**
6043
6082
  * Add keyframes, mapping offsets to absolute time.
6044
6083
  */
@@ -6243,7 +6282,7 @@ function updateMotionValuesFromProps(element, next, prev) {
6243
6282
  * and warn against mismatches.
6244
6283
  */
6245
6284
  if (process.env.NODE_ENV === "development") {
6246
- warnOnce(nextValue.version === "11.14.3", `Attempting to mix Motion versions ${nextValue.version} with 11.14.3 may not work as expected.`);
6285
+ warnOnce(nextValue.version === "11.15.0", `Attempting to mix Motion versions ${nextValue.version} with 11.15.0 may not work as expected.`);
6247
6286
  }
6248
6287
  }
6249
6288
  else if (isMotionValue(prevValue)) {
package/dist/cjs/m.js CHANGED
@@ -101,10 +101,11 @@ function createRenderStep(runNextFrame) {
101
101
  }
102
102
  isProcessing = true;
103
103
  [thisFrame, nextFrame] = [nextFrame, thisFrame];
104
- // Clear the next frame queue
105
- nextFrame.clear();
106
104
  // Execute this frame
107
105
  thisFrame.forEach(triggerCallback);
106
+ // Clear the frame so no callbacks remain. This is to avoid
107
+ // memory leaks should this render step not run for a while.
108
+ thisFrame.clear();
108
109
  isProcessing = false;
109
110
  if (flushNextFrame) {
110
111
  flushNextFrame = false;
package/dist/client.d.ts CHANGED
@@ -2538,9 +2538,9 @@ declare global {
2538
2538
 
2539
2539
  type DOMMotionComponents = HTMLMotionComponents & SVGMotionComponents;
2540
2540
 
2541
- declare const createMotionComponent: <Props, TagName extends string = "div">(Component: string | TagName | React$1.ForwardRefExoticComponent<Props>, { forwardMotionProps }?: {
2541
+ declare const createMotionComponent: <Props, TagName extends string = "div">(Component: string | TagName | React$1.ComponentType<Props>, { forwardMotionProps }?: {
2542
2542
  forwardMotionProps: boolean;
2543
- }) => TagName extends "symbol" | "filter" | "stop" | "clipPath" | "mask" | "marker" | "animate" | "text" | "path" | "image" | "circle" | "switch" | "svg" | keyof HTMLElements | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "line" | "linearGradient" | "metadata" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "textPath" | "tspan" | "use" | "view" ? DOMMotionComponents[TagName] : React$1.ForwardRefExoticComponent<MotionComponentProps<React$1.PropsWithChildren<Props>>>;
2543
+ }) => TagName extends "symbol" | "filter" | "stop" | "clipPath" | "mask" | "marker" | "animate" | "text" | "path" | "image" | "circle" | "switch" | "svg" | keyof HTMLElements | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "line" | "linearGradient" | "metadata" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "textPath" | "tspan" | "use" | "view" ? DOMMotionComponents[TagName] : React$1.ComponentType<MotionComponentProps<React$1.PropsWithChildren<Props>>>;
2544
2544
 
2545
2545
  /**
2546
2546
  * HTML components
package/dist/dom.d.ts CHANGED
@@ -665,6 +665,24 @@ interface SequenceOptions extends AnimationPlaybackOptions {
665
665
  duration?: number;
666
666
  defaultTransition?: Transition;
667
667
  }
668
+ interface AbsoluteKeyframe {
669
+ value: string | number | null;
670
+ at: number;
671
+ easing?: Easing;
672
+ }
673
+ type ValueSequence = AbsoluteKeyframe[];
674
+ interface SequenceMap {
675
+ [key: string]: ValueSequence;
676
+ }
677
+ type ResolvedAnimationDefinition = {
678
+ keyframes: {
679
+ [key: string]: UnresolvedValueKeyframe[];
680
+ };
681
+ transition: {
682
+ [key: string]: Transition;
683
+ };
684
+ };
685
+ type ResolvedAnimationDefinitions = Map<Element | MotionValue, ResolvedAnimationDefinition>;
668
686
 
669
687
  /**
670
688
  * Creates an animation function that is optionally scoped
@@ -1017,4 +1035,4 @@ declare const sync: Batcher;
1017
1035
  */
1018
1036
  declare const cancelSync: Record<string, (process: Process) => void>;
1019
1037
 
1020
- export { type BezierDefinition, type DOMKeyframesDefinition, type DelayedFunction, type Direction, type DynamicAnimationOptions, type Easing, type EasingDefinition, type EasingFunction, type EasingModifier, type InterpolateOptions, type MixerFactory, MotionValue, type PassiveEffect, type Subscriber, animate, animateMini, anticipate, backIn, backInOut, backOut, cancelFrame, cancelSync, circIn, circInOut, circOut, clamp, createScopedAnimate, cubicBezier, delayInSeconds as delay, distance, distance2D, easeIn, easeInOut, easeOut, frame, frameData, frameSteps, inView, inertia, interpolate, keyframes, mirrorEasing, mix, motionValue, pipe, progress, reverseEasing, scroll, scrollInfo, spring, stagger, steps, sync, time, transform, wrap };
1038
+ export { type AbsoluteKeyframe, type AnimationSequence, type At, type BezierDefinition, type DOMKeyframesDefinition, type DOMSegment, type DOMSegmentWithTransition, type DelayedFunction, type Direction, type DynamicAnimationOptions, type Easing, type EasingDefinition, type EasingFunction, type EasingModifier, type InterpolateOptions, type MixerFactory, MotionValue, type MotionValueSegment, type MotionValueSegmentWithTransition, type ObjectSegment, type ObjectSegmentWithTransition, type ObjectTarget, type PassiveEffect, type ResolvedAnimationDefinition, type ResolvedAnimationDefinitions, type Segment, type SequenceLabel, type SequenceLabelWithTime, type SequenceMap, type SequenceOptions, type SequenceTime, type Subscriber, type ValueSequence, animate, animateMini, anticipate, backIn, backInOut, backOut, cancelFrame, cancelSync, circIn, circInOut, circOut, clamp, createScopedAnimate, cubicBezier, delayInSeconds as delay, distance, distance2D, easeIn, easeInOut, easeOut, frame, frameData, frameSteps, inView, inertia, interpolate, keyframes, mirrorEasing, mix, motionValue, pipe, progress, reverseEasing, scroll, scrollInfo, spring, stagger, steps, sync, time, transform, wrap };