interface AnimateWithClassOptions { className: string animationName: string } /** Adds a CSS class to an element and waits for the triggered animation to complete. */ export async function animateWithClass( element: HTMLElement, { className, animationName }: AnimateWithClassOptions ): Promise { if (!element.parentNode) throw Error("Element is not in DOM") // TODO: This promise should be rejected if element is removed from DOM. const promise = new Promise(resolve => { const listener = (e: AnimationEvent): void => { if (!(e.target instanceof Node) || !element.contains(e.target) || e.animationName !== animationName) return element.removeEventListener("animationend", listener) resolve() } element.addEventListener("animationend", listener) }) element.classList.add(className) return promise }