64 lines
2.7 KiB
JavaScript
64 lines
2.7 KiB
JavaScript
import { resolveVariant } from '../../render/utils/resolve-dynamic-variants.mjs';
|
|
import { animateTarget } from './visual-element-target.mjs';
|
|
|
|
function animateVariant(visualElement, variant, options = {}) {
|
|
const resolved = resolveVariant(visualElement, variant, options.custom);
|
|
let { transition = visualElement.getDefaultTransition() || {} } = resolved || {};
|
|
if (options.transitionOverride) {
|
|
transition = options.transitionOverride;
|
|
}
|
|
/**
|
|
* If we have a variant, create a callback that runs it as an animation.
|
|
* Otherwise, we resolve a Promise immediately for a composable no-op.
|
|
*/
|
|
const getAnimation = resolved
|
|
? () => Promise.all(animateTarget(visualElement, resolved, options))
|
|
: () => Promise.resolve();
|
|
/**
|
|
* If we have children, create a callback that runs all their animations.
|
|
* Otherwise, we resolve a Promise immediately for a composable no-op.
|
|
*/
|
|
const getChildAnimations = visualElement.variantChildren && visualElement.variantChildren.size
|
|
? (forwardDelay = 0) => {
|
|
const { delayChildren = 0, staggerChildren, staggerDirection, } = transition;
|
|
return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
|
|
}
|
|
: () => Promise.resolve();
|
|
/**
|
|
* If the transition explicitly defines a "when" option, we need to resolve either
|
|
* this animation or all children animations before playing the other.
|
|
*/
|
|
const { when } = transition;
|
|
if (when) {
|
|
const [first, last] = when === "beforeChildren"
|
|
? [getAnimation, getChildAnimations]
|
|
: [getChildAnimations, getAnimation];
|
|
return first().then(() => last());
|
|
}
|
|
else {
|
|
return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
|
|
}
|
|
}
|
|
function animateChildren(visualElement, variant, delayChildren = 0, staggerChildren = 0, staggerDirection = 1, options) {
|
|
const animations = [];
|
|
const maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
|
|
const generateStaggerDuration = staggerDirection === 1
|
|
? (i = 0) => i * staggerChildren
|
|
: (i = 0) => maxStaggerDuration - i * staggerChildren;
|
|
Array.from(visualElement.variantChildren)
|
|
.sort(sortByTreeOrder)
|
|
.forEach((child, i) => {
|
|
child.notify("AnimationStart", variant);
|
|
animations.push(animateVariant(child, variant, {
|
|
...options,
|
|
delay: delayChildren + generateStaggerDuration(i),
|
|
}).then(() => child.notify("AnimationComplete", variant)));
|
|
});
|
|
return Promise.all(animations);
|
|
}
|
|
function sortByTreeOrder(a, b) {
|
|
return a.sortNodePosition(b);
|
|
}
|
|
|
|
export { animateVariant, sortByTreeOrder };
|