{"version":3,"names":["RIPPLE","getAnimationDurationInMilliseconds","radiusPixels","Math","cbrt","setPositionRelativeIfStatic","element","getComputedStyle","position","classList","add","createRipple","event","options","button","_a","parent","currentTarget","existingRipple","getElementsByClassName","remove","Array","from","children","forEach","ripple","document","createElement","style","backgroundColor","color","setAttribute","diameter","max","clientWidth","clientHeight","radius","animationDuration","top","left","getBoundingClientRect","width","height","clientX","clientY","setProperty","prepend","cleanupAnimationOnFinish","async","listenOnce","setTimeout"],"sources":["src/utils/ripple.ts"],"sourcesContent":["import {listenOnce} from './event-utils';\n\ninterface RippleOptions {\n color: string;\n /**\n * When the ripple's parent is not the event's origin\n */\n parent?: Element;\n}\n\nconst RIPPLE = 'ripple';\n\nfunction getAnimationDurationInMilliseconds(radiusPixels: number) {\n // A 318px wide button has a duration of 700ms.\n return Math.cbrt(radiusPixels) * 129.21;\n}\n\nfunction setPositionRelativeIfStatic(element: Element) {\n if (getComputedStyle(element).position === 'static') {\n element.classList.add('ripple-relative');\n }\n}\n\nexport function createRipple(event: MouseEvent, options: RippleOptions) {\n const button = options.parent ?? (event.currentTarget as Element);\n const existingRipple = button.getElementsByClassName(RIPPLE)[0];\n existingRipple && existingRipple.remove();\n\n button.classList.add('ripple-parent');\n setPositionRelativeIfStatic(button);\n Array.from(button.children).forEach(setPositionRelativeIfStatic);\n\n const ripple = document.createElement('span');\n ripple.classList.add(RIPPLE);\n ripple.style.backgroundColor = `var(--atomic-${options.color})`;\n ripple.setAttribute('part', RIPPLE);\n\n const diameter = Math.max(button.clientWidth, button.clientHeight);\n const radius = diameter / 2;\n const animationDuration = getAnimationDurationInMilliseconds(radius);\n const {top, left} = button.getBoundingClientRect();\n ripple.style.width = ripple.style.height = `${diameter}px`;\n ripple.style.left = `${event.clientX - (left + radius)}px`;\n ripple.style.top = `${event.clientY - (top + radius)}px`;\n ripple.style.setProperty('--animation-duration', `${animationDuration}ms`);\n button.prepend(ripple);\n cleanupAnimationOnFinish(ripple, animationDuration);\n}\n\nasync function cleanupAnimationOnFinish(\n ripple: HTMLSpanElement,\n animationDuration: number\n) {\n listenOnce(ripple, 'animationend', () => {\n ripple && ripple.remove();\n });\n // Backup in case the button gets hidden or unmounted and the ripple hasn't been cleaned up.\n setTimeout(\n () => ripple?.remove(),\n animationDuration + animationDuration * 0.1\n );\n}\n"],"mappings":"oCAUA,MAAMA,EAAS,SAEf,SAASC,EAAmCC,GAE1C,OAAOC,KAAKC,KAAKF,GAAgB,MACnC,CAEA,SAASG,EAA4BC,GACnC,GAAIC,iBAAiBD,GAASE,WAAa,SAAU,CACnDF,EAAQG,UAAUC,IAAI,kB,CAE1B,C,SAEgBC,EAAaC,EAAmBC,G,MAC9C,MAAMC,GAASC,EAAAF,EAAQG,UAAM,MAAAD,SAAA,EAAAA,EAAKH,EAAMK,cACxC,MAAMC,EAAiBJ,EAAOK,uBAAuBnB,GAAQ,GAC7DkB,GAAkBA,EAAeE,SAEjCN,EAAOL,UAAUC,IAAI,iBACrBL,EAA4BS,GAC5BO,MAAMC,KAAKR,EAAOS,UAAUC,QAAQnB,GAEpC,MAAMoB,EAASC,SAASC,cAAc,QACtCF,EAAOhB,UAAUC,IAAIV,GACrByB,EAAOG,MAAMC,gBAAkB,gBAAgBhB,EAAQiB,SACvDL,EAAOM,aAAa,OAAQ/B,GAE5B,MAAMgC,EAAW7B,KAAK8B,IAAInB,EAAOoB,YAAapB,EAAOqB,cACrD,MAAMC,EAASJ,EAAW,EAC1B,MAAMK,EAAoBpC,EAAmCmC,GAC7D,MAAME,IAACA,EAAGC,KAAEA,GAAQzB,EAAO0B,wBAC3Bf,EAAOG,MAAMa,MAAQhB,EAAOG,MAAMc,OAAS,GAAGV,MAC9CP,EAAOG,MAAMW,KAAO,GAAG3B,EAAM+B,SAAWJ,EAAOH,OAC/CX,EAAOG,MAAMU,IAAM,GAAG1B,EAAMgC,SAAWN,EAAMF,OAC7CX,EAAOG,MAAMiB,YAAY,uBAAwB,GAAGR,OACpDvB,EAAOgC,QAAQrB,GACfsB,EAAyBtB,EAAQY,EACnC,CAEAW,eAAeD,EACbtB,EACAY,GAEAY,EAAWxB,EAAQ,gBAAgB,KACjCA,GAAUA,EAAOL,QAAQ,IAG3B8B,YACE,IAAMzB,IAAM,MAANA,SAAM,SAANA,EAAQL,UACdiB,EAAoBA,EAAoB,GAE5C,Q"}