{"version":3,"file":"product-price-element-section.min.js","mappings":"wZAQA,MAAMA,qBAAqBC,YACzB,6BAAkBC,GAChB,MAAO,CACL,cAEJ,CA8BQC,mCAAqCC,KAAKC,8BAA8BC,KAAKF,MAC7EG,kCAAoCH,KAAKI,6BAA6BF,KAAKF,MAC3EK,aAAeL,KAAKM,QAAQJ,KAAKF,MAGlC,iBAAAO,GACLP,KAAKQ,uBAELC,iBAAiB,iCAAkCT,KAAKD,oCAExDC,KAAKU,aCKF,SAAeC,EACpBC,GACA,QAD2B,IAA3BA,IAAAA,EAA8B,oBACF,aAAxBC,SAASC,YAAuC,qBAATF,GACjB,gBAAxBC,SAASC,WAA+B,CACxC,MAAMC,EAAQC,WAAWL,EAAU,GAEnC,MAD8B,IAAMM,aAAaF,EAEnD,CAGE,OAFAN,iBAAiBG,EAAMD,GACO,IAAMO,oBAAoBN,EAAMD,EAGlE,CDjBwBQ,CAAMnB,KAAKK,aACjC,CAEO,oBAAAe,GACDpB,KAAKU,cACPV,KAAKU,eAGPQ,oBAAoB,iCAAkClB,KAAKD,oCAE3D,MAAMsB,EAASrB,KAAKsB,WAAWC,cAAc,UACvC,MAANF,GAAAA,EAAQH,oBAAoB,QAASlB,KAAKG,mCAC1C,MAAMqB,EAAmBxB,KAAKsB,WAAWC,cAA2B,qBACpD,MAAhBC,GAAAA,EAAkBN,oBAAoB,QAASlB,KAAKG,kCACtD,CAEO,wBAAAsB,CAAyBC,EAAcC,EAAkBC,GAC9D5B,KAAKQ,uBAEDR,KAAK6B,aAAeF,IAAaC,GAAqB,gBAATF,GAC/C1B,KAAK8B,QAET,CAEQ,oBAAAtB,GACDR,KAAKsB,aACRtB,KAAK+B,aAAa,CAAEC,KAAM,SAC1BhC,KAAKsB,WAAWW,UAAY,i9DAEhC,CAEQ,OAAA3B,GACN,IAAKN,KAAK6B,YACR,OAGa7B,KAAKsB,WAAWC,cAAc,UACtCd,iBAAiB,QAAST,KAAKG,mCAEbH,KAAKsB,WAAWC,cAA2B,qBACnDd,iBAAiB,QAAST,KAAKG,mCAEhDH,KAAK8B,QACP,CAEQ,4BAAA1B,CAA6B8B,GACnC,KAAMA,EAAMC,yBAAyBtC,aACnC,OAGF,MAAMuC,EAAiBpC,KAAKuB,cAAc,mBACpCc,EAAiBrC,KAAKuB,cAC1B,4BAA0C,MAAda,OAAc,EAAdA,EAAgBE,QAAQC,uBAEhDC,EAAa,IAAIC,MAAM,6BAA8B,CACzDC,SAAS,EACTC,UAAU,IAEZT,EAAMC,cAAcS,cAAcJ,GAGlC,MAAMK,EAAiB,IAAIC,YAAoB,mCAAoC,CACjFJ,SAAS,EACTC,UAAU,EACVI,OAAQ,CAAEC,QAASX,EAAeC,QAAQW,8BAE5CjD,KAAK4C,cAAcC,EACrB,CAEQ,6BAAA5C,CAA8BiC,GAKpC,MAAMgB,EAAYlD,KAAKuB,cAAc,mBACjCvB,KAAK6B,aAAeqB,GAAaA,EAAUZ,QAAQa,KAAOjB,EAAMa,OAAOI,GAAGC,aAC5EF,EAAUZ,QAAQC,kBAAoBL,EAAMa,OAAOM,oBAAoBD,WACvEpD,KAAK8B,SAET,CAQQ,MAAAA,GAEN,MAAMM,EAAiBpC,KAAKuB,cAAc,mBAC1C,IAAKa,EACH,OAGF,MAAMkB,EAAkBlB,EAAemB,iBAAiB,mBACpB,wBAAhCnB,EAAeE,QAAQ1B,MAEhB0C,EAAgBE,OAAS,EADlCxD,KAAKyD,4BAILzD,KAAK0D,sBAIP,MAAMC,EAAU3D,KAAKsB,WAAWC,cAA2B,UACvDoC,IAC6B,SAA3B3D,KAAKsC,QAAQsB,UACfD,EAAQrB,QAAQuB,KAAO,OAEvBF,EAAQrB,QAAQuB,KAAO,QAG7B,CAEQ,mBAAAH,GACN,MAAMlC,EAAmBxB,KAAKsB,WAAWC,cAA2B,qBAEpE,IACEC,EAAiBc,QAAQwB,SAAW,QACpCtC,EAAiBc,QAAQyB,aAAe/D,KAAKsC,QAAQyB,aACrDvC,EAAiBc,QAAQ0B,eAAiBhE,KAAKsC,QAAQ0B,cACzD,CAAE,MAAOC,GACPC,QAAQD,MAAMA,EAChB,CAEA,MAAME,EAAYnE,KAAKuB,cAAc,mBACjCC,IACE2C,GAAaA,EAAU7B,QAAQ8B,gBACjC5C,EAAiBc,QAAQuB,KAAO,QAChCrC,EAAiBc,QAAQ+B,gBAAkB,iBAC3C7C,EAAiBc,QAAQgC,SAAWH,EAAU7B,QAAQ8B,iBAEtD5C,EAAiBc,QAAQuB,KAAO,OAChCrC,EAAiBc,QAAQ+B,gBAAkB,KAI/C,MAAMhD,EAASrB,KAAKsB,WAAWC,cAAc,UAChC,MAAT4C,GAAAA,EAAW7B,QAAQW,4BACrB5B,EAAOkD,OAAQ,EACf/C,EAAiB+C,OAAQ,IAEzBlD,EAAOkD,OAAQ,EACf/C,EAAiB+C,OAAQ,GAG3B,MAAMC,EAAaxE,KAAKsB,WAAWC,cAA2B,sBAC9D,GAAa,MAAT4C,GAAAA,EAAW7B,QAAQ8B,gBAAsD,SAApCpE,KAAKsC,QAAQmC,mBAA+B,CACnFD,EAAWE,QAAS,EACpB,MAAMC,EAAQC,SAAST,EAAU7B,QAAQqC,MAAO,IAC1CP,EAAiBQ,SAAST,EAAU7B,QAAQ8B,eAAgB,IAC5DK,EAAqBI,KAAKC,OAAQV,EAAiBO,GAASP,EAAkB,KACpFI,EAAWO,YAAc,GAAGN,QAC9B,MACED,EAAWE,QAAS,EAGtB,MAAMf,EAAU3D,KAAKsB,WAAWC,cAA2B,UACvDoC,IACFA,EAAQrB,QAAQyB,aAAe/D,KAAKsC,QAAQyB,aAC5CJ,EAAQrB,QAAQ0B,eAAiBhE,KAAKsC,QAAQ0B,gBAGhD,MAAMW,EAAQC,SAAkB,MAATT,OAAS,EAATA,EAAW7B,QAAQqC,MAAO,IAE7ChB,GAAWqB,OAAOC,UAAUN,KAC9BhB,EAAQrB,QAAQgC,SAAWK,EAAMvB,WAC7Be,GAAaA,EAAU7B,QAAQ8B,eACjCT,EAAQrB,QAAQ+B,gBAAkB,cAElCV,EAAQrB,QAAQ+B,gBAAkB,SAGxC,CAEQ,yBAAAZ,GACN,MAAMjC,EAAmBxB,KAAKsB,WAAWC,cAA2B,qBACpE,IAAKC,EAEH,OAGFA,EAAiBc,QAAQwB,SAAW,QACpCtC,EAAiBc,QAAQyB,aAAe/D,KAAKsC,QAAQyB,aACrDvC,EAAiBc,QAAQ0B,eAAiBhE,KAAKsC,QAAQ0B,eAEvD,MAAMd,EAAYlD,KAAKuB,cAAc,mBACrC,IAAK2B,EACH,OAGF,IAAIgC,EAAoBlF,KAAKuB,cAC3B,8CAA8C2B,EAAUZ,QAAQC,uBAU1C,IAAA4C,EAAnBD,IACHA,EAAoBlF,KAAKuB,cAAc,qCACvC2B,EAAUZ,QAAQC,kBAAqC,OAApB4C,EAAGD,QAAiB,EAAjBC,EAAmB7C,QAAQa,IAGnE,IAAK+B,EAEH,YADAhB,QAAQkB,KAAK,8BAIXF,EAAkB5C,QAAQ8B,gBAC5B5C,EAAiBc,QAAQuB,KAAO,QAChCrC,EAAiBc,QAAQ+B,gBAAkB,mBAE3C7C,EAAiBc,QAAQuB,KAAO,OAChCrC,EAAiBc,QAAQ+B,gBAAkB,IAG7C,MAAMhD,EAASrB,KAAKsB,WAAWC,cAAc,UACzC2D,EAAkB5C,QAAQW,4BACiB,KAA7CiC,EAAkB5C,QAAQ8B,gBAC1B/C,EAAOkD,OAAQ,EACf/C,EAAiB+C,OAAQ,IAEzBlD,EAAOkD,OAAQ,EACf/C,EAAiB+C,OAAQ,GAG3B/C,EAAiBc,QAAQgC,SAAWY,EAAkB5C,QAAQ8B,eAE9D,MAAMT,EAAU3D,KAAKsB,WAAWC,cAA2B,UAC3DoC,EAAQrB,QAAQyB,aAAe/D,KAAKsC,QAAQyB,aAC5CJ,EAAQrB,QAAQ0B,eAAiBhE,KAAKsC,QAAQ0B,eAC9CL,EAAQrB,QAAQgC,SAAWY,EAAkB5C,QAAQqC,MAEjDO,EAAkB5C,QAAQ8B,eAC5BT,EAAQrB,QAAQ+B,gBAAkB,cAElCV,EAAQrB,QAAQ+B,gBAAkB,SAGpC,MAAMG,EAAaxE,KAAKsB,WAAWC,cAA2B,sBAC9D,GAAI2D,EAAkB5C,QAAQ8B,gBAAsD,SAApCpE,KAAKsC,QAAQmC,mBAA+B,CAC1FD,EAAWE,QAAS,EACpB,MAAMC,EAAQC,SAASM,EAAkB5C,QAAQqC,MAAO,IAClDP,EAAiBQ,SAASM,EAAkB5C,QAAQ8B,eAAgB,IACpEK,EAAqBI,KAAKC,OAAQV,EAAiBO,GAASP,EAAkB,KACpFI,EAAWO,YAAc,GAAGN,QAC9B,MACED,EAAWE,QAAS,CAExB,EASGW,eAAeC,IAAI,kBACtBD,eAAeE,OAAO,gBAAiB3F","sources":["webpack://lange/./sections/product-price-element/product-price/index.ts","webpack://lange/./lib/dom-ready.ts"],"sourcesContent":["import type { CustomElement } from '@integrabeauty/custom-elements';\nimport { ready, type ReleaseHandle } from '../../../lib/dom-ready.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Renders a product price. This relies on a `<product-element>` in a slot for data.\n */\nclass ProductPrice extends HTMLElement implements CustomElement {\n  public static get observedAttributes() {\n    return [\n      'data-update'\n    ];\n  }\n\n  declare readonly dataset: {\n    /**\n     * Currency code\n     */\n    currencyCode: string;\n\n    /**\n     * Currency Symbol (e.g., $)\n     */\n    currencySymbol: string;\n\n    /**\n     * Boolean as a string indicating whether to show the discounted percentage if a product has a\n     * compare at price in addition to a sale price.\n     */\n    discountPercentage: 'false' | 'true';\n\n    /**\n     * Hides price if set to \"true\"\n     */\n    hidePrice: string;\n\n    /**\n     * Mutate this attribute's value to trigger rendering.\n     */\n    update: string;\n  };\n\n  private onProductVariantOptionChangedBound = this.onProductVariantOptionChanged.bind(this);\n  private onCompareAtPriceModalClickedBound = this.onCompareAtPriceModalClicked.bind(this);\n  private onReadyBound = this.onReady.bind(this);\n  private declare releaseReady: ReleaseHandle;\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    addEventListener('product-variant-option-changed', this.onProductVariantOptionChangedBound);\n\n    this.releaseReady = ready(this.onReadyBound);\n  }\n\n  public disconnectedCallback() {\n    if (this.releaseReady) {\n      this.releaseReady();\n    }\n\n    removeEventListener('product-variant-option-changed', this.onProductVariantOptionChangedBound);\n\n    const button = this.shadowRoot.querySelector('button');\n    button?.removeEventListener('click', this.onCompareAtPriceModalClickedBound);\n    const compareAtPriceEl = this.shadowRoot.querySelector<HTMLElement>('#compare-at-price');\n    compareAtPriceEl?.removeEventListener('click', this.onCompareAtPriceModalClickedBound);\n  }\n\n  public attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n    this.initializeShadowRoot();\n\n    if (this.isConnected && oldValue !== newValue && name === 'data-update') {\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 onReady() {\n    if (!this.isConnected) {\n      return;\n    }\n\n    const button = this.shadowRoot.querySelector('button');\n    button.addEventListener('click', this.onCompareAtPriceModalClickedBound);\n\n    const compareAtPriceEl = this.shadowRoot.querySelector<HTMLElement>('#compare-at-price');\n    compareAtPriceEl.addEventListener('click', this.onCompareAtPriceModalClickedBound);\n\n    this.render();\n  }\n\n  private onCompareAtPriceModalClicked(event: MouseEvent) {\n    if (!(event.currentTarget instanceof HTMLElement)) {\n      return;\n    }\n\n    const productElement = this.querySelector('product-element');\n    const variantElement = this.querySelector<HTMLElementTagNameMap['variant-element']>(\n      `variant-element[data-id=\"${productElement?.dataset.selectedVariantId}\"]`);\n\n    const focusEvent = new Event('focus-stack-push-requested', {\n      bubbles: true,\n      composed: true\n    });\n    event.currentTarget.dispatchEvent(focusEvent);\n\n    type Detail = WindowEventMap['compare-at-price-modal-requested']['detail'];\n    const modalShowEvent = new CustomEvent<Detail>('compare-at-price-modal-requested', {\n      bubbles: true,\n      composed: true,\n      detail: { content: variantElement.dataset.compareAtPriceModalContent }\n    });\n    this.dispatchEvent(modalShowEvent);\n  }\n\n  private onProductVariantOptionChanged(event: WindowEventMap['product-variant-option-changed']) {\n    // This event may be fired by an element attached to a different product. Our component's slot\n    // may not even be fully parsed at the time of receiving this event if it was targeted at a\n    // different component/product.\n\n    const productEl = this.querySelector('product-element');\n    if (this.isConnected && productEl && productEl.dataset.id === event.detail.id.toString()) {\n      productEl.dataset.selectedVariantId = event.detail.selected_variant_id.toString();\n      this.render();\n    }\n  }\n\n  /**\n   * Updates the DOM based on the element's state. How this element renders is based on the type of\n   * the associated product.\n   *\n   * Configurable bundles are handled the same way as configurable products.\n   */\n  private render() {\n    // productEl is inside of a slot, so may not always be available\n    const productElement = this.querySelector('product-element');\n    if (!productElement) {\n      return;\n    }\n\n    const variantElements = productElement.querySelectorAll('variant-element');\n    if (productElement.dataset.type === 'configurable-bundle') {\n      this.renderConfigurableProduct();\n    } else if (variantElements.length > 1) {\n      this.renderConfigurableProduct();\n    } else {\n      this.renderSimpleProduct();\n    }\n\n    // Hide <price-element> if value is \"true\"\n    const priceEl = this.shadowRoot.querySelector<HTMLElement>('#price');\n    if (priceEl) {\n      if (this.dataset.hidePrice === 'true') {\n        priceEl.dataset.hide = 'true';\n      } else {\n        priceEl.dataset.hide = 'false';\n      }\n    }\n  }\n\n  private renderSimpleProduct() {\n    const compareAtPriceEl = this.shadowRoot.querySelector<HTMLElement>('#compare-at-price');\n\n    try {\n      compareAtPriceEl.dataset.showCode = 'false';\n      compareAtPriceEl.dataset.currencyCode = this.dataset.currencyCode;\n      compareAtPriceEl.dataset.currencySymbol = this.dataset.currencySymbol;\n    } catch (error) {\n      console.error(error);\n    }\n\n    const variantEl = this.querySelector('variant-element');\n    if (compareAtPriceEl) {\n      if (variantEl && variantEl.dataset.compareAtPrice) {\n        compareAtPriceEl.dataset.hide = 'false';\n        compareAtPriceEl.dataset.ariaLabelPrefix = 'Regular price:';\n        compareAtPriceEl.dataset.subunits = variantEl.dataset.compareAtPrice;\n      } else {\n        compareAtPriceEl.dataset.hide = 'true';\n        compareAtPriceEl.dataset.ariaLabelPrefix = '';\n      }\n    }\n\n    const button = this.shadowRoot.querySelector('button');\n    if (variantEl?.dataset.compareAtPriceModalContent) {\n      button.inert = false;\n      compareAtPriceEl.inert = false;\n    } else {\n      button.inert = true;\n      compareAtPriceEl.inert = true;\n    }\n\n    const discountEl = this.shadowRoot.querySelector<HTMLElement>('span.discount-copy');\n    if (variantEl?.dataset.compareAtPrice && this.dataset.discountPercentage === 'true') {\n      discountEl.hidden = false;\n      const price = parseInt(variantEl.dataset.price, 10);\n      const compareAtPrice = parseInt(variantEl.dataset.compareAtPrice, 10);\n      const discountPercentage = Math.round(((compareAtPrice - price) / compareAtPrice) * 100);\n      discountEl.textContent = `${discountPercentage}% OFF`;\n    } else {\n      discountEl.hidden = true;\n    }\n\n    const priceEl = this.shadowRoot.querySelector<HTMLElement>('#price');\n    if (priceEl) {\n      priceEl.dataset.currencyCode = this.dataset.currencyCode;\n      priceEl.dataset.currencySymbol = this.dataset.currencySymbol;\n    }\n\n    const price = parseInt(variantEl?.dataset.price, 10);\n\n    if (priceEl && Number.isInteger(price)) {\n      priceEl.dataset.subunits = price.toString();\n      if (variantEl && variantEl.dataset.compareAtPrice) {\n        priceEl.dataset.ariaLabelPrefix = 'Sale price:';\n      } else {\n        priceEl.dataset.ariaLabelPrefix = 'Price:';\n      }\n    }\n  }\n\n  private renderConfigurableProduct() {\n    const compareAtPriceEl = this.shadowRoot.querySelector<HTMLElement>('#compare-at-price');\n    if (!compareAtPriceEl) {\n      // DOM is not loaded\n      return;\n    }\n\n    compareAtPriceEl.dataset.showCode = 'false';\n    compareAtPriceEl.dataset.currencyCode = this.dataset.currencyCode;\n    compareAtPriceEl.dataset.currencySymbol = this.dataset.currencySymbol;\n\n    const productEl = this.querySelector('product-element');\n    if (!productEl) {\n      return;\n    }\n\n    let selectedVariantEl = this.querySelector<HTMLElementTagNameMap['variant-element']>(\n      `product-element > variant-element[data-id=\"${productEl.dataset.selectedVariantId}\"]`);\n\n    // This check is important. When someone visits a pdp with a variant parameter, and the variant\n    // parameter is invalid, then the selected variant id is not initialized correctly, and as a\n    // result, there is no way to figure out which variant is selected. This happens routinely when\n    // someone clicked on an invalid or out of date link. This happens routinely because marketing\n    // will advertise a page with an explicit variant, then later make catalog changes such as\n    // replacing the variants of a product, after which the ads are wrong. The ads point to the\n    // correct PDP, but the variant parameter is now wrong. In these cases we default to the first\n    // variant-element found as a child of the parent product-element.\n    if (!selectedVariantEl) {\n      selectedVariantEl = this.querySelector('product-element > variant-element');\n      productEl.dataset.selectedVariantId = selectedVariantEl?.dataset.id;\n    }\n\n    if (!selectedVariantEl) {\n      console.warn('selected variant not found');\n      return;\n    }\n\n    if (selectedVariantEl.dataset.compareAtPrice) {\n      compareAtPriceEl.dataset.hide = 'false';\n      compareAtPriceEl.dataset.ariaLabelPrefix = 'Regular price:';\n    } else {\n      compareAtPriceEl.dataset.hide = 'true';\n      compareAtPriceEl.dataset.ariaLabelPrefix = '';\n    }\n\n    const button = this.shadowRoot.querySelector('button');\n    if (selectedVariantEl.dataset.compareAtPriceModalContent &&\n      selectedVariantEl.dataset.compareAtPrice !== '') {\n      button.inert = false;\n      compareAtPriceEl.inert = false;\n    } else {\n      button.inert = true;\n      compareAtPriceEl.inert = true;\n    }\n\n    compareAtPriceEl.dataset.subunits = selectedVariantEl.dataset.compareAtPrice;\n\n    const priceEl = this.shadowRoot.querySelector<HTMLElement>('#price');\n    priceEl.dataset.currencyCode = this.dataset.currencyCode;\n    priceEl.dataset.currencySymbol = this.dataset.currencySymbol;\n    priceEl.dataset.subunits = selectedVariantEl.dataset.price;\n\n    if (selectedVariantEl.dataset.compareAtPrice) {\n      priceEl.dataset.ariaLabelPrefix = 'Sale price:';\n    } else {\n      priceEl.dataset.ariaLabelPrefix = 'Price:';\n    }\n\n    const discountEl = this.shadowRoot.querySelector<HTMLElement>('span.discount-copy');\n    if (selectedVariantEl.dataset.compareAtPrice && this.dataset.discountPercentage === 'true') {\n      discountEl.hidden = false;\n      const price = parseInt(selectedVariantEl.dataset.price, 10);\n      const compareAtPrice = parseInt(selectedVariantEl.dataset.compareAtPrice, 10);\n      const discountPercentage = Math.round(((compareAtPrice - price) / compareAtPrice) * 100);\n      discountEl.textContent = `${discountPercentage}% OFF`;\n    } else {\n      discountEl.hidden = true;\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-price': ProductPrice;\n  }\n}\n\nif (!customElements.get('product-price')) {\n  customElements.define('product-price', ProductPrice);\n}\n","/**\n * Releases the handle returned from the ready() function.\n *\n * This is idempotent. Additional calls are pointless but harmless.\n */\nexport type ReleaseHandle = () => void;\n\n/**\n * A subset of events that pertain to document ready state.\n */\ntype LoadingEventMap = Pick<DocumentEventMap, 'DOMContentLoaded' | 'load'>;\n\n/**\n * Calls the provided callback when the document is ready. This works both when the document is\n * already ready and when it is not, so callers do not have to care. This exists because it ensures\n * that each caller consistently expresses its dependency on document readiness, and to save a bit\n * of boilerplate.\n *\n * A document is considered ready when it has been parsed. This corresponds to the ready state of\n * 'interactive'. When the document has been fully loaded, the ready state is 'complete'. The\n * callback runs either way, so callers do not have to check which one they are in.\n *\n * Ready means the html is parsed and the DOM is there to query. It does not mean the page's other\n * scripts have run. Deferred scripts and module scripts run after the ready state turns\n * 'interactive' and before DOMContentLoaded fires, so a callback here can run before them. When a\n * caller needs some other script to have run already, this is the wrong tool, and it should wait on\n * whatever that script produces instead.\n *\n * That remedy has a catch of its own when the calling bundle is loaded with async. An async bundle\n * can execute after DOMContentLoaded has already fired, so a plain listener for that event never\n * runs and the work silently never happens. Nothing here can detect that, because by the time this\n * file executes the event is long gone. Catching it needs something registered at parse time,\n * before any bundle loads.\n *\n * There is a second trap right next to that one, and it applies only when waiting for\n * DOMContentLoaded. The ready state stays 'interactive' after DOMContentLoaded has fired, all the\n * way until 'complete', so the ready state cannot tell you whether DOMContentLoaded is still coming\n * or has already gone. Waiting for load is not exposed to this, because the ready state turns\n * 'complete' and load fires in the same task, so seeing 'complete' means load has fired too.\n *\n * When the document is already ready, the callback is invoked via setTimeout. This way, if the\n * callback throws, the error surfaces to the global error handler in a way that is similar to what\n * happens when an event listener throws.\n *\n * We might one day want to move this to an NPM library.\n *\n * Beware of a quirk here. setTimeout yields, and the busier the frontend, the longer it takes to\n * fire. Page load is exactly when the frontend is busiest. The timeout is a floor and not a\n * guarantee, so there is no real bound on how long that yield lasts. What this means is that using\n * this library can introduce more delay than you might expect. Compare code that runs on async load\n * and checks ready state and invokes immediately to code that runs after setTimeout. The former\n * runs in the same tick, the latter runs in \"some later tick\". That later tick can be surprisingly\n * much later. That can cause initial paint issues.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event\n * @see https://html.spec.whatwg.org/multipage/parsing.html#the-end\n */\nexport function ready(callback: (event?: Event) => void,\n  type: keyof LoadingEventMap = 'DOMContentLoaded') {\n  if (document.readyState === 'complete' || (type === 'DOMContentLoaded' &&\n    document.readyState === 'interactive')) {\n    const timer = setTimeout(callback, 0);\n    const handle: ReleaseHandle = () => clearTimeout(timer);\n    return handle;\n  } else {\n    addEventListener(type, callback);\n    const handle: ReleaseHandle = () => removeEventListener(type, callback);\n    return handle;\n  }\n}\n"],"names":["ProductPrice","HTMLElement","observedAttributes","onProductVariantOptionChangedBound","this","onProductVariantOptionChanged","bind","onCompareAtPriceModalClickedBound","onCompareAtPriceModalClicked","onReadyBound","onReady","connectedCallback","initializeShadowRoot","addEventListener","releaseReady","callback","type","document","readyState","timer","setTimeout","clearTimeout","removeEventListener","ready","disconnectedCallback","button","shadowRoot","querySelector","compareAtPriceEl","attributeChangedCallback","name","oldValue","newValue","isConnected","render","attachShadow","mode","innerHTML","event","currentTarget","productElement","variantElement","dataset","selectedVariantId","focusEvent","Event","bubbles","composed","dispatchEvent","modalShowEvent","CustomEvent","detail","content","compareAtPriceModalContent","productEl","id","toString","selected_variant_id","variantElements","querySelectorAll","length","renderConfigurableProduct","renderSimpleProduct","priceEl","hidePrice","hide","showCode","currencyCode","currencySymbol","error","console","variantEl","compareAtPrice","ariaLabelPrefix","subunits","inert","discountEl","discountPercentage","hidden","price","parseInt","Math","round","textContent","Number","isInteger","selectedVariantEl","_selectedVariantEl","warn","customElements","get","define"],"sourceRoot":""}