securityos/node_modules/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs

104 lines
4.0 KiB
JavaScript

import { transformProps } from '../../render/html/utils/transform.mjs';
import { optimizedAppearDataAttribute } from '../optimized-appear/data-id.mjs';
import { animateMotionValue } from './motion-value.mjs';
import { isWillChangeMotionValue } from '../../value/use-will-change/is.mjs';
import { setTarget } from '../../render/utils/setters.mjs';
import { getValueTransition } from '../utils/transitions.mjs';
import { frame } from '../../frameloop/frame.mjs';
/**
* Decide whether we should block this animation. Previously, we achieved this
* just by checking whether the key was listed in protectedKeys, but this
* posed problems if an animation was triggered by afterChildren and protectedKeys
* had been set to true in the meantime.
*/
function shouldBlockAnimation({ protectedKeys, needsAnimating }, key) {
const shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
needsAnimating[key] = false;
return shouldBlock;
}
function hasKeyframesChanged(value, target) {
const current = value.get();
if (Array.isArray(target)) {
for (let i = 0; i < target.length; i++) {
if (target[i] !== current)
return true;
}
}
else {
return current !== target;
}
}
function animateTarget(visualElement, definition, { delay = 0, transitionOverride, type } = {}) {
let { transition = visualElement.getDefaultTransition(), transitionEnd, ...target } = visualElement.makeTargetAnimatable(definition);
const willChange = visualElement.getValue("willChange");
if (transitionOverride)
transition = transitionOverride;
const animations = [];
const animationTypeState = type &&
visualElement.animationState &&
visualElement.animationState.getState()[type];
for (const key in target) {
const value = visualElement.getValue(key);
const valueTarget = target[key];
if (!value ||
valueTarget === undefined ||
(animationTypeState &&
shouldBlockAnimation(animationTypeState, key))) {
continue;
}
const valueTransition = {
delay,
elapsed: 0,
...getValueTransition(transition || {}, key),
};
/**
* If this is the first time a value is being animated, check
* to see if we're handling off from an existing animation.
*/
if (window.HandoffAppearAnimations) {
const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
if (appearId) {
const elapsed = window.HandoffAppearAnimations(appearId, key, value, frame);
if (elapsed !== null) {
valueTransition.elapsed = elapsed;
valueTransition.isHandoff = true;
}
}
}
let canSkip = !valueTransition.isHandoff &&
!hasKeyframesChanged(value, valueTarget);
if (valueTransition.type === "spring" &&
(value.getVelocity() || valueTransition.velocity)) {
canSkip = false;
}
/**
* Temporarily disable skipping animations if there's an animation in
* progress. Better would be to track the current target of a value
* and compare that against valueTarget.
*/
if (value.animation) {
canSkip = false;
}
if (canSkip)
continue;
value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
? { type: false }
: valueTransition));
const animation = value.animation;
if (isWillChangeMotionValue(willChange)) {
willChange.add(key);
animation.then(() => willChange.remove(key));
}
animations.push(animation);
}
if (transitionEnd) {
Promise.all(animations).then(() => {
transitionEnd && setTarget(visualElement, transitionEnd);
});
}
return animations;
}
export { animateTarget };