motion 10.2.1 → 10.3.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 (90) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +1 -0
  3. package/dist/main.cjs.js +2 -0
  4. package/dist/main.es.js +1 -0
  5. package/dist/motion.min.js +1 -1
  6. package/dist/motion.umd.js +426 -280
  7. package/dist/size-animate-dom.js +1 -1
  8. package/dist/size-animate-style.js +1 -1
  9. package/dist/size-react.js +1 -1
  10. package/dist/size-spring.js +1 -1
  11. package/dist/size-timeline-dom.js +1 -1
  12. package/dist/size-webpack-animate.js +1 -1
  13. package/dist/targets/dom/animate-style.cjs.js +135 -134
  14. package/dist/targets/dom/animate-style.es.js +137 -136
  15. package/dist/targets/dom/animate.cjs.js +15 -4
  16. package/dist/targets/dom/animate.es.js +16 -5
  17. package/dist/targets/dom/data.cjs.js +4 -3
  18. package/dist/targets/dom/data.es.js +4 -3
  19. package/dist/targets/dom/style.cjs.js +1 -1
  20. package/dist/targets/dom/style.es.js +2 -2
  21. package/dist/targets/dom/timeline/index.cjs.js +7 -6
  22. package/dist/targets/dom/timeline/index.es.js +8 -7
  23. package/dist/targets/dom/timeline/utils/calc-time.cjs.js +3 -1
  24. package/dist/targets/dom/timeline/utils/calc-time.es.js +3 -1
  25. package/dist/targets/dom/utils/apply.cjs.js +4 -8
  26. package/dist/targets/dom/utils/apply.es.js +3 -7
  27. package/dist/targets/dom/utils/controls.cjs.js +6 -2
  28. package/dist/targets/dom/utils/controls.es.js +6 -2
  29. package/dist/targets/dom/utils/css-var.cjs.js +2 -2
  30. package/dist/targets/dom/utils/css-var.es.js +3 -3
  31. package/dist/targets/dom/utils/easing.cjs.js +4 -2
  32. package/dist/targets/dom/utils/easing.es.js +4 -2
  33. package/dist/targets/dom/utils/feature-detection.cjs.js +4 -4
  34. package/dist/targets/dom/utils/feature-detection.es.js +4 -4
  35. package/dist/targets/dom/utils/get-style-name.cjs.js +13 -0
  36. package/dist/targets/dom/utils/get-style-name.es.js +9 -0
  37. package/dist/targets/dom/utils/keyframes.cjs.js +2 -4
  38. package/dist/targets/dom/utils/keyframes.es.js +2 -4
  39. package/dist/targets/dom/utils/options.cjs.js +1 -1
  40. package/dist/targets/dom/utils/options.es.js +1 -1
  41. package/dist/targets/dom/utils/stop-animation.cjs.js +2 -0
  42. package/dist/targets/dom/utils/stop-animation.es.js +2 -0
  43. package/dist/targets/dom/utils/transforms.cjs.js +10 -7
  44. package/dist/targets/dom/utils/transforms.es.js +10 -7
  45. package/dist/targets/js/{animate-number.cjs.js → NumberAnimation.cjs.js} +40 -29
  46. package/dist/targets/js/{animate-number.es.js → NumberAnimation.es.js} +40 -28
  47. package/dist/targets/js/easing/glide/generator.cjs.js +99 -0
  48. package/dist/targets/js/easing/glide/generator.es.js +95 -0
  49. package/dist/targets/js/easing/glide/index.cjs.js +10 -0
  50. package/dist/targets/js/easing/glide/index.es.js +6 -0
  51. package/dist/targets/js/easing/spring/generator.cjs.js +9 -4
  52. package/dist/targets/js/easing/spring/generator.es.js +9 -5
  53. package/dist/targets/js/easing/spring/index.cjs.js +2 -62
  54. package/dist/targets/js/easing/spring/index.es.js +2 -62
  55. package/dist/targets/js/easing/utils/create-generator-easing.cjs.js +71 -0
  56. package/dist/targets/js/easing/utils/create-generator-easing.es.js +67 -0
  57. package/dist/targets/js/easing/utils/has-reached-target.cjs.js +10 -0
  58. package/dist/targets/js/easing/utils/has-reached-target.es.js +6 -0
  59. package/dist/targets/js/easing/utils/pregenerate-keyframes.cjs.js +13 -10
  60. package/dist/targets/js/easing/utils/pregenerate-keyframes.es.js +13 -10
  61. package/dist/targets/react/hooks/use-animation.cjs.js +5 -2
  62. package/dist/targets/react/hooks/use-animation.es.js +5 -2
  63. package/dist/targets/react/utils/keyframes.cjs.js +5 -3
  64. package/dist/targets/react/utils/keyframes.es.js +6 -4
  65. package/dist/utils/is-number.cjs.js +7 -0
  66. package/dist/utils/is-number.es.js +3 -0
  67. package/dist/utils/stagger.cjs.js +2 -1
  68. package/dist/utils/stagger.es.js +2 -1
  69. package/package.json +4 -10
  70. package/types/index.d.ts +1 -0
  71. package/types/targets/dom/animate-style.d.ts +2 -2
  72. package/types/targets/dom/style.d.ts +1 -1
  73. package/types/targets/dom/types.d.ts +8 -4
  74. package/types/targets/dom/utils/apply.d.ts +3 -2
  75. package/types/targets/dom/utils/controls.d.ts +3 -3
  76. package/types/targets/dom/utils/get-style-name.d.ts +1 -0
  77. package/types/targets/dom/utils/keyframes.d.ts +1 -1
  78. package/types/targets/dom/utils/stop-animation.d.ts +1 -1
  79. package/types/targets/dom/utils/transforms.d.ts +2 -2
  80. package/types/targets/js/{animate-number.d.ts → NumberAnimation.d.ts} +2 -3
  81. package/types/targets/js/easing/glide/generator.d.ts +5 -0
  82. package/types/targets/js/easing/glide/index.d.ts +2 -0
  83. package/types/targets/js/easing/glide/types.d.ts +14 -0
  84. package/types/targets/js/easing/spring/generator.d.ts +1 -0
  85. package/types/targets/js/easing/spring/index.d.ts +1 -2
  86. package/types/targets/js/easing/utils/create-generator-easing.d.ts +3 -0
  87. package/types/targets/js/easing/utils/has-reached-target.d.ts +1 -0
  88. package/types/targets/js/easing/utils/pregenerate-keyframes.d.ts +1 -1
  89. package/types/targets/js/types.d.ts +3 -0
  90. package/types/utils/is-number.d.ts +1 -0
