framer-motion 11.16.7 → 11.17.0
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/client.js +8 -5
- package/dist/cjs/dom.js +2 -2
- package/dist/cjs/index.js +226 -220
- package/dist/dom.js +1 -1
- package/dist/es/components/AnimatePresence/index.mjs +10 -7
- package/dist/es/components/AnimatePresence/use-presence.mjs +6 -3
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +279 -273
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +6 -9
- package/package.json +2 -2
package/dist/cjs/client.js
CHANGED
|
@@ -409,7 +409,7 @@ class MotionValue {
|
|
|
409
409
|
* This will be replaced by the build step with the latest version number.
|
|
410
410
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
411
411
|
*/
|
|
412
|
-
this.version = "11.
|
|
412
|
+
this.version = "11.17.0";
|
|
413
413
|
/**
|
|
414
414
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
415
415
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -5201,7 +5201,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
5201
5201
|
* and warn against mismatches.
|
|
5202
5202
|
*/
|
|
5203
5203
|
if (process.env.NODE_ENV === "development") {
|
|
5204
|
-
warnOnce(nextValue.version === "11.
|
|
5204
|
+
warnOnce(nextValue.version === "11.17.0", `Attempting to mix Motion versions ${nextValue.version} with 11.17.0 may not work as expected.`);
|
|
5205
5205
|
}
|
|
5206
5206
|
}
|
|
5207
5207
|
else if (isMotionValue(prevValue)) {
|
|
@@ -8204,7 +8204,7 @@ const PresenceContext = react.createContext(null);
|
|
|
8204
8204
|
*
|
|
8205
8205
|
* @public
|
|
8206
8206
|
*/
|
|
8207
|
-
function usePresence() {
|
|
8207
|
+
function usePresence(subscribe = true) {
|
|
8208
8208
|
const context = react.useContext(PresenceContext);
|
|
8209
8209
|
if (context === null)
|
|
8210
8210
|
return [true, null];
|
|
@@ -8212,8 +8212,11 @@ function usePresence() {
|
|
|
8212
8212
|
// It's safe to call the following hooks conditionally (after an early return) because the context will always
|
|
8213
8213
|
// either be null or non-null for the lifespan of the component.
|
|
8214
8214
|
const id = react.useId();
|
|
8215
|
-
react.useEffect(() =>
|
|
8216
|
-
|
|
8215
|
+
react.useEffect(() => {
|
|
8216
|
+
if (subscribe)
|
|
8217
|
+
register(id);
|
|
8218
|
+
}, [subscribe]);
|
|
8219
|
+
const safeToRemove = react.useCallback(() => subscribe && onExitComplete && onExitComplete(id), [id, onExitComplete, subscribe]);
|
|
8217
8220
|
return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
|
|
8218
8221
|
}
|
|
8219
8222
|
|
package/dist/cjs/dom.js
CHANGED
|
@@ -994,7 +994,7 @@ class MotionValue {
|
|
|
994
994
|
* This will be replaced by the build step with the latest version number.
|
|
995
995
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
996
996
|
*/
|
|
997
|
-
this.version = "11.
|
|
997
|
+
this.version = "11.17.0";
|
|
998
998
|
/**
|
|
999
999
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
1000
1000
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -3924,7 +3924,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
3924
3924
|
* and warn against mismatches.
|
|
3925
3925
|
*/
|
|
3926
3926
|
if (process.env.NODE_ENV === "development") {
|
|
3927
|
-
warnOnce(nextValue.version === "11.
|
|
3927
|
+
warnOnce(nextValue.version === "11.17.0", `Attempting to mix Motion versions ${nextValue.version} with 11.17.0 may not work as expected.`);
|
|
3928
3928
|
}
|
|
3929
3929
|
}
|
|
3930
3930
|
else if (isMotionValue(prevValue)) {
|
package/dist/cjs/index.js
CHANGED
|
@@ -26,157 +26,6 @@ function _interopNamespaceDefault(e) {
|
|
|
26
26
|
|
|
27
27
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
* @public
|
|
31
|
-
*/
|
|
32
|
-
const PresenceContext = React.createContext(null);
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Creates a constant value over the lifecycle of a component.
|
|
36
|
-
*
|
|
37
|
-
* Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
|
|
38
|
-
* a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
|
|
39
|
-
* you can ensure that initialisers don't execute twice or more.
|
|
40
|
-
*/
|
|
41
|
-
function useConstant(init) {
|
|
42
|
-
const ref = React.useRef(null);
|
|
43
|
-
if (ref.current === null) {
|
|
44
|
-
ref.current = init();
|
|
45
|
-
}
|
|
46
|
-
return ref.current;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @public
|
|
51
|
-
*/
|
|
52
|
-
const MotionConfigContext = React.createContext({
|
|
53
|
-
transformPagePoint: (p) => p,
|
|
54
|
-
isStatic: false,
|
|
55
|
-
reducedMotion: "never",
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Measurement functionality has to be within a separate component
|
|
60
|
-
* to leverage snapshot lifecycle.
|
|
61
|
-
*/
|
|
62
|
-
class PopChildMeasure extends React__namespace.Component {
|
|
63
|
-
getSnapshotBeforeUpdate(prevProps) {
|
|
64
|
-
const element = this.props.childRef.current;
|
|
65
|
-
if (element && prevProps.isPresent && !this.props.isPresent) {
|
|
66
|
-
const size = this.props.sizeRef.current;
|
|
67
|
-
size.height = element.offsetHeight || 0;
|
|
68
|
-
size.width = element.offsetWidth || 0;
|
|
69
|
-
size.top = element.offsetTop;
|
|
70
|
-
size.left = element.offsetLeft;
|
|
71
|
-
}
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Required with getSnapshotBeforeUpdate to stop React complaining.
|
|
76
|
-
*/
|
|
77
|
-
componentDidUpdate() { }
|
|
78
|
-
render() {
|
|
79
|
-
return this.props.children;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
function PopChild({ children, isPresent }) {
|
|
83
|
-
const id = React.useId();
|
|
84
|
-
const ref = React.useRef(null);
|
|
85
|
-
const size = React.useRef({
|
|
86
|
-
width: 0,
|
|
87
|
-
height: 0,
|
|
88
|
-
top: 0,
|
|
89
|
-
left: 0,
|
|
90
|
-
});
|
|
91
|
-
const { nonce } = React.useContext(MotionConfigContext);
|
|
92
|
-
/**
|
|
93
|
-
* We create and inject a style block so we can apply this explicit
|
|
94
|
-
* sizing in a non-destructive manner by just deleting the style block.
|
|
95
|
-
*
|
|
96
|
-
* We can't apply size via render as the measurement happens
|
|
97
|
-
* in getSnapshotBeforeUpdate (post-render), likewise if we apply the
|
|
98
|
-
* styles directly on the DOM node, we might be overwriting
|
|
99
|
-
* styles set via the style prop.
|
|
100
|
-
*/
|
|
101
|
-
React.useInsertionEffect(() => {
|
|
102
|
-
const { width, height, top, left } = size.current;
|
|
103
|
-
if (isPresent || !ref.current || !width || !height)
|
|
104
|
-
return;
|
|
105
|
-
ref.current.dataset.motionPopId = id;
|
|
106
|
-
const style = document.createElement("style");
|
|
107
|
-
if (nonce)
|
|
108
|
-
style.nonce = nonce;
|
|
109
|
-
document.head.appendChild(style);
|
|
110
|
-
if (style.sheet) {
|
|
111
|
-
style.sheet.insertRule(`
|
|
112
|
-
[data-motion-pop-id="${id}"] {
|
|
113
|
-
position: absolute !important;
|
|
114
|
-
width: ${width}px !important;
|
|
115
|
-
height: ${height}px !important;
|
|
116
|
-
top: ${top}px !important;
|
|
117
|
-
left: ${left}px !important;
|
|
118
|
-
}
|
|
119
|
-
`);
|
|
120
|
-
}
|
|
121
|
-
return () => {
|
|
122
|
-
document.head.removeChild(style);
|
|
123
|
-
};
|
|
124
|
-
}, [isPresent]);
|
|
125
|
-
return (jsxRuntime.jsx(PopChildMeasure, { isPresent: isPresent, childRef: ref, sizeRef: size, children: React__namespace.cloneElement(children, { ref }) }));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, presenceAffectsLayout, mode, }) => {
|
|
129
|
-
const presenceChildren = useConstant(newChildrenMap);
|
|
130
|
-
const id = React.useId();
|
|
131
|
-
const memoizedOnExitComplete = React.useCallback((childId) => {
|
|
132
|
-
presenceChildren.set(childId, true);
|
|
133
|
-
for (const isComplete of presenceChildren.values()) {
|
|
134
|
-
if (!isComplete)
|
|
135
|
-
return; // can stop searching when any is incomplete
|
|
136
|
-
}
|
|
137
|
-
onExitComplete && onExitComplete();
|
|
138
|
-
}, [presenceChildren, onExitComplete]);
|
|
139
|
-
const context = React.useMemo(() => ({
|
|
140
|
-
id,
|
|
141
|
-
initial,
|
|
142
|
-
isPresent,
|
|
143
|
-
custom,
|
|
144
|
-
onExitComplete: memoizedOnExitComplete,
|
|
145
|
-
register: (childId) => {
|
|
146
|
-
presenceChildren.set(childId, false);
|
|
147
|
-
return () => presenceChildren.delete(childId);
|
|
148
|
-
},
|
|
149
|
-
}),
|
|
150
|
-
/**
|
|
151
|
-
* If the presence of a child affects the layout of the components around it,
|
|
152
|
-
* we want to make a new context value to ensure they get re-rendered
|
|
153
|
-
* so they can detect that layout change.
|
|
154
|
-
*/
|
|
155
|
-
presenceAffectsLayout
|
|
156
|
-
? [Math.random(), memoizedOnExitComplete]
|
|
157
|
-
: [isPresent, memoizedOnExitComplete]);
|
|
158
|
-
React.useMemo(() => {
|
|
159
|
-
presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
|
|
160
|
-
}, [isPresent]);
|
|
161
|
-
/**
|
|
162
|
-
* If there's no `motion` components to fire exit animations, we want to remove this
|
|
163
|
-
* component immediately.
|
|
164
|
-
*/
|
|
165
|
-
React__namespace.useEffect(() => {
|
|
166
|
-
!isPresent &&
|
|
167
|
-
!presenceChildren.size &&
|
|
168
|
-
onExitComplete &&
|
|
169
|
-
onExitComplete();
|
|
170
|
-
}, [isPresent]);
|
|
171
|
-
if (mode === "popLayout") {
|
|
172
|
-
children = jsxRuntime.jsx(PopChild, { isPresent: isPresent, children: children });
|
|
173
|
-
}
|
|
174
|
-
return (jsxRuntime.jsx(PresenceContext.Provider, { value: context, children: children }));
|
|
175
|
-
};
|
|
176
|
-
function newChildrenMap() {
|
|
177
|
-
return new Map();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
29
|
const LayoutGroupContext = React.createContext({});
|
|
181
30
|
|
|
182
31
|
function isAnimationControls(v) {
|
|
@@ -596,7 +445,7 @@ class MotionValue {
|
|
|
596
445
|
* This will be replaced by the build step with the latest version number.
|
|
597
446
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
598
447
|
*/
|
|
599
|
-
this.version = "11.
|
|
448
|
+
this.version = "11.17.0";
|
|
600
449
|
/**
|
|
601
450
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
602
451
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -4401,6 +4250,26 @@ function filterProps(props, isDom, forwardMotionProps) {
|
|
|
4401
4250
|
return filteredProps;
|
|
4402
4251
|
}
|
|
4403
4252
|
|
|
4253
|
+
/**
|
|
4254
|
+
* @public
|
|
4255
|
+
*/
|
|
4256
|
+
const PresenceContext = React.createContext(null);
|
|
4257
|
+
|
|
4258
|
+
/**
|
|
4259
|
+
* Creates a constant value over the lifecycle of a component.
|
|
4260
|
+
*
|
|
4261
|
+
* Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
|
|
4262
|
+
* a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
|
|
4263
|
+
* you can ensure that initialisers don't execute twice or more.
|
|
4264
|
+
*/
|
|
4265
|
+
function useConstant(init) {
|
|
4266
|
+
const ref = React.useRef(null);
|
|
4267
|
+
if (ref.current === null) {
|
|
4268
|
+
ref.current = init();
|
|
4269
|
+
}
|
|
4270
|
+
return ref.current;
|
|
4271
|
+
}
|
|
4272
|
+
|
|
4404
4273
|
/**
|
|
4405
4274
|
* If the provided value is a MotionValue, this returns the actual value, otherwise just the value itself
|
|
4406
4275
|
*
|
|
@@ -4547,6 +4416,202 @@ function useForceUpdate() {
|
|
|
4547
4416
|
return [deferredForceRender, forcedRenderCount];
|
|
4548
4417
|
}
|
|
4549
4418
|
|
|
4419
|
+
/**
|
|
4420
|
+
* @public
|
|
4421
|
+
*/
|
|
4422
|
+
const MotionConfigContext = React.createContext({
|
|
4423
|
+
transformPagePoint: (p) => p,
|
|
4424
|
+
isStatic: false,
|
|
4425
|
+
reducedMotion: "never",
|
|
4426
|
+
});
|
|
4427
|
+
|
|
4428
|
+
/**
|
|
4429
|
+
* Measurement functionality has to be within a separate component
|
|
4430
|
+
* to leverage snapshot lifecycle.
|
|
4431
|
+
*/
|
|
4432
|
+
class PopChildMeasure extends React__namespace.Component {
|
|
4433
|
+
getSnapshotBeforeUpdate(prevProps) {
|
|
4434
|
+
const element = this.props.childRef.current;
|
|
4435
|
+
if (element && prevProps.isPresent && !this.props.isPresent) {
|
|
4436
|
+
const size = this.props.sizeRef.current;
|
|
4437
|
+
size.height = element.offsetHeight || 0;
|
|
4438
|
+
size.width = element.offsetWidth || 0;
|
|
4439
|
+
size.top = element.offsetTop;
|
|
4440
|
+
size.left = element.offsetLeft;
|
|
4441
|
+
}
|
|
4442
|
+
return null;
|
|
4443
|
+
}
|
|
4444
|
+
/**
|
|
4445
|
+
* Required with getSnapshotBeforeUpdate to stop React complaining.
|
|
4446
|
+
*/
|
|
4447
|
+
componentDidUpdate() { }
|
|
4448
|
+
render() {
|
|
4449
|
+
return this.props.children;
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
function PopChild({ children, isPresent }) {
|
|
4453
|
+
const id = React.useId();
|
|
4454
|
+
const ref = React.useRef(null);
|
|
4455
|
+
const size = React.useRef({
|
|
4456
|
+
width: 0,
|
|
4457
|
+
height: 0,
|
|
4458
|
+
top: 0,
|
|
4459
|
+
left: 0,
|
|
4460
|
+
});
|
|
4461
|
+
const { nonce } = React.useContext(MotionConfigContext);
|
|
4462
|
+
/**
|
|
4463
|
+
* We create and inject a style block so we can apply this explicit
|
|
4464
|
+
* sizing in a non-destructive manner by just deleting the style block.
|
|
4465
|
+
*
|
|
4466
|
+
* We can't apply size via render as the measurement happens
|
|
4467
|
+
* in getSnapshotBeforeUpdate (post-render), likewise if we apply the
|
|
4468
|
+
* styles directly on the DOM node, we might be overwriting
|
|
4469
|
+
* styles set via the style prop.
|
|
4470
|
+
*/
|
|
4471
|
+
React.useInsertionEffect(() => {
|
|
4472
|
+
const { width, height, top, left } = size.current;
|
|
4473
|
+
if (isPresent || !ref.current || !width || !height)
|
|
4474
|
+
return;
|
|
4475
|
+
ref.current.dataset.motionPopId = id;
|
|
4476
|
+
const style = document.createElement("style");
|
|
4477
|
+
if (nonce)
|
|
4478
|
+
style.nonce = nonce;
|
|
4479
|
+
document.head.appendChild(style);
|
|
4480
|
+
if (style.sheet) {
|
|
4481
|
+
style.sheet.insertRule(`
|
|
4482
|
+
[data-motion-pop-id="${id}"] {
|
|
4483
|
+
position: absolute !important;
|
|
4484
|
+
width: ${width}px !important;
|
|
4485
|
+
height: ${height}px !important;
|
|
4486
|
+
top: ${top}px !important;
|
|
4487
|
+
left: ${left}px !important;
|
|
4488
|
+
}
|
|
4489
|
+
`);
|
|
4490
|
+
}
|
|
4491
|
+
return () => {
|
|
4492
|
+
document.head.removeChild(style);
|
|
4493
|
+
};
|
|
4494
|
+
}, [isPresent]);
|
|
4495
|
+
return (jsxRuntime.jsx(PopChildMeasure, { isPresent: isPresent, childRef: ref, sizeRef: size, children: React__namespace.cloneElement(children, { ref }) }));
|
|
4496
|
+
}
|
|
4497
|
+
|
|
4498
|
+
const PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, presenceAffectsLayout, mode, }) => {
|
|
4499
|
+
const presenceChildren = useConstant(newChildrenMap);
|
|
4500
|
+
const id = React.useId();
|
|
4501
|
+
const memoizedOnExitComplete = React.useCallback((childId) => {
|
|
4502
|
+
presenceChildren.set(childId, true);
|
|
4503
|
+
for (const isComplete of presenceChildren.values()) {
|
|
4504
|
+
if (!isComplete)
|
|
4505
|
+
return; // can stop searching when any is incomplete
|
|
4506
|
+
}
|
|
4507
|
+
onExitComplete && onExitComplete();
|
|
4508
|
+
}, [presenceChildren, onExitComplete]);
|
|
4509
|
+
const context = React.useMemo(() => ({
|
|
4510
|
+
id,
|
|
4511
|
+
initial,
|
|
4512
|
+
isPresent,
|
|
4513
|
+
custom,
|
|
4514
|
+
onExitComplete: memoizedOnExitComplete,
|
|
4515
|
+
register: (childId) => {
|
|
4516
|
+
presenceChildren.set(childId, false);
|
|
4517
|
+
return () => presenceChildren.delete(childId);
|
|
4518
|
+
},
|
|
4519
|
+
}),
|
|
4520
|
+
/**
|
|
4521
|
+
* If the presence of a child affects the layout of the components around it,
|
|
4522
|
+
* we want to make a new context value to ensure they get re-rendered
|
|
4523
|
+
* so they can detect that layout change.
|
|
4524
|
+
*/
|
|
4525
|
+
presenceAffectsLayout
|
|
4526
|
+
? [Math.random(), memoizedOnExitComplete]
|
|
4527
|
+
: [isPresent, memoizedOnExitComplete]);
|
|
4528
|
+
React.useMemo(() => {
|
|
4529
|
+
presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
|
|
4530
|
+
}, [isPresent]);
|
|
4531
|
+
/**
|
|
4532
|
+
* If there's no `motion` components to fire exit animations, we want to remove this
|
|
4533
|
+
* component immediately.
|
|
4534
|
+
*/
|
|
4535
|
+
React__namespace.useEffect(() => {
|
|
4536
|
+
!isPresent &&
|
|
4537
|
+
!presenceChildren.size &&
|
|
4538
|
+
onExitComplete &&
|
|
4539
|
+
onExitComplete();
|
|
4540
|
+
}, [isPresent]);
|
|
4541
|
+
if (mode === "popLayout") {
|
|
4542
|
+
children = jsxRuntime.jsx(PopChild, { isPresent: isPresent, children: children });
|
|
4543
|
+
}
|
|
4544
|
+
return (jsxRuntime.jsx(PresenceContext.Provider, { value: context, children: children }));
|
|
4545
|
+
};
|
|
4546
|
+
function newChildrenMap() {
|
|
4547
|
+
return new Map();
|
|
4548
|
+
}
|
|
4549
|
+
|
|
4550
|
+
/**
|
|
4551
|
+
* When a component is the child of `AnimatePresence`, it can use `usePresence`
|
|
4552
|
+
* to access information about whether it's still present in the React tree.
|
|
4553
|
+
*
|
|
4554
|
+
* ```jsx
|
|
4555
|
+
* import { usePresence } from "framer-motion"
|
|
4556
|
+
*
|
|
4557
|
+
* export const Component = () => {
|
|
4558
|
+
* const [isPresent, safeToRemove] = usePresence()
|
|
4559
|
+
*
|
|
4560
|
+
* useEffect(() => {
|
|
4561
|
+
* !isPresent && setTimeout(safeToRemove, 1000)
|
|
4562
|
+
* }, [isPresent])
|
|
4563
|
+
*
|
|
4564
|
+
* return <div />
|
|
4565
|
+
* }
|
|
4566
|
+
* ```
|
|
4567
|
+
*
|
|
4568
|
+
* If `isPresent` is `false`, it means that a component has been removed the tree, but
|
|
4569
|
+
* `AnimatePresence` won't really remove it until `safeToRemove` has been called.
|
|
4570
|
+
*
|
|
4571
|
+
* @public
|
|
4572
|
+
*/
|
|
4573
|
+
function usePresence(subscribe = true) {
|
|
4574
|
+
const context = React.useContext(PresenceContext);
|
|
4575
|
+
if (context === null)
|
|
4576
|
+
return [true, null];
|
|
4577
|
+
const { isPresent, onExitComplete, register } = context;
|
|
4578
|
+
// It's safe to call the following hooks conditionally (after an early return) because the context will always
|
|
4579
|
+
// either be null or non-null for the lifespan of the component.
|
|
4580
|
+
const id = React.useId();
|
|
4581
|
+
React.useEffect(() => {
|
|
4582
|
+
if (subscribe)
|
|
4583
|
+
register(id);
|
|
4584
|
+
}, [subscribe]);
|
|
4585
|
+
const safeToRemove = React.useCallback(() => subscribe && onExitComplete && onExitComplete(id), [id, onExitComplete, subscribe]);
|
|
4586
|
+
return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
|
|
4587
|
+
}
|
|
4588
|
+
/**
|
|
4589
|
+
* Similar to `usePresence`, except `useIsPresent` simply returns whether or not the component is present.
|
|
4590
|
+
* There is no `safeToRemove` function.
|
|
4591
|
+
*
|
|
4592
|
+
* ```jsx
|
|
4593
|
+
* import { useIsPresent } from "framer-motion"
|
|
4594
|
+
*
|
|
4595
|
+
* export const Component = () => {
|
|
4596
|
+
* const isPresent = useIsPresent()
|
|
4597
|
+
*
|
|
4598
|
+
* useEffect(() => {
|
|
4599
|
+
* !isPresent && console.log("I've been removed!")
|
|
4600
|
+
* }, [isPresent])
|
|
4601
|
+
*
|
|
4602
|
+
* return <div />
|
|
4603
|
+
* }
|
|
4604
|
+
* ```
|
|
4605
|
+
*
|
|
4606
|
+
* @public
|
|
4607
|
+
*/
|
|
4608
|
+
function useIsPresent() {
|
|
4609
|
+
return isPresent(React.useContext(PresenceContext));
|
|
4610
|
+
}
|
|
4611
|
+
function isPresent(context) {
|
|
4612
|
+
return context === null ? true : context.isPresent;
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4550
4615
|
const getChildKey = (child) => child.key || "";
|
|
4551
4616
|
function onlyElements(children) {
|
|
4552
4617
|
const filtered = [];
|
|
@@ -4591,8 +4656,8 @@ function onlyElements(children) {
|
|
|
4591
4656
|
*
|
|
4592
4657
|
* @public
|
|
4593
4658
|
*/
|
|
4594
|
-
const AnimatePresence = ({ children,
|
|
4595
|
-
|
|
4659
|
+
const AnimatePresence = ({ children, custom, initial = true, onExitComplete, presenceAffectsLayout = true, mode = "sync", propagate = false, }) => {
|
|
4660
|
+
const [isParentPresent, safeToRemove] = usePresence(propagate);
|
|
4596
4661
|
/**
|
|
4597
4662
|
* Filter any children that aren't ReactElements. We can only track components
|
|
4598
4663
|
* between renders with a props.key.
|
|
@@ -4602,7 +4667,7 @@ const AnimatePresence = ({ children, exitBeforeEnter, custom, initial = true, on
|
|
|
4602
4667
|
* Track the keys of the currently rendered children. This is used to
|
|
4603
4668
|
* determine which children are exiting.
|
|
4604
4669
|
*/
|
|
4605
|
-
const presentKeys = presentChildren.map(getChildKey);
|
|
4670
|
+
const presentKeys = propagate && !isParentPresent ? [] : presentChildren.map(getChildKey);
|
|
4606
4671
|
/**
|
|
4607
4672
|
* If `initial={false}` we only want to pass this to components in the first render.
|
|
4608
4673
|
*/
|
|
@@ -4684,8 +4749,10 @@ const AnimatePresence = ({ children, exitBeforeEnter, custom, initial = true, on
|
|
|
4684
4749
|
const { forceRender } = React.useContext(LayoutGroupContext);
|
|
4685
4750
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderedChildren.map((child) => {
|
|
4686
4751
|
const key = getChildKey(child);
|
|
4687
|
-
const isPresent =
|
|
4688
|
-
|
|
4752
|
+
const isPresent = propagate && !isParentPresent
|
|
4753
|
+
? false
|
|
4754
|
+
: presentChildren === renderedChildren ||
|
|
4755
|
+
presentKeys.includes(key);
|
|
4689
4756
|
const onExit = () => {
|
|
4690
4757
|
if (exitComplete.has(key)) {
|
|
4691
4758
|
exitComplete.set(key, true);
|
|
@@ -4701,6 +4768,7 @@ const AnimatePresence = ({ children, exitBeforeEnter, custom, initial = true, on
|
|
|
4701
4768
|
if (isEveryExitComplete) {
|
|
4702
4769
|
forceRender === null || forceRender === void 0 ? void 0 : forceRender();
|
|
4703
4770
|
setRenderedChildren(pendingPresentChildren.current);
|
|
4771
|
+
propagate && (safeToRemove === null || safeToRemove === void 0 ? void 0 : safeToRemove());
|
|
4704
4772
|
onExitComplete && onExitComplete();
|
|
4705
4773
|
}
|
|
4706
4774
|
};
|
|
@@ -5141,7 +5209,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
5141
5209
|
* and warn against mismatches.
|
|
5142
5210
|
*/
|
|
5143
5211
|
if (process.env.NODE_ENV === "development") {
|
|
5144
|
-
warnOnce(nextValue.version === "11.
|
|
5212
|
+
warnOnce(nextValue.version === "11.17.0", `Attempting to mix Motion versions ${nextValue.version} with 11.17.0 may not work as expected.`);
|
|
5145
5213
|
}
|
|
5146
5214
|
}
|
|
5147
5215
|
else if (isMotionValue(prevValue)) {
|
|
@@ -10274,68 +10342,6 @@ class PanGesture extends Feature {
|
|
|
10274
10342
|
}
|
|
10275
10343
|
}
|
|
10276
10344
|
|
|
10277
|
-
/**
|
|
10278
|
-
* When a component is the child of `AnimatePresence`, it can use `usePresence`
|
|
10279
|
-
* to access information about whether it's still present in the React tree.
|
|
10280
|
-
*
|
|
10281
|
-
* ```jsx
|
|
10282
|
-
* import { usePresence } from "framer-motion"
|
|
10283
|
-
*
|
|
10284
|
-
* export const Component = () => {
|
|
10285
|
-
* const [isPresent, safeToRemove] = usePresence()
|
|
10286
|
-
*
|
|
10287
|
-
* useEffect(() => {
|
|
10288
|
-
* !isPresent && setTimeout(safeToRemove, 1000)
|
|
10289
|
-
* }, [isPresent])
|
|
10290
|
-
*
|
|
10291
|
-
* return <div />
|
|
10292
|
-
* }
|
|
10293
|
-
* ```
|
|
10294
|
-
*
|
|
10295
|
-
* If `isPresent` is `false`, it means that a component has been removed the tree, but
|
|
10296
|
-
* `AnimatePresence` won't really remove it until `safeToRemove` has been called.
|
|
10297
|
-
*
|
|
10298
|
-
* @public
|
|
10299
|
-
*/
|
|
10300
|
-
function usePresence() {
|
|
10301
|
-
const context = React.useContext(PresenceContext);
|
|
10302
|
-
if (context === null)
|
|
10303
|
-
return [true, null];
|
|
10304
|
-
const { isPresent, onExitComplete, register } = context;
|
|
10305
|
-
// It's safe to call the following hooks conditionally (after an early return) because the context will always
|
|
10306
|
-
// either be null or non-null for the lifespan of the component.
|
|
10307
|
-
const id = React.useId();
|
|
10308
|
-
React.useEffect(() => register(id), []);
|
|
10309
|
-
const safeToRemove = React.useCallback(() => onExitComplete && onExitComplete(id), [id, onExitComplete]);
|
|
10310
|
-
return !isPresent && onExitComplete ? [false, safeToRemove] : [true];
|
|
10311
|
-
}
|
|
10312
|
-
/**
|
|
10313
|
-
* Similar to `usePresence`, except `useIsPresent` simply returns whether or not the component is present.
|
|
10314
|
-
* There is no `safeToRemove` function.
|
|
10315
|
-
*
|
|
10316
|
-
* ```jsx
|
|
10317
|
-
* import { useIsPresent } from "framer-motion"
|
|
10318
|
-
*
|
|
10319
|
-
* export const Component = () => {
|
|
10320
|
-
* const isPresent = useIsPresent()
|
|
10321
|
-
*
|
|
10322
|
-
* useEffect(() => {
|
|
10323
|
-
* !isPresent && console.log("I've been removed!")
|
|
10324
|
-
* }, [isPresent])
|
|
10325
|
-
*
|
|
10326
|
-
* return <div />
|
|
10327
|
-
* }
|
|
10328
|
-
* ```
|
|
10329
|
-
*
|
|
10330
|
-
* @public
|
|
10331
|
-
*/
|
|
10332
|
-
function useIsPresent() {
|
|
10333
|
-
return isPresent(React.useContext(PresenceContext));
|
|
10334
|
-
}
|
|
10335
|
-
function isPresent(context) {
|
|
10336
|
-
return context === null ? true : context.isPresent;
|
|
10337
|
-
}
|
|
10338
|
-
|
|
10339
10345
|
/**
|
|
10340
10346
|
* Internal, exported only for usage in Framer
|
|
10341
10347
|
*/
|