UNPKG

@ebay/ebayui-core

Version:

Collection of core eBay components; considered to be the building blocks for all composite structures, pages & apps.

97 lines (96 loc) 2.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const TRANSITION_END = "transitionend"; /** * Applies a primer `-init` class before starting a transition * to make transitioning properties that are not animatable easier. * * **Order** * 1. Add class: "$className-init" * 2. Wait one frame. * 3. Remove class "$className-init". * 4. Add class "$className". * 5. Wait for animation to finish. * 6. Remove class "$className". * * @param {HTMLElement} options.el The root element that contains the animation. * @param {string} options.className The base className to use for the transition. * @param {Element[]} options.waitFor Elements that will transition and should be waited for. * @param {Function} cb A callback called after the transition as ended. */ exports.default = ({ el, className, waitFor, }, cb) => { let ended; let ran = 0; const pending = waitFor ? waitFor.length : 0; const classList = el.classList; const initClass = `${className}-init`; if (!("ontransitionend" in el)) { const id = setTimeout(cb, 0); return () => clearTimeout(id); } let cancelFrame = nextFrame(() => { cancelFrame = undefined; classList.add(className); classList.remove(initClass); if (pending) { waitFor.forEach((child) => child.addEventListener(TRANSITION_END, listener)); } else { cancel(); if (cb) { cb(); } } }); classList.add(initClass); return cancel; /** * Cancels the current transition and resets the className. */ function cancel() { if (ended) { return; } ended = true; for (let i = ran; i < pending; i++) { const child = waitFor[i]; child.removeEventListener(TRANSITION_END, listener); } if (cancelFrame) { cancelFrame(); classList.remove(initClass); } else { classList.remove(className); } } /** * Handles a single transition end event. * Once all child transitions have ended the overall animation is completed. */ function listener({ target, }) { target === null || target === void 0 ? void 0 : target.removeEventListener(TRANSITION_END, listener); if (++ran === pending) { ended = true; classList.remove(className); if (cb) { cb(); } } } }; /** * Runs a function during the next animation frame. */ function nextFrame(fn) { let frame; frame = requestAnimationFrame(() => { frame = requestAnimationFrame(fn); }); return () => { if (frame) { cancelAnimationFrame(frame); frame = 0; } }; }