UNPKG

@empathyco/x-components

Version:
105 lines (102 loc) 3.76 kB
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