motion 12.0.5 → 12.0.8-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +43 -12
- package/dist/cjs/react-client.js +504 -486
- package/dist/cjs/react-m.js +494 -494
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/index.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +6 -1
- package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +3 -0
- package/dist/es/framer-motion/dist/es/render/components/create-factory.mjs +2 -2
- package/dist/es/framer-motion/dist/es/render/svg/SVGVisualElement.mjs +12 -0
- package/dist/es/framer-motion/dist/es/render/svg/config-motion.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/value/index.mjs +1 -1
- package/dist/motion.dev.js +43 -12
- package/dist/motion.js +1 -1
- package/package.json +3 -3
package/dist/cjs/react-client.js
CHANGED
|
@@ -916,7 +916,7 @@ class MotionValue {
|
|
|
916
916
|
* This will be replaced by the build step with the latest version number.
|
|
917
917
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
918
918
|
*/
|
|
919
|
-
this.version = "12.0.
|
|
919
|
+
this.version = "12.0.8-alpha.0";
|
|
920
920
|
/**
|
|
921
921
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
922
922
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -6778,6 +6778,11 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
6778
6778
|
if (this.snapshot || !this.instance)
|
|
6779
6779
|
return;
|
|
6780
6780
|
this.snapshot = this.measure();
|
|
6781
|
+
if (this.snapshot &&
|
|
6782
|
+
!calcLength(this.snapshot.measuredBox.x) &&
|
|
6783
|
+
!calcLength(this.snapshot.measuredBox.y)) {
|
|
6784
|
+
this.snapshot = undefined;
|
|
6785
|
+
}
|
|
6781
6786
|
}
|
|
6782
6787
|
updateLayout() {
|
|
6783
6788
|
if (!this.instance)
|
|
@@ -8457,156 +8462,11 @@ function getProjectionFunctionality(props) {
|
|
|
8457
8462
|
};
|
|
8458
8463
|
}
|
|
8459
8464
|
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
"animate",
|
|
8466
|
-
"circle",
|
|
8467
|
-
"defs",
|
|
8468
|
-
"desc",
|
|
8469
|
-
"ellipse",
|
|
8470
|
-
"g",
|
|
8471
|
-
"image",
|
|
8472
|
-
"line",
|
|
8473
|
-
"filter",
|
|
8474
|
-
"marker",
|
|
8475
|
-
"mask",
|
|
8476
|
-
"metadata",
|
|
8477
|
-
"path",
|
|
8478
|
-
"pattern",
|
|
8479
|
-
"polygon",
|
|
8480
|
-
"polyline",
|
|
8481
|
-
"rect",
|
|
8482
|
-
"stop",
|
|
8483
|
-
"switch",
|
|
8484
|
-
"symbol",
|
|
8485
|
-
"svg",
|
|
8486
|
-
"text",
|
|
8487
|
-
"tspan",
|
|
8488
|
-
"use",
|
|
8489
|
-
"view",
|
|
8490
|
-
];
|
|
8491
|
-
|
|
8492
|
-
function isSVGComponent(Component) {
|
|
8493
|
-
if (
|
|
8494
|
-
/**
|
|
8495
|
-
* If it's not a string, it's a custom React component. Currently we only support
|
|
8496
|
-
* HTML custom React components.
|
|
8497
|
-
*/
|
|
8498
|
-
typeof Component !== "string" ||
|
|
8499
|
-
/**
|
|
8500
|
-
* If it contains a dash, the element is a custom HTML webcomponent.
|
|
8501
|
-
*/
|
|
8502
|
-
Component.includes("-")) {
|
|
8503
|
-
return false;
|
|
8504
|
-
}
|
|
8505
|
-
else if (
|
|
8506
|
-
/**
|
|
8507
|
-
* If it's in our list of lowercase SVG tags, it's an SVG component
|
|
8508
|
-
*/
|
|
8509
|
-
lowercaseSVGElements.indexOf(Component) > -1 ||
|
|
8510
|
-
/**
|
|
8511
|
-
* If it contains a capital letter, it's an SVG component
|
|
8512
|
-
*/
|
|
8513
|
-
/[A-Z]/u.test(Component)) {
|
|
8514
|
-
return true;
|
|
8515
|
-
}
|
|
8516
|
-
return false;
|
|
8517
|
-
}
|
|
8518
|
-
|
|
8519
|
-
/**
|
|
8520
|
-
* Creates a constant value over the lifecycle of a component.
|
|
8521
|
-
*
|
|
8522
|
-
* Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
|
|
8523
|
-
* a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
|
|
8524
|
-
* you can ensure that initialisers don't execute twice or more.
|
|
8525
|
-
*/
|
|
8526
|
-
function useConstant(init) {
|
|
8527
|
-
const ref = react.useRef(null);
|
|
8528
|
-
if (ref.current === null) {
|
|
8529
|
-
ref.current = init();
|
|
8530
|
-
}
|
|
8531
|
-
return ref.current;
|
|
8532
|
-
}
|
|
8533
|
-
|
|
8534
|
-
function makeState({ scrapeMotionValuesFromProps, createRenderState, onUpdate, }, props, context, presenceContext) {
|
|
8535
|
-
const state = {
|
|
8536
|
-
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
|
|
8537
|
-
renderState: createRenderState(),
|
|
8538
|
-
};
|
|
8539
|
-
if (onUpdate) {
|
|
8540
|
-
/**
|
|
8541
|
-
* onMount works without the VisualElement because it could be
|
|
8542
|
-
* called before the VisualElement payload has been hydrated.
|
|
8543
|
-
* (e.g. if someone is using m components <m.circle />)
|
|
8544
|
-
*/
|
|
8545
|
-
state.onMount = (instance) => onUpdate({ props, current: instance, ...state });
|
|
8546
|
-
state.onUpdate = (visualElement) => onUpdate(visualElement);
|
|
8547
|
-
}
|
|
8548
|
-
return state;
|
|
8549
|
-
}
|
|
8550
|
-
const makeUseVisualState = (config) => (props, isStatic) => {
|
|
8551
|
-
const context = react.useContext(MotionContext);
|
|
8552
|
-
const presenceContext = react.useContext(PresenceContext);
|
|
8553
|
-
const make = () => makeState(config, props, context, presenceContext);
|
|
8554
|
-
return isStatic ? make() : useConstant(make);
|
|
8555
|
-
};
|
|
8556
|
-
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
|
8557
|
-
const values = {};
|
|
8558
|
-
const motionValues = scrapeMotionValues(props, {});
|
|
8559
|
-
for (const key in motionValues) {
|
|
8560
|
-
values[key] = resolveMotionValue(motionValues[key]);
|
|
8561
|
-
}
|
|
8562
|
-
let { initial, animate } = props;
|
|
8563
|
-
const isControllingVariants$1 = isControllingVariants(props);
|
|
8564
|
-
const isVariantNode$1 = isVariantNode(props);
|
|
8565
|
-
if (context &&
|
|
8566
|
-
isVariantNode$1 &&
|
|
8567
|
-
!isControllingVariants$1 &&
|
|
8568
|
-
props.inherit !== false) {
|
|
8569
|
-
if (initial === undefined)
|
|
8570
|
-
initial = context.initial;
|
|
8571
|
-
if (animate === undefined)
|
|
8572
|
-
animate = context.animate;
|
|
8573
|
-
}
|
|
8574
|
-
let isInitialAnimationBlocked = presenceContext
|
|
8575
|
-
? presenceContext.initial === false
|
|
8576
|
-
: false;
|
|
8577
|
-
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
|
8578
|
-
const variantToSet = isInitialAnimationBlocked ? animate : initial;
|
|
8579
|
-
if (variantToSet &&
|
|
8580
|
-
typeof variantToSet !== "boolean" &&
|
|
8581
|
-
!isAnimationControls(variantToSet)) {
|
|
8582
|
-
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
|
8583
|
-
for (let i = 0; i < list.length; i++) {
|
|
8584
|
-
const resolved = resolveVariantFromProps(props, list[i]);
|
|
8585
|
-
if (resolved) {
|
|
8586
|
-
const { transitionEnd, transition, ...target } = resolved;
|
|
8587
|
-
for (const key in target) {
|
|
8588
|
-
let valueTarget = target[key];
|
|
8589
|
-
if (Array.isArray(valueTarget)) {
|
|
8590
|
-
/**
|
|
8591
|
-
* Take final keyframe if the initial animation is blocked because
|
|
8592
|
-
* we want to initialise at the end of that blocked animation.
|
|
8593
|
-
*/
|
|
8594
|
-
const index = isInitialAnimationBlocked
|
|
8595
|
-
? valueTarget.length - 1
|
|
8596
|
-
: 0;
|
|
8597
|
-
valueTarget = valueTarget[index];
|
|
8598
|
-
}
|
|
8599
|
-
if (valueTarget !== null) {
|
|
8600
|
-
values[key] = valueTarget;
|
|
8601
|
-
}
|
|
8602
|
-
}
|
|
8603
|
-
for (const key in transitionEnd) {
|
|
8604
|
-
values[key] = transitionEnd[key];
|
|
8605
|
-
}
|
|
8606
|
-
}
|
|
8607
|
-
}
|
|
8608
|
-
}
|
|
8609
|
-
return values;
|
|
8465
|
+
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
8466
|
+
return (transformProps.has(key) ||
|
|
8467
|
+
key.startsWith("origin") ||
|
|
8468
|
+
((layout || layoutId !== undefined) &&
|
|
8469
|
+
(!!scaleCorrectors[key] || key === "opacity")));
|
|
8610
8470
|
}
|
|
8611
8471
|
|
|
8612
8472
|
/**
|
|
@@ -8733,97 +8593,6 @@ function buildHTMLStyles(state, latestValues, transformTemplate) {
|
|
|
8733
8593
|
}
|
|
8734
8594
|
}
|
|
8735
8595
|
|
|
8736
|
-
const dashKeys = {
|
|
8737
|
-
offset: "stroke-dashoffset",
|
|
8738
|
-
array: "stroke-dasharray",
|
|
8739
|
-
};
|
|
8740
|
-
const camelKeys = {
|
|
8741
|
-
offset: "strokeDashoffset",
|
|
8742
|
-
array: "strokeDasharray",
|
|
8743
|
-
};
|
|
8744
|
-
/**
|
|
8745
|
-
* Build SVG path properties. Uses the path's measured length to convert
|
|
8746
|
-
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8747
|
-
* and stroke-dasharray attributes.
|
|
8748
|
-
*
|
|
8749
|
-
* This function is mutative to reduce per-frame GC.
|
|
8750
|
-
*/
|
|
8751
|
-
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8752
|
-
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8753
|
-
attrs.pathLength = 1;
|
|
8754
|
-
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8755
|
-
// when defining props on a React component.
|
|
8756
|
-
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8757
|
-
// Build the dash offset
|
|
8758
|
-
attrs[keys.offset] = px.transform(-offset);
|
|
8759
|
-
// Build the dash array
|
|
8760
|
-
const pathLength = px.transform(length);
|
|
8761
|
-
const pathSpacing = px.transform(spacing);
|
|
8762
|
-
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8763
|
-
}
|
|
8764
|
-
|
|
8765
|
-
function calcOrigin(origin, offset, size) {
|
|
8766
|
-
return typeof origin === "string"
|
|
8767
|
-
? origin
|
|
8768
|
-
: px.transform(offset + size * origin);
|
|
8769
|
-
}
|
|
8770
|
-
/**
|
|
8771
|
-
* The SVG transform origin defaults are different to CSS and is less intuitive,
|
|
8772
|
-
* so we use the measured dimensions of the SVG to reconcile these.
|
|
8773
|
-
*/
|
|
8774
|
-
function calcSVGTransformOrigin(dimensions, originX, originY) {
|
|
8775
|
-
const pxOriginX = calcOrigin(originX, dimensions.x, dimensions.width);
|
|
8776
|
-
const pxOriginY = calcOrigin(originY, dimensions.y, dimensions.height);
|
|
8777
|
-
return `${pxOriginX} ${pxOriginY}`;
|
|
8778
|
-
}
|
|
8779
|
-
|
|
8780
|
-
/**
|
|
8781
|
-
* Build SVG visual attrbutes, like cx and style.transform
|
|
8782
|
-
*/
|
|
8783
|
-
function buildSVGAttrs(state, { attrX, attrY, attrScale, originX, originY, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8784
|
-
// This is object creation, which we try to avoid per-frame.
|
|
8785
|
-
...latest }, isSVGTag, transformTemplate) {
|
|
8786
|
-
buildHTMLStyles(state, latest, transformTemplate);
|
|
8787
|
-
/**
|
|
8788
|
-
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8789
|
-
* as normal HTML tags.
|
|
8790
|
-
*/
|
|
8791
|
-
if (isSVGTag) {
|
|
8792
|
-
if (state.style.viewBox) {
|
|
8793
|
-
state.attrs.viewBox = state.style.viewBox;
|
|
8794
|
-
}
|
|
8795
|
-
return;
|
|
8796
|
-
}
|
|
8797
|
-
state.attrs = state.style;
|
|
8798
|
-
state.style = {};
|
|
8799
|
-
const { attrs, style, dimensions } = state;
|
|
8800
|
-
/**
|
|
8801
|
-
* However, we apply transforms as CSS transforms. So if we detect a transform we take it from attrs
|
|
8802
|
-
* and copy it into style.
|
|
8803
|
-
*/
|
|
8804
|
-
if (attrs.transform) {
|
|
8805
|
-
if (dimensions)
|
|
8806
|
-
style.transform = attrs.transform;
|
|
8807
|
-
delete attrs.transform;
|
|
8808
|
-
}
|
|
8809
|
-
// Parse transformOrigin
|
|
8810
|
-
if (dimensions &&
|
|
8811
|
-
(originX !== undefined || originY !== undefined || style.transform)) {
|
|
8812
|
-
style.transformOrigin = calcSVGTransformOrigin(dimensions, originX !== undefined ? originX : 0.5, originY !== undefined ? originY : 0.5);
|
|
8813
|
-
}
|
|
8814
|
-
// Render attrX/attrY/attrScale as attributes
|
|
8815
|
-
if (attrX !== undefined)
|
|
8816
|
-
attrs.x = attrX;
|
|
8817
|
-
if (attrY !== undefined)
|
|
8818
|
-
attrs.y = attrY;
|
|
8819
|
-
if (attrScale !== undefined)
|
|
8820
|
-
attrs.scale = attrScale;
|
|
8821
|
-
// Build SVG path if one has been defined
|
|
8822
|
-
if (pathLength !== undefined) {
|
|
8823
|
-
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8824
|
-
}
|
|
8825
|
-
}
|
|
8826
|
-
|
|
8827
8596
|
const createHtmlRenderState = () => ({
|
|
8828
8597
|
style: {},
|
|
8829
8598
|
transform: {},
|
|
@@ -8831,15 +8600,485 @@ const createHtmlRenderState = () => ({
|
|
|
8831
8600
|
vars: {},
|
|
8832
8601
|
});
|
|
8833
8602
|
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
function
|
|
8842
|
-
|
|
8603
|
+
function copyRawValuesOnly(target, source, props) {
|
|
8604
|
+
for (const key in source) {
|
|
8605
|
+
if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
8606
|
+
target[key] = source[key];
|
|
8607
|
+
}
|
|
8608
|
+
}
|
|
8609
|
+
}
|
|
8610
|
+
function useInitialMotionValues({ transformTemplate }, visualState) {
|
|
8611
|
+
return react.useMemo(() => {
|
|
8612
|
+
const state = createHtmlRenderState();
|
|
8613
|
+
buildHTMLStyles(state, visualState, transformTemplate);
|
|
8614
|
+
return Object.assign({}, state.vars, state.style);
|
|
8615
|
+
}, [visualState]);
|
|
8616
|
+
}
|
|
8617
|
+
function useStyle(props, visualState) {
|
|
8618
|
+
const styleProp = props.style || {};
|
|
8619
|
+
const style = {};
|
|
8620
|
+
/**
|
|
8621
|
+
* Copy non-Motion Values straight into style
|
|
8622
|
+
*/
|
|
8623
|
+
copyRawValuesOnly(style, styleProp, props);
|
|
8624
|
+
Object.assign(style, useInitialMotionValues(props, visualState));
|
|
8625
|
+
return style;
|
|
8626
|
+
}
|
|
8627
|
+
function useHTMLProps(props, visualState) {
|
|
8628
|
+
// The `any` isn't ideal but it is the type of createElement props argument
|
|
8629
|
+
const htmlProps = {};
|
|
8630
|
+
const style = useStyle(props, visualState);
|
|
8631
|
+
if (props.drag && props.dragListener !== false) {
|
|
8632
|
+
// Disable the ghost element when a user drags
|
|
8633
|
+
htmlProps.draggable = false;
|
|
8634
|
+
// Disable text selection
|
|
8635
|
+
style.userSelect =
|
|
8636
|
+
style.WebkitUserSelect =
|
|
8637
|
+
style.WebkitTouchCallout =
|
|
8638
|
+
"none";
|
|
8639
|
+
// Disable scrolling on the draggable direction
|
|
8640
|
+
style.touchAction =
|
|
8641
|
+
props.drag === true
|
|
8642
|
+
? "none"
|
|
8643
|
+
: `pan-${props.drag === "x" ? "y" : "x"}`;
|
|
8644
|
+
}
|
|
8645
|
+
if (props.tabIndex === undefined &&
|
|
8646
|
+
(props.onTap || props.onTapStart || props.whileTap)) {
|
|
8647
|
+
htmlProps.tabIndex = 0;
|
|
8648
|
+
}
|
|
8649
|
+
htmlProps.style = style;
|
|
8650
|
+
return htmlProps;
|
|
8651
|
+
}
|
|
8652
|
+
|
|
8653
|
+
/**
|
|
8654
|
+
* A list of all valid MotionProps.
|
|
8655
|
+
*
|
|
8656
|
+
* @privateRemarks
|
|
8657
|
+
* This doesn't throw if a `MotionProp` name is missing - it should.
|
|
8658
|
+
*/
|
|
8659
|
+
const validMotionProps = new Set([
|
|
8660
|
+
"animate",
|
|
8661
|
+
"exit",
|
|
8662
|
+
"variants",
|
|
8663
|
+
"initial",
|
|
8664
|
+
"style",
|
|
8665
|
+
"values",
|
|
8666
|
+
"variants",
|
|
8667
|
+
"transition",
|
|
8668
|
+
"transformTemplate",
|
|
8669
|
+
"custom",
|
|
8670
|
+
"inherit",
|
|
8671
|
+
"onBeforeLayoutMeasure",
|
|
8672
|
+
"onAnimationStart",
|
|
8673
|
+
"onAnimationComplete",
|
|
8674
|
+
"onUpdate",
|
|
8675
|
+
"onDragStart",
|
|
8676
|
+
"onDrag",
|
|
8677
|
+
"onDragEnd",
|
|
8678
|
+
"onMeasureDragConstraints",
|
|
8679
|
+
"onDirectionLock",
|
|
8680
|
+
"onDragTransitionEnd",
|
|
8681
|
+
"_dragX",
|
|
8682
|
+
"_dragY",
|
|
8683
|
+
"onHoverStart",
|
|
8684
|
+
"onHoverEnd",
|
|
8685
|
+
"onViewportEnter",
|
|
8686
|
+
"onViewportLeave",
|
|
8687
|
+
"globalTapTarget",
|
|
8688
|
+
"ignoreStrict",
|
|
8689
|
+
"viewport",
|
|
8690
|
+
]);
|
|
8691
|
+
/**
|
|
8692
|
+
* Check whether a prop name is a valid `MotionProp` key.
|
|
8693
|
+
*
|
|
8694
|
+
* @param key - Name of the property to check
|
|
8695
|
+
* @returns `true` is key is a valid `MotionProp`.
|
|
8696
|
+
*
|
|
8697
|
+
* @public
|
|
8698
|
+
*/
|
|
8699
|
+
function isValidMotionProp(key) {
|
|
8700
|
+
return (key.startsWith("while") ||
|
|
8701
|
+
(key.startsWith("drag") && key !== "draggable") ||
|
|
8702
|
+
key.startsWith("layout") ||
|
|
8703
|
+
key.startsWith("onTap") ||
|
|
8704
|
+
key.startsWith("onPan") ||
|
|
8705
|
+
key.startsWith("onLayout") ||
|
|
8706
|
+
validMotionProps.has(key));
|
|
8707
|
+
}
|
|
8708
|
+
|
|
8709
|
+
let shouldForward = (key) => !isValidMotionProp(key);
|
|
8710
|
+
function loadExternalIsValidProp(isValidProp) {
|
|
8711
|
+
if (!isValidProp)
|
|
8712
|
+
return;
|
|
8713
|
+
// Explicitly filter our events
|
|
8714
|
+
shouldForward = (key) => key.startsWith("on") ? !isValidMotionProp(key) : isValidProp(key);
|
|
8715
|
+
}
|
|
8716
|
+
/**
|
|
8717
|
+
* Emotion and Styled Components both allow users to pass through arbitrary props to their components
|
|
8718
|
+
* to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
|
|
8719
|
+
* of these should be passed to the underlying DOM node.
|
|
8720
|
+
*
|
|
8721
|
+
* However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
|
|
8722
|
+
* as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
|
|
8723
|
+
* passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
|
|
8724
|
+
* `@emotion/is-prop-valid`, however to fix this problem we need to use it.
|
|
8725
|
+
*
|
|
8726
|
+
* By making it an optionalDependency we can offer this functionality only in the situations where it's
|
|
8727
|
+
* actually required.
|
|
8728
|
+
*/
|
|
8729
|
+
try {
|
|
8730
|
+
/**
|
|
8731
|
+
* We attempt to import this package but require won't be defined in esm environments, in that case
|
|
8732
|
+
* isPropValid will have to be provided via `MotionContext`. In a 6.0.0 this should probably be removed
|
|
8733
|
+
* in favour of explicit injection.
|
|
8734
|
+
*/
|
|
8735
|
+
loadExternalIsValidProp(require("@emotion/is-prop-valid").default);
|
|
8736
|
+
}
|
|
8737
|
+
catch (_a) {
|
|
8738
|
+
// We don't need to actually do anything here - the fallback is the existing `isPropValid`.
|
|
8739
|
+
}
|
|
8740
|
+
function filterProps(props, isDom, forwardMotionProps) {
|
|
8741
|
+
const filteredProps = {};
|
|
8742
|
+
for (const key in props) {
|
|
8743
|
+
/**
|
|
8744
|
+
* values is considered a valid prop by Emotion, so if it's present
|
|
8745
|
+
* this will be rendered out to the DOM unless explicitly filtered.
|
|
8746
|
+
*
|
|
8747
|
+
* We check the type as it could be used with the `feColorMatrix`
|
|
8748
|
+
* element, which we support.
|
|
8749
|
+
*/
|
|
8750
|
+
if (key === "values" && typeof props.values === "object")
|
|
8751
|
+
continue;
|
|
8752
|
+
if (shouldForward(key) ||
|
|
8753
|
+
(forwardMotionProps === true && isValidMotionProp(key)) ||
|
|
8754
|
+
(!isDom && !isValidMotionProp(key)) ||
|
|
8755
|
+
// If trying to use native HTML drag events, forward drag listeners
|
|
8756
|
+
(props["draggable"] &&
|
|
8757
|
+
key.startsWith("onDrag"))) {
|
|
8758
|
+
filteredProps[key] =
|
|
8759
|
+
props[key];
|
|
8760
|
+
}
|
|
8761
|
+
}
|
|
8762
|
+
return filteredProps;
|
|
8763
|
+
}
|
|
8764
|
+
|
|
8765
|
+
/**
|
|
8766
|
+
* We keep these listed separately as we use the lowercase tag names as part
|
|
8767
|
+
* of the runtime bundle to detect SVG components
|
|
8768
|
+
*/
|
|
8769
|
+
const lowercaseSVGElements = [
|
|
8770
|
+
"animate",
|
|
8771
|
+
"circle",
|
|
8772
|
+
"defs",
|
|
8773
|
+
"desc",
|
|
8774
|
+
"ellipse",
|
|
8775
|
+
"g",
|
|
8776
|
+
"image",
|
|
8777
|
+
"line",
|
|
8778
|
+
"filter",
|
|
8779
|
+
"marker",
|
|
8780
|
+
"mask",
|
|
8781
|
+
"metadata",
|
|
8782
|
+
"path",
|
|
8783
|
+
"pattern",
|
|
8784
|
+
"polygon",
|
|
8785
|
+
"polyline",
|
|
8786
|
+
"rect",
|
|
8787
|
+
"stop",
|
|
8788
|
+
"switch",
|
|
8789
|
+
"symbol",
|
|
8790
|
+
"svg",
|
|
8791
|
+
"text",
|
|
8792
|
+
"tspan",
|
|
8793
|
+
"use",
|
|
8794
|
+
"view",
|
|
8795
|
+
];
|
|
8796
|
+
|
|
8797
|
+
function isSVGComponent(Component) {
|
|
8798
|
+
if (
|
|
8799
|
+
/**
|
|
8800
|
+
* If it's not a string, it's a custom React component. Currently we only support
|
|
8801
|
+
* HTML custom React components.
|
|
8802
|
+
*/
|
|
8803
|
+
typeof Component !== "string" ||
|
|
8804
|
+
/**
|
|
8805
|
+
* If it contains a dash, the element is a custom HTML webcomponent.
|
|
8806
|
+
*/
|
|
8807
|
+
Component.includes("-")) {
|
|
8808
|
+
return false;
|
|
8809
|
+
}
|
|
8810
|
+
else if (
|
|
8811
|
+
/**
|
|
8812
|
+
* If it's in our list of lowercase SVG tags, it's an SVG component
|
|
8813
|
+
*/
|
|
8814
|
+
lowercaseSVGElements.indexOf(Component) > -1 ||
|
|
8815
|
+
/**
|
|
8816
|
+
* If it contains a capital letter, it's an SVG component
|
|
8817
|
+
*/
|
|
8818
|
+
/[A-Z]/u.test(Component)) {
|
|
8819
|
+
return true;
|
|
8820
|
+
}
|
|
8821
|
+
return false;
|
|
8822
|
+
}
|
|
8823
|
+
|
|
8824
|
+
const dashKeys = {
|
|
8825
|
+
offset: "stroke-dashoffset",
|
|
8826
|
+
array: "stroke-dasharray",
|
|
8827
|
+
};
|
|
8828
|
+
const camelKeys = {
|
|
8829
|
+
offset: "strokeDashoffset",
|
|
8830
|
+
array: "strokeDasharray",
|
|
8831
|
+
};
|
|
8832
|
+
/**
|
|
8833
|
+
* Build SVG path properties. Uses the path's measured length to convert
|
|
8834
|
+
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8835
|
+
* and stroke-dasharray attributes.
|
|
8836
|
+
*
|
|
8837
|
+
* This function is mutative to reduce per-frame GC.
|
|
8838
|
+
*/
|
|
8839
|
+
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8840
|
+
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8841
|
+
attrs.pathLength = 1;
|
|
8842
|
+
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8843
|
+
// when defining props on a React component.
|
|
8844
|
+
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8845
|
+
// Build the dash offset
|
|
8846
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
8847
|
+
// Build the dash array
|
|
8848
|
+
const pathLength = px.transform(length);
|
|
8849
|
+
const pathSpacing = px.transform(spacing);
|
|
8850
|
+
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8851
|
+
}
|
|
8852
|
+
|
|
8853
|
+
function calcOrigin(origin, offset, size) {
|
|
8854
|
+
return typeof origin === "string"
|
|
8855
|
+
? origin
|
|
8856
|
+
: px.transform(offset + size * origin);
|
|
8857
|
+
}
|
|
8858
|
+
/**
|
|
8859
|
+
* The SVG transform origin defaults are different to CSS and is less intuitive,
|
|
8860
|
+
* so we use the measured dimensions of the SVG to reconcile these.
|
|
8861
|
+
*/
|
|
8862
|
+
function calcSVGTransformOrigin(dimensions, originX, originY) {
|
|
8863
|
+
const pxOriginX = calcOrigin(originX, dimensions.x, dimensions.width);
|
|
8864
|
+
const pxOriginY = calcOrigin(originY, dimensions.y, dimensions.height);
|
|
8865
|
+
return `${pxOriginX} ${pxOriginY}`;
|
|
8866
|
+
}
|
|
8867
|
+
|
|
8868
|
+
/**
|
|
8869
|
+
* Build SVG visual attrbutes, like cx and style.transform
|
|
8870
|
+
*/
|
|
8871
|
+
function buildSVGAttrs(state, { attrX, attrY, attrScale, originX, originY, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8872
|
+
// This is object creation, which we try to avoid per-frame.
|
|
8873
|
+
...latest }, isSVGTag, transformTemplate) {
|
|
8874
|
+
buildHTMLStyles(state, latest, transformTemplate);
|
|
8875
|
+
/**
|
|
8876
|
+
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8877
|
+
* as normal HTML tags.
|
|
8878
|
+
*/
|
|
8879
|
+
if (isSVGTag) {
|
|
8880
|
+
if (state.style.viewBox) {
|
|
8881
|
+
state.attrs.viewBox = state.style.viewBox;
|
|
8882
|
+
}
|
|
8883
|
+
return;
|
|
8884
|
+
}
|
|
8885
|
+
state.attrs = state.style;
|
|
8886
|
+
state.style = {};
|
|
8887
|
+
const { attrs, style, dimensions } = state;
|
|
8888
|
+
/**
|
|
8889
|
+
* However, we apply transforms as CSS transforms. So if we detect a transform we take it from attrs
|
|
8890
|
+
* and copy it into style.
|
|
8891
|
+
*/
|
|
8892
|
+
if (attrs.transform) {
|
|
8893
|
+
if (dimensions)
|
|
8894
|
+
style.transform = attrs.transform;
|
|
8895
|
+
delete attrs.transform;
|
|
8896
|
+
}
|
|
8897
|
+
// Parse transformOrigin
|
|
8898
|
+
if (dimensions &&
|
|
8899
|
+
(originX !== undefined || originY !== undefined || style.transform)) {
|
|
8900
|
+
style.transformOrigin = calcSVGTransformOrigin(dimensions, originX !== undefined ? originX : 0.5, originY !== undefined ? originY : 0.5);
|
|
8901
|
+
}
|
|
8902
|
+
// Render attrX/attrY/attrScale as attributes
|
|
8903
|
+
if (attrX !== undefined)
|
|
8904
|
+
attrs.x = attrX;
|
|
8905
|
+
if (attrY !== undefined)
|
|
8906
|
+
attrs.y = attrY;
|
|
8907
|
+
if (attrScale !== undefined)
|
|
8908
|
+
attrs.scale = attrScale;
|
|
8909
|
+
// Build SVG path if one has been defined
|
|
8910
|
+
if (pathLength !== undefined) {
|
|
8911
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
|
|
8915
|
+
const createSvgRenderState = () => ({
|
|
8916
|
+
...createHtmlRenderState(),
|
|
8917
|
+
attrs: {},
|
|
8918
|
+
});
|
|
8919
|
+
|
|
8920
|
+
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
8921
|
+
|
|
8922
|
+
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
8923
|
+
const visualProps = react.useMemo(() => {
|
|
8924
|
+
const state = createSvgRenderState();
|
|
8925
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate);
|
|
8926
|
+
return {
|
|
8927
|
+
...state.attrs,
|
|
8928
|
+
style: { ...state.style },
|
|
8929
|
+
};
|
|
8930
|
+
}, [visualState]);
|
|
8931
|
+
if (props.style) {
|
|
8932
|
+
const rawStyles = {};
|
|
8933
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
8934
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
8935
|
+
}
|
|
8936
|
+
return visualProps;
|
|
8937
|
+
}
|
|
8938
|
+
|
|
8939
|
+
function createUseRender(forwardMotionProps = false) {
|
|
8940
|
+
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
8941
|
+
const useVisualProps = isSVGComponent(Component)
|
|
8942
|
+
? useSVGProps
|
|
8943
|
+
: useHTMLProps;
|
|
8944
|
+
const visualProps = useVisualProps(props, latestValues, isStatic, Component);
|
|
8945
|
+
const filteredProps = filterProps(props, typeof Component === "string", forwardMotionProps);
|
|
8946
|
+
const elementProps = Component !== react.Fragment
|
|
8947
|
+
? { ...filteredProps, ...visualProps, ref }
|
|
8948
|
+
: {};
|
|
8949
|
+
/**
|
|
8950
|
+
* If component has been handed a motion value as its child,
|
|
8951
|
+
* memoise its initial value and render that. Subsequent updates
|
|
8952
|
+
* will be handled by the onChange handler
|
|
8953
|
+
*/
|
|
8954
|
+
const { children } = props;
|
|
8955
|
+
const renderedChildren = react.useMemo(() => (isMotionValue(children) ? children.get() : children), [children]);
|
|
8956
|
+
return react.createElement(Component, {
|
|
8957
|
+
...elementProps,
|
|
8958
|
+
children: renderedChildren,
|
|
8959
|
+
});
|
|
8960
|
+
};
|
|
8961
|
+
return useRender;
|
|
8962
|
+
}
|
|
8963
|
+
|
|
8964
|
+
/**
|
|
8965
|
+
* Creates a constant value over the lifecycle of a component.
|
|
8966
|
+
*
|
|
8967
|
+
* Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
|
|
8968
|
+
* a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
|
|
8969
|
+
* you can ensure that initialisers don't execute twice or more.
|
|
8970
|
+
*/
|
|
8971
|
+
function useConstant(init) {
|
|
8972
|
+
const ref = react.useRef(null);
|
|
8973
|
+
if (ref.current === null) {
|
|
8974
|
+
ref.current = init();
|
|
8975
|
+
}
|
|
8976
|
+
return ref.current;
|
|
8977
|
+
}
|
|
8978
|
+
|
|
8979
|
+
function makeState({ scrapeMotionValuesFromProps, createRenderState, onUpdate, }, props, context, presenceContext) {
|
|
8980
|
+
const state = {
|
|
8981
|
+
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
|
|
8982
|
+
renderState: createRenderState(),
|
|
8983
|
+
};
|
|
8984
|
+
if (onUpdate) {
|
|
8985
|
+
/**
|
|
8986
|
+
* onMount works without the VisualElement because it could be
|
|
8987
|
+
* called before the VisualElement payload has been hydrated.
|
|
8988
|
+
* (e.g. if someone is using m components <m.circle />)
|
|
8989
|
+
*/
|
|
8990
|
+
state.onMount = (instance) => onUpdate({ props, current: instance, ...state });
|
|
8991
|
+
state.onUpdate = (visualElement) => onUpdate(visualElement);
|
|
8992
|
+
}
|
|
8993
|
+
return state;
|
|
8994
|
+
}
|
|
8995
|
+
const makeUseVisualState = (config) => (props, isStatic) => {
|
|
8996
|
+
const context = react.useContext(MotionContext);
|
|
8997
|
+
const presenceContext = react.useContext(PresenceContext);
|
|
8998
|
+
const make = () => makeState(config, props, context, presenceContext);
|
|
8999
|
+
return isStatic ? make() : useConstant(make);
|
|
9000
|
+
};
|
|
9001
|
+
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
|
9002
|
+
const values = {};
|
|
9003
|
+
const motionValues = scrapeMotionValues(props, {});
|
|
9004
|
+
for (const key in motionValues) {
|
|
9005
|
+
values[key] = resolveMotionValue(motionValues[key]);
|
|
9006
|
+
}
|
|
9007
|
+
let { initial, animate } = props;
|
|
9008
|
+
const isControllingVariants$1 = isControllingVariants(props);
|
|
9009
|
+
const isVariantNode$1 = isVariantNode(props);
|
|
9010
|
+
if (context &&
|
|
9011
|
+
isVariantNode$1 &&
|
|
9012
|
+
!isControllingVariants$1 &&
|
|
9013
|
+
props.inherit !== false) {
|
|
9014
|
+
if (initial === undefined)
|
|
9015
|
+
initial = context.initial;
|
|
9016
|
+
if (animate === undefined)
|
|
9017
|
+
animate = context.animate;
|
|
9018
|
+
}
|
|
9019
|
+
let isInitialAnimationBlocked = presenceContext
|
|
9020
|
+
? presenceContext.initial === false
|
|
9021
|
+
: false;
|
|
9022
|
+
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
|
9023
|
+
const variantToSet = isInitialAnimationBlocked ? animate : initial;
|
|
9024
|
+
if (variantToSet &&
|
|
9025
|
+
typeof variantToSet !== "boolean" &&
|
|
9026
|
+
!isAnimationControls(variantToSet)) {
|
|
9027
|
+
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
|
9028
|
+
for (let i = 0; i < list.length; i++) {
|
|
9029
|
+
const resolved = resolveVariantFromProps(props, list[i]);
|
|
9030
|
+
if (resolved) {
|
|
9031
|
+
const { transitionEnd, transition, ...target } = resolved;
|
|
9032
|
+
for (const key in target) {
|
|
9033
|
+
let valueTarget = target[key];
|
|
9034
|
+
if (Array.isArray(valueTarget)) {
|
|
9035
|
+
/**
|
|
9036
|
+
* Take final keyframe if the initial animation is blocked because
|
|
9037
|
+
* we want to initialise at the end of that blocked animation.
|
|
9038
|
+
*/
|
|
9039
|
+
const index = isInitialAnimationBlocked
|
|
9040
|
+
? valueTarget.length - 1
|
|
9041
|
+
: 0;
|
|
9042
|
+
valueTarget = valueTarget[index];
|
|
9043
|
+
}
|
|
9044
|
+
if (valueTarget !== null) {
|
|
9045
|
+
values[key] = valueTarget;
|
|
9046
|
+
}
|
|
9047
|
+
}
|
|
9048
|
+
for (const key in transitionEnd) {
|
|
9049
|
+
values[key] = transitionEnd[key];
|
|
9050
|
+
}
|
|
9051
|
+
}
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
9054
|
+
return values;
|
|
9055
|
+
}
|
|
9056
|
+
|
|
9057
|
+
function scrapeMotionValuesFromProps$1(props, prevProps, visualElement) {
|
|
9058
|
+
var _a;
|
|
9059
|
+
const { style } = props;
|
|
9060
|
+
const newValues = {};
|
|
9061
|
+
for (const key in style) {
|
|
9062
|
+
if (isMotionValue(style[key]) ||
|
|
9063
|
+
(prevProps.style &&
|
|
9064
|
+
isMotionValue(prevProps.style[key])) ||
|
|
9065
|
+
isForcedMotionValue(key, props) ||
|
|
9066
|
+
((_a = visualElement === null || visualElement === void 0 ? void 0 : visualElement.getValue(key)) === null || _a === void 0 ? void 0 : _a.liveStyle) !== undefined) {
|
|
9067
|
+
newValues[key] = style[key];
|
|
9068
|
+
}
|
|
9069
|
+
}
|
|
9070
|
+
return newValues;
|
|
9071
|
+
}
|
|
9072
|
+
|
|
9073
|
+
const htmlMotionConfig = {
|
|
9074
|
+
useVisualState: makeUseVisualState({
|
|
9075
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
9076
|
+
createRenderState: createHtmlRenderState,
|
|
9077
|
+
}),
|
|
9078
|
+
};
|
|
9079
|
+
|
|
9080
|
+
function renderHTML(element, { style, vars }, styleProp, projection) {
|
|
9081
|
+
Object.assign(element.style, style, projection && projection.getProjectionStyles(styleProp));
|
|
8843
9082
|
// Loop over any CSS variables and assign those.
|
|
8844
9083
|
for (const key in vars) {
|
|
8845
9084
|
element.style.setProperty(key, vars[key]);
|
|
@@ -8882,29 +9121,6 @@ function renderSVG(element, renderState, _styleProp, projection) {
|
|
|
8882
9121
|
}
|
|
8883
9122
|
}
|
|
8884
9123
|
|
|
8885
|
-
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
8886
|
-
return (transformProps.has(key) ||
|
|
8887
|
-
key.startsWith("origin") ||
|
|
8888
|
-
((layout || layoutId !== undefined) &&
|
|
8889
|
-
(!!scaleCorrectors[key] || key === "opacity")));
|
|
8890
|
-
}
|
|
8891
|
-
|
|
8892
|
-
function scrapeMotionValuesFromProps$1(props, prevProps, visualElement) {
|
|
8893
|
-
var _a;
|
|
8894
|
-
const { style } = props;
|
|
8895
|
-
const newValues = {};
|
|
8896
|
-
for (const key in style) {
|
|
8897
|
-
if (isMotionValue(style[key]) ||
|
|
8898
|
-
(prevProps.style &&
|
|
8899
|
-
isMotionValue(prevProps.style[key])) ||
|
|
8900
|
-
isForcedMotionValue(key, props) ||
|
|
8901
|
-
((_a = visualElement === null || visualElement === void 0 ? void 0 : visualElement.getValue(key)) === null || _a === void 0 ? void 0 : _a.liveStyle) !== undefined) {
|
|
8902
|
-
newValues[key] = style[key];
|
|
8903
|
-
}
|
|
8904
|
-
}
|
|
8905
|
-
return newValues;
|
|
8906
|
-
}
|
|
8907
|
-
|
|
8908
9124
|
function scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
8909
9125
|
const newValues = scrapeMotionValuesFromProps$1(props, prevProps, visualElement);
|
|
8910
9126
|
for (const key in props) {
|
|
@@ -8982,217 +9198,6 @@ const svgMotionConfig = {
|
|
|
8982
9198
|
}),
|
|
8983
9199
|
};
|
|
8984
9200
|
|
|
8985
|
-
const htmlMotionConfig = {
|
|
8986
|
-
useVisualState: makeUseVisualState({
|
|
8987
|
-
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
8988
|
-
createRenderState: createHtmlRenderState,
|
|
8989
|
-
}),
|
|
8990
|
-
};
|
|
8991
|
-
|
|
8992
|
-
function copyRawValuesOnly(target, source, props) {
|
|
8993
|
-
for (const key in source) {
|
|
8994
|
-
if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
8995
|
-
target[key] = source[key];
|
|
8996
|
-
}
|
|
8997
|
-
}
|
|
8998
|
-
}
|
|
8999
|
-
function useInitialMotionValues({ transformTemplate }, visualState) {
|
|
9000
|
-
return react.useMemo(() => {
|
|
9001
|
-
const state = createHtmlRenderState();
|
|
9002
|
-
buildHTMLStyles(state, visualState, transformTemplate);
|
|
9003
|
-
return Object.assign({}, state.vars, state.style);
|
|
9004
|
-
}, [visualState]);
|
|
9005
|
-
}
|
|
9006
|
-
function useStyle(props, visualState) {
|
|
9007
|
-
const styleProp = props.style || {};
|
|
9008
|
-
const style = {};
|
|
9009
|
-
/**
|
|
9010
|
-
* Copy non-Motion Values straight into style
|
|
9011
|
-
*/
|
|
9012
|
-
copyRawValuesOnly(style, styleProp, props);
|
|
9013
|
-
Object.assign(style, useInitialMotionValues(props, visualState));
|
|
9014
|
-
return style;
|
|
9015
|
-
}
|
|
9016
|
-
function useHTMLProps(props, visualState) {
|
|
9017
|
-
// The `any` isn't ideal but it is the type of createElement props argument
|
|
9018
|
-
const htmlProps = {};
|
|
9019
|
-
const style = useStyle(props, visualState);
|
|
9020
|
-
if (props.drag && props.dragListener !== false) {
|
|
9021
|
-
// Disable the ghost element when a user drags
|
|
9022
|
-
htmlProps.draggable = false;
|
|
9023
|
-
// Disable text selection
|
|
9024
|
-
style.userSelect =
|
|
9025
|
-
style.WebkitUserSelect =
|
|
9026
|
-
style.WebkitTouchCallout =
|
|
9027
|
-
"none";
|
|
9028
|
-
// Disable scrolling on the draggable direction
|
|
9029
|
-
style.touchAction =
|
|
9030
|
-
props.drag === true
|
|
9031
|
-
? "none"
|
|
9032
|
-
: `pan-${props.drag === "x" ? "y" : "x"}`;
|
|
9033
|
-
}
|
|
9034
|
-
if (props.tabIndex === undefined &&
|
|
9035
|
-
(props.onTap || props.onTapStart || props.whileTap)) {
|
|
9036
|
-
htmlProps.tabIndex = 0;
|
|
9037
|
-
}
|
|
9038
|
-
htmlProps.style = style;
|
|
9039
|
-
return htmlProps;
|
|
9040
|
-
}
|
|
9041
|
-
|
|
9042
|
-
/**
|
|
9043
|
-
* A list of all valid MotionProps.
|
|
9044
|
-
*
|
|
9045
|
-
* @privateRemarks
|
|
9046
|
-
* This doesn't throw if a `MotionProp` name is missing - it should.
|
|
9047
|
-
*/
|
|
9048
|
-
const validMotionProps = new Set([
|
|
9049
|
-
"animate",
|
|
9050
|
-
"exit",
|
|
9051
|
-
"variants",
|
|
9052
|
-
"initial",
|
|
9053
|
-
"style",
|
|
9054
|
-
"values",
|
|
9055
|
-
"variants",
|
|
9056
|
-
"transition",
|
|
9057
|
-
"transformTemplate",
|
|
9058
|
-
"custom",
|
|
9059
|
-
"inherit",
|
|
9060
|
-
"onBeforeLayoutMeasure",
|
|
9061
|
-
"onAnimationStart",
|
|
9062
|
-
"onAnimationComplete",
|
|
9063
|
-
"onUpdate",
|
|
9064
|
-
"onDragStart",
|
|
9065
|
-
"onDrag",
|
|
9066
|
-
"onDragEnd",
|
|
9067
|
-
"onMeasureDragConstraints",
|
|
9068
|
-
"onDirectionLock",
|
|
9069
|
-
"onDragTransitionEnd",
|
|
9070
|
-
"_dragX",
|
|
9071
|
-
"_dragY",
|
|
9072
|
-
"onHoverStart",
|
|
9073
|
-
"onHoverEnd",
|
|
9074
|
-
"onViewportEnter",
|
|
9075
|
-
"onViewportLeave",
|
|
9076
|
-
"globalTapTarget",
|
|
9077
|
-
"ignoreStrict",
|
|
9078
|
-
"viewport",
|
|
9079
|
-
]);
|
|
9080
|
-
/**
|
|
9081
|
-
* Check whether a prop name is a valid `MotionProp` key.
|
|
9082
|
-
*
|
|
9083
|
-
* @param key - Name of the property to check
|
|
9084
|
-
* @returns `true` is key is a valid `MotionProp`.
|
|
9085
|
-
*
|
|
9086
|
-
* @public
|
|
9087
|
-
*/
|
|
9088
|
-
function isValidMotionProp(key) {
|
|
9089
|
-
return (key.startsWith("while") ||
|
|
9090
|
-
(key.startsWith("drag") && key !== "draggable") ||
|
|
9091
|
-
key.startsWith("layout") ||
|
|
9092
|
-
key.startsWith("onTap") ||
|
|
9093
|
-
key.startsWith("onPan") ||
|
|
9094
|
-
key.startsWith("onLayout") ||
|
|
9095
|
-
validMotionProps.has(key));
|
|
9096
|
-
}
|
|
9097
|
-
|
|
9098
|
-
let shouldForward = (key) => !isValidMotionProp(key);
|
|
9099
|
-
function loadExternalIsValidProp(isValidProp) {
|
|
9100
|
-
if (!isValidProp)
|
|
9101
|
-
return;
|
|
9102
|
-
// Explicitly filter our events
|
|
9103
|
-
shouldForward = (key) => key.startsWith("on") ? !isValidMotionProp(key) : isValidProp(key);
|
|
9104
|
-
}
|
|
9105
|
-
/**
|
|
9106
|
-
* Emotion and Styled Components both allow users to pass through arbitrary props to their components
|
|
9107
|
-
* to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
|
|
9108
|
-
* of these should be passed to the underlying DOM node.
|
|
9109
|
-
*
|
|
9110
|
-
* However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
|
|
9111
|
-
* as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
|
|
9112
|
-
* passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
|
|
9113
|
-
* `@emotion/is-prop-valid`, however to fix this problem we need to use it.
|
|
9114
|
-
*
|
|
9115
|
-
* By making it an optionalDependency we can offer this functionality only in the situations where it's
|
|
9116
|
-
* actually required.
|
|
9117
|
-
*/
|
|
9118
|
-
try {
|
|
9119
|
-
/**
|
|
9120
|
-
* We attempt to import this package but require won't be defined in esm environments, in that case
|
|
9121
|
-
* isPropValid will have to be provided via `MotionContext`. In a 6.0.0 this should probably be removed
|
|
9122
|
-
* in favour of explicit injection.
|
|
9123
|
-
*/
|
|
9124
|
-
loadExternalIsValidProp(require("@emotion/is-prop-valid").default);
|
|
9125
|
-
}
|
|
9126
|
-
catch (_a) {
|
|
9127
|
-
// We don't need to actually do anything here - the fallback is the existing `isPropValid`.
|
|
9128
|
-
}
|
|
9129
|
-
function filterProps(props, isDom, forwardMotionProps) {
|
|
9130
|
-
const filteredProps = {};
|
|
9131
|
-
for (const key in props) {
|
|
9132
|
-
/**
|
|
9133
|
-
* values is considered a valid prop by Emotion, so if it's present
|
|
9134
|
-
* this will be rendered out to the DOM unless explicitly filtered.
|
|
9135
|
-
*
|
|
9136
|
-
* We check the type as it could be used with the `feColorMatrix`
|
|
9137
|
-
* element, which we support.
|
|
9138
|
-
*/
|
|
9139
|
-
if (key === "values" && typeof props.values === "object")
|
|
9140
|
-
continue;
|
|
9141
|
-
if (shouldForward(key) ||
|
|
9142
|
-
(forwardMotionProps === true && isValidMotionProp(key)) ||
|
|
9143
|
-
(!isDom && !isValidMotionProp(key)) ||
|
|
9144
|
-
// If trying to use native HTML drag events, forward drag listeners
|
|
9145
|
-
(props["draggable"] &&
|
|
9146
|
-
key.startsWith("onDrag"))) {
|
|
9147
|
-
filteredProps[key] =
|
|
9148
|
-
props[key];
|
|
9149
|
-
}
|
|
9150
|
-
}
|
|
9151
|
-
return filteredProps;
|
|
9152
|
-
}
|
|
9153
|
-
|
|
9154
|
-
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
9155
|
-
const visualProps = react.useMemo(() => {
|
|
9156
|
-
const state = createSvgRenderState();
|
|
9157
|
-
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate);
|
|
9158
|
-
return {
|
|
9159
|
-
...state.attrs,
|
|
9160
|
-
style: { ...state.style },
|
|
9161
|
-
};
|
|
9162
|
-
}, [visualState]);
|
|
9163
|
-
if (props.style) {
|
|
9164
|
-
const rawStyles = {};
|
|
9165
|
-
copyRawValuesOnly(rawStyles, props.style, props);
|
|
9166
|
-
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
9167
|
-
}
|
|
9168
|
-
return visualProps;
|
|
9169
|
-
}
|
|
9170
|
-
|
|
9171
|
-
function createUseRender(forwardMotionProps = false) {
|
|
9172
|
-
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
9173
|
-
const useVisualProps = isSVGComponent(Component)
|
|
9174
|
-
? useSVGProps
|
|
9175
|
-
: useHTMLProps;
|
|
9176
|
-
const visualProps = useVisualProps(props, latestValues, isStatic, Component);
|
|
9177
|
-
const filteredProps = filterProps(props, typeof Component === "string", forwardMotionProps);
|
|
9178
|
-
const elementProps = Component !== react.Fragment
|
|
9179
|
-
? { ...filteredProps, ...visualProps, ref }
|
|
9180
|
-
: {};
|
|
9181
|
-
/**
|
|
9182
|
-
* If component has been handed a motion value as its child,
|
|
9183
|
-
* memoise its initial value and render that. Subsequent updates
|
|
9184
|
-
* will be handled by the onChange handler
|
|
9185
|
-
*/
|
|
9186
|
-
const { children } = props;
|
|
9187
|
-
const renderedChildren = react.useMemo(() => (isMotionValue(children) ? children.get() : children), [children]);
|
|
9188
|
-
return react.createElement(Component, {
|
|
9189
|
-
...elementProps,
|
|
9190
|
-
children: renderedChildren,
|
|
9191
|
-
});
|
|
9192
|
-
};
|
|
9193
|
-
return useRender;
|
|
9194
|
-
}
|
|
9195
|
-
|
|
9196
9201
|
function createMotionComponentFactory(preloadedFeatures, createVisualElement) {
|
|
9197
9202
|
return function createMotionComponent(Component, { forwardMotionProps } = { forwardMotionProps: false }) {
|
|
9198
9203
|
const baseConfig = isSVGComponent(Component)
|
|
@@ -9254,7 +9259,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
9254
9259
|
* and warn against mismatches.
|
|
9255
9260
|
*/
|
|
9256
9261
|
if (process.env.NODE_ENV === "development") {
|
|
9257
|
-
warnOnce(nextValue.version === "12.0.
|
|
9262
|
+
warnOnce(nextValue.version === "12.0.8-alpha.0", `Attempting to mix Motion versions ${nextValue.version} with 12.0.8-alpha.0 may not work as expected.`);
|
|
9258
9263
|
}
|
|
9259
9264
|
}
|
|
9260
9265
|
else if (isMotionValue(prevValue)) {
|
|
@@ -9476,6 +9481,9 @@ class VisualElement {
|
|
|
9476
9481
|
this.valueSubscriptions.get(key)();
|
|
9477
9482
|
}
|
|
9478
9483
|
const valueIsTransform = transformProps.has(key);
|
|
9484
|
+
if (valueIsTransform && this.onBindTransform) {
|
|
9485
|
+
this.onBindTransform();
|
|
9486
|
+
}
|
|
9479
9487
|
const removeOnChange = value.on("change", (latestValue) => {
|
|
9480
9488
|
this.latestValues[key] = latestValue;
|
|
9481
9489
|
this.props.onUpdate && frame.preRender(this.notifyUpdate);
|
|
@@ -9826,6 +9834,11 @@ class SVGVisualElement extends DOMVisualElement {
|
|
|
9826
9834
|
this.type = "svg";
|
|
9827
9835
|
this.isSVGTag = false;
|
|
9828
9836
|
this.measureInstanceViewportBox = createBox;
|
|
9837
|
+
this.updateDimensions = () => {
|
|
9838
|
+
if (this.current && !this.renderState.dimensions) {
|
|
9839
|
+
updateSVGDimensions(this.current, this.renderState);
|
|
9840
|
+
}
|
|
9841
|
+
};
|
|
9829
9842
|
}
|
|
9830
9843
|
getBaseTargetFromProps(props, key) {
|
|
9831
9844
|
return props[key];
|
|
@@ -9841,6 +9854,11 @@ class SVGVisualElement extends DOMVisualElement {
|
|
|
9841
9854
|
scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
9842
9855
|
return scrapeMotionValuesFromProps(props, prevProps, visualElement);
|
|
9843
9856
|
}
|
|
9857
|
+
onBindTransform() {
|
|
9858
|
+
if (this.current && !this.renderState.dimensions) {
|
|
9859
|
+
frame.postRender(this.updateDimensions);
|
|
9860
|
+
}
|
|
9861
|
+
}
|
|
9844
9862
|
build(renderState, latestValues, props) {
|
|
9845
9863
|
buildSVGAttrs(renderState, latestValues, this.isSVGTag, props.transformTemplate);
|
|
9846
9864
|
}
|