{"version":3,"file":"product-card-element-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"yBAQA,MAAMA,0BAA0BC,YAQvB,iBAAAC,GACLC,KAAKC,uBACLD,KAAKE,QACP,CAEQ,oBAAAD,GACDD,KAAKG,aACRH,KAAKI,aAAa,CAAEC,KAAM,SAC1BL,KAAKG,WAAWG,UAAY,yqCAEhC,CAEQ,MAAAJ,GACN,GAAIF,KAAKO,QAAQC,IAAK,CACLR,KAAKG,WAAWM,cAAc,KACtCC,aAAa,OAAQV,KAAKO,QAAQC,IAC3C,CACF,EASGG,eAAeC,IAAI,wBACtBD,eAAeE,OAAO,sBAAuBhB,mBCnC/C,MAAMiB,oBAAoBhB,YAqChBiB,sBAAwBf,KAAKgB,iBAAiBC,KAAKjB,MAEpD,iBAAAD,GACLC,KAAKC,uBACLD,KAAKE,QACP,CAEO,oBAAAgB,GACLlB,KAAKmB,oBAAoB,kBAAmBnB,KAAKe,sBACnD,CAEQ,oBAAAd,GACDD,KAAKG,aACRH,KAAKI,aAAa,CAAEC,KAAM,SAC1BL,KAAKG,WAAWG,UAAY,2yFAEhC,CAEQ,MAAAJ,GAGN,GAFAF,KAAKoB,YAAYpB,KAAKO,QAAQC,KAE1BR,KAAKO,QAAQc,aAAc,CAC7B,MAAMC,EAAWtB,KAAKG,WAAWM,cAAc,qBAC/Ca,EAASf,QAAQgB,MAAQvB,KAAKO,QAAQc,aACtCC,EAASf,QAAQiB,MAAQxB,KAAKO,QAAQkB,mBAAqB,SAC7D,CAEAzB,KAAK0B,iBAAiB,kBAAmB1B,KAAKe,sBAChD,CAEQ,gBAAAC,CAAiBW,GAEvB,MAAMC,EAAa,GAAG5B,KAAKO,QAAQC,eAAemB,EAAME,OAAOC,QAAQC,KACvE/B,KAAKoB,YAAYQ,GAEjB,MAAMI,EAAgBhC,KAAKiC,iBAA8B,kBAGzD,IAAK,MAAMC,KAASF,EACdE,EAAM3B,QAAQ4B,YAAcR,EAAME,OAAOC,QAAQC,GAAGK,WACtDF,EAAMG,UAAUC,OAAO,UAEvBJ,EAAMG,UAAUE,IAAI,UAKxB,MAAMjB,EAAWtB,KAAKG,WAAWM,cAAc,qBAC/Ca,EAASf,QAAQgB,MAAQI,EAAME,OAAOC,QAAQR,SAC9CA,EAASf,QAAQiB,MAAQG,EAAME,OAAOC,QAAQU,cAE9C,MAAMC,EAAezC,KAAKS,cAAc,6BAClCiC,EAAgBD,EAAaE,aAAe,GAC5CC,EAAWjB,EAAME,OAAOC,QAAQe,MAAQ,IAC9C,IAAIC,EAAe,GAEjBA,EADEC,OAAOC,UAAUJ,GACJA,EAASR,WAETQ,EAASK,QAAQ,GAIlCR,EAAaE,YAAcD,EAAcQ,QAAQ,iBAAkBJ,GAKnE,MAAMK,EAAwBnD,KAAKS,cAAc,sBAKjD,GAJI0C,IACFA,EAAsBR,YAAchB,EAAME,OAAOC,QAAQsB,gBAAkB,IAG/C,SAA1BpD,KAAKO,QAAQ8C,UAEX1B,EAAME,OAAOC,QAAQwB,4BAA8BH,EAAuB,CAC5E,MAAMI,EAAqBC,SAASC,cAAc,yBAClDF,EAAmBhD,QAAQmD,QAAU/B,EAAME,OAAOC,QAAQwB,2BAC1DH,EAAsBQ,YAAYJ,EACpC,CAKF,MAAMK,EAAkB5D,KAAKS,cAAc,oBACvCmD,IACFA,EAAgBrD,QAAQsD,QAAUlC,EAAME,OAAOC,QAAQ8B,gBAE3D,CAKQ,WAAAxC,CAAYZ,GAElB,MAAMsD,EAAe9D,KAAKiC,iBAAoC,oBAC9D,IAAK,MAAM8B,KAAeD,EACxBC,EAAYrD,aAAa,OAAQF,GAIpBR,KAAKG,WAAWM,cAAc,KACtCC,aAAa,OAAQF,GAINR,KAAKS,cAAc,kBAC3BF,QAAQC,IAAMA,CAC9B,EASGG,eAAeC,IAAI,iBACtBD,eAAeE,OAAO,eAAgBC","sources":["webpack://lange/./scripts/sections/product-card-element/product-card-simple/index.ts","webpack://lange/./scripts/sections/product-card-element/product-card/index.ts"],"sourcesContent":["import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A simplified product card displaying image, title, subtitle, rating, and add to bag CTA. No\n * variant selector, price, or top badge. Used for the paired products.\n */\nclass ProductCardSimple extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Product URL used for the card link.\n     */\n    url: string;\n  };\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\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 (this.dataset.url) {\n      const anchor = this.shadowRoot.querySelector('a');\n      anchor.setAttribute('href', this.dataset.url);\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-card-simple': ProductCardSimple;\n  }\n}\n\nif (!customElements.get('product-card-simple')) {\n  customElements.define('product-card-simple', ProductCardSimple);\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A custom web component for displaying product card on PLP, predictable search, in product\n * carousels, etc.\n */\nclass ProductCard extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Initial value for the top badge.\n     *\n     * For products that don't have the variant selector and have a top badge, this value will be\n     * used. For products with variant selector, the top badge will be updated based on the selected\n     * variant by initial variant-changed event.\n     */\n    initTopBadge: string;\n\n    /**\n     * Initial style for the top badge.\n     */\n    initTopBadgeStyle: string;\n\n    /**\n     * Boolean represented as string, whether the product is an upsell product\n     */\n    isUpsell: 'false' | 'true';\n\n    /**\n     * Defines the size variant for the component\n     */\n    size: 'default' | 'small';\n\n    /**\n     * Defines the style variant for the component\n     */\n    styleVariant: 'upsell';\n\n    /**\n     * Product url without variant\n     */\n    url: string;\n  };\n\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\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    this.renderLinks(this.dataset.url);\n\n    if (this.dataset.initTopBadge) {\n      const topBadge = this.shadowRoot.querySelector('product-top-badge');\n      topBadge.dataset.value = this.dataset.initTopBadge;\n      topBadge.dataset.style = this.dataset.initTopBadgeStyle || 'default';\n    }\n\n    this.addEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    // After variant is changed, we need to update the products url to have the selected variant\n    const variantUrl = `${this.dataset.url}?variant=${event.detail.variant.id}`;\n    this.renderLinks(variantUrl);\n\n    const variantImages = this.querySelectorAll<HTMLElement>('.variant-image');\n\n    // update image\n    for (const image of variantImages) {\n      if (image.dataset.variantId === event.detail.variant.id.toString()) {\n        image.classList.remove('hidden');\n      } else {\n        image.classList.add('hidden');\n      }\n    }\n\n    // update top badge\n    const topBadge = this.shadowRoot.querySelector('product-top-badge');\n    topBadge.dataset.value = event.detail.variant.topBadge;\n    topBadge.dataset.style = event.detail.variant.topBadgeStyle;\n\n    const priceElement = this.querySelector('.product-card-final-price');\n    const previousPrice = priceElement.textContent || '';\n    const newPrice = event.detail.variant.price / 100;\n    let newPriceText = '';\n    if (Number.isInteger(newPrice)) {\n      newPriceText = newPrice.toString();\n    } else {\n      newPriceText = newPrice.toFixed(2);\n    }\n\n    // Regex to replace the price in the format of $XX.XX or $XX\n    priceElement.textContent = previousPrice.replace(/\\d+(?:\\.\\d+)?/g, newPriceText);\n\n    // Update compare at price. Compare at price is formatted string already, so we can just replace\n    // the number in the string with the new compare at price. Not every product has it, so we have\n    // to check if the element exists.\n    const compareAtPriceElement = this.querySelector('.price__compare-at');\n    if (compareAtPriceElement) {\n      compareAtPriceElement.textContent = event.detail.variant.compareAtPrice || '';\n    }\n\n    if (this.dataset.isUpsell !== 'true') {\n      // Create a compare at price info button if needed. We don't show it for upsell products\n      if (event.detail.variant.compareAtPriceModalContent && compareAtPriceElement) {\n        const compareAtPriceInfo = document.createElement('compare-at-price-info');\n        compareAtPriceInfo.dataset.content = event.detail.variant.compareAtPriceModalContent;\n        compareAtPriceElement.appendChild(compareAtPriceInfo);\n      }\n    }\n\n    // Update discount message. It's a big formatted box with a promo message. It doesn't exist for\n    // upsell products, so we need this check.\n    const discountMessage = this.querySelector('discount-message');\n    if (discountMessage) {\n      discountMessage.dataset.message = event.detail.variant.discountMessage;\n    }\n  }\n\n  /**\n   * Update the url for all the links in both shadow DOM and light DOM, including the clickable area\n   */\n  private renderLinks(url: string) {\n    // there's some links in the light DOM, updating them first\n    const productLinks = this.querySelectorAll<HTMLAnchorElement>('a[slot=\"action\"]');\n    for (const productLink of productLinks) {\n      productLink.setAttribute('href', url);\n    }\n\n    // updating the shadow DOM link url as well\n    const anchor = this.shadowRoot.querySelector('a');\n    anchor.setAttribute('href', url);\n\n    // clickable area is a custom element that provides a clickable area but not an anchor tag, url\n    // is passed through dataset attribute\n    const clickableArea = this.querySelector('clickable-area');\n    clickableArea.dataset.url = url;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-card': ProductCard;\n  }\n}\n\nif (!customElements.get('product-card')) {\n  customElements.define('product-card', ProductCard);\n}\n"],"names":["ProductCardSimple","HTMLElement","connectedCallback","this","initializeShadowRoot","render","shadowRoot","attachShadow","mode","innerHTML","dataset","url","querySelector","setAttribute","customElements","get","define","ProductCard","onVariantChangedBound","onVariantChanged","bind","disconnectedCallback","removeEventListener","renderLinks","initTopBadge","topBadge","value","style","initTopBadgeStyle","addEventListener","event","variantUrl","detail","variant","id","variantImages","querySelectorAll","image","variantId","toString","classList","remove","add","topBadgeStyle","priceElement","previousPrice","textContent","newPrice","price","newPriceText","Number","isInteger","toFixed","replace","compareAtPriceElement","compareAtPrice","isUpsell","compareAtPriceModalContent","compareAtPriceInfo","document","createElement","content","appendChild","discountMessage","message","productLinks","productLink"],"sourceRoot":""}