framer-motion 12.23.24 → 12.23.26

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.
@@ -6228,7 +6228,91 @@
6228
6228
  }
6229
6229
  }
6230
6230
 
6231
- const scaleCorrectors = {};
6231
+ function pixelsToPercent(pixels, axis) {
6232
+ if (axis.max === axis.min)
6233
+ return 0;
6234
+ return (pixels / (axis.max - axis.min)) * 100;
6235
+ }
6236
+ /**
6237
+ * We always correct borderRadius as a percentage rather than pixels to reduce paints.
6238
+ * For example, if you are projecting a box that is 100px wide with a 10px borderRadius
6239
+ * into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
6240
+ * borderRadius in both states. If we animate between the two in pixels that will trigger
6241
+ * a paint each time. If we animate between the two in percentage we'll avoid a paint.
6242
+ */
6243
+ const correctBorderRadius = {
6244
+ correct: (latest, node) => {
6245
+ if (!node.target)
6246
+ return latest;
6247
+ /**
6248
+ * If latest is a string, if it's a percentage we can return immediately as it's
6249
+ * going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
6250
+ */
6251
+ if (typeof latest === "string") {
6252
+ if (px.test(latest)) {
6253
+ latest = parseFloat(latest);
6254
+ }
6255
+ else {
6256
+ return latest;
6257
+ }
6258
+ }
6259
+ /**
6260
+ * If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
6261
+ * pixel value as a percentage of each axis
6262
+ */
6263
+ const x = pixelsToPercent(latest, node.target.x);
6264
+ const y = pixelsToPercent(latest, node.target.y);
6265
+ return `${x}% ${y}%`;
6266
+ },
6267
+ };
6268
+
6269
+ const correctBoxShadow = {
6270
+ correct: (latest, { treeScale, projectionDelta }) => {
6271
+ const original = latest;
6272
+ const shadow = complex.parse(latest);
6273
+ // TODO: Doesn't support multiple shadows
6274
+ if (shadow.length > 5)
6275
+ return original;
6276
+ const template = complex.createTransformer(latest);
6277
+ const offset = typeof shadow[0] !== "number" ? 1 : 0;
6278
+ // Calculate the overall context scale
6279
+ const xScale = projectionDelta.x.scale * treeScale.x;
6280
+ const yScale = projectionDelta.y.scale * treeScale.y;
6281
+ shadow[0 + offset] /= xScale;
6282
+ shadow[1 + offset] /= yScale;
6283
+ /**
6284
+ * Ideally we'd correct x and y scales individually, but because blur and
6285
+ * spread apply to both we have to take a scale average and apply that instead.
6286
+ * We could potentially improve the outcome of this by incorporating the ratio between
6287
+ * the two scales.
6288
+ */
6289
+ const averageScale = mixNumber$1(xScale, yScale, 0.5);
6290
+ // Blur
6291
+ if (typeof shadow[2 + offset] === "number")
6292
+ shadow[2 + offset] /= averageScale;
6293
+ // Spread
6294
+ if (typeof shadow[3 + offset] === "number")
6295
+ shadow[3 + offset] /= averageScale;
6296
+ return template(shadow);
6297
+ },
6298
+ };
6299
+
6300
+ const scaleCorrectors = {
6301
+ borderRadius: {
6302
+ ...correctBorderRadius,
6303
+ applyTo: [
6304
+ "borderTopLeftRadius",
6305
+ "borderTopRightRadius",
6306
+ "borderBottomLeftRadius",
6307
+ "borderBottomRightRadius",
6308
+ ],
6309
+ },
6310
+ borderTopLeftRadius: correctBorderRadius,
6311
+ borderTopRightRadius: correctBorderRadius,
6312
+ borderBottomLeftRadius: correctBorderRadius,
6313
+ borderBottomRightRadius: correctBorderRadius,
6314
+ boxShadow: correctBoxShadow,
6315
+ };
6232
6316
  function addScaleCorrector(correctors) {
6233
6317
  for (const key in correctors) {
6234
6318
  scaleCorrectors[key] = correctors[key];
@@ -6445,6 +6529,7 @@
6445
6529
  */
6446
6530
  this.eventHandlers = new Map();
6447
6531
  this.hasTreeAnimated = false;
6532
+ this.layoutVersion = 0;
6448
6533
  // Note: Currently only running on root node
6449
6534
  this.updateScheduled = false;
6450
6535
  this.scheduleUpdate = () => this.update();
@@ -6484,6 +6569,7 @@
6484
6569
  * Frame calculations
6485
6570
  */
6486
6571
  this.resolvedRelativeTargetAt = 0.0;
6572
+ this.linkedParentVersion = 0;
6487
6573
  this.hasProjected = false;
6488
6574
  this.isVisible = true;
6489
6575
  this.animationProgress = 0;
@@ -6837,6 +6923,7 @@
6837
6923
  }
6838
6924
  const prevLayout = this.layout;
6839
6925
  this.layout = this.measure(false);
6926
+ this.layoutVersion++;
6840
6927
  this.layoutCorrected = createBox();
6841
6928
  this.isLayoutDirty = false;
6842
6929
  this.projectionDelta = undefined;
@@ -7056,25 +7143,23 @@
7056
7143
  if (!this.layout || !(layout || layoutId))
7057
7144
  return;
7058
7145
  this.resolvedRelativeTargetAt = frameData.timestamp;
7146
+ const relativeParent = this.getClosestProjectingParent();
7147
+ if (relativeParent &&
7148
+ this.linkedParentVersion !== relativeParent.layoutVersion &&
7149
+ !relativeParent.options.layoutRoot) {
7150
+ this.removeRelativeTarget();
7151
+ }
7059
7152
  /**
7060
7153
  * If we don't have a targetDelta but do have a layout, we can attempt to resolve
7061
7154
  * a relativeParent. This will allow a component to perform scale correction
7062
7155
  * even if no animation has started.
7063
7156
  */
7064
7157
  if (!this.targetDelta && !this.relativeTarget) {
7065
- const relativeParent = this.getClosestProjectingParent();
7066
- if (relativeParent &&
7067
- relativeParent.layout &&
7068
- this.animationProgress !== 1) {
7069
- this.relativeParent = relativeParent;
7070
- this.forceRelativeParentToResolveTarget();
7071
- this.relativeTarget = createBox();
7072
- this.relativeTargetOrigin = createBox();
7073
- calcRelativePosition(this.relativeTargetOrigin, this.layout.layoutBox, relativeParent.layout.layoutBox);
7074
- copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
7158
+ if (relativeParent && relativeParent.layout) {
7159
+ this.createRelativeTarget(relativeParent, this.layout.layoutBox, relativeParent.layout.layoutBox);
7075
7160
  }
7076
7161
  else {
7077
- this.relativeParent = this.relativeTarget = undefined;
7162
+ this.removeRelativeTarget();
7078
7163
  }
7079
7164
  }
7080
7165
  /**
@@ -7124,19 +7209,13 @@
7124
7209
  */
7125
7210
  if (this.attemptToResolveRelativeTarget) {
7126
7211
  this.attemptToResolveRelativeTarget = false;
7127
- const relativeParent = this.getClosestProjectingParent();
7128
7212
  if (relativeParent &&
7129
7213
  Boolean(relativeParent.resumingFrom) ===
7130
7214
  Boolean(this.resumingFrom) &&
7131
7215
  !relativeParent.options.layoutScroll &&
7132
7216
  relativeParent.target &&
7133
7217
  this.animationProgress !== 1) {
7134
- this.relativeParent = relativeParent;
7135
- this.forceRelativeParentToResolveTarget();
7136
- this.relativeTarget = createBox();
7137
- this.relativeTargetOrigin = createBox();
7138
- calcRelativePosition(this.relativeTargetOrigin, this.target, relativeParent.target);
7139
- copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
7218
+ this.createRelativeTarget(relativeParent, this.target, relativeParent.target);
7140
7219
  }
7141
7220
  else {
7142
7221
  this.relativeParent = this.relativeTarget = undefined;
@@ -7168,6 +7247,18 @@
7168
7247
  this.options.layoutRoot) &&
7169
7248
  this.layout);
7170
7249
  }
7250
+ createRelativeTarget(relativeParent, layout, parentLayout) {
7251
+ this.relativeParent = relativeParent;
7252
+ this.linkedParentVersion = relativeParent.layoutVersion;
7253
+ this.forceRelativeParentToResolveTarget();
7254
+ this.relativeTarget = createBox();
7255
+ this.relativeTargetOrigin = createBox();
7256
+ calcRelativePosition(this.relativeTargetOrigin, layout, parentLayout);
7257
+ copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
7258
+ }
7259
+ removeRelativeTarget() {
7260
+ this.relativeParent = this.relativeTarget = undefined;
7261
+ }
7171
7262
  calcProjection() {
7172
7263
  const lead = this.getLead();
7173
7264
  const isShared = Boolean(this.resumingFrom) || this !== lead;
@@ -7935,75 +8026,6 @@
7935
8026
  checkIsScrollRoot: (instance) => Boolean(window.getComputedStyle(instance).position === "fixed"),
7936
8027
  });
