framer-motion 6.1.0 → 6.2.4

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 CHANGED
@@ -120,6 +120,7 @@ function useFeatures(props, visualElement, preloadedFeatures) {
120
120
  var MotionConfigContext = React.createContext({
121
121
  transformPagePoint: function (p) { return p; },
122
122
  isStatic: false,
123
+ reducedMotion: "never",
123
124
  });
124
125
 
125
126
  var MotionContext = React.createContext({});
@@ -136,10 +137,81 @@ var isBrowser = typeof window !== "undefined";
136
137
 
137
138
  var useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
138
139
 
140
+ // Does this device prefer reduced motion? Returns `null` server-side.
141
+ var prefersReducedMotion = { current: null };
142
+ var hasDetected = false;
143
+ function initPrefersReducedMotion() {
144
+ hasDetected = true;
145
+ if (typeof window === "undefined")
146
+ return;
147
+ if (window.matchMedia) {
148
+ var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
149
+ var setReducedMotionPreferences = function () {
150
+ return (prefersReducedMotion.current = motionMediaQuery_1.matches);
151
+ };
152
+ motionMediaQuery_1.addListener(setReducedMotionPreferences);
153
+ setReducedMotionPreferences();
154
+ }
155
+ else {
156
+ prefersReducedMotion.current = false;
157
+ }
158
+ }
159
+ /**
160
+ * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
161
+ *
162
+ * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
163
+ * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
164
+ *
165
+ * It will actively respond to changes and re-render your components with the latest setting.
166
+ *
167
+ * ```jsx
168
+ * export function Sidebar({ isOpen }) {
169
+ * const shouldReduceMotion = useReducedMotion()
170
+ * const closedX = shouldReduceMotion ? 0 : "-100%"
171
+ *
172
+ * return (
173
+ * <motion.div animate={{
174
+ * opacity: isOpen ? 1 : 0,
175
+ * x: isOpen ? 0 : closedX
176
+ * }} />
177
+ * )
178
+ * }
179
+ * ```
180
+ *
181
+ * @return boolean
182
+ *
183
+ * @public
184
+ */
185
+ function useReducedMotion() {
186
+ /**
187
+ * Lazy initialisation of prefersReducedMotion
188
+ */
189
+ !hasDetected && initPrefersReducedMotion();
190
+ var _a = tslib.__read(React.useState(prefersReducedMotion.current), 1), shouldReduceMotion = _a[0];
191
+ /**
192
+ * TODO See if people miss automatically updating shouldReduceMotion setting
193
+ */
194
+ return shouldReduceMotion;
195
+ }
196
+ function useReducedMotionConfig() {
197
+ var reducedMotionPreference = useReducedMotion();
198
+ var reducedMotion = React.useContext(MotionConfigContext).reducedMotion;
199
+ if (reducedMotion === "never") {
200
+ return false;
201
+ }
202
+ else if (reducedMotion === "always") {
203
+ return true;
204
+ }
205
+ else {
206
+ return reducedMotionPreference;
207
+ }
208
+ }
209
+
139
210
  function useVisualElement(Component, visualState, props, createVisualElement) {
140
211
  var lazyContext = React.useContext(LazyContext);
141
212
  var parent = useVisualElementContext();
142
213
  var presenceContext = React.useContext(PresenceContext);
214
+ var shouldReduceMotion = useReducedMotionConfig();
143
215
  var visualElementRef = React.useRef(undefined);
144
216
  /**
145
217
  * If we haven't preloaded a renderer, check to see if we have one lazy-loaded
@@ -153,6 +225,7 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
153
225
  props: props,
154
226
  presenceId: presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id,
155
227
  blockInitialAnimation: (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false,
228
+ shouldReduceMotion: shouldReduceMotion,
156
229
  });
157
230
  }
158
231
  var visualElement = visualElementRef.current;
@@ -1824,9 +1897,6 @@ function createProjectionNode(_a) {
1824
1897
  };
1825
1898
  this.hasProjected = false;
1826
1899
  this.isVisible = true;
1827
- /**
1828
- * Animation
1829
- */
1830
1900
  this.animationProgress = 0;
1831
1901
  /**
1832
1902
  * Shared layout
@@ -1943,9 +2013,23 @@ function createProjectionNode(_a) {
1943
2013
  _this.resumingFrom.resumingFrom = undefined;
1944
2014
  }
1945
2015
  _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
1946
- _this.startAnimation(tslib.__assign(tslib.__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
2016
+ var animationOptions = tslib.__assign(tslib.__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete });
2017
+ if (visualElement.shouldReduceMotion) {
2018
+ animationOptions.delay = 0;
2019
+ animationOptions.type = false;
2020
+ }
2021
+ _this.startAnimation(animationOptions);
1947
2022
  }
1948
2023
  else {
2024
+ /**
2025
+ * If the layout hasn't changed and we have an animation that hasn't started yet,
2026
+ * finish it immediately. Otherwise it will be animating from a location
2027
+ * that was probably never commited to screen and look like a jumpy box.
2028
+ */
2029
+ if (!hasLayoutChanged &&
2030
+ _this.animationProgress === 0) {
2031
+ _this.finishAnimation();
2032
+ }
1949
2033
  _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
1950
2034
  }
1951
2035
  _this.targetLayout = newLayout;
@@ -2435,6 +2519,7 @@ function createProjectionNode(_a) {
2435
2519
  !isOnlyMember &&
2436
2520
  this.options.crossfade === true &&
2437
2521
  !this.path.some(hasOpacityCrossfade));
2522
+ this.animationProgress = 0;
2438
2523
  this.mixTargetDelta = function (latest) {
2439
2524
  var _a;
2440
2525
  var progress = latest / 1000;
@@ -2454,6 +2539,7 @@ function createProjectionNode(_a) {
2454
2539
  }
2455
2540
  _this.root.scheduleUpdateProjection();
2456
2541
  _this.scheduleRender();
2542
+ _this.animationProgress = progress;
2457
2543
  };
2458
2544
  this.mixTargetDelta(0);
2459
2545
  };