@@ -3,8 +3,8 @@ import { isCustomEasing, isEasingList } from '../dom/utils/easing.es.js';
3
3
  import { getEasingFunction } from './easing/utils/get-function.es.js';
4
4
  import { slowInterpolateNumbers } from './utils/interpolate.es.js';
5
5
 
6
- class Animation {
7
- constructor(output, keyframes, { easing = defaults.easing, duration = defaults.duration, delay = defaults.delay, endDelay = defaults.endDelay, repeat = defaults.repeat, offset, direction = "normal", }) {
6
+ class NumberAnimation {
7
+ constructor(output, keyframes = [0, 1], { easing = defaults.easing, duration = defaults.duration, delay = defaults.delay, endDelay = defaults.endDelay, repeat = defaults.repeat, offset, direction = "normal", } = {}) {
8
8
  this.startTime = 0;
9
9
  this.rate = 1;
10
10
  this.t = 0;
@@ -15,54 +15,69 @@ class Animation {
15
15
  this.reject = reject;
16
16
  });
17
17
  const totalDuration = duration * (repeat + 1);
18
- // TODO: This isn't currently supported but keeps TypeScript happy
19
- if (isCustomEasing(easing)) {
18
+ /**
19
+ * We don't currently support custom easing (spring, glide etc) in NumberAnimation
20
+ * (although this is completely possible), so this will have been hydrated by
21
+ * animateStyle.
22
+ */
23
+ if (isCustomEasing(easing))
20
24
  easing = "ease";
21
- }
22
25
  const interpolate = slowInterpolateNumbers(keyframes, offset, isEasingList(easing)
23
26
  ? easing.map(getEasingFunction)
24
27
  : getEasingFunction(easing));
25
28
  this.tick = (timestamp) => {
26
- if (this.playState === "finished") {
27
- const latest = interpolate(1);
28
- output(latest);
29
- this.resolve(latest);
30
- return;
31
- }
32
- if (this.pauseTime) {
29
+ if (this.pauseTime)
33
30
  timestamp = this.pauseTime;
34
- }
35
31
  let t = (timestamp - this.startTime) * this.rate;
36
32
  this.t = t;
37
33
  // Convert to seconds
38
34
  t /= 1000;
39
35
  // Rebase on delay
40
36
  t = Math.max(t - delay, 0);
37
+ /**
38
+ * If this animation has finished, set the current time
39
+ * to the total duration.
40
+ */
41
+ if (this.playState === "finished")
42
+ t = totalDuration;
43
+ /**
44
+ * Get the current progress (0-1) of the animation. If t is >
45
+ * than duration we'll get values like 2.5 (midway through the
46
+ * third iteration)
47
+ */
41
48
  const progress = t / duration;
42
49
  // TODO progress += iterationStart
50
+ /**
51
+ * Get the current iteration (0 indexed). For instance the floor of
52
+ * 2.5 is 2.
53
+ */
43
54
  let currentIteration = Math.floor(progress);
55
+ /**
56
+ * Get the current progress of the iteration by taking the remainder
57
+ * so 2.5 is 0.5 through iteration 2
58
+ */
44
59
  let iterationProgress = progress % 1.0;
45
60
  if (!iterationProgress && progress >= 1) {
46
61
  iterationProgress = 1;
47
62
  }
48
- if (iterationProgress === 1) {
49
- currentIteration--;
50
- }
51
- // Reverse progress
63
+ /**
64
+ * If iteration progress is 1 we count that as the end
65
+ * of the previous iteration.
66
+ */
67
+ iterationProgress === 1 && currentIteration--;
68
+ /**
69
+ * Reverse progress if we're not running in "normal" direction
70
+ */
52
71
  const iterationIsOdd = currentIteration % 2;
53
72
  if (direction === "reverse" ||
54
73
  (direction === "alternate" && iterationIsOdd) ||
55
74
  (direction === "alternate-reverse" && !iterationIsOdd)) {
56
75
  iterationProgress = 1 - iterationProgress;
57
76
  }
58
- const interpolationIsFinished = t >= totalDuration;
59
- const interpolationProgress = interpolationIsFinished
60
- ? 1
61
- : Math.min(iterationProgress, 1);
62
- const latest = interpolate(interpolationProgress);
77
+ const latest = interpolate(t >= totalDuration ? 1 : Math.min(iterationProgress, 1));
63
78
  output(latest);
64
- const isFinished = t >= totalDuration + endDelay;
65
- if (isFinished) {
79
+ const isAnimationFinished = this.playState === "finished" || t >= totalDuration + endDelay;
80
+ if (isAnimationFinished) {
66
81
  this.playState = "finished";
67
82
  this.resolve(latest);
68
83
  }
@@ -121,8 +136,5 @@ class Animation {
121
136
  this.rate = rate;
122
137
  }
123
138
  }
124
- function animateNumber(output, keyframes = [0, 1], options = {}) {
125
- return new Animation(output, keyframes, options);
126
- }
127
139
 
128
- export { Animation, animateNumber };
140
+ export { NumberAnimation };
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var generator = require('../spring/generator.cjs.js');
6
+ var time = require('../../../dom/utils/time.cjs.js');
7
+
8
+ const createGlideGenerator = ({ from = 0, velocity = 0.0, power = 0.8, decay = 0.325, bounceDamping, bounceStiffness, changeTarget, min, max, restDistance = 0.5, restSpeed, }) => {
9
+ decay = time.ms(decay);
10
+ const state = {
11
+ value: from,
12
+ target: from,
13
+ velocity,
14
+ hasReachedTarget: false,
15
+ done: false,
16
+ };
17
+ const isOutOfBounds = (v) => (min !== undefined && v < min) || (max !== undefined && v > max);
18
+ const nearestBoundary = (v) => {
19
+ if (min === undefined)
20
+ return max;
21
+ if (max === undefined)
22
+ return min;
23
+ return Math.abs(min - v) < Math.abs(max - v) ? min : max;
24
+ };
25
+ let amplitude = power * velocity;
26
+ const ideal = from + amplitude;
27
+ const target = changeTarget === undefined ? ideal : changeTarget(ideal);
28
+ state.target = target;
29
+ /**
30
+ * If the target has changed we need to re-calculate the amplitude, otherwise
31
+ * the animation will start from the wrong position.
32
+ */
33
+ if (target !== ideal)
34
+ amplitude = target - from;
35
+ const calcDelta = (t) => -amplitude * Math.exp(-t / decay);
36
+ const calcLatest = (t) => target + calcDelta(t);
37
+ const applyFriction = (t) => {
38
+ const delta = calcDelta(t);
39
+ const latest = calcLatest(t);
40
+ state.done = Math.abs(delta) <= restDistance;
41
+ state.value = state.done ? target : latest;
42
+ state.velocity =
43
+ t === 0 ? velocity : generator.calcVelocity(calcLatest, t, state.value);
44
+ };
45
+ /**
46
+ * Ideally this would resolve for t in a stateless way, we could
47
+ * do that by always precalculating the animation but as we know
48
+ * this will be done anyway we can assume that spring will
49
+ * be discovered during that.
50
+ */
51
+ let timeReachedBoundary;
52
+ let spring;
53
+ const checkCatchBoundary = (t) => {
54
+ if (!isOutOfBounds(state.value))
55
+ return;
56
+ timeReachedBoundary = t;
57
+ spring = generator.createSpringGenerator({
58
+ from: state.value,
59
+ to: nearestBoundary(state.value),
60
+ velocity: state.velocity,
61
+ damping: bounceDamping,
62
+ stiffness: bounceStiffness,
63
+ restDistance,
64
+ restSpeed,
65
+ });
66
+ };
67
+ checkCatchBoundary(0);
68
+ return {
69
+ next: (t) => {
70
+ /**
71
+ * We need to resolve the friction to figure out if we need a
72
+ * spring but we don't want to do this twice per frame. So here
73
+ * we flag if we updated for this frame and later if we did
74
+ * we can skip doing it again.
75
+ */
76
+ let hasUpdatedFrame = false;
77
+ if (!spring && timeReachedBoundary === undefined) {
78
+ hasUpdatedFrame = true;
79
+ applyFriction(t);
80
+ checkCatchBoundary(t);
81
+ }
82
+ /**
83
+ * If we have a spring and the provided t is beyond the moment the friction
84
+ * animation crossed the min/max boundary, use the spring.
85
+ */
86
+ if (timeReachedBoundary !== undefined && t > timeReachedBoundary) {
87
+ state.hasReachedTarget = true;
88
+ return spring.next(t - timeReachedBoundary);
89
+ }
90
+ else {
91
+ state.hasReachedTarget = false;
92
+ !hasUpdatedFrame && applyFriction(t);
93
+ return state;
94
+ }
95
+ },
96
+ };
97
+ };
98
+
99
+ exports.createGlideGenerator = createGlideGenerator;
@@ -0,0 +1,95 @@
1
+ import { calcVelocity, createSpringGenerator } from '../spring/generator.es.js';
2
+ import { ms } from '../../../dom/utils/time.es.js';
3
+
4
+ const createGlideGenerator = ({ from = 0, velocity = 0.0, power = 0.8, decay = 0.325, bounceDamping, bounceStiffness, changeTarget, min, max, restDistance = 0.5, restSpeed, }) => {
5
+ decay = ms(decay);
6
+ const state = {
7
+ value: from,
8
+ target: from,
9
+ velocity,
10
+ hasReachedTarget: false,
11
+ done: false,
12
+ };
13
+ const isOutOfBounds = (v) => (min !== undefined && v < min) || (max !== undefined && v > max);
14
+ const nearestBoundary = (v) => {
15
+ if (min === undefined)
16
+ return max;
17
+ if (max === undefined)
18
+ return min;
19
+ return Math.abs(min - v) < Math.abs(max - v) ? min : max;
20
+ };
21
+ let amplitude = power * velocity;
22
+ const ideal = from + amplitude;
23
+ const target = changeTarget === undefined ? ideal : changeTarget(ideal);
24
+ state.target = target;
25
+ /**
26
+ * If the target has changed we need to re-calculate the amplitude, otherwise
27
+ * the animation will start from the wrong position.
28
+ */
29
+ if (target !== ideal)
30
+ amplitude = target - from;
31
+ const calcDelta = (t) => -amplitude * Math.exp(-t / decay);
32
+ const calcLatest = (t) => target + calcDelta(t);
33
+ const applyFriction = (t) => {
34
+ const delta = calcDelta(t);
35
+ const latest = calcLatest(t);
36
+ state.done = Math.abs(delta) <= restDistance;
37
+ state.value = state.done ? target : latest;
38
+ state.velocity =
39
+ t === 0 ? velocity : calcVelocity(calcLatest, t, state.value);
40
+ };
41
+ /**
42
+ * Ideally this would resolve for t in a stateless way, we could
43
+ * do that by always precalculating the animation but as we know
44
+ * this will be done anyway we can assume that spring will
45
+ * be discovered during that.
46
+ */
47
+ let timeReachedBoundary;
48
+ let spring;
49
+ const checkCatchBoundary = (t) => {
50
+ if (!isOutOfBounds(state.value))
51
+ return;
52
+ timeReachedBoundary = t;
53
+ spring = createSpringGenerator({
54
+ from: state.value,
55
+ to: nearestBoundary(state.value),
56
+ velocity: state.velocity,
57
+ damping: bounceDamping,
58
+ stiffness: bounceStiffness,
59
+ restDistance,
60
+ restSpeed,
61
+ });
62
+ };
63
+ checkCatchBoundary(0);
64
+ return {
65
+ next: (t) => {
66
+ /**
67
+ * We need to resolve the friction to figure out if we need a
68
+ * spring but we don't want to do this twice per frame. So here
69
+ * we flag if we updated for this frame and later if we did
70
+ * we can skip doing it again.
71
+ */
72
+ let hasUpdatedFrame = false;
73
+ if (!spring && timeReachedBoundary === undefined) {
74
+ hasUpdatedFrame = true;
75
+ applyFriction(t);
76
+ checkCatchBoundary(t);
77
+ }
78
+ /**
79
+ * If we have a spring and the provided t is beyond the moment the friction
80
+ * animation crossed the min/max boundary, use the spring.
81
+ */
82
+ if (timeReachedBoundary !== undefined && t > timeReachedBoundary) {
83
+ state.hasReachedTarget = true;
84
+ return spring.next(t - timeReachedBoundary);
85
+ }
86
+ else {
87
+ state.hasReachedTarget = false;
88
+ !hasUpdatedFrame && applyFriction(t);
89
+ return state;
90
+ }
91
+ },
92
+ };
93
+ };
94
+
95
+ export { createGlideGenerator };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var generator = require('./generator.cjs.js');
6
+ var createGeneratorEasing = require('../utils/create-generator-easing.cjs.js');
7
+
8
+ const glide = createGeneratorEasing.createGeneratorEasing(generator.createGlideGenerator);
9
+
10
+ exports.glide = glide;
@@ -0,0 +1,6 @@
1
+ import { createGlideGenerator } from './generator.es.js';
2
+ import { createGeneratorEasing } from '../utils/create-generator-easing.es.js';
3
+
4
+ const glide = createGeneratorEasing(createGlideGenerator);
5
+
6
+ export { glide };
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var velocityPerSecond = require('../../../../utils/velocity-per-second.cjs.js');
6
+ var hasReachedTarget = require('../utils/has-reached-target.cjs.js');
6
7
 
7
8
  const defaultStiffness = 100.0;
8
9
  const defaultDamping = 10.0;
@@ -11,15 +12,17 @@ const calcDampingRatio = (stiffness = defaultStiffness, damping = defaultDamping
11
12
  const calcAngularFreq = (undampedFreq, dampingRatio) => undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
12
13
  const createSpringGenerator = ({ stiffness = defaultStiffness, damping = defaultDamping, mass = defaultMass, from = 0, to = 1, velocity = 0.0, restSpeed = 2, restDistance = 0.5, } = {}) => {
13
14
  velocity = velocity ? velocity / 1000 : 0.0;
14
- const dampingRatio = calcDampingRatio(stiffness, damping, mass);
15
- const initialDelta = to - from;
16
- const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
17
- const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
18
15
  const state = {
19
16
  done: false,
20
17
  value: from,
18
+ target: to,
21
19
  velocity,
20
+ hasReachedTarget: false,
22
21
  };
22
+ const dampingRatio = calcDampingRatio(stiffness, damping, mass);
23
+ const initialDelta = to - from;
24
+ const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
25
+ const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
23
26
  let resolveSpring;
24
27
  if (dampingRatio < 1) {
25
28
  // Underdamped spring (bouncy)
@@ -44,6 +47,7 @@ const createSpringGenerator = ({ stiffness = defaultStiffness, damping = default
44
47
  const isBelowVelocityThreshold = Math.abs(state.velocity) <= restSpeed;
45
48
  const isBelowDisplacementThreshold = Math.abs(to - state.value) <= restDistance;
46
49
  state.done = isBelowVelocityThreshold && isBelowDisplacementThreshold;
50
+ state.hasReachedTarget = hasReachedTarget.hasReachedTarget(from, to, state.value);
47
51
  return state;
48
52
  },
49
53
  };
@@ -56,4 +60,5 @@ function calcVelocity(resolveValue, t, current) {
56
60
 
57
61
  exports.calcAngularFreq = calcAngularFreq;
58
62
  exports.calcDampingRatio = calcDampingRatio;
63
+ exports.calcVelocity = calcVelocity;
59
64
  exports.createSpringGenerator = createSpringGenerator;
@@ -1,4 +1,5 @@
1
1
  import { velocityPerSecond } from '../../../../utils/velocity-per-second.es.js';
2
+ import { hasReachedTarget } from '../utils/has-reached-target.es.js';
2
3
 
3
4
  const defaultStiffness = 100.0;
4
5
  const defaultDamping = 10.0;
@@ -7,15 +8,17 @@ const calcDampingRatio = (stiffness = defaultStiffness, damping = defaultDamping
7
8
  const calcAngularFreq = (undampedFreq, dampingRatio) => undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
8
9
  const createSpringGenerator = ({ stiffness = defaultStiffness, damping = defaultDamping, mass = defaultMass, from = 0, to = 1, velocity = 0.0, restSpeed = 2, restDistance = 0.5, } = {}) => {
9
10
  velocity = velocity ? velocity / 1000 : 0.0;
10
- const dampingRatio = calcDampingRatio(stiffness, damping, mass);
11
- const initialDelta = to - from;
12
- const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
13
- const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
14
11
  const state = {
15
12
  done: false,
16
13
  value: from,
14
+ target: to,
17
15
  velocity,
16
+ hasReachedTarget: false,
18
17
  };
18
+ const dampingRatio = calcDampingRatio(stiffness, damping, mass);
19
+ const initialDelta = to - from;
20
+ const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
21
+ const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
19
22
  let resolveSpring;
20
23
  if (dampingRatio < 1) {
21
24
  // Underdamped spring (bouncy)
@@ -40,6 +43,7 @@ const createSpringGenerator = ({ stiffness = defaultStiffness, damping = default
40
43
  const isBelowVelocityThreshold = Math.abs(state.velocity) <= restSpeed;
41
44
  const isBelowDisplacementThreshold = Math.abs(to - state.value) <= restDistance;
42
45
  state.done = isBelowVelocityThreshold && isBelowDisplacementThreshold;
46
+ state.hasReachedTarget = hasReachedTarget(from, to, state.value);
43
47
  return state;
44
48
  },
45
49
  };
@@ -50,4 +54,4 @@ function calcVelocity(resolveValue, t, current) {
50
54
  return velocityPerSecond(current - resolveValue(prevT), 5);
51
55
  }
52
56
 
53
- export { calcAngularFreq, calcDampingRatio, createSpringGenerator };
57
+ export { calcAngularFreq, calcDampingRatio, calcVelocity, createSpringGenerator };
@@ -3,68 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var generator = require('./generator.cjs.js');
6
- var pregenerateKeyframes = require('../utils/pregenerate-keyframes.cjs.js');
6
+ var createGeneratorEasing = require('../utils/create-generator-easing.cjs.js');
7
7
 
8
- function spring(options = {}) {
9
- const springCache = new Map();
10
- const keyframesCache = new WeakMap();
11
- const getSpring = (from = 0, to = 100, velocity = 0, isScale = false) => {
12
- const key = `${from}-${to}-${velocity}-${isScale}`;
13
- if (!springCache.has(key)) {
14
- springCache.set(key, generator.createSpringGenerator(Object.assign({ from,
15
- to,
16
- velocity, restSpeed: isScale ? 0.05 : 2, restDistance: isScale ? 0.01 : 0.5 }, options)));
17
- }
18
- return springCache.get(key);
19
- };
20
- const getKeyframes = (generator, origin, target) => {
21
- if (!keyframesCache.has(generator)) {
22
- keyframesCache.set(generator, pregenerateKeyframes.pregenerateKeyframes(generator, origin, target));
23
- }
24
- return keyframesCache.get(generator);
25
- };
26
- return {
27
- createAnimation: (keyframes, getOrigin, canUseRealSpring, name, data) => {
28
- let settings;
29
- let spring;
30
- const numKeyframes = keyframes.length;
31
- let shouldUseRealSpring = canUseRealSpring && numKeyframes <= 2 && keyframes.every(isNumberOrNull);
32
- if (shouldUseRealSpring) {
33
- const prevAnimationState = name && data && getPreviousAnimationState(name, data);
34
- const velocity = prevAnimationState &&
35
- (numKeyframes === 1 || (numKeyframes === 2 && keyframes[0] === null))
36
- ? prevAnimationState.velocity
37
- : 0;
38
- const target = keyframes[numKeyframes - 1];
39
- const unresolvedOrigin = numKeyframes === 1 ? null : keyframes[0];
40
- const origin = unresolvedOrigin === null
41
- ? prevAnimationState
42
- ? prevAnimationState.value
43
- : parseFloat(getOrigin())
44
- : unresolvedOrigin;
45
- spring = getSpring(origin, target, velocity, name === null || name === void 0 ? void 0 : name.includes("scale"));
46
- const keyframesMetadata = getKeyframes(spring, origin, target);
47
- settings = Object.assign(Object.assign({}, keyframesMetadata), { easing: "linear" });
48
- }
49
- else {
50
- spring = getSpring(0, 100);
51
- const keyframesMetadata = getKeyframes(spring, 0, 100);
52
- settings = {
53
- easing: "ease",
54
- duration: keyframesMetadata.overshootDuration,
55
- };
56
- }
57
- return settings;
58
- },
59
- };
60
- }
61
- function getPreviousAnimationState(name, data) {
62
- const animation = data.activeAnimations[name];
63
- const generator = data.activeGenerators[name];
64
- if (animation && generator) {
65
- return generator.next(animation.currentTime);
66
- }
67
- }
68
- const isNumberOrNull = (value) => typeof value !== "string";
8
+ const spring = createGeneratorEasing.createGeneratorEasing(generator.createSpringGenerator);
69
9
 
70
10
  exports.spring = spring;
@@ -1,66 +1,6 @@
1
1
  import { createSpringGenerator } from './generator.es.js';
2
- import { pregenerateKeyframes } from '../utils/pregenerate-keyframes.es.js';
2
+ import { createGeneratorEasing } from '../utils/create-generator-easing.es.js';
3
3
 
4
- function spring(options = {}) {
5
- const springCache = new Map();
6
- const keyframesCache = new WeakMap();
7
- const getSpring = (from = 0, to = 100, velocity = 0, isScale = false) => {
8
- const key = `${from}-${to}-${velocity}-${isScale}`;
9
- if (!springCache.has(key)) {
10
- springCache.set(key, createSpringGenerator(Object.assign({ from,
11
- to,
12
- velocity, restSpeed: isScale ? 0.05 : 2, restDistance: isScale ? 0.01 : 0.5 }, options)));
13
- }
14
- return springCache.get(key);
15
- };
16
- const getKeyframes = (generator, origin, target) => {
17
- if (!keyframesCache.has(generator)) {
18
- keyframesCache.set(generator, pregenerateKeyframes(generator, origin, target));
19
- }
20
- return keyframesCache.get(generator);
21
- };
22
- return {
23
- createAnimation: (keyframes, getOrigin, canUseRealSpring, name, data) => {
24
- let settings;
25
- let spring;
26
- const numKeyframes = keyframes.length;
27
- let shouldUseRealSpring = canUseRealSpring && numKeyframes <= 2 && keyframes.every(isNumberOrNull);
28
- if (shouldUseRealSpring) {
29
- const prevAnimationState = name && data && getPreviousAnimationState(name, data);
30
- const velocity = prevAnimationState &&
31
- (numKeyframes === 1 || (numKeyframes === 2 && keyframes[0] === null))
32
- ? prevAnimationState.velocity
33
- : 0;
34
- const target = keyframes[numKeyframes - 1];
35
- const unresolvedOrigin = numKeyframes === 1 ? null : keyframes[0];
36
- const origin = unresolvedOrigin === null
37
- ? prevAnimationState
38
- ? prevAnimationState.value
39
- : parseFloat(getOrigin())
40
- : unresolvedOrigin;
41
- spring = getSpring(origin, target, velocity, name === null || name === void 0 ? void 0 : name.includes("scale"));
42
- const keyframesMetadata = getKeyframes(spring, origin, target);
43
- settings = Object.assign(Object.assign({}, keyframesMetadata), { easing: "linear" });
44
- }
45
- else {
46
- spring = getSpring(0, 100);
47
- const keyframesMetadata = getKeyframes(spring, 0, 100);
48
- settings = {
49
- easing: "ease",
50
- duration: keyframesMetadata.overshootDuration,
51
- };
52
- }
53
- return settings;
54
- },
55
- };
56
- }
57
- function getPreviousAnimationState(name, data) {
58
- const animation = data.activeAnimations[name];
59
- const generator = data.activeGenerators[name];
60
- if (animation && generator) {
61
- return generator.next(animation.currentTime);
62
- }
63
- }
64
- const isNumberOrNull = (value) => typeof value !== "string";
4
+ const spring = createGeneratorEasing(createSpringGenerator);
65
5
 
66
6
  export { spring };
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var pregenerateKeyframes = require('./pregenerate-keyframes.cjs.js');
6
+
7
+ function createGeneratorEasing(createGenerator) {
8
+ const keyframesCache = new WeakMap();
9
+ return (options = {}) => {
10
+ const generatorCache = new Map();
11
+ const getGenerator = (from = 0, to = 100, velocity = 0, isScale = false) => {
12
+ const key = `${from}-${to}-${velocity}-${isScale}`;
13
+ if (!generatorCache.has(key)) {
14
+ generatorCache.set(key, createGenerator(Object.assign({ from,
15
+ to,
16
+ velocity, restSpeed: isScale ? 0.05 : 2, restDistance: isScale ? 0.01 : 0.5 }, options)));
17
+ }
18
+ return generatorCache.get(key);
19
+ };
20
+ const getKeyframes = (generator) => {
21
+ if (!keyframesCache.has(generator)) {
22
+ keyframesCache.set(generator, pregenerateKeyframes.pregenerateKeyframes(generator));
23
+ }
24
+ return keyframesCache.get(generator);
25
+ };
26
+ return {
27
+ createAnimation: (keyframes, getOrigin, canUseGenerator, name, data) => {
28
+ let settings;
29
+ let generator;
30
+ const numKeyframes = keyframes.length;
31
+ let shouldUseGenerator = canUseGenerator &&
32
+ numKeyframes <= 2 &&
33
+ keyframes.every(isNumberOrNull);
34
+ if (shouldUseGenerator) {
35
+ const prevAnimationState = name && data && data.prevGeneratorState[name];
36
+ const velocity = prevAnimationState &&
37
+ (numKeyframes === 1 ||
38
+ (numKeyframes === 2 && keyframes[0] === null))
39
+ ? prevAnimationState.velocity
40
+ : 0;
41
+ const target = keyframes[numKeyframes - 1];
42
+ const unresolvedOrigin = numKeyframes === 1 ? null : keyframes[0];
43
+ const origin = unresolvedOrigin === null
44
+ ? prevAnimationState
45
+ ? prevAnimationState.value
46
+ : parseFloat(getOrigin())
47
+ : unresolvedOrigin;
48
+ generator = getGenerator(origin, target, velocity, name === null || name === void 0 ? void 0 : name.includes("scale"));
49
+ const keyframesMetadata = getKeyframes(generator);
50
+ settings = Object.assign(Object.assign({}, keyframesMetadata), { easing: "linear" });
51
+ }
52
+ else {
53
+ generator = getGenerator(0, 100);
54
+ const keyframesMetadata = getKeyframes(generator);
55
+ settings = {
56
+ easing: "ease",
57
+ duration: keyframesMetadata.overshootDuration,
58
+ };
59
+ }
60
+ // TODO Add test for this
61
+ if (generator && data && name) {
62
+ data.generators[name] = generator;
63
+ }
64
+ return settings;
65
+ },
66
+ };
67
+ };
68
+ }
69
+ const isNumberOrNull = (value) => typeof value !== "string";
70
+
71
+ exports.createGeneratorEasing = createGeneratorEasing;