{"version":3,"file":"product-comparison-complex-section.min.js","mappings":"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","sources":["webpack://lange/./sections/product-comparison-complex/product-comparison-chart/index.ts","webpack://lange/./lib/dom-ready.ts","webpack://lange/./lib/cart-event-queue.ts","webpack://lange/./sections/product-comparison-complex/select-option-button/index.ts","webpack://lange/./lib/css-dom.ts","webpack://lange/./sections/product-comparison-complex/index.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 * Comparison table for products/variants.\n *\n * This component displays products as columns and features as rows. The mobile version shows only 2\n * products at a time with dropdown selectors that allow users to choose which products to compare.\n */\nclass ProductComparisonChart extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Whether to show the ratings in the last row of the table.\n     */\n    showRatings: 'false' | 'true';\n  };\n\n  private variants = new Map<string, string>();\n  private selectedVariants: string[] = [];\n  private featureNames = new Map<string, string>();\n\n  private isSticky = false;\n  private rafId = 0;\n  private isVisible = false;\n  private declare observer: IntersectionObserver;\n\n  private colored = false;\n  private declare releaseReady: ReleaseHandle;\n  private onScrollBound = this.onScroll.bind(this);\n  private onProductSelectorChangedBound = this.onProductSelectorChanged.bind(this);\n  private onReadyBound = this.onReady.bind(this);\n\n  private onReady() {\n    if (this.isConnected) {\n      this.readTableDefinition();\n      this.render();\n    }\n  }\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    this.observer = new IntersectionObserver(entries => {\n      this.isVisible = entries[0].isIntersecting;\n    });\n    this.observer.observe(this);\n\n    addEventListener('scroll', this.onScrollBound, { passive: true });\n\n    this.releaseReady = ready(this.onReadyBound);\n  }\n\n  public disconnectedCallback() {\n    this.observer.disconnect();\n    removeEventListener('scroll', this.onScrollBound);\n    cancelAnimationFrame(this.rafId);\n    this.rafId = 0;\n\n    if (this.releaseReady) {\n      this.releaseReady();\n    }\n\n    const productSelectorElements = this.shadowRoot.querySelectorAll<HTMLSelectElement>(\n      '.product-selectors select');\n    for (const productSelector of productSelectorElements) {\n      productSelector.removeEventListener('change', this.onProductSelectorChangedBound);\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 readTableDefinition() {\n    this.variants.clear();\n\n    const variantsEl = this.querySelectorAll<HTMLElement>('[slot=\"variants\"] [data-variant-id]');\n    for (const variantEl of variantsEl) {\n      this.variants.set(variantEl.dataset.variantId, variantEl.textContent?.trim() ?? '');\n    }\n\n    this.selectedVariants = Array.from(this.variants.keys()).slice(0, getCurrentProductLimit());\n\n    const featuresEl = this.querySelectorAll<HTMLElement>('[slot=\"features\"] [data-feature-no]');\n    for (const featureEl of featuresEl) {\n      this.featureNames.set(featureEl.dataset.featureNo, featureEl.textContent?.trim() ?? '');\n    }\n  }\n\n  private onProductSelectorChanged(_event: Event) {\n    this.selectedVariants = [];\n\n    const productSelectorElements = this.shadowRoot.querySelectorAll<HTMLSelectElement>(\n      '.product-selectors select');\n    for (const productSelectorEl of productSelectorElements) {\n      const selectedVariantId = productSelectorEl.value;\n      this.selectedVariants.push(selectedVariantId);\n    }\n\n    this.render();\n  }\n\n  private render() {\n    this.colored = false;\n\n    const thead = this.shadowRoot.querySelector('thead');\n    thead.innerHTML = '';\n\n    this.renderProductSelectors();\n    this.renderProductCards();\n\n    const tbody = this.shadowRoot.querySelector('tbody');\n    tbody.innerHTML = '';\n\n    this.renderCtaRow();\n    this.renderViewDetailsRow();\n    this.renderFeatureRows();\n\n    if (this.dataset.showRatings === 'true') {\n      this.renderRatingsRow();\n    }\n  }\n\n  private renderProductSelectors() {\n    const productSelectors = document.createElement('tr');\n    productSelectors.classList.add('product-selectors');\n\n    let i = 1;\n    for (const variantId of this.selectedVariants) {\n      const cell = document.createElement('td');\n      cell.headers = 'comparison-col' + i++;\n\n      const selector = document.createElement('select');\n      selector.setAttribute('aria-label', 'Select a product to compare');\n      selector.dataset.clickTrack = 'Comparison Chart Product Selector';\n      for (const [id, name] of this.variants.entries()) {\n        const option = document.createElement('option');\n        option.value = id;\n        option.textContent = name;\n        if (id === variantId) {\n          option.selected = true;\n        }\n\n        selector.appendChild(option);\n      }\n\n      cell.appendChild(selector);\n\n      productSelectors.appendChild(cell);\n    }\n\n    const thead = this.shadowRoot.querySelector('thead');\n    thead.appendChild(productSelectors);\n\n    const productSelectorElements = this.shadowRoot.querySelectorAll<HTMLSelectElement>(\n      '.product-selectors select');\n    for (const productSelector of productSelectorElements) {\n      productSelector.addEventListener('change', this.onProductSelectorChangedBound);\n    }\n  }\n\n  private renderProductCards() {\n    const productCards = document.createElement('tr');\n    productCards.classList.add('product-cards');\n\n    let i = 1;\n    for (const variantId of this.selectedVariants) {\n      const cell = document.createElement('th');\n      cell.scope = 'col';\n      cell.id = 'comparison-col' + i++;\n\n      const productCard = this.querySelector(\n        '[slot=\"product-cards\"] [data-variant-id=\"' + variantId + '\"]');\n      if (productCard) {\n        cell.innerHTML = productCard.innerHTML;\n      }\n\n      productCards.appendChild(cell);\n    }\n\n    const thead = this.shadowRoot.querySelector('thead');\n    thead.appendChild(productCards);\n  }\n\n  private renderCtaRow() {\n    const ctaRow = document.createElement('tr');\n    ctaRow.classList.add('cta-row');\n\n    let i = 1;\n    for (const variantId of this.selectedVariants) {\n      const cell = document.createElement('td');\n      cell.headers = 'comparison-col' + i++;\n\n      const addToCart = this.querySelector(\n        '[slot=\"add-to-cart-row\"] [data-variant-id=\"' + variantId + '\"]');\n      if (addToCart) {\n        cell.innerHTML = addToCart.innerHTML;\n      }\n\n      ctaRow.appendChild(cell);\n    }\n\n    const tbody = this.shadowRoot.querySelector('tbody');\n    tbody.appendChild(ctaRow);\n  }\n\n  private renderFeatureRows() {\n    const tbody = this.shadowRoot.querySelector('tbody');\n\n    for (const featureNo of this.featureNames.keys()) {\n      this.colored = !this.colored;\n\n      const headingRow = document.createElement('tr');\n      headingRow.classList.add('chart-heading');\n      if (this.colored) {\n        headingRow.classList.add('colored');\n      }\n\n      const heading = document.createElement('td');\n      heading.colSpan = this.selectedVariants.length;\n      heading.textContent = this.featureNames.get(featureNo) ?? '';\n\n      headingRow.appendChild(heading);\n\n      tbody.appendChild(headingRow);\n\n      const row = document.createElement('tr');\n      if (this.colored) {\n        row.classList.add('colored');\n      }\n\n      let i = 1;\n      for (const variantId of this.selectedVariants) {\n        const cell = document.createElement('td');\n        cell.headers = 'comparison-col' + i++;\n\n        const feature = this.querySelector(\n          '[slot=\"feature-rows\"] ' +\n          '[data-variant-id=\"' + variantId + '\"] ' +\n          '[data-feature-no=\"' + featureNo + '\"]');\n        if (feature) {\n          cell.innerHTML = feature.innerHTML;\n        }\n\n        row.appendChild(cell);\n      }\n\n      tbody.appendChild(row);\n    }\n  }\n\n  private renderViewDetailsRow() {\n    const viewDetailsRow = document.createElement('tr');\n    viewDetailsRow.classList.add('view-details-row');\n\n    let i = 1;\n    for (const variantId of this.selectedVariants) {\n      const cell = document.createElement('td');\n      cell.headers = 'comparison-col' + i++;\n\n      const viewDetails = this.querySelector(\n        '[slot=\"view-details-row\"] [data-variant-id=\"' + variantId + '\"]');\n      if (viewDetails) {\n        cell.innerHTML = viewDetails.innerHTML;\n      }\n\n      viewDetailsRow.appendChild(cell);\n    }\n\n    const tbody = this.shadowRoot.querySelector('tbody');\n    tbody.appendChild(viewDetailsRow);\n  }\n\n  private renderRatingsRow() {\n    const tbody = this.shadowRoot.querySelector('tbody');\n    this.colored = !this.colored;\n\n    const headingRow = document.createElement('tr');\n    headingRow.classList.add('chart-heading');\n    if (this.colored) {\n      headingRow.classList.add('colored');\n    }\n\n    const heading = document.createElement('td');\n    heading.colSpan = this.selectedVariants.length;\n    heading.textContent = 'Ratings';\n\n    headingRow.appendChild(heading);\n    tbody.appendChild(headingRow);\n\n    const ratingsRow = document.createElement('tr');\n    if (this.colored) {\n      ratingsRow.classList.add('colored');\n    }\n\n    let i = 1;\n    for (const variantId of this.selectedVariants) {\n      const cell = document.createElement('td');\n      cell.headers = 'comparison-col' + i++;\n\n      const wrapper = document.createElement('div');\n      wrapper.classList.add('rating');\n\n      const rating = this.querySelector(\n        '[slot=\"rating-stars\"] [data-variant-id=\"' + variantId + '\"]');\n      if (rating) {\n        wrapper.innerHTML = rating.innerHTML;\n      }\n\n      cell.appendChild(wrapper);\n\n      ratingsRow.appendChild(cell);\n    }\n\n    tbody.appendChild(ratingsRow);\n  }\n\n  /**\n   * Defers the sticky header update to the next animation frame. Skips the update entirely when the\n   * chart is not visible, so scrolling elsewhere on the page does no work here.\n   */\n  private onScroll(_event: Event) {\n    if (!this.isVisible || this.rafId) {\n      return;\n    }\n\n    this.rafId = requestAnimationFrame(() => {\n      this.rafId = 0;\n      this.updateStickyHeader();\n    });\n  }\n\n  /**\n   * Keeps the CTA row pinned just below the header as the user scrolls through the chart. The row\n   * is translated rather than made `position: sticky` because `border-collapse: collapse` on the\n   * table prevents sticky from working on table cells in browsers. Looks like it's not a bug but\n   * how things should work according to the specification.\n   *\n   * @see https://issues.chromium.org/issues/40511425\n   *\n   * The header bottom position comes from `getHeaderBottom`, which reads the header element's\n   * bounding rect so the offset tracks the header correctly when the promo banner hides or shows.\n   */\n  private updateStickyHeader() {\n    const tbody = this.shadowRoot.querySelector('tbody');\n    const row = tbody.querySelector<HTMLElement>('.cta-row');\n    if (!row) {\n      return;\n    }\n\n    const chartRect = tbody.getBoundingClientRect();\n    const headerBottom = getHeaderBottom();\n\n    if (chartRect.top < headerBottom && !this.isSticky) {\n      this.isSticky = true;\n      tbody.classList.add('sticky');\n    }\n\n    if (!this.isSticky) {\n      return;\n    }\n\n    const offset = headerBottom - chartRect.top;\n    const maxOffset = chartRect.height - row.offsetHeight;\n    if (offset <= 0 || maxOffset <= 0) {\n      row.style.transform = '';\n      tbody.classList.remove('sticky');\n      this.isSticky = false;\n      return;\n    }\n\n    row.style.transform = `translateY(${Math.min(offset, maxOffset)}px)`;\n  }\n}\n\nfunction getHeaderBottom() {\n  const headerWrapper = document.querySelector<HTMLElement>('header .wrapper');\n  if (!headerWrapper) {\n    return 0;\n  }\n\n  return headerWrapper.getBoundingClientRect().bottom;\n}\n\nfunction getCurrentProductLimit() {\n  const screenWidth = innerWidth;\n  if (screenWidth > 960) {\n    return 4;\n  }\n\n  if (screenWidth > 640) {\n    return 3;\n  }\n\n  return 2;\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-comparison-chart': ProductComparisonChart;\n  }\n}\n\nif (!customElements.get('product-comparison-chart')) {\n  customElements.define('product-comparison-chart', ProductComparisonChart);\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","// Accessors for the ambient cart event queue seeded and filled by the always-on cart lifecycle\n// snippet. The snippet registers a parse-time listener that buffers every cart event into the\n// queue, so a section whose bundle loads later can replay what it missed. Reaching the queue\n// through this lib, rather than the global directly, keeps the coupling to the ambient layer\n// explicit. The buffered events come off the queue untyped, so the guards here narrow each one\n// during replay.\n\ntype CartUpdatedEvent = GlobalEventHandlersEventMap['cart-updated'];\ntype CartUpdateErredEvent = GlobalEventHandlersEventMap['cart-update-erred'];\n\n/**\n * Returns the ambient queue of buffered cart events. A consumer replays this as it initializes,\n * then listens live for further events.\n */\nexport function getEventQueue() {\n  return cart_lifecycle.queue;\n}\n\n/**\n * Whether the value is a cart updated event. A consumer replaying the queue narrows each buffered\n * event with this before handling it.\n */\nexport function isCartUpdatedEvent(value: any): value is CartUpdatedEvent {\n  return value instanceof Event && value.type === 'cart-updated';\n}\n\n/**\n * Whether the value is a cart update erred event.\n */\nexport function isCartUpdateErredEvent(value: any): value is CartUpdateErredEvent {\n  return value instanceof Event && value.type === 'cart-update-erred';\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport { getEventQueue, isCartUpdatedEvent } from '../../../lib/cart-event-queue.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\ntype CartUpdatedEvent = GlobalEventHandlersEventMap['cart-updated'];\n\n/**\n * The per-column call to action in the product comparison chart for products that have more than\n * one variant. Single-variant products use the plain add to cart button instead.\n *\n * This exists so a shopper can pick a variant straight from the comparison chart without first\n * going to the product page.\n *\n * Product data is gathered from nested product elements.\n *\n * On click it broadcasts a request for the variant selector to open for this product.\n */\nclass SelectOptionButton extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Selected Shopify country code, it is used by the add to cart button.\n     */\n    countryCode: string;\n\n    /**\n     * Currency ISO Code. Required.\n     */\n    currencyCode: string;\n  };\n\n  private onSelectOptionClickBound = this.onSelectOptionClick.bind(this);\n  private onCartUpdatedBound = this.onCartUpdated.bind(this);\n  private product: Partial<Product> = {};\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    for (const event of getEventQueue()) {\n      if (isCartUpdatedEvent(event)) {\n        try {\n          this.onCartUpdatedBound(event);\n        } catch (error) {\n          console.warn(error);\n        }\n      }\n    }\n\n    addEventListener('cart-updated', this.onCartUpdatedBound);\n\n    this.addEventListener('click', this.onSelectOptionClickBound);\n    this.ingestProduct();\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('click', this.onSelectOptionClickBound);\n\n    removeEventListener('cart-updated', this.onCartUpdatedBound);\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 onCartUpdated(event: CartUpdatedEvent) {\n    if (event.detail.is_initial) {\n      const button = this.shadowRoot.querySelector('button');\n      button.disabled = false;\n    }\n  }\n\n  private ingestProduct() {\n    type VariantElement = HTMLElementTagNameMap['variant-element'];\n\n    const productElement = this.querySelector<HTMLElementTagNameMap['product-element']>(\n      'product-element[slot=\"data\"]');\n    if (!productElement) {\n      return;\n    }\n\n    this.product.available = productElement.dataset.available === 'true';\n    this.product.id = parseInt(productElement.dataset.id, 10);\n    this.product.metafields_title = productElement.dataset.metafieldsTitle;\n    this.product.metafields_subtitle = productElement.dataset.metafieldsSubtitle;\n    this.product.selected_variant_id = parseInt(productElement.dataset.selectedVariantId, 10);\n    this.product.title = productElement.dataset.title;\n    this.product.type = productElement.dataset.type;\n    this.product.url = productElement.dataset.url;\n    this.product.metafields_discount_code = productElement.dataset.discountCode;\n    this.product.metafields_discount_percentage =\n      parseFloat(productElement.dataset.discountPercentage);\n    this.product.metafields_discount_override = productElement.dataset.discountOverride;\n    this.product.reviews_average = productElement.dataset.reviewsAverage ?\n      parseFloat(productElement.dataset.reviewsAverage) : 0;\n    this.product.reviews_count = productElement.dataset.reviewsCount ?\n      parseInt(productElement.dataset.reviewsCount, 10) : 0;\n    this.product.tags = productElement.dataset.tags;\n    this.product.option_groups = [];\n\n    const optionGroupElements = productElement.querySelectorAll('product-option-group');\n    for (const optionGroupElement of optionGroupElements) {\n      const optionGroup = <Product['option_groups'][0]>{};\n      optionGroup.name = optionGroupElement.dataset.name;\n      optionGroup.selected_option = optionGroupElement.dataset.selectedOption;\n      if (optionGroupElement.dataset.position) {\n        optionGroup.position = parseInt(optionGroupElement.dataset.position, 10);\n      }\n\n      optionGroup.options = [];\n\n      type ProductOption = HTMLElementTagNameMap['product-option'];\n      const productOptionElements = optionGroupElement.querySelectorAll<ProductOption>(\n        'product-option[data-value]');\n\n      for (const productOptionElement of productOptionElements) {\n        const productOption = <Product['option_groups'][0]['options'][0]>{};\n        productOption.value = productOptionElement.dataset.value;\n        productOption.variants = [];\n\n        const variantElements = productOptionElement.querySelectorAll<VariantElement>(\n          'variant-element[data-id]');\n\n        for (const variantElement of variantElements) {\n          const variant = <ProductVariant>{};\n          variant.available = variantElement.dataset.available === 'true';\n          variant.backorder = variantElement.dataset.backorder;\n          variant.backorder_selling_plan_id = variantElement.dataset.backorderSellingPlanId ?\n            parseInt(variantElement.dataset.backorderSellingPlanId, 10) : null;\n          variant.compare_at_price = variantElement.dataset.compareAtPrice ?\n            parseInt(variantElement.dataset.compareAtPrice, 10) : null;\n          variant.id = parseInt(variantElement.dataset.id, 10);\n          variant.price = parseInt(variantElement.dataset.price, 10);\n          variant.selected = variantElement.dataset.selected === 'true';\n          variant.sku = variantElement.dataset.sku;\n          variant.title = variantElement.dataset.title || productElement.dataset.title || '';\n\n          productOption.variants.push(variant);\n        }\n\n        optionGroup.options.push(productOption);\n      }\n\n      this.product.option_groups.push(optionGroup);\n    }\n\n    this.product.variants = [];\n    const variantElements = this.querySelectorAll<VariantElement>(\n      'product-element[slot=\"data\"] > variant-element[data-id]');\n    for (const variantElement of variantElements) {\n      const variant = <ProductVariant>{};\n      variant.available = variantElement.dataset.available === 'true';\n      variant.compare_at_price = variantElement.dataset.compareAtPrice ?\n        parseInt(variantElement.dataset.compareAtPrice, 10) : null;\n      variant.currency_code = this.dataset.currencyCode;\n      variant.hide_backorder_in_collection = variantElement.dataset.hideBackorderInCollection;\n      variant.id = parseInt(variantElement.dataset.id, 10);\n      variant.image_src = variantElement.dataset.imageSrc || '';\n      variant.option1 = variantElement.dataset.option1;\n      variant.option2 = variantElement.dataset.option2;\n      variant.option3 = variantElement.dataset.option3;\n      variant.price = parseInt(variantElement.dataset.price, 10);\n      variant.selected = variantElement.dataset.selected === 'true';\n      variant.sku = variantElement.dataset.sku;\n      variant.title = variantElement.dataset.title || productElement.dataset.title || '';\n      this.product.variants.push(variant);\n    }\n  }\n\n  private onSelectOptionClick(_event: MouseEvent) {\n    type Detail = WindowEventMap['select-option-requested']['detail'];\n    const requestEvent = new CustomEvent<Detail>('select-option-requested', {\n      bubbles: true,\n      composed: true,\n      detail: {\n        country: this.dataset.countryCode,\n        product: this.product\n      }\n    });\n\n    this.dispatchEvent(requestEvent);\n  }\n}\n\n/**\n * Represents a Shopify product variant\n */\ninterface ProductVariant {\n  /**\n   * Whether the variant is in stock\n   */\n  available: boolean;\n\n  /**\n   * Whether the variant is on backorder\n   */\n  backorder: string;\n\n  /**\n   * The \"Pre-Order\" deferred payment selling plan ID associated with a backordered variant.\n   */\n  backorder_selling_plan_id: number | null;\n\n  /**\n   * The MSRP, or original sales price before discounts, per unit\n   */\n  compare_at_price: number;\n\n  /**\n   * The currency code associated with the price\n   */\n  currency_code: string;\n\n  /**\n   * Boolean as a string to indicate whether to hide any backorder message if the product card is\n   * being viewed in a collection context.\n   */\n  hide_backorder_in_collection: string;\n\n  /**\n   * Variant id\n   *\n   * @example 12345568943\n   */\n  id: number;\n\n  /**\n   * The URL for the variant image\n   */\n  image_src: string;\n\n  /**\n   * The value of the variant for the first product option. If there's no first product option, then\n   * nil is returned.\n   */\n  option1: string;\n\n  /**\n   * The value of the variant for the second product option. If there's no second product option,\n   * then nil is returned.\n   */\n  option2: string;\n\n  /**\n   * The value of the variant for the third product option. If there's no third product option, then\n   * nil is returned.\n   */\n  option3: string;\n\n  /**\n   * The price of the variant in the currency's subunit.\n   *\n   * @see https://shopify.dev/docs/api/liquid/objects/variant#variant-price\n   */\n  price: number;\n\n  /**\n   * Whether this variant is the currently selected variant out of all the variants for the product\n   */\n  selected: boolean;\n\n  /**\n   * The Stock Keeping Unit associated with the variant. This is another kind of product id.\n   */\n  sku: string;\n\n  /**\n   * The title of the variant.\n   */\n  title: string;\n}\n\n/**\n * The complete product shape this section assembles before dispatching, recovered from the shared\n * event contract so the canonical definition lives in one place. The event carries a partial\n * product, so the optional wrapper is stripped here to describe the fully built product.\n */\ntype Product = Required<WindowEventMap['select-option-requested']['detail']['product']>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'select-option-button': SelectOptionButton;\n  }\n}\n\nif (!customElements.get('select-option-button')) {\n  customElements.define('select-option-button', SelectOptionButton);\n}\n","/**\n * Generates a style element containing the given content and appends it to the dom.\n *\n * This is an alternative to the webpack style-loader that circumvents the overly complex webpack\n * configuration and plugin behavior. This intentionally avoids using CSSStyleSheet or any other\n * kind of feature that is not broadly supported or accurately polyfilled.\n *\n * This is safe to call before the dom has loaded.\n *\n * This is safe to call on platforms where document.head is not defined.\n *\n * This annotates appended style elements with a data-lazy attribute so that it is trivial to\n * identify which elements were appended to the dom in this manner. This extra annotation is not\n * expected to have a material performance impact.\n */\nexport function appendCSSText(content: string) {\n  const style = document.createElement('style');\n  style.dataset.lazy = 'true';\n  const node = document.createTextNode(content);\n  style.appendChild(node);\n  const parent = document.head || document.body || document.documentElement;\n  parent.appendChild(style);\n}\n","import './product-comparison-chart/index.js';\nimport './select-option-button/index.js';\nimport { appendCSSText } from '../../lib/css-dom.js';\nimport styles from './index.scss';\n\nappendCSSText(styles);\n"],"names":["ProductComparisonChart","HTMLElement","variants","Map","selectedVariants","featureNames","isSticky","rafId","isVisible","colored","onScrollBound","this","onScroll","bind","onProductSelectorChangedBound","onProductSelectorChanged","onReadyBound","onReady","isConnected","readTableDefinition","render","connectedCallback","initializeShadowRoot","observer","IntersectionObserver","entries","isIntersecting","observe","addEventListener","passive","releaseReady","callback","type","document","readyState","timer","setTimeout","clearTimeout","removeEventListener","ready","disconnectedCallback","disconnect","cancelAnimationFrame","productSelectorElements","shadowRoot","querySelectorAll","productSelector","attachShadow","mode","innerHTML","clear","variantsEl","variantEl","_variantEl$textConten","_variantEl$textConten2","set","dataset","variantId","textContent","trim","Array","from","keys","slice","screenWidth","innerWidth","getCurrentProductLimit","featuresEl","featureEl","_featureEl$textConten","_featureEl$textConten2","featureNo","_event","productSelectorEl","selectedVariantId","value","push","querySelector","renderProductSelectors","renderProductCards","renderCtaRow","renderViewDetailsRow","renderFeatureRows","showRatings","renderRatingsRow","productSelectors","createElement","classList","add","i","cell","headers","selector","setAttribute","clickTrack","id","name","option","selected","appendChild","productCards","scope","productCard","ctaRow","addToCart","tbody","_this$featureNames$ge","headingRow","heading","colSpan","length","get","row","feature","viewDetailsRow","viewDetails","ratingsRow","wrapper","rating","requestAnimationFrame","updateStickyHeader","chartRect","getBoundingClientRect","headerBottom","headerWrapper","bottom","getHeaderBottom","top","offset","maxOffset","height","offsetHeight","style","transform","remove","Math","min","isCartUpdatedEvent","Event","customElements","define","SelectOptionButton","onSelectOptionClickBound","onSelectOptionClick","onCartUpdatedBound","onCartUpdated","product","event","cart_lifecycle","queue","error","console","warn","ingestProduct","detail","is_initial","disabled","productElement","available","parseInt","metafields_title","metafieldsTitle","metafields_subtitle","metafieldsSubtitle","selected_variant_id","title","url","metafields_discount_code","discountCode","metafields_discount_percentage","parseFloat","discountPercentage","metafields_discount_override","discountOverride","reviews_average","reviewsAverage","reviews_count","reviewsCount","tags","option_groups","optionGroupElements","optionGroupElement","optionGroup","selected_option","selectedOption","position","options","productOptionElements","productOptionElement","productOption","variantElements","variantElement","variant","backorder","backorder_selling_plan_id","backorderSellingPlanId","compare_at_price","compareAtPrice","price","sku","currency_code","currencyCode","hide_backorder_in_collection","hideBackorderInCollection","image_src","imageSrc","option1","option2","option3","requestEvent","CustomEvent","bubbles","composed","country","countryCode","dispatchEvent","content","lazy","node","createTextNode","head","body","documentElement","appendCSSText"],"sourceRoot":""}