framer-motion 5.4.1 → 5.4.4

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,15 +1,11 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var tslib = require('tslib');
6
4
  var React = require('react');
7
5
  var heyListen = require('hey-listen');
8
6
  var sync = require('framesync');
9
7
  var popmotion = require('popmotion');
10
8
  var styleValueTypes = require('style-value-types');
11
- var three = require('three');
12
- var fiber = require('@react-three/fiber');
13
9
 
14
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
11
 
@@ -321,6 +317,17 @@ function removeItem(arr, item) {
321
317
  var index = arr.indexOf(item);
322
318
  index > -1 && arr.splice(index, 1);
323
319
  }
320
+ // Adapted from array-move
321
+ function moveItem(_a, fromIndex, toIndex) {
322
+ var _b = tslib.__read(_a), arr = _b.slice(0);
323
+ var startIndex = fromIndex < 0 ? arr.length + fromIndex : fromIndex;
324
+ if (startIndex >= 0 && startIndex < arr.length) {
325
+ var endIndex = toIndex < 0 ? arr.length + toIndex : toIndex;
326
+ var _c = tslib.__read(arr.splice(fromIndex, 1), 1), item = _c[0];
327
+ arr.splice(endIndex, 0, item);
328
+ }
329
+ return arr;
330
+ }
324
331
 
325
332
  var SubscriptionManager = /** @class */ (function () {
326
333
  function SubscriptionManager() {
@@ -1093,12 +1100,601 @@ function startAnimation(key, value, target, transition) {
1093
1100
  });
1094
1101
  }
1095
1102
 
1103
+ /**
1104
+ * Animate a single value or a `MotionValue`.
1105
+ *
1106
+ * The first argument is either a `MotionValue` to animate, or an initial animation value.
1107
+ *
1108
+ * The second is either a value to animate to, or an array of keyframes to animate through.
1109
+ *
1110
+ * The third argument can be either tween or spring options, and optional lifecycle methods: `onUpdate`, `onPlay`, `onComplete`, `onRepeat` and `onStop`.
1111
+ *
1112
+ * Returns `AnimationPlaybackControls`, currently just a `stop` method.
1113
+ *
1114
+ * ```javascript
1115
+ * const x = useMotionValue(0)
1116
+ *
1117
+ * useEffect(() => {
1118
+ * const controls = animate(x, 100, {
1119
+ * type: "spring",
1120
+ * stiffness: 2000,
1121
+ * onComplete: v => {}
1122
+ * })
1123
+ *
1124
+ * return controls.stop
1125
+ * })
1126
+ * ```
1127
+ *
1128
+ * @public
1129
+ */
1130
+ function animate(from, to, transition) {
1131
+ if (transition === void 0) { transition = {}; }
1132
+ var value = isMotionValue(from) ? from : motionValue(from);
1133
+ startAnimation("", value, to, transition);
1134
+ return {
1135
+ stop: function () { return value.stop(); },
1136
+ isAnimating: function () { return value.isAnimating(); },
1137
+ };
1138
+ }
1139
+
1140
+ var borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
1141
+ var numBorders = borders.length;
1142
+ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
1143
+ var _a, _b, _c, _d;
1144
+ if (shouldCrossfadeOpacity) {
1145
+ target.opacity = popmotion.mix(0,
1146
+ // (follow?.opacity as number) ?? 0,
1147
+ // TODO Reinstate this if only child
1148
+ (_a = lead.opacity) !== null && _a !== void 0 ? _a : 1, easeCrossfadeIn(progress));
1149
+ target.opacityExit = popmotion.mix((_b = follow.opacity) !== null && _b !== void 0 ? _b : 1, 0, easeCrossfadeOut(progress));
1150
+ }
1151
+ else if (isOnlyMember) {
1152
+ target.opacity = popmotion.mix((_c = follow.opacity) !== null && _c !== void 0 ? _c : 1, (_d = lead.opacity) !== null && _d !== void 0 ? _d : 1, progress);
1153
+ }
1154
+ /**
1155
+ * Mix border radius
1156
+ */
1157
+ for (var i = 0; i < numBorders; i++) {
1158
+ var borderLabel = "border".concat(borders[i], "Radius");
1159
+ var followRadius = getRadius(follow, borderLabel);
1160
+ var leadRadius = getRadius(lead, borderLabel);
1161
+ if (followRadius === undefined && leadRadius === undefined)
1162
+ continue;
1163
+ followRadius || (followRadius = 0);
1164
+ leadRadius || (leadRadius = 0);
1165
+ /**
1166
+ * Currently we're only crossfading between numerical border radius.
1167
+ * It would be possible to crossfade between percentages for a little
1168
+ * extra bundle size.
1169
+ */
1170
+ if (typeof followRadius === "number" &&
1171
+ typeof leadRadius === "number") {
1172
+ var radius = Math.max(popmotion.mix(followRadius, leadRadius, progress), 0);
1173
+ target[borderLabel] = radius;
1174
+ }
1175
+ }
1176
+ /**
1177
+ * Mix rotation
1178
+ */
1179
+ if (follow.rotate || lead.rotate) {
1180
+ target.rotate = popmotion.mix(follow.rotate || 0, lead.rotate || 0, progress);
1181
+ }
1182
+ }
1183
+ function getRadius(values, radiusName) {
1184
+ var _a;
1185
+ return (_a = values[radiusName]) !== null && _a !== void 0 ? _a : values.borderRadius;
1186
+ }
1187
+ // /**
1188
+ // * We only want to mix the background color if there's a follow element
1189
+ // * that we're not crossfading opacity between. For instance with switch
1190
+ // * AnimateSharedLayout animations, this helps the illusion of a continuous
1191
+ // * element being animated but also cuts down on the number of paints triggered
1192
+ // * for elements where opacity is doing that work for us.
1193
+ // */
1194
+ // if (
1195
+ // !hasFollowElement &&
1196
+ // latestLeadValues.backgroundColor &&
1197
+ // latestFollowValues.backgroundColor
1198
+ // ) {
1199
+ // /**
1200
+ // * This isn't ideal performance-wise as mixColor is creating a new function every frame.
1201
+ // * We could probably create a mixer that runs at the start of the animation but
1202
+ // * the idea behind the crossfader is that it runs dynamically between two potentially
1203
+ // * changing targets (ie opacity or borderRadius may be animating independently via variants)
1204
+ // */
1205
+ // leadState.backgroundColor = followState.backgroundColor = mixColor(
1206
+ // latestFollowValues.backgroundColor as string,
1207
+ // latestLeadValues.backgroundColor as string
1208
+ // )(p)
1209
+ // }
1210
+ var easeCrossfadeIn = compress(0, 0.5, popmotion.circOut);
1211
+ var easeCrossfadeOut = compress(0.5, 0.95, popmotion.linear);
1212
+ function compress(min, max, easing) {
1213
+ return function (p) {
1214
+ // Could replace ifs with clamp
1215
+ if (p < min)
1216
+ return 0;
1217
+ if (p > max)
1218
+ return 1;
1219
+ return easing(popmotion.progress(min, max, p));
1220
+ };
1221
+ }
1222
+
1223
+ /**
1224
+ * Reset an axis to the provided origin box.
1225
+ *
1226
+ * This is a mutative operation.
1227
+ */
1228
+ function copyAxisInto(axis, originAxis) {
1229
+ axis.min = originAxis.min;
1230
+ axis.max = originAxis.max;
1231
+ }
1232
+ /**
1233
+ * Reset a box to the provided origin box.
1234
+ *
1235
+ * This is a mutative operation.
1236
+ */
1237
+ function copyBoxInto(box, originBox) {
1238
+ copyAxisInto(box.x, originBox.x);
1239
+ copyAxisInto(box.y, originBox.y);
1240
+ }
1241
+
1242
+ function isIdentityScale(scale) {
1243
+ return scale === undefined || scale === 1;
1244
+ }
1245
+ function hasScale(_a) {
1246
+ var scale = _a.scale, scaleX = _a.scaleX, scaleY = _a.scaleY;
1247
+ return (!isIdentityScale(scale) ||
1248
+ !isIdentityScale(scaleX) ||
1249
+ !isIdentityScale(scaleY));
1250
+ }
1251
+ function hasTransform(values) {
1252
+ return (hasScale(values) ||
1253
+ hasTranslate(values.x) ||
1254
+ hasTranslate(values.y) ||
1255
+ values.z ||
1256
+ values.rotate ||
1257
+ values.rotateX ||
1258
+ values.rotateY);
1259
+ }
1260
+ function hasTranslate(value) {
1261
+ return value && value !== "0%";
1262
+ }
1263
+
1264
+ /**
1265
+ * Scales a point based on a factor and an originPoint
1266
+ */
1267
+ function scalePoint(point, scale, originPoint) {
1268
+ var distanceFromOrigin = point - originPoint;
1269
+ var scaled = scale * distanceFromOrigin;
1270
+ return originPoint + scaled;
1271
+ }
1272
+ /**
1273
+ * Applies a translate/scale delta to a point
1274
+ */
1275
+ function applyPointDelta(point, translate, scale, originPoint, boxScale) {
1276
+ if (boxScale !== undefined) {
1277
+ point = scalePoint(point, boxScale, originPoint);
1278
+ }
1279
+ return scalePoint(point, scale, originPoint) + translate;
1280
+ }
1281
+ /**
1282
+ * Applies a translate/scale delta to an axis
1283
+ */
1284
+ function applyAxisDelta(axis, translate, scale, originPoint, boxScale) {
1285
+ if (translate === void 0) { translate = 0; }
1286
+ if (scale === void 0) { scale = 1; }
1287
+ axis.min = applyPointDelta(axis.min, translate, scale, originPoint, boxScale);
1288
+ axis.max = applyPointDelta(axis.max, translate, scale, originPoint, boxScale);
1289
+ }
1290
+ /**
1291
+ * Applies a translate/scale delta to a box
1292
+ */
1293
+ function applyBoxDelta(box, _a) {
1294
+ var x = _a.x, y = _a.y;
1295
+ applyAxisDelta(box.x, x.translate, x.scale, x.originPoint);
1296
+ applyAxisDelta(box.y, y.translate, y.scale, y.originPoint);
1297
+ }
1298
+ /**
1299
+ * Apply a tree of deltas to a box. We do this to calculate the effect of all the transforms
1300
+ * in a tree upon our box before then calculating how to project it into our desired viewport-relative box
1301
+ *
1302
+ * This is the final nested loop within updateLayoutDelta for future refactoring
1303
+ */
1304
+ function applyTreeDeltas(box, treeScale, treePath, isSharedTransition) {
1305
+ var _a, _b;
1306
+ if (isSharedTransition === void 0) { isSharedTransition = false; }
1307
+ var treeLength = treePath.length;
1308
+ if (!treeLength)
1309
+ return;
1310
+ // Reset the treeScale
1311
+ treeScale.x = treeScale.y = 1;
1312
+ var node;
1313
+ var delta;
1314
+ for (var i = 0; i < treeLength; i++) {
1315
+ node = treePath[i];
1316
+ delta = node.projectionDelta;
1317
+ if (((_b = (_a = node.instance) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.display) === "contents")
1318
+ continue;
1319
+ if (isSharedTransition &&
1320
+ node.options.layoutScroll &&
1321
+ node.scroll &&
1322
+ node !== node.root) {
1323
+ transformBox(box, { x: -node.scroll.x, y: -node.scroll.y });
1324
+ }
1325
+ if (delta) {
1326
+ // Incoporate each ancestor's scale into a culmulative treeScale for this component
1327
+ treeScale.x *= delta.x.scale;
1328
+ treeScale.y *= delta.y.scale;
1329
+ // Apply each ancestor's calculated delta into this component's recorded layout box
1330
+ applyBoxDelta(box, delta);
1331
+ }
1332
+ if (isSharedTransition && hasTransform(node.latestValues)) {
1333
+ transformBox(box, node.latestValues);
1334
+ }
1335
+ }
1336
+ }
1337
+ function translateAxis(axis, distance) {
1338
+ axis.min = axis.min + distance;
1339
+ axis.max = axis.max + distance;
1340
+ }
1341
+ /**
1342
+ * Apply a transform to an axis from the latest resolved motion values.
1343
+ * This function basically acts as a bridge between a flat motion value map
1344
+ * and applyAxisDelta
1345
+ */
1346
+ function transformAxis(axis, transforms, _a) {
1347
+ var _b = tslib.__read(_a, 3), key = _b[0], scaleKey = _b[1], originKey = _b[2];
1348
+ var axisOrigin = transforms[originKey] !== undefined ? transforms[originKey] : 0.5;
1349
+ var originPoint = popmotion.mix(axis.min, axis.max, axisOrigin);
1350
+ // Apply the axis delta to the final axis
1351
+ applyAxisDelta(axis, transforms[key], transforms[scaleKey], originPoint, transforms.scale);
1352
+ }
1353
+ /**
1354
+ * The names of the motion values we want to apply as translation, scale and origin.
1355
+ */
1356
+ var xKeys$1 = ["x", "scaleX", "originX"];
1357
+ var yKeys$1 = ["y", "scaleY", "originY"];
1358
+ /**
1359
+ * Apply a transform to a box from the latest resolved motion values.
1360
+ */
1361
+ function transformBox(box, transform) {
1362
+ transformAxis(box.x, transform, xKeys$1);
1363
+ transformAxis(box.y, transform, yKeys$1);
1364
+ }
1365
+
1366
+ function calcLength(axis) {
1367
+ return axis.max - axis.min;
1368
+ }
1369
+ function isNear(value, target, maxDistance) {
1370
+ if (target === void 0) { target = 0; }
1371
+ if (maxDistance === void 0) { maxDistance = 0.01; }
1372
+ return popmotion.distance(value, target) < maxDistance;
1373
+ }
1374
+ function calcAxisDelta(delta, source, target, origin) {
1375
+ if (origin === void 0) { origin = 0.5; }
1376
+ delta.origin = origin;
1377
+ delta.originPoint = popmotion.mix(source.min, source.max, delta.origin);
1378
+ delta.scale = calcLength(target) / calcLength(source);
1379
+ if (isNear(delta.scale, 1, 0.0001) || isNaN(delta.scale))
1380
+ delta.scale = 1;
1381
+ delta.translate =
1382
+ popmotion.mix(target.min, target.max, delta.origin) - delta.originPoint;
1383
+ if (isNear(delta.translate) || isNaN(delta.translate))
1384
+ delta.translate = 0;
1385
+ }
1386
+ function calcBoxDelta(delta, source, target, origin) {
1387
+ calcAxisDelta(delta.x, source.x, target.x, origin === null || origin === void 0 ? void 0 : origin.originX);
1388
+ calcAxisDelta(delta.y, source.y, target.y, origin === null || origin === void 0 ? void 0 : origin.originY);
1389
+ }
1390
+ function calcRelativeAxis(target, relative, parent) {
1391
+ target.min = parent.min + relative.min;
1392
+ target.max = target.min + calcLength(relative);
1393
+ }
1394
+ function calcRelativeBox(target, relative, parent) {
1395
+ calcRelativeAxis(target.x, relative.x, parent.x);
1396
+ calcRelativeAxis(target.y, relative.y, parent.y);
1397
+ }
1398
+ function calcRelativeAxisPosition(target, layout, parent) {
1399
+ target.min = layout.min - parent.min;
1400
+ target.max = target.min + calcLength(layout);
1401
+ }
1402
+ function calcRelativePosition(target, layout, parent) {
1403
+ calcRelativeAxisPosition(target.x, layout.x, parent.x);
1404
+ calcRelativeAxisPosition(target.y, layout.y, parent.y);
1405
+ }
1406
+
1407
+ /**
1408
+ * Remove a delta from a point. This is essentially the steps of applyPointDelta in reverse
1409
+ */
1410
+ function removePointDelta(point, translate, scale, originPoint, boxScale) {
1411
+ point -= translate;
1412
+ point = scalePoint(point, 1 / scale, originPoint);
1413
+ if (boxScale !== undefined) {
1414
+ point = scalePoint(point, 1 / boxScale, originPoint);
1415
+ }
1416
+ return point;
1417
+ }
1418
+ /**
1419
+ * Remove a delta from an axis. This is essentially the steps of applyAxisDelta in reverse
1420
+ */
1421
+ function removeAxisDelta(axis, translate, scale, origin, boxScale, originAxis, sourceAxis) {
1422
+ if (translate === void 0) { translate = 0; }
1423
+ if (scale === void 0) { scale = 1; }
1424
+ if (origin === void 0) { origin = 0.5; }
1425
+ if (originAxis === void 0) { originAxis = axis; }
1426
+ if (sourceAxis === void 0) { sourceAxis = axis; }
1427
+ if (styleValueTypes.percent.test(translate)) {
1428
+ translate = parseFloat(translate);
1429
+ var relativeProgress = popmotion.mix(sourceAxis.min, sourceAxis.max, translate / 100);
1430
+ translate = relativeProgress - sourceAxis.min;
1431
+ }
1432
+ if (typeof translate !== "number")
1433
+ return;
1434
+ var originPoint = popmotion.mix(originAxis.min, originAxis.max, origin);
1435
+ if (axis === originAxis)
1436
+ originPoint -= translate;
1437
+ axis.min = removePointDelta(axis.min, translate, scale, originPoint, boxScale);
1438
+ axis.max = removePointDelta(axis.max, translate, scale, originPoint, boxScale);
1439
+ }
1440
+ /**
1441
+ * Remove a transforms from an axis. This is essentially the steps of applyAxisTransforms in reverse
1442
+ * and acts as a bridge between motion values and removeAxisDelta
1443
+ */
1444
+ function removeAxisTransforms(axis, transforms, _a, origin, sourceAxis) {
1445
+ var _b = tslib.__read(_a, 3), key = _b[0], scaleKey = _b[1], originKey = _b[2];
1446
+ removeAxisDelta(axis, transforms[key], transforms[scaleKey], transforms[originKey], transforms.scale, origin, sourceAxis);
1447
+ }
1448
+ /**
1449
+ * The names of the motion values we want to apply as translation, scale and origin.
1450
+ */
1451
+ var xKeys = ["x", "scaleX", "originX"];
1452
+ var yKeys = ["y", "scaleY", "originY"];
1453
+ /**
1454
+ * Remove a transforms from an box. This is essentially the steps of applyAxisBox in reverse
1455
+ * and acts as a bridge between motion values and removeAxisDelta
1456
+ */
1457
+ function removeBoxTransforms(box, transforms, originBox, sourceBox) {
1458
+ removeAxisTransforms(box.x, transforms, xKeys, originBox === null || originBox === void 0 ? void 0 : originBox.x, sourceBox === null || sourceBox === void 0 ? void 0 : sourceBox.x);
1459
+ removeAxisTransforms(box.y, transforms, yKeys, originBox === null || originBox === void 0 ? void 0 : originBox.y, sourceBox === null || sourceBox === void 0 ? void 0 : sourceBox.y);
1460
+ }
1461
+
1462
+ var createAxisDelta = function () { return ({
1463
+ translate: 0,
1464
+ scale: 1,
1465
+ origin: 0,
1466
+ originPoint: 0,
1467
+ }); };
1468
+ var createDelta = function () { return ({
1469
+ x: createAxisDelta(),
1470
+ y: createAxisDelta(),
1471
+ }); };
1096
1472
  var createAxis = function () { return ({ min: 0, max: 0 }); };
1097
1473
  var createBox = function () { return ({
1098
1474
  x: createAxis(),
1099
1475
  y: createAxis(),
1100
1476
  }); };
1101
1477
 
1478
+ function isAxisDeltaZero(delta) {
1479
+ return delta.translate === 0 && delta.scale === 1;
1480
+ }
1481
+ function isDeltaZero(delta) {
1482
+ return isAxisDeltaZero(delta.x) && isAxisDeltaZero(delta.y);
1483
+ }
1484
+ function boxEquals(a, b) {
1485
+ return (a.x.min === b.x.min &&
1486
+ a.x.max === b.x.max &&
1487
+ a.y.min === b.y.min &&
1488
+ a.y.max === b.y.max);
1489
+ }
1490
+
1491
+ var NodeStack = /** @class */ (function () {
1492
+ function NodeStack() {
1493
+ this.members = [];
1494
+ }
1495
+ NodeStack.prototype.add = function (node) {
1496
+ addUniqueItem(this.members, node);
1497
+ node.scheduleRender();
1498
+ };
1499
+ NodeStack.prototype.remove = function (node) {
1500
+ removeItem(this.members, node);
1501
+ if (node === this.prevLead) {
1502
+ this.prevLead = undefined;
1503
+ }
1504
+ if (node === this.lead) {
1505
+ var prevLead = this.members[this.members.length - 1];
1506
+ if (prevLead) {
1507
+ this.promote(prevLead);
1508
+ }
1509
+ }
1510
+ };
1511
+ NodeStack.prototype.relegate = function (node) {
1512
+ var indexOfNode = this.members.findIndex(function (member) { return node === member; });
1513
+ if (indexOfNode === 0)
1514
+ return false;
1515
+ /**
1516
+ * Find the next projection node that is present
1517
+ */
1518
+ var prevLead;
1519
+ for (var i = indexOfNode; i >= 0; i--) {
1520
+ var member = this.members[i];
1521
+ if (member.isPresent !== false) {
1522
+ prevLead = member;
1523
+ break;
1524
+ }
1525
+ }
1526
+ if (prevLead) {
1527
+ this.promote(prevLead);
1528
+ return true;
1529
+ }
1530
+ else {
1531
+ return false;
1532
+ }
1533
+ };
1534
+ NodeStack.prototype.promote = function (node, preserveFollowOpacity) {
1535
+ var _a;
1536
+ var prevLead = this.lead;
1537
+ if (node === prevLead)
1538
+ return;
1539
+ this.prevLead = prevLead;
1540
+ this.lead = node;
1541
+ node.show();
1542
+ if (prevLead) {
1543
+ prevLead.instance && prevLead.scheduleRender();
1544
+ node.scheduleRender();
1545
+ node.resumeFrom = prevLead;
1546
+ if (preserveFollowOpacity) {
1547
+ node.resumeFrom.preserveOpacity = true;
1548
+ }
1549
+ if (prevLead.snapshot) {
1550
+ node.snapshot = prevLead.snapshot;
1551
+ node.snapshot.latestValues =
1552
+ prevLead.animationValues || prevLead.latestValues;
1553
+ node.snapshot.isShared = true;
1554
+ }
1555
+ if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
1556
+ node.isLayoutDirty = true;
1557
+ }
1558
+ var crossfade = node.options.crossfade;
1559
+ if (crossfade === false) {
1560
+ prevLead.hide();
1561
+ }
1562
+ /**
1563
+ * TODO:
1564
+ * - Test border radius when previous node was deleted
1565
+ * - boxShadow mixing
1566
+ * - Shared between element A in scrolled container and element B (scroll stays the same or changes)
1567
+ * - Shared between element A in transformed container and element B (transform stays the same or changes)
1568
+ * - Shared between element A in scrolled page and element B (scroll stays the same or changes)
1569
+ * ---
1570
+ * - Crossfade opacity of root nodes
1571
+ * - layoutId changes after animation
1572
+ * - layoutId changes mid animation
1573
+ */
1574
+ }
1575
+ };
1576
+ NodeStack.prototype.exitAnimationComplete = function () {
1577
+ this.members.forEach(function (node) {
1578
+ var _a, _b, _c, _d, _e;
1579
+ (_b = (_a = node.options).onExitComplete) === null || _b === void 0 ? void 0 : _b.call(_a);
1580
+ (_e = (_c = node.resumingFrom) === null || _c === void 0 ? void 0 : (_d = _c.options).onExitComplete) === null || _e === void 0 ? void 0 : _e.call(_d);
1581
+ });
1582
+ };
1583
+ NodeStack.prototype.scheduleRender = function () {
1584
+ this.members.forEach(function (node) {
1585
+ node.instance && node.scheduleRender(false);
1586
+ });
1587
+ };
1588
+ /**
1589
+ * Clear any leads that have been removed this render to prevent them from being
1590
+ * used in future animations and to prevent memory leaks
1591
+ */
1592
+ NodeStack.prototype.removeLeadSnapshot = function () {
1593
+ if (this.lead && this.lead.snapshot) {
1594
+ this.lead.snapshot = undefined;
1595
+ }
1596
+ };
1597
+ return NodeStack;
1598
+ }());
1599
+
1600
+ var scaleCorrectors = {};
1601
+ function addScaleCorrector(correctors) {
1602
+ Object.assign(scaleCorrectors, correctors);
1603
+ }
1604
+
1605
+ var identityProjection = "translate3d(0px, 0px, 0) scale(1, 1)";
1606
+ function buildProjectionTransform(delta, treeScale, latestTransform) {
1607
+ /**
1608
+ * The translations we use to calculate are always relative to the viewport coordinate space.
1609
+ * But when we apply scales, we also scale the coordinate space of an element and its children.
1610
+ * For instance if we have a treeScale (the culmination of all parent scales) of 0.5 and we need
1611
+ * to move an element 100 pixels, we actually need to move it 200 in within that scaled space.
1612
+ */
1613
+ var xTranslate = delta.x.translate / treeScale.x;
1614
+ var yTranslate = delta.y.translate / treeScale.y;
1615
+ var transform = "translate3d(".concat(xTranslate, "px, ").concat(yTranslate, "px, 0) ");
1616
+ if (latestTransform) {
1617
+ var rotate = latestTransform.rotate, rotateX = latestTransform.rotateX, rotateY = latestTransform.rotateY;
1618
+ if (rotate)
1619
+ transform += "rotate(".concat(rotate, "deg) ");
1620
+ if (rotateX)
1621
+ transform += "rotateX(".concat(rotateX, "deg) ");
1622
+ if (rotateY)
1623
+ transform += "rotateY(".concat(rotateY, "deg) ");
1624
+ }
1625
+ transform += "scale(".concat(delta.x.scale, ", ").concat(delta.y.scale, ")");
1626
+ return transform === identityProjection ? "none" : transform;
1627
+ }
1628
+
1629
+ function eachAxis(callback) {
1630
+ return [callback("x"), callback("y")];
1631
+ }
1632
+
1633
+ /**
1634
+ * A list of all transformable axes. We'll use this list to generated a version
1635
+ * of each axes for each transform.
1636
+ */
1637
+ var transformAxes = ["", "X", "Y", "Z"];
1638
+ /**
1639
+ * An ordered array of each transformable value. By default, transform values
1640
+ * will be sorted to this order.
1641
+ */
1642
+ var order = ["translate", "scale", "rotate", "skew"];
1643
+ /**
1644
+ * Generate a list of every possible transform key.
1645
+ */
1646
+ var transformProps = ["transformPerspective", "x", "y", "z"];
1647
+ order.forEach(function (operationKey) {
1648
+ return transformAxes.forEach(function (axesKey) {
1649
+ return transformProps.push(operationKey + axesKey);
1650
+ });
1651
+ });
1652
+ /**
1653
+ * A function to use with Array.sort to sort transform keys by their default order.
1654
+ */
1655
+ function sortTransformProps(a, b) {
1656
+ return transformProps.indexOf(a) - transformProps.indexOf(b);
1657
+ }
1658
+ /**
1659
+ * A quick lookup for transform props.
1660
+ */
1661
+ var transformPropSet = new Set(transformProps);
1662
+ function isTransformProp(key) {
1663
+ return transformPropSet.has(key);
1664
+ }
1665
+ /**
1666
+ * A quick lookup for transform origin props
1667
+ */
1668
+ var transformOriginProps = new Set(["originX", "originY", "originZ"]);
1669
+ function isTransformOriginProp(key) {
1670
+ return transformOriginProps.has(key);
1671
+ }
1672
+
1673
+ var compareByDepth = function (a, b) {
1674
+ return a.depth - b.depth;
1675
+ };
1676
+
1677
+ var FlatTree = /** @class */ (function () {
1678
+ function FlatTree() {
1679
+ this.children = [];
1680
+ this.isDirty = false;
1681
+ }
1682
+ FlatTree.prototype.add = function (child) {
1683
+ addUniqueItem(this.children, child);
1684
+ this.isDirty = true;
1685
+ };
1686
+ FlatTree.prototype.remove = function (child) {
1687
+ removeItem(this.children, child);
1688
+ this.isDirty = true;
1689
+ };
1690
+ FlatTree.prototype.forEach = function (callback) {
1691
+ this.isDirty && this.children.sort(compareByDepth);
1692
+ this.isDirty = false;
1693
+ this.children.forEach(callback);
1694
+ };
1695
+ return FlatTree;
1696
+ }());
1697
+
1102
1698
  /**
1103
1699
  * If the provided value is a MotionValue, this returns the actual value, otherwise just the value itself
1104
1700
  *
@@ -1113,6 +1709,11 @@ function resolveMotionValue(value) {
1113
1709
  : unwrappedValue;
1114
1710
  }
1115
1711
 
1712
+ /**
1713
+ * We use 1000 as the animation target as 0-1000 maps better to pixels than 0-1
1714
+ * which has a noticeable difference in spring animations
1715
+ */
1716
+ var animationTarget = 1000;
1116
1717
  /**
1117
1718
  * This should only ever be modified on the client otherwise it'll
1118
1719
  * persist through server requests. If we need instanced states we
@@ -1130,450 +1731,1492 @@ var globalProjectionState = {
1130
1731
  */
