{
  "version": 3,
  "sources": ["/cdn/shop/t/6/assets/variant-picker.js?cb=20260407-7"],
  "sourcesContent": ["import { Component } from '@theme/component';\nimport { VariantSelectedEvent, VariantUpdateEvent } from '@theme/events';\nimport { morph } from '@theme/morph';\nimport { requestYieldCallback, getViewParameterValue } from '@theme/utilities';\n\n/**\n * @typedef {object} VariantPickerRefs\n * @property {HTMLFieldSetElement[]} fieldsets \u2013 The fieldset elements.\n */\n\n/**\n * A custom element that manages a variant picker.\n *\n * @template {import('@theme/component').Refs} [TRefs=VariantPickerRefs]\n * @extends Component<TRefs>\n */\nexport default class VariantPicker extends Component {\n  /** @type {string | undefined} */\n  #pendingRequestUrl;\n\n  /** @type {AbortController | undefined} */\n  #abortController;\n\n  /** @type {number[][]} */\n  #checkedIndices = [];\n\n  /** @type {HTMLInputElement[][]} */\n  #radios = [];\n\n  connectedCallback() {\n    super.connectedCallback();\n    const fieldsets = /** @type {HTMLFieldSetElement[]} */ (this.refs.fieldsets || []);\n\n    fieldsets.forEach((fieldset) => {\n      const radios = Array.from(fieldset?.querySelectorAll('input') ?? []);\n      this.#radios.push(radios);\n\n      const initialCheckedIndex = radios.findIndex((radio) => radio.dataset.currentChecked === 'true');\n      if (initialCheckedIndex !== -1) {\n        this.#checkedIndices.push([initialCheckedIndex]);\n      }\n    });\n\n    this.addEventListener('change', this.variantChanged.bind(this));\n  }\n\n  /**\n   * Handles the variant change event.\n   * @param {Event} event - The variant change event.\n   */\n  variantChanged(event) {\n    if (!(event.target instanceof HTMLElement)) return;\n\n    const selectedOption =\n      event.target instanceof HTMLSelectElement ? event.target.options[event.target.selectedIndex] : event.target;\n\n    if (!selectedOption) return;\n\n    this.updateSelectedOption(event.target);\n    this.dispatchEvent(new VariantSelectedEvent({ id: selectedOption.dataset.optionValueId ?? '' }));\n\n    const isOnProductPage =\n      this.dataset.templateProductMatch === 'true' &&\n      !event.target.closest('product-card') &&\n      !event.target.closest('quick-add-dialog');\n\n    // Morph the entire main content for combined listings child products, because changing the product\n    // might also change other sections depending on recommendations, metafields, etc.\n    const currentUrl = this.dataset.productUrl?.split('?')[0];\n    const newUrl = selectedOption.dataset.connectedProductUrl;\n    const loadsNewProduct = isOnProductPage && !!newUrl && newUrl !== currentUrl;\n\n    this.fetchUpdatedSection(this.buildRequestUrl(selectedOption), loadsNewProduct);\n\n    const url = new URL(window.location.href);\n\n    const variantId = selectedOption.dataset.variantId || null;\n\n    if (isOnProductPage) {\n      if (variantId) {\n        url.searchParams.set('variant', variantId);\n      } else {\n        url.searchParams.delete('variant');\n      }\n    }\n\n    // Change the path if the option is connected to another product via combined listing.\n    if (loadsNewProduct) {\n      url.pathname = newUrl;\n    }\n\n    if (url.href !== window.location.href) {\n      requestYieldCallback(() => {\n        history.replaceState({}, '', url.toString());\n      });\n    }\n  }\n\n  /**\n   * Updates the selected option.\n   * @param {string | Element} target - The target element.\n   */\n  updateSelectedOption(target) {\n    if (typeof target === 'string') {\n      const targetElement = this.querySelector(`[data-option-value-id=\"${target}\"]`);\n\n      if (!targetElement) throw new Error('Target element not found');\n\n      target = targetElement;\n    }\n\n    if (target instanceof HTMLInputElement) {\n      const fieldsetIndex = Number.parseInt(target.dataset.fieldsetIndex || '');\n      const inputIndex = Number.parseInt(target.dataset.inputIndex || '');\n\n      if (!Number.isNaN(fieldsetIndex) && !Number.isNaN(inputIndex)) {\n        const fieldsets = /** @type {HTMLFieldSetElement[]} */ (this.refs.fieldsets || []);\n        const fieldset = fieldsets[fieldsetIndex];\n        const checkedIndices = this.#checkedIndices[fieldsetIndex];\n        const radios = this.#radios[fieldsetIndex];\n\n        if (radios && checkedIndices && fieldset) {\n          // Clear previous checked states\n          const [currentIndex, previousIndex] = checkedIndices;\n\n          if (currentIndex !== undefined && radios[currentIndex]) {\n            radios[currentIndex].dataset.previousChecked = 'false';\n          }\n          if (previousIndex !== undefined && radios[previousIndex]) {\n            radios[previousIndex].dataset.previousChecked = 'false';\n          }\n\n          // Update checked indices array - keep only the last 2 selections\n          checkedIndices.unshift(inputIndex);\n          checkedIndices.length = Math.min(checkedIndices.length, 2);\n\n          // Update the new states\n          const newCurrentIndex = checkedIndices[0]; // This is always inputIndex\n          const newPreviousIndex = checkedIndices[1]; // This might be undefined\n\n          // newCurrentIndex is guaranteed to exist since we just added it\n          if (newCurrentIndex !== undefined && radios[newCurrentIndex]) {\n            radios[newCurrentIndex].dataset.currentChecked = 'true';\n            fieldset.style.setProperty(\n              '--pill-width-current',\n              `${radios[newCurrentIndex].parentElement?.offsetWidth || 0}px`\n            );\n          }\n\n          if (newPreviousIndex !== undefined && radios[newPreviousIndex]) {\n            radios[newPreviousIndex].dataset.previousChecked = 'true';\n            radios[newPreviousIndex].dataset.currentChecked = 'false';\n            fieldset.style.setProperty(\n              '--pill-width-previous',\n              `${radios[newPreviousIndex].parentElement?.offsetWidth || 0}px`\n            );\n          }\n        }\n      }\n      target.checked = true;\n    }\n\n    if (target instanceof HTMLSelectElement) {\n      const newValue = target.value;\n      const newSelectedOption = Array.from(target.options).find((option) => option.value === newValue);\n\n      if (!newSelectedOption) throw new Error('Option not found');\n\n      for (const option of target.options) {\n        option.removeAttribute('selected');\n      }\n\n      newSelectedOption.setAttribute('selected', 'selected');\n    }\n  }\n\n  /**\n   * Builds the request URL.\n   * @param {HTMLElement} selectedOption - The selected option.\n   * @param {string | null} [source] - The source.\n   * @param {string[]} [sourceSelectedOptionsValues] - The source selected options values.\n   * @returns {string} The request URL.\n   */\n  buildRequestUrl(selectedOption, source = null, sourceSelectedOptionsValues = []) {\n    // this productUrl and pendingRequestUrl will be useful for the support of combined listing. It is used when a user changes variant quickly and those products are using separate URLs (combined listing).\n    // We create a new URL and abort the previous fetch request if it's still pending.\n    let productUrl = selectedOption.dataset.connectedProductUrl || this.#pendingRequestUrl || this.dataset.productUrl;\n    this.#pendingRequestUrl = productUrl;\n    const params = [];\n    const viewParamValue = getViewParameterValue();\n\n    // preserve view parameter, if it exists, for alternative product view testing\n    if (viewParamValue) params.push(`view=${viewParamValue}`);\n\n    if (this.selectedOptionsValues.length && !source) {\n      params.push(`option_values=${this.selectedOptionsValues.join(',')}`);\n    } else if (source === 'product-card') {\n      if (this.selectedOptionsValues.length) {\n        params.push(`option_values=${sourceSelectedOptionsValues.join(',')}`);\n      } else {\n        params.push(`option_values=${selectedOption.dataset.optionValueId}`);\n      }\n    }\n\n    // If variant-picker is a child of quick-add-component or swatches-variant-picker-component, we need to append section_id=section-rendering-product-card to the URL\n    if (this.closest('quick-add-component') || this.closest('swatches-variant-picker-component')) {\n      if (productUrl?.includes('?')) {\n        productUrl = productUrl.split('?')[0];\n      }\n      return `${productUrl}?section_id=section-rendering-product-card&${params.join('&')}`;\n    }\n    return `${productUrl}?${params.join('&')}`;\n  }\n\n  /**\n   * Fetches the updated section.\n   * @param {string} requestUrl - The request URL.\n   * @param {boolean} shouldMorphMain - If the entire main content should be morphed. By default, only the variant picker is morphed.\n   */\n  fetchUpdatedSection(requestUrl, shouldMorphMain = false) {\n    // We use this to abort the previous fetch request if it's still pending.\n    this.#abortController?.abort();\n    this.#abortController = new AbortController();\n\n    fetch(requestUrl, { signal: this.#abortController.signal })\n      .then((response) => response.text())\n      .then((responseText) => {\n        this.#pendingRequestUrl = undefined;\n        const html = new DOMParser().parseFromString(responseText, 'text/html');\n        // Defer is only useful for the initial rendering of the page. Remove it here.\n        html.querySelector('overflow-list[defer]')?.removeAttribute('defer');\n\n        const textContent = html.querySelector(`variant-picker script[type=\"application/json\"]`)?.textContent;\n        if (!textContent) return;\n\n        if (shouldMorphMain) {\n          this.updateMain(html);\n        } else {\n          const newProduct = this.updateVariantPicker(html);\n\n          // We grab the variant object from the response and dispatch an event with it.\n          if (this.selectedOptionId) {\n            this.dispatchEvent(\n              new VariantUpdateEvent(JSON.parse(textContent), this.selectedOptionId, {\n                html,\n                productId: this.dataset.productId ?? '',\n                newProduct,\n              })\n            );\n          }\n        }\n      })\n      .catch((error) => {\n        if (error.name === 'AbortError') {\n          console.warn('Fetch aborted by user');\n        } else {\n          console.error(error);\n        }\n      });\n  }\n\n  /**\n   * @typedef {Object} NewProduct\n   * @property {string} id\n   * @property {string} url\n   */\n\n  /**\n   * Re-renders the variant picker.\n   * @param {Document} newHtml - The new HTML.\n   * @returns {NewProduct | undefined} Information about the new product if it has changed, otherwise undefined.\n   */\n  updateVariantPicker(newHtml) {\n    /** @type {NewProduct | undefined} */\n    let newProduct;\n\n    const newVariantPickerSource = newHtml.querySelector(this.tagName.toLowerCase());\n\n    if (!newVariantPickerSource) {\n      throw new Error('No new variant picker source found');\n    }\n\n    // For combined listings, the product might have changed, so update the related data attribute.\n    if (newVariantPickerSource instanceof HTMLElement) {\n      const newProductId = newVariantPickerSource.dataset.productId;\n      const newProductUrl = newVariantPickerSource.dataset.productUrl;\n\n      if (newProductId && newProductUrl && this.dataset.productId !== newProductId) {\n        newProduct = { id: newProductId, url: newProductUrl };\n      }\n\n      this.dataset.productId = newProductId;\n      this.dataset.productUrl = newProductUrl;\n    }\n\n    morph(this, newVariantPickerSource);\n\n    return newProduct;\n  }\n\n  /**\n   * Re-renders the entire main content.\n   * @param {Document} newHtml - The new HTML.\n   */\n  updateMain(newHtml) {\n    const main = document.querySelector('main');\n    const newMain = newHtml.querySelector('main');\n\n    if (!main || !newMain) {\n      throw new Error('No new main source found');\n    }\n\n    morph(main, newMain);\n  }\n\n  /**\n   * Gets the selected option.\n   * @returns {HTMLInputElement | HTMLOptionElement | undefined} The selected option.\n   */\n  get selectedOption() {\n    const selectedOption = this.querySelector('select option[selected], fieldset input:checked');\n\n    if (!(selectedOption instanceof HTMLInputElement || selectedOption instanceof HTMLOptionElement)) {\n      return undefined;\n    }\n\n    return selectedOption;\n  }\n\n  /**\n   * Gets the selected option ID.\n   * @returns {string | undefined} The selected option ID.\n   */\n  get selectedOptionId() {\n    const { selectedOption } = this;\n    if (!selectedOption) return undefined;\n    const { optionValueId } = selectedOption.dataset;\n\n    if (!optionValueId) {\n      throw new Error('No option value ID found');\n    }\n\n    return optionValueId;\n  }\n\n  /**\n   * Gets the selected options values.\n   * @returns {string[]} The selected options values.\n   */\n  get selectedOptionsValues() {\n    /** @type HTMLElement[] */\n    const selectedOptions = Array.from(this.querySelectorAll('select option[selected], fieldset input:checked'));\n\n    return selectedOptions.map((option) => {\n      const { optionValueId } = option.dataset;\n\n      if (!optionValueId) throw new Error('No option value ID found');\n\n      return optionValueId;\n    });\n  }\n}\n\nif (!customElements.get('variant-picker')) {\n  customElements.define('variant-picker', VariantPicker);\n}\n"],
  "mappings": "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",
  "names": []
}
