{"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"}