motion 12.7.4 → 12.7.5-alpha.1

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 (173) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/debug.js +22 -14
  3. package/dist/cjs/index.js +4123 -3634
  4. package/dist/cjs/mini.js +403 -324
  5. package/dist/cjs/react-client.js +3150 -3245
  6. package/dist/cjs/react-m.js +169 -166
  7. package/dist/cjs/react-mini.js +330 -251
  8. package/dist/es/framer-motion/dist/es/animation/animate/sequence.mjs +1 -1
  9. package/dist/es/framer-motion/dist/es/animation/animators/waapi/animate-elements.mjs +81 -9
  10. package/dist/es/framer-motion/dist/es/animation/interfaces/motion-value.mjs +11 -30
  11. package/dist/es/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs +1 -1
  12. package/dist/es/framer-motion/dist/es/animation/optimized-appear/store-id.mjs +1 -1
  13. package/dist/es/framer-motion/dist/es/animation/sequence/create.mjs +3 -3
  14. package/dist/es/framer-motion/dist/es/animation/sequence/utils/edit.mjs +2 -2
  15. package/dist/es/framer-motion/dist/es/animation/utils/default-transitions.mjs +1 -1
  16. package/dist/es/framer-motion/dist/es/animation/utils/stagger.mjs +1 -1
  17. package/dist/es/framer-motion/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
  18. package/dist/es/framer-motion/dist/es/gestures/drag/VisualElementDragControls.mjs +2 -2
  19. package/dist/es/framer-motion/dist/es/gestures/drag/utils/constraints.mjs +2 -2
  20. package/dist/es/framer-motion/dist/es/gestures/focus.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/motion/utils/is-forced-motion-value.mjs +1 -1
  23. package/dist/es/framer-motion/dist/es/projection/animation/mix-values.mjs +3 -3
  24. package/dist/es/framer-motion/dist/es/projection/geometry/delta-apply.mjs +1 -1
  25. package/dist/es/framer-motion/dist/es/projection/geometry/delta-calc.mjs +1 -1
  26. package/dist/es/framer-motion/dist/es/projection/geometry/delta-remove.mjs +2 -2
  27. package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +3 -5
  28. package/dist/es/framer-motion/dist/es/projection/styles/scale-border-radius.mjs +1 -1
  29. package/dist/es/framer-motion/dist/es/projection/styles/scale-box-shadow.mjs +2 -2
  30. package/dist/es/framer-motion/dist/es/projection/styles/scale-correction.mjs +1 -1
  31. package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +7 -7
  32. package/dist/es/framer-motion/dist/es/render/dom/DOMVisualElement.mjs +1 -1
  33. package/dist/es/framer-motion/dist/es/render/dom/scroll/attach-animation.mjs +17 -0
  34. package/dist/es/framer-motion/dist/es/render/dom/scroll/attach-function.mjs +23 -0
  35. package/dist/es/framer-motion/dist/es/render/dom/scroll/index.mjs +6 -82
  36. package/dist/es/framer-motion/dist/es/render/dom/scroll/offsets/index.mjs +3 -3
  37. package/dist/es/framer-motion/dist/es/render/dom/scroll/utils/get-timeline.mjs +30 -0
  38. package/dist/es/framer-motion/dist/es/render/html/HTMLVisualElement.mjs +3 -3
  39. package/dist/es/framer-motion/dist/es/render/html/utils/build-styles.mjs +4 -4
  40. package/dist/es/framer-motion/dist/es/render/html/utils/build-transform.mjs +3 -3
  41. package/dist/es/framer-motion/dist/es/render/svg/SVGVisualElement.mjs +2 -2
  42. package/dist/es/framer-motion/dist/es/render/svg/config-motion.mjs +1 -1
  43. package/dist/es/framer-motion/dist/es/render/svg/utils/path.mjs +1 -1
  44. package/dist/es/framer-motion/dist/es/render/svg/utils/scrape-motion-values.mjs +1 -1
  45. package/dist/es/framer-motion/dist/es/render/svg/utils/transform-origin.mjs +1 -1
  46. package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
  47. package/dist/es/framer-motion/dist/es/utils/delay.mjs +1 -1
  48. package/dist/es/framer-motion/dist/es/utils/transform.mjs +1 -1
  49. package/dist/es/framer-motion/dist/es/utils/use-cycle.mjs +1 -1
  50. package/dist/es/framer-motion/dist/es/utils/use-instant-transition.mjs +4 -4
  51. package/dist/es/framer-motion/dist/es/value/use-spring.mjs +2 -2
  52. package/dist/es/framer-motion/dist/es/value/use-will-change/get-will-change-name.mjs +2 -2
  53. package/dist/es/motion/lib/index.mjs +109 -26
  54. package/dist/es/motion/lib/react.mjs +108 -32
  55. package/dist/es/motion-dom/dist/es/animation/AsyncMotionValueAnimation.mjs +179 -0
  56. package/dist/es/motion-dom/dist/es/animation/GroupAnimation.mjs +6 -15
  57. package/dist/es/{framer-motion/dist/es/animation/animators/MainThreadAnimation.mjs → motion-dom/dist/es/animation/JSAnimation.mjs} +107 -156
  58. package/dist/es/motion-dom/dist/es/animation/NativeAnimation.mjs +64 -67
  59. package/dist/es/motion-dom/dist/es/animation/NativeAnimationExtended.mjs +65 -0
  60. package/dist/es/motion-dom/dist/es/animation/NativeAnimationWrapper.mjs +14 -0
  61. package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation}/drivers/driver-frameloop.mjs +2 -2
  62. package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/keyframes.mjs +5 -5
  63. package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/find.mjs +1 -1
  64. package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/index.mjs +5 -6
  65. package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation/keyframes}/DOMKeyframesResolver.mjs +9 -8
  66. package/dist/es/{framer-motion/dist/es/render/utils → motion-dom/dist/es/animation/keyframes}/KeyframesResolver.mjs +28 -35
  67. package/dist/es/motion-dom/dist/es/animation/keyframes/get-final.mjs +3 -4
  68. package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/fill.mjs +2 -2
  69. package/dist/es/motion-dom/dist/es/animation/keyframes/utils/apply-px-defaults.mjs +11 -0
  70. package/dist/es/motion-dom/dist/es/animation/keyframes/utils/fill-wildcards.mjs +7 -0
  71. package/dist/es/{framer-motion/dist/es/animation → motion-dom/dist/es/animation/keyframes}/utils/is-none.mjs +1 -1
  72. package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/animation/keyframes}/utils/make-none-animatable.mjs +1 -1
  73. package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation/keyframes}/utils/unit-conversion.mjs +2 -2
  74. package/dist/es/motion-dom/dist/es/animation/utils/WithPromise.mjs +28 -0
  75. package/dist/es/motion-dom/dist/es/animation/utils/active-animations.mjs +9 -0
  76. package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation}/utils/can-animate.mjs +3 -3
  77. package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation}/utils/css-variables-conversion.mjs +2 -2
  78. package/dist/es/motion-dom/dist/es/animation/utils/replace-transition-type.mjs +18 -0
  79. package/dist/es/motion-dom/dist/es/animation/waapi/easing/is-supported.mjs +1 -1
  80. package/dist/es/motion-dom/dist/es/animation/waapi/easing/map-easing.mjs +5 -3
  81. package/dist/es/motion-dom/dist/es/animation/waapi/start-waapi-animation.mjs +6 -4
  82. package/dist/es/motion-dom/dist/es/animation/waapi/supports/waapi.mjs +39 -0
  83. package/dist/es/motion-dom/dist/es/animation/waapi/utils/apply-generator.mjs +2 -1
  84. package/dist/es/motion-dom/dist/es/animation/waapi/utils/unsupported-easing.mjs +20 -0
  85. package/dist/es/motion-dom/dist/es/frameloop/batcher.mjs +2 -1
  86. package/dist/es/motion-dom/dist/es/frameloop/order.mjs +1 -0
  87. package/dist/es/motion-dom/dist/es/render/dom/is-css-var.mjs +3 -0
  88. package/dist/es/motion-dom/dist/es/render/dom/style-computed.mjs +10 -0
  89. package/dist/es/motion-dom/dist/es/render/dom/style-set.mjs +9 -0
  90. package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/render}/utils/keys-transform.mjs +1 -1
  91. package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es}/scroll/observe.mjs +1 -1
  92. package/dist/es/motion-dom/dist/es/stats/index.mjs +2 -0
  93. package/dist/es/{framer-motion → motion-dom}/dist/es/utils/interpolate.mjs +4 -3
  94. package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/color.mjs +3 -3
  95. package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/complex.mjs +5 -5
  96. package/dist/es/motion-dom/dist/es/value/index.mjs +3 -1
  97. package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/rgba.mjs +2 -2
  98. package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types}/dimensions.mjs +3 -3
  99. package/dist/es/{framer-motion/dist/es/render/dom/value-types/type-int.mjs → motion-dom/dist/es/value/types/int.mjs} +1 -1
  100. package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/maps}/defaults.mjs +2 -2
  101. package/dist/es/{framer-motion/dist/es/render/dom/value-types/number-browser.mjs → motion-dom/dist/es/value/types/maps/number.mjs} +13 -3
  102. package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/maps}/transform.mjs +2 -2
  103. package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/numbers/index.mjs +1 -1
  104. package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/numbers/units.mjs +3 -2
  105. package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/animatable-none.mjs +4 -4
  106. package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/find.mjs +4 -4
  107. package/dist/es/motion-dom/dist/es/view/index.mjs +64 -0
  108. package/dist/es/motion-dom/dist/es/view/queue.mjs +52 -0
  109. package/dist/es/motion-dom/dist/es/view/start.mjs +155 -0
  110. package/dist/es/motion-dom/dist/es/view/utils/choose-layer-type.mjs +11 -0
  111. package/dist/es/motion-dom/dist/es/view/utils/css.mjs +32 -0
  112. package/dist/es/motion-dom/dist/es/view/utils/get-layer-name.mjs +8 -0
  113. package/dist/es/motion-dom/dist/es/view/utils/get-view-animations.mjs +12 -0
  114. package/dist/es/motion-dom/dist/es/view/utils/has-target.mjs +5 -0
  115. package/dist/es/{framer-motion → motion-utils}/dist/es/easing/cubic-bezier.mjs +1 -1
  116. package/dist/es/{framer-motion → motion-utils}/dist/es/easing/steps.mjs +1 -1
  117. package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/get-easing-for-segment.mjs +1 -1
  118. package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/map.mjs +7 -4
  119. package/dist/es/motion-utils/dist/es/global-config.mjs +1 -4
  120. package/dist/es/motion-utils/dist/es/warn-once.mjs +4 -1
  121. package/dist/motion.dev.js +4122 -3633
  122. package/dist/motion.js +1 -1
  123. package/package.json +3 -3
  124. package/dist/es/framer-motion/dist/es/animation/animators/AcceleratedAnimation.mjs +0 -324
  125. package/dist/es/framer-motion/dist/es/animation/animators/BaseAnimation.mjs +0 -120
  126. package/dist/es/framer-motion/dist/es/animation/animators/waapi/utils/supports-waapi.mjs +0 -5
  127. package/dist/es/framer-motion/dist/es/render/dom/value-types/number.mjs +0 -18
  128. package/dist/es/framer-motion/dist/es/utils/use-instant-transition-state.mjs +0 -5
  129. package/dist/es/motion-dom/dist/es/animation/keyframes/hydrate.mjs +0 -26
  130. package/dist/es/motion-dom/dist/es/animation/waapi/utils/attach-timeline.mjs +0 -6
  131. package/dist/es/motion-dom/dist/es/render/dom/style.mjs +0 -15
  132. /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/inertia.mjs +0 -0
  133. /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/spring/defaults.mjs +0 -0
  134. /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/generators/utils/velocity.mjs +0 -0
  135. /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/default.mjs +0 -0
  136. /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/animation/keyframes}/offsets/time.mjs +0 -0
  137. /package/dist/es/{framer-motion → motion-dom}/dist/es/animation/utils/is-animatable.mjs +0 -0
  138. /package/dist/es/{framer-motion/dist/es/render/dom → motion-dom/dist/es/animation}/utils/is-css-variable.mjs +0 -0
  139. /package/dist/es/{framer-motion/dist/es/animation/animators → motion-dom/dist/es/animation/waapi}/utils/accelerated-values.mjs +0 -0
  140. /package/dist/es/{framer-motion/dist/es/render/html/utils → motion-dom/dist/es/render/dom}/parse-transform.mjs +0 -0
  141. /package/dist/es/{framer-motion/dist/es/render/html → motion-dom/dist/es/render}/utils/keys-position.mjs +0 -0
  142. /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/immediate.mjs +0 -0
  143. /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/index.mjs +0 -0
  144. /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/number.mjs +0 -0
  145. /package/dist/es/{framer-motion → motion-dom}/dist/es/utils/mix/visibility.mjs +0 -0
  146. /package/dist/es/{framer-motion/dist/es/render/dom/value-types/type-auto.mjs → motion-dom/dist/es/value/types/auto.mjs} +0 -0
  147. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/hex.mjs +0 -0
  148. /package/dist/es/{framer-motion/dist/es/utils → motion-dom/dist/es/value/types/color}/hsla-to-rgba.mjs +0 -0
  149. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/hsla.mjs +0 -0
  150. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/index.mjs +0 -0
  151. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/color/utils.mjs +0 -0
  152. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/complex/filter.mjs +0 -0
  153. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/complex/index.mjs +0 -0
  154. /package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types}/test.mjs +0 -0
  155. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/color-regex.mjs +0 -0
  156. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/float-regex.mjs +0 -0
  157. /package/dist/es/{framer-motion/dist/es/render/dom/value-types → motion-dom/dist/es/value/types/utils}/get-as-type.mjs +0 -0
  158. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/is-nullish.mjs +0 -0
  159. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/sanitize.mjs +0 -0
  160. /package/dist/es/{framer-motion → motion-dom}/dist/es/value/types/utils/single-color-regex.mjs +0 -0
  161. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/clamp.mjs +0 -0
  162. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/anticipate.mjs +0 -0
  163. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/back.mjs +0 -0
  164. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/circ.mjs +0 -0
  165. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/ease.mjs +0 -0
  166. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/modifiers/mirror.mjs +0 -0
  167. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/modifiers/reverse.mjs +0 -0
  168. /package/dist/es/{motion-dom/dist/es → motion-utils/dist/es/easing}/utils/is-bezier-definition.mjs +0 -0
  169. /package/dist/es/{framer-motion → motion-utils}/dist/es/easing/utils/is-easing-array.mjs +0 -0
  170. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/is-numerical-string.mjs +0 -0
  171. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/is-zero-value-string.mjs +0 -0
  172. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/pipe.mjs +0 -0
  173. /package/dist/es/{framer-motion/dist/es/utils → motion-utils/dist/es}/wrap.mjs +0 -0
