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 +92 -60
- package/dist/es/context/MotionConfigContext.mjs +1 -0
- package/dist/es/motion/features/viewport/use-viewport.mjs +3 -2
- package/dist/es/motion/utils/use-visual-element.mjs +3 -0
- package/dist/es/projection/node/create-projection-node.mjs +6 -1
- package/dist/es/render/index.mjs +2 -2
- package/dist/es/render/utils/animation.mjs +9 -1
- package/dist/es/utils/use-reduced-motion.mjs +26 -11
- package/dist/framer-motion.dev.js +92 -60
- package/dist/framer-motion.js +1 -1
- package/dist/projection.dev.js +8 -3
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-webpack-dom-animation.js +1 -1
- package/dist/size-webpack-dom-max.js +1 -1
- package/dist/size-webpack-m.js +1 -1
- package/package.json +18 -11
- package/types/context/MotionConfigContext.d.ts +7 -0
- package/types/motion/features/viewport/types.d.ts +1 -0
- package/types/render/html/visual-element.d.ts +1 -1
- package/types/render/index.d.ts +1 -1
- package/types/render/svg/visual-element.d.ts +1 -1
- package/types/render/types.d.ts +2 -0
- package/types/utils/use-reduced-motion.d.ts +1 -0
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
|
-
|
|
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
|
|
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
|
*/
|
|
@@ -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
|
-
|
|
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));
|
package/dist/es/render/index.mjs
CHANGED
|
@@ -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
|
|
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 {
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
!
|
|
55
|
-
var _a = __read(useState(prefersReducedMotion.
|
|
56
|
-
|
|
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
|
-
|
|
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
|
|
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
|
*/
|