framer-motion 12.38.0 → 12.40.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.
Files changed (69) hide show
  1. package/README.md +1 -3
  2. package/client/package.json +1 -1
  3. package/dist/cjs/client.js +5 -4
  4. package/dist/cjs/client.js.map +1 -1
  5. package/dist/cjs/dom-mini.js +64 -12
  6. package/dist/cjs/dom-mini.js.map +1 -1
  7. package/dist/cjs/dom.js +89 -22
  8. package/dist/cjs/dom.js.map +1 -1
  9. package/dist/cjs/{feature-bundle-BieBX2Jn.js → feature-bundle-frRcWALD.js} +32 -808
  10. package/dist/cjs/feature-bundle-frRcWALD.js.map +1 -0
  11. package/dist/cjs/index-6W16WHlG.js +802 -0
  12. package/dist/cjs/index-6W16WHlG.js.map +1 -0
  13. package/dist/cjs/index.js +211 -103
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/m.js +5 -762
  16. package/dist/cjs/m.js.map +1 -1
  17. package/dist/{types/client.d.ts → client.d.ts} +194 -3
  18. package/dist/dom-mini.d.ts +1 -0
  19. package/dist/dom-mini.js +1 -1
  20. package/dist/dom.d.ts +2 -0
  21. package/dist/dom.js +1 -1
  22. package/dist/es/animation/animate/index.mjs +8 -7
  23. package/dist/es/animation/animate/index.mjs.map +1 -1
  24. package/dist/es/animation/hooks/use-animate.mjs +4 -2
  25. package/dist/es/animation/hooks/use-animate.mjs.map +1 -1
  26. package/dist/es/animation/sequence/create.mjs +57 -9
  27. package/dist/es/animation/sequence/create.mjs.map +1 -1
  28. package/dist/es/animation/sequence/utils/calc-repeat-duration.mjs +2 -2
  29. package/dist/es/animation/sequence/utils/calc-repeat-duration.mjs.map +1 -1
  30. package/dist/es/animation/sequence/utils/normalize-times.mjs +6 -2
  31. package/dist/es/animation/sequence/utils/normalize-times.mjs.map +1 -1
  32. package/dist/es/components/AnimatePresence/PopChild.mjs +7 -2
  33. package/dist/es/components/AnimatePresence/PopChild.mjs.map +1 -1
  34. package/dist/es/components/Reorder/Group.mjs.map +1 -1
  35. package/dist/es/gestures/drag/VisualElementDragControls.mjs +15 -3
  36. package/dist/es/gestures/drag/VisualElementDragControls.mjs.map +1 -1
  37. package/dist/es/index.mjs +1 -1
  38. package/dist/es/motion/features/animation/exit.mjs +4 -1
  39. package/dist/es/motion/features/animation/exit.mjs.map +1 -1
  40. package/dist/es/motion/utils/use-motion-ref.mjs +3 -3
  41. package/dist/es/motion/utils/use-motion-ref.mjs.map +1 -1
  42. package/dist/es/render/dom/scroll/attach-function.mjs +2 -1
  43. package/dist/es/render/dom/scroll/attach-function.mjs.map +1 -1
  44. package/dist/es/render/dom/scroll/on-scroll-handler.mjs +8 -2
  45. package/dist/es/render/dom/scroll/on-scroll-handler.mjs.map +1 -1
  46. package/dist/es/render/dom/scroll/utils/is-element-tracking.mjs +10 -0
  47. package/dist/es/render/dom/scroll/utils/is-element-tracking.mjs.map +1 -0
  48. package/dist/es/value/use-scroll.mjs +44 -14
  49. package/dist/es/value/use-scroll.mjs.map +1 -1
  50. package/dist/framer-motion.dev.js +837 -475
  51. package/dist/framer-motion.js +1 -1
  52. package/dist/{types/index.d.ts → index.d.ts} +230 -8
  53. package/dist/size-rollup-animate.js +1 -1
  54. package/dist/size-rollup-animate.js.map +1 -1
  55. package/dist/size-rollup-dom-animation-assets.js +1 -1
  56. package/dist/size-rollup-dom-animation-m.js +1 -1
  57. package/dist/size-rollup-dom-animation.js +1 -1
  58. package/dist/size-rollup-dom-max-assets.js +1 -1
  59. package/dist/size-rollup-dom-max.js +1 -1
  60. package/dist/size-rollup-m.js +1 -1
  61. package/dist/size-rollup-m.js.map +1 -1
  62. package/dist/size-rollup-motion.js +1 -1
  63. package/dist/size-rollup-motion.js.map +1 -1
  64. package/dist/size-rollup-scroll.js +1 -1
  65. package/dist/size-rollup-scroll.js.map +1 -1
  66. package/dist/size-rollup-waapi-animate.js.map +1 -1
  67. package/package.json +7 -7
  68. package/dist/cjs/feature-bundle-BieBX2Jn.js.map +0 -1
  69. package/dist/types.d-DOCC-kZB.d.ts +0 -223
