@empathyco/x-components
Version:
Empathy X Components
105 lines (102 loc) • 3.76 kB
JavaScript
import { defineComponent, onUpdated, useCssVars } from 'vue';
import { useDisableAnimation } from './use-disable-animation.js';
/**
* Renders a transition group wrapping the elements passed in the default slot and animating
* them with a staggered fade and slide animation.
*
* @public
*/
const __default__ = defineComponent({
name: 'StaggeredFadeAndSlide',
props: {
/** Indicates if the transition must be applied on the initial render of the node. */
appear: {
type: Boolean,
default: true,
},
/** The tag of the node to render to the DOM. */
tag: {
type: String,
default: 'div',
},
/** The time in ms to stagger each item. */
stagger: {
type: Number,
default: 25,
},
},
setup(props) {
/** The duration of the transition in ms. */
const transitionDuration = 250;
/** Indicates if there are new elements to animate. */
let isNewSet = true;
/** The new elements to animate. */
let elementsToAnimate = [];
/** The name of the animation. */
const { name } = useDisableAnimation('x-staggered-fade-and-slide');
/**
* When the component is updated, we are considering that
* a new set of elements is being inserted, so we need
* to refresh the elements to animate.
*/
onUpdated(() => {
isNewSet = true;
});
/**
* Listener called when one frame the element is inserted.
* This calculates the stagger delay to be used as `transitionDelay` and finally resolve
* the transition end after the CSS transition duration plus stagger delay.
*
* @param el - Element inserted.
* @param done - Callback to indicate the transition end.
*/
function onEnter(el, done) {
if (isNewSet) {
refreshElementsToAnimate(el);
}
const elIndex = elementsToAnimate.indexOf(el);
const staggerDelay = elIndex > 0 ? elIndex * props.stagger : 0;
el.style.transitionDelay = `${staggerDelay}ms`;
setTimeout(done, transitionDuration + staggerDelay);
}
/**
* Finds he parent's children subset of new elements entering the DOM.
* This is achieved by filtering out the elements that are already animated.
* Those with 'transition-delay' equal to '0ms' are considered already animated.
*
* Also marks isNewSet as false as the elements are already updated.
*
* @param el - Current element.
*/
function refreshElementsToAnimate(el) {
elementsToAnimate = [...el.parentElement.children].filter(c => c.style.transitionDelay !== '0ms');
isNewSet = false;
}
/**
* Listener called when the enter transition has finished.
* This resets the `transitionDelay`.
*
* @param el - Element inserted.
*/
function onAfterEnter(el) {
el.style.transitionDelay = '0ms';
}
return {
name,
onEnter,
onAfterEnter,
transitionDurationInMs: `${transitionDuration}ms`,
};
},
});
const __injectCSSVars__ = () => {
useCssVars(_ctx => ({
"29c214c5-transitionDurationInMs": (_ctx.transitionDurationInMs)
}));
};
const __setup__ = __default__.setup;
__default__.setup = __setup__
? (props, ctx) => { __injectCSSVars__(); return __setup__(props, ctx); }
: __injectCSSVars__;
export { __default__ as default };
//# sourceMappingURL=staggered-fade-and-slide.vue2.js.map