7937
8028
 
7938
- function pixelsToPercent(pixels, axis) {
7939
- if (axis.max === axis.min)
7940
- return 0;
7941
- return (pixels / (axis.max - axis.min)) * 100;
7942
- }
7943
- /**
7944
- * We always correct borderRadius as a percentage rather than pixels to reduce paints.
7945
- * For example, if you are projecting a box that is 100px wide with a 10px borderRadius
7946
- * into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
7947
- * borderRadius in both states. If we animate between the two in pixels that will trigger
7948
- * a paint each time. If we animate between the two in percentage we'll avoid a paint.
7949
- */
7950
- const correctBorderRadius = {
7951
- correct: (latest, node) => {
7952
- if (!node.target)
7953
- return latest;
7954
- /**
7955
- * If latest is a string, if it's a percentage we can return immediately as it's
7956
- * going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
7957
- */
7958
- if (typeof latest === "string") {
7959
- if (px.test(latest)) {
7960
- latest = parseFloat(latest);
7961
- }
7962
- else {
7963
- return latest;
7964
- }
7965
- }
7966
- /**
7967
- * If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
7968
- * pixel value as a percentage of each axis
7969
- */
7970
- const x = pixelsToPercent(latest, node.target.x);
7971
- const y = pixelsToPercent(latest, node.target.y);
7972
- return `${x}% ${y}%`;
7973
- },
7974
- };
7975
-
7976
- const correctBoxShadow = {
7977
- correct: (latest, { treeScale, projectionDelta }) => {
7978
- const original = latest;
7979
- const shadow = complex.parse(latest);
7980
- // TODO: Doesn't support multiple shadows
7981
- if (shadow.length > 5)
7982
- return original;
7983
- const template = complex.createTransformer(latest);
7984
- const offset = typeof shadow[0] !== "number" ? 1 : 0;
7985
- // Calculate the overall context scale
7986
- const xScale = projectionDelta.x.scale * treeScale.x;
7987
- const yScale = projectionDelta.y.scale * treeScale.y;
7988
- shadow[0 + offset] /= xScale;
7989
- shadow[1 + offset] /= yScale;
7990
- /**
7991
- * Ideally we'd correct x and y scales individually, but because blur and
7992
- * spread apply to both we have to take a scale average and apply that instead.
7993
- * We could potentially improve the outcome of this by incorporating the ratio between
7994
- * the two scales.
7995
- */
7996
- const averageScale = mixNumber$1(xScale, yScale, 0.5);
7997
- // Blur
7998
- if (typeof shadow[2 + offset] === "number")
7999
- shadow[2 + offset] /= averageScale;
8000
- // Spread
8001
- if (typeof shadow[3 + offset] === "number")
8002
- shadow[3 + offset] /= averageScale;
8003
- return template(shadow);
8004
- },
8005
- };
8006
-
8007
8029
  /**
8008
8030
  * Bounding boxes tend to be defined as top, left, right, bottom. For various operations
8009
8031
  * it's easier to consider each axis individually. This function returns a bounding box
@@ -11466,7 +11488,6 @@
11466
11488
  componentDidMount() {
11467
11489
  const { visualElement, layoutGroup, switchLayoutGroup, layoutId } = this.props;
11468
11490
  const { projection } = visualElement;
11469
- addScaleCorrector(defaultScaleCorrectors);
11470
11491
  if (projection) {
11471
11492
  if (layoutGroup.group)
11472
11493
  layoutGroup.group.add(projection);
@@ -11565,22 +11586,6 @@
11565
11586
  const layoutGroup = React$1.useContext(LayoutGroupContext);
11566
11587
  return (jsx(MeasureLayoutWithContext, { ...props, layoutGroup: layoutGroup, switchLayoutGroup: React$1.useContext(SwitchLayoutGroupContext), isPresent: isPresent, safeToRemove: safeToRemove }));
11567
11588
  }
11568
- const defaultScaleCorrectors = {
11569
- borderRadius: {
11570
- ...correctBorderRadius,
11571
- applyTo: [
11572
- "borderTopLeftRadius",
11573
- "borderTopRightRadius",
11574
- "borderBottomLeftRadius",
11575
- "borderBottomRightRadius",
11576
- ],
11577
- },
11578
- borderTopLeftRadius: correctBorderRadius,
11579
- borderTopRightRadius: correctBorderRadius,
11580
- borderBottomLeftRadius: correctBorderRadius,
11581
- borderBottomRightRadius: correctBorderRadius,
11582
- boxShadow: correctBoxShadow,
11583
- };
11584
11589
 
11585
11590
  const drag = {
11586
11591
  pan: {