@@ -0,0 +1,179 @@
1
+ import { time } from '../frameloop/sync-time.mjs';
2
+ import { JSAnimation } from './JSAnimation.mjs';
3
+ import { getFinalKeyframe } from './keyframes/get-final.mjs';
4
+ import { KeyframeResolver, flushKeyframeResolvers } from './keyframes/KeyframesResolver.mjs';
5
+ import { NativeAnimationExtended } from './NativeAnimationExtended.mjs';
6
+ import { canAnimate } from './utils/can-animate.mjs';
7
+ import { WithPromise } from './utils/WithPromise.mjs';
8
+ import { supportsBrowserAnimation } from './waapi/supports/waapi.mjs';
9
+ import { MotionGlobalConfig } from '../../../../motion-utils/dist/es/global-config.mjs';
10
+ import { noop } from '../../../../motion-utils/dist/es/noop.mjs';
11
+
12
+ /**
13
+ * Maximum time allowed between an animation being created and it being
14
+ * resolved for us to use the latter as the start time.
15
+ *
16
+ * This is to ensure that while we prefer to "start" an animation as soon
17
+ * as it's triggered, we also want to avoid a visual jump if there's a big delay
18
+ * between these two moments.
19
+ */
20
+ const MAX_RESOLVE_DELAY = 40;
21
+ class AsyncMotionValueAnimation extends WithPromise {
22
+ constructor({ autoplay = true, delay = 0, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", keyframes, name, motionValue, element, ...options }) {
23
+ super();
24
+ /**
25
+ * Bound to support return animation.stop pattern
26
+ */
27
+ this.stop = () => {
28
+ if (this._animation) {
29
+ this._animation.stop();
30
+ this.stopTimeline?.();
31
+ }
32
+ else {
33
+ this.keyframeResolver?.cancel();
34
+ }
35
+ };
36
+ this.createdAt = time.now();
37
+ const optionsWithDefaults = {
38
+ autoplay,
39
+ delay,
40
+ type,
41
+ repeat,
42
+ repeatDelay,
43
+ repeatType,
44
+ name,
45
+ motionValue,
46
+ element,
47
+ ...options,
48
+ };
49
+ const KeyframeResolver$1 = element?.KeyframeResolver || KeyframeResolver;
50
+ this.keyframeResolver = new KeyframeResolver$1(keyframes, (resolvedKeyframes, finalKeyframe, forced) => this.onKeyframesResolved(resolvedKeyframes, finalKeyframe, optionsWithDefaults, !forced), name, motionValue, element);
51
+ this.keyframeResolver?.scheduleResolve();
52
+ }
53
+ onKeyframesResolved(keyframes, finalKeyframe, options, sync) {
54
+ this.keyframeResolver = undefined;
55
+ const { name, type, velocity, delay, isHandoff, onUpdate, onComplete } = options;
56
+ this.resolvedAt = time.now();
57
+ /**
58
+ * If we can't animate this value with the resolved keyframes
59
+ * then we should complete it immediately.
60
+ */
61
+ if (!canAnimate(keyframes, name, type, velocity)) {
62
+ if (MotionGlobalConfig.instantAnimations || !delay) {
63
+ onUpdate?.(getFinalKeyframe(keyframes, options, finalKeyframe));
64
+ }
65
+ keyframes[0] = keyframes[keyframes.length - 1];
66
+ options.duration = 0;
67
+ options.repeat = 0;
68
+ }
69
+ /**
70
+ * Resolve startTime for the animation.
71
+ *
72
+ * This method uses the createdAt and resolvedAt to calculate the
73
+ * animation startTime. *Ideally*, we would use the createdAt time as t=0
74
+ * as the following frame would then be the first frame of the animation in
75
+ * progress, which would feel snappier.
76
+ *
77
+ * However, if there's a delay (main thread work) between the creation of
78
+ * the animation and the first commited frame, we prefer to use resolvedAt
79
+ * to avoid a sudden jump into the animation.
80
+ */
81
+ const startTime = sync
82
+ ? !this.resolvedAt
83
+ ? this.createdAt
84
+ : this.resolvedAt - this.createdAt > MAX_RESOLVE_DELAY
85
+ ? this.resolvedAt
86
+ : this.createdAt
87
+ : undefined;
88
+ const resolvedOptions = {
89
+ startTime,
90
+ finalKeyframe,
91
+ ...options,
92
+ keyframes,
93
+ };
94
+ /**
95
+ * Animate via WAAPI if possible. If this is a handoff animation, the optimised animation will be running via
96
+ * WAAPI. Therefore, this animation must be JS to ensure it runs "under" the
97
+ * optimised animation.
98
+ */
99
+ const animation = !isHandoff && supportsBrowserAnimation(resolvedOptions)
100
+ ? new NativeAnimationExtended({
101
+ ...resolvedOptions,
102
+ element: resolvedOptions.motionValue.owner.current,
103
+ })
104
+ : new JSAnimation(resolvedOptions);
105
+ animation.finished
106
+ .then(() => {
107
+ onComplete?.();
108
+ this.notifyFinished();
109
+ })
110
+ .catch(noop);
111
+ if (this.pendingTimeline) {
112
+ this.stopTimeline = animation.attachTimeline(this.pendingTimeline);
113
+ this.pendingTimeline = undefined;
114
+ }
115
+ this._animation = animation;
116
+ }
117
+ get finished() {
118
+ if (!this._animation) {
119
+ return this._finished;
120
+ }
121
+ else {
122
+ return this.animation.finished;
123
+ }
124
+ }
125
+ then(onResolve, _onReject) {
126
+ return this.finished.finally(onResolve).then(() => { });
127
+ }
128
+ get animation() {
129
+ if (!this._animation) {
130
+ flushKeyframeResolvers();
131
+ }
132
+ return this._animation;
133
+ }
134
+ get duration() {
135
+ return this.animation.duration;
136
+ }
137
+ get time() {
138
+ return this.animation.time;
139
+ }
140
+ set time(newTime) {
141
+ this.animation.time = newTime;
142
+ }
143
+ get speed() {
144
+ return this.animation.speed;
145
+ }
146
+ get state() {
147
+ return this.animation.state;
148
+ }
149
+ set speed(newSpeed) {
150
+ this.animation.speed = newSpeed;
151
+ }
152
+ get startTime() {
153
+ return this.animation.startTime;
154
+ }
155
+ attachTimeline(timeline) {
156
+ if (this._animation) {
157
+ this.stopTimeline = this.animation.attachTimeline(timeline);
158
+ }
159
+ else {
160
+ this.pendingTimeline = timeline;
161
+ }
162
+ return () => this.stop();
163
+ }
164
+ play() {
165
+ this.animation.play();
166
+ }
167
+ pause() {
168
+ this.animation.pause();
169
+ }
170
+ complete() {
171
+ console.log("async animation complete");
172
+ this.animation.complete();
173
+ }
174
+ cancel() {
175
+ this.animation.cancel();
176
+ }
177
+ }
178
+
179
+ export { AsyncMotionValueAnimation };
@@ -1,8 +1,6 @@
1
- import { supportsScrollTimeline } from '../utils/supports/scroll-timeline.mjs';
2
-
3
1
  class GroupAnimation {
4
2
  constructor(animations) {
5
- // Bound to accomodate common `return animation.stop` pattern
3
+ // Bound to accomadate common `return animation.stop` pattern
6
4
  this.stop = () => this.runAll("stop");
7
5
  this.animations = animations.filter(Boolean);
8
6
  }
@@ -20,15 +18,8 @@ class GroupAnimation {
20
18
  this.animations[i][propName] = newValue;
21
19
  }
22
20
  }
23
- attachTimeline(timeline, fallback) {
24
- const subscriptions = this.animations.map((animation) => {
25
- if (supportsScrollTimeline() && animation.attachTimeline) {
26
- return animation.attachTimeline(timeline);
27
- }
28
- else if (typeof fallback === "function") {
29
- return fallback(animation);
30
- }
31
- });
21
+ attachTimeline(timeline) {
22
+ const subscriptions = this.animations.map((animation) => animation.attachTimeline(timeline));
32
23
  return () => {
33
24
  subscriptions.forEach((cancel, i) => {
34
25
  cancel && cancel();
@@ -48,6 +39,9 @@ class GroupAnimation {
48
39
  set speed(speed) {
49
40
  this.setAll("speed", speed);
50
41
  }
42
+ get state() {
43
+ return this.getAll("state");
44
+ }
51
45
  get startTime() {
52
46
  return this.getAll("startTime");
53
47
  }
@@ -61,9 +55,6 @@ class GroupAnimation {
61
55
  runAll(methodName) {
62
56
  this.animations.forEach((controls) => controls[methodName]());
63
57
  }
64
- flatten() {
65
- this.runAll("flatten");
66
- }
67
58
  play() {
68
59
  this.runAll("play");
69
60
  }
@@ -1,68 +1,46 @@
1
- import { KeyframeResolver } from '../../render/utils/KeyframesResolver.mjs';
2
- import { clamp } from '../../utils/clamp.mjs';
3
- import { mix } from '../../utils/mix/index.mjs';
4
- import { pipe } from '../../utils/pipe.mjs';
5
- import { inertia } from '../generators/inertia.mjs';
6
- import { keyframes } from '../generators/keyframes.mjs';
7
- import { spring } from '../generators/spring/index.mjs';
8
- import { BaseAnimation } from './BaseAnimation.mjs';
1
+ import { time } from '../frameloop/sync-time.mjs';
2
+ import { activeAnimations } from '../stats/animation-count.mjs';
3
+ import { mix } from '../utils/mix/index.mjs';
9
4
  import { frameloopDriver } from './drivers/driver-frameloop.mjs';
10
- import { getFinalKeyframe } from './waapi/utils/get-final-keyframe.mjs';
11
- import { invariant } from '../../../../../motion-utils/dist/es/errors.mjs';
12
- import { calcGeneratorDuration } from '../../../../../motion-dom/dist/es/animation/generators/utils/calc-duration.mjs';
13
- import { activeAnimations } from '../../../../../motion-dom/dist/es/stats/animation-count.mjs';
14
- import { millisecondsToSeconds, secondsToMilliseconds } from '../../../../../motion-utils/dist/es/time-conversion.mjs';
15
- import { isGenerator } from '../../../../../motion-dom/dist/es/animation/generators/utils/is-generator.mjs';
5
+ import { inertia } from './generators/inertia.mjs';
6
+ import { keyframes } from './generators/keyframes.mjs';
7
+ import { calcGeneratorDuration } from './generators/utils/calc-duration.mjs';
8
+ import { getFinalKeyframe } from './keyframes/get-final.mjs';
9
+ import { replaceTransitionType } from './utils/replace-transition-type.mjs';
10
+ import { WithPromise } from './utils/WithPromise.mjs';
11
+ import { invariant } from '../../../../motion-utils/dist/es/errors.mjs';
12
+ import { pipe } from '../../../../motion-utils/dist/es/pipe.mjs';
13
+ import { millisecondsToSeconds, secondsToMilliseconds } from '../../../../motion-utils/dist/es/time-conversion.mjs';
14
+ import { clamp } from '../../../../motion-utils/dist/es/clamp.mjs';
16
15
 
17
- const generators = {
18
- decay: inertia,
19
- inertia,
20
- tween: keyframes,
21
- keyframes: keyframes,
22
- spring,
23
- };
24
16
  const percentToProgress = (percent) => percent / 100;
25
- /**
26
- * Animation that runs on the main thread. Designed to be WAAPI-spec in the subset of
27
- * features we expose publically. Mostly the compatibility is to ensure visual identity
28
- * between both WAAPI and main thread animations.
29
- */
30
- class MainThreadAnimation extends BaseAnimation {
17
+ class JSAnimation extends WithPromise {
31
18
  constructor(options) {
32
- super(options);
33
- /**
34
- * The time at which the animation was paused.
35
- */
36
- this.holdTime = null;
37
- /**
38
- * The time at which the animation was cancelled.
39
- */
40
- this.cancelTime = null;
19
+ super();
20
+ this.state = "idle";
21
+ this.startTime = null;
22
+ this.isStopped = false;
41
23
  /**
42
24
  * The current time of the animation.
43
25
  */
44
26
  this.currentTime = 0;
45
27
  /**
46
- * Playback speed as a factor. 0 would be stopped, -1 reverse and 2 double speed.
47
- */
48
- this.playbackSpeed = 1;
49
- /**
50
- * The state of the animation to apply when the animation is resolved. This
51
- * allows calls to the public API to control the animation before it is resolved,
52
- * without us having to resolve it first.
28
+ * The time at which the animation was paused.
53
29
  */
54
- this.pendingPlayState = "running";
30
+ this.holdTime = null;
55
31
  /**
56
- * The time at which the animation was started.
32
+ * Playback speed as a factor. 0 would be stopped, -1 reverse and 2 double speed.
57
33
  */
58
- this.startTime = null;
59
- this.state = "idle";
34
+ this.playbackSpeed = 1;
60
35
  /**
61
36
  * This method is bound to the instance to fix a pattern where
62
37
  * animation.stop is returned as a reference from a useEffect.
63
38
  */
64
39
  this.stop = () => {
65
- this.resolver.cancel();
40
+ const { motionValue } = this.options;
41
+ if (motionValue && motionValue.updatedAt !== time.now()) {
42
+ this.tick(time.now());
43
+ }
66
44
  this.isStopped = true;
67
45
  if (this.state === "idle")
68
46
  return;
@@ -70,49 +48,36 @@ class MainThreadAnimation extends BaseAnimation {
70
48
  const { onStop } = this.options;
71
49
  onStop && onStop();
72
50
  };
73
- const { name, motionValue, element, keyframes } = this.options;
74
- const KeyframeResolver$1 = element?.KeyframeResolver || KeyframeResolver;
75
- const onResolved = (resolvedKeyframes, finalKeyframe) => this.onKeyframesResolved(resolvedKeyframes, finalKeyframe);
76
- this.resolver = new KeyframeResolver$1(keyframes, onResolved, name, motionValue, element);
77
- this.resolver.scheduleResolve();
78
- }
79
- flatten() {
80
- super.flatten();
81
- // If we've already resolved the animation, re-initialise it
82
- if (this._resolved) {
83
- Object.assign(this._resolved, this.initPlayback(this._resolved.keyframes));
84
- }
51
+ activeAnimations.mainThread++;
52
+ this.options = options;
53
+ this.initAnimation();
54
+ this.play();
55
+ if (options.autoplay === false)
56
+ this.pause();
85
57
  }
86
- initPlayback(keyframes$1) {
87
- const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = this.options;
88
- const generatorFactory = isGenerator(type)
89
- ? type
90
- : generators[type] || keyframes;
91
- /**
92
- * If our generator doesn't support mixing numbers, we need to replace keyframes with
93
- * [0, 100] and then make a function that maps that to the actual keyframes.
94
- *
95
- * 100 is chosen instead of 1 as it works nicer with spring animations.
96
- */
97
- let mapPercentToKeyframes;
98
- let mirroredGenerator;
58
+ initAnimation() {
59
+ const { options } = this;
60
+ replaceTransitionType(options);
61
+ const { type = keyframes, repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = options;
62
+ let { keyframes: keyframes$1 } = options;
63
+ const generatorFactory = type || keyframes;
99
64
  if (process.env.NODE_ENV !== "production" &&
100
65
  generatorFactory !== keyframes) {
101
66
  invariant(keyframes$1.length <= 2, `Only two keyframes currently supported with spring and inertia animations. Trying to animate ${keyframes$1}`);
102
67
  }
103
68
  if (generatorFactory !== keyframes &&
104
69
  typeof keyframes$1[0] !== "number") {
105
- mapPercentToKeyframes = pipe(percentToProgress, mix(keyframes$1[0], keyframes$1[1]));
70
+ this.mixKeyframes = pipe(percentToProgress, mix(keyframes$1[0], keyframes$1[1]));
106
71
  keyframes$1 = [0, 100];
107
72
  }
108
- const generator = generatorFactory({ ...this.options, keyframes: keyframes$1 });
73
+ const generator = generatorFactory({ ...options, keyframes: keyframes$1 });
109
74
  /**
110
75
  * If we have a mirror repeat type we need to create a second generator that outputs the
111
76
  * mirrored (not reversed) animation and later ping pong between the two generators.
112
77
  */
113
78
  if (repeatType === "mirror") {
114
- mirroredGenerator = generatorFactory({
115
- ...this.options,
79
+ this.mirroredGenerator = generatorFactory({
80
+ ...options,
116
81
  keyframes: [...keyframes$1].reverse(),
117
82
  velocity: -velocity,
118
83
  });
@@ -129,39 +94,29 @@ class MainThreadAnimation extends BaseAnimation {
129
94
  generator.calculatedDuration = calcGeneratorDuration(generator);
130
95
  }
131
96
  const { calculatedDuration } = generator;
132
- const resolvedDuration = calculatedDuration + repeatDelay;
133
- const totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
134
- return {
135
- generator,
136
- mirroredGenerator,
137
- mapPercentToKeyframes,
138
- calculatedDuration,
139
- resolvedDuration,
140
- totalDuration,
141
- };
97
+ this.calculatedDuration = calculatedDuration;
98
+ this.resolvedDuration = calculatedDuration + repeatDelay;
99
+ this.totalDuration = this.resolvedDuration * (repeat + 1) - repeatDelay;
100
+ this.generator = generator;
142
101
  }
143
- onPostResolved() {
144
- const { autoplay = true } = this.options;
145
- activeAnimations.mainThread++;
146
- this.play();
147
- if (this.pendingPlayState === "paused" || !autoplay) {
148
- this.pause();
102
+ updateTime(timestamp) {
103
+ const animationTime = Math.round(timestamp - this.startTime) * this.playbackSpeed;
104
+ // Update currentTime
105
+ if (this.holdTime !== null) {
106
+ this.currentTime = this.holdTime;
149
107
  }
150
108
  else {
151
- this.state = this.pendingPlayState;
109
+ // Rounding the time because floating point arithmetic is not always accurate, e.g. 3000.367 - 1000.367 =
110
+ // 2000.0000000000002. This is a problem when we are comparing the currentTime with the duration, for
111
+ // example.
112
+ this.currentTime = animationTime;
152
113
  }
153
114
  }
154
115
  tick(timestamp, sample = false) {
155
- const { resolved } = this;
156
- // If the animations has failed to resolve, return the final keyframe.
157
- if (!resolved) {
158
- const { keyframes } = this.options;
159
- return { done: true, value: keyframes[keyframes.length - 1] };
160
- }
161
- const { finalKeyframe, generator, mirroredGenerator, mapPercentToKeyframes, keyframes, calculatedDuration, totalDuration, resolvedDuration, } = resolved;
116
+ const { generator, totalDuration, mixKeyframes, mirroredGenerator, resolvedDuration, calculatedDuration, } = this;
162
117
  if (this.startTime === null)
163
118
  return generator.next(0);
164
- const { delay, repeat, repeatType, repeatDelay, onUpdate } = this.options;
119
+ const { delay = 0, keyframes, repeat, repeatType, repeatDelay, type, onUpdate, finalKeyframe, } = this.options;
165
120
  /**
166
121
  * requestAnimationFrame timestamps can come through as lower than
167
122
  * the startTime as set by performance.now(). Here we prevent this,
@@ -174,23 +129,15 @@ class MainThreadAnimation extends BaseAnimation {
174
129
  else if (this.speed < 0) {
175
130
  this.startTime = Math.min(timestamp - totalDuration / this.speed, this.startTime);
176
131
  }
177
- // Update currentTime
178
132
  if (sample) {
179
133
  this.currentTime = timestamp;
180
134
  }
181
- else if (this.holdTime !== null) {
182
- this.currentTime = this.holdTime;
183
- }
184
135
  else {
185
- // Rounding the time because floating point arithmetic is not always accurate, e.g. 3000.367 - 1000.367 =
186
- // 2000.0000000000002. This is a problem when we are comparing the currentTime with the duration, for
187
- // example.
188
- this.currentTime =
189
- Math.round(timestamp - this.startTime) * this.speed;
136
+ this.updateTime(timestamp);
190
137
  }
191
138
  // Rebase on delay
192
- const timeWithoutDelay = this.currentTime - delay * (this.speed >= 0 ? 1 : -1);
193
- const isInDelayPhase = this.speed >= 0
139
+ const timeWithoutDelay = this.currentTime - delay * (this.playbackSpeed >= 0 ? 1 : -1);
140
+ const isInDelayPhase = this.playbackSpeed >= 0
194
141
  ? timeWithoutDelay < 0
195
142
  : timeWithoutDelay > totalDuration;
196
143
  this.currentTime = Math.max(timeWithoutDelay, 0);
@@ -251,20 +198,21 @@ class MainThreadAnimation extends BaseAnimation {
251
198
  const state = isInDelayPhase
252
199
  ? { done: false, value: keyframes[0] }
253
200
  : frameGenerator.next(elapsed);
254
- if (mapPercentToKeyframes) {
255
- state.value = mapPercentToKeyframes(state.value);
201
+ if (mixKeyframes) {
202
+ state.value = mixKeyframes(state.value);
256
203
  }
257
204
  let { done } = state;
258
205
  if (!isInDelayPhase && calculatedDuration !== null) {
259
206
  done =
260
- this.speed >= 0
207
+ this.playbackSpeed >= 0
261
208
  ? this.currentTime >= totalDuration
262
209
  : this.currentTime <= 0;
263
210
  }
264
211
  const isAnimationFinished = this.holdTime === null &&
265
212
  (this.state === "finished" || (this.state === "running" && done));
266
- if (isAnimationFinished && finalKeyframe !== undefined) {
267
- state.value = getFinalKeyframe(keyframes, this.options, finalKeyframe);
213
+ // TODO: The exception for inertia could be cleaner here
214
+ if (isAnimationFinished && type !== inertia) {
215
+ state.value = getFinalKeyframe(keyframes, this.options, finalKeyframe, this.speed);
268
216
  }
269
217
  if (onUpdate) {
270
218
  onUpdate(state.value);
@@ -274,9 +222,16 @@ class MainThreadAnimation extends BaseAnimation {
274
222
  }
275
223
  return state;
276
224
  }
225
+ /**
226
+ * Allows the returned animation to be awaited or promise-chained. Currently
227
+ * resolves when the animation finishes at all but in a future update could/should
228
+ * reject if its cancels.
229
+ */
230
+ then(resolve, reject) {
231
+ return this.finished.then(resolve, reject);
232
+ }
277
233
  get duration() {
278
- const { resolved } = this;
279
- return resolved ? millisecondsToSeconds(resolved.calculatedDuration) : 0;
234
+ return millisecondsToSeconds(this.calculatedDuration);
280
235
  }
281
236
  get time() {
282
237
  return millisecondsToSeconds(this.currentTime);
@@ -284,17 +239,20 @@ class MainThreadAnimation extends BaseAnimation {
284
239
  set time(newTime) {
285
240
  newTime = secondsToMilliseconds(newTime);
286
241
  this.currentTime = newTime;
287
- if (this.holdTime !== null || this.speed === 0) {
242
+ if (this.startTime === null ||
243
+ this.holdTime !== null ||
244
+ this.playbackSpeed === 0) {
288
245
  this.holdTime = newTime;
289
246
  }
290
247
  else if (this.driver) {
291
- this.startTime = this.driver.now() - newTime / this.speed;
248
+ this.startTime = this.driver.now() - newTime / this.playbackSpeed;
292
249
  }
293
250
  }
294
251
  get speed() {
295
252
  return this.playbackSpeed;
296
253
  }
297
254
  set speed(newSpeed) {
255
+ this.updateTime(time.now());
298
256
  const hasChanged = this.playbackSpeed !== newSpeed;
299
257
  this.playbackSpeed = newSpeed;
300
258
  if (hasChanged) {
@@ -302,13 +260,6 @@ class MainThreadAnimation extends BaseAnimation {
302
260
  }
303
261
  }
304
262
  play() {
305
- if (!this.resolver.isScheduled) {
306
- this.resolver.resume();
307
- }
308
- if (!this._resolved) {
309
- this.pendingPlayState = "running";
310
- return;
311
- }
312
263
  if (this.isStopped)
313
264
  return;
314
265
  const { driver = frameloopDriver, onPlay, startTime } = this.options;
@@ -320,16 +271,17 @@ class MainThreadAnimation extends BaseAnimation {
320
271
  if (this.holdTime !== null) {
321
272
  this.startTime = now - this.holdTime;
322
273
  }
323
- else if (!this.startTime) {
324
- this.startTime = startTime ?? this.calcStartTime();
325
- }
326
274
  else if (this.state === "finished") {
275
+ console.log("JSAnimation updateFinished");
276
+ this.updateFinished();
327
277
  this.startTime = now;
328
278
  }
329
- if (this.state === "finished") {
330
- this.updateFinishedPromise();
279
+ else if (!this.startTime) {
280
+ this.startTime = startTime ?? now;
281
+ }
282
+ if (this.state === "finished" && this.speed < 0) {
283
+ this.startTime += this.calculatedDuration;
331
284
  }
332
- this.cancelTime = this.startTime;
333
285
  this.holdTime = null;
334
286
  /**
335
287
  * Set playState to running only after we've used it in
@@ -339,40 +291,34 @@ class MainThreadAnimation extends BaseAnimation {
339
291
  this.driver.start();
340
292
  }
341
293
  pause() {
342
- if (!this._resolved) {
343
- this.pendingPlayState = "paused";
344
- return;
345
- }
346
294
  this.state = "paused";
347
- this.holdTime = this.currentTime ?? 0;
295
+ this.updateTime(time.now());
296
+ this.holdTime = this.currentTime;
348
297
  }
349
298
  complete() {
350
299
  if (this.state !== "running") {
351
300
  this.play();
352
301
  }
353
- this.pendingPlayState = this.state = "finished";
302
+ this.state = "finished";
354
303
  this.holdTime = null;
355
304
  }
356
305
  finish() {
306
+ this.notifyFinished();
357
307
  this.teardown();
358
308
  this.state = "finished";
359
309
  const { onComplete } = this.options;
360
310
  onComplete && onComplete();
361
311
  }
362
312
  cancel() {
363
- if (this.cancelTime !== null) {
364
- this.tick(this.cancelTime);
365
- }
313
+ this.holdTime = null;
314
+ this.startTime = 0;
315
+ this.tick(0);
366
316
  this.teardown();
367
- this.updateFinishedPromise();
368
317
  }
369
318
  teardown() {
370
319
  this.state = "idle";
371
320
  this.stopDriver();
372
- this.resolveFinishedPromise();
373
- this.updateFinishedPromise();
374
- this.startTime = this.cancelTime = null;
375
- this.resolver.cancel();
321
+ this.startTime = this.holdTime = null;
376
322
  activeAnimations.mainThread--;
377
323
  }
378
324
  stopDriver() {
@@ -381,17 +327,22 @@ class MainThreadAnimation extends BaseAnimation {
381
327
  this.driver.stop();
382
328
  this.driver = undefined;
383
329
  }
384
- sample(time) {
330
+ sample(sampleTime) {
385
331
  this.startTime = 0;
386
- return this.tick(time, true);
332
+ return this.tick(sampleTime, true);
387
333
  }
388
- get finished() {
389
- return this.currentFinishedPromise;
334
+ attachTimeline(timeline) {
335
+ if (this.options.allowFlatten) {
336
+ this.options.type = "keyframes";
337
+ this.options.ease = "linear";
338
+ this.initAnimation();
339
+ }
340
+ return timeline.observe(this);
390
341
  }
391
342
  }
392
- // Legacy interface
343
+ // Legacy function support
393
344
  function animateValue(options) {
394
- return new MainThreadAnimation(options);
345
+ return new JSAnimation(options);
395
346
  }
396
347
 
397
- export { MainThreadAnimation, animateValue };
348
+ export { JSAnimation, animateValue };