framer-motion 10.1.0-alpha.3 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
- var wrap = require('./wrap-e6a894d7.js');
7
6
 
8
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
8
 
@@ -459,20 +458,49 @@ function addScaleCorrector(correctors) {
459
458
  Object.assign(scaleCorrectors, correctors);
460
459
  }
461
460
 
461
+ /**
462
+ * Generate a list of every possible transform key.
463
+ */
464
+ const transformPropOrder = [
465
+ "transformPerspective",
466
+ "x",
467
+ "y",
468
+ "z",
469
+ "translateX",
470
+ "translateY",
471
+ "translateZ",
472
+ "scale",
473
+ "scaleX",
474
+ "scaleY",
475
+ "rotate",
476
+ "rotateX",
477
+ "rotateY",
478
+ "rotateZ",
479
+ "skew",
480
+ "skewX",
481
+ "skewY",
482
+ ];
483
+ /**
484
+ * A quick lookup for transform props.
485
+ */
486
+ const transformProps = new Set(transformPropOrder);
487
+
462
488
  function isForcedMotionValue(key, { layout, layoutId }) {
463
- return (wrap.transformProps.has(key) ||
489
+ return (transformProps.has(key) ||
464
490
  key.startsWith("origin") ||
465
491
  ((layout || layoutId !== undefined) &&
466
492
  (!!scaleCorrectors[key] || key === "opacity")));
467
493
  }
468
494
 
495
+ const isMotionValue = (value) => Boolean(value && value.getVelocity);
496
+
469
497
  const translateAlias = {
470
498
  x: "translateX",
471
499
  y: "translateY",
472
500
  z: "translateZ",
473
501
  transformPerspective: "perspective",
474
502
  };
475
- const numTransforms = wrap.transformPropOrder.length;
503
+ const numTransforms = transformPropOrder.length;
476
504
  /**
477
505
  * Build a CSS transform style from individual x/y/scale etc properties.
478
506
  *
@@ -487,7 +515,7 @@ function buildTransform(transform, { enableHardwareAcceleration = true, allowTra
487
515
  * are present to the transform string.
488
516
  */
489
517
  for (let i = 0; i < numTransforms; i++) {
490
- const key = wrap.transformPropOrder[i];
518
+ const key = transformPropOrder[i];
491
519
  if (transform[key] !== undefined) {
492
520
  const transformName = translateAlias[key] || key;
493
521
  transformString += `${transformName}(${transform[key]}) `;
@@ -521,6 +549,124 @@ const getValueAsType = (value, type) => {
521
549
  : value;
522
550
  };
523
551
 
552
+ const clamp = (min, max, v) => Math.min(Math.max(v, min), max);
553
+
554
+ const number = {
555
+ test: (v) => typeof v === "number",
556
+ parse: parseFloat,
557
+ transform: (v) => v,
558
+ };
559
+ const alpha = {
560
+ ...number,
561
+ transform: (v) => clamp(0, 1, v),
562
+ };
563
+ const scale = {
564
+ ...number,
565
+ default: 1,
566
+ };
567
+
568
+ /**
569
+ * TODO: When we move from string as a source of truth to data models
570
+ * everything in this folder should probably be referred to as models vs types
571
+ */
572
+ // If this number is a decimal, make it just five decimal places
573
+ // to avoid exponents
574
+ const sanitize = (v) => Math.round(v * 100000) / 100000;
575
+ const floatRegex = /(-)?([\d]*\.?[\d])+/g;
576
+ const colorRegex = /(#[0-9a-f]{3,8}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))/gi;
577
+ const singleColorRegex = /^(#[0-9a-f]{3,8}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
578
+ function isString(v) {
579
+ return typeof v === "string";
580
+ }
581
+
582
+ const createUnitType = (unit) => ({
583
+ test: (v) => isString(v) && v.endsWith(unit) && v.split(" ").length === 1,
584
+ parse: parseFloat,
585
+ transform: (v) => `${v}${unit}`,
586
+ });
587
+ const degrees = createUnitType("deg");
588
+ const percent = createUnitType("%");
589
+ const px = createUnitType("px");
590
+ const vh = createUnitType("vh");
591
+ const vw = createUnitType("vw");
592
+ const progressPercentage = {
593
+ ...percent,
594
+ parse: (v) => percent.parse(v) / 100,
595
+ transform: (v) => percent.transform(v * 100),
596
+ };
597
+
598
+ const int = {
599
+ ...number,
600
+ transform: Math.round,
601
+ };
602
+
603
+ const numberValueTypes = {
604
+ // Border props
605
+ borderWidth: px,
606
+ borderTopWidth: px,
607
+ borderRightWidth: px,
608
+ borderBottomWidth: px,
609
+ borderLeftWidth: px,
610
+ borderRadius: px,
611
+ radius: px,
612
+ borderTopLeftRadius: px,
613
+ borderTopRightRadius: px,
614
+ borderBottomRightRadius: px,
615
+ borderBottomLeftRadius: px,
616
+ // Positioning props
617
+ width: px,
618
+ maxWidth: px,
619
+ height: px,
620
+ maxHeight: px,
621
+ size: px,
622
+ top: px,
623
+ right: px,
624
+ bottom: px,
625
+ left: px,
626
+ // Spacing props
627
+ padding: px,
628
+ paddingTop: px,
629
+ paddingRight: px,
630
+ paddingBottom: px,
631
+ paddingLeft: px,
632
+ margin: px,
633
+ marginTop: px,
634
+ marginRight: px,
635
+ marginBottom: px,
636
+ marginLeft: px,
637
+ // Transform props
638
+ rotate: degrees,
639
+ rotateX: degrees,
640
+ rotateY: degrees,
641
+ rotateZ: degrees,
642
+ scale,
643
+ scaleX: scale,
644
+ scaleY: scale,
645
+ scaleZ: scale,
646
+ skew: degrees,
647
+ skewX: degrees,
648
+ skewY: degrees,
649
+ distance: px,
650
+ translateX: px,
651
+ translateY: px,
652
+ translateZ: px,
653
+ x: px,
654
+ y: px,
655
+ z: px,
656
+ perspective: px,
657
+ transformPerspective: px,
658
+ opacity: alpha,
659
+ originX: progressPercentage,
660
+ originY: progressPercentage,
661
+ originZ: px,
662
+ // Misc
663
+ zIndex: int,
664
+ // SVG
665
+ fillOpacity: alpha,
666
+ strokeOpacity: alpha,
667
+ numOctaves: int,
668
+ };
669
+
524
670
  function buildHTMLStyles(state, latestValues, options, transformTemplate) {
525
671
  const { style, vars, transform, transformOrigin } = state;
526
672
  // Track whether we encounter any transform or transformOrigin values.
@@ -544,9 +690,9 @@ function buildHTMLStyles(state, latestValues, options, transformTemplate) {
544
690
  continue;
545
691
  }
546
692
  // Convert the value to its default value type, ie 0 -> "0px"
547
- const valueType = wrap.numberValueTypes[key];
693
+ const valueType = numberValueTypes[key];
548
694
  const valueAsType = getValueAsType(value, valueType);
549
- if (wrap.transformProps.has(key)) {
695
+ if (transformProps.has(key)) {
550
696
  // If this is a transform, flag to enable further transform processing
551
697
  hasTransform = true;
552
698
  transform[key] = valueAsType;
@@ -597,7 +743,7 @@ const createHtmlRenderState = () => ({
597
743
 
598
744
  function copyRawValuesOnly(target, source, props) {
599
745
  for (const key in source) {
600
- if (!wrap.isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
746
+ if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
601
747
  target[key] = source[key];
602
748
  }
603
749
  }
@@ -760,7 +906,7 @@ function filterProps(props, isDom, forwardMotionProps) {
760
906
  function calcOrigin$1(origin, offset, size) {
761
907
  return typeof origin === "string"
762
908
  ? origin
763
- : wrap.px.transform(offset + size * origin);
909
+ : px.transform(offset + size * origin);
764
910
  }
765
911
  /**
766
912
  * The SVG transform origin defaults are different to CSS and is less intuitive,
@@ -794,10 +940,10 @@ function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true
794
940
  // when defining props on a React component.
795
941
  const keys = useDashCase ? dashKeys : camelKeys;
796
942
  // Build the dash offset
797
- attrs[keys.offset] = wrap.px.transform(-offset);
943
+ attrs[keys.offset] = px.transform(-offset);
798
944
  // Build the dash array
799
- const pathLength = wrap.px.transform(length);
800
- const pathSpacing = wrap.px.transform(spacing);
945
+ const pathLength = px.transform(length);
946
+ const pathSpacing = px.transform(spacing);
801
947
  attrs[keys.array] = `${pathLength} ${pathSpacing}`;
802
948
  }
803
949
 
@@ -888,7 +1034,7 @@ function createUseRender(forwardMotionProps = false) {
888
1034
  * will be handled by the onChange handler
889
1035
  */
890
1036
  const { children } = props;
891
- const renderedChildren = React.useMemo(() => (wrap.isMotionValue(children) ? children.get() : children), [children]);
1037
+ const renderedChildren = React.useMemo(() => (isMotionValue(children) ? children.get() : children), [children]);
892
1038
  if (projectionId) {
893
1039
  elementProps["data-projection-id"] = projectionId;
894
1040
  }
@@ -953,8 +1099,8 @@ function scrapeMotionValuesFromProps$1(props, prevProps) {
953
1099
  const { style } = props;
954
1100
  const newValues = {};
955
1101
  for (const key in style) {
956
- if (wrap.isMotionValue(style[key]) ||
957
- (prevProps.style && wrap.isMotionValue(prevProps.style[key])) ||
1102
+ if (isMotionValue(style[key]) ||
1103
+ (prevProps.style && isMotionValue(prevProps.style[key])) ||
958
1104
  isForcedMotionValue(key, props)) {
959
1105
  newValues[key] = style[key];
960
1106
  }
@@ -965,7 +1111,7 @@ function scrapeMotionValuesFromProps$1(props, prevProps) {
965
1111
  function scrapeMotionValuesFromProps(props, prevProps) {
966
1112
  const newValues = scrapeMotionValuesFromProps$1(props, prevProps);
967
1113
  for (const key in props) {
968
- if (wrap.isMotionValue(props[key]) || wrap.isMotionValue(prevProps[key])) {
1114
+ if (isMotionValue(props[key]) || isMotionValue(prevProps[key])) {
969
1115
  const targetKey = key === "x" || key === "y" ? "attr" + key.toUpperCase() : key;
970
1116
  newValues[targetKey] = props[key];
971
1117
  }
@@ -1016,7 +1162,7 @@ const resolveFinalValueInKeyframes = (v) => {
1016
1162
  * TODO: Remove and move to library
1017
1163
  */
1018
1164
  function resolveMotionValue(value) {
1019
- const unwrappedValue = wrap.isMotionValue(value) ? value.get() : value;
1165
+ const unwrappedValue = isMotionValue(value) ? value.get() : value;
1020
1166
  return isCustomValue(unwrappedValue)
1021
1167
  ? unwrappedValue.toValue()
1022
1168
  : unwrappedValue;
@@ -1178,6 +1324,16 @@ function addPointerEvent(target, eventName, handler, options) {
1178
1324
  return addDomEvent(target, eventName, addPointerInfo(handler), options);
1179
1325
  }
1180
1326
 
1327
+ /**
1328
+ * Pipe
1329
+ * Compose other transformers to run linearily
1330
+ * pipe(min(20), max(40))
1331
+ * @param {...functions} transformers
1332
+ * @return {function}
1333
+ */
1334
+ const combineFunctions = (a, b) => (v) => b(a(v));
1335
+ const pipe = (...transformers) => transformers.reduce(combineFunctions);
1336
+
1181
1337
  function createLock(name) {
1182
1338
  let lock = null;
1183
1339
  return () => {
@@ -1238,6 +1394,163 @@ class Feature {
1238
1394
  update() { }
1239
1395
  }
1240
1396
 
1397
+ /*
1398
+ Detect and load appropriate clock setting for the execution environment
1399
+ */
1400
+ const defaultTimestep = (1 / 60) * 1000;
1401
+ const getCurrentTime = typeof performance !== "undefined"
1402
+ ? () => performance.now()
1403
+ : () => Date.now();
1404
+ const onNextFrame = typeof window !== "undefined"
1405
+ ? (callback) => window.requestAnimationFrame(callback)
1406
+ : (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
1407
+
1408
+ function createRenderStep(runNextFrame) {
1409
+ /**
1410
+ * We create and reuse two arrays, one to queue jobs for the current frame
1411
+ * and one for the next. We reuse to avoid triggering GC after x frames.
1412
+ */
1413
+ let toRun = [];
1414
+ let toRunNextFrame = [];
1415
+ /**
1416
+ *
1417
+ */
1418
+ let numToRun = 0;
1419
+ /**
1420
+ * Track whether we're currently processing jobs in this step. This way
1421
+ * we can decide whether to schedule new jobs for this frame or next.
1422
+ */
1423
+ let isProcessing = false;
1424
+ let flushNextFrame = false;
1425
+ /**
1426
+ * A set of processes which were marked keepAlive when scheduled.
1427
+ */
1428
+ const toKeepAlive = new WeakSet();
1429
+ const step = {
1430
+ /**
1431
+ * Schedule a process to run on the next frame.
1432
+ */
1433
+ schedule: (callback, keepAlive = false, immediate = false) => {
1434
+ const addToCurrentFrame = immediate && isProcessing;
1435
+ const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
1436
+ if (keepAlive)
1437
+ toKeepAlive.add(callback);
1438
+ // If the buffer doesn't already contain this callback, add it
1439
+ if (buffer.indexOf(callback) === -1) {
1440
+ buffer.push(callback);
1441
+ // If we're adding it to the currently running buffer, update its measured size
1442
+ if (addToCurrentFrame && isProcessing)
1443
+ numToRun = toRun.length;
1444
+ }
1445
+ return callback;
1446
+ },
1447
+ /**
1448
+ * Cancel the provided callback from running on the next frame.
1449
+ */
1450
+ cancel: (callback) => {
1451
+ const index = toRunNextFrame.indexOf(callback);
1452
+ if (index !== -1)
1453
+ toRunNextFrame.splice(index, 1);
1454
+ toKeepAlive.delete(callback);
1455
+ },
1456
+ /**
1457
+ * Execute all schedule callbacks.
1458
+ */
1459
+ process: (frameData) => {
1460
+ /**
1461
+ * If we're already processing we've probably been triggered by a flushSync
1462
+ * inside an existing process. Instead of executing, mark flushNextFrame
1463
+ * as true and ensure we flush the following frame at the end of this one.
1464
+ */
1465
+ if (isProcessing) {
1466
+ flushNextFrame = true;
1467
+ return;
1468
+ }
1469
+ isProcessing = true;
1470
+ [toRun, toRunNextFrame] = [toRunNextFrame, toRun];
1471
+ // Clear the next frame list
1472
+ toRunNextFrame.length = 0;
1473
+ // Execute this frame
1474
+ numToRun = toRun.length;
1475
+ if (numToRun) {
1476
+ for (let i = 0; i < numToRun; i++) {
1477
+ const callback = toRun[i];
1478
+ callback(frameData);
1479
+ if (toKeepAlive.has(callback)) {
1480
+ step.schedule(callback);
1481
+ runNextFrame();
1482
+ }
1483
+ }
1484
+ }
1485
+ isProcessing = false;
1486
+ if (flushNextFrame) {
1487
+ flushNextFrame = false;
1488
+ step.process(frameData);
1489
+ }
1490
+ },
1491
+ };
1492
+ return step;
1493
+ }
1494
+
1495
+ const frameData = {
1496
+ delta: 0,
1497
+ timestamp: 0,
1498
+ };
1499
+
1500
+ const maxElapsed$1 = 40;
1501
+ let useDefaultElapsed = true;
1502
+ let runNextFrame = false;
1503
+ let isProcessing = false;
1504
+ const stepsOrder = [
1505
+ "read",
1506
+ "update",
1507
+ "preRender",
1508
+ "render",
1509
+ "postRender",
1510
+ ];
1511
+ const steps = stepsOrder.reduce((acc, key) => {
1512
+ acc[key] = createRenderStep(() => (runNextFrame = true));
1513
+ return acc;
1514
+ }, {});
1515
+ const sync = stepsOrder.reduce((acc, key) => {
1516
+ const step = steps[key];
1517
+ acc[key] = (process, keepAlive = false, immediate = false) => {
1518
+ if (!runNextFrame)
1519
+ startLoop();
1520
+ return step.schedule(process, keepAlive, immediate);
1521
+ };
1522
+ return acc;
1523
+ }, {});
1524
+ const cancelSync = stepsOrder.reduce((acc, key) => {
1525
+ acc[key] = steps[key].cancel;
1526
+ return acc;
1527
+ }, {});
1528
+ const flushSync = stepsOrder.reduce((acc, key) => {
1529
+ acc[key] = () => steps[key].process(frameData);
1530
+ return acc;
1531
+ }, {});
1532
+ const processStep = (stepId) => steps[stepId].process(frameData);
1533
+ const processFrame = (timestamp) => {
1534
+ runNextFrame = false;
1535
+ frameData.delta = useDefaultElapsed
1536
+ ? defaultTimestep
1537
+ : Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed$1), 1);
1538
+ frameData.timestamp = timestamp;
1539
+ isProcessing = true;
1540
+ stepsOrder.forEach(processStep);
1541
+ isProcessing = false;
1542
+ if (runNextFrame) {
1543
+ useDefaultElapsed = false;
1544
+ onNextFrame(processFrame);
1545
+ }
1546
+ };
1547
+ const startLoop = () => {
1548
+ runNextFrame = true;
1549
+ useDefaultElapsed = true;
1550
+ if (!isProcessing)
1551
+ onNextFrame(processFrame);
1552
+ };
1553
+
1241
1554
  function addHoverEvent(node, isActive) {
1242
1555
  const eventName = "pointer" + (isActive ? "enter" : "leave");
1243
1556
  const callbackName = "onHover" + (isActive ? "Start" : "End");
@@ -1249,7 +1562,7 @@ function addHoverEvent(node, isActive) {
1249
1562
  node.animationState.setActive("whileHover", isActive);
1250
1563
  }
1251
1564
  if (props[callbackName]) {
1252
- props[callbackName](event, info);
1565
+ sync.update(() => props[callbackName](event, info));
1253
1566
  }
1254
1567
  };
1255
1568
  return addPointerEvent(node.current, eventName, handleEvent, {
@@ -1258,7 +1571,7 @@ function addHoverEvent(node, isActive) {
1258
1571
  }
1259
1572
  class HoverGesture extends Feature {
1260
1573
  mount() {
1261
- this.unmount = wrap.pipe(addHoverEvent(this.node, true), addHoverEvent(this.node, false));
1574
+ this.unmount = pipe(addHoverEvent(this.node, true), addHoverEvent(this.node, false));
1262
1575
  }
1263
1576
  unmount() { }
1264
1577
  }
@@ -1294,7 +1607,7 @@ class FocusGesture extends Feature {
1294
1607
  this.isActive = false;
1295
1608
  }
1296
1609
  mount() {
1297
- this.unmount = wrap.pipe(addDomEvent(this.node.current, "focus", () => this.onFocus()), addDomEvent(this.node.current, "blur", () => this.onBlur()));
1610
+ this.unmount = pipe(addDomEvent(this.node.current, "focus", () => this.onFocus()), addDomEvent(this.node.current, "blur", () => this.onBlur()));
1298
1611
  }
1299
1612
  unmount() { }
1300
1613
  }
@@ -1318,6 +1631,8 @@ const isNodeOrChild = (parent, child) => {
1318
1631
  }
1319
1632
  };
1320
1633
 
1634
+ const noop = (any) => any;
1635
+
1321
1636
  function fireSyntheticPointerEvent(name, handler) {
1322
1637
  if (!handler)
1323
1638
  return;
@@ -1327,9 +1642,9 @@ function fireSyntheticPointerEvent(name, handler) {
1327
1642
  class PressGesture extends Feature {
1328
1643
  constructor() {
1329
1644
  super(...arguments);
1330
- this.removeStartListeners = wrap.noop;
1331
- this.removeEndListeners = wrap.noop;
1332
- this.removeAccessibleListeners = wrap.noop;
1645
+ this.removeStartListeners = noop;
1646
+ this.removeEndListeners = noop;
1647
+ this.removeAccessibleListeners = noop;
1333
1648
  this.startPointerPress = (startEvent, startInfo) => {
1334
1649
  this.removeEndListeners();
1335
1650
  if (this.isPressing)
@@ -1339,17 +1654,19 @@ class PressGesture extends Feature {
1339
1654
  if (!this.checkPressEnd())
1340
1655
  return;
1341
1656
  const { onTap, onTapCancel } = this.node.getProps();
1342
- /**
1343
- * We only count this as a tap gesture if the event.target is the same
1344
- * as, or a child of, this component's element
1345
- */
1346
- !isNodeOrChild(this.node.current, endEvent.target)
1347
- ? onTapCancel && onTapCancel(endEvent, endInfo)
1348
- : onTap && onTap(endEvent, endInfo);
1657
+ sync.update(() => {
1658
+ /**
1659
+ * We only count this as a tap gesture if the event.target is the same
1660
+ * as, or a child of, this component's element
1661
+ */
1662
+ !isNodeOrChild(this.node.current, endEvent.target)
1663
+ ? onTapCancel && onTapCancel(endEvent, endInfo)
1664
+ : onTap && onTap(endEvent, endInfo);
1665
+ });
1349
1666
  };
1350
1667
  const removePointerUpListener = addPointerEvent(window, "pointerup", endPointerPress, { passive: !(props.onTap || props["onPointerUp"]) });
1351
1668
  const removePointerCancelListener = addPointerEvent(window, "pointercancel", (cancelEvent, cancelInfo) => this.cancelPress(cancelEvent, cancelInfo), { passive: !(props.onTapCancel || props["onPointerCancel"]) });
1352
- this.removeEndListeners = wrap.pipe(removePointerUpListener, removePointerCancelListener);
1669
+ this.removeEndListeners = pipe(removePointerUpListener, removePointerCancelListener);
1353
1670
  this.startPress(startEvent, startInfo);
1354
1671
  };
1355
1672
  this.startAccessiblePress = () => {
@@ -1359,7 +1676,12 @@ class PressGesture extends Feature {
1359
1676
  const handleKeyup = (keyupEvent) => {
1360
1677
  if (keyupEvent.key !== "Enter" || !this.checkPressEnd())
1361
1678
  return;
1362
- fireSyntheticPointerEvent("up", this.node.getProps().onTap);
1679
+ fireSyntheticPointerEvent("up", (event, info) => {
1680
+ const { onTap } = this.node.getProps();
1681
+ if (onTap) {
1682
+ sync.update(() => onTap(event, info));
1683
+ }
1684
+ });
1363
1685
  };
1364
1686
  this.removeEndListeners();
1365
1687
  this.removeEndListeners = addDomEvent(this.node.current, "keyup", handleKeyup);
@@ -1374,7 +1696,7 @@ class PressGesture extends Feature {
1374
1696
  fireSyntheticPointerEvent("cancel", (cancelEvent, cancelInfo) => this.cancelPress(cancelEvent, cancelInfo));
1375
1697
  };
1376
1698
  const removeBlurListener = addDomEvent(this.node.current, "blur", handleBlur);
1377
- this.removeAccessibleListeners = wrap.pipe(removeKeydownListener, removeBlurListener);
1699
+ this.removeAccessibleListeners = pipe(removeKeydownListener, removeBlurListener);
1378
1700
  };
1379
1701
  }
1380
1702
  startPress(event, info) {
@@ -1386,7 +1708,9 @@ class PressGesture extends Feature {
1386
1708
  if (whileTap && this.node.animationState) {
1387
1709
  this.node.animationState.setActive("whileTap", true);
1388
1710
  }
1389
- onTapStart && onTapStart(event, info);
1711
+ if (onTapStart) {
1712
+ sync.update(() => onTapStart(event, info));
1713
+ }
1390
1714
  }
1391
1715
  checkPressEnd() {
1392
1716
  this.removeEndListeners();
@@ -1401,13 +1725,15 @@ class PressGesture extends Feature {
1401
1725
  if (!this.checkPressEnd())
1402
1726
  return;
1403
1727
  const { onTapCancel } = this.node.getProps();
1404
- onTapCancel && onTapCancel(event, info);
1728
+ if (onTapCancel) {
1729
+ sync.update(() => onTapCancel(event, info));
1730
+ }
1405
1731
  }
1406
1732
  mount() {
1407
1733
  const props = this.node.getProps();
1408
1734
  const removePointerListener = addPointerEvent(this.node.current, "pointerdown", this.startPointerPress, { passive: !(props.onTapStart || props["onPointerStart"]) });
1409
1735
  const removeFocusListener = addDomEvent(this.node.current, "focus", this.startAccessiblePress);
1410
- this.removeStartListeners = wrap.pipe(removePointerListener, removeFocusListener);
1736
+ this.removeStartListeners = pipe(removePointerListener, removeFocusListener);
1411
1737
  }
1412
1738
  unmount() {
1413
1739
  this.removeStartListeners();
@@ -1570,178 +1896,2165 @@ const isNumericalString = (v) => /^\-?\d*\.?\d+$/.test(v);
1570
1896
  */
1571
1897
  const isZeroValueString = (v) => /^0[^.\s]+$/.test(v);
1572
1898
 
1573
- /**
1574
- * Tests a provided value against a ValueType
1575
- */
1576
- const testValueType = (v) => (type) => type.test(v);
1577
-
1578
- /**
1579
- * ValueType for "auto"
1580
- */
1581
- const auto = {
1582
- test: (v) => v === "auto",
1583
- parse: (v) => v,
1584
- };
1899
+ function addUniqueItem(arr, item) {
1900
+ if (arr.indexOf(item) === -1)
1901
+ arr.push(item);
1902
+ }
1903
+ function removeItem(arr, item) {
1904
+ const index = arr.indexOf(item);
1905
+ if (index > -1)
1906
+ arr.splice(index, 1);
1907
+ }
1908
+ // Adapted from array-move
1909
+ function moveItem([...arr], fromIndex, toIndex) {
1910
+ const startIndex = fromIndex < 0 ? arr.length + fromIndex : fromIndex;
1911
+ if (startIndex >= 0 && startIndex < arr.length) {
1912
+ const endIndex = toIndex < 0 ? arr.length + toIndex : toIndex;
1913
+ const [item] = arr.splice(fromIndex, 1);
1914
+ arr.splice(endIndex, 0, item);
1915
+ }
1916
+ return arr;
1917
+ }
1585
1918
 
1586
- /**
1587
- * A list of value types commonly used for dimensions
1588
- */
1589
- const dimensionValueTypes = [wrap.number, wrap.px, wrap.percent, wrap.degrees, wrap.vw, wrap.vh, auto];
1590
- /**
1591
- * Tests a dimensional value against the list of dimension ValueTypes
1592
- */
1593
- const findDimensionValueType = (v) => dimensionValueTypes.find(testValueType(v));
1919
+ class SubscriptionManager {
1920
+ constructor() {
1921
+ this.subscriptions = [];
1922
+ }
1923
+ add(handler) {
1924
+ addUniqueItem(this.subscriptions, handler);
1925
+ return () => removeItem(this.subscriptions, handler);
1926
+ }
1927
+ notify(a, b, c) {
1928
+ const numSubscriptions = this.subscriptions.length;
1929
+ if (!numSubscriptions)
1930
+ return;
1931
+ if (numSubscriptions === 1) {
1932
+ /**
1933
+ * If there's only a single handler we can just call it without invoking a loop.
1934
+ */
1935
+ this.subscriptions[0](a, b, c);
1936
+ }
1937
+ else {
1938
+ for (let i = 0; i < numSubscriptions; i++) {
1939
+ /**
1940
+ * Check whether the handler exists before firing as it's possible
1941
+ * the subscriptions were modified during this loop running.
1942
+ */
1943
+ const handler = this.subscriptions[i];
1944
+ handler && handler(a, b, c);
1945
+ }
1946
+ }
1947
+ }
1948
+ getSize() {
1949
+ return this.subscriptions.length;
1950
+ }
1951
+ clear() {
1952
+ this.subscriptions.length = 0;
1953
+ }
1954
+ }
1594
1955
 
1595
- /**
1596
- * A list of all ValueTypes
1597
- */
1598
- const valueTypes = [...dimensionValueTypes, wrap.color, wrap.complex];
1599
- /**
1600
- * Tests a value against the list of ValueTypes
1601
- */
1602
- const findValueType = (v) => valueTypes.find(testValueType(v));
1956
+ /*
1957
+ Convert velocity into velocity per second
1603
1958
 
1604
- /**
1605
- * Creates an object containing the latest state of every MotionValue on a VisualElement
1606
- */
1607
- function getCurrent(visualElement) {
1608
- const current = {};
1609
- visualElement.values.forEach((value, key) => (current[key] = value.get()));
1610
- return current;
1611
- }
1612
- /**
1613
- * Creates an object containing the latest velocity of every MotionValue on a VisualElement
1614
- */
1615
- function getVelocity$1(visualElement) {
1616
- const velocity = {};
1617
- visualElement.values.forEach((value, key) => (velocity[key] = value.getVelocity()));
1618
- return velocity;
1959
+ @param [number]: Unit per frame
1960
+ @param [number]: Frame duration in ms
1961
+ */
1962
+ function velocityPerSecond(velocity, frameDuration) {
1963
+ return frameDuration ? velocity * (1000 / frameDuration) : 0;
1619
1964
  }
1620
- function resolveVariant(visualElement, definition, custom) {
1621
- const props = visualElement.getProps();
1622
- return resolveVariantFromProps(props, definition, custom !== undefined ? custom : props.custom, getCurrent(visualElement), getVelocity$1(visualElement));
1965
+
1966
+ const warned = new Set();
1967
+ function warnOnce(condition, message, element) {
1968
+ if (condition || warned.has(message))
1969
+ return;
1970
+ console.warn(message);
1971
+ if (element)
1972
+ console.warn(element);
1973
+ warned.add(message);
1623
1974
  }
1624
1975
 
1976
+ const isFloat = (value) => {
1977
+ return !isNaN(parseFloat(value));
1978
+ };
1625
1979
  /**
1626
- * Set VisualElement's MotionValue, creating a new MotionValue for it if
1627
- * it doesn't exist.
1980
+ * `MotionValue` is used to track the state and velocity of motion values.
1981
+ *
1982
+ * @public
1628
1983
  */
1629
- function setMotionValue(visualElement, key, value) {
1630
- if (visualElement.hasValue(key)) {
1631
- visualElement.getValue(key).set(value);
1632
- }
1633
- else {
1634
- visualElement.addValue(key, wrap.motionValue(value));
1984
+ class MotionValue {
1985
+ /**
1986
+ * @param init - The initiating value
1987
+ * @param config - Optional configuration options
1988
+ *
1989
+ * - `transformer`: A function to transform incoming values with.
1990
+ *
1991
+ * @internal
1992
+ */
1993
+ constructor(init, options = {}) {
1994
+ /**
1995
+ * This will be replaced by the build step with the latest version number.
1996
+ * When MotionValues are provided to motion components, warn if versions are mixed.
1997
+ */
1998
+ this.version = "10.1.0";
1999
+ /**
2000
+ * Duration, in milliseconds, since last updating frame.
2001
+ *
2002
+ * @internal
2003
+ */
2004
+ this.timeDelta = 0;
2005
+ /**
2006
+ * Timestamp of the last time this `MotionValue` was updated.
2007
+ *
2008
+ * @internal
2009
+ */
2010
+ this.lastUpdated = 0;
2011
+ /**
2012
+ * Tracks whether this value can output a velocity. Currently this is only true
2013
+ * if the value is numerical, but we might be able to widen the scope here and support
2014
+ * other value types.
2015
+ *
2016
+ * @internal
2017
+ */
2018
+ this.canTrackVelocity = false;
2019
+ /**
2020
+ * An object containing a SubscriptionManager for each active event.
2021
+ */
2022
+ this.events = {};
2023
+ this.updateAndNotify = (v, render = true) => {
2024
+ this.prev = this.current;
2025
+ this.current = v;
2026
+ // Update timestamp
2027
+ const { delta, timestamp } = frameData;
2028
+ if (this.lastUpdated !== timestamp) {
2029
+ this.timeDelta = delta;
2030
+ this.lastUpdated = timestamp;
2031
+ sync.postRender(this.scheduleVelocityCheck);
2032
+ }
2033
+ // Update update subscribers
2034
+ if (this.prev !== this.current && this.events.change) {
2035
+ this.events.change.notify(this.current);
2036
+ }
2037
+ // Update velocity subscribers
2038
+ if (this.events.velocityChange) {
2039
+ this.events.velocityChange.notify(this.getVelocity());
2040
+ }
2041
+ // Update render subscribers
2042
+ if (render && this.events.renderRequest) {
2043
+ this.events.renderRequest.notify(this.current);
2044
+ }
2045
+ };
2046
+ /**
2047
+ * Schedule a velocity check for the next frame.
2048
+ *
2049
+ * This is an instanced and bound function to prevent generating a new
2050
+ * function once per frame.
2051
+ *
2052
+ * @internal
2053
+ */
2054
+ this.scheduleVelocityCheck = () => sync.postRender(this.velocityCheck);
2055
+ /**
2056
+ * Updates `prev` with `current` if the value hasn't been updated this frame.
2057
+ * This ensures velocity calculations return `0`.
2058
+ *
2059
+ * This is an instanced and bound function to prevent generating a new
2060
+ * function once per frame.
2061
+ *
2062
+ * @internal
2063
+ */
2064
+ this.velocityCheck = ({ timestamp }) => {
2065
+ if (timestamp !== this.lastUpdated) {
2066
+ this.prev = this.current;
2067
+ if (this.events.velocityChange) {
2068
+ this.events.velocityChange.notify(this.getVelocity());
2069
+ }
2070
+ }
2071
+ };
2072
+ this.hasAnimated = false;
2073
+ this.prev = this.current = init;
2074
+ this.canTrackVelocity = isFloat(this.current);
2075
+ this.owner = options.owner;
1635
2076
  }
1636
- }
1637
- function setTarget(visualElement, definition) {
1638
- const resolved = resolveVariant(visualElement, definition);
1639
- let { transitionEnd = {}, transition = {}, ...target } = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {};
1640
- target = { ...target, ...transitionEnd };
1641
- for (const key in target) {
1642
- const value = resolveFinalValueInKeyframes(target[key]);
1643
- setMotionValue(visualElement, key, value);
2077
+ /**
2078
+ * Adds a function that will be notified when the `MotionValue` is updated.
2079
+ *
2080
+ * It returns a function that, when called, will cancel the subscription.
2081
+ *
2082
+ * When calling `onChange` inside a React component, it should be wrapped with the
2083
+ * `useEffect` hook. As it returns an unsubscribe function, this should be returned
2084
+ * from the `useEffect` function to ensure you don't add duplicate subscribers..
2085
+ *
2086
+ * ```jsx
2087
+ * export const MyComponent = () => {
2088
+ * const x = useMotionValue(0)
2089
+ * const y = useMotionValue(0)
2090
+ * const opacity = useMotionValue(1)
2091
+ *
2092
+ * useEffect(() => {
2093
+ * function updateOpacity() {
2094
+ * const maxXY = Math.max(x.get(), y.get())
2095
+ * const newOpacity = transform(maxXY, [0, 100], [1, 0])
2096
+ * opacity.set(newOpacity)
2097
+ * }
2098
+ *
2099
+ * const unsubscribeX = x.on("change", updateOpacity)
2100
+ * const unsubscribeY = y.on("change", updateOpacity)
2101
+ *
2102
+ * return () => {
2103
+ * unsubscribeX()
2104
+ * unsubscribeY()
2105
+ * }
2106
+ * }, [])
2107
+ *
2108
+ * return <motion.div style={{ x }} />
2109
+ * }
2110
+ * ```
2111
+ *
2112
+ * @param subscriber - A function that receives the latest value.
2113
+ * @returns A function that, when called, will cancel this subscription.
2114
+ *
2115
+ * @deprecated
2116
+ */
2117
+ onChange(subscription) {
2118
+ if (process.env.NODE_ENV !== "production") {
2119
+ warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
2120
+ }
2121
+ return this.on("change", subscription);
1644
2122
  }
1645
- }
1646
- function setVariants(visualElement, variantLabels) {
1647
- const reversedLabels = [...variantLabels].reverse();
1648
- reversedLabels.forEach((key) => {
1649
- const variant = visualElement.getVariant(key);
1650
- variant && setTarget(visualElement, variant);
1651
- if (visualElement.variantChildren) {
1652
- visualElement.variantChildren.forEach((child) => {
1653
- setVariants(child, variantLabels);
1654
- });
2123
+ on(eventName, callback) {
2124
+ if (!this.events[eventName]) {
2125
+ this.events[eventName] = new SubscriptionManager();
1655
2126
  }
1656
- });
1657
- }
1658
- function setValues(visualElement, definition) {
1659
- if (Array.isArray(definition)) {
1660
- return setVariants(visualElement, definition);
2127
+ const unsubscribe = this.events[eventName].add(callback);
2128
+ if (eventName === "change") {
2129
+ return () => {
2130
+ unsubscribe();
2131
+ /**
2132
+ * If we have no more change listeners by the start
2133
+ * of the next frame, stop active animations.
2134
+ */
2135
+ sync.read(() => {
2136
+ if (!this.events.change.getSize()) {
2137
+ this.stop();
2138
+ }
2139
+ });
2140
+ };
2141
+ }
2142
+ return unsubscribe;
1661
2143
  }
1662
- else if (typeof definition === "string") {
1663
- return setVariants(visualElement, [definition]);
2144
+ clearListeners() {
2145
+ for (const eventManagers in this.events) {
2146
+ this.events[eventManagers].clear();
2147
+ }
1664
2148
  }
1665
- else {
1666
- setTarget(visualElement, definition);
2149
+ /**
2150
+ * Attaches a passive effect to the `MotionValue`.
2151
+ *
2152
+ * @internal
2153
+ */
2154
+ attach(passiveEffect, stopPassiveEffect) {
2155
+ this.passiveEffect = passiveEffect;
2156
+ this.stopPassiveEffect = stopPassiveEffect;
1667
2157
  }
1668
- }
1669
- function checkTargetForNewValues(visualElement, target, origin) {
1670
- var _a, _b;
1671
- const newValueKeys = Object.keys(target).filter((key) => !visualElement.hasValue(key));
1672
- const numNewValues = newValueKeys.length;
1673
- if (!numNewValues)
1674
- return;
1675
- for (let i = 0; i < numNewValues; i++) {
1676
- const key = newValueKeys[i];
1677
- const targetValue = target[key];
2158
+ /**
2159
+ * Sets the state of the `MotionValue`.
2160
+ *
2161
+ * @remarks
2162
+ *
2163
+ * ```jsx
2164
+ * const x = useMotionValue(0)
2165
+ * x.set(10)
2166
+ * ```
2167
+ *
2168
+ * @param latest - Latest value to set.
2169
+ * @param render - Whether to notify render subscribers. Defaults to `true`
2170
+ *
2171
+ * @public
2172
+ */
2173
+ set(v, render = true) {
2174
+ if (!render || !this.passiveEffect) {
2175
+ this.updateAndNotify(v, render);
2176
+ }
2177
+ else {
2178
+ this.passiveEffect(v, this.updateAndNotify);
2179
+ }
2180
+ }
2181
+ setWithVelocity(prev, current, delta) {
2182
+ this.set(current);
2183
+ this.prev = prev;
2184
+ this.timeDelta = delta;
2185
+ }
2186
+ /**
2187
+ * Set the state of the `MotionValue`, stopping any active animations,
2188
+ * effects, and resets velocity to `0`.
2189
+ */
2190
+ jump(v) {
2191
+ this.updateAndNotify(v);
2192
+ this.prev = v;
2193
+ this.stop();
2194
+ if (this.stopPassiveEffect)
2195
+ this.stopPassiveEffect();
2196
+ }
2197
+ /**
2198
+ * Returns the latest state of `MotionValue`
2199
+ *
2200
+ * @returns - The latest state of `MotionValue`
2201
+ *
2202
+ * @public
2203
+ */
2204
+ get() {
2205
+ return this.current;
2206
+ }
2207
+ /**
2208
+ * @public
2209
+ */
2210
+ getPrevious() {
2211
+ return this.prev;
2212
+ }
2213
+ /**
2214
+ * Returns the latest velocity of `MotionValue`
2215
+ *
2216
+ * @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
2217
+ *
2218
+ * @public
2219
+ */
2220
+ getVelocity() {
2221
+ // This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful
2222
+ return this.canTrackVelocity
2223
+ ? // These casts could be avoided if parseFloat would be typed better
2224
+ velocityPerSecond(parseFloat(this.current) -
2225
+ parseFloat(this.prev), this.timeDelta)
2226
+ : 0;
2227
+ }
2228
+ /**
2229
+ * Registers a new animation to control this `MotionValue`. Only one
2230
+ * animation can drive a `MotionValue` at one time.
2231
+ *
2232
+ * ```jsx
2233
+ * value.start()
2234
+ * ```
2235
+ *
2236
+ * @param animation - A function that starts the provided animation
2237
+ *
2238
+ * @internal
2239
+ */
2240
+ start(startAnimation) {
2241
+ this.stop();
2242
+ return new Promise((resolve) => {
2243
+ this.hasAnimated = true;
2244
+ this.animation = startAnimation(resolve) || null;
2245
+ if (this.events.animationStart) {
2246
+ this.events.animationStart.notify();
2247
+ }
2248
+ }).then(() => {
2249
+ if (this.events.animationComplete) {
2250
+ this.events.animationComplete.notify();
2251
+ }
2252
+ this.clearAnimation();
2253
+ });
2254
+ }
2255
+ /**
2256
+ * Stop the currently active animation.
2257
+ *
2258
+ * @public
2259
+ */
2260
+ stop() {
2261
+ if (this.animation) {
2262
+ this.animation.stop();
2263
+ if (this.events.animationCancel) {
2264
+ this.events.animationCancel.notify();
2265
+ }
2266
+ }
2267
+ this.clearAnimation();
2268
+ }
2269
+ /**
2270
+ * Returns `true` if this value is currently animating.
2271
+ *
2272
+ * @public
2273
+ */
2274
+ isAnimating() {
2275
+ return !!this.animation;
2276
+ }
2277
+ clearAnimation() {
2278
+ this.animation = null;
2279
+ }
2280
+ /**
2281
+ * Destroy and clean up subscribers to this `MotionValue`.
2282
+ *
2283
+ * The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically
2284
+ * handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually
2285
+ * created a `MotionValue` via the `motionValue` function.
2286
+ *
2287
+ * @public
2288
+ */
2289
+ destroy() {
2290
+ this.clearListeners();
2291
+ this.stop();
2292
+ if (this.stopPassiveEffect) {
2293
+ this.stopPassiveEffect();
2294
+ }
2295
+ }
2296
+ }
2297
+ function motionValue(init, options) {
2298
+ return new MotionValue(init, options);
2299
+ }
2300
+
2301
+ /**
2302
+ * Returns true if the provided string is a color, ie rgba(0,0,0,0) or #000,
2303
+ * but false if a number or multiple colors
2304
+ */
2305
+ const isColorString = (type, testProp) => (v) => {
2306
+ return Boolean((isString(v) && singleColorRegex.test(v) && v.startsWith(type)) ||
2307
+ (testProp && Object.prototype.hasOwnProperty.call(v, testProp)));
2308
+ };
2309
+ const splitColor = (aName, bName, cName) => (v) => {
2310
+ if (!isString(v))
2311
+ return v;
2312
+ const [a, b, c, alpha] = v.match(floatRegex);
2313
+ return {
2314
+ [aName]: parseFloat(a),
2315
+ [bName]: parseFloat(b),
2316
+ [cName]: parseFloat(c),
2317
+ alpha: alpha !== undefined ? parseFloat(alpha) : 1,
2318
+ };
2319
+ };
2320
+
2321
+ const clampRgbUnit = (v) => clamp(0, 255, v);
2322
+ const rgbUnit = {
2323
+ ...number,
2324
+ transform: (v) => Math.round(clampRgbUnit(v)),
2325
+ };
2326
+ const rgba = {
2327
+ test: isColorString("rgb", "red"),
2328
+ parse: splitColor("red", "green", "blue"),
2329
+ transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" +
2330
+ rgbUnit.transform(red) +
2331
+ ", " +
2332
+ rgbUnit.transform(green) +
2333
+ ", " +
2334
+ rgbUnit.transform(blue) +
2335
+ ", " +
2336
+ sanitize(alpha.transform(alpha$1)) +
2337
+ ")",
2338
+ };
2339
+
2340
+ function parseHex(v) {
2341
+ let r = "";
2342
+ let g = "";
2343
+ let b = "";
2344
+ let a = "";
2345
+ // If we have 6 characters, ie #FF0000
2346
+ if (v.length > 5) {
2347
+ r = v.substring(1, 3);
2348
+ g = v.substring(3, 5);
2349
+ b = v.substring(5, 7);
2350
+ a = v.substring(7, 9);
2351
+ // Or we have 3 characters, ie #F00
2352
+ }
2353
+ else {
2354
+ r = v.substring(1, 2);
2355
+ g = v.substring(2, 3);
2356
+ b = v.substring(3, 4);
2357
+ a = v.substring(4, 5);
2358
+ r += r;
2359
+ g += g;
2360
+ b += b;
2361
+ a += a;
2362
+ }
2363
+ return {
2364
+ red: parseInt(r, 16),
2365
+ green: parseInt(g, 16),
2366
+ blue: parseInt(b, 16),
2367
+ alpha: a ? parseInt(a, 16) / 255 : 1,
2368
+ };
2369
+ }
2370
+ const hex = {
2371
+ test: isColorString("#"),
2372
+ parse: parseHex,
2373
+ transform: rgba.transform,
2374
+ };
2375
+
2376
+ const hsla = {
2377
+ test: isColorString("hsl", "hue"),
2378
+ parse: splitColor("hue", "saturation", "lightness"),
2379
+ transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
2380
+ return ("hsla(" +
2381
+ Math.round(hue) +
2382
+ ", " +
2383
+ percent.transform(sanitize(saturation)) +
2384
+ ", " +
2385
+ percent.transform(sanitize(lightness)) +
2386
+ ", " +
2387
+ sanitize(alpha.transform(alpha$1)) +
2388
+ ")");
2389
+ },
2390
+ };
2391
+
2392
+ const color = {
2393
+ test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
2394
+ parse: (v) => {
2395
+ if (rgba.test(v)) {
2396
+ return rgba.parse(v);
2397
+ }
2398
+ else if (hsla.test(v)) {
2399
+ return hsla.parse(v);
2400
+ }
2401
+ else {
2402
+ return hex.parse(v);
2403
+ }
2404
+ },
2405
+ transform: (v) => {
2406
+ return isString(v)
2407
+ ? v
2408
+ : v.hasOwnProperty("red")
2409
+ ? rgba.transform(v)
2410
+ : hsla.transform(v);
2411
+ },
2412
+ };
2413
+
2414
+ const colorToken = "${c}";
2415
+ const numberToken = "${n}";
2416
+ function test(v) {
2417
+ var _a, _b;
2418
+ return (isNaN(v) &&
2419
+ isString(v) &&
2420
+ (((_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) || 0) +
2421
+ (((_b = v.match(colorRegex)) === null || _b === void 0 ? void 0 : _b.length) || 0) >
2422
+ 0);
2423
+ }
2424
+ function analyseComplexValue(v) {
2425
+ if (typeof v === "number")
2426
+ v = `${v}`;
2427
+ const values = [];
2428
+ let numColors = 0;
2429
+ let numNumbers = 0;
2430
+ const colors = v.match(colorRegex);
2431
+ if (colors) {
2432
+ numColors = colors.length;
2433
+ // Strip colors from input so they're not picked up by number regex.
2434
+ // There's a better way to combine these regex searches, but its beyond my regex skills
2435
+ v = v.replace(colorRegex, colorToken);
2436
+ values.push(...colors.map(color.parse));
2437
+ }
2438
+ const numbers = v.match(floatRegex);
2439
+ if (numbers) {
2440
+ numNumbers = numbers.length;
2441
+ v = v.replace(floatRegex, numberToken);
2442
+ values.push(...numbers.map(number.parse));
2443
+ }
2444
+ return { values, numColors, numNumbers, tokenised: v };
2445
+ }
2446
+ function parse(v) {
2447
+ return analyseComplexValue(v).values;
2448
+ }
2449
+ function createTransformer(source) {
2450
+ const { values, numColors, tokenised } = analyseComplexValue(source);
2451
+ const numValues = values.length;
2452
+ return (v) => {
2453
+ let output = tokenised;
2454
+ for (let i = 0; i < numValues; i++) {
2455
+ output = output.replace(i < numColors ? colorToken : numberToken, i < numColors
2456
+ ? color.transform(v[i])
2457
+ : sanitize(v[i]));
2458
+ }
2459
+ return output;
2460
+ };
2461
+ }
2462
+ const convertNumbersToZero = (v) => typeof v === "number" ? 0 : v;
2463
+ function getAnimatableNone$1(v) {
2464
+ const parsed = parse(v);
2465
+ const transformer = createTransformer(v);
2466
+ return transformer(parsed.map(convertNumbersToZero));
2467
+ }
2468
+ const complex = { test, parse, createTransformer, getAnimatableNone: getAnimatableNone$1 };
2469
+
2470
+ /**
2471
+ * Properties that should default to 1 or 100%
2472
+ */
2473
+ const maxDefaults = new Set(["brightness", "contrast", "saturate", "opacity"]);
2474
+ function applyDefaultFilter(v) {
2475
+ const [name, value] = v.slice(0, -1).split("(");
2476
+ if (name === "drop-shadow")
2477
+ return v;
2478
+ const [number] = value.match(floatRegex) || [];
2479
+ if (!number)
2480
+ return v;
2481
+ const unit = value.replace(number, "");
2482
+ let defaultValue = maxDefaults.has(name) ? 1 : 0;
2483
+ if (number !== value)
2484
+ defaultValue *= 100;
2485
+ return name + "(" + defaultValue + unit + ")";
2486
+ }
2487
+ const functionRegex = /([a-z-]*)\(.*?\)/g;
2488
+ const filter = {
2489
+ ...complex,
2490
+ getAnimatableNone: (v) => {
2491
+ const functions = v.match(functionRegex);
2492
+ return functions ? functions.map(applyDefaultFilter).join(" ") : v;
2493
+ },
2494
+ };
2495
+
2496
+ /**
2497
+ * A map of default value types for common values
2498
+ */
2499
+ const defaultValueTypes = {
2500
+ ...numberValueTypes,
2501
+ // Color props
2502
+ color,
2503
+ backgroundColor: color,
2504
+ outlineColor: color,
2505
+ fill: color,
2506
+ stroke: color,
2507
+ // Border props
2508
+ borderColor: color,
2509
+ borderTopColor: color,
2510
+ borderRightColor: color,
2511
+ borderBottomColor: color,
2512
+ borderLeftColor: color,
2513
+ filter,
2514
+ WebkitFilter: filter,
2515
+ };
2516
+ /**
2517
+ * Gets the default ValueType for the provided value key
2518
+ */
2519
+ const getDefaultValueType = (key) => defaultValueTypes[key];
2520
+
2521
+ function getAnimatableNone(key, value) {
2522
+ let defaultValueType = getDefaultValueType(key);
2523
+ if (defaultValueType !== filter)
2524
+ defaultValueType = complex;
2525
+ // If value is not recognised as animatable, ie "none", create an animatable version origin based on the target
2526
+ return defaultValueType.getAnimatableNone
2527
+ ? defaultValueType.getAnimatableNone(value)
2528
+ : undefined;
2529
+ }
2530
+
2531
+ /**
2532
+ * Tests a provided value against a ValueType
2533
+ */
2534
+ const testValueType = (v) => (type) => type.test(v);
2535
+
2536
+ /**
2537
+ * ValueType for "auto"
2538
+ */
2539
+ const auto = {
2540
+ test: (v) => v === "auto",
2541
+ parse: (v) => v,
2542
+ };
2543
+
2544
+ /**
2545
+ * A list of value types commonly used for dimensions
2546
+ */
2547
+ const dimensionValueTypes = [number, px, percent, degrees, vw, vh, auto];
2548
+ /**
2549
+ * Tests a dimensional value against the list of dimension ValueTypes
2550
+ */
2551
+ const findDimensionValueType = (v) => dimensionValueTypes.find(testValueType(v));
2552
+
2553
+ /**
2554
+ * A list of all ValueTypes
2555
+ */
2556
+ const valueTypes = [...dimensionValueTypes, color, complex];
2557
+ /**
2558
+ * Tests a value against the list of ValueTypes
2559
+ */
2560
+ const findValueType = (v) => valueTypes.find(testValueType(v));
2561
+
2562
+ /**
2563
+ * Creates an object containing the latest state of every MotionValue on a VisualElement
2564
+ */
2565
+ function getCurrent(visualElement) {
2566
+ const current = {};
2567
+ visualElement.values.forEach((value, key) => (current[key] = value.get()));
2568
+ return current;
2569
+ }
2570
+ /**
2571
+ * Creates an object containing the latest velocity of every MotionValue on a VisualElement
2572
+ */
2573
+ function getVelocity$1(visualElement) {
2574
+ const velocity = {};
2575
+ visualElement.values.forEach((value, key) => (velocity[key] = value.getVelocity()));
2576
+ return velocity;
2577
+ }
2578
+ function resolveVariant(visualElement, definition, custom) {
2579
+ const props = visualElement.getProps();
2580
+ return resolveVariantFromProps(props, definition, custom !== undefined ? custom : props.custom, getCurrent(visualElement), getVelocity$1(visualElement));
2581
+ }
2582
+
2583
+ /**
2584
+ * Set VisualElement's MotionValue, creating a new MotionValue for it if
2585
+ * it doesn't exist.
2586
+ */
2587
+ function setMotionValue(visualElement, key, value) {
2588
+ if (visualElement.hasValue(key)) {
2589
+ visualElement.getValue(key).set(value);
2590
+ }
2591
+ else {
2592
+ visualElement.addValue(key, motionValue(value));
2593
+ }
2594
+ }
2595
+ function setTarget(visualElement, definition) {
2596
+ const resolved = resolveVariant(visualElement, definition);
2597
+ let { transitionEnd = {}, transition = {}, ...target } = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {};
2598
+ target = { ...target, ...transitionEnd };
2599
+ for (const key in target) {
2600
+ const value = resolveFinalValueInKeyframes(target[key]);
2601
+ setMotionValue(visualElement, key, value);
2602
+ }
2603
+ }
2604
+ function setVariants(visualElement, variantLabels) {
2605
+ const reversedLabels = [...variantLabels].reverse();
2606
+ reversedLabels.forEach((key) => {
2607
+ const variant = visualElement.getVariant(key);
2608
+ variant && setTarget(visualElement, variant);
2609
+ if (visualElement.variantChildren) {
2610
+ visualElement.variantChildren.forEach((child) => {
2611
+ setVariants(child, variantLabels);
2612
+ });
2613
+ }
2614
+ });
2615
+ }
2616
+ function setValues(visualElement, definition) {
2617
+ if (Array.isArray(definition)) {
2618
+ return setVariants(visualElement, definition);
2619
+ }
2620
+ else if (typeof definition === "string") {
2621
+ return setVariants(visualElement, [definition]);
2622
+ }
2623
+ else {
2624
+ setTarget(visualElement, definition);
2625
+ }
2626
+ }
2627
+ function checkTargetForNewValues(visualElement, target, origin) {
2628
+ var _a, _b;
2629
+ const newValueKeys = Object.keys(target).filter((key) => !visualElement.hasValue(key));
2630
+ const numNewValues = newValueKeys.length;
2631
+ if (!numNewValues)
2632
+ return;
2633
+ for (let i = 0; i < numNewValues; i++) {
2634
+ const key = newValueKeys[i];
2635
+ const targetValue = target[key];
1678
2636
  let value = null;
1679
2637
  /**
1680
- * If the target is a series of keyframes, we can use the first value
1681
- * in the array. If this first value is null, we'll still need to read from the DOM.
2638
+ * If the target is a series of keyframes, we can use the first value
2639
+ * in the array. If this first value is null, we'll still need to read from the DOM.
2640
+ */
2641
+ if (Array.isArray(targetValue)) {
2642
+ value = targetValue[0];
2643
+ }
2644
+ /**
2645
+ * If the target isn't keyframes, or the first keyframe was null, we need to
2646
+ * first check if an origin value was explicitly defined in the transition as "from",
2647
+ * if not read the value from the DOM. As an absolute fallback, take the defined target value.
2648
+ */
2649
+ if (value === null) {
2650
+ value = (_b = (_a = origin[key]) !== null && _a !== void 0 ? _a : visualElement.readValue(key)) !== null && _b !== void 0 ? _b : target[key];
2651
+ }
2652
+ /**
2653
+ * If value is still undefined or null, ignore it. Preferably this would throw,
2654
+ * but this was causing issues in Framer.
2655
+ */
2656
+ if (value === undefined || value === null)
2657
+ continue;
2658
+ if (typeof value === "string" &&
2659
+ (isNumericalString(value) || isZeroValueString(value))) {
2660
+ // If this is a number read as a string, ie "0" or "200", convert it to a number
2661
+ value = parseFloat(value);
2662
+ }
2663
+ else if (!findValueType(value) && complex.test(targetValue)) {
2664
+ value = getAnimatableNone(key, targetValue);
2665
+ }
2666
+ visualElement.addValue(key, motionValue(value, { owner: visualElement }));
2667
+ if (origin[key] === undefined) {
2668
+ origin[key] = value;
2669
+ }
2670
+ if (value !== null)
2671
+ visualElement.setBaseTarget(key, value);
2672
+ }
2673
+ }
2674
+ function getOriginFromTransition(key, transition) {
2675
+ if (!transition)
2676
+ return;
2677
+ const valueTransition = transition[key] || transition["default"] || transition;
2678
+ return valueTransition.from;
2679
+ }
2680
+ function getOrigin(target, transition, visualElement) {
2681
+ const origin = {};
2682
+ for (const key in target) {
2683
+ const transitionOrigin = getOriginFromTransition(key, transition);
2684
+ if (transitionOrigin !== undefined) {
2685
+ origin[key] = transitionOrigin;
2686
+ }
2687
+ else {
2688
+ const value = visualElement.getValue(key);
2689
+ if (value) {
2690
+ origin[key] = value.get();
2691
+ }
2692
+ }
2693
+ }
2694
+ return origin;
2695
+ }
2696
+
2697
+ function isWillChangeMotionValue(value) {
2698
+ return Boolean(isMotionValue(value) && value.add);
2699
+ }
2700
+
2701
+ const optimizedAppearDataId = "framerAppearId";
2702
+ const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
2703
+
2704
+ exports.warning = noop;
2705
+ exports.invariant = noop;
2706
+ if (process.env.NODE_ENV !== "production") {
2707
+ exports.warning = (check, message) => {
2708
+ if (!check && typeof console !== "undefined") {
2709
+ console.warn(message);
2710
+ }
2711
+ };
2712
+ exports.invariant = (check, message) => {
2713
+ if (!check) {
2714
+ throw new Error(message);
2715
+ }
2716
+ };
2717
+ }
2718
+
2719
+ /**
2720
+ * Converts seconds to milliseconds
2721
+ *
2722
+ * @param seconds - Time in seconds.
2723
+ * @return milliseconds - Converted time in milliseconds.
2724
+ */
2725
+ const secondsToMilliseconds = (seconds) => seconds * 1000;
2726
+
2727
+ const instantAnimationState = {
2728
+ current: false,
2729
+ };
2730
+
2731
+ // Accepts an easing function and returns a new one that outputs mirrored values for
2732
+ // the second half of the animation. Turns easeIn into easeInOut.
2733
+ const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
2734
+
2735
+ // Accepts an easing function and returns a new one that outputs reversed values.
2736
+ // Turns easeIn into easeOut.
2737
+ const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
2738
+
2739
+ const easeIn = (p) => p * p;
2740
+ const easeOut = reverseEasing(easeIn);
2741
+ const easeInOut = mirrorEasing(easeIn);
2742
+
2743
+ /*
2744
+ Value in range from progress
2745
+
2746
+ Given a lower limit and an upper limit, we return the value within
2747
+ that range as expressed by progress (usually a number from 0 to 1)
2748
+
2749
+ So progress = 0.5 would change
2750
+
2751
+ from -------- to
2752
+
2753
+ to
2754
+
2755
+ from ---- to
2756
+
2757
+ E.g. from = 10, to = 20, progress = 0.5 => 15
2758
+
2759
+ @param [number]: Lower limit of range
2760
+ @param [number]: Upper limit of range
2761
+ @param [number]: The progress between lower and upper limits expressed 0-1
2762
+ @return [number]: Value as calculated from progress within range (not limited within range)
2763
+ */
2764
+ const mix = (from, to, progress) => -progress * from + progress * to + from;
2765
+
2766
+ // Adapted from https://gist.github.com/mjackson/5311256
2767
+ function hueToRgb(p, q, t) {
2768
+ if (t < 0)
2769
+ t += 1;
2770
+ if (t > 1)
2771
+ t -= 1;
2772
+ if (t < 1 / 6)
2773
+ return p + (q - p) * 6 * t;
2774
+ if (t < 1 / 2)
2775
+ return q;
2776
+ if (t < 2 / 3)
2777
+ return p + (q - p) * (2 / 3 - t) * 6;
2778
+ return p;
2779
+ }
2780
+ function hslaToRgba({ hue, saturation, lightness, alpha }) {
2781
+ hue /= 360;
2782
+ saturation /= 100;
2783
+ lightness /= 100;
2784
+ let red = 0;
2785
+ let green = 0;
2786
+ let blue = 0;
2787
+ if (!saturation) {
2788
+ red = green = blue = lightness;
2789
+ }
2790
+ else {
2791
+ const q = lightness < 0.5
2792
+ ? lightness * (1 + saturation)
2793
+ : lightness + saturation - lightness * saturation;
2794
+ const p = 2 * lightness - q;
2795
+ red = hueToRgb(p, q, hue + 1 / 3);
2796
+ green = hueToRgb(p, q, hue);
2797
+ blue = hueToRgb(p, q, hue - 1 / 3);
2798
+ }
2799
+ return {
2800
+ red: Math.round(red * 255),
2801
+ green: Math.round(green * 255),
2802
+ blue: Math.round(blue * 255),
2803
+ alpha,
2804
+ };
2805
+ }
2806
+
2807
+ // Linear color space blending
2808
+ // Explained https://www.youtube.com/watch?v=LKnqECcg6Gw
2809
+ // Demonstrated http://codepen.io/osublake/pen/xGVVaN
2810
+ const mixLinearColor = (from, to, v) => {
2811
+ const fromExpo = from * from;
2812
+ return Math.sqrt(Math.max(0, v * (to * to - fromExpo) + fromExpo));
2813
+ };
2814
+ const colorTypes = [hex, rgba, hsla];
2815
+ const getColorType = (v) => colorTypes.find((type) => type.test(v));
2816
+ function asRGBA(color) {
2817
+ const type = getColorType(color);
2818
+ exports.invariant(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
2819
+ let model = type.parse(color);
2820
+ if (type === hsla) {
2821
+ // TODO Remove this cast - needed since Framer Motion's stricter typing
2822
+ model = hslaToRgba(model);
2823
+ }
2824
+ return model;
2825
+ }
2826
+ const mixColor = (from, to) => {
2827
+ const fromRGBA = asRGBA(from);
2828
+ const toRGBA = asRGBA(to);
2829
+ const blended = { ...fromRGBA };
2830
+ return (v) => {
2831
+ blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
2832
+ blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
2833
+ blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
2834
+ blended.alpha = mix(fromRGBA.alpha, toRGBA.alpha, v);
2835
+ return rgba.transform(blended);
2836
+ };
2837
+ };
2838
+
2839
+ function getMixer$1(origin, target) {
2840
+ if (typeof origin === "number") {
2841
+ return (v) => mix(origin, target, v);
2842
+ }
2843
+ else if (color.test(origin)) {
2844
+ return mixColor(origin, target);
2845
+ }
2846
+ else {
2847
+ return mixComplex(origin, target);
2848
+ }
2849
+ }
2850
+ const mixArray = (from, to) => {
2851
+ const output = [...from];
2852
+ const numValues = output.length;
2853
+ const blendValue = from.map((fromThis, i) => getMixer$1(fromThis, to[i]));
2854
+ return (v) => {
2855
+ for (let i = 0; i < numValues; i++) {
2856
+ output[i] = blendValue[i](v);
2857
+ }
2858
+ return output;
2859
+ };
2860
+ };
2861
+ const mixObject = (origin, target) => {
2862
+ const output = { ...origin, ...target };
2863
+ const blendValue = {};
2864
+ for (const key in output) {
2865
+ if (origin[key] !== undefined && target[key] !== undefined) {
2866
+ blendValue[key] = getMixer$1(origin[key], target[key]);
2867
+ }
2868
+ }
2869
+ return (v) => {
2870
+ for (const key in blendValue) {
2871
+ output[key] = blendValue[key](v);
2872
+ }
2873
+ return output;
2874
+ };
2875
+ };
2876
+ const mixComplex = (origin, target) => {
2877
+ const template = complex.createTransformer(target);
2878
+ const originStats = analyseComplexValue(origin);
2879
+ const targetStats = analyseComplexValue(target);
2880
+ const canInterpolate = originStats.numColors === targetStats.numColors &&
2881
+ originStats.numNumbers >= targetStats.numNumbers;
2882
+ if (canInterpolate) {
2883
+ return pipe(mixArray(originStats.values, targetStats.values), template);
2884
+ }
2885
+ else {
2886
+ exports.warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`);
2887
+ return (p) => `${p > 0 ? target : origin}`;
2888
+ }
2889
+ };
2890
+
2891
+ /*
2892
+ Progress within given range
2893
+
2894
+ Given a lower limit and an upper limit, we return the progress
2895
+ (expressed as a number 0-1) represented by the given value, and
2896
+ limit that progress to within 0-1.
2897
+
2898
+ @param [number]: Lower limit
2899
+ @param [number]: Upper limit
2900
+ @param [number]: Value to find progress within given range
2901
+ @return [number]: Progress of value within range as expressed 0-1
2902
+ */
2903
+ const progress = (from, to, value) => {
2904
+ const toFromDifference = to - from;
2905
+ return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
2906
+ };
2907
+
2908
+ const mixNumber = (from, to) => (p) => mix(from, to, p);
2909
+ function detectMixerFactory(v) {
2910
+ if (typeof v === "number") {
2911
+ return mixNumber;
2912
+ }
2913
+ else if (typeof v === "string") {
2914
+ if (color.test(v)) {
2915
+ return mixColor;
2916
+ }
2917
+ else {
2918
+ return mixComplex;
2919
+ }
2920
+ }
2921
+ else if (Array.isArray(v)) {
2922
+ return mixArray;
2923
+ }
2924
+ else if (typeof v === "object") {
2925
+ return mixObject;
2926
+ }
2927
+ return mixNumber;
2928
+ }
2929
+ function createMixers(output, ease, customMixer) {
2930
+ const mixers = [];
2931
+ const mixerFactory = customMixer || detectMixerFactory(output[0]);
2932
+ const numMixers = output.length - 1;
2933
+ for (let i = 0; i < numMixers; i++) {
2934
+ let mixer = mixerFactory(output[i], output[i + 1]);
2935
+ if (ease) {
2936
+ const easingFunction = Array.isArray(ease) ? ease[i] : ease;
2937
+ mixer = pipe(easingFunction, mixer);
2938
+ }
2939
+ mixers.push(mixer);
2940
+ }
2941
+ return mixers;
2942
+ }
2943
+ /**
2944
+ * Create a function that maps from a numerical input array to a generic output array.
2945
+ *
2946
+ * Accepts:
2947
+ * - Numbers
2948
+ * - Colors (hex, hsl, hsla, rgb, rgba)
2949
+ * - Complex (combinations of one or more numbers or strings)
2950
+ *
2951
+ * ```jsx
2952
+ * const mixColor = interpolate([0, 1], ['#fff', '#000'])
2953
+ *
2954
+ * mixColor(0.5) // 'rgba(128, 128, 128, 1)'
2955
+ * ```
2956
+ *
2957
+ * TODO Revist this approach once we've moved to data models for values,
2958
+ * probably not needed to pregenerate mixer functions.
2959
+ *
2960
+ * @public
2961
+ */
2962
+ function interpolate(input, output, { clamp: isClamp = true, ease, mixer } = {}) {
2963
+ const inputLength = input.length;
2964
+ exports.invariant(inputLength === output.length, "Both input and output ranges must be the same length");
2965
+ exports.invariant(!ease || !Array.isArray(ease) || ease.length === inputLength - 1, "Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.");
2966
+ // If input runs highest -> lowest, reverse both arrays
2967
+ if (input[0] > input[inputLength - 1]) {
2968
+ input = [...input].reverse();
2969
+ output = [...output].reverse();
2970
+ }
2971
+ const mixers = createMixers(output, ease, mixer);
2972
+ const numMixers = mixers.length;
2973
+ const interpolator = (v) => {
2974
+ let i = 0;
2975
+ if (numMixers > 1) {
2976
+ for (; i < input.length - 2; i++) {
2977
+ if (v < input[i + 1])
2978
+ break;
2979
+ }
2980
+ }
2981
+ const progressInRange = progress(input[i], input[i + 1], v);
2982
+ return mixers[i](progressInRange);
2983
+ };
2984
+ return isClamp
2985
+ ? (v) => interpolator(clamp(input[0], input[inputLength - 1], v))
2986
+ : interpolator;
2987
+ }
2988
+
2989
+ function fillOffset(offset, remaining) {
2990
+ const min = offset[offset.length - 1];
2991
+ for (let i = 1; i <= remaining; i++) {
2992
+ const offsetProgress = progress(0, remaining, i);
2993
+ offset.push(mix(min, 1, offsetProgress));
2994
+ }
2995
+ }
2996
+
2997
+ function defaultOffset$1(arr) {
2998
+ const offset = [0];
2999
+ fillOffset(offset, arr.length - 1);
3000
+ return offset;
3001
+ }
3002
+
3003
+ function convertOffsetToTimes(offset, duration) {
3004
+ return offset.map((o) => o * duration);
3005
+ }
3006
+
3007
+ /*
3008
+ Bezier function generator
3009
+ This has been modified from Gaëtan Renaudeau's BezierEasing
3010
+ https://github.com/gre/bezier-easing/blob/master/src/index.js
3011
+ https://github.com/gre/bezier-easing/blob/master/LICENSE
3012
+
3013
+ I've removed the newtonRaphsonIterate algo because in benchmarking it
3014
+ wasn't noticiably faster than binarySubdivision, indeed removing it
3015
+ usually improved times, depending on the curve.
3016
+ I also removed the lookup table, as for the added bundle size and loop we're
3017
+ only cutting ~4 or so subdivision iterations. I bumped the max iterations up
3018
+ to 12 to compensate and this still tended to be faster for no perceivable
3019
+ loss in accuracy.
3020
+ Usage
3021
+ const easeOut = cubicBezier(.17,.67,.83,.67);
3022
+ const x = easeOut(0.5); // returns 0.627...
3023
+ */
3024
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
3025
+ const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
3026
+ t;
3027
+ const subdivisionPrecision = 0.0000001;
3028
+ const subdivisionMaxIterations = 12;
3029
+ function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
3030
+ let currentX;
3031
+ let currentT;
3032
+ let i = 0;
3033
+ do {
3034
+ currentT = lowerBound + (upperBound - lowerBound) / 2.0;
3035
+ currentX = calcBezier(currentT, mX1, mX2) - x;
3036
+ if (currentX > 0.0) {
3037
+ upperBound = currentT;
3038
+ }
3039
+ else {
3040
+ lowerBound = currentT;
3041
+ }
3042
+ } while (Math.abs(currentX) > subdivisionPrecision &&
3043
+ ++i < subdivisionMaxIterations);
3044
+ return currentT;
3045
+ }
3046
+ function cubicBezier(mX1, mY1, mX2, mY2) {
3047
+ // If this is a linear gradient, return linear easing
3048
+ if (mX1 === mY1 && mX2 === mY2)
3049
+ return noop;
3050
+ const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
3051
+ // If animation is at start/end, return t without easing
3052
+ return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
3053
+ }
3054
+
3055
+ const circIn = (p) => 1 - Math.sin(Math.acos(p));
3056
+ const circOut = reverseEasing(circIn);
3057
+ const circInOut = mirrorEasing(circOut);
3058
+
3059
+ const backOut = cubicBezier(0.33, 1.53, 0.69, 0.99);
3060
+ const backIn = reverseEasing(backOut);
3061
+ const backInOut = mirrorEasing(backIn);
3062
+
3063
+ const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
3064
+
3065
+ const easingLookup = {
3066
+ linear: noop,
3067
+ easeIn,
3068
+ easeInOut,
3069
+ easeOut,
3070
+ circIn,
3071
+ circInOut,
3072
+ circOut,
3073
+ backIn,
3074
+ backInOut,
3075
+ backOut,
3076
+ anticipate,
3077
+ };
3078
+ const easingDefinitionToFunction = (definition) => {
3079
+ if (Array.isArray(definition)) {
3080
+ // If cubic bezier definition, create bezier curve
3081
+ exports.invariant(definition.length === 4, `Cubic bezier arrays must contain four numerical values.`);
3082
+ const [x1, y1, x2, y2] = definition;
3083
+ return cubicBezier(x1, y1, x2, y2);
3084
+ }
3085
+ else if (typeof definition === "string") {
3086
+ // Else lookup from table
3087
+ exports.invariant(easingLookup[definition] !== undefined, `Invalid easing type '${definition}'`);
3088
+ return easingLookup[definition];
3089
+ }
3090
+ return definition;
3091
+ };
3092
+ const isEasingArray = (ease) => {
3093
+ return Array.isArray(ease) && typeof ease[0] !== "number";
3094
+ };
3095
+
3096
+ function defaultEasing(values, easing) {
3097
+ return values.map(() => easing || easeInOut).splice(0, values.length - 1);
3098
+ }
3099
+ function keyframes({ keyframes: keyframeValues, ease = easeInOut, times, duration = 300, }) {
3100
+ keyframeValues = [...keyframeValues];
3101
+ /**
3102
+ * Easing functions can be externally defined as strings. Here we convert them
3103
+ * into actual functions.
3104
+ */
3105
+ const easingFunctions = isEasingArray(ease)
3106
+ ? ease.map(easingDefinitionToFunction)
3107
+ : easingDefinitionToFunction(ease);
3108
+ /**
3109
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
3110
+ * to reduce GC during animation.
3111
+ */
3112
+ const state = {
3113
+ done: false,
3114
+ value: keyframeValues[0],
3115
+ };
3116
+ /**
3117
+ * Create a times array based on the provided 0-1 offsets
3118
+ */
3119
+ const absoluteTimes = convertOffsetToTimes(
3120
+ // Only use the provided offsets if they're the correct length
3121
+ // TODO Maybe we should warn here if there's a length mismatch
3122
+ times && times.length === keyframeValues.length
3123
+ ? times
3124
+ : defaultOffset$1(keyframeValues), duration);
3125
+ function createInterpolator() {
3126
+ return interpolate(absoluteTimes, keyframeValues, {
3127
+ ease: Array.isArray(easingFunctions)
3128
+ ? easingFunctions
3129
+ : defaultEasing(keyframeValues, easingFunctions),
3130
+ });
3131
+ }
3132
+ let interpolator = createInterpolator();
3133
+ return {
3134
+ next: (t) => {
3135
+ state.value = interpolator(t);
3136
+ state.done = t >= duration;
3137
+ return state;
3138
+ },
3139
+ flipTarget: () => {
3140
+ keyframeValues.reverse();
3141
+ interpolator = createInterpolator();
3142
+ },
3143
+ };
3144
+ }
3145
+
3146
+ const safeMin = 0.001;
3147
+ const minDuration = 0.01;
3148
+ const maxDuration = 10.0;
3149
+ const minDamping = 0.05;
3150
+ const maxDamping = 1;
3151
+ function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }) {
3152
+ let envelope;
3153
+ let derivative;
3154
+ exports.warning(duration <= maxDuration * 1000, "Spring duration must be 10 seconds or less");
3155
+ let dampingRatio = 1 - bounce;
3156
+ /**
3157
+ * Restrict dampingRatio and duration to within acceptable ranges.
3158
+ */
3159
+ dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
3160
+ duration = clamp(minDuration, maxDuration, duration / 1000);
3161
+ if (dampingRatio < 1) {
3162
+ /**
3163
+ * Underdamped spring
3164
+ */
3165
+ envelope = (undampedFreq) => {
3166
+ const exponentialDecay = undampedFreq * dampingRatio;
3167
+ const delta = exponentialDecay * duration;
3168
+ const a = exponentialDecay - velocity;
3169
+ const b = calcAngularFreq(undampedFreq, dampingRatio);
3170
+ const c = Math.exp(-delta);
3171
+ return safeMin - (a / b) * c;
3172
+ };
3173
+ derivative = (undampedFreq) => {
3174
+ const exponentialDecay = undampedFreq * dampingRatio;
3175
+ const delta = exponentialDecay * duration;
3176
+ const d = delta * velocity + velocity;
3177
+ const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration;
3178
+ const f = Math.exp(-delta);
3179
+ const g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio);
3180
+ const factor = -envelope(undampedFreq) + safeMin > 0 ? -1 : 1;
3181
+ return (factor * ((d - e) * f)) / g;
3182
+ };
3183
+ }
3184
+ else {
3185
+ /**
3186
+ * Critically-damped spring
3187
+ */
3188
+ envelope = (undampedFreq) => {
3189
+ const a = Math.exp(-undampedFreq * duration);
3190
+ const b = (undampedFreq - velocity) * duration + 1;
3191
+ return -safeMin + a * b;
3192
+ };
3193
+ derivative = (undampedFreq) => {
3194
+ const a = Math.exp(-undampedFreq * duration);
3195
+ const b = (velocity - undampedFreq) * (duration * duration);
3196
+ return a * b;
3197
+ };
3198
+ }
3199
+ const initialGuess = 5 / duration;
3200
+ const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
3201
+ duration = duration * 1000;
3202
+ if (isNaN(undampedFreq)) {
3203
+ return {
3204
+ stiffness: 100,
3205
+ damping: 10,
3206
+ duration,
3207
+ };
3208
+ }
3209
+ else {
3210
+ const stiffness = Math.pow(undampedFreq, 2) * mass;
3211
+ return {
3212
+ stiffness,
3213
+ damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
3214
+ duration,
3215
+ };
3216
+ }
3217
+ }
3218
+ const rootIterations = 12;
3219
+ function approximateRoot(envelope, derivative, initialGuess) {
3220
+ let result = initialGuess;
3221
+ for (let i = 1; i < rootIterations; i++) {
3222
+ result = result - envelope(result) / derivative(result);
3223
+ }
3224
+ return result;
3225
+ }
3226
+ function calcAngularFreq(undampedFreq, dampingRatio) {
3227
+ return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
3228
+ }
3229
+
3230
+ const durationKeys = ["duration", "bounce"];
3231
+ const physicsKeys = ["stiffness", "damping", "mass"];
3232
+ function isSpringType(options, keys) {
3233
+ return keys.some((key) => options[key] !== undefined);
3234
+ }
3235
+ function getSpringOptions(options) {
3236
+ let springOptions = {
3237
+ velocity: 0.0,
3238
+ stiffness: 100,
3239
+ damping: 10,
3240
+ mass: 1.0,
3241
+ isResolvedFromDuration: false,
3242
+ ...options,
3243
+ };
3244
+ // stiffness/damping/mass overrides duration/bounce
3245
+ if (!isSpringType(options, physicsKeys) &&
3246
+ isSpringType(options, durationKeys)) {
3247
+ const derived = findSpring(options);
3248
+ springOptions = {
3249
+ ...springOptions,
3250
+ ...derived,
3251
+ velocity: 0.0,
3252
+ mass: 1.0,
3253
+ };
3254
+ springOptions.isResolvedFromDuration = true;
3255
+ }
3256
+ return springOptions;
3257
+ }
3258
+ const velocitySampleDuration = 5;
3259
+ /**
3260
+ * This is based on the spring implementation of Wobble https://github.com/skevy/wobble
3261
+ */
3262
+ function spring({ keyframes, restDelta, restSpeed, ...options }) {
3263
+ let origin = keyframes[0];
3264
+ let target = keyframes[keyframes.length - 1];
3265
+ /**
3266
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
3267
+ * to reduce GC during animation.
3268
+ */
3269
+ const state = { done: false, value: origin };
3270
+ const { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
3271
+ let resolveSpring = zero;
3272
+ let initialVelocity = velocity ? -(velocity / 1000) : 0.0;
3273
+ const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
3274
+ function createSpring() {
3275
+ const initialDelta = target - origin;
3276
+ const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
3277
+ /**
3278
+ * If we're working on a granular scale, use smaller defaults for determining
3279
+ * when the spring is finished.
3280
+ *
3281
+ * These defaults have been selected emprically based on what strikes a good
3282
+ * ratio between feeling good and finishing as soon as changes are imperceptible.
3283
+ */
3284
+ const isGranularScale = Math.abs(initialDelta) < 5;
3285
+ restSpeed || (restSpeed = isGranularScale ? 0.01 : 2);
3286
+ restDelta || (restDelta = isGranularScale ? 0.005 : 0.5);
3287
+ if (dampingRatio < 1) {
3288
+ const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
3289
+ // Underdamped spring
3290
+ resolveSpring = (t) => {
3291
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
3292
+ return (target -
3293
+ envelope *
3294
+ (((initialVelocity +
3295
+ dampingRatio * undampedAngularFreq * initialDelta) /
3296
+ angularFreq) *
3297
+ Math.sin(angularFreq * t) +
3298
+ initialDelta * Math.cos(angularFreq * t)));
3299
+ };
3300
+ }
3301
+ else if (dampingRatio === 1) {
3302
+ // Critically damped spring
3303
+ resolveSpring = (t) => target -
3304
+ Math.exp(-undampedAngularFreq * t) *
3305
+ (initialDelta +
3306
+ (initialVelocity + undampedAngularFreq * initialDelta) *
3307
+ t);
3308
+ }
3309
+ else {
3310
+ // Overdamped spring
3311
+ const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
3312
+ resolveSpring = (t) => {
3313
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
3314
+ // When performing sinh or cosh values can hit Infinity so we cap them here
3315
+ const freqForT = Math.min(dampedAngularFreq * t, 300);
3316
+ return (target -
3317
+ (envelope *
3318
+ ((initialVelocity +
3319
+ dampingRatio * undampedAngularFreq * initialDelta) *
3320
+ Math.sinh(freqForT) +
3321
+ dampedAngularFreq *
3322
+ initialDelta *
3323
+ Math.cosh(freqForT))) /
3324
+ dampedAngularFreq);
3325
+ };
3326
+ }
3327
+ }
3328
+ createSpring();
3329
+ return {
3330
+ next: (t) => {
3331
+ const current = resolveSpring(t);
3332
+ if (!isResolvedFromDuration) {
3333
+ let currentVelocity = initialVelocity;
3334
+ if (t !== 0) {
3335
+ /**
3336
+ * We only need to calculate velocity for under-damped springs
3337
+ * as over- and critically-damped springs can't overshoot, so
3338
+ * checking only for displacement is enough.
3339
+ */
3340
+ if (dampingRatio < 1) {
3341
+ const prevT = Math.max(0, t - velocitySampleDuration);
3342
+ currentVelocity = velocityPerSecond(current - resolveSpring(prevT), t - prevT);
3343
+ }
3344
+ else {
3345
+ currentVelocity = 0;
3346
+ }
3347
+ }
3348
+ const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
3349
+ const isBelowDisplacementThreshold = Math.abs(target - current) <= restDelta;
3350
+ state.done =
3351
+ isBelowVelocityThreshold && isBelowDisplacementThreshold;
3352
+ }
3353
+ else {
3354
+ state.done = t >= duration;
3355
+ }
3356
+ state.value = state.done ? target : current;
3357
+ return state;
3358
+ },
3359
+ flipTarget: () => {
3360
+ initialVelocity = -initialVelocity;
3361
+ [origin, target] = [target, origin];
3362
+ createSpring();
3363
+ },
3364
+ };
3365
+ }
3366
+ spring.needsInterpolation = (a, b) => typeof a === "string" || typeof b === "string";
3367
+ const zero = (_t) => 0;
3368
+
3369
+ function decay({
3370
+ /**
3371
+ * The decay animation dynamically calculates an end of the animation
3372
+ * based on the initial keyframe, so we only need to define a single keyframe
3373
+ * as default.
3374
+ */
3375
+ keyframes = [0], velocity = 0, power = 0.8, timeConstant = 350, restDelta = 0.5, modifyTarget, }) {
3376
+ const origin = keyframes[0];
3377
+ /**
3378
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
3379
+ * to reduce GC during animation.
3380
+ */
3381
+ const state = { done: false, value: origin };
3382
+ let amplitude = power * velocity;
3383
+ const ideal = origin + amplitude;
3384
+ const target = modifyTarget === undefined ? ideal : modifyTarget(ideal);
3385
+ /**
3386
+ * If the target has changed we need to re-calculate the amplitude, otherwise
3387
+ * the animation will start from the wrong position.
3388
+ */
3389
+ if (target !== ideal)
3390
+ amplitude = target - origin;
3391
+ return {
3392
+ next: (t) => {
3393
+ const delta = -amplitude * Math.exp(-t / timeConstant);
3394
+ state.done = !(delta > restDelta || delta < -restDelta);
3395
+ state.value = state.done ? target : target + delta;
3396
+ return state;
3397
+ },
3398
+ flipTarget: () => { },
3399
+ };
3400
+ }
3401
+
3402
+ const types = {
3403
+ decay,
3404
+ keyframes: keyframes,
3405
+ tween: keyframes,
3406
+ spring,
3407
+ };
3408
+ function loopElapsed(elapsed, duration, delay = 0) {
3409
+ return elapsed - duration - delay;
3410
+ }
3411
+ function reverseElapsed(elapsed, duration = 0, delay = 0, isForwardPlayback = true) {
3412
+ return isForwardPlayback
3413
+ ? loopElapsed(duration + -elapsed, duration, delay)
3414
+ : duration - (elapsed - duration) + delay;
3415
+ }
3416
+ function hasRepeatDelayElapsed(elapsed, duration, delay, isForwardPlayback) {
3417
+ return isForwardPlayback ? elapsed >= duration + delay : elapsed <= -delay;
3418
+ }
3419
+ const framesync = (update) => {
3420
+ const passTimestamp = ({ delta }) => update(delta);
3421
+ return {
3422
+ start: () => sync.update(passTimestamp, true),
3423
+ stop: () => cancelSync.update(passTimestamp),
3424
+ };
3425
+ };
3426
+ function animateValue({ duration, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, keyframes: keyframes$1, autoplay = true, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
3427
+ const initialElapsed = elapsed;
3428
+ let driverControls;
3429
+ let repeatCount = 0;
3430
+ let computedDuration = duration;
3431
+ let isComplete = false;
3432
+ let isForwardPlayback = true;
3433
+ let interpolateFromNumber;
3434
+ const animator = types[keyframes$1.length > 2 ? "keyframes" : type] || keyframes;
3435
+ const origin = keyframes$1[0];
3436
+ const target = keyframes$1[keyframes$1.length - 1];
3437
+ let state = { done: false, value: origin };
3438
+ /**
3439
+ * If this value needs interpolation (ie is non-numerical), set up an interpolator.
3440
+ * TODO: Keyframes animation also performs this step. This could be removed so it only happens here.
3441
+ */
3442
+ const { needsInterpolation } = animator;
3443
+ if (needsInterpolation && needsInterpolation(origin, target)) {
3444
+ interpolateFromNumber = interpolate([0, 100], [origin, target], {
3445
+ clamp: false,
3446
+ });
3447
+ keyframes$1 = [0, 100];
3448
+ }
3449
+ const animation = animator({
3450
+ ...options,
3451
+ duration,
3452
+ keyframes: keyframes$1,
3453
+ });
3454
+ function repeat() {
3455
+ repeatCount++;
3456
+ if (repeatType === "reverse") {
3457
+ isForwardPlayback = repeatCount % 2 === 0;
3458
+ elapsed = reverseElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback);
3459
+ }
3460
+ else {
3461
+ elapsed = loopElapsed(elapsed, computedDuration, repeatDelay);
3462
+ if (repeatType === "mirror")
3463
+ animation.flipTarget();
3464
+ }
3465
+ isComplete = false;
3466
+ onRepeat && onRepeat();
3467
+ }
3468
+ function complete() {
3469
+ driverControls && driverControls.stop();
3470
+ onComplete && onComplete();
3471
+ }
3472
+ function update(delta) {
3473
+ if (!isForwardPlayback)
3474
+ delta = -delta;
3475
+ elapsed += delta;
3476
+ if (!isComplete) {
3477
+ state = animation.next(Math.max(0, elapsed));
3478
+ if (interpolateFromNumber)
3479
+ state.value = interpolateFromNumber(state.value);
3480
+ isComplete = isForwardPlayback ? state.done : elapsed <= 0;
3481
+ }
3482
+ onUpdate && onUpdate(state.value);
3483
+ if (isComplete) {
3484
+ if (repeatCount === 0) {
3485
+ computedDuration =
3486
+ computedDuration !== undefined ? computedDuration : elapsed;
3487
+ }
3488
+ if (repeatCount < repeatMax) {
3489
+ hasRepeatDelayElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback) && repeat();
3490
+ }
3491
+ else {
3492
+ complete();
3493
+ }
3494
+ }
3495
+ }
3496
+ function play() {
3497
+ onPlay && onPlay();
3498
+ driverControls = driver(update);
3499
+ driverControls.start();
3500
+ }
3501
+ autoplay && play();
3502
+ return {
3503
+ stop: () => {
3504
+ onStop && onStop();
3505
+ driverControls && driverControls.stop();
3506
+ },
3507
+ /**
3508
+ * Set the current time of the animation. This is purposefully
3509
+ * mirroring the WAAPI animation API to make them interchanagable.
3510
+ * Going forward this file should be ported more towards
3511
+ * https://github.com/motiondivision/motionone/blob/main/packages/animation/src/Animation.ts
3512
+ * Which behaviourally adheres to WAAPI as far as possible.
3513
+ *
3514
+ * WARNING: This is not safe to use for most animations. We currently
3515
+ * only use it for handoff from WAAPI within Framer.
3516
+ *
3517
+ * This animation function consumes time every frame rather than being sampled for time.
3518
+ * So the sample() method performs some headless frames to ensure
3519
+ * repeats are handled correctly. Ideally in the future we will replace
3520
+ * that method with this, once repeat calculations are pure.
3521
+ */
3522
+ set currentTime(t) {
3523
+ elapsed = initialElapsed;
3524
+ update(t);
3525
+ },
3526
+ /**
3527
+ * animate() can't yet be sampled for time, instead it
3528
+ * consumes time. So to sample it we have to run a low
3529
+ * temporal-resolution version.
3530
+ *
3531
+ * isControlled should be set to true if sample is being run within
3532
+ * a loop. This indicates that we're not arbitrarily sampling
3533
+ * the animation but running it one step after another. Therefore
3534
+ * we don't need to run a low-res version here. This is a stop-gap
3535
+ * until a rewrite can sample for time.
3536
+ */
3537
+ sample: (t, isControlled = false) => {
3538
+ elapsed = initialElapsed;
3539
+ if (isControlled) {
3540
+ update(t);
3541
+ return state;
3542
+ }
3543
+ const sampleResolution = duration && typeof duration === "number"
3544
+ ? Math.max(duration * 0.5, 50)
3545
+ : 50;
3546
+ let sampleElapsed = 0;
3547
+ update(0);
3548
+ while (sampleElapsed <= t) {
3549
+ const remaining = t - sampleElapsed;
3550
+ update(Math.min(remaining, sampleResolution));
3551
+ sampleElapsed += sampleResolution;
3552
+ }
3553
+ return state;
3554
+ },
3555
+ };
3556
+ }
3557
+
3558
+ function isWaapiSupportedEasing(easing) {
3559
+ return (!easing || // Default easing
3560
+ Array.isArray(easing) || // Bezier curve
3561
+ (typeof easing === "string" && supportedWaapiEasing[easing]));
3562
+ }
3563
+ const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
3564
+ const supportedWaapiEasing = {
3565
+ linear: "linear",
3566
+ ease: "ease",
3567
+ easeIn: "ease-in",
3568
+ easeOut: "ease-out",
3569
+ easeInOut: "ease-in-out",
3570
+ circIn: cubicBezierAsString([0, 0.65, 0.55, 1]),
3571
+ circOut: cubicBezierAsString([0.55, 0, 1, 0.45]),
3572
+ backIn: cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
3573
+ backOut: cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
3574
+ };
3575
+ function mapEasingToNativeEasing(easing) {
3576
+ if (!easing)
3577
+ return undefined;
3578
+ return Array.isArray(easing)
3579
+ ? cubicBezierAsString(easing)
3580
+ : supportedWaapiEasing[easing];
3581
+ }
3582
+
3583
+ function animateStyle(element, valueName, keyframes, { delay = 0, duration, repeat = 0, repeatType = "loop", ease, times, } = {}) {
3584
+ const keyframeOptions = { [valueName]: keyframes };
3585
+ if (times)
3586
+ keyframeOptions.offset = times;
3587
+ return element.animate(keyframeOptions, {
3588
+ delay,
3589
+ duration,
3590
+ easing: mapEasingToNativeEasing(ease),
3591
+ fill: "both",
3592
+ iterations: repeat + 1,
3593
+ direction: repeatType === "reverse" ? "alternate" : "normal",
3594
+ });
3595
+ }
3596
+
3597
+ const featureTests = {
3598
+ waapi: () => Object.hasOwnProperty.call(Element.prototype, "animate"),
3599
+ };
3600
+ const results = {};
3601
+ const supports = {};
3602
+ /**
3603
+ * Generate features tests that cache their results.
3604
+ */
3605
+ for (const key in featureTests) {
3606
+ supports[key] = () => {
3607
+ if (results[key] === undefined)
3608
+ results[key] = featureTests[key]();
3609
+ return results[key];
3610
+ };
3611
+ }
3612
+
3613
+ function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }) {
3614
+ const index = repeat && repeatType !== "loop" && repeat % 2 === 1
3615
+ ? 0
3616
+ : keyframes.length - 1;
3617
+ return keyframes[index];
3618
+ }
3619
+
3620
+ /**
3621
+ * A list of values that can be hardware-accelerated.
3622
+ */
3623
+ const acceleratedValues = new Set([
3624
+ "opacity",
3625
+ "clipPath",
3626
+ "filter",
3627
+ "transform",
3628
+ "backgroundColor",
3629
+ ]);
3630
+ /**
3631
+ * 10ms is chosen here as it strikes a balance between smooth
3632
+ * results (more than one keyframe per frame at 60fps) and
3633
+ * keyframe quantity.
3634
+ */
3635
+ const sampleDelta = 10; //ms
3636
+ const requiresPregeneratedKeyframes = (valueName, options) => options.type === "spring" ||
3637
+ valueName === "backgroundColor" ||
3638
+ !isWaapiSupportedEasing(options.ease);
3639
+ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ...options }) {
3640
+ const canAccelerateAnimation = supports.waapi() &&
3641
+ acceleratedValues.has(valueName) &&
3642
+ !options.repeatDelay &&
3643
+ options.repeatType !== "mirror" &&
3644
+ options.damping !== 0;
3645
+ if (!canAccelerateAnimation)
3646
+ return false;
3647
+ let { keyframes, duration = 300, elapsed = 0, ease } = options;
3648
+ /**
3649
+ * If this animation needs pre-generated keyframes then generate.
3650
+ */
3651
+ if (requiresPregeneratedKeyframes(valueName, options)) {
3652
+ const sampleAnimation = animateValue({
3653
+ ...options,
3654
+ repeat: 0,
3655
+ elapsed: 0,
3656
+ });
3657
+ let state = { done: false, value: keyframes[0] };
3658
+ const pregeneratedKeyframes = [];
3659
+ /**
3660
+ * Bail after 20 seconds of pre-generated keyframes as it's likely
3661
+ * we're heading for an infinite loop.
3662
+ */
3663
+ let t = 0;
3664
+ while (!state.done && t < 20000) {
3665
+ state = sampleAnimation.sample(t, true);
3666
+ pregeneratedKeyframes.push(state.value);
3667
+ t += sampleDelta;
3668
+ }
3669
+ keyframes = pregeneratedKeyframes;
3670
+ duration = t - sampleDelta;
3671
+ ease = "linear";
3672
+ }
3673
+ const animation = animateStyle(value.owner.current, valueName, keyframes, {
3674
+ ...options,
3675
+ delay: -elapsed,
3676
+ duration,
3677
+ /**
3678
+ * This function is currently not called if ease is provided
3679
+ * as a function so the cast is safe.
3680
+ *
3681
+ * However it would be possible for a future refinement to port
3682
+ * in easing pregeneration from Motion One for browsers that
3683
+ * support the upcoming `linear()` easing function.
3684
+ */
3685
+ ease: ease,
3686
+ });
3687
+ /**
3688
+ * Prefer the `onfinish` prop as it's more widely supported than
3689
+ * the `finished` promise.
3690
+ *
3691
+ * Here, we synchronously set the provided MotionValue to the end
3692
+ * keyframe. If we didn't, when the WAAPI animation is finished it would
3693
+ * be removed from the element which would then revert to its old styles.
3694
+ */
3695
+ animation.onfinish = () => {
3696
+ value.set(getFinalKeyframe(keyframes, options));
3697
+ sync.update(() => animation.cancel());
3698
+ onComplete && onComplete();
3699
+ };
3700
+ /**
3701
+ * Animation interrupt callback.
3702
+ */
3703
+ return {
3704
+ get currentTime() {
3705
+ return animation.currentTime || 0;
3706
+ },
3707
+ set currentTime(t) {
3708
+ animation.currentTime = t;
3709
+ },
3710
+ stop: () => {
3711
+ /**
3712
+ * WAAPI doesn't natively have any interruption capabilities.
3713
+ *
3714
+ * Rather than read commited styles back out of the DOM, we can
3715
+ * create a renderless JS animation and sample it twice to calculate
3716
+ * its current value, "previous" value, and therefore allow
3717
+ * Motion to calculate velocity for any subsequent animation.
3718
+ */
3719
+ const { currentTime } = animation;
3720
+ if (currentTime) {
3721
+ const sampleAnimation = animateValue({
3722
+ ...options,
3723
+ autoplay: false,
3724
+ });
3725
+ value.setWithVelocity(sampleAnimation.sample(currentTime - sampleDelta).value, sampleAnimation.sample(currentTime).value, sampleDelta);
3726
+ }
3727
+ sync.update(() => animation.cancel());
3728
+ },
3729
+ };
3730
+ }
3731
+
3732
+ /**
3733
+ * Timeout defined in ms
3734
+ */
3735
+ function delay(callback, timeout) {
3736
+ const start = performance.now();
3737
+ const checkElapsed = ({ timestamp }) => {
3738
+ const elapsed = timestamp - start;
3739
+ if (elapsed >= timeout) {
3740
+ cancelSync.read(checkElapsed);
3741
+ callback(elapsed - timeout);
3742
+ }
3743
+ };
3744
+ sync.read(checkElapsed, true);
3745
+ return () => cancelSync.read(checkElapsed);
3746
+ }
3747
+
3748
+ function createInstantAnimation({ keyframes, elapsed, onUpdate, onComplete, }) {
3749
+ const setValue = () => {
3750
+ onUpdate && onUpdate(keyframes[keyframes.length - 1]);
3751
+ onComplete && onComplete();
3752
+ };
3753
+ return elapsed ? { stop: delay(setValue, -elapsed) } : setValue();
3754
+ }
3755
+
3756
+ function inertia({ keyframes, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
3757
+ const origin = keyframes[0];
3758
+ let currentAnimation;
3759
+ function isOutOfBounds(v) {
3760
+ return (min !== undefined && v < min) || (max !== undefined && v > max);
3761
+ }
3762
+ function findNearestBoundary(v) {
3763
+ if (min === undefined)
3764
+ return max;
3765
+ if (max === undefined)
3766
+ return min;
3767
+ return Math.abs(min - v) < Math.abs(max - v) ? min : max;
3768
+ }
3769
+ function startAnimation(options) {
3770
+ currentAnimation && currentAnimation.stop();
3771
+ currentAnimation = animateValue({
3772
+ keyframes: [0, 1],
3773
+ velocity: 0,
3774
+ ...options,
3775
+ driver,
3776
+ onUpdate: (v) => {
3777
+ onUpdate && onUpdate(v);
3778
+ options.onUpdate && options.onUpdate(v);
3779
+ },
3780
+ onComplete,
3781
+ onStop,
3782
+ });
3783
+ }
3784
+ function startSpring(options) {
3785
+ startAnimation({
3786
+ type: "spring",
3787
+ stiffness: bounceStiffness,
3788
+ damping: bounceDamping,
3789
+ restDelta,
3790
+ ...options,
3791
+ });
3792
+ }
3793
+ if (isOutOfBounds(origin)) {
3794
+ // Start the animation with spring if outside the defined boundaries
3795
+ startSpring({
3796
+ velocity,
3797
+ keyframes: [origin, findNearestBoundary(origin)],
3798
+ });
3799
+ }
3800
+ else {
3801
+ /**
3802
+ * Or if the value is out of bounds, simulate the inertia movement
3803
+ * with the decay animation.
3804
+ *
3805
+ * Pre-calculate the target so we can detect if it's out-of-bounds.
3806
+ * If it is, we want to check per frame when to switch to a spring
3807
+ * animation
3808
+ */
3809
+ let target = power * velocity + origin;
3810
+ if (typeof modifyTarget !== "undefined")
3811
+ target = modifyTarget(target);
3812
+ const boundary = findNearestBoundary(target);
3813
+ const heading = boundary === min ? -1 : 1;
3814
+ let prev;
3815
+ let current;
3816
+ const checkBoundary = (v) => {
3817
+ prev = current;
3818
+ current = v;
3819
+ velocity = velocityPerSecond(v - prev, frameData.delta);
3820
+ if ((heading === 1 && v > boundary) ||
3821
+ (heading === -1 && v < boundary)) {
3822
+ startSpring({ keyframes: [v, boundary], velocity });
3823
+ }
3824
+ };
3825
+ startAnimation({
3826
+ type: "decay",
3827
+ keyframes: [origin, 0],
3828
+ velocity,
3829
+ timeConstant,
3830
+ power,
3831
+ restDelta,
3832
+ modifyTarget,
3833
+ onUpdate: isOutOfBounds(target) ? checkBoundary : undefined,
3834
+ });
3835
+ }
3836
+ return {
3837
+ stop: () => currentAnimation && currentAnimation.stop(),
3838
+ };
3839
+ }
3840
+
3841
+ const underDampedSpring = {
3842
+ type: "spring",
3843
+ stiffness: 500,
3844
+ damping: 25,
3845
+ restSpeed: 10,
3846
+ };
3847
+ const criticallyDampedSpring = (target) => ({
3848
+ type: "spring",
3849
+ stiffness: 550,
3850
+ damping: target === 0 ? 2 * Math.sqrt(550) : 30,
3851
+ restSpeed: 10,
3852
+ });
3853
+ const keyframesTransition = {
3854
+ type: "keyframes",
3855
+ duration: 0.8,
3856
+ };
3857
+ /**
3858
+ * Default easing curve is a slightly shallower version of
3859
+ * the default browser easing curve.
3860
+ */
3861
+ const ease = {
3862
+ type: "keyframes",
3863
+ ease: [0.25, 0.1, 0.35, 1],
3864
+ duration: 0.3,
3865
+ };
3866
+ const getDefaultTransition = (valueKey, { keyframes }) => {
3867
+ if (keyframes.length > 2) {
3868
+ return keyframesTransition;
3869
+ }
3870
+ else if (transformProps.has(valueKey)) {
3871
+ return valueKey.startsWith("scale")
3872
+ ? criticallyDampedSpring(keyframes[1])
3873
+ : underDampedSpring;
3874
+ }
3875
+ return ease;
3876
+ };
3877
+
3878
+ /**
3879
+ * Check if a value is animatable. Examples:
3880
+ *
3881
+ * ✅: 100, "100px", "#fff"
3882
+ * ❌: "block", "url(2.jpg)"
3883
+ * @param value
3884
+ *
3885
+ * @internal
3886
+ */
3887
+ const isAnimatable = (key, value) => {
3888
+ // If the list of keys tat might be non-animatable grows, replace with Set
3889
+ if (key === "zIndex")
3890
+ return false;
3891
+ // If it's a number or a keyframes array, we can animate it. We might at some point
3892
+ // need to do a deep isAnimatable check of keyframes, or let Popmotion handle this,
3893
+ // but for now lets leave it like this for performance reasons
3894
+ if (typeof value === "number" || Array.isArray(value))
3895
+ return true;
3896
+ if (typeof value === "string" && // It's animatable if we have a string
3897
+ complex.test(value) && // And it contains numbers and/or colors
3898
+ !value.startsWith("url(") // Unless it starts with "url("
3899
+ ) {
3900
+ return true;
3901
+ }
3902
+ return false;
3903
+ };
3904
+
3905
+ /**
3906
+ * Decide whether a transition is defined on a given Transition.
3907
+ * This filters out orchestration options and returns true
3908
+ * if any options are left.
3909
+ */
3910
+ function isTransitionDefined({ when, delay: _delay, delayChildren, staggerChildren, staggerDirection, repeat, repeatType, repeatDelay, from, elapsed, ...transition }) {
3911
+ return !!Object.keys(transition).length;
3912
+ }
3913
+ function isZero(value) {
3914
+ return (value === 0 ||
3915
+ (typeof value === "string" &&
3916
+ parseFloat(value) === 0 &&
3917
+ value.indexOf(" ") === -1));
3918
+ }
3919
+ function getZeroUnit(potentialUnitType) {
3920
+ return typeof potentialUnitType === "number"
3921
+ ? 0
3922
+ : getAnimatableNone("", potentialUnitType);
3923
+ }
3924
+ function getValueTransition(transition, key) {
3925
+ return transition[key] || transition["default"] || transition;
3926
+ }
3927
+
3928
+ function getKeyframes(value, valueName, target, transition) {
3929
+ const isTargetAnimatable = isAnimatable(valueName, target);
3930
+ let origin = transition.from !== undefined ? transition.from : value.get();
3931
+ if (origin === "none" && isTargetAnimatable && typeof target === "string") {
3932
+ /**
3933
+ * If we're trying to animate from "none", try and get an animatable version
3934
+ * of the target. This could be improved to work both ways.
3935
+ */
3936
+ origin = getAnimatableNone(valueName, target);
3937
+ }
3938
+ else if (isZero(origin) && typeof target === "string") {
3939
+ origin = getZeroUnit(target);
3940
+ }
3941
+ else if (!Array.isArray(target) &&
3942
+ isZero(target) &&
3943
+ typeof origin === "string") {
3944
+ target = getZeroUnit(origin);
3945
+ }
3946
+ /**
3947
+ * If the target has been defined as a series of keyframes
3948
+ */
3949
+ if (Array.isArray(target)) {
3950
+ /**
3951
+ * Ensure an initial wildcard keyframe is hydrated by the origin.
3952
+ * TODO: Support extra wildcard keyframes i.e [1, null, 0]
3953
+ */
3954
+ if (target[0] === null) {
3955
+ target[0] = origin;
3956
+ }
3957
+ return target;
3958
+ }
3959
+ else {
3960
+ return [origin, target];
3961
+ }
3962
+ }
3963
+
3964
+ const createMotionValueAnimation = (valueName, value, target, transition = {}) => {
3965
+ return (onComplete) => {
3966
+ const valueTransition = getValueTransition(transition, valueName) || {};
3967
+ /**
3968
+ * Most transition values are currently completely overwritten by value-specific
3969
+ * transitions. In the future it'd be nicer to blend these transitions. But for now
3970
+ * delay actually does inherit from the root transition if not value-specific.
1682
3971
  */
1683
- if (Array.isArray(targetValue)) {
1684
- value = targetValue[0];
1685
- }
3972
+ const delay = valueTransition.delay || transition.delay || 0;
1686
3973
  /**
1687
- * If the target isn't keyframes, or the first keyframe was null, we need to
1688
- * first check if an origin value was explicitly defined in the transition as "from",
1689
- * if not read the value from the DOM. As an absolute fallback, take the defined target value.
3974
+ * Elapsed isn't a public transition option but can be passed through from
3975
+ * optimized appear effects in milliseconds.
1690
3976
  */
1691
- if (value === null) {
1692
- value = (_b = (_a = origin[key]) !== null && _a !== void 0 ? _a : visualElement.readValue(key)) !== null && _b !== void 0 ? _b : target[key];
1693
- }
3977
+ let { elapsed = 0 } = transition;
3978
+ elapsed = elapsed - secondsToMilliseconds(delay);
3979
+ const keyframes = getKeyframes(value, valueName, target, valueTransition);
1694
3980
  /**
1695
- * If value is still undefined or null, ignore it. Preferably this would throw,
1696
- * but this was causing issues in Framer.
3981
+ * Check if we're able to animate between the start and end keyframes,
3982
+ * and throw a warning if we're attempting to animate between one that's
3983
+ * animatable and another that isn't.
1697
3984
  */
1698
- if (value === undefined || value === null)
1699
- continue;
1700
- if (typeof value === "string" &&
1701
- (isNumericalString(value) || isZeroValueString(value))) {
1702
- // If this is a number read as a string, ie "0" or "200", convert it to a number
1703
- value = parseFloat(value);
3985
+ const originKeyframe = keyframes[0];
3986
+ const targetKeyframe = keyframes[keyframes.length - 1];
3987
+ const isOriginAnimatable = isAnimatable(valueName, originKeyframe);
3988
+ const isTargetAnimatable = isAnimatable(valueName, targetKeyframe);
3989
+ exports.warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${valueName} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
3990
+ let options = {
3991
+ keyframes,
3992
+ velocity: value.getVelocity(),
3993
+ ...valueTransition,
3994
+ elapsed,
3995
+ onUpdate: (v) => {
3996
+ value.set(v);
3997
+ valueTransition.onUpdate && valueTransition.onUpdate(v);
3998
+ },
3999
+ onComplete: () => {
4000
+ onComplete();
4001
+ valueTransition.onComplete && valueTransition.onComplete();
4002
+ },
4003
+ };
4004
+ if (!isOriginAnimatable ||
4005
+ !isTargetAnimatable ||
4006
+ instantAnimationState.current ||
4007
+ valueTransition.type === false) {
4008
+ /**
4009
+ * If we can't animate this value, or the global instant animation flag is set,
4010
+ * or this is simply defined as an instant transition, return an instant transition.
4011
+ */
4012
+ return createInstantAnimation(options);
1704
4013
  }
1705
- else if (!findValueType(value) && wrap.complex.test(targetValue)) {
1706
- value = wrap.getAnimatableNone(key, targetValue);
4014
+ else if (valueTransition.type === "inertia") {
4015
+ /**
4016
+ * If this is an inertia animation, we currently don't support pre-generating
4017
+ * keyframes for this as such it must always run on the main thread.
4018
+ */
4019
+ return inertia(options);
1707
4020
  }
1708
- visualElement.addValue(key, wrap.motionValue(value, { owner: visualElement }));
1709
- if (origin[key] === undefined) {
1710
- origin[key] = value;
4021
+ /**
4022
+ * If there's no transition defined for this value, we can generate
4023
+ * unqiue transition settings for this value.
4024
+ */
4025
+ if (!isTransitionDefined(valueTransition)) {
4026
+ options = {
4027
+ ...options,
4028
+ ...getDefaultTransition(valueName, options),
4029
+ };
1711
4030
  }
1712
- if (value !== null)
1713
- visualElement.setBaseTarget(key, value);
1714
- }
1715
- }
1716
- function getOriginFromTransition(key, transition) {
1717
- if (!transition)
1718
- return;
1719
- const valueTransition = transition[key] || transition["default"] || transition;
1720
- return valueTransition.from;
1721
- }
1722
- function getOrigin(target, transition, visualElement) {
1723
- const origin = {};
1724
- for (const key in target) {
1725
- const transitionOrigin = getOriginFromTransition(key, transition);
1726
- if (transitionOrigin !== undefined) {
1727
- origin[key] = transitionOrigin;
4031
+ /**
4032
+ * Both WAAPI and our internal animation functions use durations
4033
+ * as defined by milliseconds, while our external API defines them
4034
+ * as seconds.
4035
+ */
4036
+ if (options.duration) {
4037
+ options.duration = secondsToMilliseconds(options.duration);
1728
4038
  }
1729
- else {
1730
- const value = visualElement.getValue(key);
1731
- if (value) {
1732
- origin[key] = value.get();
1733
- }
4039
+ if (options.repeatDelay) {
4040
+ options.repeatDelay = secondsToMilliseconds(options.repeatDelay);
1734
4041
  }
1735
- }
1736
- return origin;
1737
- }
1738
-
1739
- function isWillChangeMotionValue(value) {
1740
- return Boolean(wrap.isMotionValue(value) && value.add);
1741
- }
1742
-
1743
- const optimizedAppearDataId = "framerAppearId";
1744
- const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
4042
+ /**
4043
+ * Animate via WAAPI if possible.
4044
+ */
4045
+ if (value.owner &&
4046
+ value.owner.current instanceof HTMLElement &&
4047
+ !value.owner.getProps().onUpdate) {
4048
+ const acceleratedAnimation = createAcceleratedAnimation(value, valueName, options);
4049
+ if (acceleratedAnimation)
4050
+ return acceleratedAnimation;
4051
+ }
4052
+ /**
4053
+ * If we didn't create an accelerated animation, create a JS animation
4054
+ */
4055
+ return animateValue(options);
4056
+ };
4057
+ };
1745
4058
 
1746
4059
  function animateVisualElement(visualElement, definition, options = {}) {
1747
4060
  visualElement.notify("AnimationStart", definition);
@@ -1828,10 +4141,10 @@ function animateTarget(visualElement, definition, { delay = 0, transitionOverrid
1828
4141
  if (window.HandoffAppearAnimations && !value.hasAnimated) {
1829
4142
  const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
1830
4143
  if (appearId) {
1831
- valueTransition.elapsed = window.HandoffAppearAnimations(appearId, key, value, wrap.sync);
4144
+ valueTransition.elapsed = window.HandoffAppearAnimations(appearId, key, value, sync);
1832
4145
  }
1833
4146
  }
1834
- let animation = value.start(wrap.createMotionValueAnimation(key, value, valueTarget, visualElement.shouldReduceMotion && wrap.transformProps.has(key)
4147
+ let animation = value.start(createMotionValueAnimation(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
1835
4148
  ? { type: false }
1836
4149
  : valueTransition));
1837
4150
  if (isWillChangeMotionValue(willChange)) {
@@ -2259,6 +4572,14 @@ const animations = {
2259
4572
  },
2260
4573
  };
2261
4574
 
4575
+ const distance = (a, b) => Math.abs(a - b);
4576
+ function distance2D(a, b) {
4577
+ // Multi-dimensional
4578
+ const xDelta = distance(a.x, b.x);
4579
+ const yDelta = distance(a.y, b.y);
4580
+ return Math.sqrt(xDelta ** 2 + yDelta ** 2);
4581
+ }
4582
+
2262
4583
  /**
2263
4584
  * @internal
2264
4585
  */
@@ -2288,11 +4609,11 @@ class PanSession {
2288
4609
  // Only start panning if the offset is larger than 3 pixels. If we make it
2289
4610
  // any larger than this we'll want to reset the pointer history
2290
4611
  // on the first update to avoid visual snapping to the cursoe.
2291
- const isDistancePastThreshold = wrap.distance2D(info.offset, { x: 0, y: 0 }) >= 3;
4612
+ const isDistancePastThreshold = distance2D(info.offset, { x: 0, y: 0 }) >= 3;
2292
4613
  if (!isPanStarted && !isDistancePastThreshold)
2293
4614
  return;
2294
4615
  const { point } = info;
2295
- const { timestamp } = wrap.frameData;
4616
+ const { timestamp } = frameData;
2296
4617
  this.history.push({ ...point, timestamp });
2297
4618
  const { onStart, onMove } = this.handlers;
2298
4619
  if (!isPanStarted) {
@@ -2305,7 +4626,7 @@ class PanSession {
2305
4626
  this.lastMoveEvent = event;
2306
4627
  this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint);
2307
4628
  // Throttle mouse move event to once per frame
2308
- wrap.sync.update(this.updatePoint, true);
4629
+ sync.update(this.updatePoint, true);
2309
4630
  };
2310
4631
  this.handlePointerUp = (event, info) => {
2311
4632
  this.end();
@@ -2328,19 +4649,19 @@ class PanSession {
2328
4649
  const info = extractEventInfo(event);
2329
4650
  const initialInfo = transformPoint(info, this.transformPagePoint);
2330
4651
  const { point } = initialInfo;
2331
- const { timestamp } = wrap.frameData;
4652
+ const { timestamp } = frameData;
2332
4653
  this.history = [{ ...point, timestamp }];
2333
4654
  const { onSessionStart } = handlers;
2334
4655
  onSessionStart &&
2335
4656
  onSessionStart(event, getPanInfo(initialInfo, this.history));
2336
- this.removeListeners = wrap.pipe(addPointerEvent(window, "pointermove", this.handlePointerMove), addPointerEvent(window, "pointerup", this.handlePointerUp), addPointerEvent(window, "pointercancel", this.handlePointerUp));
4657
+ this.removeListeners = pipe(addPointerEvent(window, "pointermove", this.handlePointerMove), addPointerEvent(window, "pointerup", this.handlePointerUp), addPointerEvent(window, "pointercancel", this.handlePointerUp));
2337
4658
  }
2338
4659
  updateHandlers(handlers) {
2339
4660
  this.handlers = handlers;
2340
4661
  }
2341
4662
  end() {
2342
4663
  this.removeListeners && this.removeListeners();
2343
- wrap.cancelSync.update(this.updatePoint);
4664
+ cancelSync.update(this.updatePoint);
2344
4665
  }
2345
4666
  }
2346
4667
  function transformPoint(info, transformPagePoint) {
@@ -2373,7 +4694,7 @@ function getVelocity(history, timeDelta) {
2373
4694
  while (i >= 0) {
2374
4695
  timestampedPoint = history[i];
2375
4696
  if (lastPoint.timestamp - timestampedPoint.timestamp >
2376
- wrap.secondsToMilliseconds(timeDelta)) {
4697
+ secondsToMilliseconds(timeDelta)) {
2377
4698
  break;
2378
4699
  }
2379
4700
  i--;
@@ -2406,12 +4727,12 @@ function isNear(value, target = 0, maxDistance = 0.01) {
2406
4727
  }
2407
4728
  function calcAxisDelta(delta, source, target, origin = 0.5) {
2408
4729
  delta.origin = origin;
2409
- delta.originPoint = wrap.mix(source.min, source.max, delta.origin);
4730
+ delta.originPoint = mix(source.min, source.max, delta.origin);
2410
4731
  delta.scale = calcLength(target) / calcLength(source);
2411
4732
  if (isNear(delta.scale, 1, 0.0001) || isNaN(delta.scale))
2412
4733
  delta.scale = 1;
2413
4734
  delta.translate =
2414
- wrap.mix(target.min, target.max, delta.origin) - delta.originPoint;
4735
+ mix(target.min, target.max, delta.origin) - delta.originPoint;
2415
4736
  if (isNear(delta.translate) || isNaN(delta.translate))
2416
4737
  delta.translate = 0;
2417
4738
  }
@@ -2444,11 +4765,11 @@ function calcRelativePosition(target, layout, parent) {
2444
4765
  function applyConstraints(point, { min, max }, elastic) {
2445
4766
  if (min !== undefined && point < min) {
2446
4767
  // If we have a min point defined, and this is outside of that, constrain
2447
- point = elastic ? wrap.mix(min, point, elastic.min) : Math.max(point, min);
4768
+ point = elastic ? mix(min, point, elastic.min) : Math.max(point, min);
2448
4769
  }
2449
4770
  else if (max !== undefined && point > max) {
2450
4771
  // If we have a max point defined, and this is outside of that, constrain
2451
- point = elastic ? wrap.mix(max, point, elastic.max) : Math.min(point, max);
4772
+ point = elastic ? mix(max, point, elastic.max) : Math.min(point, max);
2452
4773
  }
2453
4774
  return point;
2454
4775
  }
@@ -2507,12 +4828,12 @@ function calcOrigin(source, target) {
2507
4828
  const sourceLength = calcLength(source);
2508
4829
  const targetLength = calcLength(target);
2509
4830
  if (targetLength > sourceLength) {
2510
- origin = wrap.progress(target.min, target.max - sourceLength, source.min);
4831
+ origin = progress(target.min, target.max - sourceLength, source.min);
2511
4832
  }
2512
4833
  else if (sourceLength > targetLength) {
2513
- origin = wrap.progress(source.min, source.max - targetLength, target.min);
4834
+ origin = progress(source.min, source.max - targetLength, target.min);
2514
4835
  }
2515
- return wrap.clamp(0, 1, origin);
4836
+ return clamp(0, 1, origin);
2516
4837
  }
2517
4838
  /**
2518
4839
  * Rebase the calculated viewport constraints relative to the layout.min point.
@@ -2731,7 +5052,7 @@ function translateAxis(axis, distance) {
2731
5052
  */
2732
5053
  function transformAxis(axis, transforms, [key, scaleKey, originKey]) {
2733
5054
  const axisOrigin = transforms[originKey] !== undefined ? transforms[originKey] : 0.5;
2734
- const originPoint = wrap.mix(axis.min, axis.max, axisOrigin);
5055
+ const originPoint = mix(axis.min, axis.max, axisOrigin);
2735
5056
  // Apply the axis delta to the final axis
2736
5057
  applyAxisDelta(axis, transforms[key], transforms[scaleKey], originPoint, transforms.scale);
2737
5058
  }
@@ -2827,7 +5148,7 @@ class VisualElementDragControls {
2827
5148
  /**
2828
5149
  * If the MotionValue is a percentage value convert to px
2829
5150
  */
2830
- if (wrap.percent.test(current)) {
5151
+ if (percent.test(current)) {
2831
5152
  const { projection } = this.visualElement;
2832
5153
  if (projection && projection.layout) {
2833
5154
  const measuredAxis = projection.layout.layoutBox[axis];
@@ -2840,7 +5161,9 @@ class VisualElementDragControls {
2840
5161
  this.originPoint[axis] = current;
2841
5162
  });
2842
5163
  // Fire onDragStart event
2843
- onDragStart && onDragStart(event, info);
5164
+ if (onDragStart) {
5165
+ sync.update(() => onDragStart(event, info));
5166
+ }
2844
5167
  const { animationState } = this.visualElement;
2845
5168
  animationState && animationState.setActive("whileDrag", true);
2846
5169
  };
@@ -2892,7 +5215,9 @@ class VisualElementDragControls {
2892
5215
  const { velocity } = info;
2893
5216
  this.startAnimation(velocity);
2894
5217
  const { onDragEnd } = this.getProps();
2895
- onDragEnd && onDragEnd(event, info);
5218
+ if (onDragEnd) {
5219
+ sync.update(() => onDragEnd(event, info));
5220
+ }
2896
5221
  }
2897
5222
  cancel() {
2898
5223
  this.isDragging = false;
@@ -2960,7 +5285,7 @@ class VisualElementDragControls {
2960
5285
  if (!constraints || !isRefObject(constraints))
2961
5286
  return false;
2962
5287
  const constraintsElement = constraints.current;
2963
- wrap.invariant(constraintsElement !== null, "If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.");
5288
+ exports.invariant(constraintsElement !== null, "If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.");
2964
5289
  const { projection } = this.visualElement;
2965
5290
  // TODO
2966
5291
  if (!projection || !projection.layout)
@@ -3019,7 +5344,7 @@ class VisualElementDragControls {
3019
5344
  }
3020
5345
  startAxisValueAnimation(axis, transition) {
3021
5346
  const axisValue = this.getAxisMotionValue(axis);
3022
- return axisValue.start(wrap.createMotionValueAnimation(axis, axisValue, 0, transition));
5347
+ return axisValue.start(createMotionValueAnimation(axis, axisValue, 0, transition));
3023
5348
  }
3024
5349
  stopAnimation() {
3025
5350
  eachAxis((axis) => this.getAxisMotionValue(axis).stop());
@@ -3048,7 +5373,7 @@ class VisualElementDragControls {
3048
5373
  const axisValue = this.getAxisMotionValue(axis);
3049
5374
  if (projection && projection.layout) {
3050
5375
  const { min, max } = projection.layout.layoutBox[axis];
3051
- axisValue.set(point[axis] - wrap.mix(min, max, 0.5));
5376
+ axisValue.set(point[axis] - mix(min, max, 0.5));
3052
5377
  }
3053
5378
  });
3054
5379
  }
@@ -3103,7 +5428,7 @@ class VisualElementDragControls {
3103
5428
  */
3104
5429
  const axisValue = this.getAxisMotionValue(axis);
3105
5430
  const { min, max } = this.constraints[axis];
3106
- axisValue.set(wrap.mix(min, max, boxProgress[axis]));
5431
+ axisValue.set(mix(min, max, boxProgress[axis]));
3107
5432
  });
3108
5433
  }
3109
5434
  addListeners() {
@@ -3198,8 +5523,8 @@ function getCurrentDirection(offset, lockThreshold = 10) {
3198
5523
  class DragGesture extends Feature {
3199
5524
  constructor(node) {
3200
5525
  super(node);
3201
- this.removeGroupControls = wrap.noop;
3202
- this.removeListeners = wrap.noop;
5526
+ this.removeGroupControls = noop;
5527
+ this.removeListeners = noop;
3203
5528
  this.controls = new VisualElementDragControls(node);
3204
5529
  }
3205
5530
  mount() {
@@ -3209,7 +5534,7 @@ class DragGesture extends Feature {
3209
5534
  if (dragControls) {
3210
5535
  this.removeGroupControls = dragControls.subscribe(this.controls);
3211
5536
  }
3212
- this.removeListeners = this.controls.addListeners() || wrap.noop;
5537
+ this.removeListeners = this.controls.addListeners() || noop;
3213
5538
  }
3214
5539
  unmount() {
3215
5540
  this.removeGroupControls();
@@ -3217,10 +5542,15 @@ class DragGesture extends Feature {
3217
5542
  }
3218
5543
  }
3219
5544
 
5545
+ const asyncHandler = (handler) => (event, info) => {
5546
+ if (handler) {
5547
+ sync.update(() => handler(event, info));
5548
+ }
5549
+ };
3220
5550
  class PanGesture extends Feature {
3221
5551
  constructor() {
3222
5552
  super(...arguments);
3223
- this.removePointerDownListener = wrap.noop;
5553
+ this.removePointerDownListener = noop;
3224
5554
  }
3225
5555
  onPointerDown(pointerDownEvent) {
3226
5556
  this.session = new PanSession(pointerDownEvent, this.createPanHandlers(), { transformPagePoint: this.node.getTransformPagePoint() });
@@ -3228,12 +5558,14 @@ class PanGesture extends Feature {
3228
5558
  createPanHandlers() {
3229
5559
  const { onPanSessionStart, onPanStart, onPan, onPanEnd } = this.node.getProps();
3230
5560
  return {
3231
- onSessionStart: onPanSessionStart,
3232
- onStart: onPanStart,
5561
+ onSessionStart: asyncHandler(onPanSessionStart),
5562
+ onStart: asyncHandler(onPanStart),
3233
5563
  onMove: onPan,
3234
5564
  onEnd: (event, info) => {
3235
5565
  delete this.session;
3236
- onPanEnd && onPanEnd(event, info);
5566
+ if (onPanEnd) {
5567
+ sync.update(() => onPanEnd(event, info));
5568
+ }
3237
5569
  },
3238
5570
  };
3239
5571
  }
@@ -3249,19 +5581,55 @@ class PanGesture extends Feature {
3249
5581
  }
3250
5582
  }
3251
5583
 
5584
+ /**
5585
+ * Animate a single value or a `MotionValue`.
5586
+ *
5587
+ * The first argument is either a `MotionValue` to animate, or an initial animation value.
5588
+ *
5589
+ * The second is either a value to animate to, or an array of keyframes to animate through.
5590
+ *
5591
+ * The third argument can be either tween or spring options, and optional lifecycle methods: `onUpdate`, `onPlay`, `onComplete`, `onRepeat` and `onStop`.
5592
+ *
5593
+ * Returns `AnimationPlaybackControls`, currently just a `stop` method.
5594
+ *
5595
+ * ```javascript
5596
+ * const x = useMotionValue(0)
5597
+ *
5598
+ * useEffect(() => {
5599
+ * const controls = animate(x, 100, {
5600
+ * type: "spring",
5601
+ * stiffness: 2000,
5602
+ * onComplete: v => {}
5603
+ * })
5604
+ *
5605
+ * return controls.stop
5606
+ * })
5607
+ * ```
5608
+ *
5609
+ * @public
5610
+ */
5611
+ function animate(from, to, transition = {}) {
5612
+ const value = isMotionValue(from) ? from : motionValue(from);
5613
+ value.start(createMotionValueAnimation("", value, to, transition));
5614
+ return {
5615
+ stop: () => value.stop(),
5616
+ isAnimating: () => value.isAnimating(),
5617
+ };
5618
+ }
5619
+
3252
5620
  const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
3253
5621
  const numBorders = borders.length;
3254
5622
  const asNumber = (value) => typeof value === "string" ? parseFloat(value) : value;
3255
- const isPx = (value) => typeof value === "number" || wrap.px.test(value);
5623
+ const isPx = (value) => typeof value === "number" || px.test(value);
3256
5624
  function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
3257
5625
  if (shouldCrossfadeOpacity) {
3258
- target.opacity = wrap.mix(0,
5626
+ target.opacity = mix(0,
3259
5627
  // TODO Reinstate this if only child
3260
5628
  lead.opacity !== undefined ? lead.opacity : 1, easeCrossfadeIn(progress));
3261
- target.opacityExit = wrap.mix(follow.opacity !== undefined ? follow.opacity : 1, 0, easeCrossfadeOut(progress));
5629
+ target.opacityExit = mix(follow.opacity !== undefined ? follow.opacity : 1, 0, easeCrossfadeOut(progress));
3262
5630
  }
3263
5631
  else if (isOnlyMember) {
3264
- target.opacity = wrap.mix(follow.opacity !== undefined ? follow.opacity : 1, lead.opacity !== undefined ? lead.opacity : 1, progress);
5632
+ target.opacity = mix(follow.opacity !== undefined ? follow.opacity : 1, lead.opacity !== undefined ? lead.opacity : 1, progress);
3265
5633
  }
3266
5634
  /**
3267
5635
  * Mix border radius
@@ -3278,8 +5646,8 @@ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnl
3278
5646
  leadRadius === 0 ||
3279
5647
  isPx(followRadius) === isPx(leadRadius);
3280
5648
  if (canMix) {
3281
- target[borderLabel] = Math.max(wrap.mix(asNumber(followRadius), asNumber(leadRadius), progress), 0);
3282
- if (wrap.percent.test(leadRadius) || wrap.percent.test(followRadius)) {
5649
+ target[borderLabel] = Math.max(mix(asNumber(followRadius), asNumber(leadRadius), progress), 0);
5650
+ if (percent.test(leadRadius) || percent.test(followRadius)) {
3283
5651
  target[borderLabel] += "%";
3284
5652
  }
3285
5653
  }
@@ -3291,7 +5659,7 @@ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnl
3291
5659
  * Mix rotation
3292
5660
  */
3293
5661
  if (follow.rotate || lead.rotate) {
3294
- target.rotate = wrap.mix(follow.rotate || 0, lead.rotate || 0, progress);
5662
+ target.rotate = mix(follow.rotate || 0, lead.rotate || 0, progress);
3295
5663
  }
3296
5664
  }
3297
5665
  function getRadius(values, radiusName) {
@@ -3322,8 +5690,8 @@ function getRadius(values, radiusName) {
3322
5690
  // latestLeadValues.backgroundColor as string
3323
5691
  // )(p)
3324
5692
  // }
3325
- const easeCrossfadeIn = compress(0, 0.5, wrap.circOut);
3326
- const easeCrossfadeOut = compress(0.5, 0.95, wrap.noop);
5693
+ const easeCrossfadeIn = compress(0, 0.5, circOut);
5694
+ const easeCrossfadeOut = compress(0.5, 0.95, noop);
3327
5695
  function compress(min, max, easing) {
3328
5696
  return (p) => {
3329
5697
  // Could replace ifs with clamp
@@ -3331,7 +5699,7 @@ function compress(min, max, easing) {
3331
5699
  return 0;
3332
5700
  if (p > max)
3333
5701
  return 1;
3334
- return easing(wrap.progress(min, max, p));
5702
+ return easing(progress(min, max, p));
3335
5703
  };
3336
5704
  }
3337
5705
 
@@ -3369,14 +5737,14 @@ function removePointDelta(point, translate, scale, originPoint, boxScale) {
3369
5737
  * Remove a delta from an axis. This is essentially the steps of applyAxisDelta in reverse
3370
5738
  */
3371
5739
  function removeAxisDelta(axis, translate = 0, scale = 1, origin = 0.5, boxScale, originAxis = axis, sourceAxis = axis) {
3372
- if (wrap.percent.test(translate)) {
5740
+ if (percent.test(translate)) {
3373
5741
  translate = parseFloat(translate);
3374
- const relativeProgress = wrap.mix(sourceAxis.min, sourceAxis.max, translate / 100);
5742
+ const relativeProgress = mix(sourceAxis.min, sourceAxis.max, translate / 100);
3375
5743
  translate = relativeProgress - sourceAxis.min;
3376
5744
  }
3377
5745
  if (typeof translate !== "number")
3378
5746
  return;
3379
- let originPoint = wrap.mix(originAxis.min, originAxis.max, origin);
5747
+ let originPoint = mix(originAxis.min, originAxis.max, origin);
3380
5748
  if (axis === originAxis)
3381
5749
  originPoint -= translate;
3382
5750
  axis.min = removePointDelta(axis.min, translate, scale, originPoint, boxScale);
@@ -3424,11 +5792,11 @@ class NodeStack {
3424
5792
  this.members = [];
3425
5793
  }
3426
5794
  add(node) {
3427
- wrap.addUniqueItem(this.members, node);
5795
+ addUniqueItem(this.members, node);
3428
5796
  node.scheduleRender();
3429
5797
  }
3430
5798
  remove(node) {
3431
- wrap.removeItem(this.members, node);
5799
+ removeItem(this.members, node);
3432
5800
  if (node === this.prevLead) {
3433
5801
  this.prevLead = undefined;
3434
5802
  }
@@ -3577,11 +5945,11 @@ class FlatTree {
3577
5945
  this.isDirty = false;
3578
5946
  }
3579
5947
  add(child) {
3580
- wrap.addUniqueItem(this.children, child);
5948
+ addUniqueItem(this.children, child);
3581
5949
  this.isDirty = true;
3582
5950
  }
3583
5951
  remove(child) {
3584
- wrap.removeItem(this.children, child);
5952
+ removeItem(this.children, child);
3585
5953
  this.isDirty = true;
3586
5954
  }
3587
5955
  forEach(callback) {
@@ -3753,7 +6121,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3753
6121
  }
3754
6122
  addEventListener(name, handler) {
3755
6123
  if (!this.eventHandlers.has(name)) {
3756
- this.eventHandlers.set(name, new wrap.SubscriptionManager());
6124
+ this.eventHandlers.set(name, new SubscriptionManager());
3757
6125
  }
3758
6126
  return this.eventHandlers.get(name).add(handler);
3759
6127
  }
@@ -3792,7 +6160,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3792
6160
  attachResizeListener(instance, () => {
3793
6161
  this.root.updateBlockedByResize = true;
3794
6162
  cancelDelay && cancelDelay();
3795
- cancelDelay = wrap.delay(resizeUnblockUpdate, 250);
6163
+ cancelDelay = delay(resizeUnblockUpdate, 250);
3796
6164
  if (globalProjectionState.hasAnimatedSinceResize) {
3797
6165
  globalProjectionState.hasAnimatedSinceResize = false;
3798
6166
  this.nodes.forEach(finishAnimation);
@@ -3841,7 +6209,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3841
6209
  }
3842
6210
  this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
3843
6211
  const animationOptions = {
3844
- ...wrap.getValueTransition(layoutTransition, "layout"),
6212
+ ...getValueTransition(layoutTransition, "layout"),
3845
6213
  onPlay: onLayoutAnimationStart,
3846
6214
  onComplete: onLayoutAnimationComplete,
3847
6215
  };
@@ -3877,7 +6245,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3877
6245
  stack && stack.remove(this);
3878
6246
  this.parent && this.parent.children.delete(this);
3879
6247
  this.instance = undefined;
3880
- wrap.cancelSync.preRender(this.updateProjection);
6248
+ cancelSync.preRender(this.updateProjection);
3881
6249
  }
3882
6250
  // only on the root
3883
6251
  blockUpdate() {
@@ -3974,16 +6342,16 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3974
6342
  this.nodes.forEach(notifyLayoutUpdate);
3975
6343
  this.clearAllSnapshots();
3976
6344
  // Flush any scheduled updates
3977
- wrap.flushSync.update();
3978
- wrap.flushSync.preRender();
3979
- wrap.flushSync.render();
6345
+ flushSync.update();
6346
+ flushSync.preRender();
6347
+ flushSync.render();
3980
6348
  }
3981
6349
  clearAllSnapshots() {
3982
6350
  this.nodes.forEach(clearSnapshot);
3983
6351
  this.sharedNodes.forEach(removeLeadSnapshots);
3984
6352
  }
3985
6353
  scheduleUpdateProjection() {
3986
- wrap.sync.preRender(this.updateProjection, false, true);
6354
+ sync.preRender(this.updateProjection, false, true);
3987
6355
  }
3988
6356
  scheduleCheckAfterUnmount() {
3989
6357
  /**
@@ -3991,7 +6359,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
3991
6359
  * we manually call didUpdate to give a chance to the siblings to animate.
3992
6360
  * Otherwise, cleanup all snapshots to prevents future nodes from reusing them.
3993
6361
  */
3994
- wrap.sync.postRender(() => {
6362
+ sync.postRender(() => {
3995
6363
  if (this.isLayoutDirty) {
3996
6364
  this.root.didUpdate();
3997
6365
  }
@@ -4503,7 +6871,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
4503
6871
  this.resumingFrom.currentAnimation.stop();
4504
6872
  }
4505
6873
  if (this.pendingAnimation) {
4506
- wrap.cancelSync.update(this.pendingAnimation);
6874
+ cancelSync.update(this.pendingAnimation);
4507
6875
  this.pendingAnimation = undefined;
4508
6876
  }
4509
6877
  /**
@@ -4511,9 +6879,9 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
4511
6879
  * where the target is the same as when the animation started, so we can
4512
6880
  * calculate the relative positions correctly for instant transitions.
4513
6881
  */
4514
- this.pendingAnimation = wrap.sync.update(() => {
6882
+ this.pendingAnimation = sync.update(() => {
4515
6883
  globalProjectionState.hasAnimatedSinceResize = true;
4516
- this.currentAnimation = wrap.animate(0, animationTarget, {
6884
+ this.currentAnimation = animate(0, animationTarget, {
4517
6885
  ...options,
4518
6886
  onUpdate: (latest) => {
4519
6887
  this.mixTargetDelta(latest);
@@ -4958,14 +7326,14 @@ function removeLeadSnapshots(stack) {
4958
7326
  stack.removeLeadSnapshot();
4959
7327
  }
4960
7328
  function mixAxisDelta(output, delta, p) {
4961
- output.translate = wrap.mix(delta.translate, 0, p);
4962
- output.scale = wrap.mix(delta.scale, 1, p);
7329
+ output.translate = mix(delta.translate, 0, p);
7330
+ output.scale = mix(delta.scale, 1, p);
4963
7331
  output.origin = delta.origin;
4964
7332
  output.originPoint = delta.originPoint;
4965
7333
  }
4966
7334
  function mixAxis(output, from, to, p) {
4967
- output.min = wrap.mix(from.min, to.min, p);
4968
- output.max = wrap.mix(from.max, to.max, p);
7335
+ output.min = mix(from.min, to.min, p);
7336
+ output.max = mix(from.max, to.max, p);
4969
7337
  }
4970
7338
  function mixBox(output, from, to, p) {
4971
7339
  mixAxis(output.x, from.x, to.x, p);
@@ -5085,7 +7453,7 @@ const correctBorderRadius = {
5085
7453
  * going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
5086
7454
  */
5087
7455
  if (typeof latest === "string") {
5088
- if (wrap.px.test(latest)) {
7456
+ if (px.test(latest)) {
5089
7457
  latest = parseFloat(latest);
5090
7458
  }
5091
7459
  else {
@@ -5121,7 +7489,7 @@ function parseCSSVariable(current) {
5121
7489
  }
5122
7490
  const maxDepth = 4;
5123
7491
  function getVariableValue(current, element, depth = 1) {
5124
- wrap.invariant(depth <= maxDepth, `Max CSS variable fallback depth detected in property "${current}". This may indicate a circular fallback dependency.`);
7492
+ exports.invariant(depth <= maxDepth, `Max CSS variable fallback depth detected in property "${current}". This may indicate a circular fallback dependency.`);
5125
7493
  const [token, fallback] = parseCSSVariable(current);
5126
7494
  // No CSS variable detected
5127
7495
  if (!token)
@@ -5198,11 +7566,11 @@ const correctBoxShadow = {
5198
7566
  return varToken;
5199
7567
  });
5200
7568
  }
5201
- const shadow = wrap.complex.parse(latest);
7569
+ const shadow = complex.parse(latest);
5202
7570
  // TODO: Doesn't support multiple shadows
5203
7571
  if (shadow.length > 5)
5204
7572
  return original;
5205
- const template = wrap.complex.createTransformer(latest);
7573
+ const template = complex.createTransformer(latest);
5206
7574
  const offset = typeof shadow[0] !== "number" ? 1 : 0;
5207
7575
  // Calculate the overall context scale
5208
7576
  const xScale = projectionDelta.x.scale * treeScale.x;
@@ -5215,7 +7583,7 @@ const correctBoxShadow = {
5215
7583
  * We could potentially improve the outcome of this by incorporating the ratio between
5216
7584
  * the two scales.
5217
7585
  */
5218
- const averageScale = wrap.mix(xScale, yScale, 0.5);
7586
+ const averageScale = mix(xScale, yScale, 0.5);
5219
7587
  // Blur
5220
7588
  if (typeof shadow[2 + offset] === "number")
5221
7589
  shadow[2 + offset] /= averageScale;
@@ -5249,7 +7617,7 @@ const isPositionalKey = (key) => positionalKeys.has(key);
5249
7617
  const hasPositionalKey = (target) => {
5250
7618
  return Object.keys(target).some(isPositionalKey);
5251
7619
  };
5252
- const isNumOrPxType = (v) => v === wrap.number || v === wrap.px;
7620
+ const isNumOrPxType = (v) => v === number || v === px;
5253
7621
  const getPosFromMatrix = (matrix, pos) => parseFloat(matrix.split(", ")[pos]);
5254
7622
  const getTranslateFromMatrix = (pos2, pos3) => (_bbox, { transform }) => {
5255
7623
  if (transform === "none" || !transform)
@@ -5269,7 +7637,7 @@ const getTranslateFromMatrix = (pos2, pos3) => (_bbox, { transform }) => {
5269
7637
  }
5270
7638
  };
5271
7639
  const transformKeys = new Set(["x", "y", "z"]);
5272
- const nonTranslationalTransformKeys = wrap.transformPropOrder.filter((key) => !transformKeys.has(key));
7640
+ const nonTranslationalTransformKeys = transformPropOrder.filter((key) => !transformKeys.has(key));
5273
7641
  function removeNonTranslationalTransform(visualElement) {
5274
7642
  const removedTransforms = [];
5275
7643
  nonTranslationalTransformKeys.forEach((key) => {
@@ -5354,11 +7722,11 @@ const checkAndConvertChangedValueTypes = (visualElement, target, origin = {}, tr
5354
7722
  for (let i = fromIndex; i < numKeyframes; i++) {
5355
7723
  if (!toType) {
5356
7724
  toType = findDimensionValueType(to[i]);
5357
- wrap.invariant(toType === fromType ||
7725
+ exports.invariant(toType === fromType ||
5358
7726
  (isNumOrPxType(fromType) && isNumOrPxType(toType)), "Keyframes must be of the same dimension as the current value");
5359
7727
  }
5360
7728
  else {
5361
- wrap.invariant(findDimensionValueType(to[i]) === toType, "All keyframes must be of the same type");
7729
+ exports.invariant(findDimensionValueType(to[i]) === toType, "All keyframes must be of the same type");
5362
7730
  }
5363
7731
  }
5364
7732
  }
@@ -5376,7 +7744,7 @@ const checkAndConvertChangedValueTypes = (visualElement, target, origin = {}, tr
5376
7744
  if (typeof to === "string") {
5377
7745
  target[key] = parseFloat(to);
5378
7746
  }
5379
- else if (Array.isArray(to) && toType === wrap.px) {
7747
+ else if (Array.isArray(to) && toType === px) {
5380
7748
  target[key] = to.map(parseFloat);
5381
7749
  }
5382
7750
  }
@@ -5480,7 +7848,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5480
7848
  for (const key in next) {
5481
7849
  const nextValue = next[key];
5482
7850
  const prevValue = prev[key];
5483
- if (wrap.isMotionValue(nextValue)) {
7851
+ if (isMotionValue(nextValue)) {
5484
7852
  /**
5485
7853
  * If this is a motion value found in props or style, we want to add it
5486
7854
  * to our visual element's motion value map.
@@ -5494,15 +7862,15 @@ function updateMotionValuesFromProps(element, next, prev) {
5494
7862
  * and warn against mismatches.
5495
7863
  */
5496
7864
  if (process.env.NODE_ENV === "development") {
5497
- wrap.warnOnce(nextValue.version === "10.1.0-alpha.3", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.1.0-alpha.3 may not work as expected.`);
7865
+ warnOnce(nextValue.version === "10.1.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.1.0 may not work as expected.`);
5498
7866
  }
5499
7867
  }
5500
- else if (wrap.isMotionValue(prevValue)) {
7868
+ else if (isMotionValue(prevValue)) {
5501
7869
  /**
5502
7870
  * If we're swapping from a motion value to a static value,
5503
7871
  * create a new motion value from that
5504
7872
  */
5505
- element.addValue(key, wrap.motionValue(nextValue, { owner: element }));
7873
+ element.addValue(key, motionValue(nextValue, { owner: element }));
5506
7874
  if (isWillChangeMotionValue(willChange)) {
5507
7875
  willChange.remove(key);
5508
7876
  }
@@ -5520,7 +7888,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5520
7888
  }
5521
7889
  else {
5522
7890
  const latestValue = element.getStaticValue(key);
5523
- element.addValue(key, wrap.motionValue(latestValue !== undefined ? latestValue : nextValue, { owner: element }));
7891
+ element.addValue(key, motionValue(latestValue !== undefined ? latestValue : nextValue, { owner: element }));
5524
7892
  }
5525
7893
  }
5526
7894
  }
@@ -5610,7 +7978,7 @@ class VisualElement {
5610
7978
  this.triggerBuild();
5611
7979
  this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
5612
7980
  };
5613
- this.scheduleRender = () => wrap.sync.render(this.render, false, true);
7981
+ this.scheduleRender = () => sync.render(this.render, false, true);
5614
7982
  const { latestValues, renderState } = visualState;
5615
7983
  this.latestValues = latestValues;
5616
7984
  this.baseTarget = { ...latestValues };
@@ -5641,7 +8009,7 @@ class VisualElement {
5641
8009
  const { willChange, ...initialMotionValues } = this.scrapeMotionValuesFromProps(props, {});
5642
8010
  for (const key in initialMotionValues) {
5643
8011
  const value = initialMotionValues[key];
5644
- if (latestValues[key] !== undefined && wrap.isMotionValue(value)) {
8012
+ if (latestValues[key] !== undefined && isMotionValue(value)) {
5645
8013
  value.set(latestValues[key], false);
5646
8014
  if (isWillChangeMotionValue(willChange)) {
5647
8015
  willChange.add(key);
@@ -5678,7 +8046,7 @@ class VisualElement {
5678
8046
  ? true
5679
8047
  : prefersReducedMotion.current;
5680
8048
  if (process.env.NODE_ENV !== "production") {
5681
- wrap.warnOnce(this.shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
8049
+ warnOnce(this.shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
5682
8050
  }
5683
8051
  if (this.parent)
5684
8052
  this.parent.children.add(this);
@@ -5686,8 +8054,8 @@ class VisualElement {
5686
8054
  }
5687
8055
  unmount() {
5688
8056
  this.projection && this.projection.unmount();
5689
- wrap.cancelSync.update(this.notifyUpdate);
5690
- wrap.cancelSync.render(this.render);
8057
+ cancelSync.update(this.notifyUpdate);
8058
+ cancelSync.render(this.render);
5691
8059
  this.valueSubscriptions.forEach((remove) => remove());
5692
8060
  this.removeFromVariantTree && this.removeFromVariantTree();
5693
8061
  this.parent && this.parent.children.delete(this);
@@ -5700,11 +8068,11 @@ class VisualElement {
5700
8068
  this.current = null;
5701
8069
  }
5702
8070
  bindToMotionValue(key, value) {
5703
- const valueIsTransform = wrap.transformProps.has(key);
8071
+ const valueIsTransform = transformProps.has(key);
5704
8072
  const removeOnChange = value.on("change", (latestValue) => {
5705
8073
  this.latestValues[key] = latestValue;
5706
8074
  this.props.onUpdate &&
5707
- wrap.sync.update(this.notifyUpdate, false, true);
8075
+ sync.update(this.notifyUpdate, false, true);
5708
8076
  if (valueIsTransform && this.projection) {
5709
8077
  this.projection.isTransformDirty = true;
5710
8078
  }
@@ -5738,8 +8106,8 @@ class VisualElement {
5738
8106
  isStrict) {
5739
8107
  const strictMessage = "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.";
5740
8108
  renderedProps.ignoreStrict
5741
- ? wrap.warning(false, strictMessage)
5742
- : wrap.invariant(false, strictMessage);
8109
+ ? exports.warning(false, strictMessage)
8110
+ : exports.invariant(false, strictMessage);
5743
8111
  }
5744
8112
  for (let i = 0; i < numFeatures; i++) {
5745
8113
  const name = featureNames[i];
@@ -5948,7 +8316,7 @@ class VisualElement {
5948
8316
  }
5949
8317
  let value = this.values.get(key);
5950
8318
  if (value === undefined && defaultValue !== undefined) {
5951
- value = wrap.motionValue(defaultValue, { owner: this });
8319
+ value = motionValue(defaultValue, { owner: this });
5952
8320
  this.addValue(key, value);
5953
8321
  }
5954
8322
  return value;
@@ -5991,7 +8359,7 @@ class VisualElement {
5991
8359
  * so we can read the value from an alternative source, try that.
5992
8360
  */
5993
8361
  const target = this.getBaseTargetFromProps(this.props, key);
5994
- if (target !== undefined && !wrap.isMotionValue(target))
8362
+ if (target !== undefined && !isMotionValue(target))
5995
8363
  return target;
5996
8364
  /**
5997
8365
  * If the value was initially defined on initial, but it doesn't any more,
@@ -6004,7 +8372,7 @@ class VisualElement {
6004
8372
  }
6005
8373
  on(eventName, callback) {
6006
8374
  if (!this.events[eventName]) {
6007
- this.events[eventName] = new wrap.SubscriptionManager();
8375
+ this.events[eventName] = new SubscriptionManager();
6008
8376
  }
6009
8377
  return this.events[eventName].add(callback);
6010
8378
  }
@@ -6063,8 +8431,8 @@ function getComputedStyle$1(element) {
6063
8431
  }
6064
8432
  class HTMLVisualElement extends DOMVisualElement {
6065
8433
  readValueFromInstance(instance, key) {
6066
- if (wrap.transformProps.has(key)) {
6067
- const defaultType = wrap.getDefaultValueType(key);
8434
+ if (transformProps.has(key)) {
8435
+ const defaultType = getDefaultValueType(key);
6068
8436
  return defaultType ? defaultType.default || 0 : 0;
6069
8437
  }
6070
8438
  else {
@@ -6090,7 +8458,7 @@ class HTMLVisualElement extends DOMVisualElement {
6090
8458
  delete this.childSubscription;
6091
8459
  }
6092
8460
  const { children } = this.props;
6093
- if (wrap.isMotionValue(children)) {
8461
+ if (isMotionValue(children)) {
6094
8462
  this.childSubscription = children.on("change", (latest) => {
6095
8463
  if (this.current)
6096
8464
  this.current.textContent = `${latest}`;
@@ -6222,7 +8590,7 @@ class MeasureLayoutWithContext extends React__default["default"].Component {
6222
8590
  * it's in charge of the exit animation and therefore should
6223
8591
  * be in charge of the safe to remove. Otherwise we call it here.
6224
8592
  */
6225
- wrap.sync.postRender(() => {
8593
+ sync.postRender(() => {
6226
8594
  const stack = projection.getStack();
6227
8595
  if (!stack || !stack.members.length) {
6228
8596
  this.safeToRemove();
@@ -6302,8 +8670,8 @@ class SVGVisualElement extends DOMVisualElement {
6302
8670
  return props[key];
6303
8671
  }
6304
8672
  readValueFromInstance(instance, key) {
6305
- if (wrap.transformProps.has(key)) {
6306
- const defaultType = wrap.getDefaultValueType(key);
8673
+ if (transformProps.has(key)) {
8674
+ const defaultType = getDefaultValueType(key);
6307
8675
  return defaultType ? defaultType.default || 0 : 0;
6308
8676
  }
6309
8677
  key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
@@ -6398,7 +8766,7 @@ function useForceUpdate() {
6398
8766
  * Defer this to the end of the next animation frame in case there are multiple
6399
8767
  * synchronous calls.
6400
8768
  */
6401
- const deferredForceRender = React.useCallback(() => wrap.sync.postRender(forceRender), [forceRender]);
8769
+ const deferredForceRender = React.useCallback(() => sync.postRender(forceRender), [forceRender]);
6402
8770
  return [deferredForceRender, forcedRenderCount];
6403
8771
  }
6404
8772
 
@@ -6572,7 +8940,7 @@ function onlyElements(children) {
6572
8940
  * @public
6573
8941
  */
6574
8942
  const AnimatePresence = ({ children, custom, initial = true, onExitComplete, exitBeforeEnter, presenceAffectsLayout = true, mode = "sync", }) => {
6575
- wrap.invariant(!exitBeforeEnter, "Replace exitBeforeEnter with mode='wait'");
8943
+ exports.invariant(!exitBeforeEnter, "Replace exitBeforeEnter with mode='wait'");
6576
8944
  // We want to force a re-render once all exiting animations have finished. We
6577
8945
  // either use a local forceRender function, or one from a parent context if it exists.
6578
8946
  let [forceRender] = useForceUpdate();
@@ -6800,10 +9168,10 @@ function checkReorder(order, value, offset, velocity) {
6800
9168
  return order;
6801
9169
  const item = order[index];
6802
9170
  const nextLayout = nextItem.layout;
6803
- const nextItemCenter = wrap.mix(nextLayout.min, nextLayout.max, 0.5);
9171
+ const nextItemCenter = mix(nextLayout.min, nextLayout.max, 0.5);
6804
9172
  if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
6805
9173
  (nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
6806
- return wrap.moveItem(order, index, index + nextOffset);
9174
+ return moveItem(order, index, index + nextOffset);
6807
9175
  }
6808
9176
  return order;
6809
9177
  }
@@ -6812,7 +9180,7 @@ function ReorderGroup({ children, as = "ul", axis = "y", onReorder, values, ...p
6812
9180
  const Component = useConstant(() => motion(as));
6813
9181
  const order = [];
6814
9182
  const isReordering = React.useRef(false);
6815
- wrap.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
9183
+ exports.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
6816
9184
  const context = {
6817
9185
  axis,
6818
9186
  registerItem: (value, layout) => {
@@ -6869,7 +9237,7 @@ function compareMin(a, b) {
6869
9237
  * @public
6870
9238
  */
6871
9239
  function useMotionValue(initial) {
6872
- const value = useConstant(() => wrap.motionValue(initial));
9240
+ const value = useConstant(() => motionValue(initial));
6873
9241
  /**
6874
9242
  * If this motion value is being used in static mode, like on
6875
9243
  * the Framer canvas, force components to rerender when the motion
@@ -6883,6 +9251,24 @@ function useMotionValue(initial) {
6883
9251
  return value;
6884
9252
  }
6885
9253
 
9254
+ const isCustomValueType = (v) => {
9255
+ return typeof v === "object" && v.mix;
9256
+ };
9257
+ const getMixer = (v) => (isCustomValueType(v) ? v.mix : undefined);
9258
+ function transform(...args) {
9259
+ const useImmediate = !Array.isArray(args[0]);
9260
+ const argOffset = useImmediate ? 0 : -1;
9261
+ const inputValue = args[0 + argOffset];
9262
+ const inputRange = args[1 + argOffset];
9263
+ const outputRange = args[2 + argOffset];
9264
+ const options = args[3 + argOffset];
9265
+ const interpolator = interpolate(inputRange, outputRange, {
9266
+ mixer: getMixer(outputRange[0]),
9267
+ ...options,
9268
+ });
9269
+ return useImmediate ? interpolator(inputValue) : interpolator;
9270
+ }
9271
+
6886
9272
  function useCombineMotionValues(values, combineValues) {
6887
9273
  /**
6888
9274
  * Initialise the returned motion value. This remains the same between renders.
@@ -6905,11 +9291,11 @@ function useCombineMotionValues(values, combineValues) {
6905
9291
  * schedule an update.
6906
9292
  */
6907
9293
  useIsomorphicLayoutEffect(() => {
6908
- const scheduleUpdate = () => wrap.sync.update(updateValue, false, true);
9294
+ const scheduleUpdate = () => sync.update(updateValue, false, true);
6909
9295
  const subscriptions = values.map((v) => v.on("change", scheduleUpdate));
6910
9296
  return () => {
6911
9297
  subscriptions.forEach((unsubscribe) => unsubscribe());
6912
- wrap.cancelSync.update(updateValue);
9298
+ cancelSync.update(updateValue);
6913
9299
  };
6914
9300
  });
6915
9301
  return value;
@@ -6918,7 +9304,7 @@ function useCombineMotionValues(values, combineValues) {
6918
9304
  function useTransform(input, inputRangeOrTransformer, outputRange, options) {
6919
9305
  const transformer = typeof inputRangeOrTransformer === "function"
6920
9306
  ? inputRangeOrTransformer
6921
- : wrap.transform(inputRangeOrTransformer, outputRange, options);
9307
+ : transform(inputRangeOrTransformer, outputRange, options);
6922
9308
  return Array.isArray(input)
6923
9309
  ? useListTransform(input, transformer)
6924
9310
  : useListTransform([input], ([latest]) => transformer(latest));
@@ -6936,7 +9322,7 @@ function useListTransform(values, transformer) {
6936
9322
  }
6937
9323
 
6938
9324
  function useDefaultMotionValue(value, defaultValue = 0) {
6939
- return wrap.isMotionValue(value) ? value : useMotionValue(defaultValue);
9325
+ return isMotionValue(value) ? value : useMotionValue(defaultValue);
6940
9326
  }
6941
9327
  function ReorderItem({ children, style = {}, value, as = "li", onDrag, layout = true, ...props }, externalRef) {
6942
9328
  const Component = useConstant(() => motion(as));
@@ -6947,7 +9333,7 @@ function ReorderItem({ children, style = {}, value, as = "li", onDrag, layout =
6947
9333
  };
6948
9334
  const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) => latestX || latestY ? 1 : "unset");
6949
9335
  const measuredLayout = React.useRef(null);
6950
- wrap.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
9336
+ exports.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
6951
9337
  const { axis, registerItem, updateOrder } = context;
6952
9338
  React.useEffect(() => {
6953
9339
  registerItem(value, measuredLayout.current);
@@ -7019,12 +9405,12 @@ function useMotionTemplate(fragments, ...values) {
7019
9405
  output += fragments[i];
7020
9406
  const value = values[i];
7021
9407
  if (value) {
7022
- output += wrap.isMotionValue(value) ? value.get() : value;
9408
+ output += isMotionValue(value) ? value.get() : value;
7023
9409
  }
7024
9410
  }
7025
9411
  return output;
7026
9412
  }
7027
- return useCombineMotionValues(values.filter(wrap.isMotionValue), buildValue);
9413
+ return useCombineMotionValues(values.filter(isMotionValue), buildValue);
7028
9414
  }
7029
9415
 
7030
9416
  /**
@@ -7049,7 +9435,7 @@ function useMotionTemplate(fragments, ...values) {
7049
9435
  function useSpring(source, config = {}) {
7050
9436
  const { isStatic } = React.useContext(MotionConfigContext);
7051
9437
  const activeSpringAnimation = React.useRef(null);
7052
- const value = useMotionValue(wrap.isMotionValue(source) ? source.get() : source);
9438
+ const value = useMotionValue(isMotionValue(source) ? source.get() : source);
7053
9439
  const stopAnimation = () => {
7054
9440
  if (activeSpringAnimation.current) {
7055
9441
  activeSpringAnimation.current.stop();
@@ -7064,7 +9450,7 @@ function useSpring(source, config = {}) {
7064
9450
  if (isStatic)
7065
9451
  return set(v);
7066
9452
  stopAnimation();
7067
- activeSpringAnimation.current = wrap.animateValue({
9453
+ activeSpringAnimation.current = animateValue({
7068
9454
  keyframes: [value.get(), v],
7069
9455
  velocity: value.getVelocity(),
7070
9456
  type: "spring",
@@ -7075,7 +9461,7 @@ function useSpring(source, config = {}) {
7075
9461
  }, stopAnimation);
7076
9462
  }, [JSON.stringify(config)]);
7077
9463
  useIsomorphicLayoutEffect(() => {
7078
- if (wrap.isMotionValue(source)) {
9464
+ if (isMotionValue(source)) {
7079
9465
  return source.on("change", (v) => value.set(parseFloat(v)));
7080
9466
  }
7081
9467
  }, [value]);
@@ -7103,14 +9489,449 @@ function useVelocity(value) {
7103
9489
  return velocity;
7104
9490
  }
7105
9491
 
9492
+ function resolveElements(elements, selectorCache) {
9493
+ var _a;
9494
+ if (typeof elements === "string") {
9495
+ if (selectorCache) {
9496
+ (_a = selectorCache[elements]) !== null && _a !== void 0 ? _a : (selectorCache[elements] = document.querySelectorAll(elements));
9497
+ elements = selectorCache[elements];
9498
+ }
9499
+ else {
9500
+ elements = document.querySelectorAll(elements);
9501
+ }
9502
+ }
9503
+ else if (elements instanceof Element) {
9504
+ elements = [elements];
9505
+ }
9506
+ /**
9507
+ * Return an empty array
9508
+ */
9509
+ return Array.from(elements || []);
9510
+ }
9511
+
9512
+ const resizeHandlers = new WeakMap();
9513
+ let observer;
9514
+ function getElementSize(target, borderBoxSize) {
9515
+ if (borderBoxSize) {
9516
+ const { inlineSize, blockSize } = borderBoxSize[0];
9517
+ return { width: inlineSize, height: blockSize };
9518
+ }
9519
+ else if (target instanceof SVGElement && "getBBox" in target) {
9520
+ return target.getBBox();
9521
+ }
9522
+ else {
9523
+ return {
9524
+ width: target.offsetWidth,
9525
+ height: target.offsetHeight,
9526
+ };
9527
+ }
9528
+ }
9529
+ function notifyTarget({ target, contentRect, borderBoxSize, }) {
9530
+ var _a;
9531
+ (_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
9532
+ handler({
9533
+ target,
9534
+ contentSize: contentRect,
9535
+ get size() {
9536
+ return getElementSize(target, borderBoxSize);
9537
+ },
9538
+ });
9539
+ });
9540
+ }
9541
+ function notifyAll(entries) {
9542
+ entries.forEach(notifyTarget);
9543
+ }
9544
+ function createResizeObserver() {
9545
+ if (typeof ResizeObserver === "undefined")
9546
+ return;
9547
+ observer = new ResizeObserver(notifyAll);
9548
+ }
9549
+ function resizeElement(target, handler) {
9550
+ if (!observer)
9551
+ createResizeObserver();
9552
+ const elements = resolveElements(target);
9553
+ elements.forEach((element) => {
9554
+ let elementHandlers = resizeHandlers.get(element);
9555
+ if (!elementHandlers) {
9556
+ elementHandlers = new Set();
9557
+ resizeHandlers.set(element, elementHandlers);
9558
+ }
9559
+ elementHandlers.add(handler);
9560
+ observer === null || observer === void 0 ? void 0 : observer.observe(element);
9561
+ });
9562
+ return () => {
9563
+ elements.forEach((element) => {
9564
+ const elementHandlers = resizeHandlers.get(element);
9565
+ elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
9566
+ if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
9567
+ observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
9568
+ }
9569
+ });
9570
+ };
9571
+ }
9572
+
9573
+ const windowCallbacks = new Set();
9574
+ let windowResizeHandler;
9575
+ function createWindowResizeHandler() {
9576
+ windowResizeHandler = () => {
9577
+ const size = {
9578
+ width: window.innerWidth,
9579
+ height: window.innerHeight,
9580
+ };
9581
+ const info = {
9582
+ target: window,
9583
+ size,
9584
+ contentSize: size,
9585
+ };
9586
+ windowCallbacks.forEach((callback) => callback(info));
9587
+ };
9588
+ window.addEventListener("resize", windowResizeHandler);
9589
+ }
9590
+ function resizeWindow(callback) {
9591
+ windowCallbacks.add(callback);
9592
+ if (!windowResizeHandler)
9593
+ createWindowResizeHandler();
9594
+ return () => {
9595
+ windowCallbacks.delete(callback);
9596
+ if (!windowCallbacks.size && windowResizeHandler) {
9597
+ windowResizeHandler = undefined;
9598
+ }
9599
+ };
9600
+ }
9601
+
9602
+ function resize(a, b) {
9603
+ return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
9604
+ }
9605
+
9606
+ /**
9607
+ * A time in milliseconds, beyond which we consider the scroll velocity to be 0.
9608
+ */
9609
+ const maxElapsed = 50;
9610
+ const createAxisInfo = () => ({
9611
+ current: 0,
9612
+ offset: [],
9613
+ progress: 0,
9614
+ scrollLength: 0,
9615
+ targetOffset: 0,
9616
+ targetLength: 0,
9617
+ containerLength: 0,
9618
+ velocity: 0,
9619
+ });
9620
+ const createScrollInfo = () => ({
9621
+ time: 0,
9622
+ x: createAxisInfo(),
9623
+ y: createAxisInfo(),
9624
+ });
9625
+ const keys = {
9626
+ x: {
9627
+ length: "Width",
9628
+ position: "Left",
9629
+ },
9630
+ y: {
9631
+ length: "Height",
9632
+ position: "Top",
9633
+ },
9634
+ };
9635
+ function updateAxisInfo(element, axisName, info, time) {
9636
+ const axis = info[axisName];
9637
+ const { length, position } = keys[axisName];
9638
+ const prev = axis.current;
9639
+ const prevTime = info.time;
9640
+ axis.current = element["scroll" + position];
9641
+ axis.scrollLength = element["scroll" + length] - element["client" + length];
9642
+ axis.offset.length = 0;
9643
+ axis.offset[0] = 0;
9644
+ axis.offset[1] = axis.scrollLength;
9645
+ axis.progress = progress(0, axis.scrollLength, axis.current);
9646
+ const elapsed = time - prevTime;
9647
+ axis.velocity =
9648
+ elapsed > maxElapsed
9649
+ ? 0
9650
+ : velocityPerSecond(axis.current - prev, elapsed);
9651
+ }
9652
+ function updateScrollInfo(element, info, time) {
9653
+ updateAxisInfo(element, "x", info, time);
9654
+ updateAxisInfo(element, "y", info, time);
9655
+ info.time = time;
9656
+ }
9657
+
9658
+ function calcInset(element, container) {
9659
+ let inset = { x: 0, y: 0 };
9660
+ let current = element;
9661
+ while (current && current !== container) {
9662
+ if (current instanceof HTMLElement) {
9663
+ inset.x += current.offsetLeft;
9664
+ inset.y += current.offsetTop;
9665
+ current = current.offsetParent;
9666
+ }
9667
+ else if (current instanceof SVGGraphicsElement && "getBBox" in current) {
9668
+ const { top, left } = current.getBBox();
9669
+ inset.x += left;
9670
+ inset.y += top;
9671
+ /**
9672
+ * Assign the next parent element as the <svg /> tag.
9673
+ */
9674
+ while (current && current.tagName !== "svg") {
9675
+ current = current.parentNode;
9676
+ }
9677
+ }
9678
+ }
9679
+ return inset;
9680
+ }
9681
+
9682
+ const ScrollOffset = {
9683
+ Enter: [
9684
+ [0, 1],
9685
+ [1, 1],
9686
+ ],
9687
+ Exit: [
9688
+ [0, 0],
9689
+ [1, 0],
9690
+ ],
9691
+ Any: [
9692
+ [1, 0],
9693
+ [0, 1],
9694
+ ],
9695
+ All: [
9696
+ [0, 0],
9697
+ [1, 1],
9698
+ ],
9699
+ };
9700
+
9701
+ const namedEdges = {
9702
+ start: 0,
9703
+ center: 0.5,
9704
+ end: 1,
9705
+ };
9706
+ function resolveEdge(edge, length, inset = 0) {
9707
+ let delta = 0;
9708
+ /**
9709
+ * If we have this edge defined as a preset, replace the definition
9710
+ * with the numerical value.
9711
+ */
9712
+ if (namedEdges[edge] !== undefined) {
9713
+ edge = namedEdges[edge];
9714
+ }
9715
+ /**
9716
+ * Handle unit values
9717
+ */
9718
+ if (typeof edge === "string") {
9719
+ const asNumber = parseFloat(edge);
9720
+ if (edge.endsWith("px")) {
9721
+ delta = asNumber;
9722
+ }
9723
+ else if (edge.endsWith("%")) {
9724
+ edge = asNumber / 100;
9725
+ }
9726
+ else if (edge.endsWith("vw")) {
9727
+ delta = (asNumber / 100) * document.documentElement.clientWidth;
9728
+ }
9729
+ else if (edge.endsWith("vh")) {
9730
+ delta = (asNumber / 100) * document.documentElement.clientHeight;
9731
+ }
9732
+ else {
9733
+ edge = asNumber;
9734
+ }
9735
+ }
9736
+ /**
9737
+ * If the edge is defined as a number, handle as a progress value.
9738
+ */
9739
+ if (typeof edge === "number") {
9740
+ delta = length * edge;
9741
+ }
9742
+ return inset + delta;
9743
+ }
9744
+
9745
+ const defaultOffset = [0, 0];
9746
+ function resolveOffset(offset, containerLength, targetLength, targetInset) {
9747
+ let offsetDefinition = Array.isArray(offset) ? offset : defaultOffset;
9748
+ let targetPoint = 0;
9749
+ let containerPoint = 0;
9750
+ if (typeof offset === "number") {
9751
+ /**
9752
+ * If we're provided offset: [0, 0.5, 1] then each number x should become
9753
+ * [x, x], so we default to the behaviour of mapping 0 => 0 of both target
9754
+ * and container etc.
9755
+ */
9756
+ offsetDefinition = [offset, offset];
9757
+ }
9758
+ else if (typeof offset === "string") {
9759
+ offset = offset.trim();
9760
+ if (offset.includes(" ")) {
9761
+ offsetDefinition = offset.split(" ");
9762
+ }
9763
+ else {
9764
+ /**
9765
+ * If we're provided a definition like "100px" then we want to apply
9766
+ * that only to the top of the target point, leaving the container at 0.
9767
+ * Whereas a named offset like "end" should be applied to both.
9768
+ */
9769
+ offsetDefinition = [offset, namedEdges[offset] ? offset : `0`];
9770
+ }
9771
+ }
9772
+ targetPoint = resolveEdge(offsetDefinition[0], targetLength, targetInset);
9773
+ containerPoint = resolveEdge(offsetDefinition[1], containerLength);
9774
+ return targetPoint - containerPoint;
9775
+ }
9776
+
9777
+ const point = { x: 0, y: 0 };
9778
+ function resolveOffsets(container, info, options) {
9779
+ let { offset: offsetDefinition = ScrollOffset.All } = options;
9780
+ const { target = container, axis = "y" } = options;
9781
+ const lengthLabel = axis === "y" ? "height" : "width";
9782
+ const inset = target !== container ? calcInset(target, container) : point;
9783
+ /**
9784
+ * Measure the target and container. If they're the same thing then we
9785
+ * use the container's scrollWidth/Height as the target, from there
9786
+ * all other calculations can remain the same.
9787
+ */
9788
+ const targetSize = target === container
9789
+ ? { width: container.scrollWidth, height: container.scrollHeight }
9790
+ : { width: target.clientWidth, height: target.clientHeight };
9791
+ const containerSize = {
9792
+ width: container.clientWidth,
9793
+ height: container.clientHeight,
9794
+ };
9795
+ /**
9796
+ * Reset the length of the resolved offset array rather than creating a new one.
9797
+ * TODO: More reusable data structures for targetSize/containerSize would also be good.
9798
+ */
9799
+ info[axis].offset.length = 0;
9800
+ /**
9801
+ * Populate the offset array by resolving the user's offset definition into
9802
+ * a list of pixel scroll offets.
9803
+ */
9804
+ let hasChanged = !info[axis].interpolate;
9805
+ const numOffsets = offsetDefinition.length;
9806
+ for (let i = 0; i < numOffsets; i++) {
9807
+ const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
9808
+ if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
9809
+ hasChanged = true;
9810
+ }
9811
+ info[axis].offset[i] = offset;
9812
+ }
9813
+ /**
9814
+ * If the pixel scroll offsets have changed, create a new interpolator function
9815
+ * to map scroll value into a progress.
9816
+ */
9817
+ if (hasChanged) {
9818
+ info[axis].interpolate = interpolate(info[axis].offset, defaultOffset$1(offsetDefinition));
9819
+ info[axis].interpolatorOffsets = [...info[axis].offset];
9820
+ }
9821
+ info[axis].progress = info[axis].interpolate(info[axis].current);
9822
+ }
9823
+
9824
+ function measure(container, target = container, info) {
9825
+ /**
9826
+ * Find inset of target within scrollable container
9827
+ */
9828
+ info.x.targetOffset = 0;
9829
+ info.y.targetOffset = 0;
9830
+ if (target !== container) {
9831
+ let node = target;
9832
+ while (node && node !== container) {
9833
+ info.x.targetOffset += node.offsetLeft;
9834
+ info.y.targetOffset += node.offsetTop;
9835
+ node = node.offsetParent;
9836
+ }
9837
+ }
9838
+ info.x.targetLength =
9839
+ target === container ? target.scrollWidth : target.clientWidth;
9840
+ info.y.targetLength =
9841
+ target === container ? target.scrollHeight : target.clientHeight;
9842
+ info.x.containerLength = container.clientWidth;
9843
+ info.y.containerLength = container.clientHeight;
9844
+ }
9845
+ function createOnScrollHandler(element, onScroll, info, options = {}) {
9846
+ return {
9847
+ measure: () => measure(element, options.target, info),
9848
+ update: (time) => {
9849
+ updateScrollInfo(element, info, time);
9850
+ if (options.offset || options.target) {
9851
+ resolveOffsets(element, info, options);
9852
+ }
9853
+ },
9854
+ notify: () => onScroll(info),
9855
+ };
9856
+ }
9857
+
9858
+ const scrollListeners = new WeakMap();
9859
+ const resizeListeners = new WeakMap();
9860
+ const onScrollHandlers = new WeakMap();
9861
+ const getEventTarget = (element) => element === document.documentElement ? window : element;
9862
+ function scroll(onScroll, { container = document.documentElement, ...options } = {}) {
9863
+ let containerHandlers = onScrollHandlers.get(container);
9864
+ /**
9865
+ * Get the onScroll handlers for this container.
9866
+ * If one isn't found, create a new one.
9867
+ */
9868
+ if (!containerHandlers) {
9869
+ containerHandlers = new Set();
9870
+ onScrollHandlers.set(container, containerHandlers);
9871
+ }
9872
+ /**
9873
+ * Create a new onScroll handler for the provided callback.
9874
+ */
9875
+ const info = createScrollInfo();
9876
+ const containerHandler = createOnScrollHandler(container, onScroll, info, options);
9877
+ containerHandlers.add(containerHandler);
9878
+ /**
9879
+ * Check if there's a scroll event listener for this container.
9880
+ * If not, create one.
9881
+ */
9882
+ if (!scrollListeners.has(container)) {
9883
+ const listener = () => {
9884
+ const time = performance.now();
9885
+ for (const handler of containerHandlers)
9886
+ handler.measure();
9887
+ for (const handler of containerHandlers)
9888
+ handler.update(time);
9889
+ for (const handler of containerHandlers)
9890
+ handler.notify();
9891
+ };
9892
+ scrollListeners.set(container, listener);
9893
+ const target = getEventTarget(container);
9894
+ window.addEventListener("resize", listener, { passive: true });
9895
+ if (container !== document.documentElement) {
9896
+ resizeListeners.set(container, resize(container, listener));
9897
+ }
9898
+ target.addEventListener("scroll", listener, { passive: true });
9899
+ }
9900
+ const listener = scrollListeners.get(container);
9901
+ const onLoadProcesss = requestAnimationFrame(listener);
9902
+ return () => {
9903
+ var _a;
9904
+ cancelAnimationFrame(onLoadProcesss);
9905
+ /**
9906
+ * Check if we even have any handlers for this container.
9907
+ */
9908
+ const currentHandlers = onScrollHandlers.get(container);
9909
+ if (!currentHandlers)
9910
+ return;
9911
+ currentHandlers.delete(containerHandler);
9912
+ if (currentHandlers.size)
9913
+ return;
9914
+ /**
9915
+ * If no more handlers, remove the scroll listener too.
9916
+ */
9917
+ const scrollListener = scrollListeners.get(container);
9918
+ scrollListeners.delete(container);
9919
+ if (scrollListener) {
9920
+ getEventTarget(container).removeEventListener("scroll", scrollListener);
9921
+ (_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
9922
+ window.removeEventListener("resize", scrollListener);
9923
+ }
9924
+ };
9925
+ }
9926
+
7106
9927
  function refWarning(name, ref) {
7107
- wrap.warning(Boolean(!ref || ref.current), `You have defined a ${name} options but the provided ref is not yet hydrated, probably because it's defined higher up the tree. Try calling useScroll() in the same component as the ref, or setting its \`layoutEffect: false\` option.`);
9928
+ exports.warning(Boolean(!ref || ref.current), `You have defined a ${name} options but the provided ref is not yet hydrated, probably because it's defined higher up the tree. Try calling useScroll() in the same component as the ref, or setting its \`layoutEffect: false\` option.`);
7108
9929
  }
7109
9930
  const createScrollMotionValues = () => ({
7110
- scrollX: wrap.motionValue(0),
7111
- scrollY: wrap.motionValue(0),
7112
- scrollXProgress: wrap.motionValue(0),
7113
- scrollYProgress: wrap.motionValue(0),
9931
+ scrollX: motionValue(0),
9932
+ scrollY: motionValue(0),
9933
+ scrollXProgress: motionValue(0),
9934
+ scrollYProgress: motionValue(0),
7114
9935
  });
7115
9936
  function useScroll({ container, target, layoutEffect = true, ...options } = {}) {
7116
9937
  const values = useConstant(createScrollMotionValues);
@@ -7120,7 +9941,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
7120
9941
  useLifecycleEffect(() => {
7121
9942
  refWarning("target", target);
7122
9943
  refWarning("container", container);
7123
- return wrap.scroll(({ x, y }) => {
9944
+ return scroll(({ x, y }) => {
7124
9945
  values.scrollX.set(x.current);
7125
9946
  values.scrollXProgress.set(x.progress);
7126
9947
  values.scrollY.set(y.current);
@@ -7139,7 +9960,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
7139
9960
  */
7140
9961
  function useElementScroll(ref) {
7141
9962
  if (process.env.NODE_ENV === "development") {
7142
- wrap.warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
9963
+ warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
7143
9964
  }
7144
9965
  return useScroll({ container: ref });
7145
9966
  }
@@ -7149,7 +9970,7 @@ function useElementScroll(ref) {
7149
9970
  */
7150
9971
  function useViewportScroll() {
7151
9972
  if (process.env.NODE_ENV !== "production") {
7152
- wrap.warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
9973
+ warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
7153
9974
  }
7154
9975
  return useScroll();
7155
9976
  }
@@ -7165,8 +9986,8 @@ function useAnimationFrame(callback) {
7165
9986
  initialTimestamp.current = timestamp;
7166
9987
  callback(timestamp - initialTimestamp.current, delta);
7167
9988
  };
7168
- wrap.sync.update(provideTimeSinceStart, true);
7169
- return () => wrap.cancelSync.update(provideTimeSinceStart);
9989
+ sync.update(provideTimeSinceStart, true);
9990
+ return () => cancelSync.update(provideTimeSinceStart);
7170
9991
  }, [callback]);
7171
9992
  }
7172
9993
 
@@ -7176,7 +9997,7 @@ function useTime() {
7176
9997
  return time;
7177
9998
  }
7178
9999
 
7179
- class WillChangeMotionValue extends wrap.MotionValue {
10000
+ class WillChangeMotionValue extends MotionValue {
7180
10001
  constructor() {
7181
10002
  super(...arguments);
7182
10003
  this.members = [];
@@ -7184,7 +10005,7 @@ class WillChangeMotionValue extends wrap.MotionValue {
7184
10005
  }
7185
10006
  add(name) {
7186
10007
  let memberName;
7187
- if (wrap.transformProps.has(name)) {
10008
+ if (transformProps.has(name)) {
7188
10009
  this.transforms.add(name);
7189
10010
  memberName = "transform";
7190
10011
  }
@@ -7194,19 +10015,19 @@ class WillChangeMotionValue extends wrap.MotionValue {
7194
10015
  memberName = camelToDash(name);
7195
10016
  }
7196
10017
  if (memberName) {
7197
- wrap.addUniqueItem(this.members, memberName);
10018
+ addUniqueItem(this.members, memberName);
7198
10019
  this.update();
7199
10020
  }
7200
10021
  }
7201
10022
  remove(name) {
7202
- if (wrap.transformProps.has(name)) {
10023
+ if (transformProps.has(name)) {
7203
10024
  this.transforms.delete(name);
7204
10025
  if (!this.transforms.size) {
7205
- wrap.removeItem(this.members, "transform");
10026
+ removeItem(this.members, "transform");
7206
10027
  }
7207
10028
  }
7208
10029
  else {
7209
- wrap.removeItem(this.members, camelToDash(name));
10030
+ removeItem(this.members, camelToDash(name));
7210
10031
  }
7211
10032
  this.update();
7212
10033
  }
@@ -7261,7 +10082,7 @@ function useReducedMotion() {
7261
10082
  !hasReducedMotionListener.current && initPrefersReducedMotion();
7262
10083
  const [shouldReduceMotion] = React.useState(prefersReducedMotion.current);
7263
10084
  if (process.env.NODE_ENV !== "production") {
7264
- wrap.warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
10085
+ warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
7265
10086
  }
7266
10087
  /**
7267
10088
  * TODO See if people miss automatically updating shouldReduceMotion setting
@@ -7301,7 +10122,7 @@ function animationControls() {
7301
10122
  return () => void subscribers.delete(visualElement);
7302
10123
  },
7303
10124
  start(definition, transitionOverride) {
7304
- wrap.invariant(hasMounted, "controls.start() should only be called after a component has mounted. Consider calling within a useEffect hook.");
10125
+ exports.invariant(hasMounted, "controls.start() should only be called after a component has mounted. Consider calling within a useEffect hook.");
7305
10126
  const animations = [];
7306
10127
  subscribers.forEach((visualElement) => {
7307
10128
  animations.push(animateVisualElement(visualElement, definition, {
@@ -7311,7 +10132,7 @@ function animationControls() {
7311
10132
  return Promise.all(animations);
7312
10133
  },
7313
10134
  set(definition) {
7314
- wrap.invariant(hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.");
10135
+ exports.invariant(hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.");
7315
10136
  return subscribers.forEach((visualElement) => {
7316
10137
  setValues(visualElement, definition);
7317
10138
  });
@@ -7368,6 +10189,11 @@ function useAnimationControls() {
7368
10189
  }
7369
10190
  const useAnimation = useAnimationControls;
7370
10191
 
10192
+ const wrap = (min, max, v) => {
10193
+ const rangeSize = max - min;
10194
+ return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
10195
+ };
10196
+
7371
10197
  /**
7372
10198
  * Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
7373
10199
  *
@@ -7400,7 +10226,7 @@ function useCycle(...items) {
7400
10226
  const runCycle = React.useCallback((next) => {
7401
10227
  index.current =
7402
10228
  typeof next !== "number"
7403
- ? wrap.wrap(0, items.length, index.current + 1)
10229
+ ? wrap(0, items.length, index.current + 1)
7404
10230
  : next;
7405
10231
  setItem(items[index.current]);
7406
10232
  },
@@ -7411,6 +10237,46 @@ function useCycle(...items) {
7411
10237
  return [item, runCycle];
7412
10238
  }
7413
10239
 
10240
+ const thresholds = {
10241
+ any: 0,
10242
+ all: 1,
10243
+ };
10244
+ function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "any" } = {}) {
10245
+ const elements = resolveElements(elementOrSelector);
10246
+ const activeIntersections = new WeakMap();
10247
+ const onIntersectionChange = (entries) => {
10248
+ entries.forEach((entry) => {
10249
+ const onEnd = activeIntersections.get(entry.target);
10250
+ /**
10251
+ * If there's no change to the intersection, we don't need to
10252
+ * do anything here.
10253
+ */
10254
+ if (entry.isIntersecting === Boolean(onEnd))
10255
+ return;
10256
+ if (entry.isIntersecting) {
10257
+ const newOnEnd = onStart(entry);
10258
+ if (typeof newOnEnd === "function") {
10259
+ activeIntersections.set(entry.target, newOnEnd);
10260
+ }
10261
+ else {
10262
+ observer.unobserve(entry.target);
10263
+ }
10264
+ }
10265
+ else if (onEnd) {
10266
+ onEnd(entry);
10267
+ activeIntersections.delete(entry.target);
10268
+ }
10269
+ });
10270
+ };
10271
+ const observer = new IntersectionObserver(onIntersectionChange, {
10272
+ root,
10273
+ rootMargin,
10274
+ threshold: typeof amount === "number" ? amount : thresholds[amount],
10275
+ });
10276
+ elements.forEach((element) => observer.observe(element));
10277
+ return () => observer.disconnect();
10278
+ }
10279
+
7414
10280
  function useInView(ref, { root, margin, amount, once = false } = {}) {
7415
10281
  const [isInView, setInView] = React.useState(false);
7416
10282
  React.useEffect(() => {
@@ -7425,7 +10291,7 @@ function useInView(ref, { root, margin, amount, once = false } = {}) {
7425
10291
  margin,
7426
10292
  amount: amount === "some" ? "any" : amount,
7427
10293
  };
7428
- return wrap.inView(ref.current, onEnter, options);
10294
+ return inView(ref.current, onEnter, options);
7429
10295
  }, [root, ref, margin, once]);
7430
10296
  return isInView;
7431
10297
  }
@@ -7585,11 +10451,11 @@ function useInstantTransition() {
7585
10451
  /**
7586
10452
  * Unblock after two animation frames, otherwise this will unblock too soon.
7587
10453
  */
7588
- wrap.sync.postRender(() => wrap.sync.postRender(() => (wrap.instantAnimationState.current = false)));
10454
+ sync.postRender(() => sync.postRender(() => (instantAnimationState.current = false)));
7589
10455
  }, [forcedRenderCount]);
7590
10456
  return (callback) => {
7591
10457
  startInstantLayoutTransition(() => {
7592
- wrap.instantAnimationState.current = true;
10458
+ instantAnimationState.current = true;
7593
10459
  forceUpdate();
7594
10460
  callback();
7595
10461
  });
@@ -7619,7 +10485,7 @@ function handoffOptimizedAppearAnimation(id, name, value,
7619
10485
  * Framer Motion bundles where it's not needed.
7620
10486
  */
7621
10487
  sync) {
7622
- const storeId = appearStoreId(id, wrap.transformProps.has(name) ? "transform" : name);
10488
+ const storeId = appearStoreId(id, transformProps.has(name) ? "transform" : name);
7623
10489
  const appearAnimation = appearAnimationStore.get(storeId);
7624
10490
  if (!appearAnimation)
7625
10491
  return 0;
@@ -7687,7 +10553,7 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
7687
10553
  *
7688
10554
  * https://bugs.chromium.org/p/chromium/issues/detail?id=1406850
7689
10555
  */
7690
- const readyAnimation = wrap.animateStyle(element, name, [keyframes[0], keyframes[0]],
10556
+ const readyAnimation = animateStyle(element, name, [keyframes[0], keyframes[0]],
7691
10557
  /**
7692
10558
  * 10 secs is basically just a super-safe duration to give Chrome
7693
10559
  * long enough to get the animation ready.
@@ -7699,7 +10565,7 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
7699
10565
  });
7700
10566
  const startAnimation = () => {
7701
10567
  readyAnimation.cancel();
7702
- const appearAnimation = wrap.animateStyle(element, name, keyframes, options);
10568
+ const appearAnimation = animateStyle(element, name, keyframes, options);
7703
10569
  if (document.timeline) {
7704
10570
  appearAnimation.startTime = document.timeline.currentTime;
7705
10571
  }
@@ -7711,7 +10577,7 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
7711
10577
  onReady(appearAnimation);
7712
10578
  };
7713
10579
  if (readyAnimation.ready) {
7714
- readyAnimation.ready.then(startAnimation).catch(wrap.noop);
10580
+ readyAnimation.ready.then(startAnimation).catch(noop);
7715
10581
  }
7716
10582
  else {
7717
10583
  startAnimation();
@@ -7806,8 +10672,8 @@ function useInvertedScale(scale) {
7806
10672
  let parentScaleX = useMotionValue(1);
7807
10673
  let parentScaleY = useMotionValue(1);
7808
10674
  const { visualElement } = React.useContext(MotionContext);
7809
- wrap.invariant(!!(scale || visualElement), "If no scale values are provided, useInvertedScale must be used within a child of another motion component.");
7810
- wrap.warning(hasWarned, "useInvertedScale is deprecated and will be removed in 3.0. Use the layout prop instead.");
10675
+ exports.invariant(!!(scale || visualElement), "If no scale values are provided, useInvertedScale must be used within a child of another motion component.");
10676
+ exports.warning(hasWarned, "useInvertedScale is deprecated and will be removed in 3.0. Use the layout prop instead.");
7811
10677
  hasWarned = true;
7812
10678
  if (scale) {
7813
10679
  parentScaleX = scale.scaleX || parentScaleX;
@@ -7825,54 +10691,11 @@ function useInvertedScale(scale) {
7825
10691
  let id = 0;
7826
10692
  const AnimateSharedLayout = ({ children }) => {
7827
10693
  React__namespace.useEffect(() => {
7828
- wrap.invariant(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
10694
+ exports.invariant(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
7829
10695
  }, []);
7830
10696
  return (React__namespace.createElement(LayoutGroup, { id: useConstant(() => `asl-${id++}`) }, children));
7831
10697
  };
7832
10698
 
7833
- exports.MotionValue = wrap.MotionValue;
7834
- exports.animate = wrap.animate;
7835
- exports.animateValue = wrap.animateValue;
7836
- exports.anticipate = wrap.anticipate;
7837
- exports.backIn = wrap.backIn;
7838
- exports.backInOut = wrap.backInOut;
7839
- exports.backOut = wrap.backOut;
7840
- exports.circIn = wrap.circIn;
7841
- exports.circInOut = wrap.circInOut;
7842
- exports.circOut = wrap.circOut;
7843
- exports.clamp = wrap.clamp;
7844
- exports.color = wrap.color;
7845
- exports.complex = wrap.complex;
7846
- exports.cubicBezier = wrap.cubicBezier;
7847
- exports.delay = wrap.delay;
7848
- exports.distance = wrap.distance;
7849
- exports.distance2D = wrap.distance2D;
7850
- exports.easeIn = wrap.easeIn;
7851
- exports.easeInOut = wrap.easeInOut;
7852
- exports.easeOut = wrap.easeOut;
7853
- exports.frameData = wrap.frameData;
7854
- exports.inView = wrap.inView;
7855
- exports.inertia = wrap.inertia;
7856
- exports.interpolate = wrap.interpolate;
7857
- Object.defineProperty(exports, 'invariant', {
7858
- enumerable: true,
7859
- get: function () { return wrap.invariant; }
7860
- });
7861
- exports.isMotionValue = wrap.isMotionValue;
7862
- exports.mix = wrap.mix;
7863
- exports.motionValue = wrap.motionValue;
7864
- exports.pipe = wrap.pipe;
7865
- exports.progress = wrap.progress;
7866
- exports.px = wrap.px;
7867
- exports.scroll = wrap.scroll;
7868
- exports.spring = wrap.spring;
7869
- exports.sync = wrap.sync;
7870
- exports.transform = wrap.transform;
7871
- Object.defineProperty(exports, 'warning', {
7872
- enumerable: true,
7873
- get: function () { return wrap.warning; }
7874
- });
7875
- exports.wrap = wrap.wrap;
7876
10699
  exports.AnimatePresence = AnimatePresence;
7877
10700
  exports.AnimateSharedLayout = AnimateSharedLayout;
7878
10701
  exports.DragControls = DragControls;
@@ -7883,6 +10706,7 @@ exports.LazyMotion = LazyMotion;
7883
10706
  exports.MotionConfig = MotionConfig;
7884
10707
  exports.MotionConfigContext = MotionConfigContext;
7885
10708
  exports.MotionContext = MotionContext;
10709
+ exports.MotionValue = MotionValue;
7886
10710
  exports.PresenceContext = PresenceContext;
7887
10711
  exports.Reorder = Reorder;
7888
10712
  exports.SwitchLayoutGroupContext = SwitchLayoutGroupContext;
@@ -7890,28 +10714,60 @@ exports.VisualElement = VisualElement;
7890
10714
  exports.addPointerEvent = addPointerEvent;
7891
10715
  exports.addPointerInfo = addPointerInfo;
7892
10716
  exports.addScaleCorrector = addScaleCorrector;
10717
+ exports.animate = animate;
10718
+ exports.animateValue = animateValue;
7893
10719
  exports.animateVisualElement = animateVisualElement;
7894
10720
  exports.animationControls = animationControls;
7895
10721
  exports.animations = animations;
10722
+ exports.anticipate = anticipate;
10723
+ exports.backIn = backIn;
10724
+ exports.backInOut = backInOut;
10725
+ exports.backOut = backOut;
7896
10726
  exports.buildTransform = buildTransform;
7897
10727
  exports.calcLength = calcLength;
7898
10728
  exports.checkTargetForNewValues = checkTargetForNewValues;
10729
+ exports.circIn = circIn;
10730
+ exports.circInOut = circInOut;
10731
+ exports.circOut = circOut;
10732
+ exports.clamp = clamp;
10733
+ exports.color = color;
10734
+ exports.complex = complex;
7899
10735
  exports.createBox = createBox;
7900
10736
  exports.createDomMotionComponent = createDomMotionComponent;
7901
10737
  exports.createMotionComponent = createMotionComponent;
10738
+ exports.cubicBezier = cubicBezier;
10739
+ exports.delay = delay;
10740
+ exports.distance = distance;
10741
+ exports.distance2D = distance2D;
7902
10742
  exports.domAnimation = domAnimation;
7903
10743
  exports.domMax = domMax;
10744
+ exports.easeIn = easeIn;
10745
+ exports.easeInOut = easeInOut;
10746
+ exports.easeOut = easeOut;
7904
10747
  exports.filterProps = filterProps;
10748
+ exports.frameData = frameData;
10749
+ exports.inertia = inertia;
10750
+ exports.interpolate = interpolate;
7905
10751
  exports.isBrowser = isBrowser;
7906
10752
  exports.isDragActive = isDragActive;
7907
10753
  exports.isMotionComponent = isMotionComponent;
10754
+ exports.isMotionValue = isMotionValue;
7908
10755
  exports.isValidMotionProp = isValidMotionProp;
7909
10756
  exports.m = m;
7910
10757
  exports.makeUseVisualState = makeUseVisualState;
10758
+ exports.mix = mix;
7911
10759
  exports.motion = motion;
10760
+ exports.motionValue = motionValue;
7912
10761
  exports.optimizedAppearDataAttribute = optimizedAppearDataAttribute;
10762
+ exports.pipe = pipe;
10763
+ exports.progress = progress;
10764
+ exports.px = px;
7913
10765
  exports.resolveMotionValue = resolveMotionValue;
10766
+ exports.scroll = scroll;
10767
+ exports.spring = spring;
7914
10768
  exports.startOptimizedAppearAnimation = startOptimizedAppearAnimation;
10769
+ exports.sync = sync;
10770
+ exports.transform = transform;
7915
10771
  exports.unwrapMotionComponent = unwrapMotionComponent;
7916
10772
  exports.useAnimation = useAnimation;
7917
10773
  exports.useAnimationControls = useAnimationControls;
@@ -7943,3 +10799,4 @@ exports.useUnmountEffect = useUnmountEffect;
7943
10799
  exports.useVelocity = useVelocity;
7944
10800
  exports.useViewportScroll = useViewportScroll;
7945
10801
  exports.useWillChange = useWillChange;
10802
+ exports.wrap = wrap;