{
  "version": 3,
  "sources": ["/cdn/shop/t/3/assets/sticky-add-to-cart.js?v%5B%5D=48956925339276737091775636882"],
  "sourcesContent": ["import { Component } from '@theme/component';\nimport { ThemeEvents, QuantitySelectorUpdateEvent } from '@theme/events';\nimport { morph } from '@theme/morph';\nimport { onAnimationEnd } from '@theme/utilities';\n\n/**\n * @typedef {Object} ProductVariant\n * @property {string|number} [id] - Variant ID\n * @property {string} [title] - Variant title\n * @property {string} [name] - Variant name\n * @property {boolean} [available] - Whether variant is available\n * @property {Object} [featured_media] - Featured media object\n * @property {Object} [featured_media.preview_image] - Preview image data\n * @property {string} [featured_media.preview_image.src] - Image source URL\n * @property {string} [featured_media.alt] - Alt text for the image\n */\n\n/**\n * @typedef {HTMLElement & {\n *   source: Element,\n *   destination: Element,\n *   useSourceSize: string | boolean\n * }} FlyToCart\n */\n\n/**\n * @typedef {Object} StickyAddToCartRefs\n * @property {HTMLElement} stickyBar - The floating bar container\n * @property {HTMLButtonElement} addToCartButton - Sticky bar's button\n * @property {HTMLElement} quantityDisplay - Quantity display container\n * @property {HTMLElement} quantityNumber - Quantity number element\n * @property {HTMLImageElement} productImage - Product image element\n */\n\n/**\n * A custom element that manages a sticky add-to-cart bar.\n * Shows when the main buy buttons scroll out of view.\n *\n * @extends {Component<StickyAddToCartRefs>}\n */\nclass StickyAddToCartComponent extends Component {\n  requiredRefs = ['stickyBar', 'addToCartButton', 'quantityDisplay', 'quantityNumber'];\n\n  /** @type {IntersectionObserver | null} */\n  #buyButtonsIntersectionObserver = null;\n\n  /** @type {IntersectionObserver | null} */\n  #mainBottomObserver = null;\n\n  /** @type {number | undefined} */\n  #resetTimeout;\n\n  /** @type {boolean} */\n  #isStuck = false;\n\n  /** @type {number | null} */\n  #animationTimeout = null;\n\n  /** @type {AbortController} */\n  #abortController = new AbortController();\n\n  /** @type {HTMLButtonElement | null} */\n  #targetAddToCartButton = null;\n\n  /** @type {number} */\n  #currentQuantity = 1;\n\n  /** @type {boolean} */\n  #hiddenByBottom = false;\n\n  connectedCallback() {\n    super.connectedCallback();\n\n    this.#setupIntersectionObserver();\n\n    const { signal } = this.#abortController;\n    const target = this.closest('.shopify-section');\n    target?.addEventListener(ThemeEvents.variantUpdate, this.#handleVariantUpdate, { signal });\n    target?.addEventListener(ThemeEvents.variantSelected, this.#handleVariantSelected, { signal });\n\n    document.addEventListener(ThemeEvents.cartUpdate, this.#handleCartAddComplete, { signal });\n    document.addEventListener(ThemeEvents.cartError, this.#handleCartAddComplete, { signal });\n    document.addEventListener(ThemeEvents.quantitySelectorUpdate, this.#handleQuantityUpdate, { signal });\n\n    this.#getInitialQuantity();\n  }\n\n  disconnectedCallback() {\n    super.disconnectedCallback();\n    this.#buyButtonsIntersectionObserver?.disconnect();\n    this.#mainBottomObserver?.disconnect();\n    this.#abortController.abort();\n    if (this.#animationTimeout) {\n      clearTimeout(this.#animationTimeout);\n    }\n  }\n\n  /**\n   * Sets up the IntersectionObserver to watch the buy buttons visibility\n   */\n  #setupIntersectionObserver() {\n    const productForm = this.#getProductForm();\n    if (!productForm) return;\n\n    const buyButtonsBlock = productForm.closest('.buy-buttons-block');\n    if (!buyButtonsBlock) return;\n\n    // In themes migrated from 2.0, the footer element doesn't exist\n    const footer = document.querySelector('footer') ?? document.querySelector('[class*=\"footer-group\"]');\n    if (!footer) return;\n\n    // Observer for buy buttons visibility\n    this.#buyButtonsIntersectionObserver = new IntersectionObserver((entries) => {\n      const [entry] = entries;\n      if (!entry) return;\n\n      // Only show sticky bar if buy buttons have been scrolled past (above viewport)\n      if (!entry.isIntersecting && !this.#isStuck) {\n        // Check if the element is above the viewport (scrolled past) or below (not yet reached)\n        const rect = entry.target.getBoundingClientRect();\n        if (rect.bottom < 0 || rect.top < 0) {\n          // Element is above viewport - show sticky bar\n          this.#showStickyBar();\n        }\n        // If rect.top >= 0, element is below viewport - don't show sticky bar yet\n      } else if (entry.isIntersecting && this.#isStuck) {\n        this.#hiddenByBottom = false;\n        this.#hideStickyBar();\n      }\n    });\n\n    // Observer for footer visibility - hides sticky bar at page bottom\n    this.#mainBottomObserver = new IntersectionObserver(\n      (entries) => {\n        const [entry] = entries;\n        if (!entry) return;\n\n        if (entry.isIntersecting && this.#isStuck) {\n          this.#hiddenByBottom = true;\n          this.#hideStickyBar();\n        } else if (!entry.isIntersecting && this.#hiddenByBottom) {\n          // Footer out of view - check if we should show sticky bar again\n          const rect = buyButtonsBlock.getBoundingClientRect();\n          // Only show if buy buttons are above the viewport (scrolled past)\n          if (rect.bottom < 0 || rect.top < 0) {\n            this.#hiddenByBottom = false;\n            this.#showStickyBar();\n          }\n        }\n      },\n      {\n        rootMargin: '200px 0px 0px 0px',\n      }\n    );\n\n    this.#buyButtonsIntersectionObserver.observe(buyButtonsBlock);\n    this.#mainBottomObserver.observe(footer);\n    this.#targetAddToCartButton = productForm.querySelector('[ref=\"addToCartButton\"]');\n  }\n\n  // Public action handlers\n  /**\n   * Handles the add to cart button click in the sticky bar\n   */\n  handleAddToCartClick = async () => {\n    if (!this.#targetAddToCartButton) return;\n    this.#targetAddToCartButton.dataset.puppet = 'true';\n    this.#targetAddToCartButton.click();\n    const cartIcon = document.querySelector('.header-actions__cart-icon');\n\n    if (this.refs.addToCartButton.dataset.added !== 'true') {\n      this.refs.addToCartButton.dataset.added = 'true';\n    }\n\n    if (!cartIcon || !this.refs.addToCartButton || !this.refs.productImage) return;\n    if (this.#resetTimeout) clearTimeout(this.#resetTimeout);\n\n    const flyToCartElement = /** @type {FlyToCart} */ (document.createElement('fly-to-cart'));\n    const sourceStyles = getComputedStyle(this.refs.productImage);\n\n    flyToCartElement.classList.add('fly-to-cart--sticky');\n    flyToCartElement.style.setProperty('background-image', `url(${this.refs.productImage.src})`);\n    flyToCartElement.useSourceSize = 'true';\n    flyToCartElement.source = this.refs.productImage;\n    flyToCartElement.destination = cartIcon;\n\n    document.body.appendChild(flyToCartElement);\n\n    await onAnimationEnd([this.refs.addToCartButton, flyToCartElement]);\n    this.#resetTimeout = setTimeout(() => {\n      this.refs.addToCartButton.removeAttribute('data-added');\n    }, 800);\n  };\n\n  /**\n   * Handles variant update events\n   * @param {CustomEvent} event - The variant update event\n   */\n  #handleVariantUpdate = (event) => {\n    if (event.detail.data.productId !== this.dataset.productId) return;\n\n    const variant = event.detail.resource;\n\n    // Get the new sticky add to cart HTML from the server response\n    const newStickyAddToCart = event.detail.data.html.querySelector('sticky-add-to-cart');\n    if (!newStickyAddToCart) return;\n\n    const newStickyBar = newStickyAddToCart.querySelector('[ref=\"stickyBar\"]');\n    if (!newStickyBar) return;\n\n    // Store current visibility state before morphing\n    const currentStuck = this.refs.stickyBar.getAttribute('data-stuck') || 'false';\n    const variantAvailable = newStickyAddToCart.dataset.variantAvailable;\n\n    // Morph the entire sticky bar content\n    morph(this.refs.stickyBar, newStickyBar, { childrenOnly: true });\n\n    // Restore visibility state after morphing\n    this.refs.stickyBar.setAttribute('data-stuck', currentStuck);\n    this.dataset.variantAvailable = variantAvailable;\n\n    // Update the dataset attributes with new variant info\n    if (variant && variant.id) {\n      this.dataset.currentVariantId = variant.id;\n    }\n\n    // Re-cache the target add to cart button after morphing\n    const productForm = this.#getProductForm();\n    if (productForm) {\n      this.#targetAddToCartButton = productForm.querySelector('[ref=\"addToCartButton\"]');\n    }\n\n    if (variant == null) {\n      this.#handleVariantUnavailable();\n    }\n    // Restore the current quantity display if needed\n    this.#updateButtonText();\n  };\n\n  /**\n   * Handles variant selected events\n   * @param {CustomEvent} event - The variant selected event\n   */\n  #handleVariantSelected = (event) => {\n    // The variant update event will follow and handle all updates via morph\n    // We just update the dataset here for tracking\n    const variantId = event.detail.resource?.id;\n    if (!variantId) return;\n    this.dataset.currentVariantId = variantId;\n  };\n\n  /**\n   * Updates the variant title based on selected options when the variant is unavailable\n   */\n  #handleVariantUnavailable = () => {\n    this.dataset.currentVariantId = '';\n    const variantTitleElement = this.querySelector('.sticky-add-to-cart__variant');\n    const productId = this.dataset.productId;\n    const variantPicker = document.querySelector(`variant-picker[data-product-id=\"${productId}\"]`);\n    if (!variantTitleElement || !variantPicker) return;\n\n    const selectedOptions = Array.from(variantPicker.querySelectorAll('input:checked'))\n      .map((option) => /** @type {HTMLInputElement} */ (option).value)\n      .filter((value) => value !== '')\n      .join(' / ');\n    if (!selectedOptions) return;\n    variantTitleElement.textContent = selectedOptions;\n  };\n\n  /**\n   * Handles cart add complete (success or error) - resets puppet flag\n   * @param {CustomEvent} _event - The cart event (unused)\n   */\n  #handleCartAddComplete = (_event) => {\n    // Reset the puppet flag after cart operation\n    if (this.#targetAddToCartButton) {\n      this.#targetAddToCartButton.dataset.puppet = 'false';\n    }\n  };\n\n  /**\n   * Handles quantity selector update events\n   * @param {QuantitySelectorUpdateEvent} event - The quantity update event\n   */\n  #handleQuantityUpdate = (event) => {\n    // Only respond to product page quantity selector updates, not cart drawer\n    if (event.detail.cartLine) return;\n\n    this.#currentQuantity = event.detail.quantity;\n    this.#updateButtonText();\n  };\n\n  /**\n   * Shows the sticky bar with animation\n   */\n  #showStickyBar() {\n    const { stickyBar } = this.refs;\n    this.#isStuck = true;\n    stickyBar.dataset.stuck = 'true';\n  }\n\n  /**\n   * Hides the sticky bar with animation\n   */\n  #hideStickyBar() {\n    const { stickyBar } = this.refs;\n    this.#isStuck = false;\n    stickyBar.dataset.stuck = 'false';\n  }\n\n  // Helper methods\n  /**\n   * Gets the product form element\n   * @returns {HTMLElement | null}\n   */\n  #getProductForm() {\n    const productId = this.dataset.productId;\n    if (!productId) return null;\n\n    const sectionElement = this.closest('.shopify-section');\n    if (!sectionElement) return null;\n\n    const sectionId = sectionElement.id.replace('shopify-section-', '');\n    return document.querySelector(\n      `#shopify-section-${sectionId} product-form-component[data-product-id=\"${productId}\"]`\n    );\n  }\n\n  /**\n   * Gets the initial quantity from the data attribute\n   */\n  #getInitialQuantity() {\n    this.#currentQuantity = parseInt(this.dataset.initialQuantity || '1') || 1;\n    this.#updateButtonText();\n  }\n\n  /**\n   * Updates the button text to include quantity\n   */\n  #updateButtonText() {\n    const { addToCartButton, quantityDisplay, quantityNumber } = this.refs;\n\n    const available = !addToCartButton.disabled;\n\n    // Update the quantity number\n    quantityNumber.textContent = this.#currentQuantity.toString();\n\n    // Show/hide the quantity display based on availability and quantity\n    if (available && this.#currentQuantity > 1) {\n      quantityDisplay.style.display = 'inline';\n    } else {\n      quantityDisplay.style.display = 'none';\n    }\n  }\n}\n\nif (!customElements.get('sticky-add-to-cart')) {\n  customElements.define('sticky-add-to-cart', StickyAddToCartComponent);\n}\n"],
  "mappings": "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",
  "names": []
}
