framer-motion 7.6.16 → 7.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +914 -56
- package/dist/es/animation/legacy-popmotion/decay.mjs +27 -0
- package/dist/es/animation/legacy-popmotion/find-spring.mjs +88 -0
- package/dist/es/animation/legacy-popmotion/index.mjs +101 -0
- package/dist/es/animation/legacy-popmotion/inertia.mjs +85 -0
- package/dist/es/animation/legacy-popmotion/keyframes.mjs +52 -0
- package/dist/es/animation/legacy-popmotion/spring.mjs +146 -0
- package/dist/es/animation/utils/easing.mjs +7 -5
- package/dist/es/animation/utils/transitions.mjs +2 -1
- package/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
- package/dist/es/easing/anticipate.mjs +11 -0
- package/dist/es/easing/back.mjs +9 -0
- package/dist/es/easing/circ.mjs +8 -0
- package/dist/es/easing/cubic-bezier.mjs +51 -0
- package/dist/es/easing/ease.mjs +8 -0
- package/dist/es/easing/modifiers/mirror.mjs +5 -0
- package/dist/es/easing/modifiers/reverse.mjs +5 -0
- package/dist/es/gestures/PanSession.mjs +3 -2
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -1
- package/dist/es/gestures/drag/utils/constraints.mjs +3 -1
- package/dist/es/gestures/use-tap-gesture.mjs +1 -1
- package/dist/es/index.mjs +5 -0
- package/dist/es/projection/animation/mix-values.mjs +5 -2
- package/dist/es/projection/geometry/delta-apply.mjs +1 -1
- package/dist/es/projection/geometry/delta-calc.mjs +1 -1
- package/dist/es/projection/geometry/delta-remove.mjs +1 -1
- package/dist/es/projection/node/create-projection-node.mjs +1 -1
- package/dist/es/projection/styles/scale-box-shadow.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/utils/clamp.mjs +3 -0
- package/dist/es/utils/distance.mjs +9 -0
- package/dist/es/utils/hsla-to-rgba.mjs +42 -0
- package/dist/es/utils/interpolate.mjs +91 -0
- package/dist/es/utils/mix-color.mjs +37 -0
- package/dist/es/utils/mix-complex.mjs +79 -0
- package/dist/es/utils/mix.mjs +24 -0
- package/dist/es/utils/noop.mjs +3 -0
- package/dist/es/utils/pipe.mjs +11 -0
- package/dist/es/utils/progress.mjs +18 -0
- package/dist/es/utils/transform.mjs +1 -1
- package/dist/es/utils/use-cycle.mjs +1 -1
- package/dist/es/utils/velocity-per-second.mjs +11 -0
- package/dist/es/utils/wrap.mjs +6 -0
- package/dist/es/value/index.mjs +2 -2
- package/dist/es/value/use-on-change.mjs +3 -1
- package/dist/es/value/use-spring.mjs +1 -1
- package/dist/framer-motion.dev.js +1272 -1222
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +41 -30
- package/dist/projection.dev.js +1397 -1373
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/size-webpack-dom-animation.js +1 -1
- package/dist/size-webpack-dom-max.js +1 -1
- package/dist/three-entry.d.ts +1 -16
- package/package.json +7 -8
package/dist/cjs/index.js
CHANGED
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var styleValueTypes = require('style-value-types');
|
|
7
|
-
var popmotion = require('popmotion');
|
|
8
7
|
var heyListen = require('hey-listen');
|
|
9
8
|
var sync = require('framesync');
|
|
10
9
|
var dom = require('@motionone/dom');
|
|
@@ -1497,6 +1496,16 @@ function useUnmountEffect(callback) {
|
|
|
1497
1496
|
return React.useEffect(() => () => callback(), []);
|
|
1498
1497
|
}
|
|
1499
1498
|
|
|
1499
|
+
/**
|
|
1500
|
+
* Pipe
|
|
1501
|
+
* Compose other transformers to run linearily
|
|
1502
|
+
* pipe(min(20), max(40))
|
|
1503
|
+
* @param {...functions} transformers
|
|
1504
|
+
* @return {function}
|
|
1505
|
+
*/
|
|
1506
|
+
const combineFunctions = (a, b) => (v) => b(a(v));
|
|
1507
|
+
const pipe = (...transformers) => transformers.reduce(combineFunctions);
|
|
1508
|
+
|
|
1500
1509
|
/**
|
|
1501
1510
|
* @param handlers -
|
|
1502
1511
|
* @internal
|
|
@@ -1543,7 +1552,7 @@ function useTapGesture({ onTap, onTapStart, onTapCancel, whileTap, visualElement
|
|
|
1543
1552
|
if (isPressing.current)
|
|
1544
1553
|
return;
|
|
1545
1554
|
isPressing.current = true;
|
|
1546
|
-
cancelPointerEndListeners.current =
|
|
1555
|
+
cancelPointerEndListeners.current = pipe(addPointerEvent(window, "pointerup", onPointerUp, eventOptions), addPointerEvent(window, "pointercancel", onPointerCancel, eventOptions));
|
|
1547
1556
|
/**
|
|
1548
1557
|
* Ensure we trigger animations before firing event callback
|
|
1549
1558
|
*/
|
|
@@ -1808,28 +1817,104 @@ function shallowCompare(next, prev) {
|
|
|
1808
1817
|
*/
|
|
1809
1818
|
const secondsToMilliseconds = (seconds) => seconds * 1000;
|
|
1810
1819
|
|
|
1820
|
+
const noop = (any) => any;
|
|
1821
|
+
|
|
1822
|
+
/*
|
|
1823
|
+
Bezier function generator
|
|
1824
|
+
This has been modified from Gaëtan Renaudeau's BezierEasing
|
|
1825
|
+
https://github.com/gre/bezier-easing/blob/master/src/index.js
|
|
1826
|
+
https://github.com/gre/bezier-easing/blob/master/LICENSE
|
|
1827
|
+
|
|
1828
|
+
I've removed the newtonRaphsonIterate algo because in benchmarking it
|
|
1829
|
+
wasn't noticiably faster than binarySubdivision, indeed removing it
|
|
1830
|
+
usually improved times, depending on the curve.
|
|
1831
|
+
I also removed the lookup table, as for the added bundle size and loop we're
|
|
1832
|
+
only cutting ~4 or so subdivision iterations. I bumped the max iterations up
|
|
1833
|
+
to 12 to compensate and this still tended to be faster for no perceivable
|
|
1834
|
+
loss in accuracy.
|
|
1835
|
+
Usage
|
|
1836
|
+
const easeOut = cubicBezier(.17,.67,.83,.67);
|
|
1837
|
+
const x = easeOut(0.5); // returns 0.627...
|
|
1838
|
+
*/
|
|
1839
|
+
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
|
1840
|
+
const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
|
|
1841
|
+
t;
|
|
1842
|
+
const subdivisionPrecision = 0.0000001;
|
|
1843
|
+
const subdivisionMaxIterations = 12;
|
|
1844
|
+
function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
|
|
1845
|
+
let currentX;
|
|
1846
|
+
let currentT;
|
|
1847
|
+
let i = 0;
|
|
1848
|
+
do {
|
|
1849
|
+
currentT = lowerBound + (upperBound - lowerBound) / 2.0;
|
|
1850
|
+
currentX = calcBezier(currentT, mX1, mX2) - x;
|
|
1851
|
+
if (currentX > 0.0) {
|
|
1852
|
+
upperBound = currentT;
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
lowerBound = currentT;
|
|
1856
|
+
}
|
|
1857
|
+
} while (Math.abs(currentX) > subdivisionPrecision &&
|
|
1858
|
+
++i < subdivisionMaxIterations);
|
|
1859
|
+
return currentT;
|
|
1860
|
+
}
|
|
1861
|
+
function cubicBezier(mX1, mY1, mX2, mY2) {
|
|
1862
|
+
// If this is a linear gradient, return linear easing
|
|
1863
|
+
if (mX1 === mY1 && mX2 === mY2)
|
|
1864
|
+
return noop;
|
|
1865
|
+
const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
|
|
1866
|
+
// If animation is at start/end, return t without easing
|
|
1867
|
+
return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
// Accepts an easing function and returns a new one that outputs mirrored values for
|
|
1871
|
+
// the second half of the animation. Turns easeIn into easeInOut.
|
|
1872
|
+
const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
|
|
1873
|
+
|
|
1874
|
+
// Accepts an easing function and returns a new one that outputs reversed values.
|
|
1875
|
+
// Turns easeIn into easeOut.
|
|
1876
|
+
const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
|
|
1877
|
+
|
|
1878
|
+
const easeIn = (p) => p * p;
|
|
1879
|
+
const easeOut = reverseEasing(easeIn);
|
|
1880
|
+
const easeInOut = mirrorEasing(easeIn);
|
|
1881
|
+
|
|
1882
|
+
const circIn = (p) => 1 - Math.sin(Math.acos(p));
|
|
1883
|
+
const circOut = reverseEasing(circIn);
|
|
1884
|
+
const circInOut = mirrorEasing(circOut);
|
|
1885
|
+
|
|
1886
|
+
const createBackIn = (power = 1.525) => (p) => p * p * ((power + 1) * p - power);
|
|
1887
|
+
const backIn = createBackIn();
|
|
1888
|
+
const backOut = reverseEasing(backIn);
|
|
1889
|
+
const backInOut = mirrorEasing(backIn);
|
|
1890
|
+
|
|
1891
|
+
const createAnticipate = (power) => {
|
|
1892
|
+
const backEasing = createBackIn(power);
|
|
1893
|
+
return (p) => (p *= 2) < 1
|
|
1894
|
+
? 0.5 * backEasing(p)
|
|
1895
|
+
: 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
|
|
1896
|
+
};
|
|
1897
|
+
const anticipate = createAnticipate();
|
|
1898
|
+
|
|
1811
1899
|
const easingLookup = {
|
|
1812
|
-
linear:
|
|
1813
|
-
easeIn
|
|
1814
|
-
easeInOut
|
|
1815
|
-
easeOut
|
|
1816
|
-
circIn
|
|
1817
|
-
circInOut
|
|
1818
|
-
circOut
|
|
1819
|
-
backIn
|
|
1820
|
-
backInOut
|
|
1821
|
-
backOut
|
|
1822
|
-
anticipate
|
|
1823
|
-
bounceIn: popmotion.bounceIn,
|
|
1824
|
-
bounceInOut: popmotion.bounceInOut,
|
|
1825
|
-
bounceOut: popmotion.bounceOut,
|
|
1900
|
+
linear: noop,
|
|
1901
|
+
easeIn,
|
|
1902
|
+
easeInOut,
|
|
1903
|
+
easeOut,
|
|
1904
|
+
circIn,
|
|
1905
|
+
circInOut,
|
|
1906
|
+
circOut,
|
|
1907
|
+
backIn,
|
|
1908
|
+
backInOut,
|
|
1909
|
+
backOut,
|
|
1910
|
+
anticipate,
|
|
1826
1911
|
};
|
|
1827
1912
|
const easingDefinitionToFunction = (definition) => {
|
|
1828
1913
|
if (Array.isArray(definition)) {
|
|
1829
1914
|
// If cubic bezier definition, create bezier curve
|
|
1830
1915
|
heyListen.invariant(definition.length === 4, `Cubic bezier arrays must contain four numerical values.`);
|
|
1831
1916
|
const [x1, y1, x2, y2] = definition;
|
|
1832
|
-
return
|
|
1917
|
+
return cubicBezier(x1, y1, x2, y2);
|
|
1833
1918
|
}
|
|
1834
1919
|
else if (typeof definition === "string") {
|
|
1835
1920
|
// Else lookup from table
|
|
@@ -1886,7 +1971,7 @@ const linearTween = () => ({
|
|
|
1886
1971
|
ease: "linear",
|
|
1887
1972
|
duration: 0.3,
|
|
1888
1973
|
});
|
|
1889
|
-
const keyframes = (values) => ({
|
|
1974
|
+
const keyframes$1 = (values) => ({
|
|
1890
1975
|
type: "keyframes",
|
|
1891
1976
|
duration: 0.8,
|
|
1892
1977
|
values,
|
|
@@ -1910,7 +1995,7 @@ const defaultTransitions = {
|
|
|
1910
1995
|
const getDefaultTransition = (valueKey, to) => {
|
|
1911
1996
|
let transitionFactory;
|
|
1912
1997
|
if (isKeyframesTarget(to)) {
|
|
1913
|
-
transitionFactory = keyframes;
|
|
1998
|
+
transitionFactory = keyframes$1;
|
|
1914
1999
|
}
|
|
1915
2000
|
else {
|
|
1916
2001
|
transitionFactory =
|
|
@@ -1970,6 +2055,758 @@ function delay(callback, timeout) {
|
|
|
1970
2055
|
return () => sync.cancelSync.read(checkElapsed);
|
|
1971
2056
|
}
|
|
1972
2057
|
|
|
2058
|
+
const clamp = (min, max, v) => Math.min(Math.max(v, min), max);
|
|
2059
|
+
|
|
2060
|
+
/*
|
|
2061
|
+
Value in range from progress
|
|
2062
|
+
|
|
2063
|
+
Given a lower limit and an upper limit, we return the value within
|
|
2064
|
+
that range as expressed by progress (usually a number from 0 to 1)
|
|
2065
|
+
|
|
2066
|
+
So progress = 0.5 would change
|
|
2067
|
+
|
|
2068
|
+
from -------- to
|
|
2069
|
+
|
|
2070
|
+
to
|
|
2071
|
+
|
|
2072
|
+
from ---- to
|
|
2073
|
+
|
|
2074
|
+
E.g. from = 10, to = 20, progress = 0.5 => 15
|
|
2075
|
+
|
|
2076
|
+
@param [number]: Lower limit of range
|
|
2077
|
+
@param [number]: Upper limit of range
|
|
2078
|
+
@param [number]: The progress between lower and upper limits expressed 0-1
|
|
2079
|
+
@return [number]: Value as calculated from progress within range (not limited within range)
|
|
2080
|
+
*/
|
|
2081
|
+
const mix = (from, to, progress) => -progress * from + progress * to + from;
|
|
2082
|
+
|
|
2083
|
+
// Adapted from https://gist.github.com/mjackson/5311256
|
|
2084
|
+
function hueToRgb(p, q, t) {
|
|
2085
|
+
if (t < 0)
|
|
2086
|
+
t += 1;
|
|
2087
|
+
if (t > 1)
|
|
2088
|
+
t -= 1;
|
|
2089
|
+
if (t < 1 / 6)
|
|
2090
|
+
return p + (q - p) * 6 * t;
|
|
2091
|
+
if (t < 1 / 2)
|
|
2092
|
+
return q;
|
|
2093
|
+
if (t < 2 / 3)
|
|
2094
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
2095
|
+
return p;
|
|
2096
|
+
}
|
|
2097
|
+
function hslaToRgba({ hue, saturation, lightness, alpha }) {
|
|
2098
|
+
hue /= 360;
|
|
2099
|
+
saturation /= 100;
|
|
2100
|
+
lightness /= 100;
|
|
2101
|
+
let red = 0;
|
|
2102
|
+
let green = 0;
|
|
2103
|
+
let blue = 0;
|
|
2104
|
+
if (!saturation) {
|
|
2105
|
+
red = green = blue = lightness;
|
|
2106
|
+
}
|
|
2107
|
+
else {
|
|
2108
|
+
const q = lightness < 0.5
|
|
2109
|
+
? lightness * (1 + saturation)
|
|
2110
|
+
: lightness + saturation - lightness * saturation;
|
|
2111
|
+
const p = 2 * lightness - q;
|
|
2112
|
+
red = hueToRgb(p, q, hue + 1 / 3);
|
|
2113
|
+
green = hueToRgb(p, q, hue);
|
|
2114
|
+
blue = hueToRgb(p, q, hue - 1 / 3);
|
|
2115
|
+
}
|
|
2116
|
+
return {
|
|
2117
|
+
red: Math.round(red * 255),
|
|
2118
|
+
green: Math.round(green * 255),
|
|
2119
|
+
blue: Math.round(blue * 255),
|
|
2120
|
+
alpha,
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
// Linear color space blending
|
|
2125
|
+
// Explained https://www.youtube.com/watch?v=LKnqECcg6Gw
|
|
2126
|
+
// Demonstrated http://codepen.io/osublake/pen/xGVVaN
|
|
2127
|
+
const mixLinearColor = (from, to, v) => {
|
|
2128
|
+
const fromExpo = from * from;
|
|
2129
|
+
return Math.sqrt(Math.max(0, v * (to * to - fromExpo) + fromExpo));
|
|
2130
|
+
};
|
|
2131
|
+
const colorTypes = [styleValueTypes.hex, styleValueTypes.rgba, styleValueTypes.hsla];
|
|
2132
|
+
const getColorType = (v) => colorTypes.find((type) => type.test(v));
|
|
2133
|
+
function asRGBA(color) {
|
|
2134
|
+
const type = getColorType(color);
|
|
2135
|
+
heyListen.invariant(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
|
|
2136
|
+
let model = type.parse(color);
|
|
2137
|
+
if (type === styleValueTypes.hsla) {
|
|
2138
|
+
model = hslaToRgba(model);
|
|
2139
|
+
}
|
|
2140
|
+
return model;
|
|
2141
|
+
}
|
|
2142
|
+
const mixColor = (from, to) => {
|
|
2143
|
+
const fromRGBA = asRGBA(from);
|
|
2144
|
+
const toRGBA = asRGBA(to);
|
|
2145
|
+
const blended = { ...fromRGBA };
|
|
2146
|
+
return (v) => {
|
|
2147
|
+
blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
|
|
2148
|
+
blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
|
|
2149
|
+
blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
|
|
2150
|
+
blended.alpha = mix(fromRGBA.alpha, toRGBA.alpha, v);
|
|
2151
|
+
return styleValueTypes.rgba.transform(blended);
|
|
2152
|
+
};
|
|
2153
|
+
};
|
|
2154
|
+
|
|
2155
|
+
function getMixer$1(origin, target) {
|
|
2156
|
+
if (typeof origin === "number") {
|
|
2157
|
+
return (v) => mix(origin, target, v);
|
|
2158
|
+
}
|
|
2159
|
+
else if (styleValueTypes.color.test(origin)) {
|
|
2160
|
+
return mixColor(origin, target);
|
|
2161
|
+
}
|
|
2162
|
+
else {
|
|
2163
|
+
return mixComplex(origin, target);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
const mixArray = (from, to) => {
|
|
2167
|
+
const output = [...from];
|
|
2168
|
+
const numValues = output.length;
|
|
2169
|
+
const blendValue = from.map((fromThis, i) => getMixer$1(fromThis, to[i]));
|
|
2170
|
+
return (v) => {
|
|
2171
|
+
for (let i = 0; i < numValues; i++) {
|
|
2172
|
+
output[i] = blendValue[i](v);
|
|
2173
|
+
}
|
|
2174
|
+
return output;
|
|
2175
|
+
};
|
|
2176
|
+
};
|
|
2177
|
+
const mixObject = (origin, target) => {
|
|
2178
|
+
const output = { ...origin, ...target };
|
|
2179
|
+
const blendValue = {};
|
|
2180
|
+
for (const key in output) {
|
|
2181
|
+
if (origin[key] !== undefined && target[key] !== undefined) {
|
|
2182
|
+
blendValue[key] = getMixer$1(origin[key], target[key]);
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
return (v) => {
|
|
2186
|
+
for (const key in blendValue) {
|
|
2187
|
+
output[key] = blendValue[key](v);
|
|
2188
|
+
}
|
|
2189
|
+
return output;
|
|
2190
|
+
};
|
|
2191
|
+
};
|
|
2192
|
+
/**
|
|
2193
|
+
* TODO: Combine with function within complex when style-value-types moved inside Framer Motion
|
|
2194
|
+
*/
|
|
2195
|
+
function analyse(value) {
|
|
2196
|
+
const parsed = styleValueTypes.complex.parse(value);
|
|
2197
|
+
const numValues = parsed.length;
|
|
2198
|
+
let numNumbers = 0;
|
|
2199
|
+
let numColors = 0;
|
|
2200
|
+
for (let i = 0; i < numValues; i++) {
|
|
2201
|
+
// Parsed complex values return with colors first, so if we've seen any number
|
|
2202
|
+
// we're already past that part of the array and don't need to continue running typeof
|
|
2203
|
+
if (numNumbers || typeof parsed[i] === "number") {
|
|
2204
|
+
numNumbers++;
|
|
2205
|
+
}
|
|
2206
|
+
else {
|
|
2207
|
+
numColors++;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
return { parsed, numNumbers, numColors };
|
|
2211
|
+
}
|
|
2212
|
+
const mixComplex = (origin, target) => {
|
|
2213
|
+
const template = styleValueTypes.complex.createTransformer(target);
|
|
2214
|
+
const originStats = analyse(origin);
|
|
2215
|
+
const targetStats = analyse(target);
|
|
2216
|
+
const canInterpolate = originStats.numColors === targetStats.numColors &&
|
|
2217
|
+
originStats.numNumbers >= targetStats.numNumbers;
|
|
2218
|
+
if (canInterpolate) {
|
|
2219
|
+
return pipe(mixArray(originStats.parsed, targetStats.parsed), template);
|
|
2220
|
+
}
|
|
2221
|
+
else {
|
|
2222
|
+
heyListen.warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`);
|
|
2223
|
+
return (p) => `${p > 0 ? target : origin}`;
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
|
|
2227
|
+
/*
|
|
2228
|
+
Progress within given range
|
|
2229
|
+
|
|
2230
|
+
Given a lower limit and an upper limit, we return the progress
|
|
2231
|
+
(expressed as a number 0-1) represented by the given value, and
|
|
2232
|
+
limit that progress to within 0-1.
|
|
2233
|
+
|
|
2234
|
+
@param [number]: Lower limit
|
|
2235
|
+
@param [number]: Upper limit
|
|
2236
|
+
@param [number]: Value to find progress within given range
|
|
2237
|
+
@return [number]: Progress of value within range as expressed 0-1
|
|
2238
|
+
*/
|
|
2239
|
+
const progress = (from, to, value) => {
|
|
2240
|
+
const toFromDifference = to - from;
|
|
2241
|
+
return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
|
|
2242
|
+
};
|
|
2243
|
+
|
|
2244
|
+
const mixNumber = (from, to) => (p) => mix(from, to, p);
|
|
2245
|
+
function detectMixerFactory(v) {
|
|
2246
|
+
if (typeof v === "number") {
|
|
2247
|
+
return mixNumber;
|
|
2248
|
+
}
|
|
2249
|
+
else if (typeof v === "string") {
|
|
2250
|
+
if (styleValueTypes.color.test(v)) {
|
|
2251
|
+
return mixColor;
|
|
2252
|
+
}
|
|
2253
|
+
else {
|
|
2254
|
+
return mixComplex;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
else if (Array.isArray(v)) {
|
|
2258
|
+
return mixArray;
|
|
2259
|
+
}
|
|
2260
|
+
else if (typeof v === "object") {
|
|
2261
|
+
return mixObject;
|
|
2262
|
+
}
|
|
2263
|
+
return mixNumber;
|
|
2264
|
+
}
|
|
2265
|
+
function createMixers(output, ease, customMixer) {
|
|
2266
|
+
const mixers = [];
|
|
2267
|
+
const mixerFactory = customMixer || detectMixerFactory(output[0]);
|
|
2268
|
+
const numMixers = output.length - 1;
|
|
2269
|
+
for (let i = 0; i < numMixers; i++) {
|
|
2270
|
+
let mixer = mixerFactory(output[i], output[i + 1]);
|
|
2271
|
+
if (ease) {
|
|
2272
|
+
const easingFunction = Array.isArray(ease) ? ease[i] : ease;
|
|
2273
|
+
mixer = pipe(easingFunction, mixer);
|
|
2274
|
+
}
|
|
2275
|
+
mixers.push(mixer);
|
|
2276
|
+
}
|
|
2277
|
+
return mixers;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Create a function that maps from a numerical input array to a generic output array.
|
|
2281
|
+
*
|
|
2282
|
+
* Accepts:
|
|
2283
|
+
* - Numbers
|
|
2284
|
+
* - Colors (hex, hsl, hsla, rgb, rgba)
|
|
2285
|
+
* - Complex (combinations of one or more numbers or strings)
|
|
2286
|
+
*
|
|
2287
|
+
* ```jsx
|
|
2288
|
+
* const mixColor = interpolate([0, 1], ['#fff', '#000'])
|
|
2289
|
+
*
|
|
2290
|
+
* mixColor(0.5) // 'rgba(128, 128, 128, 1)'
|
|
2291
|
+
* ```
|
|
2292
|
+
*
|
|
2293
|
+
* TODO Revist this approach once we've moved to data models for values,
|
|
2294
|
+
* probably not needed to pregenerate mixer functions.
|
|
2295
|
+
*
|
|
2296
|
+
* @public
|
|
2297
|
+
*/
|
|
2298
|
+
function interpolate(input, output, { clamp: isClamp = true, ease, mixer } = {}) {
|
|
2299
|
+
const inputLength = input.length;
|
|
2300
|
+
heyListen.invariant(inputLength === output.length, "Both input and output ranges must be the same length");
|
|
2301
|
+
heyListen.invariant(!ease || !Array.isArray(ease) || ease.length === inputLength - 1, "Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.");
|
|
2302
|
+
// If input runs highest -> lowest, reverse both arrays
|
|
2303
|
+
if (input[0] > input[inputLength - 1]) {
|
|
2304
|
+
input = [...input].reverse();
|
|
2305
|
+
output = [...output].reverse();
|
|
2306
|
+
}
|
|
2307
|
+
const mixers = createMixers(output, ease, mixer);
|
|
2308
|
+
const numMixers = mixers.length;
|
|
2309
|
+
const interpolator = (v) => {
|
|
2310
|
+
let i = 0;
|
|
2311
|
+
if (numMixers > 1) {
|
|
2312
|
+
for (; i < input.length - 2; i++) {
|
|
2313
|
+
if (v < input[i + 1])
|
|
2314
|
+
break;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
const progressInRange = progress(input[i], input[i + 1], v);
|
|
2318
|
+
return mixers[i](progressInRange);
|
|
2319
|
+
};
|
|
2320
|
+
return isClamp
|
|
2321
|
+
? (v) => interpolator(clamp(input[0], input[inputLength - 1], v))
|
|
2322
|
+
: interpolator;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
function defaultEasing(values, easing) {
|
|
2326
|
+
return values.map(() => easing || easeInOut).splice(0, values.length - 1);
|
|
2327
|
+
}
|
|
2328
|
+
function defaultOffset(values) {
|
|
2329
|
+
const numValues = values.length;
|
|
2330
|
+
return values.map((_value, i) => i !== 0 ? i / (numValues - 1) : 0);
|
|
2331
|
+
}
|
|
2332
|
+
function convertOffsetToTimes(offset, duration) {
|
|
2333
|
+
return offset.map((o) => o * duration);
|
|
2334
|
+
}
|
|
2335
|
+
function keyframes({ from = 0, to = 1, ease, offset, duration = 300, }) {
|
|
2336
|
+
/**
|
|
2337
|
+
* This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
|
|
2338
|
+
* to reduce GC during animation.
|
|
2339
|
+
*/
|
|
2340
|
+
const state = { done: false, value: from };
|
|
2341
|
+
/**
|
|
2342
|
+
* Convert values to an array if they've been given as from/to options
|
|
2343
|
+
*/
|
|
2344
|
+
const values = Array.isArray(to) ? to : [from, to];
|
|
2345
|
+
/**
|
|
2346
|
+
* Create a times array based on the provided 0-1 offsets
|
|
2347
|
+
*/
|
|
2348
|
+
const times = convertOffsetToTimes(
|
|
2349
|
+
// Only use the provided offsets if they're the correct length
|
|
2350
|
+
// TODO Maybe we should warn here if there's a length mismatch
|
|
2351
|
+
offset && offset.length === values.length
|
|
2352
|
+
? offset
|
|
2353
|
+
: defaultOffset(values), duration);
|
|
2354
|
+
function createInterpolator() {
|
|
2355
|
+
return interpolate(times, values, {
|
|
2356
|
+
ease: Array.isArray(ease) ? ease : defaultEasing(values, ease),
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
let interpolator = createInterpolator();
|
|
2360
|
+
return {
|
|
2361
|
+
next: (t) => {
|
|
2362
|
+
state.value = interpolator(t);
|
|
2363
|
+
state.done = t >= duration;
|
|
2364
|
+
return state;
|
|
2365
|
+
},
|
|
2366
|
+
flipTarget: () => {
|
|
2367
|
+
values.reverse();
|
|
2368
|
+
interpolator = createInterpolator();
|
|
2369
|
+
},
|
|
2370
|
+
};
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
const safeMin = 0.001;
|
|
2374
|
+
const minDuration = 0.01;
|
|
2375
|
+
const maxDuration = 10.0;
|
|
2376
|
+
const minDamping = 0.05;
|
|
2377
|
+
const maxDamping = 1;
|
|
2378
|
+
function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }) {
|
|
2379
|
+
let envelope;
|
|
2380
|
+
let derivative;
|
|
2381
|
+
heyListen.warning(duration <= maxDuration * 1000, "Spring duration must be 10 seconds or less");
|
|
2382
|
+
let dampingRatio = 1 - bounce;
|
|
2383
|
+
/**
|
|
2384
|
+
* Restrict dampingRatio and duration to within acceptable ranges.
|
|
2385
|
+
*/
|
|
2386
|
+
dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
|
|
2387
|
+
duration = clamp(minDuration, maxDuration, duration / 1000);
|
|
2388
|
+
if (dampingRatio < 1) {
|
|
2389
|
+
/**
|
|
2390
|
+
* Underdamped spring
|
|
2391
|
+
*/
|
|
2392
|
+
envelope = (undampedFreq) => {
|
|
2393
|
+
const exponentialDecay = undampedFreq * dampingRatio;
|
|
2394
|
+
const delta = exponentialDecay * duration;
|
|
2395
|
+
const a = exponentialDecay - velocity;
|
|
2396
|
+
const b = calcAngularFreq(undampedFreq, dampingRatio);
|
|
2397
|
+
const c = Math.exp(-delta);
|
|
2398
|
+
return safeMin - (a / b) * c;
|
|
2399
|
+
};
|
|
2400
|
+
derivative = (undampedFreq) => {
|
|
2401
|
+
const exponentialDecay = undampedFreq * dampingRatio;
|
|
2402
|
+
const delta = exponentialDecay * duration;
|
|
2403
|
+
const d = delta * velocity + velocity;
|
|
2404
|
+
const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration;
|
|
2405
|
+
const f = Math.exp(-delta);
|
|
2406
|
+
const g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio);
|
|
2407
|
+
const factor = -envelope(undampedFreq) + safeMin > 0 ? -1 : 1;
|
|
2408
|
+
return (factor * ((d - e) * f)) / g;
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
else {
|
|
2412
|
+
/**
|
|
2413
|
+
* Critically-damped spring
|
|
2414
|
+
*/
|
|
2415
|
+
envelope = (undampedFreq) => {
|
|
2416
|
+
const a = Math.exp(-undampedFreq * duration);
|
|
2417
|
+
const b = (undampedFreq - velocity) * duration + 1;
|
|
2418
|
+
return -safeMin + a * b;
|
|
2419
|
+
};
|
|
2420
|
+
derivative = (undampedFreq) => {
|
|
2421
|
+
const a = Math.exp(-undampedFreq * duration);
|
|
2422
|
+
const b = (velocity - undampedFreq) * (duration * duration);
|
|
2423
|
+
return a * b;
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2426
|
+
const initialGuess = 5 / duration;
|
|
2427
|
+
const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
|
|
2428
|
+
duration = duration * 1000;
|
|
2429
|
+
if (isNaN(undampedFreq)) {
|
|
2430
|
+
return {
|
|
2431
|
+
stiffness: 100,
|
|
2432
|
+
damping: 10,
|
|
2433
|
+
duration,
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
else {
|
|
2437
|
+
const stiffness = Math.pow(undampedFreq, 2) * mass;
|
|
2438
|
+
return {
|
|
2439
|
+
stiffness,
|
|
2440
|
+
damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
|
|
2441
|
+
duration,
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
const rootIterations = 12;
|
|
2446
|
+
function approximateRoot(envelope, derivative, initialGuess) {
|
|
2447
|
+
let result = initialGuess;
|
|
2448
|
+
for (let i = 1; i < rootIterations; i++) {
|
|
2449
|
+
result = result - envelope(result) / derivative(result);
|
|
2450
|
+
}
|
|
2451
|
+
return result;
|
|
2452
|
+
}
|
|
2453
|
+
function calcAngularFreq(undampedFreq, dampingRatio) {
|
|
2454
|
+
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
const durationKeys = ["duration", "bounce"];
|
|
2458
|
+
const physicsKeys = ["stiffness", "damping", "mass"];
|
|
2459
|
+
function isSpringType(options, keys) {
|
|
2460
|
+
return keys.some((key) => options[key] !== undefined);
|
|
2461
|
+
}
|
|
2462
|
+
function getSpringOptions(options) {
|
|
2463
|
+
let springOptions = {
|
|
2464
|
+
velocity: 0.0,
|
|
2465
|
+
stiffness: 100,
|
|
2466
|
+
damping: 10,
|
|
2467
|
+
mass: 1.0,
|
|
2468
|
+
isResolvedFromDuration: false,
|
|
2469
|
+
...options,
|
|
2470
|
+
};
|
|
2471
|
+
// stiffness/damping/mass overrides duration/bounce
|
|
2472
|
+
if (!isSpringType(options, physicsKeys) &&
|
|
2473
|
+
isSpringType(options, durationKeys)) {
|
|
2474
|
+
const derived = findSpring(options);
|
|
2475
|
+
springOptions = {
|
|
2476
|
+
...springOptions,
|
|
2477
|
+
...derived,
|
|
2478
|
+
velocity: 0.0,
|
|
2479
|
+
mass: 1.0,
|
|
2480
|
+
};
|
|
2481
|
+
springOptions.isResolvedFromDuration = true;
|
|
2482
|
+
}
|
|
2483
|
+
return springOptions;
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* This is based on the spring implementation of Wobble https://github.com/skevy/wobble
|
|
2487
|
+
*/
|
|
2488
|
+
function spring({ from = 0.0, to = 1.0, restSpeed = 2, restDelta = 0.01, ...options }) {
|
|
2489
|
+
/**
|
|
2490
|
+
* This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
|
|
2491
|
+
* to reduce GC during animation.
|
|
2492
|
+
*/
|
|
2493
|
+
const state = { done: false, value: from };
|
|
2494
|
+
let { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
|
|
2495
|
+
let resolveSpring = zero;
|
|
2496
|
+
let resolveVelocity = zero;
|
|
2497
|
+
function createSpring() {
|
|
2498
|
+
const initialVelocity = velocity ? -(velocity / 1000) : 0.0;
|
|
2499
|
+
const initialDelta = to - from;
|
|
2500
|
+
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2501
|
+
const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
|
|
2502
|
+
/**
|
|
2503
|
+
* If we're working within what looks like a 0-1 range, change the default restDelta
|
|
2504
|
+
* to 0.01
|
|
2505
|
+
*/
|
|
2506
|
+
if (restDelta === undefined) {
|
|
2507
|
+
restDelta = Math.min(Math.abs(to - from) / 100, 0.4);
|
|
2508
|
+
}
|
|
2509
|
+
if (dampingRatio < 1) {
|
|
2510
|
+
const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
|
|
2511
|
+
// Underdamped spring
|
|
2512
|
+
resolveSpring = (t) => {
|
|
2513
|
+
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2514
|
+
return (to -
|
|
2515
|
+
envelope *
|
|
2516
|
+
(((initialVelocity +
|
|
2517
|
+
dampingRatio * undampedAngularFreq * initialDelta) /
|
|
2518
|
+
angularFreq) *
|
|
2519
|
+
Math.sin(angularFreq * t) +
|
|
2520
|
+
initialDelta * Math.cos(angularFreq * t)));
|
|
2521
|
+
};
|
|
2522
|
+
resolveVelocity = (t) => {
|
|
2523
|
+
// TODO Resolve these calculations with the above
|
|
2524
|
+
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2525
|
+
return (dampingRatio *
|
|
2526
|
+
undampedAngularFreq *
|
|
2527
|
+
envelope *
|
|
2528
|
+
((Math.sin(angularFreq * t) *
|
|
2529
|
+
(initialVelocity +
|
|
2530
|
+
dampingRatio *
|
|
2531
|
+
undampedAngularFreq *
|
|
2532
|
+
initialDelta)) /
|
|
2533
|
+
angularFreq +
|
|
2534
|
+
initialDelta * Math.cos(angularFreq * t)) -
|
|
2535
|
+
envelope *
|
|
2536
|
+
(Math.cos(angularFreq * t) *
|
|
2537
|
+
(initialVelocity +
|
|
2538
|
+
dampingRatio *
|
|
2539
|
+
undampedAngularFreq *
|
|
2540
|
+
initialDelta) -
|
|
2541
|
+
angularFreq *
|
|
2542
|
+
initialDelta *
|
|
2543
|
+
Math.sin(angularFreq * t)));
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
else if (dampingRatio === 1) {
|
|
2547
|
+
// Critically damped spring
|
|
2548
|
+
resolveSpring = (t) => to -
|
|
2549
|
+
Math.exp(-undampedAngularFreq * t) *
|
|
2550
|
+
(initialDelta +
|
|
2551
|
+
(initialVelocity + undampedAngularFreq * initialDelta) *
|
|
2552
|
+
t);
|
|
2553
|
+
}
|
|
2554
|
+
else {
|
|
2555
|
+
// Overdamped spring
|
|
2556
|
+
const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
|
|
2557
|
+
resolveSpring = (t) => {
|
|
2558
|
+
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2559
|
+
// When performing sinh or cosh values can hit Infinity so we cap them here
|
|
2560
|
+
const freqForT = Math.min(dampedAngularFreq * t, 300);
|
|
2561
|
+
return (to -
|
|
2562
|
+
(envelope *
|
|
2563
|
+
((initialVelocity +
|
|
2564
|
+
dampingRatio * undampedAngularFreq * initialDelta) *
|
|
2565
|
+
Math.sinh(freqForT) +
|
|
2566
|
+
dampedAngularFreq *
|
|
2567
|
+
initialDelta *
|
|
2568
|
+
Math.cosh(freqForT))) /
|
|
2569
|
+
dampedAngularFreq);
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
createSpring();
|
|
2574
|
+
return {
|
|
2575
|
+
next: (t) => {
|
|
2576
|
+
const current = resolveSpring(t);
|
|
2577
|
+
if (!isResolvedFromDuration) {
|
|
2578
|
+
const currentVelocity = resolveVelocity(t) * 1000;
|
|
2579
|
+
const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
|
|
2580
|
+
const isBelowDisplacementThreshold = Math.abs(to - current) <= restDelta;
|
|
2581
|
+
state.done =
|
|
2582
|
+
isBelowVelocityThreshold && isBelowDisplacementThreshold;
|
|
2583
|
+
}
|
|
2584
|
+
else {
|
|
2585
|
+
state.done = t >= duration;
|
|
2586
|
+
}
|
|
2587
|
+
state.value = state.done ? to : current;
|
|
2588
|
+
return state;
|
|
2589
|
+
},
|
|
2590
|
+
flipTarget: () => {
|
|
2591
|
+
velocity = -velocity;
|
|
2592
|
+
[from, to] = [to, from];
|
|
2593
|
+
createSpring();
|
|
2594
|
+
},
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
spring.needsInterpolation = (a, b) => typeof a === "string" || typeof b === "string";
|
|
2598
|
+
const zero = (_t) => 0;
|
|
2599
|
+
|
|
2600
|
+
function decay({ velocity = 0, from = 0, power = 0.8, timeConstant = 350, restDelta = 0.5, modifyTarget, }) {
|
|
2601
|
+
/**
|
|
2602
|
+
* This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
|
|
2603
|
+
* to reduce GC during animation.
|
|
2604
|
+
*/
|
|
2605
|
+
const state = { done: false, value: from };
|
|
2606
|
+
let amplitude = power * velocity;
|
|
2607
|
+
const ideal = from + amplitude;
|
|
2608
|
+
const target = modifyTarget === undefined ? ideal : modifyTarget(ideal);
|
|
2609
|
+
/**
|
|
2610
|
+
* If the target has changed we need to re-calculate the amplitude, otherwise
|
|
2611
|
+
* the animation will start from the wrong position.
|
|
2612
|
+
*/
|
|
2613
|
+
if (target !== ideal)
|
|
2614
|
+
amplitude = target - from;
|
|
2615
|
+
return {
|
|
2616
|
+
next: (t) => {
|
|
2617
|
+
const delta = -amplitude * Math.exp(-t / timeConstant);
|
|
2618
|
+
state.done = !(delta > restDelta || delta < -restDelta);
|
|
2619
|
+
state.value = state.done ? target : target + delta;
|
|
2620
|
+
return state;
|
|
2621
|
+
},
|
|
2622
|
+
flipTarget: () => { },
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
const types = { decay, keyframes, spring };
|
|
2627
|
+
function loopElapsed(elapsed, duration, delay = 0) {
|
|
2628
|
+
return elapsed - duration - delay;
|
|
2629
|
+
}
|
|
2630
|
+
function reverseElapsed(elapsed, duration = 0, delay = 0, isForwardPlayback = true) {
|
|
2631
|
+
return isForwardPlayback
|
|
2632
|
+
? loopElapsed(duration + -elapsed, duration, delay)
|
|
2633
|
+
: duration - (elapsed - duration) + delay;
|
|
2634
|
+
}
|
|
2635
|
+
function hasRepeatDelayElapsed(elapsed, duration, delay, isForwardPlayback) {
|
|
2636
|
+
return isForwardPlayback ? elapsed >= duration + delay : elapsed <= -delay;
|
|
2637
|
+
}
|
|
2638
|
+
const framesync = (update) => {
|
|
2639
|
+
const passTimestamp = ({ delta }) => update(delta);
|
|
2640
|
+
return {
|
|
2641
|
+
start: () => sync__default["default"].update(passTimestamp, true),
|
|
2642
|
+
stop: () => sync.cancelSync.update(passTimestamp),
|
|
2643
|
+
};
|
|
2644
|
+
};
|
|
2645
|
+
function animate$1({ from, autoplay = true, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
|
|
2646
|
+
var _a, _b;
|
|
2647
|
+
let { to } = options;
|
|
2648
|
+
let driverControls;
|
|
2649
|
+
let repeatCount = 0;
|
|
2650
|
+
let computedDuration = options
|
|
2651
|
+
.duration;
|
|
2652
|
+
let latest;
|
|
2653
|
+
let isComplete = false;
|
|
2654
|
+
let isForwardPlayback = true;
|
|
2655
|
+
let interpolateFromNumber;
|
|
2656
|
+
const animator = types[Array.isArray(to) ? "keyframes" : type];
|
|
2657
|
+
if ((_b = (_a = animator).needsInterpolation) === null || _b === void 0 ? void 0 : _b.call(_a, from, to)) {
|
|
2658
|
+
interpolateFromNumber = interpolate([0, 100], [from, to], {
|
|
2659
|
+
clamp: false,
|
|
2660
|
+
});
|
|
2661
|
+
from = 0;
|
|
2662
|
+
to = 100;
|
|
2663
|
+
}
|
|
2664
|
+
const animation = animator({ ...options, from, to });
|
|
2665
|
+
function repeat() {
|
|
2666
|
+
repeatCount++;
|
|
2667
|
+
if (repeatType === "reverse") {
|
|
2668
|
+
isForwardPlayback = repeatCount % 2 === 0;
|
|
2669
|
+
elapsed = reverseElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback);
|
|
2670
|
+
}
|
|
2671
|
+
else {
|
|
2672
|
+
elapsed = loopElapsed(elapsed, computedDuration, repeatDelay);
|
|
2673
|
+
if (repeatType === "mirror")
|
|
2674
|
+
animation.flipTarget();
|
|
2675
|
+
}
|
|
2676
|
+
isComplete = false;
|
|
2677
|
+
onRepeat && onRepeat();
|
|
2678
|
+
}
|
|
2679
|
+
function complete() {
|
|
2680
|
+
driverControls.stop();
|
|
2681
|
+
onComplete && onComplete();
|
|
2682
|
+
}
|
|
2683
|
+
function update(delta) {
|
|
2684
|
+
if (!isForwardPlayback)
|
|
2685
|
+
delta = -delta;
|
|
2686
|
+
elapsed += delta;
|
|
2687
|
+
if (!isComplete) {
|
|
2688
|
+
const state = animation.next(Math.max(0, elapsed));
|
|
2689
|
+
latest = state.value;
|
|
2690
|
+
if (interpolateFromNumber)
|
|
2691
|
+
latest = interpolateFromNumber(latest);
|
|
2692
|
+
isComplete = isForwardPlayback ? state.done : elapsed <= 0;
|
|
2693
|
+
}
|
|
2694
|
+
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(latest);
|
|
2695
|
+
if (isComplete) {
|
|
2696
|
+
if (repeatCount === 0)
|
|
2697
|
+
computedDuration !== null && computedDuration !== void 0 ? computedDuration : (computedDuration = elapsed);
|
|
2698
|
+
if (repeatCount < repeatMax) {
|
|
2699
|
+
hasRepeatDelayElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback) && repeat();
|
|
2700
|
+
}
|
|
2701
|
+
else {
|
|
2702
|
+
complete();
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
function play() {
|
|
2707
|
+
onPlay === null || onPlay === void 0 ? void 0 : onPlay();
|
|
2708
|
+
driverControls = driver(update);
|
|
2709
|
+
driverControls.start();
|
|
2710
|
+
}
|
|
2711
|
+
autoplay && play();
|
|
2712
|
+
return {
|
|
2713
|
+
stop: () => {
|
|
2714
|
+
onStop === null || onStop === void 0 ? void 0 : onStop();
|
|
2715
|
+
driverControls.stop();
|
|
2716
|
+
},
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
/*
|
|
2721
|
+
Convert velocity into velocity per second
|
|
2722
|
+
|
|
2723
|
+
@param [number]: Unit per frame
|
|
2724
|
+
@param [number]: Frame duration in ms
|
|
2725
|
+
*/
|
|
2726
|
+
function velocityPerSecond(velocity, frameDuration) {
|
|
2727
|
+
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
2731
|
+
let currentAnimation;
|
|
2732
|
+
function isOutOfBounds(v) {
|
|
2733
|
+
return (min !== undefined && v < min) || (max !== undefined && v > max);
|
|
2734
|
+
}
|
|
2735
|
+
function boundaryNearest(v) {
|
|
2736
|
+
if (min === undefined)
|
|
2737
|
+
return max;
|
|
2738
|
+
if (max === undefined)
|
|
2739
|
+
return min;
|
|
2740
|
+
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
|
|
2741
|
+
}
|
|
2742
|
+
function startAnimation(options) {
|
|
2743
|
+
currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop();
|
|
2744
|
+
currentAnimation = animate$1({
|
|
2745
|
+
...options,
|
|
2746
|
+
driver,
|
|
2747
|
+
onUpdate: (v) => {
|
|
2748
|
+
var _a;
|
|
2749
|
+
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(v);
|
|
2750
|
+
(_a = options.onUpdate) === null || _a === void 0 ? void 0 : _a.call(options, v);
|
|
2751
|
+
},
|
|
2752
|
+
onComplete,
|
|
2753
|
+
onStop,
|
|
2754
|
+
});
|
|
2755
|
+
}
|
|
2756
|
+
function startSpring(options) {
|
|
2757
|
+
startAnimation({
|
|
2758
|
+
type: "spring",
|
|
2759
|
+
stiffness: bounceStiffness,
|
|
2760
|
+
damping: bounceDamping,
|
|
2761
|
+
restDelta,
|
|
2762
|
+
...options,
|
|
2763
|
+
});
|
|
2764
|
+
}
|
|
2765
|
+
if (isOutOfBounds(from)) {
|
|
2766
|
+
// Start the animation with spring if outside the defined boundaries
|
|
2767
|
+
startSpring({ from, velocity, to: boundaryNearest(from) });
|
|
2768
|
+
}
|
|
2769
|
+
else {
|
|
2770
|
+
/**
|
|
2771
|
+
* Or if the value is out of bounds, simulate the inertia movement
|
|
2772
|
+
* with the decay animation.
|
|
2773
|
+
*
|
|
2774
|
+
* Pre-calculate the target so we can detect if it's out-of-bounds.
|
|
2775
|
+
* If it is, we want to check per frame when to switch to a spring
|
|
2776
|
+
* animation
|
|
2777
|
+
*/
|
|
2778
|
+
let target = power * velocity + from;
|
|
2779
|
+
if (typeof modifyTarget !== "undefined")
|
|
2780
|
+
target = modifyTarget(target);
|
|
2781
|
+
const boundary = boundaryNearest(target);
|
|
2782
|
+
const heading = boundary === min ? -1 : 1;
|
|
2783
|
+
let prev;
|
|
2784
|
+
let current;
|
|
2785
|
+
const checkBoundary = (v) => {
|
|
2786
|
+
prev = current;
|
|
2787
|
+
current = v;
|
|
2788
|
+
velocity = velocityPerSecond(v - prev, sync.getFrameData().delta);
|
|
2789
|
+
if ((heading === 1 && v > boundary) ||
|
|
2790
|
+
(heading === -1 && v < boundary)) {
|
|
2791
|
+
startSpring({ from: v, to: boundary, velocity });
|
|
2792
|
+
}
|
|
2793
|
+
};
|
|
2794
|
+
startAnimation({
|
|
2795
|
+
type: "decay",
|
|
2796
|
+
from,
|
|
2797
|
+
velocity,
|
|
2798
|
+
timeConstant,
|
|
2799
|
+
power,
|
|
2800
|
+
restDelta,
|
|
2801
|
+
modifyTarget,
|
|
2802
|
+
onUpdate: isOutOfBounds(target) ? checkBoundary : undefined,
|
|
2803
|
+
});
|
|
2804
|
+
}
|
|
2805
|
+
return {
|
|
2806
|
+
stop: () => currentAnimation === null || currentAnimation === void 0 ? void 0 : currentAnimation.stop(),
|
|
2807
|
+
};
|
|
2808
|
+
}
|
|
2809
|
+
|
|
1973
2810
|
/**
|
|
1974
2811
|
* Decide whether a transition is defined on a given Transition.
|
|
1975
2812
|
* This filters out orchestration options and returns true
|
|
@@ -2100,8 +2937,8 @@ function getAnimation(key, value, target, transition, onComplete) {
|
|
|
2100
2937
|
};
|
|
2101
2938
|
return valueTransition.type === "inertia" ||
|
|
2102
2939
|
valueTransition.type === "decay"
|
|
2103
|
-
?
|
|
2104
|
-
:
|
|
2940
|
+
? inertia({ ...options, ...valueTransition })
|
|
2941
|
+
: animate$1({
|
|
2105
2942
|
...getPopmotionAnimationOptions(valueTransition, options, key),
|
|
2106
2943
|
onUpdate: (v) => {
|
|
2107
2944
|
options.onUpdate(v);
|
|
@@ -2257,7 +3094,7 @@ class MotionValue {
|
|
|
2257
3094
|
* This will be replaced by the build step with the latest version number.
|
|
2258
3095
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
2259
3096
|
*/
|
|
2260
|
-
this.version = "7.6.
|
|
3097
|
+
this.version = "7.6.18";
|
|
2261
3098
|
/**
|
|
2262
3099
|
* Duration, in milliseconds, since last updating frame.
|
|
2263
3100
|
*
|
|
@@ -2472,7 +3309,7 @@ class MotionValue {
|
|
|
2472
3309
|
// This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful
|
|
2473
3310
|
return this.canTrackVelocity
|
|
2474
3311
|
? // These casts could be avoided if parseFloat would be typed better
|
|
2475
|
-
|
|
3312
|
+
velocityPerSecond(parseFloat(this.current) -
|
|
2476
3313
|
parseFloat(this.prev), this.timeDelta)
|
|
2477
3314
|
: 0;
|
|
2478
3315
|
}
|
|
@@ -3186,6 +4023,14 @@ const animations = {
|
|
|
3186
4023
|
}),
|
|
3187
4024
|
};
|
|
3188
4025
|
|
|
4026
|
+
const distance = (a, b) => Math.abs(a - b);
|
|
4027
|
+
function distance2D(a, b) {
|
|
4028
|
+
// Multi-dimensional
|
|
4029
|
+
const xDelta = distance(a.x, b.x);
|
|
4030
|
+
const yDelta = distance(a.y, b.y);
|
|
4031
|
+
return Math.sqrt(xDelta ** 2 + yDelta ** 2);
|
|
4032
|
+
}
|
|
4033
|
+
|
|
3189
4034
|
/**
|
|
3190
4035
|
* @internal
|
|
3191
4036
|
*/
|
|
@@ -3215,7 +4060,7 @@ class PanSession {
|
|
|
3215
4060
|
// Only start panning if the offset is larger than 3 pixels. If we make it
|
|
3216
4061
|
// any larger than this we'll want to reset the pointer history
|
|
3217
4062
|
// on the first update to avoid visual snapping to the cursoe.
|
|
3218
|
-
const isDistancePastThreshold =
|
|
4063
|
+
const isDistancePastThreshold = distance2D(info.offset, { x: 0, y: 0 }) >= 3;
|
|
3219
4064
|
if (!isPanStarted && !isDistancePastThreshold)
|
|
3220
4065
|
return;
|
|
3221
4066
|
const { point } = info;
|
|
@@ -3261,7 +4106,7 @@ class PanSession {
|
|
|
3261
4106
|
const { onSessionStart } = handlers;
|
|
3262
4107
|
onSessionStart &&
|
|
3263
4108
|
onSessionStart(event, getPanInfo(initialInfo, this.history));
|
|
3264
|
-
this.removeListeners =
|
|
4109
|
+
this.removeListeners = pipe(addPointerEvent(window, "pointermove", this.handlePointerMove), addPointerEvent(window, "pointerup", this.handlePointerUp), addPointerEvent(window, "pointercancel", this.handlePointerUp));
|
|
3265
4110
|
}
|
|
3266
4111
|
updateHandlers(handlers) {
|
|
3267
4112
|
this.handlers = handlers;
|
|
@@ -3334,12 +4179,12 @@ function isNear(value, target = 0, maxDistance = 0.01) {
|
|
|
3334
4179
|
}
|
|
3335
4180
|
function calcAxisDelta(delta, source, target, origin = 0.5) {
|
|
3336
4181
|
delta.origin = origin;
|
|
3337
|
-
delta.originPoint =
|
|
4182
|
+
delta.originPoint = mix(source.min, source.max, delta.origin);
|
|
3338
4183
|
delta.scale = calcLength(target) / calcLength(source);
|
|
3339
4184
|
if (isNear(delta.scale, 1, 0.0001) || isNaN(delta.scale))
|
|
3340
4185
|
delta.scale = 1;
|
|
3341
4186
|
delta.translate =
|
|
3342
|
-
|
|
4187
|
+
mix(target.min, target.max, delta.origin) - delta.originPoint;
|
|
3343
4188
|
if (isNear(delta.translate) || isNaN(delta.translate))
|
|
3344
4189
|
delta.translate = 0;
|
|
3345
4190
|
}
|
|
@@ -3372,11 +4217,11 @@ function calcRelativePosition(target, layout, parent) {
|
|
|
3372
4217
|
function applyConstraints(point, { min, max }, elastic) {
|
|
3373
4218
|
if (min !== undefined && point < min) {
|
|
3374
4219
|
// If we have a min point defined, and this is outside of that, constrain
|
|
3375
|
-
point = elastic ?
|
|
4220
|
+
point = elastic ? mix(min, point, elastic.min) : Math.max(point, min);
|
|
3376
4221
|
}
|
|
3377
4222
|
else if (max !== undefined && point > max) {
|
|
3378
4223
|
// If we have a max point defined, and this is outside of that, constrain
|
|
3379
|
-
point = elastic ?
|
|
4224
|
+
point = elastic ? mix(max, point, elastic.max) : Math.min(point, max);
|
|
3380
4225
|
}
|
|
3381
4226
|
return point;
|
|
3382
4227
|
}
|
|
@@ -3435,12 +4280,12 @@ function calcOrigin(source, target) {
|
|
|
3435
4280
|
const sourceLength = calcLength(source);
|
|
3436
4281
|
const targetLength = calcLength(target);
|
|
3437
4282
|
if (targetLength > sourceLength) {
|
|
3438
|
-
origin =
|
|
4283
|
+
origin = progress(target.min, target.max - sourceLength, source.min);
|
|
3439
4284
|
}
|
|
3440
4285
|
else if (sourceLength > targetLength) {
|
|
3441
|
-
origin =
|
|
4286
|
+
origin = progress(source.min, source.max - targetLength, target.min);
|
|
3442
4287
|
}
|
|
3443
|
-
return
|
|
4288
|
+
return clamp(0, 1, origin);
|
|
3444
4289
|
}
|
|
3445
4290
|
/**
|
|
3446
4291
|
* Rebase the calculated viewport constraints relative to the layout.min point.
|
|
@@ -3653,7 +4498,7 @@ function translateAxis(axis, distance) {
|
|
|
3653
4498
|
*/
|
|
3654
4499
|
function transformAxis(axis, transforms, [key, scaleKey, originKey]) {
|
|
3655
4500
|
const axisOrigin = transforms[originKey] !== undefined ? transforms[originKey] : 0.5;
|
|
3656
|
-
const originPoint =
|
|
4501
|
+
const originPoint = mix(axis.min, axis.max, axisOrigin);
|
|
3657
4502
|
// Apply the axis delta to the final axis
|
|
3658
4503
|
applyAxisDelta(axis, transforms[key], transforms[scaleKey], originPoint, transforms.scale);
|
|
3659
4504
|
}
|
|
@@ -3968,7 +4813,7 @@ class VisualElementDragControls {
|
|
|
3968
4813
|
const axisValue = this.getAxisMotionValue(axis);
|
|
3969
4814
|
if (projection && projection.layout) {
|
|
3970
4815
|
const { min, max } = projection.layout.layoutBox[axis];
|
|
3971
|
-
axisValue.set(point[axis] -
|
|
4816
|
+
axisValue.set(point[axis] - mix(min, max, 0.5));
|
|
3972
4817
|
}
|
|
3973
4818
|
});
|
|
3974
4819
|
}
|
|
@@ -4024,7 +4869,7 @@ class VisualElementDragControls {
|
|
|
4024
4869
|
*/
|
|
4025
4870
|
const axisValue = this.getAxisMotionValue(axis);
|
|
4026
4871
|
const { min, max } = this.constraints[axis];
|
|
4027
|
-
axisValue.set(
|
|
4872
|
+
axisValue.set(mix(min, max, boxProgress[axis]));
|
|
4028
4873
|
});
|
|
4029
4874
|
}
|
|
4030
4875
|
addListeners() {
|
|
@@ -4534,7 +5379,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
4534
5379
|
* and warn against mismatches.
|
|
4535
5380
|
*/
|
|
4536
5381
|
if (process.env.NODE_ENV === "development") {
|
|
4537
|
-
warnOnce(nextValue.version === "7.6.
|
|
5382
|
+
warnOnce(nextValue.version === "7.6.18", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.18 may not work as expected.`);
|
|
4538
5383
|
}
|
|
4539
5384
|
}
|
|
4540
5385
|
else if (isMotionValue(prevValue)) {
|
|
@@ -5202,7 +6047,7 @@ const correctBoxShadow = {
|
|
|
5202
6047
|
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
5203
6048
|
* the two scales.
|
|
5204
6049
|
*/
|
|
5205
|
-
const averageScale =
|
|
6050
|
+
const averageScale = mix(xScale, yScale, 0.5);
|
|
5206
6051
|
// Blur
|
|
5207
6052
|
if (typeof shadow[2 + offset] === "number")
|
|
5208
6053
|
shadow[2 + offset] /= averageScale;
|
|
@@ -5387,14 +6232,14 @@ const isPx = (value) => typeof value === "number" || styleValueTypes.px.test(val
|
|
|
5387
6232
|
function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
|
|
5388
6233
|
var _a, _b, _c, _d;
|
|
5389
6234
|
if (shouldCrossfadeOpacity) {
|
|
5390
|
-
target.opacity =
|
|
6235
|
+
target.opacity = mix(0,
|
|
5391
6236
|
// (follow?.opacity as number) ?? 0,
|
|
5392
6237
|
// TODO Reinstate this if only child
|
|
5393
6238
|
(_a = lead.opacity) !== null && _a !== void 0 ? _a : 1, easeCrossfadeIn(progress));
|
|
5394
|
-
target.opacityExit =
|
|
6239
|
+
target.opacityExit = mix((_b = follow.opacity) !== null && _b !== void 0 ? _b : 1, 0, easeCrossfadeOut(progress));
|
|
5395
6240
|
}
|
|
5396
6241
|
else if (isOnlyMember) {
|
|
5397
|
-
target.opacity =
|
|
6242
|
+
target.opacity = mix((_c = follow.opacity) !== null && _c !== void 0 ? _c : 1, (_d = lead.opacity) !== null && _d !== void 0 ? _d : 1, progress);
|
|
5398
6243
|
}
|
|
5399
6244
|
/**
|
|
5400
6245
|
* Mix border radius
|
|
@@ -5411,7 +6256,7 @@ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnl
|
|
|
5411
6256
|
leadRadius === 0 ||
|
|
5412
6257
|
isPx(followRadius) === isPx(leadRadius);
|
|
5413
6258
|
if (canMix) {
|
|
5414
|
-
target[borderLabel] = Math.max(
|
|
6259
|
+
target[borderLabel] = Math.max(mix(asNumber(followRadius), asNumber(leadRadius), progress), 0);
|
|
5415
6260
|
if (styleValueTypes.percent.test(leadRadius) || styleValueTypes.percent.test(followRadius)) {
|
|
5416
6261
|
target[borderLabel] += "%";
|
|
5417
6262
|
}
|
|
@@ -5424,7 +6269,7 @@ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnl
|
|
|
5424
6269
|
* Mix rotation
|
|
5425
6270
|
*/
|
|
5426
6271
|
if (follow.rotate || lead.rotate) {
|
|
5427
|
-
target.rotate =
|
|
6272
|
+
target.rotate = mix(follow.rotate || 0, lead.rotate || 0, progress);
|
|
5428
6273
|
}
|
|
5429
6274
|
}
|
|
5430
6275
|
function getRadius(values, radiusName) {
|
|
@@ -5454,8 +6299,8 @@ function getRadius(values, radiusName) {
|
|
|
5454
6299
|
// latestLeadValues.backgroundColor as string
|
|
5455
6300
|
// )(p)
|
|
5456
6301
|
// }
|
|
5457
|
-
const easeCrossfadeIn = compress(0, 0.5,
|
|
5458
|
-
const easeCrossfadeOut = compress(0.5, 0.95,
|
|
6302
|
+
const easeCrossfadeIn = compress(0, 0.5, circOut);
|
|
6303
|
+
const easeCrossfadeOut = compress(0.5, 0.95, noop);
|
|
5459
6304
|
function compress(min, max, easing) {
|
|
5460
6305
|
return (p) => {
|
|
5461
6306
|
// Could replace ifs with clamp
|
|
@@ -5463,7 +6308,7 @@ function compress(min, max, easing) {
|
|
|
5463
6308
|
return 0;
|
|
5464
6309
|
if (p > max)
|
|
5465
6310
|
return 1;
|
|
5466
|
-
return easing(
|
|
6311
|
+
return easing(progress(min, max, p));
|
|
5467
6312
|
};
|
|
5468
6313
|
}
|
|
5469
6314
|
|
|
@@ -5503,12 +6348,12 @@ function removePointDelta(point, translate, scale, originPoint, boxScale) {
|
|
|
5503
6348
|
function removeAxisDelta(axis, translate = 0, scale = 1, origin = 0.5, boxScale, originAxis = axis, sourceAxis = axis) {
|
|
5504
6349
|
if (styleValueTypes.percent.test(translate)) {
|
|
5505
6350
|
translate = parseFloat(translate);
|
|
5506
|
-
const relativeProgress =
|
|
6351
|
+
const relativeProgress = mix(sourceAxis.min, sourceAxis.max, translate / 100);
|
|
5507
6352
|
translate = relativeProgress - sourceAxis.min;
|
|
5508
6353
|
}
|
|
5509
6354
|
if (typeof translate !== "number")
|
|
5510
6355
|
return;
|
|
5511
|
-
let originPoint =
|
|
6356
|
+
let originPoint = mix(originAxis.min, originAxis.max, origin);
|
|
5512
6357
|
if (axis === originAxis)
|
|
5513
6358
|
originPoint -= translate;
|
|
5514
6359
|
axis.min = removePointDelta(axis.min, translate, scale, originPoint, boxScale);
|
|
@@ -6961,14 +7806,14 @@ function removeLeadSnapshots(stack) {
|
|
|
6961
7806
|
stack.removeLeadSnapshot();
|
|
6962
7807
|
}
|
|
6963
7808
|
function mixAxisDelta(output, delta, p) {
|
|
6964
|
-
output.translate =
|
|
6965
|
-
output.scale =
|
|
7809
|
+
output.translate = mix(delta.translate, 0, p);
|
|
7810
|
+
output.scale = mix(delta.scale, 1, p);
|
|
6966
7811
|
output.origin = delta.origin;
|
|
6967
7812
|
output.originPoint = delta.originPoint;
|
|
6968
7813
|
}
|
|
6969
7814
|
function mixAxis(output, from, to, p) {
|
|
6970
|
-
output.min =
|
|
6971
|
-
output.max =
|
|
7815
|
+
output.min = mix(from.min, to.min, p);
|
|
7816
|
+
output.max = mix(from.max, to.max, p);
|
|
6972
7817
|
}
|
|
6973
7818
|
function mixBox(output, from, to, p) {
|
|
6974
7819
|
mixAxis(output.x, from.x, to.x, p);
|
|
@@ -7542,7 +8387,7 @@ function checkReorder(order, value, offset, velocity) {
|
|
|
7542
8387
|
return order;
|
|
7543
8388
|
const item = order[index];
|
|
7544
8389
|
const nextLayout = nextItem.layout;
|
|
7545
|
-
const nextItemCenter =
|
|
8390
|
+
const nextItemCenter = mix(nextLayout.min, nextLayout.max, 0.5);
|
|
7546
8391
|
if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
|
|
7547
8392
|
(nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
|
|
7548
8393
|
return moveItem(order, index, index + nextOffset);
|
|
@@ -7636,7 +8481,7 @@ function transform(...args) {
|
|
|
7636
8481
|
const inputRange = args[1 + argOffset];
|
|
7637
8482
|
const outputRange = args[2 + argOffset];
|
|
7638
8483
|
const options = args[3 + argOffset];
|
|
7639
|
-
const interpolator =
|
|
8484
|
+
const interpolator = interpolate(inputRange, outputRange, {
|
|
7640
8485
|
mixer: getMixer(outputRange[0]),
|
|
7641
8486
|
...options,
|
|
7642
8487
|
});
|
|
@@ -7645,8 +8490,10 @@ function transform(...args) {
|
|
|
7645
8490
|
|
|
7646
8491
|
function useOnChange(value, callback) {
|
|
7647
8492
|
useIsomorphicLayoutEffect(() => {
|
|
7648
|
-
if (isMotionValue(value))
|
|
8493
|
+
if (isMotionValue(value)) {
|
|
8494
|
+
callback(value.get());
|
|
7649
8495
|
return value.onChange(callback);
|
|
8496
|
+
}
|
|
7650
8497
|
}, [value, callback]);
|
|
7651
8498
|
}
|
|
7652
8499
|
function useMultiOnChange(values, handler, cleanup) {
|
|
@@ -7830,7 +8677,7 @@ function useSpring(source, config = {}) {
|
|
|
7830
8677
|
if (activeSpringAnimation.current) {
|
|
7831
8678
|
activeSpringAnimation.current.stop();
|
|
7832
8679
|
}
|
|
7833
|
-
activeSpringAnimation.current =
|
|
8680
|
+
activeSpringAnimation.current = animate$1({
|
|
7834
8681
|
from: value.get(),
|
|
7835
8682
|
to: v,
|
|
7836
8683
|
velocity: value.getVelocity(),
|
|
@@ -8131,6 +8978,11 @@ function useAnimationControls() {
|
|
|
8131
8978
|
}
|
|
8132
8979
|
const useAnimation = useAnimationControls;
|
|
8133
8980
|
|
|
8981
|
+
const wrap = (min, max, v) => {
|
|
8982
|
+
const rangeSize = max - min;
|
|
8983
|
+
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
|
|
8984
|
+
};
|
|
8985
|
+
|
|
8134
8986
|
/**
|
|
8135
8987
|
* Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
|
|
8136
8988
|
*
|
|
@@ -8163,7 +9015,7 @@ function useCycle(...items) {
|
|
|
8163
9015
|
const runCycle = React.useCallback((next) => {
|
|
8164
9016
|
index.current =
|
|
8165
9017
|
typeof next !== "number"
|
|
8166
|
-
?
|
|
9018
|
+
? wrap(0, items.length, index.current + 1)
|
|
8167
9019
|
: next;
|
|
8168
9020
|
setItem(items[index.current]);
|
|
8169
9021
|
},
|
|
@@ -8468,10 +9320,13 @@ exports.animations = animations;
|
|
|
8468
9320
|
exports.buildTransform = buildTransform;
|
|
8469
9321
|
exports.calcLength = calcLength;
|
|
8470
9322
|
exports.checkTargetForNewValues = checkTargetForNewValues;
|
|
9323
|
+
exports.clamp = clamp;
|
|
8471
9324
|
exports.createBox = createBox;
|
|
8472
9325
|
exports.createDomMotionComponent = createDomMotionComponent;
|
|
8473
9326
|
exports.createMotionComponent = createMotionComponent;
|
|
8474
9327
|
exports.delay = delay;
|
|
9328
|
+
exports.distance = distance;
|
|
9329
|
+
exports.distance2D = distance2D;
|
|
8475
9330
|
exports.domAnimation = domAnimation;
|
|
8476
9331
|
exports.domMax = domMax;
|
|
8477
9332
|
exports.filterProps = filterProps;
|
|
@@ -8482,8 +9337,10 @@ exports.isMotionValue = isMotionValue;
|
|
|
8482
9337
|
exports.isValidMotionProp = isValidMotionProp;
|
|
8483
9338
|
exports.m = m;
|
|
8484
9339
|
exports.makeUseVisualState = makeUseVisualState;
|
|
9340
|
+
exports.mix = mix;
|
|
8485
9341
|
exports.motion = motion;
|
|
8486
9342
|
exports.motionValue = motionValue;
|
|
9343
|
+
exports.pipe = pipe;
|
|
8487
9344
|
exports.resolveMotionValue = resolveMotionValue;
|
|
8488
9345
|
exports.transform = transform;
|
|
8489
9346
|
exports.unwrapMotionComponent = unwrapMotionComponent;
|
|
@@ -8517,4 +9374,5 @@ exports.useVelocity = useVelocity;
|
|
|
8517
9374
|
exports.useViewportScroll = useViewportScroll;
|
|
8518
9375
|
exports.useVisualElementContext = useVisualElementContext;
|
|
8519
9376
|
exports.useWillChange = useWillChange;
|
|
9377
|
+
exports.wrap = wrap;
|
|
8520
9378
|
exports.wrapHandler = wrapHandler;
|