{
  "version": 3,
  "sources": ["/cdn/shop/t/3/assets/component-quantity-selector.js?poc=d0ug"],
  "sourcesContent": ["import { Component } from '@theme/component';\nimport { QuantitySelectorUpdateEvent } from '@theme/events';\n\n/**\n * A custom element that allows the user to select a quantity.\n *\n * @typedef {Object} Refs\n * @property {HTMLInputElement} quantityInput\n * @property {HTMLButtonElement} minusButton\n * @property {HTMLButtonElement} plusButton\n *\n * @extends {Component<Refs>}\n */\nexport class QuantitySelectorComponent extends Component {\n  requiredRefs = ['quantityInput', 'minusButton', 'plusButton'];\n  serverDisabledMinus = false;\n  serverDisabledPlus = false;\n  initialized = false;\n\n  connectedCallback() {\n    super.connectedCallback();\n\n    // Capture server-disabled state on first load\n    const { minusButton, plusButton } = this.refs;\n\n    if (minusButton.disabled) {\n      this.serverDisabledMinus = true;\n    }\n    if (plusButton.disabled) {\n      this.serverDisabledPlus = true;\n    }\n\n    this.initialized = true;\n    this.updateButtonStates();\n  }\n\n  disconnectedCallback() {\n    super.disconnectedCallback();\n  }\n\n  /**\n   * Updates cart quantity and refreshes component state\n   * @param {number} cartQty - The quantity currently in cart for this variant\n   */\n  setCartQuantity(cartQty) {\n    this.refs.quantityInput.setAttribute('data-cart-quantity', cartQty.toString());\n    this.updateCartQuantity();\n  }\n\n  /**\n   * Checks if the current quantity can be added to cart without exceeding max\n   * @returns {{canAdd: boolean, maxQuantity: number|null, cartQuantity: number, quantityToAdd: number}} Validation result\n   */\n  canAddToCart() {\n    const { max, cartQuantity, value } = this.getCurrentValues();\n    const quantityToAdd = value;\n    const wouldExceedMax = max !== null && cartQuantity + quantityToAdd > max;\n\n    return {\n      canAdd: !wouldExceedMax,\n      maxQuantity: max,\n      cartQuantity,\n      quantityToAdd,\n    };\n  }\n\n  /**\n   * Gets the current quantity value\n   * @returns {string} The current value\n   */\n  getValue() {\n    return this.refs.quantityInput.value;\n  }\n\n  /**\n   * Sets the current quantity value\n   * @param {string} value - The value to set\n   */\n  setValue(value) {\n    this.refs.quantityInput.value = value;\n  }\n\n  /**\n   * Updates min/max/step constraints and snaps value to valid increment\n   * @param {string} min - Minimum value\n   * @param {string|null} max - Maximum value (null if no max)\n   * @param {string} step - Step increment\n   */\n  updateConstraints(min, max, step) {\n    const { quantityInput } = this.refs;\n    const currentValue = parseInt(quantityInput.value) || 0;\n\n    quantityInput.min = min;\n    if (max) {\n      quantityInput.max = max;\n    } else {\n      quantityInput.removeAttribute('max');\n    }\n    quantityInput.step = step;\n\n    const newMin = parseInt(min) || 1;\n    const newStep = parseInt(step) || 1;\n    const effectiveMax = this.getEffectiveMax();\n\n    // Snap to valid increment if not already aligned\n    let newValue = currentValue;\n    if ((currentValue - newMin) % newStep !== 0) {\n      // Snap DOWN to closest valid increment\n      newValue = newMin + Math.floor((currentValue - newMin) / newStep) * newStep;\n    }\n\n    // Ensure value is within bounds\n    newValue = Math.max(newMin, Math.min(effectiveMax ?? Infinity, newValue));\n\n    if (newValue !== currentValue) {\n      quantityInput.value = newValue.toString();\n    }\n\n    this.updateButtonStates();\n  }\n\n  /**\n   * Gets current values from DOM (fresh read every time)\n   * @returns {{min: number, max: number|null, step: number, value: number, cartQuantity: number}}\n   */\n  getCurrentValues() {\n    const { quantityInput } = this.refs;\n    return {\n      min: parseInt(quantityInput.min) || 1,\n      max: quantityInput.max ? parseInt(quantityInput.max) : null,\n      step: parseInt(quantityInput.step) || 1,\n      value: parseInt(quantityInput.value) || 0,\n      cartQuantity: parseInt(quantityInput.getAttribute('data-cart-quantity') || '0'),\n    };\n  }\n\n  /**\n   * Gets the effective maximum value for this quantity selector\n   * Product page: max - cartQuantity (how many can be added)\n   * Override in subclass for different behavior\n   * @returns {number | null} The effective max, or null if no max\n   */\n  getEffectiveMax() {\n    const { max, cartQuantity, min } = this.getCurrentValues();\n    if (max === null) return null;\n    // Product page: can only add what's left\n    return Math.max(max - cartQuantity, min);\n  }\n\n  /**\n   * Updates button states based on current value and limits\n   */\n  updateButtonStates() {\n    const { minusButton, plusButton } = this.refs;\n    const { min, value } = this.getCurrentValues();\n    const effectiveMax = this.getEffectiveMax();\n\n    // Only manage buttons that weren't server-disabled\n    if (!this.serverDisabledMinus) {\n      minusButton.disabled = value <= min;\n    }\n\n    if (!this.serverDisabledPlus) {\n      plusButton.disabled = effectiveMax !== null && value >= effectiveMax;\n    }\n  }\n\n  /**\n   * Updates quantity by a given step\n   * @param {number} stepMultiplier - Positive for increase, negative for decrease\n   */\n  updateQuantity(stepMultiplier) {\n    const { quantityInput } = this.refs;\n    const { min, step, value } = this.getCurrentValues();\n    const effectiveMax = this.getEffectiveMax();\n\n    const newValue = Math.min(\n      effectiveMax ?? Infinity,\n      Math.max(min, value + step * stepMultiplier)\n    );\n\n    quantityInput.value = newValue.toString();\n    this.onQuantityChange();\n    this.updateButtonStates();\n  }\n\n  /**\n   * Handles the quantity increase event.\n   * @param {Event} event - The event.\n   */\n  increaseQuantity(event) {\n    if (!(event.target instanceof HTMLElement)) return;\n    event.preventDefault();\n    this.updateQuantity(1);\n  }\n\n  /**\n   * Handles the quantity decrease event.\n   * @param {Event} event - The event.\n   */\n  decreaseQuantity(event) {\n    if (!(event.target instanceof HTMLElement)) return;\n    event.preventDefault();\n    this.updateQuantity(-1);\n  }\n\n  /**\n   * When our input gets focused, we want to fully select the value.\n   * @param {FocusEvent} event\n   */\n  selectInputValue(event) {\n    const { quantityInput } = this.refs;\n    if (!(event.target instanceof HTMLInputElement) || document.activeElement !== quantityInput) return;\n\n    quantityInput.select();\n  }\n\n  /**\n   * Handles the quantity set event (on blur).\n   * Validates and snaps to valid values.\n   * @param {Event} event - The event.\n   */\n  setQuantity(event) {\n    if (!(event.target instanceof HTMLInputElement)) return;\n\n    event.preventDefault();\n    const { quantityInput } = this.refs;\n    const { min, step } = this.getCurrentValues();\n    const effectiveMax = this.getEffectiveMax();\n\n    // Snap to bounds\n    const quantity = Math.min(\n      effectiveMax ?? Infinity,\n      Math.max(min, parseInt(event.target.value) || 0)\n    );\n\n    // Validate step increment\n    if ((quantity - min) % step !== 0) {\n      // Set the invalid value and trigger native HTML validation\n      quantityInput.value = quantity.toString();\n      quantityInput.reportValidity();\n      return;\n    }\n\n    quantityInput.value = quantity.toString();\n    this.onQuantityChange();\n    this.updateButtonStates();\n  }\n\n  /**\n   * Handles the quantity change event.\n   */\n  onQuantityChange() {\n    const { quantityInput } = this.refs;\n    const newValue = parseInt(quantityInput.value);\n\n    quantityInput.dispatchEvent(new QuantitySelectorUpdateEvent(newValue, Number(quantityInput.dataset.cartLine)));\n  }\n\n  /**\n   * Updates the cart quantity from data attribute and refreshes button states\n   * Called when cart is updated from external sources\n   */\n  updateCartQuantity() {\n    const { quantityInput } = this.refs;\n    const { min, value } = this.getCurrentValues();\n    const effectiveMax = this.getEffectiveMax();\n\n    // Clamp value to new effective max if necessary\n    const clampedValue = Math.min(\n      effectiveMax ?? Infinity,\n      Math.max(min, value)\n    );\n\n    if (clampedValue !== value) {\n      quantityInput.value = clampedValue.toString();\n    }\n\n    this.updateButtonStates();\n  }\n\n  /**\n   * Gets the quantity input.\n   * @returns {HTMLInputElement} The quantity input.\n   */\n  get quantityInput() {\n    if (!this.refs.quantityInput) {\n      throw new Error('Missing <input ref=\"quantityInput\" /> inside <quantity-selector-component />');\n    }\n\n    return this.refs.quantityInput;\n  }\n}\n\nif (!customElements.get('quantity-selector-component')) {\n  customElements.define('quantity-selector-component', QuantitySelectorComponent);\n}\n"],
  "mappings": "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",
  "names": []
}
