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.
Files changed (62) hide show
  1. package/dist/cjs/index.js +529 -155
  2. package/dist/es/animation/legacy-popmotion/index.mjs +1 -1
  3. package/dist/es/animation/legacy-popmotion/inertia.mjs +2 -2
  4. package/dist/es/animation/utils/is-animatable.mjs +1 -1
  5. package/dist/es/frameloop/create-render-step.mjs +88 -0
  6. package/dist/es/frameloop/data.mjs +6 -0
  7. package/dist/es/frameloop/index.mjs +59 -0
  8. package/dist/es/frameloop/on-next-frame.mjs +12 -0
  9. package/dist/es/gestures/PanSession.mjs +4 -3
  10. package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -1
  11. package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -1
  12. package/dist/es/projection/animation/mix-values.mjs +1 -1
  13. package/dist/es/projection/geometry/delta-remove.mjs +1 -1
  14. package/dist/es/projection/node/create-projection-node.mjs +1 -1
  15. package/dist/es/projection/styles/scale-border-radius.mjs +1 -1
  16. package/dist/es/projection/styles/scale-box-shadow.mjs +1 -1
  17. package/dist/es/render/VisualElement.mjs +1 -1
  18. package/dist/es/render/dom/utils/unit-conversion.mjs +2 -1
  19. package/dist/es/render/dom/value-types/animatable-none.mjs +2 -1
  20. package/dist/es/render/dom/value-types/defaults.mjs +2 -1
  21. package/dist/es/render/dom/value-types/dimensions.mjs +2 -1
  22. package/dist/es/render/dom/value-types/find.mjs +2 -1
  23. package/dist/es/render/dom/value-types/number.mjs +2 -1
  24. package/dist/es/render/dom/value-types/type-int.mjs +1 -1
  25. package/dist/es/render/svg/utils/path.mjs +1 -1
  26. package/dist/es/render/svg/utils/transform-origin.mjs +1 -1
  27. package/dist/es/render/utils/motion-values.mjs +1 -1
  28. package/dist/es/render/utils/setters.mjs +1 -1
  29. package/dist/es/utils/delay.mjs +1 -1
  30. package/dist/es/utils/interpolate.mjs +1 -1
  31. package/dist/es/utils/mix-color.mjs +4 -1
  32. package/dist/es/utils/mix-complex.mjs +5 -24
  33. package/dist/es/utils/use-animation-frame.mjs +1 -1
  34. package/dist/es/utils/use-force-update.mjs +1 -1
  35. package/dist/es/utils/use-instant-transition.mjs +1 -1
  36. package/dist/es/value/index.mjs +4 -3
  37. package/dist/es/value/types/color/hex.mjs +40 -0
  38. package/dist/es/value/types/color/hsla.mjs +22 -0
  39. package/dist/es/value/types/color/index.mjs +28 -0
  40. package/dist/es/value/types/color/rgba.mjs +25 -0
  41. package/dist/es/value/types/color/utils.mjs +23 -0
  42. package/dist/es/value/types/complex/filter.mjs +30 -0
  43. package/dist/es/value/types/complex/index.mjs +61 -0
  44. package/dist/es/value/types/numbers/index.mjs +17 -0
  45. package/dist/es/value/types/numbers/units.mjs +19 -0
  46. package/dist/es/value/types/utils.mjs +15 -0
  47. package/dist/es/value/use-combine-values.mjs +1 -1
  48. package/dist/framer-motion.dev.js +284 -230
  49. package/dist/framer-motion.js +1 -1
  50. package/dist/index.d.ts +7 -2
  51. package/dist/projection.dev.js +5451 -5397
  52. package/dist/size-rollup-dom-animation-assets.js +1 -1
  53. package/dist/size-rollup-dom-animation.js +1 -1
  54. package/dist/size-rollup-dom-max-assets.js +1 -1
  55. package/dist/size-rollup-dom-max.js +1 -1
  56. package/dist/size-rollup-m.js +1 -1
  57. package/dist/size-rollup-motion.js +1 -1
  58. package/dist/size-webpack-dom-animation.js +1 -1
  59. package/dist/size-webpack-dom-max.js +1 -1
  60. package/dist/size-webpack-m.js +1 -1
  61. package/dist/three-entry.d.ts +7 -2
  62. 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, { cancelSync } from 'framesync';
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, getFrameData().delta);
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 });
@@ -1,4 +1,4 @@
1
- import { complex } from 'style-value-types';
1
+ import { complex } from '../../value/types/complex/index.mjs';
2
2
 
