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 (80) hide show
  1. package/dist/cjs/debug.js +12 -12
  2. package/dist/cjs/index.js +1277 -1302
  3. package/dist/cjs/mini.js +7 -7
  4. package/dist/cjs/react-client.js +535 -540
  5. package/dist/cjs/react-m.js +20 -19
  6. package/dist/cjs/react-mini.js +1 -1
  7. package/dist/es/framer-motion/dist/es/animation/animate/single-value.mjs +2 -1
  8. package/dist/es/framer-motion/dist/es/animation/animators/BaseAnimation.mjs +2 -1
  9. package/dist/es/framer-motion/dist/es/animation/animators/MainThreadAnimation.mjs +1 -1
  10. package/dist/es/framer-motion/dist/es/animation/animators/drivers/driver-frameloop.mjs +3 -2
  11. package/dist/es/framer-motion/dist/es/animation/animators/waapi/index.mjs +2 -2
  12. package/dist/es/framer-motion/dist/es/animation/generators/utils/velocity.mjs +2 -1
  13. package/dist/es/framer-motion/dist/es/animation/interfaces/motion-value.mjs +2 -2
  14. package/dist/es/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs +1 -1
  15. package/dist/es/framer-motion/dist/es/animation/optimized-appear/start.mjs +4 -4
  16. package/dist/es/framer-motion/dist/es/animation/sequence/utils/edit.mjs +2 -1
  17. package/dist/es/framer-motion/dist/es/components/AnimatePresence/index.mjs +1 -1
  18. package/dist/es/framer-motion/dist/es/components/Reorder/utils/check-reorder.mjs +2 -1
  19. package/dist/es/framer-motion/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -1
  20. package/dist/es/framer-motion/dist/es/gestures/hover.mjs +1 -1
  21. package/dist/es/framer-motion/dist/es/gestures/pan/PanSession.mjs +1 -1
  22. package/dist/es/framer-motion/dist/es/gestures/pan/index.mjs +1 -1
  23. package/dist/es/framer-motion/dist/es/gestures/press.mjs +1 -1
  24. package/dist/es/framer-motion/dist/es/motion/features/layout/MeasureLayout.mjs +3 -2
  25. package/dist/es/framer-motion/dist/es/motion/utils/use-visual-element.mjs +7 -6
  26. package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +6 -6
  27. package/dist/es/framer-motion/dist/es/projection/shared/stack.mjs +2 -1
  28. package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +6 -5
  29. package/dist/es/framer-motion/dist/es/render/components/create-proxy.mjs +2 -1
  30. package/dist/es/framer-motion/dist/es/render/dom/DOMVisualElement.mjs +1 -1
  31. package/dist/es/framer-motion/dist/es/render/dom/scroll/info.mjs +1 -1
  32. package/dist/es/framer-motion/dist/es/render/dom/scroll/observe.mjs +2 -1
  33. package/dist/es/framer-motion/dist/es/render/dom/scroll/on-scroll-handler.mjs +2 -1
  34. package/dist/es/framer-motion/dist/es/render/dom/scroll/track.mjs +2 -1
  35. package/dist/es/framer-motion/dist/es/render/svg/SVGVisualElement.mjs +2 -1
  36. package/dist/es/framer-motion/dist/es/render/svg/config-motion.mjs +2 -1
  37. package/dist/es/framer-motion/dist/es/render/utils/KeyframesResolver.mjs +2 -1
  38. package/dist/es/framer-motion/dist/es/render/utils/flat-tree.mjs +2 -1
  39. package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +4 -3
  40. package/dist/es/framer-motion/dist/es/render/utils/setters.mjs +2 -1
  41. package/dist/es/framer-motion/dist/es/utils/delay.mjs +2 -2
  42. package/dist/es/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.mjs +2 -1
  43. package/dist/es/framer-motion/dist/es/utils/use-animation-frame.mjs +2 -1
  44. package/dist/es/framer-motion/dist/es/utils/use-force-update.mjs +2 -1
  45. package/dist/es/framer-motion/dist/es/utils/use-instant-transition.mjs +2 -1
  46. package/dist/es/framer-motion/dist/es/value/scroll/use-element-scroll.mjs +2 -1
  47. package/dist/es/framer-motion/dist/es/value/scroll/use-viewport-scroll.mjs +2 -1
  48. package/dist/es/framer-motion/dist/es/value/use-combine-values.mjs +3 -2
  49. package/dist/es/framer-motion/dist/es/value/use-computed.mjs +2 -1
  50. package/dist/es/framer-motion/dist/es/value/use-inverted-scale.mjs +3 -3
  51. package/dist/es/framer-motion/dist/es/value/use-motion-value.mjs +2 -1
  52. package/dist/es/framer-motion/dist/es/value/use-scroll.mjs +4 -4
  53. package/dist/es/framer-motion/dist/es/value/use-spring.mjs +1 -1
  54. package/dist/es/framer-motion/dist/es/value/use-transform.mjs +1 -1
  55. package/dist/es/framer-motion/dist/es/value/use-velocity.mjs +2 -1
  56. package/dist/es/framer-motion/dist/es/value/use-will-change/WillChangeMotionValue.mjs +3 -2
  57. package/dist/es/motion/lib/debug.mjs +1 -1
  58. package/dist/es/motion/lib/index.mjs +3 -4
  59. package/dist/es/motion/lib/react.mjs +19 -20
  60. package/dist/es/{framer-motion → motion-dom}/dist/es/frameloop/batcher.mjs +2 -1
  61. package/dist/es/{framer-motion → motion-dom}/dist/es/frameloop/frame.mjs +1 -1
  62. package/dist/es/motion-dom/dist/es/frameloop/microtask.mjs +6 -0
  63. package/dist/es/{framer-motion → motion-dom}/dist/es/frameloop/sync-time.mjs +2 -1
  64. package/dist/es/motion-dom/dist/es/utils/supports/scroll-timeline.mjs +1 -1
  65. package/dist/es/{framer-motion → motion-dom}/dist/es/value/index.mjs +6 -11
  66. package/dist/motion.dev.js +1277 -1302
  67. package/dist/motion.js +1 -1
  68. package/package.json +3 -3
  69. package/dist/es/framer-motion/dist/es/frameloop/index-legacy.mjs +0 -20
  70. package/dist/es/framer-motion/dist/es/frameloop/microtask.mjs +0 -5
  71. package/dist/es/{framer-motion → motion-dom}/dist/es/frameloop/order.mjs +0 -0
  72. package/dist/es/{framer-motion → motion-dom}/dist/es/frameloop/render-step.mjs +0 -0
  73. package/dist/es/{framer-motion → motion-dom}/dist/es/stats/animation-count.mjs +0 -0
  74. package/dist/es/{framer-motion → motion-dom}/dist/es/stats/buffer.mjs +0 -0
  75. package/dist/es/{framer-motion → motion-dom}/dist/es/stats/index.mjs +1 -1
  76. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/array.mjs +0 -0
  77. /package/dist/es/{framer-motion/dist/es/utils/GlobalConfig.mjs → motion-utils/dist/es/global-config.mjs} +0 -0
  78. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/subscription-manager.mjs +0 -0
  79. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/velocity-per-second.mjs +0 -0
  80. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/warn-once.mjs +0 -0
