framer-motion 6.0.0 → 6.2.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 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;
@@ -1943,7 +2016,12 @@ function createProjectionNode(_a) {
1943
2016
  _this.resumingFrom.resumingFrom = undefined;
1944
2017
  }
1945
2018
  _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
1946
- _this.startAnimation(tslib.__assign(tslib.__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
2019
+ var animationOptions = tslib.__assign(tslib.__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete });
2020
+ if (visualElement.shouldReduceMotion) {
2021
+ animationOptions.delay = 0;
2022
+ animationOptions.type = false;
2023
+ }
2024
+ _this.startAnimation(animationOptions);
1947
2025
  }
1948
2026
  else {
1949
2027
  _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
@@ -4221,9 +4299,10 @@ function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
4221
4299
  * on mount. This way, the page will be in the state the author expects users
4222
4300
  * to see it in for everyone.
4223
4301
  */
4224
- function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
4302
+ function useMissingIntersectionObserver(shouldObserve, state, visualElement, _a) {
4303
+ var _b = _a.fallback, fallback = _b === void 0 ? true : _b;
4225
4304
  React.useEffect(function () {
4226
- if (!shouldObserve)
4305
+ if (!shouldObserve || !fallback)
4227
4306
  return;
4228
4307
  if (process.env.NODE_ENV !== "production") {
4229
4308
  warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
@@ -4571,7 +4650,14 @@ function animateTarget(visualElement, definition, _a) {
4571
4650
  shouldBlockAnimation(animationTypeState, key))) {
4572
4651
  continue;
4573
4652
  }
4574
- var animation = startAnimation(key, value, valueTarget, tslib.__assign({ delay: delay }, transition));
4653
+ var valueTransition = tslib.__assign({ delay: delay }, transition);
4654
+ /**
4655
+ * Make animation instant if this is a transform prop and we should reduce motion.
4656
+ */
4657
+ if (visualElement.shouldReduceMotion && isTransformProp(key)) {
4658
+ valueTransition = tslib.__assign(tslib.__assign({}, valueTransition), { type: false, delay: 0 });
4659
+ }
4660
+ var animation = startAnimation(key, value, valueTarget, valueTransition);
4575
4661
  animations.push(animation);
4576
4662
  }
4577
4663
  return Promise.all(animations).then(function () {
@@ -5869,7 +5955,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5869
5955
  var visualElement = function (_a) {
5870
5956
  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;
5871
5957
  return function (_a, options) {
5872
- var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState;
5958
+ var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState, shouldReduceMotion = _a.shouldReduceMotion;
5873
5959
  if (options === void 0) { options = {}; }
5874
5960
  var isMounted = false;
5875
5961
  var latestValues = visualState.latestValues, renderState = visualState.renderState;
@@ -5978,7 +6064,7 @@ var visualElement = function (_a) {
5978
6064
  /**
5979
6065
  *
5980
6066
  */
5981
- presenceId: presenceId,
6067
+ presenceId: presenceId, shouldReduceMotion: shouldReduceMotion,
5982
6068
  /**
5983
6069
  * If this component is part of the variant tree, it should track
5984
6070
  * any children that are also part of the tree. This is essentially
@@ -7874,60 +7960,6 @@ function useTime() {
7874
7960
  return time;
7875
7961
  }
7876
7962
 
7877
- // Does this device prefer reduced motion? Returns `null` server-side.
7878
- var prefersReducedMotion;
7879
- function initPrefersReducedMotion() {
7880
- prefersReducedMotion = motionValue(null);
7881
- if (typeof window === "undefined")
7882
- return;
7883
- if (window.matchMedia) {
7884
- var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
7885
- var setReducedMotionPreferences = function () {
7886
- return prefersReducedMotion.set(motionMediaQuery_1.matches);
7887
- };
7888
- motionMediaQuery_1.addListener(setReducedMotionPreferences);
7889
- setReducedMotionPreferences();
7890
- }
7891
- else {
7892
- prefersReducedMotion.set(false);
7893
- }
7894
- }
7895
- /**
7896
- * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
7897
- *
7898
- * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
7899
- * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
7900
- *
7901
- * It will actively respond to changes and re-render your components with the latest setting.
7902
- *
7903
- * ```jsx
7904
- * export function Sidebar({ isOpen }) {
7905
- * const shouldReduceMotion = useReducedMotion()
7906
- * const closedX = shouldReduceMotion ? 0 : "-100%"
7907
- *
7908
- * return (
7909
- * <motion.div animate={{
7910
- * opacity: isOpen ? 1 : 0,
7911
- * x: isOpen ? 0 : closedX
7912
- * }} />
7913
- * )
7914
- * }
7915
- * ```
7916
- *
7917
- * @return boolean
7918
- *
7919
- * @public
7920
- */
7921
- function useReducedMotion() {
7922
- /**
7923
- * Lazy initialisation of prefersReducedMotion
7924
- */
7925
- !prefersReducedMotion && initPrefersReducedMotion();
7926
- var _a = tslib.__read(React.useState(prefersReducedMotion.get()), 2), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
7927
- useOnChange(prefersReducedMotion, setShouldReduceMotion);
7928
- return shouldReduceMotion;
7929
- }
7930
-
7931
7963
  /**
7932
7964
  * @public
7933
7965
  */
@@ -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 };
@@ -69,9 +69,10 @@ function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
69
69
  * on mount. This way, the page will be in the state the author expects users
70
70
  * to see it in for everyone.
71
71
  */
72
- function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
72
+ function useMissingIntersectionObserver(shouldObserve, state, visualElement, _a) {
73
+ var _b = _a.fallback, fallback = _b === void 0 ? true : _b;
73
74
  useEffect(function () {
74
- if (!shouldObserve)
75
+ if (!shouldObserve || !fallback)
75
76
  return;
76
77
  if (process.env.NODE_ENV !== "production") {
77
78
  warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
@@ -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;
@@ -244,7 +244,12 @@ function createProjectionNode(_a) {
244
244
  _this.resumingFrom.resumingFrom = undefined;
245
245
  }
246
246
  _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
247
- _this.startAnimation(__assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
247
+ var animationOptions = __assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete });
248
+ if (visualElement.shouldReduceMotion) {
249
+ animationOptions.delay = 0;
250
+ animationOptions.type = false;
251
+ }
252
+ _this.startAnimation(animationOptions);
248
253
  }
249
254
  else {
250
255
  _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
@@ -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 () {
@@ -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 };
@@ -221,6 +221,7 @@
221
221
  var MotionConfigContext = React.createContext({
222
222
  transformPagePoint: function (p) { return p; },
223
223
  isStatic: false,
224
+ reducedMotion: "never",
224
225
  });
225
226
 
226
227
  var MotionContext = React.createContext({});
@@ -237,10 +238,81 @@
237
238
 
238
239
  var useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
239
240
 
241
+ // Does this device prefer reduced motion? Returns `null` server-side.
242
+ var prefersReducedMotion = { current: null };
243
+ var hasDetected = false;
244
+ function initPrefersReducedMotion() {
245
+ hasDetected = true;
246
+ if (typeof window === "undefined")
247
+ return;
248
+ if (window.matchMedia) {
249
+ var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
250
+ var setReducedMotionPreferences = function () {
251
+ return (prefersReducedMotion.current = motionMediaQuery_1.matches);
252
+ };
253
+ motionMediaQuery_1.addListener(setReducedMotionPreferences);
254
+ setReducedMotionPreferences();
255
+ }
256
+ else {
257
+ prefersReducedMotion.current = false;
258
+ }
259
+ }
260
+ /**
261
+ * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
262
+ *
263
+ * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
264
+ * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
265
+ *
266
+ * It will actively respond to changes and re-render your components with the latest setting.
267
+ *
268
+ * ```jsx
269
+ * export function Sidebar({ isOpen }) {
270
+ * const shouldReduceMotion = useReducedMotion()
271
+ * const closedX = shouldReduceMotion ? 0 : "-100%"
272
+ *
273
+ * return (
274
+ * <motion.div animate={{
275
+ * opacity: isOpen ? 1 : 0,
276
+ * x: isOpen ? 0 : closedX
277
+ * }} />
278
+ * )
279
+ * }
280
+ * ```
281
+ *
282
+ * @return boolean
283
+ *
284
+ * @public
285
+ */
286
+ function useReducedMotion() {
287
+ /**
288
+ * Lazy initialisation of prefersReducedMotion
289
+ */
290
+ !hasDetected && initPrefersReducedMotion();
291
+ var _a = __read(React.useState(prefersReducedMotion.current), 1), shouldReduceMotion = _a[0];
292
+ /**
293
+ * TODO See if people miss automatically updating shouldReduceMotion setting
294
+ */
295
+ return shouldReduceMotion;
296
+ }
297
+ function useReducedMotionConfig() {
298
+ var reducedMotionPreference = useReducedMotion();
299
+ var reducedMotion = React.useContext(MotionConfigContext).reducedMotion;
300
+ if (reducedMotion === "never") {
301
+ return false;
302
+ }
303
+ else if (reducedMotion === "always") {
304
+ return true;
305
+ }
306
+ else {
307
+ return reducedMotionPreference;
308
+ }
309
+ }
310
+
240
311
  function useVisualElement(Component, visualState, props, createVisualElement) {
241
312
  var lazyContext = React.useContext(LazyContext);
242
313
  var parent = useVisualElementContext();
243
314
  var presenceContext = React.useContext(PresenceContext);
315
+ var shouldReduceMotion = useReducedMotionConfig();
244
316
  var visualElementRef = React.useRef(undefined);
245
317
  /**
246
318
  * If we haven't preloaded a renderer, check to see if we have one lazy-loaded
@@ -254,6 +326,7 @@
254
326
  props: props,
255
327
  presenceId: presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id,
256
328
  blockInitialAnimation: (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false,
329
+ shouldReduceMotion: shouldReduceMotion,
257
330
  });
258
331
  }
259
332
  var visualElement = visualElementRef.current;
@@ -3176,7 +3249,12 @@
3176
3249
  _this.resumingFrom.resumingFrom = undefined;
3177
3250
  }
3178
3251
  _this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
3179
- _this.startAnimation(__assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete }));
3252
+ var animationOptions = __assign(__assign({}, getValueTransition(layoutTransition, "layout")), { onComplete: onLayoutAnimationComplete });
3253
+ if (visualElement.shouldReduceMotion) {
3254
+ animationOptions.delay = 0;
3255
+ animationOptions.type = false;
3256
+ }
3257
+ _this.startAnimation(animationOptions);
3180
3258
  }
3181
3259
  else {
3182
3260
  _this.isLead() && ((_f = (_e = _this.options).onExitComplete) === null || _f === void 0 ? void 0 : _f.call(_e));
@@ -5454,9 +5532,10 @@
5454
5532
  * on mount. This way, the page will be in the state the author expects users
5455
5533
  * to see it in for everyone.
5456
5534
  */
5457
- function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
5535
+ function useMissingIntersectionObserver(shouldObserve, state, visualElement, _a) {
5536
+ var _b = _a.fallback, fallback = _b === void 0 ? true : _b;
5458
5537
  React.useEffect(function () {
5459
- if (!shouldObserve)
5538
+ if (!shouldObserve || !fallback)
5460
5539
  return;
5461
5540
  {
5462
5541
  warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
@@ -5804,7 +5883,14 @@
5804
5883
  shouldBlockAnimation(animationTypeState, key))) {
5805
5884
  continue;
5806
5885
  }
5807
- var animation = startAnimation(key, value, valueTarget, __assign({ delay: delay }, transition));
5886
+ var valueTransition = __assign({ delay: delay }, transition);
5887
+ /**
5888
+ * Make animation instant if this is a transform prop and we should reduce motion.
5889
+ */
5890
+ if (visualElement.shouldReduceMotion && isTransformProp(key)) {
5891
+ valueTransition = __assign(__assign({}, valueTransition), { type: false, delay: 0 });
5892
+ }
5893
+ var animation = startAnimation(key, value, valueTarget, valueTransition);
5808
5894
  animations.push(animation);
5809
5895
  }
5810
5896
  return Promise.all(animations).then(function () {
@@ -7102,7 +7188,7 @@
7102
7188
  var visualElement = function (_a) {
7103
7189
  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;
7104
7190
  return function (_a, options) {
7105
- var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState;
7191
+ var parent = _a.parent, props = _a.props, presenceId = _a.presenceId, blockInitialAnimation = _a.blockInitialAnimation, visualState = _a.visualState, shouldReduceMotion = _a.shouldReduceMotion;
7106
7192
  if (options === void 0) { options = {}; }
7107
7193
  var isMounted = false;
7108
7194
  var latestValues = visualState.latestValues, renderState = visualState.renderState;
@@ -7211,7 +7297,7 @@
7211
7297
  /**
7212
7298
  *
7213
7299
  */
7214
- presenceId: presenceId,
7300
+ presenceId: presenceId, shouldReduceMotion: shouldReduceMotion,
7215
7301
  /**
7216
7302
  * If this component is part of the variant tree, it should track
7217
7303
  * any children that are also part of the tree. This is essentially
@@ -9106,60 +9192,6 @@
9106
9192
  return time;
9107
9193
  }
9108
9194
 
9109
- // Does this device prefer reduced motion? Returns `null` server-side.
9110
- var prefersReducedMotion;
9111
- function initPrefersReducedMotion() {
9112
- prefersReducedMotion = motionValue(null);
9113
- if (typeof window === "undefined")
9114
- return;
9115
- if (window.matchMedia) {
9116
- var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
9117
- var setReducedMotionPreferences = function () {
9118
- return prefersReducedMotion.set(motionMediaQuery_1.matches);
9119
- };
9120
- motionMediaQuery_1.addListener(setReducedMotionPreferences);
9121
- setReducedMotionPreferences();
9122
- }
9123
- else {
9124
- prefersReducedMotion.set(false);
9125
- }
9126
- }
9127
- /**
9128
- * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
9129
- *
9130
- * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
9131
- * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
9132
- *
9133
- * It will actively respond to changes and re-render your components with the latest setting.
9134
- *
9135
- * ```jsx
9136
- * export function Sidebar({ isOpen }) {
9137
- * const shouldReduceMotion = useReducedMotion()
9138
- * const closedX = shouldReduceMotion ? 0 : "-100%"
9139
- *
9140
- * return (
9141
- * <motion.div animate={{
9142
- * opacity: isOpen ? 1 : 0,
9143
- * x: isOpen ? 0 : closedX
9144
- * }} />
9145
- * )
9146
- * }
9147
- * ```
9148
- *
9149
- * @return boolean
9150
- *
9151
- * @public
9152
- */
9153
- function useReducedMotion() {
9154
- /**
9155
- * Lazy initialisation of prefersReducedMotion
9156
- */
9157
- !prefersReducedMotion && initPrefersReducedMotion();
9158
- var _a = __read(React.useState(prefersReducedMotion.get()), 2), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
9159
- useOnChange(prefersReducedMotion, setShouldReduceMotion);
9160
- return shouldReduceMotion;
9161
- }
9162
-
9163
9195
  /**
9164
9196
  * @public
9165
9197
  */