framer-motion 7.2.0 → 7.3.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 (96) hide show
  1. package/dist/cjs/index.js +762 -627
  2. package/dist/es/animation/use-animated-state.mjs +3 -5
  3. package/dist/es/animation/utils/default-transitions.mjs +1 -1
  4. package/dist/es/animation/utils/transitions.mjs +28 -26
  5. package/dist/es/components/AnimatePresence/PopChild.mjs +3 -2
  6. package/dist/es/components/AnimatePresence/PresenceChild.mjs +5 -2
  7. package/dist/es/components/AnimatePresence/use-presence.mjs +1 -1
  8. package/dist/es/components/LayoutGroup/index.mjs +4 -5
  9. package/dist/es/components/LazyMotion/index.mjs +3 -5
  10. package/dist/es/components/MotionConfig/index.mjs +2 -4
  11. package/dist/es/components/Reorder/Group.mjs +2 -4
  12. package/dist/es/components/Reorder/Item.mjs +6 -8
  13. package/dist/es/context/MotionContext/utils.mjs +3 -2
  14. package/dist/es/gestures/PanSession.mjs +2 -2
  15. package/dist/es/gestures/drag/VisualElementDragControls.mjs +16 -4
  16. package/dist/es/gestures/use-focus-gesture.mjs +3 -4
  17. package/dist/es/gestures/use-hover-gesture.mjs +4 -3
  18. package/dist/es/gestures/use-tap-gesture.mjs +9 -10
  19. package/dist/es/index.mjs +2 -1
  20. package/dist/es/motion/features/animations.mjs +8 -3
  21. package/dist/es/motion/features/definitions.mjs +1 -13
  22. package/dist/es/motion/features/layout/MeasureLayout.mjs +12 -6
  23. package/dist/es/motion/features/load-features.mjs +14 -0
  24. package/dist/es/motion/features/viewport/observers.mjs +4 -7
  25. package/dist/es/motion/features/viewport/use-viewport.mjs +8 -6
  26. package/dist/es/motion/index.mjs +23 -23
  27. package/dist/es/motion/utils/VisualElementHandler.mjs +2 -5
  28. package/dist/es/motion/utils/is-forced-motion-value.mjs +3 -3
  29. package/dist/es/motion/utils/use-motion-ref.mjs +1 -2
  30. package/dist/es/motion/utils/use-visual-element.mjs +14 -12
  31. package/dist/es/motion/utils/use-visual-state.mjs +19 -16
  32. package/dist/es/motion/utils/valid-prop.mjs +22 -17
  33. package/dist/es/projection/geometry/utils.mjs +10 -1
  34. package/dist/es/projection/node/HTMLProjectionNode.mjs +1 -1
  35. package/dist/es/projection/node/create-projection-node.mjs +62 -20
  36. package/dist/es/projection/use-instant-layout-transition.mjs +2 -2
  37. package/dist/es/render/dom/features-animation.mjs +5 -1
  38. package/dist/es/render/dom/features-max.mjs +6 -1
  39. package/dist/es/render/dom/motion.mjs +6 -1
  40. package/dist/es/render/dom/use-render.mjs +5 -1
  41. package/dist/es/render/dom/utils/camel-to-dash.mjs +1 -3
  42. package/dist/es/render/dom/utils/create-config.mjs +7 -2
  43. package/dist/es/render/dom/utils/css-variables-conversion.mjs +5 -7
  44. package/dist/es/render/dom/utils/unit-conversion.mjs +4 -4
  45. package/dist/es/render/dom/value-types/defaults.mjs +15 -3
  46. package/dist/es/render/dom/value-types/type-int.mjs +4 -1
  47. package/dist/es/render/html/config-motion.mjs +1 -1
  48. package/dist/es/render/html/use-props.mjs +5 -9
  49. package/dist/es/render/html/utils/build-styles.mjs +17 -15
  50. package/dist/es/render/html/utils/build-transform.mjs +8 -18
  51. package/dist/es/render/html/utils/transform.mjs +21 -30
  52. package/dist/es/render/html/visual-element.mjs +8 -9
  53. package/dist/es/render/index.mjs +118 -40
  54. package/dist/es/render/svg/use-props.mjs +5 -2
  55. package/dist/es/render/svg/utils/build-attrs.mjs +3 -5
  56. package/dist/es/render/svg/utils/create-render-state.mjs +4 -1
  57. package/dist/es/render/svg/visual-element.mjs +8 -4
  58. package/dist/es/render/utils/animation-state.mjs +12 -9
  59. package/dist/es/render/utils/animation.mjs +14 -8
  60. package/dist/es/render/utils/is-controlling-variants.mjs +22 -0
  61. package/dist/es/render/utils/is-variant-label.mjs +8 -0
  62. package/dist/es/render/utils/motion-values.mjs +3 -3
  63. package/dist/es/render/utils/resolve-dynamic-variants.mjs +24 -0
  64. package/dist/es/render/utils/resolve-variants.mjs +26 -0
  65. package/dist/es/render/utils/setters.mjs +12 -9
  66. package/dist/es/utils/reduced-motion/index.mjs +19 -0
  67. package/dist/es/utils/reduced-motion/state.mjs +5 -0
  68. package/dist/es/utils/reduced-motion/use-reduced-motion-config.mjs +19 -0
  69. package/dist/es/utils/reduced-motion/use-reduced-motion.mjs +43 -0
  70. package/dist/es/utils/transform.mjs +4 -1
  71. package/dist/es/utils/use-in-view.mjs +1 -2
  72. package/dist/es/value/index.mjs +1 -1
  73. package/dist/es/value/use-scroll.mjs +6 -4
  74. package/dist/es/value/use-spring.mjs +7 -1
  75. package/dist/es/value/use-will-change/index.mjs +4 -4
  76. package/dist/es/value/utils/is-motion-value.mjs +1 -3
  77. package/dist/framer-motion.dev.js +806 -670
  78. package/dist/framer-motion.js +1 -1
  79. package/dist/index.d.ts +60 -54
  80. package/dist/projection.dev.js +402 -213
  81. package/dist/size-rollup-dom-animation-assets.js +1 -0
  82. package/dist/size-rollup-dom-animation-m.js +1 -0
  83. package/dist/size-rollup-dom-animation.js +1 -1
  84. package/dist/size-rollup-dom-max-assets.js +1 -0
  85. package/dist/size-rollup-dom-max.js +1 -1
  86. package/dist/size-rollup-m.js +1 -1
  87. package/dist/size-rollup-motion.js +1 -0
  88. package/dist/size-webpack-dom-animation.js +1 -1
  89. package/dist/size-webpack-dom-max.js +1 -1
  90. package/dist/size-webpack-m.js +1 -1
  91. package/dist/three-entry.d.ts +41 -22
  92. package/package.json +12 -8
  93. package/dist/es/motion/features/use-features.mjs +0 -40
  94. package/dist/es/motion/features/use-projection.mjs +0 -33
  95. package/dist/es/render/utils/variants.mjs +0 -73
  96. package/dist/es/utils/use-reduced-motion.mjs +0 -73
