framer-motion 7.6.7 → 7.6.8

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.
@@ -1,5 +1,5 @@
1
- const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
2
1
  function buildProjectionTransform(delta, treeScale, latestTransform) {
2
+ let transform = "";
3
3
  /**
4
4
  * The translations we use to calculate are always relative to the viewport coordinate space.
5
5
  * But when we apply scales, we also scale the coordinate space of an element and its children.
@@ -8,12 +8,16 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
8
8
  */
9
9
  const xTranslate = delta.x.translate / treeScale.x;
10
10
  const yTranslate = delta.y.translate / treeScale.y;
11
- let transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
11
+ if (xTranslate || yTranslate) {
12
+ transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
13
+ }
12
14
  /**
13
15
  * Apply scale correction for the tree transform.
14
16
  * This will apply scale to the screen-orientated axes.
15
17
  */
16
- transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
18
+ if (treeScale.x !== 1 || treeScale.y !== 1) {
19
+ transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
20
+ }
17
21
  if (latestTransform) {
18
22
  const { rotate, rotateX, rotateY } = latestTransform;
19
23
  if (rotate)
@@ -29,8 +33,10 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
29
33
  */
30
34
  const elementScaleX = delta.x.scale * treeScale.x;
31
35
  const elementScaleY = delta.y.scale * treeScale.y;
32
- transform += `scale(${elementScaleX}, ${elementScaleY})`;
33
- return transform === identityProjection ? "none" : transform;
36
+ if (elementScaleX !== 1 || elementScaleY !== 1) {
37
+ transform += `scale(${elementScaleX}, ${elementScaleY})`;
38
+ }
39
+ return transform || "none";
34
40
  }
35
41
 
36
- export { buildProjectionTransform, identityProjection };
42
+ export { buildProjectionTransform };
@@ -8,8 +8,8 @@ function measurePageBox(element, rootProjectionNode, transformPagePoint) {
8
8
  const viewportBox = measureViewportBox(element, transformPagePoint);
9
9
  const { scroll } = rootProjectionNode;
10
10
  if (scroll) {
11
- translateAxis(viewportBox.x, scroll.x);
12
- translateAxis(viewportBox.y, scroll.y);
11
+ translateAxis(viewportBox.x, scroll.offset.x);
12
+ translateAxis(viewportBox.y, scroll.offset.y);
13
13
  }
14
14
  return viewportBox;
15
15
  }
@@ -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 === "7.6.7", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.7 may not work as expected.`);
25
+ warnOnce(nextValue.version === "7.6.8", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.8 may not work as expected.`);
26
26
  }
27
27
  }
