framer-motion 10.2.4 → 10.3.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.
package/dist/index.d.ts CHANGED
@@ -896,8 +896,11 @@ declare type Driver = (update: Update) => DriverControls;
896
896
  * @public
897
897
  */
898
898
  interface AnimationPlaybackControls {
899
- currentTime: number;
899
+ time: number;
900
900
  stop: () => void;
901
+ play: () => void;
902
+ pause: () => void;
903
+ then: (onResolve: VoidFunction, onReject?: VoidFunction) => Promise<void>;
901
904
  }
902
905
  interface VelocityOptions {
903
906
  velocity?: number;
@@ -1403,6 +1406,7 @@ interface IProjectionNode<I = unknown> {
1403
1406
  isProjectionDirty: boolean;
1404
1407
  isSharedProjectionDirty: boolean;
1405
1408
  isTransformDirty: boolean;
1409
+ resolvedRelativeTargetAt?: number;
1406
1410
  shouldResetTransform: boolean;
1407
1411
  prevTransformTemplateValue: string | undefined;
1408
1412
  isUpdateBlocked(): boolean;
@@ -1438,7 +1442,7 @@ interface IProjectionNode<I = unknown> {
1438
1442
  resetTransform(): void;
1439
1443
  resetRotation(): void;
1440
1444
  applyTransform(box: Box, transformOnly?: boolean): Box;
1441
- resolveTargetDelta(): void;
1445
+ resolveTargetDelta(force?: boolean): void;
1442
1446
  calcProjection(): void;
1443
1447
  getProjectionStyles(styles?: MotionStyle): MotionStyle | undefined;
1444
1448
  clearMeasurements(): void;
@@ -1214,6 +1214,20 @@
1214
1214
  return duration;
1215
1215
  }
1216
1216
  function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, keyframes: keyframes$1, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", onPlay, onStop, onComplete, onUpdate, ...options }) {
1217
+ let resolveFinishedPromise;
1218
+ let currentFinishedPromise;
1219
+ /**
1220
+ * Create a new finished Promise every time we enter the
1221
+ * finished state and resolve the old Promise. This is
1222
+ * WAAPI-compatible behaviour.
1223
+ */
1224
+ const updateFinishedPromise = () => {
1225
+ currentFinishedPromise = new Promise((resolve) => {
1226
+ resolveFinishedPromise = resolve;
1227
+ });
1228
+ };
1229
+ // Create the first finished promise
1230
+ updateFinishedPromise();
1217
1231
  let animationDriver;
1218
1232
  const generatorFactory = types[type] || keyframes;
1219
1233
  /**
@@ -1259,26 +1273,26 @@
1259
1273
  resolvedDuration = calculatedDuration + repeatDelay;
1260
1274
  totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
1261
1275
  }
1262
- let currentTime = 0;
1276
+ let time = 0;
1263
1277
  const tick = (timestamp) => {
1264
1278
  if (startTime === null)
1265
1279
  return;
1266
1280
  if (holdTime !== null) {
1267
- currentTime = holdTime;
1281
+ time = holdTime;
1268
1282
  }
1269
1283
  else {
1270
- currentTime = timestamp - startTime;
1284
+ time = timestamp - startTime;
1271
1285
  }
1272
1286
  // Rebase on delay
1273
- currentTime = Math.max(currentTime - delay, 0);
1287
+ time = Math.max(time - delay, 0);
1274
1288
  /**
1275
1289
  * If this animation has finished, set the current time
1276
1290
  * to the total duration.
1277
1291
  */
1278
1292
  if (playState === "finished" && holdTime === null) {
1279
- currentTime = totalDuration;
1293
+ time = totalDuration;
1280
1294
  }
1281
- let elapsed = currentTime;
1295
+ let elapsed = time;
1282
1296
  let frameGenerator = generator;
1283
1297
  if (repeat) {
1284
1298
  /**
@@ -1286,7 +1300,7 @@
1286
1300
  * than duration we'll get values like 2.5 (midway through the
1287
1301
  * third iteration)
1288
1302
  */
1289
- const progress = currentTime / resolvedDuration;
1303
+ const progress = time / resolvedDuration;
1290
1304
  /**
1291
1305
  * Get the current iteration (0 indexed). For instance the floor of
1292
1306
  * 2.5 is 2.
@@ -1320,7 +1334,7 @@
1320
1334
  frameGenerator = mirroredGenerator;
1321
1335
  }
1322
1336
  }
1323
- const p = currentTime >= totalDuration
1337
+ const p = time >= totalDuration
1324
1338
  ? repeatType === "reverse" && iterationIsOdd
1325
1339
  ? 0
1326
1340
  : 1
@@ -1333,19 +1347,25 @@
1333
1347
  onUpdate(mapNumbersToKeyframes ? mapNumbersToKeyframes(value) : value);
1334
1348
  }
1335
1349
  if (calculatedDuration !== null) {
1336
- done = currentTime >= totalDuration;
1350
+ done = time >= totalDuration;
1337
1351
  }
1338
1352
  const isAnimationFinished = holdTime === null &&
1339
1353
  (playState === "finished" || (playState === "running" && done));
1340
1354
  if (isAnimationFinished) {
1341
- playState = "finished";
1342
- onComplete && onComplete();
1343
- animationDriver && animationDriver.stop();
1355
+ finish();
1344
1356
  }
1345
1357
  return state;
1346
1358
  };
1359
+ const finish = () => {
1360
+ animationDriver && animationDriver.stop();
1361
+ playState = "finished";
1362
+ onComplete && onComplete();
1363
+ resolveFinishedPromise();
1364
+ updateFinishedPromise();
1365
+ };
1347
1366
  const play = () => {
1348
- animationDriver = driver(tick);
1367
+ if (!animationDriver)
1368
+ animationDriver = driver(tick);
1349
1369
  const now = animationDriver.now();
1350
1370
  onPlay && onPlay();
1351
1371
  playState = "running";
@@ -1364,21 +1384,30 @@
1364
1384
  play();
1365
1385
  }
1366
1386
  const controls = {
1367
- get currentTime() {
1368
- return millisecondsToSeconds(currentTime);
1387
+ then(resolve, reject) {
1388
+ return currentFinishedPromise.then(resolve, reject);
1389
+ },
1390
+ get time() {
1391
+ return millisecondsToSeconds(time);
1369
1392
  },
1370
- set currentTime(newTime) {
1393
+ set time(newTime) {
1394
+ const timeInMs = secondsToMilliseconds(newTime);
1371
1395
  if (holdTime !== null || !animationDriver) {
1372
- holdTime = 0;
1396
+ holdTime = timeInMs;
1373
1397
  }
1374
1398
  else {
1375
- startTime =
1376
- animationDriver.now() - secondsToMilliseconds(newTime);
1399
+ startTime = animationDriver.now() - timeInMs;
1377
1400
  }
1378
1401
  },
1402
+ play,
1403
+ pause: () => {
1404
+ playState = "paused";
1405
+ holdTime = time;
1406
+ },
1379
1407
  stop: () => {
1380
1408
  onStop && onStop();
1381
1409
  animationDriver && animationDriver.stop();
1410
+ animationDriver = undefined;
1382
1411
  },
1383
1412
  sample: (elapsed) => {
1384
1413
  startTime = 0;
@@ -1477,12 +1506,17 @@
1477
1506
  * Animation interrupt callback.
1478
1507
  */
1479
1508
  return {
1480
- get currentTime() {
1509
+ then(resolve, reject) {
1510
+ return animation.finished.then(resolve, reject);
1511
+ },
1512
+ get time() {
1481
1513
  return millisecondsToSeconds(animation.currentTime || 0);
1482
1514
  },
1483
- set currentTime(newTime) {
1515
+ set time(newTime) {
1484
1516
  animation.currentTime = secondsToMilliseconds(newTime);
1485
1517
  },
1518
+ play: () => animation.play(),
1519
+ pause: () => animation.pause(),
1486
1520
  stop: () => {
1487
1521
  /**
1488
1522
  * WAAPI doesn't natively have any interruption capabilities.
@@ -1510,8 +1544,11 @@
1510
1544
  onUpdate && onUpdate(keyframes[keyframes.length - 1]);
1511
1545
  onComplete && onComplete();
1512
1546
  return {
1513
- stop: () => { },
1514
- currentTime: 0,
1547
+ time: 0,
1548
+ play: (noop),
1549
+ pause: (noop),
1550
+ stop: (noop),
1551
+ then: Promise.resolve,
1515
1552
  };
1516
1553
  };
1517
1554
  return delayBy
@@ -1973,7 +2010,7 @@
1973
2010
  * This will be replaced by the build step with the latest version number.
1974
2011
  * When MotionValues are provided to motion components, warn if versions are mixed.
1975
2012
  */
1976
- this.version = "10.2.4";
2013
+ this.version = "10.3.0";
1977
2014
  /**
1978
2015
  * Duration, in milliseconds, since last updating frame.
1979
2016
  *
@@ -2282,23 +2319,35 @@
2282
2319
  constructor(animations) {
2283
2320
  this.animations = animations.filter(Boolean);
2284
2321
  }
2322
+ then(onResolve, onReject) {
2323
+ return Promise.all(this.animations).then(onResolve).catch(onReject);
2324
+ }
2285
2325
  /**
2286
2326
  * TODO: Filter out cancelled or stopped animations before returning
2287
2327
  */
2288
- get currentTime() {
2289
- return this.animations[0].currentTime;
2328
+ get time() {
2329
+ return this.animations[0].time;
2290
2330
  }
2291
2331
  /**
2292
- * currentTime assignment could reasonably run every frame, so
2332
+ * time assignment could reasonably run every frame, so
2293
2333
  * we iterate using a normal loop to avoid function creation.
2294
2334
  */
2295
- set currentTime(time) {
2335
+ set time(time) {
2296
2336
  for (let i = 0; i < this.animations.length; i++) {
2297
- this.animations[i].currentTime = time;
2337
+ this.animations[i].time = time;
2298
2338
  }
2299
2339
  }
2340
+ runAll(methodName) {
2341
+ this.animations.forEach((controls) => controls[methodName]());
2342
+ }
2343
+ play() {
2344
+ this.runAll("play");
2345
+ }
2346
+ pause() {
2347
+ this.runAll("pause");
2348
+ }
2300
2349
  stop() {
2301
- this.animations.forEach((controls) => controls.stop());
2350
+ this.runAll("stop");
2302
2351
  }
2303
2352
  }
2304
2353
 
@@ -3549,10 +3598,7 @@
3549
3598
  this.target = undefined;
3550
3599
  this.isLayoutDirty = false;
3551
3600
  }
3552
- /**
3553
- * Frame calculations
3554
- */
3555
- resolveTargetDelta() {
3601
+ resolveTargetDelta(forceRecalculation = false) {
3556
3602
  var _a;
3557
3603
  /**
3558
3604
  * Once the dirty status of nodes has been spread through the tree, we also
@@ -3568,7 +3614,8 @@
3568
3614
  * We don't use transform for this step of processing so we don't
3569
3615
  * need to check whether any nodes have changed transform.
3570
3616
  */
3571
- const canSkip = !((isShared && this.isSharedProjectionDirty) ||
3617
+ const canSkip = !(forceRecalculation ||
3618
+ (isShared && this.isSharedProjectionDirty) ||
3572
3619
  this.isProjectionDirty ||
3573
3620
  ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isProjectionDirty) ||
3574
3621
  this.attemptToResolveRelativeTarget);
@@ -3580,6 +3627,7 @@
3580
3627
  */
3581
3628
  if (!this.layout || !(layout || layoutId))
3582
3629
  return;
3630
+ this.resolvedRelativeTargetAt = frameData.timestamp;
3583
3631
  /**
3584
3632
  * If we don't have a targetDelta but do have a layout, we can attempt to resolve
3585
3633
  * a relativeParent. This will allow a component to perform scale correction
@@ -3620,6 +3668,16 @@
3620
3668
  this.relativeTargetOrigin &&
3621
3669
  this.relativeParent &&
3622
3670
  this.relativeParent.target) {
3671
+ /**
3672
+ * If the parent target isn't up-to-date, force it to update.
3673
+ * This is an unfortunate de-optimisation as it means any updating relative
3674
+ * projection will cause all the relative parents to recalculate back
3675
+ * up the tree.
3676
+ */
3677
+ if (this.relativeParent.resolvedRelativeTargetAt !==
3678
+ frameData.timestamp) {
3679
+ this.relativeParent.resolveTargetDelta(true);
3680
+ }
3623
3681
  calcRelativeBox(this.target, this.relativeTarget, this.relativeParent.target);
3624
3682
  /**
3625
3683
  * If we've only got a targetDelta, resolve it into a target
@@ -3706,6 +3764,13 @@
3706
3764
  (this.isSharedProjectionDirty || this.isTransformDirty)) {
3707
3765
  canSkip = false;
3708
3766
  }
3767
+ /**
3768
+ * If we have resolved the target this frame we must recalculate the
3769
+ * projection to ensure it visually represents the internal calculations.
3770
+ */
3771
+ if (this.resolvedRelativeTargetAt === frameData.timestamp) {
3772
+ canSkip = false;
3773
+ }
3709
3774
  if (canSkip)
3710
3775
  return;
3711
3776
  const { layout, layoutId } = this.options;
@@ -5203,7 +5268,7 @@
5203
5268
  * and warn against mismatches.
5204
5269
  */
5205
5270
  {
5206
- warnOnce(nextValue.version === "10.2.4", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.2.4 may not work as expected.`);
5271
+ warnOnce(nextValue.version === "10.3.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.3.0 may not work as expected.`);
5207
5272
  }
5208
5273
  }
5209
5274
  else if (isMotionValue(prevValue)) {
@@ -5845,6 +5910,7 @@
5845
5910
  exports.calcBoxDelta = calcBoxDelta;
5846
5911
  exports.correctBorderRadius = correctBorderRadius;
5847
5912
  exports.correctBoxShadow = correctBoxShadow;
5913
+ exports.frameData = frameData;
5848
5914
  exports.mix = mix;
5849
5915
  exports.nodeGroup = nodeGroup;
5850
5916
  exports.sync = sync;
@@ -856,8 +856,11 @@ interface CustomValueType {
856
856
  * @public
857
857
  */
858
858
  interface AnimationPlaybackControls {
859
- currentTime: number;
859
+ time: number;
860
860
  stop: () => void;
861
+ play: () => void;
862
+ pause: () => void;
863
+ then: (onResolve: VoidFunction, onReject?: VoidFunction) => Promise<void>;
861
864
  }
862
865
  /**
863
866
  * @public
@@ -1299,6 +1302,7 @@ interface IProjectionNode<I = unknown> {
1299
1302
  isProjectionDirty: boolean;
1300
1303
  isSharedProjectionDirty: boolean;
1301
1304
  isTransformDirty: boolean;
1305
+ resolvedRelativeTargetAt?: number;
1302
1306
  shouldResetTransform: boolean;
1303
1307
  prevTransformTemplateValue: string | undefined;
1304
1308
  isUpdateBlocked(): boolean;
@@ -1334,7 +1338,7 @@ interface IProjectionNode<I = unknown> {
1334
1338
  resetTransform(): void;
1335
1339
  resetRotation(): void;
1336
1340
  applyTransform(box: Box, transformOnly?: boolean): Box;
1337
- resolveTargetDelta(): void;
1341
+ resolveTargetDelta(force?: boolean): void;
1338
1342
  calcProjection(): void;
1339
1343
  getProjectionStyles(styles?: MotionStyle): MotionStyle | undefined;
1340
1344
  clearMeasurements(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-motion",
3
- "version": "10.2.4",
3
+ "version": "10.3.0",
4
4
  "description": "A simple and powerful React and JavaScript animation library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.mjs",
@@ -85,7 +85,7 @@
85
85
  "bundlesize": [
86
86
  {
87
87
  "path": "./dist/size-rollup-motion.js",
88
- "maxSize": "29.85 kB"
88
+ "maxSize": "30.07 kB"
89
89
  },
90
90
  {
91
91
  "path": "./dist/size-rollup-m.js",
@@ -93,11 +93,11 @@
93
93
  },
94
94
  {
95
95
  "path": "./dist/size-rollup-dom-animation.js",
96
- "maxSize": "14.56 kB"
96
+ "maxSize": "14.68 kB"
97
97
  },
98
98
  {
99
99
  "path": "./dist/size-rollup-dom-max.js",
100
- "maxSize": "25.6 kB"
100
+ "maxSize": "25.82 kB"
101
101
  },
102
102
  {
103
103
  "path": "./dist/size-rollup-animate.js",
@@ -109,12 +109,12 @@
109
109
  },
110
110
  {
111
111
  "path": "./dist/size-webpack-dom-animation.js",
112
- "maxSize": "18.56 kB"
112
+ "maxSize": "18.68 kB"
113
113
  },
114
114
  {
115
115
  "path": "./dist/size-webpack-dom-max.js",
116
- "maxSize": "30.42 kB"
116
+ "maxSize": "30.8 kB"
117
117
  }
118
118
  ],
119
- "gitHead": "82eb0ba26cd103d524a27dc95415e437cce35822"
119
+ "gitHead": "f464ee9f02ed31e4611b7316df6ea68018721031"
120
120
  }