package/dist/cjs/dom.js CHANGED
@@ -27,8 +27,8 @@ function resolveSubjects(subject, keyframes, scope, selectorCache) {
27
27
  }
28
28
  }
29
29
 
30
- function calculateRepeatDuration(duration, repeat, _repeatDelay) {
31
- return duration * (repeat + 1);
30
+ function calculateRepeatDuration(duration, repeat, repeatDelay) {
31
+ return duration * (repeat + 1) + repeatDelay * repeat;
32
32
  }
33
33
 
34
34
  /**
@@ -84,10 +84,14 @@ function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
84
84
  * if we have original times of [0, 0.5, 1] then our repeated times will
85
85
  * be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
86
86
  * down to a 0-1 scale.
87
+ *
88
+ * `repeatDelayUnits` is the repeatDelay expressed in units of a single
89
+ * iteration's duration, so the total span equals `(repeat + 1) + repeat * repeatDelayUnits`.
87
90
  */
88
- function normalizeTimes(times, repeat) {
91
+ function normalizeTimes(times, repeat, repeatDelayUnits = 0) {
92
+ const totalUnits = repeat + 1 + repeat * repeatDelayUnits;
89
93
  for (let i = 0; i < times.length; i++) {
90
- times[i] = times[i] / (repeat + 1);
94
+ times[i] = times[i] / totalUnits;
91
95
  }
92
96
  }
93
97
 
@@ -208,25 +212,73 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
208
212
  valueKeyframesAsList.length === 1 &&
209
213
  valueKeyframesAsList.unshift(null);
210
214
  /**
211
- * Handle repeat options
215
+ * Segments can't express `repeat: Infinity` or very large
216
+ * counts — they'd leave dead time after the segment or
217
+ * explode the keyframe array. Ignore with a warning.
212
218
  */
213
219
  if (repeat) {
214
- motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20", "repeat-count-high");
215
- duration = calculateRepeatDuration(duration, repeat);
220
+ motionUtils.warning(repeat < MAX_REPEAT, `Sequence segments can't repeat ${repeat} times ignoring repeat option. Use a value below ${MAX_REPEAT} or apply repeat at the sequence level instead.`);
221
+ }
222
+ if (repeat && repeat < MAX_REPEAT) {
223
+ /**
224
+ * Express repeatDelay in units of a single iteration's duration
225
+ * so it can be added to the per-iteration time offsets below
226
+ * before they're normalized to 0-1.
227
+ */
228
+ const repeatDelayUnits = duration > 0 ? repeatDelay / duration : 0;
229
+ duration = calculateRepeatDuration(duration, repeat, repeatDelay);
216
230
  const originalKeyframes = [...valueKeyframesAsList];
217
231
  const originalTimes = [...times];
218
232
  ease = Array.isArray(ease) ? [...ease] : [ease];
219
233
  const originalEase = [...ease];
234
+ /**
235
+ * For reverse/mirror, alternate iterations play the segment
236
+ * backwards. mirror matches JSAnimation's mirroredGenerator:
237
+ * reversed keyframes, easings unchanged. reverse matches
238
+ * JSAnimation's iterationProgress = 1 - p: reversed
239
+ * keyframes, easing array reversed AND each function easing
240
+ * mapped through reverseEasing (string easings unchanged —
241
+ * they're resolved later by the keyframes engine).
242
+ */
243
+ const isFlipping = repeatType === "reverse" || repeatType === "mirror";
244
+ let flippedKeyframes = originalKeyframes;
245
+ let flippedEases = originalEase;
246
+ if (isFlipping) {
247
+ flippedKeyframes = [...originalKeyframes].reverse();
248
+ if (repeatType === "reverse") {
249
+ flippedEases = [...originalEase]
250
+ .reverse()
251
+ .map((e) => typeof e === "function"
252
+ ? motionUtils.reverseEasing(e)
253
+ : e);
254
+ }
255
+ }
220
256
  for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
221
- valueKeyframesAsList.push(...originalKeyframes);
222
- for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
223
- times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
257
+ const isFlipped = isFlipping && repeatIndex % 2 === 0;
258
+ const iterKeyframes = isFlipped
259
+ ? flippedKeyframes
260
+ : originalKeyframes;
261
+ const iterEase = isFlipped ? flippedEases : originalEase;
262
+ const iterStartOffset = (repeatIndex + 1) * (1 + repeatDelayUnits);
263
+ /**
264
+ * If repeatDelay is set, hold the previous iteration's
265
+ * final value through the delay by inserting a keyframe
266
+ * at the moment the next iteration begins.
267
+ */
268
+ if (repeatDelayUnits > 0) {
269
+ valueKeyframesAsList.push(valueKeyframesAsList[valueKeyframesAsList.length - 1]);
270
+ times.push(iterStartOffset);
271
+ ease.push("linear");
272
+ }
273
+ valueKeyframesAsList.push(...iterKeyframes);
274
+ for (let keyframeIndex = 0; keyframeIndex < iterKeyframes.length; keyframeIndex++) {
275
+ times.push(originalTimes[keyframeIndex] + iterStartOffset);
224
276
  ease.push(keyframeIndex === 0
225
277
  ? "linear"
226
- : motionUtils.getEasingForSegment(originalEase, keyframeIndex - 1));
278
+ : motionUtils.getEasingForSegment(iterEase, keyframeIndex - 1));
227
279
  }
228
280
  }
229
- normalizeTimes(times, repeat);
281
+ normalizeTimes(times, repeat, repeatDelayUnits);
230
282
  }
