{"version":3,"file":"product-card-element-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"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","sources":["webpack://lange/./scripts/sections/product-card-element/product-card-simple/index.ts","webpack://lange/./scripts/sections/product-card-element/product-card-simple/index.scss","webpack://lange/./scripts/sections/product-card-element/product-card-simple/index.html","webpack://lange/./scripts/sections/product-card-element/product-card/index.ts","webpack://lange/./scripts/sections/product-card-element/product-card/index.scss","webpack://lange/./scripts/sections/product-card-element/product-card/index.html"],"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  readonly dataset!: {\n    /**\n     * Product URL used for the card link.\n     */\n    url: string;\n  };\n\n  public shadowRoot!: ShadowRoot;\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\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","export default \":host{background-color:#f5f5f5;display:flex;height:100%;max-width:520px;width:100%}a,slot{display:block}a{color:inherit;text-decoration:none}slot[name=image]{align-items:center;display:flex;justify-content:center;padding:10px;width:110px}@media only screen and (min-width:768px){slot[name=image]{width:140px}}.main{align-items:flex-start;display:flex;flex-direction:column;justify-content:space-between;padding:12px 24px 14px 14px}h3{font-size:.875rem;font-weight:600;letter-spacing:.07em;line-height:1;margin-bottom:4px;margin-top:0;text-transform:uppercase}@media only screen and (min-width:1280px){h3{font-size:1rem}}::slotted([slot=subtitle]){font-size:.625rem;letter-spacing:.07em;line-height:1.5;margin-bottom:8px!important;text-transform:uppercase}@media only screen and (min-width:1280px){::slotted([slot=subtitle]){font-size:.75rem}}slot[name=rating]{margin-bottom:auto}slot[name=action]{display:inline-block;margin-top:10px}::slotted([slot=action]){font-size:.75rem;min-height:40px}\";","// Module\nvar code = \"<slot name=\\\"image\\\"></slot><div class=\\\"main\\\"><a href=\\\"\\\"><h3><slot name=\\\"title\\\"></slot></h3><slot name=\\\"subtitle\\\"></slot></a><slot name=\\\"rating\\\"></slot><slot name=\\\"action\\\"></slot></div>\";\n// Exports\nexport default code;","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  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     * A concatenated string of all tags\n     */\n    upsellTags: string;\n\n    /**\n     * Product url without variant\n     */\n    url: string;\n  };\n\n  public shadowRoot!: ShadowRoot;\n\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\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    // The product card is also used for upsell products in the cart and upsell modal but the price\n    // is calculated differently, so we have to update a special upsell-price element accordingly.\n    if (this.dataset.isUpsell === 'true') {\n      type UpsellPrice = HTMLElementTagNameMap['upsell-price'];\n      const upsellPrice = this.querySelector<UpsellPrice>('upsell-price');\n      if (upsellPrice) {\n        upsellPrice.dataset.price = event.detail.variant.price.toString();\n      }\n    } else {\n      // update price\n      const priceElement = this.querySelector('.product-card-final-price');\n      const previousValue = priceElement.textContent || '';\n      priceElement.textContent =\n        previousValue.replace(/\\d+/g, (event.detail.variant.price / 100).toFixed(0));\n\n      // update compare at price\n      const compareAtPriceElement = this.querySelector('.price__compare-at');\n      compareAtPriceElement.textContent = event.detail.variant.compareAtPrice || '';\n\n      // create a compare at price info button if needed\n      if (event.detail.variant.compareAtPriceModalContent) {\n        const compareAtPriceInfo = document.createElement('compare-at-price-info');\n        compareAtPriceInfo.dataset.content = event.detail.variant.compareAtPriceModalContent;\n        compareAtPriceElement.appendChild(compareAtPriceInfo);\n      }\n\n      // update discount message\n      const discountMessage = this.querySelector('discount-message');\n      if (discountMessage) {\n        discountMessage.dataset.message = event.detail.variant.discountMessage;\n      }\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","export default \":host{display:flex;flex-direction:column;height:100%;position:relative;width:100%}:host([data-size=small]) .title{font-size:1rem}:host([data-size=small]) ::slotted([slot=subtitle]){font-size:.875rem}:host([data-size=small]) ::slotted([slot=discount-message]){font-size:.75rem;line-height:1.3;padding:6px 12px}:host([data-size=small]) ::slotted([slot=action]){font-size:.875rem!important;min-height:36px!important}:host([data-size=small]) ::slotted(.cta[slot=action]){height:36px!important}:host([data-is-upsell=true]){background-color:#fff;padding:0 10px 12px}:host([data-is-upsell=true]) .title{font-size:1rem;margin-top:8px}:host([data-is-upsell=true]) ::slotted([slot=subtitle]){font-size:.75rem}:host([data-is-upsell=true]) slot[name=price]{order:-2}:host([data-is-upsell=true]) ::slotted([slot=price]){margin-bottom:8px}:host([data-is-upsell=true]) slot[name=discount-message]{margin-bottom:8px;order:-1}:host([data-is-upsell=true]) ::slotted([slot=discount-message]){font-size:.75rem;line-height:1.3;padding:0;text-align:left}:host([data-is-upsell=true]) ::slotted([slot=action]){font-size:.875rem!important;min-height:36px!important}:host([data-is-upsell=true]) ::slotted(.cta[slot=action]){height:36px!important}slot{display:block}slot[name=image]{margin-left:auto;margin-right:auto}a{color:inherit;display:block;text-decoration:none}.title{font-size:1rem;font-weight:600;letter-spacing:.07em;line-height:1;margin-bottom:4px;text-transform:uppercase}@media only screen and (min-width:1280px){.title{font-size:1.375rem}}::slotted([slot=subtitle]){font-size:.75rem;letter-spacing:.07em;line-height:1.5;margin-bottom:8px!important;text-transform:uppercase}@media only screen and (min-width:1280px){::slotted([slot=subtitle]){font-size:.875rem}}::slotted([slot=rating]){display:block;margin-bottom:18px}product-top-badge{left:0;position:absolute;top:18px}@media only screen and (min-width:768px){product-top-badge{top:30px}}::slotted([slot=price]){margin-bottom:12px}footer{display:flex;flex-direction:column;flex-grow:1}::slotted([slot=discount-message]){font-size:.75rem;margin-bottom:14px;padding:8px 10px}@media only screen and (min-width:768px){::slotted([slot=discount-message]){font-size:1rem;padding-bottom:20px;padding-top:20px}}slot[name=variant-selector]{flex-grow:1}::slotted([slot=variant-selector]){margin-bottom:22px}slot[name=action]{font-size:.75rem;margin-top:auto}::slotted([slot=action]){font-size:.875rem}@media only screen and (min-width:768px){::slotted([slot=action]){font-size:1rem}}\";","// Module\nvar code = \"<slot name=\\\"image\\\"></slot><a href=\\\"\\\"><h3 class=\\\"title\\\"><slot name=\\\"title\\\"></slot></h3><slot name=\\\"subtitle\\\"></slot></a><slot name=\\\"rating\\\"></slot><product-top-badge></product-top-badge><footer><slot name=\\\"price\\\"></slot><slot name=\\\"variant-selector\\\"></slot><slot name=\\\"discount-message\\\"></slot><slot name=\\\"action\\\"></slot></footer>\";\n// Exports\nexport default code;"],"names":["ProductCardSimple","HTMLElement","constructor","super","this","attachShadow","mode","shadowRoot","innerHTML","concat","connectedCallback","render","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","isUpsell","upsellPrice","price","priceElement","previousValue","textContent","replace","toFixed","compareAtPriceElement","compareAtPrice","compareAtPriceModalContent","compareAtPriceInfo","document","createElement","content","appendChild","discountMessage","message","productLinks","productLink"],"sourceRoot":""}