{"version":3,"file":"add-to-cart-elements-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"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","sources":["webpack://lange/./scripts/sections/add-to-cart-elements/add-to-cart-product/index.ts","webpack://lange/./scripts/sections/add-to-cart-elements/bundle-option/index.ts","webpack://lange/./scripts/sections/add-to-cart-elements/bundle-variant/index.ts","webpack://lange/webpack/bootstrap","webpack://lange/../node_modules/@integrabeauty/shopify-ajax-api/src/cart.ts","webpack://lange/./scripts/lib/call-utils.ts","webpack://lange/./scripts/common/liquid-global.ts","webpack://lange/./scripts/sections/modal-cart/cart-service/add-to-cart.ts","webpack://lange/./scripts/sections/modal-cart/update-cart-html.ts","webpack://lange/./scripts/sections/add-to-cart-elements/add-to-cart/index.ts","webpack://lange/./scripts/sections/add-to-cart-elements/notify-me-button/index.ts"],"sourcesContent":["/**\n * This is a placeholder element that carries data properties, needed for add to cart functionality\n * It has no functionality.\n */\nclass AddToCartProduct extends HTMLElement {\n  declare readonly dataset: {\n    /**\n     * Boolean represented as string representing product availability\n     */\n    available: 'false' | 'true';\n\n    /**\n     * Product ID, a stringified integer\n     */\n    id: string;\n\n    /**\n     * Product title\n     */\n    productTitle: string;\n\n    /**\n     * Selected variant ID, a stringified integer\n     */\n    selectedVariantId: string;\n\n    /**\n     * Selected variant title\n     */\n    selectedVariantTitle: string;\n  };\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'add-to-cart-product': AddToCartProduct;\n  }\n}\n\nif (!customElements.get('add-to-cart-product')) {\n  customElements.define('add-to-cart-product', AddToCartProduct);\n}\n","/**\n * This is a placeholder element that carries data properties, it has no functionality.\n */\nclass BundleOption extends HTMLElement {\n  declare readonly dataset: {\n    /**\n     * The name associated automatically when creating a bundle via the Shopify Bundle App. The name\n     * is a combination of the product title and option group name in parentheses to ensure\n     * uniqueness among multiple bundle options with the same option group name.\n     *\n     * @example \"ELATION (Shade)\"\n     */\n    name: string;\n\n    /**\n     * The position of the bundle option in the product's options array.\n     */\n    position: string;\n\n    /**\n     * The currently selected option value for this bundle option\n     */\n    selected: string;\n  };\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'bundle-option': BundleOption;\n  }\n}\n\nif (!customElements.get('bundle-option')) {\n  customElements.define('bundle-option', BundleOption);\n}\n","/**\n * This is a placeholder element that carries data properties for a bundle product variant, only\n * fields that are necessary for the add-to-cart functionality. It is used in the context of bundle\n * products. It has no functionality.\n */\nclass BundleVariant extends HTMLElement {\n  declare readonly dataset: {\n    /**\n     * Whether the bundle variant is available for purchase\n     */\n    available: 'false' | 'true';\n\n    /**\n     * Bundle variant ID, a stringified integer\n     */\n    id: string;\n\n    /**\n     * The variant title, a combination of all component option values joined by \" / \". It's\n     * generated by Shopify.\n     *\n     * @example \"Red / Small\"\n     */\n    title: string;\n  };\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'bundle-variant': BundleVariant;\n  }\n}\n\nif (!customElements.get('bundle-variant')) {\n  customElements.define('bundle-variant', BundleVariant);\n}\n","// The module cache\nlet __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tlet cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tlet module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import * as _ShopifyBrowserTypes from '@integrabeauty/shopify-browser-types';\n\n/**\n * Represents the value of a cart attribute. Ordinarily values are strings. However, Shopify also\n * supports storing nested objects as values.\n */\nexport type AttributeValue = Record<string, string> | string;\n\n/**\n * The type of the value of `Cart['attributes']`\n */\nexport type Attributes = Record<string, AttributeValue>;\n\n/**\n * @todo selling plan properties\n * @todo endpoint request body response body types\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart\n */\nexport interface Cart {\n  /**\n   * An object where the key is the attribute name and the value is the attribute value.\n   */\n  attributes: Attributes;\n\n  /**\n   * A discount application represents a type of discount.\n   *\n   * When a discount is applied to one or more line items, it is said to be _allocated_ to the line\n   * items. That is why line level discount allocation objects have a nested application object that\n   * will correlate with one of the applications in this array.\n   *\n   * When a discount is applied to the whole cart, it will only be present in this array because it\n   * is not allocated to particular lines.\n   */\n  cart_level_discount_applications: DiscountApplication[];\n\n  /**\n   * The ISO currency code for the cart.\n   *\n   * @example \"USD\"\n   */\n  currency: string;\n\n  /**\n   * Discount codes that have been applied to the cart.\n   *\n   * Not all codes are applicable. It is possible for a code to be applied but inapplicable.\n   *\n   * This does not provide information about the amount of each discount. Refer to the cart level\n   * discount applications or line level discount allocations for that information.\n   *\n   * This array will include shipping discounts. A shipping discount will be present in the array if\n   * applied but in the inapplicable state while in the cart. The discount will appear as applicable\n   * at checkout automatically.\n   */\n  discount_codes: DiscountCode[];\n\n  /**\n   * Total quantity of items in a cart\n   */\n  item_count: number;\n\n  /**\n   * The cart's line items.\n   *\n   * A cart will always have a defined items array, even if the cart is empty.\n   */\n  items: Item[];\n\n  items_subtotal_price: number;\n\n  /**\n   * An optional textual note that may be applied to the cart. If a cart becomes a checkout, and\n   * then the checkout becomes an order, the cart note will carry over to the order note.\n   *\n   * An order's note, and an order's note attributes, are two completely separate concepts.\n   */\n  note: string;\n\n  original_total_price: number;\n\n  /**\n   * This is true when at least one item in the cart requires shipping.\n   *\n   * This is false when no items in the cart require shipping.\n   *\n   * Shopify supports digital-only carts. These are carts that when purchased do not require the\n   * creation of a fulfillment. For example, a cart that consists only of a digital gift card.\n   */\n  requires_shipping: boolean;\n\n  /**\n   * This property is defined when there are cart mutations that involve the use of liquid-rendered\n   * sections.\n   *\n   * @see https://shopify.dev/docs/api/ajax/reference/cart#request-sections\n   */\n  sections: Record<string, string>;\n\n  /**\n   * This is the publicly visible cart id.\n   *\n   * If a checkout is created from this cart, the checkout's cart token will be equal to this value.\n   *\n   * Never write logic that parses this value. The format can change at any time, and has changed\n   * several times in the past.\n   *\n   * The value may contain url-like values, e.g. \"abc?key=123\"\n   */\n  token: string;\n\n  /**\n   * The total reduction in price in currency subunits (e.g. in cents for USD).\n   *\n   * @example 5010\n   */\n  total_discount: number;\n\n  /**\n   * Total price in currency subunits. For example, if the currency is USD, this is in cents.\n   *\n   * @example 1050\n   */\n  total_price: number;\n\n  /**\n   * The total weight of the cart (in grams?). This is a simple sum of the weight of the items of\n   * the cart (unit weight * quantity).\n   *\n   * @example 123.456\n   */\n  total_weight: number;\n}\n\n/**\n * Represents a discount that has been applied to an item.\n */\nexport interface Discount {\n  amount: number;\n  title: string;\n}\n\n/**\n * Represents a discount application that has been allocated to a line item.\n */\nexport interface DiscountAllocation {\n  /**\n   * The amount of the application that was allocated to a particular line item.\n   *\n   * When a discount application is allocated to several line items, this is a partial value of the\n   * full discount application amount that is allocated to this particular line. When the discount\n   * application is only allocated to a single line, this value will be equal to the total value of\n   * the discount application.\n   *\n   * For example, let's say we have cart with 2 line items and 10 dollar off discount application.\n   * The total value of the discount application is 10 dollars. Let's say the discount is allocated\n   * to both lines. The value of each allocation is 5 dollars. For each line this amount will\n   * contain the value 500. Within the nested application object, the application's total amount\n   * will be 1000. This is because each nested application object is a copy of the one application\n   * that happens to have multiple allocations (the discount is applied to multiple lines).\n   *\n   * The amount is in currency subunits. For example, for USD, this is the value of cents. For\n   * example, a discount of $2.50 is 250.\n   *\n   * @example 1050\n   */\n  amount: number;\n\n  /**\n   * The corresponding discount application that was allocated to a particular line item.\n   */\n  discount_application: DiscountApplication;\n}\n\n/**\n * A discount application represents a discount of some kind. There are automatically applied\n * discount applications, discount code applications, and script applied discount applications.\n */\nexport interface DiscountApplication {\n  allocation_method: string;\n  created_at: string;\n  description: string;\n  key: string;\n  target_selection: string;\n  target_type: string;\n  title: string;\n  total_allocated_amount: number;\n  type: string;\n  value: string;\n  value_type: string;\n}\n\n/**\n * The details of an image resource, such as the hero image for a product.\n */\nexport interface Image {\n  alt: string;\n  aspect_ratio: number;\n  height: number;\n  url: string;\n  width: number;\n}\n\n/**\n * Represents a line item in a cart.\n */\nexport interface Item {\n  /**\n   * The price of the line item after discounts\n   */\n  discounted_price: number;\n\n  /**\n   * Discount codes applied to the line item.\n   *\n   * @deprecated\n   */\n  discounts: Discount[];\n\n  /**\n   * The main image for the product\n   */\n  featured_image: Image;\n\n  /**\n   * The combined price, in the currency's subunit, of all of the items in the line item. This\n   * includes any line-level discounts.\n   *\n   * The value is equal to line_item.final_price multiplied by line_item.quantity. It's output in\n   * the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  final_line_price: number;\n\n  /**\n   * The price of the line item in the currency's subunit. This includes any line-level discounts.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  final_price: number;\n\n  /**\n   * Returns true if the product associated with the line item is a gift card. Returns false if not.\n   */\n  gift_card: boolean;\n\n  /**\n   * The weight of the line item in the store's default weight unit.\n   */\n  grams: number;\n\n  handle: string;\n\n  has_components: boolean;\n\n  /**\n   * The ID of the line item. The ID differs depending on the context. The following table outlines\n   * the possible contexts and their associated values:\n   *\n   * Context Value\n   *\n   * * cart.items The ID of the line item's variant. This ID isn't unique, and can be shared by\n   *   multiple items with the same variant.\n   * * checkout.line_items A temporary unique hash generated for the checkout.\n   * * order.line_items A unique integer ID.\n   */\n  id: number;\n\n  image: string;\n\n  /**\n   * Added in conjunction with parent_relationship to support determining whether a line item can be\n   * removed or have its quantity updated when the line item is a child of another line item, e.g.\n   * part of a bundle or value set or promotional gift.\n   */\n  instructions: {\n    can_remove: boolean;\n    can_update_quantity: boolean;\n  };\n\n  key: string;\n\n  /**\n   * The discount allocations that apply to the line item.\n   */\n  line_level_discount_allocations: DiscountAllocation[];\n\n  /**\n   * The total amount of any discounts applied to the line item in the currency's subunit.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  line_level_total_discount: number;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  line_price: number;\n\n  /**\n   * The name and value pairs for each option of the variant associated with the line item.\n   *\n   * The array is never empty because variants with no options still have a default option. Because\n   * of this, you should use line_item.product.has_only_default_variant to check whether there's any\n   * information to output.\n   */\n  options_with_values: Option[];\n\n  /**\n   * The combined price of all of the items in a line item in the currency's subunit, before any\n   * discounts have been applied.\n   *\n   * The value is equal to line_item.original_price multiplied by line_item.quantity. It's output in\n   * the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  original_line_price: number;\n\n  /**\n   * The price of the line item in the currency's subunit, before discounts have been applied.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  original_price: number;\n\n  /**\n   * The parent relationship of the line item. This is only present if the line item is a child of\n   * another line item. For example, when the line item is part of a bundle or value set or\n   * promotional gift.\n   *\n   * The parent relationship must be established by adding the \"parent_id\" property to the add to\n   * bag request.\n   *\n   * @see https://shopify.dev/docs/apps/build/product-merchandising/nested-cart-lines/create-nested-cart-lines#cart-ajax-api\n   */\n  parent_relationship: {\n    parent_key: string;\n  };\n\n  presentment_price: number;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  price: number;\n\n  product_description: string;\n\n  product_has_only_default_variant: boolean;\n\n  /**\n   * The ID of the line item's product.\n   */\n  product_id: number;\n\n  product_title: string;\n\n  product_type: string;\n\n  properties: Record<string, string>;\n  quantity: number;\n\n  quantity_rule: QuantityRule;\n\n  requires_shipping: boolean;\n\n  /**\n   * The selling plan allocation of the line item.\n   */\n  selling_plan_allocation: SellingPlanAllocation;\n\n  /**\n   * The SKU of the variant in the line item.\n   *\n   * Stock Keeping Unit.\n   */\n  sku: string;\n\n  successfully_fulfilled_quantity: number;\n\n  taxable: boolean;\n\n  /**\n   * The title of the line item. The title is a combination of line_item.product.title and\n   * line_item.variant.title, separated by a hyphen.\n   *\n   * In most contexts, the line item title appears in the customer's preferred language. However, in\n   * the context of an order, the line item title appears in the language that the customer checked\n   * out in. The title can receive an override value from the Cart Transform API. Overrides take\n   * precedence over translations.\n   *\n   * #### Line item title history\n   *\n   * When referencing line item, product, and variant titles in the context of an order, the\n   * following changes might result in a different output than you expect:\n   * * A product or variant being deleted\n   * * A product or variant title being edited\n   *\n   * When line_item.title is referenced for an order, the line item title at the time of the order\n   * is returned. However, when line_item.product.title and line_item.variant.title are referenced,\n   * the current value for each title is returned.\n   */\n  title: string;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  total_discount: number;\n\n  unit_price_measurement: {\n    measured_type: string;\n    quantity_unit: string;\n    quantity_value: string;\n    reference_unit: string;\n    reference_value: number;\n  };\n\n  untranslated_produce_title: string;\n\n  untranslated_variant_title: string;\n\n  /**\n   * The relative URL of the variant associated with the line item.\n   */\n  url: string;\n\n  /**\n   * The ID of the line item's variant.\n   */\n  variant_id: number;\n\n  variant_options: string[];\n\n  variant_title: string;\n\n  /**\n   * The vendor of the variant associated with the line item.\n   */\n  vendor: string;\n}\n\nexport interface SellingPlanAllocation {\n  compare_at_price: number;\n\n  per_delivery_price: number;\n\n  /**\n   * @example 900\n   */\n  price: number;\n\n  price_adjustments: SellingPlanAllocationPriceAdjustment[];\n  selling_plan: SellingPlan;\n}\n\nexport interface SellingPlanAllocationPriceAdjustment {\n  /**\n   * @example 1\n   */\n  position: number;\n\n  /**\n   * @example 900\n   */\n  price: number;\n}\n\nexport interface SellingPlan {\n  description: unknown;\n\n  fixed_selling_plan: boolean;\n\n  id: number;\n  name: string;\n\n  options: SellingPlanOption[];\n\n  price_adjustments: SellingPlanPriceAdjustment[];\n\n  recurring_deliveries: boolean;\n}\n\nexport interface SellingPlanOption {\n  name: string;\n  position: number;\n  value: string;\n}\n\nexport interface SellingPlanPriceAdjustment {\n  order_count: unknown;\n  position: number;\n  value: number;\n  value_type: string;\n}\n\nexport interface Option {\n  name: string;\n  value: string;\n}\n\nexport interface QuantityRule {\n  increment: number;\n  max: number;\n  min: number;\n}\n\nexport interface DiscountCode {\n  /**\n   * Whether the discount is currently applicable. It is possible to apply a discount code to a cart\n   * but have it not yet be applicable. When not applicable, there will not be any associated\n   * discount applications or allocations. The moment someone performs an action that makes the\n   * discount code applicable, Shopify will update the property to true.\n   */\n  applicable: boolean;\n\n  /**\n   * The discount code string.\n   *\n   * This is NOT guaranteed to be uppercase. Discount codes entered at checkout are captured in\n   * whatever case was used during input.\n   *\n   * @example \"MONEY1234\"\n   * @example \"Abc123def\"\n   */\n  code: string;\n}\n\n/**\n * Returns the request id header from the ajax cart api response. Capturing this value is important\n * when helping Shopify support investigate issues.\n *\n * This does not error. If there is a problem, this returns null or undefined.\n */\nfunction getRequestId(response: Response) {\n  try {\n    return response.headers.get('X-Request-Id');\n  } catch (error) {\n    // ignore\n  }\n}\n\n/**\n * Returns whether the given value is shaped like a fetch Response.\n *\n * The return type of fetch is a contract, not a verified fact. A third party that overrides the\n * global fetch can resolve it to null, undefined, or some unrelated value, in which case the very\n * next property access throws an opaque error with no indication that a bad override was the cause.\n * This checks structurally for the members this module reads rather than with an instanceof, so a\n * conforming fetch polyfill that returns its own Response class still passes while a missing or\n * malformed value is trapped at the point it is received.\n *\n * This type check does not technically prove that the value is a genuine Response object, only that\n * it has the expected shape. We are intentionally lying with types here, so that we can leverage\n * the type inference to support the subset of use cases this module actually relies on. More over,\n * this lying is ok, as the call to `response = await fetch` is also lying because it overly trusts\n * that fetch returns value of type Response. We are going to keep trying to \"make fetch happen\"\n * regardless.\n *\n *\n * ## War Story\n *\n * As much as it seems like this is an insane and irrationally paranoid check, you would be\n * surprised. For example, in the wild, we observed a third party vendor that hooked global fetch,\n * had an error in their hook, and simultaneously, another vendor's third party polyfill that only\n * defined fetch without also defining Response, leading to even more obscure cases when older\n * browsers were involved. Then, to make matters worse, a fix was implemented leveraging the clean\n * global fetch using an iframe content window hack to work around the inability to cleanly capture\n * the native fetch before it was erroneously hooked, and this broke certain expressions that use\n * instanceof because instanceof has unintuitive behavior when checking instanceof of a value from a\n * different global context, e.g. from an iframe. A web of lies!\n */\nfunction isResponse(value: any): value is Response {\n  if (value === null || typeof value !== 'object') {\n    return false;\n  }\n\n  if (typeof value.ok !== 'boolean') {\n    return false;\n  }\n\n  if (typeof value.status !== 'number') {\n    return false;\n  }\n\n  if (typeof value.json !== 'function') {\n    return false;\n  }\n\n  return true;\n}\n\n/**\n * Attaches a single piece of context onto an error before it is thrown.\n *\n * The target may be a value caught upstream rather than one constructed here, and such a value can\n * carry a non-writable property, such as a DOMException whose code is a read-only accessor, or be\n * frozen outright, in which case assigning to it throws. Decorating an error must never itself\n * fail, so a rejected assignment is swallowed. This context is best effort metadata, so the\n * property is skipped when it cannot be set, leaving the error otherwise intact to be thrown and\n * handled by the caller.\n */\nfunction decorateError(error: any, key: string, value: unknown) {\n  try {\n    error[key] = value;\n  } catch (error) {\n    // The target rejects this property. Skip it rather than letting decoration fail.\n  }\n}\n\n/**\n * An item to add to the cart\n */\nexport interface AddItem {\n  /**\n   * Variant id\n   *\n   * Shopify says that it supports variant ids as numbers, but we have witnessed strange errors when\n   * using numbers so we impose an artificial limitation on the type here and require strings.\n   */\n  id: string;\n\n  /**\n   * The id of the line item to add the item as a child of. This is used for adding items as\n   * children of value sets and bundles. If not specified, the item is added as a top level line\n   * item.\n   *\n   * @see https://shopify.dev/docs/apps/build/product-merchandising/nested-cart-lines/create-nested-cart-lines#cart-ajax-api\n   */\n  parent_id?: number | string;\n\n  /**\n   * Line item properties to include.\n   *\n   * If the variant does not already exist in the cart, then the logic is straightforward. This will\n   * result in a new line item with these properties.\n   *\n   * If the variant exists in the cart, then the logic is convoluted. If the specified properties\n   * are identical to the existing properties, then the quantity of the existing line item\n   * increments. If the specified properties are different, then a new line item is created with\n   * these properties, resulting in the same variant being present in multiple line items.\n   */\n  properties?: Attributes;\n\n  /**\n   * The amount of the variant to add.\n   *\n   * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js\n   */\n  quantity: number;\n\n  selling_plan?: number | string;\n}\n\n/**\n * Adds items to the cart. At least one item should be specified.\n *\n * This does not fetch the response body. The raw response body does not contain the full cart\n * state. The raw response body may not be the latest state of cart items. The raw response body may\n * contain zero-quantity items still present after prior removal.\n *\n * This validates the response status. If the status is not ok this throws an error.\n *\n * This specifies fetch mode no-store so that the call is not unintentionally cached.\n *\n * Adding an item the cart does not necessarily mean a new line item is created. For each item in\n * the input, Shopify makes a server side determination of whether to update the quantity of an\n * existing line item or add a new line item. The factors in that decision are related to how a line\n * item key is determined, which is poorly documented. Basically, if an item has some different\n * properties, e.g. line item properties, or pricing, then the item will always be added as a new\n * line item, even though the variant id is the same as an existing line item.\n *\n * The line item scripts run on every mutation. The scripts will remove any orphaned value set line\n * items implicitly. Keep this in mind when debugging.\n *\n * The content type header must be specified in the request or Shopify interprets the request as a\n * form submission, which we are not doing here, which leads to an error.\n *\n * Shopify's injected front end code (e.g. Trekkie, Monorail) triggers a console warning when it\n * detects that the number of items requested to be added is less than the number that was added.\n * This is not necessarily an error. It can indicate that the line item scripts removed one or more\n * line items during the add mutation.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js\n * @see https://help.shopify.com/en/manual/checkout-settings/script-editor/shopify-scripts\n */\nexport async function cartAdd(items: AddItem[]) {\n  const response = await fetch(Shopify.routes.root + 'cart/add.js', {\n    body: JSON.stringify({ items }),\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    cache: 'no-store',\n    method: 'POST'\n  });\n\n  if (!isResponse(response)) {\n    const error: any = new Error('fetch did not return a response adding to cart');\n    decorateError(error, 'items', items);\n    decorateError(error, 'response', response);\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} adding to cart`);\n    decorateError(error, 'items', items);\n    decorateError(error, 'request_id', getRequestId(response));\n\n    decorateError(error, 'response_status', response.status);\n\n    try {\n      const responseBody = await response.json();\n      decorateError(error, 'response_body', responseBody);\n    } catch (error) {\n      // ignore\n    }\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // On some 422 responses a more specific description is present alongside the generic message,\n    // so prefer the description, fall back to the generic message, and otherwise leave the default\n    // received-status message in place. For example, adding a bundle whose component is unavailable\n    // yields a body like the following, where description is meaningful and message is generic:\n    //\n    // { \"description\": \"The bundle product 'Product Title' cannot be added to the cart.\",\n    // \"message\": \"Cart Error\", \"status\": 422 }\n    //\n    // The status property of the response body mirrors the HTTP status code (empirical).\n\n    let message;\n    if (response.status === 422 && typeof error.response_body?.description === 'string') {\n      message = error.response_body.description;\n    } else if (typeof error.response_body?.message === 'string') {\n      message = error.response_body.message;\n    }\n\n    if (message) {\n      decorateError(error, 'message', message);\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Either id or line must be specified.\n */\nexport interface CartChangeInput {\n  /**\n   * Can be either the variant id or the line item key.\n   */\n  id?: number | string;\n\n  /**\n   * A cart can have multiple line items that share the same variant_id. For example, when variants\n   * have different line item properties, or automatic discounts create variants at different\n   * prices. To account for this, you can use the line property when updating the cart.\n   *\n   * The value of line is the 1-based index position of the item in the cart.\n   */\n  line?: number;\n\n  /**\n   * The properties property sets the line item properties. Its value must be an object of key-value\n   * pairs.\n   *\n   * Whenever a POST request includes properties, it overwrites the entire properties object. Any\n   * key-value pairs that were already in the properties object are erased.\n   *\n   * It's not possible to set a line item's properties property to an empty object once a value is\n   * set. If you need to remove all line item properties, then you need to remove the entire line\n   * item.\n   *\n   * You can visually hide line item properties at checkout by creating private properties. This\n   * technique might be an alternative to removing a line item when managing properties.\n   */\n  properties?: Record<string, any>;\n\n  /**\n   * The value of the quantity property represents the new quantity you want for the line item. It\n   * must be an integer.\n   *\n   * You can remove a line item by setting the quantity to 0.\n   *\n   * It is not clear from the documentation, but based on the description of the selling plan\n   * property, it looks like quantity is actually optional and defaults to 1 when not specified.\n   */\n  quantity?: number;\n\n  /**\n   * The selling_plan property sets the line item selling plan. Its value must be one of the\n   * following:\n   *\n   * * The selling plan ID: To set a specific selling plan for the line item.\n   * * null or an empty string: To remove any selling plan from the line item.\n   *\n   * When specifying the selling_plan property, consider the following:\n   * * You can use only the line property for identifying the line item.\n   * * You should always specify the quantity property. If the quantity isn't specified, then it's\n   *   assumed to be 1.\n   */\n  selling_plan?: number;\n}\n\n/**\n * Use the /{locale}/cart/change.js endpoint to change the quantity, properties, and selling_plan\n * properties of a cart line item. Only items already in your cart can be changed, and you can\n * change only one line item at a time.\n *\n * The POST data requires either an id or line property to identify the line item to be changed.\n *\n * The value of the id property can be one of the following:\n *\n * * The line item's variant_id\n * * The line item's key\n *\n * A cart can have multiple line items that share the same variant_id. For example, when variants\n * have different line item properties, or automatic discounts create variants at different prices.\n * Because of this, it's recommended to use the line item key to ensure that you're only changing\n * the intended line item.\n *\n * If the item that you're attempting to change isn't already in the cart, then\n * /{locale}/cart/change.js doesn't add it. Instead, it returns a 404 error.\n *\n * The documentation states that the response body is the JSON of the cart. This exposes the\n * response object but does not fetch the response body.\n *\n * ### Removing out of stock items\n * It is unclear but based on a conversation with Shopify support, prefer to use cart/change instead\n * of cart/update to avoid issues with removing an out of stock item from the cart. Using update\n * results in a 422 error but supposedly cart/change does not.\n */\nexport async function cartChange(input: CartChangeInput) {\n  const response = await fetch(Shopify.routes.root + 'cart/change.js', {\n    body: JSON.stringify(input),\n    cache: 'no-store',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    method: 'POST'\n  });\n\n  if (!isResponse(response)) {\n    const error: any = new Error('fetch did not return a response changing cart');\n    decorateError(error, 'request_body', input);\n    decorateError(error, 'response', response);\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} changing cart`);\n    decorateError(error, 'request_body', input);\n    decorateError(error, 'request_id', getRequestId(response));\n\n    try {\n      decorateError(error, 'response_body', await response.json());\n    } catch (error) {\n      // ignore\n    }\n\n    decorateError(error, 'response_status', response.status);\n    decorateError(error, 'response_url', response.url);\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // Extract the message from the response and use that as the thrown error message.\n\n    if (typeof error.response_body?.message === 'string') {\n      decorateError(error, 'message', error.response_body.message);\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Use the GET /{locale}/cart.js endpoint to get the cart as JSON.\n *\n * All monetary properties are returned in the customer's presentment currency. To check the\n * customer's presentment currency, you can use the currency field in the response.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#get-locale-cart-js\n */\nexport async function cartFetch() {\n  const url = Shopify.routes.root + 'cart.js';\n\n  let response;\n  try {\n    response = await fetch(url, { cache: 'no-store' });\n  } catch (error) {\n    decorateError(error, 'url', url);\n    throw error;\n  }\n\n  if (!isResponse(response)) {\n    const error: any = new Error('fetch did not return a response fetching cart');\n    decorateError(error, 'response', response);\n    decorateError(error, 'url', url);\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} fetching cart`);\n    decorateError(error, 'request_id', getRequestId(response));\n\n    try {\n      decorateError(error, 'response_body', await response.json());\n    } catch (error) {\n      // ignore\n    }\n\n    decorateError(error, 'status', response.status);\n    decorateError(error, 'url', response.url);\n    throw error;\n  }\n\n  let body;\n  try {\n    body = await response.json();\n  } catch (error) {\n    decorateError(error, 'status', response.status);\n    decorateError(error, 'url', response.url);\n    throw error;\n  }\n\n  if (!isCart(body)) {\n    const error: any = new Error('Unexpected get cart response body');\n    decorateError(error, 'response_body', body);\n    decorateError(error, 'status', response.status);\n    decorateError(error, 'url', response.url);\n    throw error;\n  }\n\n  return body;\n}\n\nexport interface CartUpdateInput {\n  /**\n   * New cart attributes. Existing cart attributes are overwritten.\n   */\n  attributes?: Attributes;\n\n  /**\n   * Beta shopify feature. Essentially works like Storefront discount apply mutation.\n   *\n   * Pass an empty string to remove discount(s).\n   */\n  discount?: string;\n\n  /**\n   * Cart note.\n   */\n  note?: string;\n\n  /**\n   * Even though Shopify supports specifying variant ids as numbers, we impose the restriction that\n   * the property names of the updates object must be strings due to some strange looking errors\n   * when specifying numbers.\n   */\n  updates?: Record<string, any>;\n}\n\n/**\n * Performs a cart update.\n *\n * This does not return the cart updated state. You will need to do a followup call to fetch the\n * updated state of the cart. One reason this does also return the updated state is that we must\n * perform a second call to fetch the updated state but not all callers are interested in doing so.\n *\n * This does not return the response body of the call. There is no need to fetch the body because\n * the body does not contain useful data. The response body can contain 0 quantity items and other\n * kinds of strange things.\n *\n * This must specify the content type header. Shopify supports both a JSON request body and a form\n * data request body. Shopify defaults to interpreting requests as form submissions. This uses the\n * JSON format so the header is required.\n *\n * Backend scripts may affect the output.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-update-js\n * @see https://shopify.dev/docs/api/ajax/reference/cart#update-line-item-quantities\n * @see https://shopify.dev/docs/api/ajax/reference/cart#private-cart-attributes\n */\nexport async function cartUpdate(input: CartUpdateInput) {\n  const response = await fetch(Shopify.routes.root + 'cart/update.js', {\n    body: JSON.stringify(input),\n    cache: 'no-store',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    method: 'POST'\n  });\n\n  if (!isResponse(response)) {\n    const error: any = new Error('fetch did not return a response updating cart');\n    decorateError(error, 'request_body', input);\n    decorateError(error, 'response', response);\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} updating cart`);\n    decorateError(error, 'request_body', input);\n    decorateError(error, 'request_id', getRequestId(response));\n\n    try {\n      decorateError(error, 'response_body', await response.json());\n    } catch (error) {\n      // ignore\n    }\n\n    decorateError(error, 'response_status', response.status);\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // Extract the message from the response and use that as the thrown error message.\n\n    if (typeof error.response_body?.message === 'string') {\n      decorateError(error, 'message', error.response_body.message);\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Returns whether the error indicates the add failed because one of the products is out of stock\n * (not available for sale). In this case Shopify provides an error response body that looks like\n * this:\n *\n * ```json\n * {\n *   \"description\": \"All 0 <product title> are in your cart\",\n *   \"message\": \"Cart Error\",\n *   \"status\": 422\n * }\n * ```\n *\n * ```json\n * {\n *   \"description\": \"The product '<title>' is already sold out.\",\n *   \"message\": \"Cart Error\",\n *   \"status\": 422\n * }\n * ```\n *\n * This error can happen both when adding an item or updating the quantity of an item.\n *\n * This assumes error messages are in English.\n */\nexport function isUnavailableError(error: any) {\n  if (error instanceof Error && 'response_body' in error && isObject(error.response_body) &&\n    error.response_body.status === 422) {\n    const description = error.response_body.description;\n    if (typeof description === 'string') {\n      // this one is only present in the add error response\n      if (description.startsWith('All 0') && description.includes('in your cart')) {\n        return true;\n      }\n\n      // this string is sometimes present in the update error response, not just the add response\n      if (description.includes('already sold out')) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Returns whether the error indicates the add failed because the selling plan sent with the item is\n * not one Shopify will accept for that variant. This happens when a rendered page carries a selling\n * plan ID (for example a pre-order deferred-payment plan) that has since become stale: the variant\n * came back in stock, or the plan was edited or removed, after the page was rendered but before the\n * shopper clicked add. Shopify responds with a body that looks like this:\n *\n * ```json\n * {\n *   \"description\": \"Cannot apply selling plan to variant\",\n *   \"message\": \"Cart Error\",\n *   \"status\": 422\n * }\n * ```\n *\n * This assumes error messages are in English.\n */\nexport function isInvalidSellingPlanError(error: any) {\n  if (error instanceof Error && 'response_body' in error && isObject(error.response_body) &&\n    error.response_body.status === 422) {\n    const description = error.response_body.description;\n    if (typeof description === 'string') {\n      if (description.includes('Cannot apply selling plan to variant')) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Returns whether the given value looks like a cart object.\n *\n * This is not a complete validation. This is a shallow check that examines whether the value is an\n * object containing an items property that is an array. Any value that meets that criteria\n * satisfies the meaning of a cart.\n */\nexport function isCart(value: any): value is Cart {\n  return isObject(value) && Array.isArray(value.items);\n}\n\nfunction isObject(value: any): value is Record<string, any> {\n  return typeof value === 'object' && value !== null;\n}\n","// Keeps track of the timeout timer between the start and end of all calls\nlet timerId: ReturnType<typeof setTimeout>;\n\n/**\n * Called at the beginning of most service operations. This signals to the view that an operation\n * has started.\n *\n * @see http://jdebp.info/FGA/function-perilogues.html\n */\nexport function startCall(...args: any[]) {\n  // This should never happen because we always clear the timeout and set the variable value back to\n  // undefined in the epilogue. This might help debug some screwy things.\n\n  if (typeof timerId !== 'undefined') {\n    window.console.error('concurrent call detected!');\n    window.console.error('[call-utils.ts] args: ', args);\n\n    window.Sentry?.captureException(new Error('Concurrent checkout service call detected'), {\n      extra: {\n        args\n      },\n      level: 'warning'\n    });\n  }\n\n  // Guarantee that the end event will fire by starting a timer.\n  timerId = setTimeout(() => {\n    endCall(false, true);\n  }, 30 * 1000, true);\n\n  const event = new Event('ofir-cart-call-started', { cancelable: false });\n  dispatchEvent(event);\n}\n\n/**\n * Called at the end of most service operations. This signals to the view that an operation has\n * completed (successfully or not).\n *\n * This is called either manually whenever the operation completed, or automatically, if the\n * operation errored or has not completed after a certain amount of time. We do this to prevent the\n * situation of never firing an end event in case of extremely messed up code. Sometimes that kind\n * of thing happens and we never want to fully lock someone out of cart interactions.\n *\n * @see http://jdebp.info/FGA/function-perilogues.html\n */\nexport function endCall(notifyView = true, didTimeOut = false) {\n  // Unconditionally clear the timeout timer, regardless of whether the timer id is set.\n  clearTimeout(timerId);\n\n  // Reset the timer id. Not really needed but it makes it crystal clear that there is no timer id\n  // active.\n  timerId = undefined;\n\n  // If we got here from a timeout, just make sure something is logged. In theory, nothing ever\n  // times out.\n  if (didTimeOut) {\n    console.warn('epilogue timed out');\n  }\n\n  const event = new CustomEvent('ofir-cart-call-ended', {\n    cancelable: false,\n    detail: {\n      is_timeout: didTimeOut,\n      notify_view: notifyView\n    }\n  });\n\n  dispatchEvent(event);\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\n/**\n * Do not use this export. This is a hacky fix to a strange inlining optimization performed by\n * webpack where it removes this module and points identifiers directly to the global values.\n * Without this export, webpack fails to understand that `window.__ofir` must also be inlined.\n *\n * @type {unknown}\n */\nexport const __ofir: unknown = window.__ofir;\n\n/**\n * Cart should never be undefined\n */\nexport const Cart: OfirLiquidGlobals.Cart = window.__ofir?.Cart;\n\n/**\n * Checkout is undefined if user is not loading a checkout page.\n *\n * @type {OfirLiquidGlobals.Checkout}\n */\nexport const Checkout: OfirLiquidGlobals.Checkout = window.__ofir?.Checkout;\n\n/**\n * Collection is undefined if user is not loading a product or collection page.\n *\n * @type {OfirLiquidGlobals.Collection}\n */\nexport const Collection: OfirLiquidGlobals.Collection = window.__ofir?.Collection;\n\n/**\n * Customer is undefined if user is not logged in.\n *\n * @type {OfirLiquidGlobals.Customer}\n */\nexport const Customer: OfirLiquidGlobals.Customer = window.__ofir?.Customer;\n\n/**\n * GiftCard is undefined if user is not on gift card page.\n *\n * @type {OfirLiquidGlobals.GiftCard}\n */\nexport const GiftCard: OfirLiquidGlobals.GiftCard = window.__ofir?.GiftCard;\n\n/**\n * Order is undefined unless user is on thank_you page, order status page or account/order detail\n * page.\n *\n * @type {OfirLiquidGlobals.Order}\n */\nexport const Order: OfirLiquidGlobals.Order = window.__ofir?.Order;\n\n/** @type {OfirLiquidGlobals.Page} */\nexport const Page: OfirLiquidGlobals.Page = window.__ofir?.Page;\n\n/** @type {OfirLiquidGlobals.Pagination} */\nexport const Pagination: OfirLiquidGlobals.Pagination = window.__ofir?.Pagination;\n\n/**\n * Product is undefined if not accessing a product page template.\n *\n * @type {OfirLiquidGlobals.Product}\n */\nexport const Product: OfirLiquidGlobals.Product = window.__ofir?.Product;\n\n/** @type {OfirLiquidGlobals.Request} */\nexport const Request: OfirLiquidGlobals.Request = window.__ofir?.Request;\n\n/** @type {OfirLiquidGlobals.Scripts} */\nexport const Scripts: OfirLiquidGlobals.Scripts = window.__ofir?.Scripts;\n\n/** @type {OfirLiquidGlobals.Search} */\nexport const Search: OfirLiquidGlobals.Search = window.__ofir?.Search;\n\n/** @type {OfirLiquidGlobals.SearchEngineListing} */\nexport const SearchEngineListing: OfirLiquidGlobals.SearchEngineListing =\n  window.__ofir?.SearchEngineListing;\n\n/** @type {OfirLiquidGlobals.SectionSettings} */\nexport const SectionSettings: OfirLiquidGlobals.SectionSettings = window.__ofir?.SectionSettings;\n\n/** @type {OfirLiquidGlobals.Shop} */\nexport const Shop: OfirLiquidGlobals.Shop = window.__ofir?.Shop;\n\n/** @type {OfirLiquidGlobals.Template} */\nexport const Template: OfirLiquidGlobals.Template = window.__ofir?.Template;\n\n/** @type {OfirLiquidGlobals.Theme} */\nexport const Theme: OfirLiquidGlobals.Theme = window.__ofir?.Theme;\n\n/** @type {OfirLiquidGlobals.ThemeSettings} */\nexport const ThemeSettings: OfirLiquidGlobals.ThemeSettings = window.__ofir?.ThemeSettings;\n","import * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CallUtils from '../../../lib/call-utils.js';\nimport updateCartHtml from '../update-cart-html.js';\n\n/**\n * Utilizes the Shopify Ajax API endpoint to add an array of products to a users shopping cart.\n *\n * The imported CallUtils methods emit events to notify any view layer logic listening so it can\n * implement any required changes to update the user of the application state. You only need to use\n * these methods if you want the UX/UI to represent and/or provide messaging for the asynchronous\n * request.\n *\n * @param payload form data to be submitted\n * @param notifyView passed on to ofir-cart-call-ended event to for view layer listeners\n *\n * @returns lineItems cart data\n *\n * @see https://shopify.dev/api/ajax/reference/cart#post-locale-cart-add-js\n */\nexport async function addToCart(payload: ShopifyAjaxApi.AddToCartPayload, notifyView = true) {\n  CallUtils.startCall('addToCart', payload);\n\n  let response;\n  let lineItems;\n  const addedItems = <ShopifyAjaxApi.LineItem[]>[];\n\n  try {\n    const body = JSON.stringify({ ...payload, sections: 'modal-cart' });\n    response = await fetch('/cart/add.js', {\n      method: 'POST',\n      body,\n      headers: {\n        'Content-Type': 'application/json'\n      }\n    });\n\n    if (!response.ok) {\n      throw new Error(`CartService.addToCart Error: ${response.status} ${response.statusText} ` +\n        response.url);\n    }\n\n    lineItems = <ShopifyAjaxApi.AddToCartResponse> await response.json();\n\n    const addedVariantIds = payload.items.map((i: ShopifyAjaxApi.AddToCartItem) => i.id);\n    for (const item of lineItems.items) {\n      if (addedVariantIds.indexOf(item.variant_id) > -1) {\n        const addedItem = payload.items.find(\n          (i: ShopifyAjaxApi.AddToCartItem) => i.id === item.variant_id);\n        addedItems.push({ ...item, quantity: addedItem.quantity });\n        break;\n      }\n    }\n\n    const customEvent = new CustomEvent('ofir-add-to-cart', {\n      cancelable: false,\n      detail: {\n        items: addedItems,\n        modal_cart: lineItems.sections['modal-cart'],\n        success: true\n      }\n    });\n    dispatchEvent(customEvent);\n\n    if (lineItems.sections?.['modal-cart']) {\n      updateCartHtml(lineItems.sections['modal-cart']);\n    }\n\n    // This must perform multiple http requests due to limitations in Shopify's ajax cart api. The\n    // first fetch mutates, and the second fetch gets the updated state. Unfortunately, this means\n    // that it is possible for the mutation to succeed but for the subsequent fetch to fail. Callers\n    // should be wary of this situation. On some future successful retrieval of server side state,\n    // the added items will appear, despite this function emitting an error event. This means, for\n    // example, that callers should not assume that failure to add is necessarily a real failure.\n    const cart = await ajax.cartFetch();\n    type CartUpdatedDetail = WindowEventMap['cart-updated']['detail'];\n    const cartUpdatedEvent = new CustomEvent<CartUpdatedDetail>('cart-updated', {\n      cancelable: false,\n      detail: {\n        cart,\n        success: true\n      }\n    });\n    dispatchEvent(cartUpdatedEvent);\n\n    if (notifyView) {\n      type Detail = OfirCustomEvents.ViewCartEventDetails;\n      const viewCartEvent = new CustomEvent<Detail>('ofir-view-cart', {\n        cancelable: false,\n        detail: {\n          items: lineItems.items,\n          source: 'add-to-cart-cta'\n        }\n      });\n\n      dispatchEvent(viewCartEvent);\n    }\n  } catch (error) {\n    const detail = <OfirCustomEvents.AddToCartEvent['detail']>{\n      error_code: response.status,\n      error_message: response.statusText,\n      items: addedItems,\n      payload,\n      success: false\n    };\n\n    window.Sentry?.captureException(error, {\n      extra: {\n        ...detail,\n        source: 'cart-service-add-to-cart'\n      }\n    });\n\n    const customEvent = new CustomEvent('ofir-add-to-cart', {\n      cancelable: false,\n      detail\n    });\n\n    dispatchEvent(customEvent);\n  } finally {\n    CallUtils.endCall(notifyView, false);\n  }\n\n  return lineItems;\n}\n\ndeclare global {\n  interface WindowEventMap {\n    'ofir-add-to-cart': OfirCustomEvents.AddToCartEvent;\n  }\n}\n","import * as LiquidGlobals from '../../common/liquid-global.js';\n\nexport default function updateCartHtml(html: string) {\n  const element = document.createElement('div');\n  element.innerHTML = html;\n\n  const cartContentElement = element.querySelector('.modal-content');\n  if (!cartContentElement) {\n    return;\n  }\n\n  if (LiquidGlobals.Template.name !== 'cart') {\n    const cartModalElement = document.getElementById('cart-modal');\n    const modalContentElement = cartModalElement?.querySelector('.modal-content');\n    if (!modalContentElement) {\n      return;\n    }\n\n    const modalContentCartHeaderElement = modalContentElement.querySelector('.cart__header');\n    modalContentCartHeaderElement.innerHTML =\n      cartContentElement.querySelector('.cart__header').innerHTML;\n\n    const modalContentCartContentElement = modalContentElement.querySelector('.cart__main');\n    modalContentCartContentElement.innerHTML =\n      cartContentElement.querySelector('.cart__main').innerHTML;\n\n    const cartCount =\n      cartContentElement.querySelector('.cart__header > span').textContent.replace(/\\D+/, '');\n    const cartCounterElement = document.querySelector('#cart-counter');\n    cartCounterElement.textContent = cartCount;\n\n    if (parseInt(cartCount, 10) === 0) {\n      cartCounterElement.classList.add('hidden');\n    } else {\n      cartCounterElement.classList.remove('hidden');\n    }\n  } else {\n    // Update cart content if user landed on cart page\n    const cartPageElement = document.getElementById('cart-page');\n    if (cartPageElement.classList.contains('cart--empty')) {\n      return;\n    }\n\n    const cartPageCartHeaderElement = cartPageElement.querySelector('.cart__header');\n    cartPageCartHeaderElement.innerHTML =\n      cartContentElement.querySelector('.cart__header').innerHTML;\n\n    const cartPageCartContentElement = cartPageElement.querySelector('.cart__main');\n    cartPageCartContentElement.innerHTML =\n      cartContentElement.querySelector('.cart__main').innerHTML;\n  }\n\n  const event = new Event('cart-html-updated');\n  dispatchEvent(event);\n}\n\ndeclare global {\n  interface WindowEventMap {\n    'cart-html-updated': Event;\n  }\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\n// TODO this web component shouldn't import anything from another section\nimport * as CartService from '../../modal-cart/cart-service/index.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * The custom element that handles \"Add to Cart\" functionality.\n *\n * This component relies on <add-to-cart-product> placeholder elements passed to the default slot.\n * The <add-to-cart-product> element holds the data of the product that should be added to the cart.\n * On the \"variant-changed\" event the selected variant ID and availability of the product are\n * updated. When the button is clicked the payload object of type ShopifyAjaxApi.AddToCartPayload is\n * composed and sent via the CartService. In case the selected variant is unavailable the notify me\n * button should be shown instead of add to cart button.\n */\nclass AddToCart extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Defines the button variant. Currently, only 'secondary' is supported. Default styles applied\n     * if no value is set.\n     */\n    buttonVariant: 'secondary';\n\n    /**\n     * The message to be shown in the CTA. Currently, it's used for the simple product card in the\n     * pair product card section.\n     */\n    discountMessage: string;\n\n    /**\n     * Represents whether the component for an upsell product.\n     */\n    isUpsell: 'false' | 'true';\n\n    /**\n     * Whether to keep the added state of the product after adding it to the cart. If true, the CTA\n     * will be updated to the \"added\" state. This is used for the paired product card section\n     */\n    keepAddedState: 'false' | 'true';\n\n    /**\n     * Whether to notify other parts of the website that product was added to the cart. If false,\n     * the cart drawer won't be opened after adding the product to the cart. Used for upsell\n     * products in the upsell modal (but not in the upsell carousel!), we don't want to open the\n     * cart drawer after adding the product from the upsell modal.\n     */\n    notifyView: 'false' | 'true';\n\n    /**\n     * The price of the product to render in the CTA, e.g. '$17'\n     */\n    price: string;\n  };\n\n  /**\n   * Indicates the quantity of products to be added to the cart.\n   */\n  private quantity = 1;\n\n  private onAddToCartClickedBound = this.onAddToCartClicked.bind(this);\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n  private onQuantityChangedBound = this.onQuantityChanged.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n\n    const addToCart = this.shadowRoot.querySelector('button');\n    addToCart.addEventListener('click', this.onAddToCartClickedBound);\n\n    addEventListener('variant-changed', this.onVariantChangedBound);\n    addEventListener('quantity-input-changed', this.onQuantityChangedBound);\n\n    // call it to set initial component state\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const addToCart = this.shadowRoot.querySelector('button');\n    addToCart.removeEventListener('click', this.onAddToCartClickedBound);\n\n    removeEventListener('variant-changed', this.onVariantChangedBound);\n    removeEventListener('quantity-input-changed', this.onQuantityChangedBound);\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 onAddToCartClicked(_event: Event) {\n    const button = this.shadowRoot.querySelector('button');\n    button.disabled = true;\n\n    let payload;\n    if (this.dataset.isUpsell === 'true') {\n      payload = this.composeUpsellProductPayload();\n    } else {\n      payload = this.composeRegularProductPayload();\n    }\n\n    CartService.addToCart(payload, this.dataset.notifyView === 'true')\n      .catch(error => {\n        throw new Error(<string>error);\n      })\n      .finally(() => {\n        if (this.dataset.keepAddedState === 'true') {\n          this.renderAddedState();\n        } else {\n          // In other cases, we need to keep it as it is and enable the button\n          button.disabled = false;\n        }\n      });\n  }\n\n  /**\n   * Handle the change in product quantity input.\n   *\n   * At present, this is only relevant for PDP.\n   */\n  private onQuantityChanged(event: WindowEventMap['quantity-input-changed']) {\n    if (event.detail.source === 'pdp') {\n      // We need to update quantity only if the \"quantity-input-changed\" event is fired from a PDP\n      // product details section. This event is also fired from the quantity input in the mini cart.\n      // In this case, we don't need to update the quantity of any <add-to-cart> button, even if the\n      // product ID is the same.\n      const product = this.querySelector(`[data-id=\"${ event.detail.product_id }\"]`);\n      if (product) {\n        this.quantity = event.detail.quantity;\n      }\n    }\n  }\n\n  private composeRegularProductPayload() {\n    const product = this.querySelector('add-to-cart-product');\n    const payload: ShopifyAjaxApi.AddToCartPayload = {\n      items: [\n        {\n          id: parseInt(product.dataset.selectedVariantId, 10),\n          quantity: this.quantity\n        }\n      ]\n    };\n\n    const sellingPlan = getSellingPlan();\n    if (sellingPlan) {\n      payload.items[0].selling_plan = sellingPlan;\n    }\n\n    return payload;\n  }\n\n  private composeUpsellProductPayload() {\n    const product = this.querySelector('add-to-cart-product');\n    const payload: ShopifyAjaxApi.AddToCartPayload = {\n      items: [\n        {\n          id: parseInt(product.dataset.selectedVariantId, 10),\n          quantity: this.quantity,\n          properties: {\n            '_is_upsell': 'true'\n          }\n        }\n      ]\n    };\n\n    const sellingPlan = getSellingPlan();\n    if (sellingPlan) {\n      payload.items[0].selling_plan = sellingPlan;\n    }\n\n    return payload;\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const { id, available, option, bundleOptionGroup,\n      product_id: productId } = event.detail.variant;\n\n    // For bundle products, the sub-product variant selectors dispatch \"variant-changed\" with a\n    // component product ID. Check if this event belongs to a bundle option of this element.\n    if (bundleOptionGroup) {\n      type BundleOption = HTMLElementTagNameMap['bundle-option'];\n      const bundleOption = this.querySelector<BundleOption>(\n        `bundle-option[data-name=\"${bundleOptionGroup}\"]`\n      );\n      if (bundleOption) {\n        bundleOption.dataset.selected = option;\n        this.updateBundleVariant();\n        return;\n      }\n    }\n\n    // Regular product: find the add-to-cart-product element by product ID.\n    const product = this.querySelector<HTMLElementTagNameMap['add-to-cart-product']>(\n      `add-to-cart-product[data-id=\"${productId}\"]`\n    );\n\n    if (!product) {\n      // The \"variant-changed\" event can be dispatched by any variant selector on the page. If the\n      // product element is not found, it means that the variant that had been changed is not\n      // related to this add to cart button.\n      return;\n    }\n\n    product.dataset.selectedVariantId = id.toString();\n    product.dataset.available = available ? 'true' : 'false';\n    product.dataset.selectedVariantTitle = option;\n\n    this.render();\n  }\n\n  /**\n   * When a bundle sub-product option changes, derive the new bundle variant by matching all\n   * currently selected bundle-option values against the bundle-variant elements, then update the\n   * add-to-cart-product to reflect the new selection.\n   */\n  private updateBundleVariant() {\n    // Collect selected values in option position order to reconstruct the variant title.\n    type BundleOption = HTMLElementTagNameMap['bundle-option'];\n    const bundleOptionElements = this.querySelectorAll<BundleOption>('bundle-option');\n    const bundleOptions: string[] = [];\n    for (const bundleOption of bundleOptionElements) {\n      const index = parseInt(bundleOption.dataset.position, 10) - 1;\n      bundleOptions[index] = bundleOption.dataset.selected;\n    }\n\n    // The bundle variant title is a combination of the selected option values joined by \" / \", it's\n    // generated by Shopify\n    const variantName = bundleOptions.join(' / ');\n\n    // Find the bundle-variant whose title matches the combined selection.\n    type BundleVariant = HTMLElementTagNameMap['bundle-variant'];\n    const selector = `bundle-variant[data-title=\"${variantName}\"]`;\n    const matchedVariant = this.querySelector<BundleVariant>(selector);\n    if (!matchedVariant) {\n      return;\n    }\n\n    type AddToCartProduct = HTMLElementTagNameMap['add-to-cart-product'];\n    const product = this.querySelector<AddToCartProduct>('add-to-cart-product');\n    if (!product) {\n      return;\n    }\n\n    product.dataset.selectedVariantId = matchedVariant.dataset.id;\n    product.dataset.available = matchedVariant.dataset.available;\n    product.dataset.selectedVariantTitle = variantName;\n\n    this.render();\n  }\n\n  /**\n   * Update the availability of the product for displaying either the add to cart button or the\n   * notify me button based on product availability.\n   */\n  private render() {\n    const addToCart = this.shadowRoot.querySelector('button');\n    const notifyMe = this.shadowRoot.querySelector('notify-me-button');\n\n    // render optional discount message\n    if (this.dataset.discountMessage) {\n      const discount = this.shadowRoot.querySelector('.discount');\n      discount.textContent = this.dataset.discountMessage;\n    }\n\n    // render optional price inside the CTA\n    if (this.dataset.price) {\n      const price = this.shadowRoot.querySelector('.price');\n      price.textContent = this.dataset.price;\n    }\n\n    type AddToCartProduct = HTMLElementTagNameMap['add-to-cart-product'];\n\n    // Selecting the first unavailable product. This will be effective with a regular product\n    // containing only one <add-to-cart-product> element and a bundle with multiple <add-to-cart-\n    // product> elements. If no element is found, it means that the product can be added to the\n    // cart.\n    const unavailableProduct =\n      this.querySelector<AddToCartProduct>('add-to-cart-product[data-available=\"false\"]');\n    if (unavailableProduct) {\n      addToCart.hidden = true;\n      notifyMe.hidden = false;\n\n      notifyMe.dataset.productId = unavailableProduct.dataset.id;\n      notifyMe.dataset.productTitle = unavailableProduct.dataset.productTitle;\n      notifyMe.dataset.variantId = unavailableProduct.dataset.selectedVariantId;\n      notifyMe.dataset.variantTitle = unavailableProduct.dataset.selectedVariantTitle;\n    } else {\n      addToCart.hidden = false;\n      notifyMe.hidden = true;\n    }\n  }\n\n  /**\n   * Update the CTA to the \"added\" state\n   */\n  private renderAddedState() {\n    const button = this.shadowRoot.querySelector('button');\n    button.classList.add('added');\n\n    const label = button.firstChild;\n    label.textContent = 'Added to bag!';\n\n    const price = this.shadowRoot.querySelector('.price');\n    if (price) {\n      price.remove();\n    }\n\n    const discount = this.shadowRoot.querySelector('.discount');\n    if (discount) {\n      // Setting the number of added products. For now, it's just hardcoded \"1\", but in the future,\n      // we can pass a real quantity of added products. It might be relevant if the same product is\n      // already in the cart.\n      discount.textContent = '1';\n    }\n  }\n}\n\n/**\n * Retrieves the selected selling plan based on the subscription checkbox and radio button selection\n *\n * TODO Move it out of this custom element. I don't think it should be here, but for now it's more\n * or less a copy-paste of the existing functionality encapsulated in the custom element. We can\n * create a custom element to handle the subscription selector which will dispatch some event that\n * we can handle in this component then.\n */\nfunction getSellingPlan() {\n  const subscribeCheckbox =\n    document.querySelector<HTMLInputElement>('.subscribe-and-save__checkbox');\n  if (!subscribeCheckbox?.checked) {\n    return null;\n  }\n\n  const selectedRadioElement =\n    document.querySelector<HTMLInputElement>('.subscribe-and-save__radio:checked');\n  if (selectedRadioElement) {\n    return parseInt(selectedRadioElement.value, 10);\n  } else {\n    return null;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'add-to-cart': AddToCart;\n  }\n}\n\nif (!customElements.get('add-to-cart')) {\n  customElements.define('add-to-cart', AddToCart);\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * The custom element that is used to show a notify me button that opens a modal when clicked.\n */\nclass NotifyMeButton extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Product ID, a stringified integer number\n     */\n    productId: string;\n\n    /**\n     * Product title\n     */\n    productTitle: string;\n\n    /**\n     * Product variant ID, a stringified integer number\n     */\n    variantId: string;\n\n    /**\n     * Variant title\n     */\n    variantTitle: string;\n  };\n\n  private onButtonClickedBound = this.onButtonClicked.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const button = this.shadowRoot.querySelector('button');\n    button.removeEventListener('click', this.onButtonClickedBound);\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 render() {\n    const button = this.shadowRoot.querySelector('button');\n    button.addEventListener('click', this.onButtonClickedBound);\n  }\n\n  private onButtonClicked(_event: Event) {\n    type Detail = WindowEventMap['notify-me-modal-show-requested']['detail'];\n    const event = new CustomEvent<Detail>('notify-me-modal-show-requested', {\n      detail: {\n        productId: this.dataset.productId,\n        productTitle: this.dataset.productTitle || '',\n        variantId: this.dataset.variantId,\n        variantTitle: this.dataset.variantTitle || ''\n      }\n    });\n    dispatchEvent(event);\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'notify-me-button': NotifyMeButton;\n  }\n}\n\nif (!customElements.get('notify-me-button')) {\n  customElements.define('notify-me-button', NotifyMeButton);\n}\n"],"names":["AddToCartProduct","HTMLElement","customElements","get","define","BundleOption","BundleVariant","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","getRequestId","response","headers","error","isResponse","value","ok","status","json","decorateError","key","async","cartFetch","url","Shopify","routes","root","body","fetch","cache","Error","isObject","Array","isArray","items","timerId","endCall","notifyView","didTimeOut","clearTimeout","console","warn","event","CustomEvent","cancelable","detail","is_timeout","notify_view","dispatchEvent","window","__ofir","_window$__ofir","Cart","_window$__ofir2","Checkout","_window$__ofir3","Collection","_window$__ofir4","Customer","_window$__ofir5","GiftCard","_window$__ofir6","Order","_window$__ofir7","Page","_window$__ofir8","Pagination","_window$__ofir9","Product","_window$__ofir0","Request","_window$__ofir1","Scripts","_window$__ofir10","Search","_window$__ofir11","SearchEngineListing","_window$__ofir12","SectionSettings","_window$__ofir13","Shop","Template","_window$__ofir14","_window$__ofir15","Theme","_window$__ofir16","ThemeSettings","addToCart","payload","lineItems","_window$Sentry","_len","arguments","length","args","_key","Sentry","captureException","extra","level","setTimeout","Event","startCall","addedItems","_lineItems$sections","JSON","stringify","_extends","sections","method","statusText","addedVariantIds","map","i","id","item","indexOf","variant_id","addedItem","find","push","quantity","customEvent","modal_cart","success","html","element","document","createElement","innerHTML","cartContentElement","querySelector","name","cartModalElement","getElementById","modalContentElement","cartCount","textContent","replace","cartCounterElement","parseInt","classList","add","remove","cartPageElement","contains","updateCartHtml","cart","cartUpdatedEvent","viewCartEvent","source","error_code","error_message","AddToCart","onAddToCartClickedBound","this","onAddToCartClicked","bind","onVariantChangedBound","onVariantChanged","onQuantityChangedBound","onQuantityChanged","connectedCallback","initializeShadowRoot","shadowRoot","addEventListener","render","disconnectedCallback","removeEventListener","attachShadow","mode","_event","button","disabled","dataset","isUpsell","composeUpsellProductPayload","composeRegularProductPayload","catch","finally","keepAddedState","renderAddedState","product_id","product","selectedVariantId","sellingPlan","getSellingPlan","selling_plan","properties","_is_upsell","available","option","bundleOptionGroup","productId","variant","bundleOption","selected","updateBundleVariant","toString","selectedVariantTitle","bundleOptionElements","querySelectorAll","bundleOptions","position","variantName","join","selector","matchedVariant","notifyMe","discountMessage","price","unavailableProduct","hidden","productTitle","variantId","variantTitle","firstChild","discount","subscribeCheckbox","checked","selectedRadioElement","NotifyMeButton","onButtonClickedBound","onButtonClicked"],"sourceRoot":""}