/** * Starts a spinning animation and returns a function to be called when it should be stopped * The callback will be called when the animation is finished * It waits until a full rotation is complete */ function applyLoadingAnimation(element: HTMLElement, time: number, callback?: () => void): () => Promise { element.style.animation = `rotate ${time}s 0s infinite`; return async () => new Promise((resolve) => { // Make the animation finite element.style.animation = `rotate ${time}s`; // When the animation is over, hide the button const animationEndListener = () => { if (callback) callback(); element.style.animation = "none"; element.removeEventListener("animationend", animationEndListener); resolve(); }; element.addEventListener("animationend", animationEndListener); }); } function setupCustomHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): { hide: () => void, show: () => void } { if (enabled) element.classList.add("autoHiding"); element.classList.add("hidden"); element.classList.add("animationDone"); if (!rightSlide) element.classList.add("autoHideLeft"); let mouseEntered = false; return { hide: () => { mouseEntered = false; if (element.classList.contains("autoHiding")) { element.classList.add("hidden"); } }, show: () => { mouseEntered = true; element.classList.remove("animationDone"); // Wait for next event loop setTimeout(() => { if (mouseEntered) element.classList.remove("hidden") }, 10); } }; } function setupAutoHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): void { const { hide, show } = this.setupCustomHideAnimation(element, container, enabled, rightSlide); container.addEventListener("mouseleave", () => hide()); container.addEventListener("mouseenter", () => show()); } function enableAutoHideAnimation(element: Element): void { element.classList.add("autoHiding"); element.classList.add("hidden"); } function disableAutoHideAnimation(element: Element): void { element.classList.remove("autoHiding"); element.classList.remove("hidden"); } export const AnimationUtils = { applyLoadingAnimation, setupAutoHideAnimation, setupCustomHideAnimation, enableAutoHideAnimation, disableAutoHideAnimation };