1131
1732
  hasEverUpdated: false,
1132
1733
  };
1133
-
1134
- var id = 1;
1135
- function useProjectionId() {
1136
- return useConstant(function () {
1137
- if (globalProjectionState.hasEverUpdated) {
1138
- return id++;
1734
+ function createProjectionNode(_a) {
1735
+ var attachResizeListener = _a.attachResizeListener, defaultParent = _a.defaultParent, measureScroll = _a.measureScroll, resetTransform = _a.resetTransform;
1736
+ return /** @class */ (function () {
1737
+ function ProjectionNode(id, latestValues, parent) {
1738
+ var _this = this;
1739
+ if (latestValues === void 0) { latestValues = {}; }
1740
+ if (parent === void 0) { parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent(); }
1741
+ /**
1742
+ * A Set containing all this component's children. This is used to iterate
1743
+ * through the children.
1744
+ *
1745
+ * TODO: This could be faster to iterate as a flat array stored on the root node.
1746
+ */
1747
+ this.children = new Set();
1748
+ /**
1749
+ * Options for the node. We use this to configure what kind of layout animations
1750
+ * we should perform (if any).
1751
+ */
1752
+ this.options = {};
1753
+ /**
1754
+ * We use this to detect when its safe to shut down part of a projection tree.
1755
+ * We have to keep projecting children for scale correction and relative projection
1756
+ * until all their parents stop performing layout animations.
1757
+ */
1758
+ this.isTreeAnimating = false;
1759
+ this.isAnimationBlocked = false;
1760
+ /**
1761
+ * Flag to true if we think this layout has been changed. We can't always know this,
1762
+ * currently we set it to true every time a component renders, or if it has a layoutDependency
1763
+ * if that has changed between renders. Additionally, components can be grouped by LayoutGroup
1764
+ * and if one node is dirtied, they all are.
1765
+ */
1766
+ this.isLayoutDirty = false;
1767
+ /**
1768
+ * Block layout updates for instant layout transitions throughout the tree.
1769
+ */
1770
+ this.updateManuallyBlocked = false;
1771
+ this.updateBlockedByResize = false;
1772
+ /**
1773
+ * Set to true between the start of the first `willUpdate` call and the end of the `didUpdate`
1774
+ * call.
1775
+ */
1776
+ this.isUpdating = false;
1777
+ /**
1778
+ * If this is an SVG element we currently disable projection transforms
1779
+ */
1780
+ this.isSVG = false;
1781
+ /**
1782
+ * Flag to true (during promotion) if a node doing an instant layout transition needs to reset
1783
+ * its projection styles.
1784
+ */
1785
+ this.needsReset = false;
1786
+ /**
1787
+ * Flags whether this node should have its transform reset prior to measuring.
1788
+ */
1789
+ this.shouldResetTransform = false;
1790
+ /**
1791
+ * An object representing the calculated contextual/accumulated/tree scale.
1792
+ * This will be used to scale calculcated projection transforms, as these are
1793
+ * calculated in screen-space but need to be scaled for elements to actually
1794
+ * make it to their calculated destinations.
1795
+ *
1796
+ * TODO: Lazy-init
1797
+ */
1798
+ this.treeScale = { x: 1, y: 1 };
1799
+ /**
1800
+ *
1801
+ */
1802
+ this.eventHandlers = new Map();
1803
+ // Note: Currently only running on root node
1804
+ this.potentialNodes = new Map();
1805
+ this.checkUpdateFailed = function () {
1806
+ if (_this.isUpdating) {
1807
+ _this.isUpdating = false;
1808
+ _this.clearAllSnapshots();
1809
+ }
1810
+ };
1811
+ this.updateProjection = function () {
1812
+ _this.nodes.forEach(resolveTargetDelta);
1813
+ _this.nodes.forEach(calcProjection);
1814
+ };
1815
+ this.hasProjected = false;
1816
+ this.isVisible = true;
1817
+ /**
1818
+ * Animation
1819
+ */
1820
+ this.animationProgress = 0;
1821
+ /**
1822
+ * Shared layout
1823
+ */
1824
+ // TODO Only running on root node
1825
+ this.sharedNodes = new Map();
1826
+ this.id = id;
1827
+ this.latestValues = latestValues;
1828
+ this.root = parent ? parent.root || parent : this;
1829
+ this.path = parent ? tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(parent.path), false), [parent], false) : [];
1830
+ this.parent = parent;
1831
+ this.depth = parent ? parent.depth + 1 : 0;
1832
+ id && this.root.registerPotentialNode(id, this);
1833
+ for (var i = 0; i < this.path.length; i++) {
1834
+ this.path[i].shouldResetTransform = true;
1835
+ }
1836
+ if (this.root === this)
1837
+ this.nodes = new FlatTree();
1139
1838
  }
1140
- });
1141
- }
1142
-
1143
- /**
1144
- * @internal
1145
- */
1146
- var LayoutGroupContext = React.createContext({});
1147
-
1148
- /**
1149
- * @internal
1150
- */
1151
- var SwitchLayoutGroupContext = React.createContext({});
1152
-
1153
- function useProjection(projectionId, _a, visualElement, ProjectionNodeConstructor) {
1154
- var _b;
1155
- var layoutId = _a.layoutId, layout = _a.layout, drag = _a.drag, dragConstraints = _a.dragConstraints, layoutScroll = _a.layoutScroll;
1156
- var initialPromotionConfig = React.useContext(SwitchLayoutGroupContext);
1157
- if (!ProjectionNodeConstructor ||
1158
- !visualElement ||
1159
- (visualElement === null || visualElement === void 0 ? void 0 : visualElement.projection)) {
1160
- return;
1161
- }
1162
- visualElement.projection = new ProjectionNodeConstructor(projectionId, visualElement.getLatestValues(), (_b = visualElement.parent) === null || _b === void 0 ? void 0 : _b.projection);
1163
- visualElement.projection.setOptions({
1164
- layoutId: layoutId,
1165
- layout: layout,
1166
- alwaysMeasureLayout: Boolean(drag) || (dragConstraints && isRefObject(dragConstraints)),
1167
- visualElement: visualElement,
1168
- scheduleRender: function () { return visualElement.scheduleRender(); },
1839
+ ProjectionNode.prototype.addEventListener = function (name, handler) {
1840
+ if (!this.eventHandlers.has(name)) {
1841
+ this.eventHandlers.set(name, new SubscriptionManager());
1842
+ }
1843
+ return this.eventHandlers.get(name).add(handler);
1844
+ };
1845
+ ProjectionNode.prototype.notifyListeners = function (name) {
1846
+ var args = [];
1847
+ for (var _i = 1; _i < arguments.length; _i++) {
1848
+ args[_i - 1] = arguments[_i];
1849
+ }
1850
+ var subscriptionManager = this.eventHandlers.get(name);
1851
+ subscriptionManager === null || subscriptionManager === void 0 ? void 0 : subscriptionManager.notify.apply(subscriptionManager, tslib.__spreadArray([], tslib.__read(args), false));
1852
+ };
1853
+ ProjectionNode.prototype.hasListeners = function (name) {
1854
+ return this.eventHandlers.has(name);
1855
+ };
1856
+ ProjectionNode.prototype.registerPotentialNode = function (id, node) {
1857
+ this.potentialNodes.set(id, node);
1858
+ };
1169
1859
  /**
1170
- * TODO: Update options in an effect. This could be tricky as it'll be too late
1171
- * to update by the time layout animations run.
1172
- * We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
1173
- * ensuring it gets called if there's no potential layout animations.
1174
- *
1860
+ * Lifecycles
1175
1861
  */
1176
- animationType: typeof layout === "string" ? layout : "both",
1177
- initialPromotionConfig: initialPromotionConfig,
1178
- layoutScroll: layoutScroll,
1179
- });
1180
- }
1181
-
1182
- var VisualElementHandler = /** @class */ (function (_super) {
1183
- tslib.__extends(VisualElementHandler, _super);
1184
- function VisualElementHandler() {
1185
- return _super !== null && _super.apply(this, arguments) || this;
1186
- }
1187
- /**
1188
- * Update visual element props as soon as we know this update is going to be commited.
1189
- */
1190
- VisualElementHandler.prototype.getSnapshotBeforeUpdate = function () {
1191
- this.updateProps();
1192
- return null;
1193
- };
1194
- VisualElementHandler.prototype.componentDidUpdate = function () { };
1195
- VisualElementHandler.prototype.updateProps = function () {
1196
- var _a = this.props, visualElement = _a.visualElement, props = _a.props;
1197
- if (visualElement)
1198
- visualElement.setProps(props);
1199
- };
1200
- VisualElementHandler.prototype.render = function () {
1201
- return this.props.children;
1202
- };
1203
- return VisualElementHandler;
1204
- }(React__default["default"].Component));
1205
-
1206
- /**
1207
- * Create a `motion` component.
1208
- *
1209
- * This function accepts a Component argument, which can be either a string (ie "div"
1210
- * for `motion.div`), or an actual React component.
1211
- *
1212
- * Alongside this is a config option which provides a way of rendering the provided
1213
- * component "offline", or outside the React render cycle.
1214
- *
1215
- * @internal
1216
- */
1217
- function createMotionComponent(_a) {
1218
- var preloadedFeatures = _a.preloadedFeatures, createVisualElement = _a.createVisualElement, projectionNodeConstructor = _a.projectionNodeConstructor, useRender = _a.useRender, useVisualState = _a.useVisualState, Component = _a.Component;
1219
- preloadedFeatures && loadFeatures(preloadedFeatures);
1220
- function MotionComponent(props, externalRef) {
1221
- var layoutId = useLayoutId(props);
1222
- props = tslib.__assign(tslib.__assign({}, props), { layoutId: layoutId });
1862
+ ProjectionNode.prototype.mount = function (instance, isLayoutDirty) {
1863
+ var _this = this;
1864
+ var _a;
1865
+ if (isLayoutDirty === void 0) { isLayoutDirty = false; }
1866
+ if (this.instance)
1867
+ return;
1868
+ this.isSVG =
1869
+ instance instanceof SVGElement && instance.tagName !== "svg";
1870
+ this.instance = instance;
1871
+ var _b = this.options, layoutId = _b.layoutId, layout = _b.layout, visualElement = _b.visualElement;
1872
+ if (visualElement && !visualElement.getInstance()) {
1873
+ visualElement.mount(instance);
1874
+ }
1875
+ this.root.nodes.add(this);
1876
+ (_a = this.parent) === null || _a === void 0 ? void 0 : _a.children.add(this);
1877
+ this.id && this.root.potentialNodes.delete(this.id);
1878
+ if (isLayoutDirty && (layout || layoutId)) {
1879
+ this.isLayoutDirty = true;
1880
+ }
1881
+ if (attachResizeListener) {
1882
+ var unblockTimeout_1;
1883
+ var resizeUnblockUpdate_1 = function () {
1884
+ return (_this.root.updateBlockedByResize = false);
1885
+ };
1886
+ attachResizeListener(instance, function () {
1887
+ _this.root.updateBlockedByResize = true;
1888
+ clearTimeout(unblockTimeout_1);
1889
+ unblockTimeout_1 = setTimeout(resizeUnblockUpdate_1, 250);
1890
+ if (globalProjectionState.hasAnimatedSinceResize) {
1891
+ globalProjectionState.hasAnimatedSinceResize = false;
1892
+ _this.nodes.forEach(finishAnimation);
1893
+ }
1894
+ });
1895
+ }
1896
+ if (layoutId) {
1897
+ this.root.registerSharedNode(layoutId, this);
1898
+ }
1899
+ // Only register the handler if it requires layout animation
1900
+ if (this.options.animate !== false &&
1901
+ visualElement &&
1902
+ (layoutId || layout)) {
1903
+ this.addEventListener("didUpdate", function (_a) {
1904
+ var _b, _c, _d, _e, _f;
1905
+ var delta = _a.delta, hasLayoutChanged = _a.hasLayoutChanged, hasRelativeTargetChanged = _a.hasRelativeTargetChanged, newLayout = _a.layout;
1906
+ if (_this.isTreeAnimationBlocked()) {
1907
+ _this.target = undefined;
1908
+ _this.relativeTarget = undefined;
1909
+ return;
1910
+ }
1911
+ // TODO: Check here if an animation exists
1912
+ var layoutTransition = (_c = (_b = _this.options.transition) !== null && _b !== void 0 ? _b : visualElement.getDefaultTransition()) !== null && _c !== void 0 ? _c : defaultLayoutTransition;
1913
+ var onLayoutAnimationComplete = visualElement.getProps().onLayoutAnimationComplete;
1914
+ /**
1915
+ * The target layout of the element might stay the same,
1916
+ * but its position relative to its parent has changed.
1917
+ */
1918
+ var targetChanged = !_this.targetLayout ||
1919
+ !boxEquals(_this.targetLayout, newLayout) ||
1920
+ hasRelativeTargetChanged;
1921
+ /**
1922
+ * If the layout hasn't seemed to have changed, it might be that the
1923
+ * element is visually in the same place in the document but its position
1924
+ * relative to its parent has indeed changed. So here we check for that.
1925
+ */
1926
+ var hasOnlyRelativeTargetChanged = !hasLayoutChanged && hasRelativeTargetChanged;
1927
+ if (((_d = _this.resumeFrom) === null || _d === void 0 ? void 0 : _d.instance) ||
1928
+ hasOnlyRelativeTargetChanged ||
1929
+ (hasLayoutChanged &&
1930
+ (targetChanged || !_this.currentAnimation))) {
1931
+ if (_this.resumeFrom) {
1932
+ _this.resumingFrom = _this.resumeFrom;
1933
+ _this.resumingFrom.resumingFrom = undefined;
1934
+ }
1935
+ _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
1936
+ _this.startAnimation(tslib.__assign(tslib.__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
1937
+ }
1938
+ else {
1939
+ _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
1940
+ }
1941
+ _this.targetLayout = newLayout;
1942
+ });
1943
+ }
1944
+ };
1945
+ ProjectionNode.prototype.unmount = function () {
1946
+ var _a, _b;
1947
+ this.options.layoutId && this.willUpdate();
1948
+ this.root.nodes.remove(this);
1949
+ (_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.remove(this);
1950
+ (_b = this.parent) === null || _b === void 0 ? void 0 : _b.children.delete(this);
1951
+ this.instance = undefined;
1952
+ sync.cancelSync.preRender(this.updateProjection);
1953
+ };
1954
+ // only on the root
1955
+ ProjectionNode.prototype.blockUpdate = function () {
1956
+ this.updateManuallyBlocked = true;
1957
+ };
1958
+ ProjectionNode.prototype.unblockUpdate = function () {
1959
+ this.updateManuallyBlocked = false;
1960
+ };
1961
+ ProjectionNode.prototype.isUpdateBlocked = function () {
1962
+ return this.updateManuallyBlocked || this.updateBlockedByResize;
1963
+ };
1964
+ ProjectionNode.prototype.isTreeAnimationBlocked = function () {
1965
+ var _a;
1966
+ return (this.isAnimationBlocked ||
1967
+ ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isTreeAnimationBlocked()) ||
1968
+ false);
1969
+ };
1970
+ // Note: currently only running on root node
1971
+ ProjectionNode.prototype.startUpdate = function () {
1972
+ var _a;
1973
+ if (this.isUpdateBlocked())
1974
+ return;
1975
+ this.isUpdating = true;
1976
+ (_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
1977
+ };
1978
+ ProjectionNode.prototype.willUpdate = function (shouldNotifyListeners) {
1979
+ var _a, _b, _c;
1980
+ if (shouldNotifyListeners === void 0) { shouldNotifyListeners = true; }
1981
+ if (this.root.isUpdateBlocked()) {
1982
+ (_b = (_a = this.options).onExitComplete) === null || _b === void 0 ? void 0 : _b.call(_a);
1983
+ return;
1984
+ }
1985
+ !this.root.isUpdating && this.root.startUpdate();
1986
+ if (this.isLayoutDirty)
1987
+ return;
1988
+ this.isLayoutDirty = true;
1989
+ for (var i = 0; i < this.path.length; i++) {
1990
+ var node = this.path[i];
1991
+ node.shouldResetTransform = true;
1992
+ /**
1993
+ * TODO: Check we haven't updated the scroll
1994
+ * since the last didUpdate
1995
+ */
1996
+ node.updateScroll();
1997
+ }
1998
+ var _d = this.options, layoutId = _d.layoutId, layout = _d.layout;
1999
+ if (layoutId === undefined && !layout)
2000
+ return;
2001
+ var transformTemplate = (_c = this.options.visualElement) === null || _c === void 0 ? void 0 : _c.getProps().transformTemplate;
2002
+ this.prevTransformTemplateValue = transformTemplate === null || transformTemplate === void 0 ? void 0 : transformTemplate(this.latestValues, "");
2003
+ this.updateSnapshot();
2004
+ shouldNotifyListeners && this.notifyListeners("willUpdate");
2005
+ };
2006
+ // Note: Currently only running on root node
2007
+ ProjectionNode.prototype.didUpdate = function () {
2008
+ var updateWasBlocked = this.isUpdateBlocked();
2009
+ // When doing an instant transition, we skip the layout update,
2010
+ // but should still clean up the measurements so that the next
2011
+ // snapshot could be taken correctly.
2012
+ if (updateWasBlocked) {
2013
+ this.unblockUpdate();
2014
+ this.clearAllSnapshots();
2015
+ this.nodes.forEach(clearMeasurements);
2016
+ return;
2017
+ }
2018
+ if (!this.isUpdating)
2019
+ return;
2020
+ this.isUpdating = false;
2021
+ /**
2022
+ * Search for and mount newly-added projection elements.
2023
+ *
2024
+ * TODO: Every time a new component is rendered we could search up the tree for
2025
+ * the closest mounted node and query from there rather than document.
2026
+ */
2027
+ if (this.potentialNodes.size) {
2028
+ this.potentialNodes.forEach(mountNodeEarly);
2029
+ this.potentialNodes.clear();
2030
+ }
2031
+ /**
2032
+ * Write
2033
+ */
2034
+ this.nodes.forEach(resetTransformStyle);
2035
+ /**
2036
+ * Read ==================
2037
+ */
2038
+ // Update layout measurements of updated children
2039
+ this.nodes.forEach(updateLayout);
2040
+ /**
2041
+ * Write
2042
+ */
2043
+ // Notify listeners that the layout is updated
2044
+ this.nodes.forEach(notifyLayoutUpdate);
2045
+ this.clearAllSnapshots();
2046
+ // Flush any scheduled updates
2047
+ sync.flushSync.update();
2048
+ sync.flushSync.preRender();
2049
+ sync.flushSync.render();
2050
+ };
2051
+ ProjectionNode.prototype.clearAllSnapshots = function () {
2052
+ this.nodes.forEach(clearSnapshot);
2053
+ this.sharedNodes.forEach(removeLeadSnapshots);
2054
+ };
2055
+ ProjectionNode.prototype.scheduleUpdateProjection = function () {
2056
+ sync__default["default"].preRender(this.updateProjection, false, true);
2057
+ };
2058
+ ProjectionNode.prototype.scheduleCheckAfterUnmount = function () {
2059
+ var _this = this;
2060
+ /**
2061
+ * If the unmounting node is in a layoutGroup and did trigger a willUpdate,
2062
+ * we manually call didUpdate to give a chance to the siblings to animate.
2063
+ * Otherwise, cleanup all snapshots to prevents future nodes from reusing them.
2064
+ */
2065
+ sync__default["default"].postRender(function () {
2066
+ if (_this.isLayoutDirty) {
2067
+ _this.root.didUpdate();
2068
+ }
2069
+ else {
2070
+ _this.root.checkUpdateFailed();
2071
+ }
2072
+ });
2073
+ };
1223
2074
  /**
1224
- * If we're rendering in a static environment, we only visually update the component
1225
- * as a result of a React-rerender rather than interactions or animations. This
1226
- * means we don't need to load additional memory structures like VisualElement,
1227
- * or any gesture/animation features.
2075
+ * Update measurements
1228
2076
  */
1229
- var config = React.useContext(MotionConfigContext);
1230
- var features = null;
1231
- var context = useCreateMotionContext(props);
2077
+ ProjectionNode.prototype.updateSnapshot = function () {
2078
+ if (this.snapshot || !this.instance)
2079
+ return;
2080
+ var measured = this.measure();
2081
+ var layout = this.removeTransform(this.removeElementScroll(measured));
2082
+ roundBox(layout);
2083
+ this.snapshot = {
2084
+ measured: measured,
2085
+ layout: layout,
2086
+ latestValues: {},
2087
+ };
2088
+ };
2089
+ ProjectionNode.prototype.updateLayout = function () {
2090
+ var _a;
2091
+ if (!this.instance)
2092
+ return;
2093
+ // TODO: Incorporate into a forwarded scroll offset
2094
+ this.updateScroll();
2095
+ if (!(this.options.alwaysMeasureLayout && this.isLead()) &&
2096
+ !this.isLayoutDirty) {
2097
+ return;
2098
+ }
2099
+ /**
2100
+ * When a node is mounted, it simply resumes from the prevLead's
2101
+ * snapshot instead of taking a new one, but the ancestors scroll
2102
+ * might have updated while the prevLead is unmounted. We need to
2103
+ * update the scroll again to make sure the layout we measure is
2104
+ * up to date.
2105
+ */
2106
+ if (this.resumeFrom && !this.resumeFrom.instance) {
2107
+ for (var i = 0; i < this.path.length; i++) {
2108
+ var node = this.path[i];
2109
+ node.updateScroll();
2110
+ }
2111
+ }
2112
+ var measured = this.measure();
2113
+ roundBox(measured);
2114
+ var prevLayout = this.layout;
2115
+ this.layout = {
2116
+ measured: measured,
2117
+ actual: this.removeElementScroll(measured),
2118
+ };
2119
+ this.layoutCorrected = createBox();
2120
+ this.isLayoutDirty = false;
2121
+ this.projectionDelta = undefined;
2122
+ this.notifyListeners("measure");
2123
+ (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notifyLayoutMeasure(this.layout.actual, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.actual);
2124
+ };
2125
+ ProjectionNode.prototype.updateScroll = function () {
2126
+ if (this.options.layoutScroll && this.instance) {
2127
+ this.scroll = measureScroll(this.instance);
2128
+ }
2129
+ };
2130
+ ProjectionNode.prototype.resetTransform = function () {
2131
+ var _a;
2132
+ if (!resetTransform)
2133
+ return;
2134
+ var isResetRequested = this.isLayoutDirty || this.shouldResetTransform;
2135
+ var hasProjection = this.projectionDelta && !isDeltaZero(this.projectionDelta);
2136
+ var transformTemplate = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.getProps().transformTemplate;
2137
+ var transformTemplateValue = transformTemplate === null || transformTemplate === void 0 ? void 0 : transformTemplate(this.latestValues, "");
2138
+ var transformTemplateHasChanged = transformTemplateValue !== this.prevTransformTemplateValue;
2139
+ if (isResetRequested &&
2140
+ (hasProjection ||
2141
+ hasTransform(this.latestValues) ||
2142
+ transformTemplateHasChanged)) {
2143
+ resetTransform(this.instance, transformTemplateValue);
2144
+ this.shouldResetTransform = false;
2145
+ this.scheduleRender();
2146
+ }
2147
+ };
2148
+ ProjectionNode.prototype.measure = function () {
2149
+ var visualElement = this.options.visualElement;
2150
+ if (!visualElement)
2151
+ return createBox();
2152
+ var box = visualElement.measureViewportBox();
2153
+ // Remove viewport scroll to give page-relative coordinates
2154
+ var scroll = this.root.scroll;
2155
+ if (scroll) {
2156
+ translateAxis(box.x, scroll.x);
2157
+ translateAxis(box.y, scroll.y);
2158
+ }
2159
+ return box;
2160
+ };
2161
+ ProjectionNode.prototype.removeElementScroll = function (box) {
2162
+ var boxWithoutScroll = createBox();
2163
+ copyBoxInto(boxWithoutScroll, box);
2164
+ /**
2165
+ * Performance TODO: Keep a cumulative scroll offset down the tree
2166
+ * rather than loop back up the path.
2167
+ */
2168
+ for (var i = 0; i < this.path.length; i++) {
2169
+ var node = this.path[i];
2170
+ var scroll_1 = node.scroll, options = node.options;
2171
+ if (node !== this.root && scroll_1 && options.layoutScroll) {
2172
+ translateAxis(boxWithoutScroll.x, scroll_1.x);
2173
+ translateAxis(boxWithoutScroll.y, scroll_1.y);
2174
+ }
2175
+ }
2176
+ return boxWithoutScroll;
2177
+ };
2178
+ ProjectionNode.prototype.applyTransform = function (box, transformOnly) {
2179
+ if (transformOnly === void 0) { transformOnly = false; }
2180
+ var withTransforms = createBox();
2181
+ copyBoxInto(withTransforms, box);
2182
+ for (var i = 0; i < this.path.length; i++) {
2183
+ var node = this.path[i];
2184
+ if (!transformOnly &&
2185
+ node.options.layoutScroll &&
2186
+ node.scroll &&
2187
+ node !== node.root) {
2188
+ transformBox(withTransforms, {
2189
+ x: -node.scroll.x,
2190
+ y: -node.scroll.y,
2191
+ });
2192
+ }
2193
+ if (!hasTransform(node.latestValues))
2194
+ continue;
2195
+ transformBox(withTransforms, node.latestValues);
2196
+ }
2197
+ if (hasTransform(this.latestValues)) {
2198
+ transformBox(withTransforms, this.latestValues);
2199
+ }
2200
+ return withTransforms;
2201
+ };
2202
+ ProjectionNode.prototype.removeTransform = function (box) {
2203
+ var _a;
2204
+ var boxWithoutTransform = createBox();
2205
+ copyBoxInto(boxWithoutTransform, box);
2206
+ for (var i = 0; i < this.path.length; i++) {
2207
+ var node = this.path[i];
2208
+ if (!node.instance)
2209
+ continue;
2210
+ if (!hasTransform(node.latestValues))
2211
+ continue;
2212
+ hasScale(node.latestValues) && node.updateSnapshot();
2213
+ var sourceBox = createBox();
2214
+ var nodeBox = node.measure();
2215
+ copyBoxInto(sourceBox, nodeBox);
2216
+ removeBoxTransforms(boxWithoutTransform, node.latestValues, (_a = node.snapshot) === null || _a === void 0 ? void 0 : _a.layout, sourceBox);
2217
+ }
2218
+ if (hasTransform(this.latestValues)) {
2219
+ removeBoxTransforms(boxWithoutTransform, this.latestValues);
2220
+ }
2221
+ return boxWithoutTransform;
2222
+ };
1232
2223
  /**
1233
- * Create a unique projection ID for this component. If a new component is added
1234
- * during a layout animation we'll use this to query the DOM and hydrate its ref early, allowing
1235
- * us to measure it as soon as any layout effect flushes pending layout animations.
1236
2224
  *
1237
- * Performance note: It'd be better not to have to search the DOM for these elements.
1238
- * For newly-entering components it could be enough to only correct treeScale, in which
1239
- * case we could mount in a scale-correction mode. This wouldn't be enough for
1240
- * shared element transitions however. Perhaps for those we could revert to a root node
1241
- * that gets forceRendered and layout animations are triggered on its layout effect.
1242
2225
  */
1243
- var projectionId = useProjectionId();
2226
+ ProjectionNode.prototype.setTargetDelta = function (delta) {
2227
+ this.targetDelta = delta;
2228
+ this.root.scheduleUpdateProjection();
2229
+ };
2230
+ ProjectionNode.prototype.setOptions = function (options) {
2231
+ var _a;
2232
+ this.options = tslib.__assign(tslib.__assign(tslib.__assign({}, this.options), options), { crossfade: (_a = options.crossfade) !== null && _a !== void 0 ? _a : true });
2233
+ };
2234
+ ProjectionNode.prototype.clearMeasurements = function () {
2235
+ this.scroll = undefined;
2236
+ this.layout = undefined;
2237
+ this.snapshot = undefined;
2238
+ this.prevTransformTemplateValue = undefined;
2239
+ this.targetDelta = undefined;
2240
+ this.target = undefined;
2241
+ this.isLayoutDirty = false;
2242
+ };
1244
2243
  /**
1245
- *
2244
+ * Frame calculations
1246
2245
  */
1247
- var visualState = useVisualState(props, config.isStatic);
1248
- if (!config.isStatic && isBrowser) {
2246
+ ProjectionNode.prototype.resolveTargetDelta = function () {
2247
+ var _a;
2248
+ var _b = this.options, layout = _b.layout, layoutId = _b.layoutId;
1249
2249
  /**
1250
- * Create a VisualElement for this component. A VisualElement provides a common
1251
- * interface to renderer-specific APIs (ie DOM/Three.js etc) as well as
1252
- * providing a way of rendering to these APIs outside of the React render loop
1253
- * for more performant animations and interactions
2250
+ * If we have no layout, we can't perform projection, so early return
1254
2251
  */
1255
- context.visualElement = useVisualElement(Component, visualState, tslib.__assign(tslib.__assign({}, config), props), createVisualElement);
1256
- useProjection(projectionId, props, context.visualElement, projectionNodeConstructor ||
1257
- featureDefinitions.projectionNodeConstructor);
2252
+ if (!this.layout || !(layout || layoutId))
2253
+ return;
1258
2254
  /**
1259
- * Load Motion gesture and animation features. These are rendered as renderless
1260
- * components so each feature can optionally make use of React lifecycle methods.
2255
+ * If we don't have a targetDelta but do have a layout, we can attempt to resolve
2256
+ * a relativeParent. This will allow a component to perform scale correction
2257
+ * even if no animation has started.
1261
2258
  */
1262
- features = useFeatures(props, context.visualElement, preloadedFeatures);
1263
- }
1264
- /**
1265
- * The mount order and hierarchy is specific to ensure our element ref
1266
- * is hydrated by the time features fire their effects.
1267
- */
1268
- return (React__namespace.createElement(VisualElementHandler, { visualElement: context.visualElement, props: tslib.__assign(tslib.__assign({}, config), props) },
1269
- features,
1270
- React__namespace.createElement(MotionContext.Provider, { value: context }, useRender(Component, props, projectionId, useMotionRef(visualState, context.visualElement, externalRef), visualState, config.isStatic, context.visualElement))));
1271
- }
1272
- return React.forwardRef(MotionComponent);
1273
- }
1274
- function useLayoutId(_a) {
1275
- var _b;
1276
- var layoutId = _a.layoutId;
1277
- var layoutGroupId = (_b = React.useContext(LayoutGroupContext)) === null || _b === void 0 ? void 0 : _b.id;
1278
- return layoutGroupId && layoutId !== undefined
1279
- ? layoutGroupId + "-" + layoutId
1280
- : layoutId;
1281
- }
1282
-
1283
- function isAnimationControls(v) {
1284
- return typeof v === "object" && typeof v.start === "function";
1285
- }
1286
-
1287
- /**
1288
- * When a component is the child of `AnimatePresence`, it can use `usePresence`
1289
- * to access information about whether it's still present in the React tree.
1290
- *
1291
- * ```jsx
1292
- * import { usePresence } from "framer-motion"
1293
- *
1294
- * export const Component = () => {
1295
- * const [isPresent, safeToRemove] = usePresence()
1296
- *
1297
- * useEffect(() => {
1298
- * !isPresent && setTimeout(safeToRemove, 1000)
1299
- * }, [isPresent])
1300
- *
1301
- * return <div />
1302
- * }
1303
- * ```
1304
- *
1305
- * If `isPresent` is `false`, it means that a component has been removed the tree, but
1306
- * `AnimatePresence` won't really remove it until `safeToRemove` has been called.
1307
- *
1308
- * @public
1309
- */
1310
- function usePresence() {
1311
- var context = React.useContext(PresenceContext);
1312
- if (context === null)
1313
- return [true, null];
1314
- var isPresent = context.isPresent, onExitComplete = context.onExitComplete, register = context.register;
1315
- // It's safe to call the following hooks conditionally (after an early return) because the context will always
1316
- // either be null or non-null for the lifespan of the component.
1317
- // Replace with useOpaqueId when released in React
1318
- var id = useUniqueId();
1319
- React.useEffect(function () { return register(id); }, []);
1320
- var safeToRemove = function () { return onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete(id); };
1321
- return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
1322
- }
1323
- var counter = 0;
1324
- var incrementId = function () { return counter++; };
1325
- var useUniqueId = function () { return useConstant(incrementId); };
1326
-
1327
- function shallowCompare(next, prev) {
1328
- if (!Array.isArray(prev))
1329
- return false;
1330
- var prevLength = prev.length;
1331
- if (prevLength !== next.length)
1332
- return false;
1333
- for (var i = 0; i < prevLength; i++) {
1334
- if (prev[i] !== next[i])
1335
- return false;
2259
+ // TODO If this is unsuccessful this currently happens every frame
2260
+ if (!this.targetDelta && !this.relativeTarget) {
2261
+ // TODO: This is a semi-repetition of further down this function, make DRY
2262
+ this.relativeParent = this.getClosestProjectingParent();
2263
+ if (this.relativeParent && this.relativeParent.layout) {
2264
+ this.relativeTarget = createBox();
2265
+ this.relativeTargetOrigin = createBox();
2266
+ calcRelativePosition(this.relativeTargetOrigin, this.layout.actual, this.relativeParent.layout.actual);
2267
+ copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
2268
+ }
2269
+ }
2270
+ /**
2271
+ * If we have no relative target or no target delta our target isn't valid
2272
+ * for this frame.
2273
+ */
2274
+ if (!this.relativeTarget && !this.targetDelta)
2275
+ return;
2276
+ /**
2277
+ * Lazy-init target data structure
2278
+ */
2279
+ if (!this.target) {
2280
+ this.target = createBox();
2281
+ this.targetWithTransforms = createBox();
2282
+ }
2283
+ /**
2284
+ * If we've got a relative box for this component, resolve it into a target relative to the parent.
2285
+ */
2286
+ if (this.relativeTarget &&
2287
+ this.relativeTargetOrigin &&
2288
+ ((_a = this.relativeParent) === null || _a === void 0 ? void 0 : _a.target)) {
2289
+ calcRelativeBox(this.target, this.relativeTarget, this.relativeParent.target);
2290
+ /**
2291
+ * If we've only got a targetDelta, resolve it into a target
2292
+ */
2293
+ }
2294
+ else if (this.targetDelta) {
2295
+ if (Boolean(this.resumingFrom)) {
2296
+ // TODO: This is creating a new object every frame
2297
+ this.target = this.applyTransform(this.layout.actual);
2298
+ }
2299
+ else {
2300
+ copyBoxInto(this.target, this.layout.actual);
2301
+ }
2302
+ applyBoxDelta(this.target, this.targetDelta);
2303
+ }
2304
+ else {
2305
+ /**
2306
+ * If no target, use own layout as target
2307
+ */
2308
+ copyBoxInto(this.target, this.layout.actual);
2309
+ }
2310
+ /**
2311
+ * If we've been told to attempt to resolve a relative target, do so.
2312
+ */
2313
+ if (this.attemptToResolveRelativeTarget) {
2314
+ this.attemptToResolveRelativeTarget = false;
2315
+ this.relativeParent = this.getClosestProjectingParent();
2316
+ if (this.relativeParent &&
2317
+ Boolean(this.relativeParent.resumingFrom) ===
2318
+ Boolean(this.resumingFrom) &&
2319
+ !this.relativeParent.options.layoutScroll &&
2320
+ this.relativeParent.target) {
2321
+ this.relativeTarget = createBox();
2322
+ this.relativeTargetOrigin = createBox();
2323
+ calcRelativePosition(this.relativeTargetOrigin, this.target, this.relativeParent.target);
2324
+ copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
2325
+ }
2326
+ }
2327
+ };
2328
+ ProjectionNode.prototype.getClosestProjectingParent = function () {
2329
+ if (!this.parent || hasTransform(this.parent.latestValues))
2330
+ return undefined;
2331
+ if ((this.parent.relativeTarget || this.parent.targetDelta) &&
2332
+ this.parent.layout) {
2333
+ return this.parent;
2334
+ }
2335
+ else {
2336
+ return this.parent.getClosestProjectingParent();
2337
+ }
2338
+ };
2339
+ ProjectionNode.prototype.calcProjection = function () {
2340
+ var _a;
2341
+ var _b = this.options, layout = _b.layout, layoutId = _b.layoutId;
2342
+ /**
2343
+ * If this section of the tree isn't animating we can
2344
+ * delete our target sources for the following frame.
2345
+ */
2346
+ this.isTreeAnimating = Boolean(((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isTreeAnimating) ||
2347
+ this.currentAnimation ||
2348
+ this.pendingAnimation);
2349
+ if (!this.isTreeAnimating) {
2350
+ this.targetDelta = this.relativeTarget = undefined;
2351
+ }
2352
+ if (!this.layout || !(layout || layoutId))
2353
+ return;
2354
+ var lead = this.getLead();
2355
+ /**
2356
+ * Reset the corrected box with the latest values from box, as we're then going
2357
+ * to perform mutative operations on it.
2358
+ */
2359
+ copyBoxInto(this.layoutCorrected, this.layout.actual);
2360
+ /**
2361
+ * Apply all the parent deltas to this box to produce the corrected box. This
2362
+ * is the layout box, as it will appear on screen as a result of the transforms of its parents.
2363
+ */
2364
+ applyTreeDeltas(this.layoutCorrected, this.treeScale, this.path, Boolean(this.resumingFrom) || this !== lead);
2365
+ var target = lead.target;
2366
+ if (!target)
2367
+ return;
2368
+ if (!this.projectionDelta) {
2369
+ this.projectionDelta = createDelta();
2370
+ this.projectionDeltaWithTransform = createDelta();
2371
+ }
2372
+ var prevTreeScaleX = this.treeScale.x;
2373
+ var prevTreeScaleY = this.treeScale.y;
2374
+ var prevProjectionTransform = this.projectionTransform;
2375
+ /**
2376
+ * Update the delta between the corrected box and the target box before user-set transforms were applied.
2377
+ * This will allow us to calculate the corrected borderRadius and boxShadow to compensate
2378
+ * for our layout reprojection, but still allow them to be scaled correctly by the user.
2379
+ * It might be that to simplify this we may want to accept that user-set scale is also corrected
2380
+ * and we wouldn't have to keep and calc both deltas, OR we could support a user setting
2381
+ * to allow people to choose whether these styles are corrected based on just the
2382
+ * layout reprojection or the final bounding box.
2383
+ */
2384
+ calcBoxDelta(this.projectionDelta, this.layoutCorrected, target, this.latestValues);
2385
+ this.projectionTransform = buildProjectionTransform(this.projectionDelta, this.treeScale);
2386
+ if (this.projectionTransform !== prevProjectionTransform ||
2387
+ this.treeScale.x !== prevTreeScaleX ||
2388
+ this.treeScale.y !== prevTreeScaleY) {
2389
+ this.hasProjected = true;
2390
+ this.scheduleRender();
2391
+ }
2392
+ };
2393
+ ProjectionNode.prototype.hide = function () {
2394
+ this.isVisible = false;
2395
+ // TODO: Schedule render
2396
+ };
2397
+ ProjectionNode.prototype.show = function () {
2398
+ this.isVisible = true;
2399
+ // TODO: Schedule render
2400
+ };
2401
+ ProjectionNode.prototype.scheduleRender = function (notifyAll) {
2402
+ var _a, _b, _c;
2403
+ if (notifyAll === void 0) { notifyAll = true; }
2404
+ (_b = (_a = this.options).scheduleRender) === null || _b === void 0 ? void 0 : _b.call(_a);
2405
+ notifyAll && ((_c = this.getStack()) === null || _c === void 0 ? void 0 : _c.scheduleRender());
2406
+ if (this.resumingFrom && !this.resumingFrom.instance) {
2407
+ this.resumingFrom = undefined;
2408
+ }
2409
+ };
2410
+ ProjectionNode.prototype.setAnimationOrigin = function (delta, hasOnlyRelativeTargetChanged) {
2411
+ var _this = this;
2412
+ var _a;
2413
+ if (hasOnlyRelativeTargetChanged === void 0) { hasOnlyRelativeTargetChanged = false; }
2414
+ var snapshot = this.snapshot;
2415
+ var snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
2416
+ var mixedValues = tslib.__assign({}, this.latestValues);
2417
+ var targetDelta = createDelta();
2418
+ this.relativeTarget = this.relativeTargetOrigin = undefined;
2419
+ this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
2420
+ var relativeLayout = createBox();
2421
+ var isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.isShared;
2422
+ var isOnlyMember = (((_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.members.length) || 0) <= 1;
2423
+ var shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
2424
+ !isOnlyMember &&
2425
+ this.options.crossfade === true &&
2426
+ !this.path.some(hasOpacityCrossfade));
2427
+ this.mixTargetDelta = function (latest) {
2428
+ var _a;
2429
+ var progress = latest / 1000;
2430
+ mixAxisDelta(targetDelta.x, delta.x, progress);
2431
+ mixAxisDelta(targetDelta.y, delta.y, progress);
2432
+ _this.setTargetDelta(targetDelta);
2433
+ if (_this.relativeTarget &&
2434
+ _this.relativeTargetOrigin &&
2435
+ _this.layout &&
2436
+ ((_a = _this.relativeParent) === null || _a === void 0 ? void 0 : _a.layout)) {
2437
+ calcRelativePosition(relativeLayout, _this.layout.actual, _this.relativeParent.layout.actual);
2438
+ mixBox(_this.relativeTarget, _this.relativeTargetOrigin, relativeLayout, progress);
2439
+ }
2440
+ if (isSharedLayoutAnimation) {
2441
+ _this.animationValues = mixedValues;
2442
+ mixValues(mixedValues, snapshotLatestValues, _this.latestValues, progress, shouldCrossfadeOpacity, isOnlyMember);
2443
+ }
2444
+ _this.root.scheduleUpdateProjection();
2445
+ _this.scheduleRender();
2446
+ };
2447
+ this.mixTargetDelta(0);
2448
+ };
2449
+ ProjectionNode.prototype.startAnimation = function (options) {
2450
+ var _this = this;
2451
+ var _a, _b;
2452
+ (_a = this.currentAnimation) === null || _a === void 0 ? void 0 : _a.stop();
2453
+ if (this.resumingFrom) {
2454
+ (_b = this.resumingFrom.currentAnimation) === null || _b === void 0 ? void 0 : _b.stop();
2455
+ }
2456
+ if (this.pendingAnimation) {
2457
+ sync.cancelSync.update(this.pendingAnimation);
2458
+ this.pendingAnimation = undefined;
2459
+ }
2460
+ /**
2461
+ * Start the animation in the next frame to have a frame with progress 0,
2462
+ * where the target is the same as when the animation started, so we can
2463
+ * calculate the relative positions correctly for instant transitions.
2464
+ */
2465
+ this.pendingAnimation = sync__default["default"].update(function () {
2466
+ globalProjectionState.hasAnimatedSinceResize = true;
2467
+ _this.currentAnimation = animate(0, animationTarget, tslib.__assign(tslib.__assign({}, options), { onUpdate: function (latest) {
2468
+ var _a;
2469
+ _this.mixTargetDelta(latest);
2470
+ (_a = options.onUpdate) === null || _a === void 0 ? void 0 : _a.call(options, latest);
2471
+ }, onComplete: function () {
2472
+ var _a;
2473
+ (_a = options.onComplete) === null || _a === void 0 ? void 0 : _a.call(options);
2474
+ _this.completeAnimation();
2475
+ } }));
2476
+ if (_this.resumingFrom) {
2477
+ _this.resumingFrom.currentAnimation = _this.currentAnimation;
2478
+ }
2479
+ _this.pendingAnimation = undefined;
2480
+ });
2481
+ };
2482
+ ProjectionNode.prototype.completeAnimation = function () {
2483
+ var _a;
2484
+ if (this.resumingFrom) {
2485
+ this.resumingFrom.currentAnimation = undefined;
2486
+ this.resumingFrom.preserveOpacity = undefined;
2487
+ }
2488
+ (_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.exitAnimationComplete();
2489
+ this.resumingFrom =
2490
+ this.currentAnimation =
2491
+ this.animationValues =
2492
+ undefined;
2493
+ };
2494
+ ProjectionNode.prototype.finishAnimation = function () {
2495
+ var _a;
2496
+ if (this.currentAnimation) {
2497
+ (_a = this.mixTargetDelta) === null || _a === void 0 ? void 0 : _a.call(this, animationTarget);
2498
+ this.currentAnimation.stop();
2499
+ }
2500
+ this.completeAnimation();
2501
+ };
2502
+ ProjectionNode.prototype.applyTransformsToTarget = function () {
2503
+ var _a = this.getLead(), targetWithTransforms = _a.targetWithTransforms, target = _a.target, layout = _a.layout, latestValues = _a.latestValues;
2504
+ if (!targetWithTransforms || !target || !layout)
2505
+ return;
2506
+ copyBoxInto(targetWithTransforms, target);
2507
+ /**
2508
+ * Apply the latest user-set transforms to the targetBox to produce the targetBoxFinal.
2509
+ * This is the final box that we will then project into by calculating a transform delta and
2510
+ * applying it to the corrected box.
2511
+ */
2512
+ transformBox(targetWithTransforms, latestValues);
2513
+ /**
2514
+ * Update the delta between the corrected box and the final target box, after
2515
+ * user-set transforms are applied to it. This will be used by the renderer to
2516
+ * create a transform style that will reproject the element from its actual layout
2517
+ * into the desired bounding box.
2518
+ */
2519
+ calcBoxDelta(this.projectionDeltaWithTransform, this.layoutCorrected, targetWithTransforms, latestValues);
2520
+ };
2521
+ ProjectionNode.prototype.registerSharedNode = function (layoutId, node) {
2522
+ var _a, _b, _c;
2523
+ if (!this.sharedNodes.has(layoutId)) {
2524
+ this.sharedNodes.set(layoutId, new NodeStack());
2525
+ }
2526
+ var stack = this.sharedNodes.get(layoutId);
2527
+ stack.add(node);
2528
+ node.promote({
2529
+ transition: (_a = node.options.initialPromotionConfig) === null || _a === void 0 ? void 0 : _a.transition,
2530
+ preserveFollowOpacity: (_c = (_b = node.options.initialPromotionConfig) === null || _b === void 0 ? void 0 : _b.shouldPreserveFollowOpacity) === null || _c === void 0 ? void 0 : _c.call(_b, node),
2531
+ });
2532
+ };
2533
+ ProjectionNode.prototype.isLead = function () {
2534
+ var stack = this.getStack();
2535
+ return stack ? stack.lead === this : true;
2536
+ };
2537
+ ProjectionNode.prototype.getLead = function () {
2538
+ var _a;
2539
+ var layoutId = this.options.layoutId;
2540
+ return layoutId ? ((_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.lead) || this : this;
2541
+ };
2542
+ ProjectionNode.prototype.getPrevLead = function () {
2543
+ var _a;
2544
+ var layoutId = this.options.layoutId;
2545
+ return layoutId ? (_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.prevLead : undefined;
2546
+ };
2547
+ ProjectionNode.prototype.getStack = function () {
2548
+ var layoutId = this.options.layoutId;
2549
+ if (layoutId)
2550
+ return this.root.sharedNodes.get(layoutId);
2551
+ };
2552
+ ProjectionNode.prototype.promote = function (_a) {
2553
+ var _b = _a === void 0 ? {} : _a, needsReset = _b.needsReset, transition = _b.transition, preserveFollowOpacity = _b.preserveFollowOpacity;
2554
+ var stack = this.getStack();
2555
+ if (stack)
2556
+ stack.promote(this, preserveFollowOpacity);
2557
+ if (needsReset) {
2558
+ this.projectionDelta = undefined;
2559
+ this.needsReset = true;
2560
+ }
2561
+ if (transition)
2562
+ this.setOptions({ transition: transition });
2563
+ };
2564
+ ProjectionNode.prototype.relegate = function () {
2565
+ var stack = this.getStack();
2566
+ if (stack) {
2567
+ return stack.relegate(this);
2568
+ }
2569
+ else {
2570
+ return false;
2571
+ }
2572
+ };
2573
+ ProjectionNode.prototype.resetRotation = function () {
2574
+ var visualElement = this.options.visualElement;
2575
+ if (!visualElement)
2576
+ return;
2577
+ // If there's no detected rotation values, we can early return without a forced render.
2578
+ var hasRotate = false;
2579
+ // Keep a record of all the values we've reset
2580
+ var resetValues = {};
2581
+ // Check the rotate value of all axes and reset to 0
2582
+ for (var i = 0; i < transformAxes.length; i++) {
2583
+ var axis = transformAxes[i];
2584
+ var key = "rotate" + axis;
2585
+ // If this rotation doesn't exist as a motion value, then we don't
2586
+ // need to reset it
2587
+ if (!visualElement.getStaticValue(key)) {
2588
+ continue;
2589
+ }
2590
+ hasRotate = true;
2591
+ // Record the rotation and then temporarily set it to 0
2592
+ resetValues[key] = visualElement.getStaticValue(key);
2593
+ visualElement.setStaticValue(key, 0);
2594
+ }
2595
+ // If there's no rotation values, we don't need to do any more.
2596
+ if (!hasRotate)
2597
+ return;
2598
+ // Force a render of this element to apply the transform with all rotations
2599
+ // set to 0.
2600
+ visualElement === null || visualElement === void 0 ? void 0 : visualElement.syncRender();
2601
+ // Put back all the values we reset
2602
+ for (var key in resetValues) {
2603
+ visualElement.setStaticValue(key, resetValues[key]);
2604
+ }
2605
+ // Schedule a render for the next frame. This ensures we won't visually
2606
+ // see the element with the reset rotate value applied.
2607
+ visualElement.scheduleRender();
2608
+ };
2609
+ ProjectionNode.prototype.getProjectionStyles = function (styleProp) {
2610
+ var _a, _b, _c, _d, _e, _f;
2611
+ if (styleProp === void 0) { styleProp = {}; }
2612
+ // TODO: Return lifecycle-persistent object
2613
+ var styles = {};
2614
+ if (!this.instance || this.isSVG)
2615
+ return styles;
2616
+ if (!this.isVisible) {
2617
+ return { visibility: "hidden" };
2618
+ }
2619
+ else {
2620
+ styles.visibility = "";
2621
+ }
2622
+ var transformTemplate = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.getProps().transformTemplate;
2623
+ if (this.needsReset) {
2624
+ this.needsReset = false;
2625
+ styles.opacity = "";
2626
+ styles.pointerEvents =
2627
+ resolveMotionValue(styleProp.pointerEvents) || "";
2628
+ styles.transform = transformTemplate
2629
+ ? transformTemplate(this.latestValues, "")
2630
+ : "none";
2631
+ return styles;
2632
+ }
2633
+ var lead = this.getLead();
2634
+ if (!this.projectionDelta || !this.layout || !lead.target) {
2635
+ var emptyStyles = {};
2636
+ if (this.options.layoutId) {
2637
+ emptyStyles.opacity = (_b = this.latestValues.opacity) !== null && _b !== void 0 ? _b : 1;
2638
+ emptyStyles.pointerEvents =
2639
+ resolveMotionValue(styleProp.pointerEvents) || "";
2640
+ }
2641
+ if (this.hasProjected && !hasTransform(this.latestValues)) {
2642
+ emptyStyles.transform = transformTemplate
2643
+ ? transformTemplate({}, "")
2644
+ : "none";
2645
+ this.hasProjected = false;
2646
+ }
2647
+ return emptyStyles;
2648
+ }
2649
+ var valuesToRender = lead.animationValues || lead.latestValues;
2650
+ this.applyTransformsToTarget();
2651
+ styles.transform = buildProjectionTransform(this.projectionDeltaWithTransform, this.treeScale, valuesToRender);
2652
+ if (transformTemplate) {
2653
+ styles.transform = transformTemplate(valuesToRender, styles.transform);
2654
+ }
2655
+ var _g = this.projectionDelta, x = _g.x, y = _g.y;
2656
+ styles.transformOrigin = "".concat(x.origin * 100, "% ").concat(y.origin * 100, "% 0");
2657
+ if (lead.animationValues) {
2658
+ /**
2659
+ * If the lead component is animating, assign this either the entering/leaving
2660
+ * opacity
2661
+ */
2662
+ styles.opacity =
2663
+ lead === this
2664
+ ? (_d = (_c = valuesToRender.opacity) !== null && _c !== void 0 ? _c : this.latestValues.opacity) !== null && _d !== void 0 ? _d : 1
2665
+ : this.preserveOpacity
2666
+ ? this.latestValues.opacity
2667
+ : valuesToRender.opacityExit;
2668
+ }
2669
+ else {
2670
+ /**
2671
+ * Or we're not animating at all, set the lead component to its actual
2672
+ * opacity and other components to hidden.
2673
+ */
2674
+ styles.opacity =
2675
+ lead === this
2676
+ ? (_e = valuesToRender.opacity) !== null && _e !== void 0 ? _e : ""
2677
+ : (_f = valuesToRender.opacityExit) !== null && _f !== void 0 ? _f : 0;
2678
+ }
2679
+ /**
2680
+ * Apply scale correction
2681
+ */
2682
+ for (var key in scaleCorrectors) {
2683
+ if (valuesToRender[key] === undefined)
2684
+ continue;
2685
+ var _h = scaleCorrectors[key], correct = _h.correct, applyTo = _h.applyTo;
2686
+ var corrected = correct(valuesToRender[key], lead);
2687
+ if (applyTo) {
2688
+ var num = applyTo.length;
2689
+ for (var i = 0; i < num; i++) {
2690
+ styles[applyTo[i]] = corrected;
2691
+ }
2692
+ }
2693
+ else {
2694
+ styles[key] = corrected;
2695
+ }
2696
+ }
2697
+ /**
2698
+ * Disable pointer events on follow components. This is to ensure
2699
+ * that if a follow component covers a lead component it doesn't block
2700
+ * pointer events on the lead.
2701
+ */
2702
+ if (this.options.layoutId) {
2703
+ styles.pointerEvents =
2704
+ lead === this
2705
+ ? resolveMotionValue(styleProp.pointerEvents) || ""
2706
+ : "none";
2707
+ }
2708
+ return styles;
2709
+ };
2710
+ ProjectionNode.prototype.clearSnapshot = function () {
2711
+ this.resumeFrom = this.snapshot = undefined;
2712
+ };
2713
+ // Only run on root
2714
+ ProjectionNode.prototype.resetTree = function () {
2715
+ this.root.nodes.forEach(function (node) { var _a; return (_a = node.currentAnimation) === null || _a === void 0 ? void 0 : _a.stop(); });
2716
+ this.root.nodes.forEach(clearMeasurements);
2717
+ this.root.sharedNodes.clear();
2718
+ };
2719
+ return ProjectionNode;
2720
+ }());
2721
+ }
2722
+ function updateLayout(node) {
2723
+ node.updateLayout();
2724
+ }
2725
+ function notifyLayoutUpdate(node) {
2726
+ var _a, _b, _c, _d;
2727
+ var snapshot = (_b = (_a = node.resumeFrom) === null || _a === void 0 ? void 0 : _a.snapshot) !== null && _b !== void 0 ? _b : node.snapshot;
2728
+ if (node.isLead() &&
2729
+ node.layout &&
2730
+ snapshot &&
2731
+ node.hasListeners("didUpdate")) {
2732
+ var _e = node.layout, layout_1 = _e.actual, measuredLayout = _e.measured;
2733
+ // TODO Maybe we want to also resize the layout snapshot so we don't trigger
2734
+ // animations for instance if layout="size" and an element has only changed position
2735
+ if (node.options.animationType === "size") {
2736
+ eachAxis(function (axis) {
2737
+ var axisSnapshot = snapshot.isShared
2738
+ ? snapshot.measured[axis]
2739
+ : snapshot.layout[axis];
2740
+ var length = calcLength(axisSnapshot);
2741
+ axisSnapshot.min = layout_1[axis].min;
2742
+ axisSnapshot.max = axisSnapshot.min + length;
2743
+ });
2744
+ }
2745
+ else if (node.options.animationType === "position") {
2746
+ eachAxis(function (axis) {
2747
+ var axisSnapshot = snapshot.isShared
2748
+ ? snapshot.measured[axis]
2749
+ : snapshot.layout[axis];
2750
+ var length = calcLength(layout_1[axis]);
2751
+ axisSnapshot.max = axisSnapshot.min + length;
2752
+ });
2753
+ }
2754
+ var layoutDelta = createDelta();
2755
+ calcBoxDelta(layoutDelta, layout_1, snapshot.layout);
2756
+ var visualDelta = createDelta();
2757
+ if (snapshot.isShared) {
2758
+ calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measured);
2759
+ }
2760
+ else {
2761
+ calcBoxDelta(visualDelta, layout_1, snapshot.layout);
2762
+ }
2763
+ var hasLayoutChanged = !isDeltaZero(layoutDelta);
2764
+ var hasRelativeTargetChanged = false;
2765
+ if (!node.resumeFrom) {
2766
+ node.relativeParent = node.getClosestProjectingParent();
2767
+ /**
2768
+ * If the relativeParent is itself resuming from a different element then
2769
+ * the relative snapshot is not relavent
2770
+ */
2771
+ if (node.relativeParent && !node.relativeParent.resumeFrom) {
2772
+ var _f = node.relativeParent, parentSnapshot = _f.snapshot, parentLayout = _f.layout;
2773
+ if (parentSnapshot && parentLayout) {
2774
+ var relativeSnapshot = createBox();
2775
+ calcRelativePosition(relativeSnapshot, snapshot.layout, parentSnapshot.layout);
2776
+ var relativeLayout = createBox();
2777
+ calcRelativePosition(relativeLayout, layout_1, parentLayout.actual);
2778
+ if (!boxEquals(relativeSnapshot, relativeLayout)) {
2779
+ hasRelativeTargetChanged = true;
2780
+ }
2781
+ }
2782
+ }
2783
+ }
2784
+ node.notifyListeners("didUpdate", {
2785
+ layout: layout_1,
2786
+ snapshot: snapshot,
2787
+ delta: visualDelta,
2788
+ layoutDelta: layoutDelta,
2789
+ hasLayoutChanged: hasLayoutChanged,
2790
+ hasRelativeTargetChanged: hasRelativeTargetChanged,
2791
+ });
1336
2792
  }
1337
- return true;
2793
+ else if (node.isLead()) {
2794
+ (_d = (_c = node.options).onExitComplete) === null || _d === void 0 ? void 0 : _d.call(_c);
2795
+ }
2796
+ /**
2797
+ * Clearing transition
2798
+ * TODO: Investigate why this transition is being passed in as {type: false } from Framer
2799
+ * and why we need it at all
2800
+ */
2801
+ node.options.transition = undefined;
1338
2802
  }
1339
-
1340
- /**
1341
- * Check if value is a numerical string, ie a string that is purely a number eg "100" or "-100.1"
1342
- */
1343
- var isNumericalString = function (v) { return /^\-?\d*\.?\d+$/.test(v); };
1344
-
1345
- /**
1346
- * Check if the value is a zero value string like "0px" or "0%"
1347
- */
1348
- var isZeroValueString = function (v) { return /^0[^.\s]+$/.test(v); };
1349
-
1350
- /**
1351
- * Tests a provided value against a ValueType
1352
- */
1353
- var testValueType = function (v) { return function (type) { return type.test(v); }; };
1354
-
1355
- /**
1356
- * ValueType for "auto"
1357
- */
1358
- var auto = {
1359
- test: function (v) { return v === "auto"; },
1360
- parse: function (v) { return v; },
2803
+ function clearSnapshot(node) {
2804
+ node.clearSnapshot();
2805
+ }
2806
+ function clearMeasurements(node) {
2807
+ node.clearMeasurements();
2808
+ }
2809
+ function resetTransformStyle(node) {
2810
+ node.resetTransform();
2811
+ }
2812
+ function finishAnimation(node) {
2813
+ node.finishAnimation();
2814
+ node.targetDelta = node.relativeTarget = node.target = undefined;
2815
+ }
2816
+ function resolveTargetDelta(node) {
2817
+ node.resolveTargetDelta();
2818
+ }
2819
+ function calcProjection(node) {
2820
+ node.calcProjection();
2821
+ }
2822
+ function resetRotation(node) {
2823
+ node.resetRotation();
2824
+ }
2825
+ function removeLeadSnapshots(stack) {
2826
+ stack.removeLeadSnapshot();
2827
+ }
2828
+ function mixAxisDelta(output, delta, p) {
2829
+ output.translate = popmotion.mix(delta.translate, 0, p);
2830
+ output.scale = popmotion.mix(delta.scale, 1, p);
2831
+ output.origin = delta.origin;
2832
+ output.originPoint = delta.originPoint;
2833
+ }
2834
+ function mixAxis(output, from, to, p) {
2835
+ output.min = popmotion.mix(from.min, to.min, p);
2836
+ output.max = popmotion.mix(from.max, to.max, p);
2837
+ }
2838
+ function mixBox(output, from, to, p) {
2839
+ mixAxis(output.x, from.x, to.x, p);
2840
+ mixAxis(output.y, from.y, to.y, p);
2841
+ }
2842
+ function hasOpacityCrossfade(node) {
2843
+ return (node.animationValues && node.animationValues.opacityExit !== undefined);
2844
+ }
2845
+ var defaultLayoutTransition = {
2846
+ duration: 0.45,
2847
+ ease: [0.4, 0, 0.1, 1],
1361
2848
  };
2849
+ function mountNodeEarly(node, id) {
2850
+ /**
2851
+ * Rather than searching the DOM from document we can search the
2852
+ * path for the deepest mounted ancestor and search from there
2853
+ */
2854
+ var searchNode = node.root;
2855
+ for (var i = node.path.length - 1; i >= 0; i--) {
2856
+ if (Boolean(node.path[i].instance)) {
2857
+ searchNode = node.path[i];
2858
+ break;
2859
+ }
2860
+ }
2861
+ var searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
2862
+ var element = searchElement.querySelector("[data-projection-id=\"".concat(id, "\"]"));
2863
+ if (element)
2864
+ node.mount(element, true);
2865
+ }
2866
+ function roundAxis(axis) {
2867
+ axis.min = Math.round(axis.min);
2868
+ axis.max = Math.round(axis.max);
2869
+ }
2870
+ function roundBox(box) {
2871
+ roundAxis(box.x);
2872
+ roundAxis(box.y);
2873
+ }
1362
2874
 
1363
- /**
1364
- * A list of value types commonly used for dimensions
1365
- */
1366
- var dimensionValueTypes = [styleValueTypes.number, styleValueTypes.px, styleValueTypes.percent, styleValueTypes.degrees, styleValueTypes.vw, styleValueTypes.vh, auto];
2875
+ var id = 1;
2876
+ function useProjectionId() {
2877
+ return useConstant(function () {
2878
+ if (globalProjectionState.hasEverUpdated) {
2879
+ return id++;
2880
+ }
2881
+ });
2882
+ }
1367
2883
 
1368
2884
  /**
1369
- * A list of all ValueTypes
1370
- */
1371
- var valueTypes = tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(dimensionValueTypes), false), [styleValueTypes.color, styleValueTypes.complex], false);
1372
- /**
1373
- * Tests a value against the list of ValueTypes
2885
+ * @internal
1374
2886
  */
1375
- var findValueType = function (v) { return valueTypes.find(testValueType(v)); };
2887
+ var LayoutGroupContext = React.createContext({});
1376
2888
 
1377
2889
  /**
1378
- * Set VisualElement's MotionValue, creating a new MotionValue for it if
1379
- * it doesn't exist.
2890
+ * @internal
1380
2891
  */
1381
- function setMotionValue(visualElement, key, value) {
1382
- if (visualElement.hasValue(key)) {
1383
- visualElement.getValue(key).set(value);
1384
- }
1385
- else {
1386
- visualElement.addValue(key, motionValue(value));
1387
- }
1388
- }
1389
- function setTarget(visualElement, definition) {
1390
- var resolved = resolveVariant(visualElement, definition);
1391
- var _a = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {}, _b = _a.transitionEnd, transitionEnd = _b === void 0 ? {} : _b; _a.transition; var target = tslib.__rest(_a, ["transitionEnd", "transition"]);
1392
- target = tslib.__assign(tslib.__assign({}, target), transitionEnd);
1393
- for (var key in target) {
1394
- var value = resolveFinalValueInKeyframes(target[key]);
1395
- setMotionValue(visualElement, key, value);
1396
- }
1397
- }
1398
- function checkTargetForNewValues(visualElement, target, origin) {
1399
- var _a, _b, _c;
1400
- var _d;
1401
- var newValueKeys = Object.keys(target).filter(function (key) { return !visualElement.hasValue(key); });
1402
- var numNewValues = newValueKeys.length;
1403
- if (!numNewValues)
2892
+ var SwitchLayoutGroupContext = React.createContext({});
2893
+
2894
+ function useProjection(projectionId, _a, visualElement, ProjectionNodeConstructor) {
2895
+ var _b;
2896
+ var layoutId = _a.layoutId, layout = _a.layout, drag = _a.drag, dragConstraints = _a.dragConstraints, layoutScroll = _a.layoutScroll;
2897
+ var initialPromotionConfig = React.useContext(SwitchLayoutGroupContext);
2898
+ if (!ProjectionNodeConstructor ||
2899
+ !visualElement ||
2900
+ (visualElement === null || visualElement === void 0 ? void 0 : visualElement.projection)) {
1404
2901
  return;
1405
- for (var i = 0; i < numNewValues; i++) {
1406
- var key = newValueKeys[i];
1407
- var targetValue = target[key];
1408
- var value = null;
1409
- /**
1410
- * If the target is a series of keyframes, we can use the first value
1411
- * in the array. If this first value is null, we'll still need to read from the DOM.
1412
- */
1413
- if (Array.isArray(targetValue)) {
1414
- value = targetValue[0];
1415
- }
1416
- /**
1417
- * If the target isn't keyframes, or the first keyframe was null, we need to
1418
- * first check if an origin value was explicitly defined in the transition as "from",
1419
- * if not read the value from the DOM. As an absolute fallback, take the defined target value.
1420
- */
1421
- if (value === null) {
1422
- value = (_b = (_a = origin[key]) !== null && _a !== void 0 ? _a : visualElement.readValue(key)) !== null && _b !== void 0 ? _b : target[key];
1423
- }
2902
+ }
2903
+ visualElement.projection = new ProjectionNodeConstructor(projectionId, visualElement.getLatestValues(), (_b = visualElement.parent) === null || _b === void 0 ? void 0 : _b.projection);
2904
+ visualElement.projection.setOptions({
2905
+ layoutId: layoutId,
2906
+ layout: layout,
2907
+ alwaysMeasureLayout: Boolean(drag) || (dragConstraints && isRefObject(dragConstraints)),
2908
+ visualElement: visualElement,
2909
+ scheduleRender: function () { return visualElement.scheduleRender(); },
1424
2910
  /**
1425
- * If value is still undefined or null, ignore it. Preferably this would throw,
1426
- * but this was causing issues in Framer.
2911
+ * TODO: Update options in an effect. This could be tricky as it'll be too late
2912
+ * to update by the time layout animations run.
2913
+ * We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
2914
+ * ensuring it gets called if there's no potential layout animations.
2915
+ *
1427
2916
  */
1428
- if (value === undefined || value === null)
1429
- continue;
1430
- if (typeof value === "string" &&
1431
- (isNumericalString(value) || isZeroValueString(value))) {
1432
- // If this is a number read as a string, ie "0" or "200", convert it to a number
1433
- value = parseFloat(value);
1434
- }
1435
- else if (!findValueType(value) && styleValueTypes.complex.test(targetValue)) {
1436
- value = getAnimatableNone(key, targetValue);
1437
- }
1438
- visualElement.addValue(key, motionValue(value));
1439
- (_c = (_d = origin)[key]) !== null && _c !== void 0 ? _c : (_d[key] = value);
1440
- visualElement.setBaseTarget(key, value);
1441
- }
1442
- }
1443
-
1444
- /**
1445
- * @internal
1446
- */
1447
- function animateVisualElement(visualElement, definition, options) {
1448
- if (options === void 0) { options = {}; }
1449
- visualElement.notifyAnimationStart(definition);
1450
- var animation;
1451
- if (Array.isArray(definition)) {
1452
- var animations = definition.map(function (variant) {
1453
- return animateVariant(visualElement, variant, options);
1454
- });
1455
- animation = Promise.all(animations);
1456
- }
1457
- else if (typeof definition === "string") {
1458
- animation = animateVariant(visualElement, definition, options);
1459
- }
1460
- else {
1461
- var resolvedDefinition = typeof definition === "function"
1462
- ? resolveVariant(visualElement, definition, options.custom)
1463
- : definition;
1464
- animation = animateTarget(visualElement, resolvedDefinition, options);
1465
- }
1466
- return animation.then(function () {
1467
- return visualElement.notifyAnimationComplete(definition);
2917
+ animationType: typeof layout === "string" ? layout : "both",
2918
+ initialPromotionConfig: initialPromotionConfig,
2919
+ layoutScroll: layoutScroll,
1468
2920
  });
1469
2921
  }
1470
- function animateVariant(visualElement, variant, options) {
1471
- var _a;
1472
- if (options === void 0) { options = {}; }
1473
- var resolved = resolveVariant(visualElement, variant, options.custom);
1474
- var _b = (resolved || {}).transition, transition = _b === void 0 ? visualElement.getDefaultTransition() || {} : _b;
1475
- if (options.transitionOverride) {
1476
- transition = options.transitionOverride;
2922
+
2923
+ var VisualElementHandler = /** @class */ (function (_super) {
2924
+ tslib.__extends(VisualElementHandler, _super);
2925
+ function VisualElementHandler() {
2926
+ return _super !== null && _super.apply(this, arguments) || this;
1477
2927
  }
1478
2928
  /**
1479
- * If we have a variant, create a callback that runs it as an animation.
1480
- * Otherwise, we resolve a Promise immediately for a composable no-op.
1481
- */
1482
- var getAnimation = resolved
1483
- ? function () { return animateTarget(visualElement, resolved, options); }
1484
- : function () { return Promise.resolve(); };
1485
- /**
1486
- * If we have children, create a callback that runs all their animations.
1487
- * Otherwise, we resolve a Promise immediately for a composable no-op.
1488
- */
1489
- var getChildAnimations = ((_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.size)
1490
- ? function (forwardDelay) {
1491
- if (forwardDelay === void 0) { forwardDelay = 0; }
1492
- var _a = transition.delayChildren, delayChildren = _a === void 0 ? 0 : _a, staggerChildren = transition.staggerChildren, staggerDirection = transition.staggerDirection;
1493
- return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
1494
- }
1495
- : function () { return Promise.resolve(); };
1496
- /**
1497
- * If the transition explicitly defines a "when" option, we need to resolve either
1498
- * this animation or all children animations before playing the other.
2929
+ * Update visual element props as soon as we know this update is going to be commited.
1499
2930
  */
1500
- var when = transition.when;
1501
- if (when) {
1502
- var _c = tslib.__read(when === "beforeChildren"
1503
- ? [getAnimation, getChildAnimations]
1504
- : [getChildAnimations, getAnimation], 2), first = _c[0], last = _c[1];
1505
- return first().then(last);
1506
- }
1507
- else {
1508
- return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
1509
- }
1510
- }
2931
+ VisualElementHandler.prototype.getSnapshotBeforeUpdate = function () {
2932
+ this.updateProps();
2933
+ return null;
2934
+ };
2935
+ VisualElementHandler.prototype.componentDidUpdate = function () { };
2936
+ VisualElementHandler.prototype.updateProps = function () {
2937
+ var _a = this.props, visualElement = _a.visualElement, props = _a.props;
2938
+ if (visualElement)
2939
+ visualElement.setProps(props);
2940
+ };
2941
+ VisualElementHandler.prototype.render = function () {
2942
+ return this.props.children;
2943
+ };
2944
+ return VisualElementHandler;
2945
+ }(React__default["default"].Component));
2946
+
1511
2947
  /**
2948
+ * Create a `motion` component.
2949
+ *
2950
+ * This function accepts a Component argument, which can be either a string (ie "div"
2951
+ * for `motion.div`), or an actual React component.
2952
+ *
2953
+ * Alongside this is a config option which provides a way of rendering the provided
2954
+ * component "offline", or outside the React render cycle.
2955
+ *
1512
2956
  * @internal
1513
2957
  */
1514
- function animateTarget(visualElement, definition, _a) {
1515
- var _b;
1516
- var _c = _a === void 0 ? {} : _a, _d = _c.delay, delay = _d === void 0 ? 0 : _d, transitionOverride = _c.transitionOverride, type = _c.type;
1517
- var _e = visualElement.makeTargetAnimatable(definition), _f = _e.transition, transition = _f === void 0 ? visualElement.getDefaultTransition() : _f, transitionEnd = _e.transitionEnd, target = tslib.__rest(_e, ["transition", "transitionEnd"]);
1518
- if (transitionOverride)
1519
- transition = transitionOverride;
1520
- var animations = [];
1521
- var animationTypeState = type && ((_b = visualElement.animationState) === null || _b === void 0 ? void 0 : _b.getState()[type]);
1522
- for (var key in target) {
1523
- var value = visualElement.getValue(key);
1524
- var valueTarget = target[key];
1525
- if (!value ||
1526
- valueTarget === undefined ||
1527
- (animationTypeState &&
1528
- shouldBlockAnimation(animationTypeState, key))) {
1529
- continue;
2958
+ function createMotionComponent(_a) {
2959
+ var preloadedFeatures = _a.preloadedFeatures, createVisualElement = _a.createVisualElement, projectionNodeConstructor = _a.projectionNodeConstructor, useRender = _a.useRender, useVisualState = _a.useVisualState, Component = _a.Component;
2960
+ preloadedFeatures && loadFeatures(preloadedFeatures);
2961
+ function MotionComponent(props, externalRef) {
2962
+ var layoutId = useLayoutId(props);
2963
+ props = tslib.__assign(tslib.__assign({}, props), { layoutId: layoutId });
2964
+ /**
2965
+ * If we're rendering in a static environment, we only visually update the component
2966
+ * as a result of a React-rerender rather than interactions or animations. This
2967
+ * means we don't need to load additional memory structures like VisualElement,
2968
+ * or any gesture/animation features.
2969
+ */
2970
+ var config = React.useContext(MotionConfigContext);
2971
+ var features = null;
2972
+ var context = useCreateMotionContext(props);
2973
+ /**
2974
+ * Create a unique projection ID for this component. If a new component is added
2975
+ * during a layout animation we'll use this to query the DOM and hydrate its ref early, allowing
2976
+ * us to measure it as soon as any layout effect flushes pending layout animations.
2977
+ *
2978
+ * Performance note: It'd be better not to have to search the DOM for these elements.
2979
+ * For newly-entering components it could be enough to only correct treeScale, in which
2980
+ * case we could mount in a scale-correction mode. This wouldn't be enough for
2981
+ * shared element transitions however. Perhaps for those we could revert to a root node
2982
+ * that gets forceRendered and layout animations are triggered on its layout effect.
2983
+ */
2984
+ var projectionId = useProjectionId();
2985
+ /**
2986
+ *
2987
+ */
2988
+ var visualState = useVisualState(props, config.isStatic);
2989
+ if (!config.isStatic && isBrowser) {
2990
+ /**
2991
+ * Create a VisualElement for this component. A VisualElement provides a common
2992
+ * interface to renderer-specific APIs (ie DOM/Three.js etc) as well as
2993
+ * providing a way of rendering to these APIs outside of the React render loop
2994
+ * for more performant animations and interactions
2995
+ */
2996
+ context.visualElement = useVisualElement(Component, visualState, tslib.__assign(tslib.__assign({}, config), props), createVisualElement);
2997
+ useProjection(projectionId, props, context.visualElement, projectionNodeConstructor ||
2998
+ featureDefinitions.projectionNodeConstructor);
2999
+ /**
3000
+ * Load Motion gesture and animation features. These are rendered as renderless
3001
+ * components so each feature can optionally make use of React lifecycle methods.
3002
+ */
3003
+ features = useFeatures(props, context.visualElement, preloadedFeatures);
1530
3004
  }
1531
- var animation = startAnimation(key, value, valueTarget, tslib.__assign({ delay: delay }, transition));
1532
- animations.push(animation);
3005
+ /**
3006
+ * The mount order and hierarchy is specific to ensure our element ref
3007
+ * is hydrated by the time features fire their effects.
3008
+ */
3009
+ return (React__namespace.createElement(VisualElementHandler, { visualElement: context.visualElement, props: tslib.__assign(tslib.__assign({}, config), props) },
3010
+ features,
3011
+ React__namespace.createElement(MotionContext.Provider, { value: context }, useRender(Component, props, projectionId, useMotionRef(visualState, context.visualElement, externalRef), visualState, config.isStatic, context.visualElement))));
1533
3012
  }
1534
- return Promise.all(animations).then(function () {
1535
- transitionEnd && setTarget(visualElement, transitionEnd);
1536
- });
1537
- }
1538
- function animateChildren(visualElement, variant, delayChildren, staggerChildren, staggerDirection, options) {
1539
- if (delayChildren === void 0) { delayChildren = 0; }
1540
- if (staggerChildren === void 0) { staggerChildren = 0; }
1541
- if (staggerDirection === void 0) { staggerDirection = 1; }
1542
- var animations = [];
1543
- var maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
1544
- var generateStaggerDuration = staggerDirection === 1
1545
- ? function (i) {
1546
- if (i === void 0) { i = 0; }
1547
- return i * staggerChildren;
1548
- }
1549
- : function (i) {
1550
- if (i === void 0) { i = 0; }
1551
- return maxStaggerDuration - i * staggerChildren;
1552
- };
1553
- Array.from(visualElement.variantChildren)
1554
- .sort(sortByTreeOrder)
1555
- .forEach(function (child, i) {
1556
- animations.push(animateVariant(child, variant, tslib.__assign(tslib.__assign({}, options), { delay: delayChildren + generateStaggerDuration(i) })).then(function () { return child.notifyAnimationComplete(variant); }));
1557
- });
1558
- return Promise.all(animations);
3013
+ return React.forwardRef(MotionComponent);
1559
3014
  }
1560
- function sortByTreeOrder(a, b) {
1561
- return a.sortNodePosition(b);
3015
+ function useLayoutId(_a) {
3016
+ var _b;
3017
+ var layoutId = _a.layoutId;
3018
+ var layoutGroupId = (_b = React.useContext(LayoutGroupContext)) === null || _b === void 0 ? void 0 : _b.id;
3019
+ return layoutGroupId && layoutId !== undefined
3020
+ ? layoutGroupId + "-" + layoutId
3021
+ : layoutId;
1562
3022
  }
3023
+
1563
3024
  /**
1564
- * Decide whether we should block this animation. Previously, we achieved this
1565
- * just by checking whether the key was listed in protectedKeys, but this
1566
- * posed problems if an animation was triggered by afterChildren and protectedKeys
1567
- * had been set to true in the meantime.
1568
- */
1569
- function shouldBlockAnimation(_a, key) {
1570
- var protectedKeys = _a.protectedKeys, needsAnimating = _a.needsAnimating;
1571
- var shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
1572
- needsAnimating[key] = false;
1573
- return shouldBlock;
3025
+ * A list of all valid MotionProps.
3026
+ *
3027
+ * @internalremarks
3028
+ * This doesn't throw if a `MotionProp` name is missing - it should.
3029
+ */
3030
+ var validMotionProps = new Set([
3031
+ "initial",
3032
+ "animate",
3033
+ "exit",
3034
+ "style",
3035
+ "variants",
3036
+ "transition",
3037
+ "transformTemplate",
3038
+ "transformValues",
3039
+ "custom",
3040
+ "inherit",
3041
+ "layout",
3042
+ "layoutId",
3043
+ "layoutDependency",
3044
+ "onLayoutAnimationComplete",
3045
+ "onLayoutMeasure",
3046
+ "onBeforeLayoutMeasure",
3047
+ "onAnimationStart",
3048
+ "onAnimationComplete",
3049
+ "onUpdate",
3050
+ "onDragStart",
3051
+ "onDrag",
3052
+ "onDragEnd",
3053
+ "onMeasureDragConstraints",
3054
+ "onDirectionLock",
3055
+ "onDragTransitionEnd",
3056
+ "drag",
3057
+ "dragControls",
3058
+ "dragListener",
3059
+ "dragConstraints",
3060
+ "dragDirectionLock",
3061
+ "dragSnapToOrigin",
3062
+ "_dragX",
3063
+ "_dragY",
3064
+ "dragElastic",
3065
+ "dragMomentum",
3066
+ "dragPropagation",
3067
+ "dragTransition",
3068
+ "whileDrag",
3069
+ "onPan",
3070
+ "onPanStart",
3071
+ "onPanEnd",
3072
+ "onPanSessionStart",
3073
+ "onTap",
3074
+ "onTapStart",
3075
+ "onTapCancel",
3076
+ "onHoverStart",
3077
+ "onHoverEnd",
3078
+ "whileFocus",
3079
+ "whileTap",
3080
+ "whileHover",
3081
+ "whileInView",
3082
+ "onViewportEnter",
3083
+ "onViewportLeave",
3084
+ "viewport",
3085
+ "layoutScroll",
3086
+ ]);
3087
+ /**
3088
+ * Check whether a prop name is a valid `MotionProp` key.
3089
+ *
3090
+ * @param key - Name of the property to check
3091
+ * @returns `true` is key is a valid `MotionProp`.
3092
+ *
3093
+ * @public
3094
+ */
3095
+ function isValidMotionProp(key) {
3096
+ return validMotionProps.has(key);
3097
+ }
3098
+
3099
+ var shouldForward = function (key) { return !isValidMotionProp(key); };
3100
+ /**
3101
+ * Emotion and Styled Components both allow users to pass through arbitrary props to their components
3102
+ * to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
3103
+ * of these should be passed to the underlying DOM node.
3104
+ *
3105
+ * However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
3106
+ * as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
3107
+ * passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
3108
+ * `@emotion/is-prop-valid`, however to fix this problem we need to use it.
3109
+ *
3110
+ * By making it an optionalDependency we can offer this functionality only in the situations where it's
3111
+ * actually required.
3112
+ */
3113
+ try {
3114
+ var emotionIsPropValid_1 = require("@emotion/is-prop-valid").default;
3115
+ shouldForward = function (key) {
3116
+ // Handle events explicitly as Emotion validates them all as true
3117
+ if (key.startsWith("on")) {
3118
+ return !isValidMotionProp(key);
3119
+ }
3120
+ else {
3121
+ return emotionIsPropValid_1(key);
3122
+ }
3123
+ };
3124
+ }
3125
+ catch (_a) {
3126
+ // We don't need to actually do anything here - the fallback is the existing `isPropValid`.
3127
+ }
3128
+ function filterProps(props, isDom, forwardMotionProps) {
3129
+ var filteredProps = {};
3130
+ for (var key in props) {
3131
+ if (shouldForward(key) ||
3132
+ (forwardMotionProps === true && isValidMotionProp(key)) ||
3133
+ (!isDom && !isValidMotionProp(key)) ||
3134
+ // If trying to use native HTML drag events, forward drag listeners
3135
+ (props["draggable"] && key.startsWith("onDrag"))) {
3136
+ filteredProps[key] = props[key];
3137
+ }
3138
+ }
3139
+ return filteredProps;
3140
+ }
3141
+
3142
+ function isAnimationControls(v) {
3143
+ return typeof v === "object" && typeof v.start === "function";
3144
+ }
3145
+
3146
+ function makeState(_a, props, context, presenceContext) {
3147
+ var scrapeMotionValuesFromProps = _a.scrapeMotionValuesFromProps, createRenderState = _a.createRenderState, onMount = _a.onMount;
3148
+ var state = {
3149
+ latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
3150
+ renderState: createRenderState(),
3151
+ };
3152
+ if (onMount) {
3153
+ state.mount = function (instance) { return onMount(props, instance, state); };
3154
+ }
3155
+ return state;
3156
+ }
3157
+ var makeUseVisualState = function (config) {
3158
+ return function (props, isStatic) {
3159
+ var context = React.useContext(MotionContext);
3160
+ var presenceContext = React.useContext(PresenceContext);
3161
+ return isStatic
3162
+ ? makeState(config, props, context, presenceContext)
3163
+ : useConstant(function () {
3164
+ return makeState(config, props, context, presenceContext);
3165
+ });
3166
+ };
3167
+ };
3168
+ function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
3169
+ var values = {};
3170
+ var blockInitialAnimation = (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false;
3171
+ var motionValues = scrapeMotionValues(props);
3172
+ for (var key in motionValues) {
3173
+ values[key] = resolveMotionValue(motionValues[key]);
3174
+ }
3175
+ var initial = props.initial, animate = props.animate;
3176
+ var isControllingVariants = checkIfControllingVariants(props);
3177
+ var isVariantNode = checkIfVariantNode(props);
3178
+ if (context &&
3179
+ isVariantNode &&
3180
+ !isControllingVariants &&
3181
+ props.inherit !== false) {
3182
+ initial !== null && initial !== void 0 ? initial : (initial = context.initial);
3183
+ animate !== null && animate !== void 0 ? animate : (animate = context.animate);
3184
+ }
3185
+ var initialAnimationIsBlocked = blockInitialAnimation || initial === false;
3186
+ var variantToSet = initialAnimationIsBlocked ? animate : initial;
3187
+ if (variantToSet &&
3188
+ typeof variantToSet !== "boolean" &&
3189
+ !isAnimationControls(variantToSet)) {
3190
+ var list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
3191
+ list.forEach(function (definition) {
3192
+ var resolved = resolveVariantFromProps(props, definition);
3193
+ if (!resolved)
3194
+ return;
3195
+ var transitionEnd = resolved.transitionEnd; resolved.transition; var target = tslib.__rest(resolved, ["transitionEnd", "transition"]);
3196
+ for (var key in target) {
3197
+ var valueTarget = target[key];
3198
+ if (Array.isArray(valueTarget)) {
3199
+ /**
3200
+ * Take final keyframe if the initial animation is blocked because
3201
+ * we want to initialise at the end of that blocked animation.
3202
+ */
3203
+ var index = initialAnimationIsBlocked
3204
+ ? valueTarget.length - 1
3205
+ : 0;
3206
+ valueTarget = valueTarget[index];
3207
+ }
3208
+ if (valueTarget !== null) {
3209
+ values[key] = valueTarget;
3210
+ }
3211
+ }
3212
+ for (var key in transitionEnd)
3213
+ values[key] = transitionEnd[key];
3214
+ });
3215
+ }
3216
+ return values;
1574
3217
  }
1575
3218
 
1576
- var AnimationType;
3219
+ exports.AnimationType = void 0;
1577
3220
  (function (AnimationType) {
1578
3221
  AnimationType["Animate"] = "animate";
1579
3222
  AnimationType["Hover"] = "whileHover";
@@ -1582,785 +3225,923 @@ var AnimationType;
1582
3225
  AnimationType["Focus"] = "whileFocus";
1583
3226
  AnimationType["InView"] = "whileInView";
1584
3227
  AnimationType["Exit"] = "exit";
1585
- })(AnimationType || (AnimationType = {}));
3228
+ })(exports.AnimationType || (exports.AnimationType = {}));
1586
3229
 
1587
- var variantPriorityOrder = [
1588
- AnimationType.Animate,
1589
- AnimationType.InView,
1590
- AnimationType.Focus,
1591
- AnimationType.Hover,
1592
- AnimationType.Tap,
1593
- AnimationType.Drag,
1594
- AnimationType.Exit,
1595
- ];
1596
- var reversePriorityOrder = tslib.__spreadArray([], tslib.__read(variantPriorityOrder), false).reverse();
1597
- var numAnimationTypes = variantPriorityOrder.length;
1598
- function animateList(visualElement) {
1599
- return function (animations) {
1600
- return Promise.all(animations.map(function (_a) {
1601
- var animation = _a.animation, options = _a.options;
1602
- return animateVisualElement(visualElement, animation, options);
1603
- }));
1604
- };
3230
+ function addDomEvent(target, eventName, handler, options) {
3231
+ target.addEventListener(eventName, handler, options);
3232
+ return function () { return target.removeEventListener(eventName, handler, options); };
1605
3233
  }
1606
- function createAnimationState(visualElement) {
1607
- var animate = animateList(visualElement);
1608
- var state = createState();
1609
- var allAnimatedKeys = {};
1610
- var isInitialRender = true;
1611
- /**
1612
- * This function will be used to reduce the animation definitions for
1613
- * each active animation type into an object of resolved values for it.
1614
- */
1615
- var buildResolvedTypeValues = function (acc, definition) {
1616
- var resolved = resolveVariant(visualElement, definition);
1617
- if (resolved) {
1618
- resolved.transition; var transitionEnd = resolved.transitionEnd, target = tslib.__rest(resolved, ["transition", "transitionEnd"]);
1619
- acc = tslib.__assign(tslib.__assign(tslib.__assign({}, acc), target), transitionEnd);
3234
+ /**
3235
+ * Attaches an event listener directly to the provided DOM element.
3236
+ *
3237
+ * Bypassing React's event system can be desirable, for instance when attaching non-passive
3238
+ * event handlers.
3239
+ *
3240
+ * ```jsx
3241
+ * const ref = useRef(null)
3242
+ *
3243
+ * useDomEvent(ref, 'wheel', onWheel, { passive: false })
3244
+ *
3245
+ * return <div ref={ref} />
3246
+ * ```
3247
+ *
3248
+ * @param ref - React.RefObject that's been provided to the element you want to bind the listener to.
3249
+ * @param eventName - Name of the event you want listen for.
3250
+ * @param handler - Function to fire when receiving the event.
3251
+ * @param options - Options to pass to `Event.addEventListener`.
3252
+ *
3253
+ * @public
3254
+ */
3255
+ function useDomEvent(ref, eventName, handler, options) {
3256
+ React.useEffect(function () {
3257
+ var element = ref.current;
3258
+ if (handler && element) {
3259
+ return addDomEvent(element, eventName, handler, options);
1620
3260
  }
1621
- return acc;
1622
- };
1623
- function isAnimated(key) {
1624
- return allAnimatedKeys[key] !== undefined;
1625
- }
1626
- /**
1627
- * This just allows us to inject mocked animation functions
1628
- * @internal
1629
- */
1630
- function setAnimateFunction(makeAnimator) {
1631
- animate = makeAnimator(visualElement);
3261
+ }, [ref, eventName, handler, options]);
3262
+ }
3263
+
3264
+ function isMouseEvent(event) {
3265
+ // PointerEvent inherits from MouseEvent so we can't use a straight instanceof check.
3266
+ if (typeof PointerEvent !== "undefined" && event instanceof PointerEvent) {
3267
+ return !!(event.pointerType === "mouse");
1632
3268
  }
1633
- /**
1634
- * When we receive new props, we need to:
1635
- * 1. Create a list of protected keys for each type. This is a directory of
1636
- * value keys that are currently being "handled" by types of a higher priority
1637
- * so that whenever an animation is played of a given type, these values are
1638
- * protected from being animated.
1639
- * 2. Determine if an animation type needs animating.
1640
- * 3. Determine if any values have been removed from a type and figure out
1641
- * what to animate those to.
1642
- */
1643
- function animateChanges(options, changedActiveType) {
1644
- var _a;
1645
- var props = visualElement.getProps();
1646
- var context = visualElement.getVariantContext(true) || {};
1647
- /**
1648
- * A list of animations that we'll build into as we iterate through the animation
1649
- * types. This will get executed at the end of the function.
1650
- */
1651
- var animations = [];
1652
- /**
1653
- * Keep track of which values have been removed. Then, as we hit lower priority
1654
- * animation types, we can check if they contain removed values and animate to that.
1655
- */
1656
- var removedKeys = new Set();
1657
- /**
1658
- * A dictionary of all encountered keys. This is an object to let us build into and
1659
- * copy it without iteration. Each time we hit an animation type we set its protected
1660
- * keys - the keys its not allowed to animate - to the latest version of this object.
1661
- */
1662
- var encounteredKeys = {};
1663
- /**
1664
- * If a variant has been removed at a given index, and this component is controlling
1665
- * variant animations, we want to ensure lower-priority variants are forced to animate.
1666
- */
1667
- var removedVariantIndex = Infinity;
1668
- var _loop_1 = function (i) {
1669
- var type = reversePriorityOrder[i];
1670
- var typeState = state[type];
1671
- var prop = (_a = props[type]) !== null && _a !== void 0 ? _a : context[type];
1672
- var propIsVariant = isVariantLabel(prop);
1673
- /**
1674
- * If this type has *just* changed isActive status, set activeDelta
1675
- * to that status. Otherwise set to null.
1676
- */
1677
- var activeDelta = type === changedActiveType ? typeState.isActive : null;
1678
- if (activeDelta === false)
1679
- removedVariantIndex = i;
1680
- /**
1681
- * If this prop is an inherited variant, rather than been set directly on the
1682
- * component itself, we want to make sure we allow the parent to trigger animations.
1683
- *
1684
- * TODO: Can probably change this to a !isControllingVariants check
1685
- */
1686
- var isInherited = prop === context[type] && prop !== props[type] && propIsVariant;
1687
- /**
1688
- *
1689
- */
1690
- if (isInherited &&
1691
- isInitialRender &&
1692
- visualElement.manuallyAnimateOnMount) {
1693
- isInherited = false;
1694
- }
1695
- /**
1696
- * Set all encountered keys so far as the protected keys for this type. This will
1697
- * be any key that has been animated or otherwise handled by active, higher-priortiy types.
1698
- */
1699
- typeState.protectedKeys = tslib.__assign({}, encounteredKeys);
1700
- // Check if we can skip analysing this prop early
1701
- if (
1702
- // If it isn't active and hasn't *just* been set as inactive
1703
- (!typeState.isActive && activeDelta === null) ||
1704
- // If we didn't and don't have any defined prop for this animation type
1705
- (!prop && !typeState.prevProp) ||
1706
- // Or if the prop doesn't define an animation
1707
- isAnimationControls(prop) ||
1708
- typeof prop === "boolean") {
1709
- return "continue";
1710
- }
1711
- /**
1712
- * As we go look through the values defined on this type, if we detect
1713
- * a changed value or a value that was removed in a higher priority, we set
1714
- * this to true and add this prop to the animation list.
1715
- */
1716
- var variantDidChange = checkVariantsDidChange(typeState.prevProp, prop);
1717
- var shouldAnimateType = variantDidChange ||
1718
- // If we're making this variant active, we want to always make it active
1719
- (type === changedActiveType &&
1720
- typeState.isActive &&
1721
- !isInherited &&
1722
- propIsVariant) ||
1723
- // If we removed a higher-priority variant (i is in reverse order)
1724
- (i > removedVariantIndex && propIsVariant);
1725
- /**
1726
- * As animations can be set as variant lists, variants or target objects, we
1727
- * coerce everything to an array if it isn't one already
1728
- */
1729
- var definitionList = Array.isArray(prop) ? prop : [prop];
1730
- /**
1731
- * Build an object of all the resolved values. We'll use this in the subsequent
1732
- * animateChanges calls to determine whether a value has changed.
1733
- */
1734
- var resolvedValues = definitionList.reduce(buildResolvedTypeValues, {});
1735
- if (activeDelta === false)
1736
- resolvedValues = {};
1737
- /**
1738
- * Now we need to loop through all the keys in the prev prop and this prop,
1739
- * and decide:
1740
- * 1. If the value has changed, and needs animating
1741
- * 2. If it has been removed, and needs adding to the removedKeys set
1742
- * 3. If it has been removed in a higher priority type and needs animating
1743
- * 4. If it hasn't been removed in a higher priority but hasn't changed, and
1744
- * needs adding to the type's protectedKeys list.
1745
- */
1746
- var _b = typeState.prevResolvedValues, prevResolvedValues = _b === void 0 ? {} : _b;
1747
- var allKeys = tslib.__assign(tslib.__assign({}, prevResolvedValues), resolvedValues);
1748
- var markToAnimate = function (key) {
1749
- shouldAnimateType = true;
1750
- removedKeys.delete(key);
1751
- typeState.needsAnimating[key] = true;
1752
- };
1753
- for (var key in allKeys) {
1754
- var next = resolvedValues[key];
1755
- var prev = prevResolvedValues[key];
1756
- // If we've already handled this we can just skip ahead
1757
- if (encounteredKeys.hasOwnProperty(key))
1758
- continue;
1759
- /**
1760
- * If the value has changed, we probably want to animate it.
1761
- */
1762
- if (next !== prev) {
1763
- /**
1764
- * If both values are keyframes, we need to shallow compare them to
1765
- * detect whether any value has changed. If it has, we animate it.
1766
- */
1767
- if (isKeyframesTarget(next) && isKeyframesTarget(prev)) {
1768
- if (!shallowCompare(next, prev) || variantDidChange) {
1769
- markToAnimate(key);
1770
- }
1771
- else {
1772
- /**
1773
- * If it hasn't changed, we want to ensure it doesn't animate by
1774
- * adding it to the list of protected keys.
1775
- */
1776
- typeState.protectedKeys[key] = true;
1777
- }
1778
- }
1779
- else if (next !== undefined) {
1780
- // If next is defined and doesn't equal prev, it needs animating
1781
- markToAnimate(key);
1782
- }
1783
- else {
1784
- // If it's undefined, it's been removed.
1785
- removedKeys.add(key);
1786
- }
1787
- }
1788
- else if (next !== undefined && removedKeys.has(key)) {
1789
- /**
1790
- * If next hasn't changed and it isn't undefined, we want to check if it's
1791
- * been removed by a higher priority
1792
- */
1793
- markToAnimate(key);
1794
- }
1795
- else {
1796
- /**
1797
- * If it hasn't changed, we add it to the list of protected values
1798
- * to ensure it doesn't get animated.
1799
- */
1800
- typeState.protectedKeys[key] = true;
1801
- }
1802
- }
1803
- /**
1804
- * Update the typeState so next time animateChanges is called we can compare the
1805
- * latest prop and resolvedValues to these.
1806
- */
1807
- typeState.prevProp = prop;
1808
- typeState.prevResolvedValues = resolvedValues;
1809
- /**
1810
- *
1811
- */
1812
- if (typeState.isActive) {
1813
- encounteredKeys = tslib.__assign(tslib.__assign({}, encounteredKeys), resolvedValues);
1814
- }
1815
- if (isInitialRender && visualElement.blockInitialAnimation) {
1816
- shouldAnimateType = false;
1817
- }
1818
- /**
1819
- * If this is an inherited prop we want to hard-block animations
1820
- * TODO: Test as this should probably still handle animations triggered
1821
- * by removed values?
1822
- */
1823
- if (shouldAnimateType && !isInherited) {
1824
- animations.push.apply(animations, tslib.__spreadArray([], tslib.__read(definitionList.map(function (animation) { return ({
1825
- animation: animation,
1826
- options: tslib.__assign({ type: type }, options),
1827
- }); })), false));
1828
- }
1829
- };
1830
- /**
1831
- * Iterate through all animation types in reverse priority order. For each, we want to
1832
- * detect which values it's handling and whether or not they've changed (and therefore
1833
- * need to be animated). If any values have been removed, we want to detect those in
1834
- * lower priority props and flag for animation.
1835
- */
1836
- for (var i = 0; i < numAnimationTypes; i++) {
1837
- _loop_1(i);
1838
- }
1839
- allAnimatedKeys = tslib.__assign({}, encounteredKeys);
1840
- /**
1841
- * If there are some removed value that haven't been dealt with,
1842
- * we need to create a new animation that falls back either to the value
1843
- * defined in the style prop, or the last read value.
1844
- */
1845
- if (removedKeys.size) {
1846
- var fallbackAnimation_1 = {};
1847
- removedKeys.forEach(function (key) {
1848
- var fallbackTarget = visualElement.getBaseTarget(key);
1849
- if (fallbackTarget !== undefined) {
1850
- fallbackAnimation_1[key] = fallbackTarget;
1851
- }
1852
- });
1853
- animations.push({ animation: fallbackAnimation_1 });
1854
- }
1855
- var shouldAnimate = Boolean(animations.length);
1856
- if (isInitialRender &&
1857
- props.initial === false &&
1858
- !visualElement.manuallyAnimateOnMount) {
1859
- shouldAnimate = false;
3269
+ return event instanceof MouseEvent;
3270
+ }
3271
+ function isTouchEvent(event) {
3272
+ var hasTouches = !!event.touches;
3273
+ return hasTouches;
3274
+ }
3275
+
3276
+ /**
3277
+ * Filters out events not attached to the primary pointer (currently left mouse button)
3278
+ * @param eventHandler
3279
+ */
3280
+ function filterPrimaryPointer(eventHandler) {
3281
+ return function (event) {
3282
+ var isMouseEvent = event instanceof MouseEvent;
3283
+ var isPrimaryPointer = !isMouseEvent ||
3284
+ (isMouseEvent && event.button === 0);
3285
+ if (isPrimaryPointer) {
3286
+ eventHandler(event);
1860
3287
  }
1861
- isInitialRender = false;
1862
- return shouldAnimate ? animate(animations) : Promise.resolve();
1863
- }
1864
- /**
1865
- * Change whether a certain animation type is active.
1866
- */
1867
- function setActive(type, isActive, options) {
1868
- var _a;
1869
- // If the active state hasn't changed, we can safely do nothing here
1870
- if (state[type].isActive === isActive)
1871
- return Promise.resolve();
1872
- // Propagate active change to children
1873
- (_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.forEach(function (child) { var _a; return (_a = child.animationState) === null || _a === void 0 ? void 0 : _a.setActive(type, isActive); });
1874
- state[type].isActive = isActive;
1875
- return animateChanges(options, type);
1876
- }
1877
- return {
1878
- isAnimated: isAnimated,
1879
- animateChanges: animateChanges,
1880
- setActive: setActive,
1881
- setAnimateFunction: setAnimateFunction,
1882
- getState: function () { return state; },
1883
3288
  };
1884
3289
  }
1885
- function checkVariantsDidChange(prev, next) {
1886
- if (typeof next === "string") {
1887
- return next !== prev;
1888
- }
1889
- else if (isVariantLabels(next)) {
1890
- return !shallowCompare(next, prev);
1891
- }
1892
- return false;
3290
+ var defaultPagePoint = { pageX: 0, pageY: 0 };
3291
+ function pointFromTouch(e, pointType) {
3292
+ if (pointType === void 0) { pointType = "page"; }
3293
+ var primaryTouch = e.touches[0] || e.changedTouches[0];
3294
+ var point = primaryTouch || defaultPagePoint;
3295
+ return {
3296
+ x: point[pointType + "X"],
3297
+ y: point[pointType + "Y"],
3298
+ };
1893
3299
  }
1894
- function createTypeState(isActive) {
1895
- if (isActive === void 0) { isActive = false; }
3300
+ function pointFromMouse(point, pointType) {
3301
+ if (pointType === void 0) { pointType = "page"; }
1896
3302
  return {
1897
- isActive: isActive,
1898
- protectedKeys: {},
1899
- needsAnimating: {},
1900
- prevResolvedValues: {},
3303
+ x: point[pointType + "X"],
3304
+ y: point[pointType + "Y"],
1901
3305
  };
1902
3306
  }
1903
- function createState() {
1904
- var _a;
1905
- return _a = {},
1906
- _a[AnimationType.Animate] = createTypeState(true),
1907
- _a[AnimationType.InView] = createTypeState(),
1908
- _a[AnimationType.Hover] = createTypeState(),
1909
- _a[AnimationType.Tap] = createTypeState(),
1910
- _a[AnimationType.Drag] = createTypeState(),
1911
- _a[AnimationType.Focus] = createTypeState(),
1912
- _a[AnimationType.Exit] = createTypeState(),
1913
- _a;
3307
+ function extractEventInfo(event, pointType) {
3308
+ if (pointType === void 0) { pointType = "page"; }
3309
+ return {
3310
+ point: isTouchEvent(event)
3311
+ ? pointFromTouch(event, pointType)
3312
+ : pointFromMouse(event, pointType),
3313
+ };
1914
3314
  }
3315
+ var wrapHandler = function (handler, shouldFilterPrimaryPointer) {
3316
+ if (shouldFilterPrimaryPointer === void 0) { shouldFilterPrimaryPointer = false; }
3317
+ var listener = function (event) {
3318
+ return handler(event, extractEventInfo(event));
3319
+ };
3320
+ return shouldFilterPrimaryPointer
3321
+ ? filterPrimaryPointer(listener)
3322
+ : listener;
3323
+ };
1915
3324
 
1916
- var makeRenderlessComponent = function (hook) { return function (props) {
1917
- hook(props);
1918
- return null;
1919
- }; };
1920
-
1921
- var animations = {
1922
- animation: makeRenderlessComponent(function (_a) {
1923
- var visualElement = _a.visualElement, animate = _a.animate;
1924
- /**
1925
- * We dynamically generate the AnimationState manager as it contains a reference
1926
- * to the underlying animation library. We only want to load that if we load this,
1927
- * so people can optionally code split it out using the `m` component.
1928
- */
1929
- visualElement.animationState || (visualElement.animationState = createAnimationState(visualElement));
1930
- /**
1931
- * Subscribe any provided AnimationControls to the component's VisualElement
1932
- */
1933
- if (isAnimationControls(animate)) {
1934
- React.useEffect(function () { return animate.subscribe(visualElement); }, [animate]);
1935
- }
1936
- }),
1937
- exit: makeRenderlessComponent(function (props) {
1938
- var custom = props.custom, visualElement = props.visualElement;
1939
- var _a = tslib.__read(usePresence(), 2), isPresent = _a[0], safeToRemove = _a[1];
1940
- var presenceContext = React.useContext(PresenceContext);
1941
- React.useEffect(function () {
1942
- var _a, _b;
1943
- visualElement.isPresent = isPresent;
1944
- var animation = (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Exit, !isPresent, { custom: (_b = presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.custom) !== null && _b !== void 0 ? _b : custom });
1945
- !isPresent && (animation === null || animation === void 0 ? void 0 : animation.then(safeToRemove));
1946
- }, [isPresent]);
1947
- }),
3325
+ // We check for event support via functions in case they've been mocked by a testing suite.
3326
+ var supportsPointerEvents = function () {
3327
+ return isBrowser && window.onpointerdown === null;
3328
+ };
3329
+ var supportsTouchEvents = function () {
3330
+ return isBrowser && window.ontouchstart === null;
3331
+ };
3332
+ var supportsMouseEvents = function () {
3333
+ return isBrowser && window.onmousedown === null;
1948
3334
  };
1949
3335
 
1950
- function makeState(_a, props, context, presenceContext) {
1951
- var scrapeMotionValuesFromProps = _a.scrapeMotionValuesFromProps, createRenderState = _a.createRenderState, onMount = _a.onMount;
1952
- var state = {
1953
- latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
1954
- renderState: createRenderState(),
1955
- };
1956
- if (onMount) {
1957
- state.mount = function (instance) { return onMount(props, instance, state); };
3336
+ var mouseEventNames = {
3337
+ pointerdown: "mousedown",
3338
+ pointermove: "mousemove",
3339
+ pointerup: "mouseup",
3340
+ pointercancel: "mousecancel",
3341
+ pointerover: "mouseover",
3342
+ pointerout: "mouseout",
3343
+ pointerenter: "mouseenter",
3344
+ pointerleave: "mouseleave",
3345
+ };
3346
+ var touchEventNames = {
3347
+ pointerdown: "touchstart",
3348
+ pointermove: "touchmove",
3349
+ pointerup: "touchend",
3350
+ pointercancel: "touchcancel",
3351
+ };
3352
+ function getPointerEventName(name) {
3353
+ if (supportsPointerEvents()) {
3354
+ return name;
1958
3355
  }
1959
- return state;
3356
+ else if (supportsTouchEvents()) {
3357
+ return touchEventNames[name];
3358
+ }
3359
+ else if (supportsMouseEvents()) {
3360
+ return mouseEventNames[name];
3361
+ }
3362
+ return name;
1960
3363
  }
1961
- var makeUseVisualState = function (config) {
1962
- return function (props, isStatic) {
1963
- var context = React.useContext(MotionContext);
1964
- var presenceContext = React.useContext(PresenceContext);
1965
- return isStatic
1966
- ? makeState(config, props, context, presenceContext)
1967
- : useConstant(function () {
1968
- return makeState(config, props, context, presenceContext);
1969
- });
3364
+ function addPointerEvent(target, eventName, handler, options) {
3365
+ return addDomEvent(target, getPointerEventName(eventName), wrapHandler(handler, eventName === "pointerdown"), options);
3366
+ }
3367
+ function usePointerEvent(ref, eventName, handler, options) {
3368
+ return useDomEvent(ref, getPointerEventName(eventName), handler && wrapHandler(handler, eventName === "pointerdown"), options);
3369
+ }
3370
+
3371
+ function createLock(name) {
3372
+ var lock = null;
3373
+ return function () {
3374
+ var openLock = function () {
3375
+ lock = null;
3376
+ };
3377
+ if (lock === null) {
3378
+ lock = name;
3379
+ return openLock;
3380
+ }
3381
+ return false;
1970
3382
  };
1971
- };
1972
- function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
1973
- var values = {};
1974
- var blockInitialAnimation = (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false;
1975
- var motionValues = scrapeMotionValues(props);
1976
- for (var key in motionValues) {
1977
- values[key] = resolveMotionValue(motionValues[key]);
3383
+ }
3384
+ var globalHorizontalLock = createLock("dragHorizontal");
3385
+ var globalVerticalLock = createLock("dragVertical");
3386
+ function getGlobalLock(drag) {
3387
+ var lock = false;
3388
+ if (drag === "y") {
3389
+ lock = globalVerticalLock();
1978
3390
  }
1979
- var initial = props.initial, animate = props.animate;
1980
- var isControllingVariants = checkIfControllingVariants(props);
1981
- var isVariantNode = checkIfVariantNode(props);
1982
- if (context &&
1983
- isVariantNode &&
1984
- !isControllingVariants &&
1985
- props.inherit !== false) {
1986
- initial !== null && initial !== void 0 ? initial : (initial = context.initial);
1987
- animate !== null && animate !== void 0 ? animate : (animate = context.animate);
3391
+ else if (drag === "x") {
3392
+ lock = globalHorizontalLock();
1988
3393
  }
1989
- var initialAnimationIsBlocked = blockInitialAnimation || initial === false;
1990
- var variantToSet = initialAnimationIsBlocked ? animate : initial;
1991
- if (variantToSet &&
1992
- typeof variantToSet !== "boolean" &&
1993
- !isAnimationControls(variantToSet)) {
1994
- var list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
1995
- list.forEach(function (definition) {
1996
- var resolved = resolveVariantFromProps(props, definition);
1997
- if (!resolved)
1998
- return;
1999
- var transitionEnd = resolved.transitionEnd; resolved.transition; var target = tslib.__rest(resolved, ["transitionEnd", "transition"]);
2000
- for (var key in target) {
2001
- var valueTarget = target[key];
2002
- if (Array.isArray(valueTarget)) {
2003
- /**
2004
- * Take final keyframe if the initial animation is blocked because
2005
- * we want to initialise at the end of that blocked animation.
2006
- */
2007
- var index = initialAnimationIsBlocked
2008
- ? valueTarget.length - 1
2009
- : 0;
2010
- valueTarget = valueTarget[index];
2011
- }
2012
- if (valueTarget !== null) {
2013
- values[key] = valueTarget;
2014
- }
2015
- }
2016
- for (var key in transitionEnd)
2017
- values[key] = transitionEnd[key];
2018
- });
3394
+ else {
3395
+ var openHorizontal_1 = globalHorizontalLock();
3396
+ var openVertical_1 = globalVerticalLock();
3397
+ if (openHorizontal_1 && openVertical_1) {
3398
+ lock = function () {
3399
+ openHorizontal_1();
3400
+ openVertical_1();
3401
+ };
3402
+ }
3403
+ else {
3404
+ // Release the locks because we don't use them
3405
+ if (openHorizontal_1)
3406
+ openHorizontal_1();
3407
+ if (openVertical_1)
3408
+ openVertical_1();
3409
+ }
2019
3410
  }
2020
- return values;
3411
+ return lock;
3412
+ }
3413
+ function isDragActive() {
3414
+ // Check the gesture lock - if we get it, it means no drag gesture is active
3415
+ // and we can safely fire the tap gesture.
3416
+ var openGestureLock = getGlobalLock(true);
3417
+ if (!openGestureLock)
3418
+ return true;
3419
+ openGestureLock();
3420
+ return false;
2021
3421
  }
2022
3422
 
3423
+ var makeRenderlessComponent = function (hook) { return function (props) {
3424
+ hook(props);
3425
+ return null;
3426
+ }; };
3427
+
2023
3428
  /**
2024
- * A list of all valid MotionProps.
3429
+ * When a component is the child of `AnimatePresence`, it can use `usePresence`
3430
+ * to access information about whether it's still present in the React tree.
2025
3431
  *
2026
- * @internalremarks
2027
- * This doesn't throw if a `MotionProp` name is missing - it should.
3432
+ * ```jsx
3433
+ * import { usePresence } from "framer-motion"
3434
+ *
3435
+ * export const Component = () => {
3436
+ * const [isPresent, safeToRemove] = usePresence()
3437
+ *
3438
+ * useEffect(() => {
3439
+ * !isPresent && setTimeout(safeToRemove, 1000)
3440
+ * }, [isPresent])
3441
+ *
3442
+ * return <div />
3443
+ * }
3444
+ * ```
3445
+ *
3446
+ * If `isPresent` is `false`, it means that a component has been removed the tree, but
3447
+ * `AnimatePresence` won't really remove it until `safeToRemove` has been called.
3448
+ *
3449
+ * @public
2028
3450
  */
2029
- var validMotionProps = new Set([
2030
- "initial",
2031
- "animate",
2032
- "exit",
2033
- "style",
2034
- "variants",
2035
- "transition",
2036
- "transformTemplate",
2037
- "transformValues",
2038
- "custom",
2039
- "inherit",
2040
- "layout",
2041
- "layoutId",
2042
- "layoutDependency",
2043
- "onLayoutAnimationComplete",
2044
- "onLayoutMeasure",
2045
- "onBeforeLayoutMeasure",
2046
- "onAnimationStart",
2047
- "onAnimationComplete",
2048
- "onUpdate",
2049
- "onDragStart",
2050
- "onDrag",
2051
- "onDragEnd",
2052
- "onMeasureDragConstraints",
2053
- "onDirectionLock",
2054
- "onDragTransitionEnd",
2055
- "drag",
2056
- "dragControls",
2057
- "dragListener",
2058
- "dragConstraints",
2059
- "dragDirectionLock",
2060
- "dragSnapToOrigin",
2061
- "_dragX",
2062
- "_dragY",
2063
- "dragElastic",
2064
- "dragMomentum",
2065
- "dragPropagation",
2066
- "dragTransition",
2067
- "whileDrag",
2068
- "onPan",
2069
- "onPanStart",
2070
- "onPanEnd",
2071
- "onPanSessionStart",
2072
- "onTap",
2073
- "onTapStart",
2074
- "onTapCancel",
2075
- "onHoverStart",
2076
- "onHoverEnd",
2077
- "whileFocus",
2078
- "whileTap",
2079
- "whileHover",
2080
- "whileInView",
2081
- "onViewportEnter",
2082
- "onViewportLeave",
2083
- "viewport",
2084
- "layoutScroll",
2085
- ]);
3451
+ function usePresence() {
3452
+ var context = React.useContext(PresenceContext);
3453
+ if (context === null)
3454
+ return [true, null];
3455
+ var isPresent = context.isPresent, onExitComplete = context.onExitComplete, register = context.register;
3456
+ // It's safe to call the following hooks conditionally (after an early return) because the context will always
3457
+ // either be null or non-null for the lifespan of the component.
3458
+ // Replace with useOpaqueId when released in React
3459
+ var id = useUniqueId();
3460
+ React.useEffect(function () { return register(id); }, []);
3461
+ var safeToRemove = function () { return onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete(id); };
3462
+ return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
3463
+ }
2086
3464
  /**
2087
- * Check whether a prop name is a valid `MotionProp` key.
3465
+ * Similar to `usePresence`, except `useIsPresent` simply returns whether or not the component is present.
3466
+ * There is no `safeToRemove` function.
2088
3467
  *
2089
- * @param key - Name of the property to check
2090
- * @returns `true` is key is a valid `MotionProp`.
3468
+ * ```jsx
3469
+ * import { useIsPresent } from "framer-motion"
3470
+ *
3471
+ * export const Component = () => {
3472
+ * const isPresent = useIsPresent()
3473
+ *
3474
+ * useEffect(() => {
3475
+ * !isPresent && console.log("I've been removed!")
3476
+ * }, [isPresent])
3477
+ *
3478
+ * return <div />
3479
+ * }
3480
+ * ```
2091
3481
  *
2092
3482
  * @public
2093
3483
  */
2094
- function isValidMotionProp(key) {
2095
- return validMotionProps.has(key);
2096
- }
3484
+ function useIsPresent() {
3485
+ return isPresent(React.useContext(PresenceContext));
3486
+ }
3487
+ function isPresent(context) {
3488
+ return context === null ? true : context.isPresent;
3489
+ }
3490
+ var counter = 0;
3491
+ var incrementId = function () { return counter++; };
3492
+ var useUniqueId = function () { return useConstant(incrementId); };
3493
+
3494
+ function shallowCompare(next, prev) {
3495
+ if (!Array.isArray(prev))
3496
+ return false;
3497
+ var prevLength = prev.length;
3498
+ if (prevLength !== next.length)
3499
+ return false;
3500
+ for (var i = 0; i < prevLength; i++) {
3501
+ if (prev[i] !== next[i])
3502
+ return false;
3503
+ }
3504
+ return true;
3505
+ }
3506
+
3507
+ /**
3508
+ * Check if value is a numerical string, ie a string that is purely a number eg "100" or "-100.1"
3509
+ */
3510
+ var isNumericalString = function (v) { return /^\-?\d*\.?\d+$/.test(v); };
3511
+
3512
+ /**
3513
+ * Check if the value is a zero value string like "0px" or "0%"
3514
+ */
3515
+ var isZeroValueString = function (v) { return /^0[^.\s]+$/.test(v); };
3516
+
3517
+ /**
3518
+ * Tests a provided value against a ValueType
3519
+ */
3520
+ var testValueType = function (v) { return function (type) { return type.test(v); }; };
3521
+
3522
+ /**
3523
+ * ValueType for "auto"
3524
+ */
3525
+ var auto = {
3526
+ test: function (v) { return v === "auto"; },
3527
+ parse: function (v) { return v; },
3528
+ };
3529
+
3530
+ /**
3531
+ * A list of value types commonly used for dimensions
3532
+ */
3533
+ var dimensionValueTypes = [styleValueTypes.number, styleValueTypes.px, styleValueTypes.percent, styleValueTypes.degrees, styleValueTypes.vw, styleValueTypes.vh, auto];
3534
+ /**
3535
+ * Tests a dimensional value against the list of dimension ValueTypes
3536
+ */
3537
+ var findDimensionValueType = function (v) {
3538
+ return dimensionValueTypes.find(testValueType(v));
3539
+ };
3540
+
3541
+ /**
3542
+ * A list of all ValueTypes
3543
+ */
3544
+ var valueTypes = tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(dimensionValueTypes), false), [styleValueTypes.color, styleValueTypes.complex], false);
3545
+ /**
3546
+ * Tests a value against the list of ValueTypes
3547
+ */
3548
+ var findValueType = function (v) { return valueTypes.find(testValueType(v)); };
2097
3549
 
2098
- var shouldForward = function (key) { return !isValidMotionProp(key); };
2099
3550
  /**
2100
- * Emotion and Styled Components both allow users to pass through arbitrary props to their components
2101
- * to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
2102
- * of these should be passed to the underlying DOM node.
2103
- *
2104
- * However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
2105
- * as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
2106
- * passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
2107
- * `@emotion/is-prop-valid`, however to fix this problem we need to use it.
2108
- *
2109
- * By making it an optionalDependency we can offer this functionality only in the situations where it's
2110
- * actually required.
3551
+ * Set VisualElement's MotionValue, creating a new MotionValue for it if
3552
+ * it doesn't exist.
2111
3553
  */
2112
- try {
2113
- var emotionIsPropValid_1 = require("@emotion/is-prop-valid").default;
2114
- shouldForward = function (key) {
2115
- // Handle events explicitly as Emotion validates them all as true
2116
- if (key.startsWith("on")) {
2117
- return !isValidMotionProp(key);
3554
+ function setMotionValue(visualElement, key, value) {
3555
+ if (visualElement.hasValue(key)) {
3556
+ visualElement.getValue(key).set(value);
3557
+ }
3558
+ else {
3559
+ visualElement.addValue(key, motionValue(value));
3560
+ }
3561
+ }
3562
+ function setTarget(visualElement, definition) {
3563
+ var resolved = resolveVariant(visualElement, definition);
3564
+ var _a = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {}, _b = _a.transitionEnd, transitionEnd = _b === void 0 ? {} : _b; _a.transition; var target = tslib.__rest(_a, ["transitionEnd", "transition"]);
3565
+ target = tslib.__assign(tslib.__assign({}, target), transitionEnd);
3566
+ for (var key in target) {
3567
+ var value = resolveFinalValueInKeyframes(target[key]);
3568
+ setMotionValue(visualElement, key, value);
3569
+ }
3570
+ }
3571
+ function setVariants(visualElement, variantLabels) {
3572
+ var reversedLabels = tslib.__spreadArray([], tslib.__read(variantLabels), false).reverse();
3573
+ reversedLabels.forEach(function (key) {
3574
+ var _a;
3575
+ var variant = visualElement.getVariant(key);
3576
+ variant && setTarget(visualElement, variant);
3577
+ (_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.forEach(function (child) {
3578
+ setVariants(child, variantLabels);
3579
+ });
3580
+ });
3581
+ }
3582
+ function setValues(visualElement, definition) {
3583
+ if (Array.isArray(definition)) {
3584
+ return setVariants(visualElement, definition);
3585
+ }
3586
+ else if (typeof definition === "string") {
3587
+ return setVariants(visualElement, [definition]);
3588
+ }
3589
+ else {
3590
+ setTarget(visualElement, definition);
3591
+ }
3592
+ }
3593
+ function checkTargetForNewValues(visualElement, target, origin) {
3594
+ var _a, _b, _c;
3595
+ var _d;
3596
+ var newValueKeys = Object.keys(target).filter(function (key) { return !visualElement.hasValue(key); });
3597
+ var numNewValues = newValueKeys.length;
3598
+ if (!numNewValues)
3599
+ return;
3600
+ for (var i = 0; i < numNewValues; i++) {
3601
+ var key = newValueKeys[i];
3602
+ var targetValue = target[key];
3603
+ var value = null;
3604
+ /**
3605
+ * If the target is a series of keyframes, we can use the first value
3606
+ * in the array. If this first value is null, we'll still need to read from the DOM.
3607
+ */
3608
+ if (Array.isArray(targetValue)) {
3609
+ value = targetValue[0];
2118
3610
  }
2119
- else {
2120
- return emotionIsPropValid_1(key);
3611
+ /**
3612
+ * If the target isn't keyframes, or the first keyframe was null, we need to
3613
+ * first check if an origin value was explicitly defined in the transition as "from",
3614
+ * if not read the value from the DOM. As an absolute fallback, take the defined target value.
3615
+ */
3616
+ if (value === null) {
3617
+ value = (_b = (_a = origin[key]) !== null && _a !== void 0 ? _a : visualElement.readValue(key)) !== null && _b !== void 0 ? _b : target[key];
2121
3618
  }
2122
- };
3619
+ /**
3620
+ * If value is still undefined or null, ignore it. Preferably this would throw,
3621
+ * but this was causing issues in Framer.
3622
+ */
3623
+ if (value === undefined || value === null)
3624
+ continue;
3625
+ if (typeof value === "string" &&
3626
+ (isNumericalString(value) || isZeroValueString(value))) {
3627
+ // If this is a number read as a string, ie "0" or "200", convert it to a number
3628
+ value = parseFloat(value);
3629
+ }
3630
+ else if (!findValueType(value) && styleValueTypes.complex.test(targetValue)) {
3631
+ value = getAnimatableNone(key, targetValue);
3632
+ }
3633
+ visualElement.addValue(key, motionValue(value));
3634
+ (_c = (_d = origin)[key]) !== null && _c !== void 0 ? _c : (_d[key] = value);
3635
+ visualElement.setBaseTarget(key, value);
3636
+ }
2123
3637
  }
2124
- catch (_a) {
2125
- // We don't need to actually do anything here - the fallback is the existing `isPropValid`.
3638
+ function getOriginFromTransition(key, transition) {
3639
+ if (!transition)
3640
+ return;
3641
+ var valueTransition = transition[key] || transition["default"] || transition;
3642
+ return valueTransition.from;
2126
3643
  }
2127
- function filterProps(props, isDom, forwardMotionProps) {
2128
- var filteredProps = {};
2129
- for (var key in props) {
2130
- if (shouldForward(key) ||
2131
- (forwardMotionProps === true && isValidMotionProp(key)) ||
2132
- (!isDom && !isValidMotionProp(key)) ||
2133
- // If trying to use native HTML drag events, forward drag listeners
2134
- (props["draggable"] && key.startsWith("onDrag"))) {
2135
- filteredProps[key] = props[key];
2136
- }
3644
+ function getOrigin(target, transition, visualElement) {
3645
+ var _a, _b;
3646
+ var origin = {};
3647
+ for (var key in target) {
3648
+ origin[key] =
3649
+ (_a = getOriginFromTransition(key, transition)) !== null && _a !== void 0 ? _a : (_b = visualElement.getValue(key)) === null || _b === void 0 ? void 0 : _b.get();
2137
3650
  }
2138
- return filteredProps;
3651
+ return origin;
2139
3652
  }
2140
3653
 
2141
- function useHover(isStatic, _a, visualElement) {
2142
- var whileHover = _a.whileHover, onHoverStart = _a.onHoverStart, onHoverEnd = _a.onHoverEnd, onPointerOver = _a.onPointerOver, onPointerOut = _a.onPointerOut;
2143
- var isHoverEnabled = whileHover || onHoverStart || onHoverEnd;
2144
- if (isStatic || !visualElement || !isHoverEnabled)
2145
- return {};
2146
- return {
2147
- onPointerOver: function (event) {
2148
- var _a;
2149
- (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Hover, true);
2150
- onPointerOver === null || onPointerOver === void 0 ? void 0 : onPointerOver(event);
2151
- },
2152
- onPointerOut: function (event) {
2153
- var _a;
2154
- (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Hover, false);
2155
- onPointerOut === null || onPointerOut === void 0 ? void 0 : onPointerOut(event);
2156
- },
2157
- };
3654
+ /**
3655
+ * @internal
3656
+ */
3657
+ function animateVisualElement(visualElement, definition, options) {
3658
+ if (options === void 0) { options = {}; }
3659
+ visualElement.notifyAnimationStart(definition);
3660
+ var animation;
3661
+ if (Array.isArray(definition)) {
3662
+ var animations = definition.map(function (variant) {
3663
+ return animateVariant(visualElement, variant, options);
3664
+ });
3665
+ animation = Promise.all(animations);
3666
+ }
3667
+ else if (typeof definition === "string") {
3668
+ animation = animateVariant(visualElement, definition, options);
3669
+ }
3670
+ else {
3671
+ var resolvedDefinition = typeof definition === "function"
3672
+ ? resolveVariant(visualElement, definition, options.custom)
3673
+ : definition;
3674
+ animation = animateTarget(visualElement, resolvedDefinition, options);
3675
+ }
3676
+ return animation.then(function () {
3677
+ return visualElement.notifyAnimationComplete(definition);
3678
+ });
2158
3679
  }
2159
-
2160
- function isTouchEvent(event) {
2161
- var hasTouches = !!event.touches;
2162
- return hasTouches;
3680
+ function animateVariant(visualElement, variant, options) {
3681
+ var _a;
3682
+ if (options === void 0) { options = {}; }
3683
+ var resolved = resolveVariant(visualElement, variant, options.custom);
3684
+ var _b = (resolved || {}).transition, transition = _b === void 0 ? visualElement.getDefaultTransition() || {} : _b;
3685
+ if (options.transitionOverride) {
3686
+ transition = options.transitionOverride;
3687
+ }
3688
+ /**
3689
+ * If we have a variant, create a callback that runs it as an animation.
3690
+ * Otherwise, we resolve a Promise immediately for a composable no-op.
3691
+ */
3692
+ var getAnimation = resolved
3693
+ ? function () { return animateTarget(visualElement, resolved, options); }
3694
+ : function () { return Promise.resolve(); };
3695
+ /**
3696
+ * If we have children, create a callback that runs all their animations.
3697
+ * Otherwise, we resolve a Promise immediately for a composable no-op.
3698
+ */
3699
+ var getChildAnimations = ((_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.size)
3700
+ ? function (forwardDelay) {
3701
+ if (forwardDelay === void 0) { forwardDelay = 0; }
3702
+ var _a = transition.delayChildren, delayChildren = _a === void 0 ? 0 : _a, staggerChildren = transition.staggerChildren, staggerDirection = transition.staggerDirection;
3703
+ return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
3704
+ }
3705
+ : function () { return Promise.resolve(); };
3706
+ /**
3707
+ * If the transition explicitly defines a "when" option, we need to resolve either
3708
+ * this animation or all children animations before playing the other.
3709
+ */
3710
+ var when = transition.when;
3711
+ if (when) {
3712
+ var _c = tslib.__read(when === "beforeChildren"
3713
+ ? [getAnimation, getChildAnimations]
3714
+ : [getChildAnimations, getAnimation], 2), first = _c[0], last = _c[1];
3715
+ return first().then(last);
3716
+ }
3717
+ else {
3718
+ return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
3719
+ }
2163
3720
  }
2164
-
2165
3721
  /**
2166
- * Filters out events not attached to the primary pointer (currently left mouse button)
2167
- * @param eventHandler
3722
+ * @internal
2168
3723
  */
2169
- function filterPrimaryPointer(eventHandler) {
2170
- return function (event) {
2171
- var isMouseEvent = event instanceof MouseEvent;
2172
- var isPrimaryPointer = !isMouseEvent ||
2173
- (isMouseEvent && event.button === 0);
2174
- if (isPrimaryPointer) {
2175
- eventHandler(event);
3724
+ function animateTarget(visualElement, definition, _a) {
3725
+ var _b;
3726
+ var _c = _a === void 0 ? {} : _a, _d = _c.delay, delay = _d === void 0 ? 0 : _d, transitionOverride = _c.transitionOverride, type = _c.type;
3727
+ var _e = visualElement.makeTargetAnimatable(definition), _f = _e.transition, transition = _f === void 0 ? visualElement.getDefaultTransition() : _f, transitionEnd = _e.transitionEnd, target = tslib.__rest(_e, ["transition", "transitionEnd"]);
3728
+ if (transitionOverride)
3729
+ transition = transitionOverride;
3730
+ var animations = [];
3731
+ var animationTypeState = type && ((_b = visualElement.animationState) === null || _b === void 0 ? void 0 : _b.getState()[type]);
3732
+ for (var key in target) {
3733
+ var value = visualElement.getValue(key);
3734
+ var valueTarget = target[key];
3735
+ if (!value ||
3736
+ valueTarget === undefined ||
3737
+ (animationTypeState &&
3738
+ shouldBlockAnimation(animationTypeState, key))) {
3739
+ continue;
2176
3740
  }
2177
- };
3741
+ var animation = startAnimation(key, value, valueTarget, tslib.__assign({ delay: delay }, transition));
3742
+ animations.push(animation);
3743
+ }
3744
+ return Promise.all(animations).then(function () {
3745
+ transitionEnd && setTarget(visualElement, transitionEnd);
3746
+ });
2178
3747
  }
2179
- var defaultPagePoint = { pageX: 0, pageY: 0 };
2180
- function pointFromTouch(e, pointType) {
2181
- if (pointType === void 0) { pointType = "page"; }
2182
- var primaryTouch = e.touches[0] || e.changedTouches[0];
2183
- var point = primaryTouch || defaultPagePoint;
2184
- return {
2185
- x: point[pointType + "X"],
2186
- y: point[pointType + "Y"],
2187
- };
3748
+ function animateChildren(visualElement, variant, delayChildren, staggerChildren, staggerDirection, options) {
3749
+ if (delayChildren === void 0) { delayChildren = 0; }
3750
+ if (staggerChildren === void 0) { staggerChildren = 0; }
3751
+ if (staggerDirection === void 0) { staggerDirection = 1; }
3752
+ var animations = [];
3753
+ var maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
3754
+ var generateStaggerDuration = staggerDirection === 1
3755
+ ? function (i) {
3756
+ if (i === void 0) { i = 0; }
3757
+ return i * staggerChildren;
3758
+ }
3759
+ : function (i) {
3760
+ if (i === void 0) { i = 0; }
3761
+ return maxStaggerDuration - i * staggerChildren;
3762
+ };
3763
+ Array.from(visualElement.variantChildren)
3764
+ .sort(sortByTreeOrder)
3765
+ .forEach(function (child, i) {
3766
+ animations.push(animateVariant(child, variant, tslib.__assign(tslib.__assign({}, options), { delay: delayChildren + generateStaggerDuration(i) })).then(function () { return child.notifyAnimationComplete(variant); }));
3767
+ });
3768
+ return Promise.all(animations);
2188
3769
  }
2189
- function pointFromMouse(point, pointType) {
2190
- if (pointType === void 0) { pointType = "page"; }
2191
- return {
2192
- x: point[pointType + "X"],
2193
- y: point[pointType + "Y"],
2194
- };
3770
+ function stopAnimation(visualElement) {
3771
+ visualElement.forEachValue(function (value) { return value.stop(); });
2195
3772
  }
2196
- function extractEventInfo(event, pointType) {
2197
- if (pointType === void 0) { pointType = "page"; }
2198
- return {
2199
- point: isTouchEvent(event)
2200
- ? pointFromTouch(event, pointType)
2201
- : pointFromMouse(event, pointType),
2202
- };
3773
+ function sortByTreeOrder(a, b) {
3774
+ return a.sortNodePosition(b);
2203
3775
  }
2204
- var wrapHandler = function (handler, shouldFilterPrimaryPointer) {
2205
- if (shouldFilterPrimaryPointer === void 0) { shouldFilterPrimaryPointer = false; }
2206
- var listener = function (event) {
2207
- return handler(event, extractEventInfo(event));
2208
- };
2209
- return shouldFilterPrimaryPointer
2210
- ? filterPrimaryPointer(listener)
2211
- : listener;
2212
- };
2213
-
2214
- function addDomEvent(target, eventName, handler, options) {
2215
- target.addEventListener(eventName, handler, options);
2216
- return function () { return target.removeEventListener(eventName, handler, options); };
3776
+ /**
3777
+ * Decide whether we should block this animation. Previously, we achieved this
3778
+ * just by checking whether the key was listed in protectedKeys, but this
3779
+ * posed problems if an animation was triggered by afterChildren and protectedKeys
3780
+ * had been set to true in the meantime.
3781
+ */
3782
+ function shouldBlockAnimation(_a, key) {
3783
+ var protectedKeys = _a.protectedKeys, needsAnimating = _a.needsAnimating;
3784
+ var shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
3785
+ needsAnimating[key] = false;
3786
+ return shouldBlock;
2217
3787
  }
2218
3788
 
2219
- // We check for event support via functions in case they've been mocked by a testing suite.
2220
- var supportsPointerEvents = function () {
2221
- return isBrowser && window.onpointerdown === null;
2222
- };
2223
- var supportsTouchEvents = function () {
2224
- return isBrowser && window.ontouchstart === null;
2225
- };
2226
- var supportsMouseEvents = function () {
2227
- return isBrowser && window.onmousedown === null;
2228
- };
2229
-
2230
- var mouseEventNames = {
2231
- pointerdown: "mousedown",
2232
- pointermove: "mousemove",
2233
- pointerup: "mouseup",
2234
- pointercancel: "mousecancel",
2235
- pointerover: "mouseover",
2236
- pointerout: "mouseout",
2237
- pointerenter: "mouseenter",
2238
- pointerleave: "mouseleave",
2239
- };
2240
- var touchEventNames = {
2241
- pointerdown: "touchstart",
2242
- pointermove: "touchmove",
2243
- pointerup: "touchend",
2244
- pointercancel: "touchcancel",
2245
- };
2246
- function getPointerEventName(name) {
2247
- if (supportsPointerEvents()) {
2248
- return name;
2249
- }
2250
- else if (supportsTouchEvents()) {
2251
- return touchEventNames[name];
3789
+ var variantPriorityOrder = [
3790
+ exports.AnimationType.Animate,
3791
+ exports.AnimationType.InView,
3792
+ exports.AnimationType.Focus,
3793
+ exports.AnimationType.Hover,
3794
+ exports.AnimationType.Tap,
3795
+ exports.AnimationType.Drag,
3796
+ exports.AnimationType.Exit,
3797
+ ];
3798
+ var reversePriorityOrder = tslib.__spreadArray([], tslib.__read(variantPriorityOrder), false).reverse();
3799
+ var numAnimationTypes = variantPriorityOrder.length;
3800
+ function animateList(visualElement) {
3801
+ return function (animations) {
3802
+ return Promise.all(animations.map(function (_a) {
3803
+ var animation = _a.animation, options = _a.options;
3804
+ return animateVisualElement(visualElement, animation, options);
3805
+ }));
3806
+ };
3807
+ }
3808
+ function createAnimationState(visualElement) {
3809
+ var animate = animateList(visualElement);
3810
+ var state = createState();
3811
+ var allAnimatedKeys = {};
3812
+ var isInitialRender = true;
3813
+ /**
3814
+ * This function will be used to reduce the animation definitions for
3815
+ * each active animation type into an object of resolved values for it.
3816
+ */
3817
+ var buildResolvedTypeValues = function (acc, definition) {
3818
+ var resolved = resolveVariant(visualElement, definition);
3819
+ if (resolved) {
3820
+ resolved.transition; var transitionEnd = resolved.transitionEnd, target = tslib.__rest(resolved, ["transition", "transitionEnd"]);
3821
+ acc = tslib.__assign(tslib.__assign(tslib.__assign({}, acc), target), transitionEnd);
3822
+ }
3823
+ return acc;
3824
+ };
3825
+ function isAnimated(key) {
3826
+ return allAnimatedKeys[key] !== undefined;
2252
3827
  }
2253
- else if (supportsMouseEvents()) {
2254
- return mouseEventNames[name];
3828
+ /**
3829
+ * This just allows us to inject mocked animation functions
3830
+ * @internal
3831
+ */
3832
+ function setAnimateFunction(makeAnimator) {
3833
+ animate = makeAnimator(visualElement);
2255
3834
  }
2256
- return name;
2257
- }
2258
- function addPointerEvent(target, eventName, handler, options) {
2259
- return addDomEvent(target, getPointerEventName(eventName), wrapHandler(handler, eventName === "pointerdown"), options);
2260
- }
2261
-
2262
- function createLock(name) {
2263
- var lock = null;
2264
- return function () {
2265
- var openLock = function () {
2266
- lock = null;
3835
+ /**
3836
+ * When we receive new props, we need to:
3837
+ * 1. Create a list of protected keys for each type. This is a directory of
3838
+ * value keys that are currently being "handled" by types of a higher priority
3839
+ * so that whenever an animation is played of a given type, these values are
3840
+ * protected from being animated.
3841
+ * 2. Determine if an animation type needs animating.
3842
+ * 3. Determine if any values have been removed from a type and figure out
3843
+ * what to animate those to.
3844
+ */
3845
+ function animateChanges(options, changedActiveType) {
3846
+ var _a;
3847
+ var props = visualElement.getProps();
3848
+ var context = visualElement.getVariantContext(true) || {};
3849
+ /**
3850
+ * A list of animations that we'll build into as we iterate through the animation
3851
+ * types. This will get executed at the end of the function.
3852
+ */
3853
+ var animations = [];
3854
+ /**
3855
+ * Keep track of which values have been removed. Then, as we hit lower priority
3856
+ * animation types, we can check if they contain removed values and animate to that.
3857
+ */
3858
+ var removedKeys = new Set();
3859
+ /**
3860
+ * A dictionary of all encountered keys. This is an object to let us build into and
3861
+ * copy it without iteration. Each time we hit an animation type we set its protected
3862
+ * keys - the keys its not allowed to animate - to the latest version of this object.
3863
+ */
3864
+ var encounteredKeys = {};
3865
+ /**
3866
+ * If a variant has been removed at a given index, and this component is controlling
3867
+ * variant animations, we want to ensure lower-priority variants are forced to animate.
3868
+ */
3869
+ var removedVariantIndex = Infinity;
3870
+ var _loop_1 = function (i) {
3871
+ var type = reversePriorityOrder[i];
3872
+ var typeState = state[type];
3873
+ var prop = (_a = props[type]) !== null && _a !== void 0 ? _a : context[type];
3874
+ var propIsVariant = isVariantLabel(prop);
3875
+ /**
3876
+ * If this type has *just* changed isActive status, set activeDelta
3877
+ * to that status. Otherwise set to null.
3878
+ */
3879
+ var activeDelta = type === changedActiveType ? typeState.isActive : null;
3880
+ if (activeDelta === false)
3881
+ removedVariantIndex = i;
3882
+ /**
3883
+ * If this prop is an inherited variant, rather than been set directly on the
3884
+ * component itself, we want to make sure we allow the parent to trigger animations.
3885
+ *
3886
+ * TODO: Can probably change this to a !isControllingVariants check
3887
+ */
3888
+ var isInherited = prop === context[type] && prop !== props[type] && propIsVariant;
3889
+ /**
3890
+ *
3891
+ */
3892
+ if (isInherited &&
3893
+ isInitialRender &&
3894
+ visualElement.manuallyAnimateOnMount) {
3895
+ isInherited = false;
3896
+ }
3897
+ /**
3898
+ * Set all encountered keys so far as the protected keys for this type. This will
3899
+ * be any key that has been animated or otherwise handled by active, higher-priortiy types.
3900
+ */
3901
+ typeState.protectedKeys = tslib.__assign({}, encounteredKeys);
3902
+ // Check if we can skip analysing this prop early
3903
+ if (
3904
+ // If it isn't active and hasn't *just* been set as inactive
3905
+ (!typeState.isActive && activeDelta === null) ||
3906
+ // If we didn't and don't have any defined prop for this animation type
3907
+ (!prop && !typeState.prevProp) ||
3908
+ // Or if the prop doesn't define an animation
3909
+ isAnimationControls(prop) ||
3910
+ typeof prop === "boolean") {
3911
+ return "continue";
3912
+ }
3913
+ /**
3914
+ * As we go look through the values defined on this type, if we detect
3915
+ * a changed value or a value that was removed in a higher priority, we set
3916
+ * this to true and add this prop to the animation list.
3917
+ */
3918
+ var variantDidChange = checkVariantsDidChange(typeState.prevProp, prop);
3919
+ var shouldAnimateType = variantDidChange ||
3920
+ // If we're making this variant active, we want to always make it active
3921
+ (type === changedActiveType &&
3922
+ typeState.isActive &&
3923
+ !isInherited &&
3924
+ propIsVariant) ||
3925
+ // If we removed a higher-priority variant (i is in reverse order)
3926
+ (i > removedVariantIndex && propIsVariant);
3927
+ /**
3928
+ * As animations can be set as variant lists, variants or target objects, we
3929
+ * coerce everything to an array if it isn't one already
3930
+ */
3931
+ var definitionList = Array.isArray(prop) ? prop : [prop];
3932
+ /**
3933
+ * Build an object of all the resolved values. We'll use this in the subsequent
3934
+ * animateChanges calls to determine whether a value has changed.
3935
+ */
3936
+ var resolvedValues = definitionList.reduce(buildResolvedTypeValues, {});
3937
+ if (activeDelta === false)
3938
+ resolvedValues = {};
3939
+ /**
3940
+ * Now we need to loop through all the keys in the prev prop and this prop,
3941
+ * and decide:
3942
+ * 1. If the value has changed, and needs animating
3943
+ * 2. If it has been removed, and needs adding to the removedKeys set
3944
+ * 3. If it has been removed in a higher priority type and needs animating
3945
+ * 4. If it hasn't been removed in a higher priority but hasn't changed, and
3946
+ * needs adding to the type's protectedKeys list.
3947
+ */
3948
+ var _b = typeState.prevResolvedValues, prevResolvedValues = _b === void 0 ? {} : _b;
3949
+ var allKeys = tslib.__assign(tslib.__assign({}, prevResolvedValues), resolvedValues);
3950
+ var markToAnimate = function (key) {
3951
+ shouldAnimateType = true;
3952
+ removedKeys.delete(key);
3953
+ typeState.needsAnimating[key] = true;
3954
+ };
3955
+ for (var key in allKeys) {
3956
+ var next = resolvedValues[key];
3957
+ var prev = prevResolvedValues[key];
3958
+ // If we've already handled this we can just skip ahead
3959
+ if (encounteredKeys.hasOwnProperty(key))
3960
+ continue;
3961
+ /**
3962
+ * If the value has changed, we probably want to animate it.
3963
+ */
3964
+ if (next !== prev) {
3965
+ /**
3966
+ * If both values are keyframes, we need to shallow compare them to
3967
+ * detect whether any value has changed. If it has, we animate it.
3968
+ */
3969
+ if (isKeyframesTarget(next) && isKeyframesTarget(prev)) {
3970
+ if (!shallowCompare(next, prev) || variantDidChange) {
3971
+ markToAnimate(key);
3972
+ }
3973
+ else {
3974
+ /**
3975
+ * If it hasn't changed, we want to ensure it doesn't animate by
3976
+ * adding it to the list of protected keys.
3977
+ */
3978
+ typeState.protectedKeys[key] = true;
3979
+ }
3980
+ }
3981
+ else if (next !== undefined) {
3982
+ // If next is defined and doesn't equal prev, it needs animating
3983
+ markToAnimate(key);
3984
+ }
3985
+ else {
3986
+ // If it's undefined, it's been removed.
3987
+ removedKeys.add(key);
3988
+ }
3989
+ }
3990
+ else if (next !== undefined && removedKeys.has(key)) {
3991
+ /**
3992
+ * If next hasn't changed and it isn't undefined, we want to check if it's
3993
+ * been removed by a higher priority
3994
+ */
3995
+ markToAnimate(key);
3996
+ }
3997
+ else {
3998
+ /**
3999
+ * If it hasn't changed, we add it to the list of protected values
4000
+ * to ensure it doesn't get animated.
4001
+ */
4002
+ typeState.protectedKeys[key] = true;
4003
+ }
4004
+ }
4005
+ /**
4006
+ * Update the typeState so next time animateChanges is called we can compare the
4007
+ * latest prop and resolvedValues to these.
4008
+ */
4009
+ typeState.prevProp = prop;
4010
+ typeState.prevResolvedValues = resolvedValues;
4011
+ /**
4012
+ *
4013
+ */
4014
+ if (typeState.isActive) {
4015
+ encounteredKeys = tslib.__assign(tslib.__assign({}, encounteredKeys), resolvedValues);
4016
+ }
4017
+ if (isInitialRender && visualElement.blockInitialAnimation) {
4018
+ shouldAnimateType = false;
4019
+ }
4020
+ /**
4021
+ * If this is an inherited prop we want to hard-block animations
4022
+ * TODO: Test as this should probably still handle animations triggered
4023
+ * by removed values?
4024
+ */
4025
+ if (shouldAnimateType && !isInherited) {
4026
+ animations.push.apply(animations, tslib.__spreadArray([], tslib.__read(definitionList.map(function (animation) { return ({
4027
+ animation: animation,
4028
+ options: tslib.__assign({ type: type }, options),
4029
+ }); })), false));
4030
+ }
2267
4031
  };
2268
- if (lock === null) {
2269
- lock = name;
2270
- return openLock;
4032
+ /**
4033
+ * Iterate through all animation types in reverse priority order. For each, we want to
4034
+ * detect which values it's handling and whether or not they've changed (and therefore
4035
+ * need to be animated). If any values have been removed, we want to detect those in
4036
+ * lower priority props and flag for animation.
4037
+ */
4038
+ for (var i = 0; i < numAnimationTypes; i++) {
4039
+ _loop_1(i);
2271
4040
  }
2272
- return false;
2273
- };
2274
- }
2275
- var globalHorizontalLock = createLock("dragHorizontal");
2276
- var globalVerticalLock = createLock("dragVertical");
2277
- function getGlobalLock(drag) {
2278
- var lock = false;
2279
- if (drag === "y") {
2280
- lock = globalVerticalLock();
2281
- }
2282
- else if (drag === "x") {
2283
- lock = globalHorizontalLock();
2284
- }
2285
- else {
2286
- var openHorizontal_1 = globalHorizontalLock();
2287
- var openVertical_1 = globalVerticalLock();
2288
- if (openHorizontal_1 && openVertical_1) {
2289
- lock = function () {
2290
- openHorizontal_1();
2291
- openVertical_1();
2292
- };
4041
+ allAnimatedKeys = tslib.__assign({}, encounteredKeys);
4042
+ /**
4043
+ * If there are some removed value that haven't been dealt with,
4044
+ * we need to create a new animation that falls back either to the value
4045
+ * defined in the style prop, or the last read value.
4046
+ */
4047
+ if (removedKeys.size) {
4048
+ var fallbackAnimation_1 = {};
4049
+ removedKeys.forEach(function (key) {
4050
+ var fallbackTarget = visualElement.getBaseTarget(key);
4051
+ if (fallbackTarget !== undefined) {
4052
+ fallbackAnimation_1[key] = fallbackTarget;
4053
+ }
4054
+ });
4055
+ animations.push({ animation: fallbackAnimation_1 });
2293
4056
  }
2294
- else {
2295
- // Release the locks because we don't use them
2296
- if (openHorizontal_1)
2297
- openHorizontal_1();
2298
- if (openVertical_1)
2299
- openVertical_1();
4057
+ var shouldAnimate = Boolean(animations.length);
4058
+ if (isInitialRender &&
4059
+ props.initial === false &&
4060
+ !visualElement.manuallyAnimateOnMount) {
4061
+ shouldAnimate = false;
2300
4062
  }
4063
+ isInitialRender = false;
4064
+ return shouldAnimate ? animate(animations) : Promise.resolve();
2301
4065
  }
2302
- return lock;
2303
- }
2304
- function isDragActive() {
2305
- // Check the gesture lock - if we get it, it means no drag gesture is active
2306
- // and we can safely fire the tap gesture.
2307
- var openGestureLock = getGlobalLock(true);
2308
- if (!openGestureLock)
2309
- return true;
2310
- openGestureLock();
2311
- return false;
2312
- }
2313
-
2314
- function useTap(isStatic, _a, visualElement) {
2315
- var whileTap = _a.whileTap, onTapStart = _a.onTapStart, onTap = _a.onTap, onTapCancel = _a.onTapCancel, onPointerDown = _a.onPointerDown;
2316
- var isTapEnabled = onTap || onTapStart || onTapCancel || whileTap;
2317
- var isPressing = React.useRef(false);
2318
- var cancelPointerEndListeners = React.useRef(null);
2319
- if (isStatic || !visualElement || !isTapEnabled)
2320
- return {};
2321
- function removePointerEndListener() {
2322
- var _a;
2323
- (_a = cancelPointerEndListeners.current) === null || _a === void 0 ? void 0 : _a.call(cancelPointerEndListeners);
2324
- cancelPointerEndListeners.current = null;
2325
- }
2326
- function checkPointerEnd() {
4066
+ /**
4067
+ * Change whether a certain animation type is active.
4068
+ */
4069
+ function setActive(type, isActive, options) {
2327
4070
  var _a;
2328
- removePointerEndListener();
2329
- isPressing.current = false;
2330
- (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Tap, false);
2331
- return !isDragActive();
4071
+ // If the active state hasn't changed, we can safely do nothing here
4072
+ if (state[type].isActive === isActive)
4073
+ return Promise.resolve();
4074
+ // Propagate active change to children
4075
+ (_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.forEach(function (child) { var _a; return (_a = child.animationState) === null || _a === void 0 ? void 0 : _a.setActive(type, isActive); });
4076
+ state[type].isActive = isActive;
4077
+ return animateChanges(options, type);
2332
4078
  }
2333
- function onPointerUp(event, info) {
2334
- if (!checkPointerEnd())
2335
- return;
2336
- /**
2337
- * We only count this as a tap gesture if the event.target is the same
2338
- * as, or a child of, this component's element
2339
- */
2340
- onTap === null || onTap === void 0 ? void 0 : onTap(event, info);
4079
+ return {
4080
+ isAnimated: isAnimated,
4081
+ animateChanges: animateChanges,
4082
+ setActive: setActive,
4083
+ setAnimateFunction: setAnimateFunction,
4084
+ getState: function () { return state; },
4085
+ };
4086
+ }
4087
+ function checkVariantsDidChange(prev, next) {
4088
+ if (typeof next === "string") {
4089
+ return next !== prev;
2341
4090
  }
2342
- function onPointerCancel(event, info) {
2343
- if (!checkPointerEnd())
2344
- return;
2345
- onTapCancel === null || onTapCancel === void 0 ? void 0 : onTapCancel(event, info);
4091
+ else if (isVariantLabels(next)) {
4092
+ return !shallowCompare(next, prev);
2346
4093
  }
4094
+ return false;
4095
+ }
4096
+ function createTypeState(isActive) {
4097
+ if (isActive === void 0) { isActive = false; }
2347
4098
  return {
2348
- onPointerDown: wrapHandler(function (event, info) {
2349
- var _a;
2350
- removePointerEndListener();
2351
- if (isPressing.current)
2352
- return;
2353
- isPressing.current = true;
2354
- cancelPointerEndListeners.current = popmotion.pipe(addPointerEvent(window, "pointerup", onPointerUp), addPointerEvent(window, "pointercancel", onPointerCancel));
2355
- (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Tap, true);
2356
- onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
2357
- onTapStart === null || onTapStart === void 0 ? void 0 : onTapStart(event, info);
2358
- }, true),
4099
+ isActive: isActive,
4100
+ protectedKeys: {},
4101
+ needsAnimating: {},
4102
+ prevResolvedValues: {},
2359
4103
  };
2360
4104
  }
4105
+ function createState() {
4106
+ var _a;
4107
+ return _a = {},
4108
+ _a[exports.AnimationType.Animate] = createTypeState(true),
4109
+ _a[exports.AnimationType.InView] = createTypeState(),
4110
+ _a[exports.AnimationType.Hover] = createTypeState(),
4111
+ _a[exports.AnimationType.Tap] = createTypeState(),
4112
+ _a[exports.AnimationType.Drag] = createTypeState(),
4113
+ _a[exports.AnimationType.Focus] = createTypeState(),
4114
+ _a[exports.AnimationType.Exit] = createTypeState(),
4115
+ _a;
4116
+ }
2361
4117
 
2362
- var useRender = function (Component, props, _projectionId, ref, _state, isStatic, visualElement) {
2363
- return React.createElement(Component, tslib.__assign(tslib.__assign(tslib.__assign(tslib.__assign({ ref: ref }, filterProps(props, false, false)), { onUpdate: props.onInstanceUpdate }), useHover(isStatic, props, visualElement)), useTap(isStatic, props, visualElement)));
4118
+ var animations = {
4119
+ animation: makeRenderlessComponent(function (_a) {
4120
+ var visualElement = _a.visualElement, animate = _a.animate;
4121
+ /**
4122
+ * We dynamically generate the AnimationState manager as it contains a reference
4123
+ * to the underlying animation library. We only want to load that if we load this,
4124
+ * so people can optionally code split it out using the `m` component.
4125
+ */
4126
+ visualElement.animationState || (visualElement.animationState = createAnimationState(visualElement));
4127
+ /**
4128
+ * Subscribe any provided AnimationControls to the component's VisualElement
4129
+ */
4130
+ if (isAnimationControls(animate)) {
4131
+ React.useEffect(function () { return animate.subscribe(visualElement); }, [animate]);
4132
+ }
4133
+ }),
4134
+ exit: makeRenderlessComponent(function (props) {
4135
+ var custom = props.custom, visualElement = props.visualElement;
4136
+ var _a = tslib.__read(usePresence(), 2), isPresent = _a[0], safeToRemove = _a[1];
4137
+ var presenceContext = React.useContext(PresenceContext);
4138
+ React.useEffect(function () {
4139
+ var _a, _b;
4140
+ visualElement.isPresent = isPresent;
4141
+ var animation = (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(exports.AnimationType.Exit, !isPresent, { custom: (_b = presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.custom) !== null && _b !== void 0 ? _b : custom });
4142
+ !isPresent && (animation === null || animation === void 0 ? void 0 : animation.then(safeToRemove));
4143
+ }, [isPresent]);
4144
+ }),
2364
4145
  };
2365
4146
 
2366
4147
  var names = [
@@ -2838,197 +4619,6 @@ var visualElement = function (_a) {
2838
4619
  var variantProps = tslib.__spreadArray(["initial"], tslib.__read(variantPriorityOrder), false);
2839
4620
  var numVariantProps = variantProps.length;
2840
4621
 
2841
- var setVector = function (name, defaultValue) {
2842
- return function (i) {
2843
- return function (instance, value) {
2844
- var _a;
2845
- (_a = instance[name]) !== null && _a !== void 0 ? _a : (instance[name] = new three.Vector3(defaultValue));
2846
- var vector = instance[name];
2847
- vector.setComponent(i, value);
2848
- };
2849
- };
2850
- };
2851
- var setEuler = function (name, defaultValue) {
2852
- return function (axis) {
2853
- return function (instance, value) {
2854
- var _a;
2855
- (_a = instance[name]) !== null && _a !== void 0 ? _a : (instance[name] = new three.Euler(defaultValue));
2856
- var euler = instance[name];
2857
- euler[axis] = value;
2858
- };
2859
- };
2860
- };
2861
- var setColor = function (name) { return function (instance, value) {
2862
- var _a;
2863
- (_a = instance[name]) !== null && _a !== void 0 ? _a : (instance[name] = new three.Color(value));
2864
- instance[name].set(value);
2865
- }; };
2866
- var setScale = setVector("scale", 1);
2867
- var setPosition = setVector("position", 0);
2868
- var setRotation = setEuler("rotation", 0);
2869
- var setters = {
2870
- x: setPosition(0),
2871
- y: setPosition(1),
2872
- z: setPosition(2),
2873
- scale: function (instance, value) {
2874
- var _a;
2875
- (_a = instance.scale) !== null && _a !== void 0 ? _a : (instance.scale = new three.Vector3(1));
2876
- var scale = instance.scale;
2877
- scale.set(value, value, value);
2878
- },
2879
- scaleX: setScale(0),
2880
- scaleY: setScale(1),
2881
- scaleZ: setScale(2),
2882
- rotateX: setRotation("x"),
2883
- rotateY: setRotation("y"),
2884
- rotateZ: setRotation("z"),
2885
- color: setColor("color"),
2886
- specular: setColor("specular"),
2887
- };
2888
- function setThreeValue(instance, key, values) {
2889
- if (setters[key]) {
2890
- setters[key](instance, values[key]);
2891
- }
2892
- else {
2893
- instance[key] = values[key];
2894
- }
2895
- }
2896
-
2897
- var readVector = function (name, defaultValue) {
2898
- return function (axis) {
2899
- return function (instance) {
2900
- var value = instance[name];
2901
- return value ? value[axis] : defaultValue;
2902
- };
2903
- };
2904
- };
2905
- var readPosition = readVector("position", 0);
2906
- var readScale = readVector("scale", 1);
2907
- var readRotation = readVector("rotation", 0);
2908
- var readers = {
2909
- x: readPosition("x"),
2910
- y: readPosition("y"),
2911
- z: readPosition("z"),
2912
- scale: readScale("x"),
2913
- scaleX: readScale("x"),
2914
- scaleY: readScale("y"),
2915
- scaleZ: readScale("z"),
2916
- rotateX: readRotation("x"),
2917
- rotateY: readRotation("y"),
2918
- rotateZ: readRotation("z"),
2919
- };
2920
- function readAnimatableValue(value) {
2921
- if (!value)
2922
- return;
2923
- if (value instanceof three.Color) {
2924
- return value.getStyle();
2925
- }
2926
- else {
2927
- return value;
2928
- }
2929
- }
2930
- function readThreeValue(instance, name) {
2931
- var _a;
2932
- return readers[name]
2933
- ? readers[name](instance)
2934
- : (_a = readAnimatableValue(instance[name])) !== null && _a !== void 0 ? _a : 0;
2935
- }
2936
-
2937
- var axes = ["x", "y", "z"];
2938
- var valueMap = {
2939
- "position-x": "x",
2940
- "position-y": "y",
2941
- "position-z": "z",
2942
- "rotation-x": "rotateX",
2943
- "rotation-y": "rotateY",
2944
- "rotation-z": "rotateZ",
2945
- "scale-x": "scaleX",
2946
- "scale-y": "scaleY",
2947
- "scale-z": "scaleZ",
2948
- };
2949
- var scrapeMotionValuesFromProps = function (props) {
2950
- var motionValues = {};
2951
- for (var key in props) {
2952
- var prop = props[key];
2953
- if (isMotionValue(prop)) {
2954
- motionValues[valueMap[key] || key] = prop;
2955
- }
2956
- else if (Array.isArray(prop)) {
2957
- for (var i = 0; i < prop.length; i++) {
2958
- var value = prop[i];
2959
- if (isMotionValue(value)) {
2960
- var name_1 = valueMap[key + "-" + axes[i]];
2961
- motionValues[name_1] = value;
2962
- }
2963
- }
2964
- }
2965
- }
2966
- return motionValues;
2967
- };
2968
-
2969
- var createRenderState = function () { return ({}); };
2970
- var threeVisualElement = visualElement({
2971
- treeType: "three",
2972
- readValueFromInstance: readThreeValue,
2973
- getBaseTarget: function () {
2974
- return undefined;
2975
- },
2976
- sortNodePosition: function (a, b) {
2977
- return a.id - b.id;
2978
- },
2979
- makeTargetAnimatable: function (element, target) {
2980
- checkTargetForNewValues(element, target, {});
2981
- return target;
2982
- },
2983
- restoreTransform: function () { },
2984
- resetTransform: function () { },
2985
- removeValueFromRenderState: function (_key, _renderState) { },
2986
- measureViewportBox: createBox,
2987
- scrapeMotionValuesFromProps: scrapeMotionValuesFromProps,
2988
- build: function (_element, state, latestValues) {
2989
- for (var key in latestValues) {
2990
- state[key] = latestValues[key];
2991
- }
2992
- },
2993
- render: function (instance, renderState) {
2994
- for (var key in renderState) {
2995
- setThreeValue(instance, key, renderState);
2996
- }
2997
- },
2998
- });
2999
- var createVisualElement = function (_, options) {
3000
- return threeVisualElement(options);
3001
- };
3002
-
3003
- var useVisualState = makeUseVisualState({
3004
- scrapeMotionValuesFromProps: scrapeMotionValuesFromProps,
3005
- createRenderState: createRenderState,
3006
- });
3007
- var preloadedFeatures = tslib.__assign({}, animations);
3008
- function custom(Component) {
3009
- return createMotionComponent({
3010
- Component: Component,
3011
- preloadedFeatures: preloadedFeatures,
3012
- useRender: useRender,
3013
- useVisualState: useVisualState,
3014
- createVisualElement: createVisualElement,
3015
- });
3016
- }
3017
- var componentCache = new Map();
3018
- var motion = new Proxy(custom, {
3019
- get: function (_, key) {
3020
- !componentCache.has(key) && componentCache.set(key, custom(key));
3021
- return componentCache.get(key);
3022
- },
3023
- });
3024
-
3025
- function MotionCanvas(_a) {
3026
- var children = _a.children, props = tslib.__rest(_a, ["children"]);
3027
- var motionContext = React.useContext(MotionContext);
3028
- return (React__namespace.createElement(fiber.Canvas, tslib.__assign({}, props),
3029
- React__namespace.createElement(MotionContext.Provider, { value: motionContext }, children)));
3030
- }
3031
-
3032
4622
  /**
3033
4623
  * Creates a `MotionValue` to track the state and velocity of a value.
3034
4624
  *
@@ -3061,12 +4651,65 @@ function useMotionValue(initial) {
3061
4651
  return value;
3062
4652
  }
3063
4653
 
3064
- function useTime() {
3065
- var time = useMotionValue(0);
3066
- fiber.useFrame(function (state) { return time.set(state.clock.getElapsedTime()); });
3067
- return time;
3068
- }
3069
-
3070
- exports.MotionCanvas = MotionCanvas;
3071
- exports.motion = motion;
3072
- exports.useTime = useTime;
4654
+ exports.FlatTree = FlatTree;
4655
+ exports.LayoutGroupContext = LayoutGroupContext;
4656
+ exports.LazyContext = LazyContext;
4657
+ exports.MotionConfigContext = MotionConfigContext;
4658
+ exports.MotionContext = MotionContext;
4659
+ exports.MotionValue = MotionValue;
4660
+ exports.PresenceContext = PresenceContext;
4661
+ exports.SwitchLayoutGroupContext = SwitchLayoutGroupContext;
4662
+ exports.addDomEvent = addDomEvent;
4663
+ exports.addPointerEvent = addPointerEvent;
4664
+ exports.addScaleCorrector = addScaleCorrector;
4665
+ exports.animate = animate;
4666
+ exports.animateVisualElement = animateVisualElement;
4667
+ exports.animations = animations;
4668
+ exports.calcLength = calcLength;
4669
+ exports.checkTargetForNewValues = checkTargetForNewValues;
4670
+ exports.createBox = createBox;
4671
+ exports.createMotionComponent = createMotionComponent;
4672
+ exports.createProjectionNode = createProjectionNode;
4673
+ exports.eachAxis = eachAxis;
4674
+ exports.extractEventInfo = extractEventInfo;
4675
+ exports.filterProps = filterProps;
4676
+ exports.findDimensionValueType = findDimensionValueType;
4677
+ exports.getDefaultValueType = getDefaultValueType;
4678
+ exports.getGlobalLock = getGlobalLock;
4679
+ exports.getOrigin = getOrigin;
4680
+ exports.globalProjectionState = globalProjectionState;
4681
+ exports.instantAnimationState = instantAnimationState;
4682
+ exports.isDragActive = isDragActive;
4683
+ exports.isKeyframesTarget = isKeyframesTarget;
4684
+ exports.isMotionValue = isMotionValue;
4685
+ exports.isMouseEvent = isMouseEvent;
4686
+ exports.isRefObject = isRefObject;
4687
+ exports.isTouchEvent = isTouchEvent;
4688
+ exports.isTransformOriginProp = isTransformOriginProp;
4689
+ exports.isTransformProp = isTransformProp;
4690
+ exports.isValidMotionProp = isValidMotionProp;
4691
+ exports.loadFeatures = loadFeatures;
4692
+ exports.makeRenderlessComponent = makeRenderlessComponent;
4693
+ exports.makeUseVisualState = makeUseVisualState;
4694
+ exports.motionValue = motionValue;
4695
+ exports.moveItem = moveItem;
4696
+ exports.numberValueTypes = numberValueTypes;
4697
+ exports.resolveMotionValue = resolveMotionValue;
4698
+ exports.scaleCorrectors = scaleCorrectors;
4699
+ exports.secondsToMilliseconds = secondsToMilliseconds;
4700
+ exports.setValues = setValues;
4701
+ exports.sortTransformProps = sortTransformProps;
4702
+ exports.startAnimation = startAnimation;
4703
+ exports.stopAnimation = stopAnimation;
4704
+ exports.transformProps = transformProps;
4705
+ exports.translateAxis = translateAxis;
4706
+ exports.useConstant = useConstant;
4707
+ exports.useDomEvent = useDomEvent;
4708
+ exports.useIsPresent = useIsPresent;
4709
+ exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
4710
+ exports.useMotionValue = useMotionValue;
4711
+ exports.usePointerEvent = usePointerEvent;
4712
+ exports.usePresence = usePresence;
4713
+ exports.useVisualElementContext = useVisualElementContext;
4714
+ exports.visualElement = visualElement;
4715
+ exports.wrapHandler = wrapHandler;