framer-motion 7.6.6 → 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.
@@ -62,7 +62,6 @@ class NodeStack {
62
62
  node.snapshot = prevLead.snapshot;
63
63
  node.snapshot.latestValues =
64
64
  prevLead.animationValues || prevLead.latestValues;
65
- node.snapshot.isShared = true;
66
65
  }
67
66
  if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
68
67
  node.isLayoutDirty = true;
@@ -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
  }
@@ -133,17 +133,6 @@ class VisualElement {
133
133
  }
134
134
  }
135
135
  }
136
- /**
137
- * Update external values with initial values
138
- */
139
- if (props.values) {
140
- for (const key in props.values) {
141
- const value = props.values[key];
142
- if (latestValues[key] !== undefined && isMotionValue(value)) {
143
- value.set(latestValues[key]);
144
- }
145
- }
146
- }
147
136
  }
148
137
  /**
149
138
  * This method takes React props and returns found MotionValues. For example, HTML
@@ -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.6", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.6 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.6";
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.6";
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.6", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.6 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)) {
@@ -5843,17 +5846,6 @@
5843
5846
  }
5844
5847
  }
5845
5848
  }
5846
- /**
5847
- * Update external values with initial values
5848
- */
5849
- if (props.values) {
5850
- for (const key in props.values) {
5851
- const value = props.values[key];
5852
- if (latestValues[key] !== undefined && isMotionValue(value)) {
5853
- value.set(latestValues[key]);
5854
- }
5855
- }
5856
- }
5857
5849
  }
5858
5850
  /**
5859
5851
  * This method takes React props and returns found MotionValues. For example, HTML
@@ -6778,7 +6770,6 @@
6778
6770
  node.snapshot = prevLead.snapshot;
6779
6771
  node.snapshot.latestValues =
6780
6772
  prevLead.animationValues || prevLead.latestValues;
6781
- node.snapshot.isShared = true;
6782
6773
  }
6783
6774
  if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
6784
6775
  node.isLayoutDirty = true;
@@ -6824,8 +6815,8 @@
6824
6815
  }
6825
6816
  }
6826
6817
 
6827
- const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
6828
6818
  function buildProjectionTransform(delta, treeScale, latestTransform) {
6819
+ let transform = "";
6829
6820
  /**
6830
6821
  * The translations we use to calculate are always relative to the viewport coordinate space.
6831
6822
  * But when we apply scales, we also scale the coordinate space of an element and its children.
@@ -6834,12 +6825,16 @@
6834
6825
  */
6835
6826
  const xTranslate = delta.x.translate / treeScale.x;
6836
6827
  const yTranslate = delta.y.translate / treeScale.y;
6837
- let transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
6828
+ if (xTranslate || yTranslate) {
6829
+ transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
6830
+ }
6838
6831
  /**
6839
6832
  * Apply scale correction for the tree transform.
6840
6833
  * This will apply scale to the screen-orientated axes.
6841
6834
  */
6842
- 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
+ }
6843
6838
  if (latestTransform) {
6844
6839
  const { rotate, rotateX, rotateY } = latestTransform;
6845
6840
  if (rotate)
@@ -6855,8 +6850,10 @@
6855
6850
  */
6856
6851
  const elementScaleX = delta.x.scale * treeScale.x;
6857
6852
  const elementScaleY = delta.y.scale * treeScale.y;
6858
- transform += `scale(${elementScaleX}, ${elementScaleY})`;
6859
- return transform === identityProjection ? "none" : transform;
6853
+ if (elementScaleX !== 1 || elementScaleY !== 1) {
6854
+ transform += `scale(${elementScaleX}, ${elementScaleY})`;
6855
+ }
6856
+ return transform || "none";
6860
6857
  }
6861
6858
 
6862
6859
  const compareByDepth = (a, b) => a.depth - b.depth;
@@ -6887,9 +6884,18 @@
6887
6884
  * which has a noticeable difference in spring animations
6888
6885
  */
6889
6886
  const animationTarget = 1000;
6887
+ let id$1 = 0;
6890
6888
  function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
