const requestedScripts=new Set;function loadScriptOnce(src,isModule){if(!src||requestedScripts.has(src)||(requestedScripts.add(src),document.querySelector(`script[src="${src}"]`)))return;const script=document.createElement("script");script.src=src,isModule?(script.type="module",script.setAttribute("fetchpriority","low")):script.defer=!0,document.body.appendChild(script)}class ProductCarousel extends HTMLElement{#carousel=null;#source=null;#productId=null;#collectionHandle=null;#sectionId=null;#bestSellersServerRendered=!1;#maxProducts=8;#observer=null;#abortController=null;#connectedAt=0;#dotsController=null;#deferRender=!1;#loading=!1;#loadGeneration=0;static emarsysHelpers=null;static async loadEmarsysHelpers(){return ProductCarousel.emarsysHelpers??=await import("@theme/gco-emarsys-recs"),ProductCarousel.emarsysHelpers}static get observedAttributes(){return["data-source","data-collection-handle","data-product-id","data-max-products"]}constructor(){super(),this.#ensureRuntime()}#ensureRuntime(){this.#abortController??=new AbortController,this.#observer??=new IntersectionObserver(entries=>{entries[0]?.isIntersecting&&(this.#observer.disconnect(),this._loadProducts())},{rootMargin:"0px 0px 400px 0px"})}connectedCallback(){if(this.#ensureRuntime(),this.#source=this.dataset.source,this.#productId=this.dataset.productId,this.#collectionHandle=this.dataset.collectionHandle,this.#sectionId=this.dataset.sectionId,this.#bestSellersServerRendered=this.dataset.bestSellersServerRendered==="true",this.#maxProducts=parseInt(this.dataset.maxProducts||"8",10),this.#deferRender=this.dataset.deferRender==="true",this.addEventListener("click",event=>{event.target.closest?.("[data-carousel-retry]")&&this._loadProducts()},{signal:this.#abortController.signal}),this.#source==="emarsys"){this.#connectedAt=Date.now(),this._loadProducts();return}if(this.#source==="recently_viewed"&&this._getRecentlyViewed().length===0){this._showFallback();return}this.#observer.observe(this),this._setupDots()}disconnectedCallback(){this.#loadGeneration++,this.#loading=!1,this.#dotsController?.abort(),this.#dotsController=null,this.#abortController&&(this.#abortController.abort(),this.#abortController=null),this.#observer&&(this.#observer.disconnect(),this.#observer=null)}async _loadProducts(){if(!this.#source||this.#loading)return;this.#loading=!0;const generation=++this.#loadGeneration,current=()=>this.isConnected&&generation===this.#loadGeneration;try{if(this.#deferRender){const html=await this._fetchRelated();if(!current())return;if(!this._renderProducts(html))throw new Error("Deferred carousel section missing");this.#deferRender=!1,this.dataset.deferRender="false"}else if(this.#source==="related"){const html=await this._fetchRelated();if(!current())return;this._renderProducts(html)||this._showFallback()}else if(this.#source==="best_sellers"&&!this.#bestSellersServerRendered){const html=await this._fetchBestSellers();if(!current())return;this._renderProducts(html)||this._showFallback()}else if(this.#source==="recently_viewed"){const ids=this._getRecentlyViewed();if(ids.length===0)return;const html=await this._fetchRecentlyViewed(ids);if(!current())return;this._renderProducts(html)||this._showFallback()}else this.#source==="emarsys"&&await this._loadEmarsys(current)}catch(error){if(current()&&error.name!=="AbortError")if(console.error("[ProductCarousel] Load failed:",error.message),this.#deferRender){const error2=this.querySelector("[data-carousel-error]");error2&&(error2.hidden=!1)}else this._showFallback()}finally{current()&&(this.#loading=!1)}}_showFallback(){const template=this.querySelector("template[data-carousel-fallback]");template instanceof HTMLTemplateElement&&(this.querySelector("[data-carousel-placeholder]")?.remove(),template.replaceWith(template.content.cloneNode(!0)),this._afterMarkupInserted())}_afterMarkupInserted(){const hasSnap=!!this.querySelector("gco-snap-carousel");hasSnap&&loadScriptOnce(this.dataset.snapSrc,!0),this.querySelector("[data-gco-quick-add-lazy]")&&loadScriptOnce(this.dataset.quickAddLazySrc,!0),this.querySelector(".quick-add-custom__inner, [data-gco-quick-add-lazy]")&&loadScriptOnce(this.dataset.quickAddSrc,!1),this.#carousel=this.querySelector("carousel-component"),!hasSnap&&this.#carousel?.reinit&&this.#carousel.reinit(),this._setupDots()}async _loadEmarsys(current=()=>this.isConnected){const blockId=this.dataset.blockId||this.id;let helpers;try{if(helpers=await ProductCarousel.loadEmarsysHelpers(),!current())return}catch(error){if(!current())return;console.warn(`[Emarsys carousel] Block ${blockId}: the helper module could not be loaded (${error.message}). The block stays hidden.`);return}const logic=this.dataset.emarsysLogic||"PERSONAL",timeoutMs=parseInt(this.dataset.emarsysTimeout||"4000",10),context={blockId,logic,timeoutMs},fail=(reason,extra,level="warn")=>{const message=helpers.buildWarning(reason,{...context,rendered:this.hidden?0:1,...extra});console[level](message),this._showEditorNotice(message)};try{this._ensureEmarsysRequest(helpers,logic);const result=await this._waitForEmarsysResult(timeoutMs);if(!current())return;if(!result){const scarabLoaded=window.ScarabQueue&&!Array.isArray(window.ScarabQueue);fail(scarabLoaded?"no-response":"scarab-not-loaded");return}const entries=helpers.dedupeByGroup(result.page?.products,parseInt(this.dataset.emarsysLimit||"",10)||this.#maxProducts*2);if(entries.length===0){fail("zero-items");return}let html;try{if(html=await this._fetchRecentlyViewed(entries.map(entry=>entry.groupId)),!current())return}catch(error){if(!current())return;if(error.name==="AbortError")throw error;fail("hydration-failed",{detail:error.message});return}if(await this._ensureElementsDefined(html),!current())return;let arranged=null;if(this._renderProducts(html,content=>(arranged=helpers.arrangeCards(content,entries,this.#maxProducts),arranged.count>0&&this.removeAttribute("hidden"),arranged.count>0)),!arranged){fail("hydration-failed",{detail:"the response did not contain the carousel markup"});return}arranged.missing.length>0&&fail("missing-ids",{missingIds:arranged.missing,requested:entries.length,rendered:arranged.count},arranged.count>0?"info":"warn")}catch(error){current()&&error.name!=="AbortError"&&fail("hydration-failed",{detail:error.message})}}_ensureEmarsysRequest(helpers,logic){if(this.__emarsysRegistered||!window.ScarabQueue)return;this.__emarsysRegistered=!0,helpers.buildRecommendCommands({logic,limit:parseInt(this.dataset.emarsysLimit||"16",10),zone:this.dataset.emarsysZone,containerId:this.id,viewId:this.dataset.scarabViewId,success:response=>{this.__emarsysRecs=response,this.dispatchEvent(new CustomEvent("emarsys:recs"))}}).forEach(command=>window.ScarabQueue.push(command))}_waitForEmarsysResult(timeoutMs){if(this.__emarsysRecs)return Promise.resolve(this.__emarsysRecs);const remaining=Math.max(0,this.#connectedAt+timeoutMs-Date.now()),signal=this.#abortController?.signal;return new Promise((resolve,reject)=>{const cleanup=()=>{clearTimeout(timer),this.removeEventListener("emarsys:recs",onResult),signal?.removeEventListener("abort",onAbort)},onResult=()=>{cleanup(),resolve(this.__emarsysRecs??null)},onAbort=()=>{cleanup(),reject(Object.assign(new Error("Aborted"),{name:"AbortError"}))},timer=setTimeout(()=>{cleanup(),resolve(null)},remaining);this.addEventListener("emarsys:recs",onResult),signal?.addEventListener("abort",onAbort)})}static loadElementModule(specifier){return import(specifier)}async _ensureElementsDefined(html){const needed=[["carousel-component","@theme/gco-carousel"],["slideshow-component","@theme/slideshow"]].filter(([tag])=>html.includes(`<${tag}`)&&!customElements.get(tag));await Promise.all(needed.map(([,specifier])=>ProductCarousel.loadElementModule(specifier))),await Promise.all(needed.map(([tag])=>customElements.whenDefined(tag)))}_showEditorNotice(message){if(!window.Shopify?.designMode)return;const notice=document.createElement("p");notice.className="product-carousel__editor-notice",notice.setAttribute("role","status"),notice.textContent=message,this.insertAdjacentElement("afterend",notice)}_setupDots(){this.#dotsController?.abort(),this.#dotsController=null;const mode=this.dataset.dotsVisibility;if(!mode||mode==="never"||(this.querySelector(".product-carousel__dots")?.remove(),this.querySelector("carousel-component")))return;const scroller=this.querySelector("slideshow-slides");if(!scroller)return;const controller=new AbortController;this.#dotsController=controller;const nav=document.createElement("div");nav.className="product-carousel__dots",nav.setAttribute("role","group"),nav.setAttribute("aria-label",this.dataset.dotsGroupLabel||"Pagination"),this.appendChild(nav);const pageLabel=this.dataset.dotsLabel||"Page {index} of {length}";let pages=0;const pageCount=()=>Math.max(1,Math.ceil((scroller.scrollWidth-1)/Math.max(1,scroller.clientWidth))),currentPage=()=>{const max=scroller.scrollWidth-scroller.clientWidth;return max>0&&pages>1?Math.round(scroller.scrollLeft/max*(pages-1)):0},sync=()=>{const active=currentPage();nav.querySelectorAll("button").forEach((button,index)=>{index===active?button.setAttribute("aria-current","true"):button.removeAttribute("aria-current")})},build=()=>{const count=pageCount();if(count===pages)return sync();pages=count,nav.replaceChildren(),nav.hidden=pages<=1;for(let index=0;index{const max=scroller.scrollWidth-scroller.clientWidth;scroller.scrollTo({left:pages>1?max*index/(pages-1):0,behavior:"smooth"})},{signal:controller.signal}),nav.appendChild(button)}sync()};if(scroller.addEventListener("scroll",sync,{passive:!0,signal:controller.signal}),typeof ResizeObserver=="function"){const resizeObserver=new ResizeObserver(build);resizeObserver.observe(scroller),controller.signal.addEventListener("abort",()=>resizeObserver.disconnect())}build()}async fetchWithRetry(url,retries=2){const controller=this.#abortController;for(let i=0;i<=retries;i++)try{const response=await fetch(url,{signal:controller.signal});if(!response.ok)throw new Error(`HTTP ${response.status}`);return await response.text()}catch(error){if(error.name==="AbortError"||i===retries)throw error;await new Promise(resolve=>setTimeout(resolve,500))}}async _fetchBestSellers(){const rootUrl=(window.Theme?.routes||window.routes||{}).root_url||"/",handle=this.#collectionHandle||"all",url=`${rootUrl}collections/${handle}?sort_by=best-selling§ion_id=${encodeURIComponent(this.#sectionId)}`;return this.fetchWithRetry(url)}async _fetchRelated(){const url=`${(window.Theme?.routes||window.routes||{}).product_recommendations_url||"/recommendations/products"}?product_id=${this.#productId}&limit=${this.#maxProducts}&intent=related§ion_id=${encodeURIComponent(this.#sectionId)}`;return this.fetchWithRetry(url)}async _fetchRecentlyViewed(ids){const searchUrl=(window.Theme?.routes||window.routes||{}).search_url||"/search",query=ids.map(id=>`id:${id}`).join(" OR "),url=`${searchUrl}?q=${encodeURIComponent(query)}&type=product§ion_id=${encodeURIComponent(this.#sectionId)}`;return this.fetchWithRetry(url)}_getRecentlyViewed(){try{const raw=localStorage.getItem("horizon_recently_viewed_products");if(!raw)return[];const{ids,timestamp}=JSON.parse(raw),ttl=1440*60*1e3;return Date.now()-timestamp>ttl?[]:(ids||[]).slice(0,12)}catch{return[]}}_renderProducts(html,transform){const doc=new DOMParser().parseFromString(html,"text/html"),blockId=this.dataset.blockId,blockContent=blockId?doc.querySelector(`#ProductCarousel-${blockId}`)||doc.querySelector(`#EmarsysRecs-${blockId}`):null,fallback=doc.querySelector("product-carousel, carousel-component"),content=blockContent||fallback;return!content||transform&&transform(content)===!1?!1:(this.innerHTML=content.innerHTML,this._afterMarkupInserted(),!0)}}customElements.get("product-carousel")||customElements.define("product-carousel",ProductCarousel);export{ProductCarousel}; //# sourceMappingURL=/cdn/shop/t/35/assets/gco-product-carousel.js.map?v=33628110662834275811793372365