{"version":3,"file":"variant-selector-elements-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"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","sources":["webpack://lange/./scripts/sections/variant-selector-elements/variant-selector/index.ts","webpack://lange/./scripts/sections/variant-selector-elements/variant-selector/index.scss","webpack://lange/./scripts/sections/variant-selector-elements/variant-selector/index.html"],"sourcesContent":["import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A custom element for selecting product variants. Includes list of selectable options and\n * the title and description of the selected variant.\n *\n * The data for all variants are stored as `<variant-selector-option>` elements. Each element\n * contains data-attributes, which store the values needed to handle the variant selector's\n * functionality.\n *\n * This component can optionally group variants into categories using `<variant-category>` elements.\n * Each category can have its own title and alternative product description that should be displayed\n * when a variant from that category is selected.\n *\n * TODO: Check accessibility. Since we change the description dynamically, there might be\n * accessibility issues or improvements we need to make.\n *\n * This custom element doesn't gather all variants data to an object. It's easily accessible via\n * `querySelector`, we don't need to access it frequently, nor process this data. The selected\n * variant is also not stored as a class property and taken via `querySelector('input:checked')`.\n *\n * Currently, only one option group is used for products, but technically a Shopify product can have\n * multiple options, e.g. \"Color\", \"Size\" etc.\n */\nclass VariantSelector extends HTMLElement implements CustomElement {\n  readonly dataset!: {\n    /**\n     * Boolean represented as string that indicates whether the element is expandable or not.\n     * If categories are used, expandable must be false.\n     */\n    expandable: 'false' | 'true';\n\n    /**\n     * Set the horizontal alignment of the component on desktop. Depending on where it's placed we\n     * need to make the elements of the component centered.\n     */\n    horizontalAlignmentDesktop: 'center';\n\n    /**\n     * Set the horizontal alignment of the component on mobile. Depending on where it's placed we\n     * need to make the elements of the component centered.\n     */\n    horizontalAlignmentMobile: 'center';\n\n    /**\n     * The ID of the initially selected product variant, a stringified integer\n     */\n    initSelectedVariantId: string;\n\n    /**\n     * A string representing a boolean that indicates whether the component is being used for a\n     * gift card product.\n     *\n     * Depending on whether this is a basic product or a gift card, the component should be\n     * rendered and styled differently.\n     */\n    isGiftCard: 'false' | 'true';\n\n    /**\n     * Product ID, a stringified integer\n     */\n    productId: string;\n\n    /**\n     * Index of the product in the set, string representing a positive integer. Optional\n     *\n     * Required only for subproducts on sets PDP. A set can consist of similar products. We need\n     * \"setIndex\" to distinguish them\n     */\n    setIndex: string;\n\n    /**\n     * Set the size of the component. We need the variant selector component in different sizes\n     * depending on where it's placed. It affects only styles.\n     *\n     * TODO: The `lagre` option is not in use for now and most likely we won't need it. I'll keep it\n     * here for now and remove later if really not needed.\n     */\n    size: 'large' | 'medium' | 'small';\n\n    /**\n     * Represents the possible variants for the title style.\n     *\n     * <strong>Berry</strong> - Muted Plum with Cool Undertones\"\n     * Default: variant name + variant short description, e.g.\"Berry - Muted Plum with Cool\n     * Undertones\"\n     * Condensed: variant name, e.g. \"Berry\"\n     */\n    titleFormat: 'condensed' | 'default' | 'none';\n  };\n\n  public shadowRoot!: ShadowRoot;\n  private onInputChangedBound = this.onInputChanged.bind(this);\n  private onExpandButtonClickedBound = this.onExpandButtonClicked.bind(this);\n  private onSlotChangeBound = this.onSlotChange.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    const slot = this.shadowRoot.querySelector('slot');\n    slot.removeEventListener('slotchange', this.onSlotChangeBound);\n\n    this.shadowRoot.removeEventListener('change', this.onInputChangedBound);\n\n    const expandButton = this.shadowRoot.querySelector('.expand');\n    if (expandButton) {\n      // Checking this condition is important. The expand buttons are added only if the attribute\n      // data-expandable=\"true\" is set and the variant selector contains more than 4 options. Also,\n      // we remove it after clicking.\n      expandButton.removeEventListener('click', this.onExpandButtonClickedBound);\n    }\n  }\n\n  private render() {\n    const slot = this.shadowRoot.querySelector('slot');\n    slot.addEventListener('slotchange', this.onSlotChangeBound);\n  }\n\n  /**\n   * Handles the `slotchange` event. When the slot is populated with `<variant-selector-option>`\n   * elements, it calls the `onSlotReady` method to proceed with rendering and event setup.\n   * DOMContentLoaded is not reliable for cases when this component is slotted into another\n   * component, like in the upsell modal.\n   */\n  private onSlotChange(e: Event) {\n    const slot = <HTMLSlotElement>e.target;\n    const assignedElements = slot.assignedElements();\n    if (assignedElements.length > 0) {\n      this.onSlotReady();\n    }\n  }\n\n  /**\n   * Renders the variant selector options when the default slot is populated with child elements.\n   */\n  private onSlotReady() {\n    // Checking for categories\n    const categories =\n      this.querySelectorAll<HTMLElementTagNameMap['variant-category']>('variant-category');\n\n    // Having categories affects some logic later, so we store this info\n    const hasCategories = categories.length > 0;\n\n    if (hasCategories) {\n      // Rendering categories if they exist. Creating a document fragment which will be appended\n      // to the DOM in one operation for better performance.\n      const categoriesFragment = document.createDocumentFragment();\n\n      for (const category of categories) {\n        const categoryContainer = document.createElement('div');\n        categoryContainer.classList.add('category');\n\n        const title = document.createElement('h3');\n        title.classList.add('category-title');\n        title.textContent = category.dataset.title;\n        categoryContainer.appendChild(title);\n\n        categoriesFragment.appendChild(categoryContainer);\n\n        // Rendering options container. We don't need to check if there are options, because\n        // category data is stored in the variant metafield, which means that if there are\n        // categories, there will be options for each category.\n        const optionsContainer = document.createElement('div');\n        optionsContainer.classList.add('options');\n        categoryContainer.appendChild(optionsContainer);\n\n        // Searching for options that belong to this category, rendering and appending them to\n        // the options container.\n        const options = this.querySelectorAll<HTMLElementTagNameMap['variant-selector-option']>(\n          `variant-selector-option[data-category-id=\"${category.dataset.id}\"]`);\n        for (const variant of options) {\n          const optionElement = this.createOptionElement(variant);\n          optionsContainer.appendChild(optionElement);\n        }\n      }\n\n      // All categories elements are created, appending them to the shadow DOM\n      const categoriesContainer = this.shadowRoot.querySelector('.categories');\n      categoriesContainer.appendChild(categoriesFragment);\n    }\n\n    // Rendering the remaining variant options that don't belong to any category based on data\n    // stored in `<variant-selector-option>` elements. These options will be rendered in the\n    // main options container. Creating a document fragment to improve performance.\n    //\n    // We don't expect to have options that don't belong to any category when categories are used,\n    // but just in case we handle this scenario too.\n    const options = this.querySelectorAll<HTMLElementTagNameMap['variant-selector-option']>(\n      'variant-selector-option:not([data-category-id])');\n    if (options.length > 0) {\n      const optionsFragment = document.createDocumentFragment();\n      for (const variant of options) {\n        const optionElement = this.createOptionElement(variant);\n        optionsFragment.appendChild(optionElement);\n      }\n\n      const optionsContainer = this.shadowRoot.querySelector('.options');\n\n      // Handling expandable variant selector.\n      // It's turned on via the `data-expandable=\"true\"` attribute but only if there are more than\n      // 4 options.\n      //\n      // Also, we need to force-disable it if there are categories, categories are designed to\n      // be used on the PDP only, while expandable variant selector is for product cards, but\n      // just for safety we add this check.\n      if (this.dataset.expandable === 'true' && options.length > 4 && !hasCategories) {\n        optionsContainer.classList.add('collapsed');\n\n        // Creating expand button and add it to the options container. We store the button HTML\n        // in a template element in the shadow DOM to keep the code clean and not create the\n        // button via explicit DOM methods.\n        const expandButtonTemplate =\n          this.shadowRoot.querySelector<HTMLTemplateElement>('#expand-button');\n        optionsFragment.appendChild(expandButtonTemplate.content.cloneNode(true));\n\n        // The HTMLTemplateElement.content.cloneNode() method returns a DocumentFragment, so we\n        // can't attach any event listener directly to it. We need to query the button\n        // after appending the fragment. Hovever, optionsFragment is a DocumentFragment too it's\n        // possible to add the event listener before appending to the DOM to any element inside but\n        // not to the fragment itself.\n        const expandButton = optionsFragment.querySelector('.expand');\n        expandButton.addEventListener('click', this.onExpandButtonClickedBound);\n      }\n\n      // Appending remaining options to the main options container.\n      optionsContainer.appendChild(optionsFragment);\n    }\n\n    this.renderTitle();\n\n    // attaching event listeners\n    this.shadowRoot.addEventListener('change', this.onInputChangedBound);\n\n    // Sending initial event\n    const selector =\n      `variant-selector-option[data-variant-id=\"${this.dataset.initSelectedVariantId}\"]`;\n    type VariantSelectorOptionType = HTMLElementTagNameMap['variant-selector-option'];\n    let initialVariant = this.querySelector<VariantSelectorOptionType>(selector);\n    if (!initialVariant) {\n      // There's a strange error in Sentry. I cannot reproduce so trying to catch it. I assume\n      // that `this.dataset.initSelectedVariantId` is not passed sometimes. If it helps we\n      // will investigate more why it happens.\n      const variantOptions = this.querySelectorAll('variant-selector-option');\n      const options = [];\n      for (const variantOption of variantOptions) {\n        options.push({\n          variantId: variantOption.dataset.variantId,\n          value: variantOption.dataset.value,\n          available: variantOption.dataset.available\n        });\n      }\n\n      Sentry.captureMessage('Variant selector initial variant not found', {\n        level: 'warning',\n        extra: {\n          initSelectedVariantId: this.dataset.initSelectedVariantId,\n          productId: this.dataset.productId,\n          parentElement: this.parentElement,\n          options\n        }\n      });\n\n      // Fallback to the first variant\n      initialVariant = this.querySelector<VariantSelectorOptionType>('variant-selector-option');\n    }\n\n    const category = this.findCategoryForVariant(initialVariant);\n\n    const variantChangedEvent = new CustomEvent<VariantChangedEvent['detail']>('variant-changed', {\n      cancelable: false,\n      bubbles: true,\n      detail: {\n        initial: true,\n        source: 'variant-selector',\n        variant: {\n          available: initialVariant.dataset.available === 'true',\n          description: initialVariant.dataset.description,\n          id: parseInt(initialVariant.dataset.variantId, 10),\n          product_id: parseInt(this.dataset.productId, 10),\n          coming_soon: false,\n          option: initialVariant.dataset.value,\n          price: parseInt(initialVariant.dataset.price, 10),\n          compareAtPrice: initialVariant.dataset.compareAtPrice,\n          compareAtPriceModalContent: initialVariant.dataset.compareAtPriceModalContent,\n          setIndex: parseInt(this.dataset.setIndex, 10) ?? null,\n          image: initialVariant.dataset.image ?? '',\n          color: this.getVariantColor(initialVariant.dataset.backgroundClass),\n          discountMessage: initialVariant.dataset.discountMessage ?? '',\n          topBadge: initialVariant.dataset.topBadge ?? '',\n          topBadgeStyle: initialVariant.dataset.topBadgeStyle ?? 'default',\n          categoryDescription: category?.dataset.description ?? null\n        }\n      }\n    });\n    this.dispatchEvent(variantChangedEvent);\n  }\n\n  private onInputChanged(_event: Event) {\n    this.renderTitle();\n\n    const input = this.shadowRoot.querySelector('input:checked');\n    type Variant = HTMLElementTagNameMap['variant-selector-option'];\n    const selector = `variant-selector-option[data-variant-id=\"${input.id}\"]`;\n    const variant = this.querySelector<Variant>(selector);\n    const category = this.findCategoryForVariant(variant);\n\n    const variantChangedEvent = new CustomEvent<VariantChangedEvent['detail']>('variant-changed', {\n      cancelable: false,\n      bubbles: true,\n      detail: {\n        initial: false,\n        source: 'variant-selector',\n        variant: {\n          available: variant.dataset.available === 'true',\n          description: variant.dataset.description,\n          id: parseInt(variant.dataset.variantId, 10),\n          product_id: parseInt(this.dataset.productId, 10),\n          coming_soon: false,\n          option: variant.dataset.value,\n          price: parseInt(variant.dataset.price, 10),\n          compareAtPrice: variant.dataset.compareAtPrice,\n          compareAtPriceModalContent: variant.dataset.compareAtPriceModalContent,\n          setIndex: parseInt(this.dataset.setIndex, 10) ?? null,\n          image: variant.dataset.image ?? '',\n          color: this.getVariantColor(variant.dataset.backgroundClass),\n          discountMessage: variant.dataset.discountMessage,\n          topBadge: variant.dataset.topBadge ?? '',\n          topBadgeStyle: variant.dataset.topBadgeStyle ?? 'default',\n          categoryDescription: category?.dataset.description ?? null\n        }\n      }\n    });\n    this.dispatchEvent(variantChangedEvent);\n  }\n\n  private onExpandButtonClicked(event: Event) {\n    const button = <HTMLElement>event.currentTarget;\n    button.remove();\n\n    const options = this.shadowRoot.querySelector('.options');\n    options.classList.remove('collapsed');\n  }\n\n  /**\n   * Renders the title and short description based on the selected variant.\n   */\n  private renderTitle() {\n    const titleElement = this.shadowRoot.querySelector('.title');\n    if (this.dataset.titleFormat === 'none') {\n      if (titleElement) {\n        titleElement.remove();\n      }\n\n      return;\n    }\n\n    let checkedInput = this.shadowRoot.querySelector('input:checked');\n    if (!checkedInput) {\n      // This is a fallback, it should not happen normally. Trying to fix a strange Sentry error\n      checkedInput = this.shadowRoot.querySelector('input');\n    }\n\n    type Variant = HTMLElementTagNameMap['variant-selector-option'];\n    const selector = `variant-selector-option[data-variant-id=\"${checkedInput.id}\"]`;\n    const selectedVariant = this.querySelector<Variant>(selector);\n    const { value, description } = selectedVariant.dataset;\n\n    let title = '';\n\n    if (value) {\n      if (this.dataset.isGiftCard === 'true') {\n        title += `<strong>${removeDecimals(value)}</strong>`;\n      } else {\n        title += `<strong>${value}</strong>`;\n      }\n    }\n\n    if (this.dataset.titleFormat !== 'condensed' && description) {\n      title += ` - ${description}`;\n    }\n\n    titleElement.innerHTML = title;\n  }\n\n  /**\n   * Creates an element containing a radio input and label element for a given variant option.\n   * We need to create option elements from different places, so it's separated into its own method.\n   */\n  private createOptionElement(variant: HTMLElementTagNameMap['variant-selector-option']) {\n    // Creating a radia input representing the variant option. It's visually hidden, the label\n    // element is styled to look like the option swatch.\n    const input = document.createElement('input');\n    input.id = variant.dataset.variantId;\n    input.type = 'radio';\n    input.name = variant.dataset.group;\n    input.value = variant.dataset.value;\n    input.classList.add('visually-hidden');\n    if (variant.dataset.available !== 'true') {\n      input.classList.add('unavailable');\n    }\n\n    input.checked = variant.dataset.variantId === this.dataset.initSelectedVariantId;\n\n    // Creating the label element associated with the input. This is the visible part of the option\n    // swatch that the user interacts with.\n    const label = document.createElement('label');\n    label.setAttribute('for', variant.dataset.variantId);\n    label.setAttribute('title', variant.dataset.value);\n    if (variant.dataset.backgroundClass) {\n      label.classList.add(variant.dataset.backgroundClass);\n    }\n\n    // Preparing label inner HTML. We add conditionally different content and then set it to the\n    // label element in one operation.\n    let labelHtml = '';\n\n    // Adding a text label inside the label element. For gift cards, we show the price directly. For\n    // regular products, we add a visually hidden span for screen readers.\n    if (this.dataset.isGiftCard === 'true') {\n      labelHtml = removeDecimals(variant.dataset.value);\n    } else {\n      labelHtml = `<span class=\"visually-hidden\">${variant.dataset.value}</span>`;\n    }\n\n    // Adding badge if exists. It's a small marketing label shown on the color swatch, e.g. \"New\"\n    if (variant.dataset.badge) {\n      const badgeStyleClass = variant.dataset.badgeStyle ?? '';\n      labelHtml += `<span class=\"badge ${badgeStyleClass}\">${variant.dataset.badge}</span>`;\n    }\n\n    // Adding prepared HTML to the label element\n    label.innerHTML = labelHtml;\n\n    // Creating a container for the input and label to return as a single element. We need to wrap\n    // them in a container to keep the structure clean and easier to style.\n    const container = document.createElement('div');\n    container.appendChild(input);\n    container.appendChild(label);\n\n    return container;\n  }\n\n  /**\n   * Finds the category element associated with a given variant\n   */\n  private findCategoryForVariant(variant: HTMLElementTagNameMap['variant-selector-option']) {\n    let category: HTMLElementTagNameMap['variant-category'];\n    const categoryId = variant.dataset.categoryId;\n    if (categoryId) {\n      category = this.querySelector<HTMLElementTagNameMap['variant-category']>(\n        `variant-category[data-id=\"${categoryId}\"]`);\n    }\n\n    return category;\n  }\n\n  /**\n   * Retrieves the background color defined in the CSS for a variant color swatch.\n   *\n   * @todo This approach isn't ideal, but it's set up like this for now to get things working.\n   * We need to start discussing a better way to handle variant colors. One idea is to store them in\n   * Shopify so the content team can manage them directly, but this would require more investigation\n   */\n  private getVariantColor(backgroundClass: string) {\n    // e.g., gift card\n    if (!backgroundClass) {\n      return '';\n    }\n\n    const style = this.shadowRoot.querySelector('style');\n    const rules: CSSRuleList = style.sheet.cssRules;\n\n    // Escape exclamation marks and other common problematic characters\n    const escapedBackgroundClass = backgroundClass\n      .replace(/[!\"#$%&'()*+,.:;?@^`{|}~]/g, '\\\\$&');\n\n    for (const rule of rules) {\n      if (rule instanceof CSSStyleRule && rule.selectorText === `.${escapedBackgroundClass}`) {\n        const backgroundColor = rule.style.backgroundColor;\n        if (backgroundColor) {\n          return backgroundColor;\n        }\n      }\n    }\n\n    return '';\n  }\n}\n\n/**\n * Removes the decimal part from a price string if it ends with \".00\".\n *\n * @param priceString - e.g. \"$10.00\"\n */\nfunction removeDecimals(priceString: string): string {\n  return priceString.replace(/\\.00$/, '');\n}\n\n// TODO The detail of the event should be refactored, it's very old and tends to copy the structure\n// and key names of some Shopify object, but there's no sense to do that, we don't need all these\n// values. This object has to be reviewed and only the parameters we need for the variant selector\n// functionality should stay. For now, I leave them as optional for compatibility until the old\n// variant selector is replaced with this custom element for all places.\ntype VariantChangedEvent = CustomEvent<{\n  initial: boolean;\n  source: string;\n  variant: {\n    /**\n     * Indicates whether the variant is available or not.\n     */\n    available: boolean;\n\n    /**\n     * The category description for the variant's category.\n     * It's null if no category description is set or if the variant doesn't belong to any category.\n     */\n    categoryDescription: string | null;\n\n    /**\n     * The variant's color in CSS RGB format, used in the UI to display color swatches.\n     * Returns an empty string if no color is found.\n     *\n     * @example \"rgb(51, 47, 33)\"\n     */\n    color: string;\n\n    /**\n     * Indicates whether the coming soon variant.\n     */\n    coming_soon: boolean | null;\n\n    /**\n     * Variant compare at price. It's possible, that's different variants will have each own\n     * compare at price. Represented as string with currency symbol, e.g. \"$12\"\n     */\n    compareAtPrice: string;\n\n    /**\n     * Content to be displayed in the compare at price modal for a particular variant\n     */\n    compareAtPriceModalContent: string;\n\n    /**\n     * Variant additional short description\n     */\n    description: string | null;\n\n    /**\n     * Discount offer message\n     */\n    discountMessage: string;\n\n    /**\n     * Product variant ID\n     */\n    id: number;\n\n    /**\n     * Variant image src\n     */\n    image: string;\n\n    /**\n     * Variant main media ID\n     *\n     * @todo check if we need it anywhere\n     */\n    media_id?: number | null;\n\n    /**\n     * Variant associated option name\n     */\n    option?: string;\n\n    /**\n     * List of all variant options\n     *\n     * @todo check if we need it anywhere\n     */\n    options?: string[];\n\n    /**\n     * Variant price. It's possible, that's different variants will have each own price, e.g. the\n     * gift card. Represented as cents, e.g. \"1200\" means $12\n     */\n    price?: number;\n\n    /**\n     * Variant product ID\n     */\n    product_id: number;\n\n    /**\n     * Index of the product in the set.\n     *\n     * A set can consist of similar products. We need \"setIndex\" to distinguish them\n     */\n    setIndex?: number;\n\n    /**\n     * Top badge label, e.g. \"50% off\", \"Sale\"\n     */\n    topBadge: string;\n\n    /**\n     * Top badge style (black or red color), e.g. \"default\", \"highlighted\"\n     */\n    topBadgeStyle: 'default' | 'highlighted';\n  };\n}>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'variant-selector': VariantSelector;\n  }\n\n  interface WindowEventMap {\n    'variant-changed': VariantChangedEvent;\n  }\n\n  interface HTMLElementEventMap {\n    'variant-changed': VariantChangedEvent;\n  }\n}\n\nif (!customElements.get('variant-selector')) {\n  customElements.define('variant-selector', VariantSelector);\n}\n","export default \":host{display:block}@media only screen and (max-width:767px){:host([data-horizontal-alignment-mobile=center]){text-align:center}:host([data-horizontal-alignment-mobile=center]) .options{justify-content:center}}@media only screen and (min-width:768px){:host([data-horizontal-alignment-desktop=center]){text-align:center}:host([data-horizontal-alignment-desktop=center]) .options{justify-content:center}}:host([data-size=large]) .expand,:host([data-size=large]) label{height:42px;width:42px}:host([data-size=medium]) .title{font-size:.75rem}@media only screen and (min-width:768px){:host([data-size=medium]) .title{font-size:.875rem}}:host([data-size=medium]) .options{column-gap:0}@media only screen and (min-width:768px){:host([data-size=medium]) .options{column-gap:3px}}:host([data-size=medium]) .expand,:host([data-size=medium]) label{height:28px;width:28px}@media only screen and (min-width:768px){:host([data-size=medium]) .expand,:host([data-size=medium]) label{height:32px;width:32px}}:host([data-size=small]) .title{font-size:.75rem}:host([data-size=small]) .expand,:host([data-size=small]) label{height:24px;width:24px}:host([data-size=small]) .badge{font-size:9px;padding:1px 3px}:host([data-is-gift-card=true]) label{background-color:#000;font-size:.875rem;font-weight:500;height:auto;line-height:1;padding:8px 12px;text-align:center;width:auto}:host([data-is-gift-card=true]) .expand{background-color:#000;border-radius:100px;height:30px;width:36px}:host([data-is-gift-card=true]) .expand svg{stroke:#fff}:host([data-is-gift-card=true]) input:checked+label:before{border-color:#000}:host([data-is-gift-card=true]):host([data-size=small]) label{padding:6px 8px}:host([data-is-gift-card=true]):host([data-size=small]) .expand{height:28px}strong{font-weight:600}.title{margin-bottom:8px}@media only screen and (min-width:768px){.categories{margin-top:8px}}.categories:empty{display:none}.category{border-bottom:1px solid #dbdbdb;margin-bottom:10px;padding-bottom:10px}.category:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}.category-title{font-size:.825rem;font-weight:300;letter-spacing:.07em;margin-bottom:4px;margin-top:0;text-transform:uppercase}@media only screen and (min-width:768px){.category-title{margin-bottom:6px}}.options{align-items:center;column-gap:3px;display:flex;flex-wrap:wrap;margin-left:-4px;margin-right:-4px}@media only screen and (min-width:768px){.options{row-gap:4px}}.options.collapsed>div:nth-of-type(n+5){display:none}.expand,label{background-clip:padding-box;border:4px solid #0000;border-radius:100px;box-sizing:initial;color:#fff;cursor:pointer;display:block;position:relative}label:hover:before{border-color:#cdcfd1}label:before{border:1px solid #0000;border-radius:100px;bottom:-4px;content:\\\"\\\";left:-4px;position:absolute;right:-4px;top:-4px}label:after{border-right:1px solid #fff;bottom:-5px;left:50%;position:absolute;top:-5px;transform:rotate(-45deg)}@media only screen and (min-width:768px){label:after{bottom:-4px;top:-4px}}.badge{background-color:#000;bottom:-4px;color:#fff;font-size:.625rem;font-weight:600;left:50%;line-height:1;padding:2px 3px;position:absolute;text-transform:uppercase;transform:translateX(-50%)}@media only screen and (min-width:768px){.badge{font-size:.6875rem;padding-left:4px;padding-right:4px}}.badge.highlighted{background-color:#e71d13}input:checked+label:before{border-color:#1e1e1e}input:focus+label:before{border-color:#000;border-width:2px}.unavailable+label:after{content:\\\"\\\"}.expand{align-items:center;appearance:none;background-color:#e6e7e8;border-radius:50%;cursor:pointer;display:flex;justify-content:center;min-width:unset;padding:0}.expand:hover{background-color:#cdcfd1;border-color:#0000}.expand svg{width:20px}.visually-hidden{height:1px;overflow:hidden;position:absolute;width:1px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);white-space:nowrap}.bg-120ml{background-color:#e9ecee}.bg-6pm{background-color:#b16a56}.bg-all-that{background-color:#683431}.bg-allspice{background-color:#774212}.bg-almond{background-color:#dbb497}.bg-almond-fruit{background-color:#9f5f54}.bg-amber{background-color:#d19c70}.bg-anise{background-color:#a86531}.bg-apricot{background-color:#f09491}.bg-bare-rice{background-color:#dbc8b6}.bg-barley{background-color:#f8d4b2}.bg-berry{background-color:#b66c6d}.bg-biscuit{background-color:#debc8b}.bg-black{background-color:#0f171f}.bg-blonde-shot{background-color:#bba370}.bg-blush{background-color:#dea39c}.bg-brick{background-color:#7c2629}.bg-burgundy{background-color:#992359}.bg-burgundy-2{background-color:#7c0d3f}.bg-burgundy-3{background-color:#b24d76}.bg-cacao{background-color:#7e694f}.bg-caramel{background-color:#d2a57c}.bg-cardamon{background-color:#dea76e}.bg-cardinal{background-color:#ab2328}.bg-carob{background-color:#4f3324}.bg-cashew{background-color:#d7a179}.bg-celestial-cool-tones{background-color:#b4b5df}.bg-ceramic{background-color:#ce9464}.bg-chai{background-color:#733d11}.bg-chalkshine{background-color:#d9d2ca}.bg-charcoal{background-color:#212721}.bg-cherry{background-color:#d6001c}.bg-chili{background-color:#c10016}.bg-chocolate{background-color:#5c3d31}.bg-cinnamon{background-color:#ae7947}.bg-clear{background-color:#e6e6e6}.bg-cloudless{background-color:#a7bcd6}.bg-clove{background-color:#4c2812}.bg-cocoa{background-color:#7e502e}.bg-coffee{background-color:#7a4617}.bg-coral{background-color:#fa4616}.bg-coriander{background-color:#d8a379}.bg-cork{background-color:#f3d3b0}.bg-cotton{background-color:#f3d8bb}.bg-cranberry{background-color:#971b2f}.bg-cream{background-color:#f6dec4}.bg-crimson{background-color:#9b2242}.bg-cumin{background-color:#c6925c}.bg-currant{background-color:#ad5389}.bg-daydream{background-color:#b47d75}.bg-deep{background-color:#c48e50}.bg-deep-hunter-green{background-color:#183029}.bg-dewy{background-color:#f7f7f7}.bg-enamel{background-color:#fee8d3}.bg-espresso{background-color:#382e2c}.bg-fair{background-color:#fce7c4}.bg-fig{background-color:#6f2c3f}.bg-flax{background-color:#b08054}.bg-future-dusk{background-color:#3b3a4a}.bg-ginger{background-color:#e7b78a}.bg-glacier{background-color:#e0e0e0}.bg-go-there\\\\!{background-color:#905e7b}.bg-gold-dust{background-color:#db9900}.bg-graphite{background-color:#545859}.bg-guava{background-color:#df7a99}.bg-henna{background-color:#965c2c}.bg-hibiscus{background-color:#b46b7a}.bg-high-desert{background-color:#dda69d}.bg-honey{background-color:#dda87b}.bg-ink{background-color:#0f171f}.bg-jute{background-color:#ddb182}.bg-latte{background-color:#ad7c59}.bg-leather{background-color:#4e3629}.bg-licorice{background-color:#0f171f}.bg-lilac{background-color:#d6c1d7}.bg-linen{background-color:#f4d1ab}.bg-longan-berry{background-color:#bf9474}.bg-lychee{background-color:#e4aeb1}.bg-matte{background-color:#f8eeee}.bg-matte-finish\\\\/standard{background-color:#7e4d4d}.bg-medium{background-color:#f3d098}.bg-milk{background-color:#fde4ce}.bg-millet{background-color:#9d6e46}.bg-sapphire{background-color:#002f6c}.bg-nudesicle{background-color:#dfb8a7}.bg-nutmeg{background-color:#dca86e}.bg-off-pink{background-color:#bc8a7e}.bg-opal-shades{background-color:#8b5a6b}.bg-orange-caves{background-color:#f38e58}.bg-original{background-color:#f6ece5}.bg-onyx{background-color:#332f21}.bg-papyrus{background-color:#bf9474}.bg-pecan{background-color:#8c5c30}.bg-peony{background-color:#fac0b8}.bg-pepper{background-color:#4e4b48}.bg-pink-smoothie{background-color:#dea09a}.bg-porcelain{background-color:#fdecd8}.bg-praline{background-color:#d5a286}.bg-quinoa{background-color:#cda890}.bg-rattan{background-color:#e6ba8b}.bg-red-clay{background-color:#b0493d}.bg-rich-brown{background-color:#4f2c1d}.bg-rose{background-color:#cf6f77}.bg-rye{background-color:#c09c83}.bg-sable{background-color:#b27846}.bg-sand{background-color:#edcea2}.bg-sesame{background-color:#ecc49b}.bg-silk{background-color:#eddbc1}.bg-smudge-proof-licorice{background-color:#0f171f}.bg-sumac{background-color:#89532f}.bg-tamarind{background-color:#c68f56}.bg-marine{background-color:#003b49}.bg-terracotta{background-color:#e3b699}.bg-toffee{background-color:#8f3237}.bg-truffle{background-color:#562d0f}.bg-ultra-violet{background-color:#512a44}.bg-waterproof-licorice{background-color:#0f171f}.bg-what-eh-ver\\\\!{background-color:#c48672}.bg-silver-ice{background-color:#f2ebe7}.bg-sunset-spark{background-color:#c48672}.bg-radiant-rose{background-color:#dea39c}.bg-gold-rush{background-color:#d4b59e}.bg-diva{background-color:#dd5680}.bg-doll{background-color:#e3aeb1}.bg-muse{background-color:#be625e}.bg-dew{background-color:#e7e6e6}.bg-pink-ice{background-color:#dda69d}.bg-golden-hour{background-color:#d9ac95}.bg-copper-glow{background-color:#cf7b69}.bg-pink-apple{background-color:#e17974}.bg-watermelon{background-color:#c52f40}.bg-dragon-fruit{background-color:#9f2842}.bg-raisin{background-color:#b66b7a}.bg-rhubarb{background-color:#9a4856}.bg-brown-pear{background-color:#a75247}.bg-clay{background-color:#cc9a8d}.bg-bluff{background-color:#ad7f66}.bg-oasis{background-color:#af6f53}.bg-cove{background-color:#7f4c3a}.bg-mesa{background-color:#5b3427}.bg-poppy{background-color:#b06f76}.bg-sangria{background-color:#852c4d}.bg-mocha-glow{background-color:#ae6a61}.bg-desert-rose{background-color:#a94545}.bg-zest{background-color:#de754b}.bg-ivory-pearl{background-color:#dfb8a7}.bg-satin-cloud{background-color:#f1c6a6}.bg-golden-olive{background-color:#d7a179}.bg-honey-beige{background-color:#e59e6d}.bg-toasted-brown{background-color:#ac7052}.bg-coral-mist{background-color:#dd7975}.bg-pink-pearl{background-color:#f5e0cf}.bg-gold-glow{background-color:#f3e4cd}.bg-butter{background-color:#efd4b7}.bg-hazelnut{background-color:#d39973}.bg-glaze{background-color:#f1e3e3}.bg-oat{background-color:#ecc4aa}.bg-eggshell{background-color:#f7e5d7}\";","// Module\nvar code = \"<div class=\\\"title\\\"></div><div class=\\\"options\\\"></div><div class=\\\"categories\\\"></div><slot></slot><template id=\\\"expand-button\\\"><button class=\\\"expand\\\" aria-label=\\\"Show all options\\\"><svg role=\\\"presentation\\\" width=\\\"20\\\" height=\\\"20\\\" viewBox=\\\"0 0 20 20\\\" fill=\\\"none\\\" stroke=\\\"#83888C\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><title>Show all options</title><path d=\\\"M1 9.99976L19 9.99992M9.99965 0.999969L9.99982 19\\\" stroke-linecap=\\\"square\\\"></path></svg></button></template>\";\n// Exports\nexport default code;"],"names":["VariantSelector","HTMLElement","constructor","super","onInputChangedBound","this","onInputChanged","bind","onExpandButtonClickedBound","onExpandButtonClicked","onSlotChangeBound","onSlotChange","attachShadow","mode","shadowRoot","innerHTML","concat","connectedCallback","render","disconnectedCallback","querySelector","removeEventListener","expandButton","addEventListener","e","target","assignedElements","length","onSlotReady","_parseInt","_initialVariant$datas","_initialVariant$datas2","_initialVariant$datas3","_initialVariant$datas4","_category$dataset$des","categories","querySelectorAll","hasCategories","categoriesFragment","document","createDocumentFragment","category","categoryContainer","createElement","classList","add","title","textContent","dataset","appendChild","optionsContainer","options","id","variant","optionElement","createOptionElement","optionsFragment","expandable","expandButtonTemplate","content","cloneNode","renderTitle","selector","initSelectedVariantId","initialVariant","variantOptions","variantOption","push","variantId","value","available","Sentry","captureMessage","level","extra","productId","parentElement","findCategoryForVariant","variantChangedEvent","CustomEvent","cancelable","bubbles","detail","initial","source","description","parseInt","product_id","coming_soon","option","price","compareAtPrice","compareAtPriceModalContent","setIndex","image","color","getVariantColor","backgroundClass","discountMessage","topBadge","topBadgeStyle","categoryDescription","dispatchEvent","_event","_parseInt2","_variant$dataset$imag","_variant$dataset$topB","_variant$dataset$topB2","_category$dataset$des2","input","event","currentTarget","remove","titleElement","titleFormat","checkedInput","selectedVariant","isGiftCard","removeDecimals","type","name","group","checked","label","setAttribute","labelHtml","badge","_variant$dataset$badg","badgeStyleClass","badgeStyle","container","categoryId","rules","sheet","cssRules","escapedBackgroundClass","replace","rule","CSSStyleRule","selectorText","backgroundColor","style","priceString","customElements","get","define"],"sourceRoot":""}