framer-motion 11.5.5 → 11.6.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.
@@ -338,7 +338,7 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
338
338
  return { schedule, cancel, state, steps };
339
339
  }
340
340
 
341
- const { schedule: frame, cancel: cancelFrame, state: frameData, steps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
341
+ const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
342
342
 
343
343
  /**
344
344
  * Check if the value is a zero value string like "0px" or "0%"
@@ -3032,14 +3032,7 @@ class GroupPlaybackControls {
3032
3032
  }
3033
3033
  }
3034
3034
 
3035
- const animateMotionValue = (name, value, target, transition = {}, element, isHandoff,
3036
- /**
3037
- * Currently used to remove values from will-change when an animation ends.
3038
- * Preferably this would be handled by event listeners on the MotionValue
3039
- * but these aren't consistent enough yet when considering the different ways
3040
- * an animation can be cancelled.
3041
- */
3042
- onEnd) => (onComplete) => {
3035
+ const animateMotionValue = (name, value, target, transition = {}, element, isHandoff) => (onComplete) => {
3043
3036
  const valueTransition = getValueTransition(transition, name) || {};
3044
3037
  /**
3045
3038
  * Most transition values are currently completely overwritten by value-specific
@@ -3066,9 +3059,7 @@ onEnd) => (onComplete) => {
3066
3059
  onComplete: () => {
3067
3060
  onComplete();
3068
3061
  valueTransition.onComplete && valueTransition.onComplete();
3069
- onEnd && onEnd();
3070
3062
  },
3071
- onStop: onEnd,
3072
3063
  name,
3073
3064
  motionValue: value,
3074
3065
  element: isHandoff ? undefined : element,
@@ -3227,7 +3218,7 @@ class MotionValue {
3227
3218
  * This will be replaced by the build step with the latest version number.
3228
3219
  * When MotionValues are provided to motion components, warn if versions are mixed.
3229
3220
  */
3230
- this.version = "11.5.5";
3221
+ this.version = "11.6.0";
3231
3222
  /**
3232
3223
  * Tracks whether this value can output a velocity. Currently this is only true
3233
3224
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -3552,42 +3543,17 @@ function getWillChangeName(name) {
3552
3543
  class WillChangeMotionValue extends MotionValue {
3553
3544
  constructor() {
3554
3545
  super(...arguments);
3555
- this.output = [];
3556
- this.counts = new Map();
3546
+ this.values = [];
3557
3547
  }
3558
3548
  add(name) {
3559
3549
  const styleName = getWillChangeName(name);
3560
- if (!styleName)
3561
- return;
3562
- /**
3563
- * Update counter. Each value has an indepdent counter
3564
- * as multiple sources could be requesting the same value
3565
- * gets added to will-change.
3566
- */
3567
- const prevCount = this.counts.get(styleName) || 0;
3568
- this.counts.set(styleName, prevCount + 1);
3569
- if (prevCount === 0) {
3570
- this.output.push(styleName);
3550
+ if (styleName) {
3551
+ addUniqueItem(this.values, styleName);
3571
3552
  this.update();
3572
3553
  }
3573
- /**
3574
- * Prevents the remove function from being called multiple times.
3575
- */
3576
- let hasRemoved = false;
3577
- return () => {
3578
- if (hasRemoved)
3579
- return;
3580
- hasRemoved = true;
3581
- const newCount = this.counts.get(styleName) - 1;
3582
- this.counts.set(styleName, newCount);
3583
- if (newCount === 0) {
3584
- removeItem(this.output, styleName);
3585
- this.update();
3586
- }
3587
- };
3588
3554
  }
3589
3555
  update() {
3590
- this.set(this.output.length ? this.output.join(", ") : "auto");
3556
+ this.set(this.values.length ? this.values.join(", ") : "auto");
3591
3557
  }
3592
3558
  }
3593
3559
 
@@ -3666,9 +3632,10 @@ function animateTarget(visualElement, targetAndTransition, { delay = 0, transiti
3666
3632
  }
3667
3633
  }
3668
3634
  }
