framer-motion 5.1.0 → 5.3.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/CHANGELOG.md +1953 -0
- package/dist/es/motion/features/definitions.mjs +6 -0
- package/dist/es/motion/features/gestures.mjs +2 -0
- package/dist/es/motion/features/viewport/observers.mjs +52 -0
- package/dist/es/motion/features/viewport/use-viewport.mjs +97 -0
- package/dist/es/motion/utils/valid-prop.mjs +4 -0
- package/dist/es/projection/node/create-projection-node.mjs +1 -1
- package/dist/es/render/dom/utils/unit-conversion.mjs +8 -1
- package/dist/es/render/utils/animation-state.mjs +2 -0
- package/dist/es/render/utils/types.mjs +1 -0
- package/dist/es/utils/warn-once.mjs +11 -0
- package/dist/framer-motion.cjs.js +173 -2
- package/dist/framer-motion.dev.js +226 -14
- package/dist/framer-motion.js +1 -1
- package/dist/projection.dev.js +63 -13
- 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/package.json +158 -158
- package/types/motion/features/types.d.ts +2 -0
- package/types/motion/features/viewport/observers.d.ts +3 -0
- package/types/motion/features/viewport/types.d.ts +20 -0
- package/types/motion/features/viewport/use-viewport.d.ts +2 -0
- package/types/motion/types.d.ts +2 -1
- package/types/render/utils/types.d.ts +1 -0
- package/types/utils/warn-once.d.ts +2 -0
|
@@ -11,6 +11,7 @@ var featureDefinitions = {
|
|
|
11
11
|
"whileTap",
|
|
12
12
|
"whileFocus",
|
|
13
13
|
"whileDrag",
|
|
14
|
+
"whileInView",
|
|
14
15
|
]),
|
|
15
16
|
exit: createDefinition(["exit"]),
|
|
16
17
|
drag: createDefinition(["drag", "dragControls"]),
|
|
@@ -23,6 +24,11 @@ var featureDefinitions = {
|
|
|
23
24
|
"onPanSessionStart",
|
|
24
25
|
"onPanEnd",
|
|
25
26
|
]),
|
|
27
|
+
inView: createDefinition([
|
|
28
|
+
"whileInView",
|
|
29
|
+
"onViewportEnter",
|
|
30
|
+
"onViewportLeave",
|
|
31
|
+
]),
|
|
26
32
|
};
|
|
27
33
|
function loadFeatures(features) {
|
|
28
34
|
for (var key in features) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useFocusGesture } from '../../gestures/use-focus-gesture.mjs';
|
|
2
2
|
import { useHoverGesture } from '../../gestures/use-hover-gesture.mjs';
|
|
3
3
|
import { useTapGesture } from '../../gestures/use-tap-gesture.mjs';
|
|
4
|
+
import { useViewport } from './viewport/use-viewport.mjs';
|
|
4
5
|
import { makeRenderlessComponent } from '../utils/make-renderless-component.mjs';
|
|
5
6
|
|
|
6
7
|
var gestureAnimations = {
|
|
8
|
+
inView: makeRenderlessComponent(useViewport),
|
|
7
9
|
tap: makeRenderlessComponent(useTapGesture),
|
|
8
10
|
focus: makeRenderlessComponent(useFocusGesture),
|
|
9
11
|
hover: makeRenderlessComponent(useHoverGesture),
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { __rest, __assign } from 'tslib';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Map an IntersectionHandler callback to an element. We only ever make one handler for one
|
|
5
|
+
* element, so even though these handlers might all be triggered by different
|
|
6
|
+
* observers, we can keep them in the same map.
|
|
7
|
+
*/
|
|
8
|
+
var observerCallbacks = new WeakMap();
|
|
9
|
+
/**
|
|
10
|
+
* Multiple observers can be created for multiple element/document roots. Each with
|
|
11
|
+
* different settings. So here we store dictionaries of observers to each root,
|
|
12
|
+
* using serialised settings (threshold/margin) as lookup keys.
|
|
13
|
+
*/
|
|
14
|
+
var observers = new WeakMap();
|
|
15
|
+
var fireObserverCallback = function (entry) {
|
|
16
|
+
var _a;
|
|
17
|
+
(_a = observerCallbacks.get(entry.target)) === null || _a === void 0 ? void 0 : _a(entry);
|
|
18
|
+
};
|
|
19
|
+
var fireAllObserverCallbacks = function (entries) {
|
|
20
|
+
entries.forEach(fireObserverCallback);
|
|
21
|
+
};
|
|
22
|
+
function initIntersectionObserver(_a) {
|
|
23
|
+
var root = _a.root, options = __rest(_a, ["root"]);
|
|
24
|
+
var lookupRoot = root || document;
|
|
25
|
+
/**
|
|
26
|
+
* If we don't have an observer lookup map for this root, create one.
|
|
27
|
+
*/
|
|
28
|
+
if (!observers.has(lookupRoot)) {
|
|
29
|
+
observers.set(lookupRoot, {});
|
|
30
|
+
}
|
|
31
|
+
var rootObservers = observers.get(lookupRoot);
|
|
32
|
+
var key = JSON.stringify(options);
|
|
33
|
+
/**
|
|
34
|
+
* If we don't have an observer for this combination of root and settings,
|
|
35
|
+
* create one.
|
|
36
|
+
*/
|
|
37
|
+
if (!rootObservers[key]) {
|
|
38
|
+
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, __assign({ root: root }, options));
|
|
39
|
+
}
|
|
40
|
+
return rootObservers[key];
|
|
41
|
+
}
|
|
42
|
+
function observeIntersection(element, options, callback) {
|
|
43
|
+
var rootInteresectionObserver = initIntersectionObserver(options);
|
|
44
|
+
observerCallbacks.set(element, callback);
|
|
45
|
+
rootInteresectionObserver.observe(element);
|
|
46
|
+
return function () {
|
|
47
|
+
observerCallbacks.delete(element);
|
|
48
|
+
rootInteresectionObserver.unobserve(element);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { observeIntersection };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
import { AnimationType } from '../../../render/utils/types.mjs';
|
|
3
|
+
import { warnOnce } from '../../../utils/warn-once.mjs';
|
|
4
|
+
import { observeIntersection } from './observers.mjs';
|
|
5
|
+
|
|
6
|
+
function useViewport(_a) {
|
|
7
|
+
var visualElement = _a.visualElement, whileInView = _a.whileInView, onViewportEnter = _a.onViewportEnter, onViewportLeave = _a.onViewportLeave, _b = _a.viewport, viewport = _b === void 0 ? {} : _b;
|
|
8
|
+
var state = useRef({
|
|
9
|
+
hasEnteredView: false,
|
|
10
|
+
isInView: false,
|
|
11
|
+
});
|
|
12
|
+
var shouldObserve = Boolean(whileInView || onViewportEnter || onViewportLeave);
|
|
13
|
+
if (viewport.once && state.current.hasEnteredView)
|
|
14
|
+
shouldObserve = false;
|
|
15
|
+
var useObserver = typeof IntersectionObserver === "undefined"
|
|
16
|
+
? useMissingIntersectionObserver
|
|
17
|
+
: useIntersectionObserver;
|
|
18
|
+
useObserver(shouldObserve, state.current, visualElement, viewport);
|
|
19
|
+
}
|
|
20
|
+
var thresholdNames = {
|
|
21
|
+
some: 0,
|
|
22
|
+
all: 1,
|
|
23
|
+
};
|
|
24
|
+
function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
|
|
25
|
+
var root = _a.root, rootMargin = _a.margin, _b = _a.amount, amount = _b === void 0 ? "some" : _b, once = _a.once;
|
|
26
|
+
useEffect(function () {
|
|
27
|
+
if (!shouldObserve)
|
|
28
|
+
return;
|
|
29
|
+
var options = {
|
|
30
|
+
root: root === null || root === void 0 ? void 0 : root.current,
|
|
31
|
+
rootMargin: rootMargin,
|
|
32
|
+
threshold: typeof amount === "number" ? amount : thresholdNames[amount],
|
|
33
|
+
};
|
|
34
|
+
var intersectionCallback = function (entry) {
|
|
35
|
+
var _a;
|
|
36
|
+
var isIntersecting = entry.isIntersecting;
|
|
37
|
+
/**
|
|
38
|
+
* If there's been no change in the viewport state, early return.
|
|
39
|
+
*/
|
|
40
|
+
if (state.isInView === isIntersecting)
|
|
41
|
+
return;
|
|
42
|
+
state.isInView = isIntersecting;
|
|
43
|
+
/**
|
|
44
|
+
* Handle hasEnteredView. If this is only meant to run once, and
|
|
45
|
+
* element isn't visible, early return. Otherwise set hasEnteredView to true.
|
|
46
|
+
*/
|
|
47
|
+
if (once && !isIntersecting && state.hasEnteredView) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
else if (isIntersecting) {
|
|
51
|
+
state.hasEnteredView = true;
|
|
52
|
+
}
|
|
53
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, isIntersecting);
|
|
54
|
+
/**
|
|
55
|
+
* Use the latest committed props rather than the ones in scope
|
|
56
|
+
* when this observer is created
|
|
57
|
+
*/
|
|
58
|
+
var props = visualElement.getProps();
|
|
59
|
+
var callback = isIntersecting
|
|
60
|
+
? props.onViewportEnter
|
|
61
|
+
: props.onViewportLeave;
|
|
62
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
63
|
+
};
|
|
64
|
+
return observeIntersection(visualElement.getInstance(), options, intersectionCallback);
|
|
65
|
+
}, [shouldObserve, root, rootMargin, amount]);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* If IntersectionObserver is missing, we activate inView and fire onViewportEnter
|
|
69
|
+
* on mount. This way, the page will be in the state the author expects users
|
|
70
|
+
* to see it in for everyone.
|
|
71
|
+
*/
|
|
72
|
+
function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
|
|
73
|
+
useEffect(function () {
|
|
74
|
+
if (!shouldObserve)
|
|
75
|
+
return;
|
|
76
|
+
if (process.env.NODE_ENV !== "production") {
|
|
77
|
+
warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fire this in an rAF because, at this point, the animation state
|
|
81
|
+
* won't have flushed for the first time and there's certain logic in
|
|
82
|
+
* there that behaves differently on the initial animation.
|
|
83
|
+
*
|
|
84
|
+
* This hook should be quite rarely called so setting this in an rAF
|
|
85
|
+
* is preferred to changing the behaviour of the animation state.
|
|
86
|
+
*/
|
|
87
|
+
requestAnimationFrame(function () {
|
|
88
|
+
var _a;
|
|
89
|
+
state.hasEnteredView = true;
|
|
90
|
+
var onViewportEnter = visualElement.getProps().onViewportEnter;
|
|
91
|
+
onViewportEnter === null || onViewportEnter === void 0 ? void 0 : onViewportEnter();
|
|
92
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, true);
|
|
93
|
+
});
|
|
94
|
+
}, [shouldObserve]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { useViewport };
|
|
@@ -307,7 +307,7 @@ function createProjectionNode(_a) {
|
|
|
307
307
|
node.updateScroll();
|
|
308
308
|
}
|
|
309
309
|
var _d = this.options, layoutId = _d.layoutId, layout = _d.layout;
|
|
310
|
-
if (
|
|
310
|
+
if (layoutId === undefined && !layout)
|
|
311
311
|
return;
|
|
312
312
|
var transformTemplate = (_c = this.options.visualElement) === null || _c === void 0 ? void 0 : _c.getProps().transformTemplate;
|
|
313
313
|
this.prevTransformTemplateValue = transformTemplate === null || transformTemplate === void 0 ? void 0 : transformTemplate(this.latestValues, "");
|
|
@@ -115,11 +115,18 @@ var convertChangedValueTypes = function (target, visualElement, changedKeys) {
|
|
|
115
115
|
var element = visualElement.getInstance();
|
|
116
116
|
var elementComputedStyle = getComputedStyle(element);
|
|
117
117
|
var display = elementComputedStyle.display;
|
|
118
|
+
var origin = {};
|
|
118
119
|
// If the element is currently set to display: "none", make it visible before
|
|
119
120
|
// measuring the target bounding box
|
|
120
121
|
if (display === "none") {
|
|
121
122
|
visualElement.setStaticValue("display", target.display || "block");
|
|
122
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Record origins before we render and update styles
|
|
126
|
+
*/
|
|
127
|
+
changedKeys.forEach(function (key) {
|
|
128
|
+
origin[key] = positionalValues[key](originBbox, elementComputedStyle);
|
|
129
|
+
});
|
|
123
130
|
// Apply the latest values (as set in checkAndConvertChangedValueTypes)
|
|
124
131
|
visualElement.syncRender();
|
|
125
132
|
var targetBbox = visualElement.measureViewportBox();
|
|
@@ -127,7 +134,7 @@ var convertChangedValueTypes = function (target, visualElement, changedKeys) {
|
|
|
127
134
|
// Restore styles to their **calculated computed style**, not their actual
|
|
128
135
|
// originally set style. This allows us to animate between equivalent pixel units.
|
|
129
136
|
var value = visualElement.getValue(key);
|
|
130
|
-
setAndResetVelocity(value,
|
|
137
|
+
setAndResetVelocity(value, origin[key]);
|
|
131
138
|
target[key] = positionalValues[key](targetBbox, elementComputedStyle);
|
|
132
139
|
});
|
|
133
140
|
return target;
|
|
@@ -8,6 +8,7 @@ import { isVariantLabels, resolveVariant, isVariantLabel } from './variants.mjs'
|
|
|
8
8
|
|
|
9
9
|
var variantPriorityOrder = [
|
|
10
10
|
AnimationType.Animate,
|
|
11
|
+
AnimationType.InView,
|
|
11
12
|
AnimationType.Focus,
|
|
12
13
|
AnimationType.Hover,
|
|
13
14
|
AnimationType.Tap,
|
|
@@ -324,6 +325,7 @@ function createState() {
|
|
|
324
325
|
var _a;
|
|
325
326
|
return _a = {},
|
|
326
327
|
_a[AnimationType.Animate] = createTypeState(true),
|
|
328
|
+
_a[AnimationType.InView] = createTypeState(),
|
|
327
329
|
_a[AnimationType.Hover] = createTypeState(),
|
|
328
330
|
_a[AnimationType.Tap] = createTypeState(),
|
|
329
331
|
_a[AnimationType.Drag] = createTypeState(),
|
|
@@ -48,6 +48,7 @@ var featureDefinitions = {
|
|
|
48
48
|
"whileTap",
|
|
49
49
|
"whileFocus",
|
|
50
50
|
"whileDrag",
|
|
51
|
+
"whileInView",
|
|
51
52
|
]),
|
|
52
53
|
exit: createDefinition(["exit"]),
|
|
53
54
|
drag: createDefinition(["drag", "dragControls"]),
|
|
@@ -60,6 +61,11 @@ var featureDefinitions = {
|
|
|
60
61
|
"onPanSessionStart",
|
|
61
62
|
"onPanEnd",
|
|
62
63
|
]),
|
|
64
|
+
inView: createDefinition([
|
|
65
|
+
"whileInView",
|
|
66
|
+
"onViewportEnter",
|
|
67
|
+
"onViewportLeave",
|
|
68
|
+
]),
|
|
63
69
|
};
|
|
64
70
|
function loadFeatures(features) {
|
|
65
71
|
for (var key in features) {
|
|
@@ -1988,7 +1994,7 @@ function createProjectionNode(_a) {
|
|
|
1988
1994
|
node.updateScroll();
|
|
1989
1995
|
}
|
|
1990
1996
|
var _d = this.options, layoutId = _d.layoutId, layout = _d.layout;
|
|
1991
|
-
if (
|
|
1997
|
+
if (layoutId === undefined && !layout)
|
|
1992
1998
|
return;
|
|
1993
1999
|
var transformTemplate = (_c = this.options.visualElement) === null || _c === void 0 ? void 0 : _c.getProps().transformTemplate;
|
|
1994
2000
|
this.prevTransformTemplateValue = transformTemplate === null || transformTemplate === void 0 ? void 0 : transformTemplate(this.latestValues, "");
|
|
@@ -3368,6 +3374,10 @@ var validMotionProps = new Set([
|
|
|
3368
3374
|
"whileFocus",
|
|
3369
3375
|
"whileTap",
|
|
3370
3376
|
"whileHover",
|
|
3377
|
+
"whileInView",
|
|
3378
|
+
"onViewportEnter",
|
|
3379
|
+
"onViewportLeave",
|
|
3380
|
+
"viewport",
|
|
3371
3381
|
"layoutScroll",
|
|
3372
3382
|
]);
|
|
3373
3383
|
/**
|
|
@@ -3722,6 +3732,7 @@ var AnimationType;
|
|
|
3722
3732
|
AnimationType["Tap"] = "whileTap";
|
|
3723
3733
|
AnimationType["Drag"] = "whileDrag";
|
|
3724
3734
|
AnimationType["Focus"] = "whileFocus";
|
|
3735
|
+
AnimationType["InView"] = "whileInView";
|
|
3725
3736
|
AnimationType["Exit"] = "exit";
|
|
3726
3737
|
})(AnimationType || (AnimationType = {}));
|
|
3727
3738
|
|
|
@@ -4031,12 +4042,163 @@ function useTapGesture(_a) {
|
|
|
4031
4042
|
useUnmountEffect(removePointerEndListener);
|
|
4032
4043
|
}
|
|
4033
4044
|
|
|
4045
|
+
var warned = new Set();
|
|
4046
|
+
function warnOnce(condition, message, element) {
|
|
4047
|
+
if (condition || warned.has(message))
|
|
4048
|
+
return;
|
|
4049
|
+
console.warn(message);
|
|
4050
|
+
if (element)
|
|
4051
|
+
console.warn(element);
|
|
4052
|
+
warned.add(message);
|
|
4053
|
+
}
|
|
4054
|
+
|
|
4055
|
+
/**
|
|
4056
|
+
* Map an IntersectionHandler callback to an element. We only ever make one handler for one
|
|
4057
|
+
* element, so even though these handlers might all be triggered by different
|
|
4058
|
+
* observers, we can keep them in the same map.
|
|
4059
|
+
*/
|
|
4060
|
+
var observerCallbacks = new WeakMap();
|
|
4061
|
+
/**
|
|
4062
|
+
* Multiple observers can be created for multiple element/document roots. Each with
|
|
4063
|
+
* different settings. So here we store dictionaries of observers to each root,
|
|
4064
|
+
* using serialised settings (threshold/margin) as lookup keys.
|
|
4065
|
+
*/
|
|
4066
|
+
var observers = new WeakMap();
|
|
4067
|
+
var fireObserverCallback = function (entry) {
|
|
4068
|
+
var _a;
|
|
4069
|
+
(_a = observerCallbacks.get(entry.target)) === null || _a === void 0 ? void 0 : _a(entry);
|
|
4070
|
+
};
|
|
4071
|
+
var fireAllObserverCallbacks = function (entries) {
|
|
4072
|
+
entries.forEach(fireObserverCallback);
|
|
4073
|
+
};
|
|
4074
|
+
function initIntersectionObserver(_a) {
|
|
4075
|
+
var root = _a.root, options = tslib.__rest(_a, ["root"]);
|
|
4076
|
+
var lookupRoot = root || document;
|
|
4077
|
+
/**
|
|
4078
|
+
* If we don't have an observer lookup map for this root, create one.
|
|
4079
|
+
*/
|
|
4080
|
+
if (!observers.has(lookupRoot)) {
|
|
4081
|
+
observers.set(lookupRoot, {});
|
|
4082
|
+
}
|
|
4083
|
+
var rootObservers = observers.get(lookupRoot);
|
|
4084
|
+
var key = JSON.stringify(options);
|
|
4085
|
+
/**
|
|
4086
|
+
* If we don't have an observer for this combination of root and settings,
|
|
4087
|
+
* create one.
|
|
4088
|
+
*/
|
|
4089
|
+
if (!rootObservers[key]) {
|
|
4090
|
+
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, tslib.__assign({ root: root }, options));
|
|
4091
|
+
}
|
|
4092
|
+
return rootObservers[key];
|
|
4093
|
+
}
|
|
4094
|
+
function observeIntersection(element, options, callback) {
|
|
4095
|
+
var rootInteresectionObserver = initIntersectionObserver(options);
|
|
4096
|
+
observerCallbacks.set(element, callback);
|
|
4097
|
+
rootInteresectionObserver.observe(element);
|
|
4098
|
+
return function () {
|
|
4099
|
+
observerCallbacks.delete(element);
|
|
4100
|
+
rootInteresectionObserver.unobserve(element);
|
|
4101
|
+
};
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
function useViewport(_a) {
|
|
4105
|
+
var visualElement = _a.visualElement, whileInView = _a.whileInView, onViewportEnter = _a.onViewportEnter, onViewportLeave = _a.onViewportLeave, _b = _a.viewport, viewport = _b === void 0 ? {} : _b;
|
|
4106
|
+
var state = React.useRef({
|
|
4107
|
+
hasEnteredView: false,
|
|
4108
|
+
isInView: false,
|
|
4109
|
+
});
|
|
4110
|
+
var shouldObserve = Boolean(whileInView || onViewportEnter || onViewportLeave);
|
|
4111
|
+
if (viewport.once && state.current.hasEnteredView)
|
|
4112
|
+
shouldObserve = false;
|
|
4113
|
+
var useObserver = typeof IntersectionObserver === "undefined"
|
|
4114
|
+
? useMissingIntersectionObserver
|
|
4115
|
+
: useIntersectionObserver;
|
|
4116
|
+
useObserver(shouldObserve, state.current, visualElement, viewport);
|
|
4117
|
+
}
|
|
4118
|
+
var thresholdNames = {
|
|
4119
|
+
some: 0,
|
|
4120
|
+
all: 1,
|
|
4121
|
+
};
|
|
4122
|
+
function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
|
|
4123
|
+
var root = _a.root, rootMargin = _a.margin, _b = _a.amount, amount = _b === void 0 ? "some" : _b, once = _a.once;
|
|
4124
|
+
React.useEffect(function () {
|
|
4125
|
+
if (!shouldObserve)
|
|
4126
|
+
return;
|
|
4127
|
+
var options = {
|
|
4128
|
+
root: root === null || root === void 0 ? void 0 : root.current,
|
|
4129
|
+
rootMargin: rootMargin,
|
|
4130
|
+
threshold: typeof amount === "number" ? amount : thresholdNames[amount],
|
|
4131
|
+
};
|
|
4132
|
+
var intersectionCallback = function (entry) {
|
|
4133
|
+
var _a;
|
|
4134
|
+
var isIntersecting = entry.isIntersecting;
|
|
4135
|
+
/**
|
|
4136
|
+
* If there's been no change in the viewport state, early return.
|
|
4137
|
+
*/
|
|
4138
|
+
if (state.isInView === isIntersecting)
|
|
4139
|
+
return;
|
|
4140
|
+
state.isInView = isIntersecting;
|
|
4141
|
+
/**
|
|
4142
|
+
* Handle hasEnteredView. If this is only meant to run once, and
|
|
4143
|
+
* element isn't visible, early return. Otherwise set hasEnteredView to true.
|
|
4144
|
+
*/
|
|
4145
|
+
if (once && !isIntersecting && state.hasEnteredView) {
|
|
4146
|
+
return;
|
|
4147
|
+
}
|
|
4148
|
+
else if (isIntersecting) {
|
|
4149
|
+
state.hasEnteredView = true;
|
|
4150
|
+
}
|
|
4151
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, isIntersecting);
|
|
4152
|
+
/**
|
|
4153
|
+
* Use the latest committed props rather than the ones in scope
|
|
4154
|
+
* when this observer is created
|
|
4155
|
+
*/
|
|
4156
|
+
var props = visualElement.getProps();
|
|
4157
|
+
var callback = isIntersecting
|
|
4158
|
+
? props.onViewportEnter
|
|
4159
|
+
: props.onViewportLeave;
|
|
4160
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
4161
|
+
};
|
|
4162
|
+
return observeIntersection(visualElement.getInstance(), options, intersectionCallback);
|
|
4163
|
+
}, [shouldObserve, root, rootMargin, amount]);
|
|
4164
|
+
}
|
|
4165
|
+
/**
|
|
4166
|
+
* If IntersectionObserver is missing, we activate inView and fire onViewportEnter
|
|
4167
|
+
* on mount. This way, the page will be in the state the author expects users
|
|
4168
|
+
* to see it in for everyone.
|
|
4169
|
+
*/
|
|
4170
|
+
function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
|
|
4171
|
+
React.useEffect(function () {
|
|
4172
|
+
if (!shouldObserve)
|
|
4173
|
+
return;
|
|
4174
|
+
if (process.env.NODE_ENV !== "production") {
|
|
4175
|
+
warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
|
|
4176
|
+
}
|
|
4177
|
+
/**
|
|
4178
|
+
* Fire this in an rAF because, at this point, the animation state
|
|
4179
|
+
* won't have flushed for the first time and there's certain logic in
|
|
4180
|
+
* there that behaves differently on the initial animation.
|
|
4181
|
+
*
|
|
4182
|
+
* This hook should be quite rarely called so setting this in an rAF
|
|
4183
|
+
* is preferred to changing the behaviour of the animation state.
|
|
4184
|
+
*/
|
|
4185
|
+
requestAnimationFrame(function () {
|
|
4186
|
+
var _a;
|
|
4187
|
+
state.hasEnteredView = true;
|
|
4188
|
+
var onViewportEnter = visualElement.getProps().onViewportEnter;
|
|
4189
|
+
onViewportEnter === null || onViewportEnter === void 0 ? void 0 : onViewportEnter();
|
|
4190
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, true);
|
|
4191
|
+
});
|
|
4192
|
+
}, [shouldObserve]);
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4034
4195
|
var makeRenderlessComponent = function (hook) { return function (props) {
|
|
4035
4196
|
hook(props);
|
|
4036
4197
|
return null;
|
|
4037
4198
|
}; };
|
|
4038
4199
|
|
|
4039
4200
|
var gestureAnimations = {
|
|
4201
|
+
inView: makeRenderlessComponent(useViewport),
|
|
4040
4202
|
tap: makeRenderlessComponent(useTapGesture),
|
|
4041
4203
|
focus: makeRenderlessComponent(useFocusGesture),
|
|
4042
4204
|
hover: makeRenderlessComponent(useHoverGesture),
|
|
@@ -4407,6 +4569,7 @@ function shouldBlockAnimation(_a, key) {
|
|
|
4407
4569
|
|
|
4408
4570
|
var variantPriorityOrder = [
|
|
4409
4571
|
AnimationType.Animate,
|
|
4572
|
+
AnimationType.InView,
|
|
4410
4573
|
AnimationType.Focus,
|
|
4411
4574
|
AnimationType.Hover,
|
|
4412
4575
|
AnimationType.Tap,
|
|
@@ -4723,6 +4886,7 @@ function createState() {
|
|
|
4723
4886
|
var _a;
|
|
4724
4887
|
return _a = {},
|
|
4725
4888
|
_a[AnimationType.Animate] = createTypeState(true),
|
|
4889
|
+
_a[AnimationType.InView] = createTypeState(),
|
|
4726
4890
|
_a[AnimationType.Hover] = createTypeState(),
|
|
4727
4891
|
_a[AnimationType.Tap] = createTypeState(),
|
|
4728
4892
|
_a[AnimationType.Drag] = createTypeState(),
|
|
@@ -6232,11 +6396,18 @@ var convertChangedValueTypes = function (target, visualElement, changedKeys) {
|
|
|
6232
6396
|
var element = visualElement.getInstance();
|
|
6233
6397
|
var elementComputedStyle = getComputedStyle(element);
|
|
6234
6398
|
var display = elementComputedStyle.display;
|
|
6399
|
+
var origin = {};
|
|
6235
6400
|
// If the element is currently set to display: "none", make it visible before
|
|
6236
6401
|
// measuring the target bounding box
|
|
6237
6402
|
if (display === "none") {
|
|
6238
6403
|
visualElement.setStaticValue("display", target.display || "block");
|
|
6239
6404
|
}
|
|
6405
|
+
/**
|
|
6406
|
+
* Record origins before we render and update styles
|
|
6407
|
+
*/
|
|
6408
|
+
changedKeys.forEach(function (key) {
|
|
6409
|
+
origin[key] = positionalValues[key](originBbox, elementComputedStyle);
|
|
6410
|
+
});
|
|
6240
6411
|
// Apply the latest values (as set in checkAndConvertChangedValueTypes)
|
|
6241
6412
|
visualElement.syncRender();
|
|
6242
6413
|
var targetBbox = visualElement.measureViewportBox();
|
|
@@ -6244,7 +6415,7 @@ var convertChangedValueTypes = function (target, visualElement, changedKeys) {
|
|
|
6244
6415
|
// Restore styles to their **calculated computed style**, not their actual
|
|
6245
6416
|
// originally set style. This allows us to animate between equivalent pixel units.
|
|
6246
6417
|
var value = visualElement.getValue(key);
|
|
6247
|
-
setAndResetVelocity(value,
|
|
6418
|
+
setAndResetVelocity(value, origin[key]);
|
|
6248
6419
|
target[key] = positionalValues[key](targetBbox, elementComputedStyle);
|
|
6249
6420
|
});
|
|
6250
6421
|
return target;
|