{"version":3,"file":"installment-payment-message-element-section.min.js","mappings":"wZAQA,MAAMA,kCAAkCC,YACtC,6BAAkBC,GAChB,MAAO,CAAC,uBACV,CAwCO,iBAAAC,GACLC,KAAKC,uBAEmBD,KAAKE,WAAWC,cAAc,UACtCC,iBAAiB,QAASC,GAE1CL,KAAKM,QACP,CAEO,oBAAAC,GACL,MAAMC,EAAkBR,KAAKE,WAAWC,cAAc,UACvC,MAAfK,GAAAA,EAAiBC,oBAAoB,QAASJ,EAChD,CAEO,wBAAAK,CAAyBC,EAAeC,EAAkBC,GAC/Db,KAAKC,uBAEDD,KAAKc,aAAeF,IAAaC,GACnCb,KAAKM,QAET,CAEQ,oBAAAL,GACDD,KAAKE,aACRF,KAAKe,aAAa,CAAEC,KAAM,SAC1BhB,KAAKE,WAAWe,UAAY,kkCAEhC,CAEQ,MAAAX,GACFY,SAASlB,KAAKmB,QAAQC,eAAgB,IAAMF,SAASlB,KAAKmB,QAAQE,UAAW,IAC/ErB,KAAKsB,aAAa,oBAAqB,SAIzCtB,KAAKsB,aAAa,oBAAqB,SACvCtB,KAAKuB,qBACLvB,KAAKwB,aACLxB,KAAKyB,iBACP,CAEQ,kBAAAF,GACN,MAAMH,EAAiBF,SAASlB,KAAKmB,QAAQC,eAAgB,IAEvDM,EAAe1B,KAAKE,WAAWC,cAA4B,UAC7DuB,GACFA,EAAaP,QAAQQ,aAAe3B,KAAKmB,QAAQQ,aACjDD,EAAaP,QAAQS,eAAiB5B,KAAKmB,QAAQS,eAE/CC,OAAOC,UAAUV,GACnBM,EAAaP,QAAQY,UAAYX,EAAiB,GAAGY,WAErDN,EAAaO,gBAAgB,kBAG/BC,QAAQC,IAAI,yCAEhB,CAEQ,UAAAX,GAGN,GAAIxB,KAAKmB,QAAQiB,cAAe,CAC9B,MAAMC,EAAcrC,KAAKE,WAAWoC,iBAAmC,gBACvE,IAAK,MAAMC,KAAQF,EACjBE,EAAKC,IAAMxC,KAAKmB,QAAQiB,aAE5B,CAEA,GAAIpC,KAAKmB,QAAQsB,gBAAiB,CAChC,MAAMC,EAAgB1C,KAAKE,WAAWoC,iBAAmC,kBACzE,IAAK,MAAMC,KAAQG,EACjBH,EAAKC,IAAMxC,KAAKmB,QAAQsB,eAE5B,CACF,CAEQ,cAAAhB,GACN,MAAMkB,EAAsB3C,KAAKE,WAAWC,cAA2B,iBACvE,IAAKwC,EAEH,OAIF,MAAMvB,EAAiBF,SAASlB,KAAKmB,QAAQC,eAAgB,IACvDC,EAAYH,SAASlB,KAAKmB,QAAQE,UAAW,IAC7CuB,EAAaf,OAAOC,UAAUV,IAAmBA,EAAiBC,EAGtEsB,EAAoBE,QADlBD,CAKN,EAGF,SAASvC,EAAuByC,GAC9B,KAAMA,EAAMC,yBAAyBlD,aACnC,OAGF,MAAMmD,EAAa,IAAIC,MAAM,6BAA8B,CACzDC,SAAS,EACTC,UAAU,IAEZL,EAAMC,cAAcK,cAAcJ,GAOlCI,cAAc,IAAIH,MAAM,4BAGVI,SAASlD,cAA4B,8BAC7CgB,QAAQmC,KAAO,MACvB,CAQKC,eAAeC,IAAI,gCACtBD,eAAeE,OAAO,8BAA+B7D","sources":["webpack://lange/./sections/installment-payment-message/installment-payment-message/index.ts"],"sourcesContent":["import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Conditionally renders an installment payment message that lets the customer know they can pay for\n * their order using a supported installment payment vendor.\n */\nclass InstallmentPaymentMessage extends HTMLElement implements CustomElement {\n  public static get observedAttributes() {\n    return ['data-estimated-total'];\n  }\n\n  declare readonly dataset: {\n    /**\n     * The currency code, e.g. \"CAD\"\n     */\n    currencyCode: string;\n\n    /**\n     * The currency symbol, e.g. \"$\"\n     */\n    currencySymbol: string;\n\n    /**\n     * Estimated total price in cents\n     */\n    estimatedTotal: string;\n\n    /**\n     * Whether or not the message should be hidden. This updates automatically based on the\n     * estimated total meeting the threshold for installment payment eligibility.\n     */\n    hideMessage: 'false' | 'true';\n\n    /**\n     * Url for the installment payment afterpay logo asset\n     */\n    logoUrlAfterpay: string;\n\n    /**\n     * Url for the installment payment Klarna logo asset\n     */\n    logoUrlKlarna: string;\n\n    /**\n     * The threshold from which installment payment is possible\n     */\n    threshold: string;\n  };\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    const learnMoreButton = this.shadowRoot.querySelector('button');\n    learnMoreButton.addEventListener('click', onLearnMoreButtonClick);\n\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const learnMoreButton = this.shadowRoot.querySelector('button');\n    learnMoreButton?.removeEventListener('click', onLearnMoreButtonClick);\n  }\n\n  public attributeChangedCallback(_name: string, oldValue: string, newValue: string) {\n    this.initializeShadowRoot();\n\n    if (this.isConnected && oldValue !== newValue) {\n      this.render();\n    }\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: 'open' });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private render() {\n    if (parseInt(this.dataset.estimatedTotal, 10) < parseInt(this.dataset.threshold, 10)) {\n      this.setAttribute('data-hide-message', 'true');\n      return;\n    }\n\n    this.setAttribute('data-hide-message', 'false');\n    this.renderInstallments();\n    this.renderLogo();\n    this.renderMessages();\n  }\n\n  private renderInstallments() {\n    const estimatedTotal = parseInt(this.dataset.estimatedTotal, 10);\n    type PriceElement = HTMLElementTagNameMap['price-element'];\n    const totalElement = this.shadowRoot.querySelector<PriceElement>('#total');\n    if (totalElement) {\n      totalElement.dataset.currencyCode = this.dataset.currencyCode;\n      totalElement.dataset.currencySymbol = this.dataset.currencySymbol;\n\n      if (Number.isInteger(estimatedTotal)) {\n        totalElement.dataset.subunits = (estimatedTotal / 4).toString();\n      } else {\n        totalElement.removeAttribute('data-subunits');\n      }\n    } else {\n      console.log('could not find total element to update');\n    }\n  }\n\n  private renderLogo() {\n    // A script that creates this element can connect it before it copies the logo urls on, and an\n    // unset url would otherwise go out as a request for the path \"undefined\".\n    if (this.dataset.logoUrlKlarna) {\n      const klarnaLogos = this.shadowRoot.querySelectorAll<HTMLImageElement>('.logo-klarna');\n      for (const logo of klarnaLogos) {\n        logo.src = this.dataset.logoUrlKlarna;\n      }\n    }\n\n    if (this.dataset.logoUrlAfterpay) {\n      const afterpayLogos = this.shadowRoot.querySelectorAll<HTMLImageElement>('.logo-afterpay');\n      for (const logo of afterpayLogos) {\n        logo.src = this.dataset.logoUrlAfterpay;\n      }\n    }\n  }\n\n  private renderMessages() {\n    const installmentsElement = this.shadowRoot.querySelector<HTMLElement>('#installments');\n    if (!installmentsElement) {\n      // DOM structure is not as expected, short circuiting\n      return;\n    }\n\n    // render installments and minimum requirements messages\n    const estimatedTotal = parseInt(this.dataset.estimatedTotal, 10);\n    const threshold = parseInt(this.dataset.threshold, 10);\n    const isEligible = Number.isInteger(estimatedTotal) && estimatedTotal > threshold;\n\n    if (isEligible) {\n      installmentsElement.hidden = false;\n    } else {\n      installmentsElement.hidden = true;\n    }\n  }\n}\n\nfunction onLearnMoreButtonClick(event: MouseEvent) {\n  if (!(event.currentTarget instanceof HTMLElement)) {\n    return;\n  }\n\n  const focusEvent = new Event('focus-stack-push-requested', {\n    bubbles: true,\n    composed: true\n  });\n  event.currentTarget.dispatchEvent(focusEvent);\n\n  // We show up inside several modals, not just the cart drawer, and this button opens a modal of\n  // its own. Leaving two modals open at once breaks the page, because the first one to close takes\n  // the backdrop, the scroll lock and the inert flags away from the one still showing. So we ask\n  // everything that is open to close before we open ours. We send this every time instead of first\n  // working out whether a modal is around us, since a dismiss with nothing open does nothing.\n  dispatchEvent(new Event('modal-dismiss-requested'));\n\n  type ModalElement = HTMLElementTagNameMap['modal-element'];\n  const modal = document.querySelector<ModalElement>('#installment-payment-modal');\n  modal.dataset.open = 'true';\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'installment-payment-message': InstallmentPaymentMessage;\n  }\n}\n\nif (!customElements.get('installment-payment-message')) {\n  customElements.define('installment-payment-message', InstallmentPaymentMessage);\n}\n"],"names":["InstallmentPaymentMessage","HTMLElement","observedAttributes","connectedCallback","this","initializeShadowRoot","shadowRoot","querySelector","addEventListener","onLearnMoreButtonClick","render","disconnectedCallback","learnMoreButton","removeEventListener","attributeChangedCallback","_name","oldValue","newValue","isConnected","attachShadow","mode","innerHTML","parseInt","dataset","estimatedTotal","threshold","setAttribute","renderInstallments","renderLogo","renderMessages","totalElement","currencyCode","currencySymbol","Number","isInteger","subunits","toString","removeAttribute","console","log","logoUrlKlarna","klarnaLogos","querySelectorAll","logo","src","logoUrlAfterpay","afterpayLogos","installmentsElement","isEligible","hidden","event","currentTarget","focusEvent","Event","bubbles","composed","dispatchEvent","document","open","customElements","get","define"],"sourceRoot":""}