3635
+ addValueToWillChange(visualElement, key);
3669
3636
  value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
3670
3637
  ? { type: false }
3671
- : valueTransition, visualElement, isHandoff, addValueToWillChange(visualElement, key)));
3638
+ : valueTransition, visualElement, isHandoff));
3672
3639
  const animation = value.animation;
3673
3640
  if (animation) {
3674
3641
  animations.push(animation);
@@ -4869,7 +4836,6 @@ class VisualElementDragControls {
4869
4836
  }
4870
4837
  };
4871
4838
  const onStart = (event, info) => {
4872
- var _a;
4873
4839
  // Attempt to grab the global drag gesture lock - maybe make this part of PanSession
4874
4840
  const { drag, dragPropagation, onDragStart } = this.getProps();
4875
4841
  if (drag && !dragPropagation) {
@@ -4911,8 +4877,7 @@ class VisualElementDragControls {
4911
4877
  if (onDragStart) {
4912
4878
  frame.postRender(() => onDragStart(event, info));
4913
4879
  }
4914
- (_a = this.removeWillChange) === null || _a === void 0 ? void 0 : _a.call(this);
4915
- this.removeWillChange = addValueToWillChange(this.visualElement, "transform");
4880
+ addValueToWillChange(this.visualElement, "transform");
4916
4881
  const { animationState } = this.visualElement;
4917
4882
  animationState && animationState.setActive("whileDrag", true);
4918
4883
  };
@@ -4968,8 +4933,6 @@ class VisualElementDragControls {
4968
4933
  });
4969
4934
  }
