motion 12.11.4 → 12.12.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 +110 -16
- package/dist/cjs/react-client.js +141 -120
- 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/animation/utils/create-visual-element.mjs +3 -2
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs +4 -1
- package/dist/es/framer-motion/dist/es/components/Reorder/Item.mjs +1 -1
- package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +3 -2
- 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/resize/handle-element.mjs +2 -1
- package/dist/es/framer-motion/dist/es/render/dom/scroll/offsets/inset.mjs +3 -1
- package/dist/es/framer-motion/dist/es/render/dom/use-render.mjs +2 -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 +6 -0
- package/dist/es/motion/lib/react.mjs +6 -1
- package/dist/es/motion-dom/dist/es/animation/waapi/supports/waapi.mjs +3 -5
- package/dist/es/motion-dom/dist/es/gestures/press/index.mjs +2 -1
- package/dist/es/motion-dom/dist/es/utils/interpolate.mjs +1 -1
- package/dist/es/motion-dom/dist/es/utils/is-html-element.mjs +11 -0
- package/dist/es/motion-dom/dist/es/utils/is-svg-element.mjs +11 -0
- package/dist/es/motion-dom/dist/es/utils/is-svg-svg-element.mjs +11 -0
- package/dist/es/motion-dom/dist/es/value/spring-value.mjs +72 -0
- package/dist/es/motion-utils/dist/es/is-object.mjs +5 -0
- package/dist/motion.dev.js +110 -16
- package/dist/motion.js +1 -1
- package/package.json +3 -3
- package/dist/es/framer-motion/dist/es/render/dom/utils/is-svg-element.mjs +0 -5
- /package/dist/es/{framer-motion → motion-dom}/dist/es/value/utils/is-motion-value.mjs +0 -0
package/dist/cjs/index.js
CHANGED
|
@@ -52,6 +52,10 @@ const MotionGlobalConfig = {};
|
|
|
52
52
|
*/
|
|
53
53
|
const isNumericalString = (v) => /^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(v);
|
|
54
54
|
|
|
55
|
+
function isObject(value) {
|
|
56
|
+
return typeof value === "object" && value !== null;
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
/**
|
|
56
60
|
* Check if the value is a zero value string like "0px" or "0%"
|
|
57
61
|
*/
|
|
@@ -1423,7 +1427,7 @@ function createMixers(output, ease, customMixer) {
|
|
|
1423
1427
|
* mixColor(0.5) // 'rgba(128, 128, 128, 1)'
|
|
1424
1428
|
* ```
|
|
1425
1429
|
*
|
|
1426
|
-
* TODO
|
|
1430
|
+
* TODO Revisit this approach once we've moved to data models for values,
|
|
1427
1431
|
* probably not needed to pregenerate mixer functions.
|
|
1428
1432
|
*
|
|
1429
1433
|
* @public
|
|
@@ -2596,6 +2600,14 @@ function canAnimate(keyframes, name, type, velocity) {
|
|
|
2596
2600
|
((type === "spring" || isGenerator(type)) && velocity));
|
|
2597
2601
|
}
|
|
2598
2602
|
|
|
2603
|
+
/**
|
|
2604
|
+
* Checks if an element is an HTML element in a way
|
|
2605
|
+
* that works across iframes
|
|
2606
|
+
*/
|
|
2607
|
+
function isHTMLElement(element) {
|
|
2608
|
+
return isObject(element) && "offsetHeight" in element;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2599
2611
|
/**
|
|
2600
2612
|
* A list of values that can be hardware-accelerated.
|
|
2601
2613
|
*/
|
|
@@ -2604,16 +2616,13 @@ const acceleratedValues$1 = new Set([
|
|
|
2604
2616
|
"clipPath",
|
|
2605
2617
|
"filter",
|
|
2606
2618
|
"transform",
|
|
2607
|
-
// TODO:
|
|
2608
|
-
// or until we implement support for linear() easing.
|
|
2619
|
+
// TODO: Could be re-enabled now we have support for linear() easing
|
|
2609
2620
|
// "background-color"
|
|
2610
2621
|
]);
|
|
2611
2622
|
const supportsWaapi = /*@__PURE__*/ memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
|
|
2612
2623
|
function supportsBrowserAnimation(options) {
|
|
2613
2624
|
const { motionValue, name, repeatDelay, repeatType, damping, type } = options;
|
|
2614
|
-
if (!motionValue
|
|
2615
|
-
!motionValue.owner ||
|
|
2616
|
-
!(motionValue.owner.current instanceof HTMLElement)) {
|
|
2625
|
+
if (!isHTMLElement(motionValue?.owner?.current)) {
|
|
2617
2626
|
return false;
|
|
2618
2627
|
}
|
|
2619
2628
|
const { onUpdate, transformTemplate } = motionValue.owner.getProps();
|
|
@@ -4029,7 +4038,7 @@ function press(targetOrSelector, onPressStart, options = {}) {
|
|
|
4029
4038
|
targets.forEach((target) => {
|
|
4030
4039
|
const pointerDownTarget = options.useGlobalTarget ? window : target;
|
|
4031
4040
|
pointerDownTarget.addEventListener("pointerdown", startPress, eventOptions);
|
|
4032
|
-
if (target
|
|
4041
|
+
if (isHTMLElement(target)) {
|
|
4033
4042
|
target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions));
|
|
4034
4043
|
if (!isElementKeyboardAccessible(target) &&
|
|
4035
4044
|
!target.hasAttribute("tabindex")) {
|
|
@@ -4174,6 +4183,22 @@ function recordStats() {
|
|
|
4174
4183
|
return reportStats;
|
|
4175
4184
|
}
|
|
4176
4185
|
|
|
4186
|
+
/**
|
|
4187
|
+
* Checks if an element is an SVG element in a way
|
|
4188
|
+
* that works across iframes
|
|
4189
|
+
*/
|
|
4190
|
+
function isSVGElement(element) {
|
|
4191
|
+
return isObject(element) && "ownerSVGElement" in element;
|
|
4192
|
+
}
|
|
4193
|
+
|
|
4194
|
+
/**
|
|
4195
|
+
* Checks if an element is specifically an SVGSVGElement (the root SVG element)
|
|
4196
|
+
* in a way that works across iframes
|
|
4197
|
+
*/
|
|
4198
|
+
function isSVGSVGElement(element) {
|
|
4199
|
+
return isSVGElement(element) && element.tagName === "svg";
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4177
4202
|
function transform(...args) {
|
|
4178
4203
|
const useImmediate = !Array.isArray(args[0]);
|
|
4179
4204
|
const argOffset = useImmediate ? 0 : -1;
|
|
@@ -4268,6 +4293,74 @@ function mapValue(inputValue, inputRange, outputRange, options) {
|
|
|
4268
4293
|
return transformValue(() => map(inputValue.get()));
|
|
4269
4294
|
}
|
|
4270
4295
|
|
|
4296
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
4297
|
+
|
|
4298
|
+
/**
|
|
4299
|
+
* Create a `MotionValue` that animates to its latest value using a spring.
|
|
4300
|
+
* Can either be a value or track another `MotionValue`.
|
|
4301
|
+
*
|
|
4302
|
+
* ```jsx
|
|
4303
|
+
* const x = motionValue(0)
|
|
4304
|
+
* const y = transformValue(() => x.get() * 2) // double x
|
|
4305
|
+
* ```
|
|
4306
|
+
*
|
|
4307
|
+
* @param transformer - A transform function. This function must be pure with no side-effects or conditional statements.
|
|
4308
|
+
* @returns `MotionValue`
|
|
4309
|
+
*
|
|
4310
|
+
* @public
|
|
4311
|
+
*/
|
|
4312
|
+
function springValue(source, options) {
|
|
4313
|
+
const initialValue = isMotionValue(source) ? source.get() : source;
|
|
4314
|
+
const value = motionValue(initialValue);
|
|
4315
|
+
attachSpring(value, source, options);
|
|
4316
|
+
return value;
|
|
4317
|
+
}
|
|
4318
|
+
function attachSpring(value, source, options) {
|
|
4319
|
+
const initialValue = value.get();
|
|
4320
|
+
let activeAnimation = null;
|
|
4321
|
+
let latestValue = initialValue;
|
|
4322
|
+
let latestSetter;
|
|
4323
|
+
const unit = typeof initialValue === "string"
|
|
4324
|
+
? initialValue.replace(/[\d.-]/g, "")
|
|
4325
|
+
: undefined;
|
|
4326
|
+
const stopAnimation = () => {
|
|
4327
|
+
if (activeAnimation) {
|
|
4328
|
+
activeAnimation.stop();
|
|
4329
|
+
activeAnimation = null;
|
|
4330
|
+
}
|
|
4331
|
+
};
|
|
4332
|
+
const startAnimation = () => {
|
|
4333
|
+
stopAnimation();
|
|
4334
|
+
activeAnimation = new JSAnimation({
|
|
4335
|
+
keyframes: [asNumber(value.get()), asNumber(latestValue)],
|
|
4336
|
+
velocity: value.getVelocity(),
|
|
4337
|
+
type: "spring",
|
|
4338
|
+
restDelta: 0.001,
|
|
4339
|
+
restSpeed: 0.01,
|
|
4340
|
+
...options,
|
|
4341
|
+
onUpdate: latestSetter,
|
|
4342
|
+
});
|
|
4343
|
+
};
|
|
4344
|
+
value.attach((v, set) => {
|
|
4345
|
+
latestValue = v;
|
|
4346
|
+
latestSetter = (latest) => set(parseValue(latest, unit));
|
|
4347
|
+
frame.postRender(startAnimation);
|
|
4348
|
+
return value.get();
|
|
4349
|
+
}, stopAnimation);
|
|
4350
|
+
let unsubscribe = undefined;
|
|
4351
|
+
if (isMotionValue(source)) {
|
|
4352
|
+
unsubscribe = source.on("change", (v) => value.set(parseValue(v, unit)));
|
|
4353
|
+
value.on("destroy", unsubscribe);
|
|
4354
|
+
}
|
|
4355
|
+
return unsubscribe;
|
|
4356
|
+
}
|
|
4357
|
+
function parseValue(v, unit) {
|
|
4358
|
+
return unit ? v + unit : v;
|
|
4359
|
+
}
|
|
4360
|
+
function asNumber(v) {
|
|
4361
|
+
return typeof v === "number" ? v : parseFloat(v);
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4271
4364
|
/**
|
|
4272
4365
|
* A list of all ValueTypes
|
|
4273
4366
|
*/
|
|
@@ -4604,8 +4697,6 @@ const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
|
4604
4697
|
return acc;
|
|
4605
4698
|
}, {});
|
|
4606
4699
|
|
|
4607
|
-
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
4608
|
-
|
|
4609
4700
|
function isDOMKeyframes(keyframes) {
|
|
4610
4701
|
return typeof keyframes === "object" && !Array.isArray(keyframes);
|
|
4611
4702
|
}
|
|
@@ -5266,10 +5357,6 @@ function animateTarget(visualElement, targetAndTransition, { delay = 0, transiti
|
|
|
5266
5357
|
return animations;
|
|
5267
5358
|
}
|
|
5268
5359
|
|
|
5269
|
-
function isSVGElement(element) {
|
|
5270
|
-
return element instanceof SVGElement && element.tagName !== "svg";
|
|
5271
|
-
}
|
|
5272
|
-
|
|
5273
5360
|
/**
|
|
5274
5361
|
* Bounding boxes tend to be defined as top, left, right, bottom. For various operations
|
|
5275
5362
|
* it's easier to consider each axis individually. This function returns a bounding box
|
|
@@ -6329,7 +6416,7 @@ function createDOMVisualElement(element) {
|
|
|
6329
6416
|
latestValues: {},
|
|
6330
6417
|
},
|
|
6331
6418
|
};
|
|
6332
|
-
const node = isSVGElement(element)
|
|
6419
|
+
const node = isSVGElement(element) && !isSVGSVGElement(element)
|
|
6333
6420
|
? new SVGVisualElement(options)
|
|
6334
6421
|
: new HTMLVisualElement(options);
|
|
6335
6422
|
node.mount(element);
|
|
@@ -6553,7 +6640,7 @@ function getElementSize(target, borderBoxSize) {
|
|
|
6553
6640
|
const { inlineSize, blockSize } = borderBoxSize[0];
|
|
6554
6641
|
return { width: inlineSize, height: blockSize };
|
|
6555
6642
|
}
|
|
6556
|
-
else if (target
|
|
6643
|
+
else if (isSVGElement(target) && "getBBox" in target) {
|
|
6557
6644
|
return target.getBBox();
|
|
6558
6645
|
}
|
|
6559
6646
|
else {
|
|
@@ -6695,7 +6782,7 @@ function calcInset(element, container) {
|
|
|
6695
6782
|
const inset = { x: 0, y: 0 };
|
|
6696
6783
|
let current = element;
|
|
6697
6784
|
while (current && current !== container) {
|
|
6698
|
-
if (current
|
|
6785
|
+
if (isHTMLElement(current)) {
|
|
6699
6786
|
inset.x += current.offsetLeft;
|
|
6700
6787
|
inset.y += current.offsetTop;
|
|
6701
6788
|
current = current.offsetParent;
|
|
@@ -7186,6 +7273,7 @@ exports.animateView = animateView;
|
|
|
7186
7273
|
exports.animationMapKey = animationMapKey;
|
|
7187
7274
|
exports.anticipate = anticipate;
|
|
7188
7275
|
exports.applyPxDefaults = applyPxDefaults;
|
|
7276
|
+
exports.attachSpring = attachSpring;
|
|
7189
7277
|
exports.backIn = backIn;
|
|
7190
7278
|
exports.backInOut = backInOut;
|
|
7191
7279
|
exports.backOut = backOut;
|
|
@@ -7253,9 +7341,14 @@ exports.isDragActive = isDragActive;
|
|
|
7253
7341
|
exports.isDragging = isDragging;
|
|
7254
7342
|
exports.isEasingArray = isEasingArray;
|
|
7255
7343
|
exports.isGenerator = isGenerator;
|
|
7344
|
+
exports.isHTMLElement = isHTMLElement;
|
|
7345
|
+
exports.isMotionValue = isMotionValue;
|
|
7256
7346
|
exports.isNodeOrChild = isNodeOrChild;
|
|
7257
7347
|
exports.isNumericalString = isNumericalString;
|
|
7348
|
+
exports.isObject = isObject;
|
|
7258
7349
|
exports.isPrimaryPointer = isPrimaryPointer;
|
|
7350
|
+
exports.isSVGElement = isSVGElement;
|
|
7351
|
+
exports.isSVGSVGElement = isSVGSVGElement;
|
|
7259
7352
|
exports.isWaapiSupportedEasing = isWaapiSupportedEasing;
|
|
7260
7353
|
exports.isZeroValueString = isZeroValueString;
|
|
7261
7354
|
exports.keyframes = keyframes;
|
|
@@ -7304,6 +7397,7 @@ exports.secondsToMilliseconds = secondsToMilliseconds;
|
|
|
7304
7397
|
exports.setDragLock = setDragLock;
|
|
7305
7398
|
exports.setStyle = setStyle;
|
|
7306
7399
|
exports.spring = spring;
|
|
7400
|
+
exports.springValue = springValue;
|
|
7307
7401
|
exports.stagger = stagger;
|
|
7308
7402
|
exports.startWaapiAnimation = startWaapiAnimation;
|
|
7309
7403
|
exports.statsBuffer = statsBuffer;
|
package/dist/cjs/react-client.js
CHANGED
|
@@ -91,6 +91,10 @@ const MotionGlobalConfig = {};
|
|
|
91
91
|
*/
|
|
92
92
|
const isNumericalString = (v) => /^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(v);
|
|
93
93
|
|
|
94
|
+
function isObject(value) {
|
|
95
|
+
return typeof value === "object" && value !== null;
|
|
96
|
+
}
|
|
97
|
+
|
|
94
98
|
/**
|
|
95
99
|
* Check if the value is a zero value string like "0px" or "0%"
|
|
96
100
|
*/
|
|
@@ -1432,7 +1436,7 @@ function createMixers(output, ease, customMixer) {
|
|
|
1432
1436
|
* mixColor(0.5) // 'rgba(128, 128, 128, 1)'
|
|
1433
1437
|
* ```
|
|
1434
1438
|
*
|
|
1435
|
-
* TODO
|
|
1439
|
+
* TODO Revisit this approach once we've moved to data models for values,
|
|
1436
1440
|
* probably not needed to pregenerate mixer functions.
|
|
1437
1441
|
*
|
|
1438
1442
|
* @public
|
|
@@ -2591,6 +2595,14 @@ function canAnimate(keyframes, name, type, velocity) {
|
|
|
2591
2595
|
((type === "spring" || isGenerator(type)) && velocity));
|
|
2592
2596
|
}
|
|
2593
2597
|
|
|
2598
|
+
/**
|
|
2599
|
+
* Checks if an element is an HTML element in a way
|
|
2600
|
+
* that works across iframes
|
|
2601
|
+
*/
|
|
2602
|
+
function isHTMLElement(element) {
|
|
2603
|
+
return isObject(element) && "offsetHeight" in element;
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2594
2606
|
/**
|
|
2595
2607
|
* A list of values that can be hardware-accelerated.
|
|
2596
2608
|
*/
|
|
@@ -2599,16 +2611,13 @@ const acceleratedValues = new Set([
|
|
|
2599
2611
|
"clipPath",
|
|
2600
2612
|
"filter",
|
|
2601
2613
|
"transform",
|
|
2602
|
-
// TODO:
|
|
2603
|
-
// or until we implement support for linear() easing.
|
|
2614
|
+
// TODO: Could be re-enabled now we have support for linear() easing
|
|
2604
2615
|
// "background-color"
|
|
2605
2616
|
]);
|
|
2606
2617
|
const supportsWaapi = /*@__PURE__*/ memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
|
|
2607
2618
|
function supportsBrowserAnimation(options) {
|
|
2608
2619
|
const { motionValue, name, repeatDelay, repeatType, damping, type } = options;
|
|
2609
|
-
if (!motionValue
|
|
2610
|
-
!motionValue.owner ||
|
|
2611
|
-
!(motionValue.owner.current instanceof HTMLElement)) {
|
|
2620
|
+
if (!isHTMLElement(motionValue?.owner?.current)) {
|
|
2612
2621
|
return false;
|
|
2613
2622
|
}
|
|
2614
2623
|
const { onUpdate, transformTemplate } = motionValue.owner.getProps();
|
|
@@ -3730,7 +3739,7 @@ function press(targetOrSelector, onPressStart, options = {}) {
|
|
|
3730
3739
|
targets.forEach((target) => {
|
|
3731
3740
|
const pointerDownTarget = options.useGlobalTarget ? window : target;
|
|
3732
3741
|
pointerDownTarget.addEventListener("pointerdown", startPress, eventOptions);
|
|
3733
|
-
if (target
|
|
3742
|
+
if (isHTMLElement(target)) {
|
|
3734
3743
|
target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions));
|
|
3735
3744
|
if (!isElementKeyboardAccessible(target) &&
|
|
3736
3745
|
!target.hasAttribute("tabindex")) {
|
|
@@ -3741,6 +3750,24 @@ function press(targetOrSelector, onPressStart, options = {}) {
|
|
|
3741
3750
|
return cancelEvents;
|
|
3742
3751
|
}
|
|
3743
3752
|
|
|
3753
|
+
/**
|
|
3754
|
+
* Checks if an element is an SVG element in a way
|
|
3755
|
+
* that works across iframes
|
|
3756
|
+
*/
|
|
3757
|
+
function isSVGElement(element) {
|
|
3758
|
+
return isObject(element) && "ownerSVGElement" in element;
|
|
3759
|
+
}
|
|
3760
|
+
|
|
3761
|
+
/**
|
|
3762
|
+
* Checks if an element is specifically an SVGSVGElement (the root SVG element)
|
|
3763
|
+
* in a way that works across iframes
|
|
3764
|
+
*/
|
|
3765
|
+
function isSVGSVGElement(element) {
|
|
3766
|
+
return isSVGElement(element) && element.tagName === "svg";
|
|
3767
|
+
}
|
|
3768
|
+
|
|
3769
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
3770
|
+
|
|
3744
3771
|
/**
|
|
3745
3772
|
* A list of all ValueTypes
|
|
3746
3773
|
*/
|
|
@@ -3780,8 +3807,6 @@ function setTarget(visualElement, definition) {
|
|
|
3780
3807
|
}
|
|
3781
3808
|
}
|
|
3782
3809
|
|
|
3783
|
-
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
3784
|
-
|
|
3785
3810
|
function isWillChangeMotionValue(value) {
|
|
3786
3811
|
return Boolean(isMotionValue(value) && value.add);
|
|
3787
3812
|
}
|
|
@@ -5955,10 +5980,6 @@ function animateSingleValue(value, keyframes, options) {
|
|
|
5955
5980
|
return motionValue$1.animation;
|
|
5956
5981
|
}
|
|
5957
5982
|
|
|
5958
|
-
function isSVGElement(element) {
|
|
5959
|
-
return element instanceof SVGElement && element.tagName !== "svg";
|
|
5960
|
-
}
|
|
5961
|
-
|
|
5962
5983
|
const compareByDepth = (a, b) => a.depth - b.depth;
|
|
5963
5984
|
|
|
5964
5985
|
class FlatTree {
|
|
@@ -6550,7 +6571,7 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
6550
6571
|
mount(instance) {
|
|
6551
6572
|
if (this.instance)
|
|
6552
6573
|
return;
|
|
6553
|
-
this.isSVG = isSVGElement(instance);
|
|
6574
|
+
this.isSVG = isSVGElement(instance) && !isSVGSVGElement(instance);
|
|
6554
6575
|
this.instance = instance;
|
|
6555
6576
|
const { layoutId, layout, visualElement } = this.options;
|
|
6556
6577
|
if (visualElement && !visualElement.current) {
|
|
@@ -8652,6 +8673,112 @@ function useHTMLProps(props, visualState) {
|
|
|
8652
8673
|
return htmlProps;
|
|
8653
8674
|
}
|
|
8654
8675
|
|
|
8676
|
+
const dashKeys = {
|
|
8677
|
+
offset: "stroke-dashoffset",
|
|
8678
|
+
array: "stroke-dasharray",
|
|
8679
|
+
};
|
|
8680
|
+
const camelKeys = {
|
|
8681
|
+
offset: "strokeDashoffset",
|
|
8682
|
+
array: "strokeDasharray",
|
|
8683
|
+
};
|
|
8684
|
+
/**
|
|
8685
|
+
* Build SVG path properties. Uses the path's measured length to convert
|
|
8686
|
+
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
8687
|
+
* and stroke-dasharray attributes.
|
|
8688
|
+
*
|
|
8689
|
+
* This function is mutative to reduce per-frame GC.
|
|
8690
|
+
*/
|
|
8691
|
+
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
8692
|
+
// Normalise path length by setting SVG attribute pathLength to 1
|
|
8693
|
+
attrs.pathLength = 1;
|
|
8694
|
+
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
8695
|
+
// when defining props on a React component.
|
|
8696
|
+
const keys = useDashCase ? dashKeys : camelKeys;
|
|
8697
|
+
// Build the dash offset
|
|
8698
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
8699
|
+
// Build the dash array
|
|
8700
|
+
const pathLength = px.transform(length);
|
|
8701
|
+
const pathSpacing = px.transform(spacing);
|
|
8702
|
+
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
8703
|
+
}
|
|
8704
|
+
|
|
8705
|
+
/**
|
|
8706
|
+
* Build SVG visual attrbutes, like cx and style.transform
|
|
8707
|
+
*/
|
|
8708
|
+
function buildSVGAttrs(state, { attrX, attrY, attrScale, pathLength, pathSpacing = 1, pathOffset = 0,
|
|
8709
|
+
// This is object creation, which we try to avoid per-frame.
|
|
8710
|
+
...latest }, isSVGTag, transformTemplate, styleProp) {
|
|
8711
|
+
buildHTMLStyles(state, latest, transformTemplate);
|
|
8712
|
+
/**
|
|
8713
|
+
* For svg tags we just want to make sure viewBox is animatable and treat all the styles
|
|
8714
|
+
* as normal HTML tags.
|
|
8715
|
+
*/
|
|
8716
|
+
if (isSVGTag) {
|
|
8717
|
+
if (state.style.viewBox) {
|
|
8718
|
+
state.attrs.viewBox = state.style.viewBox;
|
|
8719
|
+
}
|
|
8720
|
+
return;
|
|
8721
|
+
}
|
|
8722
|
+
state.attrs = state.style;
|
|
8723
|
+
state.style = {};
|
|
8724
|
+
const { attrs, style } = state;
|
|
8725
|
+
/**
|
|
8726
|
+
* However, we apply transforms as CSS transforms.
|
|
8727
|
+
* So if we detect a transform, transformOrigin we take it from attrs and copy it into style.
|
|
8728
|
+
*/
|
|
8729
|
+
if (attrs.transform) {
|
|
8730
|
+
style.transform = attrs.transform;
|
|
8731
|
+
delete attrs.transform;
|
|
8732
|
+
}
|
|
8733
|
+
if (style.transform || attrs.transformOrigin) {
|
|
8734
|
+
style.transformOrigin = attrs.transformOrigin ?? "50% 50%";
|
|
8735
|
+
delete attrs.transformOrigin;
|
|
8736
|
+
}
|
|
8737
|
+
if (style.transform) {
|
|
8738
|
+
/**
|
|
8739
|
+
* SVG's element transform-origin uses its own median as a reference.
|
|
8740
|
+
* Therefore, transformBox becomes a fill-box
|
|
8741
|
+
*/
|
|
8742
|
+
style.transformBox = styleProp?.transformBox ?? "fill-box";
|
|
8743
|
+
delete attrs.transformBox;
|
|
8744
|
+
}
|
|
8745
|
+
// Render attrX/attrY/attrScale as attributes
|
|
8746
|
+
if (attrX !== undefined)
|
|
8747
|
+
attrs.x = attrX;
|
|
8748
|
+
if (attrY !== undefined)
|
|
8749
|
+
attrs.y = attrY;
|
|
8750
|
+
if (attrScale !== undefined)
|
|
8751
|
+
attrs.scale = attrScale;
|
|
8752
|
+
// Build SVG path if one has been defined
|
|
8753
|
+
if (pathLength !== undefined) {
|
|
8754
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
8755
|
+
}
|
|
8756
|
+
}
|
|
8757
|
+
|
|
8758
|
+
const createSvgRenderState = () => ({
|
|
8759
|
+
...createHtmlRenderState(),
|
|
8760
|
+
attrs: {},
|
|
8761
|
+
});
|
|
8762
|
+
|
|
8763
|
+
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
8764
|
+
|
|
8765
|
+
function useSVGProps(props, visualState, _isStatic, Component) {
|
|
8766
|
+
const visualProps = react.useMemo(() => {
|
|
8767
|
+
const state = createSvgRenderState();
|
|
8768
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
8769
|
+
return {
|
|
8770
|
+
...state.attrs,
|
|
8771
|
+
style: { ...state.style },
|
|
8772
|
+
};
|
|
8773
|
+
}, [visualState]);
|
|
8774
|
+
if (props.style) {
|
|
8775
|
+
const rawStyles = {};
|
|
8776
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
8777
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
8778
|
+
}
|
|
8779
|
+
return visualProps;
|
|
8780
|
+
}
|
|
8781
|
+
|
|
8655
8782
|
/**
|
|
8656
8783
|
* A list of all valid MotionProps.
|
|
8657
8784
|
*
|
|
@@ -8823,112 +8950,6 @@ function isSVGComponent(Component) {
|
|
|
8823
8950
|
return false;
|
|
8824
8951
|
}
|
|
8825
8952
|
|
|
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
8953
|
function createUseRender(forwardMotionProps = false) {
|
|
8933
8954
|
const useRender = (Component, props, ref, { latestValues }, isStatic) => {
|
|
8934
8955
|
const useVisualProps = isSVGComponent(Component)
|