(() => { var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); // js/webcomponents/utils/BaseComponent.ts var externalWebComponents = ["cart-header", "cart-items-list", "cart-footer"]; var BaseComponent = class extends HTMLElement { constructor(styles) { super(); this.attachShadow({ mode: "open" }); this.applyStyles(styles); } loadTemplate(templateName) { var _a; const template = this.children.namedItem(templateName); if (externalWebComponents.includes(templateName)) { const existingAttr = this.getAttribute("data-cart-drawer-target"); const attributes = existingAttr ? `${existingAttr} drawerComponent` : "drawerComponent"; this.setAttribute("data-cart-drawer-target", attributes); } if (template) { (_a = this.shadowRoot) == null ? void 0 : _a.appendChild(template); } } applyStyles(styles) { if (this.shadowRoot && styles) { try { const stylesheet = new CSSStyleSheet(); stylesheet.replaceSync(styles); this.shadowRoot.adoptedStyleSheets = [stylesheet]; } catch (e) { const styleElement = document.createElement("style"); styleElement.textContent = styles; this.shadowRoot.appendChild(styleElement); } } } }; // js/webcomponents/CartFooter/CartFooterStyles.ts var ctaLabels = [1, 2, 3, 4]; var ctaStyles = ctaLabels.reduce((acc, i) => { const styles = ` --button-cta-${i}-bg: var(--cart-drawer-footer-btn-bg-cta-${i}, #ffffff); --button-cta-${i}-fg: var(--cart-drawer-footer-btn-cl-cta-${i}, #000000); --button-cta-${i}-border: var(--cart-drawer-footer-btn-bd-cta-${i}, #000000); --button-cta-${i}-bg-hover: var(--cart-drawer-footer-btn-bg-cta-${i}-hover, #000000); --button-cta-${i}-fg-hover: var(--cart-drawer-footer-btn-cl-cta-${i}-hover, #ffffff); --button-cta-${i}-border-hover: var(--cart-drawer-footer-btn-bd-cta-${i}-hover, #000000); `; return `${acc} ${styles}`; }, ""); var CartFooterStyles_default = ` :host { --footer-bg: #ffffff; --footer-top-border-color: var(--cart-drawer-footer-top-border-cl, #f2f2f2); --footer-message-font: inherit; --footer-message-font-size: var(--cart-drawer-footer-message-font-size, 0.75rem); --footer-message-color: var(--cart-drawer-font-cl, #000000); --footer-shadow: var(--cart-drawer-footer-shadow, 0px -4px 12px rgba(0, 0, 0, 0.1)); --footer-shadow-overlay: var(--cart-drawer-overlay-footer-shadow, var(--footer-shadow)); --total-label-font: inherit; --total-label-font-size: var(--cart-drawer-estimated-total-label-font-size, 0.75rem); --total-label-color: var(--cart-drawer-font-cl, #000000); --total-label-font-weight: normal; --total-value-font: inherit; --total-value-font-size: var(--cart-drawer-item-price-font-size, 0.75rem); --total-value-font-weight: var(--cart-drawer-item-prices-weight, normal); --total-value-color: var(--cart-drawer-font-cl, #000000); --estimated-total-value-font-weight: var(--cart-drawer-footer-est-total-font-wt, var(--total-value-font-weight)); --count-font: var(--cart-drawer-footer-count-font, inherit); --count-font-size: var(--cart-drawer-item-price-font-size, 0.75rem); --count-color: var(--cart-drawer-font-cl, #000000); --count-text-transform: var(--cart-drawer-footer-count-text-transform, uppercase); ${ctaStyles} --button-font-size: var(--cart-drawer-footer-btn-font-size, 0.9375rem); --button-font: var(--cart-drawer-footer-btn-font, inherit); --button-flex-direction: column; --button-letter-spacing: var(--cart-drawer-footer-btn-letter-spacing, 1.8px); --button-text-transform: var(--cart-drawer-footer-btn-text-transform, uppercase); --button-font-weight: var(--cart-drawer-footer-btn-weight, normal); --price-font: var(--cart-drawer-item-price-font, inherit); --price-font-size: var(--cart-drawer-item-price-font-size, 0.875rem); --button-height: var(--cart-drawer-footer-btn-height, 60px); --button-border-radius: var(--cart-drawer-button-border-radius, 0); --toast-notification-bg: var(--cart-drawer-toast-container-bg, #404040); --toast-notification-color: var(--cart-drawer-toast-font-color, #ffffff); --footer-modal-box-shadow: var(--cart-footer-modal-box-shadow, none); --footer-modal-border-top: var(--cart-footer-modal-border-top, none); --footer-modal-message-display: var(--cart-drawer-footer-modal-message-display, block); --item-details-color: var(--cart-drawer-item-details-cl, #000000); } .cart-footer { position: relative; display: flex; flex-direction: column; padding: 16px; width: calc(100% - 32px); background-color: var(--footer-bg); border-top: solid 1px var(--footer-top-border-color); box-shadow: var(--footer-shadow); } .cart-footer.error { --footer-top-border-color: transparent; } .cart-footer.overlay { box-shadow: var(--footer-shadow-overlay, none); } .cart-footer.modal { box-shadow: var(--footer-modal-box-shadow); border-block-start: var(--footer-modal-border-top); } .cart-footer.modal .cart-additional-message { display: var(--footer-modal-message-display); } .cart-details { display: flex; justify-content: space-between; flex-direction: row; } .cart-buttons { display: flex; flex-direction: var(--button-flex-direction); gap: 12px; margin-block-start: 0.5rem; } [class*=cart-button--drawer-cta-], .cart-button--close { flex: var(--button-flex-props); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; letter-spacing: var(--button-letter-spacing); font-family: var(--button-font); font-weight: var(--button-font-weight); height: var(--button-height); font-size: var(--button-font-size); text-transform: var(--button-text-transform); border-radius: var(--button-border-radius); transition-duration: 0.3s; } [class*=cart-button--drawer-cta-] ::slotted(.cart-button), .cart-button--close ::slotted(.cart-button) { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; text-align: center; } .cart-button--close, .cart-button--drawer-cta-1 { border: solid 1px var(--button-cta-1-border); background: var(--button-cta-1-bg); color: var(--button-cta-1-fg); } .cart-button--drawer-cta-2 { border: solid 1px var(--button-cta-2-border); background: var(--button-cta-2-bg); color: var(--button-cta-2-fg); } .cart-button--drawer-cta-3 { border: solid 1px var(--button-cta-3-border); background: var(--button-cta-3-bg); color: var(--button-cta-3-fg); } .cart-button--drawer-cta-4 { border: solid 1px var(--button-cta-4-border); background: var(--button-cta-4-bg); color: var(--button-cta-4-fg); } .cart-count { align-self: end; font-size: var(--count-font-size); font-family: var(--count-font); font-weight: bold; color: var(--count-color); text-transform: var(--count-text-transform); letter-spacing: var(--cart-drawer-item-price-letter-spacing); line-height: var(--cart-drawer-item-price-line-height); } .cart-estimated-total-label { font-size: var(--total-label-font-size); font-family: var(--total-label-font); color: var(--total-label-color); font-weight: var(--total-label-font-weight); } .cart-estimated-total-value { font-size: var(--price-font-size); font-family: var(--price-font); color: var(--total-value-color); font-weight: var(--estimated-total-value-font-weight); letter-spacing: var(--cart-drawer-item-price-letter-spacing); line-height: var(--cart-drawer-item-price-line-height); } .cart-gst-label { font-size: var(--cart-drawer-item-details-font-size, 0.875rem); font-weight: var(--cart-drawer-item-details-font-weight, 400); line-height: var(--cart-drawer-item-details-line-height, 1.5); letter-spacing: var(--cart-drawer-item-details-letter-spacing, 0.005em); color: var(--item-details-color); text-align: end; } .cart-additional-message { font-size: var(--footer-message-font-size); font-family: var(--footer-message-font); color: var(--footer-message-color); margin-block-start: 1rem; } ::slotted(.cart-toast-notification) { background-color: var(--toast-notification-bg); color: var(--toast-notification-color); text-transform: uppercase; padding: 0.75rem; font-size: 0.75rem; position: absolute; min-width: 340px; max-width: 345px; bottom: -100%; animation: cartToastSlideIn 0.5s forwards, cartToastSlideOut 0.5s 3s forwards; } ::slotted(.cart-toast-notification.hidden) { display: none; } @media (min-width: 768px) { :host { --button-flex-props: 1 1 50%; --button-flex-direction: row; } } @media (hover: hover) { .cart-button--close:hover, .cart-button--drawer-cta-1:hover { background: var(--button-cta-1-bg-hover); color: var(--button-cta-1-fg-hover); border: solid 1px var(--button-cta-1-border-hover); } .cart-button--drawer-cta-2:hover { background: var(--button-cta-2-bg-hover); color: var(--button-cta-2-fg-hover); border: solid 1px var(--button-cta-2-border-hover); } .cart-button--drawer-cta-3:hover { background: var(--button-cta-3-bg-hover); color: var(--button-cta-3-fg-hover); border: solid 1px var(--button-cta-3-border-hover); } .cart-button--drawer-cta-4:hover { background: var(--button-cta-4-bg-hover); color: var(--button-cta-4-fg-hover); border: solid 1px var(--button-cta-4-border-hover); } } `; // js/webcomponents/CartFooter/CartFooter.ts var CartFooter = class extends BaseComponent { constructor() { super(CartFooterStyles_default); this.loadTemplate("cart-footer"); } }; try { if (!customElements.get("cart-footer")) { customElements.define("cart-footer", CartFooter); } } catch (error2) { console.info("[Cart 3.0] cart-footer definition failed: ", error2); } // js/webcomponents/CartHeader/CartHeaderStyles.ts var cartHeaderStyles = ` :host { --close-icon-size: var(--cart-drawer-close-icon-size, 24px); --close-icon-color: var(--cart-drawer-close-icon-color, #000000); --check-icon-size-width: 24px; --check-icon-size-height: 24px; --error-title-color: var(--cart-drawer-error-title-color, #a80000); --error-icon-color: var(--cart-drawer-error-title-color, #a80000); --check-icon-color: var(--cart-drawer-title-icon-color, var(--cart-drawer-title-color, #000000)); --title-bg-color: #ffffff; --title-border-color: var(--cart-drawer-title-bd-cl, #d4d4d4); --title-font-family: var(--cart-drawer-title-font, inherit); --title-font-size: var(--cart-drawer-title-font-size, 1rem); --title-text-transform: var(--cart-drawer-title-text-transform, uppercase); --title-line-height: var(--cart-drawer-title-line-height, 1.25); --title-font-weight: bold; --title-letter-spacing: var(--cart-drawer-title-letter-spacing, inherit); --title-color: var(--cart-drawer-title-color, #000000); --message-fg-color: var(--cart-drawer-font-cl, #000000); --message-error-fg-color: var(--cart-drawer-error-font-cl, var(--message-fg-color)); --message-font-family: inherit; --message-font-size: var(--cart-drawer-message-font-size, 0.75rem); --message-line-height: 1.25; --message-alignment: flex-start; --message-bg-color: var(--cart-drawer-message-bg, #fafafa); --message-error-bg-color: var(--cart-drawer-error-bg, var(--message-bg-color)); --modal-title-border-top: var(--cart-modal-title-border-top, none); --modal-handle-color: var(--cart-modal-handle-color, #d4d4d4); } .cart-header { display: flex; flex-direction: row; flex-wrap: var(--cart-drawer-header-flex-wrap, wrap); width: calc(100% - 32px); align-items: center; padding: var(--cart-drawer-header-padding, 12px 16px); justify-content: space-between; text-transform: var( --title-text-transform); background-color: var(--title-bg-color); border-bottom: 1px solid var(--title-border-color); border-top: var(--cart-drawer-title-border-top, none); font-family: var(--title-font-family); font-size: var(--title-font-size); line-height: var(--title-line-height); font-weight: var(--title-font-weight); letter-spacing: var(--title-letter-spacing); color: var(--title-color); } .cart-header--modal { border-top: var(--modal-title-border-top); } .cart-header.error { color: var(--error-title-color); justify-content: var(--cart-drawer-hide-title-justify-content, space-between); border-bottom-color: var(--cart-drawer-hide-title-border-color, var(--title-border-color)); } .cart-header-title { display: flex; gap: 11px; align-items: center; } .cart-header.error .cart-header-title { display: var(--cart-drawer-hide-title-display, flex); } .cart-messages { display: flex; flex-direction: column; padding: 12px 16px; gap: 8px; width: calc(100% - 32px); justify-content: center; color: var(--message-fg-color); background-color: var(--message-bg-color); font-family: var(--message-font-family); font-size: var(--message-font-size); line-height: var(--message-line-height); align-items: var(--message-alignment); border-bottom: 1px solid var(--cart-drawer-message-border-bottom, transparent); } .cart-messages.error-messages { color: var(--message-error-fg-color); background-color: var(--message-error-bg-color); } .cart-header-title .cart-svg { display: block; } ::slotted(.cart-header__close-button) { width: var(--close-icon-size); height: var(--close-icon-size); fill: var(--close-icon-color); cursor: pointer; } .cart-drawer__handle-wrapper { display: var(--modal-handle-display); justify-content: center; margin-block: -1rem; width: 100%; } ::slotted(.cart-drawer__handle) { cursor: grab; padding: 1rem; } ::slotted(.cart-drawer__handle)::before { background-color: var(--modal-handle-color); border-radius: 2px; content: ''; display: block; height: 3px; margin-block-end: 10px; margin-inline: auto; width: 32px; } @media (min-width: 1024px) { :host { --title-font-size: var(--cart-drawer-title-font-size, 0.875rem); --title-line-height: var(--cart-drawer-title-line-height, 1.43); } } `; var cartFreeShippingBarStyles = ` :host { --free-shipping-progress-color: var(--cart-drawer-font-cl, #000000); --free-shipping-progress-bg-color: var(--cart-drawer-font-cl, #e3e3e3); --free-shipping-border-color: var(--cart-drawer-title-bd-cl, #d4d4d4); } .cart-free-shipping { padding: 16px; display: flex; justify-content: center; align-items: center; border-bottom: 1px solid var(--free-shipping-border-color); } .cart-free-shipping .cart-free-shipping__container { width: 100%; } .cart-free-shipping .cart-free-shipping__label { font-size: 0.813rem; } .cart-free-shipping .cart-free-shipping__progress-bar { width: 100%; height: 4px; margin-block-start: 10px; background-color: var(--free-shipping-progress-bg-color); } .cart-free-shipping .cart-free-shipping__progress { height: 100%; background-color: var(--free-shipping-progress-color); } `; var cartAlertStyles = ` :host { --alert-bg-color: var(--cart-drawer-alert-bg-color, #FEF1F1); --alert-font-color: var(--cart-drawer-alert-font-cl, #D0021B); --alert-font-transform: var(--cart-drawer-font-cl, #D0021B); } .cart-alerts ::slotted(.cart-alert__container) { display: flex; align-items: flex-start; font-size: 0.75rem; color: var(--alert-font-color); margin: 16px; text-transform: uppercase; font-weight: 450; gap: 12px; padding: 12px; background-color: var(--alert-bg-color); } `; var CartHeaderStyles_default = cartAlertStyles + cartHeaderStyles + cartFreeShippingBarStyles; // js/webcomponents/CartHeader/CartHeader.ts var CartHeader = class extends BaseComponent { constructor() { super(CartHeaderStyles_default); this.loadTemplate("cart-header"); } }; try { if (!customElements.get("cart-header")) { customElements.define("cart-header", CartHeader); } } catch (error2) { console.info("[Cart 3.0] cart-header definition failed: ", error2); } // js/webcomponents/CartItemsList/CartItemStyles.ts var cartItemStyles = ` :host { --font-color: var(--cart-drawer-font-cl, #000000); --font-color-sec: var(--cart-drawer-font-cl-sec, #606060); --item-border: var(--cart-drawer-item-bd, #cccccc); --item-background: var(--cart-drawer-item-bg, #ffffff); --quantity-btn-size: var(--cart-drawer-item-qty-size, 32px); --quantity-btn-bg: var(--cart-drawer-item-qty-bg, #ffffff); --quantity-btn-bd: var(--cart-drawer-item-qty-bd, #a3a3a3); --quantity-btn-cl: var(--cart-drawer-item-qty-cl, #000000); --quantity-btn-cl-disabled: var(--cart-drawer-item-qty-cl-disabled, #a3a3a3); --quantity-btn-bd-disabled: var(--cart-drawer-item-qty-bd-disabled, #d4d4d4); --sample-label-font: var(--cart-drawer-item-sample-font, inherit); --item-name-display: var(--cart-drawer-item-name-display, flex); --item-name-margin: var(--cart-drawer-item-name-margin, 0 8px 0 0); --item-name-font: var(--cart-drawer-item-name-font, inherit); --item-name-text-transform: var(--cart-drawer-item-name-text-transform, normal); --item-details-color: var(--cart-drawer-item-details-cl, #000000); --item-details-text-transform: var(--cart-drawer-item-text-transform, none); --item-details-shade-radius: var(--cart-drawer-item-shade-radius, 50%); --item-details-shade-border-color: var(--cart-drawer-item-shade-border-color, #737373); --item-details-shade-border-padding: var(--cart-drawer-item-shade-border-padding, 4px); --item-shade-text-transform: var(--cart-drawer-item-shade-transform, none); --item-sub-header-font: var(--cart-drawer-item-sub-header-font, var(--price-font)); --button-remove-font-size: var(--cart-drawer-remove-button-font-size, 0.875rem); --button-remove-font-weight: var(--cart-drawer-remove-button-font-weight, 400); --button-remove-line-height: var(--cart-drawer-remove-button-line-height, 1.5); --button-remove-letter-spacing: var(--cart-drawer-remove-button-letter-spacing, 0.005em); --price-font: var(--cart-drawer-item-price-font, inherit); --price-font-size: var(--cart-drawer-item-price-font-size, 0.875rem); --price-text-transform: var(--cart-drawer-item-price-text-transform, none); --prices-weight: var(--cart-drawer-item-prices-weight, 400); --discounted-price-opacity: var(--cart-drawer-item-discounted-op, 1); --discounted-price-color: var(--cart-drawer-item-discounted-cl, --font-color); --discount-percent-color: var(--cart-drawer-item-discount-percent-cl, --font-color); --old-price-color: var(--cart-drawer-item-old-price-cl, --font-color); --button-remove-text-transform: var(--cart-drawer-item-rm-text-transform, capitalize); --engraving-line-color: var(--cart-drawer-item-engr-line-cl, #EBEAEF); --reward-points-opacity: var(--cart-drawer-item-reward-points-op, 1); --reward-points-color: var(--cart-drawer-item-reward-points-cl, --font-color); --rewards-opacity: var(--cart-drawer-item-rewards-op, 1); --rewards-color: var(--cart-drawer-item-rewards-cl, --font-color); color: var(--font-color); } ::slotted(span:empty) { display: none; } ::slotted(img) { width: var(--cart-drawer-item-image-width, 80px); max-height: var(--cart-drawer-item-image-height, auto); max-width: 100%; margin: auto; opacity: 0; transition: opacity 0.2s ease-in-out; } ::slotted(img.loaded) { opacity: 1; } ::slotted(.cart-item__shade-color), .cart-item__shade-color { width: 16px; height: 16px; border-radius: var(--item-details-shade-radius); } ::slotted(.cart-item__shade-color.multi), .cart-item__shade-color.multi { display: flex; flex-wrap: wrap; } .cart-item__shade-contents { display: flex; align-items: center; } p { margin: 0; } .cart-item { display: flex; padding: 16px; align-items: start; background-color: var(--item-background); } .cart-item.modal.bundled { padding: 16px 0; } .cart-item-container { position: relative; } .cart-item-loader { position: absolute; top: 0; width: 100%; height: 0; overflow: hidden; display: flex; justify-content: center; align-items: center; cursor: default; transition-property: height; opacity: 0.4; transition-delay: 2s; background-color: #fff; } .cart-item-container.loading .cart-item-loader { height: 100%; } .cart-item.overlay { border-block-start: 1px solid var(--item-border); } .cart-item__thumbnail { flex: 0 0 88px; margin-inline-end: 16px; max-height: 106px; min-height: 80px; width: 80px; text-align: center; background-color: var(--cart-drawer-item-image-bg-color, transparent); } .cart-item__thumbnail.bundled { margin-inline-end: 0; max-height: 86px; min-height: 3rem; width: 3rem; } .cart-item__thumbnail.bundled.last_bundled { filter: brightness(60%); } ::slotted(.cart-item__bundled-extra) { position: absolute; inset-block-start: 35%; inset-inline-start: 25%; color: white; font-size: 1.5rem; } .cart-item__custom-kit { display: flex; column-gap: 24px; row-gap: 8px; margin-block-start: 8px; flex-direction: var(--cart-drawer-item-kit-shade-direction, column); } .cart-item__custom-kit .cart-item__quantity-readonly-label { margin-block-start: 0; } .cart-item__custom-kit .cart-item__price { flex: 1; margin-block-start: 0; } .cart-item__kit-items { display: flex; gap: 8px; flex-direction: column; margin-block: 8px; } .cart-item__kit--dramming .cart-item__kit-thumbnail, .cart-item__kit--dramming .cart-item__name { display: none; } .cart-item__kit--dramming .kit-shades { margin-block-start: 0; } .cart-item__kit { display: flex; align-items: start; background-color: var(--item-background); } .cart-item__kit-thumbnail { flex: 0 0 40px; margin-inline-end: 16px; height: 40px; text-align: center; overflow: hidden; } .cart-item__kit-thumbnail-image { max-width: 100%; height: 100%; } .cart-item__description { flex: 1; } .cart-item__description.bundled { display: none; } .cart-item__header { display: flex; align-items: flex-start; justify-content: space-between; } .cart-item__full-name { text-decoration: none; color: inherit; } .cart-item__name, .cart-item__sub-header { flex: 0 0 1; display: var(--item-name-display); font-size: var(--cart-drawer-item-name-font-size, 0.875rem); font-weight: var(--cart-drawer-item-name-font-weight, 600); line-height: var(--cart-drawer-item-name-line-height, 1.4); word-wrap: break-word; letter-spacing: var(--cart-drawer-item-name-letter-spacing, 0.005em); margin: var(--item-name-margin); font-family: var(--item-name-font); text-transform: var(--item-name-text-transform); } .cart-item__sub-header { display: var(--cart-drawer-item-sub-name-display, var(--item-name-display)); } .cart-item__kit-sub-header { font-size: var(--cart-drawer-item-details-font-size, 0.875rem); margin: 0 8px 0 0; font-family: var(--item-sub-header-font); text-transform: var(--item-name-text-transform); } .cart-item__details { gap: 8px; display: flex; align-items: start; flex-direction: column; font-size: var(--cart-drawer-item-details-font-size, 0.875rem); font-weight: var(--cart-drawer-item-details-font-weight, 400); line-height: var(--cart-drawer-item-details-line-height, 1.5); letter-spacing: var(--cart-drawer-item-details-letter-spacing, 0.005em); margin-block-start: var(--cart-drawer-item-details-margin-top, 8px); color: var(--item-details-color); text-transform: var(--item-details-text-transform, none); } .cart-item__shade { display: flex; align-items: center; color: var(--cart-drawer-item-shade-cl, var(--item-details-color)); font-weight: var(--cart-drawer-item-shade-font-weight, normal); text-transform: var(--item-shade-text-transform); line-height: 1.3; row-gap: 8px; } .kit-shades .cart-item__shade, .cart-item__kit-details .cart-item__shade { flex-direction: var(--cart-drawer-item-kit-shade-direction, column); align-items: start; } .cart-item_shade-wrapper { border: 0.5px solid var(--item-details-shade-border-color); padding: var(--item-details-shade-border-padding); border-radius: var(--item-details-shade-radius); display: inline-block; margin-inline-end: 5px; } .kit-shades .cart-item_shade-wrapper { display: flex; } .cart-item__price .cart-item__sku-type { color: var(--font-color-sec); text-transform: var(--price-text-transform); font-family: var(--sample-label-font); font-weight: var(--cart-drawer-item-type-font-weight, normal); } .cart-item__price { display: flex; font-family: var(--price-font); font-size: var(--price-font-size); justify-content: space-between; margin-block-start: var(--cart-drawer-item-price-margin-top, 14px); letter-spacing: var(--cart-drawer-item-price-letter-spacing); line-height: var(--cart-drawer-item-price-line-height, 1.5); } .cart-item__price .cart-item__prices { gap: 4px; display: flex; flex-wrap: wrap; color: var(--font-color); font-weight: var(--prices-weight); line-height: var(--cart-drawer-item-price-line-height, 1.5); margin-inline-end: 8px; } .cart-item__price .cart-item__prices.reward { gap: 0; } .cart-item__engraving-price .old-price, .cart-item__prices ::slotted(.old-price) { opacity: var(--discounted-price-opacity); text-decoration: line-through; color: var(--old-price-color); } .cart-item__prices ::slotted(.rewards) { opacity: var(--rewards-opacity); color: var(--rewards-color); } .cart-item__prices ::slotted(.discount-percent) { color: var(--discount-percent-color); } .cart-item__prices ::slotted(.discounted-price) { color: var(--discounted-price-color); font-weight: var(--cart-drawer-discounted-price-weight, var(--prices-weight)); } .cart-item__total-price { font-weight: var(--cart-drawer-item-total-price-weight, var(--prices-weight)); font-family: var(--price-font); line-height: var(--cart-drawer-item-price-line-height, 1.5); letter-spacing: var(--cart-drawer-item-price-letter-spacing); text-transform: var(--cart-drawer-total-price-text-transform, uppercase); } .cart-item__total-price ::slotted(.reward-points) { opacity: var(--reward-points-opacity); color: var(--reward-points-color); text-transform: capitalize; } .cart-item__quantity-readonly-label { margin: 0; line-height: 1.5; font-size: var(--cart-drawer-item-quantity-font-size, 0.875rem); margin-block-start: 8px; color: var(--cart-drawer-item-quantity-readonly-cl, inherit); } .cart-item-quantity-limit-wrapper, .cart-item-quantity-oos-wrapper, .cart-item-order-qty-limit-wrapper { display: flex; position: absolute; margin-block-start: 8px; inset-inline: 1rem; } .cart-item__replenishment { font-size: 0.75rem; line-height: 20px; letter-spacing: 1.8px; margin-block-start: 8px; text-transform: uppercase; color: var(--font-color); } .cart-item__quantity_limit, .cart-item__quantity_oos, .cart-item__order_quantity_limit { margin: auto; display: flex; justify-content: center; align-items: center; padding: 12px; color: var(--cart-drawer-item-quantity-limit-color, #a80000); font-size: var(--cart-drawer-item-quantity-limit-font-size); font-weight: var(--cart-drawer-item-quantity-limit-font-weight); line-height: var(--cart-drawer-item-quantity-limit-line-height); background-color: var(--cart-drawer-item-quantity-limit-bg, #f9eeee); border: 1px solid var(--cart-drawer-item-quantity-limit-border-color); } . .cart-item__quantity_limit::before, .cart-item__quantity_oos::before, .cart-item__order_quantity_limit::before { position: absolute; content: ''; inset-block-start: -8px; border-style: solid; border-width: 0 8px 8px 8px; border-color: transparent transparent var(--cart-drawer-item-quantity-limit-border-color) transparent; } .cart-item__quantity_limit::after, .cart-item__quantity_oos::after, .cart-item__order_quantity_limit::after { position: absolute; content: ''; inset-block-start: -7px; border-style: solid; border-width: 0 8px 8px 8px; border-color: transparent transparent var(--cart-drawer-item-quantity-limit-bg) transparent; } .cart-item-quantity-limit-wrapper.hidden, .cart-item-quantity-oos-wrapper.hidden, .cart-item-order-qty-limit-wrapper.hidden { display: none; } .cart-item__btn-remove { border: none; cursor: pointer; background: none; width: fit-content; font-family: var(--button-remove-font); font-size: var(--button-remove-font-size); font-weight: var(--button-remove-font-weight); line-height: var(--button-remove-line-height); letter-spacing: var(--button-remove-letter-spacing); text-decoration: underline; text-transform: var(--button-remove-text-transform); margin-block-start: 16px; } .cart-item__quantity { display: inline-flex; align-items: center; margin-block-start: 14px; border: var(--cart-drawer-item-quantity-border, none); } .cart-item__quantity-input { margin: 0; border: none; padding: var(--cart-drawer-item-quantity-input-padding, 0 12px); width: fit-content; background-color: transparent; color: var(--cart-drawer-item-quantity-cl, #000000); font-size: var(--cart-drawer-item-quantity-input-font-size, inherit); } .cart-item__quantity-button { --cart-qty-icon-color: var(--quantity-btn-cl); margin: 0; width: var(--quantity-btn-size); height: var(--quantity-btn-size); font-weight: bold; text-align: center; border: 1px solid var(--quantity-btn-bd); background-color: var(--quantity-btn-bg); color: var(--quantity-btn-cl); } .cart-item__quantity-button.disabled { --cart-qty-icon-color: var(--quantity-btn-cl-disabled); color: var(--quantity-btn-cl-disabled); border: solid 1px var(--quantity-btn-bd-disabled); cursor: not-allowed; } .cart-item__quantity-button ::slotted(span[slot]) { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; cursor: pointer; } .cart-item__quantity-button.disabled ::slotted(span[slot]) { cursor: not-allowed; } .cart-item__engraving { display: flex; flex-direction: column; margin: 4px 16px 16px; border-top: 1px solid var(--engraving-line-color); } .cart-item__engraving-details { display: flex; padding-top: 16px; justify-content: space-between; } .cart-item__engraving-details p { font-weight: bold; font-size: 0.75rem; text-transform: uppercase; } .cart-item__engraving-price { gap: 12px; display: flex; font-weight: bold; font-size: 0.75rem; } .cart-item__engraving-label { font-size: 0.813rem; } .kit-shades { display: flex; flex-direction: column; align-items: flex-start; justify-items: center; font-size: var(--cart-drawer-item-details-font-size, 0.875rem); color: var(--item-details-color); text-transform: var(--item-details-text-transform, none); font-weight: var(--cart-drawer-item-details-font-weight, 400); line-height: var(--cart-drawer-item-details-line-height, 1.5); letter-spacing: var(--cart-drawer-item-details-letter-spacing, 0.005em); } .kit-shades .cart-item__shade-contents + .cart-item__size, .kit-shades .cart-item__shade-name + .cart-item__size { border-left: solid var(--cart-drawer-item-size-border-width, 1px) var(--item-border); margin-inline-start: var(--cart-drawer-item-size-margin-top, 8px); padding-inline-start: var(--cart-drawer-item-size-padding-left, 8px); } @media (min-width: 768px) { .cart-item__thumbnail.bundled { min-height: 3.8rem; width: 3.8rem; } } `; var cartItemsListStyles = ` slot[name="cart-items"] { display: flex; flex-direction: column; justify-content: center; background-color: var(--cart-drawer-item-bg, #ffffff); border-block-end: solid 1px var(--cart-drawer-item-bd, transparent); } slot[name="cart-items"].bundled { gap: 10px; flex-direction: row; justify-content: flex-start; padding-inline: 16px; } slot[name="cart-items"].bundled::slotted(:nth-child(n+7)) { display: none; } ::slotted(.cart-error-container) { padding: 16px; } .bag-icon { display: flex; justify-content: center; align-items: center; margin-block-start: 32px; } .cart-svg { width: var(--cart-drawer-bag-icon-size-width, 20px); height: var(--cart-drawer-bag-icon-size-height, 20px); fill: var(--cart-drawer-bag-icon-color, #000000); } .empty-bag-message { font-family: var(--cart-drawer-empty-message-font-family); font-size: var(--cart-drawer-empty-message-font-size, 1.25rem); text-transform: var(--cart-drawer-empty-title-transform, none); font-weight: var(--cart-drawer-empty-message-font-weight, normal); line-height: var(--cart-drawer-empty-title-line-height, 1.136); letter-spacing: var(--cart-drawer-empty-letter-spacing, 0); text-align: center; color: var(--cart-drawer-empty-message-font-color, --font-color); margin-inline: 32px; margin-block: 16px 32px; } .sign-in-link { font-size: var(--cart-drawer-sign-in-font-size, 0.875rem); font-weight: normal; line-height: var(--cart-drawer-sign-in-line-height, 1.428); letter-spacing: var(--cart-drawer-sign-in-letter-spacing, 0); text-align: center; color: var(--cart-drawer-sign-in-font-color, --font-color); margin-inline: 32px; margin-block: -16px 32px; } .sign-in-link a { color: inherit; text-decoration: underline; } ::slotted(:first-child) { --item-border: transparent; } `; // js/webcomponents/CartItemsList/CartEngravingStyles.ts var cartEngravingRules = ` .Optima { font-family: Optima; } .Roman { font-family: Nh4Roman; } .Script { font-family: Script; } .Arial_Uni { font-family: ArialOSRegular; } .Roman_L_Monog_aBc, .Roman_L_Monog_abc { font-family: Roman_L_Monog_aBc; } .Interlock_M_Script_aBc, .Interlock_M_Script_abc { font-family: Interlock-M-Script-abc; } `; // js/webcomponents/CartItemsList/CartItem.ts var CartItem = class extends BaseComponent { constructor() { const styles = `${cartItemStyles} ${cartEngravingRules}`; super(styles); this.loadTemplate(this.templateName); } get templateName() { return this.getAttribute("data-cart-item-type-value") || "cart_item"; } }; try { if (!customElements.get("cart-item")) { customElements.define("cart-item", CartItem); } } catch (error2) { console.info("[Cart 3.0] cart-item definition failed: ", error2); } // js/webcomponents/CartItemsList/CartItemsList.ts var CartItemsList = class extends BaseComponent { constructor() { super(cartItemsListStyles); this.loadTemplate("cart-items-list"); } }; try { if (!customElements.get("cart-items-list")) { customElements.define("cart-items-list", CartItemsList); } } catch (error2) { console.info("[Cart 3.0] cart-items-list definition failed: ", error2); } // js/webcomponents/CartDrawer/CartDrawerStyles.ts var CartDrawerStyles_default = ` :host { --background-dim-color: var(--cart-drawer-bg-dim-color, rgba(0, 0, 0, 0.4)); --cart-overlay-display-mobile: none; --modal-animation: var(--cart-modal-animation, fadeInAnimation 0.5s ease forwards); --modal-border: var(--cart-modal-border, 1px solid rgba(0, 0, 0, 0.4)); --modal-border-radius: var(--cart-modal-border-radius, 0); --modal-display: var(--cart-modal-display, flex); --modal-height: var(--cart-modal-height, auto); --modal-max-height: var(--cart-modal-max-height, 80vh); --modal-max-width: var(--cart-modal-max-width, none); --modal-min-width: var(--cart-modal-min-width, 358px); --modal-opacity: var(--cart-modal-opacity, 0); --modal-transform: var(--cart-modal-transform, translate(-50%, -50%)); --modal-transition: var(--cart-modal-transition, none); --modal-width: var(--cart-modal-width, calc(100% - 32px)); --modal-inset-block-start: var(--cart-modal-inset-block-start, 50%); --modal-inset-block-end: var(--cart-modal-inset-block-end, auto); --modal-inset-inline-start: var(--cart-modal-inset-inline-start, 50%); --modal-inset-inline-end: var(--cart-modal-inset-inline-end, auto); --modal-footer-box-shadow: var(--cart-modal-footer-box-shadow, none); --modal-hidden-animation: var(--cart-modal-hidden-animation, fadeOutAnimation 0.5s ease forwards); --modal-hidden-display: var(--cart-modal-hidden-display, none); --modal-handle-display: var(--cart-modal-handle-display, none); --overlay-slide-in-animation: var(--cart-overlay-slide-in-animation, slideInFromRight); --overlay-slide-out-animation: var(--cart-overlay-slide-out-animation, slideOutToRight); } .cart-wrapper__overlay ::slotted(cart-items-list) { height: 100%; min-width:380px; overflow-y: auto; overflow-x: hidden; background-color: var(--cart-drawer-items-list-bg, #ffffff); } .cart-wrapper { display: flex; font-family: var(--cart-wrapper-font-family, inherit); letter-spacing: var(--cart-wrapper-letter-spacing, normal); visibility: var(--cart-wrapper-visibility, hidden); } .cart-wrapper__modal { position: fixed; inset-block-start: var(--modal-inset-block-start); inset-block-end: var(--modal-inset-block-end); inset-inline-start: var(--modal-inset-inline-start); inset-inline-end: var(--modal-inset-inline-end); background-color: white; border-radius: var(--modal-border-radius); overflow: hidden; z-index: 999999; transform: var(--modal-transform); transition: var(--modal-transition); border: var(--modal-border); opacity: var(--modal-opacity); animation: var(--modal-animation); min-width: var(--modal-min-width); max-width: var(--modal-max-width); width: var(--modal-width); height: var(--modal-height); max-height: var(--modal-max-height); display: var(--modal-display); flex-direction: column; font-family: var(--cart-drawer-font, inherit); outline: none; } .cart-wrapper__modal ::slotted(cart-items-list) { height: 100%; overflow-y: auto; overflow-x: hidden; } .cart-wrapper__modal.hidden--onload { display: none; } .cart-wrapper__modal.hidden { animation: var(--modal-hidden-animation); } slot[name="background"]::slotted(.cart-wrapper__bg) { opacity: 1; } slot[name="background"].hidden::slotted(.cart-wrapper__bg) { visibility: hidden; opacity: 0; } .cart-wrapper__overlay { display: var(--cart-overlay-display-mobile); flex-direction: column; position: fixed; top: 0; inset-inline-end: 0; max-width: 380px; height: 100vh; background-color: white; overflow: hidden; z-index: 999999; transition: 0.1s; animation: var(--overlay-slide-in-animation) 0.2s ease-in-out forwards; outline: none; } .cart-wrapper__overlay.hidden { animation: var(--overlay-slide-out-animation) 0.2s ease-in-out forwards; } ::slotted(.cart-wrapper__bg) { inset-inline-start: 0; width: 100vw; z-index: 999998; min-width: 100vw; position: fixed; top: 0; height: 100vh; transition: 0.2s ease all; background-color: var(--background-dim-color); } ::slotted(.cart-wrapper__bg.modal), ::slotted(.cart-wrapper__bg.cart-modal) { top: 0; height: 100vh; } ::slotted(.cart-wrapper__bg.overlay), ::slotted(.cart-wrapper__bg.cart-overlay) { display: var(--cart-overlay-display-mobile); top: 0; height: 100vh; width: calc(100vw - 380px); min-width: calc(100vw - 380px); } .cart-wrapper__bg-placeholder { background-color: var(--background-dim-color); position: fixed; top: 0; inset-inline-end: 0; content: ''; overflow: hidden; opacity: 1; transition: 0.2s ease all; visibility: visible; outline: none; } .cart-wrapper__bg-placeholder.overlay { width: 380px; z-index: 999999; height: 100vh; } .cart-wrapper__bg-placeholder.hidden { visibility: hidden; opacity: 0; } .cart-wrapper__button { display: flex; align-items: center; justify-content: center; cursor: pointer; height: var(--cart-button-height); width: var(--cart-button-width); color: var(--cart-button-fg); background-color: var(--cart-button-bg); border: 1px solid var(--cart-button-border-color); border-radius: var(--cart-button-border-radius); font-size: var(--cart-button-font-size); } .cart-drawer__fullscreen { border-radius: 0; height: 100dvh; } @keyframes slideInFromRight { 0% { transform: translateX(100%); opacity: 0; } 100% { transform: translateX(0); opacity: 1; } } @keyframes slideOutToRight { 0% { transform: translateX(0); opacity: 1; } 100% { transform: translateX(100%); opacity: 0; visibility: hidden; } } @keyframes slideInFromLeft { 0% { transform: translateX(-100%); opacity: 0; } 100% { transform: translateX(0); opacity: 1; } } @keyframes slideOutToLeft { 0% { transform: translateX(0); opacity: 1; } 100% { transform: translateX(-100%); opacity: 0; visibility: hidden; } } @keyframes fadeInAnimation { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fadeOutAnimation { 0% { opacity: 1; } 100% { opacity: 0; visibility: hidden; } } @keyframes slideUp { 0% { transform: translateY(100%); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } } @keyframes slideDown { 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(100%); opacity: 0; visibility: hidden; } } @media(min-width: 768px) { :host { --modal-max-width: var(--cart-modal-max-width, 450px); } } @media(min-width: 1024px) { :host { --cart-overlay-display-mobile: flex; } } `; // js/webcomponents/CartDrawer/CartDrawer.ts var CartDrawer = class extends BaseComponent { constructor() { super(CartDrawerStyles_default); this.setTemplates(); } setTemplates() { if (this.shadowRoot) { const wrapper = document.createElement("div"); wrapper.classList.add("cart-wrapper"); wrapper.id = "cart-wrapper"; const bgPlaceholder = document.createElement("div"); bgPlaceholder.classList.add("cart-wrapper__bg-placeholder"); bgPlaceholder.setAttribute("data-cart-element", "background"); bgPlaceholder.classList.add("hidden"); const background = document.createElement("slot"); background.classList.add("hidden"); background.name = "background"; background.setAttribute("data-cart-element", "background"); const modal = document.createElement("div"); modal.classList.add("cart-wrapper__modal", "hidden--onload"); modal.setAttribute("data-cart-element", "modal"); modal.setAttribute("role", "dialog"); modal.setAttribute("aria-modal", "true"); const modalSlot = document.createElement("slot"); modalSlot.name = "modal"; modal.appendChild(modalSlot); const overlay = document.createElement("div"); overlay.classList.add("cart-wrapper__overlay"); overlay.classList.add("hidden"); overlay.setAttribute("data-cart-element", "overlay"); overlay.setAttribute("role", "dialog"); overlay.setAttribute("aria-modal", "true"); const overlaySlot = document.createElement("slot"); overlaySlot.name = "overlay"; overlay.appendChild(overlaySlot); wrapper.appendChild(bgPlaceholder); wrapper.appendChild(background); wrapper.appendChild(modal); wrapper.appendChild(overlay); this.shadowRoot.appendChild(wrapper); } } get innerElements() { var _a, _b; return ((_b = (_a = this.shadowRoot) == null ? void 0 : _a.getElementById("cart-wrapper")) == null ? void 0 : _b.children) || []; } }; try { if (!customElements.get("cart-drawer")) { customElements.define("cart-drawer", CartDrawer); } } catch (error2) { console.info("[Cart 3.0] cart-drawer definition failed: ", error2); } // ../../../node_modules/@hotwired/stimulus/dist/stimulus.js var EventListener = class { constructor(eventTarget, eventName, eventOptions) { this.eventTarget = eventTarget; this.eventName = eventName; this.eventOptions = eventOptions; this.unorderedBindings = new Set(); } connect() { this.eventTarget.addEventListener(this.eventName, this, this.eventOptions); } disconnect() { this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions); } bindingConnected(binding) { this.unorderedBindings.add(binding); } bindingDisconnected(binding) { this.unorderedBindings.delete(binding); } handleEvent(event) { const extendedEvent = extendEvent(event); for (const binding of this.bindings) { if (extendedEvent.immediatePropagationStopped) { break; } else { binding.handleEvent(extendedEvent); } } } hasBindings() { return this.unorderedBindings.size > 0; } get bindings() { return Array.from(this.unorderedBindings).sort((left, right) => { const leftIndex = left.index, rightIndex = right.index; return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0; }); } }; function extendEvent(event) { if ("immediatePropagationStopped" in event) { return event; } else { const { stopImmediatePropagation } = event; return Object.assign(event, { immediatePropagationStopped: false, stopImmediatePropagation() { this.immediatePropagationStopped = true; stopImmediatePropagation.call(this); } }); } } var Dispatcher = class { constructor(application) { this.application = application; this.eventListenerMaps = new Map(); this.started = false; } start() { if (!this.started) { this.started = true; this.eventListeners.forEach((eventListener) => eventListener.connect()); } } stop() { if (this.started) { this.started = false; this.eventListeners.forEach((eventListener) => eventListener.disconnect()); } } get eventListeners() { return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []); } bindingConnected(binding) { this.fetchEventListenerForBinding(binding).bindingConnected(binding); } bindingDisconnected(binding, clearEventListeners = false) { this.fetchEventListenerForBinding(binding).bindingDisconnected(binding); if (clearEventListeners) this.clearEventListenersForBinding(binding); } handleError(error2, message, detail = {}) { this.application.handleError(error2, `Error ${message}`, detail); } clearEventListenersForBinding(binding) { const eventListener = this.fetchEventListenerForBinding(binding); if (!eventListener.hasBindings()) { eventListener.disconnect(); this.removeMappedEventListenerFor(binding); } } removeMappedEventListenerFor(binding) { const { eventTarget, eventName, eventOptions } = binding; const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); const cacheKey = this.cacheKey(eventName, eventOptions); eventListenerMap.delete(cacheKey); if (eventListenerMap.size == 0) this.eventListenerMaps.delete(eventTarget); } fetchEventListenerForBinding(binding) { const { eventTarget, eventName, eventOptions } = binding; return this.fetchEventListener(eventTarget, eventName, eventOptions); } fetchEventListener(eventTarget, eventName, eventOptions) { const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); const cacheKey = this.cacheKey(eventName, eventOptions); let eventListener = eventListenerMap.get(cacheKey); if (!eventListener) { eventListener = this.createEventListener(eventTarget, eventName, eventOptions); eventListenerMap.set(cacheKey, eventListener); } return eventListener; } createEventListener(eventTarget, eventName, eventOptions) { const eventListener = new EventListener(eventTarget, eventName, eventOptions); if (this.started) { eventListener.connect(); } return eventListener; } fetchEventListenerMapForEventTarget(eventTarget) { let eventListenerMap = this.eventListenerMaps.get(eventTarget); if (!eventListenerMap) { eventListenerMap = new Map(); this.eventListenerMaps.set(eventTarget, eventListenerMap); } return eventListenerMap; } cacheKey(eventName, eventOptions) { const parts = [eventName]; Object.keys(eventOptions).sort().forEach((key) => { parts.push(`${eventOptions[key] ? "" : "!"}${key}`); }); return parts.join(":"); } }; var defaultActionDescriptorFilters = { stop({ event, value }) { if (value) event.stopPropagation(); return true; }, prevent({ event, value }) { if (value) event.preventDefault(); return true; }, self({ event, value, element }) { if (value) { return element === event.target; } else { return true; } } }; var descriptorPattern = /^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/; function parseActionDescriptorString(descriptorString) { const source = descriptorString.trim(); const matches = source.match(descriptorPattern) || []; let eventName = matches[2]; let keyFilter = matches[3]; if (keyFilter && !["keydown", "keyup", "keypress"].includes(eventName)) { eventName += `.${keyFilter}`; keyFilter = ""; } return { eventTarget: parseEventTarget(matches[4]), eventName, eventOptions: matches[7] ? parseEventOptions(matches[7]) : {}, identifier: matches[5], methodName: matches[6], keyFilter: matches[1] || keyFilter }; } function parseEventTarget(eventTargetName) { if (eventTargetName == "window") { return window; } else if (eventTargetName == "document") { return document; } } function parseEventOptions(eventOptions) { return eventOptions.split(":").reduce((options, token) => Object.assign(options, { [token.replace(/^!/, "")]: !/^!/.test(token) }), {}); } function stringifyEventTarget(eventTarget) { if (eventTarget == window) { return "window"; } else if (eventTarget == document) { return "document"; } } function camelize(value) { return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase()); } function namespaceCamelize(value) { return camelize(value.replace(/--/g, "-").replace(/__/g, "_")); } function capitalize(value) { return value.charAt(0).toUpperCase() + value.slice(1); } function dasherize(value) { return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`); } function tokenize(value) { return value.match(/[^\s]+/g) || []; } function isSomething(object) { return object !== null && object !== void 0; } function hasProperty(object, property) { return Object.prototype.hasOwnProperty.call(object, property); } var allModifiers = ["meta", "ctrl", "alt", "shift"]; var Action = class { constructor(element, index, descriptor, schema) { this.element = element; this.index = index; this.eventTarget = descriptor.eventTarget || element; this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name"); this.eventOptions = descriptor.eventOptions || {}; this.identifier = descriptor.identifier || error("missing identifier"); this.methodName = descriptor.methodName || error("missing method name"); this.keyFilter = descriptor.keyFilter || ""; this.schema = schema; } static forToken(token, schema) { return new this(token.element, token.index, parseActionDescriptorString(token.content), schema); } toString() { const eventFilter = this.keyFilter ? `.${this.keyFilter}` : ""; const eventTarget = this.eventTargetName ? `@${this.eventTargetName}` : ""; return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}`; } shouldIgnoreKeyboardEvent(event) { if (!this.keyFilter) { return false; } const filters = this.keyFilter.split("+"); if (this.keyFilterDissatisfied(event, filters)) { return true; } const standardFilter = filters.filter((key) => !allModifiers.includes(key))[0]; if (!standardFilter) { return false; } if (!hasProperty(this.keyMappings, standardFilter)) { error(`contains unknown key filter: ${this.keyFilter}`); } return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase(); } shouldIgnoreMouseEvent(event) { if (!this.keyFilter) { return false; } const filters = [this.keyFilter]; if (this.keyFilterDissatisfied(event, filters)) { return true; } return false; } get params() { const params = {}; const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i"); for (const { name, value } of Array.from(this.element.attributes)) { const match = name.match(pattern); const key = match && match[1]; if (key) { params[camelize(key)] = typecast(value); } } return params; } get eventTargetName() { return stringifyEventTarget(this.eventTarget); } get keyMappings() { return this.schema.keyMappings; } keyFilterDissatisfied(event, filters) { const [meta, ctrl, alt, shift] = allModifiers.map((modifier) => filters.includes(modifier)); return event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift; } }; var defaultEventNames = { a: () => "click", button: () => "click", form: () => "submit", details: () => "toggle", input: (e) => e.getAttribute("type") == "submit" ? "click" : "input", select: () => "change", textarea: () => "input" }; function getDefaultEventNameForElement(element) { const tagName = element.tagName.toLowerCase(); if (tagName in defaultEventNames) { return defaultEventNames[tagName](element); } } function error(message) { throw new Error(message); } function typecast(value) { try { return JSON.parse(value); } catch (o_O) { return value; } } var Binding = class { constructor(context, action) { this.context = context; this.action = action; } get index() { return this.action.index; } get eventTarget() { return this.action.eventTarget; } get eventOptions() { return this.action.eventOptions; } get identifier() { return this.context.identifier; } handleEvent(event) { const actionEvent = this.prepareActionEvent(event); if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(actionEvent)) { this.invokeWithEvent(actionEvent); } } get eventName() { return this.action.eventName; } get method() { const method = this.controller[this.methodName]; if (typeof method == "function") { return method; } throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`); } applyEventModifiers(event) { const { element } = this.action; const { actionDescriptorFilters } = this.context.application; const { controller } = this.context; let passes = true; for (const [name, value] of Object.entries(this.eventOptions)) { if (name in actionDescriptorFilters) { const filter = actionDescriptorFilters[name]; passes = passes && filter({ name, value, event, element, controller }); } else { continue; } } return passes; } prepareActionEvent(event) { return Object.assign(event, { params: this.action.params }); } invokeWithEvent(event) { const { target, currentTarget } = event; try { this.method.call(this.controller, event); this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName }); } catch (error2) { const { identifier, controller, element, index } = this; const detail = { identifier, controller, element, index, event }; this.context.handleError(error2, `invoking action "${this.action}"`, detail); } } willBeInvokedByEvent(event) { const eventTarget = event.target; if (event instanceof KeyboardEvent && this.action.shouldIgnoreKeyboardEvent(event)) { return false; } if (event instanceof MouseEvent && this.action.shouldIgnoreMouseEvent(event)) { return false; } if (this.element === eventTarget) { return true; } else if (eventTarget instanceof Element && this.element.contains(eventTarget)) { return this.scope.containsElement(eventTarget); } else { return this.scope.containsElement(this.action.element); } } get controller() { return this.context.controller; } get methodName() { return this.action.methodName; } get element() { return this.scope.element; } get scope() { return this.context.scope; } }; var ElementObserver = class { constructor(element, delegate) { this.mutationObserverInit = { attributes: true, childList: true, subtree: true }; this.element = element; this.started = false; this.delegate = delegate; this.elements = new Set(); this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); } start() { if (!this.started) { this.started = true; this.mutationObserver.observe(this.element, this.mutationObserverInit); this.refresh(); } } pause(callback) { if (this.started) { this.mutationObserver.disconnect(); this.started = false; } callback(); if (!this.started) { this.mutationObserver.observe(this.element, this.mutationObserverInit); this.started = true; } } stop() { if (this.started) { this.mutationObserver.takeRecords(); this.mutationObserver.disconnect(); this.started = false; } } refresh() { if (this.started) { const matches = new Set(this.matchElementsInTree()); for (const element of Array.from(this.elements)) { if (!matches.has(element)) { this.removeElement(element); } } for (const element of Array.from(matches)) { this.addElement(element); } } } processMutations(mutations) { if (this.started) { for (const mutation of mutations) { this.processMutation(mutation); } } } processMutation(mutation) { if (mutation.type == "attributes") { this.processAttributeChange(mutation.target, mutation.attributeName); } else if (mutation.type == "childList") { this.processRemovedNodes(mutation.removedNodes); this.processAddedNodes(mutation.addedNodes); } } processAttributeChange(element, attributeName) { if (this.elements.has(element)) { if (this.delegate.elementAttributeChanged && this.matchElement(element)) { this.delegate.elementAttributeChanged(element, attributeName); } else { this.removeElement(element); } } else if (this.matchElement(element)) { this.addElement(element); } } processRemovedNodes(nodes) { for (const node of Array.from(nodes)) { const element = this.elementFromNode(node); if (element) { this.processTree(element, this.removeElement); } } } processAddedNodes(nodes) { for (const node of Array.from(nodes)) { const element = this.elementFromNode(node); if (element && this.elementIsActive(element)) { this.processTree(element, this.addElement); } } } matchElement(element) { return this.delegate.matchElement(element); } matchElementsInTree(tree = this.element) { return this.delegate.matchElementsInTree(tree); } processTree(tree, processor) { for (const element of this.matchElementsInTree(tree)) { processor.call(this, element); } } elementFromNode(node) { if (node.nodeType == Node.ELEMENT_NODE) { return node; } } elementIsActive(element) { if (element.isConnected != this.element.isConnected) { return false; } else { return this.element.contains(element); } } addElement(element) { if (!this.elements.has(element)) { if (this.elementIsActive(element)) { this.elements.add(element); if (this.delegate.elementMatched) { this.delegate.elementMatched(element); } } } } removeElement(element) { if (this.elements.has(element)) { this.elements.delete(element); if (this.delegate.elementUnmatched) { this.delegate.elementUnmatched(element); } } } }; var AttributeObserver = class { constructor(element, attributeName, delegate) { this.attributeName = attributeName; this.delegate = delegate; this.elementObserver = new ElementObserver(element, this); } get element() { return this.elementObserver.element; } get selector() { return `[${this.attributeName}]`; } start() { this.elementObserver.start(); } pause(callback) { this.elementObserver.pause(callback); } stop() { this.elementObserver.stop(); } refresh() { this.elementObserver.refresh(); } get started() { return this.elementObserver.started; } matchElement(element) { return element.hasAttribute(this.attributeName); } matchElementsInTree(tree) { const match = this.matchElement(tree) ? [tree] : []; const matches = Array.from(tree.querySelectorAll(this.selector)); return match.concat(matches); } elementMatched(element) { if (this.delegate.elementMatchedAttribute) { this.delegate.elementMatchedAttribute(element, this.attributeName); } } elementUnmatched(element) { if (this.delegate.elementUnmatchedAttribute) { this.delegate.elementUnmatchedAttribute(element, this.attributeName); } } elementAttributeChanged(element, attributeName) { if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) { this.delegate.elementAttributeValueChanged(element, attributeName); } } }; function add(map, key, value) { fetch2(map, key).add(value); } function del(map, key, value) { fetch2(map, key).delete(value); prune(map, key); } function fetch2(map, key) { let values = map.get(key); if (!values) { values = new Set(); map.set(key, values); } return values; } function prune(map, key) { const values = map.get(key); if (values != null && values.size == 0) { map.delete(key); } } var Multimap = class { constructor() { this.valuesByKey = new Map(); } get keys() { return Array.from(this.valuesByKey.keys()); } get values() { const sets = Array.from(this.valuesByKey.values()); return sets.reduce((values, set) => values.concat(Array.from(set)), []); } get size() { const sets = Array.from(this.valuesByKey.values()); return sets.reduce((size, set) => size + set.size, 0); } add(key, value) { add(this.valuesByKey, key, value); } delete(key, value) { del(this.valuesByKey, key, value); } has(key, value) { const values = this.valuesByKey.get(key); return values != null && values.has(value); } hasKey(key) { return this.valuesByKey.has(key); } hasValue(value) { const sets = Array.from(this.valuesByKey.values()); return sets.some((set) => set.has(value)); } getValuesForKey(key) { const values = this.valuesByKey.get(key); return values ? Array.from(values) : []; } getKeysForValue(value) { return Array.from(this.valuesByKey).filter(([_key, values]) => values.has(value)).map(([key, _values]) => key); } }; var SelectorObserver = class { constructor(element, selector, delegate, details) { this._selector = selector; this.details = details; this.elementObserver = new ElementObserver(element, this); this.delegate = delegate; this.matchesByElement = new Multimap(); } get started() { return this.elementObserver.started; } get selector() { return this._selector; } set selector(selector) { this._selector = selector; this.refresh(); } start() { this.elementObserver.start(); } pause(callback) { this.elementObserver.pause(callback); } stop() { this.elementObserver.stop(); } refresh() { this.elementObserver.refresh(); } get element() { return this.elementObserver.element; } matchElement(element) { const { selector } = this; if (selector) { const matches = element.matches(selector); if (this.delegate.selectorMatchElement) { return matches && this.delegate.selectorMatchElement(element, this.details); } return matches; } else { return false; } } matchElementsInTree(tree) { const { selector } = this; if (selector) { const match = this.matchElement(tree) ? [tree] : []; const matches = Array.from(tree.querySelectorAll(selector)).filter((match2) => this.matchElement(match2)); return match.concat(matches); } else { return []; } } elementMatched(element) { const { selector } = this; if (selector) { this.selectorMatched(element, selector); } } elementUnmatched(element) { const selectors = this.matchesByElement.getKeysForValue(element); for (const selector of selectors) { this.selectorUnmatched(element, selector); } } elementAttributeChanged(element, _attributeName) { const { selector } = this; if (selector) { const matches = this.matchElement(element); const matchedBefore = this.matchesByElement.has(selector, element); if (matches && !matchedBefore) { this.selectorMatched(element, selector); } else if (!matches && matchedBefore) { this.selectorUnmatched(element, selector); } } } selectorMatched(element, selector) { this.delegate.selectorMatched(element, selector, this.details); this.matchesByElement.add(selector, element); } selectorUnmatched(element, selector) { this.delegate.selectorUnmatched(element, selector, this.details); this.matchesByElement.delete(selector, element); } }; var StringMapObserver = class { constructor(element, delegate) { this.element = element; this.delegate = delegate; this.started = false; this.stringMap = new Map(); this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); } start() { if (!this.started) { this.started = true; this.mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true }); this.refresh(); } } stop() { if (this.started) { this.mutationObserver.takeRecords(); this.mutationObserver.disconnect(); this.started = false; } } refresh() { if (this.started) { for (const attributeName of this.knownAttributeNames) { this.refreshAttribute(attributeName, null); } } } processMutations(mutations) { if (this.started) { for (const mutation of mutations) { this.processMutation(mutation); } } } processMutation(mutation) { const attributeName = mutation.attributeName; if (attributeName) { this.refreshAttribute(attributeName, mutation.oldValue); } } refreshAttribute(attributeName, oldValue) { const key = this.delegate.getStringMapKeyForAttribute(attributeName); if (key != null) { if (!this.stringMap.has(attributeName)) { this.stringMapKeyAdded(key, attributeName); } const value = this.element.getAttribute(attributeName); if (this.stringMap.get(attributeName) != value) { this.stringMapValueChanged(value, key, oldValue); } if (value == null) { const oldValue2 = this.stringMap.get(attributeName); this.stringMap.delete(attributeName); if (oldValue2) this.stringMapKeyRemoved(key, attributeName, oldValue2); } else { this.stringMap.set(attributeName, value); } } } stringMapKeyAdded(key, attributeName) { if (this.delegate.stringMapKeyAdded) { this.delegate.stringMapKeyAdded(key, attributeName); } } stringMapValueChanged(value, key, oldValue) { if (this.delegate.stringMapValueChanged) { this.delegate.stringMapValueChanged(value, key, oldValue); } } stringMapKeyRemoved(key, attributeName, oldValue) { if (this.delegate.stringMapKeyRemoved) { this.delegate.stringMapKeyRemoved(key, attributeName, oldValue); } } get knownAttributeNames() { return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames))); } get currentAttributeNames() { return Array.from(this.element.attributes).map((attribute) => attribute.name); } get recordedAttributeNames() { return Array.from(this.stringMap.keys()); } }; var TokenListObserver = class { constructor(element, attributeName, delegate) { this.attributeObserver = new AttributeObserver(element, attributeName, this); this.delegate = delegate; this.tokensByElement = new Multimap(); } get started() { return this.attributeObserver.started; } start() { this.attributeObserver.start(); } pause(callback) { this.attributeObserver.pause(callback); } stop() { this.attributeObserver.stop(); } refresh() { this.attributeObserver.refresh(); } get element() { return this.attributeObserver.element; } get attributeName() { return this.attributeObserver.attributeName; } elementMatchedAttribute(element) { this.tokensMatched(this.readTokensForElement(element)); } elementAttributeValueChanged(element) { const [unmatchedTokens, matchedTokens] = this.refreshTokensForElement(element); this.tokensUnmatched(unmatchedTokens); this.tokensMatched(matchedTokens); } elementUnmatchedAttribute(element) { this.tokensUnmatched(this.tokensByElement.getValuesForKey(element)); } tokensMatched(tokens) { tokens.forEach((token) => this.tokenMatched(token)); } tokensUnmatched(tokens) { tokens.forEach((token) => this.tokenUnmatched(token)); } tokenMatched(token) { this.delegate.tokenMatched(token); this.tokensByElement.add(token.element, token); } tokenUnmatched(token) { this.delegate.tokenUnmatched(token); this.tokensByElement.delete(token.element, token); } refreshTokensForElement(element) { const previousTokens = this.tokensByElement.getValuesForKey(element); const currentTokens = this.readTokensForElement(element); const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken)); if (firstDifferingIndex == -1) { return [[], []]; } else { return [previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex)]; } } readTokensForElement(element) { const attributeName = this.attributeName; const tokenString = element.getAttribute(attributeName) || ""; return parseTokenString(tokenString, element, attributeName); } }; function parseTokenString(tokenString, element, attributeName) { return tokenString.trim().split(/\s+/).filter((content) => content.length).map((content, index) => ({ element, attributeName, content, index })); } function zip(left, right) { const length = Math.max(left.length, right.length); return Array.from({ length }, (_, index) => [left[index], right[index]]); } function tokensAreEqual(left, right) { return left && right && left.index == right.index && left.content == right.content; } var ValueListObserver = class { constructor(element, attributeName, delegate) { this.tokenListObserver = new TokenListObserver(element, attributeName, this); this.delegate = delegate; this.parseResultsByToken = new WeakMap(); this.valuesByTokenByElement = new WeakMap(); } get started() { return this.tokenListObserver.started; } start() { this.tokenListObserver.start(); } stop() { this.tokenListObserver.stop(); } refresh() { this.tokenListObserver.refresh(); } get element() { return this.tokenListObserver.element; } get attributeName() { return this.tokenListObserver.attributeName; } tokenMatched(token) { const { element } = token; const { value } = this.fetchParseResultForToken(token); if (value) { this.fetchValuesByTokenForElement(element).set(token, value); this.delegate.elementMatchedValue(element, value); } } tokenUnmatched(token) { const { element } = token; const { value } = this.fetchParseResultForToken(token); if (value) { this.fetchValuesByTokenForElement(element).delete(token); this.delegate.elementUnmatchedValue(element, value); } } fetchParseResultForToken(token) { let parseResult = this.parseResultsByToken.get(token); if (!parseResult) { parseResult = this.parseToken(token); this.parseResultsByToken.set(token, parseResult); } return parseResult; } fetchValuesByTokenForElement(element) { let valuesByToken = this.valuesByTokenByElement.get(element); if (!valuesByToken) { valuesByToken = new Map(); this.valuesByTokenByElement.set(element, valuesByToken); } return valuesByToken; } parseToken(token) { try { const value = this.delegate.parseValueForToken(token); return { value }; } catch (error2) { return { error: error2 }; } } }; var BindingObserver = class { constructor(context, delegate) { this.context = context; this.delegate = delegate; this.bindingsByAction = new Map(); } start() { if (!this.valueListObserver) { this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this); this.valueListObserver.start(); } } stop() { if (this.valueListObserver) { this.valueListObserver.stop(); delete this.valueListObserver; this.disconnectAllActions(); } } get element() { return this.context.element; } get identifier() { return this.context.identifier; } get actionAttribute() { return this.schema.actionAttribute; } get schema() { return this.context.schema; } get bindings() { return Array.from(this.bindingsByAction.values()); } connectAction(action) { const binding = new Binding(this.context, action); this.bindingsByAction.set(action, binding); this.delegate.bindingConnected(binding); } disconnectAction(action) { const binding = this.bindingsByAction.get(action); if (binding) { this.bindingsByAction.delete(action); this.delegate.bindingDisconnected(binding); } } disconnectAllActions() { this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true)); this.bindingsByAction.clear(); } parseValueForToken(token) { const action = Action.forToken(token, this.schema); if (action.identifier == this.identifier) { return action; } } elementMatchedValue(element, action) { this.connectAction(action); } elementUnmatchedValue(element, action) { this.disconnectAction(action); } }; var ValueObserver = class { constructor(context, receiver) { this.context = context; this.receiver = receiver; this.stringMapObserver = new StringMapObserver(this.element, this); this.valueDescriptorMap = this.controller.valueDescriptorMap; } start() { this.stringMapObserver.start(); this.invokeChangedCallbacksForDefaultValues(); } stop() { this.stringMapObserver.stop(); } get element() { return this.context.element; } get controller() { return this.context.controller; } getStringMapKeyForAttribute(attributeName) { if (attributeName in this.valueDescriptorMap) { return this.valueDescriptorMap[attributeName].name; } } stringMapKeyAdded(key, attributeName) { const descriptor = this.valueDescriptorMap[attributeName]; if (!this.hasValue(key)) { this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), descriptor.writer(descriptor.defaultValue)); } } stringMapValueChanged(value, name, oldValue) { const descriptor = this.valueDescriptorNameMap[name]; if (value === null) return; if (oldValue === null) { oldValue = descriptor.writer(descriptor.defaultValue); } this.invokeChangedCallback(name, value, oldValue); } stringMapKeyRemoved(key, attributeName, oldValue) { const descriptor = this.valueDescriptorNameMap[key]; if (this.hasValue(key)) { this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), oldValue); } else { this.invokeChangedCallback(key, descriptor.writer(descriptor.defaultValue), oldValue); } } invokeChangedCallbacksForDefaultValues() { for (const { key, name, defaultValue, writer } of this.valueDescriptors) { if (defaultValue != void 0 && !this.controller.data.has(key)) { this.invokeChangedCallback(name, writer(defaultValue), void 0); } } } invokeChangedCallback(name, rawValue, rawOldValue) { const changedMethodName = `${name}Changed`; const changedMethod = this.receiver[changedMethodName]; if (typeof changedMethod == "function") { const descriptor = this.valueDescriptorNameMap[name]; try { const value = descriptor.reader(rawValue); let oldValue = rawOldValue; if (rawOldValue) { oldValue = descriptor.reader(rawOldValue); } changedMethod.call(this.receiver, value, oldValue); } catch (error2) { if (error2 instanceof TypeError) { error2.message = `Stimulus Value "${this.context.identifier}.${descriptor.name}" - ${error2.message}`; } throw error2; } } } get valueDescriptors() { const { valueDescriptorMap } = this; return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]); } get valueDescriptorNameMap() { const descriptors = {}; Object.keys(this.valueDescriptorMap).forEach((key) => { const descriptor = this.valueDescriptorMap[key]; descriptors[descriptor.name] = descriptor; }); return descriptors; } hasValue(attributeName) { const descriptor = this.valueDescriptorNameMap[attributeName]; const hasMethodName = `has${capitalize(descriptor.name)}`; return this.receiver[hasMethodName]; } }; var TargetObserver = class { constructor(context, delegate) { this.context = context; this.delegate = delegate; this.targetsByName = new Multimap(); } start() { if (!this.tokenListObserver) { this.tokenListObserver = new TokenListObserver(this.element, this.attributeName, this); this.tokenListObserver.start(); } } stop() { if (this.tokenListObserver) { this.disconnectAllTargets(); this.tokenListObserver.stop(); delete this.tokenListObserver; } } tokenMatched({ element, content: name }) { if (this.scope.containsElement(element)) { this.connectTarget(element, name); } } tokenUnmatched({ element, content: name }) { this.disconnectTarget(element, name); } connectTarget(element, name) { var _a; if (!this.targetsByName.has(name, element)) { this.targetsByName.add(name, element); (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetConnected(element, name)); } } disconnectTarget(element, name) { var _a; if (this.targetsByName.has(name, element)) { this.targetsByName.delete(name, element); (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetDisconnected(element, name)); } } disconnectAllTargets() { for (const name of this.targetsByName.keys) { for (const element of this.targetsByName.getValuesForKey(name)) { this.disconnectTarget(element, name); } } } get attributeName() { return `data-${this.context.identifier}-target`; } get element() { return this.context.element; } get scope() { return this.context.scope; } }; function readInheritableStaticArrayValues(constructor, propertyName) { const ancestors = getAncestorsForConstructor(constructor); return Array.from(ancestors.reduce((values, constructor2) => { getOwnStaticArrayValues(constructor2, propertyName).forEach((name) => values.add(name)); return values; }, new Set())); } function readInheritableStaticObjectPairs(constructor, propertyName) { const ancestors = getAncestorsForConstructor(constructor); return ancestors.reduce((pairs, constructor2) => { pairs.push(...getOwnStaticObjectPairs(constructor2, propertyName)); return pairs; }, []); } function getAncestorsForConstructor(constructor) { const ancestors = []; while (constructor) { ancestors.push(constructor); constructor = Object.getPrototypeOf(constructor); } return ancestors.reverse(); } function getOwnStaticArrayValues(constructor, propertyName) { const definition = constructor[propertyName]; return Array.isArray(definition) ? definition : []; } function getOwnStaticObjectPairs(constructor, propertyName) { const definition = constructor[propertyName]; return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : []; } var OutletObserver = class { constructor(context, delegate) { this.started = false; this.context = context; this.delegate = delegate; this.outletsByName = new Multimap(); this.outletElementsByName = new Multimap(); this.selectorObserverMap = new Map(); this.attributeObserverMap = new Map(); } start() { if (!this.started) { this.outletDefinitions.forEach((outletName) => { this.setupSelectorObserverForOutlet(outletName); this.setupAttributeObserverForOutlet(outletName); }); this.started = true; this.dependentContexts.forEach((context) => context.refresh()); } } refresh() { this.selectorObserverMap.forEach((observer) => observer.refresh()); this.attributeObserverMap.forEach((observer) => observer.refresh()); } stop() { if (this.started) { this.started = false; this.disconnectAllOutlets(); this.stopSelectorObservers(); this.stopAttributeObservers(); } } stopSelectorObservers() { if (this.selectorObserverMap.size > 0) { this.selectorObserverMap.forEach((observer) => observer.stop()); this.selectorObserverMap.clear(); } } stopAttributeObservers() { if (this.attributeObserverMap.size > 0) { this.attributeObserverMap.forEach((observer) => observer.stop()); this.attributeObserverMap.clear(); } } selectorMatched(element, _selector, { outletName }) { const outlet = this.getOutlet(element, outletName); if (outlet) { this.connectOutlet(outlet, element, outletName); } } selectorUnmatched(element, _selector, { outletName }) { const outlet = this.getOutletFromMap(element, outletName); if (outlet) { this.disconnectOutlet(outlet, element, outletName); } } selectorMatchElement(element, { outletName }) { const selector = this.selector(outletName); const hasOutlet = this.hasOutlet(element, outletName); const hasOutletController = element.matches(`[${this.schema.controllerAttribute}~=${outletName}]`); if (selector) { return hasOutlet && hasOutletController && element.matches(selector); } else { return false; } } elementMatchedAttribute(_element, attributeName) { const outletName = this.getOutletNameFromOutletAttributeName(attributeName); if (outletName) { this.updateSelectorObserverForOutlet(outletName); } } elementAttributeValueChanged(_element, attributeName) { const outletName = this.getOutletNameFromOutletAttributeName(attributeName); if (outletName) { this.updateSelectorObserverForOutlet(outletName); } } elementUnmatchedAttribute(_element, attributeName) { const outletName = this.getOutletNameFromOutletAttributeName(attributeName); if (outletName) { this.updateSelectorObserverForOutlet(outletName); } } connectOutlet(outlet, element, outletName) { var _a; if (!this.outletElementsByName.has(outletName, element)) { this.outletsByName.add(outletName, outlet); this.outletElementsByName.add(outletName, element); (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletConnected(outlet, element, outletName)); } } disconnectOutlet(outlet, element, outletName) { var _a; if (this.outletElementsByName.has(outletName, element)) { this.outletsByName.delete(outletName, outlet); this.outletElementsByName.delete(outletName, element); (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletDisconnected(outlet, element, outletName)); } } disconnectAllOutlets() { for (const outletName of this.outletElementsByName.keys) { for (const element of this.outletElementsByName.getValuesForKey(outletName)) { for (const outlet of this.outletsByName.getValuesForKey(outletName)) { this.disconnectOutlet(outlet, element, outletName); } } } } updateSelectorObserverForOutlet(outletName) { const observer = this.selectorObserverMap.get(outletName); if (observer) { observer.selector = this.selector(outletName); } } setupSelectorObserverForOutlet(outletName) { const selector = this.selector(outletName); const selectorObserver = new SelectorObserver(document.body, selector, this, { outletName }); this.selectorObserverMap.set(outletName, selectorObserver); selectorObserver.start(); } setupAttributeObserverForOutlet(outletName) { const attributeName = this.attributeNameForOutletName(outletName); const attributeObserver = new AttributeObserver(this.scope.element, attributeName, this); this.attributeObserverMap.set(outletName, attributeObserver); attributeObserver.start(); } selector(outletName) { return this.scope.outlets.getSelectorForOutletName(outletName); } attributeNameForOutletName(outletName) { return this.scope.schema.outletAttributeForScope(this.identifier, outletName); } getOutletNameFromOutletAttributeName(attributeName) { return this.outletDefinitions.find((outletName) => this.attributeNameForOutletName(outletName) === attributeName); } get outletDependencies() { const dependencies = new Multimap(); this.router.modules.forEach((module) => { const constructor = module.definition.controllerConstructor; const outlets = readInheritableStaticArrayValues(constructor, "outlets"); outlets.forEach((outlet) => dependencies.add(outlet, module.identifier)); }); return dependencies; } get outletDefinitions() { return this.outletDependencies.getKeysForValue(this.identifier); } get dependentControllerIdentifiers() { return this.outletDependencies.getValuesForKey(this.identifier); } get dependentContexts() { const identifiers = this.dependentControllerIdentifiers; return this.router.contexts.filter((context) => identifiers.includes(context.identifier)); } hasOutlet(element, outletName) { return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName); } getOutlet(element, outletName) { return this.application.getControllerForElementAndIdentifier(element, outletName); } getOutletFromMap(element, outletName) { return this.outletsByName.getValuesForKey(outletName).find((outlet) => outlet.element === element); } get scope() { return this.context.scope; } get schema() { return this.context.schema; } get identifier() { return this.context.identifier; } get application() { return this.context.application; } get router() { return this.application.router; } }; var Context = class { constructor(module, scope) { this.logDebugActivity = (functionName, detail = {}) => { const { identifier, controller, element } = this; detail = Object.assign({ identifier, controller, element }, detail); this.application.logDebugActivity(this.identifier, functionName, detail); }; this.module = module; this.scope = scope; this.controller = new module.controllerConstructor(this); this.bindingObserver = new BindingObserver(this, this.dispatcher); this.valueObserver = new ValueObserver(this, this.controller); this.targetObserver = new TargetObserver(this, this); this.outletObserver = new OutletObserver(this, this); try { this.controller.initialize(); this.logDebugActivity("initialize"); } catch (error2) { this.handleError(error2, "initializing controller"); } } connect() { this.bindingObserver.start(); this.valueObserver.start(); this.targetObserver.start(); this.outletObserver.start(); try { this.controller.connect(); this.logDebugActivity("connect"); } catch (error2) { this.handleError(error2, "connecting controller"); } } refresh() { this.outletObserver.refresh(); } disconnect() { try { this.controller.disconnect(); this.logDebugActivity("disconnect"); } catch (error2) { this.handleError(error2, "disconnecting controller"); } this.outletObserver.stop(); this.targetObserver.stop(); this.valueObserver.stop(); this.bindingObserver.stop(); } get application() { return this.module.application; } get identifier() { return this.module.identifier; } get schema() { return this.application.schema; } get dispatcher() { return this.application.dispatcher; } get element() { return this.scope.element; } get parentElement() { return this.element.parentElement; } handleError(error2, message, detail = {}) { const { identifier, controller, element } = this; detail = Object.assign({ identifier, controller, element }, detail); this.application.handleError(error2, `Error ${message}`, detail); } targetConnected(element, name) { this.invokeControllerMethod(`${name}TargetConnected`, element); } targetDisconnected(element, name) { this.invokeControllerMethod(`${name}TargetDisconnected`, element); } outletConnected(outlet, element, name) { this.invokeControllerMethod(`${namespaceCamelize(name)}OutletConnected`, outlet, element); } outletDisconnected(outlet, element, name) { this.invokeControllerMethod(`${namespaceCamelize(name)}OutletDisconnected`, outlet, element); } invokeControllerMethod(methodName, ...args) { const controller = this.controller; if (typeof controller[methodName] == "function") { controller[methodName](...args); } } }; function bless(constructor) { return shadow(constructor, getBlessedProperties(constructor)); } function shadow(constructor, properties) { const shadowConstructor = extend(constructor); const shadowProperties = getShadowProperties(constructor.prototype, properties); Object.defineProperties(shadowConstructor.prototype, shadowProperties); return shadowConstructor; } function getBlessedProperties(constructor) { const blessings = readInheritableStaticArrayValues(constructor, "blessings"); return blessings.reduce((blessedProperties, blessing) => { const properties = blessing(constructor); for (const key in properties) { const descriptor = blessedProperties[key] || {}; blessedProperties[key] = Object.assign(descriptor, properties[key]); } return blessedProperties; }, {}); } function getShadowProperties(prototype, properties) { return getOwnKeys(properties).reduce((shadowProperties, key) => { const descriptor = getShadowedDescriptor(prototype, properties, key); if (descriptor) { Object.assign(shadowProperties, { [key]: descriptor }); } return shadowProperties; }, {}); } function getShadowedDescriptor(prototype, properties, key) { const shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key); const shadowedByValue = shadowingDescriptor && "value" in shadowingDescriptor; if (!shadowedByValue) { const descriptor = Object.getOwnPropertyDescriptor(properties, key).value; if (shadowingDescriptor) { descriptor.get = shadowingDescriptor.get || descriptor.get; descriptor.set = shadowingDescriptor.set || descriptor.set; } return descriptor; } } var getOwnKeys = (() => { if (typeof Object.getOwnPropertySymbols == "function") { return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)]; } else { return Object.getOwnPropertyNames; } })(); var extend = (() => { function extendWithReflect(constructor) { function extended() { return Reflect.construct(constructor, arguments, new.target); } extended.prototype = Object.create(constructor.prototype, { constructor: { value: extended } }); Reflect.setPrototypeOf(extended, constructor); return extended; } function testReflectExtension() { const a = function() { this.a.call(this); }; const b = extendWithReflect(a); b.prototype.a = function() { }; return new b(); } try { testReflectExtension(); return extendWithReflect; } catch (error2) { return (constructor) => class extended extends constructor { }; } })(); function blessDefinition(definition) { return { identifier: definition.identifier, controllerConstructor: bless(definition.controllerConstructor) }; } var Module = class { constructor(application, definition) { this.application = application; this.definition = blessDefinition(definition); this.contextsByScope = new WeakMap(); this.connectedContexts = new Set(); } get identifier() { return this.definition.identifier; } get controllerConstructor() { return this.definition.controllerConstructor; } get contexts() { return Array.from(this.connectedContexts); } connectContextForScope(scope) { const context = this.fetchContextForScope(scope); this.connectedContexts.add(context); context.connect(); } disconnectContextForScope(scope) { const context = this.contextsByScope.get(scope); if (context) { this.connectedContexts.delete(context); context.disconnect(); } } fetchContextForScope(scope) { let context = this.contextsByScope.get(scope); if (!context) { context = new Context(this, scope); this.contextsByScope.set(scope, context); } return context; } }; var ClassMap = class { constructor(scope) { this.scope = scope; } has(name) { return this.data.has(this.getDataKey(name)); } get(name) { return this.getAll(name)[0]; } getAll(name) { const tokenString = this.data.get(this.getDataKey(name)) || ""; return tokenize(tokenString); } getAttributeName(name) { return this.data.getAttributeNameForKey(this.getDataKey(name)); } getDataKey(name) { return `${name}-class`; } get data() { return this.scope.data; } }; var DataMap = class { constructor(scope) { this.scope = scope; } get element() { return this.scope.element; } get identifier() { return this.scope.identifier; } get(key) { const name = this.getAttributeNameForKey(key); return this.element.getAttribute(name); } set(key, value) { const name = this.getAttributeNameForKey(key); this.element.setAttribute(name, value); return this.get(key); } has(key) { const name = this.getAttributeNameForKey(key); return this.element.hasAttribute(name); } delete(key) { if (this.has(key)) { const name = this.getAttributeNameForKey(key); this.element.removeAttribute(name); return true; } else { return false; } } getAttributeNameForKey(key) { return `data-${this.identifier}-${dasherize(key)}`; } }; var Guide = class { constructor(logger) { this.warnedKeysByObject = new WeakMap(); this.logger = logger; } warn(object, key, message) { let warnedKeys = this.warnedKeysByObject.get(object); if (!warnedKeys) { warnedKeys = new Set(); this.warnedKeysByObject.set(object, warnedKeys); } if (!warnedKeys.has(key)) { warnedKeys.add(key); this.logger.warn(message, object); } } }; function attributeValueContainsToken(attributeName, token) { return `[${attributeName}~="${token}"]`; } var TargetSet = class { constructor(scope) { this.scope = scope; } get element() { return this.scope.element; } get identifier() { return this.scope.identifier; } get schema() { return this.scope.schema; } has(targetName) { return this.find(targetName) != null; } find(...targetNames) { return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), void 0); } findAll(...targetNames) { return targetNames.reduce((targets, targetName) => [ ...targets, ...this.findAllTargets(targetName), ...this.findAllLegacyTargets(targetName) ], []); } findTarget(targetName) { const selector = this.getSelectorForTargetName(targetName); return this.scope.findElement(selector); } findAllTargets(targetName) { const selector = this.getSelectorForTargetName(targetName); return this.scope.findAllElements(selector); } getSelectorForTargetName(targetName) { const attributeName = this.schema.targetAttributeForScope(this.identifier); return attributeValueContainsToken(attributeName, targetName); } findLegacyTarget(targetName) { const selector = this.getLegacySelectorForTargetName(targetName); return this.deprecate(this.scope.findElement(selector), targetName); } findAllLegacyTargets(targetName) { const selector = this.getLegacySelectorForTargetName(targetName); return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName)); } getLegacySelectorForTargetName(targetName) { const targetDescriptor = `${this.identifier}.${targetName}`; return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor); } deprecate(element, targetName) { if (element) { const { identifier } = this; const attributeName = this.schema.targetAttribute; const revisedAttributeName = this.schema.targetAttributeForScope(identifier); this.guide.warn(element, `target:${targetName}`, `Please replace ${attributeName}="${identifier}.${targetName}" with ${revisedAttributeName}="${targetName}". The ${attributeName} attribute is deprecated and will be removed in a future version of Stimulus.`); } return element; } get guide() { return this.scope.guide; } }; var OutletSet = class { constructor(scope, controllerElement) { this.scope = scope; this.controllerElement = controllerElement; } get element() { return this.scope.element; } get identifier() { return this.scope.identifier; } get schema() { return this.scope.schema; } has(outletName) { return this.find(outletName) != null; } find(...outletNames) { return outletNames.reduce((outlet, outletName) => outlet || this.findOutlet(outletName), void 0); } findAll(...outletNames) { return outletNames.reduce((outlets, outletName) => [...outlets, ...this.findAllOutlets(outletName)], []); } getSelectorForOutletName(outletName) { const attributeName = this.schema.outletAttributeForScope(this.identifier, outletName); return this.controllerElement.getAttribute(attributeName); } findOutlet(outletName) { const selector = this.getSelectorForOutletName(outletName); if (selector) return this.findElement(selector, outletName); } findAllOutlets(outletName) { const selector = this.getSelectorForOutletName(outletName); return selector ? this.findAllElements(selector, outletName) : []; } findElement(selector, outletName) { const elements = this.scope.queryElements(selector); return elements.filter((element) => this.matchesElement(element, selector, outletName))[0]; } findAllElements(selector, outletName) { const elements = this.scope.queryElements(selector); return elements.filter((element) => this.matchesElement(element, selector, outletName)); } matchesElement(element, selector, outletName) { const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || ""; return element.matches(selector) && controllerAttribute.split(" ").includes(outletName); } }; var Scope = class { constructor(schema, element, identifier, logger) { this.targets = new TargetSet(this); this.classes = new ClassMap(this); this.data = new DataMap(this); this.containsElement = (element2) => { return element2.closest(this.controllerSelector) === this.element; }; this.schema = schema; this.element = element; this.identifier = identifier; this.guide = new Guide(logger); this.outlets = new OutletSet(this.documentScope, element); } findElement(selector) { return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement); } findAllElements(selector) { return [ ...this.element.matches(selector) ? [this.element] : [], ...this.queryElements(selector).filter(this.containsElement) ]; } queryElements(selector) { return Array.from(this.element.querySelectorAll(selector)); } get controllerSelector() { return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier); } get isDocumentScope() { return this.element === document.documentElement; } get documentScope() { return this.isDocumentScope ? this : new Scope(this.schema, document.documentElement, this.identifier, this.guide.logger); } }; var ScopeObserver = class { constructor(element, schema, delegate) { this.element = element; this.schema = schema; this.delegate = delegate; this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this); this.scopesByIdentifierByElement = new WeakMap(); this.scopeReferenceCounts = new WeakMap(); } start() { this.valueListObserver.start(); } stop() { this.valueListObserver.stop(); } get controllerAttribute() { return this.schema.controllerAttribute; } parseValueForToken(token) { const { element, content: identifier } = token; return this.parseValueForElementAndIdentifier(element, identifier); } parseValueForElementAndIdentifier(element, identifier) { const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element); let scope = scopesByIdentifier.get(identifier); if (!scope) { scope = this.delegate.createScopeForElementAndIdentifier(element, identifier); scopesByIdentifier.set(identifier, scope); } return scope; } elementMatchedValue(element, value) { const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1; this.scopeReferenceCounts.set(value, referenceCount); if (referenceCount == 1) { this.delegate.scopeConnected(value); } } elementUnmatchedValue(element, value) { const referenceCount = this.scopeReferenceCounts.get(value); if (referenceCount) { this.scopeReferenceCounts.set(value, referenceCount - 1); if (referenceCount == 1) { this.delegate.scopeDisconnected(value); } } } fetchScopesByIdentifierForElement(element) { let scopesByIdentifier = this.scopesByIdentifierByElement.get(element); if (!scopesByIdentifier) { scopesByIdentifier = new Map(); this.scopesByIdentifierByElement.set(element, scopesByIdentifier); } return scopesByIdentifier; } }; var Router = class { constructor(application) { this.application = application; this.scopeObserver = new ScopeObserver(this.element, this.schema, this); this.scopesByIdentifier = new Multimap(); this.modulesByIdentifier = new Map(); } get element() { return this.application.element; } get schema() { return this.application.schema; } get logger() { return this.application.logger; } get controllerAttribute() { return this.schema.controllerAttribute; } get modules() { return Array.from(this.modulesByIdentifier.values()); } get contexts() { return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), []); } start() { this.scopeObserver.start(); } stop() { this.scopeObserver.stop(); } loadDefinition(definition) { this.unloadIdentifier(definition.identifier); const module = new Module(this.application, definition); this.connectModule(module); const afterLoad = definition.controllerConstructor.afterLoad; if (afterLoad) { afterLoad.call(definition.controllerConstructor, definition.identifier, this.application); } } unloadIdentifier(identifier) { const module = this.modulesByIdentifier.get(identifier); if (module) { this.disconnectModule(module); } } getContextForElementAndIdentifier(element, identifier) { const module = this.modulesByIdentifier.get(identifier); if (module) { return module.contexts.find((context) => context.element == element); } } proposeToConnectScopeForElementAndIdentifier(element, identifier) { const scope = this.scopeObserver.parseValueForElementAndIdentifier(element, identifier); if (scope) { this.scopeObserver.elementMatchedValue(scope.element, scope); } else { console.error(`Couldn't find or create scope for identifier: "${identifier}" and element:`, element); } } handleError(error2, message, detail) { this.application.handleError(error2, message, detail); } createScopeForElementAndIdentifier(element, identifier) { return new Scope(this.schema, element, identifier, this.logger); } scopeConnected(scope) { this.scopesByIdentifier.add(scope.identifier, scope); const module = this.modulesByIdentifier.get(scope.identifier); if (module) { module.connectContextForScope(scope); } } scopeDisconnected(scope) { this.scopesByIdentifier.delete(scope.identifier, scope); const module = this.modulesByIdentifier.get(scope.identifier); if (module) { module.disconnectContextForScope(scope); } } connectModule(module) { this.modulesByIdentifier.set(module.identifier, module); const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); scopes.forEach((scope) => module.connectContextForScope(scope)); } disconnectModule(module) { this.modulesByIdentifier.delete(module.identifier); const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); scopes.forEach((scope) => module.disconnectContextForScope(scope)); } }; var defaultSchema = { controllerAttribute: "data-controller", actionAttribute: "data-action", targetAttribute: "data-target", targetAttributeForScope: (identifier) => `data-${identifier}-target`, outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`, keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))) }; function objectFromEntries(array) { return array.reduce((memo, [k, v]) => Object.assign(Object.assign({}, memo), { [k]: v }), {}); } var Application = class { constructor(element = document.documentElement, schema = defaultSchema) { this.logger = console; this.debug = false; this.logDebugActivity = (identifier, functionName, detail = {}) => { if (this.debug) { this.logFormattedMessage(identifier, functionName, detail); } }; this.element = element; this.schema = schema; this.dispatcher = new Dispatcher(this); this.router = new Router(this); this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters); } static start(element, schema) { const application = new this(element, schema); application.start(); return application; } async start() { await domReady(); this.logDebugActivity("application", "starting"); this.dispatcher.start(); this.router.start(); this.logDebugActivity("application", "start"); } stop() { this.logDebugActivity("application", "stopping"); this.dispatcher.stop(); this.router.stop(); this.logDebugActivity("application", "stop"); } register(identifier, controllerConstructor) { this.load({ identifier, controllerConstructor }); } registerActionOption(name, filter) { this.actionDescriptorFilters[name] = filter; } load(head, ...rest) { const definitions = Array.isArray(head) ? head : [head, ...rest]; definitions.forEach((definition) => { if (definition.controllerConstructor.shouldLoad) { this.router.loadDefinition(definition); } }); } unload(head, ...rest) { const identifiers = Array.isArray(head) ? head : [head, ...rest]; identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier)); } get controllers() { return this.router.contexts.map((context) => context.controller); } getControllerForElementAndIdentifier(element, identifier) { const context = this.router.getContextForElementAndIdentifier(element, identifier); return context ? context.controller : null; } handleError(error2, message, detail) { var _a; this.logger.error(`%s %o %o`, message, error2, detail); (_a = window.onerror) === null || _a === void 0 ? void 0 : _a.call(window, message, "", 0, 0, error2); } logFormattedMessage(identifier, functionName, detail = {}) { detail = Object.assign({ application: this }, detail); this.logger.groupCollapsed(`${identifier} #${functionName}`); this.logger.log("details:", Object.assign({}, detail)); this.logger.groupEnd(); } }; function domReady() { return new Promise((resolve) => { if (document.readyState == "loading") { document.addEventListener("DOMContentLoaded", () => resolve()); } else { resolve(); } }); } function ClassPropertiesBlessing(constructor) { const classes = readInheritableStaticArrayValues(constructor, "classes"); return classes.reduce((properties, classDefinition) => { return Object.assign(properties, propertiesForClassDefinition(classDefinition)); }, {}); } function propertiesForClassDefinition(key) { return { [`${key}Class`]: { get() { const { classes } = this; if (classes.has(key)) { return classes.get(key); } else { const attribute = classes.getAttributeName(key); throw new Error(`Missing attribute "${attribute}"`); } } }, [`${key}Classes`]: { get() { return this.classes.getAll(key); } }, [`has${capitalize(key)}Class`]: { get() { return this.classes.has(key); } } }; } function OutletPropertiesBlessing(constructor) { const outlets = readInheritableStaticArrayValues(constructor, "outlets"); return outlets.reduce((properties, outletDefinition) => { return Object.assign(properties, propertiesForOutletDefinition(outletDefinition)); }, {}); } function getOutletController(controller, element, identifier) { return controller.application.getControllerForElementAndIdentifier(element, identifier); } function getControllerAndEnsureConnectedScope(controller, element, outletName) { let outletController = getOutletController(controller, element, outletName); if (outletController) return outletController; controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName); outletController = getOutletController(controller, element, outletName); if (outletController) return outletController; } function propertiesForOutletDefinition(name) { const camelizedName = namespaceCamelize(name); return { [`${camelizedName}Outlet`]: { get() { const outletElement = this.outlets.find(name); const selector = this.outlets.getSelectorForOutletName(name); if (outletElement) { const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name); if (outletController) return outletController; throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`); } throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`); } }, [`${camelizedName}Outlets`]: { get() { const outlets = this.outlets.findAll(name); if (outlets.length > 0) { return outlets.map((outletElement) => { const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name); if (outletController) return outletController; console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement); }).filter((controller) => controller); } return []; } }, [`${camelizedName}OutletElement`]: { get() { const outletElement = this.outlets.find(name); const selector = this.outlets.getSelectorForOutletName(name); if (outletElement) { return outletElement; } else { throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`); } } }, [`${camelizedName}OutletElements`]: { get() { return this.outlets.findAll(name); } }, [`has${capitalize(camelizedName)}Outlet`]: { get() { return this.outlets.has(name); } } }; } function TargetPropertiesBlessing(constructor) { const targets = readInheritableStaticArrayValues(constructor, "targets"); return targets.reduce((properties, targetDefinition) => { return Object.assign(properties, propertiesForTargetDefinition(targetDefinition)); }, {}); } function propertiesForTargetDefinition(name) { return { [`${name}Target`]: { get() { const target = this.targets.find(name); if (target) { return target; } else { throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`); } } }, [`${name}Targets`]: { get() { return this.targets.findAll(name); } }, [`has${capitalize(name)}Target`]: { get() { return this.targets.has(name); } } }; } function ValuePropertiesBlessing(constructor) { const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values"); const propertyDescriptorMap = { valueDescriptorMap: { get() { return valueDefinitionPairs.reduce((result, valueDefinitionPair) => { const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier); const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key); return Object.assign(result, { [attributeName]: valueDescriptor }); }, {}); } } }; return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => { return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair)); }, propertyDescriptorMap); } function propertiesForValueDefinitionPair(valueDefinitionPair, controller) { const definition = parseValueDefinitionPair(valueDefinitionPair, controller); const { key, name, reader: read, writer: write } = definition; return { [name]: { get() { const value = this.data.get(key); if (value !== null) { return read(value); } else { return definition.defaultValue; } }, set(value) { if (value === void 0) { this.data.delete(key); } else { this.data.set(key, write(value)); } } }, [`has${capitalize(name)}`]: { get() { return this.data.has(key) || definition.hasCustomDefaultValue; } } }; } function parseValueDefinitionPair([token, typeDefinition], controller) { return valueDescriptorForTokenAndTypeDefinition({ controller, token, typeDefinition }); } function parseValueTypeConstant(constant) { switch (constant) { case Array: return "array"; case Boolean: return "boolean"; case Number: return "number"; case Object: return "object"; case String: return "string"; } } function parseValueTypeDefault(defaultValue) { switch (typeof defaultValue) { case "boolean": return "boolean"; case "number": return "number"; case "string": return "string"; } if (Array.isArray(defaultValue)) return "array"; if (Object.prototype.toString.call(defaultValue) === "[object Object]") return "object"; } function parseValueTypeObject(payload) { const { controller, token, typeObject } = payload; const hasType = isSomething(typeObject.type); const hasDefault = isSomething(typeObject.default); const fullObject = hasType && hasDefault; const onlyType = hasType && !hasDefault; const onlyDefault = !hasType && hasDefault; const typeFromObject = parseValueTypeConstant(typeObject.type); const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default); if (onlyType) return typeFromObject; if (onlyDefault) return typeFromDefaultValue; if (typeFromObject !== typeFromDefaultValue) { const propertyPath = controller ? `${controller}.${token}` : token; throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`); } if (fullObject) return typeFromObject; } function parseValueTypeDefinition(payload) { const { controller, token, typeDefinition } = payload; const typeObject = { controller, token, typeObject: typeDefinition }; const typeFromObject = parseValueTypeObject(typeObject); const typeFromDefaultValue = parseValueTypeDefault(typeDefinition); const typeFromConstant = parseValueTypeConstant(typeDefinition); const type = typeFromObject || typeFromDefaultValue || typeFromConstant; if (type) return type; const propertyPath = controller ? `${controller}.${typeDefinition}` : token; throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`); } function defaultValueForDefinition(typeDefinition) { const constant = parseValueTypeConstant(typeDefinition); if (constant) return defaultValuesByType[constant]; const hasDefault = hasProperty(typeDefinition, "default"); const hasType = hasProperty(typeDefinition, "type"); const typeObject = typeDefinition; if (hasDefault) return typeObject.default; if (hasType) { const { type } = typeObject; const constantFromType = parseValueTypeConstant(type); if (constantFromType) return defaultValuesByType[constantFromType]; } return typeDefinition; } function valueDescriptorForTokenAndTypeDefinition(payload) { const { token, typeDefinition } = payload; const key = `${dasherize(token)}-value`; const type = parseValueTypeDefinition(payload); return { type, key, name: camelize(key), get defaultValue() { return defaultValueForDefinition(typeDefinition); }, get hasCustomDefaultValue() { return parseValueTypeDefault(typeDefinition) !== void 0; }, reader: readers[type], writer: writers[type] || writers.default }; } var defaultValuesByType = { get array() { return []; }, boolean: false, number: 0, get object() { return {}; }, string: "" }; var readers = { array(value) { const array = JSON.parse(value); if (!Array.isArray(array)) { throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`); } return array; }, boolean(value) { return !(value == "0" || String(value).toLowerCase() == "false"); }, number(value) { return Number(value.replace(/_/g, "")); }, object(value) { const object = JSON.parse(value); if (object === null || typeof object != "object" || Array.isArray(object)) { throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`); } return object; }, string(value) { return value; } }; var writers = { default: writeString, array: writeJSON, object: writeJSON }; function writeJSON(value) { return JSON.stringify(value); } function writeString(value) { return `${value}`; } var Controller = class { constructor(context) { this.context = context; } static get shouldLoad() { return true; } static afterLoad(_identifier, _application) { return; } get application() { return this.context.application; } get scope() { return this.context.scope; } get element() { return this.scope.element; } get identifier() { return this.scope.identifier; } get targets() { return this.scope.targets; } get outlets() { return this.scope.outlets; } get classes() { return this.scope.classes; } get data() { return this.scope.data; } initialize() { } connect() { } disconnect() { } dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}) { const type = prefix ? `${prefix}:${eventName}` : eventName; const event = new CustomEvent(type, { detail, bubbles, cancelable }); target.dispatchEvent(event); return event; } }; Controller.blessings = [ ClassPropertiesBlessing, TargetPropertiesBlessing, ValuePropertiesBlessing, OutletPropertiesBlessing ]; Controller.targets = []; Controller.outlets = []; Controller.values = {}; // js/utils/controller.ts var ELEMENT_CHECKS = [ { key: "Target", requiredName: "requiredTargets", sourceName: "targets" }, { key: "Class", requiredName: "requiredClasses", sourceName: "classes" }, { key: "Outlet", requiredName: "requiredOutlets", sourceName: "outlets" } ]; var Controller2 = class extends Controller { constructor(context) { super(context); var _a; if ((_a = window.StimulusConfig) == null ? void 0 : _a.checks_enabled) { this.healthCheck(); } } healthCheck() { ELEMENT_CHECKS.forEach((check) => { this.checkElements(check); }); } checkElements(check) { const elementType = check.key; const required = this.constructor[check.requiredName]; const baseElements = this.constructor[check.sourceName]; if (required && required.length > 0) { const errors = []; const warnings = []; required.forEach((requiredKey) => { if (!this[`has${capitalize2(requiredKey)}${elementType}`]) { errors.push(requiredKey); } if (!baseElements.includes(requiredKey)) { warnings.push(requiredKey); } }); if (errors.length > 0) { console.warn(`Missing ${elementType} elements for "${this.identifier}" controller: [${errors.join(", ")}] (Not found in DOM)`); } if (warnings.length > 0) { console.warn(`Some required ${check.sourceName} for "${this.identifier}" controller are missing: [${warnings.join(" ")}]`); } } } get csrfToken() { var _a; return ((_a = document.querySelector('meta[name="csrf-token"]')) == null ? void 0 : _a.getAttribute("content")) || ""; } }; Controller2.blessings = [ ...Controller.blessings.filter((bless2) => bless2.name == "TargetPropertiesBlessing"), CustomTargetPropertiesBlessing ]; function readInheritableStaticArrayValues2(constructor, propertyName) { const ancestors = getAncestorsForConstructor2(constructor); return Array.from(ancestors.reduce((values, constructor2) => { getOwnStaticArrayValues2(constructor2, propertyName).forEach((name) => values.add(name)); return values; }, new Set())); } function getAncestorsForConstructor2(constructor) { const ancestors = []; while (constructor) { ancestors.push(constructor); constructor = Object.getPrototypeOf(constructor); } return ancestors.reverse(); } function getOwnStaticArrayValues2(constructor, propertyName) { const definition = constructor[propertyName]; return Array.isArray(definition) ? definition : []; } function CustomTargetPropertiesBlessing(constructor) { const targets = readInheritableStaticArrayValues2(constructor, "targets"); return targets.reduce((properties, targetDefinition) => { return Object.assign(properties, propertiesForTargetDefinition2(targetDefinition)); }, {}); } function propertiesForTargetDefinition2(name) { return { [`${name}Target`]: { get() { const target = this.targets.find(name); if (target) { return target; } else { console.error(`Missing target element "${name}" for "${this.identifier}" controller`); } } }, [`${name}Targets`]: { get() { return this.targets.findAll(name); } }, [`has${capitalize2(name)}Target`]: { get() { return this.targets.has(name); } } }; } function capitalize2(value) { return value.charAt(0).toUpperCase() + value.slice(1); } // js/controllers/cart_item_controller.ts var cart_item_controller_default = class extends Controller2 { connect() { this.setDataEndpointFromParent(); this.handleImageLoading(); this.handleQtyBtnState(); if (this.multiLastValue) { this.handleBundledItems(); } } setDataEndpointFromParent() { var _a; const cartItemsList = (_a = this.element) == null ? void 0 : _a.parentElement; if (cartItemsList) { const cartDrawer = cartItemsList.parentElement; const dataEndpoint = cartDrawer == null ? void 0 : cartDrawer.getAttribute("data-cart-drawer-data-endpoint-value"); if (!!dataEndpoint && dataEndpoint !== this.dataEndpointValue) { this.dataEndpointValue = dataEndpoint; } } } checkLimit() { this.handleOnHoverMessages([this.quantityLimitElement, this.quantityOOSElement, this.orderQuantityLimitElement], "remove"); } hideLimit() { this.handleOnHoverMessages([this.quantityLimitElement, this.quantityOOSElement, this.orderQuantityLimitElement], "add"); } handleOnHoverMessages(elements, method) { elements.forEach(({ messageSelector, shouldUpdate }) => { var _a, _b; const element = (_b = (_a = this.element) == null ? void 0 : _a.shadowRoot) == null ? void 0 : _b.querySelector(messageSelector); if (element && shouldUpdate) { element.classList[method]("hidden"); } }); } handleBundledItems() { const bundledExtraItems = document.createElement("div"); bundledExtraItems.classList.add("cart-item__bundled-extra"); bundledExtraItems.slot = "bundled"; bundledExtraItems.textContent = `+${this.extraItemsValue}`; this.element.appendChild(bundledExtraItems); } loading(element, state) { element == null ? void 0 : element.classList[state ? "add" : "remove"]("loading"); } async updateQuantity({ params: { newQty, disabled } }) { var _a, _b; if (disabled) { return; } const requestBody = this.buildUpdateRequest(newQty); const cartItemElement = (_b = (_a = this.element) == null ? void 0 : _a.shadowRoot) == null ? void 0 : _b.querySelector(".cart-item-container"); this.loading(cartItemElement, true); fetch(this.dataEndpointValue, requestBody).then(async (response) => { try { const htmlCartResponse = await response.text(); const action = newQty === 0 ? "remove" : newQty > this.qtyValue ? "increase" : "decrease"; const detail = { action, newQty, updatedSkuId: this.skuIdValue, updatedSkuName: this.skuNameValue }; if (this.validateHTMLResponse(htmlCartResponse)) { detail["html"] = htmlCartResponse; } this.qtyValue = newQty; const event = new CustomEvent("fetchCartDrawer", { detail }); window.dispatchEvent(event); } catch (error2) { console.error("Could not dispatch event", error2); this.loading(cartItemElement, false); } }).catch((error2) => { console.error("Could not update item", this.skuIdValue, "reason", error2); this.loading(cartItemElement, false); }); } async removeItem() { await this.updateQuantity({ params: { newQty: 0 } }); } buildUpdateRequest(newQty) { const isOfferItem = this.offerCodeValue !== ""; const isCollectionItem = Object.entries(this.collectionValue).length > 0; const action = newQty === 0 ? "delete" : "update"; const requestParams = isOfferItem ? { offerCode: this.offerCodeValue } : { action, quantity: newQty, skus: [this.skuIdValue], isReward: !!this.isRewardValue }; if (isCollectionItem) { requestParams.skus = this.skuIdValue; requestParams["collectionData"] = this.collectionValue; } return { method: "POST", headers: { "Content-Type": "application/json", "x-csrf-token": this.csrfToken }, body: JSON.stringify(requestParams) }; } validateHTMLResponse(html) { try { const parsedResponse = JSON.parse(html); if (parsedResponse && "sku" in parsedResponse) { return false; } } catch (e) { return true; } return false; } handleImageLoading() { var _a; const images = (_a = this.element) == null ? void 0 : _a.querySelectorAll("img"); if ((images == null ? void 0 : images.length) > 0) { images.forEach((image) => { image.addEventListener("load", () => { image.classList.add("loaded"); }); image.addEventListener("error", this.checkImage.bind(this, image)); }); } } handleQtyBtnState() { var _a, _b, _c, _d; const className = ".cart-item__quantity-button"; const increaseButton = (_b = (_a = this.element) == null ? void 0 : _a.shadowRoot) == null ? void 0 : _b.querySelector(`${className}--up`); const decreaseButton = (_d = (_c = this.element) == null ? void 0 : _c.shadowRoot) == null ? void 0 : _d.querySelector(`${className}--down`); if (this.increaseDisabled && increaseButton) { increaseButton.ariaDisabled = "true"; increaseButton.classList.add("disabled"); } if (this.decreaseDisabled && decreaseButton) { decreaseButton.ariaDisabled = "true"; decreaseButton.classList.add("disabled"); } } checkImage(element) { element.classList.remove("loaded"); const alternatives = JSON.parse((element == null ? void 0 : element.getAttribute("data-cart-item-thumbnail-alternatives-value")) || "[]"); if (alternatives.length > 0) { const alternative = alternatives.shift(); if (alternative) { element.src = alternative; element.setAttribute("data-cart-item-thumbnail-alternatives-value", JSON.stringify(alternatives)); } } } get increaseDisabled() { return this.cartLimitValue || this.qtyValue === this.qtyLimitValue || this.isOutOfStockValue; } get decreaseDisabled() { return this.qtyValue === 1; } get quantityLimitElement() { return { messageSelector: ".cart-item-quantity-limit-wrapper", shouldUpdate: this.qtyValue === this.qtyLimitValue }; } get quantityOOSElement() { return { messageSelector: ".cart-item-quantity-oos-wrapper", shouldUpdate: this.isOutOfStockValue }; } get orderQuantityLimitElement() { return { messageSelector: ".cart-item-order-qty-limit-wrapper", shouldUpdate: this.cartLimitValue }; } }; cart_item_controller_default.values = { cartLimit: Boolean, collection: Object, extraItems: Number, isOutOfStock: Boolean, isReward: Boolean, multiLast: Boolean, offerCode: String, qty: Number, qtyLimit: Number, skuId: String, skuName: String, thumbnailAlternatives: Array, type: String, dataEndpoint: "/cart/v3_0/drawer/" }; // js/controllers/cart_icon_controller.ts var cart_icon_controller_default = class extends Controller2 { connect() { this.checkMobile(); window.addEventListener("resize", this.checkMobile.bind(this)); } checkMobile() { this.isMobileValue = window.innerWidth < 1024; } setItemsCount({ detail: { itemsCount } }) { var _a, _b; const emptyCartClass = "cart-empty"; const classAction = itemsCount === "0" ? "add" : "remove"; const selector = `[data-${this.identifier}-target~="itemsCount"]`; const itemsCountTarget = this.hasItemsCountTarget ? this.itemsCountTarget : (_b = (_a = this.element) == null ? void 0 : _a.parentNode) == null ? void 0 : _b.querySelector(selector); if (itemsCountTarget) { itemsCountTarget.textContent = itemsCount; itemsCountTarget.classList[classAction](emptyCartClass); } } handleMouseEnter() { if (!this.isMouseActionDisabled) { const event = new CustomEvent("openCart"); window.dispatchEvent(event); } } handleCartIconClick() { this.isRedirectingValue = true; if (this.cartIconUrlValue) { const event = new CustomEvent("closeCart", { detail: { delay: 0 } }); window.dispatchEvent(event); window.location.href = this.cartIconUrlValue; } this.isRedirectingValue = false; } get isMouseActionDisabled() { return this.isMobileValue || this.isDrawerDisabledValue || this.isRedirectingValue; } }; cart_icon_controller_default.targets = ["itemsCount"]; cart_icon_controller_default.values = { isMobile: false, cartIconUrl: "/cart", isDrawerDisabled: false, isRedirecting: false }; // js/utils/cart.ts var FULL_HEIGHT = 100; var FULL_SCREEN_CLASS = "cart-drawer__fullscreen"; var cartDrawerTargets = [ "alerts", "cartItemsList", "quantity", "drawerComponent", "errorModal", "handle", "toastNotifications", "overlayClose", "modalClose", "styles" ]; var cartDrawerValues = { mode: "overlay", dataEndpoint: "/cart/v3_0/drawer/", errorEndpoint: "/cart/v3_0/drawer/error", forceClose: false, isLoading: false, missingData: false, blockUpdate: false, stylesLoaded: false }; var CartDrawer2 = class extends Controller2 { }; var processATBResponse = (params) => { const atbData = params.atbResponseData; if ("getItem" in atbData && "getAllItems" in atbData) { params.atbResponseData["added_item"] = atbData.getItem() || {}; params.atbResponseData["cart_items"] = atbData.getAllItems() || []; } return params; }; var fetchCartWithATB = async ({ endpoint, csrfToken, params }) => { const processedParams = params ? processATBResponse(params) : params; return await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", "x-csrf-token": csrfToken || "" }, body: JSON.stringify(processedParams) }).then(async (response) => await response.text()).catch((error2) => { console.error("Could not update cart", "reason", error2); }); }; var fetchCart = (args) => { const { endpoint, errorEndpoint, mode, params } = args; const { collectionId, offerCode, skuId = [], quantity = 1, error: error2 = false, errorMessage } = params || {}; const shouldIncludeParams = mode === "modal" && params && error2 === false; const idParams = offerCode ? `&offerCode=${offerCode}` : `&skuId=${skuId.toString()}`; const collectionParams = collectionId ? `&collectionId=${collectionId.toString()}` : ""; const errorParams = error2 && errorMessage ? `&message=${encodeURIComponent(errorMessage)}` : ""; const updateParams = `${idParams}&quantity=${quantity}${collectionParams}`; const requestParams = shouldIncludeParams ? updateParams : errorParams; const baseUrl = error2 ? errorEndpoint : endpoint; const url = `${baseUrl}?mode=${mode}${requestParams}`; return fetch(url).then((response) => response.text()).catch((error3) => console.warn("Could not fetch cart drawer", { error: error3, url })); }; var cartDrawerAnalytics = ({ drawerAction, drawerLabel, mode }) => { const cartDrawerType = mode === "overlay" ? "cart_dropdown" : "cart_overlay"; if (cartDrawerType) { const cartDrawerEvent = new CustomEvent("cart.drawer.clicked", { detail: { cartDrawerCta: drawerLabel, cartDrawerAction: drawerAction, cartDrawerCategory: cartDrawerType } }); window.dispatchEvent(cartDrawerEvent); } }; var handlePageScroll = (action) => { const hasVulcanStyles = window._platform === "vulcan"; const scrollClass = hasVulcanStyles ? "disable-scroll--modernized" : "disable-scroll"; const removeAdditionalClass = "active-gnav"; if (action === "disable") { document.body.classList.add(scrollClass); document.body.classList.remove(removeAdditionalClass); document.documentElement.classList.add(scrollClass); } else { document.body.classList.remove(scrollClass, removeAdditionalClass); document.documentElement.classList.remove(scrollClass); } }; var setDrawerHeight = (modal, value) => { const newHeight = Math.max(0, Math.min(FULL_HEIGHT, value)); if (newHeight === FULL_HEIGHT) { modal.classList.add(FULL_SCREEN_CLASS); } else { modal.style.height = `${newHeight}dvh`; modal.classList.remove(FULL_SCREEN_CLASS); } return newHeight; }; var getDrawerHeight = (modal) => modal.offsetHeight / window.innerHeight * 100; var clearDrawerHeight = (modal) => { modal.style.height = ""; modal.classList.remove(FULL_SCREEN_CLASS); }; var touchPosition = (event) => { const data = event.touches ? event.touches[0] : event; return data.pageY; }; var setGlobalStyles = (element) => { const stylesInRoot = document.head.querySelector('[data-cart-drawer-target="styles"][data-loaded="true"]'); if (!stylesInRoot) { const updatedElement = element.cloneNode(true); updatedElement.setAttribute("data-loaded", "true"); document.head.appendChild(updatedElement); element.remove(); return true; } element.remove(); return !!stylesInRoot; }; var sanitizePayload = (payload) => { const sanitizedPayload = __spreadValues({}, payload); const isMultiSku = "ac_results" in payload && payload.ac_results.length > 1; const isCollection = "coll_info" in payload && payload.coll_info; if ("dataLayer" in payload) { delete sanitizedPayload.dataLayer; } if ("trans_data" in payload) { delete sanitizedPayload.trans_data; } if (isMultiSku && !isCollection) { sanitizedPayload.ac_results = sanitizedPayload.ac_results.map((item) => { var _a; const cartItem = ((_a = item == null ? void 0 : item.result) == null ? void 0 : _a.CARTITEM) || {}; cartItem == null ? true : delete cartItem.itemForm; cartItem == null ? true : delete cartItem.replenishmentItemForm; return item; }); } return sanitizedPayload; }; // js/controllers/cart_drawer_controller.ts var cart_drawer_controller_default = class extends CartDrawer2 { constructor() { super(...arguments); this.CLOSE_THRESHOLD = 25; this.EXPAND_THRESHOLD = 75; this.drawerHeight = 0; this.fullscreenClass = FULL_SCREEN_CLASS; this.onKeypress = (event) => { if (event.key === "Escape") { this.close(); } }; this.onDragStart = (event) => { const newHeight = getDrawerHeight(this.modalContentTarget); setDrawerHeight(this.modalContentTarget, newHeight); this.dragPosition = touchPosition(event); window.addEventListener("mousemove", this.onDragMove); window.addEventListener("touchmove", this.onDragMove, { passive: true }); window.addEventListener("mouseup", this.onDragEnd); window.addEventListener("touchend", this.onDragEnd); }; this.onDragMove = (event) => { if (this.dragPosition === void 0) { return; } const y = touchPosition(event); const deltaY = this.dragPosition - y; const deltaHeight = deltaY / window.innerHeight * 100; const newHeight = this.drawerHeight + deltaHeight; setDrawerHeight(this.modalContentTarget, newHeight); this.dragPosition = y; }; this.onDragEnd = () => { this.dragPosition = void 0; if (this.drawerHeight < this.CLOSE_THRESHOLD) { this.close(); setTimeout(() => { clearDrawerHeight(this.modalContentTarget); }, 500); } else if (this.drawerHeight > this.EXPAND_THRESHOLD) { clearDrawerHeight(this.modalContentTarget); this.modalContentTarget.classList.add(this.fullscreenClass); } else { clearDrawerHeight(this.modalContentTarget); } }; } initialize() { const shadowHost = document.querySelector('[data-controller="cart-drawer"]'); const shadowRoot = shadowHost == null ? void 0 : shadowHost.shadowRoot; this.modalContentTarget = shadowRoot == null ? void 0 : shadowRoot.querySelector(".cart-wrapper__modal"); this.overlayContentTarget = shadowRoot == null ? void 0 : shadowRoot.querySelector(".cart-wrapper__overlay"); } connect() { this.initialize(); this.updateContent().then(() => this.toggleComponents()); } stylesTargetConnected() { if (this.hasStylesTarget) { if (this.stylesLoadedValue) { this.stylesTarget.remove(); } else { this.stylesLoadedValue = setGlobalStyles(this.stylesTarget); } } } stylesTargetDisconnected() { this.stylesLoadedValue = true; } open(event) { var _a, _b; this.forceCloseValue = false; if (!this.isLoadingValue && !this.blockUpdate) { this.blockUpdate = (_b = (_a = event == null ? void 0 : event.detail) == null ? void 0 : _a.blockUpdate) != null ? _b : false; this.toggleCartMode(event).then(() => { setTimeout(() => { if (!this.isDrawerDisabled) { handlePageScroll("disable"); this.displayComponents("enable"); const initialFocusTarget = this.modeValue === "overlay" ? this.overlayCloseTarget : this.modalCloseTarget; initialFocusTarget.focus(); window.addEventListener("keydown", this.onKeypress); } }, this.timeOut); }); this.unblockUpdate(); } } close(event) { var _a, _b; event && this.forceClosing(event); const delay = (_b = (_a = event == null ? void 0 : event.detail) == null ? void 0 : _a.delay) != null ? _b : this.timeOut; const eventType = event && event["type"]; if (eventType === "click") { cartDrawerAnalytics({ drawerAction: "dismiss", drawerLabel: "close_icon", mode: this.modeValue }); } this._closingTimeout = setTimeout(() => { handlePageScroll("enable"); this.displayComponents("disable"); window.removeEventListener("keydown", this.onKeypress); window.removeEventListener("mousemove", this.onDragMove); window.removeEventListener("touchmove", this.onDragMove); window.removeEventListener("mouseup", this.onDragEnd); window.removeEventListener("touchend", this.onDragEnd); }, delay); } abortClosing() { !this.forceCloseValue && clearTimeout(this._closingTimeout); } forceClosing(event) { if (!this.forceCloseValue && (event == null ? void 0 : event.params) && (event == null ? void 0 : event.params.forceClose)) { this.forceCloseValue = true; } } redirect({ params: { url, analytics, ctaLabel } }) { if (!analytics) { if (url.includes("viewcart") || url.includes("cart")) { analytics = "view_bag_cta"; } else if (url.includes("checkout")) { analytics = "checkout_cta"; } else { analytics = this.modeValue === "overlay" ? `cart_dropdown - ${ctaLabel}` : `cart_overlay - ${ctaLabel}`; } } cartDrawerAnalytics({ drawerLabel: analytics, drawerAction: "click", mode: this.modeValue }); handlePageScroll("enable"); this.displayComponents("disable"); if (url) { window.location.href = url; } } dismissAlert({ params: { key } }) { if (this.hasAlertsTarget) { const alertTarget = this.alertsTargets.find((alert) => alert.dataset.key === key); if (alertTarget) { alertTarget.remove(); } } } unblockUpdate() { if (this.blockUpdate) { setTimeout(() => { this.blockUpdate = false; }, 500); } } displayComponents(action) { for (const element of this.element.innerElements) { const elementName = (element == null ? void 0 : element.getAttribute("data-cart-element")) || ""; const shouldUpdate = [`${this.modeValue}`, "background"].includes(elementName); const showElement = () => { element == null ? void 0 : element.classList.remove("hidden", "hidden--onload"); }; if (shouldUpdate) { action === "enable" ? showElement() : element == null ? void 0 : element.classList.add("hidden"); if (element.classList.contains("cart-wrapper__bg-placeholder")) { this.handleBgPlaceholder(element); } } } } handleBgPlaceholder(element) { if (element.classList.contains("modal") && this.modeValue !== "modal") { element.classList.remove("modal"); } else { element.classList.remove("overlay"); } element.classList.add(this.modeValue); } updateDialogLabel() { const label = document.querySelector(`#cart-drawer-header-${this.modeValue}`); const content = this.modeValue === "overlay" ? this.overlayContentTarget : this.modalContentTarget; content.setAttribute("aria-label", (label == null ? void 0 : label.textContent) || ""); } async updateContent(params) { const newContent = await this.getHTMLContent(params); if (newContent) { this.repaint(newContent); if (params == null ? void 0 : params.detail) { this.triggerToastNotifications(params.detail); } this.updateCartIconCount(); this.updateDialogLabel(); } this.toggleComponents(); } async getHTMLContent(params) { var _a; const fetchParams = { params, mode: this.modeValue, csrfToken: this.csrfToken, endpoint: this.dataEndpointValue, errorEndpoint: this.errorEndpointValue }; if (params == null ? void 0 : params.atbResponseData) { return await fetchCartWithATB(fetchParams); } if (this.missingDataValue) { return await fetchCart(fetchParams).finally(() => { this.isLoadingValue = false; this.missingDataValue = false; }); } const htmlResponse = (params == null ? void 0 : params.html) || ((_a = params == null ? void 0 : params.detail) == null ? void 0 : _a.html); if (htmlResponse) { return htmlResponse; } this.isLoadingValue = true; return await fetchCart(fetchParams).finally(() => { this.isLoadingValue = false; this.missingDataValue = false; }); } repaint(html) { const prevScrollPos = this.hasCartItemsListTarget ? this.cartItemsListTarget.scrollTop : 0; this.element.innerHTML = html; requestAnimationFrame(() => { if (this.hasCartItemsListTarget) { this.cartItemsListTarget.scrollTop = prevScrollPos; } }); } updateCartIconCount() { if (this.hasQuantityTarget) { const itemsCount = this.quantityTarget.getAttribute("data-value"); try { if (itemsCount) { const event = new CustomEvent("setCartIconCount", { detail: { itemsCount } }); window.dispatchEvent(event); } } catch (error2) { console.error("Could not dispatch event", error2); } } } async toggleCartMode(event) { var _a; const newMode = ((_a = event == null ? void 0 : event.detail) == null ? void 0 : _a.cartMode) || "overlay"; const hasToggled = this.modeValue !== newMode || newMode === "modal"; if (hasToggled) { this.modeValue = newMode; if (newMode === "modal" || this.hasErrorModalTarget) { await this.updateContent(event == null ? void 0 : event.detail); } this.toggleComponents(); if (this.missingDataValue && newMode === "overlay") { setTimeout(async () => { await this.updateContent(); }, 1); } } } toggleComponents() { if (this.hasDrawerComponentTarget) { for (const component of this.drawerComponentTargets) { const elementMode = (component == null ? void 0 : component.getAttribute("data-cart-drawer-mode")) || (component == null ? void 0 : component.getAttribute("slot")) || ""; if (elementMode !== this.modeValue) { component.classList.add("hidden"); } else { component.classList.remove("hidden"); } } } } triggerToastNotifications(event) { const { action = "", updatedSkuName = "" } = event || {}; if (action === "remove" && this.hasToastNotificationsTarget) { const message = this.toastNotificationsTarget.textContent || ""; this.toastNotificationsTarget.textContent = message.replace(/::[^:]+::/g, updatedSkuName); this.toastNotificationsTarget.classList.remove("hidden"); setTimeout(() => { this.toastNotificationsTarget.classList.add("hidden"); }, 4e3); } } get timeOut() { return this.modeValue === "overlay" ? 500 : 0; } get isDrawerDisabled() { const cartIcon = document.querySelector('[id="cart-icon"][data-controller~="cart-icon"]'); if (cartIcon) { const isDrawerDisabled = cartIcon.getAttribute("data-cart-icon-is-drawer-disabled-value"); return isDrawerDisabled === "true"; } } }; cart_drawer_controller_default.targets = cartDrawerTargets; cart_drawer_controller_default.values = cartDrawerValues; // js/webcomponents/utils/constants.ts var defaultKeys = { cartItem: "cart-item", cartIcon: "cart-icon", cartDrawer: "cart-drawer" }; var defaultIdentifiers = { [defaultKeys.cartItem]: cart_item_controller_default, [defaultKeys.cartIcon]: cart_icon_controller_default, [defaultKeys.cartDrawer]: cart_drawer_controller_default }; // js/webcomponents/utils/controllers.ts var domReady2 = new Promise((resolve) => { if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => resolve()); } else { resolve(); } }); var registerController = async (identifiers) => { await domReady2; const app = window.Stimulus || (window.Stimulus = Application.start()); identifiers.map((identifier) => { if (identifier in defaultIdentifiers && !app.controllers.find((controller) => controller.identifier === identifier)) { app.register(identifier, defaultIdentifiers[identifier]); } }); }; // js/cart/utils/constants.ts var ALLOWED_ERROR_MSG_KEYS = [ "allocation.qty_reduced", "cart.item_limit", "cart.qty_limit.reduced", "early_access_item" ]; var ATB_EVENTS = ["addToCart.success", "dwAddToCart.success"]; var ATB_FAILURE_EVENTS = ["addToCart.failure"]; var CART_CONFIGS = { aud_seg_allow: false, cart_drawer: false, cart_drawer_automount: false, has_audseg: false, drawer_route: "/cart/v3_0/drawer" }; var CONTROLLER_EVENTS = [ "openCart@window->cart-drawer#open", "failCart@window->cart-drawer#fail", "fetchCartDrawer@window->cart-drawer#updateContent", "closeCart@window->cart-drawer#close" ]; var DRAWER_ATTRIBUTES = { "data-cart-drawer-mode": "overlay", "data-controller": "cart-drawer", "data-cart-drawer-mode-value": "overlay", "data-action": CONTROLLER_EVENTS.join(" ") }; var SELECTORS = { cartDrawer: "cart-drawer", cbox: "#cboxContent", cartIconDrupal: '[data-behavior-cart="icon"]', cartIconGemini: '[data-behavior-cart="icon"]', cartIconVulcan: '[data-controller*="cart"]', countIconNodesOrder: [ ".site-bag__link-count", ".utility-nav__cart-count", ".gnav-util__icon__cart-count", ".header-gnav-cart__count", '[class*="utility-nav__cart"]', '[data-cart-target="itemsCount"]' ], itemSelector: "data-sku-base-id", legacyCartDrawerVulcan: '[data-behaviour="cart-drawer"]', legacyCartDrawerDrupal: ['[data-behavior-cart="modal"]', ".header-gnav-cart__overlay"], maxErrorMessage: '[data-test-id="max_error_message"]', offerCode: "[data-offercode]", qtySelector: '[data-test-id="cart_product_quantity"]', recentAddedItem: "data-cart-item-sku-id-value" }; var SUPPRESSED_PLATFORMS = ["tomfordbeauty"]; var SUPPRESSED_PAGES = [ "/checkout/viewcart.tmpl", "/cart", "/guest-checkout", "/checkout", "/sign-in", "/sign-up" ]; var WEBCOMPONENTS_CONTROLLERS = ["cart-icon", "cart-drawer", "cart-item"]; // js/cart/utils/helpers.ts var isVulcan = () => window._platform === "vulcan"; var matchLocation = (suppressed, location) => !!suppressed.some((path) => location.includes(path)); var setAttributes = (element, attributes) => { Object.entries(attributes).forEach(([key, value]) => { element.setAttribute(key, value); }); }; var getCookie = (cookieWithValue) => { return document.cookie.split(";").some((item) => item.trim().toUpperCase().startsWith(cookieWithValue)); }; var debugMode = () => getCookie("VULCANIZE_CART_DEBUG=1"); var forceMount = () => getCookie("VULCANIZE_CART=1"); // js/cart/platform/gemini/index.ts var openCartEvent = (params) => { var _a; const { quantity, collectionId, offerCode, skuId } = params; const detail = { cartMode: "modal", quantity }; if (skuId) { detail["skuId"] = skuId; } if (offerCode) { detail["offerCode"] = offerCode; } if (collectionId) { detail["collectionId"] = collectionId; } const newCartEvent = new CustomEvent("openCart", { detail }); window.dispatchEvent(newCartEvent); const generic = typeof window.generic === "object" ? window.generic : {}; (_a = generic == null ? void 0 : generic.overlay) == null ? void 0 : _a.hide(); }; var isGem = () => "__NEXT_DATA__" in window && typeof window.__NEXT_DATA__ === "object"; var mountIconOnGemini = (icon) => { var _a; const iconCountElement = document.createElement("div"); setAttributes(iconCountElement, { "data-cart-icon-target": "itemsCount", "data-testid": "cartOverlayIconCounter", class: "utility-nav_utility-nav__cart__WxHwB" }); (_a = icon.parentNode) == null ? void 0 : _a.insertBefore(iconCountElement, icon.nextSibling); }; var mountOnGeminiATB = () => { window.addEventListener("addToCart.success", (event) => { const { cartItems } = event.detail; if (cartItems && cartItems.length) { const { skuBaseId = "", quantity: itemQuantity = 1 } = cartItems[0]; const recentAddedItem = document.querySelector(`[${SELECTORS.recentAddedItem}="${skuBaseId}"]`); const recentAddedItemPrevQty = (recentAddedItem == null ? void 0 : recentAddedItem.getAttribute("data-cart-item-qty-value")) || "0"; const previousItemQuantity = parseInt(recentAddedItemPrevQty, 10); const quantity = itemQuantity > previousItemQuantity ? itemQuantity - previousItemQuantity : itemQuantity; openCartEvent({ skuId: skuBaseId, quantity }); } }); }; // js/cart/utils/mutations.ts var observeMutations = (target, callback, config) => { const observer = new MutationObserver(callback); if (target) { observer.observe(target, __spreadValues({ childList: true }, config)); } return observer; }; // js/cart/utils/debug.ts var debugConsole = (message, level = "info", context, error2) => { var _a; if (debugMode()) { const levels = { debug: 0, info: 1, warn: 2, error: 3 }; const isConcerning = levels[level] > levels["info"] && error2; if (levels[level] >= levels["info"]) { console[level](message, context); if (isConcerning && "DD_RUM" in window) { (_a = window.DD_RUM) == null ? void 0 : _a.onReady(() => { var _a2; (_a2 = window.DD_RUM) == null ? void 0 : _a2.addError(error2, { message, context }); }); } } } }; // js/cart/platform/tenants.ts var deactivateLegacyCart = () => { if ($(".js-gnav-cart").length) { $(".js-gnav-cart").removeClass("active"); } }; var overrideCartIconLink = () => { try { if ($(".js-gnav-util-trigger--cart").length) { $(document).on("click", ".js-gnav-util-trigger--cart", function() { window.location = $(this).attr("href"); return true; }); } } catch (error2) { debugConsole("[Cart 3.0] Unable to override Cart Icon link", "warn", { component: "Cart Icon", details: error2 }, error2); } }; var handleDWAddToCart = (collectionId, allItems = []) => { var _a; if (allItems.length > 0) { const itemInCart = allItems.find((item) => item.COLLECTION_ID === collectionId); if (itemInCart && itemInCart.COLLECTION_SUBTYPE === "EL_DW_DRAMMING" && itemInCart["sku.SKU_BASE_ID"]) { return (_a = itemInCart.sku_string) != null ? _a : itemInCart["sku.SKU_BASE_ID"]; } } }; var observeRemountIcon = (mountOnIcon2) => { var _a; const cartIcon = document.querySelector(SELECTORS.cartIconGemini); if (cartIcon) { const target = ((_a = cartIcon.parentNode) == null ? void 0 : _a.parentNode) || document.body; observeMutations(target, () => mountOnIcon2()); } }; var TENANTS_SAFEGUARDS = { AV: { LEGACY_CART: { fn: deactivateLegacyCart, desc: "When ATB success event is triggered, it tries to enable legacy cart drawer. This function will try to prevent that." }, CART_ICON_OVERRIDE: { fn: overrideCartIconLink, desc: "There is a small hack on Drupal that sets and blocks cart link on cart icon. This will override the cart icon link in case this happens." } }, EL: { DOUBLE_WEAR: { fn: handleDWAddToCart, desc: "Special handling for Double Wear products (collection). It will return the SKU strings for the two products involved." }, REMOUNT_ICON: { fn: observeRemountIcon, desc: "EL on Gemini updates the cart icon and this causes that the original mounting logic is lost. This will remount the icon." } } }; // js/cart/actions/remove.ts var removeLegacyOfferPopup = () => { const mutationCallback = () => { const popups = document.querySelectorAll(".sop--v2__success-popup"); popups.forEach((popup) => { popup.remove(); }); }; observeMutations(document.body, () => mutationCallback(), { subtree: true }); }; var removeLegacyErrorOverlay = () => { const mutationCallback = () => { var _a; const generic = typeof window.generic === "object" ? window.generic : {}; (_a = generic == null ? void 0 : generic.overlay) == null ? void 0 : _a.hide(); }; const maxErrorMessageElement = document.querySelector(SELECTORS.maxErrorMessage); const cboxContentElement = document.querySelector(SELECTORS.cbox); const element = maxErrorMessageElement || cboxContentElement || document.body; return observeMutations(element, () => mutationCallback(), { subtree: true }); }; var removeLegacyCartDrawer = () => { if (skipCartDrawer()) { return; } if (isGem()) { TENANTS_SAFEGUARDS["EL"]["REMOUNT_ICON"].fn(mountOnIcon); } const mutationCallback = () => { const query = isVulcan() ? SELECTORS.legacyCartDrawerVulcan : SELECTORS.legacyCartDrawerDrupal.join(","); const legacyCartDrawer = document.querySelectorAll(query); legacyCartDrawer.forEach((cartDrawer) => { if (isGem()) { cartDrawer.style.display = "none"; } else { cartDrawer.remove(); } }); }; window.dispatchEvent(new CustomEvent("cart.removeLegacyCart", { detail: { removeLegacyCart: true } })); return observeMutations(document == null ? void 0 : document.body, () => mutationCallback(), { subtree: true }); }; // js/cart/events/cart.ts var skipCartDrawer = () => { let matchesTenant = false; const { pathname, hostname, search: params } = window.location; if (params) { const tenant = new URLSearchParams(params).get("tenant") || ""; matchesTenant = matchLocation(SUPPRESSED_PLATFORMS, tenant); } const shouldSkipMount = matchLocation(SUPPRESSED_PAGES, pathname) || matchLocation(SUPPRESSED_PLATFORMS, hostname); return shouldSkipMount || matchesTenant; }; var failingCartEvent = (errorMessage) => { const observer = removeLegacyErrorOverlay(); const detail = { blockUpdate: true, cartMode: "modal", error: true, errorMessage }; const newCartEvent = new CustomEvent("openCart", { detail }); window.dispatchEvent(newCartEvent); setTimeout(() => { observer.disconnect(); }, 500); }; var openCartEvent2 = (params) => { const observer = removeLegacyErrorOverlay(); const { quantity, collectionId, offerCode, skuId } = params; const detail = { cartMode: "modal", quantity }; if (skuId) { detail["skuId"] = skuId; } if (offerCode) { detail["offerCode"] = offerCode; } if (collectionId) { detail["collectionId"] = collectionId; } const newCartEvent = new CustomEvent("openCart", { detail }); window.dispatchEvent(newCartEvent); setTimeout(() => { observer.disconnect(); }, 500); }; // js/cart/platform/drupal/mappings.ts var getCollectionID = (results) => { for (const result of results) { if ("COLLECTION_ID" in result.result && result.result.COLLECTION_ID) { return result.result.COLLECTION_ID; } } }; var getRecentAddedItem = (resultData) => { var _a, _b; const acResultsData = resultData.ac_results; const transData = resultData == null ? void 0 : resultData.trans_data; if (acResultsData.length === 1) { return acResultsData[0].result; } else { const recentItemCollectionId = getCollectionID(acResultsData); const recentItem = (_b = (_a = transData == null ? void 0 : transData.order) == null ? void 0 : _a.items) == null ? void 0 : _b.filter((eachItem) => eachItem.COLLECTION_ID === recentItemCollectionId); const recentItemSkuId = recentItem == null ? void 0 : recentItem[0]["sku.SKU_BASE_ID"]; const filteredAcResult = acResultsData.filter((eachItem) => { var _a2, _b2, _c, _d; return ((_b2 = (_a2 = eachItem.result) == null ? void 0 : _a2.CARTITEM) == null ? void 0 : _b2.CART_ID) !== null && ((_d = (_c = eachItem.result) == null ? void 0 : _c.CARTITEM) == null ? void 0 : _d["sku.SKU_BASE_ID"]) === recentItemSkuId; }); return filteredAcResult == null ? void 0 : filteredAcResult[0].result; } }; var getQuantityValue = (qtySelectorElement, skuBaseId, itemQuantity) => { if (qtySelectorElement && qtySelectorElement.textContent) { const qty = qtySelectorElement.textContent; return parseInt(qty, 10); } else { const recentAddedItem = document.querySelector(`[${SELECTORS.recentAddedItem}="${skuBaseId}"]`); const recentAddedItemPrevQty = (recentAddedItem == null ? void 0 : recentAddedItem.getAttribute("data-cart-item-qty-value")) || "0"; const previousItemQuantity = parseInt(recentAddedItemPrevQty, 10); const quantity = itemQuantity > previousItemQuantity ? itemQuantity - previousItemQuantity : itemQuantity; return quantity; } }; var getErrorMessage = (resultData) => { const _resultData = resultData != null ? resultData : []; const messages = Array.isArray(_resultData) ? _resultData : _resultData.errorObjects ? _resultData.errorObjects : []; if (messages.length > 0) { const filteredMessages = messages.filter((message) => { if (message && typeof message === "object" && "key" in message) { return ALLOWED_ERROR_MSG_KEYS.includes(message.key); } return false; }); const firstMessage = filteredMessages[0]; if (typeof firstMessage === "object" && (firstMessage == null ? void 0 : firstMessage.text)) { return firstMessage.text; } } return ""; }; var processRawATBPayload = (resultData) => { var _a, _b, _c; let collectionId; let quantity = 1; let skuId = ""; const { PREVIOUS_ITEM_QUANTITY = 0, CARTITEM } = getRecentAddedItem(resultData); const { ITEM_QUANTITY = 1, "sku.SKU_BASE_ID": skuBaseId = "" } = CARTITEM; quantity = ITEM_QUANTITY - PREVIOUS_ITEM_QUANTITY; skuId = skuBaseId; if (resultData.coll_info && resultData.coll_info.COLLECTION_TYPE && ((_a = resultData.trans_data) == null ? void 0 : _a.order)) { const COLLECTION_ID = resultData.coll_info.COLLECTION_ID; const skuData = ((_c = (_b = resultData.trans_data.order) == null ? void 0 : _b.kits) != null ? _c : []).find((kit) => kit.COLLECTION_ID === COLLECTION_ID); if (skuData) { collectionId = COLLECTION_ID; skuId = skuData["sku.SKU_BASE_ID"]; } } return { collectionId, quantity, skuId }; }; var processATBPayloadMethods = (resultData) => { var _a; const item = resultData.getItem(); const allItems = resultData.getAllItems() || []; const { COLLECTION_ID, product, ITEM_QUANTITY: itemQuantity = 1 } = item; const { sku } = product; const { SKU_BASE_ID: skuBaseId = "" } = sku; const hasEngraving = ((_a = item == null ? void 0 : item.coll_info) == null ? void 0 : _a.COLLECTION_TYPE) === "MONO"; const qtySelectorElement = document.querySelector(`[${SELECTORS.itemSelector}="${skuBaseId}"] ${SELECTORS.qtySelector}`); const skuId = TENANTS_SAFEGUARDS["EL"]["DOUBLE_WEAR"].fn(COLLECTION_ID, allItems) || skuBaseId; const collectionId = COLLECTION_ID; const quantityValue = getQuantityValue(qtySelectorElement, skuBaseId, itemQuantity); const quantity = hasEngraving ? 1 : quantityValue; return { collectionId, quantity, skuId }; }; // js/cart/platform/drupal/index.ts var fetchCartDrawer = () => { const newCartEvent = new CustomEvent("fetchCartDrawer"); window.dispatchEvent(newCartEvent); }; var atbOffer = (offerElement) => { try { const offerCode = offerElement.getAttribute("data-offercode") || ""; const eventName = offerCode ? `offer:${offerCode}:applied` : ""; try { removeLegacyOfferPopup(); } catch (e) { debugConsole("[Cart 3.0] Unable to remove legacy offer popup"); } if (eventName) { $(document).on(eventName, () => { openCartEvent2({ offerCode, quantity: 1 }); }); } } catch (e) { fetchCartDrawer(); } }; var mapATBResults = (resultData) => { const isMultiSku = "ac_results" in resultData && resultData.ac_results.length > 1; const isCollection = "coll_info" in resultData && resultData.coll_info; if (isMultiSku && !isCollection) { const newCartEvent = new CustomEvent("openCart", { detail: { atbResponseData: { result: { data: sanitizePayload(resultData) } }, cartMode: "modal", quantity: 1 } }); window.dispatchEvent(newCartEvent); return; } const rawResults = resultData.ac_results; const { collectionId, skuId, quantity } = rawResults ? processRawATBPayload(resultData) : processATBPayloadMethods(resultData); return { collectionId, quantity, skuId }; }; var isDrp = () => "jQuery" in window && typeof window.jQuery === "function"; var mountOnVulcanATB = (offerElement) => { const failATB = (_event, resultData) => { const messages = getErrorMessage(resultData); failingCartEvent(messages); }; const successATB = (_event, resultData) => { try { const atbData = mapATBResults(resultData); if (atbData) { const { collectionId, quantity, skuId } = atbData; openCartEvent2({ skuId, quantity, collectionId }); TENANTS_SAFEGUARDS["AV"]["LEGACY_CART"].fn(); } } catch (error2) { debugConsole("[Cart 3.0] Unable to trigger Drupal ATB cart modal", "error", { component: "AddToBag", details: error2.message }, error2); } }; ATB_FAILURE_EVENTS.forEach((atbFailureEvent) => { $(window).on(atbFailureEvent, failATB); $(document).on(atbFailureEvent, failATB); }); ATB_EVENTS.forEach((atbEvent) => { $(window).on(atbEvent, successATB); $(document).on(atbEvent, successATB); }); if (offerElement) { atbOffer(offerElement); } TENANTS_SAFEGUARDS["AV"]["CART_ICON_OVERRIDE"].fn(); }; // js/cart/events/atb.ts var mountATBListener = () => { if (!isVulcan()) { const offerElement = document.querySelector(SELECTORS.offerCode); isDrp() && mountOnVulcanATB(offerElement); isGem() && mountOnGeminiATB(); } }; // js/cart/actions/mount.ts var mountOnIcon = () => { const query = isVulcan() ? SELECTORS.cartIconVulcan : SELECTORS.cartIconDrupal; const icon = document.querySelector(query); if (icon && !icon.hasAttribute("data-mounted")) { const controller = icon.getAttribute("data-controller"); const target = icon.getAttribute("data-controller"); const actions = icon.getAttribute("data-action"); setAttributes(icon, { "data-mounted": "true", "data-controller": `${controller ? controller : ""} cart-icon`.trimStart(), "data-cart-target": `${target ? target : ""} cartButton`.trimStart(), "data-action": `${actions ? actions : ""} click->cart-icon#handleCartIconClick mouseenter->cart-icon#handleMouseEnter setCartIconCount@window->cart-icon#setItemsCount`.trimStart(), "data-cart-icon-cart-icon-url-value": "/checkout/viewcart.tmpl" }); const iconCount = SELECTORS.countIconNodesOrder.map((selector) => document.querySelector(selector)).find(Boolean); if (iconCount) { setAttributes(iconCount, { "data-cart-icon-target": "itemsCount" }); } else if (isGem()) { mountIconOnGemini(icon); } } return icon; }; var mountCartDrawer = async (params) => { if (skipCartDrawer()) { return; } try { const { cartDrawerEndpoint = CART_CONFIGS.drawer_route } = params || {}; return registerController(WEBCOMPONENTS_CONTROLLERS).then(() => { if (!mountOnIcon()) { debugConsole("[Cart 3.0] Cart icon not found", "warn", { component: "Cart Icon", details: "Cart icon is necessary to mount cart drawer and set basic interactions" }, new Error("Cart icon not found. Impossible to mount cart drawer.")); return; } const cartDrawer = document.createElement(SELECTORS.cartDrawer); setAttributes(cartDrawer, __spreadProps(__spreadValues({}, DRAWER_ATTRIBUTES), { "data-cart-drawer-data-endpoint-value": cartDrawerEndpoint })); document.body.appendChild(cartDrawer); mountATBListener(); debugConsole("[Cart 3.0] Cart drawer mounted"); return cartDrawer; }); } catch (error2) { debugConsole("[Cart 3.0] Unable to mount cart drawer", "error", { component: "Cart Drawer", details: "An error occurred while trying to mount cart drawer" }, error2); } }; // js/cart/actions/override.ts var overrideCartDrawerComponent = (cartDrawer, { override, elementName }) => { const { value = "", attribute = "", text = false, className = "", styles = "", mode = "overlay" } = override; const queryMode = `[slot="${mode}"]`; const query = styles ? `${elementName}${queryMode}` : `${queryMode} [slot="${elementName}"]`; const component = cartDrawer.querySelector(query); if (component) { if (attribute && component.getAttribute(attribute) !== value) { component.setAttribute(attribute, value); } if (text && component.textContent !== value) { component.textContent = value; } if (className && !component.classList.contains(className)) { component.classList.add(className); } if (styles) { overrideCartDrawerComponentStyles(component, styles); } return true; } return false; }; var overrideCartDrawerComponents = (componentOverrides, element) => { if (skipCartDrawer()) { return; } const cartDrawer = element || document.querySelector(SELECTORS.cartDrawer); observeMutations(cartDrawer || document.body, () => { if (cartDrawer) { for (const { override, elementName } of componentOverrides) { overrideCartDrawerComponent(cartDrawer, { override, elementName }); } } }, { subtree: true }); }; var overrideCartDrawerComponentStyles = (component, styles) => { if (component.shadowRoot) { try { const previousStyles = component.shadowRoot.adoptedStyleSheets; const overridedStyles = new CSSStyleSheet(); overridedStyles.replaceSync(styles); component.shadowRoot.adoptedStyleSheets = [...previousStyles, overridedStyles]; } catch (e) { const previousStyles = component.shadowRoot.querySelector("style"); if (previousStyles) { previousStyles.innerText += styles; } } } }; // js/cart/utils/configs.ts var fetchCartConfigs = async () => { var _a; if (skipCartDrawer()) { return {}; } const countryAndLanguage = /^\/([a-z]{2})\/([a-z]{2})(\/|$)/i; const languageOnly = /^\/([a-z]{2})(\/|$)/i; const pathname = window.location.pathname; const countryLangPair = countryAndLanguage.exec(pathname); const lang = countryLangPair ? countryLangPair[2] : (_a = languageOnly.exec(pathname)) == null ? void 0 : _a[1]; const country = countryLangPair ? countryLangPair[1] : null; const url = "/cart/v3_0/config" + (lang ? "?language=" + lang : "") + (country ? "&country=" + country : ""); try { const response = await fetch(url); return response.json(); } catch (error2) { debugConsole(`Could not fetch cart configs from ${url}`, "error", { component: "configs" }, error2); return CART_CONFIGS; } }; // js/cart/injection.ts var initializeCartDrawer = async (cartDrawerEndpoint) => removeLegacyCartDrawer() && await mountCartDrawer({ cartDrawerEndpoint }); var setWindowMethods = () => window._glcart = { mountCartDrawer, overrideCartDrawerComponents, removeLegacyCartDrawer }; var cartDrawerInjection = async () => { const { aud_seg_allow, cart_drawer, cart_drawer_automount, has_audseg, drawer_route } = await fetchCartConfigs(); if (forceMount()) { return initializeCartDrawer(drawer_route); } const isValidSeg = has_audseg && aud_seg_allow && (cart_drawer_automount || forceMount()); if (!has_audseg || isValidSeg) { if (cart_drawer) { cart_drawer_automount ? initializeCartDrawer(drawer_route) : setWindowMethods(); } else { debugConsole("[Cart 3.0] Cart Drawer is not enabled", "info", { component: "Cart Drawer", details: "In order to enable cart, please set the corresponding configurations and necessary feature flags in ShopKeeper." }); } } }; if (!document.querySelector(SELECTORS.cartDrawer)) { if (!skipCartDrawer()) { cartDrawerInjection(); } } })(); //# sourceMappingURL=injection.js.map