motion 12.11.3 → 12.12.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/README.md +21 -5
- package/dist/cjs/index.js +76 -4
- package/dist/cjs/react-client.js +112 -110
- package/dist/cjs/react-m.js +108 -108
- package/dist/es/framer-motion/dist/es/animation/animate/single-value.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/animate/subject.mjs +1 -1
- package/dist/es/framer-motion/dist/es/animation/sequence/create.mjs +1 -1
- package/dist/es/framer-motion/dist/es/components/Reorder/Item.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/dom/DOMVisualElement.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/dom/use-render.mjs +2 -2
- package/dist/es/framer-motion/dist/es/render/html/HTMLVisualElement.mjs +4 -2
- package/dist/es/framer-motion/dist/es/render/html/use-props.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/html/utils/scrape-motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/svg/utils/scrape-motion-values.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/use-motion-template.mjs +1 -1
- package/dist/es/framer-motion/dist/es/value/use-spring.mjs +13 -53
- package/dist/es/framer-motion/dist/es/value/use-will-change/is.mjs +1 -1
- package/dist/es/framer-motion/dist/es/value/utils/resolve-motion-value.mjs +1 -1
- package/dist/es/motion/lib/index.mjs +3 -1
- package/dist/es/motion/lib/react.mjs +3 -2
- package/dist/es/motion-dom/dist/es/render/dom/parse-transform.mjs +1 -1
- package/dist/es/motion-dom/dist/es/utils/interpolate.mjs +1 -1
- package/dist/es/motion-dom/dist/es/value/spring-value.mjs +72 -0
- package/dist/motion.dev.js +76 -4
- package/dist/motion.js +1 -1
- package/package.json +3 -3
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/utils/is-motion-value.mjs +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
2
|
+
<img width="100" height="100" alt="Motion logo" src="https://github.com/user-attachments/assets/00d6d1c3-72c4-4c2f-a664-69da13182ffc" />
|
|
3
3
|
</p>
|
|
4
|
-
<h1 align="center">Motion
|
|
4
|
+
<h1 align="center">Motion</h1>
|
|
5
5
|
|
|
6
6
|
<br>
|
|
7
7
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<hr>
|
|
22
22
|
<br>
|
|
23
23
|
|
|
24
|
-
Motion
|
|
24
|
+
Motion is an open source, production-ready library that’s designed for all creative developers.
|
|
25
25
|
|
|
26
26
|
It's the only animation library with a hybrid engine, combining the power of JavaScript animations with the performance of native browser APIs.
|
|
27
27
|
|
|
@@ -58,7 +58,21 @@ Install `motion` via your package manager:
|
|
|
58
58
|
npm install motion
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
#### JavaScript
|
|
62
|
+
|
|
63
|
+
Import the `animate` function:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
import { animate } from "motion"
|
|
67
|
+
|
|
68
|
+
animate("div", { scale: 1.2 })
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
[Get started](https://motion.dev/docs/quick-start)
|
|
72
|
+
|
|
73
|
+
#### React
|
|
74
|
+
|
|
75
|
+
Import the `motion` component:
|
|
62
76
|
|
|
63
77
|
```jsx
|
|
64
78
|
import { motion } from "motion/react"
|
|
@@ -68,13 +82,15 @@ export function Component({ isVisible }) {
|
|
|
68
82
|
}
|
|
69
83
|
```
|
|
70
84
|
|
|
85
|
+
[Get started](https://motion.dev/docs/react-quick-start)
|
|
86
|
+
|
|
71
87
|
### 💎 Contribute
|
|
72
88
|
|
|
73
89
|
- Want to contribute to Motion? Our [contributing guide](https://github.com/motiondivision/motion/blob/master/CONTRIBUTING.md) has you covered.
|
|
74
90
|
|
|
75
91
|
### 👩🏻⚖️ License
|
|
76
92
|
|
|
77
|
-
- Motion
|
|
93
|
+
- Motion is MIT licensed.
|
|
78
94
|
|
|
79
95
|
## ✨ Sponsors
|
|
80
96
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -1423,7 +1423,7 @@ function createMixers(output, ease, customMixer) {
|
|
|
1423
1423
|
* mixColor(0.5) // 'rgba(128, 128, 128, 1)'
|
|
1424
1424
|
* ```
|
|
1425
1425
|
*
|
|
1426
|
-
* TODO
|
|
1426
|
+
* TODO Revisit this approach once we've moved to data models for values,
|
|
1427
1427
|
* probably not needed to pregenerate mixer functions.
|
|
1428
1428
|
*
|
|
1429
1429
|
* @public
|
|
@@ -4268,6 +4268,74 @@ function mapValue(inputValue, inputRange, outputRange, options) {
|
|
|
4268
4268
|
return transformValue(() => map(inputValue.get()));
|
|
4269
4269
|
}
|
|
4270
4270
|
|
|
4271
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
4272
|
+
|
|
4273
|
+
/**
|
|
4274
|
+
* Create a `MotionValue` that animates to its latest value using a spring.
|
|
4275
|
+
* Can either be a value or track another `MotionValue`.
|
|
4276
|
+
*
|
|
4277
|
+
* ```jsx
|
|
4278
|
+
* const x = motionValue(0)
|
|
4279
|
+
* const y = transformValue(() => x.get() * 2) // double x
|
|
4280
|
+
* ```
|
|
4281
|
+
*
|
|
4282
|
+
* @param transformer - A transform function. This function must be pure with no side-effects or conditional statements.
|
|
4283
|
+
* @returns `MotionValue`
|
|
4284
|
+
*
|
|
4285
|
+
* @public
|
|
4286
|
+
*/
|
|
4287
|
+
function springValue(source, options) {
|
|
4288
|
+
const initialValue = isMotionValue(source) ? source.get() : source;
|
|
4289
|
+
const value = motionValue(initialValue);
|
|
4290
|
+
attachSpring(value, source, options);
|
|
4291
|
+
return value;
|
|
4292
|
+
}
|
|
4293
|
+
function attachSpring(value, source, options) {
|
|
4294
|
+
const initialValue = value.get();
|
|
4295
|
+
let activeAnimation = null;
|
|
4296
|
+
let latestValue = initialValue;
|
|
4297
|
+
let latestSetter;
|
|
4298
|
+
const unit = typeof initialValue === "string"
|
|
4299
|
+
? initialValue.replace(/[\d.-]/g, "")
|
|
4300
|
+
: undefined;
|
|
4301
|
+
const stopAnimation = () => {
|
|
4302
|
+
if (activeAnimation) {
|
|
4303
|
+
activeAnimation.stop();
|
|
4304
|
+
activeAnimation = null;
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
const startAnimation = () => {
|
|
4308
|
+
stopAnimation();
|
|
4309
|
+
activeAnimation = new JSAnimation({
|
|
4310
|
+
keyframes: [asNumber(value.get()), asNumber(latestValue)],
|
|
4311
|
+
velocity: value.getVelocity(),
|
|
4312
|
+
type: "spring",
|
|
4313
|
+
restDelta: 0.001,
|
|
4314
|
+
restSpeed: 0.01,
|
|
4315
|
+
...options,
|
|
4316
|
+
onUpdate: latestSetter,
|
|
4317
|
+
});
|
|
4318
|
+
};
|
|
4319
|
+
value.attach((v, set) => {
|
|
4320
|
+
latestValue = v;
|
|
4321
|
+
latestSetter = (latest) => set(parseValue(latest, unit));
|
|
4322
|
+
frame.postRender(startAnimation);
|
|
4323
|
+
return value.get();
|
|
4324
|
+
}, stopAnimation);
|
|
4325
|
+
let unsubscribe = undefined;
|
|
4326
|
+
if (isMotionValue(source)) {
|
|
4327
|
+
unsubscribe = source.on("change", (v) => value.set(parseValue(v, unit)));
|
|
4328
|
+
value.on("destroy", unsubscribe);
|
|
4329
|
+
}
|
|
4330
|
+
return unsubscribe;
|
|
4331
|
+
}
|
|
4332
|
+
function parseValue(v, unit) {
|
|
4333
|
+
return unit ? v + unit : v;
|
|
4334
|
+
}
|
|
4335
|
+
function asNumber(v) {
|
|
4336
|
+
return typeof v === "number" ? v : parseFloat(v);
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4271
4339
|
/**
|
|
4272
4340
|
* A list of all ValueTypes
|
|
4273
4341
|
*/
|
|
@@ -4604,8 +4672,6 @@ const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
|
4604
4672
|
return acc;
|
|
4605
4673
|
}, {});
|
|
4606
4674
|
|
|
4607
|
-
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
4608
|
-
|
|
4609
4675
|
function isDOMKeyframes(keyframes) {
|
|
4610
4676
|
return typeof keyframes === "object" && !Array.isArray(keyframes);
|
|
4611
4677
|
}
|
|
@@ -6087,7 +6153,9 @@ class HTMLVisualElement extends DOMVisualElement {
|
|
|
6087
6153
|
}
|
|
6088
6154
|
readValueFromInstance(instance, key) {
|
|
6089
6155
|
if (transformProps.has(key)) {
|
|
6090
|
-
return
|
|
6156
|
+
return this.projection?.isProjecting
|
|
6157
|
+
? defaultTransformValue(key)
|
|
6158
|
+
: readTransformValue(instance, key);
|
|
6091
6159
|
}
|
|
6092
6160
|
else {
|
|
6093
6161
|
const computedStyle = getComputedStyle$1(instance);
|
|
@@ -7184,6 +7252,7 @@ exports.animateView = animateView;
|
|
|
7184
7252
|
exports.animationMapKey = animationMapKey;
|
|
7185
7253
|
exports.anticipate = anticipate;
|
|
7186
7254
|
exports.applyPxDefaults = applyPxDefaults;
|
|
7255
|
+
exports.attachSpring = attachSpring;
|
|
7187
7256
|
exports.backIn = backIn;
|
|
7188
7257
|
exports.backInOut = backInOut;
|
|
7189
7258
|
exports.backOut = backOut;
|
|
@@ -7206,6 +7275,7 @@ exports.cubicBezier = cubicBezier;
|
|
|
7206
7275
|
exports.cubicBezierAsString = cubicBezierAsString;
|
|
7207
7276
|
exports.defaultEasing = defaultEasing;
|
|
7208
7277
|
exports.defaultOffset = defaultOffset$1;
|
|
7278
|
+
exports.defaultTransformValue = defaultTransformValue;
|
|
7209
7279
|
exports.defaultValueTypes = defaultValueTypes;
|
|
7210
7280
|
exports.degrees = degrees;
|
|
7211
7281
|
exports.delay = delayInSeconds;
|
|
@@ -7250,6 +7320,7 @@ exports.isDragActive = isDragActive;
|
|
|
7250
7320
|
exports.isDragging = isDragging;
|
|
7251
7321
|
exports.isEasingArray = isEasingArray;
|
|
7252
7322
|
exports.isGenerator = isGenerator;
|
|
7323
|
+
exports.isMotionValue = isMotionValue;
|
|
7253
7324
|
exports.isNodeOrChild = isNodeOrChild;
|
|
7254
7325
|
exports.isNumericalString = isNumericalString;
|
|
7255
7326
|
exports.isPrimaryPointer = isPrimaryPointer;
|
|
@@ -7301,6 +7372,7 @@ exports.secondsToMilliseconds = secondsToMilliseconds;
|
|
|
7301
7372
|
exports.setDragLock = setDragLock;
|
|
7302
7373
|
exports.setStyle = setStyle;
|
|
7303
7374
|
exports.spring = spring;
|
|
7375
|
+
exports.springValue = springValue;
|
|
7304
7376
|
exports.stagger = stagger;
|
|
7305
7377
|
exports.startWaapiAnimation = startWaapiAnimation;
|
|
7306
7378
|
exports.statsBuffer = statsBuffer;
|
package/dist/cjs/react-client.js
CHANGED
|
@@ -1432,7 +1432,7 @@ function createMixers(output, ease, customMixer) {
|
|
|
1432
1432
|
* mixColor(0.5) // 'rgba(128, 128, 128, 1)'
|
|
1433
1433
|
* ```
|
|
1434
1434
|
*
|
|
1435
|
-
* TODO
|
|
1435
|
+
* TODO Revisit this approach once we've moved to data models for values,
|
|
1436
1436
|
* probably not needed to pregenerate mixer functions.
|
|
1437
1437
|
*
|
|
1438
1438
|
* @public
|
|
@@ -3741,6 +3741,8 @@ function press(targetOrSelector, onPressStart, options = {}) {
|
|
|
3741
3741
|
return cancelEvents;
|
|
3742
3742
|
}
|
|
3743
3743
|
|
|
3744
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
3745
|
+
|
|
3744
3746
|
/**
|
|
3745
3747
|
* A list of all ValueTypes
|
|
3746
3748
|
*/
|
|
@@ -3780,8 +3782,6 @@ function setTarget(visualElement, definition) {
|
|
|
3780
3782
|
}
|
|
3781
3783
|
}
|
|
3782
3784
|
|
|
3783
|
-
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
3784
|
-
|
|
3785
3785
|
function isWillChangeMotionValue(value) {
|
|
3786
3786
|
return Boolean(isMotionValue(value) && value.add);
|
|
3787
3787
|
}
|
|
@@ -8652,6 +8652,112 @@ function useHTMLProps(props, visualState) {
|
|
|
8652
8652
|
return htmlProps;
|
|
8653
8653
|
}
|
|
8654
8654
|
|
|
8655
|
+
const dashKeys = {
|
|
8656
|
+
offset: "stroke-dashoffset",
|
|
8657
|
+
array: "stroke-dasharray",
|
|
8658
|
+
};
|
|
8659
|
+
const camelKeys = {
|
|
8660
|
+
offset: "strokeDashoffset",
|
|
8661
|
+
array: "strokeDasharray",
|
|
8662
|
+
};
|
|
8663
|
+
/**
|
|
8664
|
+
* Build SVG path properties. Uses the path's measured length to convert
|
|
8665
|
+
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8666
|
+
* and stroke-dasharray attributes.
|
|
8667
|
+
*
|
|
8668
|
+
* This function is mutative to reduce per-frame GC.
|
|
8669
|
+
*/
|
|
8670
|
+
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8671
|
+
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8672
|
+
attrs.pathLength = 1;
|
|
8673
|
+
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8674
|
+
// when defining props on a React component.
|
|
8675
|
+
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8676
|
+
// Build the dash offset
|
|
8677
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
8678
|
+
// Build the dash array
|
|
8679
|
+
const pathLength = px.transform(length);
|
|
8680
|
+
const pathSpacing = px.transform(spacing);
|
|
8681
|
+
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8682
|
+
}
|
|
8683
|
+
|
|
8684
|
+
/**
|
|
8685
|
+
* Build SVG visual attrbutes, like cx and style.transform
|
|
8686
|
+
*/
|
|
8687
|
+
function buildSVGAttrs(state, { attrX, attrY, attrScale, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8688
|
+
// This is object creation, which we try to avoid per-frame.
|
|
8689
|
+
...latest }, isSVGTag, transformTemplate, styleProp) {
|
|
8690
|
+
buildHTMLStyles(state, latest, transformTemplate);
|
|
8691
|
+
/**
|
|
8692
|
+
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8693
|
+
* as normal HTML tags.
|
|
8694
|
+
*/
|
|
8695
|
+
if (isSVGTag) {
|
|
8696
|
+
if (state.style.viewBox) {
|
|
8697
|
+
state.attrs.viewBox = state.style.viewBox;
|
|
8698
|
+
}
|
|
8699
|
+
return;
|
|
8700
|
+
}
|
|
8701
|
+
state.attrs = state.style;
|
|
8702
|
+
state.style = {};
|
|
8703
|
+
const { attrs, style } = state;
|
|
8704
|
+
/**
|
|
8705
|
+
* However, we apply transforms as CSS transforms.
|
|
8706
|
+
* So if we detect a transform, transformOrigin we take it from attrs and copy it into style.
|
|
8707
|
+
*/
|
|
8708
|
+
if (attrs.transform) {
|
|
8709
|
+
style.transform = attrs.transform;
|
|
8710
|
+
delete attrs.transform;
|
|
8711
|
+
}
|
|
8712
|
+
if (style.transform || attrs.transformOrigin) {
|
|
8713
|
+
style.transformOrigin = attrs.transformOrigin ?? "50% 50%";
|
|
8714
|
+
delete attrs.transformOrigin;
|
|
8715
|
+
}
|
|
8716
|
+
if (style.transform) {
|
|
8717
|
+
/**
|
|
8718
|
+
* SVG's element transform-origin uses its own median as a reference.
|
|
8719
|
+
* Therefore, transformBox becomes a fill-box
|
|
8720
|
+
*/
|
|
8721
|
+
style.transformBox = styleProp?.transformBox ?? "fill-box";
|
|
8722
|
+
delete attrs.transformBox;
|
|
8723
|
+
}
|
|
8724
|
+
// Render attrX/attrY/attrScale as attributes
|
|
8725
|
+
if (attrX !== undefined)
|
|
8726
|
+
attrs.x = attrX;
|
|
8727
|
+
if (attrY !== undefined)
|
|
8728
|
+
attrs.y = attrY;
|
|
8729
|
+
if (attrScale !== undefined)
|
|
8730
|
+
attrs.scale = attrScale;
|
|
8731
|
+
// Build SVG path if one has been defined
|
|
8732
|
+
if (pathLength !== undefined) {
|
|
8733
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8734
|
+
}
|
|
8735
|
+
}
|
|
8736
|
+
|
|
8737
|
+
const createSvgRenderState = () => ({
|
|
8738
|
+
...createHtmlRenderState(),
|
|
8739
|
+
attrs: {},
|
|
8740
|
+
});
|
|
8741
|
+
|
|
8742
|
+
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
8743
|
+
|
|
8744
|
+
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
8745
|
+
const visualProps = react.useMemo(() => {
|
|
8746
|
+
const state = createSvgRenderState();
|
|
8747
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
8748
|
+
return {
|
|
8749
|
+
...state.attrs,
|
|
8750
|
+
style: { ...state.style },
|
|
8751
|
+
};
|
|
8752
|
+
}, [visualState]);
|
|
8753
|
+
if (props.style) {
|
|
8754
|
+
const rawStyles = {};
|
|
8755
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
8756
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
8757
|
+
}
|
|
8758
|
+
return visualProps;
|
|
8759
|
+
}
|
|
8760
|
+
|
|
8655
8761
|
/**
|
|
8656
8762
|
* A list of all valid MotionProps.
|
|
8657
8763
|
*
|
|
@@ -8823,112 +8929,6 @@ function isSVGComponent(Component) {
|
|
|
8823
8929
|
return false;
|
|
8824
8930
|
}
|
|
8825
8931
|
|
|
8826
|
-
const dashKeys = {
|
|
8827
|
-
offset: "stroke-dashoffset",
|
|
8828
|
-
array: "stroke-dasharray",
|
|
8829
|
-
};
|
|
8830
|
-
const camelKeys = {
|
|
8831
|
-
offset: "strokeDashoffset",
|
|
8832
|
-
array: "strokeDasharray",
|
|
8833
|
-
};
|
|
8834
|
-
/**
|
|
8835
|
-
* Build SVG path properties. Uses the path's measured length to convert
|
|
8836
|
-
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8837
|
-
* and stroke-dasharray attributes.
|
|
8838
|
-
*
|
|
8839
|
-
* This function is mutative to reduce per-frame GC.
|
|
8840
|
-
*/
|
|
8841
|
-
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8842
|
-
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8843
|
-
attrs.pathLength = 1;
|
|
8844
|
-
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8845
|
-
// when defining props on a React component.
|
|
8846
|
-
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8847
|
-
// Build the dash offset
|
|
8848
|
-
attrs[keys.offset] = px.transform(-offset);
|
|
8849
|
-
// Build the dash array
|
|
8850
|
-
const pathLength = px.transform(length);
|
|
8851
|
-
const pathSpacing = px.transform(spacing);
|
|
8852
|
-
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8853
|
-
}
|
|
8854
|
-
|
|
8855
|
-
/**
|
|
8856
|
-
* Build SVG visual attrbutes, like cx and style.transform
|
|
8857
|
-
*/
|
|
8858
|
-
function buildSVGAttrs(state, { attrX, attrY, attrScale, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8859
|
-
// This is object creation, which we try to avoid per-frame.
|
|
8860
|
-
...latest }, isSVGTag, transformTemplate, styleProp) {
|
|
8861
|
-
buildHTMLStyles(state, latest, transformTemplate);
|
|
8862
|
-
/**
|
|
8863
|
-
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8864
|
-
* as normal HTML tags.
|
|
8865
|
-
*/
|
|
8866
|
-
if (isSVGTag) {
|
|
8867
|
-
if (state.style.viewBox) {
|
|
8868
|
-
state.attrs.viewBox = state.style.viewBox;
|
|
8869
|
-
}
|
|
8870
|
-
return;
|
|
8871
|
-
}
|
|
8872
|
-
state.attrs = state.style;
|
|
8873
|
-
state.style = {};
|
|
8874
|
-
const { attrs, style } = state;
|
|
8875
|
-
/**
|
|
8876
|
-
* However, we apply transforms as CSS transforms.
|
|
8877
|
-
* So if we detect a transform, transformOrigin we take it from attrs and copy it into style.
|
|
8878
|
-
*/
|
|
8879
|
-
if (attrs.transform) {
|
|
8880
|
-
style.transform = attrs.transform;
|
|
8881
|
-
delete attrs.transform;
|
|
8882
|
-
}
|
|
8883
|
-
if (style.transform || attrs.transformOrigin) {
|
|
8884
|
-
style.transformOrigin = attrs.transformOrigin ?? "50% 50%";
|
|
8885
|
-
delete attrs.transformOrigin;
|
|
8886
|
-
}
|
|
8887
|
-
if (style.transform) {
|
|
8888
|
-
/**
|
|
8889
|
-
* SVG's element transform-origin uses its own median as a reference.
|
|
8890
|
-
* Therefore, transformBox becomes a fill-box
|
|
8891
|
-
*/
|
|
8892
|
-
style.transformBox = styleProp?.transformBox ?? "fill-box";
|
|
8893
|
-
delete attrs.transformBox;
|
|
8894
|
-
}
|
|
8895
|
-
// Render attrX/attrY/attrScale as attributes
|
|
8896
|
-
if (attrX !== undefined)
|
|
8897
|
-
attrs.x = attrX;
|
|
8898
|
-
if (attrY !== undefined)
|
|
8899
|
-
attrs.y = attrY;
|
|
8900
|
-
if (attrScale !== undefined)
|
|
8901
|
-
attrs.scale = attrScale;
|
|
8902
|
-
// Build SVG path if one has been defined
|
|
8903
|
-
if (pathLength !== undefined) {
|
|
8904
|
-
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8905
|
-
}
|
|
8906
|
-
}
|
|
8907
|
-
|
|
8908
|
-
const createSvgRenderState = () => ({
|
|
8909
|
-
...createHtmlRenderState(),
|
|
8910
|
-
attrs: {},
|
|
8911
|
-
});
|
|
8912
|
-
|
|
8913
|
-
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
8914
|
-
|
|
8915
|
-
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
8916
|
-
const visualProps = react.useMemo(() => {
|
|
8917
|
-
const state = createSvgRenderState();
|
|
8918
|
-
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
8919
|
-
return {
|
|
8920
|
-
...state.attrs,
|
|
8921
|
-
style: { ...state.style },
|
|
8922
|
-
};
|
|
8923
|
-
}, [visualState]);
|
|
8924
|
-
if (props.style) {
|
|
8925
|
-
const rawStyles = {};
|
|
8926
|
-
copyRawValuesOnly(rawStyles, props.style, props);
|
|
8927
|
-
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
8928
|
-
}
|
|
8929
|
-
return visualProps;
|
|
8930
|
-
}
|
|
8931
|
-
|
|
8932
8932
|
function createUseRender(forwardMotionProps = false) {
|
|
8933
8933
|
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
8934
8934
|
const useVisualProps = isSVGComponent(Component)
|
|
@@ -9677,7 +9677,9 @@ class HTMLVisualElement extends DOMVisualElement {
|
|
|
9677
9677
|
}
|
|
9678
9678
|
readValueFromInstance(instance, key) {
|
|
9679
9679
|
if (transformProps.has(key)) {
|
|
9680
|
-
return
|
|
9680
|
+
return this.projection?.isProjecting
|
|
9681
|
+
? defaultTransformValue(key)
|
|
9682
|
+
: readTransformValue(instance, key);
|
|
9681
9683
|
}
|
|
9682
9684
|
else {
|
|
9683
9685
|
const computedStyle = getComputedStyle$1(instance);
|
package/dist/cjs/react-m.js
CHANGED
|
@@ -497,6 +497,8 @@ const getValueAsType = (value, type) => {
|
|
|
497
497
|
const { schedule: microtask, cancel: cancelMicrotask } =
|
|
498
498
|
/* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
|
|
499
499
|
|
|
500
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
501
|
+
|
|
500
502
|
/**
|
|
501
503
|
* Convert camelCase to dash-case properties.
|
|
502
504
|
*/
|
|
@@ -732,8 +734,6 @@ function isForcedMotionValue(key, { layout, layoutId }) {
|
|
|
732
734
|
(!!scaleCorrectors[key] || key === "opacity")));
|
|
733
735
|
}
|
|
734
736
|
|
|
735
|
-
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
736
|
-
|
|
737
737
|
const translateAlias = {
|
|
738
738
|
x: "translateX",
|
|
739
739
|
y: "translateY",
|
|
@@ -906,6 +906,112 @@ function useHTMLProps(props, visualState) {
|
|
|
906
906
|
return htmlProps;
|
|
907
907
|
}
|
|
908
908
|
|
|
909
|
+
const dashKeys = {
|
|
910
|
+
offset: "stroke-dashoffset",
|
|
911
|
+
array: "stroke-dasharray",
|
|
912
|
+
};
|
|
913
|
+
const camelKeys = {
|
|
914
|
+
offset: "strokeDashoffset",
|
|
915
|
+
array: "strokeDasharray",
|
|
916
|
+
};
|
|
917
|
+
/**
|
|
918
|
+
* Build SVG path properties. Uses the path's measured length to convert
|
|
919
|
+
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
920
|
+
* and stroke-dasharray attributes.
|
|
921
|
+
*
|
|
922
|
+
* This function is mutative to reduce per-frame GC.
|
|
923
|
+
*/
|
|
924
|
+
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
925
|
+
// Normalise path length by setting SVG attribute pathLength to 1
|
|
926
|
+
attrs.pathLength = 1;
|
|
927
|
+
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
928
|
+
// when defining props on a React component.
|
|
929
|
+
const keys = useDashCase ? dashKeys : camelKeys;
|
|
930
|
+
// Build the dash offset
|
|
931
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
932
|
+
// Build the dash array
|
|
933
|
+
const pathLength = px.transform(length);
|
|
934
|
+
const pathSpacing = px.transform(spacing);
|
|
935
|
+
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Build SVG visual attrbutes, like cx and style.transform
|
|
940
|
+
*/
|
|
941
|
+
function buildSVGAttrs(state, { attrX, attrY, attrScale, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
942
|
+
// This is object creation, which we try to avoid per-frame.
|
|
943
|
+
...latest }, isSVGTag, transformTemplate, styleProp) {
|
|
944
|
+
buildHTMLStyles(state, latest, transformTemplate);
|
|
945
|
+
/**
|
|
946
|
+
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
947
|
+
* as normal HTML tags.
|
|
948
|
+
*/
|
|
949
|
+
if (isSVGTag) {
|
|
950
|
+
if (state.style.viewBox) {
|
|
951
|
+
state.attrs.viewBox = state.style.viewBox;
|
|
952
|
+
}
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
state.attrs = state.style;
|
|
956
|
+
state.style = {};
|
|
957
|
+
const { attrs, style } = state;
|
|
958
|
+
/**
|
|
959
|
+
* However, we apply transforms as CSS transforms.
|
|
960
|
+
* So if we detect a transform, transformOrigin we take it from attrs and copy it into style.
|
|
961
|
+
*/
|
|
962
|
+
if (attrs.transform) {
|
|
963
|
+
style.transform = attrs.transform;
|
|
964
|
+
delete attrs.transform;
|
|
965
|
+
}
|
|
966
|
+
if (style.transform || attrs.transformOrigin) {
|
|
967
|
+
style.transformOrigin = attrs.transformOrigin ?? "50% 50%";
|
|
968
|
+
delete attrs.transformOrigin;
|
|
969
|
+
}
|
|
970
|
+
if (style.transform) {
|
|
971
|
+
/**
|
|
972
|
+
* SVG's element transform-origin uses its own median as a reference.
|
|
973
|
+
* Therefore, transformBox becomes a fill-box
|
|
974
|
+
*/
|
|
975
|
+
style.transformBox = styleProp?.transformBox ?? "fill-box";
|
|
976
|
+
delete attrs.transformBox;
|
|
977
|
+
}
|
|
978
|
+
// Render attrX/attrY/attrScale as attributes
|
|
979
|
+
if (attrX !== undefined)
|
|
980
|
+
attrs.x = attrX;
|
|
981
|
+
if (attrY !== undefined)
|
|
982
|
+
attrs.y = attrY;
|
|
983
|
+
if (attrScale !== undefined)
|
|
984
|
+
attrs.scale = attrScale;
|
|
985
|
+
// Build SVG path if one has been defined
|
|
986
|
+
if (pathLength !== undefined) {
|
|
987
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
const createSvgRenderState = () => ({
|
|
992
|
+
...createHtmlRenderState(),
|
|
993
|
+
attrs: {},
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
997
|
+
|
|
998
|
+
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
999
|
+
const visualProps = react.useMemo(() => {
|
|
1000
|
+
const state = createSvgRenderState();
|
|
1001
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
1002
|
+
return {
|
|
1003
|
+
...state.attrs,
|
|
1004
|
+
style: { ...state.style },
|
|
1005
|
+
};
|
|
1006
|
+
}, [visualState]);
|
|
1007
|
+
if (props.style) {
|
|
1008
|
+
const rawStyles = {};
|
|
1009
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
1010
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
1011
|
+
}
|
|
1012
|
+
return visualProps;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
909
1015
|
/**
|
|
910
1016
|
* A list of all valid MotionProps.
|
|
911
1017
|
*
|
|
@@ -1077,112 +1183,6 @@ function isSVGComponent(Component) {
|
|
|
1077
1183
|
return false;
|
|
1078
1184
|
}
|
|
1079
1185
|
|
|
1080
|
-
const dashKeys = {
|
|
1081
|
-
offset: "stroke-dashoffset",
|
|
1082
|
-
array: "stroke-dasharray",
|
|
1083
|
-
};
|
|
1084
|
-
const camelKeys = {
|
|
1085
|
-
offset: "strokeDashoffset",
|
|
1086
|
-
array: "strokeDasharray",
|
|
1087
|
-
};
|
|
1088
|
-
/**
|
|
1089
|
-
* Build SVG path properties. Uses the path's measured length to convert
|
|
1090
|
-
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
1091
|
-
* and stroke-dasharray attributes.
|
|
1092
|
-
*
|
|
1093
|
-
* This function is mutative to reduce per-frame GC.
|
|
1094
|
-
*/
|
|
1095
|
-
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
1096
|
-
// Normalise path length by setting SVG attribute pathLength to 1
|
|
1097
|
-
attrs.pathLength = 1;
|
|
1098
|
-
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
1099
|
-
// when defining props on a React component.
|
|
1100
|
-
const keys = useDashCase ? dashKeys : camelKeys;
|
|
1101
|
-
// Build the dash offset
|
|
1102
|
-
attrs[keys.offset] = px.transform(-offset);
|
|
1103
|
-
// Build the dash array
|
|
1104
|
-
const pathLength = px.transform(length);
|
|
1105
|
-
const pathSpacing = px.transform(spacing);
|
|
1106
|
-
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
/**
|
|
1110
|
-
* Build SVG visual attrbutes, like cx and style.transform
|
|
1111
|
-
*/
|
|
1112
|
-
function buildSVGAttrs(state, { attrX, attrY, attrScale, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
1113
|
-
// This is object creation, which we try to avoid per-frame.
|
|
1114
|
-
...latest }, isSVGTag, transformTemplate, styleProp) {
|
|
1115
|
-
buildHTMLStyles(state, latest, transformTemplate);
|
|
1116
|
-
/**
|
|
1117
|
-
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
1118
|
-
* as normal HTML tags.
|
|
1119
|
-
*/
|
|
1120
|
-
if (isSVGTag) {
|
|
1121
|
-
if (state.style.viewBox) {
|
|
1122
|
-
state.attrs.viewBox = state.style.viewBox;
|
|
1123
|
-
}
|
|
1124
|
-
return;
|
|
1125
|
-
}
|
|
1126
|
-
state.attrs = state.style;
|
|
1127
|
-
state.style = {};
|
|
1128
|
-
const { attrs, style } = state;
|
|
1129
|
-
/**
|
|
1130
|
-
* However, we apply transforms as CSS transforms.
|
|
1131
|
-
* So if we detect a transform, transformOrigin we take it from attrs and copy it into style.
|
|
1132
|
-
*/
|
|
1133
|
-
if (attrs.transform) {
|
|
1134
|
-
style.transform = attrs.transform;
|
|
1135
|
-
delete attrs.transform;
|
|
1136
|
-
}
|
|
1137
|
-
if (style.transform || attrs.transformOrigin) {
|
|
1138
|
-
style.transformOrigin = attrs.transformOrigin ?? "50% 50%";
|
|
1139
|
-
delete attrs.transformOrigin;
|
|
1140
|
-
}
|
|
1141
|
-
if (style.transform) {
|
|
1142
|
-
/**
|
|
1143
|
-
* SVG's element transform-origin uses its own median as a reference.
|
|
1144
|
-
* Therefore, transformBox becomes a fill-box
|
|
1145
|
-
*/
|
|
1146
|
-
style.transformBox = styleProp?.transformBox ?? "fill-box";
|
|
1147
|
-
delete attrs.transformBox;
|
|
1148
|
-
}
|
|
1149
|
-
// Render attrX/attrY/attrScale as attributes
|
|
1150
|
-
if (attrX !== undefined)
|
|
1151
|
-
attrs.x = attrX;
|
|
1152
|
-
if (attrY !== undefined)
|
|
1153
|
-
attrs.y = attrY;
|
|
1154
|
-
if (attrScale !== undefined)
|
|
1155
|
-
attrs.scale = attrScale;
|
|
1156
|
-
// Build SVG path if one has been defined
|
|
1157
|
-
if (pathLength !== undefined) {
|
|
1158
|
-
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
const createSvgRenderState = () => ({
|
|
1163
|
-
...createHtmlRenderState(),
|
|
1164
|
-
attrs: {},
|
|
1165
|
-
});
|
|
1166
|
-
|
|
1167
|
-
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
1168
|
-
|
|
1169
|
-
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
1170
|
-
const visualProps = react.useMemo(() => {
|
|
1171
|
-
const state = createSvgRenderState();
|
|
1172
|
-
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
1173
|
-
return {
|
|
1174
|
-
...state.attrs,
|
|
1175
|
-
style: { ...state.style },
|
|
1176
|
-
};
|
|
1177
|
-
}, [visualState]);
|
|
1178
|
-
if (props.style) {
|
|
1179
|
-
const rawStyles = {};
|
|
1180
|
-
copyRawValuesOnly(rawStyles, props.style, props);
|
|
1181
|
-
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
1182
|
-
}
|
|
1183
|
-
return visualProps;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
1186
|
function createUseRender(forwardMotionProps = false) {
|
|
1187
1187
|
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
1188
1188
|
const useVisualProps = isSVGComponent(Component)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isMotionValue } from '../../value/utils/is-motion-value.mjs';
|
|
2
1
|
import { animateMotionValue } from '../interfaces/motion-value.mjs';
|
|
2
|
+
import { isMotionValue } from '../../../../../motion-dom/dist/es/value/utils/is-motion-value.mjs';
|
|
3
3
|
import { motionValue } from '../../../../../motion-dom/dist/es/value/index.mjs';
|
|
4
4
|
|
|
5
5
|
function animateSingleValue(value, keyframes, options) {
|