28
28
  else if (isMotionValue(prevValue)) {
@@ -24,7 +24,7 @@ class MotionValue {
24
24
  * This will be replaced by the build step with the latest version number.
25
25
  * When MotionValues are provided to motion components, warn if versions are mixed.
26
26
  */
27
- this.version = "7.6.7";
27
+ this.version = "7.6.8";
28
28
  /**
29
29
  * Duration, in milliseconds, since last updating frame.
30
30
  *
@@ -248,11 +248,11 @@
248
248
  hasEverUpdated: false,
249
249
  };
250
250
 
251
- let id$1 = 1;
251
+ let id$2 = 1;
252
252
  function useProjectionId() {
253
253
  return useConstant(() => {
254
254
  if (globalProjectionState.hasEverUpdated) {
255
- return id$1++;
255
+ return id$2++;
256
256
  }
257
257
  });
258
258
  }
@@ -3426,7 +3426,7 @@
3426
3426
  * This will be replaced by the build step with the latest version number.
3427
3427
  * When MotionValues are provided to motion components, warn if versions are mixed.
3428
3428
  */
3429
- this.version = "7.6.7";
3429
+ this.version = "7.6.8";
3430
3430
  /**
3431
3431
  * Duration, in milliseconds, since last updating frame.
3432
3432
  *
@@ -4783,7 +4783,10 @@
4783
4783
  node.options.layoutScroll &&
4784
4784
  node.scroll &&
4785
4785
  node !== node.root) {
4786
- transformBox(box, { x: -node.scroll.x, y: -node.scroll.y });
4786
+ transformBox(box, {
4787
+ x: -node.scroll.offset.x,
4788
+ y: -node.scroll.offset.y,
4789
+ });
4787
4790
  }
4788
4791
  if (delta) {
4789
4792
  // Incoporate each ancestor's scale into a culmulative treeScale for this component
@@ -4832,8 +4835,8 @@
4832
4835
  const viewportBox = measureViewportBox(element, transformPagePoint);
4833
4836
  const { scroll } = rootProjectionNode;
4834
4837
  if (scroll) {
4835
- translateAxis(viewportBox.x, scroll.x);
4836
- translateAxis(viewportBox.y, scroll.y);
4838
+ translateAxis(viewportBox.x, scroll.offset.x);
4839
+ translateAxis(viewportBox.y, scroll.offset.y);
4837
4840
  }
4838
4841
  return viewportBox;
4839
4842
  }
@@ -5689,7 +5692,7 @@
5689
5692
  * and warn against mismatches.
5690
5693
  */
5691
5694
  {
5692
- warnOnce(nextValue.version === "7.6.7", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.7 may not work as expected.`);
5695
+ warnOnce(nextValue.version === "7.6.8", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.8 may not work as expected.`);
5693
5696
  }
5694
5697
  }
5695
5698
  else if (isMotionValue(prevValue)) {
@@ -6767,7 +6770,6 @@
6767
6770
  node.snapshot = prevLead.snapshot;
6768
6771
  node.snapshot.latestValues =
6769
6772
  prevLead.animationValues || prevLead.latestValues;
6770
- node.snapshot.isShared = true;
6771
6773
  }
6772
6774
  if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
6773
6775
  node.isLayoutDirty = true;
@@ -6813,8 +6815,8 @@
6813
6815
  }
6814
6816
  }
6815
6817
 
