{"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/add-to-cart-set/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/toggle-sub-line-items.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/add-to-cart/index.scss","webpack://lange/./scripts/sections/add-to-cart-elements/add-to-cart/index.html","webpack://lange/./scripts/sections/add-to-cart-elements/notify-me-button/index.ts","webpack://lange/./scripts/sections/add-to-cart-elements/notify-me-button/index.scss","webpack://lange/./scripts/sections/add-to-cart-elements/notify-me-button/index.html"],"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  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     * Set subproduct index, a stringified integer started from 0\n     */\n    setIndex: 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, needed for add to cart functionality\n * It has no functionality.\n */\nclass AddToCartSet extends HTMLElement {\n  readonly dataset!: {\n    /**\n     * Set compare at price as cents, a stringified integer number\n     */\n    compareAtPrice: string;\n\n    /**\n     * Set product ID, a stringified integer number\n     */\n    id: string;\n\n    /**\n     * Set image url\n     */\n    imageUrl: string;\n\n    /**\n     * Set name\n     */\n    name: string;\n\n    /**\n     * Set price as cents, a stringified integer number\n     */\n    price: string;\n  };\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'add-to-cart-set': AddToCartSet;\n  }\n}\n\nif (!customElements.get('add-to-cart-set')) {\n  customElements.define('add-to-cart-set', AddToCartSet);\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar 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\tvar 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\n   * line items. That is why line level discount allocation objects have a nested application\n   * object that 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\n   * if applied but in the inapplicable state while in the cart. The discount will appear as\n   * applicable 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  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  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\n   * cart 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 * 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   * 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\n * may 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 (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} adding to cart`);\n    error.items = items;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    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      error.message = error.response_body.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 (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} changing cart`);\n    error.request_body = input;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.response_status = response.status;\n    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      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    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    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.status = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  let body;\n  try {\n    body = await response.json();\n  } catch (error) {\n    error.status = response.status;\n    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    error.response_body = body;\n    error.status = response.status;\n    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 (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} updating cart`);\n    error.request_body = input;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    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      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 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\n * an 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\n  // to 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\n * the situation of never firing an end event in case of extremely messed up code. Sometimes that\n * kind 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","export function attachToggleHandlers() {\n  const variantToggles = document.querySelectorAll('.cart-line-item__show-details');\n\n  for (const toggle of variantToggles) {\n    toggle.addEventListener('click', onToggleClicked);\n  }\n}\n\nfunction onToggleClicked(event: Event) {\n  event.preventDefault();\n\n  const element = <HTMLElement>event.currentTarget;\n  const targetId = element.getAttribute('aria-controls');\n  const toggleTarget = document.getElementById(targetId);\n  if (!toggleTarget) {\n    return;\n  }\n\n  toggleTarget.classList.toggle('hidden');\n\n  if (toggleTarget.classList.contains('hidden')) {\n    element.textContent = 'Show Details';\n    element.setAttribute('aria-expanded', 'false');\n  } else {\n    element.textContent = 'Hide Details';\n    element.setAttribute('aria-expanded', 'true');\n  }\n}\n\naddEventListener('DOMContentLoaded', attachToggleHandlers);\n","import * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CallUtils from '../../../lib/call-utils';\nimport updateCartHtml from '../update-cart-html';\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\n    // means that it is possible for the mutation to succeed but for the subsequent fetch to\n    // fail. Callers should be wary of this situation. On some future successful retrieval of\n    // server side state, the added items will appear, despite this function emitting an error\n    // event. This means, for example, that callers should not assume that failure to add is\n    // 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      const detail = <OfirCustomEvents.ViewCartEventDetails>{\n        items: lineItems.items,\n        source: 'add-to-cart-cta'\n      };\n      const viewCartEvent = new CustomEvent('ofir-view-cart', {\n        cancelable: false,\n        detail\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';\nimport * as ToggleSubLineItems from './toggle-sub-line-items';\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  ToggleSubLineItems.attachToggleHandlers();\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';\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> and <add-to-cart-set> placeholder elements passed\n * to the default slot. The <add-to-cart-product> element holds the data of the product that should\n * be added to the cart. The <add-to-cart-set> holds data set's properties.\n *\n * *Regular product:*\n * The product data is held by <add-to-cart-product>. On the \"variant-changed\" event the\n * selected variant ID and availability of the product are updated. When the button clicked the\n * payload object of type ShopifyAjaxApi.AddToCartPayload composed and sent via the CartService.\n * In case the selected variant is unavailable the notify me button should be shown instead of add\n * to cart button.\n *\n * *Set product:*\n * The products data is help by several <add-to-cart-product> elements that should\n * be passed to the default slot. Each represents the product in the bundle. Since the set can\n * consist from similar products the \"data-set-index\" attribute should be set for each\n * <add-to-cart-product> to distinguish products. On the \"variant-changed\" event the selected\n * variant ID and availability of the related product are updated. Also, <add-to-cart-set> should\n * be passed to the default slot. This element holds set properties. When the button clicked the\n * payload object of type ShopifyAjaxApi.AddToCartPayload composed and sent via the CartService. In\n * case any of selected product variant is unavailable the notify me button should be shown instead\n * of add to cart button.\n */\nclass AddToCart extends HTMLElement implements CustomElement {\n  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 a Sets product.\n     */\n    isSet: 'false' | 'true';\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\n     * false, the cart drawer won't be opened after adding the product to the cart. Used for\n     * upsell products in the upsell modal (but not in the upsell carousel!), we don't want to\n     * open the 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  public shadowRoot!: ShadowRoot;\n  private listenersInitialized = false;\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 constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\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 onAddToCartClicked(_event: Event) {\n    const button = this.shadowRoot.querySelector('button');\n    button.disabled = true;\n\n    let payload;\n    if (this.dataset.isSet === 'true') {\n      payload = this.composeSetProductPayload();\n    } else 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\n          // At the moment, there's a quantity selector only on the set PDP. So in this case always\n          // the default value \"1\" will be used.\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\n          // At the moment, there's a quantity selector only on the set PDP. So in this case always\n          // the default value \"1\" will be used.\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 composeSetProductPayload() {\n    const products = this.querySelectorAll('add-to-cart-product');\n    const variantIds = [];\n    for (const product of products) {\n      variantIds.push(product.dataset.selectedVariantId);\n    }\n\n    // Compose set properties. This object should be added to each product item in the add to cart\n    // request payload.\n    const setPropertiesElement = this.querySelector('add-to-cart-set');\n    const properties = {\n      'Set': setPropertiesElement.dataset.name,\n      '_is_set': 'true',\n      '_set_product_id': setPropertiesElement.dataset.id,\n      '_set_name': setPropertiesElement.dataset.name,\n      '_set_image_url': setPropertiesElement.dataset.imageUrl,\n      '_set_compare_at_price': setPropertiesElement.dataset.compareAtPrice,\n      '_set_price': setPropertiesElement.dataset.price,\n      _set_variant_ids: variantIds.join(',')\n    };\n\n    // A set can consist of similar products. If the same variants are selected for similar\n    // products, we shouldn't send them as different items but set the appropriate quantity.\n    const variantQuantities: Record<string, number> = {};\n    for (const variantId of variantIds) {\n      if (variantQuantities[variantId]) {\n        variantQuantities[variantId] = variantQuantities[variantId] + 1;\n      } else {\n        variantQuantities[variantId] = 1;\n      }\n    }\n\n    const payload: ShopifyAjaxApi.AddToCartPayload = { items: [] };\n    for (const id in variantQuantities) {\n      payload.items.push({\n        id: parseInt(id, 10),\n        properties,\n        quantity: variantQuantities[id] * this.quantity\n      });\n    }\n\n    return payload;\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const {\n      id,\n      available,\n      product_id: productId,\n      setIndex\n    } = event.detail.variant;\n\n    let product: HTMLElementTagNameMap['add-to-cart-product'];\n    if (this.dataset.isSet === 'true') {\n      // A set can consist of similar products. We need \"setIndex\" to distinguish them.\n      const selector = `add-to-cart-product[data-id=\"${productId}\"][data-set-index=\"${setIndex}\"]`;\n      product = this.querySelector(selector);\n    } else {\n      product = this.querySelector(`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\n    this.render();\n  }\n\n  /**\n   * Update the availability of the product for displaying either the add to cart button\n   * or the notify me button based on product availability.\n   */\n  private render() {\n    if (!this.listenersInitialized) {\n      this.listenersInitialized = true;\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\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 set with multiple\n    // <add-to-cart-product> elements. If no element is found, it means that the product or set\n    // can be added to the 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      // Set product ID and variant ID of the unavailable item.\n\n      // TODO: How to handle cases when two or more items of the set are unavailable? Currently,\n      // the data from the first unavailable item is used.\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","export default \":host{display:inline-flex;flex-direction:column;font-size:1rem;justify-content:flex-end;min-height:48px;width:100%}:host([data-button-variant=secondary]) button{background-color:#fff;border-color:#000;color:#000}:host([data-button-variant=secondary]) button:active,:host([data-button-variant=secondary]) button:hover{background-color:#f5f5f5}:host([data-button-variant=secondary]) button.added{background-color:#000;color:#fff;opacity:1}:host([data-button-variant=secondary]) button.added:hover .discount{background-color:#fff;color:#e71d13}:host([data-button-variant=secondary]) button.added .discount{padding-top:8px;text-indent:2px}:host([data-button-variant=secondary]) button.added .discount:after{background-image:url(\\\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M15.782 7.24V4.846C15.782 2.702 14.017 1 11.937 1S8.092 2.765 8.092 4.845v2.396H2.607L4.12 23h15.76l1.512-15.76h-5.61M9.29 4.846c0-1.45 1.198-2.584 2.585-2.584s2.584 1.197 2.584 2.584v2.396H9.226V4.845zm9.33 16.894H5.129L3.869 8.501h4.097v1.324h1.26V8.501h5.232v1.324h1.261V8.501h4.098L18.556 21.74z'/%3E%3C/svg%3E\\\");background-repeat:no-repeat;background-size:contain;content:\\\"\\\";height:24px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:24px}:host([data-discount-message]) button{padding-left:8px;padding-right:53px;position:relative}:host([data-discount-message]) button:hover{background-color:#000;color:#fff}:host([data-discount-message]) button:hover .discount{background-color:#e71d13;color:#fff}:host([data-discount-message]) .discount{display:flex}:host([data-price]) button{display:flex}:host([data-price]) .price{display:block}button{align-items:center;background-color:#000;border:1px solid #000;border-radius:0;color:#fff;cursor:pointer;flex-shrink:0;font-family:Poppins,sans-serif;font-size:inherit;font-weight:600;justify-content:center;letter-spacing:.16em;line-height:1;min-height:inherit;padding:10px 16px;text-align:center;text-transform:uppercase;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);white-space:nowrap;width:100%}button:active,button:hover{background-color:#333;border-color:#333}button:focus{outline:2px solid #000;outline-offset:1px}notify-me-button{min-height:inherit}button:disabled{cursor:default;opacity:.6}.price,slot:not([name]){display:none}.price{border-left:2px solid;margin-left:4px;padding-left:5px}.discount{align-items:center;background-color:#fff;border-left:1px solid #000;bottom:0;color:#e71d13;display:none;justify-content:center;line-height:1.1;position:absolute;right:0;top:0;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);white-space:normal;width:45px;z-index:1}\";","// Module\nvar code = \"<button>Add to Bag<span class=\\\"price\\\"></span><span class=\\\"discount\\\"></span></button><notify-me-button></notify-me-button><slot></slot>\";\n// Exports\nexport default code;","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  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  public shadowRoot!: ShadowRoot;\n\n  private onButtonClickedBound = this.onButtonClicked.bind(this);\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const button = this.shadowRoot.querySelector('button');\n    button.removeEventListener('click', this.onButtonClickedBound);\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","export default \":host{display:inline-block;font-size:1rem;min-height:48px;width:100%}button{align-items:center;background-color:#d6d6d6;border:1px solid #d6d6d6;border-radius:0;color:#545454;cursor:pointer;display:inline-flex;font-family:Poppins,sans-serif;font-size:inherit;font-weight:600;justify-content:center;letter-spacing:.16em;line-height:1;min-height:inherit;padding:10px 16px;text-align:center;text-transform:uppercase;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);white-space:nowrap;width:100%}button:active,button:hover{background-color:#d1d1d1;border-color:#d1d1d1}button:focus{outline:2px solid #000;outline-offset:1px}:host([hidden]){display:none}\";","// Module\nvar code = \"<button>Notify Me</button>\";\n// Exports\nexport default code;"],"names":["AddToCartProduct","HTMLElement","customElements","get","define","AddToCartSet","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","getRequestId","response","headers","error","async","cartFetch","url","Shopify","routes","root","body","fetch","cache","ok","Error","concat","status","request_id","response_body","json","isObject","value","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","attachToggleHandlers","variantToggles","document","querySelectorAll","toggle","addEventListener","onToggleClicked","preventDefault","element","currentTarget","targetId","getAttribute","toggleTarget","getElementById","classList","contains","textContent","setAttribute","addToCart","payload","lineItems","_window$Sentry","_len","arguments","length","args","_key","Sentry","captureException","extra","level","setTimeout","Event","CallUtils","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","createElement","innerHTML","cartContentElement","querySelector","LiquidGlobals","name","cartModalElement","modalContentElement","cartCount","replace","cartCounterElement","parseInt","add","remove","cartPageElement","ToggleSubLineItems","updateCartHtml","cart","ajax","cartUpdatedEvent","source","viewCartEvent","error_code","error_message","AddToCart","constructor","super","listenersInitialized","onAddToCartClickedBound","this","onAddToCartClicked","bind","onVariantChangedBound","onVariantChanged","onQuantityChangedBound","onQuantityChanged","attachShadow","mode","shadowRoot","connectedCallback","render","disconnectedCallback","removeEventListener","_event","button","disabled","dataset","isSet","composeSetProductPayload","isUpsell","composeUpsellProductPayload","composeRegularProductPayload","CartService","catch","finally","keepAddedState","renderAddedState","product_id","product","selectedVariantId","sellingPlan","getSellingPlan","selling_plan","properties","products","variantIds","setPropertiesElement","imageUrl","compareAtPrice","price","_set_variant_ids","join","variantQuantities","variantId","available","productId","setIndex","variant","selector","toString","notifyMe","discountMessage","unavailableProduct","hidden","productTitle","variantTitle","selectedVariantTitle","firstChild","discount","subscribeCheckbox","checked","selectedRadioElement","NotifyMeButton","onButtonClickedBound","onButtonClicked"],"sourceRoot":""}