framer-motion 12.4.13 → 12.5.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.
Files changed (99) hide show
  1. package/dist/cjs/client.js +1 -1
  2. package/dist/cjs/{create-DkTZDHiS.js → create-BErQMR-o.js} +4234 -4792
  3. package/dist/cjs/debug.js +5 -281
  4. package/dist/cjs/dom-mini.js +9 -7
  5. package/dist/cjs/dom.js +81 -639
  6. package/dist/cjs/index.js +1555 -1553
  7. package/dist/cjs/m.js +11 -179
  8. package/dist/cjs/mini.js +8 -0
  9. package/dist/debug.d.ts +2 -35
  10. package/dist/dom-mini.d.ts +1 -181
  11. package/dist/dom-mini.js +1 -1
  12. package/dist/dom.d.ts +3 -242
  13. package/dist/dom.js +1 -1
  14. package/dist/es/animation/animate/single-value.mjs +1 -1
  15. package/dist/es/animation/animators/BaseAnimation.mjs +1 -1
  16. package/dist/es/animation/animators/MainThreadAnimation.mjs +1 -2
  17. package/dist/es/animation/animators/drivers/driver-frameloop.mjs +1 -2
  18. package/dist/es/animation/animators/waapi/index.mjs +1 -3
  19. package/dist/es/animation/generators/utils/velocity.mjs +1 -1
  20. package/dist/es/animation/interfaces/motion-value.mjs +2 -4
  21. package/dist/es/animation/interfaces/visual-element-target.mjs +1 -2
  22. package/dist/es/animation/optimized-appear/start.mjs +3 -3
  23. package/dist/es/animation/sequence/utils/edit.mjs +1 -1
  24. package/dist/es/components/AnimatePresence/index.mjs +1 -1
  25. package/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
  26. package/dist/es/debug.mjs +1 -1
  27. package/dist/es/dom.mjs +1 -5
  28. package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -2
  29. package/dist/es/gestures/hover.mjs +1 -2
  30. package/dist/es/gestures/pan/PanSession.mjs +1 -2
  31. package/dist/es/gestures/pan/index.mjs +1 -1
  32. package/dist/es/gestures/press.mjs +1 -2
  33. package/dist/es/index.mjs +14 -19
  34. package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -2
  35. package/dist/es/motion/utils/use-visual-element.mjs +6 -6
  36. package/dist/es/projection/node/create-projection-node.mjs +2 -8
  37. package/dist/es/projection/shared/stack.mjs +1 -1
  38. package/dist/es/projection.mjs +1 -3
  39. package/dist/es/render/VisualElement.mjs +2 -5
  40. package/dist/es/render/components/create-proxy.mjs +1 -1
  41. package/dist/es/render/dom/DOMVisualElement.mjs +1 -1
  42. package/dist/es/render/dom/scroll/info.mjs +1 -2
  43. package/dist/es/render/dom/scroll/observe.mjs +1 -1
  44. package/dist/es/render/dom/scroll/on-scroll-handler.mjs +1 -1
  45. package/dist/es/render/dom/scroll/track.mjs +1 -1
  46. package/dist/es/render/svg/SVGVisualElement.mjs +1 -1
  47. package/dist/es/render/svg/config-motion.mjs +1 -1
  48. package/dist/es/render/utils/KeyframesResolver.mjs +1 -1
  49. package/dist/es/render/utils/flat-tree.mjs +1 -1
  50. package/dist/es/render/utils/motion-values.mjs +3 -3
  51. package/dist/es/render/utils/setters.mjs +1 -1
  52. package/dist/es/utils/delay.mjs +1 -2
  53. package/dist/es/utils/reduced-motion/use-reduced-motion.mjs +1 -1
  54. package/dist/es/utils/use-animation-frame.mjs +1 -1
  55. package/dist/es/utils/use-force-update.mjs +1 -1
  56. package/dist/es/utils/use-instant-transition.mjs +1 -1
  57. package/dist/es/value/scroll/use-element-scroll.mjs +1 -1
  58. package/dist/es/value/scroll/use-viewport-scroll.mjs +1 -1
  59. package/dist/es/value/use-combine-values.mjs +2 -2
  60. package/dist/es/value/use-computed.mjs +1 -1
  61. package/dist/es/value/use-inverted-scale.mjs +3 -3
  62. package/dist/es/value/use-motion-value.mjs +1 -1
  63. package/dist/es/value/use-scroll.mjs +4 -4
  64. package/dist/es/value/use-spring.mjs +1 -1
  65. package/dist/es/value/use-transform.mjs +1 -1
  66. package/dist/es/value/use-velocity.mjs +1 -1
  67. package/dist/es/value/use-will-change/WillChangeMotionValue.mjs +2 -2
  68. package/dist/framer-motion.dev.js +8227 -8251
  69. package/dist/framer-motion.js +1 -1
  70. package/dist/m.d.ts +49 -241
  71. package/dist/size-rollup-animate.js +1 -1
  72. package/dist/size-rollup-dom-animation-assets.js +1 -1
  73. package/dist/size-rollup-dom-animation.js +1 -1
  74. package/dist/size-rollup-dom-max-assets.js +1 -1
  75. package/dist/size-rollup-dom-max.js +1 -1
  76. package/dist/size-rollup-m.js +1 -1
  77. package/dist/size-rollup-motion.js +1 -1
  78. package/dist/size-rollup-scroll.js +1 -1
  79. package/dist/types/client.d.ts +2 -2
  80. package/dist/types/index.d.ts +43 -79
  81. package/dist/{types.d-6pKw1mTI.d.ts → types.d-B50aGbjN.d.ts} +81 -289
  82. package/package.json +4 -6
  83. package/dist/es/frameloop/batcher.mjs +0 -69
  84. package/dist/es/frameloop/frame.mjs +0 -6
  85. package/dist/es/frameloop/index-legacy.mjs +0 -20
  86. package/dist/es/frameloop/microtask.mjs +0 -5
  87. package/dist/es/frameloop/order.mjs +0 -10
  88. package/dist/es/frameloop/render-step.mjs +0 -92
  89. package/dist/es/frameloop/sync-time.mjs +0 -31
  90. package/dist/es/stats/animation-count.mjs +0 -7
  91. package/dist/es/stats/buffer.mjs +0 -6
  92. package/dist/es/stats/index.mjs +0 -113
  93. package/dist/es/utils/GlobalConfig.mjs +0 -6
  94. package/dist/es/utils/array.mjs +0 -21
  95. package/dist/es/utils/subscription-manager.mjs +0 -40
  96. package/dist/es/utils/velocity-per-second.mjs +0 -11
  97. package/dist/es/utils/warn-once.mjs +0 -11
  98. package/dist/es/value/index.mjs +0 -319
  99. package/dist/three.d.ts +0 -2833
package/dist/cjs/index.js CHANGED
@@ -4,9 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
- var create = require('./create-DkTZDHiS.js');
8
- var motionUtils = require('motion-utils');
7
+ var create = require('./create-BErQMR-o.js');
9
8
  var motionDom = require('motion-dom');
9
+ var motionUtils = require('motion-utils');
10
10
 
