1import{Component}from"@theme/component";import{CartItemsComponent}from"@theme/component-cart-items";import{morphSection,sectionRenderer}from"@theme/section-renderer";import{fetchConfig}from"@theme/utilities";import{cartPerformance}from"@theme/performance";import{CartDiscountUpdateEvent,CartErrorEvent}from"@shopify/events";class CartDiscount extends Component{requiredRefs=["cartDiscountError","cartDiscountErrorDiscountCode","cartDiscountErrorShipping"];#activeFetch=null;#pending=!1;#needsRefresh=!1;#disableControls(){const previousBusy=this.getAttribute("aria-busy"),input=this.querySelector('input[name="discount"]'),previousReadOnly=input instanceof HTMLInputElement&&input.readOnly,buttons=Array.from(this.querySelectorAll("button"),button=>({button,previousDisabled:button.getAttribute("aria-disabled")}));this.setAttribute("aria-busy","true"),input instanceof HTMLInputElement&&(input.readOnly=!0);for(const{button}of buttons)button.setAttribute("aria-disabled","true");return()=>{previousBusy===null?this.removeAttribute("aria-busy"):this.setAttribute("aria-busy",previousBusy),input instanceof HTMLInputElement&&(input.readOnly=previousReadOnly);for(const{button,previousDisabled}of buttons)previousDisabled===null?button.removeAttribute("aria-disabled"):button.setAttribute("aria-disabled",previousDisabled)}}#createAbortController(){this.#activeFetch&&this.#activeFetch.abort();const abortController=new AbortController;return this.#activeFetch=abortController,abortController}async#refreshDiscountSection(shouldRender){const sectionId=this.dataset.sectionId;if(!sectionId)return;this.#needsRefresh=!0;let validated=!1;try{for(;!validated&&this.isConnected;){let pendingQuantityUpdates=CartItemsComponent.pendingQuantityUpdates;for(;pendingQuantityUpdates.length;)await Promise.all(pendingQuantityUpdates),pendingQuantityUpdates=CartItemsComponent.pendingQuantityUpdates;if(!this.isConnected)return;await sectionRenderer.renderSection(sectionId,{cache:!1,mode:this.closest("theme-drawer")?"hydration":"full",shouldRender:html=>(validated=!0,shouldRender?.(html)??!0)})}validated&&(this.#needsRefresh=!1)}catch(error){if(error?.name==="AbortError")return;this.dispatchEvent(new CartErrorEvent({error:error?.message||"Failed to refresh cart discounts",code:"SERVICE_UNAVAILABLE"}))}}async#refreshStaleDiscounts(){this.#pending=!0;const restoreControls=this.#disableControls();try{await this.#refreshDiscountSection()}finally{this.#pending=!1,restoreControls()}}applyDiscount=async event=>{if(event.preventDefault(),event.stopPropagation(),this.#pending)return;if(this.#needsRefresh){await this.#refreshStaleDiscounts();return}const{cartDiscountError,cartDiscountErrorDiscountCode,cartDiscountErrorShipping}=this.refs,form=event.target;if(!(form instanceof HTMLFormElement))return;const discountCode=form.querySelector('input[name="discount"]');if(!(discountCode instanceof HTMLInputElement)||typeof this.dataset.sectionId!="string")return;const discountCodeValue=discountCode.value,existingDiscounts=this.#existingDiscounts();if(existingDiscounts.includes(discountCodeValue))return;sectionRenderer.abortRender(this.dataset.sectionId);const abortController=this.#createAbortController();cartDiscountError.classList.add("hidden"),cartDiscountErrorDiscountCode.classList.add("hidden"),cartDiscountErrorShipping.classList.add("hidden");const allDiscountCodes=[...existingDiscounts,discountCodeValue],deferredPromise=CartDiscountUpdateEvent.createPromise();this.#pending=!0;const restoreControls=this.#disableControls();try{this.dispatchEvent(new CartDiscountUpdateEvent({discountCodes:allDiscountCodes.map(code=>({code})),promise:deferredPromise.promise}));const config=fetchConfig("json",{body:JSON.stringify({discount:allDiscountCodes.join(","),sections:[this.dataset.sectionId]})}),data=await(await fetch(Theme.routes.cart_update_url,{...config,signal:abortController.signal})).json();if(data.discount_codes.find(discount=>discount.code===discountCodeValue&&discount.applicable===!1)){discountCode.value="",this.#handleDiscountError("discount_code"),deferredPromise.resolve({cart:CartDiscountUpdateEvent.createCartFromAjaxResponse(data)});return}const newHtml=data.sections?.[this.dataset.sectionId],shouldRender=html=>{const section=new DOMParser().parseFromString(html,"text/html").getElementById(`shopify-section-${this.dataset.sectionId}`),discountCodes=section?.querySelectorAll(".cart-discount__pill")||[];if(section){const codes=Array.from(discountCodes).map(element=>element instanceof HTMLLIElement?element.dataset.discountCode:null).filter(
1Boolean);if(codes.length===existingDiscounts.length&&codes.every(code=>existingDiscounts.includes(code))&&data.discount_codes.find(discount=>discount.code===discountCodeValue&&discount.applicable===!0))return this.#handleDiscountError("shipping"),!1}return!0};if(!newHtml){discountCode.value="",deferredPromise.resolve({cart:CartDiscountUpdateEvent.createCartFromAjaxResponse(data)}),await this.#refreshDiscountSection(shouldRender);return}if(!shouldRender(newHtml)){discountCode.value="",deferredPromise.resolve({cart:CartDiscountUpdateEvent.createCartFromAjaxResponse(data)});return}deferredPromise.resolve({cart:CartDiscountUpdateEvent.createCartFromAjaxResponse(data)}),discountCode.value="",sectionRenderer.abortRender(this.dataset.sectionId),await morphSection(this.dataset.sectionId,newHtml,{mode:this.closest("theme-drawer")?"hydration":"full"})}catch(error){deferredPromise.reject(error),error instanceof Error&&error.name!=="AbortError"&&this.dispatchEvent(new CartErrorEvent({error:error.message||"Failed to apply discount",code:"SERVICE_UNAVAILABLE"}))}finally{this.#activeFetch=null,this.#pending=!1,restoreControls(),cartPerformance.measureFromEvent("discount-update:user-action",event)}};removeDiscount=async event=>{if(event.preventDefault(),event.stopPropagation(),this.#pending)return;if(this.#needsRefresh){await this.#refreshStaleDiscounts();return}if(event instanceof KeyboardEvent&&event.key!=="Enter"||!(event instanceof MouseEvent)||!(event.target instanceof HTMLElement)||typeof this.dataset.sectionId!="string")return;const pill=event.target.closest(".cart-discount__pill");if(!(pill instanceof HTMLLIElement))return;const discountCode=pill.dataset.discountCode;if(!discountCode)return;const existingDiscounts=this.#existingDiscounts(),index=existingDiscounts.indexOf(discountCode);if(index===-1)return;existingDiscounts.splice(index,1),sectionRenderer.abortRender(this.dataset.sectionId);const abortController=this.#createAbortController(),deferredPromise=CartDiscountUpdateEvent.createPromise();this.#pending=!0;const restoreControls=this.#disableControls();try{this.dispatchEvent(new CartDiscountUpdateEvent({discountCodes:existingDiscounts.map(code=>({code})),promise:deferredPromise.promise}));const config=fetchConfig("json",{body:JSON.stringify({discount:existingDiscounts.join(","),sections:[this.dataset.sectionId]})}),data=await(await fetch(Theme.routes.cart_update_url,{...config,signal:abortController.signal})).json(),newHtml=data.sections?.[this.dataset.sectionId];if(deferredPromise.resolve({cart:CartDiscountUpdateEvent.createCartFromAjaxResponse(data)}),!newHtml){await this.#refreshDiscountSection();return}sectionRenderer.abortRender(this.dataset.sectionId),await morphSection(this.dataset.sectionId,newHtml,{mode:this.closest("theme-drawer")?"hydration":"full"})}catch(error){deferredPromise.reject(error),error instanceof Error&&error.name!=="AbortError"&&this.dispatchEvent(new CartErrorEvent({error:error.message||"Failed to remove discount",code:"SERVICE_UNAVAILABLE"}))}finally{this.#activeFetch=null,this.#pending=!1,restoreControls()}};#handleDiscountError(type){const{cartDiscountError,cartDiscountErrorDiscountCode,cartDiscountErrorShipping}=this.refs,target=type==="discount_code"?cartDiscountErrorDiscountCode:cartDiscountErrorShipping;cartDiscountError.classList.remove("hidden"),target.classList.remove("hidden");const errorMessage=type==="discount_code"?"Invalid discount code":"Discount not applicable for shipping";this.dispatchEvent(new CartErrorEvent({error:errorMessage,code:"VALIDATION_CUSTOM"}))}#existingDiscounts(){const discountCodes=[],discountPills=this.querySelectorAll(".cart-discount__pill");for(const pill of discountPills)pill instanceof HTMLLIElement&&typeof pill.dataset.discountCode=="string"&&discountCodes.push(pill.dataset.discountCode);return discountCodes}}customElements.get("cart-discount-component")||customElements.define("cart-discount-component",CartDiscount); 2//# sourceMappingURL=/cdn/shop/t/129/assets/cart-discount.js.map?v=131878396574145547181789886690
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.