framer-motion 7.7.0 → 7.7.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.
- package/dist/cjs/index.js +529 -155
- package/dist/es/animation/legacy-popmotion/index.mjs +1 -1
- package/dist/es/animation/legacy-popmotion/inertia.mjs +2 -2
- package/dist/es/animation/utils/is-animatable.mjs +1 -1
- package/dist/es/frameloop/create-render-step.mjs +88 -0
- package/dist/es/frameloop/data.mjs +6 -0
- package/dist/es/frameloop/index.mjs +59 -0
- package/dist/es/frameloop/on-next-frame.mjs +12 -0
- package/dist/es/gestures/PanSession.mjs +4 -3
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -1
- package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -1
- package/dist/es/projection/animation/mix-values.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-border-radius.mjs +1 -1
- package/dist/es/projection/styles/scale-box-shadow.mjs +1 -1
- package/dist/es/render/VisualElement.mjs +1 -1
- package/dist/es/render/dom/utils/unit-conversion.mjs +2 -1
- package/dist/es/render/dom/value-types/animatable-none.mjs +2 -1
- package/dist/es/render/dom/value-types/defaults.mjs +2 -1
- package/dist/es/render/dom/value-types/dimensions.mjs +2 -1
- package/dist/es/render/dom/value-types/find.mjs +2 -1
- package/dist/es/render/dom/value-types/number.mjs +2 -1
- package/dist/es/render/dom/value-types/type-int.mjs +1 -1
- package/dist/es/render/svg/utils/path.mjs +1 -1
- package/dist/es/render/svg/utils/transform-origin.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/render/utils/setters.mjs +1 -1
- package/dist/es/utils/delay.mjs +1 -1
- package/dist/es/utils/interpolate.mjs +1 -1
- package/dist/es/utils/mix-color.mjs +4 -1
- package/dist/es/utils/mix-complex.mjs +5 -24
- package/dist/es/utils/use-animation-frame.mjs +1 -1
- package/dist/es/utils/use-force-update.mjs +1 -1
- package/dist/es/utils/use-instant-transition.mjs +1 -1
- package/dist/es/value/index.mjs +4 -3
- package/dist/es/value/types/color/hex.mjs +40 -0
- package/dist/es/value/types/color/hsla.mjs +22 -0
- package/dist/es/value/types/color/index.mjs +28 -0
- package/dist/es/value/types/color/rgba.mjs +25 -0
- package/dist/es/value/types/color/utils.mjs +23 -0
- package/dist/es/value/types/complex/filter.mjs +30 -0
- package/dist/es/value/types/complex/index.mjs +61 -0
- package/dist/es/value/types/numbers/index.mjs +17 -0
- package/dist/es/value/types/numbers/units.mjs +19 -0
- package/dist/es/value/types/utils.mjs +15 -0
- package/dist/es/value/use-combine-values.mjs +1 -1
- package/dist/framer-motion.dev.js +284 -230
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/projection.dev.js +5451 -5397
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.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/size-webpack-m.js +1 -1
- package/dist/three-entry.d.ts +7 -2
- package/package.json +9 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { keyframes } from './keyframes.mjs';
|
|
2
2
|
import { spring } from './spring.mjs';
|
|
3
3
|
import { decay } from './decay.mjs';
|
|
4
|
-
import sync,
|
|
4
|
+
import { sync, cancelSync } from '../../frameloop/index.mjs';
|
|
5
5
|
import { interpolate } from '../../utils/interpolate.mjs';
|
|
6
6
|
|
|
7
7
|
const types = { decay, keyframes, spring };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { animate } from './index.mjs';
|
|
2
|
-
import { getFrameData } from 'framesync';
|
|
3
2
|
import { velocityPerSecond } from '../../utils/velocity-per-second.mjs';
|
|
3
|
+
import { frameData } from '../../frameloop/data.mjs';
|
|
4
4
|
|
|
5
5
|
function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
6
6
|
let currentAnimation;
|
|
@@ -60,7 +60,7 @@ function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant =
|
|
|
60
60
|
const checkBoundary = (v) => {
|
|
61
61
|
prev = current;
|
|
62
62
|
current = v;
|
|
63
|
-
velocity = velocityPerSecond(v - prev,
|
|
63
|
+
velocity = velocityPerSecond(v - prev, frameData.delta);
|
|
64
64
|
if ((heading === 1 && v > boundary) ||
|
|
65
65
|
(heading === -1 && v < boundary)) {
|
|
66
66
|
startSpring({ from: v, to: boundary, velocity });
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
function createRenderStep(runNextFrame) {
|
|
2
|
+
/**
|
|
3
|
+
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
4
|
+
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
5
|
+
*/
|
|
6
|
+
let toRun = [];
|
|
7
|
+
let toRunNextFrame = [];
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
let numToRun = 0;
|
|
12
|
+
/**
|
|
13
|
+
* Track whether we're currently processing jobs in this step. This way
|
|
14
|
+
* we can decide whether to schedule new jobs for this frame or next.
|
|
15
|
+
*/
|
|
16
|
+
let isProcessing = false;
|
|
17
|
+
let flushNextFrame = false;
|
|
18
|
+
/**
|
|
19
|
+
* A set of processes which were marked keepAlive when scheduled.
|
|
20
|
+
*/
|
|
21
|
+
const toKeepAlive = new WeakSet();
|
|
22
|
+
const step = {
|
|
23
|
+
/**
|
|
24
|
+
* Schedule a process to run on the next frame.
|
|
25
|
+
*/
|
|
26
|
+
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
27
|
+
const addToCurrentFrame = immediate && isProcessing;
|
|
28
|
+
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
29
|
+
if (keepAlive)
|
|
30
|
+
toKeepAlive.add(callback);
|
|
31
|
+
// If the buffer doesn't already contain this callback, add it
|
|
32
|
+
if (buffer.indexOf(callback) === -1) {
|
|
33
|
+
buffer.push(callback);
|
|
34
|
+
// If we're adding it to the currently running buffer, update its measured size
|
|
35
|
+
if (addToCurrentFrame && isProcessing)
|
|
36
|
+
numToRun = toRun.length;
|
|
37
|
+
}
|
|
38
|
+
return callback;
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Cancel the provided callback from running on the next frame.
|
|
42
|
+
*/
|
|
43
|
+
cancel: (callback) => {
|
|
44
|
+
const index = toRunNextFrame.indexOf(callback);
|
|
45
|
+
if (index !== -1)
|
|
46
|
+
toRunNextFrame.splice(index, 1);
|
|
47
|
+
toKeepAlive.delete(callback);
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* Execute all schedule callbacks.
|
|
51
|
+
*/
|
|
52
|
+
process: (frameData) => {
|
|
53
|
+
/**
|
|
54
|
+
* If we're already processing we've probably been triggered by a flushSync
|
|
55
|
+
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
56
|
+
* as true and ensure we flush the following frame at the end of this one.
|
|
57
|
+
*/
|
|
58
|
+
if (isProcessing) {
|
|
59
|
+
flushNextFrame = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
isProcessing = true;
|
|
63
|
+
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
64
|
+
// Clear the next frame list
|
|
65
|
+
toRunNextFrame.length = 0;
|
|
66
|
+
// Execute this frame
|
|
67
|
+
numToRun = toRun.length;
|
|
68
|
+
if (numToRun) {
|
|
69
|
+
for (let i = 0; i < numToRun; i++) {
|
|
70
|
+
const callback = toRun[i];
|
|
71
|
+
callback(frameData);
|
|
72
|
+
if (toKeepAlive.has(callback)) {
|
|
73
|
+
step.schedule(callback);
|
|
74
|
+
runNextFrame();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
isProcessing = false;
|
|
79
|
+
if (flushNextFrame) {
|
|
80
|
+
flushNextFrame = false;
|
|
81
|
+
step.process(frameData);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
return step;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { createRenderStep };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { onNextFrame, defaultTimestep } from './on-next-frame.mjs';
|
|
2
|
+
import { createRenderStep } from './create-render-step.mjs';
|
|
3
|
+
import { frameData } from './data.mjs';
|
|
4
|
+
|
|
5
|
+
const maxElapsed = 40;
|
|
6
|
+
let useDefaultElapsed = true;
|
|
7
|
+
let runNextFrame = false;
|
|
8
|
+
let isProcessing = false;
|
|
9
|
+
const stepsOrder = [
|
|
10
|
+
"read",
|
|
11
|
+
"update",
|
|
12
|
+
"preRender",
|
|
13
|
+
"render",
|
|
14
|
+
"postRender",
|
|
15
|
+
];
|
|
16
|
+
const steps = stepsOrder.reduce((acc, key) => {
|
|
17
|
+
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
const sync = stepsOrder.reduce((acc, key) => {
|
|
21
|
+
const step = steps[key];
|
|
22
|
+
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
23
|
+
if (!runNextFrame)
|
|
24
|
+
startLoop();
|
|
25
|
+
return step.schedule(process, keepAlive, immediate);
|
|
26
|
+
};
|
|
27
|
+
return acc;
|
|
28
|
+
}, {});
|
|
29
|
+
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
30
|
+
acc[key] = steps[key].cancel;
|
|
31
|
+
return acc;
|
|
32
|
+
}, {});
|
|
33
|
+
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
34
|
+
acc[key] = () => steps[key].process(frameData);
|
|
35
|
+
return acc;
|
|
36
|
+
}, {});
|
|
37
|
+
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
38
|
+
const processFrame = (timestamp) => {
|
|
39
|
+
runNextFrame = false;
|
|
40
|
+
frameData.delta = useDefaultElapsed
|
|
41
|
+
? defaultTimestep
|
|
42
|
+
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed), 1);
|
|
43
|
+
frameData.timestamp = timestamp;
|
|
44
|
+
isProcessing = true;
|
|
45
|
+
stepsOrder.forEach(processStep);
|
|
46
|
+
isProcessing = false;
|
|
47
|
+
if (runNextFrame) {
|
|
48
|
+
useDefaultElapsed = false;
|
|
49
|
+
onNextFrame(processFrame);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const startLoop = () => {
|
|
53
|
+
runNextFrame = true;
|
|
54
|
+
useDefaultElapsed = true;
|
|
55
|
+
if (!isProcessing)
|
|
56
|
+
onNextFrame(processFrame);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { cancelSync, flushSync, sync };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Detect and load appropriate clock setting for the execution environment
|
|
3
|
+
*/
|
|
4
|
+
const defaultTimestep = (1 / 60) * 1000;
|
|
5
|
+
const getCurrentTime = typeof performance !== "undefined"
|
|
6
|
+
? () => performance.now()
|
|
7
|
+
: () => Date.now();
|
|
8
|
+
const onNextFrame = typeof window !== "undefined"
|
|
9
|
+
? (callback) => window.requestAnimationFrame(callback)
|
|
10
|
+
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
11
|
+
|
|
12
|
+
export { defaultTimestep, onNextFrame };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { isMouseEvent, isTouchEvent } from './utils/event-type.mjs';
|
|
2
2
|
import { extractEventInfo } from '../events/event-info.mjs';
|
|
3
|
-
import
|
|
3
|
+
import { sync, cancelSync } from '../frameloop/index.mjs';
|
|
4
4
|
import { secondsToMilliseconds } from '../utils/time-conversion.mjs';
|
|
5
5
|
import { addPointerEvent } from '../events/use-pointer-event.mjs';
|
|
6
6
|
import { pipe } from '../utils/pipe.mjs';
|
|
7
7
|
import { distance2D } from '../utils/distance.mjs';
|
|
8
|
+
import { frameData } from '../frameloop/data.mjs';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @internal
|
|
@@ -39,7 +40,7 @@ class PanSession {
|
|
|
39
40
|
if (!isPanStarted && !isDistancePastThreshold)
|
|
40
41
|
return;
|
|
41
42
|
const { point } = info;
|
|
42
|
-
const { timestamp } =
|
|
43
|
+
const { timestamp } = frameData;
|
|
43
44
|
this.history.push({ ...point, timestamp });
|
|
44
45
|
const { onStart, onMove } = this.handlers;
|
|
45
46
|
if (!isPanStarted) {
|
|
@@ -76,7 +77,7 @@ class PanSession {
|
|
|
76
77
|
const info = extractEventInfo(event);
|
|
77
78
|
const initialInfo = transformPoint(info, this.transformPagePoint);
|
|
78
79
|
const { point } = initialInfo;
|
|
79
|
-
const { timestamp } =
|
|
80
|
+
const { timestamp } = frameData;
|
|
80
81
|
this.history = [{ ...point, timestamp }];
|
|
81
82
|
const { onSessionStart } = handlers;
|
|
82
83
|
onSessionStart &&
|
|
@@ -12,9 +12,9 @@ import { extractEventInfo } from '../../events/event-info.mjs';
|
|
|
12
12
|
import { startAnimation } from '../../animation/utils/transitions.mjs';
|
|
13
13
|
import { convertBoxToBoundingBox, convertBoundingBoxToBox } from '../../projection/geometry/conversion.mjs';
|
|
14
14
|
import { addDomEvent } from '../../events/use-dom-event.mjs';
|
|
15
|
-
import { percent } from 'style-value-types';
|
|
16
15
|
import { calcLength } from '../../projection/geometry/delta-calc.mjs';
|
|
17
16
|
import { mix } from '../../utils/mix.mjs';
|
|
17
|
+
import { percent } from '../../value/types/numbers/units.mjs';
|
|
18
18
|
|
|
19
19
|
const elementDragControls = new WeakMap();
|
|
20
20
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import sync from '
|
|
1
|
+
import { sync } from '../../../frameloop/index.mjs';
|
|
2
2
|
import React__default, { useContext } from 'react';
|
|
3
3
|
import { usePresence } from '../../../components/AnimatePresence/use-presence.mjs';
|
|
4
4
|
import { LayoutGroupContext } from '../../../context/LayoutGroupContext.mjs';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { percent, px } from 'style-value-types';
|
|
2
1
|
import { circOut } from '../../easing/circ.mjs';
|
|
3
2
|
import { progress } from '../../utils/progress.mjs';
|
|
4
3
|
import { mix } from '../../utils/mix.mjs';
|
|
5
4
|
import { noop } from '../../utils/noop.mjs';
|
|
5
|
+
import { percent, px } from '../../value/types/numbers/units.mjs';
|
|
6
6
|
|
|
7
7
|
const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
|
|
8
8
|
const numBorders = borders.length;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { cancelSync, flushSync, sync } from '../../frameloop/index.mjs';
|
|
2
2
|
import { animate } from '../../animation/animate.mjs';
|
|
3
3
|
import { SubscriptionManager } from '../../utils/subscription-manager.mjs';
|
|
4
4
|
import { mixValues } from '../animation/mix-values.mjs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { complex } from 'style-value-types';
|
|
2
1
|
import { cssVariableRegex } from '../../render/dom/utils/css-variables-conversion.mjs';
|
|
3
2
|
import { mix } from '../../utils/mix.mjs';
|
|
3
|
+
import { complex } from '../../value/types/complex/index.mjs';
|
|
4
4
|
|
|
5
5
|
const varToken = "_$css";
|
|
6
6
|
const correctBoxShadow = {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { px, number } from 'style-value-types';
|
|
2
1
|
import { isKeyframesTarget } from '../../../animation/utils/is-keyframes-target.mjs';
|
|
3
2
|
import { invariant } from 'hey-listen';
|
|
4
3
|
import { transformPropOrder } from '../../html/utils/transform.mjs';
|
|
5
4
|
import { findDimensionValueType } from '../value-types/dimensions.mjs';
|
|
6
5
|
import { isBrowser } from '../../../utils/is-browser.mjs';
|
|
6
|
+
import { number } from '../../../value/types/numbers/index.mjs';
|
|
7
|
+
import { px } from '../../../value/types/numbers/units.mjs';
|
|
7
8
|
|
|
8
9
|
const positionalKeys = new Set([
|
|
9
10
|
"width",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { complex } from '../../../value/types/complex/index.mjs';
|
|
2
|
+
import { filter } from '../../../value/types/complex/filter.mjs';
|
|
2
3
|
import { getDefaultValueType } from './defaults.mjs';
|
|
3
4
|
|
|
4
5
|
function getAnimatableNone(key, value) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { number
|
|
1
|
+
import { number } from '../../../value/types/numbers/index.mjs';
|
|
2
|
+
import { px, percent, degrees, vw, vh } from '../../../value/types/numbers/units.mjs';
|
|
2
3
|
import { testValueType } from './test.mjs';
|
|
3
4
|
import { auto } from './type-auto.mjs';
|
|
4
5
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { color
|
|
1
|
+
import { color } from '../../../value/types/color/index.mjs';
|
|
2
|
+
import { complex } from '../../../value/types/complex/index.mjs';
|
|
2
3
|
import { dimensionValueTypes } from './dimensions.mjs';
|
|
3
4
|
import { testValueType } from './test.mjs';
|
|
4
5
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { scale, alpha } from '../../../value/types/numbers/index.mjs';
|
|
2
|
+
import { px, degrees, progressPercentage } from '../../../value/types/numbers/units.mjs';
|
|
2
3
|
import { int } from './type-int.mjs';
|
|
3
4
|
|
|
4
5
|
const numberValueTypes = {
|
|
@@ -22,7 +22,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
22
22
|
* and warn against mismatches.
|
|
23
23
|
*/
|
|
24
24
|
if (process.env.NODE_ENV === "development") {
|
|
25
|
-
warnOnce(nextValue.version === "7.7.
|
|
25
|
+
warnOnce(nextValue.version === "7.7.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.7.1 may not work as expected.`);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
else if (isMotionValue(prevValue)) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { complex } from 'style-value-types';
|
|
2
1
|
import { isNumericalString } from '../../utils/is-numerical-string.mjs';
|
|
3
2
|
import { isZeroValueString } from '../../utils/is-zero-value-string.mjs';
|
|
4
3
|
import { resolveFinalValueInKeyframes } from '../../utils/resolve-value.mjs';
|
|
5
4
|
import { motionValue } from '../../value/index.mjs';
|
|
5
|
+
import { complex } from '../../value/types/complex/index.mjs';
|
|
6
6
|
import { getAnimatableNone } from '../dom/value-types/animatable-none.mjs';
|
|
7
7
|
import { findValueType } from '../dom/value-types/find.mjs';
|
|
8
8
|
import { resolveVariant } from './resolve-dynamic-variants.mjs';
|
package/dist/es/utils/delay.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { mix } from './mix.mjs';
|
|
2
|
-
import { rgba, hsla, hex } from 'style-value-types';
|
|
3
2
|
import { invariant } from 'hey-listen';
|
|
4
3
|
import { hslaToRgba } from './hsla-to-rgba.mjs';
|
|
4
|
+
import { hex } from '../value/types/color/hex.mjs';
|
|
5
|
+
import { rgba } from '../value/types/color/rgba.mjs';
|
|
6
|
+
import { hsla } from '../value/types/color/hsla.mjs';
|
|
5
7
|
|
|
6
8
|
// Linear color space blending
|
|
7
9
|
// Explained https://www.youtube.com/watch?v=LKnqECcg6Gw
|
|
@@ -17,6 +19,7 @@ function asRGBA(color) {
|
|
|
17
19
|
invariant(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
|
|
18
20
|
let model = type.parse(color);
|
|
19
21
|
if (type === hsla) {
|
|
22
|
+
// TODO Remove this cast - needed since Framer Motion's stricter typing
|
|
20
23
|
model = hslaToRgba(model);
|
|
21
24
|
}
|
|
22
25
|
return model;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { complex, color } from 'style-value-types';
|
|
2
1
|
import { mix } from './mix.mjs';
|
|
3
2
|
import { mixColor } from './mix-color.mjs';
|
|
4
3
|
import { pipe } from './pipe.mjs';
|
|
5
4
|
import { warning } from 'hey-listen';
|
|
5
|
+
import { color } from '../value/types/color/index.mjs';
|
|
6
|
+
import { complex, analyseComplexValue } from '../value/types/complex/index.mjs';
|
|
6
7
|
|
|
7
8
|
function getMixer(origin, target) {
|
|
8
9
|
if (typeof origin === "number") {
|
|
@@ -41,34 +42,14 @@ const mixObject = (origin, target) => {
|
|
|
41
42
|
return output;
|
|
42
43
|
};
|
|
43
44
|
};
|
|
44
|
-
/**
|
|
45
|
-
* TODO: Combine with function within complex when style-value-types moved inside Framer Motion
|
|
46
|
-
*/
|
|
47
|
-
function analyse(value) {
|
|
48
|
-
const parsed = complex.parse(value);
|
|
49
|
-
const numValues = parsed.length;
|
|
50
|
-
let numNumbers = 0;
|
|
51
|
-
let numColors = 0;
|
|
52
|
-
for (let i = 0; i < numValues; i++) {
|
|
53
|
-
// Parsed complex values return with colors first, so if we've seen any number
|
|
54
|
-
// we're already past that part of the array and don't need to continue running typeof
|
|
55
|
-
if (numNumbers || typeof parsed[i] === "number") {
|
|
56
|
-
numNumbers++;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
numColors++;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return { parsed, numNumbers, numColors };
|
|
63
|
-
}
|
|
64
45
|
const mixComplex = (origin, target) => {
|
|
65
46
|
const template = complex.createTransformer(target);
|
|
66
|
-
const originStats =
|
|
67
|
-
const targetStats =
|
|
47
|
+
const originStats = analyseComplexValue(origin);
|
|
48
|
+
const targetStats = analyseComplexValue(target);
|
|
68
49
|
const canInterpolate = originStats.numColors === targetStats.numColors &&
|
|
69
50
|
originStats.numNumbers >= targetStats.numNumbers;
|
|
70
51
|
if (canInterpolate) {
|
|
71
|
-
return pipe(mixArray(originStats.
|
|
52
|
+
return pipe(mixArray(originStats.values, targetStats.values), template);
|
|
72
53
|
}
|
|
73
54
|
else {
|
|
74
55
|
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.`);
|
package/dist/es/value/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { sync } from '../frameloop/index.mjs';
|
|
2
|
+
import { frameData } from '../frameloop/data.mjs';
|
|
2
3
|
import { SubscriptionManager } from '../utils/subscription-manager.mjs';
|
|
3
4
|
import { velocityPerSecond } from '../utils/velocity-per-second.mjs';
|
|
4
5
|
|
|
@@ -24,7 +25,7 @@ class MotionValue {
|
|
|
24
25
|
* This will be replaced by the build step with the latest version number.
|
|
25
26
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
26
27
|
*/
|
|
27
|
-
this.version = "7.7.
|
|
28
|
+
this.version = "7.7.1";
|
|
28
29
|
/**
|
|
29
30
|
* Duration, in milliseconds, since last updating frame.
|
|
30
31
|
*
|
|
@@ -67,7 +68,7 @@ class MotionValue {
|
|
|
67
68
|
this.prev = this.current;
|
|
68
69
|
this.current = v;
|
|
69
70
|
// Update timestamp
|
|
70
|
-
const { delta, timestamp } =
|
|
71
|
+
const { delta, timestamp } = frameData;
|
|
71
72
|
if (this.lastUpdated !== timestamp) {
|
|
72
73
|
this.timeDelta = delta;
|
|
73
74
|
this.lastUpdated = timestamp;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { rgba } from './rgba.mjs';
|
|
2
|
+
import { isColorString } from './utils.mjs';
|
|
3
|
+
|
|
4
|
+
function parseHex(v) {
|
|
5
|
+
let r = "";
|
|
6
|
+
let g = "";
|
|
7
|
+
let b = "";
|
|
8
|
+
let a = "";
|
|
9
|
+
// If we have 6 characters, ie #FF0000
|
|
10
|
+
if (v.length > 5) {
|
|
11
|
+
r = v.substring(1, 3);
|
|
12
|
+
g = v.substring(3, 5);
|
|
13
|
+
b = v.substring(5, 7);
|
|
14
|
+
a = v.substring(7, 9);
|
|
15
|
+
// Or we have 3 characters, ie #F00
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
r = v.substring(1, 2);
|
|
19
|
+
g = v.substring(2, 3);
|
|
20
|
+
b = v.substring(3, 4);
|
|
21
|
+
a = v.substring(4, 5);
|
|
22
|
+
r += r;
|
|
23
|
+
g += g;
|
|
24
|
+
b += b;
|
|
25
|
+
a += a;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
red: parseInt(r, 16),
|
|
29
|
+
green: parseInt(g, 16),
|
|
30
|
+
blue: parseInt(b, 16),
|
|
31
|
+
alpha: a ? parseInt(a, 16) / 255 : 1,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const hex = {
|
|
35
|
+
test: isColorString("#"),
|
|
36
|
+
parse: parseHex,
|
|
37
|
+
transform: rgba.transform,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { hex };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { alpha } from '../numbers/index.mjs';
|
|
2
|
+
import { percent } from '../numbers/units.mjs';
|
|
3
|
+
import { sanitize } from '../utils.mjs';
|
|
4
|
+
import { isColorString, splitColor } from './utils.mjs';
|
|
5
|
+
|
|
6
|
+
const hsla = {
|
|
7
|
+
test: isColorString("hsl", "hue"),
|
|
8
|
+
parse: splitColor("hue", "saturation", "lightness"),
|
|
9
|
+
transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
|
|
10
|
+
return ("hsla(" +
|
|
11
|
+
Math.round(hue) +
|
|
12
|
+
", " +
|
|
13
|
+
percent.transform(sanitize(saturation)) +
|
|
14
|
+
", " +
|
|
15
|
+
percent.transform(sanitize(lightness)) +
|
|
16
|
+
", " +
|
|
17
|
+
sanitize(alpha.transform(alpha$1)) +
|
|
18
|
+
")");
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { hsla };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { isString } from '../utils.mjs';
|
|
2
|
+
import { hex } from './hex.mjs';
|
|
3
|
+
import { hsla } from './hsla.mjs';
|
|
4
|
+
import { rgba } from './rgba.mjs';
|
|
5
|
+
|
|
6
|
+
const color = {
|
|
7
|
+
test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
|
|
8
|
+
parse: (v) => {
|
|
9
|
+
if (rgba.test(v)) {
|
|
10
|
+
return rgba.parse(v);
|
|
11
|
+
}
|
|
12
|
+
else if (hsla.test(v)) {
|
|
13
|
+
return hsla.parse(v);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return hex.parse(v);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
transform: (v) => {
|
|
20
|
+
return isString(v)
|
|
21
|
+
? v
|
|
22
|
+
: v.hasOwnProperty("red")
|
|
23
|
+
? rgba.transform(v)
|
|
24
|
+
: hsla.transform(v);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { color };
|