11
11
  function _interopNamespaceDefault(e) {
12
12
  var n = Object.create(null);
@@ -27,35 +27,6 @@ function _interopNamespaceDefault(e) {
27
27
 
28
28
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
29
29
 
30
- function useUnmountEffect(callback) {
31
- return React.useEffect(() => () => callback(), []);
32
- }
33
-
34
- function useIsMounted() {
35
- const isMounted = React.useRef(false);
36
- create.useIsomorphicLayoutEffect(() => {
37
- isMounted.current = true;
38
- return () => {
39
- isMounted.current = false;
40
- };
41
- }, []);
42
- return isMounted;
43
- }
44
-
45
- function useForceUpdate() {
46
- const isMounted = useIsMounted();
47
- const [forcedRenderCount, setForcedRenderCount] = React.useState(0);
48
- const forceRender = React.useCallback(() => {
49
- isMounted.current && setForcedRenderCount(forcedRenderCount + 1);
50
- }, [forcedRenderCount]);
51
- /**
52
- * Defer this to the end of the next animation frame in case there are multiple
53
- * synchronous calls.
54
- */
55
- const deferredForceRender = React.useCallback(() => create.frame.postRender(forceRender), [forceRender]);
56
- return [deferredForceRender, forcedRenderCount];
57
- }
58
-
59
30
  /**
60
31
  * Measurement functionality has to be within a separate component
61
32
  * to leverage snapshot lifecycle.
@@ -379,1684 +350,1697 @@ function nodeGroup() {
379
350
  };
380
351
  }
381
352
 
382
- const wrap = (min, max, v) => {
383
- const rangeSize = max - min;
384
- return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
385
- };
386
-
387
- function getEasingForSegment(easing, i) {
388
- return create.isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
353
+ function useIsMounted() {
354
+ const isMounted = React.useRef(false);
355
+ create.useIsomorphicLayoutEffect(() => {
356
+ isMounted.current = true;
357
+ return () => {
358
+ isMounted.current = false;
359
+ };
360
+ }, []);
361
+ return isMounted;
389
362
  }
390
363
 
391
- function isDOMKeyframes(keyframes) {
392
- return typeof keyframes === "object" && !Array.isArray(keyframes);
364
+ function useForceUpdate() {
365
+ const isMounted = useIsMounted();
366
+ const [forcedRenderCount, setForcedRenderCount] = React.useState(0);
367
+ const forceRender = React.useCallback(() => {
368
+ isMounted.current && setForcedRenderCount(forcedRenderCount + 1);
369
+ }, [forcedRenderCount]);
370
+ /**
371
+ * Defer this to the end of the next animation frame in case there are multiple
372
+ * synchronous calls.
373
+ */
374
+ const deferredForceRender = React.useCallback(() => motionDom.frame.postRender(forceRender), [forceRender]);
375
+ return [deferredForceRender, forcedRenderCount];
393
376
  }
394
377
 
395
- function resolveSubjects(subject, keyframes, scope, selectorCache) {
396
- if (typeof subject === "string" && isDOMKeyframes(keyframes)) {
397
- return motionDom.resolveElements(subject, scope, selectorCache);
398
- }
399
- else if (subject instanceof NodeList) {
400
- return Array.from(subject);
401
- }
402
- else if (Array.isArray(subject)) {
403
- return subject;
404
- }
405
- else {
406
- return [subject];
378
+ const shouldInheritGroup = (inherit) => inherit === true;
379
+ const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
380
+ const LayoutGroup = ({ children, id, inherit = true }) => {
381
+ const layoutGroupContext = React.useContext(create.LayoutGroupContext);
382
+ const deprecatedLayoutGroupContext = React.useContext(DeprecatedLayoutGroupContext);
383
+ const [forceRender, key] = useForceUpdate();
384
+ const context = React.useRef(null);
385
+ const upstreamId = layoutGroupContext.id || deprecatedLayoutGroupContext;
386
+ if (context.current === null) {
387
+ if (shouldInheritId(inherit) && upstreamId) {
388
+ id = id ? upstreamId + "-" + id : upstreamId;
389
+ }
390
+ context.current = {
391
+ id,
392
+ group: shouldInheritGroup(inherit)
393
+ ? layoutGroupContext.group || nodeGroup()
394
+ : nodeGroup(),
395
+ };
407
396
  }
408
- }
409
-
410
- function calculateRepeatDuration(duration, repeat, _repeatDelay) {
411
- return duration * (repeat + 1);
412
- }
397
+ const memoizedContext = React.useMemo(() => ({ ...context.current, forceRender }), [key]);
398
+ return (jsxRuntime.jsx(create.LayoutGroupContext.Provider, { value: memoizedContext, children: children }));
399
+ };
413
400
 
414
401
  /**
415
- * Given a absolute or relative time definition and current/prev time state of the sequence,
416
- * calculate an absolute time for the next keyframes.
402
+ * Used in conjunction with the `m` component to reduce bundle size.
403
+ *
404
+ * `m` is a version of the `motion` component that only loads functionality
405
+ * critical for the initial render.
406
+ *
407
+ * `LazyMotion` can then be used to either synchronously or asynchronously
408
+ * load animation and gesture support.
409
+ *
410
+ * ```jsx
411
+ * // Synchronous loading
412
+ * import { LazyMotion, m, domAnimation } from "framer-motion"
413
+ *
414
+ * function App() {
415
+ * return (
416
+ * <LazyMotion features={domAnimation}>
417
+ * <m.div animate={{ scale: 2 }} />
418
+ * </LazyMotion>
419
+ * )
420
+ * }
421
+ *
422
+ * // Asynchronous loading
423
+ * import { LazyMotion, m } from "framer-motion"
424
+ *
425
+ * function App() {
426
+ * return (
427
+ * <LazyMotion features={() => import('./path/to/domAnimation')}>
428
+ * <m.div animate={{ scale: 2 }} />
429
+ * </LazyMotion>
430
+ * )
431
+ * }
432
+ * ```
433
+ *
434
+ * @public
417
435
  */
418
- function calcNextTime(current, next, prev, labels) {
419
- var _a;
420
- if (typeof next === "number") {
421
- return next;
422
- }
423
- else if (next.startsWith("-") || next.startsWith("+")) {
424
- return Math.max(0, current + parseFloat(next));
425
- }
426
- else if (next === "<") {
427
- return prev;
428
- }
429
- else {
430
- return (_a = labels.get(next)) !== null && _a !== void 0 ? _a : current;
431
- }
432
- }
433
-
434
- function eraseKeyframes(sequence, startTime, endTime) {
435
- for (let i = 0; i < sequence.length; i++) {
436
- const keyframe = sequence[i];
437
- if (keyframe.at > startTime && keyframe.at < endTime) {
438
- create.removeItem(sequence, keyframe);
439
- // If we remove this item we have to push the pointer back one
440
- i--;
441
- }
442
- }
443
- }
444
- function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
436
+ function LazyMotion({ children, features, strict = false }) {
437
+ const [, setIsLoaded] = React.useState(!isLazyBundle(features));
438
+ const loadedRenderer = React.useRef(undefined);
445
439
  /**
446
- * Erase every existing value between currentTime and targetTime,
447
- * this will essentially splice this timeline into any currently
448
- * defined ones.
440
+ * If this is a synchronous load, load features immediately
449
441
  */
450
- eraseKeyframes(sequence, startTime, endTime);
451
- for (let i = 0; i < keyframes.length; i++) {
452
- sequence.push({
453
- value: keyframes[i],
454
- at: create.mixNumber(startTime, endTime, offset[i]),
455
- easing: getEasingForSegment(easing, i),
456
- });
442
+ if (!isLazyBundle(features)) {
443
+ const { renderer, ...loadedFeatures } = features;
444
+ loadedRenderer.current = renderer;
445
+ create.loadFeatures(loadedFeatures);
457
446
  }
447
+ React.useEffect(() => {
448
+ if (isLazyBundle(features)) {
449
+ features().then(({ renderer, ...loadedFeatures }) => {
450
+ create.loadFeatures(loadedFeatures);
451
+ loadedRenderer.current = renderer;
452
+ setIsLoaded(true);
453
+ });
454
+ }
455
+ }, []);
456
+ return (jsxRuntime.jsx(create.LazyContext.Provider, { value: { renderer: loadedRenderer.current, strict }, children: children }));
457
+ }
458
+ function isLazyBundle(features) {
459
+ return typeof features === "function";
458
460
  }
459
461
 
460
462
  /**
461
- * Take an array of times that represent repeated keyframes. For instance
462
- * if we have original times of [0, 0.5, 1] then our repeated times will
463
- * be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
464
- * down to a 0-1 scale.
463
+ * `MotionConfig` is used to set configuration options for all children `motion` components.
464
+ *
465
+ * ```jsx
466
+ * import { motion, MotionConfig } from "framer-motion"
467
+ *
468
+ * export function App() {
469
+ * return (
470
+ * <MotionConfig transition={{ type: "spring" }}>
471
+ * <motion.div animate={{ x: 100 }} />
472
+ * </MotionConfig>
473
+ * )
474
+ * }
475
+ * ```
476
+ *
477
+ * @public
465
478
  */
466
- function normalizeTimes(times, repeat) {
467
- for (let i = 0; i < times.length; i++) {
468
- times[i] = times[i] / (repeat + 1);
469
- }
479
+ function MotionConfig({ children, isValidProp, ...config }) {
480
+ isValidProp && create.loadExternalIsValidProp(isValidProp);
481
+ /**
482
+ * Inherit props from any parent MotionConfig components
483
+ */
484
+ config = { ...React.useContext(create.MotionConfigContext), ...config };
485
+ /**
486
+ * Don't allow isStatic to change between renders as it affects how many hooks
487
+ * motion components fire.
488
+ */
489
+ config.isStatic = create.useConstant(() => config.isStatic);
490
+ /**
491
+ * Creating a new config context object will re-render every `motion` component
492
+ * every time it renders. So we only want to create a new one sparingly.
493
+ */
494
+ const context = React.useMemo(() => config, [
495
+ JSON.stringify(config.transition),
496
+ config.transformPagePoint,
497
+ config.reducedMotion,
498
+ ]);
499
+ return (jsxRuntime.jsx(create.MotionConfigContext.Provider, { value: context, children: children }));
470
500
  }
471
501
 
472
- function compareByTime(a, b) {
473
- if (a.at === b.at) {
474
- if (a.value === null)
475
- return 1;
476
- if (b.value === null)
477
- return -1;
478
- return 0;
479
- }
480
- else {
481
- return a.at - b.at;
482
- }
483
- }
502
+ const ReorderContext = React.createContext(null);
484
503
 
485
- const defaultSegmentEasing = "easeInOut";
486
- const MAX_REPEAT = 20;
487
- function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
488
- const defaultDuration = defaultTransition.duration || 0.3;
489
- const animationDefinitions = new Map();
490
- const sequences = new Map();
491
- const elementCache = {};
492
- const timeLabels = new Map();
493
- let prevTime = 0;
494
- let currentTime = 0;
495
- let totalDuration = 0;
504
+ function createDOMMotionComponentProxy(componentFactory) {
505
+ if (typeof Proxy === "undefined") {
506
+ return componentFactory;
507
+ }
496
508
  /**
497
- * Build the timeline by mapping over the sequence array and converting
498
- * the definitions into keyframes and offsets with absolute time values.
499
- * These will later get converted into relative offsets in a second pass.
509
+ * A cache of generated `motion` components, e.g `motion.div`, `motion.input` etc.
510
+ * Rather than generating them anew every render.
500
511
  */
501
- for (let i = 0; i < sequence.length; i++) {
502
- const segment = sequence[i];
503
- /**
504
- * If this is a timeline label, mark it and skip the rest of this iteration.
505
- */
506
- if (typeof segment === "string") {
507
- timeLabels.set(segment, currentTime);
508
- continue;
509
- }
510
- else if (!Array.isArray(segment)) {
511
- timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
512
- continue;
513
- }
514
- let [subject, keyframes, transition = {}] = segment;
515
- /**
516
- * If a relative or absolute time value has been specified we need to resolve
517
- * it in relation to the currentTime.
518
- */
519
- if (transition.at !== undefined) {
520
- currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
512
+ const componentCache = new Map();
513
+ const deprecatedFactoryFunction = (...args) => {
514
+ if (process.env.NODE_ENV !== "production") {
515
+ motionUtils.warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
521
516
  }
517
+ return componentFactory(...args);
518
+ };
519
+ return new Proxy(deprecatedFactoryFunction, {
522
520
  /**
523
- * Keep track of the maximum duration in this definition. This will be
524
- * applied to currentTime once the definition has been parsed.
521
+ * Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
522
+ * The prop name is passed through as `key` and we can use that to generate a `motion`
523
+ * DOM component with that name.
525
524
  */
526
- let maxDuration = 0;
527
- const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
528
- const valueKeyframesAsList = keyframesAsList(valueKeyframes);
529
- const { delay = 0, times = create.defaultOffset(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
530
- let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
531
- /**
532
- * Resolve stagger() if defined.
533
- */
534
- const calculatedDelay = typeof delay === "function"
535
- ? delay(elementIndex, numSubjects)
536
- : delay;
525
+ get: (_target, key) => {
526
+ if (key === "create")
527
+ return componentFactory;
537
528
  /**
538
- * If this animation should and can use a spring, generate a spring easing function.
529
+ * If this element doesn't exist in the component cache, create it and cache.
539
530
  */
540
- const numKeyframes = valueKeyframesAsList.length;
541
- const createGenerator = motionDom.isGenerator(type)
542
- ? type
543
- : generators === null || generators === void 0 ? void 0 : generators[type];
544
- if (numKeyframes <= 2 && createGenerator) {
545
- /**
546
- * As we're creating an easing function from a spring,
547
- * ideally we want to generate it using the real distance
548
- * between the two keyframes. However this isn't always
549
- * possible - in these situations we use 0-100.
550
- */
551
- let absoluteDelta = 100;
552
- if (numKeyframes === 2 &&
553
- isNumberKeyframesArray(valueKeyframesAsList)) {
554
- const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
555
- absoluteDelta = Math.abs(delta);
556
- }
557
- const springTransition = { ...remainingTransition };
558
- if (duration !== undefined) {
559
- springTransition.duration = motionUtils.secondsToMilliseconds(duration);
560
- }
561
- const springEasing = motionDom.createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
562
- ease = springEasing.ease;
563
- duration = springEasing.duration;
531
+ if (!componentCache.has(key)) {
532
+ componentCache.set(key, componentFactory(key));
564
533
  }
565
- duration !== null && duration !== void 0 ? duration : (duration = defaultDuration);
566
- const startTime = currentTime + calculatedDelay;
567
- /**
568
- * If there's only one time offset of 0, fill in a second with length 1
569
- */
570
- if (times.length === 1 && times[0] === 0) {
571
- times[1] = 1;
534
+ return componentCache.get(key);
535
+ },
536
+ });
537
+ }
538
+
539
+ const motion = /*@__PURE__*/ createDOMMotionComponentProxy(create.createMotionComponent);
540
+
541
+ function checkReorder(order, value, offset, velocity) {
542
+ if (!velocity)
543
+ return order;
544
+ const index = order.findIndex((item) => item.value === value);
545
+ if (index === -1)
546
+ return order;
547
+ const nextOffset = velocity > 0 ? 1 : -1;
548
+ const nextItem = order[index + nextOffset];
549
+ if (!nextItem)
550
+ return order;
551
+ const item = order[index];
552
+ const nextLayout = nextItem.layout;
553
+ const nextItemCenter = create.mixNumber(nextLayout.min, nextLayout.max, 0.5);
554
+ if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
555
+ (nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
556
+ return motionUtils.moveItem(order, index, index + nextOffset);
557
+ }
558
+ return order;
559
+ }
560
+
561
+ function ReorderGroupComponent({ children, as = "ul", axis = "y", onReorder, values, ...props }, externalRef) {
562
+ const Component = create.useConstant(() => motion[as]);
563
+ const order = [];
564
+ const isReordering = React.useRef(false);
565
+ motionUtils.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
566
+ const context = {
567
+ axis,
568
+ registerItem: (value, layout) => {
569
+ // If the entry was already added, update it rather than adding it again
570
+ const idx = order.findIndex((entry) => value === entry.value);
571
+ if (idx !== -1) {
572
+ order[idx].layout = layout[axis];
572
573
  }
573
- /**
574
- * Fill out if offset if fewer offsets than keyframes
575
- */
576
- const remainder = times.length - valueKeyframesAsList.length;
577
- remainder > 0 && create.fillOffset(times, remainder);
578
- /**
579
- * If only one value has been set, ie [1], push a null to the start of
580
- * the keyframe array. This will let us mark a keyframe at this point
581
- * that will later be hydrated with the previous value.
582
- */
583
- valueKeyframesAsList.length === 1 &&
584
- valueKeyframesAsList.unshift(null);
585
- /**
586
- * Handle repeat options
587
- */
588
- if (repeat) {
589
- motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
590
- duration = calculateRepeatDuration(duration, repeat);
591
- const originalKeyframes = [...valueKeyframesAsList];
592
- const originalTimes = [...times];
593
- ease = Array.isArray(ease) ? [...ease] : [ease];
594
- const originalEase = [...ease];
595
- for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
596
- valueKeyframesAsList.push(...originalKeyframes);
597
- for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
598
- times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
599
- ease.push(keyframeIndex === 0
600
- ? "linear"
601
- : getEasingForSegment(originalEase, keyframeIndex - 1));
602
- }
603
- }
604
- normalizeTimes(times, repeat);
574
+ else {
575
+ order.push({ value: value, layout: layout[axis] });
605
576
  }
606
- const targetTime = startTime + duration;
607
- /**
608
- * Add keyframes, mapping offsets to absolute time.
609
- */
610
- addKeyframes(valueSequence, valueKeyframesAsList, ease, times, startTime, targetTime);
611
- maxDuration = Math.max(calculatedDelay + duration, maxDuration);
612
- totalDuration = Math.max(targetTime, totalDuration);
613
- };
614
- if (create.isMotionValue(subject)) {
615
- const subjectSequence = getSubjectSequence(subject, sequences);
616
- resolveValueSequence(keyframes, transition, getValueSequence("default", subjectSequence));
617
- }
618
- else {
619
- const subjects = resolveSubjects(subject, keyframes, scope, elementCache);
620
- const numSubjects = subjects.length;
621
- /**
622
- * For every element in this segment, process the defined values.
623
- */
624
- for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
625
- /**
626
- * Cast necessary, but we know these are of this type
627
- */
628
- keyframes = keyframes;
629
- transition = transition;
630
- const thisSubject = subjects[subjectIndex];
631
- const subjectSequence = getSubjectSequence(thisSubject, sequences);
632
- for (const key in keyframes) {
633
- resolveValueSequence(keyframes[key], getValueTransition(transition, key), getValueSequence(key, subjectSequence), subjectIndex, numSubjects);
634
- }
577
+ order.sort(compareMin);
578
+ },
579
+ updateOrder: (item, offset, velocity) => {
580
+ if (isReordering.current)
581
+ return;
582
+ const newOrder = checkReorder(order, item, offset, velocity);
583
+ if (order !== newOrder) {
584
+ isReordering.current = true;
585
+ onReorder(newOrder
586
+ .map(getValue)
587
+ .filter((value) => values.indexOf(value) !== -1));
635
588
  }
636
- }
637
- prevTime = currentTime;
638
- currentTime += maxDuration;
639
- }
589
+ },
590
+ };
591
+ React.useEffect(() => {
592
+ isReordering.current = false;
593
+ });
594
+ return (jsxRuntime.jsx(Component, { ...props, ref: externalRef, ignoreStrict: true, children: jsxRuntime.jsx(ReorderContext.Provider, { value: context, children: children }) }));
595
+ }
596
+ const ReorderGroup = /*@__PURE__*/ React.forwardRef(ReorderGroupComponent);
597
+ function getValue(item) {
598
+ return item.value;
599
+ }
600
+ function compareMin(a, b) {
601
+ return a.layout.min - b.layout.min;
602
+ }
603
+
604
+ /**
605
+ * Creates a `MotionValue` to track the state and velocity of a value.
606
+ *
607
+ * Usually, these are created automatically. For advanced use-cases, like use with `useTransform`, you can create `MotionValue`s externally and pass them into the animated component via the `style` prop.
608
+ *
609
+ * ```jsx
610
+ * export const MyComponent = () => {
611
+ * const scale = useMotionValue(1)
612
+ *
613
+ * return <motion.div style={{ scale }} />
614
+ * }
615
+ * ```
616
+ *
617
+ * @param initial - The initial state.
618
+ *
619
+ * @public
620
+ */
621
+ function useMotionValue(initial) {
622
+ const value = create.useConstant(() => motionDom.motionValue(initial));
640
623
  /**
641
- * For every element and value combination create a new animation.
624
+ * If this motion value is being used in static mode, like on
625
+ * the Framer canvas, force components to rerender when the motion
626
+ * value is updated.
642
627
  */
643
- sequences.forEach((valueSequences, element) => {
644
- for (const key in valueSequences) {
645
- const valueSequence = valueSequences[key];
646
- /**
647
- * Arrange all the keyframes in ascending time order.
648
- */
649
- valueSequence.sort(compareByTime);
650
- const keyframes = [];
651
- const valueOffset = [];
652
- const valueEasing = [];
653
- /**
654
- * For each keyframe, translate absolute times into
655
- * relative offsets based on the total duration of the timeline.
656
- */
657
- for (let i = 0; i < valueSequence.length; i++) {
658
- const { at, value, easing } = valueSequence[i];
659
- keyframes.push(value);
660
- valueOffset.push(motionUtils.progress(0, totalDuration, at));
661
- valueEasing.push(easing || "easeOut");
662
- }
663
- /**
664
- * If the first keyframe doesn't land on offset: 0
665
- * provide one by duplicating the initial keyframe. This ensures
666
- * it snaps to the first keyframe when the animation starts.
667
- */
668
- if (valueOffset[0] !== 0) {
669
- valueOffset.unshift(0);
670
- keyframes.unshift(keyframes[0]);
671
- valueEasing.unshift(defaultSegmentEasing);
672
- }
673
- /**
674
- * If the last keyframe doesn't land on offset: 1
675
- * provide one with a null wildcard value. This will ensure it
676
- * stays static until the end of the animation.
677
- */
678
- if (valueOffset[valueOffset.length - 1] !== 1) {
679
- valueOffset.push(1);
680
- keyframes.push(null);
681
- }
682
- if (!animationDefinitions.has(element)) {
683
- animationDefinitions.set(element, {
684
- keyframes: {},
685
- transition: {},
686
- });
687
- }
688
- const definition = animationDefinitions.get(element);
689
- definition.keyframes[key] = keyframes;
690
- definition.transition[key] = {
691
- ...defaultTransition,
692
- duration: totalDuration,
693
- ease: valueEasing,
694
- times: valueOffset,
695
- ...sequenceTransition,
696
- };
697
- }
628
+ const { isStatic } = React.useContext(create.MotionConfigContext);
629
+ if (isStatic) {
630
+ const [, setLatest] = React.useState(initial);
631
+ React.useEffect(() => value.on("change", setLatest), []);
632
+ }
633
+ return value;
634
+ }
635
+
636
+ const isCustomValueType = (v) => {
637
+ return v && typeof v === "object" && v.mix;
638
+ };
639
+ const getMixer = (v) => (isCustomValueType(v) ? v.mix : undefined);
640
+ function transform(...args) {
641
+ const useImmediate = !Array.isArray(args[0]);
642
+ const argOffset = useImmediate ? 0 : -1;
643
+ const inputValue = args[0 + argOffset];
644
+ const inputRange = args[1 + argOffset];
645
+ const outputRange = args[2 + argOffset];
646
+ const options = args[3 + argOffset];
647
+ const interpolator = create.interpolate(inputRange, outputRange, {
648
+ mixer: getMixer(outputRange[0]),
649
+ ...options,
698
650
  });
699
- return animationDefinitions;
651
+ return useImmediate ? interpolator(inputValue) : interpolator;
700
652
  }
701
- function getSubjectSequence(subject, sequences) {
702
- !sequences.has(subject) && sequences.set(subject, {});
703
- return sequences.get(subject);
653
+
654
+ function useCombineMotionValues(values, combineValues) {
655
+ /**
656
+ * Initialise the returned motion value. This remains the same between renders.
657
+ */
658
+ const value = useMotionValue(combineValues());
659
+ /**
660
+ * Create a function that will update the template motion value with the latest values.
661
+ * This is pre-bound so whenever a motion value updates it can schedule its
662
+ * execution in Framesync. If it's already been scheduled it won't be fired twice
663
+ * in a single frame.
664
+ */
665
+ const updateValue = () => value.set(combineValues());
666
+ /**
667
+ * Synchronously update the motion value with the latest values during the render.
668
+ * This ensures that within a React render, the styles applied to the DOM are up-to-date.
669
+ */
670
+ updateValue();
671
+ /**
672
+ * Subscribe to all motion values found within the template. Whenever any of them change,
673
+ * schedule an update.
674
+ */
675
+ create.useIsomorphicLayoutEffect(() => {
676
+ const scheduleUpdate = () => motionDom.frame.preRender(updateValue, false, true);
677
+ const subscriptions = values.map((v) => v.on("change", scheduleUpdate));
678
+ return () => {
679
+ subscriptions.forEach((unsubscribe) => unsubscribe());
680
+ motionDom.cancelFrame(updateValue);
681
+ };
682
+ });
683
+ return value;
704
684
  }
705
- function getValueSequence(name, sequences) {
706
- if (!sequences[name])
707
- sequences[name] = [];
708
- return sequences[name];
685
+
686
+ function useComputed(compute) {
687
+ /**
688
+ * Open session of collectMotionValues. Any MotionValue that calls get()
689
+ * will be saved into this array.
690
+ */
691
+ motionDom.collectMotionValues.current = [];
692
+ compute();
693
+ const value = useCombineMotionValues(motionDom.collectMotionValues.current, compute);
694
+ /**
695
+ * Synchronously close session of collectMotionValues.
696
+ */
697
+ motionDom.collectMotionValues.current = undefined;
698
+ return value;
709
699
  }
710
- function keyframesAsList(keyframes) {
711
- return Array.isArray(keyframes) ? keyframes : [keyframes];
700
+
701
+ function useTransform(input, inputRangeOrTransformer, outputRange, options) {
702
+ if (typeof input === "function") {
703
+ return useComputed(input);
704
+ }
705
+ const transformer = typeof inputRangeOrTransformer === "function"
706
+ ? inputRangeOrTransformer
707
+ : transform(inputRangeOrTransformer, outputRange, options);
708
+ return Array.isArray(input)
709
+ ? useListTransform(input, transformer)
710
+ : useListTransform([input], ([latest]) => transformer(latest));
712
711
  }
713
- function getValueTransition(transition, key) {
714
- return transition && transition[key]
715
- ? {
716
- ...transition,
717
- ...transition[key],
712
+ function useListTransform(values, transformer) {
713
+ const latest = create.useConstant(() => []);
714
+ return useCombineMotionValues(values, () => {
715
+ latest.length = 0;
716
+ const numValues = values.length;
717
+ for (let i = 0; i < numValues; i++) {
718
+ latest[i] = values[i].get();
718
719
  }
719
- : { ...transition };
720
+ return transformer(latest);
721
+ });
720
722
  }
721
- const isNumber = (keyframe) => typeof keyframe === "number";
722
- const isNumberKeyframesArray = (keyframes) => keyframes.every(isNumber);
723
723
 
724
- function isObjectKey(key, object) {
725
- return key in object;
724
+ function useDefaultMotionValue(value, defaultValue = 0) {
725
+ return create.isMotionValue(value) ? value : useMotionValue(defaultValue);
726
726
  }
727
- class ObjectVisualElement extends create.VisualElement {
728
- constructor() {
729
- super(...arguments);
730
- this.type = "object";
727
+ function ReorderItemComponent({ children, style = {}, value, as = "li", onDrag, layout = true, ...props }, externalRef) {
728
+ const Component = create.useConstant(() => motion[as]);
729
+ const context = React.useContext(ReorderContext);
730
+ const point = {
731
+ x: useDefaultMotionValue(style.x),
732
+ y: useDefaultMotionValue(style.y),
733
+ };
734
+ const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) => latestX || latestY ? 1 : "unset");
735
+ motionUtils.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
736
+ const { axis, registerItem, updateOrder } = context;
737
+ return (jsxRuntime.jsx(Component, { drag: axis, ...props, dragSnapToOrigin: true, style: { ...style, x: point.x, y: point.y, zIndex }, layout: layout, onDrag: (event, gesturePoint) => {
738
+ const { velocity } = gesturePoint;
739
+ velocity[axis] &&
740
+ updateOrder(value, point[axis].get(), velocity[axis]);
741
+ onDrag && onDrag(event, gesturePoint);
742
+ }, onLayoutMeasure: (measured) => registerItem(value, measured), ref: externalRef, ignoreStrict: true, children: children }));
743
+ }
744
+ const ReorderItem = /*@__PURE__*/ React.forwardRef(ReorderItemComponent);
745
+
746
+ var namespace = /*#__PURE__*/Object.freeze({
747
+ __proto__: null,
748
+ Group: ReorderGroup,
749
+ Item: ReorderItem
750
+ });
751
+
752
+ const wrap = (min, max, v) => {
753
+ const rangeSize = max - min;
754
+ return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
755
+ };
756
+
757
+ function getEasingForSegment(easing, i) {
758
+ return create.isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
759
+ }
760
+
761
+ function isDOMKeyframes(keyframes) {
762
+ return typeof keyframes === "object" && !Array.isArray(keyframes);
763
+ }
764
+
765
+ function resolveSubjects(subject, keyframes, scope, selectorCache) {
766
+ if (typeof subject === "string" && isDOMKeyframes(keyframes)) {
767
+ return motionDom.resolveElements(subject, scope, selectorCache);
731
768
  }
732
- readValueFromInstance(instance, key) {
733
- if (isObjectKey(key, instance)) {
734
- const value = instance[key];
735
- if (typeof value === "string" || typeof value === "number") {
736
- return value;
737
- }
738
- }
739
- return undefined;
769
+ else if (subject instanceof NodeList) {
770
+ return Array.from(subject);
740
771
  }
741
- getBaseTargetFromProps() {
742
- return undefined;
772
+ else if (Array.isArray(subject)) {
773
+ return subject;
743
774
  }
744
- removeValueFromRenderState(key, renderState) {
745
- delete renderState.output[key];
775
+ else {
776
+ return [subject];
746
777
  }
747
- measureInstanceViewportBox() {
748
- return create.createBox();
778
+ }
779
+
780
+ function calculateRepeatDuration(duration, repeat, _repeatDelay) {
781
+ return duration * (repeat + 1);
782
+ }
783
+
784
+ /**
785
+ * Given a absolute or relative time definition and current/prev time state of the sequence,
786
+ * calculate an absolute time for the next keyframes.
787
+ */
788
+ function calcNextTime(current, next, prev, labels) {
789
+ var _a;
790
+ if (typeof next === "number") {
791
+ return next;
749
792
  }
750
- build(renderState, latestValues) {
751
- Object.assign(renderState.output, latestValues);
793
+ else if (next.startsWith("-") || next.startsWith("+")) {
794
+ return Math.max(0, current + parseFloat(next));
752
795
  }
753
- renderInstance(instance, { output }) {
754
- Object.assign(instance, output);
796
+ else if (next === "<") {
797
+ return prev;
755
798
  }
756
- sortInstanceNodePosition() {
757
- return 0;
799
+ else {
800
+ return (_a = labels.get(next)) !== null && _a !== void 0 ? _a : current;
758
801
  }
759
802
  }
760
803
 
761
- function createDOMVisualElement(element) {
762
- const options = {
763
- presenceContext: null,
764
- props: {},
765
- visualState: {
766
- renderState: {
767
- transform: {},
768
- transformOrigin: {},
769
- style: {},
770
- vars: {},
771
- attrs: {},
772
- },
773
- latestValues: {},
774
- },
775
- };
776
- const node = create.isSVGElement(element)
777
- ? new create.SVGVisualElement(options)
778
- : new create.HTMLVisualElement(options);
779
- node.mount(element);
780
- create.visualElementStore.set(element, node);
781
- }
782
- function createObjectVisualElement(subject) {
783
- const options = {
784
- presenceContext: null,
785
- props: {},
786
- visualState: {
787
- renderState: {
788
- output: {},
789
- },
790
- latestValues: {},
791
- },
792
- };
793
- const node = new ObjectVisualElement(options);
794
- node.mount(subject);
795
- create.visualElementStore.set(subject, node);
796
- }
797
-
798
- function isSingleValue(subject, keyframes) {
799
- return (create.isMotionValue(subject) ||
800
- typeof subject === "number" ||
801
- (typeof subject === "string" && !isDOMKeyframes(keyframes)));
802
- }
803
- /**
804
- * Implementation
805
- */
806
- function animateSubject(subject, keyframes, options, scope) {
807
- const animations = [];
808
- if (isSingleValue(subject, keyframes)) {
809
- animations.push(create.animateSingleValue(subject, isDOMKeyframes(keyframes)
810
- ? keyframes.default || keyframes
811
- : keyframes, options ? options.default || options : options));
812
- }
813
- else {
814
- const subjects = resolveSubjects(subject, keyframes, scope);
815
- const numSubjects = subjects.length;
816
- motionUtils.invariant(Boolean(numSubjects), "No valid elements provided.");
817
- for (let i = 0; i < numSubjects; i++) {
818
- const thisSubject = subjects[i];
819
- const createVisualElement = thisSubject instanceof Element
820
- ? createDOMVisualElement
821
- : createObjectVisualElement;
822
- if (!create.visualElementStore.has(thisSubject)) {
823
- createVisualElement(thisSubject);
824
- }
825
- const visualElement = create.visualElementStore.get(thisSubject);
826
- const transition = { ...options };
827
- /**
828
- * Resolve stagger function if provided.
829
- */
830
- if ("delay" in transition &&
831
- typeof transition.delay === "function") {
832
- transition.delay = transition.delay(i, numSubjects);
833
- }
834
- animations.push(...create.animateTarget(visualElement, { ...keyframes, transition }, {}));
804
+ function eraseKeyframes(sequence, startTime, endTime) {
805
+ for (let i = 0; i < sequence.length; i++) {
806
+ const keyframe = sequence[i];
807
+ if (keyframe.at > startTime && keyframe.at < endTime) {
808
+ motionUtils.removeItem(sequence, keyframe);
809
+ // If we remove this item we have to push the pointer back one
810
+ i--;
835
811
  }
836
812
  }
837
- return animations;
838
- }
839
-
840
- function animateSequence(sequence, options, scope) {
841
- const animations = [];
842
- const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring: create.spring });
843
- animationDefinitions.forEach(({ keyframes, transition }, subject) => {
844
- animations.push(...animateSubject(subject, keyframes, transition));
845
- });
846
- return animations;
847
813
  }
848
-
849
- function isSequence(value) {
850
- return Array.isArray(value) && value.some(Array.isArray);
851
- }
852
- /**
853
- * Creates an animation function that is optionally scoped
854
- * to a specific element.
855
- */
856
- function createScopedAnimate(scope) {
814
+ function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
857
815
  /**
858
- * Implementation
816
+ * Erase every existing value between currentTime and targetTime,
817
+ * this will essentially splice this timeline into any currently
818
+ * defined ones.
859
819
  */
860
- function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options) {
861
- let animations = [];
862
- if (isSequence(subjectOrSequence)) {
863
- animations = animateSequence(subjectOrSequence, optionsOrKeyframes, scope);
864
- }
865
- else {
866
- animations = animateSubject(subjectOrSequence, optionsOrKeyframes, options, scope);
867
- }
868
- const animation = new motionDom.GroupPlaybackControls(animations);
869
- if (scope) {
870
- scope.animations.push(animation);
871
- }
872
- return animation;
820
+ eraseKeyframes(sequence, startTime, endTime);
821
+ for (let i = 0; i < keyframes.length; i++) {
822
+ sequence.push({
823
+ value: keyframes[i],
824
+ at: create.mixNumber(startTime, endTime, offset[i]),
825
+ easing: getEasingForSegment(easing, i),
826
+ });
873
827
  }
874
- return scopedAnimate;
875
- }
876
- const animate = createScopedAnimate();
877
-
878
- function setCSSVar(element, name, value) {
879
- element.style.setProperty(name, value);
880
- }
881
- function setStyle(element, name, value) {
882
- element.style[name] = value;
883
828
  }
884
829
 
885
- const supportsPartialKeyframes = /*@__PURE__*/ motionUtils.memo(() => {
886
- try {
887
- document.createElement("div").animate({ opacity: [1] });
888
- }
889
- catch (e) {
890
- return false;
830
+ /**
831
+ * Take an array of times that represent repeated keyframes. For instance
832
+ * if we have original times of [0, 0.5, 1] then our repeated times will
833
+ * be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
834
+ * down to a 0-1 scale.
835
+ */
836
+ function normalizeTimes(times, repeat) {
837
+ for (let i = 0; i < times.length; i++) {
838
+ times[i] = times[i] / (repeat + 1);
891
839
  }
892
- return true;
893
- });
840
+ }
894
841
 
895
- const state = new WeakMap();
896
- function hydrateKeyframes(valueName, keyframes, read) {
897
- for (let i = 0; i < keyframes.length; i++) {
898
- if (keyframes[i] === null) {
899
- keyframes[i] = i === 0 ? read() : keyframes[i - 1];
900
- }
901
- if (typeof keyframes[i] === "number" &&
902
- create.browserNumberValueTypes[valueName]) {
903
- keyframes[i] = create.browserNumberValueTypes[valueName].transform(keyframes[i]);
904
- }
842
+ function compareByTime(a, b) {
843
+ if (a.at === b.at) {
844
+ if (a.value === null)
845
+ return 1;
846
+ if (b.value === null)
847
+ return -1;
848
+ return 0;
905
849
  }
906
- if (!supportsPartialKeyframes() && keyframes.length < 2) {
907
- keyframes.unshift(read());
850
+ else {
851
+ return a.at - b.at;
908
852
  }
909
853
  }
910
- const defaultEasing = "easeOut";
911
- function getElementAnimationState(element) {
912
- const animationState = state.get(element) || new Map();
913
- state.set(element, animationState);
914
- return state.get(element);
915
- }
916
- class NativeAnimation extends motionDom.NativeAnimationControls {
917
- constructor(element, valueName, valueKeyframes, options) {
918
- const isCSSVar = valueName.startsWith("--");
919
- motionUtils.invariant(typeof options.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "framer-motion"?`);
920
- const existingAnimation = getElementAnimationState(element).get(valueName);
921
- existingAnimation && existingAnimation.stop();
922
- const readInitialKeyframe = () => {
923
- return valueName.startsWith("--")
924
- ? element.style.getPropertyValue(valueName)
925
- : window.getComputedStyle(element)[valueName];
926
- };
927
- if (!Array.isArray(valueKeyframes)) {
928
- valueKeyframes = [valueKeyframes];
929
- }
930
- hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
931
- // TODO: Replace this with toString()?
932
- if (motionDom.isGenerator(options.type)) {
933
- const generatorOptions = motionDom.createGeneratorEasing(options, 100, options.type);
934
- options.ease = motionDom.supportsLinearEasing()
935
- ? generatorOptions.ease
936
- : defaultEasing;
937
- options.duration = motionUtils.secondsToMilliseconds(generatorOptions.duration);
938
- options.type = "keyframes";
939
- }
940
- else {
941
- options.ease = options.ease || defaultEasing;
942
- }
943
- const onFinish = () => {
944
- this.setValue(element, valueName, create.getFinalKeyframe(valueKeyframes, options));
945
- this.cancel();
946
- this.resolveFinishedPromise();
947
- };
948
- const init = () => {
949
- this.setValue = isCSSVar ? setCSSVar : setStyle;
950
- this.options = options;
951
- this.updateFinishedPromise();
952
- this.removeAnimation = () => {
953
- const elementState = state.get(element);
954
- elementState && elementState.delete(valueName);
955
- };
956
- };
957
- if (!create.supportsWaapi()) {
958
- super();
959
- init();
960
- onFinish();
961
- }
962
- else {
963
- super(create.startWaapiAnimation(element, valueName, valueKeyframes, options));
964
- init();
965
- if (options.autoplay === false) {
966
- this.animation.pause();
967
- }
968
- this.animation.onfinish = onFinish;
969
- getElementAnimationState(element).set(valueName, this);
970
- }
971
- }
854
+
855
+ const defaultSegmentEasing = "easeInOut";
856
+ const MAX_REPEAT = 20;
857
+ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
858
+ const defaultDuration = defaultTransition.duration || 0.3;
859
+ const animationDefinitions = new Map();
860
+ const sequences = new Map();
861
+ const elementCache = {};
862
+ const timeLabels = new Map();
863
+ let prevTime = 0;
864
+ let currentTime = 0;
865
+ let totalDuration = 0;
972
866
  /**
973
- * Allows the returned animation to be awaited or promise-chained. Currently
974
- * resolves when the animation finishes at all but in a future update could/should
975
- * reject if its cancels.
867
+ * Build the timeline by mapping over the sequence array and converting
868
+ * the definitions into keyframes and offsets with absolute time values.
869
+ * These will later get converted into relative offsets in a second pass.
976
870
  */
977
- then(resolve, reject) {
978
- return this.currentFinishedPromise.then(resolve, reject);
979
- }
980
- updateFinishedPromise() {
981
- this.currentFinishedPromise = new Promise((resolve) => {
982
- this.resolveFinishedPromise = resolve;
983
- });
984
- }
985
- play() {
986
- if (this.state === "finished") {
987
- this.updateFinishedPromise();
871
+ for (let i = 0; i < sequence.length; i++) {
872
+ const segment = sequence[i];
873
+ /**
874
+ * If this is a timeline label, mark it and skip the rest of this iteration.
875
+ */
876
+ if (typeof segment === "string") {
877
+ timeLabels.set(segment, currentTime);
878
+ continue;
988
879
  }
989
- super.play();
990
- }
991
- cancel() {
992
- this.removeAnimation();
993
- super.cancel();
994
- }
995
- }
996
-
997
- function animateElements(elementOrSelector, keyframes, options, scope) {
998
- const elements = motionDom.resolveElements(elementOrSelector, scope);
999
- const numElements = elements.length;
1000
- motionUtils.invariant(Boolean(numElements), "No valid element provided.");
1001
- const animations = [];
1002
- for (let i = 0; i < numElements; i++) {
1003
- const element = elements[i];
1004
- const elementTransition = { ...options };
880
+ else if (!Array.isArray(segment)) {
881
+ timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
882
+ continue;
883
+ }
884
+ let [subject, keyframes, transition = {}] = segment;
1005
885
  /**
1006
- * Resolve stagger function if provided.
886
+ * If a relative or absolute time value has been specified we need to resolve
887
+ * it in relation to the currentTime.
1007
888
  */
1008
- if (typeof elementTransition.delay === "function") {
1009
- elementTransition.delay = elementTransition.delay(i, numElements);
1010
- }
1011
- for (const valueName in keyframes) {
1012
- const valueKeyframes = keyframes[valueName];
1013
- const valueOptions = {
1014
- ...motionDom.getValueTransition(elementTransition, valueName),
1015
- };
1016
- valueOptions.duration = valueOptions.duration
1017
- ? motionUtils.secondsToMilliseconds(valueOptions.duration)
1018
- : valueOptions.duration;
1019
- valueOptions.delay = motionUtils.secondsToMilliseconds(valueOptions.delay || 0);
1020
- valueOptions.allowFlatten =
1021
- !elementTransition.type && !elementTransition.ease;
1022
- animations.push(new NativeAnimation(element, valueName, valueKeyframes, valueOptions));
1023
- }
1024
- }
1025
- return animations;
1026
- }
1027
-
1028
- const createScopedWaapiAnimate = (scope) => {
1029
- function scopedAnimate(elementOrSelector, keyframes, options) {
1030
- return new motionDom.GroupPlaybackControls(animateElements(elementOrSelector, keyframes, options, scope));
1031
- }
1032
- return scopedAnimate;
1033
- };
1034
- const animateMini = /*@__PURE__*/ createScopedWaapiAnimate();
1035
-
1036
- function observeTimeline(update, timeline) {
1037
- let prevProgress;
1038
- const onFrame = () => {
1039
- const { currentTime } = timeline;
1040
- const percentage = currentTime === null ? 0 : currentTime.value;
1041
- const progress = percentage / 100;
1042
- if (prevProgress !== progress) {
1043
- update(progress);
1044
- }
1045
- prevProgress = progress;
1046
- };
1047
- create.frame.update(onFrame, true);
1048
- return () => create.cancelFrame(onFrame);
1049
- }
1050
-
1051
- const resizeHandlers = new WeakMap();
1052
- let observer;
1053
- function getElementSize(target, borderBoxSize) {
1054
- if (borderBoxSize) {
1055
- const { inlineSize, blockSize } = borderBoxSize[0];
1056
- return { width: inlineSize, height: blockSize };
1057
- }
1058
- else if (target instanceof SVGElement && "getBBox" in target) {
1059
- return target.getBBox();
1060
- }
1061
- else {
1062
- return {
1063
- width: target.offsetWidth,
1064
- height: target.offsetHeight,
1065
- };
1066
- }
1067
- }
1068
- function notifyTarget({ target, contentRect, borderBoxSize, }) {
1069
- var _a;
1070
- (_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
1071
- handler({
1072
- target,
1073
- contentSize: contentRect,
1074
- get size() {
1075
- return getElementSize(target, borderBoxSize);
1076
- },
1077
- });
1078
- });
1079
- }
1080
- function notifyAll(entries) {
1081
- entries.forEach(notifyTarget);
1082
- }
1083
- function createResizeObserver() {
1084
- if (typeof ResizeObserver === "undefined")
1085
- return;
1086
- observer = new ResizeObserver(notifyAll);
1087
- }
1088
- function resizeElement(target, handler) {
1089
- if (!observer)
1090
- createResizeObserver();
1091
- const elements = motionDom.resolveElements(target);
1092
- elements.forEach((element) => {
1093
- let elementHandlers = resizeHandlers.get(element);
1094
- if (!elementHandlers) {
1095
- elementHandlers = new Set();
1096
- resizeHandlers.set(element, elementHandlers);
889
+ if (transition.at !== undefined) {
890
+ currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
1097
891
  }
1098
- elementHandlers.add(handler);
1099
- observer === null || observer === void 0 ? void 0 : observer.observe(element);
1100
- });
1101
- return () => {
1102
- elements.forEach((element) => {
1103
- const elementHandlers = resizeHandlers.get(element);
1104
- elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
1105
- if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
1106
- observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
892
+ /**
893
+ * Keep track of the maximum duration in this definition. This will be
894
+ * applied to currentTime once the definition has been parsed.
895
+ */
896
+ let maxDuration = 0;
897
+ const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
898
+ const valueKeyframesAsList = keyframesAsList(valueKeyframes);
899
+ const { delay = 0, times = create.defaultOffset(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
900
+ let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
901
+ /**
902
+ * Resolve stagger() if defined.
903
+ */
904
+ const calculatedDelay = typeof delay === "function"
905
+ ? delay(elementIndex, numSubjects)
906
+ : delay;
907
+ /**
908
+ * If this animation should and can use a spring, generate a spring easing function.
909
+ */
910
+ const numKeyframes = valueKeyframesAsList.length;
911
+ const createGenerator = motionDom.isGenerator(type)
912
+ ? type
913
+ : generators === null || generators === void 0 ? void 0 : generators[type];
914
+ if (numKeyframes <= 2 && createGenerator) {
915
+ /**
916
+ * As we're creating an easing function from a spring,
917
+ * ideally we want to generate it using the real distance
918
+ * between the two keyframes. However this isn't always
919
+ * possible - in these situations we use 0-100.
920
+ */
921
+ let absoluteDelta = 100;
922
+ if (numKeyframes === 2 &&
923
+ isNumberKeyframesArray(valueKeyframesAsList)) {
924
+ const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
925
+ absoluteDelta = Math.abs(delta);
926
+ }
927
+ const springTransition = { ...remainingTransition };
928
+ if (duration !== undefined) {
929
+ springTransition.duration = motionUtils.secondsToMilliseconds(duration);
930
+ }
931
+ const springEasing = motionDom.createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
932
+ ease = springEasing.ease;
933
+ duration = springEasing.duration;
1107
934
  }
1108
- });
1109
- };
1110
- }
1111
-
1112
- const windowCallbacks = new Set();
1113
- let windowResizeHandler;
1114
- function createWindowResizeHandler() {
1115
- windowResizeHandler = () => {
1116
- const size = {
1117
- width: window.innerWidth,
1118
- height: window.innerHeight,
1119
- };
1120
- const info = {
1121
- target: window,
1122
- size,
1123
- contentSize: size,
1124
- };
1125
- windowCallbacks.forEach((callback) => callback(info));
1126
- };
1127
- window.addEventListener("resize", windowResizeHandler);
1128
- }
1129
- function resizeWindow(callback) {
1130
- windowCallbacks.add(callback);
1131
- if (!windowResizeHandler)
1132
- createWindowResizeHandler();
1133
- return () => {
1134
- windowCallbacks.delete(callback);
1135
- if (!windowCallbacks.size && windowResizeHandler) {
1136
- windowResizeHandler = undefined;
1137
- }
1138
- };
1139
- }
1140
-
1141
- function resize(a, b) {
1142
- return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
1143
- }
1144
-
1145
- /**
1146
- * A time in milliseconds, beyond which we consider the scroll velocity to be 0.
1147
- */
1148
- const maxElapsed = 50;
1149
- const createAxisInfo = () => ({
1150
- current: 0,
1151
- offset: [],
1152
- progress: 0,
1153
- scrollLength: 0,
1154
- targetOffset: 0,
1155
- targetLength: 0,
1156
- containerLength: 0,
1157
- velocity: 0,
1158
- });
1159
- const createScrollInfo = () => ({
1160
- time: 0,
1161
- x: createAxisInfo(),
1162
- y: createAxisInfo(),
1163
- });
1164
- const keys = {
1165
- x: {
1166
- length: "Width",
1167
- position: "Left",
1168
- },
1169
- y: {
1170
- length: "Height",
1171
- position: "Top",
1172
- },
1173
- };
1174
- function updateAxisInfo(element, axisName, info, time) {
1175
- const axis = info[axisName];
1176
- const { length, position } = keys[axisName];
1177
- const prev = axis.current;
1178
- const prevTime = info.time;
1179
- axis.current = element[`scroll${position}`];
1180
- axis.scrollLength = element[`scroll${length}`] - element[`client${length}`];
1181
- axis.offset.length = 0;
1182
- axis.offset[0] = 0;
1183
- axis.offset[1] = axis.scrollLength;
1184
- axis.progress = motionUtils.progress(0, axis.scrollLength, axis.current);
1185
- const elapsed = time - prevTime;
1186
- axis.velocity =
1187
- elapsed > maxElapsed
1188
- ? 0
1189
- : create.velocityPerSecond(axis.current - prev, elapsed);
1190
- }
1191
- function updateScrollInfo(element, info, time) {
1192
- updateAxisInfo(element, "x", info, time);
1193
- updateAxisInfo(element, "y", info, time);
1194
- info.time = time;
1195
- }
1196
-
1197
- function calcInset(element, container) {
1198
- const inset = { x: 0, y: 0 };
1199
- let current = element;
1200
- while (current && current !== container) {
1201
- if (current instanceof HTMLElement) {
1202
- inset.x += current.offsetLeft;
1203
- inset.y += current.offsetTop;
1204
- current = current.offsetParent;
1205
- }
1206
- else if (current.tagName === "svg") {
935
+ duration !== null && duration !== void 0 ? duration : (duration = defaultDuration);
936
+ const startTime = currentTime + calculatedDelay;
1207
937
  /**
1208
- * This isn't an ideal approach to measuring the offset of <svg /> tags.
1209
- * It would be preferable, given they behave like HTMLElements in most ways
1210
- * to use offsetLeft/Top. But these don't exist on <svg />. Likewise we
1211
- * can't use .getBBox() like most SVG elements as these provide the offset
1212
- * relative to the SVG itself, which for <svg /> is usually 0x0.
938
+ * If there's only one time offset of 0, fill in a second with length 1
1213
939
  */
1214
- const svgBoundingBox = current.getBoundingClientRect();
1215
- current = current.parentElement;
1216
- const parentBoundingBox = current.getBoundingClientRect();
1217
- inset.x += svgBoundingBox.left - parentBoundingBox.left;
1218
- inset.y += svgBoundingBox.top - parentBoundingBox.top;
1219
- }
1220
- else if (current instanceof SVGGraphicsElement) {
1221
- const { x, y } = current.getBBox();
1222
- inset.x += x;
1223
- inset.y += y;
1224
- let svg = null;
1225
- let parent = current.parentNode;
1226
- while (!svg) {
1227
- if (parent.tagName === "svg") {
1228
- svg = parent;
940
+ if (times.length === 1 && times[0] === 0) {
941
+ times[1] = 1;
942
+ }
943
+ /**
944
+ * Fill out if offset if fewer offsets than keyframes
945
+ */
946
+ const remainder = times.length - valueKeyframesAsList.length;
947
+ remainder > 0 && create.fillOffset(times, remainder);
948
+ /**
949
+ * If only one value has been set, ie [1], push a null to the start of
950
+ * the keyframe array. This will let us mark a keyframe at this point
951
+ * that will later be hydrated with the previous value.
952
+ */
953
+ valueKeyframesAsList.length === 1 &&
954
+ valueKeyframesAsList.unshift(null);
955
+ /**
956
+ * Handle repeat options
957
+ */
958
+ if (repeat) {
959
+ motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
960
+ duration = calculateRepeatDuration(duration, repeat);
961
+ const originalKeyframes = [...valueKeyframesAsList];
962
+ const originalTimes = [...times];
963
+ ease = Array.isArray(ease) ? [...ease] : [ease];
964
+ const originalEase = [...ease];
965
+ for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
966
+ valueKeyframesAsList.push(...originalKeyframes);
967
+ for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
968
+ times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
969
+ ease.push(keyframeIndex === 0
970
+ ? "linear"
971
+ : getEasingForSegment(originalEase, keyframeIndex - 1));
972
+ }
1229
973
  }
1230
- parent = current.parentNode;
974
+ normalizeTimes(times, repeat);
1231
975
  }
1232
- current = svg;
976
+ const targetTime = startTime + duration;
977
+ /**
978
+ * Add keyframes, mapping offsets to absolute time.
979
+ */
980
+ addKeyframes(valueSequence, valueKeyframesAsList, ease, times, startTime, targetTime);
981
+ maxDuration = Math.max(calculatedDelay + duration, maxDuration);
982
+ totalDuration = Math.max(targetTime, totalDuration);
983
+ };
984
+ if (create.isMotionValue(subject)) {
985
+ const subjectSequence = getSubjectSequence(subject, sequences);
986
+ resolveValueSequence(keyframes, transition, getValueSequence("default", subjectSequence));
1233
987
  }
1234
988
  else {
1235
- break;
989
+ const subjects = resolveSubjects(subject, keyframes, scope, elementCache);
990
+ const numSubjects = subjects.length;
991
+ /**
992
+ * For every element in this segment, process the defined values.
993
+ */
994
+ for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
995
+ /**
996
+ * Cast necessary, but we know these are of this type
997
+ */
998
+ keyframes = keyframes;
999
+ transition = transition;
1000
+ const thisSubject = subjects[subjectIndex];
1001
+ const subjectSequence = getSubjectSequence(thisSubject, sequences);
1002
+ for (const key in keyframes) {
1003
+ resolveValueSequence(keyframes[key], getValueTransition(transition, key), getValueSequence(key, subjectSequence), subjectIndex, numSubjects);
1004
+ }
1005
+ }
1236
1006
  }
1237
- }
1238
- return inset;
1239
- }
1240
-
1241
- const namedEdges = {
1242
- start: 0,
1243
- center: 0.5,
1244
- end: 1,
1245
- };
1246
- function resolveEdge(edge, length, inset = 0) {
1247
- let delta = 0;
1248
- /**
1249
- * If we have this edge defined as a preset, replace the definition
1250
- * with the numerical value.
1251
- */
1252
- if (edge in namedEdges) {
1253
- edge = namedEdges[edge];
1007
+ prevTime = currentTime;
1008
+ currentTime += maxDuration;
1254
1009
  }
1255
1010
  /**
1256
- * Handle unit values
1011
+ * For every element and value combination create a new animation.
1257
1012
  */
1258
- if (typeof edge === "string") {
1259
- const asNumber = parseFloat(edge);
1260
- if (edge.endsWith("px")) {
1261
- delta = asNumber;
1262
- }
1263
- else if (edge.endsWith("%")) {
1264
- edge = asNumber / 100;
1265
- }
1266
- else if (edge.endsWith("vw")) {
1267
- delta = (asNumber / 100) * document.documentElement.clientWidth;
1013
+ sequences.forEach((valueSequences, element) => {
1014
+ for (const key in valueSequences) {
1015
+ const valueSequence = valueSequences[key];
1016
+ /**
1017
+ * Arrange all the keyframes in ascending time order.
1018
+ */
1019
+ valueSequence.sort(compareByTime);
1020
+ const keyframes = [];
1021
+ const valueOffset = [];
1022
+ const valueEasing = [];
1023
+ /**
1024
+ * For each keyframe, translate absolute times into
1025
+ * relative offsets based on the total duration of the timeline.
1026
+ */
1027
+ for (let i = 0; i < valueSequence.length; i++) {
1028
+ const { at, value, easing } = valueSequence[i];
1029
+ keyframes.push(value);
1030
+ valueOffset.push(motionUtils.progress(0, totalDuration, at));
1031
+ valueEasing.push(easing || "easeOut");
1032
+ }
1033
+ /**
1034
+ * If the first keyframe doesn't land on offset: 0
1035
+ * provide one by duplicating the initial keyframe. This ensures
1036
+ * it snaps to the first keyframe when the animation starts.
1037
+ */
1038
+ if (valueOffset[0] !== 0) {
1039
+ valueOffset.unshift(0);
1040
+ keyframes.unshift(keyframes[0]);
1041
+ valueEasing.unshift(defaultSegmentEasing);
1042
+ }
1043
+ /**
1044
+ * If the last keyframe doesn't land on offset: 1
1045
+ * provide one with a null wildcard value. This will ensure it
1046
+ * stays static until the end of the animation.
1047
+ */
1048
+ if (valueOffset[valueOffset.length - 1] !== 1) {
1049
+ valueOffset.push(1);
1050
+ keyframes.push(null);
1051
+ }
1052
+ if (!animationDefinitions.has(element)) {
1053
+ animationDefinitions.set(element, {
1054
+ keyframes: {},
1055
+ transition: {},
1056
+ });
1057
+ }
1058
+ const definition = animationDefinitions.get(element);
1059
+ definition.keyframes[key] = keyframes;
1060
+ definition.transition[key] = {
1061
+ ...defaultTransition,
1062
+ duration: totalDuration,
1063
+ ease: valueEasing,
1064
+ times: valueOffset,
1065
+ ...sequenceTransition,
1066
+ };
1268
1067
  }
1269
- else if (edge.endsWith("vh")) {
1270
- delta = (asNumber / 100) * document.documentElement.clientHeight;
1068
+ });
1069
+ return animationDefinitions;
1070
+ }
1071
+ function getSubjectSequence(subject, sequences) {
1072
+ !sequences.has(subject) && sequences.set(subject, {});
1073
+ return sequences.get(subject);
1074
+ }
1075
+ function getValueSequence(name, sequences) {
1076
+ if (!sequences[name])
1077
+ sequences[name] = [];
1078
+ return sequences[name];
1079
+ }
1080
+ function keyframesAsList(keyframes) {
1081
+ return Array.isArray(keyframes) ? keyframes : [keyframes];
1082
+ }
1083
+ function getValueTransition(transition, key) {
1084
+ return transition && transition[key]
1085
+ ? {
1086
+ ...transition,
1087
+ ...transition[key],
1271
1088
  }
1272
- else {
1273
- edge = asNumber;
1089
+ : { ...transition };
1090
+ }
1091
+ const isNumber = (keyframe) => typeof keyframe === "number";
1092
+ const isNumberKeyframesArray = (keyframes) => keyframes.every(isNumber);
1093
+
1094
+ function isObjectKey(key, object) {
1095
+ return key in object;
1096
+ }
1097
+ class ObjectVisualElement extends create.VisualElement {
1098
+ constructor() {
1099
+ super(...arguments);
1100
+ this.type = "object";
1101
+ }
1102
+ readValueFromInstance(instance, key) {
1103
+ if (isObjectKey(key, instance)) {
1104
+ const value = instance[key];
1105
+ if (typeof value === "string" || typeof value === "number") {
1106
+ return value;
1107
+ }
1274
1108
  }
1109
+ return undefined;
1275
1110
  }
1276
- /**
1277
- * If the edge is defined as a number, handle as a progress value.
1278
- */
1279
- if (typeof edge === "number") {
1280
- delta = length * edge;
1111
+ getBaseTargetFromProps() {
1112
+ return undefined;
1113
+ }
1114
+ removeValueFromRenderState(key, renderState) {
1115
+ delete renderState.output[key];
1116
+ }
1117
+ measureInstanceViewportBox() {
1118
+ return create.createBox();
1119
+ }
1120
+ build(renderState, latestValues) {
1121
+ Object.assign(renderState.output, latestValues);
1122
+ }
1123
+ renderInstance(instance, { output }) {
1124
+ Object.assign(instance, output);
1125
+ }
1126
+ sortInstanceNodePosition() {
1127
+ return 0;
1281
1128
  }
1282
- return inset + delta;
1283
1129
  }
1284
1130
 
1285
- const defaultOffset = [0, 0];
1286
- function resolveOffset(offset, containerLength, targetLength, targetInset) {
1287
- let offsetDefinition = Array.isArray(offset) ? offset : defaultOffset;
1288
- let targetPoint = 0;
1289
- let containerPoint = 0;
1290
- if (typeof offset === "number") {
1291
- /**
1292
- * If we're provided offset: [0, 0.5, 1] then each number x should become
1293
- * [x, x], so we default to the behaviour of mapping 0 => 0 of both target
1294
- * and container etc.
1295
- */
1296
- offsetDefinition = [offset, offset];
1131
+ function createDOMVisualElement(element) {
1132
+ const options = {
1133
+ presenceContext: null,
1134
+ props: {},
1135
+ visualState: {
1136
+ renderState: {
1137
+ transform: {},
1138
+ transformOrigin: {},
1139
+ style: {},
1140
+ vars: {},
1141
+ attrs: {},
1142
+ },
1143
+ latestValues: {},
1144
+ },
1145
+ };
1146
+ const node = create.isSVGElement(element)
1147
+ ? new create.SVGVisualElement(options)
1148
+ : new create.HTMLVisualElement(options);
1149
+ node.mount(element);
1150
+ create.visualElementStore.set(element, node);
1151
+ }
1152
+ function createObjectVisualElement(subject) {
1153
+ const options = {
1154
+ presenceContext: null,
1155
+ props: {},
1156
+ visualState: {
1157
+ renderState: {
1158
+ output: {},
1159
+ },
1160
+ latestValues: {},
1161
+ },
1162
+ };
1163
+ const node = new ObjectVisualElement(options);
1164
+ node.mount(subject);
1165
+ create.visualElementStore.set(subject, node);
1166
+ }
1167
+
1168
+ function isSingleValue(subject, keyframes) {
1169
+ return (create.isMotionValue(subject) ||
1170
+ typeof subject === "number" ||
1171
+ (typeof subject === "string" && !isDOMKeyframes(keyframes)));
1172
+ }
1173
+ /**
1174
+ * Implementation
1175
+ */
1176
+ function animateSubject(subject, keyframes, options, scope) {
1177
+ const animations = [];
1178
+ if (isSingleValue(subject, keyframes)) {
1179
+ animations.push(create.animateSingleValue(subject, isDOMKeyframes(keyframes)
1180
+ ? keyframes.default || keyframes
1181
+ : keyframes, options ? options.default || options : options));
1297
1182
  }
1298
- else if (typeof offset === "string") {
1299
- offset = offset.trim();
1300
- if (offset.includes(" ")) {
1301
- offsetDefinition = offset.split(" ");
1302
- }
1303
- else {
1183
+ else {
1184
+ const subjects = resolveSubjects(subject, keyframes, scope);
1185
+ const numSubjects = subjects.length;
1186
+ motionUtils.invariant(Boolean(numSubjects), "No valid elements provided.");
1187
+ for (let i = 0; i < numSubjects; i++) {
1188
+ const thisSubject = subjects[i];
1189
+ const createVisualElement = thisSubject instanceof Element
1190
+ ? createDOMVisualElement
1191
+ : createObjectVisualElement;
1192
+ if (!create.visualElementStore.has(thisSubject)) {
1193
+ createVisualElement(thisSubject);
1194
+ }
1195
+ const visualElement = create.visualElementStore.get(thisSubject);
1196
+ const transition = { ...options };
1304
1197
  /**
1305
- * If we're provided a definition like "100px" then we want to apply
1306
- * that only to the top of the target point, leaving the container at 0.
1307
- * Whereas a named offset like "end" should be applied to both.
1198
+ * Resolve stagger function if provided.
1308
1199
  */
1309
- offsetDefinition = [offset, namedEdges[offset] ? offset : `0`];
1200
+ if ("delay" in transition &&
1201
+ typeof transition.delay === "function") {
1202
+ transition.delay = transition.delay(i, numSubjects);
1203
+ }
1204
+ animations.push(...create.animateTarget(visualElement, { ...keyframes, transition }, {}));
1310
1205
  }
1311
1206
  }
1312
- targetPoint = resolveEdge(offsetDefinition[0], targetLength, targetInset);
1313
- containerPoint = resolveEdge(offsetDefinition[1], containerLength);
1314
- return targetPoint - containerPoint;
1207
+ return animations;
1315
1208
  }
1316
1209
 
1317
- const ScrollOffset = {
1318
- Enter: [
1319
- [0, 1],
1320
- [1, 1],
1321
- ],
1322
- Exit: [
1323
- [0, 0],
1324
- [1, 0],
1325
- ],
1326
- Any: [
1327
- [1, 0],
1328
- [0, 1],
1329
- ],
1330
- All: [
1331
- [0, 0],
1332
- [1, 1],
1333
- ],
1334
- };
1210
+ function animateSequence(sequence, options, scope) {
1211
+ const animations = [];
1212
+ const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring: create.spring });
1213
+ animationDefinitions.forEach(({ keyframes, transition }, subject) => {
1214
+ animations.push(...animateSubject(subject, keyframes, transition));
1215
+ });
1216
+ return animations;
1217
+ }
1335
1218
 
1336
- const point = { x: 0, y: 0 };
1337
- function getTargetSize(target) {
1338
- return "getBBox" in target && target.tagName !== "svg"
1339
- ? target.getBBox()
1340
- : { width: target.clientWidth, height: target.clientHeight };
1219
+ function isSequence(value) {
1220
+ return Array.isArray(value) && value.some(Array.isArray);
1341
1221
  }
1342
- function resolveOffsets(container, info, options) {
1343
- const { offset: offsetDefinition = ScrollOffset.All } = options;
1344
- const { target = container, axis = "y" } = options;
1345
- const lengthLabel = axis === "y" ? "height" : "width";
1346
- const inset = target !== container ? calcInset(target, container) : point;
1347
- /**
1348
- * Measure the target and container. If they're the same thing then we
1349
- * use the container's scrollWidth/Height as the target, from there
1350
- * all other calculations can remain the same.
1351
- */
1352
- const targetSize = target === container
1353
- ? { width: container.scrollWidth, height: container.scrollHeight }
1354
- : getTargetSize(target);
1355
- const containerSize = {
1356
- width: container.clientWidth,
1357
- height: container.clientHeight,
1358
- };
1359
- /**
1360
- * Reset the length of the resolved offset array rather than creating a new one.
1361
- * TODO: More reusable data structures for targetSize/containerSize would also be good.
1362
- */
1363
- info[axis].offset.length = 0;
1222
+ /**
1223
+ * Creates an animation function that is optionally scoped
1224
+ * to a specific element.
1225
+ */
1226
+ function createScopedAnimate(scope) {
1364
1227
  /**
1365
- * Populate the offset array by resolving the user's offset definition into
1366
- * a list of pixel scroll offets.
1228
+ * Implementation
1367
1229
  */
1368
- let hasChanged = !info[axis].interpolate;
1369
- const numOffsets = offsetDefinition.length;
1370
- for (let i = 0; i < numOffsets; i++) {
1371
- const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
1372
- if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
1373
- hasChanged = true;
1230
+ function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options) {
1231
+ let animations = [];
1232
+ if (isSequence(subjectOrSequence)) {
1233
+ animations = animateSequence(subjectOrSequence, optionsOrKeyframes, scope);
1374
1234
  }
1375
- info[axis].offset[i] = offset;
1235
+ else {
1236
+ animations = animateSubject(subjectOrSequence, optionsOrKeyframes, options, scope);
1237
+ }
1238
+ const animation = new motionDom.GroupPlaybackControls(animations);
1239
+ if (scope) {
1240
+ scope.animations.push(animation);
1241
+ }
1242
+ return animation;
1376
1243
  }
1377
- /**
1378
- * If the pixel scroll offsets have changed, create a new interpolator function
1379
- * to map scroll value into a progress.
1380
- */
1381
- if (hasChanged) {
1382
- info[axis].interpolate = create.interpolate(info[axis].offset, create.defaultOffset(offsetDefinition), { clamp: false });
1383
- info[axis].interpolatorOffsets = [...info[axis].offset];
1244
+ return scopedAnimate;
1245
+ }
1246
+ const animate = createScopedAnimate();
1247
+
1248
+ function setCSSVar(element, name, value) {
1249
+ element.style.setProperty(name, value);
1250
+ }
1251
+ function setStyle(element, name, value) {
1252
+ element.style[name] = value;
1253
+ }
1254
+
1255
+ const supportsPartialKeyframes = /*@__PURE__*/ motionUtils.memo(() => {
1256
+ try {
1257
+ document.createElement("div").animate({ opacity: [1] });
1384
1258
  }
1385
- info[axis].progress = create.clamp(0, 1, info[axis].interpolate(info[axis].current));
1386
- }
1259
+ catch (e) {
1260
+ return false;
1261
+ }
1262
+ return true;
1263
+ });
1387
1264
 
1388
- function measure(container, target = container, info) {
1389
- /**
1390
- * Find inset of target within scrollable container
1391
- */
1392
- info.x.targetOffset = 0;
1393
- info.y.targetOffset = 0;
1394
- if (target !== container) {
1395
- let node = target;
1396
- while (node && node !== container) {
1397
- info.x.targetOffset += node.offsetLeft;
1398
- info.y.targetOffset += node.offsetTop;
1399
- node = node.offsetParent;
1265
+ const state = new WeakMap();
1266
+ function hydrateKeyframes(valueName, keyframes, read) {
1267
+ for (let i = 0; i < keyframes.length; i++) {
1268
+ if (keyframes[i] === null) {
1269
+ keyframes[i] = i === 0 ? read() : keyframes[i - 1];
1400
1270
  }
1401
- }
1402
- info.x.targetLength =
1403
- target === container ? target.scrollWidth : target.clientWidth;
1404
- info.y.targetLength =
1405
- target === container ? target.scrollHeight : target.clientHeight;
1406
- info.x.containerLength = container.clientWidth;
1407
- info.y.containerLength = container.clientHeight;
1408
- /**
1409
- * In development mode ensure scroll containers aren't position: static as this makes
1410
- * it difficult to measure their relative positions.
1411
- */
1412
- if (process.env.NODE_ENV !== "production") {
1413
- if (container && target && target !== container) {
1414
- create.warnOnce(getComputedStyle(container).position !== "static", "Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly.");
1271
+ if (typeof keyframes[i] === "number" &&
1272
+ create.browserNumberValueTypes[valueName]) {
1273
+ keyframes[i] = create.browserNumberValueTypes[valueName].transform(keyframes[i]);
1415
1274
  }
1416
1275
  }
1276
+ if (!supportsPartialKeyframes() && keyframes.length < 2) {
1277
+ keyframes.unshift(read());
1278
+ }
1417
1279
  }
1418
- function createOnScrollHandler(element, onScroll, info, options = {}) {
1419
- return {
1420
- measure: () => measure(element, options.target, info),
1421
- update: (time) => {
1422
- updateScrollInfo(element, info, time);
1423
- if (options.offset || options.target) {
1424
- resolveOffsets(element, info, options);
1425
- }
1426
- },
1427
- notify: () => onScroll(info),
1428
- };
1280
+ const defaultEasing = "easeOut";
1281
+ function getElementAnimationState(element) {
1282
+ const animationState = state.get(element) || new Map();
1283
+ state.set(element, animationState);
1284
+ return state.get(element);
1429
1285
  }
1430
-
1431
- const scrollListeners = new WeakMap();
1432
- const resizeListeners = new WeakMap();
1433
- const onScrollHandlers = new WeakMap();
1434
- const getEventTarget = (element) => element === document.documentElement ? window : element;
1435
- function scrollInfo(onScroll, { container = document.documentElement, ...options } = {}) {
1436
- let containerHandlers = onScrollHandlers.get(container);
1437
- /**
1438
- * Get the onScroll handlers for this container.
1439
- * If one isn't found, create a new one.
1440
- */
1441
- if (!containerHandlers) {
1442
- containerHandlers = new Set();
1443
- onScrollHandlers.set(container, containerHandlers);
1444
- }
1445
- /**
1446
- * Create a new onScroll handler for the provided callback.
1447
- */
1448
- const info = createScrollInfo();
1449
- const containerHandler = createOnScrollHandler(container, onScroll, info, options);
1450
- containerHandlers.add(containerHandler);
1451
- /**
1452
- * Check if there's a scroll event listener for this container.
1453
- * If not, create one.
1454
- */
1455
- if (!scrollListeners.has(container)) {
1456
- const measureAll = () => {
1457
- for (const handler of containerHandlers)
1458
- handler.measure();
1459
- };
1460
- const updateAll = () => {
1461
- for (const handler of containerHandlers) {
1462
- handler.update(create.frameData.timestamp);
1463
- }
1286
+ class NativeAnimation extends motionDom.NativeAnimationControls {
1287
+ constructor(element, valueName, valueKeyframes, options) {
1288
+ const isCSSVar = valueName.startsWith("--");
1289
+ motionUtils.invariant(typeof options.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "framer-motion"?`);
1290
+ const existingAnimation = getElementAnimationState(element).get(valueName);
1291
+ existingAnimation && existingAnimation.stop();
1292
+ const readInitialKeyframe = () => {
1293
+ return valueName.startsWith("--")
1294
+ ? element.style.getPropertyValue(valueName)
1295
+ : window.getComputedStyle(element)[valueName];
1464
1296
  };
1465
- const notifyAll = () => {
1466
- for (const handler of containerHandlers)
1467
- handler.notify();
1297
+ if (!Array.isArray(valueKeyframes)) {
1298
+ valueKeyframes = [valueKeyframes];
1299
+ }
1300
+ hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
1301
+ // TODO: Replace this with toString()?
1302
+ if (motionDom.isGenerator(options.type)) {
1303
+ const generatorOptions = motionDom.createGeneratorEasing(options, 100, options.type);
1304
+ options.ease = motionDom.supportsLinearEasing()
1305
+ ? generatorOptions.ease
1306
+ : defaultEasing;
1307
+ options.duration = motionUtils.secondsToMilliseconds(generatorOptions.duration);
1308
+ options.type = "keyframes";
1309
+ }
1310
+ else {
1311
+ options.ease = options.ease || defaultEasing;
1312
+ }
1313
+ const onFinish = () => {
1314
+ this.setValue(element, valueName, create.getFinalKeyframe(valueKeyframes, options));
1315
+ this.cancel();
1316
+ this.resolveFinishedPromise();
1468
1317
  };
1469
- const listener = () => {
1470
- create.frame.read(measureAll, false, true);
1471
- create.frame.read(updateAll, false, true);
1472
- create.frame.update(notifyAll, false, true);
1318
+ const init = () => {
1319
+ this.setValue = isCSSVar ? setCSSVar : setStyle;
1320
+ this.options = options;
1321
+ this.updateFinishedPromise();
1322
+ this.removeAnimation = () => {
1323
+ const elementState = state.get(element);
1324
+ elementState && elementState.delete(valueName);
1325
+ };
1473
1326
  };
1474
- scrollListeners.set(container, listener);
1475
- const target = getEventTarget(container);
1476
- window.addEventListener("resize", listener, { passive: true });
1477
- if (container !== document.documentElement) {
1478
- resizeListeners.set(container, resize(container, listener));
1327
+ if (!create.supportsWaapi()) {
1328
+ super();
1329
+ init();
1330
+ onFinish();
1331
+ }
1332
+ else {
1333
+ super(create.startWaapiAnimation(element, valueName, valueKeyframes, options));
1334
+ init();
1335
+ if (options.autoplay === false) {
1336
+ this.animation.pause();
1337
+ }
1338
+ this.animation.onfinish = onFinish;
1339
+ getElementAnimationState(element).set(valueName, this);
1479
1340
  }
1480
- target.addEventListener("scroll", listener, { passive: true });
1481
1341
  }
1482
- const listener = scrollListeners.get(container);
1483
- create.frame.read(listener, false, true);
1484
- return () => {
1485
- var _a;
1486
- create.cancelFrame(listener);
1487
- /**
1488
- * Check if we even have any handlers for this container.
1489
- */
1490
- const currentHandlers = onScrollHandlers.get(container);
1491
- if (!currentHandlers)
1492
- return;
1493
- currentHandlers.delete(containerHandler);
1494
- if (currentHandlers.size)
1495
- return;
1496
- /**
1497
- * If no more handlers, remove the scroll listener too.
1498
- */
1499
- const scrollListener = scrollListeners.get(container);
1500
- scrollListeners.delete(container);
1501
- if (scrollListener) {
1502
- getEventTarget(container).removeEventListener("scroll", scrollListener);
1503
- (_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
1504
- window.removeEventListener("resize", scrollListener);
1342
+ /**
1343
+ * Allows the returned animation to be awaited or promise-chained. Currently
1344
+ * resolves when the animation finishes at all but in a future update could/should
1345
+ * reject if its cancels.
1346
+ */
1347
+ then(resolve, reject) {
1348
+ return this.currentFinishedPromise.then(resolve, reject);
1349
+ }
1350
+ updateFinishedPromise() {
1351
+ this.currentFinishedPromise = new Promise((resolve) => {
1352
+ this.resolveFinishedPromise = resolve;
1353
+ });
1354
+ }
1355
+ play() {
1356
+ if (this.state === "finished") {
1357
+ this.updateFinishedPromise();
1505
1358
  }
1506
- };
1507
- }
1508
-
1509
- function scrollTimelineFallback({ source, container, axis = "y", }) {
1510
- // Support legacy source argument. Deprecate later.
1511
- if (source)
1512
- container = source;
1513
- // ScrollTimeline records progress as a percentage CSSUnitValue
1514
- const currentTime = { value: 0 };
1515
- const cancel = scrollInfo((info) => {
1516
- currentTime.value = info[axis].progress * 100;
1517
- }, { container, axis });
1518
- return { currentTime, cancel };
1519
- }
1520
- const timelineCache = new Map();
1521
- function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
1522
- // Support legacy source argument. Deprecate later.
1523
- if (source)
1524
- container = source;
1525
- if (!timelineCache.has(container)) {
1526
- timelineCache.set(container, {});
1359
+ super.play();
1527
1360
  }
1528
- const elementCache = timelineCache.get(container);
1529
- if (!elementCache[axis]) {
1530
- elementCache[axis] = motionDom.supportsScrollTimeline()
1531
- ? new ScrollTimeline({ source: container, axis })
1532
- : scrollTimelineFallback({ source: container, axis });
1361
+ cancel() {
1362
+ this.removeAnimation();
1363
+ super.cancel();
1533
1364
  }
1534
- return elementCache[axis];
1535
- }
1536
- /**
1537
- * If the onScroll function has two arguments, it's expecting
1538
- * more specific information about the scroll from scrollInfo.
1539
- */
1540
- function isOnScrollWithInfo(onScroll) {
1541
- return onScroll.length === 2;
1542
- }
1543
- /**
1544
- * Currently, we only support element tracking with `scrollInfo`, though in
1545
- * the future we can also offer ViewTimeline support.
1546
- */
1547
- function needsElementTracking(options) {
1548
- return options && (options.target || options.offset);
1549
1365
  }
1550
- function scrollFunction(onScroll, options) {
1551
- if (isOnScrollWithInfo(onScroll) || needsElementTracking(options)) {
1552
- return scrollInfo((info) => {
1553
- onScroll(info[options.axis].progress, info);
1554
- }, options);
1366
+
1367
+ function animateElements(elementOrSelector, keyframes, options, scope) {
1368
+ const elements = motionDom.resolveElements(elementOrSelector, scope);
1369
+ const numElements = elements.length;
1370
+ motionUtils.invariant(Boolean(numElements), "No valid element provided.");
1371
+ const animations = [];
1372
+ for (let i = 0; i < numElements; i++) {
1373
+ const element = elements[i];
1374
+ const elementTransition = { ...options };
1375
+ /**
1376
+ * Resolve stagger function if provided.
1377
+ */
1378
+ if (typeof elementTransition.delay === "function") {
1379
+ elementTransition.delay = elementTransition.delay(i, numElements);
1380
+ }
1381
+ for (const valueName in keyframes) {
1382
+ const valueKeyframes = keyframes[valueName];
1383
+ const valueOptions = {
1384
+ ...motionDom.getValueTransition(elementTransition, valueName),
1385
+ };
1386
+ valueOptions.duration = valueOptions.duration
1387
+ ? motionUtils.secondsToMilliseconds(valueOptions.duration)
1388
+ : valueOptions.duration;
1389
+ valueOptions.delay = motionUtils.secondsToMilliseconds(valueOptions.delay || 0);
1390
+ valueOptions.allowFlatten =
1391
+ !elementTransition.type && !elementTransition.ease;
1392
+ animations.push(new NativeAnimation(element, valueName, valueKeyframes, valueOptions));
1393
+ }
1555
1394
  }
1556
- else {
1557
- return observeTimeline(onScroll, getTimeline(options));
1395
+ return animations;
1396
+ }
1397
+
1398
+ const createScopedWaapiAnimate = (scope) => {
1399
+ function scopedAnimate(elementOrSelector, keyframes, options) {
1400
+ return new motionDom.GroupPlaybackControls(animateElements(elementOrSelector, keyframes, options, scope));
1558
1401
  }
1402
+ return scopedAnimate;
1403
+ };
1404
+ const animateMini = /*@__PURE__*/ createScopedWaapiAnimate();
1405
+
1406
+ function observeTimeline(update, timeline) {
1407
+ let prevProgress;
1408
+ const onFrame = () => {
1409
+ const { currentTime } = timeline;
1410
+ const percentage = currentTime === null ? 0 : currentTime.value;
1411
+ const progress = percentage / 100;
1412
+ if (prevProgress !== progress) {
1413
+ update(progress);
1414
+ }
1415
+ prevProgress = progress;
1416
+ };
1417
+ motionDom.frame.update(onFrame, true);
1418
+ return () => motionDom.cancelFrame(onFrame);
1559
1419
  }
1560
- function scrollAnimation(animation, options) {
1561
- animation.flatten();
1562
- if (needsElementTracking(options)) {
1563
- animation.pause();
1564
- return scrollInfo((info) => {
1565
- animation.time = animation.duration * info[options.axis].progress;
1566
- }, options);
1420
+
1421
+ const resizeHandlers = new WeakMap();
1422
+ let observer;
1423
+ function getElementSize(target, borderBoxSize) {
1424
+ if (borderBoxSize) {
1425
+ const { inlineSize, blockSize } = borderBoxSize[0];
1426
+ return { width: inlineSize, height: blockSize };
1427
+ }
1428
+ else if (target instanceof SVGElement && "getBBox" in target) {
1429
+ return target.getBBox();
1567
1430
  }
1568
1431
  else {
1569
- const timeline = getTimeline(options);
1570
- if (animation.attachTimeline) {
1571
- return animation.attachTimeline(timeline, (valueAnimation) => {
1572
- valueAnimation.pause();
1573
- return observeTimeline((progress) => {
1574
- valueAnimation.time = valueAnimation.duration * progress;
1575
- }, timeline);
1576
- });
1577
- }
1578
- else {
1579
- return motionUtils.noop;
1580
- }
1432
+ return {
1433
+ width: target.offsetWidth,
1434
+ height: target.offsetHeight,
1435
+ };
1581
1436
  }
1582
1437
  }
1583
- function scroll(onScroll, { axis = "y", ...options } = {}) {
1584
- const optionsWithDefaults = { axis, ...options };
1585
- return typeof onScroll === "function"
1586
- ? scrollFunction(onScroll, optionsWithDefaults)
1587
- : scrollAnimation(onScroll, optionsWithDefaults);
1438
+ function notifyTarget({ target, contentRect, borderBoxSize, }) {
1439
+ var _a;
1440
+ (_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
1441
+ handler({
1442
+ target,
1443
+ contentSize: contentRect,
1444
+ get size() {
1445
+ return getElementSize(target, borderBoxSize);
1446
+ },
1447
+ });
1448
+ });
1588
1449
  }
1589
-
1590
- const thresholds = {
1591
- some: 0,
1592
- all: 1,
1593
- };
1594
- function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "some" } = {}) {
1595
- const elements = motionDom.resolveElements(elementOrSelector);
1596
- const activeIntersections = new WeakMap();
1597
- const onIntersectionChange = (entries) => {
1598
- entries.forEach((entry) => {
1599
- const onEnd = activeIntersections.get(entry.target);
1600
- /**
1601
- * If there's no change to the intersection, we don't need to
1602
- * do anything here.
1603
- */
1604
- if (entry.isIntersecting === Boolean(onEnd))
1605
- return;
1606
- if (entry.isIntersecting) {
1607
- const newOnEnd = onStart(entry.target, entry);
1608
- if (typeof newOnEnd === "function") {
1609
- activeIntersections.set(entry.target, newOnEnd);
1610
- }
1611
- else {
1612
- observer.unobserve(entry.target);
1613
- }
1614
- }
1615
- else if (typeof onEnd === "function") {
1616
- onEnd(entry);
1617
- activeIntersections.delete(entry.target);
1450
+ function notifyAll(entries) {
1451
+ entries.forEach(notifyTarget);
1452
+ }
1453
+ function createResizeObserver() {
1454
+ if (typeof ResizeObserver === "undefined")
1455
+ return;
1456
+ observer = new ResizeObserver(notifyAll);
1457
+ }
1458
+ function resizeElement(target, handler) {
1459
+ if (!observer)
1460
+ createResizeObserver();
1461
+ const elements = motionDom.resolveElements(target);
1462
+ elements.forEach((element) => {
1463
+ let elementHandlers = resizeHandlers.get(element);
1464
+ if (!elementHandlers) {
1465
+ elementHandlers = new Set();
1466
+ resizeHandlers.set(element, elementHandlers);
1467
+ }
1468
+ elementHandlers.add(handler);
1469
+ observer === null || observer === void 0 ? void 0 : observer.observe(element);
1470
+ });
1471
+ return () => {
1472
+ elements.forEach((element) => {
1473
+ const elementHandlers = resizeHandlers.get(element);
1474
+ elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
1475
+ if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
1476
+ observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
1618
1477
  }
1619
1478
  });
1620
1479
  };
1621
- const observer = new IntersectionObserver(onIntersectionChange, {
1622
- root,
1623
- rootMargin,
1624
- threshold: typeof amount === "number" ? amount : thresholds[amount],
1625
- });
1626
- elements.forEach((element) => observer.observe(element));
1627
- return () => observer.disconnect();
1628
1480
  }
1629
1481
 
1630
- function steps(numSteps, direction = "end") {
1631
- return (progress) => {
1632
- progress =
1633
- direction === "end"
1634
- ? Math.min(progress, 0.999)
1635
- : Math.max(progress, 0.001);
1636
- const expanded = progress * numSteps;
1637
- const rounded = direction === "end" ? Math.floor(expanded) : Math.ceil(expanded);
1638
- return create.clamp(0, 1, rounded / numSteps);
1482
+ const windowCallbacks = new Set();
1483
+ let windowResizeHandler;
1484
+ function createWindowResizeHandler() {
1485
+ windowResizeHandler = () => {
1486
+ const size = {
1487
+ width: window.innerWidth,
1488
+ height: window.innerHeight,
1489
+ };
1490
+ const info = {
1491
+ target: window,
1492
+ size,
1493
+ contentSize: size,
1494
+ };
1495
+ windowCallbacks.forEach((callback) => callback(info));
1639
1496
  };
1497
+ window.addEventListener("resize", windowResizeHandler);
1640
1498
  }
1641
-
1642
- function getOriginIndex(from, total) {
1643
- if (from === "first") {
1644
- return 0;
1645
- }
1646
- else {
1647
- const lastIndex = total - 1;
1648
- return from === "last" ? lastIndex : lastIndex / 2;
1649
- }
1650
- }
1651
- function stagger(duration = 0.1, { startDelay = 0, from = 0, ease } = {}) {
1652
- return (i, total) => {
1653
- const fromIndex = typeof from === "number" ? from : getOriginIndex(from, total);
1654
- const distance = Math.abs(fromIndex - i);
1655
- let delay = duration * distance;
1656
- if (ease) {
1657
- const maxDelay = total * duration;
1658
- const easingFunction = create.easingDefinitionToFunction(ease);
1659
- delay = easingFunction(delay / maxDelay) * maxDelay;
1499
+ function resizeWindow(callback) {
1500
+ windowCallbacks.add(callback);
1501
+ if (!windowResizeHandler)
1502
+ createWindowResizeHandler();
1503
+ return () => {
1504
+ windowCallbacks.delete(callback);
1505
+ if (!windowCallbacks.size && windowResizeHandler) {
1506
+ windowResizeHandler = undefined;
1660
1507
  }
1661
- return startDelay + delay;
1662
1508
  };
1663
1509
  }
1664
1510
 
1665
- const isCustomValueType = (v) => {
1666
- return v && typeof v === "object" && v.mix;
1511
+ function resize(a, b) {
1512
+ return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
1513
+ }
1514
+
1515
+ /**
1516
+ * A time in milliseconds, beyond which we consider the scroll velocity to be 0.
1517
+ */
1518
+ const maxElapsed = 50;
1519
+ const createAxisInfo = () => ({
1520
+ current: 0,
1521
+ offset: [],
1522
+ progress: 0,
1523
+ scrollLength: 0,
1524
+ targetOffset: 0,
1525
+ targetLength: 0,
1526
+ containerLength: 0,
1527
+ velocity: 0,
1528
+ });
1529
+ const createScrollInfo = () => ({
1530
+ time: 0,
1531
+ x: createAxisInfo(),
1532
+ y: createAxisInfo(),
1533
+ });
1534
+ const keys = {
1535
+ x: {
1536
+ length: "Width",
1537
+ position: "Left",
1538
+ },
1539
+ y: {
1540
+ length: "Height",
1541
+ position: "Top",
1542
+ },
1667
1543
  };
1668
- const getMixer = (v) => (isCustomValueType(v) ? v.mix : undefined);
1669
- function transform(...args) {
1670
- const useImmediate = !Array.isArray(args[0]);
1671
- const argOffset = useImmediate ? 0 : -1;
1672
- const inputValue = args[0 + argOffset];
1673
- const inputRange = args[1 + argOffset];
1674
- const outputRange = args[2 + argOffset];
1675
- const options = args[3 + argOffset];
1676
- const interpolator = create.interpolate(inputRange, outputRange, {
1677
- mixer: getMixer(outputRange[0]),
1678
- ...options,
1679
- });
1680
- return useImmediate ? interpolator(inputValue) : interpolator;
1544
+ function updateAxisInfo(element, axisName, info, time) {
1545
+ const axis = info[axisName];
1546
+ const { length, position } = keys[axisName];
1547
+ const prev = axis.current;
1548
+ const prevTime = info.time;
1549
+ axis.current = element[`scroll${position}`];
1550
+ axis.scrollLength = element[`scroll${length}`] - element[`client${length}`];
1551
+ axis.offset.length = 0;
1552
+ axis.offset[0] = 0;
1553
+ axis.offset[1] = axis.scrollLength;
1554
+ axis.progress = motionUtils.progress(0, axis.scrollLength, axis.current);
1555
+ const elapsed = time - prevTime;
1556
+ axis.velocity =
1557
+ elapsed > maxElapsed
1558
+ ? 0
1559
+ : motionUtils.velocityPerSecond(axis.current - prev, elapsed);
1560
+ }
1561
+ function updateScrollInfo(element, info, time) {
1562
+ updateAxisInfo(element, "x", info, time);
1563
+ updateAxisInfo(element, "y", info, time);
1564
+ info.time = time;
1681
1565
  }
1682
1566
 
1683
- /**
1684
- * @deprecated
1685
- *
1686
- * Import as `frame` instead.
1687
- */
1688
- const sync = create.frame;
1689
- /**
1690
- * @deprecated
1691
- *
1692
- * Use cancelFrame(callback) instead.
1693
- */
1694
- const cancelSync = create.stepsOrder.reduce((acc, key) => {
1695
- acc[key] = (process) => create.cancelFrame(process);
1696
- return acc;
1697
- }, {});
1698
-
1699
- const shouldInheritGroup = (inherit) => inherit === true;
1700
- const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
1701
- const LayoutGroup = ({ children, id, inherit = true }) => {
1702
- const layoutGroupContext = React.useContext(create.LayoutGroupContext);
1703
- const deprecatedLayoutGroupContext = React.useContext(DeprecatedLayoutGroupContext);
1704
- const [forceRender, key] = useForceUpdate();
1705
- const context = React.useRef(null);
1706
- const upstreamId = layoutGroupContext.id || deprecatedLayoutGroupContext;
1707
- if (context.current === null) {
1708
- if (shouldInheritId(inherit) && upstreamId) {
1709
- id = id ? upstreamId + "-" + id : upstreamId;
1567
+ function calcInset(element, container) {
1568
+ const inset = { x: 0, y: 0 };
1569
+ let current = element;
1570
+ while (current && current !== container) {
1571
+ if (current instanceof HTMLElement) {
1572
+ inset.x += current.offsetLeft;
1573
+ inset.y += current.offsetTop;
1574
+ current = current.offsetParent;
1575
+ }
1576
+ else if (current.tagName === "svg") {
1577
+ /**
1578
+ * This isn't an ideal approach to measuring the offset of <svg /> tags.
1579
+ * It would be preferable, given they behave like HTMLElements in most ways
1580
+ * to use offsetLeft/Top. But these don't exist on <svg />. Likewise we
1581
+ * can't use .getBBox() like most SVG elements as these provide the offset
1582
+ * relative to the SVG itself, which for <svg /> is usually 0x0.
1583
+ */
1584
+ const svgBoundingBox = current.getBoundingClientRect();
1585
+ current = current.parentElement;
1586
+ const parentBoundingBox = current.getBoundingClientRect();
1587
+ inset.x += svgBoundingBox.left - parentBoundingBox.left;
1588
+ inset.y += svgBoundingBox.top - parentBoundingBox.top;
1589
+ }
1590
+ else if (current instanceof SVGGraphicsElement) {
1591
+ const { x, y } = current.getBBox();
1592
+ inset.x += x;
1593
+ inset.y += y;
1594
+ let svg = null;
1595
+ let parent = current.parentNode;
1596
+ while (!svg) {
1597
+ if (parent.tagName === "svg") {
1598
+ svg = parent;
1599
+ }
1600
+ parent = current.parentNode;
1601
+ }
1602
+ current = svg;
1603
+ }
1604
+ else {
1605
+ break;
1710
1606
  }
1711
- context.current = {
1712
- id,
1713
- group: shouldInheritGroup(inherit)
1714
- ? layoutGroupContext.group || nodeGroup()
1715
- : nodeGroup(),
1716
- };
1717
1607
  }
1718
- const memoizedContext = React.useMemo(() => ({ ...context.current, forceRender }), [key]);
1719
- return (jsxRuntime.jsx(create.LayoutGroupContext.Provider, { value: memoizedContext, children: children }));
1720
- };
1608
+ return inset;
1609
+ }
1721
1610
 
1722
- /**
1723
- * Used in conjunction with the `m` component to reduce bundle size.
1724
- *
1725
- * `m` is a version of the `motion` component that only loads functionality
1726
- * critical for the initial render.
1727
- *
1728
- * `LazyMotion` can then be used to either synchronously or asynchronously
1729
- * load animation and gesture support.
1730
- *
1731
- * ```jsx
1732
- * // Synchronous loading
1733
- * import { LazyMotion, m, domAnimation } from "framer-motion"
1734
- *
1735
- * function App() {
1736
- * return (
1737
- * <LazyMotion features={domAnimation}>
1738
- * <m.div animate={{ scale: 2 }} />
1739
- * </LazyMotion>
1740
- * )
1741
- * }
1742
- *
1743
- * // Asynchronous loading
1744
- * import { LazyMotion, m } from "framer-motion"
1745
- *
1746
- * function App() {
1747
- * return (
1748
- * <LazyMotion features={() => import('./path/to/domAnimation')}>
1749
- * <m.div animate={{ scale: 2 }} />
1750
- * </LazyMotion>
1751
- * )
1752
- * }
1753
- * ```
1754
- *
1755
- * @public
1756
- */
1757
- function LazyMotion({ children, features, strict = false }) {
1758
- const [, setIsLoaded] = React.useState(!isLazyBundle(features));
1759
- const loadedRenderer = React.useRef(undefined);
1611
+ const namedEdges = {
1612
+ start: 0,
1613
+ center: 0.5,
1614
+ end: 1,
1615
+ };
1616
+ function resolveEdge(edge, length, inset = 0) {
1617
+ let delta = 0;
1760
1618
  /**
1761
- * If this is a synchronous load, load features immediately
1619
+ * If we have this edge defined as a preset, replace the definition
1620
+ * with the numerical value.
1762
1621
  */
1763
- if (!isLazyBundle(features)) {
1764
- const { renderer, ...loadedFeatures } = features;
1765
- loadedRenderer.current = renderer;
1766
- create.loadFeatures(loadedFeatures);
1622
+ if (edge in namedEdges) {
1623
+ edge = namedEdges[edge];
1767
1624
  }
1768
- React.useEffect(() => {
1769
- if (isLazyBundle(features)) {
1770
- features().then(({ renderer, ...loadedFeatures }) => {
1771
- create.loadFeatures(loadedFeatures);
1772
- loadedRenderer.current = renderer;
1773
- setIsLoaded(true);
1774
- });
1625
+ /**
1626
+ * Handle unit values
1627
+ */
1628
+ if (typeof edge === "string") {
1629
+ const asNumber = parseFloat(edge);
1630
+ if (edge.endsWith("px")) {
1631
+ delta = asNumber;
1775
1632
  }
1776
- }, []);
1777
- return (jsxRuntime.jsx(create.LazyContext.Provider, { value: { renderer: loadedRenderer.current, strict }, children: children }));
1633
+ else if (edge.endsWith("%")) {
1634
+ edge = asNumber / 100;
1635
+ }
1636
+ else if (edge.endsWith("vw")) {
1637
+ delta = (asNumber / 100) * document.documentElement.clientWidth;
1638
+ }
1639
+ else if (edge.endsWith("vh")) {
1640
+ delta = (asNumber / 100) * document.documentElement.clientHeight;
1641
+ }
1642
+ else {
1643
+ edge = asNumber;
1644
+ }
1645
+ }
1646
+ /**
1647
+ * If the edge is defined as a number, handle as a progress value.
1648
+ */
1649
+ if (typeof edge === "number") {
1650
+ delta = length * edge;
1651
+ }
1652
+ return inset + delta;
1778
1653
  }
1779
- function isLazyBundle(features) {
1780
- return typeof features === "function";
1654
+
1655
+ const defaultOffset = [0, 0];
1656
+ function resolveOffset(offset, containerLength, targetLength, targetInset) {
1657
+ let offsetDefinition = Array.isArray(offset) ? offset : defaultOffset;
1658
+ let targetPoint = 0;
1659
+ let containerPoint = 0;
1660
+ if (typeof offset === "number") {
1661
+ /**
1662
+ * If we're provided offset: [0, 0.5, 1] then each number x should become
1663
+ * [x, x], so we default to the behaviour of mapping 0 => 0 of both target
1664
+ * and container etc.
1665
+ */
1666
+ offsetDefinition = [offset, offset];
1667
+ }
1668
+ else if (typeof offset === "string") {
1669
+ offset = offset.trim();
1670
+ if (offset.includes(" ")) {
1671
+ offsetDefinition = offset.split(" ");
1672
+ }
1673
+ else {
1674
+ /**
1675
+ * If we're provided a definition like "100px" then we want to apply
1676
+ * that only to the top of the target point, leaving the container at 0.
1677
+ * Whereas a named offset like "end" should be applied to both.
1678
+ */
1679
+ offsetDefinition = [offset, namedEdges[offset] ? offset : `0`];
1680
+ }
1681
+ }
1682
+ targetPoint = resolveEdge(offsetDefinition[0], targetLength, targetInset);
1683
+ containerPoint = resolveEdge(offsetDefinition[1], containerLength);
1684
+ return targetPoint - containerPoint;
1781
1685
  }
1782
1686
 
1783
- /**
1784
- * `MotionConfig` is used to set configuration options for all children `motion` components.
1785
- *
1786
- * ```jsx
1787
- * import { motion, MotionConfig } from "framer-motion"
1788
- *
1789
- * export function App() {
1790
- * return (
1791
- * <MotionConfig transition={{ type: "spring" }}>
1792
- * <motion.div animate={{ x: 100 }} />
1793
- * </MotionConfig>
1794
- * )
1795
- * }
1796
- * ```
1797
- *
1798
- * @public
1799
- */
1800
- function MotionConfig({ children, isValidProp, ...config }) {
1801
- isValidProp && create.loadExternalIsValidProp(isValidProp);
1687
+ const ScrollOffset = {
1688
+ Enter: [
1689
+ [0, 1],
1690
+ [1, 1],
1691
+ ],
1692
+ Exit: [
1693
+ [0, 0],
1694
+ [1, 0],
1695
+ ],
1696
+ Any: [
1697
+ [1, 0],
1698
+ [0, 1],
1699
+ ],
1700
+ All: [
1701
+ [0, 0],
1702
+ [1, 1],
1703
+ ],
1704
+ };
1705
+
1706
+ const point = { x: 0, y: 0 };
1707
+ function getTargetSize(target) {
1708
+ return "getBBox" in target && target.tagName !== "svg"
1709
+ ? target.getBBox()
1710
+ : { width: target.clientWidth, height: target.clientHeight };
1711
+ }
1712
+ function resolveOffsets(container, info, options) {
1713
+ const { offset: offsetDefinition = ScrollOffset.All } = options;
1714
+ const { target = container, axis = "y" } = options;
1715
+ const lengthLabel = axis === "y" ? "height" : "width";
1716
+ const inset = target !== container ? calcInset(target, container) : point;
1717
+ /**
1718
+ * Measure the target and container. If they're the same thing then we
1719
+ * use the container's scrollWidth/Height as the target, from there
1720
+ * all other calculations can remain the same.
1721
+ */
1722
+ const targetSize = target === container
1723
+ ? { width: container.scrollWidth, height: container.scrollHeight }
1724
+ : getTargetSize(target);
1725
+ const containerSize = {
1726
+ width: container.clientWidth,
1727
+ height: container.clientHeight,
1728
+ };
1802
1729
  /**
1803
- * Inherit props from any parent MotionConfig components
1730
+ * Reset the length of the resolved offset array rather than creating a new one.
1731
+ * TODO: More reusable data structures for targetSize/containerSize would also be good.
1804
1732
  */
1805
- config = { ...React.useContext(create.MotionConfigContext), ...config };
1733
+ info[axis].offset.length = 0;
1806
1734
  /**
1807
- * Don't allow isStatic to change between renders as it affects how many hooks
1808
- * motion components fire.
1735
+ * Populate the offset array by resolving the user's offset definition into
1736
+ * a list of pixel scroll offets.
1809
1737
  */
1810
- config.isStatic = create.useConstant(() => config.isStatic);
1738
+ let hasChanged = !info[axis].interpolate;
1739
+ const numOffsets = offsetDefinition.length;
1740
+ for (let i = 0; i < numOffsets; i++) {
1741
+ const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
1742
+ if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
1743
+ hasChanged = true;
1744
+ }
1745
+ info[axis].offset[i] = offset;
1746
+ }
1811
1747
  /**
1812
- * Creating a new config context object will re-render every `motion` component
1813
- * every time it renders. So we only want to create a new one sparingly.
1748
+ * If the pixel scroll offsets have changed, create a new interpolator function
1749
+ * to map scroll value into a progress.
1814
1750
  */
1815
- const context = React.useMemo(() => config, [
1816
- JSON.stringify(config.transition),
1817
- config.transformPagePoint,
1818
- config.reducedMotion,
1819
- ]);
1820
- return (jsxRuntime.jsx(create.MotionConfigContext.Provider, { value: context, children: children }));
1751
+ if (hasChanged) {
1752
+ info[axis].interpolate = create.interpolate(info[axis].offset, create.defaultOffset(offsetDefinition), { clamp: false });
1753
+ info[axis].interpolatorOffsets = [...info[axis].offset];
1754
+ }
1755
+ info[axis].progress = create.clamp(0, 1, info[axis].interpolate(info[axis].current));
1821
1756
  }
1822
1757
 
1823
- const ReorderContext = React.createContext(null);
1824
-
1825
- function createDOMMotionComponentProxy(componentFactory) {
1826
- if (typeof Proxy === "undefined") {
1827
- return componentFactory;
1758
+ function measure(container, target = container, info) {
1759
+ /**
1760
+ * Find inset of target within scrollable container
1761
+ */
1762
+ info.x.targetOffset = 0;
1763
+ info.y.targetOffset = 0;
1764
+ if (target !== container) {
1765
+ let node = target;
1766
+ while (node && node !== container) {
1767
+ info.x.targetOffset += node.offsetLeft;
1768
+ info.y.targetOffset += node.offsetTop;
1769
+ node = node.offsetParent;
1770
+ }
1828
1771
  }
1772
+ info.x.targetLength =
1773
+ target === container ? target.scrollWidth : target.clientWidth;
1774
+ info.y.targetLength =
1775
+ target === container ? target.scrollHeight : target.clientHeight;
1776
+ info.x.containerLength = container.clientWidth;
1777
+ info.y.containerLength = container.clientHeight;
1829
1778
  /**
1830
- * A cache of generated `motion` components, e.g `motion.div`, `motion.input` etc.
1831
- * Rather than generating them anew every render.
1779
+ * In development mode ensure scroll containers aren't position: static as this makes
1780
+ * it difficult to measure their relative positions.
1832
1781
  */
1833
- const componentCache = new Map();
1834
- const deprecatedFactoryFunction = (...args) => {
1835
- if (process.env.NODE_ENV !== "production") {
1836
- create.warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
1782
+ if (process.env.NODE_ENV !== "production") {
1783
+ if (container && target && target !== container) {
1784
+ motionUtils.warnOnce(getComputedStyle(container).position !== "static", "Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly.");
1837
1785
  }
1838
- return componentFactory(...args);
1839
- };
1840
- return new Proxy(deprecatedFactoryFunction, {
1841
- /**
1842
- * Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
1843
- * The prop name is passed through as `key` and we can use that to generate a `motion`
1844
- * DOM component with that name.
1845
- */
1846
- get: (_target, key) => {
1847
- if (key === "create")
1848
- return componentFactory;
1849
- /**
1850
- * If this element doesn't exist in the component cache, create it and cache.
1851
- */
1852
- if (!componentCache.has(key)) {
1853
- componentCache.set(key, componentFactory(key));
1786
+ }
1787
+ }
1788
+ function createOnScrollHandler(element, onScroll, info, options = {}) {
1789
+ return {
1790
+ measure: () => measure(element, options.target, info),
1791
+ update: (time) => {
1792
+ updateScrollInfo(element, info, time);
1793
+ if (options.offset || options.target) {
1794
+ resolveOffsets(element, info, options);
1854
1795
  }
1855
- return componentCache.get(key);
1856
1796
  },
1857
- });
1797
+ notify: () => onScroll(info),
1798
+ };
1858
1799
  }
1859
1800
 
1860
- const motion = /*@__PURE__*/ createDOMMotionComponentProxy(create.createMotionComponent);
1861
-
1862
- function checkReorder(order, value, offset, velocity) {
1863
- if (!velocity)
1864
- return order;
1865
- const index = order.findIndex((item) => item.value === value);
1866
- if (index === -1)
1867
- return order;
1868
- const nextOffset = velocity > 0 ? 1 : -1;
1869
- const nextItem = order[index + nextOffset];
1870
- if (!nextItem)
1871
- return order;
1872
- const item = order[index];
1873
- const nextLayout = nextItem.layout;
1874
- const nextItemCenter = create.mixNumber(nextLayout.min, nextLayout.max, 0.5);
1875
- if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
1876
- (nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
1877
- return create.moveItem(order, index, index + nextOffset);
1801
+ const scrollListeners = new WeakMap();
1802
+ const resizeListeners = new WeakMap();
1803
+ const onScrollHandlers = new WeakMap();
1804
+ const getEventTarget = (element) => element === document.documentElement ? window : element;
1805
+ function scrollInfo(onScroll, { container = document.documentElement, ...options } = {}) {
1806
+ let containerHandlers = onScrollHandlers.get(container);
1807
+ /**
1808
+ * Get the onScroll handlers for this container.
1809
+ * If one isn't found, create a new one.
1810
+ */
1811
+ if (!containerHandlers) {
1812
+ containerHandlers = new Set();
1813
+ onScrollHandlers.set(container, containerHandlers);
1878
1814
  }
1879
- return order;
1880
- }
1881
-
1882
- function ReorderGroupComponent({ children, as = "ul", axis = "y", onReorder, values, ...props }, externalRef) {
1883
- const Component = create.useConstant(() => motion[as]);
1884
- const order = [];
1885
- const isReordering = React.useRef(false);
1886
- motionUtils.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
1887
- const context = {
1888
- axis,
1889
- registerItem: (value, layout) => {
1890
- // If the entry was already added, update it rather than adding it again
1891
- const idx = order.findIndex((entry) => value === entry.value);
1892
- if (idx !== -1) {
1893
- order[idx].layout = layout[axis];
1894
- }
1895
- else {
1896
- order.push({ value: value, layout: layout[axis] });
1897
- }
1898
- order.sort(compareMin);
1899
- },
1900
- updateOrder: (item, offset, velocity) => {
1901
- if (isReordering.current)
1902
- return;
1903
- const newOrder = checkReorder(order, item, offset, velocity);
1904
- if (order !== newOrder) {
1905
- isReordering.current = true;
1906
- onReorder(newOrder
1907
- .map(getValue)
1908
- .filter((value) => values.indexOf(value) !== -1));
1815
+ /**
1816
+ * Create a new onScroll handler for the provided callback.
1817
+ */
1818
+ const info = createScrollInfo();
1819
+ const containerHandler = createOnScrollHandler(container, onScroll, info, options);
1820
+ containerHandlers.add(containerHandler);
1821
+ /**
1822
+ * Check if there's a scroll event listener for this container.
1823
+ * If not, create one.
1824
+ */
1825
+ if (!scrollListeners.has(container)) {
1826
+ const measureAll = () => {
1827
+ for (const handler of containerHandlers)
1828
+ handler.measure();
1829
+ };
1830
+ const updateAll = () => {
1831
+ for (const handler of containerHandlers) {
1832
+ handler.update(motionDom.frameData.timestamp);
1909
1833
  }
1910
- },
1834
+ };
1835
+ const notifyAll = () => {
1836
+ for (const handler of containerHandlers)
1837
+ handler.notify();
1838
+ };
1839
+ const listener = () => {
1840
+ motionDom.frame.read(measureAll, false, true);
1841
+ motionDom.frame.read(updateAll, false, true);
1842
+ motionDom.frame.update(notifyAll, false, true);
1843
+ };
1844
+ scrollListeners.set(container, listener);
1845
+ const target = getEventTarget(container);
1846
+ window.addEventListener("resize", listener, { passive: true });
1847
+ if (container !== document.documentElement) {
1848
+ resizeListeners.set(container, resize(container, listener));
1849
+ }
1850
+ target.addEventListener("scroll", listener, { passive: true });
1851
+ }
1852
+ const listener = scrollListeners.get(container);
1853
+ motionDom.frame.read(listener, false, true);
1854
+ return () => {
1855
+ var _a;
1856
+ motionDom.cancelFrame(listener);
1857
+ /**
1858
+ * Check if we even have any handlers for this container.
1859
+ */
1860
+ const currentHandlers = onScrollHandlers.get(container);
1861
+ if (!currentHandlers)
1862
+ return;
1863
+ currentHandlers.delete(containerHandler);
1864
+ if (currentHandlers.size)
1865
+ return;
1866
+ /**
1867
+ * If no more handlers, remove the scroll listener too.
1868
+ */
1869
+ const scrollListener = scrollListeners.get(container);
1870
+ scrollListeners.delete(container);
1871
+ if (scrollListener) {
1872
+ getEventTarget(container).removeEventListener("scroll", scrollListener);
1873
+ (_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
1874
+ window.removeEventListener("resize", scrollListener);
1875
+ }
1911
1876
  };
1912
- React.useEffect(() => {
1913
- isReordering.current = false;
1914
- });
1915
- return (jsxRuntime.jsx(Component, { ...props, ref: externalRef, ignoreStrict: true, children: jsxRuntime.jsx(ReorderContext.Provider, { value: context, children: children }) }));
1916
1877
  }
1917
- const ReorderGroup = /*@__PURE__*/ React.forwardRef(ReorderGroupComponent);
1918
- function getValue(item) {
1919
- return item.value;
1878
+
1879
+ function scrollTimelineFallback({ source, container, axis = "y", }) {
1880
+ // Support legacy source argument. Deprecate later.
1881
+ if (source)
1882
+ container = source;
1883
+ // ScrollTimeline records progress as a percentage CSSUnitValue
1884
+ const currentTime = { value: 0 };
1885
+ const cancel = scrollInfo((info) => {
1886
+ currentTime.value = info[axis].progress * 100;
1887
+ }, { container, axis });
1888
+ return { currentTime, cancel };
1920
1889
  }
1921
- function compareMin(a, b) {
1922
- return a.layout.min - b.layout.min;
1890
+ const timelineCache = new Map();
1891
+ function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
1892
+ // Support legacy source argument. Deprecate later.
1893
+ if (source)
1894
+ container = source;
1895
+ if (!timelineCache.has(container)) {
1896
+ timelineCache.set(container, {});
1897
+ }
1898
+ const elementCache = timelineCache.get(container);
1899
+ if (!elementCache[axis]) {
1900
+ elementCache[axis] = motionDom.supportsScrollTimeline()
1901
+ ? new ScrollTimeline({ source: container, axis })
1902
+ : scrollTimelineFallback({ source: container, axis });
1903
+ }
1904
+ return elementCache[axis];
1905
+ }
1906
+ /**
1907
+ * If the onScroll function has two arguments, it's expecting
1908
+ * more specific information about the scroll from scrollInfo.
1909
+ */
1910
+ function isOnScrollWithInfo(onScroll) {
1911
+ return onScroll.length === 2;
1923
1912
  }
1924
-
1925
1913
  /**
1926
- * Creates a `MotionValue` to track the state and velocity of a value.
1927
- *
1928
- * Usually, these are created automatically. For advanced use-cases, like use with `useTransform`, you can create `MotionValue`s externally and pass them into the animated component via the `style` prop.
1929
- *
1930
- * ```jsx
1931
- * export const MyComponent = () => {
1932
- * const scale = useMotionValue(1)
1933
- *
1934
- * return <motion.div style={{ scale }} />
1935
- * }
1936
- * ```
1937
- *
1938
- * @param initial - The initial state.
1939
- *
1940
- * @public
1914
+ * Currently, we only support element tracking with `scrollInfo`, though in
1915
+ * the future we can also offer ViewTimeline support.
1941
1916
  */
1942
- function useMotionValue(initial) {
1943
- const value = create.useConstant(() => create.motionValue(initial));
1944
- /**
1945
- * If this motion value is being used in static mode, like on
1946
- * the Framer canvas, force components to rerender when the motion
1947
- * value is updated.
1948
- */
1949
- const { isStatic } = React.useContext(create.MotionConfigContext);
1950
- if (isStatic) {
1951
- const [, setLatest] = React.useState(initial);
1952
- React.useEffect(() => value.on("change", setLatest), []);
1917
+ function needsElementTracking(options) {
1918
+ return options && (options.target || options.offset);
1919
+ }
1920
+ function scrollFunction(onScroll, options) {
1921
+ if (isOnScrollWithInfo(onScroll) || needsElementTracking(options)) {
1922
+ return scrollInfo((info) => {
1923
+ onScroll(info[options.axis].progress, info);
1924
+ }, options);
1953
1925
  }
1954
- return value;
1926
+ else {
1927
+ return observeTimeline(onScroll, getTimeline(options));
1928
+ }
1929
+ }
1930
+ function scrollAnimation(animation, options) {
1931
+ animation.flatten();
1932
+ if (needsElementTracking(options)) {
1933
+ animation.pause();
1934
+ return scrollInfo((info) => {
1935
+ animation.time = animation.duration * info[options.axis].progress;
1936
+ }, options);
1937
+ }
1938
+ else {
1939
+ const timeline = getTimeline(options);
1940
+ if (animation.attachTimeline) {
1941
+ return animation.attachTimeline(timeline, (valueAnimation) => {
1942
+ valueAnimation.pause();
1943
+ return observeTimeline((progress) => {
1944
+ valueAnimation.time = valueAnimation.duration * progress;
1945
+ }, timeline);
1946
+ });
1947
+ }
1948
+ else {
1949
+ return motionUtils.noop;
1950
+ }
1951
+ }
1952
+ }
1953
+ function scroll(onScroll, { axis = "y", ...options } = {}) {
1954
+ const optionsWithDefaults = { axis, ...options };
1955
+ return typeof onScroll === "function"
1956
+ ? scrollFunction(onScroll, optionsWithDefaults)
1957
+ : scrollAnimation(onScroll, optionsWithDefaults);
1955
1958
  }
1956
1959
 
1957
- function useCombineMotionValues(values, combineValues) {
1958
- /**
1959
- * Initialise the returned motion value. This remains the same between renders.
1960
- */
1961
- const value = useMotionValue(combineValues());
1962
- /**
1963
- * Create a function that will update the template motion value with the latest values.
1964
- * This is pre-bound so whenever a motion value updates it can schedule its
1965
- * execution in Framesync. If it's already been scheduled it won't be fired twice
1966
- * in a single frame.
1967
- */
1968
- const updateValue = () => value.set(combineValues());
1969
- /**
1970
- * Synchronously update the motion value with the latest values during the render.
1971
- * This ensures that within a React render, the styles applied to the DOM are up-to-date.
1972
- */
1973
- updateValue();
1974
- /**
1975
- * Subscribe to all motion values found within the template. Whenever any of them change,
1976
- * schedule an update.
1977
- */
1978
- create.useIsomorphicLayoutEffect(() => {
1979
- const scheduleUpdate = () => create.frame.preRender(updateValue, false, true);
1980
- const subscriptions = values.map((v) => v.on("change", scheduleUpdate));
1981
- return () => {
1982
- subscriptions.forEach((unsubscribe) => unsubscribe());
1983
- create.cancelFrame(updateValue);
1984
- };
1960
+ const thresholds = {
1961
+ some: 0,
1962
+ all: 1,
1963
+ };
1964
+ function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "some" } = {}) {
1965
+ const elements = motionDom.resolveElements(elementOrSelector);
1966
+ const activeIntersections = new WeakMap();
1967
+ const onIntersectionChange = (entries) => {
1968
+ entries.forEach((entry) => {
1969
+ const onEnd = activeIntersections.get(entry.target);
1970
+ /**
1971
+ * If there's no change to the intersection, we don't need to
1972
+ * do anything here.
1973
+ */
1974
+ if (entry.isIntersecting === Boolean(onEnd))
1975
+ return;
1976
+ if (entry.isIntersecting) {
1977
+ const newOnEnd = onStart(entry.target, entry);
1978
+ if (typeof newOnEnd === "function") {
1979
+ activeIntersections.set(entry.target, newOnEnd);
1980
+ }
1981
+ else {
1982
+ observer.unobserve(entry.target);
1983
+ }
1984
+ }
1985
+ else if (typeof onEnd === "function") {
1986
+ onEnd(entry);
1987
+ activeIntersections.delete(entry.target);
1988
+ }
1989
+ });
1990
+ };
1991
+ const observer = new IntersectionObserver(onIntersectionChange, {
1992
+ root,
1993
+ rootMargin,
1994
+ threshold: typeof amount === "number" ? amount : thresholds[amount],
1985
1995
  });
1986
- return value;
1996
+ elements.forEach((element) => observer.observe(element));
1997
+ return () => observer.disconnect();
1987
1998
  }
1988
1999
 
1989
- function useComputed(compute) {
1990
- /**
1991
- * Open session of collectMotionValues. Any MotionValue that calls get()
1992
- * will be saved into this array.
1993
- */
1994
- create.collectMotionValues.current = [];
1995
- compute();
1996
- const value = useCombineMotionValues(create.collectMotionValues.current, compute);
1997
- /**
1998
- * Synchronously close session of collectMotionValues.
1999
- */
2000
- create.collectMotionValues.current = undefined;
2001
- return value;
2000
+ function steps(numSteps, direction = "end") {
2001
+ return (progress) => {
2002
+ progress =
2003
+ direction === "end"
2004
+ ? Math.min(progress, 0.999)
2005
+ : Math.max(progress, 0.001);
2006
+ const expanded = progress * numSteps;
2007
+ const rounded = direction === "end" ? Math.floor(expanded) : Math.ceil(expanded);
2008
+ return create.clamp(0, 1, rounded / numSteps);
2009
+ };
2002
2010
  }
2003
2011
 
2004
- function useTransform(input, inputRangeOrTransformer, outputRange, options) {
2005
- if (typeof input === "function") {
2006
- return useComputed(input);
2012
+ function getOriginIndex(from, total) {
2013
+ if (from === "first") {
2014
+ return 0;
2015
+ }
2016
+ else {
2017
+ const lastIndex = total - 1;
2018
+ return from === "last" ? lastIndex : lastIndex / 2;
2007
2019
  }
2008
- const transformer = typeof inputRangeOrTransformer === "function"
2009
- ? inputRangeOrTransformer
2010
- : transform(inputRangeOrTransformer, outputRange, options);
2011
- return Array.isArray(input)
2012
- ? useListTransform(input, transformer)
2013
- : useListTransform([input], ([latest]) => transformer(latest));
2014
2020
  }
2015
- function useListTransform(values, transformer) {
2016
- const latest = create.useConstant(() => []);
2017
- return useCombineMotionValues(values, () => {
2018
- latest.length = 0;
2019
- const numValues = values.length;
2020
- for (let i = 0; i < numValues; i++) {
2021
- latest[i] = values[i].get();
2021
+ function stagger(duration = 0.1, { startDelay = 0, from = 0, ease } = {}) {
2022
+ return (i, total) => {
2023
+ const fromIndex = typeof from === "number" ? from : getOriginIndex(from, total);
2024
+ const distance = Math.abs(fromIndex - i);
2025
+ let delay = duration * distance;
2026
+ if (ease) {
2027
+ const maxDelay = total * duration;
2028
+ const easingFunction = create.easingDefinitionToFunction(ease);
2029
+ delay = easingFunction(delay / maxDelay) * maxDelay;
2022
2030
  }
2023
- return transformer(latest);
2024
- });
2025
- }
2026
-
2027
- function useDefaultMotionValue(value, defaultValue = 0) {
2028
- return create.isMotionValue(value) ? value : useMotionValue(defaultValue);
2029
- }
2030
- function ReorderItemComponent({ children, style = {}, value, as = "li", onDrag, layout = true, ...props }, externalRef) {
2031
- const Component = create.useConstant(() => motion[as]);
2032
- const context = React.useContext(ReorderContext);
2033
- const point = {
2034
- x: useDefaultMotionValue(style.x),
2035
- y: useDefaultMotionValue(style.y),
2031
+ return startDelay + delay;
2036
2032
  };
2037
- const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) => latestX || latestY ? 1 : "unset");
2038
- motionUtils.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
2039
- const { axis, registerItem, updateOrder } = context;
2040
- return (jsxRuntime.jsx(Component, { drag: axis, ...props, dragSnapToOrigin: true, style: { ...style, x: point.x, y: point.y, zIndex }, layout: layout, onDrag: (event, gesturePoint) => {
2041
- const { velocity } = gesturePoint;
2042
- velocity[axis] &&
2043
- updateOrder(value, point[axis].get(), velocity[axis]);
2044
- onDrag && onDrag(event, gesturePoint);
2045
- }, onLayoutMeasure: (measured) => registerItem(value, measured), ref: externalRef, ignoreStrict: true, children: children }));
2046
2033
  }
2047
- const ReorderItem = /*@__PURE__*/ React.forwardRef(ReorderItemComponent);
2048
-
2049
- var namespace = /*#__PURE__*/Object.freeze({
2050
- __proto__: null,
2051
- Group: ReorderGroup,
2052
- Item: ReorderItem
2053
- });
2054
2034
 
2055
2035
  const createMinimalMotionComponent =
2056
2036
  /*@__PURE__*/ create.createMotionComponentFactory();
2057
2037
 
2058
2038
  const m = /*@__PURE__*/ createDOMMotionComponentProxy(createMinimalMotionComponent);
2059
2039
 
2040
+ function useUnmountEffect(callback) {
2041
+ return React.useEffect(() => () => callback(), []);
2042
+ }
2043
+
2060
2044
  /**
2061
2045
  * @public
2062
2046
  */
@@ -2097,10 +2081,10 @@ function refWarning(name, ref) {
2097
2081
  motionUtils.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.`);
2098
2082
  }
2099
2083
  const createScrollMotionValues = () => ({
2100
- scrollX: create.motionValue(0),
2101
- scrollY: create.motionValue(0),
2102
- scrollXProgress: create.motionValue(0),
2103
- scrollYProgress: create.motionValue(0),
2084
+ scrollX: motionDom.motionValue(0),
2085
+ scrollY: motionDom.motionValue(0),
2086
+ scrollXProgress: motionDom.motionValue(0),
2087
+ scrollYProgress: motionDom.motionValue(0),
2104
2088
  });
2105
2089
  function useScroll({ container, target, layoutEffect = true, ...options } = {}) {
2106
2090
  const values = create.useConstant(createScrollMotionValues);
@@ -2110,7 +2094,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
2110
2094
  useLifecycleEffect(() => {
2111
2095
  refWarning("target", target);
2112
2096
  refWarning("container", container);
2113
- return scroll((_progress, { x, y }) => {
2097
+ return scroll((_progress, { x, y, }) => {
2114
2098
  values.scrollX.set(x.current);
2115
2099
  values.scrollXProgress.set(x.progress);
2116
2100
  values.scrollY.set(y.current);
@@ -2129,7 +2113,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
2129
2113
  */
2130
2114
  function useElementScroll(ref) {
2131
2115
  if (process.env.NODE_ENV === "development") {
2132
- create.warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
2116
+ motionUtils.warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
2133
2117
  }
2134
2118
  return useScroll({ container: ref });
2135
2119
  }
@@ -2139,7 +2123,7 @@ function useElementScroll(ref) {
2139
2123
  */
2140
2124
  function useViewportScroll() {
2141
2125
  if (process.env.NODE_ENV !== "production") {
2142
- create.warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
2126
+ motionUtils.warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
2143
2127
  }
2144
2128
  return useScroll();
2145
2129
  }
@@ -2218,7 +2202,7 @@ function useSpring(source, config = {}) {
2218
2202
  return set(v);
2219
2203
  latestValue.current = v;
2220
2204
  latestSetter.current = (latest) => set(parseValue(latest, unit));
2221
- create.frame.postRender(startAnimation);
2205
+ motionDom.frame.postRender(startAnimation);
2222
2206
  return value.get();
2223
2207
  }, stopAnimation);
2224
2208
  }, [JSON.stringify(config)]);
@@ -2247,8 +2231,8 @@ function useAnimationFrame(callback) {
2247
2231
  initialTimestamp.current = timestamp;
2248
2232
  callback(timestamp - initialTimestamp.current, delta);
2249
2233
  };
2250
- create.frame.update(provideTimeSinceStart, true);
2251
- return () => create.cancelFrame(provideTimeSinceStart);
2234
+ motionDom.frame.update(provideTimeSinceStart, true);
2235
+ return () => motionDom.cancelFrame(provideTimeSinceStart);
2252
2236
  }, [callback]);
2253
2237
  }
2254
2238
 
@@ -2279,11 +2263,11 @@ function useVelocity(value) {
2279
2263
  * to keep checking until it is zero.
2280
2264
  */
2281
2265
  if (latest)
2282
- create.frame.update(updateVelocity);
2266
+ motionDom.frame.update(updateVelocity);
2283
2267
  };
2284
2268
  useMotionValueEvent(value, "change", () => {
2285
2269
  // Schedule an update to this value at the end of the current frame.
2286
- create.frame.update(updateVelocity, false, true);
2270
+ motionDom.frame.update(updateVelocity, false, true);
2287
2271
  });
2288
2272
  return velocity;
2289
2273
  }
@@ -2297,7 +2281,7 @@ function getWillChangeName(name) {
2297
2281
  }
2298
2282
  }
2299
2283
 
2300
- class WillChangeMotionValue extends create.MotionValue {
2284
+ class WillChangeMotionValue extends motionDom.MotionValue {
2301
2285
  constructor() {
2302
2286
  super(...arguments);
2303
2287
  this.values = [];
@@ -2305,7 +2289,7 @@ class WillChangeMotionValue extends create.MotionValue {
2305
2289
  add(name) {
2306
2290
  const styleName = getWillChangeName(name);
2307
2291
  if (styleName) {
2308
- create.addUniqueItem(this.values, styleName);
2292
+ motionUtils.addUniqueItem(this.values, styleName);
2309
2293
  this.update();
2310
2294
  }
2311
2295
  }
@@ -2351,7 +2335,7 @@ function useReducedMotion() {
2351
2335
  !create.hasReducedMotionListener.current && create.initPrefersReducedMotion();
2352
2336
  const [shouldReduceMotion] = React.useState(create.prefersReducedMotion.current);
2353
2337
  if (process.env.NODE_ENV !== "production") {
2354
- create.warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
2338
+ motionUtils.warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
2355
2339
  }
2356
2340
  /**
2357
2341
  * TODO See if people miss automatically updating shouldReduceMotion setting
@@ -2741,7 +2725,7 @@ function useInstantTransition() {
2741
2725
  /**
2742
2726
  * Unblock after two animation frames, otherwise this will unblock too soon.
2743
2727
  */
2744
- create.frame.postRender(() => create.frame.postRender(() => {
2728
+ motionDom.frame.postRender(() => motionDom.frame.postRender(() => {
2745
2729
  /**
2746
2730
  * If the callback has been called again after the effect
2747
2731
  * triggered this 2 frame delay, don't unblock animations. This
@@ -2767,14 +2751,14 @@ function disableInstantTransitions() {
2767
2751
  create.instantAnimationState.current = false;
2768
2752
  }
2769
2753
 
2754
+ const appearAnimationStore = new Map();
2755
+ const appearComplete = new Map();
2756
+
2770
2757
  const appearStoreId = (elementId, valueName) => {
2771
2758
  const key = create.transformProps.has(valueName) ? "transform" : valueName;
2772
2759
  return `${elementId}: ${key}`;
2773
2760
  };
2774
2761
 
2775
- const appearAnimationStore = new Map();
2776
- const appearComplete = new Map();
2777
-
2778
2762
  function handoffOptimizedAppearAnimation(elementId, valueName, frame) {
2779
2763
  var _a;
2780
2764
  const storeId = appearStoreId(elementId, valueName);
@@ -3089,8 +3073,6 @@ exports.FlatTree = create.FlatTree;
3089
3073
  exports.LayoutGroupContext = create.LayoutGroupContext;
3090
3074
  exports.MotionConfigContext = create.MotionConfigContext;
3091
3075
  exports.MotionContext = create.MotionContext;
3092
- exports.MotionGlobalConfig = create.MotionGlobalConfig;
3093
- exports.MotionValue = create.MotionValue;
3094
3076
  exports.PresenceContext = create.PresenceContext;
3095
3077
  exports.SwitchLayoutGroupContext = create.SwitchLayoutGroupContext;
3096
3078
  exports.VisualElement = create.VisualElement;
@@ -3106,7 +3088,6 @@ exports.backInOut = create.backInOut;
3106
3088
  exports.backOut = create.backOut;
3107
3089
  exports.buildTransform = create.buildTransform;
3108
3090
  exports.calcLength = create.calcLength;
3109
- exports.cancelFrame = create.cancelFrame;
3110
3091
  exports.circIn = create.circIn;
3111
3092
  exports.circInOut = create.circInOut;
3112
3093
  exports.circOut = create.circOut;
@@ -3124,9 +3105,6 @@ exports.easeInOut = create.easeInOut;
3124
3105
  exports.easeOut = create.easeOut;
3125
3106
  exports.filterProps = create.filterProps;
3126
3107
  exports.findSpring = create.findSpring;
3127
- exports.frame = create.frame;
3128
- exports.frameData = create.frameData;
3129
- exports.frameSteps = create.frameSteps;
3130
3108
  exports.inertia = create.inertia;
3131
3109
  exports.interpolate = create.interpolate;
3132
3110
  exports.isBrowser = create.isBrowser;
@@ -3136,29 +3114,31 @@ exports.keyframes = create.keyframes;
3136
3114
  exports.makeUseVisualState = create.makeUseVisualState;
3137
3115
  exports.mirrorEasing = create.mirrorEasing;
3138
3116
  exports.mix = create.mix;
3139
- exports.motionValue = create.motionValue;
3140
3117
  exports.optimizedAppearDataAttribute = create.optimizedAppearDataAttribute;
3141
3118
  exports.pipe = create.pipe;
3142
3119
  exports.px = create.px;
3143
3120
  exports.resolveMotionValue = create.resolveMotionValue;
3144
3121
  exports.reverseEasing = create.reverseEasing;
3145
3122
  exports.spring = create.spring;
3146
- exports.time = create.time;
3147
3123
  exports.useIsPresent = create.useIsPresent;
3148
3124
  exports.useIsomorphicLayoutEffect = create.useIsomorphicLayoutEffect;
3149
3125
  exports.usePresence = create.usePresence;
3150
3126
  exports.visualElementStore = create.visualElementStore;
3151
- Object.defineProperty(exports, "invariant", {
3127
+ Object.defineProperty(exports, "MotionValue", {
3152
3128
  enumerable: true,
3153
- get: function () { return motionUtils.invariant; }
3129
+ get: function () { return motionDom.MotionValue; }
3154
3130
  });
3155
- Object.defineProperty(exports, "noop", {
3131
+ Object.defineProperty(exports, "cancelFrame", {
3156
3132
  enumerable: true,
3157
- get: function () { return motionUtils.noop; }
3133
+ get: function () { return motionDom.cancelFrame; }
3158
3134
  });
3159
- Object.defineProperty(exports, "progress", {
3135
+ Object.defineProperty(exports, "frame", {
3160
3136
  enumerable: true,
3161
- get: function () { return motionUtils.progress; }
3137
+ get: function () { return motionDom.frame; }
3138
+ });
3139
+ Object.defineProperty(exports, "frameData", {
3140
+ enumerable: true,
3141
+ get: function () { return motionDom.frameData; }
3162
3142
  });
3163
3143
  Object.defineProperty(exports, "hover", {
3164
3144
  enumerable: true,
@@ -3168,10 +3148,34 @@ Object.defineProperty(exports, "isDragActive", {
3168
3148
  enumerable: true,
3169
3149
  get: function () { return motionDom.isDragActive; }
3170
3150
  });
3151
+ Object.defineProperty(exports, "motionValue", {
3152
+ enumerable: true,
3153
+ get: function () { return motionDom.motionValue; }
3154
+ });
3171
3155
  Object.defineProperty(exports, "press", {
3172
3156
  enumerable: true,
3173
3157
  get: function () { return motionDom.press; }
3174
3158
  });
3159
+ Object.defineProperty(exports, "time", {
3160
+ enumerable: true,
3161
+ get: function () { return motionDom.time; }
3162
+ });
3163
+ Object.defineProperty(exports, "MotionGlobalConfig", {
3164
+ enumerable: true,
3165
+ get: function () { return motionUtils.MotionGlobalConfig; }
3166
+ });
3167
+ Object.defineProperty(exports, "invariant", {
3168
+ enumerable: true,
3169
+ get: function () { return motionUtils.invariant; }
3170
+ });
3171
+ Object.defineProperty(exports, "noop", {
3172
+ enumerable: true,
3173
+ get: function () { return motionUtils.noop; }
3174
+ });
3175
+ Object.defineProperty(exports, "progress", {
3176
+ enumerable: true,
3177
+ get: function () { return motionUtils.progress; }
3178
+ });
3175
3179
  exports.AnimatePresence = AnimatePresence;
3176
3180
  exports.AnimateSharedLayout = AnimateSharedLayout;
3177
3181
  exports.DeprecatedLayoutGroupContext = DeprecatedLayoutGroupContext;
@@ -3183,7 +3187,6 @@ exports.Reorder = namespace;
3183
3187
  exports.animate = animate;
3184
3188
  exports.animateMini = animateMini;
3185
3189
  exports.animationControls = animationControls;
3186
- exports.cancelSync = cancelSync;
3187
3190
  exports.createScopedAnimate = createScopedAnimate;
3188
3191
  exports.disableInstantTransitions = disableInstantTransitions;
3189
3192
  exports.domAnimation = domAnimation;
@@ -3198,7 +3201,6 @@ exports.scrollInfo = scrollInfo;
3198
3201
  exports.stagger = stagger;
3199
3202
  exports.startOptimizedAppearAnimation = startOptimizedAppearAnimation;
3200
3203
  exports.steps = steps;
3201
- exports.sync = sync;
3202
3204
  exports.transform = transform;
3203
3205
  exports.unwrapMotionComponent = unwrapMotionComponent;
3204
3206
  exports.useAnimate = useAnimate;