@@ -51,6 +51,16 @@ function resolveVariant(visualElement, definition, custom) {
51
51
  return resolveVariantFromProps(props, definition, custom !== undefined ? custom : props.custom, visualElement);
52
52
  }
53
53
 
54
+ function addUniqueItem(arr, item) {
55
+ if (arr.indexOf(item) === -1)
56
+ arr.push(item);
57
+ }
58
+ function removeItem(arr, item) {
59
+ const index = arr.indexOf(item);
60
+ if (index > -1)
61
+ arr.splice(index, 1);
62
+ }
63
+
54
64
  /*#__NO_SIDE_EFFECTS__*/
55
65
  const noop = (any) => any;
56
66
 
@@ -69,6 +79,11 @@ if (process.env.NODE_ENV !== "production") {
69
79
  };
70
80
  }
71
81
 
82
+ const MotionGlobalConfig = {
83
+ skipAnimations: false,
84
+ useManualTiming: false,
85
+ };
86
+
72
87
  /*#__NO_SIDE_EFFECTS__*/
73
88
  function memo(callback) {
74
89
  let result;
@@ -97,6 +112,43 @@ const progress = (from, to, value) => {
97
112
  return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
98
113
  };
99
114
 
115
+ class SubscriptionManager {
116
+ constructor() {
117
+ this.subscriptions = [];
118
+ }
119
+ add(handler) {
120
+ addUniqueItem(this.subscriptions, handler);
121
+ return () => removeItem(this.subscriptions, handler);
122
+ }
123
+ notify(a, b, c) {
124
+ const numSubscriptions = this.subscriptions.length;
125
+ if (!numSubscriptions)
126
+ return;
127
+ if (numSubscriptions === 1) {
128
+ /**
129
+ * If there's only a single handler we can just call it without invoking a loop.
130
+ */
131
+ this.subscriptions[0](a, b, c);
132
+ }
133
+ else {
134
+ for (let i = 0; i < numSubscriptions; i++) {
135
+ /**
136
+ * Check whether the handler exists before firing as it's possible
137
+ * the subscriptions were modified during this loop running.
138
+ */
139
+ const handler = this.subscriptions[i];
140
+ handler && handler(a, b, c);
141
+ }
142
+ }
143
+ }
144
+ getSize() {
145
+ return this.subscriptions.length;
146
+ }
147
+ clear() {
148
+ this.subscriptions.length = 0;
149
+ }
150
+ }
151
+
100
152
  /**
101
153
  * Converts seconds to milliseconds
102
154
  *
@@ -108,7 +160,27 @@ const secondsToMilliseconds = (seconds) => seconds * 1000;
108
160
  /*#__NO_SIDE_EFFECTS__*/
109
161
  const millisecondsToSeconds = (milliseconds) => milliseconds / 1000;
110
162
 
111
- const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
163
+ /*
164
+ Convert velocity into velocity per second
165
+
166
+ @param [number]: Unit per frame
167
+ @param [number]: Frame duration in ms
168
+ */
169
+ function velocityPerSecond(velocity, frameDuration) {
170
+ return frameDuration ? velocity * (1000 / frameDuration) : 0;
171
+ }
172
+
173
+ const warned = new Set();
174
+ function warnOnce(condition, message, element) {
175
+ if (condition || warned.has(message))
176
+ return;
177
+ console.warn(message);
178
+ if (element)
179
+ console.warn(element);
180
+ warned.add(message);
181
+ }
182
+
183
+ const supportsScrollTimeline = /* @__PURE__ */ memo(() => window.ScrollTimeline !== undefined);
112
184
 
113
185
  class BaseGroupPlaybackControls {
114
186
  constructor(animations) {
@@ -309,454 +381,107 @@ function mapEasingToNativeEasing(easing, duration) {
309
381
  }
310
382
  }
311
383
 
312
- const isDragging = {
313
- x: false,
314
- y: false,
384
+ const stepsOrder = [
385
+ "read", // Read
386
+ "resolveKeyframes", // Write/Read/Write/Read
387
+ "update", // Compute
388
+ "preRender", // Compute
389
+ "render", // Write
390
+ "postRender", // Compute
391
+ ];
392
+
393
+ const statsBuffer = {
394
+ value: null,
395
+ addProjectionMetrics: null,
315
396
  };
316
- function isDragActive() {
317
- return isDragging.x || isDragging.y;
318
- }
319
397
 
320
- function resolveElements(elementOrSelector, scope, selectorCache) {
321
- var _a;
322
- if (elementOrSelector instanceof EventTarget) {
323
- return [elementOrSelector];
324
- }
325
- else if (typeof elementOrSelector === "string") {
326
- let root = document;
327
- if (scope) {
328
- // TODO: Refactor to utils package
329
- // invariant(
330
- // Boolean(scope.current),
331
- // "Scope provided, but no element detected."
332
- // )
333
- root = scope.current;
398
+ function createRenderStep(runNextFrame, stepName) {
399
+ /**
400
+ * We create and reuse two queues, one to queue jobs for the current frame
401
+ * and one for the next. We reuse to avoid triggering GC after x frames.
402
+ */
403
+ let thisFrame = new Set();
404
+ let nextFrame = new Set();
405
+ /**
406
+ * Track whether we're currently processing jobs in this step. This way
407
+ * we can decide whether to schedule new jobs for this frame or next.
408
+ */
409
+ let isProcessing = false;
410
+ let flushNextFrame = false;
411
+ /**
412
+ * A set of processes which were marked keepAlive when scheduled.
413
+ */
414
+ const toKeepAlive = new WeakSet();
415
+ let latestFrameData = {
416
+ delta: 0.0,
417
+ timestamp: 0.0,
418
+ isProcessing: false,
419
+ };
420
+ let numCalls = 0;
421
+ function triggerCallback(callback) {
422
+ if (toKeepAlive.has(callback)) {
423
+ step.schedule(callback);
424
+ runNextFrame();
334
425
  }
335
- const elements = (_a = selectorCache === null || selectorCache === void 0 ? void 0 : selectorCache[elementOrSelector]) !== null && _a !== void 0 ? _a : root.querySelectorAll(elementOrSelector);
336
- return elements ? Array.from(elements) : [];
426
+ numCalls++;
427
+ callback(latestFrameData);
337
428
  }
338
- return Array.from(elementOrSelector);
339
- }
340
-
341
- function setupGesture(elementOrSelector, options) {
342
- const elements = resolveElements(elementOrSelector);
343
- const gestureAbortController = new AbortController();
344
- const eventOptions = {
345
- passive: true,
346
- ...options,
347
- signal: gestureAbortController.signal,
348
- };
349
- const cancel = () => gestureAbortController.abort();
350
- return [elements, eventOptions, cancel];
351
- }
352
-
353
- function isValidHover(event) {
354
- return !(event.pointerType === "touch" || isDragActive());
355
- }
356
- /**
357
- * Create a hover gesture. hover() is different to .addEventListener("pointerenter")
358
- * in that it has an easier syntax, filters out polyfilled touch events, interoperates
359
- * with drag gestures, and automatically removes the "pointerennd" event listener when the hover ends.
360
- *
361
- * @public
362
- */
363
- function hover(elementOrSelector, onHoverStart, options = {}) {
364
- const [elements, eventOptions, cancel] = setupGesture(elementOrSelector, options);
365
- const onPointerEnter = (enterEvent) => {
366
- if (!isValidHover(enterEvent))
367
- return;
368
- const { target } = enterEvent;
369
- const onHoverEnd = onHoverStart(target, enterEvent);
370
- if (typeof onHoverEnd !== "function" || !target)
371
- return;
372
- const onPointerLeave = (leaveEvent) => {
373
- if (!isValidHover(leaveEvent))
429
+ const step = {
430
+ /**
431
+ * Schedule a process to run on the next frame.
432
+ */
433
+ schedule: (callback, keepAlive = false, immediate = false) => {
434
+ const addToCurrentFrame = immediate && isProcessing;
435
+ const queue = addToCurrentFrame ? thisFrame : nextFrame;
436
+ if (keepAlive)
437
+ toKeepAlive.add(callback);
438
+ if (!queue.has(callback))
439
+ queue.add(callback);
440
+ return callback;
441
+ },
442
+ /**
443
+ * Cancel the provided callback from running on the next frame.
444
+ */
445
+ cancel: (callback) => {
446
+ nextFrame.delete(callback);
447
+ toKeepAlive.delete(callback);
448
+ },
449
+ /**
450
+ * Execute all schedule callbacks.
451
+ */
452
+ process: (frameData) => {
453
+ latestFrameData = frameData;
454
+ /**
455
+ * If we're already processing we've probably been triggered by a flushSync
456
+ * inside an existing process. Instead of executing, mark flushNextFrame
457
+ * as true and ensure we flush the following frame at the end of this one.
458
+ */
459
+ if (isProcessing) {
460
+ flushNextFrame = true;
374
461
  return;
375
- onHoverEnd(leaveEvent);
376
- target.removeEventListener("pointerleave", onPointerLeave);
377
- };
378
- target.addEventListener("pointerleave", onPointerLeave, eventOptions);
462
+ }
463
+ isProcessing = true;
464
+ [thisFrame, nextFrame] = [nextFrame, thisFrame];
465
+ // Execute this frame
466
+ thisFrame.forEach(triggerCallback);
467
+ /**
468
+ * If we're recording stats then
469
+ */
470
+ if (stepName && statsBuffer.value) {
471
+ statsBuffer.value.frameloop[stepName].push(numCalls);
472
+ }
473
+ numCalls = 0;
474
+ // Clear the frame so no callbacks remain. This is to avoid
475
+ // memory leaks should this render step not run for a while.
476
+ thisFrame.clear();
477
+ isProcessing = false;
478
+ if (flushNextFrame) {
479
+ flushNextFrame = false;
480
+ step.process(frameData);
481
+ }
482
+ },
379
483
  };
380
- elements.forEach((element) => {
381
- element.addEventListener("pointerenter", onPointerEnter, eventOptions);
382
- });
383
- return cancel;
384
- }
385
-
386
- function capturePointer(event, action) {
387
- const actionName = `${action}PointerCapture`;
388
- if (event.target instanceof Element &&
389
- actionName in event.target &&
390
- event.pointerId !== undefined) {
391
- try {
392
- event.target[actionName](event.pointerId);
393
- }
394
- catch (e) { }
395
- }
396
- }
397
-
398
- /**
399
- * Recursively traverse up the tree to check whether the provided child node
400
- * is the parent or a descendant of it.
401
- *
402
- * @param parent - Element to find
403
- * @param child - Element to test against parent
404
- */
405
- const isNodeOrChild = (parent, child) => {
406
- if (!child) {
407
- return false;
408
- }
409
- else if (parent === child) {
410
- return true;
411
- }
412
- else {
413
- return isNodeOrChild(parent, child.parentElement);
414
- }
415
- };
416
-
417
- const isPrimaryPointer = (event) => {
418
- if (event.pointerType === "mouse") {
419
- return typeof event.button !== "number" || event.button <= 0;
420
- }
421
- else {
422
- /**
423
- * isPrimary is true for all mice buttons, whereas every touch point
424
- * is regarded as its own input. So subsequent concurrent touch points
425
- * will be false.
426
- *
427
- * Specifically match against false here as incomplete versions of
428
- * PointerEvents in very old browser might have it set as undefined.
429
- */
430
- return event.isPrimary !== false;
431
- }
432
- };
433
-
434
- const focusableElements = new Set([
435
- "BUTTON",
436
- "INPUT",
437
- "SELECT",
438
- "TEXTAREA",
439
- "A",
440
- ]);
441
- function isElementKeyboardAccessible(element) {
442
- return (focusableElements.has(element.tagName) ||
443
- element.tabIndex !== -1);
444
- }
445
-
446
- const isPressing = new WeakSet();
447
-
448
- /**
449
- * Filter out events that are not "Enter" keys.
450
- */
451
- function filterEvents(callback) {
452
- return (event) => {
453
- if (event.key !== "Enter")
454
- return;
455
- callback(event);
456
- };
457
- }
458
- function firePointerEvent(target, type) {
459
- target.dispatchEvent(new PointerEvent("pointer" + type, { isPrimary: true, bubbles: true }));
460
- }
461
- const enableKeyboardPress = (focusEvent, eventOptions) => {
462
- const element = focusEvent.currentTarget;
463
- if (!element)
464
- return;
465
- const handleKeydown = filterEvents(() => {
466
- if (isPressing.has(element))
467
- return;
468
- firePointerEvent(element, "down");
469
- const handleKeyup = filterEvents(() => {
470
- firePointerEvent(element, "up");
471
- });
472
- const handleBlur = () => firePointerEvent(element, "cancel");
473
- element.addEventListener("keyup", handleKeyup, eventOptions);
474
- element.addEventListener("blur", handleBlur, eventOptions);
475
- });
476
- element.addEventListener("keydown", handleKeydown, eventOptions);
477
- /**
478
- * Add an event listener that fires on blur to remove the keydown events.
479
- */
480
- element.addEventListener("blur", () => element.removeEventListener("keydown", handleKeydown), eventOptions);
481
- };
482
-
483
- /**
484
- * Filter out events that are not primary pointer events, or are triggering
485
- * while a Motion gesture is active.
486
- */
487
- function isValidPressEvent(event) {
488
- return isPrimaryPointer(event) && !isDragActive();
489
- }
490
- /**
491
- * Create a press gesture.
492
- *
493
- * Press is different to `"pointerdown"`, `"pointerup"` in that it
494
- * automatically filters out secondary pointer events like right
495
- * click and multitouch.
496
- *
497
- * It also adds accessibility support for keyboards, where
498
- * an element with a press gesture will receive focus and
499
- * trigger on Enter `"keydown"` and `"keyup"` events.
500
- *
501
- * This is different to a browser's `"click"` event, which does
502
- * respond to keyboards but only for the `"click"` itself, rather
503
- * than the press start and end/cancel. The element also needs
504
- * to be focusable for this to work, whereas a press gesture will
505
- * make an element focusable by default.
506
- *
507
- * @public
508
- */
509
- function press(targetOrSelector, onPressStart, options = {}) {
510
- const [targets, eventOptions, cancelEvents] = setupGesture(targetOrSelector, options);
511
- const startPress = (startEvent) => {
512
- const target = startEvent.currentTarget;
513
- if (!target || !isValidPressEvent(startEvent) || isPressing.has(target))
514
- return;
515
- isPressing.add(target);
516
- capturePointer(startEvent, "set");
517
- const onPressEnd = onPressStart(target, startEvent);
518
- const onPointerEnd = (endEvent, success) => {
519
- target.removeEventListener("pointerup", onPointerUp);
520
- target.removeEventListener("pointercancel", onPointerCancel);
521
- capturePointer(endEvent, "release");
522
- if (!isValidPressEvent(endEvent) || !isPressing.has(target)) {
523
- return;
524
- }
525
- isPressing.delete(target);
526
- if (typeof onPressEnd === "function") {
527
- onPressEnd(endEvent, { success });
528
- }
529
- };
530
- const onPointerUp = (upEvent) => {
531
- const isOutside = !upEvent.isTrusted
532
- ? false
533
- : checkOutside(upEvent, target instanceof Element
534
- ? target.getBoundingClientRect()
535
- : {
536
- left: 0,
537
- top: 0,
538
- right: window.innerWidth,
539
- bottom: window.innerHeight,
540
- });
541
- if (isOutside) {
542
- onPointerEnd(upEvent, false);
543
- }
544
- else {
545
- onPointerEnd(upEvent, !(target instanceof Element) ||
546
- isNodeOrChild(target, upEvent.target));
547
- }
548
- };
549
- const onPointerCancel = (cancelEvent) => {
550
- onPointerEnd(cancelEvent, false);
551
- };
552
- target.addEventListener("pointerup", onPointerUp, eventOptions);
553
- target.addEventListener("pointercancel", onPointerCancel, eventOptions);
554
- target.addEventListener("lostpointercapture", onPointerCancel, eventOptions);
555
- };
556
- targets.forEach((target) => {
557
- target = options.useGlobalTarget ? window : target;
558
- let canAddKeyboardAccessibility = false;
559
- if (target instanceof HTMLElement) {
560
- canAddKeyboardAccessibility = true;
561
- if (!isElementKeyboardAccessible(target) &&
562
- target.getAttribute("tabindex") === null) {
563
- target.tabIndex = 0;
564
- }
565
- }
566
- target.addEventListener("pointerdown", startPress, eventOptions);
567
- if (canAddKeyboardAccessibility) {
568
- target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions), eventOptions);
569
- }
570
- });
571
- return cancelEvents;
572
- }
573
- function checkOutside(event, rect) {
574
- return (event.clientX < rect.left ||
575
- event.clientX > rect.right ||
576
- event.clientY < rect.top ||
577
- event.clientY > rect.bottom);
578
- }
579
-
580
- function setDragLock(axis) {
581
- if (axis === "x" || axis === "y") {
582
- if (isDragging[axis]) {
583
- return null;
584
- }
585
- else {
586
- isDragging[axis] = true;
587
- return () => {
588
- isDragging[axis] = false;
589
- };
590
- }
591
- }
592
- else {
593
- if (isDragging.x || isDragging.y) {
594
- return null;
595
- }
596
- else {
597
- isDragging.x = isDragging.y = true;
598
- return () => {
599
- isDragging.x = isDragging.y = false;
600
- };
601
- }
602
- }
603
- }
604
-
605
- /**
606
- * Generate a list of every possible transform key.
607
- */
608
- const transformPropOrder = [
609
- "transformPerspective",
610
- "x",
611
- "y",
612
- "z",
613
- "translateX",
614
- "translateY",
615
- "translateZ",
616
- "scale",
617
- "scaleX",
618
- "scaleY",
619
- "rotate",
620
- "rotateX",
621
- "rotateY",
622
- "rotateZ",
623
- "skew",
624
- "skewX",
625
- "skewY",
626
- ];
627
- /**
628
- * A quick lookup for transform props.
629
- */
630
- const transformProps = new Set(transformPropOrder);
631
-
632
- const positionalKeys = new Set([
633
- "width",
634
- "height",
635
- "top",
636
- "left",
637
- "right",
638
- "bottom",
639
- ...transformPropOrder,
640
- ]);
641
-
642
- const isKeyframesTarget = (v) => {
643
- return Array.isArray(v);
644
- };
645
-
646
- const isCustomValue = (v) => {
647
- return Boolean(v && typeof v === "object" && v.mix && v.toValue);
648
- };
649
- const resolveFinalValueInKeyframes = (v) => {
650
- // TODO maybe throw if v.length - 1 is placeholder token?
651
- return isKeyframesTarget(v) ? v[v.length - 1] || 0 : v;
652
- };
653
-
654
- const MotionGlobalConfig = {
655
- skipAnimations: false,
656
- useManualTiming: false,
657
- };
658
-
659
- const stepsOrder = [
660
- "read", // Read
661
- "resolveKeyframes", // Write/Read/Write/Read
662
- "update", // Compute
663
- "preRender", // Compute
664
- "render", // Write
665
- "postRender", // Compute
666
- ];
667
-
668
- const statsBuffer = {
669
- value: null,
670
- addProjectionMetrics: null,
671
- };
672
-
673
- function createRenderStep(runNextFrame, stepName) {
674
- /**
675
- * We create and reuse two queues, one to queue jobs for the current frame
676
- * and one for the next. We reuse to avoid triggering GC after x frames.
677
- */
678
- let thisFrame = new Set();
679
- let nextFrame = new Set();
680
- /**
681
- * Track whether we're currently processing jobs in this step. This way
682
- * we can decide whether to schedule new jobs for this frame or next.
683
- */
684
- let isProcessing = false;
685
- let flushNextFrame = false;
686
- /**
687
- * A set of processes which were marked keepAlive when scheduled.
688
- */
689
- const toKeepAlive = new WeakSet();
690
- let latestFrameData = {
691
- delta: 0.0,
692
- timestamp: 0.0,
693
- isProcessing: false,
694
- };
695
- let numCalls = 0;
696
- function triggerCallback(callback) {
697
- if (toKeepAlive.has(callback)) {
698
- step.schedule(callback);
699
- runNextFrame();
700
- }
701
- numCalls++;
702
- callback(latestFrameData);
703
- }
704
- const step = {
705
- /**
706
- * Schedule a process to run on the next frame.
707
- */
708
- schedule: (callback, keepAlive = false, immediate = false) => {
709
- const addToCurrentFrame = immediate && isProcessing;
710
- const queue = addToCurrentFrame ? thisFrame : nextFrame;
711
- if (keepAlive)
712
- toKeepAlive.add(callback);
713
- if (!queue.has(callback))
714
- queue.add(callback);
715
- return callback;
716
- },
717
- /**
718
- * Cancel the provided callback from running on the next frame.
719
- */
720
- cancel: (callback) => {
721
- nextFrame.delete(callback);
722
- toKeepAlive.delete(callback);
723
- },
724
- /**
725
- * Execute all schedule callbacks.
726
- */
727
- process: (frameData) => {
728
- latestFrameData = frameData;
729
- /**
730
- * If we're already processing we've probably been triggered by a flushSync
731
- * inside an existing process. Instead of executing, mark flushNextFrame
732
- * as true and ensure we flush the following frame at the end of this one.
733
- */
734
- if (isProcessing) {
735
- flushNextFrame = true;
736
- return;
737
- }
738
- isProcessing = true;
739
- [thisFrame, nextFrame] = [nextFrame, thisFrame];
740
- // Execute this frame
741
- thisFrame.forEach(triggerCallback);
742
- /**
743
- * If we're recording stats then
744
- */
745
- if (stepName && statsBuffer.value) {
746
- statsBuffer.value.frameloop[stepName].push(numCalls);
747
- }
748
- numCalls = 0;
749
- // Clear the frame so no callbacks remain. This is to avoid
750
- // memory leaks should this render step not run for a while.
751
- thisFrame.clear();
752
- isProcessing = false;
753
- if (flushNextFrame) {
754
- flushNextFrame = false;
755
- step.process(frameData);
756
- }
757
- },
758
- };
759
- return step;
484
+ return step;
760
485
  }
761
486
 
762
487
  const maxElapsed = 40;
@@ -818,103 +543,332 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
818
543
  steps[stepsOrder[i]].cancel(process);
819
544
  }
820
545
  };
821
- return { schedule, cancel, state, steps };
546
+ return { schedule, cancel, state, steps };
547
+ }
548
+
549
+ const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = /* @__PURE__ */ createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
550
+
551
+ const { schedule: microtask, cancel: cancelMicrotask } =
552
+ /* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
553
+
554
+ let now;
555
+ function clearTime() {
556
+ now = undefined;
557
+ }
558
+ /**
559
+ * An eventloop-synchronous alternative to performance.now().
560
+ *
561
+ * Ensures that time measurements remain consistent within a synchronous context.
562
+ * Usually calling performance.now() twice within the same synchronous context
563
+ * will return different values which isn't useful for animations when we're usually
564
+ * trying to sync animations to the same frame.
565
+ */
566
+ const time = {
567
+ now: () => {
568
+ if (now === undefined) {
569
+ time.set(frameData.isProcessing || MotionGlobalConfig.useManualTiming
570
+ ? frameData.timestamp
571
+ : performance.now());
572
+ }
573
+ return now;
574
+ },
575
+ set: (newTime) => {
576
+ now = newTime;
577
+ queueMicrotask(clearTime);
578
+ },
579
+ };
580
+
581
+ const isDragging = {
582
+ x: false,
583
+ y: false,
584
+ };
585
+ function isDragActive() {
586
+ return isDragging.x || isDragging.y;
587
+ }
588
+
589
+ function setDragLock(axis) {
590
+ if (axis === "x" || axis === "y") {
591
+ if (isDragging[axis]) {
592
+ return null;
593
+ }
594
+ else {
595
+ isDragging[axis] = true;
596
+ return () => {
597
+ isDragging[axis] = false;
598
+ };
599
+ }
600
+ }
601
+ else {
602
+ if (isDragging.x || isDragging.y) {
603
+ return null;
604
+ }
605
+ else {
606
+ isDragging.x = isDragging.y = true;
607
+ return () => {
608
+ isDragging.x = isDragging.y = false;
609
+ };
610
+ }
611
+ }
612
+ }
613
+
614
+ function resolveElements(elementOrSelector, scope, selectorCache) {
615
+ var _a;
616
+ if (elementOrSelector instanceof EventTarget) {
617
+ return [elementOrSelector];
618
+ }
619
+ else if (typeof elementOrSelector === "string") {
620
+ let root = document;
621
+ if (scope) {
622
+ // TODO: Refactor to utils package
623
+ // invariant(
624
+ // Boolean(scope.current),
625
+ // "Scope provided, but no element detected."
626
+ // )
627
+ root = scope.current;
628
+ }
629
+ const elements = (_a = selectorCache === null || selectorCache === void 0 ? void 0 : selectorCache[elementOrSelector]) !== null && _a !== void 0 ? _a : root.querySelectorAll(elementOrSelector);
630
+ return elements ? Array.from(elements) : [];
631
+ }
632
+ return Array.from(elementOrSelector);
633
+ }
634
+
635
+ function setupGesture(elementOrSelector, options) {
636
+ const elements = resolveElements(elementOrSelector);
637
+ const gestureAbortController = new AbortController();
638
+ const eventOptions = {
639
+ passive: true,
640
+ ...options,
641
+ signal: gestureAbortController.signal,
642
+ };
643
+ const cancel = () => gestureAbortController.abort();
644
+ return [elements, eventOptions, cancel];
645
+ }
646
+
647
+ function isValidHover(event) {
648
+ return !(event.pointerType === "touch" || isDragActive());
649
+ }
650
+ /**
651
+ * Create a hover gesture. hover() is different to .addEventListener("pointerenter")
652
+ * in that it has an easier syntax, filters out polyfilled touch events, interoperates
653
+ * with drag gestures, and automatically removes the "pointerennd" event listener when the hover ends.
654
+ *
655
+ * @public
656
+ */
657
+ function hover(elementOrSelector, onHoverStart, options = {}) {
658
+ const [elements, eventOptions, cancel] = setupGesture(elementOrSelector, options);
659
+ const onPointerEnter = (enterEvent) => {
660
+ if (!isValidHover(enterEvent))
661
+ return;
662
+ const { target } = enterEvent;
663
+ const onHoverEnd = onHoverStart(target, enterEvent);
664
+ if (typeof onHoverEnd !== "function" || !target)
665
+ return;
666
+ const onPointerLeave = (leaveEvent) => {
667
+ if (!isValidHover(leaveEvent))
668
+ return;
669
+ onHoverEnd(leaveEvent);
670
+ target.removeEventListener("pointerleave", onPointerLeave);
671
+ };
672
+ target.addEventListener("pointerleave", onPointerLeave, eventOptions);
673
+ };
674
+ elements.forEach((element) => {
675
+ element.addEventListener("pointerenter", onPointerEnter, eventOptions);
676
+ });
677
+ return cancel;
678
+ }
679
+
680
+ function capturePointer(event, action) {
681
+ const actionName = `${action}PointerCapture`;
682
+ if (event.target instanceof Element &&
683
+ actionName in event.target &&
684
+ event.pointerId !== undefined) {
685
+ try {
686
+ event.target[actionName](event.pointerId);
687
+ }
688
+ catch (e) { }
689
+ }
690
+ }
691
+
692
+ /**
693
+ * Recursively traverse up the tree to check whether the provided child node
694
+ * is the parent or a descendant of it.
695
+ *
696
+ * @param parent - Element to find
697
+ * @param child - Element to test against parent
698
+ */
699
+ const isNodeOrChild = (parent, child) => {
700
+ if (!child) {
701
+ return false;
702
+ }
703
+ else if (parent === child) {
704
+ return true;
705
+ }
706
+ else {
707
+ return isNodeOrChild(parent, child.parentElement);
708
+ }
709
+ };
710
+
711
+ const isPrimaryPointer = (event) => {
712
+ if (event.pointerType === "mouse") {
713
+ return typeof event.button !== "number" || event.button <= 0;
714
+ }
715
+ else {
716
+ /**
717
+ * isPrimary is true for all mice buttons, whereas every touch point
718
+ * is regarded as its own input. So subsequent concurrent touch points
719
+ * will be false.
720
+ *
721
+ * Specifically match against false here as incomplete versions of
722
+ * PointerEvents in very old browser might have it set as undefined.
723
+ */
724
+ return event.isPrimary !== false;
725
+ }
726
+ };
727
+
728
+ const focusableElements = new Set([
729
+ "BUTTON",
730
+ "INPUT",
731
+ "SELECT",
732
+ "TEXTAREA",
733
+ "A",
734
+ ]);
735
+ function isElementKeyboardAccessible(element) {
736
+ return (focusableElements.has(element.tagName) ||
737
+ element.tabIndex !== -1);
738
+ }
739
+
740
+ const isPressing = new WeakSet();
741
+
742
+ /**
743
+ * Filter out events that are not "Enter" keys.
744
+ */
745
+ function filterEvents(callback) {
746
+ return (event) => {
747
+ if (event.key !== "Enter")
748
+ return;
749
+ callback(event);
750
+ };
822
751
  }
752
+ function firePointerEvent(target, type) {
753
+ target.dispatchEvent(new PointerEvent("pointer" + type, { isPrimary: true, bubbles: true }));
754
+ }
755
+ const enableKeyboardPress = (focusEvent, eventOptions) => {
756
+ const element = focusEvent.currentTarget;
757
+ if (!element)
758
+ return;
759
+ const handleKeydown = filterEvents(() => {
760
+ if (isPressing.has(element))
761
+ return;
762
+ firePointerEvent(element, "down");
763
+ const handleKeyup = filterEvents(() => {
764
+ firePointerEvent(element, "up");
765
+ });
766
+ const handleBlur = () => firePointerEvent(element, "cancel");
767
+ element.addEventListener("keyup", handleKeyup, eventOptions);
768
+ element.addEventListener("blur", handleBlur, eventOptions);
769
+ });
770
+ element.addEventListener("keydown", handleKeydown, eventOptions);
771
+ /**
772
+ * Add an event listener that fires on blur to remove the keydown events.
773
+ */
774
+ element.addEventListener("blur", () => element.removeEventListener("keydown", handleKeydown), eventOptions);
775
+ };
823
776
 
824
- const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
825
-
826
- let now;
827
- function clearTime() {
828
- now = undefined;
777
+ /**
778
+ * Filter out events that are not primary pointer events, or are triggering
779
+ * while a Motion gesture is active.
780
+ */
781
+ function isValidPressEvent(event) {
782
+ return isPrimaryPointer(event) && !isDragActive();
829
783
  }
830
784
  /**
831
- * An eventloop-synchronous alternative to performance.now().
785
+ * Create a press gesture.
832
786
  *
833
- * Ensures that time measurements remain consistent within a synchronous context.
834
- * Usually calling performance.now() twice within the same synchronous context
835
- * will return different values which isn't useful for animations when we're usually
836
- * trying to sync animations to the same frame.
787
+ * Press is different to `"pointerdown"`, `"pointerup"` in that it
788
+ * automatically filters out secondary pointer events like right
789
+ * click and multitouch.
790
+ *
791
+ * It also adds accessibility support for keyboards, where
792
+ * an element with a press gesture will receive focus and
793
+ * trigger on Enter `"keydown"` and `"keyup"` events.
794
+ *
795
+ * This is different to a browser's `"click"` event, which does
796
+ * respond to keyboards but only for the `"click"` itself, rather
797
+ * than the press start and end/cancel. The element also needs
798
+ * to be focusable for this to work, whereas a press gesture will
799
+ * make an element focusable by default.
800
+ *
801
+ * @public
837
802
  */
838
- const time = {
839
- now: () => {
840
- if (now === undefined) {
841
- time.set(frameData.isProcessing || MotionGlobalConfig.useManualTiming
842
- ? frameData.timestamp
843
- : performance.now());
844
- }
845
- return now;
846
- },
847
- set: (newTime) => {
848
- now = newTime;
849
- queueMicrotask(clearTime);
850
- },
851
- };
852
-
853
- function addUniqueItem(arr, item) {
854
- if (arr.indexOf(item) === -1)
855
- arr.push(item);
856
- }
857
- function removeItem(arr, item) {
858
- const index = arr.indexOf(item);
859
- if (index > -1)
860
- arr.splice(index, 1);
861
- }
862
-
863
- class SubscriptionManager {
864
- constructor() {
865
- this.subscriptions = [];
866
- }
867
- add(handler) {
868
- addUniqueItem(this.subscriptions, handler);
869
- return () => removeItem(this.subscriptions, handler);
870
- }
871
- notify(a, b, c) {
872
- const numSubscriptions = this.subscriptions.length;
873
- if (!numSubscriptions)
803
+ function press(targetOrSelector, onPressStart, options = {}) {
804
+ const [targets, eventOptions, cancelEvents] = setupGesture(targetOrSelector, options);
805
+ const startPress = (startEvent) => {
806
+ const target = startEvent.currentTarget;
807
+ if (!target || !isValidPressEvent(startEvent) || isPressing.has(target))
874
808
  return;
875
- if (numSubscriptions === 1) {
876
- /**
877
- * If there's only a single handler we can just call it without invoking a loop.
878
- */
879
- this.subscriptions[0](a, b, c);
880
- }
881
- else {
882
- for (let i = 0; i < numSubscriptions; i++) {
883
- /**
884
- * Check whether the handler exists before firing as it's possible
885
- * the subscriptions were modified during this loop running.
886
- */
887
- const handler = this.subscriptions[i];
888
- handler && handler(a, b, c);
809
+ isPressing.add(target);
810
+ capturePointer(startEvent, "set");
811
+ const onPressEnd = onPressStart(target, startEvent);
812
+ const onPointerEnd = (endEvent, success) => {
813
+ target.removeEventListener("pointerup", onPointerUp);
814
+ target.removeEventListener("pointercancel", onPointerCancel);
815
+ capturePointer(endEvent, "release");
816
+ if (!isValidPressEvent(endEvent) || !isPressing.has(target)) {
817
+ return;
818
+ }
819
+ isPressing.delete(target);
820
+ if (typeof onPressEnd === "function") {
821
+ onPressEnd(endEvent, { success });
822
+ }
823
+ };
824
+ const onPointerUp = (upEvent) => {
825
+ const isOutside = !upEvent.isTrusted
826
+ ? false
827
+ : checkOutside(upEvent, target instanceof Element
828
+ ? target.getBoundingClientRect()
829
+ : {
830
+ left: 0,
831
+ top: 0,
832
+ right: window.innerWidth,
833
+ bottom: window.innerHeight,
834
+ });
835
+ if (isOutside) {
836
+ onPointerEnd(upEvent, false);
837
+ }
838
+ else {
839
+ onPointerEnd(upEvent, !(target instanceof Element) ||
840
+ isNodeOrChild(target, upEvent.target));
841
+ }
842
+ };
843
+ const onPointerCancel = (cancelEvent) => {
844
+ onPointerEnd(cancelEvent, false);
845
+ };
846
+ target.addEventListener("pointerup", onPointerUp, eventOptions);
847
+ target.addEventListener("pointercancel", onPointerCancel, eventOptions);
848
+ target.addEventListener("lostpointercapture", onPointerCancel, eventOptions);
849
+ };
850
+ targets.forEach((target) => {
851
+ target = options.useGlobalTarget ? window : target;
852
+ let canAddKeyboardAccessibility = false;
853
+ if (target instanceof HTMLElement) {
854
+ canAddKeyboardAccessibility = true;
855
+ if (!isElementKeyboardAccessible(target) &&
856
+ target.getAttribute("tabindex") === null) {
857
+ target.tabIndex = 0;
889
858
  }
890
859
  }
891
- }
892
- getSize() {
893
- return this.subscriptions.length;
894
- }
895
- clear() {
896
- this.subscriptions.length = 0;
897
- }
898
- }
899
-
900
- /*
901
- Convert velocity into velocity per second
902
-
903
- @param [number]: Unit per frame
904
- @param [number]: Frame duration in ms
905
- */
906
- function velocityPerSecond(velocity, frameDuration) {
907
- return frameDuration ? velocity * (1000 / frameDuration) : 0;
860
+ target.addEventListener("pointerdown", startPress, eventOptions);
861
+ if (canAddKeyboardAccessibility) {
862
+ target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions), eventOptions);
863
+ }
864
+ });
865
+ return cancelEvents;
908
866
  }
909
-
910
- const warned = new Set();
911
- function warnOnce(condition, message, element) {
912
- if (condition || warned.has(message))
913
- return;
914
- console.warn(message);
915
- if (element)
916
- console.warn(element);
917
- warned.add(message);
867
+ function checkOutside(event, rect) {
868
+ return (event.clientX < rect.left ||
869
+ event.clientX > rect.right ||
870
+ event.clientY < rect.top ||
871
+ event.clientY > rect.bottom);
918
872
  }
919
873
 
920
874
  /**
@@ -936,15 +890,13 @@ class MotionValue {
936
890
  * @param config - Optional configuration options
937
891
  *
938
892
  * - `transformer`: A function to transform incoming values with.
939
- *
940
- * @internal
941
893
  */
942
894
  constructor(init, options = {}) {
943
895
  /**
944
896
  * This will be replaced by the build step with the latest version number.
945
897
  * When MotionValues are provided to motion components, warn if versions are mixed.
946
898
  */
947
- this.version = "12.4.13";
899
+ this.version = "12.5.0";
948
900
  /**
949
901
  * Tracks whether this value can output a velocity. Currently this is only true
950
902
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -1067,8 +1019,6 @@ class MotionValue {
1067
1019
  }
1068
1020
  /**
1069
1021
  * Attaches a passive effect to the `MotionValue`.
1070
- *
1071
- * @internal
1072
1022
  */
1073
1023
  attach(passiveEffect, stopPassiveEffect) {
1074
1024
  this.passiveEffect = passiveEffect;
@@ -1159,8 +1109,6 @@ class MotionValue {
1159
1109
  * ```
1160
1110
  *
1161
1111
  * @param animation - A function that starts the provided animation
1162
- *
1163
- * @internal
1164
1112
  */
1165
1113
  start(startAnimation) {
1166
1114
  this.stop();
@@ -1223,6 +1171,55 @@ function motionValue(init, options) {
1223
1171
  return new MotionValue(init, options);
1224
1172
  }
1225
1173
 
1174
+ /**
1175
+ * Generate a list of every possible transform key.
1176
+ */
1177
+ const transformPropOrder = [
1178
+ "transformPerspective",
1179
+ "x",
1180
+ "y",
1181
+ "z",
1182
+ "translateX",
1183
+ "translateY",
1184
+ "translateZ",
1185
+ "scale",
1186
+ "scaleX",
1187
+ "scaleY",
1188
+ "rotate",
1189
+ "rotateX",
1190
+ "rotateY",
1191
+ "rotateZ",
1192
+ "skew",
1193
+ "skewX",
1194
+ "skewY",
1195
+ ];
1196
+ /**
1197
+ * A quick lookup for transform props.
1198
+ */
1199
+ const transformProps = new Set(transformPropOrder);
1200
+
1201
+ const positionalKeys = new Set([
1202
+ "width",
1203
+ "height",
1204
+ "top",
1205
+ "left",
1206
+ "right",
1207
+ "bottom",
1208
+ ...transformPropOrder,
1209
+ ]);
1210
+
1211
+ const isKeyframesTarget = (v) => {
1212
+ return Array.isArray(v);
1213
+ };
1214
+
1215
+ const isCustomValue = (v) => {
1216
+ return Boolean(v && typeof v === "object" && v.mix && v.toValue);
1217
+ };
1218
+ const resolveFinalValueInKeyframes = (v) => {
1219
+ // TODO maybe throw if v.length - 1 is placeholder token?
1220
+ return isKeyframesTarget(v) ? v[v.length - 1] || 0 : v;
1221
+ };
1222
+
1226
1223
  /**
1227
1224
  * Set VisualElement's MotionValue, creating a new MotionValue for it if
1228
1225
  * it doesn't exist.
@@ -5822,8 +5819,6 @@ const LayoutGroupContext = react.createContext({});
5822
5819
  */
5823
5820
  const SwitchLayoutGroupContext = react.createContext({});
5824
5821
 
5825
- const { schedule: microtask, cancel: cancelMicrotask } = createRenderBatcher(queueMicrotask, false);
5826
-
5827
5822
  /**
5828
5823
  * This should only ever be modified on the client otherwise it'll
5829
5824
  * persist through server requests. If we need instanced states we
@@ -9379,7 +9374,7 @@ function updateMotionValuesFromProps(element, next, prev) {
9379
9374
  * and warn against mismatches.
9380
9375
  */
9381
9376
  if (process.env.NODE_ENV === "development") {
9382
- warnOnce(nextValue.version === "12.4.13", `Attempting to mix Motion versions ${nextValue.version} with 12.4.13 may not work as expected.`);
9377
+ warnOnce(nextValue.version === "12.5.0", `Attempting to mix Motion versions ${nextValue.version} with 12.5.0 may not work as expected.`);
9383
9378
  }
9384
9379
  }
9385
9380
  else if (isMotionValue(prevValue)) {