@@ -2819,6 +2905,10 @@ function clearMeasurements(node) {
2819
2905
  node.clearMeasurements();
2820
2906
  }
2821
2907
  function resetTransformStyle(node) {
2908
+ var visualElement = node.options.visualElement;
2909
+ if (visualElement === null || visualElement === void 0 ? void 0 : visualElement.getProps().onBeforeLayoutMeasure) {
2910
+ visualElement.notifyBeforeLayoutMeasure();
2911
+ }
2822
2912
  node.resetTransform();
2823
2913
  }
2824
2914
  function finishAnimation(node) {
@@ -4572,7 +4662,14 @@ function animateTarget(visualElement, definition, _a) {
4572
4662
  shouldBlockAnimation(animationTypeState, key))) {
4573
4663
  continue;
4574
4664
  }
4575
- var animation = startAnimation(key, value, valueTarget, tslib.__assign({ delay: delay }, transition));
4665
+ var valueTransition = tslib.__assign({ delay: delay }, transition);
4666
+ /**
4667
+ * Make animation instant if this is a transform prop and we should reduce motion.
4668
+ */
4669
+ if (visualElement.shouldReduceMotion && isTransformProp(key)) {
4670
+ valueTransition = tslib.__assign(tslib.__assign({}, valueTransition), { type: false, delay: 0 });
4671
+ }
4672
+ var animation = startAnimation(key, value, valueTarget, valueTransition);
4576
4673
  animations.push(animation);
4577
4674
  }
4578
4675
  return Promise.all(animations).then(function () {
@@ -5818,7 +5915,7 @@ function createLifecycles() {
5818
5915
  for (var _i = 0; _i < arguments.length; _i++) {
5819
5916
  args[_i] = arguments[_i];
5820
5917
  }
5821
- manager.notify.apply(manager, tslib.__spreadArray([], tslib.__read(args), false));
5918
+ return manager.notify.apply(manager, tslib.__spreadArray([], tslib.__read(args), false));
5822
5919
  };
5823
5920
  });
5824
5921
  return lifecycles;
