framer-motion 7.6.4 → 7.6.5
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 +734 -801
- package/dist/es/animation/use-animated-state.mjs +29 -17
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +9 -5
- package/dist/es/gestures/use-focus-gesture.mjs +1 -1
- package/dist/es/gestures/use-tap-gesture.mjs +1 -1
- package/dist/es/index.mjs +1 -1
- package/dist/es/motion/features/viewport/use-viewport.mjs +2 -2
- package/dist/es/motion/utils/use-visual-element.mjs +3 -3
- package/dist/es/projection/node/create-projection-node.mjs +24 -16
- package/dist/es/render/VisualElement.mjs +480 -0
- package/dist/es/render/dom/DOMVisualElement.mjs +49 -0
- package/dist/es/render/dom/create-visual-element.mjs +4 -4
- package/dist/es/render/dom/utils/css-variables-conversion.mjs +2 -2
- package/dist/es/render/dom/utils/unit-conversion.mjs +4 -4
- package/dist/es/render/html/HTMLVisualElement.mjs +41 -0
- package/dist/es/render/svg/{visual-element.mjs → SVGVisualElement.mjs} +21 -15
- package/dist/es/render/utils/animation.mjs +4 -4
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/render/utils/resolve-dynamic-variants.mjs +2 -2
- package/dist/es/render/utils/setters.mjs +2 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +734 -801
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +2100 -1927
- package/dist/projection.dev.js +983 -1072
- package/dist/size-rollup-dom-animation-m.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.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/dist/three-entry.d.ts +1946 -1732
- package/package.json +8 -8
- package/dist/es/render/html/visual-element.mjs +0 -109
- package/dist/es/render/index.mjs +0 -515
- package/dist/es/render/utils/lifecycles.mjs +0 -43
package/dist/cjs/index.js
CHANGED
|
@@ -63,7 +63,7 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
|
|
|
63
63
|
const lazyContext = React.useContext(LazyContext);
|
|
64
64
|
const presenceContext = React.useContext(PresenceContext);
|
|
65
65
|
const reducedMotionConfig = React.useContext(MotionConfigContext).reducedMotion;
|
|
66
|
-
const visualElementRef = React.useRef(
|
|
66
|
+
const visualElementRef = React.useRef();
|
|
67
67
|
/**
|
|
68
68
|
* If we haven't preloaded a renderer, check to see if we have one lazy-loaded
|
|
69
69
|
*/
|
|
@@ -82,14 +82,14 @@ function useVisualElement(Component, visualState, props, createVisualElement) {
|
|
|
82
82
|
}
|
|
83
83
|
const visualElement = visualElementRef.current;
|
|
84
84
|
useIsomorphicLayoutEffect(() => {
|
|
85
|
-
visualElement && visualElement.
|
|
85
|
+
visualElement && visualElement.render();
|
|
86
86
|
});
|
|
87
87
|
React.useEffect(() => {
|
|
88
88
|
if (visualElement && visualElement.animationState) {
|
|
89
89
|
visualElement.animationState.animateChanges();
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
|
-
useIsomorphicLayoutEffect(() => () => visualElement && visualElement.
|
|
92
|
+
useIsomorphicLayoutEffect(() => () => visualElement && visualElement.notify("Unmount"), []);
|
|
93
93
|
return visualElement;
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -1294,7 +1294,7 @@ function useDomEvent(ref, eventName, handler, options) {
|
|
|
1294
1294
|
* @param ref
|
|
1295
1295
|
* @internal
|
|
1296
1296
|
*/
|
|
1297
|
-
function useFocusGesture({ whileFocus, visualElement }) {
|
|
1297
|
+
function useFocusGesture({ whileFocus, visualElement, }) {
|
|
1298
1298
|
const { animationState } = visualElement;
|
|
1299
1299
|
const onFocus = () => {
|
|
1300
1300
|
animationState && animationState.setActive(exports.AnimationType.Focus, true);
|
|
@@ -1530,7 +1530,7 @@ function useTapGesture({ onTap, onTapStart, onTapCancel, whileTap, visualElement
|
|
|
1530
1530
|
* We only count this as a tap gesture if the event.target is the same
|
|
1531
1531
|
* as, or a child of, this component's element
|
|
1532
1532
|
*/
|
|
1533
|
-
!isNodeOrChild(visualElement.
|
|
1533
|
+
!isNodeOrChild(visualElement.current, event.target)
|
|
1534
1534
|
? onTapCancel && onTapCancel(event, info)
|
|
1535
1535
|
: onTap && onTap(event, info);
|
|
1536
1536
|
}
|
|
@@ -1641,7 +1641,7 @@ const thresholdNames = {
|
|
|
1641
1641
|
};
|
|
1642
1642
|
function useIntersectionObserver(shouldObserve, state, visualElement, { root, margin: rootMargin, amount = "some", once }) {
|
|
1643
1643
|
React.useEffect(() => {
|
|
1644
|
-
if (!shouldObserve)
|
|
1644
|
+
if (!shouldObserve || !visualElement.current)
|
|
1645
1645
|
return;
|
|
1646
1646
|
const options = {
|
|
1647
1647
|
root: root === null || root === void 0 ? void 0 : root.current,
|
|
@@ -1679,7 +1679,7 @@ function useIntersectionObserver(shouldObserve, state, visualElement, { root, ma
|
|
|
1679
1679
|
: props.onViewportLeave;
|
|
1680
1680
|
callback && callback(entry);
|
|
1681
1681
|
};
|
|
1682
|
-
return observeIntersection(visualElement.
|
|
1682
|
+
return observeIntersection(visualElement.current, options, intersectionCallback);
|
|
1683
1683
|
}, [shouldObserve, root, rootMargin, amount]);
|
|
1684
1684
|
}
|
|
1685
1685
|
/**
|
|
@@ -2258,7 +2258,7 @@ class MotionValue {
|
|
|
2258
2258
|
* This will be replaced by the build step with the latest version number.
|
|
2259
2259
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
2260
2260
|
*/
|
|
2261
|
-
this.version = "7.6.
|
|
2261
|
+
this.version = "7.6.5";
|
|
2262
2262
|
/**
|
|
2263
2263
|
* Duration, in milliseconds, since last updating frame.
|
|
2264
2264
|
*
|
|
@@ -2572,7 +2572,7 @@ const findValueType = (v) => valueTypes.find(testValueType(v));
|
|
|
2572
2572
|
*/
|
|
2573
2573
|
function getCurrent(visualElement) {
|
|
2574
2574
|
const current = {};
|
|
2575
|
-
visualElement.
|
|
2575
|
+
visualElement.values.forEach((value, key) => (current[key] = value.get()));
|
|
2576
2576
|
return current;
|
|
2577
2577
|
}
|
|
2578
2578
|
/**
|
|
@@ -2580,7 +2580,7 @@ function getCurrent(visualElement) {
|
|
|
2580
2580
|
*/
|
|
2581
2581
|
function getVelocity$1(visualElement) {
|
|
2582
2582
|
const velocity = {};
|
|
2583
|
-
visualElement.
|
|
2583
|
+
visualElement.values.forEach((value, key) => (velocity[key] = value.getVelocity()));
|
|
2584
2584
|
return velocity;
|
|
2585
2585
|
}
|
|
2586
2586
|
function resolveVariant(visualElement, definition, custom) {
|
|
@@ -2674,7 +2674,8 @@ function checkTargetForNewValues(visualElement, target, origin) {
|
|
|
2674
2674
|
if (origin[key] === undefined) {
|
|
2675
2675
|
origin[key] = value;
|
|
2676
2676
|
}
|
|
2677
|
-
|
|
2677
|
+
if (value !== null)
|
|
2678
|
+
visualElement.setBaseTarget(key, value);
|
|
2678
2679
|
}
|
|
2679
2680
|
}
|
|
2680
2681
|
function getOriginFromTransition(key, transition) {
|
|
@@ -2701,7 +2702,7 @@ function isWillChangeMotionValue(value) {
|
|
|
2701
2702
|
}
|
|
2702
2703
|
|
|
2703
2704
|
function animateVisualElement(visualElement, definition, options = {}) {
|
|
2704
|
-
visualElement.
|
|
2705
|
+
visualElement.notify("AnimationStart", definition);
|
|
2705
2706
|
let animation;
|
|
2706
2707
|
if (Array.isArray(definition)) {
|
|
2707
2708
|
const animations = definition.map((variant) => animateVariant(visualElement, variant, options));
|
|
@@ -2716,7 +2717,7 @@ function animateVisualElement(visualElement, definition, options = {}) {
|
|
|
2716
2717
|
: definition;
|
|
2717
2718
|
animation = animateTarget(visualElement, resolvedDefinition, options);
|
|
2718
2719
|
}
|
|
2719
|
-
return animation.then(() => visualElement.
|
|
2720
|
+
return animation.then(() => visualElement.notify("AnimationComplete", definition));
|
|
2720
2721
|
}
|
|
2721
2722
|
function animateVariant(visualElement, variant, options = {}) {
|
|
2722
2723
|
var _a;
|
|
@@ -2811,12 +2812,12 @@ function animateChildren(visualElement, variant, delayChildren = 0, staggerChild
|
|
|
2811
2812
|
animations.push(animateVariant(child, variant, {
|
|
2812
2813
|
...options,
|
|
2813
2814
|
delay: delayChildren + generateStaggerDuration(i),
|
|
2814
|
-
}).then(() => child.
|
|
2815
|
+
}).then(() => child.notify("AnimationComplete", variant)));
|
|
2815
2816
|
});
|
|
2816
2817
|
return Promise.all(animations);
|
|
2817
2818
|
}
|
|
2818
2819
|
function stopAnimation(visualElement) {
|
|
2819
|
-
visualElement.
|
|
2820
|
+
visualElement.values.forEach((value) => value.stop());
|
|
2820
2821
|
}
|
|
2821
2822
|
function sortByTreeOrder(a, b) {
|
|
2822
2823
|
return a.sortNodePosition(b);
|
|
@@ -3774,9 +3775,9 @@ class VisualElementDragControls {
|
|
|
3774
3775
|
* of a re-render we want to ensure the browser can read the latest
|
|
3775
3776
|
* bounding box to ensure the pointer and element don't fall out of sync.
|
|
3776
3777
|
*/
|
|
3777
|
-
this.visualElement.
|
|
3778
|
+
this.visualElement.render();
|
|
3778
3779
|
/**
|
|
3779
|
-
* This must fire after the
|
|
3780
|
+
* This must fire after the render call as it might trigger a state
|
|
3780
3781
|
* change which itself might trigger a layout update.
|
|
3781
3782
|
*/
|
|
3782
3783
|
onDrag === null || onDrag === void 0 ? void 0 : onDrag(event, info);
|
|
@@ -3965,6 +3966,8 @@ class VisualElementDragControls {
|
|
|
3965
3966
|
*/
|
|
3966
3967
|
scalePositionWithinConstraints() {
|
|
3967
3968
|
var _a;
|
|
3969
|
+
if (!this.visualElement.current)
|
|
3970
|
+
return;
|
|
3968
3971
|
const { drag, dragConstraints } = this.getProps();
|
|
3969
3972
|
const { projection } = this.visualElement;
|
|
3970
3973
|
if (!isRefObject(dragConstraints) || !projection || !this.constraints)
|
|
@@ -3990,7 +3993,7 @@ class VisualElementDragControls {
|
|
|
3990
3993
|
* Update the layout of this element and resolve the latest drag constraints
|
|
3991
3994
|
*/
|
|
3992
3995
|
const { transformTemplate } = this.visualElement.getProps();
|
|
3993
|
-
this.visualElement.
|
|
3996
|
+
this.visualElement.current.style.transform = transformTemplate
|
|
3994
3997
|
? transformTemplate({}, "")
|
|
3995
3998
|
: "none";
|
|
3996
3999
|
(_a = projection.root) === null || _a === void 0 ? void 0 : _a.updateScroll();
|
|
@@ -4013,8 +4016,10 @@ class VisualElementDragControls {
|
|
|
4013
4016
|
}
|
|
4014
4017
|
addListeners() {
|
|
4015
4018
|
var _a;
|
|
4019
|
+
if (!this.visualElement.current)
|
|
4020
|
+
return;
|
|
4016
4021
|
elementDragControls.set(this.visualElement, this);
|
|
4017
|
-
const element = this.visualElement.
|
|
4022
|
+
const element = this.visualElement.current;
|
|
4018
4023
|
/**
|
|
4019
4024
|
* Attach a pointerdown event listener on this DOM element to initiate drag tracking.
|
|
4020
4025
|
*/
|
|
@@ -4053,7 +4058,7 @@ class VisualElementDragControls {
|
|
|
4053
4058
|
this.originPoint[axis] += delta[axis].translate;
|
|
4054
4059
|
motionValue.set(motionValue.get() + delta[axis].translate);
|
|
4055
4060
|
});
|
|
4056
|
-
this.visualElement.
|
|
4061
|
+
this.visualElement.render();
|
|
4057
4062
|
}
|
|
4058
4063
|
}));
|
|
4059
4064
|
return () => {
|
|
@@ -4158,618 +4163,6 @@ const drag = {
|
|
|
4158
4163
|
drag: makeRenderlessComponent(useDrag),
|
|
4159
4164
|
};
|
|
4160
4165
|
|
|
4161
|
-
// Does this device prefer reduced motion? Returns `null` server-side.
|
|
4162
|
-
const prefersReducedMotion = { current: null };
|
|
4163
|
-
const hasReducedMotionListener = { current: false };
|
|
4164
|
-
|
|
4165
|
-
function initPrefersReducedMotion() {
|
|
4166
|
-
hasReducedMotionListener.current = true;
|
|
4167
|
-
if (!isBrowser)
|
|
4168
|
-
return;
|
|
4169
|
-
if (window.matchMedia) {
|
|
4170
|
-
const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)");
|
|
4171
|
-
const setReducedMotionPreferences = () => (prefersReducedMotion.current = motionMediaQuery.matches);
|
|
4172
|
-
motionMediaQuery.addListener(setReducedMotionPreferences);
|
|
4173
|
-
setReducedMotionPreferences();
|
|
4174
|
-
}
|
|
4175
|
-
else {
|
|
4176
|
-
prefersReducedMotion.current = false;
|
|
4177
|
-
}
|
|
4178
|
-
}
|
|
4179
|
-
|
|
4180
|
-
const names = [
|
|
4181
|
-
"LayoutMeasure",
|
|
4182
|
-
"BeforeLayoutMeasure",
|
|
4183
|
-
"LayoutUpdate",
|
|
4184
|
-
"ViewportBoxUpdate",
|
|
4185
|
-
"Update",
|
|
4186
|
-
"Render",
|
|
4187
|
-
"AnimationComplete",
|
|
4188
|
-
"LayoutAnimationComplete",
|
|
4189
|
-
"AnimationStart",
|
|
4190
|
-
"LayoutAnimationStart",
|
|
4191
|
-
"SetAxisTarget",
|
|
4192
|
-
"Unmount",
|
|
4193
|
-
];
|
|
4194
|
-
function createLifecycles() {
|
|
4195
|
-
const managers = names.map(() => new SubscriptionManager());
|
|
4196
|
-
const propSubscriptions = {};
|
|
4197
|
-
const lifecycles = {
|
|
4198
|
-
clearAllListeners: () => managers.forEach((manager) => manager.clear()),
|
|
4199
|
-
updatePropListeners: (props) => {
|
|
4200
|
-
names.forEach((name) => {
|
|
4201
|
-
var _a;
|
|
4202
|
-
const on = "on" + name;
|
|
4203
|
-
const propListener = props[on];
|
|
4204
|
-
// Unsubscribe existing subscription
|
|
4205
|
-
(_a = propSubscriptions[name]) === null || _a === void 0 ? void 0 : _a.call(propSubscriptions);
|
|
4206
|
-
// Add new subscription
|
|
4207
|
-
if (propListener) {
|
|
4208
|
-
propSubscriptions[name] = lifecycles[on](propListener);
|
|
4209
|
-
}
|
|
4210
|
-
});
|
|
4211
|
-
},
|
|
4212
|
-
};
|
|
4213
|
-
managers.forEach((manager, i) => {
|
|
4214
|
-
lifecycles["on" + names[i]] = (handler) => manager.add(handler);
|
|
4215
|
-
lifecycles["notify" + names[i]] = (...args) => manager.notify(...args);
|
|
4216
|
-
});
|
|
4217
|
-
return lifecycles;
|
|
4218
|
-
}
|
|
4219
|
-
|
|
4220
|
-
function updateMotionValuesFromProps(element, next, prev) {
|
|
4221
|
-
const { willChange } = next;
|
|
4222
|
-
for (const key in next) {
|
|
4223
|
-
const nextValue = next[key];
|
|
4224
|
-
const prevValue = prev[key];
|
|
4225
|
-
if (isMotionValue(nextValue)) {
|
|
4226
|
-
/**
|
|
4227
|
-
* If this is a motion value found in props or style, we want to add it
|
|
4228
|
-
* to our visual element's motion value map.
|
|
4229
|
-
*/
|
|
4230
|
-
element.addValue(key, nextValue);
|
|
4231
|
-
if (isWillChangeMotionValue(willChange)) {
|
|
4232
|
-
willChange.add(key);
|
|
4233
|
-
}
|
|
4234
|
-
/**
|
|
4235
|
-
* Check the version of the incoming motion value with this version
|
|
4236
|
-
* and warn against mismatches.
|
|
4237
|
-
*/
|
|
4238
|
-
if (process.env.NODE_ENV === "development") {
|
|
4239
|
-
warnOnce(nextValue.version === "7.6.4", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.4 may not work as expected.`);
|
|
4240
|
-
}
|
|
4241
|
-
}
|
|
4242
|
-
else if (isMotionValue(prevValue)) {
|
|
4243
|
-
/**
|
|
4244
|
-
* If we're swapping from a motion value to a static value,
|
|
4245
|
-
* create a new motion value from that
|
|
4246
|
-
*/
|
|
4247
|
-
element.addValue(key, motionValue(nextValue));
|
|
4248
|
-
if (isWillChangeMotionValue(willChange)) {
|
|
4249
|
-
willChange.remove(key);
|
|
4250
|
-
}
|
|
4251
|
-
}
|
|
4252
|
-
else if (prevValue !== nextValue) {
|
|
4253
|
-
/**
|
|
4254
|
-
* If this is a flat value that has changed, update the motion value
|
|
4255
|
-
* or create one if it doesn't exist. We only want to do this if we're
|
|
4256
|
-
* not handling the value with our animation state.
|
|
4257
|
-
*/
|
|
4258
|
-
if (element.hasValue(key)) {
|
|
4259
|
-
const existingValue = element.getValue(key);
|
|
4260
|
-
// TODO: Only update values that aren't being animated or even looked at
|
|
4261
|
-
!existingValue.hasAnimated && existingValue.set(nextValue);
|
|
4262
|
-
}
|
|
4263
|
-
else {
|
|
4264
|
-
const latestValue = element.getStaticValue(key);
|
|
4265
|
-
element.addValue(key, motionValue(latestValue !== undefined ? latestValue : nextValue));
|
|
4266
|
-
}
|
|
4267
|
-
}
|
|
4268
|
-
}
|
|
4269
|
-
// Handle removed values
|
|
4270
|
-
for (const key in prev) {
|
|
4271
|
-
if (next[key] === undefined)
|
|
4272
|
-
element.removeValue(key);
|
|
4273
|
-
}
|
|
4274
|
-
return next;
|
|
4275
|
-
}
|
|
4276
|
-
|
|
4277
|
-
const featureNames = Object.keys(featureDefinitions);
|
|
4278
|
-
const numFeatures = featureNames.length;
|
|
4279
|
-
const visualElement = ({ treeType = "", build, getBaseTarget, makeTargetAnimatable, measureViewportBox, render: renderInstance, readValueFromInstance, removeValueFromRenderState, sortNodePosition, scrapeMotionValuesFromProps, }) => ({ parent, props, presenceId, blockInitialAnimation, visualState, reducedMotionConfig, }, options = {}) => {
|
|
4280
|
-
let isMounted = false;
|
|
4281
|
-
const { latestValues, renderState } = visualState;
|
|
4282
|
-
/**
|
|
4283
|
-
* The instance of the render-specific node that will be hydrated by the
|
|
4284
|
-
* exposed React ref. So for example, this visual element can host a
|
|
4285
|
-
* HTMLElement, plain object, or Three.js object. The functions provided
|
|
4286
|
-
* in VisualElementConfig allow us to interface with this instance.
|
|
4287
|
-
*/
|
|
4288
|
-
let instance;
|
|
4289
|
-
/**
|
|
4290
|
-
* Manages the subscriptions for a visual element's lifecycle, for instance
|
|
4291
|
-
* onRender
|
|
4292
|
-
*/
|
|
4293
|
-
const lifecycles = createLifecycles();
|
|
4294
|
-
/**
|
|
4295
|
-
* A map of all motion values attached to this visual element. Motion
|
|
4296
|
-
* values are source of truth for any given animated value. A motion
|
|
4297
|
-
* value might be provided externally by the component via props.
|
|
4298
|
-
*/
|
|
4299
|
-
const values = new Map();
|
|
4300
|
-
/**
|
|
4301
|
-
* A map of every subscription that binds the provided or generated
|
|
4302
|
-
* motion values onChange listeners to this visual element.
|
|
4303
|
-
*/
|
|
4304
|
-
const valueSubscriptions = new Map();
|
|
4305
|
-
/**
|
|
4306
|
-
* A reference to the previously-provided motion values as returned
|
|
4307
|
-
* from scrapeMotionValuesFromProps. We use the keys in here to determine
|
|
4308
|
-
* if any motion values need to be removed after props are updated.
|
|
4309
|
-
*/
|
|
4310
|
-
let prevMotionValues = {};
|
|
4311
|
-
/**
|
|
4312
|
-
* When values are removed from all animation props we need to search
|
|
4313
|
-
* for a fallback value to animate to. These values are tracked in baseTarget.
|
|
4314
|
-
*/
|
|
4315
|
-
const baseTarget = {
|
|
4316
|
-
...latestValues,
|
|
4317
|
-
};
|
|
4318
|
-
/**
|
|
4319
|
-
* Create an object of the values we initially animated from (if initial prop present).
|
|
4320
|
-
*/
|
|
4321
|
-
const initialValues = props.initial ? { ...latestValues } : {};
|
|
4322
|
-
// Internal methods ========================
|
|
4323
|
-
/**
|
|
4324
|
-
* On mount, this will be hydrated with a callback to disconnect
|
|
4325
|
-
* this visual element from its parent on unmount.
|
|
4326
|
-
*/
|
|
4327
|
-
let removeFromVariantTree;
|
|
4328
|
-
/**
|
|
4329
|
-
* Render the element with the latest styles outside of the React
|
|
4330
|
-
* render lifecycle
|
|
4331
|
-
*/
|
|
4332
|
-
function render() {
|
|
4333
|
-
if (!instance || !isMounted)
|
|
4334
|
-
return;
|
|
4335
|
-
triggerBuild();
|
|
4336
|
-
renderInstance(instance, renderState, props.style, element.projection);
|
|
4337
|
-
}
|
|
4338
|
-
function triggerBuild() {
|
|
4339
|
-
build(element, renderState, latestValues, options, props);
|
|
4340
|
-
}
|
|
4341
|
-
function update() {
|
|
4342
|
-
lifecycles.notifyUpdate(latestValues);
|
|
4343
|
-
}
|
|
4344
|
-
/**
|
|
4345
|
-
*
|
|
4346
|
-
*/
|
|
4347
|
-
function bindToMotionValue(key, value) {
|
|
4348
|
-
const removeOnChange = value.onChange((latestValue) => {
|
|
4349
|
-
latestValues[key] = latestValue;
|
|
4350
|
-
props.onUpdate && sync__default["default"].update(update, false, true);
|
|
4351
|
-
});
|
|
4352
|
-
const removeOnRenderRequest = value.onRenderRequest(element.scheduleRender);
|
|
4353
|
-
valueSubscriptions.set(key, () => {
|
|
4354
|
-
removeOnChange();
|
|
4355
|
-
removeOnRenderRequest();
|
|
4356
|
-
});
|
|
4357
|
-
}
|
|
4358
|
-
/**
|
|
4359
|
-
* Any motion values that are provided to the element when created
|
|
4360
|
-
* aren't yet bound to the element, as this would technically be impure.
|
|
4361
|
-
* However, we iterate through the motion values and set them to the
|
|
4362
|
-
* initial values for this component.
|
|
4363
|
-
*
|
|
4364
|
-
* TODO: This is impure and we should look at changing this to run on mount.
|
|
4365
|
-
* Doing so will break some tests but this isn't neccessarily a breaking change,
|
|
4366
|
-
* more a reflection of the test.
|
|
4367
|
-
*/
|
|
4368
|
-
const { willChange, ...initialMotionValues } = scrapeMotionValuesFromProps(props);
|
|
4369
|
-
for (const key in initialMotionValues) {
|
|
4370
|
-
const value = initialMotionValues[key];
|
|
4371
|
-
if (latestValues[key] !== undefined && isMotionValue(value)) {
|
|
4372
|
-
value.set(latestValues[key], false);
|
|
4373
|
-
if (isWillChangeMotionValue(willChange)) {
|
|
4374
|
-
willChange.add(key);
|
|
4375
|
-
}
|
|
4376
|
-
}
|
|
4377
|
-
}
|
|
4378
|
-
/**
|
|
4379
|
-
* Update external values with initial values
|
|
4380
|
-
*/
|
|
4381
|
-
if (props.values) {
|
|
4382
|
-
for (const key in props.values) {
|
|
4383
|
-
const value = props.values[key];
|
|
4384
|
-
if (latestValues[key] !== undefined && isMotionValue(value)) {
|
|
4385
|
-
value.set(latestValues[key]);
|
|
4386
|
-
}
|
|
4387
|
-
}
|
|
4388
|
-
}
|
|
4389
|
-
/**
|
|
4390
|
-
* Determine what role this visual element should take in the variant tree.
|
|
4391
|
-
*/
|
|
4392
|
-
const isControllingVariants$1 = isControllingVariants(props);
|
|
4393
|
-
const isVariantNode$1 = isVariantNode(props);
|
|
4394
|
-
const element = {
|
|
4395
|
-
treeType,
|
|
4396
|
-
/**
|
|
4397
|
-
* This is a mirror of the internal instance prop, which keeps
|
|
4398
|
-
* VisualElement type-compatible with React's RefObject.
|
|
4399
|
-
*/
|
|
4400
|
-
current: null,
|
|
4401
|
-
/**
|
|
4402
|
-
* The depth of this visual element within the visual element tree.
|
|
4403
|
-
*/
|
|
4404
|
-
depth: parent ? parent.depth + 1 : 0,
|
|
4405
|
-
parent,
|
|
4406
|
-
children: new Set(),
|
|
4407
|
-
/**
|
|
4408
|
-
*
|
|
4409
|
-
*/
|
|
4410
|
-
presenceId,
|
|
4411
|
-
shouldReduceMotion: null,
|
|
4412
|
-
/**
|
|
4413
|
-
* If this component is part of the variant tree, it should track
|
|
4414
|
-
* any children that are also part of the tree. This is essentially
|
|
4415
|
-
* a shadow tree to simplify logic around how to stagger over children.
|
|
4416
|
-
*/
|
|
4417
|
-
variantChildren: isVariantNode$1 ? new Set() : undefined,
|
|
4418
|
-
/**
|
|
4419
|
-
* Whether this instance is visible. This can be changed imperatively
|
|
4420
|
-
* by the projection tree, is analogous to CSS's visibility in that
|
|
4421
|
-
* hidden elements should take up layout, and needs enacting by the configured
|
|
4422
|
-
* render function.
|
|
4423
|
-
*/
|
|
4424
|
-
isVisible: undefined,
|
|
4425
|
-
/**
|
|
4426
|
-
* Normally, if a component is controlled by a parent's variants, it can
|
|
4427
|
-
* rely on that ancestor to trigger animations further down the tree.
|
|
4428
|
-
* However, if a component is created after its parent is mounted, the parent
|
|
4429
|
-
* won't trigger that mount animation so the child needs to.
|
|
4430
|
-
*
|
|
4431
|
-
* TODO: This might be better replaced with a method isParentMounted
|
|
4432
|
-
*/
|
|
4433
|
-
manuallyAnimateOnMount: Boolean(parent === null || parent === void 0 ? void 0 : parent.isMounted()),
|
|
4434
|
-
/**
|
|
4435
|
-
* This can be set by AnimatePresence to force components that mount
|
|
4436
|
-
* at the same time as it to mount as if they have initial={false} set.
|
|
4437
|
-
*/
|
|
4438
|
-
blockInitialAnimation,
|
|
4439
|
-
/**
|
|
4440
|
-
* Determine whether this component has mounted yet. This is mostly used
|
|
4441
|
-
* by variant children to determine whether they need to trigger their
|
|
4442
|
-
* own animations on mount.
|
|
4443
|
-
*/
|
|
4444
|
-
isMounted: () => Boolean(instance),
|
|
4445
|
-
mount(newInstance) {
|
|
4446
|
-
isMounted = true;
|
|
4447
|
-
instance = element.current = newInstance;
|
|
4448
|
-
if (element.projection) {
|
|
4449
|
-
element.projection.mount(newInstance);
|
|
4450
|
-
}
|
|
4451
|
-
if (isVariantNode$1 && parent && !isControllingVariants$1) {
|
|
4452
|
-
removeFromVariantTree = parent === null || parent === void 0 ? void 0 : parent.addVariantChild(element);
|
|
4453
|
-
}
|
|
4454
|
-
values.forEach((value, key) => bindToMotionValue(key, value));
|
|
4455
|
-
if (!hasReducedMotionListener.current) {
|
|
4456
|
-
initPrefersReducedMotion();
|
|
4457
|
-
}
|
|
4458
|
-
element.shouldReduceMotion =
|
|
4459
|
-
reducedMotionConfig === "never"
|
|
4460
|
-
? false
|
|
4461
|
-
: reducedMotionConfig === "always"
|
|
4462
|
-
? true
|
|
4463
|
-
: prefersReducedMotion.current;
|
|
4464
|
-
parent === null || parent === void 0 ? void 0 : parent.children.add(element);
|
|
4465
|
-
element.setProps(props);
|
|
4466
|
-
},
|
|
4467
|
-
/**
|
|
4468
|
-
*
|
|
4469
|
-
*/
|
|
4470
|
-
unmount() {
|
|
4471
|
-
var _a;
|
|
4472
|
-
(_a = element.projection) === null || _a === void 0 ? void 0 : _a.unmount();
|
|
4473
|
-
sync.cancelSync.update(update);
|
|
4474
|
-
sync.cancelSync.render(render);
|
|
4475
|
-
valueSubscriptions.forEach((remove) => remove());
|
|
4476
|
-
removeFromVariantTree === null || removeFromVariantTree === void 0 ? void 0 : removeFromVariantTree();
|
|
4477
|
-
parent === null || parent === void 0 ? void 0 : parent.children.delete(element);
|
|
4478
|
-
lifecycles.clearAllListeners();
|
|
4479
|
-
instance = undefined;
|
|
4480
|
-
isMounted = false;
|
|
4481
|
-
},
|
|
4482
|
-
loadFeatures(renderedProps, isStrict, preloadedFeatures, projectionId, ProjectionNodeConstructor, initialLayoutGroupConfig) {
|
|
4483
|
-
const features = [];
|
|
4484
|
-
/**
|
|
4485
|
-
* If we're in development mode, check to make sure we're not rendering a motion component
|
|
4486
|
-
* as a child of LazyMotion, as this will break the file-size benefits of using it.
|
|
4487
|
-
*/
|
|
4488
|
-
if (env !== "production" && preloadedFeatures && isStrict) {
|
|
4489
|
-
heyListen.invariant(false, "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.");
|
|
4490
|
-
}
|
|
4491
|
-
for (let i = 0; i < numFeatures; i++) {
|
|
4492
|
-
const name = featureNames[i];
|
|
4493
|
-
const { isEnabled, Component } = featureDefinitions[name];
|
|
4494
|
-
/**
|
|
4495
|
-
* It might be possible in the future to use this moment to
|
|
4496
|
-
* dynamically request functionality. In initial tests this
|
|
4497
|
-
* was producing a lot of duplication amongst bundles.
|
|
4498
|
-
*/
|
|
4499
|
-
if (isEnabled(renderedProps) && Component) {
|
|
4500
|
-
features.push(React.createElement(Component, {
|
|
4501
|
-
key: name,
|
|
4502
|
-
...renderedProps,
|
|
4503
|
-
visualElement: element,
|
|
4504
|
-
}));
|
|
4505
|
-
}
|
|
4506
|
-
}
|
|
4507
|
-
if (!element.projection && ProjectionNodeConstructor) {
|
|
4508
|
-
element.projection = new ProjectionNodeConstructor(projectionId, element.getLatestValues(), parent && parent.projection);
|
|
4509
|
-
const { layoutId, layout, drag, dragConstraints, layoutScroll, } = renderedProps;
|
|
4510
|
-
element.projection.setOptions({
|
|
4511
|
-
layoutId,
|
|
4512
|
-
layout,
|
|
4513
|
-
alwaysMeasureLayout: Boolean(drag) ||
|
|
4514
|
-
(dragConstraints && isRefObject(dragConstraints)),
|
|
4515
|
-
visualElement: element,
|
|
4516
|
-
scheduleRender: () => element.scheduleRender(),
|
|
4517
|
-
/**
|
|
4518
|
-
* TODO: Update options in an effect. This could be tricky as it'll be too late
|
|
4519
|
-
* to update by the time layout animations run.
|
|
4520
|
-
* We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
|
|
4521
|
-
* ensuring it gets called if there's no potential layout animations.
|
|
4522
|
-
*
|
|
4523
|
-
*/
|
|
4524
|
-
animationType: typeof layout === "string" ? layout : "both",
|
|
4525
|
-
initialPromotionConfig: initialLayoutGroupConfig,
|
|
4526
|
-
layoutScroll,
|
|
4527
|
-
});
|
|
4528
|
-
}
|
|
4529
|
-
return features;
|
|
4530
|
-
},
|
|
4531
|
-
/**
|
|
4532
|
-
* Add a child visual element to our set of children.
|
|
4533
|
-
*/
|
|
4534
|
-
addVariantChild(child) {
|
|
4535
|
-
var _a;
|
|
4536
|
-
const closestVariantNode = element.getClosestVariantNode();
|
|
4537
|
-
if (closestVariantNode) {
|
|
4538
|
-
(_a = closestVariantNode.variantChildren) === null || _a === void 0 ? void 0 : _a.add(child);
|
|
4539
|
-
return () => closestVariantNode.variantChildren.delete(child);
|
|
4540
|
-
}
|
|
4541
|
-
},
|
|
4542
|
-
sortNodePosition(other) {
|
|
4543
|
-
/**
|
|
4544
|
-
* If these nodes aren't even of the same type we can't compare their depth.
|
|
4545
|
-
*/
|
|
4546
|
-
if (!sortNodePosition || treeType !== other.treeType)
|
|
4547
|
-
return 0;
|
|
4548
|
-
return sortNodePosition(element.getInstance(), other.getInstance());
|
|
4549
|
-
},
|
|
4550
|
-
/**
|
|
4551
|
-
* Returns the closest variant node in the tree starting from
|
|
4552
|
-
* this visual element.
|
|
4553
|
-
*/
|
|
4554
|
-
getClosestVariantNode: () => isVariantNode$1 ? element : parent === null || parent === void 0 ? void 0 : parent.getClosestVariantNode(),
|
|
4555
|
-
/**
|
|
4556
|
-
* Expose the latest layoutId prop.
|
|
4557
|
-
*/
|
|
4558
|
-
getLayoutId: () => props.layoutId,
|
|
4559
|
-
/**
|
|
4560
|
-
* Returns the current instance.
|
|
4561
|
-
*/
|
|
4562
|
-
getInstance: () => instance,
|
|
4563
|
-
/**
|
|
4564
|
-
* Get/set the latest static values.
|
|
4565
|
-
*/
|
|
4566
|
-
getStaticValue: (key) => latestValues[key],
|
|
4567
|
-
setStaticValue: (key, value) => (latestValues[key] = value),
|
|
4568
|
-
/**
|
|
4569
|
-
* Returns the latest motion value state. Currently only used to take
|
|
4570
|
-
* a snapshot of the visual element - perhaps this can return the whole
|
|
4571
|
-
* visual state
|
|
4572
|
-
*/
|
|
4573
|
-
getLatestValues: () => latestValues,
|
|
4574
|
-
/**
|
|
4575
|
-
* Set the visiblity of the visual element. If it's changed, schedule
|
|
4576
|
-
* a render to reflect these changes.
|
|
4577
|
-
*/
|
|
4578
|
-
setVisibility(visibility) {
|
|
4579
|
-
if (element.isVisible === visibility)
|
|
4580
|
-
return;
|
|
4581
|
-
element.isVisible = visibility;
|
|
4582
|
-
element.scheduleRender();
|
|
4583
|
-
},
|
|
4584
|
-
/**
|
|
4585
|
-
* Make a target animatable by Popmotion. For instance, if we're
|
|
4586
|
-
* trying to animate width from 100px to 100vw we need to measure 100vw
|
|
4587
|
-
* in pixels to determine what we really need to animate to. This is also
|
|
4588
|
-
* pluggable to support Framer's custom value types like Color,
|
|
4589
|
-
* and CSS variables.
|
|
4590
|
-
*/
|
|
4591
|
-
makeTargetAnimatable(target, canMutate = true) {
|
|
4592
|
-
return makeTargetAnimatable(element, target, props, canMutate);
|
|
4593
|
-
},
|
|
4594
|
-
/**
|
|
4595
|
-
* Measure the current viewport box with or without transforms.
|
|
4596
|
-
* Only measures axis-aligned boxes, rotate and skew must be manually
|
|
4597
|
-
* removed with a re-render to work.
|
|
4598
|
-
*/
|
|
4599
|
-
measureViewportBox() {
|
|
4600
|
-
return measureViewportBox(instance, props);
|
|
4601
|
-
},
|
|
4602
|
-
// Motion values ========================
|
|
4603
|
-
/**
|
|
4604
|
-
* Add a motion value and bind it to this visual element.
|
|
4605
|
-
*/
|
|
4606
|
-
addValue(key, value) {
|
|
4607
|
-
// Remove existing value if it exists
|
|
4608
|
-
if (element.hasValue(key))
|
|
4609
|
-
element.removeValue(key);
|
|
4610
|
-
values.set(key, value);
|
|
4611
|
-
latestValues[key] = value.get();
|
|
4612
|
-
bindToMotionValue(key, value);
|
|
4613
|
-
},
|
|
4614
|
-
/**
|
|
4615
|
-
* Remove a motion value and unbind any active subscriptions.
|
|
4616
|
-
*/
|
|
4617
|
-
removeValue(key) {
|
|
4618
|
-
var _a;
|
|
4619
|
-
values.delete(key);
|
|
4620
|
-
(_a = valueSubscriptions.get(key)) === null || _a === void 0 ? void 0 : _a();
|
|
4621
|
-
valueSubscriptions.delete(key);
|
|
4622
|
-
delete latestValues[key];
|
|
4623
|
-
removeValueFromRenderState(key, renderState);
|
|
4624
|
-
},
|
|
4625
|
-
/**
|
|
4626
|
-
* Check whether we have a motion value for this key
|
|
4627
|
-
*/
|
|
4628
|
-
hasValue: (key) => values.has(key),
|
|
4629
|
-
/**
|
|
4630
|
-
* Get a motion value for this key. If called with a default
|
|
4631
|
-
* value, we'll create one if none exists.
|
|
4632
|
-
*/
|
|
4633
|
-
getValue(key, defaultValue) {
|
|
4634
|
-
if (props.values && props.values[key]) {
|
|
4635
|
-
return props.values[key];
|
|
4636
|
-
}
|
|
4637
|
-
let value = values.get(key);
|
|
4638
|
-
if (value === undefined && defaultValue !== undefined) {
|
|
4639
|
-
value = motionValue(defaultValue);
|
|
4640
|
-
element.addValue(key, value);
|
|
4641
|
-
}
|
|
4642
|
-
return value;
|
|
4643
|
-
},
|
|
4644
|
-
/**
|
|
4645
|
-
* Iterate over our motion values.
|
|
4646
|
-
*/
|
|
4647
|
-
forEachValue: (callback) => values.forEach(callback),
|
|
4648
|
-
/**
|
|
4649
|
-
* If we're trying to animate to a previously unencountered value,
|
|
4650
|
-
* we need to check for it in our state and as a last resort read it
|
|
4651
|
-
* directly from the instance (which might have performance implications).
|
|
4652
|
-
*/
|
|
4653
|
-
readValue: (key) => latestValues[key] !== undefined
|
|
4654
|
-
? latestValues[key]
|
|
4655
|
-
: readValueFromInstance(instance, key, options),
|
|
4656
|
-
/**
|
|
4657
|
-
* Set the base target to later animate back to. This is currently
|
|
4658
|
-
* only hydrated on creation and when we first read a value.
|
|
4659
|
-
*/
|
|
4660
|
-
setBaseTarget(key, value) {
|
|
4661
|
-
baseTarget[key] = value;
|
|
4662
|
-
},
|
|
4663
|
-
/**
|
|
4664
|
-
* Find the base target for a value thats been removed from all animation
|
|
4665
|
-
* props.
|
|
4666
|
-
*/
|
|
4667
|
-
getBaseTarget(key) {
|
|
4668
|
-
var _a;
|
|
4669
|
-
const { initial } = props;
|
|
4670
|
-
const valueFromInitial = typeof initial === "string" || typeof initial === "object"
|
|
4671
|
-
? (_a = resolveVariantFromProps(props, initial)) === null || _a === void 0 ? void 0 : _a[key]
|
|
4672
|
-
: undefined;
|
|
4673
|
-
/**
|
|
4674
|
-
* If this value still exists in the current initial variant, read that.
|
|
4675
|
-
*/
|
|
4676
|
-
if (initial && valueFromInitial !== undefined) {
|
|
4677
|
-
return valueFromInitial;
|
|
4678
|
-
}
|
|
4679
|
-
/**
|
|
4680
|
-
* Alternatively, if this VisualElement config has defined a getBaseTarget
|
|
4681
|
-
* so we can read the value from an alternative source, try that.
|
|
4682
|
-
*/
|
|
4683
|
-
if (getBaseTarget) {
|
|
4684
|
-
const target = getBaseTarget(props, key);
|
|
4685
|
-
if (target !== undefined && !isMotionValue(target))
|
|
4686
|
-
return target;
|
|
4687
|
-
}
|
|
4688
|
-
/**
|
|
4689
|
-
* If the value was initially defined on initial, but it doesn't any more,
|
|
4690
|
-
* return undefined. Otherwise return the value as initially read from the DOM.
|
|
4691
|
-
*/
|
|
4692
|
-
return initialValues[key] !== undefined &&
|
|
4693
|
-
valueFromInitial === undefined
|
|
4694
|
-
? undefined
|
|
4695
|
-
: baseTarget[key];
|
|
4696
|
-
},
|
|
4697
|
-
// Lifecyles ========================
|
|
4698
|
-
...lifecycles,
|
|
4699
|
-
/**
|
|
4700
|
-
* Build the renderer state based on the latest visual state.
|
|
4701
|
-
*/
|
|
4702
|
-
build() {
|
|
4703
|
-
triggerBuild();
|
|
4704
|
-
return renderState;
|
|
4705
|
-
},
|
|
4706
|
-
/**
|
|
4707
|
-
* Schedule a render on the next animation frame.
|
|
4708
|
-
*/
|
|
4709
|
-
scheduleRender() {
|
|
4710
|
-
sync__default["default"].render(render, false, true);
|
|
4711
|
-
},
|
|
4712
|
-
/**
|
|
4713
|
-
* Synchronously fire render. It's prefered that we batch renders but
|
|
4714
|
-
* in many circumstances, like layout measurement, we need to run this
|
|
4715
|
-
* synchronously. However in those instances other measures should be taken
|
|
4716
|
-
* to batch reads/writes.
|
|
4717
|
-
*/
|
|
4718
|
-
syncRender: render,
|
|
4719
|
-
/**
|
|
4720
|
-
* Update the provided props. Ensure any newly-added motion values are
|
|
4721
|
-
* added to our map, old ones removed, and listeners updated.
|
|
4722
|
-
*/
|
|
4723
|
-
setProps(newProps) {
|
|
4724
|
-
if (newProps.transformTemplate || props.transformTemplate) {
|
|
4725
|
-
element.scheduleRender();
|
|
4726
|
-
}
|
|
4727
|
-
props = newProps;
|
|
4728
|
-
lifecycles.updatePropListeners(newProps);
|
|
4729
|
-
prevMotionValues = updateMotionValuesFromProps(element, scrapeMotionValuesFromProps(props), prevMotionValues);
|
|
4730
|
-
},
|
|
4731
|
-
getProps: () => props,
|
|
4732
|
-
// Variants ==============================
|
|
4733
|
-
/**
|
|
4734
|
-
* Returns the variant definition with a given name.
|
|
4735
|
-
*/
|
|
4736
|
-
getVariant: (name) => { var _a; return (_a = props.variants) === null || _a === void 0 ? void 0 : _a[name]; },
|
|
4737
|
-
/**
|
|
4738
|
-
* Returns the defined default transition on this component.
|
|
4739
|
-
*/
|
|
4740
|
-
getDefaultTransition: () => props.transition,
|
|
4741
|
-
getTransformPagePoint: () => {
|
|
4742
|
-
return props.transformPagePoint;
|
|
4743
|
-
},
|
|
4744
|
-
/**
|
|
4745
|
-
* Used by child variant nodes to get the closest ancestor variant props.
|
|
4746
|
-
*/
|
|
4747
|
-
getVariantContext(startAtParent = false) {
|
|
4748
|
-
if (startAtParent)
|
|
4749
|
-
return parent === null || parent === void 0 ? void 0 : parent.getVariantContext();
|
|
4750
|
-
if (!isControllingVariants$1) {
|
|
4751
|
-
const context = (parent === null || parent === void 0 ? void 0 : parent.getVariantContext()) || {};
|
|
4752
|
-
if (props.initial !== undefined) {
|
|
4753
|
-
context.initial = props.initial;
|
|
4754
|
-
}
|
|
4755
|
-
return context;
|
|
4756
|
-
}
|
|
4757
|
-
const context = {};
|
|
4758
|
-
for (let i = 0; i < numVariantProps; i++) {
|
|
4759
|
-
const name = variantProps[i];
|
|
4760
|
-
const prop = props[name];
|
|
4761
|
-
if (isVariantLabel(prop) || prop === false) {
|
|
4762
|
-
context[name] = prop;
|
|
4763
|
-
}
|
|
4764
|
-
}
|
|
4765
|
-
return context;
|
|
4766
|
-
},
|
|
4767
|
-
};
|
|
4768
|
-
return element;
|
|
4769
|
-
};
|
|
4770
|
-
const variantProps = ["initial", ...variantPriorityOrder];
|
|
4771
|
-
const numVariantProps = variantProps.length;
|
|
4772
|
-
|
|
4773
4166
|
function isCSSVariable(value) {
|
|
4774
4167
|
return typeof value === "string" && value.startsWith("var(--");
|
|
4775
4168
|
}
|
|
@@ -4816,7 +4209,7 @@ function getVariableValue(current, element, depth = 1) {
|
|
|
4816
4209
|
* @internal
|
|
4817
4210
|
*/
|
|
4818
4211
|
function resolveCSSVariables(visualElement, { ...target }, transitionEnd) {
|
|
4819
|
-
const element = visualElement.
|
|
4212
|
+
const element = visualElement.current;
|
|
4820
4213
|
if (!(element instanceof Element))
|
|
4821
4214
|
return { target, transitionEnd };
|
|
4822
4215
|
// If `transitionEnd` isn't `undefined`, clone it. We could clone `target` and `transitionEnd`
|
|
@@ -4825,7 +4218,7 @@ function resolveCSSVariables(visualElement, { ...target }, transitionEnd) {
|
|
|
4825
4218
|
transitionEnd = { ...transitionEnd };
|
|
4826
4219
|
}
|
|
4827
4220
|
// Go through existing `MotionValue`s and ensure any existing CSS variables are resolved
|
|
4828
|
-
visualElement.
|
|
4221
|
+
visualElement.values.forEach((value) => {
|
|
4829
4222
|
const current = value.get();
|
|
4830
4223
|
if (!isCSSVariable(current))
|
|
4831
4224
|
return;
|
|
@@ -4915,7 +4308,7 @@ function removeNonTranslationalTransform(visualElement) {
|
|
|
4915
4308
|
});
|
|
4916
4309
|
// Apply changes to element before measurement
|
|
4917
4310
|
if (removedTransforms.length)
|
|
4918
|
-
visualElement.
|
|
4311
|
+
visualElement.render();
|
|
4919
4312
|
return removedTransforms;
|
|
4920
4313
|
}
|
|
4921
4314
|
const positionalValues = {
|
|
@@ -4932,7 +4325,7 @@ const positionalValues = {
|
|
|
4932
4325
|
};
|
|
4933
4326
|
const convertChangedValueTypes = (target, visualElement, changedKeys) => {
|
|
4934
4327
|
const originBbox = visualElement.measureViewportBox();
|
|
4935
|
-
const element = visualElement.
|
|
4328
|
+
const element = visualElement.current;
|
|
4936
4329
|
const elementComputedStyle = getComputedStyle(element);
|
|
4937
4330
|
const { display } = elementComputedStyle;
|
|
4938
4331
|
const origin = {};
|
|
@@ -4948,7 +4341,7 @@ const convertChangedValueTypes = (target, visualElement, changedKeys) => {
|
|
|
4948
4341
|
origin[key] = positionalValues[key](originBbox, elementComputedStyle);
|
|
4949
4342
|
});
|
|
4950
4343
|
// Apply the latest values (as set in checkAndConvertChangedValueTypes)
|
|
4951
|
-
visualElement.
|
|
4344
|
+
visualElement.render();
|
|
4952
4345
|
const targetBbox = visualElement.measureViewportBox();
|
|
4953
4346
|
changedKeys.forEach((key) => {
|
|
4954
4347
|
// Restore styles to their **calculated computed style**, not their actual
|
|
@@ -5026,131 +4419,625 @@ const checkAndConvertChangedValueTypes = (visualElement, target, origin = {}, tr
|
|
|
5026
4419
|
target[key] = fromType.transform(to);
|
|
5027
4420
|
}
|
|
5028
4421
|
}
|
|
5029
|
-
else {
|
|
5030
|
-
// If we're going to do value conversion via DOM measurements, we first
|
|
5031
|
-
// need to remove non-positional transform values that could affect the bbox measurements.
|
|
5032
|
-
if (!hasAttemptedToRemoveTransformValues) {
|
|
5033
|
-
removedTransformValues =
|
|
5034
|
-
removeNonTranslationalTransform(visualElement);
|
|
5035
|
-
hasAttemptedToRemoveTransformValues = true;
|
|
4422
|
+
else {
|
|
4423
|
+
// If we're going to do value conversion via DOM measurements, we first
|
|
4424
|
+
// need to remove non-positional transform values that could affect the bbox measurements.
|
|
4425
|
+
if (!hasAttemptedToRemoveTransformValues) {
|
|
4426
|
+
removedTransformValues =
|
|
4427
|
+
removeNonTranslationalTransform(visualElement);
|
|
4428
|
+
hasAttemptedToRemoveTransformValues = true;
|
|
4429
|
+
}
|
|
4430
|
+
changedValueTypeKeys.push(key);
|
|
4431
|
+
transitionEnd[key] =
|
|
4432
|
+
transitionEnd[key] !== undefined
|
|
4433
|
+
? transitionEnd[key]
|
|
4434
|
+
: target[key];
|
|
4435
|
+
setAndResetVelocity(value, to);
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
});
|
|
4439
|
+
if (changedValueTypeKeys.length) {
|
|
4440
|
+
const scrollY = changedValueTypeKeys.indexOf("height") >= 0
|
|
4441
|
+
? window.pageYOffset
|
|
4442
|
+
: null;
|
|
4443
|
+
const convertedTarget = convertChangedValueTypes(target, visualElement, changedValueTypeKeys);
|
|
4444
|
+
// If we removed transform values, reapply them before the next render
|
|
4445
|
+
if (removedTransformValues.length) {
|
|
4446
|
+
removedTransformValues.forEach(([key, value]) => {
|
|
4447
|
+
visualElement.getValue(key).set(value);
|
|
4448
|
+
});
|
|
4449
|
+
}
|
|
4450
|
+
// Reapply original values
|
|
4451
|
+
visualElement.render();
|
|
4452
|
+
// Restore scroll position
|
|
4453
|
+
if (isBrowser && scrollY !== null) {
|
|
4454
|
+
window.scrollTo({ top: scrollY });
|
|
4455
|
+
}
|
|
4456
|
+
return { target: convertedTarget, transitionEnd };
|
|
4457
|
+
}
|
|
4458
|
+
else {
|
|
4459
|
+
return { target, transitionEnd };
|
|
4460
|
+
}
|
|
4461
|
+
};
|
|
4462
|
+
/**
|
|
4463
|
+
* Convert value types for x/y/width/height/top/left/bottom/right
|
|
4464
|
+
*
|
|
4465
|
+
* Allows animation between `'auto'` -> `'100%'` or `0` -> `'calc(50% - 10vw)'`
|
|
4466
|
+
*
|
|
4467
|
+
* @internal
|
|
4468
|
+
*/
|
|
4469
|
+
function unitConversion(visualElement, target, origin, transitionEnd) {
|
|
4470
|
+
return hasPositionalKey(target)
|
|
4471
|
+
? checkAndConvertChangedValueTypes(visualElement, target, origin, transitionEnd)
|
|
4472
|
+
: { target, transitionEnd };
|
|
4473
|
+
}
|
|
4474
|
+
|
|
4475
|
+
/**
|
|
4476
|
+
* Parse a DOM variant to make it animatable. This involves resolving CSS variables
|
|
4477
|
+
* and ensuring animations like "20%" => "calc(50vw)" are performed in pixels.
|
|
4478
|
+
*/
|
|
4479
|
+
const parseDomVariant = (visualElement, target, origin, transitionEnd) => {
|
|
4480
|
+
const resolved = resolveCSSVariables(visualElement, target, transitionEnd);
|
|
4481
|
+
target = resolved.target;
|
|
4482
|
+
transitionEnd = resolved.transitionEnd;
|
|
4483
|
+
return unitConversion(visualElement, target, origin, transitionEnd);
|
|
4484
|
+
};
|
|
4485
|
+
|
|
4486
|
+
// Does this device prefer reduced motion? Returns `null` server-side.
|
|
4487
|
+
const prefersReducedMotion = { current: null };
|
|
4488
|
+
const hasReducedMotionListener = { current: false };
|
|
4489
|
+
|
|
4490
|
+
function initPrefersReducedMotion() {
|
|
4491
|
+
hasReducedMotionListener.current = true;
|
|
4492
|
+
if (!isBrowser)
|
|
4493
|
+
return;
|
|
4494
|
+
if (window.matchMedia) {
|
|
4495
|
+
const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)");
|
|
4496
|
+
const setReducedMotionPreferences = () => (prefersReducedMotion.current = motionMediaQuery.matches);
|
|
4497
|
+
motionMediaQuery.addListener(setReducedMotionPreferences);
|
|
4498
|
+
setReducedMotionPreferences();
|
|
4499
|
+
}
|
|
4500
|
+
else {
|
|
4501
|
+
prefersReducedMotion.current = false;
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
function updateMotionValuesFromProps(element, next, prev) {
|
|
4506
|
+
const { willChange } = next;
|
|
4507
|
+
for (const key in next) {
|
|
4508
|
+
const nextValue = next[key];
|
|
4509
|
+
const prevValue = prev[key];
|
|
4510
|
+
if (isMotionValue(nextValue)) {
|
|
4511
|
+
/**
|
|
4512
|
+
* If this is a motion value found in props or style, we want to add it
|
|
4513
|
+
* to our visual element's motion value map.
|
|
4514
|
+
*/
|
|
4515
|
+
element.addValue(key, nextValue);
|
|
4516
|
+
if (isWillChangeMotionValue(willChange)) {
|
|
4517
|
+
willChange.add(key);
|
|
4518
|
+
}
|
|
4519
|
+
/**
|
|
4520
|
+
* Check the version of the incoming motion value with this version
|
|
4521
|
+
* and warn against mismatches.
|
|
4522
|
+
*/
|
|
4523
|
+
if (process.env.NODE_ENV === "development") {
|
|
4524
|
+
warnOnce(nextValue.version === "7.6.5", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.5 may not work as expected.`);
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
else if (isMotionValue(prevValue)) {
|
|
4528
|
+
/**
|
|
4529
|
+
* If we're swapping from a motion value to a static value,
|
|
4530
|
+
* create a new motion value from that
|
|
4531
|
+
*/
|
|
4532
|
+
element.addValue(key, motionValue(nextValue));
|
|
4533
|
+
if (isWillChangeMotionValue(willChange)) {
|
|
4534
|
+
willChange.remove(key);
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
else if (prevValue !== nextValue) {
|
|
4538
|
+
/**
|
|
4539
|
+
* If this is a flat value that has changed, update the motion value
|
|
4540
|
+
* or create one if it doesn't exist. We only want to do this if we're
|
|
4541
|
+
* not handling the value with our animation state.
|
|
4542
|
+
*/
|
|
4543
|
+
if (element.hasValue(key)) {
|
|
4544
|
+
const existingValue = element.getValue(key);
|
|
4545
|
+
// TODO: Only update values that aren't being animated or even looked at
|
|
4546
|
+
!existingValue.hasAnimated && existingValue.set(nextValue);
|
|
4547
|
+
}
|
|
4548
|
+
else {
|
|
4549
|
+
const latestValue = element.getStaticValue(key);
|
|
4550
|
+
element.addValue(key, motionValue(latestValue !== undefined ? latestValue : nextValue));
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
// Handle removed values
|
|
4555
|
+
for (const key in prev) {
|
|
4556
|
+
if (next[key] === undefined)
|
|
4557
|
+
element.removeValue(key);
|
|
4558
|
+
}
|
|
4559
|
+
return next;
|
|
4560
|
+
}
|
|
4561
|
+
|
|
4562
|
+
const featureNames = Object.keys(featureDefinitions);
|
|
4563
|
+
const numFeatures = featureNames.length;
|
|
4564
|
+
const propEventHandlers = [
|
|
4565
|
+
"AnimationStart",
|
|
4566
|
+
"AnimationComplete",
|
|
4567
|
+
"Update",
|
|
4568
|
+
"Unmount",
|
|
4569
|
+
"BeforeLayoutMeasure",
|
|
4570
|
+
"LayoutMeasure",
|
|
4571
|
+
"LayoutAnimationStart",
|
|
4572
|
+
"LayoutAnimationComplete",
|
|
4573
|
+
];
|
|
4574
|
+
/**
|
|
4575
|
+
* A VisualElement is an imperative abstraction around UI elements such as
|
|
4576
|
+
* HTMLElement, SVGElement, Three.Object3D etc.
|
|
4577
|
+
*/
|
|
4578
|
+
class VisualElement {
|
|
4579
|
+
constructor({ parent, props, reducedMotionConfig, visualState, }, options = {}) {
|
|
4580
|
+
/**
|
|
4581
|
+
* A reference to the current underlying Instance, e.g. a HTMLElement
|
|
4582
|
+
* or Three.Mesh etc.
|
|
4583
|
+
*/
|
|
4584
|
+
this.current = null;
|
|
4585
|
+
/**
|
|
4586
|
+
* A set containing references to this VisualElement's children.
|
|
4587
|
+
*/
|
|
4588
|
+
this.children = new Set();
|
|
4589
|
+
/**
|
|
4590
|
+
* Determine what role this visual element should take in the variant tree.
|
|
4591
|
+
*/
|
|
4592
|
+
this.isVariantNode = false;
|
|
4593
|
+
this.isControllingVariants = false;
|
|
4594
|
+
/**
|
|
4595
|
+
* Decides whether this VisualElement should animate in reduced motion
|
|
4596
|
+
* mode.
|
|
4597
|
+
*
|
|
4598
|
+
* TODO: This is currently set on every individual VisualElement but feels
|
|
4599
|
+
* like it could be set globally.
|
|
4600
|
+
*/
|
|
4601
|
+
this.shouldReduceMotion = null;
|
|
4602
|
+
/**
|
|
4603
|
+
* A map of all motion values attached to this visual element. Motion
|
|
4604
|
+
* values are source of truth for any given animated value. A motion
|
|
4605
|
+
* value might be provided externally by the component via props.
|
|
4606
|
+
*/
|
|
4607
|
+
this.values = new Map();
|
|
4608
|
+
/**
|
|
4609
|
+
* Tracks whether this VisualElement's React component is currently present
|
|
4610
|
+
* within the defined React tree.
|
|
4611
|
+
*/
|
|
4612
|
+
this.isPresent = true;
|
|
4613
|
+
/**
|
|
4614
|
+
* A map of every subscription that binds the provided or generated
|
|
4615
|
+
* motion values onChange listeners to this visual element.
|
|
4616
|
+
*/
|
|
4617
|
+
this.valueSubscriptions = new Map();
|
|
4618
|
+
/**
|
|
4619
|
+
* A reference to the previously-provided motion values as returned
|
|
4620
|
+
* from scrapeMotionValuesFromProps. We use the keys in here to determine
|
|
4621
|
+
* if any motion values need to be removed after props are updated.
|
|
4622
|
+
*/
|
|
4623
|
+
this.prevMotionValues = {};
|
|
4624
|
+
/**
|
|
4625
|
+
* An object containing a SubscriptionManager for each active event.
|
|
4626
|
+
*/
|
|
4627
|
+
this.events = {};
|
|
4628
|
+
/**
|
|
4629
|
+
* An object containing an unsubscribe function for each prop event subscription.
|
|
4630
|
+
* For example, every "Update" event can have multiple subscribers via
|
|
4631
|
+
* VisualElement.on(), but only one of those can be defined via the onUpdate prop.
|
|
4632
|
+
*/
|
|
4633
|
+
this.propEventSubscriptions = {};
|
|
4634
|
+
this.notifyUpdate = () => this.notify("Update", this.latestValues);
|
|
4635
|
+
this.render = () => {
|
|
4636
|
+
if (!this.current)
|
|
4637
|
+
return;
|
|
4638
|
+
this.triggerBuild();
|
|
4639
|
+
this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
|
|
4640
|
+
};
|
|
4641
|
+
this.scheduleRender = () => sync__default["default"].render(this.render, false, true);
|
|
4642
|
+
const { latestValues, renderState } = visualState;
|
|
4643
|
+
this.latestValues = latestValues;
|
|
4644
|
+
this.baseTarget = { ...latestValues };
|
|
4645
|
+
this.initialValues = props.initial ? { ...latestValues } : {};
|
|
4646
|
+
this.renderState = renderState;
|
|
4647
|
+
this.parent = parent;
|
|
4648
|
+
this.props = props;
|
|
4649
|
+
this.depth = parent ? parent.depth + 1 : 0;
|
|
4650
|
+
this.reducedMotionConfig = reducedMotionConfig;
|
|
4651
|
+
this.options = options;
|
|
4652
|
+
this.isControllingVariants = isControllingVariants(props);
|
|
4653
|
+
this.isVariantNode = isVariantNode(props);
|
|
4654
|
+
if (this.isVariantNode) {
|
|
4655
|
+
this.variantChildren = new Set();
|
|
4656
|
+
}
|
|
4657
|
+
this.manuallyAnimateOnMount = Boolean(parent && parent.current);
|
|
4658
|
+
/**
|
|
4659
|
+
* Any motion values that are provided to the element when created
|
|
4660
|
+
* aren't yet bound to the element, as this would technically be impure.
|
|
4661
|
+
* However, we iterate through the motion values and set them to the
|
|
4662
|
+
* initial values for this component.
|
|
4663
|
+
*
|
|
4664
|
+
* TODO: This is impure and we should look at changing this to run on mount.
|
|
4665
|
+
* Doing so will break some tests but this isn't neccessarily a breaking change,
|
|
4666
|
+
* more a reflection of the test.
|
|
4667
|
+
*/
|
|
4668
|
+
const { willChange, ...initialMotionValues } = this.scrapeMotionValuesFromProps(props);
|
|
4669
|
+
for (const key in initialMotionValues) {
|
|
4670
|
+
const value = initialMotionValues[key];
|
|
4671
|
+
if (latestValues[key] !== undefined && isMotionValue(value)) {
|
|
4672
|
+
value.set(latestValues[key], false);
|
|
4673
|
+
if (isWillChangeMotionValue(willChange)) {
|
|
4674
|
+
willChange.add(key);
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
/**
|
|
4679
|
+
* Update external values with initial values
|
|
4680
|
+
*/
|
|
4681
|
+
if (props.values) {
|
|
4682
|
+
for (const key in props.values) {
|
|
4683
|
+
const value = props.values[key];
|
|
4684
|
+
if (latestValues[key] !== undefined && isMotionValue(value)) {
|
|
4685
|
+
value.set(latestValues[key]);
|
|
5036
4686
|
}
|
|
5037
|
-
changedValueTypeKeys.push(key);
|
|
5038
|
-
transitionEnd[key] =
|
|
5039
|
-
transitionEnd[key] !== undefined
|
|
5040
|
-
? transitionEnd[key]
|
|
5041
|
-
: target[key];
|
|
5042
|
-
setAndResetVelocity(value, to);
|
|
5043
4687
|
}
|
|
5044
4688
|
}
|
|
5045
|
-
}
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
4689
|
+
}
|
|
4690
|
+
/**
|
|
4691
|
+
* This method takes React props and returns found MotionValues. For example, HTML
|
|
4692
|
+
* MotionValues will be found within the style prop, whereas for Three.js within attribute arrays.
|
|
4693
|
+
*
|
|
4694
|
+
* This isn't an abstract method as it needs calling in the constructor, but it is
|
|
4695
|
+
* intended to be one.
|
|
4696
|
+
*/
|
|
4697
|
+
scrapeMotionValuesFromProps(_props) {
|
|
4698
|
+
return {};
|
|
4699
|
+
}
|
|
4700
|
+
mount(instance) {
|
|
4701
|
+
var _a;
|
|
4702
|
+
this.current = instance;
|
|
4703
|
+
if (this.projection) {
|
|
4704
|
+
this.projection.mount(instance);
|
|
4705
|
+
}
|
|
4706
|
+
if (this.parent && this.isVariantNode && !this.isControllingVariants) {
|
|
4707
|
+
this.removeFromVariantTree = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.addVariantChild(this);
|
|
4708
|
+
}
|
|
4709
|
+
this.values.forEach((value, key) => this.bindToMotionValue(key, value));
|
|
4710
|
+
if (!hasReducedMotionListener.current) {
|
|
4711
|
+
initPrefersReducedMotion();
|
|
4712
|
+
}
|
|
4713
|
+
this.shouldReduceMotion =
|
|
4714
|
+
this.reducedMotionConfig === "never"
|
|
4715
|
+
? false
|
|
4716
|
+
: this.reducedMotionConfig === "always"
|
|
4717
|
+
? true
|
|
4718
|
+
: prefersReducedMotion.current;
|
|
4719
|
+
if (this.parent)
|
|
4720
|
+
this.parent.children.add(this);
|
|
4721
|
+
this.setProps(this.props);
|
|
4722
|
+
}
|
|
4723
|
+
unmount() {
|
|
4724
|
+
var _a, _b, _c;
|
|
4725
|
+
(_a = this.projection) === null || _a === void 0 ? void 0 : _a.unmount();
|
|
4726
|
+
sync.cancelSync.update(this.notifyUpdate);
|
|
4727
|
+
sync.cancelSync.render(this.render);
|
|
4728
|
+
this.valueSubscriptions.forEach((remove) => remove());
|
|
4729
|
+
(_b = this.removeFromVariantTree) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
4730
|
+
(_c = this.parent) === null || _c === void 0 ? void 0 : _c.children.delete(this);
|
|
4731
|
+
for (const key in this.events) {
|
|
4732
|
+
this.events[key].clear();
|
|
4733
|
+
}
|
|
4734
|
+
this.current = null;
|
|
4735
|
+
}
|
|
4736
|
+
bindToMotionValue(key, value) {
|
|
4737
|
+
const removeOnChange = value.onChange((latestValue) => {
|
|
4738
|
+
this.latestValues[key] = latestValue;
|
|
4739
|
+
this.props.onUpdate &&
|
|
4740
|
+
sync__default["default"].update(this.notifyUpdate, false, true);
|
|
4741
|
+
});
|
|
4742
|
+
const removeOnRenderRequest = value.onRenderRequest(this.scheduleRender);
|
|
4743
|
+
this.valueSubscriptions.set(key, () => {
|
|
4744
|
+
removeOnChange();
|
|
4745
|
+
removeOnRenderRequest();
|
|
4746
|
+
});
|
|
4747
|
+
}
|
|
4748
|
+
sortNodePosition(other) {
|
|
4749
|
+
/**
|
|
4750
|
+
* If these nodes aren't even of the same type we can't compare their depth.
|
|
4751
|
+
*/
|
|
4752
|
+
if (!this.current ||
|
|
4753
|
+
!this.sortInstanceNodePosition ||
|
|
4754
|
+
this.type !== other.type)
|
|
4755
|
+
return 0;
|
|
4756
|
+
return this.sortInstanceNodePosition(this.current, other.current);
|
|
4757
|
+
}
|
|
4758
|
+
loadFeatures(renderedProps, isStrict, preloadedFeatures, projectionId, ProjectionNodeConstructor, initialLayoutGroupConfig) {
|
|
4759
|
+
const features = [];
|
|
4760
|
+
/**
|
|
4761
|
+
* If we're in development mode, check to make sure we're not rendering a motion component
|
|
4762
|
+
* as a child of LazyMotion, as this will break the file-size benefits of using it.
|
|
4763
|
+
*/
|
|
4764
|
+
if (env !== "production" && preloadedFeatures && isStrict) {
|
|
4765
|
+
heyListen.invariant(false, "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.");
|
|
4766
|
+
}
|
|
4767
|
+
for (let i = 0; i < numFeatures; i++) {
|
|
4768
|
+
const name = featureNames[i];
|
|
4769
|
+
const { isEnabled, Component } = featureDefinitions[name];
|
|
4770
|
+
/**
|
|
4771
|
+
* It might be possible in the future to use this moment to
|
|
4772
|
+
* dynamically request functionality. In initial tests this
|
|
4773
|
+
* was producing a lot of duplication amongst bundles.
|
|
4774
|
+
*/
|
|
4775
|
+
if (isEnabled(renderedProps) && Component) {
|
|
4776
|
+
features.push(React.createElement(Component, {
|
|
4777
|
+
key: name,
|
|
4778
|
+
...renderedProps,
|
|
4779
|
+
visualElement: this,
|
|
4780
|
+
}));
|
|
4781
|
+
}
|
|
4782
|
+
}
|
|
4783
|
+
if (!this.projection && ProjectionNodeConstructor) {
|
|
4784
|
+
this.projection = new ProjectionNodeConstructor(projectionId, this.latestValues, this.parent && this.parent.projection);
|
|
4785
|
+
const { layoutId, layout, drag, dragConstraints, layoutScroll } = renderedProps;
|
|
4786
|
+
this.projection.setOptions({
|
|
4787
|
+
layoutId,
|
|
4788
|
+
layout,
|
|
4789
|
+
alwaysMeasureLayout: Boolean(drag) ||
|
|
4790
|
+
(dragConstraints && isRefObject(dragConstraints)),
|
|
4791
|
+
visualElement: this,
|
|
4792
|
+
scheduleRender: () => this.scheduleRender(),
|
|
4793
|
+
/**
|
|
4794
|
+
* TODO: Update options in an effect. This could be tricky as it'll be too late
|
|
4795
|
+
* to update by the time layout animations run.
|
|
4796
|
+
* We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
|
|
4797
|
+
* ensuring it gets called if there's no potential layout animations.
|
|
4798
|
+
*
|
|
4799
|
+
*/
|
|
4800
|
+
animationType: typeof layout === "string" ? layout : "both",
|
|
4801
|
+
initialPromotionConfig: initialLayoutGroupConfig,
|
|
4802
|
+
layoutScroll,
|
|
5055
4803
|
});
|
|
5056
4804
|
}
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
4805
|
+
return features;
|
|
4806
|
+
}
|
|
4807
|
+
triggerBuild() {
|
|
4808
|
+
this.build(this.renderState, this.latestValues, this.options, this.props);
|
|
4809
|
+
}
|
|
4810
|
+
/**
|
|
4811
|
+
* Measure the current viewport box with or without transforms.
|
|
4812
|
+
* Only measures axis-aligned boxes, rotate and skew must be manually
|
|
4813
|
+
* removed with a re-render to work.
|
|
4814
|
+
*/
|
|
4815
|
+
measureViewportBox() {
|
|
4816
|
+
return this.current
|
|
4817
|
+
? this.measureInstanceViewportBox(this.current, this.props)
|
|
4818
|
+
: createBox();
|
|
4819
|
+
}
|
|
4820
|
+
getStaticValue(key) {
|
|
4821
|
+
return this.latestValues[key];
|
|
4822
|
+
}
|
|
4823
|
+
setStaticValue(key, value) {
|
|
4824
|
+
this.latestValues[key] = value;
|
|
4825
|
+
}
|
|
4826
|
+
/**
|
|
4827
|
+
* Make a target animatable by Popmotion. For instance, if we're
|
|
4828
|
+
* trying to animate width from 100px to 100vw we need to measure 100vw
|
|
4829
|
+
* in pixels to determine what we really need to animate to. This is also
|
|
4830
|
+
* pluggable to support Framer's custom value types like Color,
|
|
4831
|
+
* and CSS variables.
|
|
4832
|
+
*/
|
|
4833
|
+
makeTargetAnimatable(target, canMutate = true) {
|
|
4834
|
+
return this.makeTargetAnimatableFromInstance(target, this.props, canMutate);
|
|
4835
|
+
}
|
|
4836
|
+
/**
|
|
4837
|
+
* Update the provided props. Ensure any newly-added motion values are
|
|
4838
|
+
* added to our map, old ones removed, and listeners updated.
|
|
4839
|
+
*/
|
|
4840
|
+
setProps(props) {
|
|
4841
|
+
if (props.transformTemplate || this.props.transformTemplate) {
|
|
4842
|
+
this.scheduleRender();
|
|
5062
4843
|
}
|
|
5063
|
-
|
|
4844
|
+
this.props = props;
|
|
4845
|
+
/**
|
|
4846
|
+
* Update prop event handlers ie onAnimationStart, onAnimationComplete
|
|
4847
|
+
*/
|
|
4848
|
+
for (let i = 0; i < propEventHandlers.length; i++) {
|
|
4849
|
+
const key = propEventHandlers[i];
|
|
4850
|
+
if (this.propEventSubscriptions[key]) {
|
|
4851
|
+
this.propEventSubscriptions[key]();
|
|
4852
|
+
delete this.propEventSubscriptions[key];
|
|
4853
|
+
}
|
|
4854
|
+
const listener = props["on" + key];
|
|
4855
|
+
if (listener) {
|
|
4856
|
+
this.propEventSubscriptions[key] = this.on(key, listener);
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
this.prevMotionValues = updateMotionValuesFromProps(this, this.scrapeMotionValuesFromProps(props), this.prevMotionValues);
|
|
5064
4860
|
}
|
|
5065
|
-
|
|
5066
|
-
return
|
|
4861
|
+
getProps() {
|
|
4862
|
+
return this.props;
|
|
5067
4863
|
}
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
}
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
readValueFromInstance(domElement, key) {
|
|
5099
|
-
if (transformProps.has(key)) {
|
|
5100
|
-
const defaultType = getDefaultValueType(key);
|
|
5101
|
-
return defaultType ? defaultType.default || 0 : 0;
|
|
4864
|
+
/**
|
|
4865
|
+
* Returns the variant definition with a given name.
|
|
4866
|
+
*/
|
|
4867
|
+
getVariant(name) {
|
|
4868
|
+
var _a;
|
|
4869
|
+
return (_a = this.props.variants) === null || _a === void 0 ? void 0 : _a[name];
|
|
4870
|
+
}
|
|
4871
|
+
/**
|
|
4872
|
+
* Returns the defined default transition on this component.
|
|
4873
|
+
*/
|
|
4874
|
+
getDefaultTransition() {
|
|
4875
|
+
return this.props.transition;
|
|
4876
|
+
}
|
|
4877
|
+
getTransformPagePoint() {
|
|
4878
|
+
return this.props.transformPagePoint;
|
|
4879
|
+
}
|
|
4880
|
+
getClosestVariantNode() {
|
|
4881
|
+
var _a;
|
|
4882
|
+
return this.isVariantNode ? this : (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getClosestVariantNode();
|
|
4883
|
+
}
|
|
4884
|
+
getVariantContext(startAtParent = false) {
|
|
4885
|
+
var _a, _b;
|
|
4886
|
+
if (startAtParent)
|
|
4887
|
+
return (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getVariantContext();
|
|
4888
|
+
if (!this.isControllingVariants) {
|
|
4889
|
+
const context = ((_b = this.parent) === null || _b === void 0 ? void 0 : _b.getVariantContext()) || {};
|
|
4890
|
+
if (this.props.initial !== undefined) {
|
|
4891
|
+
context.initial = this.props.initial;
|
|
4892
|
+
}
|
|
4893
|
+
return context;
|
|
5102
4894
|
}
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
const
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
4895
|
+
const context = {};
|
|
4896
|
+
for (let i = 0; i < numVariantProps; i++) {
|
|
4897
|
+
const name = variantProps[i];
|
|
4898
|
+
const prop = this.props[name];
|
|
4899
|
+
if (isVariantLabel(prop) || prop === false) {
|
|
4900
|
+
context[name] = prop;
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
return context;
|
|
4904
|
+
}
|
|
4905
|
+
/**
|
|
4906
|
+
* Add a child visual element to our set of children.
|
|
4907
|
+
*/
|
|
4908
|
+
addVariantChild(child) {
|
|
4909
|
+
var _a;
|
|
4910
|
+
const closestVariantNode = this.getClosestVariantNode();
|
|
4911
|
+
if (closestVariantNode) {
|
|
4912
|
+
(_a = closestVariantNode.variantChildren) === null || _a === void 0 ? void 0 : _a.add(child);
|
|
4913
|
+
return () => closestVariantNode.variantChildren.delete(child);
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4916
|
+
/**
|
|
4917
|
+
* Add a motion value and bind it to this visual element.
|
|
4918
|
+
*/
|
|
4919
|
+
addValue(key, value) {
|
|
4920
|
+
// Remove existing value if it exists
|
|
4921
|
+
if (this.hasValue(key))
|
|
4922
|
+
this.removeValue(key);
|
|
4923
|
+
this.values.set(key, value);
|
|
4924
|
+
this.latestValues[key] = value.get();
|
|
4925
|
+
this.bindToMotionValue(key, value);
|
|
4926
|
+
}
|
|
4927
|
+
/**
|
|
4928
|
+
* Remove a motion value and unbind any active subscriptions.
|
|
4929
|
+
*/
|
|
4930
|
+
removeValue(key) {
|
|
4931
|
+
var _a;
|
|
4932
|
+
this.values.delete(key);
|
|
4933
|
+
(_a = this.valueSubscriptions.get(key)) === null || _a === void 0 ? void 0 : _a();
|
|
4934
|
+
this.valueSubscriptions.delete(key);
|
|
4935
|
+
delete this.latestValues[key];
|
|
4936
|
+
this.removeValueFromRenderState(key, this.renderState);
|
|
4937
|
+
}
|
|
4938
|
+
/**
|
|
4939
|
+
* Check whether we have a motion value for this key
|
|
4940
|
+
*/
|
|
4941
|
+
hasValue(key) {
|
|
4942
|
+
return this.values.has(key);
|
|
4943
|
+
}
|
|
4944
|
+
/**
|
|
4945
|
+
* Get a motion value for this key. If called with a default
|
|
4946
|
+
* value, we'll create one if none exists.
|
|
4947
|
+
*/
|
|
4948
|
+
getValue(key, defaultValue) {
|
|
4949
|
+
if (this.props.values && this.props.values[key]) {
|
|
4950
|
+
return this.props.values[key];
|
|
4951
|
+
}
|
|
4952
|
+
let value = this.values.get(key);
|
|
4953
|
+
if (value === undefined && defaultValue !== undefined) {
|
|
4954
|
+
value = motionValue(defaultValue);
|
|
4955
|
+
this.addValue(key, value);
|
|
4956
|
+
}
|
|
4957
|
+
return value;
|
|
4958
|
+
}
|
|
4959
|
+
/**
|
|
4960
|
+
* If we're trying to animate to a previously unencountered value,
|
|
4961
|
+
* we need to check for it in our state and as a last resort read it
|
|
4962
|
+
* directly from the instance (which might have performance implications).
|
|
4963
|
+
*/
|
|
4964
|
+
readValue(key) {
|
|
4965
|
+
return this.latestValues[key] !== undefined || !this.current
|
|
4966
|
+
? this.latestValues[key]
|
|
4967
|
+
: this.readValueFromInstance(this.current, key, this.options);
|
|
4968
|
+
}
|
|
4969
|
+
/**
|
|
4970
|
+
* Set the base target to later animate back to. This is currently
|
|
4971
|
+
* only hydrated on creation and when we first read a value.
|
|
4972
|
+
*/
|
|
4973
|
+
setBaseTarget(key, value) {
|
|
4974
|
+
this.baseTarget[key] = value;
|
|
4975
|
+
}
|
|
4976
|
+
/**
|
|
4977
|
+
* Find the base target for a value thats been removed from all animation
|
|
4978
|
+
* props.
|
|
4979
|
+
*/
|
|
4980
|
+
getBaseTarget(key) {
|
|
4981
|
+
var _a;
|
|
4982
|
+
const { initial } = this.props;
|
|
4983
|
+
const valueFromInitial = typeof initial === "string" || typeof initial === "object"
|
|
4984
|
+
? (_a = resolveVariantFromProps(this.props, initial)) === null || _a === void 0 ? void 0 : _a[key]
|
|
4985
|
+
: undefined;
|
|
4986
|
+
/**
|
|
4987
|
+
* If this value still exists in the current initial variant, read that.
|
|
4988
|
+
*/
|
|
4989
|
+
if (initial && valueFromInitial !== undefined) {
|
|
4990
|
+
return valueFromInitial;
|
|
5109
4991
|
}
|
|
5110
|
-
|
|
5111
|
-
|
|
4992
|
+
/**
|
|
4993
|
+
* Alternatively, if this VisualElement config has defined a getBaseTarget
|
|
4994
|
+
* so we can read the value from an alternative source, try that.
|
|
4995
|
+
*/
|
|
4996
|
+
const target = this.getBaseTargetFromProps(this.props, key);
|
|
4997
|
+
if (target !== undefined && !isMotionValue(target))
|
|
4998
|
+
return target;
|
|
4999
|
+
/**
|
|
5000
|
+
* If the value was initially defined on initial, but it doesn't any more,
|
|
5001
|
+
* return undefined. Otherwise return the value as initially read from the DOM.
|
|
5002
|
+
*/
|
|
5003
|
+
return this.initialValues[key] !== undefined &&
|
|
5004
|
+
valueFromInitial === undefined
|
|
5005
|
+
? undefined
|
|
5006
|
+
: this.baseTarget[key];
|
|
5007
|
+
}
|
|
5008
|
+
on(eventName, callback) {
|
|
5009
|
+
if (!this.events[eventName]) {
|
|
5010
|
+
this.events[eventName] = new SubscriptionManager();
|
|
5011
|
+
}
|
|
5012
|
+
return this.events[eventName].add(callback);
|
|
5013
|
+
}
|
|
5014
|
+
notify(eventName, ...args) {
|
|
5015
|
+
var _a;
|
|
5016
|
+
(_a = this.events[eventName]) === null || _a === void 0 ? void 0 : _a.notify(...args);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
const variantProps = ["initial", ...variantPriorityOrder];
|
|
5020
|
+
const numVariantProps = variantProps.length;
|
|
5021
|
+
|
|
5022
|
+
class DOMVisualElement extends VisualElement {
|
|
5023
|
+
sortInstanceNodePosition(a, b) {
|
|
5112
5024
|
/**
|
|
5113
5025
|
* compareDocumentPosition returns a bitmask, by using the bitwise &
|
|
5114
5026
|
* we're returning true if 2 in that bitmask is set to true. 2 is set
|
|
5115
5027
|
* to true if b preceeds a.
|
|
5116
5028
|
*/
|
|
5117
5029
|
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
|
|
5118
|
-
}
|
|
5119
|
-
|
|
5030
|
+
}
|
|
5031
|
+
getBaseTargetFromProps(props, key) {
|
|
5120
5032
|
var _a;
|
|
5121
5033
|
return (_a = props.style) === null || _a === void 0 ? void 0 : _a[key];
|
|
5122
|
-
}
|
|
5123
|
-
measureViewportBox(element, { transformPagePoint }) {
|
|
5124
|
-
return measureViewportBox(element, transformPagePoint);
|
|
5125
|
-
},
|
|
5126
|
-
/**
|
|
5127
|
-
* Reset the transform on the current Element. This is called as part
|
|
5128
|
-
* of a batched process across the entire layout tree. To remove this write
|
|
5129
|
-
* cycle it'd be interesting to see if it's possible to "undo" all the current
|
|
5130
|
-
* layout transforms up the tree in the same way this.getBoundingBoxWithoutTransforms
|
|
5131
|
-
* works
|
|
5132
|
-
*/
|
|
5133
|
-
resetTransform(element, domElement, props) {
|
|
5134
|
-
const { transformTemplate } = props;
|
|
5135
|
-
domElement.style.transform = transformTemplate
|
|
5136
|
-
? transformTemplate({}, "")
|
|
5137
|
-
: "none";
|
|
5138
|
-
// Ensure that whatever happens next, we restore our transform on the next frame
|
|
5139
|
-
element.scheduleRender();
|
|
5140
|
-
},
|
|
5141
|
-
restoreTransform(instance, mutableState) {
|
|
5142
|
-
instance.style.transform = mutableState.style.transform;
|
|
5143
|
-
},
|
|
5034
|
+
}
|
|
5144
5035
|
removeValueFromRenderState(key, { vars, style }) {
|
|
5145
5036
|
delete vars[key];
|
|
5146
5037
|
delete style[key];
|
|
5147
|
-
}
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
* can be animated by Motion.
|
|
5151
|
-
*/
|
|
5152
|
-
makeTargetAnimatable(element, { transition, transitionEnd, ...target }, { transformValues }, isMounted = true) {
|
|
5153
|
-
let origin = getOrigin(target, transition || {}, element);
|
|
5038
|
+
}
|
|
5039
|
+
makeTargetAnimatableFromInstance({ transition, transitionEnd, ...target }, { transformValues }, isMounted) {
|
|
5040
|
+
let origin = getOrigin(target, transition || {}, this);
|
|
5154
5041
|
/**
|
|
5155
5042
|
* If Framer has provided a function to convert `Color` etc value types, convert them
|
|
5156
5043
|
*/
|
|
@@ -5163,8 +5050,8 @@ const htmlConfig = {
|
|
|
5163
5050
|
origin = transformValues(origin);
|
|
5164
5051
|
}
|
|
5165
5052
|
if (isMounted) {
|
|
5166
|
-
checkTargetForNewValues(
|
|
5167
|
-
const parsed = parseDomVariant(
|
|
5053
|
+
checkTargetForNewValues(this, target, origin);
|
|
5054
|
+
const parsed = parseDomVariant(this, target, origin, transitionEnd);
|
|
5168
5055
|
transitionEnd = parsed.transitionEnd;
|
|
5169
5056
|
target = parsed.target;
|
|
5170
5057
|
}
|
|
@@ -5173,44 +5060,70 @@ const htmlConfig = {
|
|
|
5173
5060
|
transitionEnd,
|
|
5174
5061
|
...target,
|
|
5175
5062
|
};
|
|
5176
|
-
}
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5065
|
+
|
|
5066
|
+
function getComputedStyle$1(element) {
|
|
5067
|
+
return window.getComputedStyle(element);
|
|
5068
|
+
}
|
|
5069
|
+
class HTMLVisualElement extends DOMVisualElement {
|
|
5070
|
+
readValueFromInstance(instance, key) {
|
|
5071
|
+
if (transformProps.has(key)) {
|
|
5072
|
+
const defaultType = getDefaultValueType(key);
|
|
5073
|
+
return defaultType ? defaultType.default || 0 : 0;
|
|
5074
|
+
}
|
|
5075
|
+
else {
|
|
5076
|
+
const computedStyle = getComputedStyle$1(instance);
|
|
5077
|
+
const value = (isCSSVariable$1(key)
|
|
5078
|
+
? computedStyle.getPropertyValue(key)
|
|
5079
|
+
: computedStyle[key]) || 0;
|
|
5080
|
+
return typeof value === "string" ? value.trim() : value;
|
|
5183
5081
|
}
|
|
5082
|
+
}
|
|
5083
|
+
measureInstanceViewportBox(instance, { transformPagePoint }) {
|
|
5084
|
+
return measureViewportBox(instance, transformPagePoint);
|
|
5085
|
+
}
|
|
5086
|
+
build(renderState, latestValues, options, props) {
|
|
5184
5087
|
buildHTMLStyles(renderState, latestValues, options, props.transformTemplate);
|
|
5185
|
-
}
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5088
|
+
}
|
|
5089
|
+
scrapeMotionValuesFromProps(props) {
|
|
5090
|
+
return scrapeMotionValuesFromProps$1(props);
|
|
5091
|
+
}
|
|
5092
|
+
renderInstance(instance, renderState, styleProp, projection) {
|
|
5093
|
+
renderHTML(instance, renderState, styleProp, projection);
|
|
5094
|
+
}
|
|
5095
|
+
}
|
|
5189
5096
|
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
getBaseTarget(props, key) {
|
|
5097
|
+
class SVGVisualElement extends DOMVisualElement {
|
|
5098
|
+
getBaseTargetFromProps(props, key) {
|
|
5193
5099
|
return props[key];
|
|
5194
|
-
}
|
|
5195
|
-
readValueFromInstance(
|
|
5100
|
+
}
|
|
5101
|
+
readValueFromInstance(instance, key) {
|
|
5196
5102
|
var _a;
|
|
5197
5103
|
if (transformProps.has(key)) {
|
|
5198
5104
|
return ((_a = getDefaultValueType(key)) === null || _a === void 0 ? void 0 : _a.default) || 0;
|
|
5199
5105
|
}
|
|
5200
5106
|
key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
|
|
5201
|
-
return
|
|
5202
|
-
}
|
|
5203
|
-
|
|
5204
|
-
|
|
5107
|
+
return instance.getAttribute(key);
|
|
5108
|
+
}
|
|
5109
|
+
measureInstanceViewportBox() {
|
|
5110
|
+
return createBox();
|
|
5111
|
+
}
|
|
5112
|
+
scrapeMotionValuesFromProps(props) {
|
|
5113
|
+
return scrapeMotionValuesFromProps(props);
|
|
5114
|
+
}
|
|
5115
|
+
build(renderState, latestValues, options, props) {
|
|
5205
5116
|
buildSVGAttrs(renderState, latestValues, options, props.transformTemplate);
|
|
5206
|
-
}
|
|
5207
|
-
|
|
5208
|
-
|
|
5117
|
+
}
|
|
5118
|
+
renderInstance(instance, renderState, styleProp, projection) {
|
|
5119
|
+
renderSVG(instance, renderState, styleProp, projection);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5209
5122
|
|
|
5210
5123
|
const createDomVisualElement = (Component, options) => {
|
|
5211
5124
|
return isSVGComponent(Component)
|
|
5212
|
-
?
|
|
5213
|
-
:
|
|
5125
|
+
? new SVGVisualElement(options, { enableHardwareAcceleration: false })
|
|
5126
|
+
: new HTMLVisualElement(options, { enableHardwareAcceleration: true });
|
|
5214
5127
|
};
|
|
5215
5128
|
|
|
5216
5129
|
function pixelsToPercent(pixels, axis) {
|
|
@@ -5931,7 +5844,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5931
5844
|
instance instanceof SVGElement && instance.tagName !== "svg";
|
|
5932
5845
|
this.instance = instance;
|
|
5933
5846
|
const { layoutId, layout, visualElement } = this.options;
|
|
5934
|
-
if (visualElement && !visualElement.
|
|
5847
|
+
if (visualElement && !visualElement.current) {
|
|
5935
5848
|
visualElement.mount(instance);
|
|
5936
5849
|
}
|
|
5937
5850
|
this.root.nodes.add(this);
|
|
@@ -6195,7 +6108,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6195
6108
|
this.isLayoutDirty = false;
|
|
6196
6109
|
this.projectionDelta = undefined;
|
|
6197
6110
|
this.notifyListeners("measure", this.layout.actual);
|
|
6198
|
-
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.
|
|
6111
|
+
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notify("LayoutMeasure", this.layout.actual, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.actual);
|
|
6199
6112
|
}
|
|
6200
6113
|
updateScroll() {
|
|
6201
6114
|
if (this.options.layoutScroll && this.instance) {
|
|
@@ -6353,13 +6266,17 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6353
6266
|
// TODO If this is unsuccessful this currently happens every frame
|
|
6354
6267
|
if (!this.targetDelta && !this.relativeTarget) {
|
|
6355
6268
|
// TODO: This is a semi-repetition of further down this function, make DRY
|
|
6356
|
-
|
|
6357
|
-
if (
|
|
6269
|
+
const relativeParent = this.getClosestProjectingParent();
|
|
6270
|
+
if (relativeParent && relativeParent.layout) {
|
|
6271
|
+
this.relativeParent = relativeParent;
|
|
6358
6272
|
this.relativeTarget = createBox();
|
|
6359
6273
|
this.relativeTargetOrigin = createBox();
|
|
6360
|
-
calcRelativePosition(this.relativeTargetOrigin, this.layout.actual,
|
|
6274
|
+
calcRelativePosition(this.relativeTargetOrigin, this.layout.actual, relativeParent.layout.actual);
|
|
6361
6275
|
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
6362
6276
|
}
|
|
6277
|
+
else {
|
|
6278
|
+
this.relativeParent = this.relativeTarget = undefined;
|
|
6279
|
+
}
|
|
6363
6280
|
}
|
|
6364
6281
|
/**
|
|
6365
6282
|
* If we have no relative target or no target delta our target isn't valid
|
|
@@ -6406,17 +6323,21 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6406
6323
|
*/
|
|
6407
6324
|
if (this.attemptToResolveRelativeTarget) {
|
|
6408
6325
|
this.attemptToResolveRelativeTarget = false;
|
|
6409
|
-
|
|
6410
|
-
if (
|
|
6411
|
-
Boolean(
|
|
6326
|
+
const relativeParent = this.getClosestProjectingParent();
|
|
6327
|
+
if (relativeParent &&
|
|
6328
|
+
Boolean(relativeParent.resumingFrom) ===
|
|
6412
6329
|
Boolean(this.resumingFrom) &&
|
|
6413
|
-
!
|
|
6414
|
-
|
|
6330
|
+
!relativeParent.options.layoutScroll &&
|
|
6331
|
+
relativeParent.target) {
|
|
6332
|
+
this.relativeParent = relativeParent;
|
|
6415
6333
|
this.relativeTarget = createBox();
|
|
6416
6334
|
this.relativeTargetOrigin = createBox();
|
|
6417
|
-
calcRelativePosition(this.relativeTargetOrigin, this.target,
|
|
6335
|
+
calcRelativePosition(this.relativeTargetOrigin, this.target, relativeParent.target);
|
|
6418
6336
|
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
6419
6337
|
}
|
|
6338
|
+
else {
|
|
6339
|
+
this.relativeParent = this.relativeTarget = undefined;
|
|
6340
|
+
}
|
|
6420
6341
|
}
|
|
6421
6342
|
}
|
|
6422
6343
|
getClosestProjectingParent() {
|
|
@@ -6715,7 +6636,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6715
6636
|
return;
|
|
6716
6637
|
// Force a render of this element to apply the transform with all rotations
|
|
6717
6638
|
// set to 0.
|
|
6718
|
-
visualElement === null || visualElement === void 0 ? void 0 : visualElement.
|
|
6639
|
+
visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
|
|
6719
6640
|
// Put back all the values we reset
|
|
6720
6641
|
for (const key in resetValues) {
|
|
6721
6642
|
visualElement.setStaticValue(key, resetValues[key]);
|
|
@@ -6887,13 +6808,13 @@ function notifyLayoutUpdate(node) {
|
|
|
6887
6808
|
const hasLayoutChanged = !isDeltaZero(layoutDelta);
|
|
6888
6809
|
let hasRelativeTargetChanged = false;
|
|
6889
6810
|
if (!node.resumeFrom) {
|
|
6890
|
-
|
|
6811
|
+
const relativeParent = node.getClosestProjectingParent();
|
|
6891
6812
|
/**
|
|
6892
6813
|
* If the relativeParent is itself resuming from a different element then
|
|
6893
6814
|
* the relative snapshot is not relavent
|
|
6894
6815
|
*/
|
|
6895
|
-
if (
|
|
6896
|
-
const { snapshot: parentSnapshot, layout: parentLayout } =
|
|
6816
|
+
if (relativeParent && !relativeParent.resumeFrom) {
|
|
6817
|
+
const { snapshot: parentSnapshot, layout: parentLayout } = relativeParent;
|
|
6897
6818
|
if (parentSnapshot && parentLayout) {
|
|
6898
6819
|
const relativeSnapshot = createBox();
|
|
6899
6820
|
calcRelativePosition(relativeSnapshot, snapshot.layout, parentSnapshot.layout);
|
|
@@ -6933,7 +6854,7 @@ function clearMeasurements(node) {
|
|
|
6933
6854
|
function resetTransformStyle(node) {
|
|
6934
6855
|
const { visualElement } = node.options;
|
|
6935
6856
|
if (visualElement === null || visualElement === void 0 ? void 0 : visualElement.getProps().onBeforeLayoutMeasure) {
|
|
6936
|
-
visualElement.
|
|
6857
|
+
visualElement.notify("BeforeLayoutMeasure");
|
|
6937
6858
|
}
|
|
6938
6859
|
node.resetTransform();
|
|
6939
6860
|
}
|
|
@@ -8333,23 +8254,33 @@ function useResetProjection() {
|
|
|
8333
8254
|
}
|
|
8334
8255
|
|
|
8335
8256
|
const createObject = () => ({});
|
|
8336
|
-
|
|
8337
|
-
build() { }
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8257
|
+
class StateVisualElement extends VisualElement {
|
|
8258
|
+
build() { }
|
|
8259
|
+
measureInstanceViewportBox() {
|
|
8260
|
+
return createBox();
|
|
8261
|
+
}
|
|
8262
|
+
resetTransform() { }
|
|
8263
|
+
restoreTransform() { }
|
|
8264
|
+
removeValueFromRenderState() { }
|
|
8265
|
+
renderInstance() { }
|
|
8266
|
+
scrapeMotionValuesFromProps() {
|
|
8267
|
+
return createObject();
|
|
8268
|
+
}
|
|
8269
|
+
getBaseTargetFromProps() {
|
|
8270
|
+
return undefined;
|
|
8271
|
+
}
|
|
8344
8272
|
readValueFromInstance(_state, key, options) {
|
|
8345
8273
|
return options.initialState[key] || 0;
|
|
8346
|
-
}
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8274
|
+
}
|
|
8275
|
+
sortInstanceNodePosition() {
|
|
8276
|
+
return 0;
|
|
8277
|
+
}
|
|
8278
|
+
makeTargetAnimatableFromInstance({ transition, transitionEnd, ...target }) {
|
|
8279
|
+
const origin = getOrigin(target, transition || {}, this);
|
|
8280
|
+
checkTargetForNewValues(this, target, origin);
|
|
8350
8281
|
return { transition, transitionEnd, ...target };
|
|
8351
|
-
}
|
|
8352
|
-
}
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8353
8284
|
const useVisualState = makeUseVisualState({
|
|
8354
8285
|
scrapeMotionValuesFromProps: createObject,
|
|
8355
8286
|
createRenderState: createObject,
|
|
@@ -8361,10 +8292,12 @@ const useVisualState = makeUseVisualState({
|
|
|
8361
8292
|
function useAnimatedState(initialState) {
|
|
8362
8293
|
const [animationState, setAnimationState] = React.useState(initialState);
|
|
8363
8294
|
const visualState = useVisualState({}, false);
|
|
8364
|
-
const element = useConstant(() =>
|
|
8295
|
+
const element = useConstant(() => {
|
|
8296
|
+
return new StateVisualElement({ props: {}, visualState }, { initialState });
|
|
8297
|
+
});
|
|
8365
8298
|
React.useEffect(() => {
|
|
8366
8299
|
element.mount({});
|
|
8367
|
-
return element.unmount;
|
|
8300
|
+
return () => element.unmount();
|
|
8368
8301
|
}, [element]);
|
|
8369
8302
|
React.useEffect(() => {
|
|
8370
8303
|
element.setProps({
|
|
@@ -8439,6 +8372,7 @@ exports.MotionValue = MotionValue;
|
|
|
8439
8372
|
exports.PresenceContext = PresenceContext;
|
|
8440
8373
|
exports.Reorder = Reorder;
|
|
8441
8374
|
exports.SwitchLayoutGroupContext = SwitchLayoutGroupContext;
|
|
8375
|
+
exports.VisualElement = VisualElement;
|
|
8442
8376
|
exports.addPointerEvent = addPointerEvent;
|
|
8443
8377
|
exports.addScaleCorrector = addScaleCorrector;
|
|
8444
8378
|
exports.animate = animate;
|
|
@@ -8497,5 +8431,4 @@ exports.useVelocity = useVelocity;
|
|
|
8497
8431
|
exports.useViewportScroll = useViewportScroll;
|
|
8498
8432
|
exports.useVisualElementContext = useVisualElementContext;
|
|
8499
8433
|
exports.useWillChange = useWillChange;
|
|
8500
|
-
exports.visualElement = visualElement;
|
|
8501
8434
|
exports.wrapHandler = wrapHandler;
|