4970
4935
  stop(event, info) {
4971
- var _a;
4972
- (_a = this.removeWillChange) === null || _a === void 0 ? void 0 : _a.call(this);
4973
4936
  const isDragging = this.isDragging;
4974
4937
  this.cancel();
4975
4938
  if (!isDragging)
@@ -5111,7 +5074,8 @@ class VisualElementDragControls {
5111
5074
  }
5112
5075
  startAxisValueAnimation(axis, transition) {
5113
5076
  const axisValue = this.getAxisMotionValue(axis);
5114
- return axisValue.start(animateMotionValue(axis, axisValue, 0, transition, this.visualElement, false, addValueToWillChange(this.visualElement, axis)));
5077
+ addValueToWillChange(this.visualElement, axis);
5078
+ return axisValue.start(animateMotionValue(axis, axisValue, 0, transition, this.visualElement, false));
5115
5079
  }
5116
5080
  stopAnimation() {
5117
5081
  eachAxis((axis) => this.getAxisMotionValue(axis).stop());
@@ -5877,7 +5841,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5877
5841
  * and warn against mismatches.
5878
5842
  */
5879
5843
  if (process.env.NODE_ENV === "development") {
5880
- warnOnce(nextValue.version === "11.5.5", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.5.5 may not work as expected.`);
5844
+ warnOnce(nextValue.version === "11.6.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.6.0 may not work as expected.`);
5881
5845
  }
5882
5846
  }
5883
5847
  else if (isMotionValue(prevValue)) {
@@ -6038,16 +6002,16 @@ class VisualElement {
6038
6002
  this.propEventSubscriptions = {};
6039
6003
  this.notifyUpdate = () => this.notify("Update", this.latestValues);
6040
6004
  this.render = () => {
6041
- this.isRenderScheduled = false;
6042
6005
  if (!this.current)
6043
6006
  return;
6044
6007
  this.triggerBuild();
6045
6008
  this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
6046
6009
  };
6047
- this.isRenderScheduled = false;
6010
+ this.renderScheduledAt = 0.0;
6048
6011
  this.scheduleRender = () => {
6049
- if (!this.isRenderScheduled) {
6050
- this.isRenderScheduled = true;
6012
+ const now = time.now();
6013
+ if (this.renderScheduledAt < now) {
6014
+ this.renderScheduledAt = now;
6051
6015
  frame.render(this.render, false, true);
6052
6016
  }
6053
6017
  };
@@ -7214,9 +7178,9 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
7214
7178
  frameData.delta = clamp(0, 1000 / 60, now - frameData.timestamp);
7215
7179
  frameData.timestamp = now;
7216
7180
  frameData.isProcessing = true;
7217
- steps.update.process(frameData);
7218
- steps.preRender.process(frameData);
7219
- steps.render.process(frameData);
7181
+ frameSteps.update.process(frameData);
7182
+ frameSteps.preRender.process(frameData);
7183
+ frameSteps.render.process(frameData);
7220
7184
  frameData.isProcessing = false;
7221
7185
  }
7222
7186
  didUpdate() {
@@ -156,7 +156,7 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
156
156
  return { schedule, cancel, state, steps };
157
157
  }
158
158
 
159
- const { schedule: frame, cancel: cancelFrame, state: frameData, steps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
159
+ const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
160
160
 
161
161
  function addUniqueItem(arr, item) {
162
162
  if (arr.indexOf(item) === -1)
@@ -279,7 +279,7 @@ class MotionValue {
279
279
  * This will be replaced by the build step with the latest version number.
280
280
  * When MotionValues are provided to motion components, warn if versions are mixed.
281
281
  */
282
- this.version = "11.5.5";
282
+ this.version = "11.6.0";
283
283
  /**
284
284
  * Tracks whether this value can output a velocity. Currently this is only true
285
285
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -3342,14 +3342,7 @@ class AcceleratedAnimation extends BaseAnimation {
3342
3342
  }
3343
3343
  }
3344
3344
 
3345
- const animateMotionValue = (name, value, target, transition = {}, element, isHandoff,
3346
- /**
3347
- * Currently used to remove values from will-change when an animation ends.
3348
- * Preferably this would be handled by event listeners on the MotionValue
3349
- * but these aren't consistent enough yet when considering the different ways
3350
- * an animation can be cancelled.
3351
- */
3352
- onEnd) => (onComplete) => {
3345
+ const animateMotionValue = (name, value, target, transition = {}, element, isHandoff) => (onComplete) => {
3353
3346
  const valueTransition = getValueTransition$1(transition, name) || {};
3354
3347
  /**
3355
3348
  * Most transition values are currently completely overwritten by value-specific
@@ -3376,9 +3369,7 @@ onEnd) => (onComplete) => {
3376
3369
  onComplete: () => {
3377
3370
  onComplete();
3378
3371
  valueTransition.onComplete && valueTransition.onComplete();
3379
- onEnd && onEnd();
3380
3372
  },
3381
- onStop: onEnd,
3382
3373
  name,
3383
3374
  motionValue: value,
3384
3375
  element: isHandoff ? undefined : element,
@@ -3540,42 +3531,17 @@ function getWillChangeName(name) {
3540
3531
  class WillChangeMotionValue extends MotionValue {
3541
3532
  constructor() {
3542
3533
  super(...arguments);
3543
- this.output = [];
3544
- this.counts = new Map();
3534
+ this.values = [];
3545
3535
  }
3546
3536
  add(name) {
3547
3537
  const styleName = getWillChangeName(name);
3548
- if (!styleName)
3549
- return;
3550
- /**
3551
- * Update counter. Each value has an indepdent counter
3552
- * as multiple sources could be requesting the same value
3553
- * gets added to will-change.
3554
- */
3555
- const prevCount = this.counts.get(styleName) || 0;
3556
- this.counts.set(styleName, prevCount + 1);
3557
- if (prevCount === 0) {
3558
- this.output.push(styleName);
3538
+ if (styleName) {
3539
+ addUniqueItem(this.values, styleName);
3559
3540
  this.update();
3560
3541
  }
3561
- /**
3562
- * Prevents the remove function from being called multiple times.
3563
- */
3564
- let hasRemoved = false;
3565
- return () => {
3566
- if (hasRemoved)
3567
- return;
3568
- hasRemoved = true;
3569
- const newCount = this.counts.get(styleName) - 1;
3570
- this.counts.set(styleName, newCount);
3571
- if (newCount === 0) {
3572
- removeItem(this.output, styleName);
3573
- this.update();
3574
- }
3575
- };
3576
3542
  }
3577
3543
  update() {
3578
- this.set(this.output.length ? this.output.join(", ") : "auto");
3544
+ this.set(this.values.length ? this.values.join(", ") : "auto");
3579
3545
  }
3580
3546
  }
3581
3547
 
@@ -3654,9 +3620,10 @@ function animateTarget(visualElement, targetAndTransition, { delay = 0, transiti
3654
3620
  }
3655
3621
  }
3656
3622
  }
3623
+ addValueToWillChange(visualElement, key);
3657
3624
  value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
3658
3625
  ? { type: false }
3659
- : valueTransition, visualElement, isHandoff, addValueToWillChange(visualElement, key)));
3626
+ : valueTransition, visualElement, isHandoff));
3660
3627
  const animation = value.animation;
3661
3628
  if (animation) {
3662
3629
  animations.push(animation);
@@ -3790,7 +3757,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3790
3757
  * and warn against mismatches.
3791
3758
  */
3792
3759
  if (process.env.NODE_ENV === "development") {
3793
- warnOnce(nextValue.version === "11.5.5", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.5.5 may not work as expected.`);
3760
+ warnOnce(nextValue.version === "11.6.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.6.0 may not work as expected.`);
3794
3761
  }
3795
3762
  }
3796
3763
  else if (isMotionValue(prevValue)) {
@@ -3957,16 +3924,16 @@ class VisualElement {
3957
3924
  this.propEventSubscriptions = {};
3958
3925
  this.notifyUpdate = () => this.notify("Update", this.latestValues);
3959
3926
  this.render = () => {
3960
- this.isRenderScheduled = false;
3961
3927
  if (!this.current)
3962
3928
  return;
3963
3929
  this.triggerBuild();
3964
3930
  this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
3965
3931
  };
3966
- this.isRenderScheduled = false;
3932
+ this.renderScheduledAt = 0.0;
3967
3933
  this.scheduleRender = () => {
3968
- if (!this.isRenderScheduled) {
3969
- this.isRenderScheduled = true;
3934
+ const now = time.now();
3935
+ if (this.renderScheduledAt < now) {
3936
+ this.renderScheduledAt = now;
3970
3937
  frame.render(this.render, false, true);
3971
3938
  }
3972
3939
  };
@@ -5584,34 +5551,71 @@ function scrollInfo(onScroll, { container = document.documentElement, ...options
5584
5551
  };
5585
5552
  }
5586
5553
 
5587
- function scrollTimelineFallback({ source, axis = "y" }) {
5554
+ function scrollTimelineFallback({ source, container, axis = "y", }) {
5555
+ // Support legacy source argument. Deprecate later.
5556
+ if (source)
5557
+ container = source;
5588
5558
  // ScrollTimeline records progress as a percentage CSSUnitValue
5589
5559
  const currentTime = { value: 0 };
5590
5560
  const cancel = scrollInfo((info) => {
5591
5561
  currentTime.value = info[axis].progress * 100;
5592
- }, { container: source, axis });
5562
+ }, { container, axis });
5593
5563
  return { currentTime, cancel };
5594
5564
  }
5595
5565
  const timelineCache = new Map();
5596
- function getTimeline({ source = document.documentElement, axis = "y", } = {}) {
5597
- if (!timelineCache.has(source)) {
5598
- timelineCache.set(source, {});
5599
- }
5600
- const elementCache = timelineCache.get(source);
5566
+ function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
5567
+ // Support legacy source argument. Deprecate later.
5568
+ if (source)
5569
+ container = source;
5570
+ if (!timelineCache.has(container)) {
5571
+ timelineCache.set(container, {});
5572
+ }
5573
+ const elementCache = timelineCache.get(container);
5601
5574
  if (!elementCache[axis]) {
5602
5575
  elementCache[axis] = supportsScrollTimeline()
5603
- ? new ScrollTimeline({ source, axis })
5604
- : scrollTimelineFallback({ source, axis });
5576
+ ? new ScrollTimeline({ source: container, axis })
5577
+ : scrollTimelineFallback({ source: container, axis });
5605
5578
  }
5606
5579
  return elementCache[axis];
5607
5580
  }
5581
+ function isOnScrollWithInfo(onScroll) {
5582
+ return onScroll.length === 2;
5583
+ }
5584
+ function needsMainThreadScrollTracking(options) {
5585
+ return options && (options.target || options.offset);
5586
+ }
5608
5587
  function scroll(onScroll, options) {
5609
- const timeline = getTimeline(options);
5588
+ const axis = (options === null || options === void 0 ? void 0 : options.axis) || "y";
5610
5589
  if (typeof onScroll === "function") {
5611
- return observeTimeline(onScroll, timeline);
5590
+ /**
5591
+ * If the onScroll function has two arguments, it's expecting
5592
+ * more specific information about the scroll from scrollInfo.
5593
+ */
5594
+ if (isOnScrollWithInfo(onScroll) ||
5595
+ needsMainThreadScrollTracking(options)) {
5596
+ return scrollInfo((info) => {
5597
+ onScroll(info[axis].progress, info);
5598
+ }, options);
5599
+ }
5600
+ else {
5601
+ return observeTimeline(onScroll, getTimeline(options));
5602
+ }
5612
5603
  }
5613
5604
  else {
5614
- return onScroll.attachTimeline(timeline);
5605
+ /**
5606
+ * If we need main thread scroll tracking because we're tracking
5607
+ * a target or defined offsets, we need to create a scrollInfo timeline.
5608
+ * Over time the number of sitauations where this is true
5609
+ */
5610
+ if (needsMainThreadScrollTracking(options)) {
5611
+ onScroll.pause();
5612
+ return scrollInfo((info) => {
5613
+ onScroll.time = onScroll.duration * info[axis].progress;
5614
+ }, options);
5615
+ }
5616
+ else {
5617
+ return onScroll.attachTimeline(getTimeline(options));
5618
+ }
5615
5619
  }
5616
5620
  }
5617
5621
 
@@ -5655,6 +5659,18 @@ function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount =
5655
5659
  return () => observer.disconnect();
5656
5660
  }
5657
5661
 
5662
+ function steps(numSteps, direction = "end") {
5663
+ return (progress) => {
5664
+ progress =
5665
+ direction === "end"
5666
+ ? Math.min(progress, 0.999)
5667
+ : Math.max(progress, 0.001);
5668
+ const expanded = progress * numSteps;
5669
+ const rounded = direction === "end" ? Math.floor(expanded) : Math.ceil(expanded);
5670
+ return clamp(0, 1, rounded / numSteps);
5671
+ };
5672
+ }
5673
+
5658
5674
  function getOriginIndex(from, total) {
5659
5675
  if (from === "first") {
5660
5676
  return 0;
@@ -5758,6 +5774,7 @@ exports.easeInOut = easeInOut;
5758
5774
  exports.easeOut = easeOut;
5759
5775
  exports.frame = frame;
5760
5776
  exports.frameData = frameData;
5777
+ exports.frameSteps = frameSteps;
5761
5778
  exports.inView = inView;
5762
5779
  exports.interpolate = interpolate;
5763
5780
  exports.mirrorEasing = mirrorEasing;