6816
- const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
6817
6818
  function buildProjectionTransform(delta, treeScale, latestTransform) {
6819
+ let transform = "";
6818
6820
  /**
6819
6821
  * The translations we use to calculate are always relative to the viewport coordinate space.
6820
6822
  * But when we apply scales, we also scale the coordinate space of an element and its children.
@@ -6823,12 +6825,16 @@
6823
6825
  */
6824
6826
  const xTranslate = delta.x.translate / treeScale.x;
6825
6827
  const yTranslate = delta.y.translate / treeScale.y;
6826
- let transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
6828
+ if (xTranslate || yTranslate) {
6829
+ transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
6830
+ }
6827
6831
  /**
6828
6832
  * Apply scale correction for the tree transform.
6829
6833
  * This will apply scale to the screen-orientated axes.
6830
6834
  */
6831
- transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
6835
+ if (treeScale.x !== 1 || treeScale.y !== 1) {
6836
+ transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
6837
+ }
6832
6838
  if (latestTransform) {
6833
6839
  const { rotate, rotateX, rotateY } = latestTransform;
6834
6840
  if (rotate)
@@ -6844,8 +6850,10 @@
6844
6850
  */
6845
6851
  const elementScaleX = delta.x.scale * treeScale.x;
6846
6852
  const elementScaleY = delta.y.scale * treeScale.y;
6847
- transform += `scale(${elementScaleX}, ${elementScaleY})`;
6848
- return transform === identityProjection ? "none" : transform;
6853
+ if (elementScaleX !== 1 || elementScaleY !== 1) {
6854
+ transform += `scale(${elementScaleX}, ${elementScaleY})`;
6855
+ }
6856
+ return transform || "none";
6849
6857
  }
6850
6858
 
6851
6859
  const compareByDepth = (a, b) => a.depth - b.depth;
@@ -6876,9 +6884,18 @@
6876
6884
  * which has a noticeable difference in spring animations
6877
6885
  */
6878
6886
  const animationTarget = 1000;
6887
+ let id$1 = 0;
6879
6888
  function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
6880
6889
  return class ProjectionNode {
6881
6890
  constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
6891
+ /**
6892
+ * A unique ID generated for every projection node.
6893
+ */
6894
+ this.id = id$1++;
6895
+ /**
6896
+ * An id that represents a unique session instigated by startUpdate.
6897
+ */
6898
+ this.animationId = 0;
6882
6899
  /**
6883
6900
  * A Set containing all this component's children. This is used to iterate
6884
6901
  * through the children.
@@ -6987,8 +7004,8 @@
6987
7004
  hasListeners(name) {
6988
7005
  return this.eventHandlers.has(name);
6989
7006
  }
6990
- registerPotentialNode(id, node) {
6991
- this.potentialNodes.set(id, node);
7007
+ registerPotentialNode(elementId, node) {
7008
+ this.potentialNodes.set(elementId, node);
6992
7009
  }
6993
7010
  /**
6994
7011
  * Lifecycles
@@ -7121,6 +7138,7 @@
7121
7138
  return;
7122
7139
  this.isUpdating = true;
7123
7140
  (_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
7141
+ this.animationId++;
7124
7142
  }
7125
7143
  willUpdate(shouldNotifyListeners = true) {
7126
7144
  var _a, _b, _c;
@@ -7135,11 +7153,7 @@
7135
7153
  for (let i = 0; i < this.path.length; i++) {
7136
7154
  const node = this.path[i];
7137
7155
  node.shouldResetTransform = true;
7138
- /**
7139
- * TODO: Check we haven't updated the scroll
7140
- * since the last didUpdate
7141
- */
7142
- node.updateScroll();
7156
+ node.updateScroll("snapshot");
7143
7157
  }
7144
7158
  const { layoutId, layout } = this.options;
7145
7159
  if (layoutId === undefined && !layout)
@@ -7255,10 +7269,20 @@
7255
7269
  this.notifyListeners("measure", this.layout.layoutBox);
7256
7270
  (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notify("LayoutMeasure", this.layout.layoutBox, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.layoutBox);
7257
7271
  }
7258
- updateScroll() {
7259
- if (this.options.layoutScroll && this.instance) {
7260
- this.isScrollRoot = checkIsScrollRoot(this.instance);
7261
- this.scroll = measureScroll(this.instance);
7272
+ updateScroll(phase = "measure") {
7273
+ let needsMeasurement = Boolean(this.options.layoutScroll && this.instance);
7274
+ if (this.scroll &&
7275
+ this.scroll.animationId === this.root.animationId &&
7276
+ this.scroll.phase === phase) {
7277
+ needsMeasurement = false;
7278
+ }
7279
+ if (needsMeasurement) {
7280
+ this.scroll = {
7281
+ animationId: this.root.animationId,
7282
+ phase,
7283
+ isRoot: checkIsScrollRoot(this.instance),
7284
+ offset: measureScroll(this.instance),
7285
+ };
7262
7286
  }
7263
7287
  }
7264
7288
  resetTransform() {
@@ -7280,6 +7304,7 @@
7280
7304
  }
7281
7305
  }
7282
7306
  measure(removeTransform = true) {
7307
+ var _a;
7283
7308
  const pageBox = this.measurePageBox();
7284
7309
  let layoutBox = this.removeElementScroll(pageBox);
7285
7310
  /**
@@ -7291,10 +7316,17 @@
7291
7316
  layoutBox = this.removeTransform(layoutBox);
7292
7317
  }
7293
7318
  roundBox(layoutBox);
7319
+ const positionStyle = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.readValue("position");
7320
+ const position = positionStyle === "fixed" || positionStyle === "sticky"
7321
+ ? positionStyle
7322
+ : "static";
7294
7323
  return {
7324
+ animationId: this.root.animationId,
7295
7325
  measuredBox: pageBox,
7296
7326
  layoutBox,
7297
7327
  latestValues: {},
7328
+ source: this.id,
7329
+ position,
7298
7330
  };
7299
7331
  }
7300
7332
  measurePageBox() {
@@ -7305,8 +7337,8 @@
7305
7337
  // Remove viewport scroll to give page-relative coordinates
7306
7338
  const { scroll } = this.root;
7307
7339
  if (scroll) {
7308
- translateAxis(box.x, scroll.x);
7309
- translateAxis(box.y, scroll.y);
7340
+ translateAxis(box.x, scroll.offset.x);
7341
+ translateAxis(box.y, scroll.offset.y);
7310
7342
  }
7311
7343
  return box;
7312
7344
  }
@@ -7319,13 +7351,13 @@
7319
7351
  */
7320
7352
  for (let i = 0; i < this.path.length; i++) {
7321
7353
  const node = this.path[i];
7322
- const { scroll, options, isScrollRoot } = node;
7354
+ const { scroll, options } = node;
7323
7355
  if (node !== this.root && scroll && options.layoutScroll) {
7324
7356
  /**
7325
7357
  * If this is a new scroll root, we want to remove all previous scrolls
7326
7358
  * from the viewport box.
7327
7359
  */
7328
- if (isScrollRoot) {
7360
+ if (scroll.isRoot) {
7329
7361
  copyBoxInto(boxWithoutScroll, box);
7330
7362
  const { scroll: rootScroll } = this.root;
7331
7363
  /**
@@ -7333,12 +7365,12 @@
7333
7365
  * to the measured bounding box.
7334
7366
  */
7335
7367
  if (rootScroll) {
7336
- translateAxis(boxWithoutScroll.x, -rootScroll.x);
7337
- translateAxis(boxWithoutScroll.y, -rootScroll.y);
7368
+ translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
7369
+ translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
7338
7370
  }
7339
7371
  }
7340
- translateAxis(boxWithoutScroll.x, scroll.x);
7341
- translateAxis(boxWithoutScroll.y, scroll.y);
7372
+ translateAxis(boxWithoutScroll.x, scroll.offset.x);
7373
+ translateAxis(boxWithoutScroll.y, scroll.offset.y);
7342
7374
  }
7343
7375
  }
7344
7376
  return boxWithoutScroll;
@@ -7353,8 +7385,8 @@
7353
7385
  node.scroll &&
7354
7386
  node !== node.root) {
7355
7387
  transformBox(withTransforms, {
7356
- x: -node.scroll.x,
7357
- y: -node.scroll.y,
7388
+ x: -node.scroll.offset.x,
7389
+ y: -node.scroll.offset.y,
7358
7390
  });
7359
7391
  }
7360
7392
  if (!hasTransform(node.latestValues))
@@ -7588,7 +7620,7 @@
7588
7620
  }
7589
7621
  }
7590
7622
  setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
7591
- var _a;
7623
+ var _a, _b;
7592
7624
  const snapshot = this.snapshot;
7593
7625
  const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
7594
7626
  const mixedValues = { ...this.latestValues };
@@ -7596,8 +7628,8 @@
7596
7628
  this.relativeTarget = this.relativeTargetOrigin = undefined;
7597
7629
  this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
7598
7630
  const relativeLayout = createBox();
7599
- const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.isShared;
7600
- const isOnlyMember = (((_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.members.length) || 0) <= 1;
7631
+ const isSharedLayoutAnimation = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.source) !== ((_a = this.layout) === null || _a === void 0 ? void 0 : _a.source);
7632
+ const isOnlyMember = (((_b = this.getStack()) === null || _b === void 0 ? void 0 : _b.members.length) || 0) <= 1;
7601
7633
  const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
7602
7634
  !isOnlyMember &&
7603
7635
  this.options.crossfade === true &&
@@ -7778,25 +7810,30 @@
7778
7810
  return;
7779
7811
  // If there's no detected rotation values, we can early return without a forced render.
7780
7812
  let hasRotate = false;
7781
- // Keep a record of all the values we've reset
7782
- const resetValues = {};
7783
- // Check the rotate value of all axes and reset to 0
7784
- for (let i = 0; i < transformAxes.length; i++) {
7785
- const axis = transformAxes[i];
7786
- const key = "rotate" + axis;
7787
- // If this rotation doesn't exist as a motion value, then we don't
7788
- // need to reset it
7789
- if (!visualElement.getStaticValue(key)) {
7790
- continue;
7791
- }
7813
+ /**
7814
+ * An unrolled check for rotation values. Most elements don't have any rotation and
7815
+ * skipping the nested loop and new object creation is 50% faster.
7816
+ */
7817
+ const { latestValues } = visualElement;
7818
+ if (latestValues.rotate ||
7819
+ latestValues.rotateX ||
7820
+ latestValues.rotateY ||
7821
+ latestValues.rotateZ) {
7792
7822
  hasRotate = true;
7793
- // Record the rotation and then temporarily set it to 0
7794
- resetValues[key] = visualElement.getStaticValue(key);
7795
- visualElement.setStaticValue(key, 0);
7796
7823
  }
7797
7824
  // If there's no rotation values, we don't need to do any more.
7798
7825
  if (!hasRotate)
7799
7826
  return;
7827
+ const resetValues = {};
7828
+ // Check the rotate value of all axes and reset to 0
7829
+ for (let i = 0; i < transformAxes.length; i++) {
7830
+ const key = "rotate" + transformAxes[i];
7831
+ // Record the rotation and then temporarily set it to 0
7832
+ if (latestValues[key]) {
7833
+ resetValues[key] = latestValues[key];
7834
+ visualElement.setStaticValue(key, 0);
7835
+ }
7836
+ }
7800
7837
  // Force a render of this element to apply the transform with all rotations
7801
7838
  // set to 0.
7802
7839
  visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
@@ -7938,11 +7975,12 @@
7938
7975
  node.hasListeners("didUpdate")) {
7939
7976
  const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
7940
7977
  const { animationType } = node.options;
7978
+ const isShared = snapshot.source !== node.layout.source;
7941
7979
  // TODO Maybe we want to also resize the layout snapshot so we don't trigger
7942
7980
  // animations for instance if layout="size" and an element has only changed position
7943
7981
  if (animationType === "size") {
7944
7982
  eachAxis((axis) => {
7945
- const axisSnapshot = snapshot.isShared
7983
+ const axisSnapshot = isShared
7946
7984
  ? snapshot.measuredBox[axis]
7947
7985
  : snapshot.layoutBox[axis];
7948
7986
  const length = calcLength(axisSnapshot);
@@ -7952,7 +7990,7 @@
7952
7990
  }
7953
7991
  else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
7954
7992
  eachAxis((axis) => {
7955
- const axisSnapshot = snapshot.isShared
7993
+ const axisSnapshot = isShared
7956
7994
  ? snapshot.measuredBox[axis]
7957
7995
  : snapshot.layoutBox[axis];
7958
7996
  const length = calcLength(layout[axis]);
@@ -7962,7 +8000,7 @@
7962
8000
  const layoutDelta = createDelta();
7963
8001
  calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
7964
8002
  const visualDelta = createDelta();
7965
- if (snapshot.isShared) {
8003
+ if (isShared) {
7966
8004
  calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
7967
8005
  }
7968
8006
  else {
@@ -8058,7 +8096,7 @@
8058
8096
  duration: 0.45,
8059
8097
  ease: [0.4, 0, 0.1, 1],
8060
8098
  };
8061
- function mountNodeEarly(node, id) {
8099
+ function mountNodeEarly(node, elementId) {
8062
8100
  /**
8063
8101
  * Rather than searching the DOM from document we can search the
8064
8102
  * path for the deepest mounted ancestor and search from there
@@ -8071,7 +8109,7 @@
8071
8109
  }
8072
8110
  }
8073
8111
  const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
8074
- const element = searchElement.querySelector(`[data-projection-id="${id}"]`);
8112
+ const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
8075
8113
  if (element)
8076
8114
  node.mount(element, true);
8077
8115
  }