@@ -649,9 +649,12 @@ interface LayoutProps {
649
649
  * If `layout` is set to `"size"`, the position of the component will change instantly and
650
650
  * only its size will animate.
651
651
  *
652
+ * If `layout` is set to `"preserve-aspect"`, the component will animate size & position if
653
+ * the aspect ratio remains the same between renders, and just position if the ratio changes.
654
+ *
652
655
  * @public
653
656
  */
654
- layout?: boolean | "position" | "size";
657
+ layout?: boolean | "position" | "size" | "preserve-aspect";
655
658
  /**
656
659
  * Enable shared layout transitions between different components with the same `layoutId`.
657
660
  *
@@ -2256,6 +2259,10 @@ declare class FlatTree {
2256
2259
  forEach(callback: (child: WithDepth) => void): void;
2257
2260
  }
2258
2261
 
2262
+ interface SwitchLayoutGroup {
2263
+ register?: (member: IProjectionNode) => void;
2264
+ deregister?: (member: IProjectionNode) => void;
2265
+ }
2259
2266
  declare type InitialPromotionConfig = {
2260
2267
  /**
2261
2268
  * The initial transition to use when the elements in this group mount (and automatically promoted).
@@ -2267,6 +2274,11 @@ declare type InitialPromotionConfig = {
2267
2274
  */
2268
2275
  shouldPreserveFollowOpacity?: (member: IProjectionNode) => boolean;
2269
2276
  };