6891
6889
  return class ProjectionNode {
6892
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;
6893
6899
  /**
6894
6900
  * A Set containing all this component's children. This is used to iterate
6895
6901
  * through the children.
@@ -6998,8 +7004,8 @@
6998
7004
  hasListeners(name) {
6999
7005
  return this.eventHandlers.has(name);
7000
7006
  }
7001
- registerPotentialNode(id, node) {
7002
- this.potentialNodes.set(id, node);
7007
+ registerPotentialNode(elementId, node) {
7008
+ this.potentialNodes.set(elementId, node);
7003
7009
  }
7004
7010
  /**
7005
7011
  * Lifecycles
@@ -7132,6 +7138,7 @@
7132
7138
  return;
7133
7139
  this.isUpdating = true;
7134
7140
  (_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
7141
+ this.animationId++;
7135
7142
  }
7136
7143
  willUpdate(shouldNotifyListeners = true) {
7137
7144
  var _a, _b, _c;
@@ -7146,11 +7153,7 @@
7146
7153
  for (let i = 0; i < this.path.length; i++) {
7147
7154
  const node = this.path[i];
7148
7155
  node.shouldResetTransform = true;
7149
- /**
7150
- * TODO: Check we haven't updated the scroll
7151
- * since the last didUpdate
7152
- */
7153
- node.updateScroll();
7156
+ node.updateScroll("snapshot");
7154
7157
  }
7155
7158
  const { layoutId, layout } = this.options;
7156
7159
  if (layoutId === undefined && !layout)
@@ -7266,10 +7269,20 @@
7266
7269
  this.notifyListeners("measure", this.layout.layoutBox);
7267
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);
7268
7271
  }
7269
- updateScroll() {
7270
- if (this.options.layoutScroll && this.instance) {
7271
- this.isScrollRoot = checkIsScrollRoot(this.instance);
7272
- 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
+ };
7273
7286
  }
7274
7287
  }
7275
7288
  resetTransform() {
@@ -7291,6 +7304,7 @@
7291
7304
  }
7292
7305
  }
7293
7306
  measure(removeTransform = true) {
7307
+ var _a;
7294
7308
  const pageBox = this.measurePageBox();
7295
7309
  let layoutBox = this.removeElementScroll(pageBox);
7296
7310
  /**
@@ -7302,10 +7316,17 @@
7302
7316
  layoutBox = this.removeTransform(layoutBox);
7303
7317
  }
7304
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";
7305
7323
  return {
7324
+ animationId: this.root.animationId,
7306
7325
  measuredBox: pageBox,
7307
7326
  layoutBox,
7308
7327
  latestValues: {},
7328
+ source: this.id,
7329
+ position,
7309
7330
  };
7310
7331
  }
7311
7332
  measurePageBox() {
@@ -7316,8 +7337,8 @@
7316
7337
  // Remove viewport scroll to give page-relative coordinates
7317
7338
  const { scroll } = this.root;
7318
7339
  if (scroll) {
7319
- translateAxis(box.x, scroll.x);
7320
- translateAxis(box.y, scroll.y);
7340
+ translateAxis(box.x, scroll.offset.x);
7341
+ translateAxis(box.y, scroll.offset.y);
7321
7342
  }
7322
7343
  return box;
7323
7344
  }
@@ -7330,13 +7351,13 @@
7330
7351
  */
7331
7352
  for (let i = 0; i < this.path.length; i++) {
7332
7353
  const node = this.path[i];
7333
- const { scroll, options, isScrollRoot } = node;
7354
+ const { scroll, options } = node;
7334
7355
  if (node !== this.root && scroll && options.layoutScroll) {
7335
7356
  /**
7336
7357
  * If this is a new scroll root, we want to remove all previous scrolls
7337
7358
  * from the viewport box.
7338
7359
  */
7339
- if (isScrollRoot) {
7360
+ if (scroll.isRoot) {
7340
7361
  copyBoxInto(boxWithoutScroll, box);
7341
7362
  const { scroll: rootScroll } = this.root;
7342
7363
  /**
@@ -7344,12 +7365,12 @@
7344
7365
  * to the measured bounding box.
7345
7366
  */
7346
7367
  if (rootScroll) {
7347
- translateAxis(boxWithoutScroll.x, -rootScroll.x);
7348
- translateAxis(boxWithoutScroll.y, -rootScroll.y);
7368
+ translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
7369
+ translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
7349
7370
  }
7350
7371
  }
7351
- translateAxis(boxWithoutScroll.x, scroll.x);
7352
- translateAxis(boxWithoutScroll.y, scroll.y);
7372
+ translateAxis(boxWithoutScroll.x, scroll.offset.x);
7373
+ translateAxis(boxWithoutScroll.y, scroll.offset.y);
7353
7374
  }
7354
7375
  }
7355
7376
  return boxWithoutScroll;
@@ -7364,8 +7385,8 @@
7364
7385
  node.scroll &&
7365
7386
  node !== node.root) {
7366
7387
  transformBox(withTransforms, {
7367
- x: -node.scroll.x,
7368
- y: -node.scroll.y,
7388
+ x: -node.scroll.offset.x,
7389
+ y: -node.scroll.offset.y,
7369
7390
  });
7370
7391
  }
7371
7392
  if (!hasTransform(node.latestValues))
@@ -7599,7 +7620,7 @@
7599
7620
  }
