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.
@@ -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.6";
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
- * We keep these listed separately as we use the lowercase tag names as part
8467
- * of the runtime bundle to detect SVG components
8468
- */
8469
- const lowercaseSVGElements = [
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
- const createSvgRenderState = () => ({
8840
- ...createHtmlRenderState(),
8841
- attrs: {},
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 isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
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.6", `Attempting to mix Motion versions ${nextValue.version} with 12.0.6 may not work as expected.`);
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
  }