2277
+ declare type SwitchLayoutGroupContext = SwitchLayoutGroup & InitialPromotionConfig;
2278
+ /**
2279
+ * Internal, exported only for usage in Framer
2280
+ */
2281
+ declare const SwitchLayoutGroupContext: React.Context<SwitchLayoutGroupContext>;
2270
2282
 
2271
2283
  interface Snapshot {
2272
2284
  measured: Box;
@@ -2373,7 +2385,7 @@ interface ProjectionNodeOptions {
2373
2385
  alwaysMeasureLayout?: boolean;
2374
2386
  scheduleRender?: VoidFunction;
2375
2387
  onExitComplete?: VoidFunction;
2376
- animationType?: "size" | "position" | "both";
2388
+ animationType?: "size" | "position" | "both" | "preserve-aspect";
2377
2389
  layoutId?: string;
2378
2390
  layout?: boolean | string;
2379
2391
  visualElement?: VisualElement;
@@ -2382,8 +2394,33 @@ interface ProjectionNodeOptions {
2382
2394
  initialPromotionConfig?: InitialPromotionConfig;
2383
2395
  }
2384
2396
 
2397
+ declare type ReducedMotionConfig = "always" | "never" | "user";
2398
+
2385
2399
  declare function filterProps(props: MotionProps, isDom: boolean, forwardMotionProps: boolean): {};
2386
2400
 
2401
+ /**
2402
+ * @public
2403
+ */
2404
+ interface FeatureProps extends MotionProps {
2405
+ visualElement: VisualElement;
2406
+ }
2407
+ declare type FeatureComponent = React.ComponentType<React.PropsWithChildren<FeatureProps>>;
2408
+ interface FeatureComponents {
2409
+ animation?: FeatureComponent;
2410
+ exit?: FeatureComponent;
2411
+ drag?: FeatureComponent;
2412
+ tap?: FeatureComponent;
2413
+ focus?: FeatureComponent;
2414
+ hover?: FeatureComponent;
2415
+ pan?: FeatureComponent;
2416
+ inView?: FeatureComponent;
2417
+ measureLayout?: FeatureComponent;
2418
+ }
2419
+ interface FeatureBundle extends FeatureComponents {
2420
+ renderer: CreateVisualElement<any>;
2421
+ projectionNodeConstructor?: any;
2422
+ }
2423
+
2387
2424
  interface VisualElement<Instance = any, RenderState = any> extends LifecycleManager {
2388
2425
  treeType: string;
2389
2426
  depth: number;
@@ -2405,6 +2442,7 @@ interface VisualElement<Instance = any, RenderState = any> extends LifecycleMana
2405
2442
  getClosestVariantNode(): VisualElement | undefined;
2406
2443
  shouldReduceMotion?: boolean | null;
2407
2444
  animateMotionValue?: typeof startAnimation;
2445
+ loadFeatures(props: MotionProps, isStrict?: boolean, preloadedFeatures?: FeatureBundle, projectionId?: number, ProjectionNodeConstructor?: any, initialPromotionConfig?: SwitchLayoutGroupContext): JSX.Element[];
2408
2446
  projection?: IProjectionNode;
2409
2447
  /**
2410
2448
  * Visibility
@@ -2458,7 +2496,7 @@ declare type VisualElementOptions<Instance, RenderState = any> = {
2458
2496
  presenceId?: string | undefined;
2459
2497
  props: MotionProps;
2460
2498
  blockInitialAnimation?: boolean;
2461
- shouldReduceMotion?: boolean | null;
2499
+ reducedMotionConfig?: ReducedMotionConfig;
2462
2500
  };
2463
2501
  declare type CreateVisualElement<Instance> = (Component: string | React.ComponentType<React.PropsWithChildren<unknown>>, options: VisualElementOptions<Instance>) => VisualElement<Instance>;
2464
2502
  /**
@@ -2468,25 +2506,6 @@ interface ResolvedValues {
2468
2506
  [key: string]: string | number;
2469
2507
  }
2470
2508
 
2471
- /**
2472
- * @public
2473
- */
2474
- interface FeatureProps extends MotionProps {
2475
- visualElement: VisualElement;
2476
- }
2477
- declare type FeatureComponent = React.ComponentType<React.PropsWithChildren<FeatureProps>>;
2478
- interface FeatureComponents {
2479
- animation?: FeatureComponent;
2480
- exit?: FeatureComponent;
2481
- drag?: FeatureComponent;
2482
- tap?: FeatureComponent;
2483
- focus?: FeatureComponent;
2484
- hover?: FeatureComponent;
2485
- pan?: FeatureComponent;
2486
- inView?: FeatureComponent;
2487
- measureLayout?: FeatureComponent;
2488
- }
2489
-
2490
2509
  declare const animations: FeatureComponents;
2491
2510
 
2492
2511
  declare function useVisualElementContext(): VisualElement<any, any> | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-motion",
3
- "version": "7.2.0",
3
+ "version": "7.3.1",
4
4
  "description": "A simple and powerful React animation library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.mjs",
@@ -71,30 +71,34 @@
71
71
  "@emotion/is-prop-valid": "^0.8.2"
72
72
  },
73
73
  "bundlesize": [
74
+ {
75
+ "path": "./dist/size-rollup-motion.js",
76
+ "maxSize": "29.2 kB"
77
+ },
74
78
  {
75
79
  "path": "./dist/size-rollup-m.js",
76
- "maxSize": "5.5 kB"
80
+ "maxSize": "4.67 kB"
77
81
  },
78
82
  {
79
83
  "path": "./dist/size-rollup-dom-animation.js",
80
- "maxSize": "16.6 kB"
84
+ "maxSize": "16.75 kB"
81
85
  },
82
86
  {
83
87
  "path": "./dist/size-rollup-dom-max.js",
84
- "maxSize": "27.1 kB"
88
+ "maxSize": "27.2 kB"
85
89
  },
86
90
  {
87
91
  "path": "./dist/size-webpack-m.js",
88
- "maxSize": "5.7 kB"
92
+ "maxSize": "4.9 kB"
89
93
  },
90
94
  {
91
95
  "path": "./dist/size-webpack-dom-animation.js",
92
- "maxSize": "19 kB"
96
+ "maxSize": "19.1 kB"
93
97
  },
94
98
  {
95
99
  "path": "./dist/size-webpack-dom-max.js",
96
- "maxSize": "30.1kB"
100
+ "maxSize": "30.3kB"
97
101
  }
98
102
  ],
99
- "gitHead": "3fc155b6afa513a2d38dc3728ccd69853480df3d"
103
+ "gitHead": "650ba252cf541f4108e8b514d20105d171fc35e3"
100
104
  }
@@ -1,40 +0,0 @@
1
- import * as React from 'react';
2
- import { useContext } from 'react';
3
- import { env } from '../../utils/process.mjs';
4
- import { featureDefinitions } from './definitions.mjs';
5
- import { invariant } from 'hey-listen';
6
- import { LazyContext } from '../../context/LazyContext.mjs';
7
-
8
- const featureNames = Object.keys(featureDefinitions);
9
- const numFeatures = featureNames.length;
10
- /**
11
- * Load features via renderless components based on the provided MotionProps.
12
- */
13
- function useFeatures(props, visualElement, preloadedFeatures) {
14
- const features = [];
15
- const lazyContext = useContext(LazyContext);
16
- if (!visualElement)
17
- return null;
18
- /**
19
- * If we're in development mode, check to make sure we're not rendering a motion component
20
- * as a child of LazyMotion, as this will break the file-size benefits of using it.
21
- */
22
- if (env !== "production" && preloadedFeatures && lazyContext.strict) {
23
- invariant(false, "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.");
24
- }
25
- for (let i = 0; i < numFeatures; i++) {
26
- const name = featureNames[i];
27
- const { isEnabled, Component } = featureDefinitions[name];
28
- /**
29
- * It might be possible in the future to use this moment to
30
- * dynamically request functionality. In initial tests this
31
- * was producing a lot of duplication amongst bundles.
32
- */
33
- if (isEnabled(props) && Component) {
34
- features.push(React.createElement(Component, Object.assign({ key: name }, props, { visualElement: visualElement })));
35
- }
36
- }
37
- return features;
38
- }
39
-
40
- export { useFeatures };
@@ -1,33 +0,0 @@
1
- import { isRefObject } from '../../utils/is-ref-object.mjs';
2
- import { useContext } from 'react';
3
- import { SwitchLayoutGroupContext } from '../../context/SwitchLayoutGroupContext.mjs';
4
-
5
- function useProjection(projectionId, { layoutId, layout, drag, dragConstraints, layoutScroll }, visualElement, ProjectionNodeConstructor) {
6
- var _a;
7
- const initialPromotionConfig = useContext(SwitchLayoutGroupContext);
8
- if (!ProjectionNodeConstructor ||
9
- !visualElement ||
10
- (visualElement === null || visualElement === void 0 ? void 0 : visualElement.projection)) {
11
- return;
12
- }
13
- visualElement.projection = new ProjectionNodeConstructor(projectionId, visualElement.getLatestValues(), (_a = visualElement.parent) === null || _a === void 0 ? void 0 : _a.projection);
14
- visualElement.projection.setOptions({
15
- layoutId,
16
- layout,
17
- alwaysMeasureLayout: Boolean(drag) || (dragConstraints && isRefObject(dragConstraints)),
18
- visualElement,
19
- scheduleRender: () => visualElement.scheduleRender(),
20
- /**
21
- * TODO: Update options in an effect. This could be tricky as it'll be too late
22
- * to update by the time layout animations run.
23
- * We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
24
- * ensuring it gets called if there's no potential layout animations.
25
- *
26
- */
27
- animationType: typeof layout === "string" ? layout : "both",
28
- initialPromotionConfig,
29
- layoutScroll,
30
- });
31
- }
32
-
33
- export { useProjection };
@@ -1,73 +0,0 @@
1
- /**
2
- * Decides if the supplied variable is an array of variant labels
3
- */
4
- function isVariantLabels(v) {
5
- return Array.isArray(v);
6
- }
7
- /**
8
- * Decides if the supplied variable is variant label
9
- */
10
- function isVariantLabel(v) {
11
- return typeof v === "string" || isVariantLabels(v);
12
- }
13
- /**
14
- * Creates an object containing the latest state of every MotionValue on a VisualElement
15
- */
16
- function getCurrent(visualElement) {
17
- const current = {};
18
- visualElement.forEachValue((value, key) => (current[key] = value.get()));
19
- return current;
20
- }
21
- /**
22
- * Creates an object containing the latest velocity of every MotionValue on a VisualElement
23
- */
24
- function getVelocity(visualElement) {
25
- const velocity = {};
26
- visualElement.forEachValue((value, key) => (velocity[key] = value.getVelocity()));
27
- return velocity;
28
- }
29
- function resolveVariantFromProps(props, definition, custom, currentValues = {}, currentVelocity = {}) {
30
- var _a;
31
- /**
32
- * If the variant definition is a function, resolve.
33
- */
34
- if (typeof definition === "function") {
35
- definition = definition(custom !== null && custom !== void 0 ? custom : props.custom, currentValues, currentVelocity);
36
- }
37
- /**
38
- * If the variant definition is a variant label, or
39
- * the function returned a variant label, resolve.
40
- */
41
- if (typeof definition === "string") {
42
- definition = (_a = props.variants) === null || _a === void 0 ? void 0 : _a[definition];
43
- }
44
- /**
45
- * At this point we've resolved both functions and variant labels,
46
- * but the resolved variant label might itself have been a function.
47
- * If so, resolve. This can only have returned a valid target object.
48
- */
49
- if (typeof definition === "function") {
50
- definition = definition(custom !== null && custom !== void 0 ? custom : props.custom, currentValues, currentVelocity);
51
- }
52
- return definition;
53
- }
54
- function resolveVariant(visualElement, definition, custom) {
55
- const props = visualElement.getProps();
56
- return resolveVariantFromProps(props, definition, custom !== null && custom !== void 0 ? custom : props.custom, getCurrent(visualElement), getVelocity(visualElement));
57
- }
58
- function checkIfControllingVariants(props) {
59
- var _a;
60
- return (typeof ((_a = props.animate) === null || _a === void 0 ? void 0 : _a.start) === "function" ||
61
- isVariantLabel(props.initial) ||
62
- isVariantLabel(props.animate) ||
63
- isVariantLabel(props.whileHover) ||
64
- isVariantLabel(props.whileDrag) ||
65
- isVariantLabel(props.whileTap) ||
66
- isVariantLabel(props.whileFocus) ||
67
- isVariantLabel(props.exit));
68
- }
69
- function checkIfVariantNode(props) {
70
- return Boolean(checkIfControllingVariants(props) || props.variants);
71
- }
72
-
73
- export { checkIfControllingVariants, checkIfVariantNode, isVariantLabel, isVariantLabels, resolveVariant, resolveVariantFromProps };
@@ -1,73 +0,0 @@
1
- import { useState, useContext } from 'react';
2
- import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
3
- import { isBrowser } from './is-browser.mjs';
4
-
5
- // Does this device prefer reduced motion? Returns `null` server-side.
6
- const prefersReducedMotion = { current: null };
7
- let hasDetected = false;
8
- function initPrefersReducedMotion() {
9
- hasDetected = true;
10
- if (!isBrowser)
11
- return;
12
- if (window.matchMedia) {
13
- const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)");
14
- const setReducedMotionPreferences = () => (prefersReducedMotion.current = motionMediaQuery.matches);
15
- motionMediaQuery.addListener(setReducedMotionPreferences);
16
- setReducedMotionPreferences();
17
- }
18
- else {
19
- prefersReducedMotion.current = false;
20
- }
21
- }
22
- /**
23
- * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
24
- *
25
- * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
26
- * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
27
- *
28
- * It will actively respond to changes and re-render your components with the latest setting.
29
- *
30
- * ```jsx
31
- * export function Sidebar({ isOpen }) {
32
- * const shouldReduceMotion = useReducedMotion()
33
- * const closedX = shouldReduceMotion ? 0 : "-100%"
34
- *
35
- * return (
36
- * <motion.div animate={{
37
- * opacity: isOpen ? 1 : 0,
38
- * x: isOpen ? 0 : closedX
39
- * }} />
40
- * )
41
- * }
42
- * ```
43
- *
44
- * @return boolean
45
- *
46
- * @public
47
- */
48
- function useReducedMotion() {
49
- /**
50
- * Lazy initialisation of prefersReducedMotion
51
- */
52
- !hasDetected && initPrefersReducedMotion();
53
- const [shouldReduceMotion] = useState(prefersReducedMotion.current);
54
- /**
55
- * TODO See if people miss automatically updating shouldReduceMotion setting
56
- */
57
- return shouldReduceMotion;
58
- }
59
- function useReducedMotionConfig() {
60
- const reducedMotionPreference = useReducedMotion();
61
- const { reducedMotion } = useContext(MotionConfigContext);
62
- if (reducedMotion === "never") {
63
- return false;
64
- }
65
- else if (reducedMotion === "always") {
66
- return true;
67
- }
68
- else {
69
- return reducedMotionPreference;
70
- }
71
- }
72
-
73
- export { useReducedMotion, useReducedMotionConfig };