7600
7621
  }
7601
7622
  setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
7602
- var _a;
7623
+ var _a, _b;
7603
7624
  const snapshot = this.snapshot;
7604
7625
  const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
7605
7626
  const mixedValues = { ...this.latestValues };
@@ -7607,8 +7628,8 @@
7607
7628
  this.relativeTarget = this.relativeTargetOrigin = undefined;
7608
7629
  this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
7609
7630
  const relativeLayout = createBox();
7610
- const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.isShared;
7611
- 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;
7612
7633
  const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
7613
7634
  !isOnlyMember &&
7614
7635
  this.options.crossfade === true &&
@@ -7789,25 +7810,30 @@
7789
7810
  return;
7790
7811
  // If there's no detected rotation values, we can early return without a forced render.
7791
7812
  let hasRotate = false;
7792
- // Keep a record of all the values we've reset
7793
- const resetValues = {};
7794
- // Check the rotate value of all axes and reset to 0
7795
- for (let i = 0; i < transformAxes.length; i++) {
7796
- const axis = transformAxes[i];
7797
- const key = "rotate" + axis;
7798
- // If this rotation doesn't exist as a motion value, then we don't
7799
- // need to reset it
7800
- if (!visualElement.getStaticValue(key)) {
7801
- continue;
7802
- }
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) {
7803
7822
  hasRotate = true;
7804
- // Record the rotation and then temporarily set it to 0
7805
- resetValues[key] = visualElement.getStaticValue(key);
7806
- visualElement.setStaticValue(key, 0);
7807
7823
  }
7808
7824
  // If there's no rotation values, we don't need to do any more.
7809
7825
  if (!hasRotate)
7810
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
+ }
7811
7837
  // Force a render of this element to apply the transform with all rotations
7812
7838
  // set to 0.
7813
7839
  visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
@@ -7949,11 +7975,12 @@
7949
7975
  node.hasListeners("didUpdate")) {
7950
7976
  const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
7951
7977
  const { animationType } = node.options;
7978
+ const isShared = snapshot.source !== node.layout.source;
7952
7979
  // TODO Maybe we want to also resize the layout snapshot so we don't trigger
7953
7980
  // animations for instance if layout="size" and an element has only changed position
7954
7981
  if (animationType === "size") {
7955
7982
  eachAxis((axis) => {
7956
- const axisSnapshot = snapshot.isShared
7983
+ const axisSnapshot = isShared
7957
7984
  ? snapshot.measuredBox[axis]
7958
7985
  : snapshot.layoutBox[axis];
7959
7986
  const length = calcLength(axisSnapshot);
@@ -7963,7 +7990,7 @@
7963
7990
  }
7964
7991
  else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
7965
7992
  eachAxis((axis) => {
7966
- const axisSnapshot = snapshot.isShared
7993
+ const axisSnapshot = isShared
7967
7994
  ? snapshot.measuredBox[axis]
7968
7995
  : snapshot.layoutBox[axis];
7969
7996
  const length = calcLength(layout[axis]);
@@ -7973,7 +8000,7 @@
7973
8000
  const layoutDelta = createDelta();
7974
8001
  calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
7975
8002
  const visualDelta = createDelta();
7976
- if (snapshot.isShared) {
8003
+ if (isShared) {
7977
8004
  calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
7978
8005
  }
7979
8006
  else {
@@ -8069,7 +8096,7 @@
8069
8096
  duration: 0.45,
8070
8097
  ease: [0.4, 0, 0.1, 1],
8071
8098
  };
8072
- function mountNodeEarly(node, id) {
8099
+ function mountNodeEarly(node, elementId) {
8073
8100
  /**
8074
8101
  * Rather than searching the DOM from document we can search the
8075
8102
  * path for the deepest mounted ancestor and search from there
@@ -8082,7 +8109,7 @@
8082
8109
  }
8083
8110
  }
8084
8111
  const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
8085
- const element = searchElement.querySelector(`[data-projection-id="${id}"]`);
8112
+ const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
8086
8113
  if (element)
8087
8114
  node.mount(element, true);
8088
8115
  }