motion 12.0.6 → 12.0.8-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +43 -12
- package/dist/cjs/react-client.js +495 -482
- 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/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.1";
|
|
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
|
|
@@ -8462,156 +8462,11 @@ function getProjectionFunctionality(props) {
|
|
|
8462
8462
|
};
|
|
8463
8463
|
}
|
|
8464
8464
|
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
"animate",
|
|
8471
|
-
"circle",
|
|
8472
|
-
"defs",
|
|
8473
|
-
"desc",
|
|
8474
|
-
"ellipse",
|
|
8475
|
-
"g",
|
|
8476
|
-
"image",
|
|
8477
|
-
"line",
|
|
8478
|
-
"filter",
|
|
8479
|
-
"marker",
|
|
8480
|
-
"mask",
|
|
8481
|
-
"metadata",
|
|
8482
|
-
"path",
|
|
8483
|
-
"pattern",
|
|
8484
|
-
"polygon",
|
|
8485
|
-
"polyline",
|
|
8486
|
-
"rect",
|
|
8487
|
-
"stop",
|
|
8488
|
-
"switch",
|
|
8489
|
-
"symbol",
|
|
8490
|
-
"svg",
|
|
8491
|
-
"text",
|
|
8492
|
-
"tspan",
|
|
8493
|
-
"use",
|
|
8494
|
-
"view",
|
|
8495
|
-
];
|
|
8496
|
-
|
|
8497
|
-
function isSVGComponent(Component) {
|
|
8498
|
-
if (
|
|
8499
|
-
/**
|
|
8500
|
-
* If it's not a string, it's a custom React component. Currently we only support
|
|
8501
|
-
* HTML custom React components.
|
|
8502
|
-
*/
|
|
8503
|
-
typeof Component !== "string" ||
|
|
8504
|
-
/**
|
|
8505
|
-
* If it contains a dash, the element is a custom HTML webcomponent.
|
|
8506
|
-
*/
|
|
8507
|
-
Component.includes("-")) {
|
|
8508
|
-
return false;
|
|
8509
|
-
}
|
|
8510
|
-
else if (
|
|
8511
|
-
/**
|
|
8512
|
-
* If it's in our list of lowercase SVG tags, it's an SVG component
|
|
8513
|
-
*/
|
|
8514
|
-
lowercaseSVGElements.indexOf(Component) > -1 ||
|
|
8515
|
-
/**
|
|
8516
|
-
* If it contains a capital letter, it's an SVG component
|
|
8517
|
-
*/
|
|
8518
|
-
/[A-Z]/u.test(Component)) {
|
|
8519
|
-
return true;
|
|
8520
|
-
}
|
|
8521
|
-
return false;
|
|
8522
|
-
}
|
|
8523
|
-
|
|
8524
|
-
/**
|
|
8525
|
-
* Creates a constant value over the lifecycle of a component.
|
|
8526
|
-
*
|
|
8527
|
-
* Even if `useMemo` is provided an empty array as its final argument, it doesn't offer
|
|
8528
|
-
* a guarantee that it won't re-run for performance reasons later on. By using `useConstant`
|
|
8529
|
-
* you can ensure that initialisers don't execute twice or more.
|
|
8530
|
-
*/
|
|
8531
|
-
function useConstant(init) {
|
|
8532
|
-
const ref = react.useRef(null);
|
|
8533
|
-
if (ref.current === null) {
|
|
8534
|
-
ref.current = init();
|
|
8535
|
-
}
|
|
8536
|
-
return ref.current;
|
|
8537
|
-
}
|
|
8538
|
-
|
|
8539
|
-
function makeState({ scrapeMotionValuesFromProps, createRenderState, onUpdate, }, props, context, presenceContext) {
|
|
8540
|
-
const state = {
|
|
8541
|
-
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
|
|
8542
|
-
renderState: createRenderState(),
|
|
8543
|
-
};
|
|
8544
|
-
if (onUpdate) {
|
|
8545
|
-
/**
|
|
8546
|
-
* onMount works without the VisualElement because it could be
|
|
8547
|
-
* called before the VisualElement payload has been hydrated.
|
|
8548
|
-
* (e.g. if someone is using m components <m.circle />)
|
|
8549
|
-
*/
|
|
8550
|
-
state.onMount = (instance) => onUpdate({ props, current: instance, ...state });
|
|
8551
|
-
state.onUpdate = (visualElement) => onUpdate(visualElement);
|
|
8552
|
-
}
|
|
8553
|
-
return state;
|
|
8554
|
-
}
|
|
8555
|
-
const makeUseVisualState = (config) => (props, isStatic) => {
|
|
8556
|
-
const context = react.useContext(MotionContext);
|
|
8557
|
-
const presenceContext = react.useContext(PresenceContext);
|
|
8558
|
-
const make = () => makeState(config, props, context, presenceContext);
|
|
8559
|
-
return isStatic ? make() : useConstant(make);
|
|
8560
|
-
};
|
|
8561
|
-
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
|
8562
|
-
const values = {};
|
|
8563
|
-
const motionValues = scrapeMotionValues(props, {});
|
|
8564
|
-
for (const key in motionValues) {
|
|
8565
|
-
values[key] = resolveMotionValue(motionValues[key]);
|
|
8566
|
-
}
|
|
8567
|
-
let { initial, animate } = props;
|
|
8568
|
-
const isControllingVariants$1 = isControllingVariants(props);
|
|
8569
|
-
const isVariantNode$1 = isVariantNode(props);
|
|
8570
|
-
if (context &&
|
|
8571
|
-
isVariantNode$1 &&
|
|
8572
|
-
!isControllingVariants$1 &&
|
|
8573
|
-
props.inherit !== false) {
|
|
8574
|
-
if (initial === undefined)
|
|
8575
|
-
initial = context.initial;
|
|
8576
|
-
if (animate === undefined)
|
|
8577
|
-
animate = context.animate;
|
|
8578
|
-
}
|
|
8579
|
-
let isInitialAnimationBlocked = presenceContext
|
|
8580
|
-
? presenceContext.initial === false
|
|
8581
|
-
: false;
|
|
8582
|
-
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
|
8583
|
-
const variantToSet = isInitialAnimationBlocked ? animate : initial;
|
|
8584
|
-
if (variantToSet &&
|
|
8585
|
-
typeof variantToSet !== "boolean" &&
|
|
8586
|
-
!isAnimationControls(variantToSet)) {
|
|
8587
|
-
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
|
8588
|
-
for (let i = 0; i < list.length; i++) {
|
|
8589
|
-
const resolved = resolveVariantFromProps(props, list[i]);
|
|
8590
|
-
if (resolved) {
|
|
8591
|
-
const { transitionEnd, transition, ...target } = resolved;
|
|
8592
|
-
for (const key in target) {
|
|
8593
|
-
let valueTarget = target[key];
|
|
8594
|
-
if (Array.isArray(valueTarget)) {
|
|
8595
|
-
/**
|
|
8596
|
-
* Take final keyframe if the initial animation is blocked because
|
|
8597
|
-
* we want to initialise at the end of that blocked animation.
|
|
8598
|
-
*/
|
|
8599
|
-
const index = isInitialAnimationBlocked
|
|
8600
|
-
? valueTarget.length - 1
|
|
8601
|
-
: 0;
|
|
8602
|
-
valueTarget = valueTarget[index];
|
|
8603
|
-
}
|
|
8604
|
-
if (valueTarget !== null) {
|
|
8605
|
-
values[key] = valueTarget;
|
|
8606
|
-
}
|
|
8607
|
-
}
|
|
8608
|
-
for (const key in transitionEnd) {
|
|
8609
|
-
values[key] = transitionEnd[key];
|
|
8610
|
-
}
|
|
8611
|
-
}
|
|
8612
|
-
}
|
|
8613
|
-
}
|
|
8614
|
-
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")));
|
|
8615
8470
|
}
|
|
8616
8471
|
|
|
8617
8472
|
/**
|
|
@@ -8738,97 +8593,6 @@ function buildHTMLStyles(state, latestValues, transformTemplate) {
|
|
|
8738
8593
|
}
|
|
8739
8594
|
}
|
|
8740
8595
|
|
|
8741
|
-
const dashKeys = {
|
|
8742
|
-
offset: "stroke-dashoffset",
|
|
8743
|
-
array: "stroke-dasharray",
|
|
8744
|
-
};
|
|
8745
|
-
const camelKeys = {
|
|
8746
|
-
offset: "strokeDashoffset",
|
|
8747
|
-
array: "strokeDasharray",
|
|
8748
|
-
};
|
|
8749
|
-
/**
|
|
8750
|
-
* Build SVG path properties. Uses the path's measured length to convert
|
|
8751
|
-
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8752
|
-
* and stroke-dasharray attributes.
|
|
8753
|
-
*
|
|
8754
|
-
* This function is mutative to reduce per-frame GC.
|
|
8755
|
-
*/
|
|
8756
|
-
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8757
|
-
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8758
|
-
attrs.pathLength = 1;
|
|
8759
|
-
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8760
|
-
// when defining props on a React component.
|
|
8761
|
-
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8762
|
-
// Build the dash offset
|
|
8763
|
-
attrs[keys.offset] = px.transform(-offset);
|
|
8764
|
-
// Build the dash array
|
|
8765
|
-
const pathLength = px.transform(length);
|
|
8766
|
-
const pathSpacing = px.transform(spacing);
|
|
8767
|
-
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8768
|
-
}
|
|
8769
|
-
|
|
8770
|
-
function calcOrigin(origin, offset, size) {
|
|
8771
|
-
return typeof origin === "string"
|
|
8772
|
-
? origin
|
|
8773
|
-
: px.transform(offset + size * origin);
|
|
8774
|
-
}
|
|
8775
|
-
/**
|
|
8776
|
-
* The SVG transform origin defaults are different to CSS and is less intuitive,
|
|
8777
|
-
* so we use the measured dimensions of the SVG to reconcile these.
|
|
8778
|
-
*/
|
|
8779
|
-
function calcSVGTransformOrigin(dimensions, originX, originY) {
|
|
8780
|
-
const pxOriginX = calcOrigin(originX, dimensions.x, dimensions.width);
|
|
8781
|
-
const pxOriginY = calcOrigin(originY, dimensions.y, dimensions.height);
|
|
8782
|
-
return `${pxOriginX} ${pxOriginY}`;
|
|
8783
|
-
}
|
|
8784
|
-
|
|
8785
|
-
/**
|
|
8786
|
-
* Build SVG visual attrbutes, like cx and style.transform
|
|
8787
|
-
*/
|
|
8788
|
-
function buildSVGAttrs(state, { attrX, attrY, attrScale, originX, originY, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8789
|
-
// This is object creation, which we try to avoid per-frame.
|
|
8790
|
-
...latest }, isSVGTag, transformTemplate) {
|
|
8791
|
-
buildHTMLStyles(state, latest, transformTemplate);
|
|
8792
|
-
/**
|
|
8793
|
-
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8794
|
-
* as normal HTML tags.
|
|
8795
|
-
*/
|
|
8796
|
-
if (isSVGTag) {
|
|
8797
|
-
if (state.style.viewBox) {
|
|
8798
|
-
state.attrs.viewBox = state.style.viewBox;
|
|
8799
|
-
}
|
|
8800
|
-
return;
|
|
8801
|
-
}
|
|
8802
|
-
state.attrs = state.style;
|
|
8803
|
-
state.style = {};
|
|
8804
|
-
const { attrs, style, dimensions } = state;
|
|
8805
|
-
/**
|
|
8806
|
-
* However, we apply transforms as CSS transforms. So if we detect a transform we take it from attrs
|
|
8807
|
-
* and copy it into style.
|
|
8808
|
-
*/
|
|
8809
|
-
if (attrs.transform) {
|
|
8810
|
-
if (dimensions)
|
|
8811
|
-
style.transform = attrs.transform;
|
|
8812
|
-
delete attrs.transform;
|
|
8813
|
-
}
|
|
8814
|
-
// Parse transformOrigin
|
|
8815
|
-
if (dimensions &&
|
|
8816
|
-
(originX !== undefined || originY !== undefined || style.transform)) {
|
|
8817
|
-
style.transformOrigin = calcSVGTransformOrigin(dimensions, originX !== undefined ? originX : 0.5, originY !== undefined ? originY : 0.5);
|
|
8818
|
-
}
|
|
8819
|
-
// Render attrX/attrY/attrScale as attributes
|
|
8820
|
-
if (attrX !== undefined)
|
|
8821
|
-
attrs.x = attrX;
|
|
8822
|
-
if (attrY !== undefined)
|
|
8823
|
-
attrs.y = attrY;
|
|
8824
|
-
if (attrScale !== undefined)
|
|
8825
|
-
attrs.scale = attrScale;
|
|
8826
|
-
// Build SVG path if one has been defined
|
|
8827
|
-
if (pathLength !== undefined) {
|
|
8828
|
-
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8829
|
-
}
|
|
8830
|
-
}
|
|
8831
|
-
|
|
8832
8596
|
const createHtmlRenderState = () => ({
|
|
8833
8597
|
style: {},
|
|
8834
8598
|
transform: {},
|
|
@@ -8836,12 +8600,482 @@ const createHtmlRenderState = () => ({
|
|
|
8836
8600
|
vars: {},
|
|
8837
8601
|
});
|
|
8838
8602
|
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
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
|
+
}
|
|
8843
9072
|
|
|
8844
|
-
const
|
|
9073
|
+
const htmlMotionConfig = {
|
|
9074
|
+
useVisualState: makeUseVisualState({
|
|
9075
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
9076
|
+
createRenderState: createHtmlRenderState,
|
|
9077
|
+
}),
|
|
9078
|
+
};
|
|
8845
9079
|
|
|
8846
9080
|
function renderHTML(element, { style, vars }, styleProp, projection) {
|
|
8847
9081
|
Object.assign(element.style, style, projection && projection.getProjectionStyles(styleProp));
|
|
@@ -8887,29 +9121,6 @@ function renderSVG(element, renderState, _styleProp, projection) {
|
|
|
8887
9121
|
}
|
|
8888
9122
|
}
|
|
8889
9123
|
|
|
8890
|
-
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
8891
|
-
return (transformProps.has(key) ||
|
|
8892
|
-
key.startsWith("origin") ||
|
|
8893
|
-
((layout || layoutId !== undefined) &&
|
|
8894
|
-
(!!scaleCorrectors[key] || key === "opacity")));
|
|
8895
|
-
}
|
|
8896
|
-
|
|
8897
|
-
function scrapeMotionValuesFromProps$1(props, prevProps, visualElement) {
|
|
8898
|
-
var _a;
|
|
8899
|
-
const { style } = props;
|
|
8900
|
-
const newValues = {};
|
|
8901
|
-
for (const key in style) {
|
|
8902
|
-
if (isMotionValue(style[key]) ||
|
|
8903
|
-
(prevProps.style &&
|
|
8904
|
-
isMotionValue(prevProps.style[key])) ||
|
|
8905
|
-
isForcedMotionValue(key, props) ||
|
|
8906
|
-
((_a = visualElement === null || visualElement === void 0 ? void 0 : visualElement.getValue(key)) === null || _a === void 0 ? void 0 : _a.liveStyle) !== undefined) {
|
|
8907
|
-
newValues[key] = style[key];
|
|
8908
|
-
}
|
|
8909
|
-
}
|
|
8910
|
-
return newValues;
|
|
8911
|
-
}
|
|
8912
|
-
|
|
8913
9124
|
function scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
8914
9125
|
const newValues = scrapeMotionValuesFromProps$1(props, prevProps, visualElement);
|
|
8915
9126
|
for (const key in props) {
|
|
@@ -8987,217 +9198,6 @@ const svgMotionConfig = {
|
|
|
8987
9198
|
}),
|
|
8988
9199
|
};
|
|
8989
9200
|
|
|
8990
|
-
const htmlMotionConfig = {
|
|
8991
|
-
useVisualState: makeUseVisualState({
|
|
8992
|
-
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
8993
|
-
createRenderState: createHtmlRenderState,
|
|
8994
|
-
}),
|
|
8995
|
-
};
|
|
8996
|
-
|
|
8997
|
-
function copyRawValuesOnly(target, source, props) {
|
|
8998
|
-
for (const key in source) {
|
|
8999
|
-
if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
9000
|
-
target[key] = source[key];
|
|
9001
|
-
}
|
|
9002
|
-
}
|
|
9003
|
-
}
|
|
9004
|
-
function useInitialMotionValues({ transformTemplate }, visualState) {
|
|
9005
|
-
return react.useMemo(() => {
|
|
9006
|
-
const state = createHtmlRenderState();
|
|
9007
|
-
buildHTMLStyles(state, visualState, transformTemplate);
|
|
9008
|
-
return Object.assign({}, state.vars, state.style);
|
|
9009
|
-
}, [visualState]);
|
|
9010
|
-
}
|
|
9011
|
-
function useStyle(props, visualState) {
|
|
9012
|
-
const styleProp = props.style || {};
|
|
9013
|
-
const style = {};
|
|
9014
|
-
/**
|
|
9015
|
-
* Copy non-Motion Values straight into style
|
|
9016
|
-
*/
|
|
9017
|
-
copyRawValuesOnly(style, styleProp, props);
|
|
9018
|
-
Object.assign(style, useInitialMotionValues(props, visualState));
|
|
9019
|
-
return style;
|
|
9020
|
-
}
|
|
9021
|
-
function useHTMLProps(props, visualState) {
|
|
9022
|
-
// The `any` isn't ideal but it is the type of createElement props argument
|
|
9023
|
-
const htmlProps = {};
|
|
9024
|
-
const style = useStyle(props, visualState);
|
|
9025
|
-
if (props.drag && props.dragListener !== false) {
|
|
9026
|
-
// Disable the ghost element when a user drags
|
|
9027
|
-
htmlProps.draggable = false;
|
|
9028
|
-
// Disable text selection
|
|
9029
|
-
style.userSelect =
|
|
9030
|
-
style.WebkitUserSelect =
|
|
9031
|
-
style.WebkitTouchCallout =
|
|
9032
|
-
"none";
|
|
9033
|
-
// Disable scrolling on the draggable direction
|
|
9034
|
-
style.touchAction =
|
|
9035
|
-
props.drag === true
|
|
9036
|
-
? "none"
|
|
9037
|
-
: `pan-${props.drag === "x" ? "y" : "x"}`;
|
|
9038
|
-
}
|
|
9039
|
-
if (props.tabIndex === undefined &&
|
|
9040
|
-
(props.onTap || props.onTapStart || props.whileTap)) {
|
|
9041
|
-
htmlProps.tabIndex = 0;
|
|
9042
|
-
}
|
|
9043
|
-
htmlProps.style = style;
|
|
9044
|
-
return htmlProps;
|
|
9045
|
-
}
|
|
9046
|
-
|
|
9047
|
-
/**
|
|
9048
|
-
* A list of all valid MotionProps.
|
|
9049
|
-
*
|
|
9050
|
-
* @privateRemarks
|
|
9051
|
-
* This doesn't throw if a `MotionProp` name is missing - it should.
|
|
9052
|
-
*/
|
|
9053
|
-
const validMotionProps = new Set([
|
|
9054
|
-
"animate",
|
|
9055
|
-
"exit",
|
|
9056
|
-
"variants",
|
|
9057
|
-
"initial",
|
|
9058
|
-
"style",
|
|
9059
|
-
"values",
|
|
9060
|
-
"variants",
|
|
9061
|
-
"transition",
|
|
9062
|
-
"transformTemplate",
|
|
9063
|
-
"custom",
|
|
9064
|
-
"inherit",
|
|
9065
|
-
"onBeforeLayoutMeasure",
|
|
9066
|
-
"onAnimationStart",
|
|
9067
|
-
"onAnimationComplete",
|
|
9068
|
-
"onUpdate",
|
|
9069
|
-
"onDragStart",
|
|
9070
|
-
"onDrag",
|
|
9071
|
-
"onDragEnd",
|
|
9072
|
-
"onMeasureDragConstraints",
|
|
9073
|
-
"onDirectionLock",
|
|
9074
|
-
"onDragTransitionEnd",
|
|
9075
|
-
"_dragX",
|
|
9076
|
-
"_dragY",
|
|
9077
|
-
"onHoverStart",
|
|
9078
|
-
"onHoverEnd",
|
|
9079
|
-
"onViewportEnter",
|
|
9080
|
-
"onViewportLeave",
|
|
9081
|
-
"globalTapTarget",
|
|
9082
|
-
"ignoreStrict",
|
|
9083
|
-
"viewport",
|
|
9084
|
-
]);
|
|
9085
|
-
/**
|
|
9086
|
-
* Check whether a prop name is a valid `MotionProp` key.
|
|
9087
|
-
*
|
|
9088
|
-
* @param key - Name of the property to check
|
|
9089
|
-
* @returns `true` is key is a valid `MotionProp`.
|
|
9090
|
-
*
|
|
9091
|
-
* @public
|
|
9092
|
-
*/
|
|
9093
|
-
function isValidMotionProp(key) {
|
|
9094
|
-
return (key.startsWith("while") ||
|
|
9095
|
-
(key.startsWith("drag") && key !== "draggable") ||
|
|
9096
|
-
key.startsWith("layout") ||
|
|
9097
|
-
key.startsWith("onTap") ||
|
|
9098
|
-
key.startsWith("onPan") ||
|
|
9099
|
-
key.startsWith("onLayout") ||
|
|
9100
|
-
validMotionProps.has(key));
|
|
9101
|
-
}
|
|
9102
|
-
|
|
9103
|
-
let shouldForward = (key) => !isValidMotionProp(key);
|
|
9104
|
-
function loadExternalIsValidProp(isValidProp) {
|
|
9105
|
-
if (!isValidProp)
|
|
9106
|
-
return;
|
|
9107
|
-
// Explicitly filter our events
|
|
9108
|
-
shouldForward = (key) => key.startsWith("on") ? !isValidMotionProp(key) : isValidProp(key);
|
|
9109
|
-
}
|
|
9110
|
-
/**
|
|
9111
|
-
* Emotion and Styled Components both allow users to pass through arbitrary props to their components
|
|
9112
|
-
* to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which
|
|
9113
|
-
* of these should be passed to the underlying DOM node.
|
|
9114
|
-
*
|
|
9115
|
-
* However, when styling a Motion component `styled(motion.div)`, both packages pass through *all* props
|
|
9116
|
-
* as it's seen as an arbitrary component rather than a DOM node. Motion only allows arbitrary props
|
|
9117
|
-
* passed through the `custom` prop so it doesn't *need* the payload or computational overhead of
|
|
9118
|
-
* `@emotion/is-prop-valid`, however to fix this problem we need to use it.
|
|
9119
|
-
*
|
|
9120
|
-
* By making it an optionalDependency we can offer this functionality only in the situations where it's
|
|
9121
|
-
* actually required.
|
|
9122
|
-
*/
|
|
9123
|
-
try {
|
|
9124
|
-
/**
|
|
9125
|
-
* We attempt to import this package but require won't be defined in esm environments, in that case
|
|
9126
|
-
* isPropValid will have to be provided via `MotionContext`. In a 6.0.0 this should probably be removed
|
|
9127
|
-
* in favour of explicit injection.
|
|
9128
|
-
*/
|
|
9129
|
-
loadExternalIsValidProp(require("@emotion/is-prop-valid").default);
|
|
9130
|
-
}
|
|
9131
|
-
catch (_a) {
|
|
9132
|
-
// We don't need to actually do anything here - the fallback is the existing `isPropValid`.
|
|
9133
|
-
}
|
|
9134
|
-
function filterProps(props, isDom, forwardMotionProps) {
|
|
9135
|
-
const filteredProps = {};
|
|
9136
|
-
for (const key in props) {
|
|
9137
|
-
/**
|
|
9138
|
-
* values is considered a valid prop by Emotion, so if it's present
|
|
9139
|
-
* this will be rendered out to the DOM unless explicitly filtered.
|
|
9140
|
-
*
|
|
9141
|
-
* We check the type as it could be used with the `feColorMatrix`
|
|
9142
|
-
* element, which we support.
|
|
9143
|
-
*/
|
|
9144
|
-
if (key === "values" && typeof props.values === "object")
|
|
9145
|
-
continue;
|
|
9146
|
-
if (shouldForward(key) ||
|
|
9147
|
-
(forwardMotionProps === true && isValidMotionProp(key)) ||
|
|
9148
|
-
(!isDom && !isValidMotionProp(key)) ||
|
|
9149
|
-
// If trying to use native HTML drag events, forward drag listeners
|
|
9150
|
-
(props["draggable"] &&
|
|
9151
|
-
key.startsWith("onDrag"))) {
|
|
9152
|
-
filteredProps[key] =
|
|
9153
|
-
props[key];
|
|
9154
|
-
}
|
|
9155
|
-
}
|
|
9156
|
-
return filteredProps;
|
|
9157
|
-
}
|
|
9158
|
-
|
|
9159
|
-
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
9160
|
-
const visualProps = react.useMemo(() => {
|
|
9161
|
-
const state = createSvgRenderState();
|
|
9162
|
-
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate);
|
|
9163
|
-
return {
|
|
9164
|
-
...state.attrs,
|
|
9165
|
-
style: { ...state.style },
|
|
9166
|
-
};
|
|
9167
|
-
}, [visualState]);
|
|
9168
|
-
if (props.style) {
|
|
9169
|
-
const rawStyles = {};
|
|
9170
|
-
copyRawValuesOnly(rawStyles, props.style, props);
|
|
9171
|
-
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
9172
|
-
}
|
|
9173
|
-
return visualProps;
|
|
9174
|
-
}
|
|
9175
|
-
|
|
9176
|
-
function createUseRender(forwardMotionProps = false) {
|
|
9177
|
-
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
9178
|
-
const useVisualProps = isSVGComponent(Component)
|
|
9179
|
-
? useSVGProps
|
|
9180
|
-
: useHTMLProps;
|
|
9181
|
-
const visualProps = useVisualProps(props, latestValues, isStatic, Component);
|
|
9182
|
-
const filteredProps = filterProps(props, typeof Component === "string", forwardMotionProps);
|
|
9183
|
-
const elementProps = Component !== react.Fragment
|
|
9184
|
-
? { ...filteredProps, ...visualProps, ref }
|
|
9185
|
-
: {};
|
|
9186
|
-
/**
|
|
9187
|
-
* If component has been handed a motion value as its child,
|
|
9188
|
-
* memoise its initial value and render that. Subsequent updates
|
|
9189
|
-
* will be handled by the onChange handler
|
|
9190
|
-
*/
|
|
9191
|
-
const { children } = props;
|
|
9192
|
-
const renderedChildren = react.useMemo(() => (isMotionValue(children) ? children.get() : children), [children]);
|
|
9193
|
-
return react.createElement(Component, {
|
|
9194
|
-
...elementProps,
|
|
9195
|
-
children: renderedChildren,
|
|
9196
|
-
});
|
|
9197
|
-
};
|
|
9198
|
-
return useRender;
|
|
9199
|
-
}
|
|
9200
|
-
|
|
9201
9201
|
function createMotionComponentFactory(preloadedFeatures, createVisualElement) {
|
|
9202
9202
|
return function createMotionComponent(Component, { forwardMotionProps } = { forwardMotionProps: false }) {
|
|
9203
9203
|
const baseConfig = isSVGComponent(Component)
|
|
@@ -9259,7 +9259,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
9259
9259
|
* and warn against mismatches.
|
|
9260
9260
|
*/
|
|
9261
9261
|
if (process.env.NODE_ENV === "development") {
|
|
9262
|
-
warnOnce(nextValue.version === "12.0.
|
|
9262
|
+
warnOnce(nextValue.version === "12.0.8-alpha.1", `Attempting to mix Motion versions ${nextValue.version} with 12.0.8-alpha.1 may not work as expected.`);
|
|
9263
9263
|
}
|
|
9264
9264
|
}
|
|
9265
9265
|
else if (isMotionValue(prevValue)) {
|
|
@@ -9481,6 +9481,9 @@ class VisualElement {
|
|
|
9481
9481
|
this.valueSubscriptions.get(key)();
|
|
9482
9482
|
}
|
|
9483
9483
|
const valueIsTransform = transformProps.has(key);
|
|
9484
|
+
if (valueIsTransform && this.onBindTransform) {
|
|
9485
|
+
this.onBindTransform();
|
|
9486
|
+
}
|
|
9484
9487
|
const removeOnChange = value.on("change", (latestValue) => {
|
|
9485
9488
|
this.latestValues[key] = latestValue;
|
|
9486
9489
|
this.props.onUpdate && frame.preRender(this.notifyUpdate);
|
|
@@ -9831,6 +9834,11 @@ class SVGVisualElement extends DOMVisualElement {
|
|
|
9831
9834
|
this.type = "svg";
|
|
9832
9835
|
this.isSVGTag = false;
|
|
9833
9836
|
this.measureInstanceViewportBox = createBox;
|
|
9837
|
+
this.updateDimensions = () => {
|
|
9838
|
+
if (this.current && !this.renderState.dimensions) {
|
|
9839
|
+
updateSVGDimensions(this.current, this.renderState);
|
|
9840
|
+
}
|
|
9841
|
+
};
|
|
9834
9842
|
}
|
|
9835
9843
|
getBaseTargetFromProps(props, key) {
|
|
9836
9844
|
return props[key];
|
|
@@ -9846,6 +9854,11 @@ class SVGVisualElement extends DOMVisualElement {
|
|
|
9846
9854
|
scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
9847
9855
|
return scrapeMotionValuesFromProps(props, prevProps, visualElement);
|
|
9848
9856
|
}
|
|
9857
|
+
onBindTransform() {
|
|
9858
|
+
if (this.current && !this.renderState.dimensions) {
|
|
9859
|
+
frame.postRender(this.updateDimensions);
|
|
9860
|
+
}
|
|
9861
|
+
}
|
|
9849
9862
|
build(renderState, latestValues, props) {
|
|
9850
9863
|
buildSVGAttrs(renderState, latestValues, this.isSVGTag, props.transformTemplate);
|
|
9851
9864
|
}
|