3
3
  /**
4
4
  * Check if a value is animatable. Examples:
@@ -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,6 @@
1
+ const frameData = {
2
+ delta: 0,
3
+ timestamp: 0,
4
+ };
5
+
6
+ export { frameData };
@@ -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 sync, { getFrameData, cancelSync } from 'framesync';
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 } = getFrameData();
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 } = getFrameData();
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 'framesync';
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,5 +1,5 @@
1
- import { percent } from 'style-value-types';
2
1
  import { mix } from '../../utils/mix.mjs';
2
+ import { percent } from '../../value/types/numbers/units.mjs';
3
3
  import { scalePoint } from './delta-apply.mjs';
4
4
 
5
5
  /**
@@ -1,4 +1,4 @@
1
- import sync, { cancelSync, flushSync } from 'framesync';
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,4 +1,4 @@
1
- import { px } from 'style-value-types';
1
+ import { px } from '../../value/types/numbers/units.mjs';
2
2
 
3
3
  function pixelsToPercent(pixels, axis) {
4
4
  if (axis.max === axis.min)
@@ -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,4 +1,4 @@
1
- import sync, { cancelSync } from 'framesync';
1
+ import { sync, cancelSync } from '../frameloop/index.mjs';
2
2
  import { invariant } from 'hey-listen';
3
3
  import { createElement } from 'react';
4
4
  import { featureDefinitions } from '../motion/features/definitions.mjs';
@@ -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 { filter, complex } from 'style-value-types';
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 { color, filter } from 'style-value-types';
1
+ import { color } from '../../../value/types/color/index.mjs';
2
+ import { filter } from '../../../value/types/complex/filter.mjs';
2
3
  import { numberValueTypes } from './number.mjs';
3
4
 
4
5
  /**
@@ -1,4 +1,5 @@
1
- import { number, px, percent, degrees, vw, vh } from 'style-value-types';
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, complex } from 'style-value-types';
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 { px, degrees, scale, alpha, progressPercentage } from 'style-value-types';
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 = {
@@ -1,4 +1,4 @@
1
- import { number } from 'style-value-types';
1
+ import { number } from '../../../value/types/numbers/index.mjs';
2
2
 
3
3
  const int = {
4
4
  ...number,
@@ -1,4 +1,4 @@
1
- import { px } from 'style-value-types';
1
+ import { px } from '../../../value/types/numbers/units.mjs';
2
2
 
3
3
  const dashKeys = {
4
4
  offset: "stroke-dashoffset",
@@ -1,4 +1,4 @@
1
- import { px } from 'style-value-types';
1
+ import { px } from '../../../value/types/numbers/units.mjs';
2
2
 
3
3
  function calcOrigin(origin, offset, size) {
4
4
  return typeof origin === "string"
@@ -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.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.7.0 may not work as expected.`);
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';
@@ -1,4 +1,4 @@
1
- import sync, { cancelSync } from 'framesync';
1
+ import { sync, cancelSync } from '../frameloop/index.mjs';
2
2
 
3
3
  function delay(callback, timeout) {
4
4
  const start = performance.now();
@@ -1,5 +1,5 @@
1
1
  import { invariant } from 'hey-listen';
2
- import { color } from 'style-value-types';
2
+ import { color } from '../value/types/color/index.mjs';
3
3
  import { clamp } from './clamp.mjs';
4
4
  import { mix } from './mix.mjs';
5
5
  import { mixColor } from './mix-color.mjs';
@@ -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 = analyse(origin);
67
- const targetStats = analyse(target);
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.parsed, targetStats.parsed), template);
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.`);
@@ -1,4 +1,4 @@
1
- import sync, { cancelSync } from 'framesync';
1
+ import { sync, cancelSync } from '../frameloop/index.mjs';
2
2
  import { useRef, useContext, useEffect } from 'react';
3
3
  import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import sync from 'framesync';
1
+ import { sync } from '../frameloop/index.mjs';
2
2
  import { useState, useCallback } from 'react';
3
3
  import { useIsMounted } from './use-is-mounted.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import sync from 'framesync';
1
+ import { sync } from '../frameloop/index.mjs';
2
2
  import { useEffect } from 'react';
3
3
  import { useInstantLayoutTransition } from '../projection/use-instant-layout-transition.mjs';
4
4
  import { useForceUpdate } from './use-force-update.mjs';
@@ -1,4 +1,5 @@
1
- import sync, { getFrameData } from 'framesync';
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.0";
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 } = getFrameData();
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 };