231
283
  const targetTime = startTime + duration;
232
284
  /**
@@ -474,21 +526,24 @@ function isSequence(value) {
474
526
  * to a specific element.
475
527
  */
476
528
  function createScopedAnimate(options = {}) {
477
- const { scope, reduceMotion } = options;
529
+ const { scope, reduceMotion, skipAnimations } = options;
478
530
  /**
479
531
  * Implementation
480
532
  */
481
533
  function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options) {
482
534
  let animations = [];
483
535
  let animationOnComplete;
536
+ const inherited = {};
537
+ if (reduceMotion !== undefined)
538
+ inherited.reduceMotion = reduceMotion;
539
+ if (skipAnimations !== undefined)
540
+ inherited.skipAnimations = skipAnimations;
484
541
  if (isSequence(subjectOrSequence)) {
485
542
  const { onComplete, ...sequenceOptions } = optionsOrKeyframes || {};
486
543
  if (typeof onComplete === "function") {
487
544
  animationOnComplete = onComplete;
488
545
  }
489
- animations = animateSequence(subjectOrSequence, reduceMotion !== undefined
490
- ? { reduceMotion, ...sequenceOptions }
491
- : sequenceOptions, scope);
546
+ animations = animateSequence(subjectOrSequence, { ...inherited, ...sequenceOptions }, scope);
492
547
  }
493
548
  else {
494
549
  // Extract top-level onComplete so it doesn't get applied per-value
@@ -496,9 +551,7 @@ function createScopedAnimate(options = {}) {
496
551
  if (typeof onComplete === "function") {
497
552
  animationOnComplete = onComplete;
498
553
  }
499
- animations = animateSubject(subjectOrSequence, optionsOrKeyframes, (reduceMotion !== undefined
500
- ? { reduceMotion, ...rest }
501
- : rest), scope);
554
+ animations = animateSubject(subjectOrSequence, optionsOrKeyframes, { ...inherited, ...rest }, scope);
502
555
  }
503
556
  const animation = new motionDom.GroupAnimationWithThen(animations);
504
557
  if (animationOnComplete) {
@@ -900,10 +953,16 @@ function measure(container, target = container, info) {
900
953
  info.y.containerLength = container.clientHeight;
901
954
  /**
902
955
  * In development mode ensure scroll containers aren't position: static as this makes
903
- * it difficult to measure their relative positions.
956
+ * it difficult to measure their relative positions. The document scrolling element
957
+ * is exempt: offsetParent measurements naturally resolve relative to the document.
904
958
  */
905
959
  if (process.env.NODE_ENV !== "production") {
906
- if (container && target && target !== container) {
960
+ if (container &&
961
+ target &&
962
+ target !== container &&
963
+ container !== document.documentElement &&
964
+ container !== document.scrollingElement &&
965
+ container !== document.body) {
907
966
  motionUtils.warnOnce(getComputedStyle(container).position !== "static", "Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly.");
908
967
  }
909
968
  }
@@ -1185,6 +1244,14 @@ function attachToAnimation(animation, options) {
1185
1244
  });
1186
1245
  }
1187
1246
 
1247
+ /**
1248
+ * Currently, we only support element tracking with `scrollInfo`, though in
1249
+ * the future we can also offer ViewTimeline support.
1250
+ */
1251
+ function isElementTracking(options) {
1252
+ return options && (options.target || options.offset);
1253
+ }
1254
+
1188
1255
  /**
1189
1256
  * If the onScroll function has two arguments, it's expecting
1190
1257
  * more specific information about the scroll from scrollInfo.
@@ -1193,7 +1260,7 @@ function isOnScrollWithInfo(onScroll) {
1193
1260
  return onScroll.length === 2;
1194
1261
  }
1195
1262
  function attachToFunction(onScroll, options) {
1196
- if (isOnScrollWithInfo(onScroll)) {
1263
+ if (isOnScrollWithInfo(onScroll) || isElementTracking(options)) {
1197
1264
  return scrollInfo((info) => {
1198
1265
  onScroll(info[options.axis].progress, info);
1199
1266
  }, options);