@@ -5870,7 +5967,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5870
5967
  var visualElement = function (_a) {
5871
5968
  var _b = _a.treeType, treeType = _b === void 0 ? "" : _b, build = _a.build, getBaseTarget = _a.getBaseTarget, makeTargetAnimatable = _a.makeTargetAnimatable, measureViewportBox = _a.measureViewportBox, renderInstance = _a.render, readValueFromInstance = _a.readValueFromInstance, removeValueFromRenderState = _a.removeValueFromRenderState, sortNodePosition = _a.sortNodePosition, scrapeMotionValuesFromProps = _a.scrapeMotionValuesFromProps;
5872
5969
  return function (_a, options) {
5873
- var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState;
5970
+ var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState, shouldReduceMotion = _a.shouldReduceMotion;
5874
5971
  if (options === void 0) { options = {}; }
5875
5972
  var isMounted = false;
5876
5973
  var latestValues = visualState.latestValues, renderState = visualState.renderState;
@@ -5979,7 +6076,7 @@ var visualElement = function (_a) {
5979
6076
  /**
5980
6077
  *
5981
6078
  */
5982
- presenceId: presenceId,
6079
+ presenceId: presenceId, shouldReduceMotion: shouldReduceMotion,
5983
6080
  /**
5984
6081
  * If this component is part of the variant tree, it should track
5985
6082
  * any children that are also part of the tree. This is essentially
@@ -7875,60 +7972,6 @@ function useTime() {
7875
7972
  return time;
7876
7973
  }
7877
7974
 
7878
- // Does this device prefer reduced motion? Returns `null` server-side.
7879
- var prefersReducedMotion;
7880
- function initPrefersReducedMotion() {
7881
- prefersReducedMotion = motionValue(null);
7882
- if (typeof window === "undefined")
7883
- return;
7884
- if (window.matchMedia) {
7885
- var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
7886
- var setReducedMotionPreferences = function () {
7887
- return prefersReducedMotion.set(motionMediaQuery_1.matches);
7888
- };
7889
- motionMediaQuery_1.addListener(setReducedMotionPreferences);
7890
- setReducedMotionPreferences();
7891
- }
7892
- else {
7893
- prefersReducedMotion.set(false);
7894
- }
7895
- }
7896
- /**
7897
- * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
7898
- *
7899
- * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
7900
- * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
7901
- *
7902
- * It will actively respond to changes and re-render your components with the latest setting.
7903
- *
7904
- * ```jsx
7905
- * export function Sidebar({ isOpen }) {
7906
- * const shouldReduceMotion = useReducedMotion()
7907
- * const closedX = shouldReduceMotion ? 0 : "-100%"
7908
- *
7909
- * return (
7910
- * <motion.div animate={{
7911
- * opacity: isOpen ? 1 : 0,
7912
- * x: isOpen ? 0 : closedX
7913
- * }} />
7914
- * )
7915
- * }
7916
- * ```
7917
- *
7918
- * @return boolean
7919
- *
7920
- * @public
7921
- */
7922
- function useReducedMotion() {
7923
- /**
7924
- * Lazy initialisation of prefersReducedMotion
7925
- */
7926
- !prefersReducedMotion && initPrefersReducedMotion();
7927
- var _a = tslib.__read(React.useState(prefersReducedMotion.get()), 2), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
7928
- useOnChange(prefersReducedMotion, setShouldReduceMotion);
7929
- return shouldReduceMotion;
7930
- }
7931
-
7932
7975
  /**
7933
7976
  * @public
7934
7977
  */
@@ -8363,6 +8406,7 @@ exports.useMotionTemplate = useMotionTemplate;
8363
8406
  exports.useMotionValue = useMotionValue;
8364
8407
  exports.usePresence = usePresence;
8365
8408
  exports.useReducedMotion = useReducedMotion;
8409
+ exports.useReducedMotionConfig = useReducedMotionConfig;
8366
8410
  exports.useResetProjection = useResetProjection;
8367
8411
  exports.useSpring = useSpring;
8368
8412
  exports.useTime = useTime;
@@ -6,6 +6,7 @@ import { createContext } from 'react';
6
6
  var MotionConfigContext = createContext({
7
7
  transformPagePoint: function (p) { return p; },
8
8
  isStatic: false,
9
+ reducedMotion: "never",
9
10
  });
10
11
 
11
12
  export { MotionConfigContext };
package/dist/es/index.mjs CHANGED
@@ -18,7 +18,7 @@ export { useVelocity } from './value/use-velocity.mjs';
18
18
  export { useElementScroll } from './value/scroll/use-element-scroll.mjs';
19
19
  export { useViewportScroll } from './value/scroll/use-viewport-scroll.mjs';
20
20
  export { useTime } from './value/use-time.mjs';
21
- export { useReducedMotion } from './utils/use-reduced-motion.mjs';
21
+ export { useReducedMotion, useReducedMotionConfig } from './utils/use-reduced-motion.mjs';
22
22
  export { animationControls } from './animation/animation-controls.mjs';
23
23
  export { useAnimation } from './animation/use-animation.mjs';
24
24
  export { useAnimationFrame } from './utils/use-animation-frame.mjs';
@@ -3,11 +3,13 @@ import { PresenceContext } from '../../context/PresenceContext.mjs';
3
3
  import { useVisualElementContext } from '../../context/MotionContext/index.mjs';
4
4
  import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
5
5
  import { LazyContext } from '../../context/LazyContext.mjs';
6
+ import { useReducedMotionConfig } from '../../utils/use-reduced-motion.mjs';
6
7
 
7
8
  function useVisualElement(Component, visualState, props, createVisualElement) {
8
9
  var lazyContext = useContext(LazyContext);
9
10
  var parent = useVisualElementContext();
10
11
  var presenceContext = useContext(PresenceContext);
12
+ var shouldReduceMotion = useReducedMotionConfig();
11
13
  var visualElementRef = useRef(undefined);
12
14
  /**
13
15
  * If we haven't preloaded a renderer, check to see if we have one lazy-loaded
@@ -21,6 +23,7 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
21
23
  props: props,
22
24
  presenceId: presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id,
23
25
  blockInitialAnimation: (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false,
26
+ shouldReduceMotion: shouldReduceMotion,
24
27
  });
25
28
  }
26
29
  var visualElement = visualElementRef.current;
@@ -125,9 +125,6 @@ function createProjectionNode(_a) {
125
125
  };
126
126
  this.hasProjected = false;
127
127
  this.isVisible = true;
128
- /**
129
- * Animation
130
- */
131
128
  this.animationProgress = 0;
132
129
  /**
133
130
  * Shared layout
@@ -244,9 +241,23 @@ function createProjectionNode(_a) {
244
241
  _this.resumingFrom.resumingFrom = undefined;
245
242
  }
246
243
  _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
247
- _this.startAnimation(__assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
244
+ var animationOptions = __assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete });
245
+ if (visualElement.shouldReduceMotion) {
246
+ animationOptions.delay = 0;
247
+ animationOptions.type = false;
248
+ }
249
+ _this.startAnimation(animationOptions);
248
250
  }
249
251
  else {
252
+ /**
253
+ * If the layout hasn't changed and we have an animation that hasn't started yet,
254
+ * finish it immediately. Otherwise it will be animating from a location
255
+ * that was probably never commited to screen and look like a jumpy box.
256
+ */
257
+ if (!hasLayoutChanged &&
258
+ _this.animationProgress === 0) {
259
+ _this.finishAnimation();
260
+ }
250
261
  _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
251
262
  }
252
263
  _this.targetLayout = newLayout;
@@ -736,6 +747,7 @@ function createProjectionNode(_a) {
736
747
  !isOnlyMember &&
737
748
  this.options.crossfade === true &&
738
749
  !this.path.some(hasOpacityCrossfade));
750
+ this.animationProgress = 0;
739
751
  this.mixTargetDelta = function (latest) {
740
752
  var _a;
741
753
  var progress = latest / 1000;
@@ -755,6 +767,7 @@ function createProjectionNode(_a) {
755
767
  }
756
768
  _this.root.scheduleUpdateProjection();
757
769
  _this.scheduleRender();
770
+ _this.animationProgress = progress;
758
771
  };
759
772
  this.mixTargetDelta(0);
760
773
  };
@@ -1120,6 +1133,10 @@ function clearMeasurements(node) {
1120
1133
  node.clearMeasurements();
1121
1134
  }
1122
1135
  function resetTransformStyle(node) {
1136
+ var visualElement = node.options.visualElement;
1137
+ if (visualElement === null || visualElement === void 0 ? void 0 : visualElement.getProps().onBeforeLayoutMeasure) {
1138
+ visualElement.notifyBeforeLayoutMeasure();
1139
+ }
1123
1140
  node.resetTransform();
1124
1141
  }
1125
1142
  function finishAnimation(node) {
@@ -10,7 +10,7 @@ import { checkIfControllingVariants, checkIfVariantNode, isVariantLabel } from '
10
10
  var visualElement = function (_a) {
11
11
  var _b = _a.treeType, treeType = _b === void 0 ? "" : _b, build = _a.build, getBaseTarget = _a.getBaseTarget, makeTargetAnimatable = _a.makeTargetAnimatable, measureViewportBox = _a.measureViewportBox, renderInstance = _a.render, readValueFromInstance = _a.readValueFromInstance, removeValueFromRenderState = _a.removeValueFromRenderState, sortNodePosition = _a.sortNodePosition, scrapeMotionValuesFromProps = _a.scrapeMotionValuesFromProps;
12
12
  return function (_a, options) {
13
- var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState;
13
+ var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState, shouldReduceMotion = _a.shouldReduceMotion;
14
14
  if (options === void 0) { options = {}; }
15
15
  var isMounted = false;
16
16
  var latestValues = visualState.latestValues, renderState = visualState.renderState;
@@ -119,7 +119,7 @@ var visualElement = function (_a) {
119
119
  /**
120
120
  *
121
121
  */
122
- presenceId: presenceId,
122
+ presenceId: presenceId, shouldReduceMotion: shouldReduceMotion,
123
123
  /**
124
124
  * If this component is part of the variant tree, it should track
125
125
  * any children that are also part of the tree. This is essentially
@@ -2,6 +2,7 @@ import { __read, __rest, __assign } from 'tslib';
2
2
  import { startAnimation } from '../../animation/utils/transitions.mjs';
3
3
  import { setTarget } from './setters.mjs';
4
4
  import { resolveVariant } from './variants.mjs';
5
+ import { isTransformProp } from '../html/utils/transform.mjs';
5
6
 
6
7
  /**
7
8
  * @internal
@@ -90,7 +91,14 @@ function animateTarget(visualElement, definition, _a) {
90
91
  shouldBlockAnimation(animationTypeState, key))) {
91
92
  continue;
92
93
  }
93
- var animation = startAnimation(key, value, valueTarget, __assign({ delay: delay }, transition));
94
+ var valueTransition = __assign({ delay: delay }, transition);
95
+ /**
96
+ * Make animation instant if this is a transform prop and we should reduce motion.
97
+ */
98
+ if (visualElement.shouldReduceMotion && isTransformProp(key)) {
99
+ valueTransition = __assign(__assign({}, valueTransition), { type: false, delay: 0 });
100
+ }
101
+ var animation = startAnimation(key, value, valueTarget, valueTransition);
94
102
  animations.push(animation);
95
103
  }
96
104
  return Promise.all(animations).then(function () {
@@ -40,7 +40,7 @@ function createLifecycles() {
40
40
  for (var _i = 0; _i < arguments.length; _i++) {
41
41
  args[_i] = arguments[_i];
42
42
  }
43
- manager.notify.apply(manager, __spreadArray([], __read(args), false));
43
+ return manager.notify.apply(manager, __spreadArray([], __read(args), false));
44
44
  };
45
45
  });
46
46
  return lifecycles;
@@ -1,24 +1,24 @@
1
1
  import { __read } from 'tslib';
2
- import { useState } from 'react';
3
- import { motionValue } from '../value/index.mjs';
4
- import { useOnChange } from '../value/use-on-change.mjs';
2
+ import { useState, useContext } from 'react';
3
+ import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
5
4
 
6
5
  // Does this device prefer reduced motion? Returns `null` server-side.
7
- var prefersReducedMotion;
6
+ var prefersReducedMotion = { current: null };
7
+ var hasDetected = false;
8
8
  function initPrefersReducedMotion() {
9
- prefersReducedMotion = motionValue(null);
9
+ hasDetected = true;
10
10
  if (typeof window === "undefined")
11
11
  return;
12
12
  if (window.matchMedia) {
13
13
  var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
14
14
  var setReducedMotionPreferences = function () {
15
- return prefersReducedMotion.set(motionMediaQuery_1.matches);
15
+ return (prefersReducedMotion.current = motionMediaQuery_1.matches);
16
16
  };
17
17
  motionMediaQuery_1.addListener(setReducedMotionPreferences);
18
18
  setReducedMotionPreferences();
19
19
  }
20
20
  else {
21
- prefersReducedMotion.set(false);
21
+ prefersReducedMotion.current = false;
22
22
  }
23
23
  }
24
24
  /**
@@ -51,10 +51,25 @@ function useReducedMotion() {
51
51
  /**
52
52
  * Lazy initialisation of prefersReducedMotion
53
53
  */
54
- !prefersReducedMotion && initPrefersReducedMotion();
55
- var _a = __read(useState(prefersReducedMotion.get()), 2), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
56
- useOnChange(prefersReducedMotion, setShouldReduceMotion);
54
+ !hasDetected && initPrefersReducedMotion();
55
+ var _a = __read(useState(prefersReducedMotion.current), 1), shouldReduceMotion = _a[0];
56
+ /**
57
+ * TODO See if people miss automatically updating shouldReduceMotion setting
58
+ */
57
59
  return shouldReduceMotion;
58
60
  }
61
+ function useReducedMotionConfig() {
62
+ var reducedMotionPreference = useReducedMotion();
63
+ var reducedMotion = useContext(MotionConfigContext).reducedMotion;
64
+ if (reducedMotion === "never") {
65
+ return false;
66
+ }
67
+ else if (reducedMotion === "always") {
68
+ return true;
69
+ }
70
+ else {
71
+ return reducedMotionPreference;
72
+ }
73
+ }
59
74
 
60
- export { useReducedMotion };
75
+ export { useReducedMotion, useReducedMotionConfig };