1import{createElementFromHTML,decodeHTMLEntities,getLazyLoadComponentObserver,parseConfig}from"@utilities/theme";import{normalizeVariantId}from"@utilities/product";if(!window.customElements.get("cyo-product")){class CYOAvailabilityManager{constructor(debugMode=!1){this.debugMode=debugMode}isProductAvailable(product){try{return product.available_shopify===!1?(this.debugMode&&console.log(`\u{1F6AB} CYO: Product ${product.id} (${product.title}) filtered out - available_shopify: false`),!1):product.available_greyson===!1?(this.debugMode&&console.log(`\u{1F6AB} CYO: Product ${product.id} (${product.title}) filtered out - available_greyson: false`),!1):!0}catch(error){return console.error("\u274C CYO: Error checking product availability:",error),!1}}isVariantAvailable(variant){try{return variant.available_shopify===!1?(this.debugMode&&console.log(`\u{1F6AB} CYO: Variant ${variant.id} filtered out - available_shopify: false`),!1):variant.available_greyson===!1?(this.debugMode&&console.log(`\u{1F6AB} CYO: Variant ${variant.id} filtered out - available_greyson: false`),!1):!0}catch(error){return console.error("\u274C CYO: Error checking variant availability:",error),!1}}getAvailableVariants(product,option){try{const normalizedAllowedColors=option.allowed_colors?.length>0?option.allowed_colors.map(c=>c.toUpperCase()):[],normalizedAllowedSizes=option.allowed_sizes?.length>0?option.allowed_sizes.map(s=>s.toUpperCase()):[];return product.variants.filter(variant=>{if(!this.isVariantAvailable(variant)||normalizedAllowedColors.length>0&&product.has_color_option&&!normalizedAllowedColors.includes(variant.color?.toUpperCase()))return!1;if(normalizedAllowedSizes.length>0&&product.has_size_option){const sizeOption=variant.options[product.size_option_index];if(!normalizedAllowedSizes.includes(sizeOption?.toUpperCase()))return!1}return!0})}catch(error){return console.error("\u274C CYO: Error getting available variants:",error),[]}}}class CYOAccessibilityManager{constructor(shadowRoot,debugMode=!1){this.shadowRoot=shadowRoot,this.debugMode=debugMode,this.liveRegion=null,this.lastFocusedElement=null,this.keyboardNavigation=!1,this.setupAccessibility()}setupAccessibility(){this.liveRegion=document.createElement("div"),this.liveRegion.className="cyo-live-region",this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.id="cyo-live-region",this.shadowRoot.appendChild(this.liveRegion);const progress=document.createElement("div");progress.className="cyo-progress",progress.setAttribute("aria-live","polite"),progress.id="cyo-progress",this.shadowRoot.appendChild(progress)}announce(message,priority="polite"){this.liveRegion&&(this.liveRegion.setAttribute("aria-live",priority),this.liveRegion.textContent=message,setTimeout(()=>{this.liveRegion&&(this.liveRegion.textContent="")},1e3))}updateProgress(currentStep,totalSteps,stepName){const progressElement=this.shadowRoot.querySelector("#cyo-progress");progressElement&&(progressElement.textContent=`Step ${currentStep} of ${totalSteps}: ${stepName}`)}handleKeyboardNavigation(event){this.keyboardNavigation=!0,document.documentElement.setAttribute("data-keyboard-navigation","true");const{key,target}=event;return key==="Escape"?"escape":key==="Enter"&&target.tagName==="BUTTON"?(event.preventDefault(),target.click(),"enter"):["ArrowDown","ArrowUp","ArrowLeft","ArrowRight"].includes(key)?this.handleArrowKeyNavigation(event):null}handleArrowKeyNavigation(event){const{key,target}=event;if(target.type!=="radio")return null;const radioGroup=target.closest("fieldset");if(!radioGroup)return null;const radios=Array.from(radioGroup.querySelectorAll('input[type="radio"]')),currentIndex=radios.indexOf(target);if(currentIndex===-1)return null;let nextIndex;if(key==="ArrowDown"||key==="ArrowRight")nextIndex=(currentIndex+1)%radios.length;else if(key==="ArrowUp"||key==="ArrowLeft")nextIndex=(currentIndex-1+radios.length)%radios.length;else return null;event.preventDefault();const nextRadio=radios[nextIndex];return nextRadio.focus(),nextRadio.checked=!0,nextRadio.dispatchEvent(new Event("change",{bubbles:!0})),"arrow"}}class CYODebounceManager{constructor(){this.timers=new Map}debounce(key,callback,delay){this.timers.has(key)&&clearTimeout(this.timers.get(key));const timer=setTimeout(()=>{callback(),this.timers.delete(key)},delay);this.timers.set(key,timer)}
1clearAll(){this.timers.forEach(timer=>clearTimeout(timer)),this.timers.clear()}clear(key){this.timers.has(key)&&(clearTimeout(this.timers.get(key)),this.timers.delete(key))}}class CYOProduct extends HTMLElement{static get observedAttributes(){return["data-cart-transform","data-enable-sticky-atb","data-enable-sticky-atb-on"]}#productOptionTypesCache=new Map;constructor(){super(),this.attachShadow({mode:"open"}),this.config={},this.selectFirstAvailableOption=!1,this.cartTransformation="merge",this.currentStepIndex=0,this.currentPath=[],this.selections=new Map,this.productOverview=null,this.price=0,this.compareAtPrice=0,this.priceHTML=null,this.clickDebounceDelay=150,this.mediaUpdateDelay=300,this.aggregatePrefetchDebounceDelay=50,this.prefetchedAggregateMediaUrls=new Set,this.availabilityManager=null,this.accessibilityManager=null,this.debounceManager=new CYODebounceManager,this.currentStep1MediaUrl=null,this.currentDisplayedMediaUrl=null,this.currentBundleFeaturedMedia=null,this.zoneExpansionState={},this.defaultProductOptionsPagination={enabled:!1,optionsPerPage:8,viewMoreCta:"MORE OPTIONS +",viewLessCta:"LESS OPTIONS -"},this.enableStickyATB=!1,this.enableStickyATBOn="scroll",this.boundHandleStickyATC=null,this.boundHandleResize=null,this.atbButtonMarginOffset=0}#setupShadowDOM(){const stylesTemplate=this.querySelector("template[component-styles]");if(stylesTemplate){const stylesContent=stylesTemplate.content.cloneNode(!0);this.shadowRoot.appendChild(stylesContent)}this.availabilityManager=new CYOAvailabilityManager(this.allowDebug()),this.accessibilityManager=new CYOAccessibilityManager(this.shadowRoot,this.allowDebug());const container=document.createElement("div");container.className="cyo-container",container.id="cyo-content",container.setAttribute("role","main"),container.setAttribute("aria-label","Product customization interface"),this.shadowRoot.appendChild(container)}isLazyLoad(){return this.classList.contains("lazy-load")}announceToScreenReader=(message,priority="polite")=>{this.accessibilityManager?.announce(message,priority)};updateProgress=(currentStep,totalSteps,stepName)=>{this.accessibilityManager?.updateProgress(currentStep,totalSteps,stepName)};handleKeyboardNavigation=event=>{this.accessibilityManager?.handleKeyboardNavigation(event)==="escape"&&this.handleEscapeKey(event)};handleEscapeKey=event=>{this.currentStepIndex>0&&(event.preventDefault(),this.handleBack())};allowDebug=()=>this.classList.contains("debug");isProductAvailable=product=>this.availabilityManager?.isProductAvailable(product)??!1;isVariantAvailable=variant=>this.availabilityManager?.isVariantAvailable(variant)??!1;async connectedCallback(){try{this.allowDebug()&&console.log("\u{1F50C} CYO: Component connected to DOM"),this.boundHandleStickyATC=this.handleStickyATC.bind(this),this.boundHandleResize=this.handleResize.bind(this),this.handleStickyATBChange(),this.isLazyLoad()?getLazyLoadComponentObserver().observe(this):await this.init()}catch(error){console.error("\u274C CYO: Error in connectedCallback:",error)}}attributeChangedCallback(name,oldValue,newValue){try{if(name==="data-cart-transform"){const previousValue=this.cartTransformation;newValue&&["merge","expand"].includes(newValue)?this.cartTransformation=newValue:this.cartTransformation=this.config.cart_transformation||"merge",this.allowDebug()&&previousValue!==this.cartTransformation&&console.log(`\u2699\uFE0F CYO: Cart transformation changed from "${previousValue}" to "${this.cartTransformation}" via data-cart-transform attribute`)}else(name==="data-enable-sticky-atb"||name==="data-enable-sticky-atb-on")&&this.handleStickyATBChange()}catch(error){console.error("\u274C CYO: Error in attributeChangedCallback:",error)}}disconnectedCallback(){try{this.allowDebug()&&console.log("\u{1F50C} CYO: Component disconnected from DOM"),this.debounceManager.clearAll(),this.setAddingToBagState(!1),this.disableStickyATBEvents(),this.shadowRoot&&(this.shadowRoot.removeEventListener("change",this.handleDelegatedChange),this.shadowRoot.removeEventListener("click",this.handleDelegatedClick),this.shadowRoot.removeEventListener("keydown",this.handleKeyboardNavigation),this.shadowRoot.removeEventListener("focusin",this.handleFocusIn),this.shadowRoot.removeEventListener("mousedown",this.handleMouseDown),this.shadowRoot.removeEventListener("pointerover",this.handlePointerOver))}catch(error){console.error("\u274C CYO: Error in disconnectedCallback:",error)}}init=async()=>{try{if(this.allowDebug()&&console.log("\u{1F680} CYO: Initializing component"),this.#setupShadowDOM(),this.productOverview=this.closest("product-overview"),this.productOverview?this.allowDebug()&&console.log("\u{1F517} CYO: Found parent product-overview component"):this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No parent product-overview component found"),this.config=parseConfig(this,this.allowDebug()),this.allowDebug()&&console.log("\u{1F4CB} CYO: Parsed config:",this.config),this.config&&this.config.steps){this.allowDebug()&&console.log(`\u{1F4CA} CYO: Found ${this.config.steps.length} steps to render`),this.selectFirstAvailableOption=this.config.select_first_available_option??!1;const dataCartTransform=this.getAttribute("data-cart-transform");dataCartTransform&&["merge","expand"].includes(dataCartTransform)?this.cartTransformation=dataCartTransform:this.cartTransformation=this.config.cart_transformation||"merge",this.defaultProductOptionsPagination={enabled:this.config.pagination?.enabled??!1,optionsPerPage:this.config.pagination?.options_per_page??8,viewMoreCta:this.config.pagination?.view_more_cta??"MORE OPTIONS +",viewLessCta:this.config.pagination?.view_less_cta??"LESS OPTIONS -"},this.allowDebug()&&(console.log(`\u2699\uFE0F CYO: Select first available option: ${this.selectFirstAvailableOption}`),console.log(`\u2699\uFE0F CYO: Cart transformation mode: ${this.cartTransformation}`),console.log(`\u2699\uFE0F CYO: Default pagination enabled: ${this.defaultProductOptionsPagination.enabled}`),console.log(`\u2699\uFE0F CYO: Default options per page: ${this.defaultProductOptionsPagination.optionsPerPage}`)),await this.render(),await this.calculatePricing(),this.allowDebug()&&console.log("\u{1F4B0} CYO: Initializing pricing system"),await this.updatePrice()}else console.warn("\u26A0\uFE0F CYO: No valid config or steps found"),this.renderError("Failed to initialize component")}catch(error){console.error("\u274C CYO: Error in init:",error),this.renderError("Failed to initialize component")}this.classList.add("loaded")};getCurrentStep=()=>{try{return this.config.steps[this.currentStepIndex]}catch(error){return console.error("\u274C CYO: Error getting current step:",error),null}};isReviewStep=()=>this.currentStepIndex>=this.config.steps.length;getSelectionForStep=step=>
1step?this.selections.get(step.id):null;setSelectionForStep=(step,selection,updatePrice=!1)=>{step&&(this.selections.set(step.id,selection),updatePrice&&(this.config.use_bundle_product_price?this.allowDebug()&&console.log("\u{1F4B0} CYO: Skipping price update - using bundle product price"):this.debouncedUpdatePrice()),this.allowDebug()&&console.log(`\u{1F4BE} CYO: Selection saved for step "${step.label}":`,selection))};calculatePricing=async()=>{let price=0,compareAtPrice=0;return this.config.use_bundle_product_price?(price=this.config.bundle_product?.price||0,compareAtPrice=this.config.bundle_product?.compare_at_price||0,this.allowDebug()&&console.log(`\u{1F4B0} CYO: Using bundle product price - Price: ${price}, Compare: ${compareAtPrice}`)):(this.selections.forEach(selection=>{selection.variant&&(price+=selection.variant.price||0,compareAtPrice+=selection.variant.compare_at_price||0)}),this.allowDebug()&&console.log(`\u{1F4B0} CYO: Calculated aggregate price - Price: ${price}, Compare: ${compareAtPrice}`)),this.price=price,this.compareAtPrice=compareAtPrice,this.priceHTML=await this.fetchFormattedPrice(),this.allowDebug()&&console.log(`\u{1F4B0} CYO: Pricing calculation complete - Price: ${this.price}, Compare: ${this.compareAtPrice}, HTML: ${!!this.priceHTML}`),{price:this.price,compareAtPrice:this.compareAtPrice,priceHTML:this.priceHTML}};debouncedUpdatePrice=(delay=300)=>{this.debounceManager.debounce("priceUpdate",async()=>{await this.calculatePricing(),await this.updatePrice()},delay)};fetchFormattedPrice=async()=>{try{if(this.config.use_bundle_product_price){const cachedPriceHTML=this.config.bundle_product?.price_html;return cachedPriceHTML?(this.allowDebug()&&console.log("\u{1F4B0} CYO: Using cached bundle product price HTML"),cachedPriceHTML):(this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No cached bundle product price HTML available"),null)}if(!this.config.bundle_product?.url)return this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No bundle product URL available"),null;const url=`${this.config.bundle_product.url}?view=product-price&price=${this.price}&compareAtPrice=${this.compareAtPrice}`;this.allowDebug()&&console.log(`\u{1F310} CYO: Fetching aggregate price from: ${url}`);const response=await fetch(url);if(!response.ok)throw new Error(`HTTP ${response.status}: ${response.statusText}`);const data=await response.json();return data.price_html?(this.allowDebug()&&console.log("\u{1F4B0} CYO: Received aggregate price from server"),data.price_html):(console.warn("\u26A0\uFE0F CYO: Server response missing price_html"),null)}catch(error){return console.error("\u274C CYO: Error fetching formatted price:",error),null}};updatePrice=async()=>{try{if(this.allowDebug()&&console.log("\u{1F4B0} CYO: Starting price update"),(this.price===void 0||this.price===null)&&(this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No pricing data available, calculating now"),await this.calculatePricing(),this.price===void 0||this.price===null)){console.error("\u274C CYO: Failed to calculate pricing data");return}this.priceHTML&&this.productOverview&&typeof this.productOverview.setPrice=="function"?(this.productOverview.setPrice(this.priceHTML),this.allowDebug()&&console.log("\u{1F4B0} CYO: Updated price via product-overview with stored HTML")):this.priceHTML?this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: Product-overview component not available or setPrice method not found"):this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No formatted price HTML available")}catch(error){console.error("\u274C CYO: Error updating price display:",error)}};getAvailableVariants=(product,option)=>this.availabilityManager?.getAvailableVariants(product,option)??[];getCustomerMembership=()=>{try{return window.theme?.customer?.membership||null}catch(error){return console.error("\u274C CYO: Error getting customer membership:",error),null}};validateMembershipRequirement=membershipRequirement=>{try{if(!membershipRequirement?.loyalty_required)return!0;const customerMembership=this.getCustomerMembership(),requiredRank=membershipRequirement?.loyalty_tier_required?.rank||0;return(customerMembership?.level?.rank||0)>=requiredRank}catch(error){return console.error("\u274C CYO: Error validating membership requirement:",error),!1}};isNonMember=()=>{try{const customerMembership=this.getCustomerMembership();return!customerMembership||!customerMembership.active}catch(error){return console.error("\u274C CYO: Error checking non-member status:",error),!0}};getStepPaginationSettings=step=>{try{return step.pagination?{enabled:step.pagination.enabled??this.defaultProductOptionsPagination.enabled,optionsPerPage:step.pagination.options_per_page??this.defaultProductOptionsPagination.optionsPerPage,viewMoreCta:step.pagination.view_more_cta??this.defaultProductOptionsPagination.viewMoreCta??"MORE OPTIONS +",viewLessCta:step.pagination.view_less_cta??this.defaultProductOptionsPagination.viewLessCta??"LESS OPTIONS -"}:{...this.defaultProductOptionsPagination,viewMoreCta:this.defaultProductOptionsPagination.viewMoreCta??"MORE OPTIONS +",viewLessCta:this.defaultProductOptionsPagination.viewLessCta??"LESS OPTIONS -"}}catch(error){return console.error("\u274C CYO: Error getting step pagination settings:",error),{...this.defaultProductOptionsPagination,viewMoreCta:"MORE OPTIONS +",viewLessCta:"LESS OPTIONS -"}}};render=async()=>{try{this.allowDebug()&&console.log("\u{1F3A8} CYO: Starting render");const stepForProgress=this.getCurrentStep(),totalSteps=this.config.steps.length;if(this.isReviewStep())this.updateProgress(totalSteps+1,totalSteps+1,"Review Your Selections"),this.announceToScreenReader("Now reviewing your selections. You can modify any step or add to bag.");else{const stepName=stepForProgress?.label||`Step ${this.currentStepIndex+1}`;this.updateProgress(this.currentStepIndex+1,totalSteps,stepName),this.announceToScreenReader(`${stepName}. Make your selection to continue.`)}let htmlContent;this.isReviewStep()?(this.allowDebug()&&console.log("\u{1F3A8} CYO: Rendering review step"),htmlContent=await this.renderReviewStep()):(this.allowDebug()&&console.log("\u{1F3A8} CYO: Rendering current step"),htmlContent=this.renderCurrentStep());const container=this.shadowRoot.getElementById("cyo-content");
1if(container){container.replaceChildren();const content=createElementFromHTML(htmlContent);content&&container.appendChild(content)}this.attachEventListeners();const currentStep=this.getCurrentStep(),existingSelection=this.getSelectionForStep(currentStep);if(existingSelection)this.allowDebug()&&console.log(`\u{1F504} CYO: Restoring existing selection for step "${currentStep.label}": ${existingSelection.product.title}`),setTimeout(()=>{this.restoreStepState(existingSelection)},0);else if(!this.isReviewStep()&&this.selectFirstAvailableOption){const selectionZones=this.getAvailableOptions(currentStep),zonesToCheck=["regular","members_only"];for(const zoneKey of zonesToCheck)if(selectionZones[zoneKey]&&selectionZones[zoneKey].options.length>0){const firstOption=selectionZones[zoneKey].options[0],firstProduct=firstOption.products.find(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,firstOption).length>0);if(firstProduct){this.allowDebug()&&console.log(`\u{1F916} CYO: Auto-selecting first available product: ${firstProduct.title} from ${zoneKey} zone`),setTimeout(()=>{this.handleProductSelection(firstProduct.id,firstOption.id,zoneKey)},0);break}}}}catch(error){console.error("\u274C CYO: Error in render:",error),this.renderError("Failed to render component")}};renderCurrentStep=()=>{try{const currentStep=this.getCurrentStep();if(!currentStep)return this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No current step found"),'<div class="cyo-error">No current step found</div>';this.allowDebug()&&console.log(`\u{1F3A8} CYO: Rendering step "${currentStep.label}"`);const selectionZones=this.getAvailableOptions(currentStep);if(Object.keys(selectionZones).length===0)return this.allowDebug()&&console.warn(`\u26A0\uFE0F CYO: No available selection zones for step "${currentStep.label}"`),this.renderUnavailableMessage();this.allowDebug()&&console.log(`\u{1F3A8} CYO: Found ${Object.keys(selectionZones).length} selection zones:`,Object.keys(selectionZones));const selectionZonesHTML=Object.entries(selectionZones).map(([zoneKey,zone])=>this.renderSelectionZone(zoneKey,zone)).join("");return` 2 <div class="cyo-step"> 3 <div class="cyo-step__header"> 4 <h2 class="cyo-step__title">${this.currentStepIndex+1}. ${currentStep.label}</h2> 5 ${this.renderHeaderNavigation()} 6 </div> 7 <div class="cyo-step__content"> 8 ${selectionZonesHTML} 9 </div> 10 <div class="cyo-cart-error-container" style="display: none;"></div> 11 <div class="cyo-step__actions"> 12 ${this.renderActionButtons()} 13 </div> 14 </div> 15 `}catch(error){return console.error("\u274C CYO: Error rendering current step:",error),'<div class="cyo-error">Failed to render step</div>'}};getAvailableOptions=step=>{try{const selectionZones={};if(step.options&&step.options.length>0){const availableOptions=step.options.filter(option=>{const hasAnyProducts=option.products.some(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,option).length>0),hasProductsWithVariants=option.products.some(product=>product.variants&&product.variants.length>0);return hasAnyProducts||hasProductsWithVariants});availableOptions.length>0&&(selectionZones.regular={type:"regular",label:step.name||"Style",options:availableOptions}),this.allowDebug()&&console.log(`\u2705 CYO: ${availableOptions.length}/${step.options.length} regular options available`)}if(step.members_only_options&&step.members_only_options.length>0){const availableMembersOptions=step.members_only_options.map(option=>{const hasValidMembership=this.validateMembershipRequirement(option.membership),hasAvailableProducts=option.products.some(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,option).length>0),hasProductsWithVariants=option.products.some(product=>product.variants&&product.variants.length>0);return{...option,isEligible:hasValidMembership,hasAvailableProducts:hasAvailableProducts||hasProductsWithVariants}}).filter(option=>option.hasAvailableProducts);if(availableMembersOptions.length>0&&(selectionZones.members_only={type:"members_only",label:step.members_only_name||"Style",title:step.members_only_label||"Members Only",non_members_cta:step.members_only_non_members_cta||"",options:availableMembersOptions,showNonMemberCta:this.isNonMember()}),this.allowDebug()){const eligibleCount=availableMembersOptions.filter(opt=>opt.isEligible).length;console.log(`\u2705 CYO: ${availableMembersOptions.length}/${step.members_only_options.length} members only options available (${eligibleCount} eligible for customer)`)}}return selectionZones}catch(error){return console.error("\u274C CYO: Error getting available options:",error),{}}};renderSelectionZone=(zoneKey,zone)=>{try{const zoneTitle=zone.title?`<div class="cyo-selection-zone__header"><h3 class="cyo-selection-zone__title">${zone.title}</h3>${window.theme?.elements?.membership_icons?.default}</div>`:"",nonMemberCTA=zone.type==="members_only"&&zone.showNonMemberCta&&zone.non_members_cta?`<div class="cyo-non-member-cta">${zone.non_members_cta}</div>`:"",productOptionsHTML=zone.options&&zone.options.length>0?`<div class="cyo-variant-option"> 16 <label class="cyo-variant-option__label">${zone.label} - <span class="cyo-step__selection-name"></span></label> 17 ${this.renderProductOptions(zone.options,zone.type)} 18 </div>`:"";return` 19 <div class="cyo-selection-zone cyo-selection-zone--${zone.type}" data-zone-type="${zone.type}" data-zone-key="${zoneKey}"> 20 ${zoneTitle} 21 ${productOptionsHTML} 22 <div class="cyo-variant-selection" data-zone-key="${zoneKey}"></div> 23 ${nonMemberCTA} 24 </div> 25 `}catch(error){return console.error(`\u274C CYO: Error rendering selection zone ${zoneKey}:`,error),""}};renderProductOptions=(options,zoneType="regular")=>{const currentStep=this.getCurrentStep(),currentSelection=this.getSelectionForStep(currentStep),fieldsetId=`product-options-${currentStep.id}-${zoneType}`,zoneKey=`${currentStep.id}-${zoneType}`,paginationSettings=this.getStepPaginationSettings(currentStep),allProducts=[];options.forEach(option=>{const products=option.products.filter(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,option).length>0),unavailableProducts=option.products.filter(product=>product.variants&&product.variants.length>0&&(!this.isProductAvailable(product)||this.getAvailableVariants(product,option).length===0));
25[...products,...unavailableProducts].forEach(product=>allProducts.push({product,option}))});const totalProducts=allProducts.length,isZoneExpanded=this.zoneExpansionState[zoneKey]||!1,shouldShowPagination=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage,showCount=isZoneExpanded?totalProducts:shouldShowPagination?Math.min(paginationSettings.optionsPerPage,totalProducts):totalProducts,productsToShow=allProducts.slice(0,showCount),hasMoreProducts=shouldShowPagination&&totalProducts>paginationSettings.optionsPerPage;this.allowDebug()&&console.log(`\u{1F3A8} CYO: Zone ${zoneType} - Showing ${showCount}/${totalProducts} products, expanded: ${isZoneExpanded}`);const productOptionsHTML=productsToShow.map(({product,option})=>{const isSelected=currentSelection&¤tSelection.product.id===product.id&¤tSelection.option.id===option.id&¤tSelection.zoneType===zoneType,inputId=`${fieldsetId}-${zoneType}-product-${product.id}-option-${option.id}`,radioName=`${fieldsetId}-${zoneType}-selection`,isEligible=zoneType==="members_only"?option.isEligible!==!1:!0,hasAvailableVariants=this.getAvailableVariants(product,option).length>0,isDisabled=!isEligible;return` 26 <div class="${`cyo-product-option${isDisabled?" cyo-product-option--disabled":""}${hasAvailableVariants?"":" cyo-product-option--sold-out"}`}"> 27 <input 28 type="radio" 29 class="${`cyo-product-option__input${isDisabled?" cyo-product-option__input--disabled":""}`}" 30 id="${inputId}" 31 name="${radioName}" 32 value="${product.id}-${option.id}" 33 data-product-id="${product.id}" 34 data-option-id="${option.id}" 35 data-zone-type="${zoneType}" 36 data-is-eligible="${isEligible}" 37 data-has-available-variants="${hasAvailableVariants}" 38 ${isSelected?"checked":""} 39 ${isDisabled?"disabled":""} 40 /> 41 <label for="${inputId}" class="cyo-product-option__label"> 42 ${product.media[0]||""} 43 <div class="cyo-product-option__title">${product.title}</div> 44 </label> 45 </div> 46 `}).join(""),toggleButtonHTML=hasMoreProducts?` 47 <div class="cyo-product-options-toggle" data-zone-key="${zoneKey}"> 48 ${isZoneExpanded?`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-less" data-zone-key="${zoneKey}" data-zone-type="${zoneType}"> 49 <span>${paginationSettings.viewLessCta}</span> 50 </button>`:`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-more" data-zone-key="${zoneKey}" data-zone-type="${zoneType}"> 51 <span>${paginationSettings.viewMoreCta}</span> 52 </button>`} 53 </div> 54 `:"";return` 55 <fieldset class="cyo-variant-option__fieldset"> 56 <legend class="visually-hidden">Select a product option</legend> 57 <div class="cyo-product-options"> 58 ${productOptionsHTML} 59 </div> 60 ${toggleButtonHTML} 61 </fieldset> 62 `};isOptionSelectorAllowed=optionName=>{try{const currentStep=this.getCurrentStep();if(!currentStep||!currentStep.allowed_option_selectors)return!0;const allowed=currentStep.allowed_option_selectors.includes(optionName);return this.allowDebug()&&console.log(`\u{1F39B}\uFE0F CYO: General option check - ${optionName}: ${allowed?"ALLOWED":"HIDDEN"}`),allowed}catch(error){return console.error("\u274C CYO: Error checking option selector allowance:",error),!0}};shouldShowSingleOptionSelector=(optionName,optionCount)=>{try{if(!this.isOptionSelectorAllowed(optionName))return this.allowDebug()&&console.log(`\u{1F39B}\uFE0F CYO: Option ${optionName} hidden by allowed_option_selectors`),!1;if(optionCount>1)return this.allowDebug()&&console.log(`\u{1F39B}\uFE0F CYO: Option ${optionName} shown (${optionCount} options available)`),!0;const currentStep=this.getCurrentStep();if(!currentStep||!currentStep.allowed_single_option_selectors)return this.allowDebug()&&console.log(`\u{1F39B}
62\uFE0F CYO: Single option ${optionName} hidden (no allowed_single_option_selectors config)`),!1;const allowed=currentStep.allowed_single_option_selectors.includes(optionName);return this.allowDebug()&&console.log(`\u{1F39B}\uFE0F CYO: Single option check - ${optionName} (${optionCount} options): ${allowed?"SHOW":"HIDE"}`),allowed}catch(error){return console.error("\u274C CYO: Error checking single option selector:",error),!1}};getProductOptionTypes=product=>{try{if(this.#productOptionTypesCache.has(product.id))return this.#productOptionTypesCache.get(product.id);const optionTypes=[];return product.options.forEach((optionName,index)=>{const optionKey=optionName.toLowerCase();let renderType="button",specialKey=optionKey;optionKey==="color"?(renderType="swatch",product.has_color_option&&product.color_option_index!==void 0&&(specialKey="color")):optionKey==="size"&&product.has_size_option&&product.size_option_index!==void 0&&(specialKey="size"),optionTypes.push({key:optionKey,name:optionName,index,type:renderType,specialKey})}),this.#productOptionTypesCache.set(product.id,optionTypes),this.allowDebug()&&console.log(`\u{1F50D} CYO: Discovered ${optionTypes.length} option types for product ${product.id}:`,optionTypes),optionTypes}catch(error){return console.error("\u274C CYO: Error discovering product option types:",error),[]}};renderOptionGroup=(product,selectionOption,optionType,allVariants,preSelectedVariant)=>{try{const optionKey=optionType.key,optionName=optionType.name,optionIndex=optionType.index,renderType=optionType.type,availableVariants=this.getAvailableVariants(product,selectionOption);let allValues,selectedValue=null;if(optionType.specialKey==="color"&&product.has_color_option&&product.color_option_index!==void 0){if(allValues=[...new Set(allVariants.map(v=>v.color).filter(Boolean))],selectedValue=preSelectedVariant?.color,selectionOption.allowed_colors&&selectionOption.allowed_colors.length>0){const normalizedAllowedColors=selectionOption.allowed_colors.map(c=>c.toUpperCase());allValues=allValues.filter(value=>normalizedAllowedColors.includes(value.toUpperCase()))}}else if(optionType.specialKey==="size"&&product.has_size_option&&product.size_option_index!==void 0){const sizeIndex=product.size_option_index;if(allValues=[...new Set(allVariants.map(v=>v.options[sizeIndex]).filter(Boolean))],selectedValue=preSelectedVariant?.options?.[sizeIndex],selectionOption.allowed_sizes&&selectionOption.allowed_sizes.length>0){const normalizedAllowedSizes=selectionOption.allowed_sizes.map(s=>s.toUpperCase());allValues=allValues.filter(value=>normalizedAllowedSizes.includes(value.toUpperCase()))}}else if(allValues=[...new Set(allVariants.map(v=>v.options[optionIndex]).filter(Boolean))],selectedValue=preSelectedVariant?.options?.[optionIndex],optionKey==="color"&&selectionOption.allowed_colors&&selectionOption.allowed_colors.length>0){const normalizedAllowedColors=selectionOption.allowed_colors.map(c=>c.toUpperCase());allValues=allValues.filter(value=>normalizedAllowedColors.includes(value.toUpperCase()))}else if(optionKey==="size"&&selectionOption.allowed_sizes&&selectionOption.allowed_sizes.length>0){const normalizedAllowedSizes=selectionOption.allowed_sizes.map(s=>s.toUpperCase());allValues=allValues.filter(value=>normalizedAllowedSizes.includes(value.toUpperCase()))}else{const allowedKey=`allowed_${optionKey}s`;selectionOption[allowedKey]&&selectionOption[allowedKey].length>0&&(allValues=allValues.filter(value=>selectionOption[allowedKey].includes(value)))}if(allValues.length===0)return"";const hideClass=this.shouldShowSingleOptionSelector(optionName,allValues.length)?"":"cyo-variant-option--hidden",fieldsetId=`${optionKey}-selection-${product.id}`,dataAttr=`data-${optionKey}`;if(renderType==="swatch"&&optionKey==="color")return` 63 <div class="cyo-variant-option ${hideClass}"> 64 <label class="cyo-variant-option__label">${optionName} - <span class="cyo-step__selection-name" data-option-type="${optionKey}"></span></label> 65 <fieldset class="cyo-variant-option__fieldset"> 66 <legend class="visually-hidden">${optionName} selection</legend> 67 <div class="cyo-color-swatches"> 68 ${allValues.map(value=>{const valueHandle=value.toLowerCase().replace(/[^a-z0-9]/g,"-"),inputId=`${fieldsetId}-${valueHandle}`,isSelected=value===selectedValue,isSoldOut=!availableVariants.some(v=>optionType.specialKey==="color"&&product.has_color_option?v.color===value:v.options[optionIndex]===value);return` 69 <div class="cyo-color-option ${isSelected?"cyo-color-option--selected":""} ${isSoldOut?"cyo-color-option--sold-out":""}"> 70 <input 71 type="radio" 72 class="cyo-color-option__input ${isSoldOut?"cyo-color-option__input--unavailable":""}" 73 id="${inputId}" 74 name="${fieldsetId}" 75 value="${value}" 76 ${dataAttr}="${value}" 77 ${isSelected?"checked":""} 78 /> 79 <label for="${inputId}" class="cyo-color-option__label"> 80 <div class="cyo-color-option__swatch" style="background: var(--swatch-${valueHandle});"></div>
81 <span class="visually-hidden">${value}</span> 82 </label> 83 </div> 84 `}).join("")} 85 </div> 86 </fieldset> 87 </div> 88 `;{const optionClass=optionKey==="size"?"cyo-size-options":`cyo-${optionKey}-options`,itemClass=optionKey==="size"?"cyo-size-option":`cyo-${optionKey}-option`;return` 89 <div class="cyo-variant-option ${hideClass}"> 90 <label class="cyo-variant-option__label">${optionName} - <span class="cyo-step__selection-name" data-option-type="${optionKey}"></span></label> 91 <fieldset class="cyo-variant-option__fieldset"> 92 <legend class="visually-hidden">${optionName} selection</legend> 93 <div class="${optionClass}"> 94 ${allValues.map(value=>{const inputId=`${fieldsetId}-${value.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,isSelected=value===selectedValue,isSoldOut=!availableVariants.some(v=>optionType.specialKey==="size"&&product.has_size_option?v.options[product.size_option_index]===value:v.options[optionIndex]===value);return` 95 <div class="${itemClass} ${isSelected?`${itemClass}--selected`:""} ${isSoldOut?`${itemClass}--sold-out`:""}"> 96 <input 97 type="radio" 98 class="${itemClass}__input ${isSoldOut?`${itemClass}__input--unavailable`:""}" 99 id="${inputId}" 100 name="${fieldsetId}" 101 value="${value}" 102 ${dataAttr}="${value}" 103 ${isSelected?"checked":""} 104 /> 105 <label for="${inputId}" class="${itemClass}__label">${value}</label> 106 </div> 107 `}).join("")} 108 </div> 109 </fieldset> 110 </div> 111 `}}catch(error){return console.error(`\u274C CYO: Error rendering option group for ${optionType.key}:`,error),""}};renderVariantSelection=(product,selection,zoneKey=null)=>{const option=selection.option,availableVariants=this.getAvailableVariants(product,option),allVariants=product.variants||[];if(allVariants.length===0)return;const selector=zoneKey?`.cyo-variant-selection[data-zone-key="${zoneKey}"]`:".cyo-variant-selection",variantContainer=this.shadowRoot.querySelector(selector);if(!variantContainer)return;const preSelectedVariant=selection.variant;let variantHTML="";const optionTypes=this.getProductOptionTypes(product);for(const optionType of optionTypes){const optionHTML=this.renderOptionGroup(product,option,optionType,allVariants,preSelectedVariant);variantHTML+=optionHTML}if(variantContainer.replaceChildren(),variantHTML.trim()){const content=createElementFromHTML(`<div>${variantHTML}</div>`);if(content)for(;content.firstChild;)variantContainer.appendChild(content.firstChild)}!preSelectedVariant&&this.selectFirstAvailableOption&&availableVariants.length>=1?(this.allowDebug()&&console.log(`\u{1F916} CYO: Auto-selecting first of ${availableVariants.length} available variants`),this.handleVariantSelection(availableVariants[0],selection)):preSelectedVariant?(this.updateActionButtons(),this.debouncedUpdateMediaGallery()):this.updateOptionValueDisplay()};renderHeaderNavigation=(wrapperOnly=!1)=>{const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep),hasSelection=selection&&selection.variant,isVariantAvailable=hasSelection?this.isVariantAvailable(selection.variant):!1,canProceed=hasSelection&&isVariantAvailable,showBack=this.currentStepIndex>0||this.currentPath.length>0;let nextLabel="Next",backLabel="Back";this.isReviewStep()?nextLabel="Add to Bag":this.currentStepIndex===this.config.steps.length-1&&this.currentPath.length===0?nextLabel="Review":this.currentStepIndex<this.config.steps.length-1&&(nextLabel=this.config.steps[this.currentStepIndex+1].name),hasSelection&&!isVariantAvailable&&(nextLabel="SOLD OUT"),showBack&&(this.currentStepIndex===1?backLabel=this.config.steps[0].name:this.currentStepIndex>1&&(backLabel=this.config.steps[this.currentStepIndex-1].name));const innerContent=` 112 ${showBack?`<button class="cyo-step__nav-item cyo-step__nav-item--back" type="button">
113 <span class="cyo-step__nav-arrow"> 114 <svg xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12" fill="none"> 115 <path d="M7 11L2 6L7 1" stroke="#414142" stroke-width="1.5"/> 116 </svg> 117 </span> 118 <span class="cyo-step__nav-text">Back: ${backLabel}</span> 119 <div class="loading-overlay__spinner hidden"> 120 <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> 121 <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> 122 </svg> 123 </div> 124 </button>`:""} 125 ${this.isReviewStep()?"":`<button class="cyo-step__nav-item cyo-step__nav-item--next ${canProceed?"":"disabled"}" ${canProceed?"":"disabled"} type="button"> 126 <span class="cyo-step__nav-text">Next: ${nextLabel}</span> 127 <span class="cyo-step__nav-arrow"> 128 <svg xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12" fill="none"> 129 <path d="M1 1L6 6L1 11" stroke="#414142" stroke-width="1.5"/> 130 </svg> 131 </span> 132 <div class="loading-overlay__spinner hidden"> 133 <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> 134 <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> 135 </svg> 136 </div> 137 </button>`} 138 `;return wrapperOnly?innerContent:`<div class="cyo-step__nav">${innerContent}</div>`};renderActionButtons=()=>{const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep),isReview=this.isReviewStep(),hasSelection=selection&&selection.variant,isVariantAvailable=hasSelection?this.isVariantAvailable(selection.variant):!1,canProceed=isReview?this.selections.size>0:hasSelection&&isVariantAvailable,showBack=this.currentStepIndex>0||this.currentPath.length>0;let nextLabel="Next",nextButtonClass="cyo-step__action--next";return isReview?(nextLabel="Add to Bag",nextButtonClass="cyo-step__action--add-to-bag"):this.currentStepIndex===this.config.steps.length-1&&this.currentPath.length===0?nextLabel="Next: Review":this.currentStepIndex<this.config.steps.length-1&&(nextLabel=`Next: ${this.config.steps[this.currentStepIndex+1].name}`),hasSelection&&!isVariantAvailable&&(nextLabel="SOLD OUT",nextButtonClass="cyo-step__action--sold-out"),` 139 ${showBack?`<button class="cyo-step__action cyo-step__action--back"> 140 <span class="cyo-step__action-arrow"> 141 <svg xmlns="http://www.w3.org/2000/svg" width="11" height="17" viewBox="0 0 11 17" fill="none"> 142 <path d="M9.5 16L2 8.5L9.5 0.999998" stroke="white" stroke-width="1.5"/> 143 </svg> 144 </span> 145 <span class="cyo-step__action-text">Back</span> 146 <div class="loading-overlay__spinner hidden"> 147 <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> 148 <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> 149 </svg> 150 </div> 151 </button>`:""} 152 <button class="cyo-step__action ${nextButtonClass} ${canProceed?"":"disabled"}" ${canProceed?"":"disabled"}> 153 <span class="cyo-step__action-text">${nextLabel}</span> 154 <div class="loading-overlay__spinner hidden"> 155 <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> 156 <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> 157 </svg> 158 </div> 159 </button> 160 `};renderReviewStep=async()=>{try{if(Array.from(this.selections.values()).length===0)return'<div class="cyo-error">
160No selections found</div>';await this.calculatePricing();const stepSummaries=await this.renderStepSummaries();return` 161 <div class="cyo-step"> 162 <div class="cyo-step__header"> 163 <h2 class="cyo-step__title">${this.config.steps.length+1}. Verify Your Selection</h2> 164 ${this.renderHeaderNavigation()} 165 </div> 166 <div class="cyo-step__content"> 167 ${stepSummaries} 168 </div> 169 <div class="cyo-cart-error-container" style="display: none;"></div> 170 <div class="cyo-step__actions"> 171 ${this.renderActionButtons()} 172 </div> 173 </div> 174 `}catch(error){return console.error("\u274C CYO: Error rendering review step:",error),'<div class="cyo-error">Failed to render review</div>'}};renderStepSummaries=async()=>{try{const summaries=[];for(const step of this.config.steps){const selection=this.getSelectionForStep(step);if(selection&&selection.variant){const summary=await this.renderStepSummary(step,selection);summary&&summaries.push(summary)}}return summaries.join("")}catch(error){return console.error("\u274C CYO: Error rendering step summaries:",error),'<div class="cyo-error">Failed to render step summaries</div>'}};getVariantMediaHtml=async variant=>{try{if(!variant||!variant.media_url)return null;const response=await fetch(variant.media_url);if(!response.ok)return null;const mediaHtml=await response.text(),tempDiv=document.createElement("div");tempDiv.innerHTML=mediaHtml;const imgElement=tempDiv.querySelector("img");return imgElement?imgElement.outerHTML:null}catch(error){return console.error("\u274C CYO: Error fetching variant media HTML:",error),null}};renderStepSummary=async(step,selection)=>{try{const product=selection.product,option=selection.option,variant=selection.variant;if(!product||!variant)return"";const reviewStepId=`review-step-${step.id}`,reviewProductId=`review-product-${product.id}`,optionTypes=this.getProductOptionTypes(product);let productMediaHtml=product.media[0]||"";if(variant&&variant.media_url)try{const variantMediaHtml=await this.getVariantMediaHtml(variant);variantMediaHtml?(productMediaHtml=variantMediaHtml,this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Review step using variant media for ${product.title} - ${variant.title}`)):this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Review step falling back to default media for ${product.title}`)}catch(error){console.error("\u274C CYO: Error getting variant media for review:",error)}const productSwatchHtml=` 175 <div class="cyo-variant-option"> 176 <label class="cyo-variant-option__label">${step.name||"Style"} - <span class="cyo-step__selection-name">${product.title.toLowerCase()}</span></label> 177 <fieldset class="cyo-variant-option__fieldset"> 178 <legend class="visually-hidden">Selected product option</legend> 179 <div class="cyo-product-options"> 180 <div class="cyo-product-option"> 181 <input type="radio" class="cyo-product-option__input" id="${reviewProductId}" name="${reviewStepId}-product" checked disabled /> 182 <label for="${reviewProductId}" class="cyo-product-option__label"> 183 ${productMediaHtml} 184 </label> 185 </div> 186 </div> 187 </fieldset> 188 </div> 189 `;let variantOptionsHtml="";for(const optionType of optionTypes){const optionName=optionType.name;if(!(!step.allowed_option_selectors||step.allowed_option_selectors.includes(optionName))||!(step.allowed_single_option_selectors&&step.allowed_single_option_selectors.includes(optionName)))continue;const optionHtml=this.renderReviewOptionGroup(product,option,optionType,variant,reviewStepId);optionHtml&&(variantOptionsHtml+=optionHtml)}return` 190 <div class="cyo-review-step" data-step-id="${step.id}"> 191 ${productSwatchHtml} 192 ${variantOptionsHtml} 193 </div> 194 `}catch(error){return console.error("\u274C CYO: Error rendering step summary:",error),""}};renderReviewOptionGroup=(product,selectionOption,optionType,selectedVariant,reviewStepId)=>
194{try{const optionKey=optionType.key,optionName=optionType.name,optionIndex=optionType.index,renderType=optionType.type;let selectedValue=null;if(optionType.specialKey==="color"&&product.has_color_option&&product.color_option_index!==void 0?selectedValue=selectedVariant.color:optionType.specialKey==="size"&&product.has_size_option&&product.size_option_index!==void 0?selectedValue=selectedVariant.options[product.size_option_index]:selectedValue=selectedVariant.options[optionIndex],!selectedValue)return"";const fieldsetId=`${reviewStepId}-${optionKey}`,inputId=`${fieldsetId}-${selectedValue.toLowerCase().replace(/[^a-z0-9]/g,"-")}`;if(renderType==="swatch"&&optionKey==="color"){const valueHandle=selectedValue.toLowerCase().replace(/[^a-z0-9]/g,"-");return` 195 <div class="cyo-variant-option"> 196 <label class="cyo-variant-option__label">${optionName} - <span class="cyo-step__selection-name">${selectedValue.toLowerCase()}</span></label> 197 <fieldset class="cyo-variant-option__fieldset"> 198 <legend class="visually-hidden">${optionName} selection</legend> 199 <div class="cyo-color-swatches"> 200 <div class="cyo-color-option cyo-color-option--selected"> 201 <input 202 type="radio" 203 class="cyo-color-option__input" 204 id="${inputId}" 205 name="${fieldsetId}" 206 value="${selectedValue}" 207 checked 208 disabled 209 /> 210 <label for="${inputId}" class="cyo-color-option__label"> 211 <div class="cyo-color-option__swatch" style="background: var(--swatch-${valueHandle});"></div> 212 <span class="visually-hidden">${selectedValue}</span> 213 </label> 214 </div> 215 </div> 216 </fieldset> 217 </div> 218 `}else{const optionClass=optionKey==="size"?"cyo-size-options":`cyo-${optionKey}-options`,itemClass=optionKey==="size"?"cyo-size-option":`cyo-${optionKey}-option`;return` 219 <div class="cyo-variant-option"> 220 <label class="cyo-variant-option__label">${optionName} - <span class="cyo-step__selection-name">${selectedValue.toLowerCase()}</span></label> 221 <fieldset class="cyo-variant-option__fieldset"> 222 <legend class="visually-hidden">${optionName} selection</legend> 223 <div class="${optionClass}"> 224 <div class="${itemClass} ${itemClass}--selected"> 225 <input 226 type="radio" 227 class="${itemClass}__input" 228 id="${inputId}" 229 name="${fieldsetId}" 230 value="${selectedValue}" 231 checked 232 disabled 233 /> 234 <label for="${inputId}" class="${itemClass}__label">${selectedValue}</label> 235 </div> 236 </div> 237 </fieldset> 238 </div> 239 `}}catch(error){return console.error(`\u274C CYO: Error rendering review option group for ${optionType.key}:`,error),""}};renderUnavailableMessage=()=>` 240 <div class="cyo-error"> 241 <h3>No Available Options</h3> 242 <p>Sorry, there are no available options for this step at the moment.</p> 243 </div> 244 `;attachEventListeners=()=>{try{this.shadowRoot.removeEventListener("change",this.handleDelegatedChange),this.shadowRoot.removeEventListener("click",this.handleDelegatedClick),this.shadowRoot.removeEventListener("keydown",this.handleKeyboardNavigation),this.shadowRoot.removeEventListener("focusin",this.handleFocusIn),this.shadowRoot.removeEventListener("mousedown",this.handleMouseDown),this.shadowRoot.removeEventListener("pointerover",this.handlePointerOver),this.shadowRoot.addEventListener("change",this.handleDelegatedChange),this.shadowRoot.addEventListener("click",this.handleDelegatedClick),this.shadowRoot.addEventListener("keydown",this.handleKeyboardNavigation),this.shadowRoot.addEventListener("focusin",this.handleFocusIn),this.shadowRoot.addEventListener("mousedown",this.handleMouseDown),this.shadowRoot.addEventListener("pointerover",this.handlePointerOver),this.allowDebug()&&console.log("\u{1F3A7} CYO: Event delegation listeners attached to shadow root (with accessibility enhancements)")}catch(error){console.error("\u274C CYO: Error attaching event listeners:",error)}};handleFocusIn=event=>{this.keyboardNavigation=!0,document.documentElement.setAttribute("data-keyboard-navigation","true");const radioInput=event.target?.closest?.("input[type='radio']");radioInput&&this.scheduleAggregatePrefetch(radioInput)};handleMouseDown=()=>{this.keyboardNavigation=!1,document.documentElement.removeAttribute("data-keyboard-navigation")};handlePointerOver=event=>{const optionContainer=event.target?.closest?.(".cyo-product-option, .cyo-size-option, .cyo-color-option");if(optionContainer&&event.relatedTarget&&optionContainer.contains(event.relatedTarget))return;const radioInput=optionContainer?.querySelector("input[type='radio']")||event.target?.closest?.("input[type='radio']");!radioInput||radioInput.disabled||!(radioInput.name?.includes("product-options")||radioInput.name?.includes("-selection-"))||this.scheduleAggregatePrefetch(radioInput)};scheduleAggregatePrefetch=input=>{if(!input?.name)return;const debounceKey=`aggregateMediaPrefetch:${input.name}:${input.value}:${input.dataset.productId||""}:${input.dataset.optionId||""}`;this.debounceManager.debounce(debounceKey,()=>this.prefetchAggregateMediaForInput(input),this.aggregatePrefetchDebounceDelay)};prefetchAggregateMediaForInput=input=>{try{const currentStep=this.getCurrentStep();if(!currentStep)return;const predictedVariant=this.getPredictedVariantFromInput(input,currentStep);if(!predictedVariant?.sku)return;const selectedVariants=[];for(let stepIndex=0;stepIndex<=this.currentStepIndex;stepIndex++){const step=this.config.steps[stepIndex];if(!step)continue;const selection=this.getSelectionForStep(step),variant=step.id===currentStep.id?predictedVariant:selection?.variant;variant?.sku&&selectedVariants.push(variant)}const aggregateMediaUrl=this.findAggregateMediaMatchForVariants(selectedVariants)?.media_json_url;if(!aggregateMediaUrl||this.prefetchedAggregateMediaUrls.has(aggregateMediaUrl))return;const productMediaComponent=this.productOverview?.querySelector("product-media");if(!productMediaComponent||typeof productMediaComponent.prefetchMedia!="function")return;this.prefetchedAggregateMediaUrls.add(aggregateMediaUrl),productMediaComponent.prefetchMedia(aggregateMediaUrl),this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Prefetching aggregate media on intent: ${aggregateMediaUrl}`)}catch(error){console.error("\u274C CYO: Error prefetching aggregate media on intent:",error)}};getPredictedVariantFromInput=(input,currentStep)=>{try{if(!input?.name||!currentStep)return null;if(input.name.includes("product-options")){const productId=parseInt(input.dataset.productId,10),optionId=parseInt(input.dataset.optionId,10),zoneType=input.dataset.zoneType||"regular";if(!(input.dataset.isEligible==="true"))return null;const option=(zoneType==="members_only"?currentStep.members_only_options:currentStep.options)?.find(opt=>opt.id===optionId),product=option?.products?.find(prod=>prod.id===productId);if(!product||!option)return null;const previousSelections=this.getPreviousVariantSelections();if(Object.keys(previousSelections).some(key=>previousSelections[key])){const matchingVariant=this.findMatchingVariant(product,option,previousSelections);if(matchingVariant)return matchingVariant}return this.getAvailableVariants(product,option)[0]||null}if(input.name.includes("-selection-")){const selection=this.getSelectionForStep(currentStep);if(!selection?.product||!selection?.option)return null;const product=selection.product,availableVariants=this.getAvailableVariants(product,selection.option);if(!availableVariants.length)return null;const optionTypes=this.getProductOptionTypes(product),selectedValues={};
244optionTypes.forEach(optionType=>{const selectedInput=this.shadowRoot.querySelector(`input[name*="${optionType.key}-selection"]:checked`);selectedInput&&(selectedValues[optionType.key]=selectedInput.value)});const hoveredOptionKey=input.name.split("-selection-")[0];return selectedValues[hoveredOptionKey]=input.value,availableVariants.find(variant=>optionTypes.every(optionType=>{const selectedValue=selectedValues[optionType.key];return selectedValue?optionType.key==="color"?variant.color===selectedValue:variant.options[optionType.index]===selectedValue:!0}))||null}return null}catch(error){return console.error("\u274C CYO: Error predicting variant from input:",error),null}};handleDelegatedChange=event=>{try{const target=event.target;if(this.allowDebug()&&console.log("\u{1F3A7} CYO: Delegated change event on:",target,`checked: ${target.checked}`),!target.matches("input[type='radio']")||!target.checked){this.allowDebug()&&console.log("\u{1F3A7} CYO: Change event ignored - not a checked radio input");return}if(this.allowDebug()&&console.log(`\u{1F3A7} CYO: Processing radio change - ${target.name} = ${target.value}`),target.name&&target.name.includes("product-options")){const productId=parseInt(target.dataset.productId,10),optionId=parseInt(target.dataset.optionId,10),zoneType=target.dataset.zoneType||"regular";if(!(target.dataset.isEligible==="true")){this.allowDebug()&&console.log(`\u{1F6AB} CYO: Product selection blocked - Customer not eligible for Product: ${productId}, Option: ${optionId}, Zone: ${zoneType}`),target.checked=!1,this.announceToScreenReader("This selection requires membership access. Please explore memberships to unlock.","assertive");return}this.allowDebug()&&console.log(`\u{1F3A7} CYO: Product selection detected - Product: ${productId}, Option: ${optionId}, Zone: ${zoneType}`),this.handleProductSelection(productId,optionId,zoneType);return}if(target.name&&target.name.includes("-selection-")){const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep);if(selection&&selection.product){const availableVariants=this.getAvailableVariants(selection.product,selection.option);this.allowDebug()&&console.log(`\u{1F3A7} CYO: Variant option selection detected - ${target.name} = ${target.value}`),this.updateVariantSelection(selection.product,selection,availableVariants)}return}this.allowDebug()&&console.log(`\u{1F3A7} CYO: Unhandled change event for: ${target.name}`)}catch(error){console.error("\u274C CYO: Error in delegated change handler:",error)}};handleDelegatedClick=event=>{try{if(this.allowDebug()&&console.log("\u{1F3A7} CYO: Delegated click event",event.target,event.currentTarget),this.debounceManager.timers.has("clickDebounce")){this.allowDebug()&&console.log("\u{1F3A7} CYO: Click ignored - debounce active");return}const target=event.target;if(target.matches(".cyo-color-option__swatch")||target.matches(".cyo-color-option")||target.closest(".cyo-color-option")){const colorOption=target.closest(".cyo-color-option");if(colorOption){const radioInput=colorOption.querySelector(".cyo-color-option__input");radioInput&&!radioInput.checked&&(this.allowDebug()&&console.log("\u{1F3A7} CYO: Color swatch clicked - triggering radio input",radioInput),this.startClickDebounce(),radioInput.checked=!0,radioInput.dispatchEvent(new Event("change",{bubbles:!0})));return}}if(target.matches(".cyo-size-option")||target.closest(".cyo-size-option")){const sizeOption=target.closest(".cyo-size-option");if(sizeOption){const radioInput=sizeOption.querySelector(".cyo-size-option__input");radioInput&&!radioInput.checked&&(this.allowDebug()&&console.log("\u{1F3A7} CYO: Size option clicked - triggering radio input",radioInput),this.startClickDebounce(),radioInput.checked=!0,radioInput.dispatchEvent(new Event("change",{bubbles:!0})));return}}if(target.matches(".cyo-product-option")||target.closest(".cyo-product-option")){const productOption=target.closest(".cyo-product-option");if(productOption){const radioInput=productOption.querySelector(".cyo-product-option__input");if(radioInput&&!radioInput.checked){if(!(radioInput.dataset.isEligible==="true")){this.allowDebug()&&console.log("\u{1F6AB} CYO: Product option click blocked - customer not eligible",radioInput),this.announceToScreenReader("This selection requires membership access. Please explore memberships to unlock.","assertive");return}this.allowDebug()&&console.log("\u{1F3A7} CYO: Product option clicked - triggering radio input",radioInput),this.startClickDebounce(),radioInput.checked=!0,radioInput.dispatchEvent(new Event("change",{bubbles:!0}))}return}}if(target.matches(".cyo-more-options-btn--show-more")||target.closest(".cyo-more-options-btn--show-more")){event.preventDefault();const button=target.matches(".cyo-more-options-btn--show-more")?target:target.closest(".cyo-more-options-btn--show-more"),zoneKey=button?.dataset.zoneKey,zoneType=button?.dataset.zoneType;this.allowDebug()&&console.log(`\u{1F3A7} CYO: MORE OPTIONS + button clicked for zone: ${zoneKey}`),this.startClickDebounce(),this.handleMoreOptionsClick(zoneKey,zoneType);return}if(target.matches(".cyo-more-options-btn--show-less")||target.closest(".cyo-more-options-btn--show-less")){event.preventDefault();const button=target.matches(".cyo-more-options-btn--show-less")?target:target.closest(".cyo-more-options-btn--show-less"),zoneKey=button?.dataset.zoneKey,zoneType=button?.dataset.zoneType;this.allowDebug()&&console.log(`\u{1F3A7} CYO: LESS OPTIONS - button clicked for zone: ${zoneKey}`),this.startClickDebounce(),this.handleLessOptionsClick(zoneKey,zoneType);return}const backButton=target.closest(".cyo-step__action--back, .cyo-step__nav-item--back");if(backButton){event.preventDefault(),this.allowDebug()&&console.log("\u{1F3A7} CYO: Back button clicked",backButton),backButton.classList.add("loading");const spinner=backButton.querySelector(".loading-overlay__spinner");spinner&&spinner.classList.remove("hidden"),this.startClickDebounce(),this.handleBack();return}const addToBagButton=target.closest(".cyo-step__action--add-to-bag");if(addToBagButton){event.preventDefault(),this.allowDebug()&&console.log("\u{1F3A7} CYO: Add to Bag button clicked",addToBagButton),addToBagButton.classList.add("loading");const spinner=addToBagButton.querySelector(".loading-overlay__spinner");spinner&&spinner.classList.remove("hidden"),this.startClickDebounce(),this.handleAddToBag();return}const nextButton=target.closest(".cyo-step__action--next, .cyo-step__nav-item--next");if(nextButton){event.preventDefault(),this.allowDebug()&&console.log("\u{1F3A7} CYO: Next button clicked",nextButton),nextButton.classList.add("loading");const spinner=nextButton.querySelector(".loading-overlay__spinner");spinner&&spinner.classList.remove("hidden"),this.startClickDebounce(),this.handleNext();return}this.allowDebug()&&console.log("\u{1F3A7} CYO: No matching click handler found for",target)}catch(error){console.error("\u274C CYO: Error in delegated click handler:",error)}};startClickDebounce=()=>{this.debounceManager.debounce("clickDebounce",()=>{this.allowDebug()&&console.log("\u{1F3A7} CYO: Click debounce cleared")},this.clickDebounceDelay),this.allowDebug()&&console.log(`\u{1F3A7} CYO: Click debounce started (${this.clickDebounceDelay}ms)`)};handleMoreOptionsClick=async(zoneKey,zoneType)=>{try{this.allowDebug()&&console.log(`\u{1F4D6}
244 CYO: Expanding product options for zone: ${zoneKey}`);const moreButton=this.shadowRoot.querySelector(`.cyo-more-options-btn--show-more[data-zone-key="${zoneKey}"]`);moreButton&&(moreButton.classList.add("loading"),moreButton.disabled=!0),this.zoneExpansionState[zoneKey]=!0,await this.reRenderZoneProductOptions(zoneKey,zoneType),this.announceToScreenReader(`Expanded ${zoneType} options to show all`,"polite")}catch(error){console.error(`\u274C CYO: Error handling MORE OPTIONS click for zone ${zoneKey}:`,error)}};handleLessOptionsClick=async(zoneKey,zoneType)=>{try{this.allowDebug()&&console.log(`\u{1F4D6} CYO: Collapsing product options for zone: ${zoneKey}`);const lessButton=this.shadowRoot.querySelector(`.cyo-more-options-btn:not(.cyo-more-options-btn--show-more)[data-zone-key="${zoneKey}"]`);lessButton&&(lessButton.classList.add("loading"),lessButton.disabled=!0),this.zoneExpansionState[zoneKey]=!1,await this.reRenderZoneProductOptions(zoneKey,zoneType),this.announceToScreenReader(`Collapsed ${zoneType} options to show fewer`,"polite")}catch(error){console.error(`\u274C CYO: Error handling LESS OPTIONS click for zone ${zoneKey}:`,error)}};reRenderZoneProductOptions=async(zoneKey,zoneType)=>{try{const currentStep=this.getCurrentStep(),zone=this.getAvailableOptions(currentStep)[zoneType];if(!zone||!zone.options.length){this.allowDebug()&&console.warn(`\u26A0\uFE0F CYO: No zone data found for ${zoneKey}`);return}const paginationSettings=this.getStepPaginationSettings(currentStep),selectionZoneElement=this.shadowRoot.querySelector(`.cyo-selection-zone[data-zone-type="${zoneType}"]`);if(!selectionZoneElement){this.allowDebug()&&console.warn(`\u26A0\uFE0F CYO: Zone element not found for ${zoneType}`);return}const fieldset=selectionZoneElement.querySelector(".cyo-variant-option__fieldset"),optionsGrid=selectionZoneElement.querySelector(".cyo-product-options");if(!fieldset||!optionsGrid){this.allowDebug()&&console.warn(`\u26A0\uFE0F CYO: Required elements not found in zone ${zoneType}`);return}this.allowDebug()&&console.log(`\u{1F3AC} CYO: Starting animated transition for zone ${zoneKey} to ${this.zoneExpansionState[zoneKey]?"expanded":"collapsed"} state`);const allProducts=[];zone.options.forEach(option=>{option.products.filter(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,option).length>0).forEach(product=>allProducts.push({product,option}))});const totalProducts=allProducts.length,isExpanding=this.zoneExpansionState[zoneKey],currentHeight=fieldset.offsetHeight;if(fieldset.style.height=`${currentHeight}px`,isExpanding){const currentCount=optionsGrid.querySelectorAll(".cyo-product-option").length,additionalProducts=allProducts.slice(currentCount);if(additionalProducts.length>0){const additionalHTML=additionalProducts.map(({product,option})=>{const inputId=`product-options-${currentStep.id}-${zoneType}-product-${product.id}-option-${option.id}`,radioName=`product-options-${currentStep.id}-${zoneType}-selection`,isEligible=zoneType==="members_only"?option.isEligible!==!1:!0,isDisabled=!isEligible;return` 245 <div class="${`cyo-product-option${isDisabled?" cyo-product-option--disabled":""}`}" style="opacity: 0; transform: translateY(20px);"> 246 <input 247 type="radio" 248 id="${inputId}" 249 class="${`cyo-product-option__input${isDisabled?" cyo-product-option__input--disabled":""}`}" 250 name="${radioName}" 251 value="${product.id}-${option.id}" 252 data-product-id="${product.id}" 253 data-option-id="${option.id}" 254 data-zone-type="${zoneType}" 255 data-is-eligible="${isEligible}" 256 ${isDisabled?"disabled":""} 257 /> 258 <label for="${inputId}" class="cyo-product-option__label"> 259 ${product.media[0]||""} 260 <div class="cyo-product-option__title">${product.title}</div> 261 </label> 262 </div> 263 `}).join("");optionsGrid.insertAdjacentHTML("beforeend",additionalHTML)}}else{const allOptions=optionsGrid.querySelectorAll(".cyo-product-option"),keepCount=Math.min(paginationSettings.optionsPerPage,totalProducts);Array.from(allOptions).slice(keepCount).forEach((option,index)=>{setTimeout(()=>{option.style.transition="opacity 0.3s ease, transform 0.3s ease",option.style.opacity="0",option.style.transform="translateY(-20px)"},index*30)})}fieldset.style.height="auto";const newHeight=fieldset.offsetHeight;fieldset.style.height=`${currentHeight}px`,requestAnimationFrame(()=>{if(fieldset.style.height=`${newHeight}px`,setTimeout(()=>{this.updateZoneToggleButton(zoneKey,zoneType,totalProducts)},100),isExpanding){const newOptions=optionsGrid.querySelectorAll(".cyo-product-option"),startIndex=Math.min(paginationSettings.optionsPerPage,newOptions.length);newOptions.forEach((option,index)=>{index>=startIndex&&setTimeout(()=>{option.style.transition="opacity 0.3s ease, transform 0.3s ease",option.style.opacity="1",option.style.transform="translateY(0)"},(index-startIndex)*50)})}setTimeout(()=>{if(fieldset.style.height="auto",!isExpanding){const keepCount=Math.min(paginationSettings.optionsPerPage,totalProducts);Array.from(optionsGrid.querySelectorAll(".cyo-product-option")).slice(keepCount).forEach(option=>option.remove())}optionsGrid.querySelectorAll(".cyo-product-option").forEach(option=>{option.style.opacity="",option.style.transform="",option.style.transition=""}),this.allowDebug()&&console.log(`\u2705 CYO: Animated transition completed for zone ${zoneKey}`)},400)})}catch(error){console.error("\u274C CYO: Error in zone-specific product options transition:",error)}};reRenderProductOptions=async()=>{try{const currentStep=this.getCurrentStep(),availableOptions=this.getAvailableOptions(currentStep),fieldset=this.shadowRoot.querySelector(".cyo-variant-option__fieldset"),optionsGrid=this.shadowRoot.querySelector(".cyo-product-options");
263if(!fieldset||!optionsGrid||Object.keys(availableOptions).length===0)return;const paginationSettings=this.getStepPaginationSettings(currentStep);this.allowDebug()&&console.log(`\u{1F3AC} CYO: Starting animated transition to ${this.productOptionsExpanded?"expanded":"collapsed"} state`);const allProducts=[];availableOptions.regular&&availableOptions.regular.options.forEach(option=>{option.products.filter(product=>this.isProductAvailable(product)&&this.getAvailableVariants(product,option).length>0).forEach(product=>allProducts.push({product,option}))});const totalProducts=allProducts.length,isExpanding=this.productOptionsExpanded,currentHeight=fieldset.offsetHeight;if(fieldset.style.height=`${currentHeight}px`,isExpanding){const currentCount=optionsGrid.querySelectorAll(".cyo-product-option").length,additionalProducts=allProducts.slice(currentCount);if(additionalProducts.length>0){const additionalHTML=additionalProducts.map(({product,option})=>{const inputId=`product-options-${currentStep.id}-product-${product.id}-option-${option.id}`,radioName=`product-options-${currentStep.id}-selection`,isEligible=!0,isDisabled=!isEligible;return` 264 <div class="${`cyo-product-option${isDisabled?" cyo-product-option--disabled":""}`}" style="opacity: 0; transform: translateY(20px);"> 265 <input 266 type="radio" 267 id="${inputId}" 268 class="${`cyo-product-option__input${isDisabled?" cyo-product-option__input--disabled":""}`}" 269 name="${radioName}" 270 value="${product.id}-${option.id}" 271 data-product-id="${product.id}" 272 data-option-id="${option.id}" 273 data-is-eligible="${isEligible}" 274 ${isDisabled?"disabled":""} 275 /> 276 <label for="${inputId}" class="cyo-product-option__label"> 277 ${product.media[0]||""} 278 <div class="cyo-product-option__title">${product.title}</div> 279 </label> 280 </div> 281 `}).join("");optionsGrid.insertAdjacentHTML("beforeend",additionalHTML)}}else{const allOptions=optionsGrid.querySelectorAll(".cyo-product-option"),keepCount=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage?paginationSettings.optionsPerPage:totalProducts;Array.from(allOptions).slice(keepCount).forEach((option,index)=>{setTimeout(()=>{option.style.transition="opacity 0.3s ease, transform 0.3s ease",option.style.opacity="0",option.style.transform="translateY(-20px)"},index*30)})}fieldset.style.height="auto";const newHeight=fieldset.offsetHeight;fieldset.style.height=`${currentHeight}px`,requestAnimationFrame(()=>{if(fieldset.style.height=`${newHeight}px`,setTimeout(()=>{this.updateToggleButton(totalProducts)},100),isExpanding){const newOptions=optionsGrid.querySelectorAll(".cyo-product-option"),startIndex=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage?Math.min(paginationSettings.optionsPerPage,newOptions.length):newOptions.length;newOptions.forEach((option,index)=>{index>=startIndex&&setTimeout(()=>{option.style.transition="opacity 0.3s ease, transform 0.3s ease",option.style.opacity="1",option.style.transform="translateY(0)"},(index-startIndex)*50)})}setTimeout(()=>{if(fieldset.style.height="auto",!isExpanding){const keepCount=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage?paginationSettings.optionsPerPage:totalProducts;Array.from(optionsGrid.querySelectorAll(".cyo-product-option")).slice(keepCount).forEach(option=>option.remove())}optionsGrid.querySelectorAll(".cyo-product-option").forEach(option=>{option.style.opacity="",option.style.transform="",option.style.transition=""}),this.allowDebug()&&console.log("\u2705 CYO: Animated product options transition completed")},400)})}catch(error){console.error("\u274C CYO: Error in animated product options transition:",error)}};updateZoneToggleButton=(zoneKey,zoneType,totalProducts)=>{try{const toggleContainer=this.shadowRoot.querySelector(`.cyo-product-options-toggle[data-zone-key="${zoneKey}"]`);if(!toggleContainer)return;const currentStep=this.getCurrentStep(),paginationSettings=this.getStepPaginationSettings(currentStep),hasMoreProducts=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage&&totalProducts>paginationSettings.optionsPerPage;toggleContainer.classList.add("transitioning"),setTimeout(()=>{if(hasMoreProducts){const buttonHTML=this.zoneExpansionState[zoneKey]?`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-less" data-zone-key="${zoneKey}" data-zone-type="${zoneType}">
282 <span>${paginationSettings.viewLessCta}</span> 283 </button>`:`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-more" data-zone-key="${zoneKey}" data-zone-type="${zoneType}"> 284 <span>${paginationSettings.viewMoreCta}</span> 285 </button>`;toggleContainer.innerHTML=buttonHTML}else toggleContainer.innerHTML="";setTimeout(()=>{toggleContainer.classList.remove("transitioning")},50)},150),this.allowDebug()&&console.log(`\u2705 CYO: Updated toggle button for zone ${zoneKey}`)}catch(error){console.error(`\u274C CYO: Error updating zone toggle button for ${zoneKey}:`,error)}};updateToggleButton=totalProducts=>{try{const toggleContainer=this.shadowRoot.querySelector(".cyo-product-options-toggle");if(!toggleContainer)return;const currentStep=this.getCurrentStep(),paginationSettings=this.getStepPaginationSettings(currentStep),hasMoreProducts=paginationSettings.enabled&&totalProducts>paginationSettings.optionsPerPage&&totalProducts>paginationSettings.optionsPerPage;toggleContainer.classList.add("transitioning"),setTimeout(()=>{if(hasMoreProducts){const buttonHTML=this.productOptionsExpanded?`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-less"> 286 <span>${paginationSettings.viewLessCta}</span> 287 </button>`:`<button type="button" class="cyo-more-options-btn cyo-more-options-btn--show-more"> 288 <span>${paginationSettings.viewMoreCta}</span> 289 </button>`;toggleContainer.innerHTML=buttonHTML}else toggleContainer.innerHTML="";setTimeout(()=>{toggleContainer.classList.remove("transitioning")},50)},150)}catch(error){console.error("\u274C CYO: Error updating toggle button:",error)}};getPreviousVariantSelections=()=>{const previousSelections={};for(const selection of this.selections.values())selection.variant&&selection.product&&this.getProductOptionTypes(selection.product).forEach(optionType=>{if(optionType.specialKey==="color"&&selection.product.has_color_option&&selection.variant.color)previousSelections.color=selection.variant.color;else if(selection.variant.options&&optionType.index!==void 0){const optionValue=selection.variant.options[optionType.index];optionValue&&(previousSelections[optionType.key]=optionValue)}});return previousSelections};findMatchingVariant=(product,option,previousSelections)=>{const availableVariants=this.getAvailableVariants(product,option),optionTypes=this.getProductOptionTypes(product);return availableVariants.find(variant=>optionTypes.every(optionType=>{const previousValue=previousSelections[optionType.key];if(!previousValue)return!0;if(optionType.specialKey==="color"&&product.has_color_option)return variant.color===previousValue;{const optionIndex=optionType.index;if(optionIndex!==void 0&&variant.options&&variant.options[optionIndex])return variant.options[optionIndex]===previousValue}return!0}))};updateProductSwatchSelection=(product,option,zoneType="regular")=>{try{this.shadowRoot.querySelectorAll(".cyo-product-option").forEach(swatch=>{const input=swatch.querySelector(".cyo-product-option__input");if(input){const inputProductId=parseInt(input.dataset.productId,10),inputOptionId=parseInt(input.dataset.optionId,10),inputZoneType=input.dataset.zoneType||"regular";inputProductId===product.id&&inputOptionId===option.id&&inputZoneType===zoneType?(swatch.classList.add("cyo-product-option--selected"),input.checked=!0,this.allowDebug()&&console.log(`\u2705 CYO: Updated product swatch selection for product ${product.id}, option ${option.id}, zone ${zoneType}`)):(swatch.classList.remove("cyo-product-option--selected"),input.checked=!1)}})}catch(error){console.error("\u274C CYO: Error updating product swatch selection:",error)}};restoreStepState=existingSelection=>{try{this.allowDebug()&&console.log("\u{1F504} CYO: Restoring step state",existingSelection),this.updateProductSwatchSelection(existingSelection.product,existingSelection.option,existingSelection.zoneType||"regular");const zoneKey=existingSelection.zoneKey||existingSelection.zoneType||"regular";this.renderVariantSelection(existingSelection.product,existingSelection,zoneKey),this.updateOptionValueDisplay(),this.updateActionButtons(),this.debouncedUpdateMediaGallery(),this.allowDebug()&&console.log("\u2705 CYO: Step state restoration completed")}catch(error){console.error("\u274C CYO: Error restoring step state:",error)}};updateOptionValueDisplay=()=>{try{const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep);if(this.shadowRoot.querySelectorAll(".cyo-selection-zone").forEach(zoneElement=>{const zoneType=zoneElement.dataset.zoneType,selectionNameElement=zoneElement.querySelector(".cyo-step__selection-name");if(selectionNameElement)if(selection&&selection.product&&selection.zoneType===zoneType){const decodedTitle=decodeHTMLEntities(selection.product.title);selectionNameElement.textContent=decodedTitle.toLowerCase(),this.allowDebug()&&console.log(`\u{1F3F7}\uFE0F CYO: Updated ${zoneType} zone selection name with product: ${selection.product.title}`)}else selectionNameElement.textContent="",this.allowDebug()&&selection&&console.log(`\u{1F3F7}\uFE0F CYO: Cleared ${zoneType} zone selection name (selection is in ${selection.zoneType||"unknown"} zone)`)}),selection&&selection.product&&selection.zoneType){const optionTypes=this.getProductOptionTypes(selection.product),zoneElement=this.shadowRoot.querySelector(`.cyo-selection-zone[data-zone-type="${selection.zoneType}"]`);
289zoneElement&&optionTypes.forEach(optionType=>{const optionValueElement=zoneElement.querySelector(`[data-option-type='${optionType.key}']`);if(optionValueElement)if(selection.variant){let optionText;if(optionType.specialKey==="color"&&selection.product.has_color_option&&selection.variant.color)if(optionText=decodeHTMLEntities(selection.variant.color).toLowerCase(),selection.variant.color_family){const decodedColorFamily=decodeHTMLEntities(selection.variant.color_family);optionValueElement.replaceChildren(),optionValueElement.appendChild(document.createTextNode(optionText));const subValueElement=createElementFromHTML(`<span class="cyo-step__selection-detail">${decodedColorFamily.toLowerCase()}</span>`);subValueElement&&(optionValueElement.appendChild(document.createTextNode(" ")),optionValueElement.appendChild(subValueElement)),this.allowDebug()&&console.log(`\u{1F3A8} CYO: Updated ${optionType.key} option value: ${optionText} (${selection.variant.color_family})`)}else optionValueElement.textContent=optionText||"",this.allowDebug()&&optionText&&console.log(`\u{1F3A8} CYO: Updated ${optionType.key} option value: ${optionText}`);else{const optionIndex=optionType.index;optionIndex!==void 0&&selection.variant.options&&selection.variant.options[optionIndex]?(optionText=decodeHTMLEntities(selection.variant.options[optionIndex]).toLowerCase(),optionValueElement.textContent=optionText,this.allowDebug()&&console.log(`\u{1F4CF} CYO: Updated ${optionType.key} option value: ${optionText}`)):optionValueElement.textContent=""}}else if(selection.selectedValues&&selection.selectedValues[optionType.key]){const selectedValue=selection.selectedValues[optionType.key],decodedValue=decodeHTMLEntities(selectedValue);if(optionType.key==="color"&&selection.product.has_color_option){const colorVariant=selection.product.variants.find(v=>v.color&&decodeHTMLEntities(v.color).toLowerCase()===decodedValue.toLowerCase());if(colorVariant&&colorVariant.color_family){const decodedColorFamily=decodeHTMLEntities(colorVariant.color_family);optionValueElement.replaceChildren(),optionValueElement.appendChild(document.createTextNode(decodedValue.toLowerCase()));const subValueElement=createElementFromHTML(`<span class="cyo-step__selection-detail">${decodedColorFamily.toLowerCase()}</span>`);subValueElement&&(optionValueElement.appendChild(document.createTextNode(" ")),optionValueElement.appendChild(subValueElement)),this.allowDebug()&&console.log(`\u{1F3A8} CYO: Updated unavailable ${optionType.key} option value: ${decodedValue.toLowerCase()} (${decodedColorFamily})`)}else optionValueElement.textContent=decodedValue.toLowerCase(),this.allowDebug()&&console.log(`\u{1F4CF} CYO: Updated unavailable ${optionType.key} option value: ${decodedValue.toLowerCase()}`)}else optionValueElement.textContent=decodedValue.toLowerCase(),this.allowDebug()&&console.log(`\u{1F4CF} CYO: Updated unavailable ${optionType.key} option value: ${decodedValue.toLowerCase()}`)}else optionValueElement.textContent=""})}}catch(error){console.error("\u274C CYO: Error updating option value display:",error)}};updateActionButtons=()=>{const actionsContainer=this.shadowRoot.querySelector(".cyo-step__actions");if(actionsContainer){actionsContainer.replaceChildren();const content=createElementFromHTML(`<div>${this.renderActionButtons()}</div>`);if(content)for(;content.firstChild;)actionsContainer.appendChild(content.firstChild)}const headerNavContainer=this.shadowRoot.querySelector(".cyo-step__nav");if(headerNavContainer){headerNavContainer.replaceChildren();const content=createElementFromHTML(`<div>${this.renderHeaderNavigation(!0)}</div>`);if(content)for(;content.firstChild;)headerNavContainer.appendChild(content.firstChild)}};updateVariantOptionSelection=(variant,selection)=>{try{const product=selection.product,optionTypes=this.getProductOptionTypes(product);this.allowDebug()&&console.log("\u{1F3A8} CYO: Updating variant option selection UI",variant,optionTypes),optionTypes.forEach(optionType=>{let selectedValue;if(optionType.specialKey==="color"&&product.has_color_option?selectedValue=variant.color:selectedValue=variant.options?.[optionType.index],selectedValue){const dataAttr=`data-${optionType.key}`,optionInputs=this.shadowRoot.querySelectorAll(`input[${dataAttr}]`),containerClass=optionType.key==="color"?".cyo-color-option":optionType.key==="size"?".cyo-size-option":`.cyo-${optionType.key}-option`;this.allowDebug()&&console.log(`\u{1F3A8} CYO: Updating ${optionType.key} selection to: ${selectedValue}, found ${optionInputs.length}
289 inputs`),optionInputs.forEach(input=>{const container=input.closest(containerClass);if(input.dataset[optionType.key]===selectedValue){input.checked=!0;const modifierClass=containerClass.replace(".","")+"--selected";container?.classList.add(modifierClass),this.allowDebug()&&console.log(`\u2705 CYO: Selected ${optionType.key} option: ${selectedValue}`)}else{input.checked=!1;const modifierClass=containerClass.replace(".","")+"--selected";container?.classList.remove(modifierClass)}})}})}catch(error){console.error("\u274C CYO: Error updating variant option selection:",error)}};handleProductSelection=(productId,optionId,zoneType="regular")=>{try{this.allowDebug()&&console.log(`\u{1F3AF} CYO: Product selected - ID: ${productId}, Option: ${optionId}, Zone: ${zoneType}`);const currentStep=this.getCurrentStep();if(!currentStep){console.error("\u274C CYO: No current step found");return}const option=(zoneType==="members_only"?currentStep.members_only_options:currentStep.options)?.find(opt=>opt.id===optionId),product=option?.products.find(prod=>prod.id===productId);if(!product||!option){console.error("\u274C CYO: Product or option not found",{productId,optionId,currentStep});return}const previousSelections=this.getPreviousVariantSelections(),selection={step:currentStep,option,product,variant:null,zoneType,zoneKey:zoneType};let preSelectedVariant=null;Object.keys(previousSelections).some(key=>previousSelections[key])&&(preSelectedVariant=this.findMatchingVariant(product,option,previousSelections),preSelectedVariant&&(this.allowDebug()&&console.log(`\u{1F916} CYO: Pre-selecting matching variant: ${preSelectedVariant.title||preSelectedVariant.id}`),selection.variant=preSelectedVariant)),this.setSelectionForStep(currentStep,selection,!!preSelectedVariant),this.updateProductSwatchSelection(product,option,zoneType),this.renderVariantSelection(product,selection,zoneType),this.updateOptionValueDisplay(),this.updateCombinationUnavailableStates(),preSelectedVariant&&this.updateActionButtons(),this.debouncedUpdateMediaGallery(),this.allowDebug()&&console.log("\u2705 CYO: Product selection handling completed")}catch(error){console.error("\u274C CYO: Error handling product selection:",error)}};updateVariantSelection=(product,selection,availableVariants)=>{try{this.allowDebug()&&console.log(`\u{1F504} CYO: Updating variant selection for product: ${product.title}`);const optionTypes=this.getProductOptionTypes(product),selectedValues={};optionTypes.forEach(optionType=>{const selectedInput=this.shadowRoot.querySelector(`input[name*="${optionType.key}-selection"]:checked`);selectedInput&&(selectedValues[optionType.key]=selectedInput.value,this.allowDebug()&&console.log(`\u{1F504} CYO: Found selected ${optionType.key}: ${selectedInput.value}`))}),this.allowDebug()&&console.log("\u{1F504} CYO: Selected values:",selectedValues);const matchingVariant=availableVariants.find(variant=>optionTypes.every(optionType=>{const selectedValue=selectedValues[optionType.key];return selectedValue?optionType.key==="color"?variant.color===selectedValue:variant.options[optionType.index]===selectedValue:!0}));matchingVariant?(this.allowDebug()&&console.log(`\u{1F504} CYO: Found matching variant: ${matchingVariant.title||matchingVariant.id}`),this.handleVariantSelection(matchingVariant,selection)):(this.allowDebug()&&console.log("\u{1F504} CYO: No matching variant found - marking as unavailable selection"),this.handleUnavailableVariantSelection(selectedValues,selection))}catch(error){console.error("\u274C CYO: Error updating variant selection:",error)}};updateProductOptionImages=(selectedVariant,selection)=>{try{this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Updating product option images based on variant: ${selectedVariant.title}`);const currentStep=this.getCurrentStep();if(!currentStep)return;const selectionZones=this.getAvailableOptions(currentStep);Object.entries(selectionZones).forEach(([zoneKey,zone])=>{if(!zone.options||zone.options.length===0)return;const zoneElement=this.shadowRoot.querySelector(`.cyo-selection-zone[data-zone-key="${zoneKey}"]`);zoneElement&&zone.options.forEach(option=>
289{option.products.forEach(product=>{if(product.id===selection.product.id)this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Updating selected product image: ${product.title} to variant ${selectedVariant.title}`),this.updateSingleProductOptionImage(zoneElement,product,option,selectedVariant,zoneKey);else{const matchingVariant=this.findMatchingVariantForImageUpdate(product,selectedVariant,selection.product);matchingVariant?this.updateSingleProductOptionImage(zoneElement,product,option,matchingVariant,zoneKey):this.resetProductOptionImageToDefault(zoneElement,product,option)}})})})}catch(error){console.error("\u274C CYO: Error updating product option images:",error)}};findMatchingVariantForImageUpdate=(targetProduct,selectedVariant,selectedProduct)=>{try{const selectedProductOptionTypes=this.getProductOptionTypes(selectedProduct),targetProductOptionTypes=this.getProductOptionTypes(targetProduct),matchingVariant=targetProduct.variants.find(variant=>{if(!this.isVariantAvailable(variant))return!1;const sharedOptionTypes=selectedProductOptionTypes.filter(selectedOptionType=>targetProductOptionTypes.some(targetOptionType=>targetOptionType.key===selectedOptionType.key));return sharedOptionTypes.length===0?!1:sharedOptionTypes.every(selectedOptionType=>{const targetOptionType=targetProductOptionTypes.find(type=>type.key===selectedOptionType.key);if(!targetOptionType)return!1;if(selectedOptionType.specialKey==="color"&&selectedVariant.color&&variant.color)return selectedVariant.color===variant.color;const selectedValue=selectedVariant.options[selectedOptionType.index],targetValue=variant.options[targetOptionType.index];return selectedValue===targetValue})});return this.allowDebug()&&matchingVariant?console.log(`\u{1F50D} CYO: Found matching variant for ${targetProduct.title}: ${matchingVariant.title} (${matchingVariant.color})`):this.allowDebug()&&console.log(`\u{1F50D} CYO: No matching variant found for ${targetProduct.title} with selected ${selectedVariant.color}`),matchingVariant||null}catch(error){return console.error("\u274C CYO: Error finding matching variant for image update:",error),null}};updateSingleProductOptionImage=async(zoneElement,product,option,variant,zoneKey)=>{try{const productOptionElement=zoneElement.querySelector(`input[data-product-id="${product.id}"][data-option-id="${option.id}"]`);if(!productOptionElement)return;const labelElement=productOptionElement.nextElementSibling;if(!labelElement)return;const imgElement=labelElement.querySelector("img");if(!imgElement)return;if(variant.media_url)try{const response=await fetch(variant.media_url);if(response.ok){const mediaHtml=await response.text(),tempDiv=document.createElement("div");tempDiv.innerHTML=mediaHtml;const newImgElement=tempDiv.querySelector("img");newImgElement&&(imgElement.src=newImgElement.src,imgElement.srcset=newImgElement.srcset||"",imgElement.alt=newImgElement.alt||"",this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Updated image for product ${product.title} to variant ${variant.title}`))}}catch(fetchError){console.error(`\u274C CYO: Error fetching variant media for ${product.title}:`,fetchError)}}catch(error){console.error("\u274C CYO: Error updating single product option image:",error)}};resetProductOptionImageToDefault=(zoneElement,product,option)=>{try{const productOptionElement=zoneElement.querySelector(`input[data-product-id="${product.id}"][data-option-id="${option.id}"]`);if(!productOptionElement)return;const labelElement=productOptionElement.nextElementSibling;if(!labelElement)return;const imgElement=labelElement.querySelector("img");if(!imgElement)return;if(product.media&&product.media[0]){const tempDiv=document.createElement("div");tempDiv.innerHTML=product.media[0];const defaultImgElement=tempDiv.querySelector("img");defaultImgElement&&(imgElement.src=defaultImgElement.src,imgElement.srcset=defaultImgElement.srcset||"",imgElement.alt=defaultImgElement.alt||"",this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Reset image for product ${product.title} to default`))}}catch(error){console.error("\u274C CYO: Error resetting product option image to default:",error)}};handleUnavailableVariantSelection=(selectedValues,selection)=>{try{this.allowDebug()&&console.log("\u{1F6AB} CYO: Handling unavailable variant selection:",selectedValues),selection.variant=null,selection.selectedValues=selectedValues,this.setSelectionForStep(selection.step,selection,!1),this.updateUnavailableOptionSelection(selectedValues,selection),this.updateActionButtons(),this.updateOptionValueDisplay(),this.updateCombinationUnavailableStates(),this.debouncedUpdateMediaGallery(),this.allowDebug()&&console.log("\u2705 CYO: Unavailable variant selection handled")}catch(error){console.error("\u274C CYO: Error handling unavailable variant selection:",error)}};updateUnavailableOptionSelection=(selectedValues,selection)=>{try{const product=selection.product,optionTypes=this.getProductOptionTypes(product);this.allowDebug()&&console.log("\u{1F3A8} CYO: Updating unavailable option selection UI",selectedValues);const allCheckedInputs=this.shadowRoot.querySelectorAll('input[type="radio"]:checked');this.allowDebug()&&console.log(`\u{1F3A8} CYO: Found ${allCheckedInputs.length}
289 currently checked inputs to mark as sold out`),allCheckedInputs.forEach(input=>{const container=input.closest(".cyo-color-option, .cyo-size-option, .cyo-product-option")||input.closest('[class*="cyo-"][class*="-option"]');container&&(container.classList.add("cyo-option--combination-unavailable"),this.allowDebug()&&console.log("\u{1F6AB} CYO: Marked option as combination unavailable:",input.name,input.value))}),optionTypes.forEach(optionType=>{const selectedValue=selectedValues[optionType.key];if(selectedValue!==void 0){const dataAttr=`data-${optionType.key}`,optionInputs=this.shadowRoot.querySelectorAll(`input[${dataAttr}]`),containerClass=optionType.key==="color"?".cyo-color-option":optionType.key==="size"?".cyo-size-option":`.cyo-${optionType.key}-option`;this.allowDebug()&&console.log(`\u{1F3A8} CYO: Updating ${optionType.key} unavailable selection to: ${selectedValue}, found ${optionInputs.length} inputs`),optionInputs.forEach(input=>{const container=input.closest(containerClass);if(input.dataset[optionType.key]===selectedValue){input.checked=!0;const modifierClass=containerClass.replace(".","")+"--selected";container?.classList.add(modifierClass),this.allowDebug()&&console.log(`\u2705 CYO: Selected unavailable ${optionType.key} option: ${selectedValue}`)}else{input.checked=!1;const modifierClass=containerClass.replace(".","")+"--selected";container?.classList.remove(modifierClass)}})}})}catch(error){console.error("\u274C CYO: Error updating unavailable option selection UI:",error)}};updateCombinationUnavailableStates=()=>{try{const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep);if(!selection||!selection.product){this.allowDebug()&&console.log("\u2139\uFE0F CYO: No selection or product found, skipping combination unavailable state update");return}const product=selection.product,optionTypes=this.getProductOptionTypes(product);this.allowDebug()&&console.log(`\u{1F50D} CYO: Updating combination unavailable states for product: ${product.title}`),this.clearCombinationUnavailableState();const currentSelectedValues={};optionTypes.forEach(optionType=>{const fieldsetName=`${optionType.key}-selection-${product.id}`,selectedInput=this.shadowRoot.querySelector(`input[name="${fieldsetName}"]:checked`);selectedInput&&(currentSelectedValues[optionType.key]=selectedInput.value)}),this.allowDebug()&&console.log("\u{1F4CA} CYO: Current selected values:",currentSelectedValues),optionTypes.forEach(optionType=>{const fieldsetName=`${optionType.key}-selection-${product.id}`;this.shadowRoot.querySelectorAll(`input[name="${fieldsetName}"]`).forEach(input=>{const optionValue=input.value,container=input.closest(".cyo-color-option, .cyo-size-option, .cyo-product-option")||input.closest('[class*="cyo-"][class*="-option"]');if(!container)return;const testCombination={...currentSelectedValues};testCombination[optionType.key]=optionValue,product.variants.some(variant=>this.isVariantAvailable(variant)?optionTypes.every(ot=>{const testValue=testCombination[ot.key];return testValue?ot.specialKey==="color"&&product.has_color_option?variant.color===testValue:variant.options[ot.index]===testValue:!0}):!1)||(container.classList.add("cyo-option--combination-unavailable"),this.allowDebug()&&console.log(`\u{1F6AB} CYO: Marked ${optionType.key} option "${optionValue}" as combination unavailable`))})}),this.allowDebug()&&console.log("\u2705 CYO: Updated combination unavailable states")}catch(error){console.error("\u274C CYO: Error updating combination unavailable states:",error)}};clearCombinationUnavailableState=()=>{try{this.shadowRoot.querySelectorAll('.cyo-color-option, .cyo-size-option, .cyo-product-option, [class*="cyo-"][class*="-option"]').forEach(container=>{container.classList.remove("cyo-option--combination-unavailable"),this.allowDebug()&&console.log("\u2705 CYO: Cleared combination unavailable state from option container")})}catch(error){console.error("\u274C CYO: Error clearing combination unavailable state:",error)}};handleVariantSelection=(variant,selection)=>{try{this.allowDebug()&&console.log(`\u{1F3A8} CYO: Variant selected - ${variant.title||variant.id} for product "${selection.product.title}"`),selection.variant=variant,this.updateCombinationUnavailableStates(),this.setSelectionForStep(selection.step,selection,!0),this.updateActionButtons(),this.updateV
289ariantOptionSelection(variant,selection),this.updateOptionValueDisplay(),this.updateProductOptionImages(variant,selection),this.debouncedUpdateMediaGallery()}catch(error){console.error("\u274C CYO: Error handling variant selection:",error)}};handleNext=async()=>{try{const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep);if(!selection||!selection.variant){this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: Cannot proceed - no selection or variant"),this.announceToScreenReader("Please make a selection before continuing","assertive");return}if(!this.isVariantAvailable(selection.variant)){this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: Cannot proceed - selected variant is sold out"),this.announceToScreenReader("This item is sold out. Please select a different option.","assertive");return}if(this.zoneExpansionState={},this.currentStepIndex++,await this.render(),setTimeout(()=>{this.updateMediaGallery()},100),this.isReviewStep())this.announceToScreenReader("Moved to review step","assertive");else{const stepName=this.getCurrentStep()?.label||`Step ${this.currentStepIndex+1}`;this.announceToScreenReader(`Moved to ${stepName}`,"assertive")}}catch(error){console.error("\u274C CYO: Error handling next:",error)}};handleBack=async()=>{try{if(this.currentStepIndex>0){this.zoneExpansionState={},this.currentStepIndex--,await this.render(),setTimeout(()=>{this.updateMediaGallery()},100);const stepName=this.getCurrentStep()?.label||`Step ${this.currentStepIndex+1}`;this.announceToScreenReader(`Moved back to ${stepName}`,"assertive")}}catch(error){console.error("\u274C CYO: Error handling back:",error)}};resetComponent=async()=>{try{this.allowDebug()&&console.log("\u{1F504} CYO: Resetting component to initial state"),this.currentStepIndex=0,this.currentPath=[],this.selections.clear(),this.price=0,this.compareAtPrice=0,this.priceHTML=null,this.#productOptionTypesCache.clear(),this.currentStep1MediaUrl=null,this.currentDisplayedMediaUrl=null,this.currentBundleFeaturedMedia=null,this.zoneExpansionState={},this.clearCartError(),await this.render(),this.allowDebug()&&console.log("\u2705 CYO: Component reset completed")}catch(error){console.error("\u274C CYO: Error resetting component:",error)}};handleAddToBag=async()=>{try{this.allowDebug()&&console.log("\u{1F6D2} CYO: Add to Bag triggered");const validSelections=Array.from(this.selections.values()).filter(selection=>selection.variant);if(validSelections.length===0){console.error("\u274C CYO: No variants selected for cart");return}this.allowDebug()&&(console.log(`\u{1F6D2} CYO: Cart transformation mode: ${this.cartTransformation}`),console.log("\u{1F6D2} CYO: Valid selections:",validSelections));const cartItems=this.prepareCartItems(validSelections,this.cartTransformation);if(cartItems.length===0){console.error("\u274C CYO: Failed to prepare cart items"),this.setAddingToBagState(!1),this.showCartError("There was a problem building your CYO product. Please try again.");return}this.allowDebug()&&console.log("\u{1F6D2} CYO: Cart items:",cartItems),this.setAddingToBagState(!0),this.allowDebug()&&console.log("\u{1F6D2} CYO: Submitting cart items:",cartItems),await this.captureBundleAnalytics(validSelections,cartItems);const{addToCartViaStandardAction}=await import("@utilities/theme"),cartResponse=await addToCartViaStandardAction(cartItems,{context:"product"});if(this.setAddingToBagState(!1),cartResponse?.userErrors?.length>0){await this.clearBundleAnalytics(),this.showCartError(cartResponse.userErrors[0].message||"An error occurred while adding to cart"),this.allowDebug()&&console.error("\u{1F6D2} CYO: Cart error:",cartResponse);return}this.allowDebug()&&console.log("\u{1F6D2} CYO: Cart response:",cartResponse),this.clearCartError(),this.allowDebug()&&console.log("\u{1F6D2} CYO: Successfully added to cart",{cartItems,cartTransformation:this.cartTransformation}),this.resetComponent()}catch(error){console.error("\u274C CYO: Error handling Add to Bag:",error),this.setAddingToBagState(!1),await this.clearBundleAnalytics(),this.showCartError("There was a problem adding your CYO product to the bag. Please try again.")}};captureBundleAnalytics=async(validSelections,cartItems)=>{try{if(this.cartTransformation!=="merge")return;const{captureBundleAdd}=await import("@utilities/bundle-analytics"),components=[];for(const selection of validSelections){const variant=selection?.variant,variantId=normalizeVariantId(variant?.id);if(!variantId)continue;const product=selection.product||{};components.push({variantId,price:variant.price||0,quantity:1,variantTitle:variant.title||"",product:{id:product.id??null,title:product.title||"",vendor:product.vendor||"",type:product.type||""}})}const bundleProduct=this.config.bundle_product||{};captureBundleAdd({bundleId:cartItems?.[0]?.properties?._bundled_id||null,components,parent:{variantId:normalizeVariantId(bundleProduct.default_variant_id),variantTitle:"",product:{id:bundleProduct.id??null,title:bundleProduct.title||"",vendor:bundleProduct.vendor||"",type:bundleProduct.type||""}}})}
289catch(error){console.warn("\u26A0\uFE0F CYO: analytics capture failed",error)}};clearBundleAnalytics=async()=>{try{const{clearBundleCapture}=await import("@utilities/bundle-analytics");clearBundleCapture()}catch(error){console.warn("\u26A0\uFE0F CYO: analytics clear failed",error)}};debouncedUpdateMediaGallery=(delay=this.mediaUpdateDelay)=>{this.debounceManager.debounce("mediaUpdate",()=>{this.updateMediaGallery()},delay),this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Media update debounced (${delay}ms)`)};updateMediaGallery=async()=>{try{const productMediaComponent=this.productOverview?.querySelector("product-media");if(!productMediaComponent){this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No product-media component found for media update");return}let mediaUrl=null;if(this.currentStepIndex===0){const currentStep=this.getCurrentStep(),selection=this.getSelectionForStep(currentStep);selection&&selection.variant&&selection.variant.media_url&&(mediaUrl=selection.variant.media_url,this.currentStep1MediaUrl=mediaUrl,this.updateBundleFeaturedMedia(selection.variant),this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Step 1 - Using variant media from: ${mediaUrl}`))}else{const aggregateResult=this.getAggregateMediaUrlWithMetadata();mediaUrl=aggregateResult?.mediaUrl||null,aggregateResult?.aggregateGallery&&this.updateBundleFeaturedMediaFromAggregate(aggregateResult.aggregateGallery),this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Step ${this.currentStepIndex+1} - Using aggregate media from: ${mediaUrl||"none found"}`)}if(mediaUrl)this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Updating product-media component with URL: ${mediaUrl}`),await productMediaComponent.updateMedia(mediaUrl),this.currentDisplayedMediaUrl=mediaUrl,this.allowDebug()&&console.log("\u2705 CYO: Successfully updated media via product-media component");else{const fallbackUrl=this.currentStep1MediaUrl;fallbackUrl&&fallbackUrl!==this.currentDisplayedMediaUrl?(this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: No aggregate found, falling back to step 1 media: ${fallbackUrl}`),await productMediaComponent.updateMedia(fallbackUrl),this.currentDisplayedMediaUrl=fallbackUrl):this.allowDebug()&&(fallbackUrl===this.currentDisplayedMediaUrl?console.log("\u{1F5BC}\uFE0F CYO: Fallback media already displayed, skipping update"):console.log("\u{1F5BC}\uFE0F CYO: No media URL found and no fallback available"))}}catch(error){console.error("\u274C CYO: Error updating media gallery:",error)}};updateBundleFeaturedMedia=variant=>{try{variant?.featured_media?.id&&(this.currentBundleFeaturedMedia={type:"variant",id:variant.featured_media.id,gid:`gid://shopify/MediaImage/${variant.featured_media.id}`,url:variant.featured_media.src||variant.featured_media.url,alt:variant.featured_media.alt||variant.title||"",source:"step1_variant"},this.allowDebug()&&console.log("\u{1F5BC}\uFE0F CYO: Updated bundle featured media from variant:",this.currentBundleFeaturedMedia))}catch(error){console.error("\u274C CYO: Error updating bundle featured media from variant:",error)}};updateBundleFeaturedMediaFromAggregate=aggregateGallery=>{try{const firstMedia=aggregateGallery.media?.[0]||aggregateGallery.featured_media;firstMedia?.id?(this.currentBundleFeaturedMedia={type:"aggregate",id:firstMedia.id,gid:`gid://shopify/MediaImage/${firstMedia.id}`,url:firstMedia.src||firstMedia.url,alt:firstMedia.alt||`${aggregateGallery.handle} bundle`,source:"aggregate_gallery",aggregateHandle:aggregateGallery.handle},this.allowDebug()&&console.log("\u{1F5BC}\uFE0F CYO: Updated bundle featured media from aggregate:",this.currentBundleFeaturedMedia)):this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No featured media found in aggregate gallery:",aggregateGallery)}catch(error){console.error("\u274C CYO: Error updating bundle featured media from aggregate:",error)}};prepareCartItems=(selections,cartTransformation)=>{try{const bundleId=this.generateBundleId(),featuredMedia=this.determineFeaturedMedia(selections);return this.allowDebug()&&(console.log(`\u{1F6D2} CYO: Generated bundle ID: ${bundleId}`),console.log(`\u{1F6D2} CYO: Featured media: ${featuredMedia}`)),cartTransformation==="expand"?this.prepareExpandItems(selections,bundleId):this.prepareMergeItems(selections,bundleId)}catch(error){return console.error("\u274C CYO: Error preparing cart items:",error),[]}};generateBundleId=()=>{const timestamp=Date.now(),random=Math.floor(Math.random()*1e4);return`cyo_bundle_${timestamp}_${random}`};collectParentProductProperties=()=>{try{const productOverview=document.querySelector("product-overview");if(productOverview&&typeof productOverview.collectLineItemProperties=="function"){const parentProperties=productOverview.collectLineItemProperties();return this.allowDebug()&&console.log("\u{1F6D2} CYO: Collected parent product properties:",parentProperties),parentProperties}return this.allowDebug()&&console.log("\u{1F6D2} CYO: No product-overview component found or collectLineItemProperties method not available"),{}}
289catch(error){return console.error("\u274C CYO: Error collecting parent product properties:",error),{}}};determineFeaturedMedia=selections=>{try{if(this.currentBundleFeaturedMedia?.gid)return this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Using tracked bundle featured media: ${this.currentBundleFeaturedMedia.gid} (${this.currentBundleFeaturedMedia.source})`),this.currentBundleFeaturedMedia.gid;const firstSelection=selections[0];if(firstSelection?.variant?.featured_media?.id){const gid=`gid://shopify/MediaImage/${firstSelection.variant.featured_media.id}`;return this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Using fallback featured media from first selection variant: ${gid}`),gid}else if(firstSelection?.product?.featured_media?.id){const gid=`gid://shopify/MediaImage/${firstSelection.product.featured_media.id}`;return this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Using fallback featured media from first selection product: ${gid}`),gid}return this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: No featured media found for bundle"),null}catch(error){return console.error("\u274C CYO: Error determining featured media:",error),null}};prepareExpandItems=(selections,bundleId)=>{try{if(!this.config.bundle_product?.id)throw new Error("Bundle product ID not found in config");const parentVariantId=normalizeVariantId(this.config.bundle_product?.default_variant_id);if(!parentVariantId)throw new Error("Bundle parent variant ID is invali
289d");const bundleCost=this.price,bundledVariants=selections.map(selection=>{const variantId=normalizeVariantId(selection?.variant?.id);return variantId?{variant_gid:`gid://shopify/ProductVariant/${variantId}`,variant_price:selection.variant.price||0}:null}).filter(Boolean);if(bundledVariants.length===0)throw new Error("No valid bundled variants found for expand transformation");const bundledData={_bundled_id:bundleId,_bundle_parent:`gid://shopify/ProductVariant/${parentVariantId}`,_bundle_title:this.config.bundle_product.title,_bundle_cost:bundleCost,_bundled_variants:bundledVariants,_bundled_featured_media:this.currentBundleFeaturedMedia?this.currentBundleFeaturedMedia:null},parentProperties=this.collectParentProductProperties(),cartItem={id:parentVariantId,quantity:1,properties:{_cyo_bundle:!0,_bundled_id:bundleId,_bundled_type:this.cartTransformation,_bundled_data:JSON.stringify(bundledData),...parentProperties}};return cartItem.properties._add_to_cart_component="cyo-product",this.allowDebug()&&(console.log("\u{1F6D2} CYO: Prepared expand cart item:",cartItem),console.log("\u{1F6D2} CYO: Bundled variants:",bundledVariants),console.log("\u{1F6D2} CYO: Bundle cost:",bundleCost)),[cartItem]}catch(error){return console.error("\u274C CYO: Error preparing expand items:",error),[]}};prepareMergeItems=(selections,bundleId)=>{try{if(!this.config.bundle_product?.id)throw new Error("Bundle product ID not found in config");const parentVariantId=normalizeVariantId(this.config.bundle_product?.default_variant_id);if(!parentVariantId)throw new Error("Bundle parent variant ID is invali
289d");const cartItems=[],parentProperties=this.collectParentProductProperties(),bundleCost=this.price;for(const selection of selections){const selectionVariantId=normalizeVariantId(selection?.variant?.id);if(!selectionVariantId)continue;const bundledData={_bundled_id:bundleId,_bundle_parent:`gid://shopify/ProductVariant/${parentVariantId}`,_bundle_title:this.config.bundle_product.title,_bundle_cost:bundleCost,_bundled_component_price:selection.variant.price||0,_bundled_featured_media:this.currentBundleFeaturedMedia?this.currentBundleFeaturedMedia:null},cartItem={id:selectionVariantId,quantity:1,properties:{_cyo_bundle:!0,_bundled_id:bundleId,_bundled_type:this.cartTransformation,_bundled_data:JSON.stringify(bundledData),...parentProperties}};cartItem.properties._add_to_cart_component="cyo-product",selection.variant.color&&(cartItem.properties._color_id=selection.variant.color),cartItems.push(cartItem)}if(cartItems.length===0)throw new Error("No valid merge cart items found");return this.allowDebug()&&(console.log("\u{1F6D2} CYO: Prepared merge cart items:",cartItems),console.log("\u{1F6D2} CYO: Bundle cost:",bundleCost)),cartItems}catch(error){return console.error("\u274C CYO: Error preparing merge items:",error),[]}};setActionButtonLoadingState=(selector,isLoading,loadingText,defaultText)=>{try{this.shadowRoot.querySelectorAll(selector).forEach(button=>{const buttonText=button.querySelector(".cyo-step__action-text, .cyo-step__nav-text"),spinner=button.querySelector(".loading-overlay__spinner");button.classList.toggle("loading",isLoading),button.toggleAttribute("disabled",isLoading),button.toggleAttribute("aria-disabled",isLoading),buttonText&&loadingText&&defaultText&&(buttonText.textContent=isLoading?loadingText:defaultText),spinner&&spinner.classList.toggle("hidden",!isLoading)}),this.allowDebug()&&console.log(`\u{1F504} CYO: Set loading state for ${selector}: ${isLoading}`)}catch(error){console.error("\u274C CYO: Error setting button loading state:",error)}};setAddingToBagState=isAdding=>{this.setActionButtonLoadingState(".cyo-step__action--add-to-bag",isAdding,"Adding to Bag...","Add to Bag")};showCartError=errorMessage=>{try{const errorContainer=this.shadowRoot.querySelector(".cyo-cart-error-container");if(!errorContainer){this.allowDebug()&&console.warn("\u26A0\uFE0F CYO: Error container not found");return}errorContainer.innerHTML=` 290 <div class="cyo-cart-error" role="alert" aria-live="assertive"> 291 <span class="visually-hidden">Error: </span> 292 <p class="cyo-cart-error__message">${errorMessage}</p> 293 </div> 294 `,errorContainer.style.display="block",this.announceToScreenReader(`Error: ${errorMessage}`,"assertive");const errorElement=errorContainer.querySelector(".cyo-cart-error");errorElement&&this.keyboardNavigation&&(errorElement.tabIndex=-1,errorElement.focus()),errorContainer.scrollIntoView({behavior:"smooth",block:"nearest"}),this.allowDebug()&&console.log("\u{1F6A8} CYO: Cart error displayed:",errorMessage)}catch(error){console.error("\u274C CYO: Error showing cart error:",error)}};clearCartError=()=>{try{const errorContainer=this.shadowRoot.querySelector(".cyo-cart-error-container");errorContainer&&(errorContainer.innerHTML="",errorContainer.style.display="none",this.allowDebug()&&console.log("\u2705 CYO: Cart error cleared"))}catch(error){console.error("\u274C CYO: Error clearing cart error:",error)}};renderError=message=>{const errorHTML=` 295 <div class="cyo-error"> 296 <h3>Error</h3> 297 <p>${message}</p> 298 </div> 299 `,container=this.shadowRoot.getElementById("cyo-content");if(container){container.replaceChildren();const content=createElementFromHTML(errorHTML);content&&container.appendChild(content)}else{this.#setupShadowDOM();const newContainer=this.shadowRoot.getElementById("cyo-content");if(newContainer){const content=createElementFromHTML(errorHTML);content&&newContainer.appendChild(content)}}};handleStickyATBChange=()=>{const newEnableStickyATB=this.getAttribute("data-enable-sticky-atb")=="true",newEnableStickyATBOn=this.getAttribute("data-enable-sticky-atb-on")||"scroll";(newEnableStickyATB!=this.enableStickyATB||newEnableStickyATBOn!=this.enableStickyATBOn)&&(this.enableStickyATB=newEnableStickyATB,this.enableStickyATBOn=newEnableStickyATBOn,this.toggleStickyATBFunctionality())};toggleStickyATBFunctionality=()=>{this.enableStickyATB?(this.enableStickyATBEvents(),this.handleStickyATC()):this.disableStickyATBEvents()};enableStickyATBEvents=()=>{this.boundHandleStickyATC&&this.boundHandleResize&&(window.addEventListener("scroll",this.boundHandleStickyATC),window.addEventListener("resize",this.boundHandleResize),this.handleStickyATC())};disableStickyATBEvents=()=>{this.boundHandleStickyATC&&this.boundHandleResize&&(window.removeEventListener("scroll",this.boundHandleStickyATC),window.removeEventListener("resize",this.boundHandleResize),this.resetStickyATBStyles())};resetStickyATBStyles=()=>{const actionsElement=this.shadowRoot?.querySelector(".cyo-step__actions");actionsElement&&actionsElement.classList.remove("cyo-step__actions--sticky","cyo-step__actions--sticky-stop")};handleStickyATC=()=>
299{if(!this.enableStickyATB)return;const actionsElement=this.shadowRoot?.querySelector(".cyo-step__actions");if(!actionsElement)return;const mainContent=document.getElementById("main-content");if(!mainContent)return;const mainContentRect=mainContent.getBoundingClientRect(),scrollTop=window.scrollY,totalHeaderHeight=parseInt(getComputedStyle(document.body).getPropertyValue("--header-height"),10)||92,actionsTop=actionsElement.getBoundingClientRect().top+scrollTop;let shouldBeSticky=!1;if(this.enableStickyATBOn==="render"?shouldBeSticky=!0:this.enableStickyATBOn==="scroll"&&(shouldBeSticky=scrollTop>actionsTop-totalHeaderHeight),!shouldBeSticky){actionsElement.classList.remove("cyo-step__actions--sticky","cyo-step__actions--sticky-stop");return}const mainContentBottom=mainContentRect.bottom,viewportHeight=window.innerHeight;mainContentBottom<=viewportHeight?(actionsElement.classList.add("cyo-step__actions--sticky-stop"),actionsElement.classList.remove("cyo-step__actions--sticky")):(actionsElement.classList.add("cyo-step__actions--sticky"),actionsElement.classList.remove("cyo-step__actions--sticky-stop"))};handleResize=()=>{this.handleStickyATC()};findAggregateMediaMatchForVariants=selectedVariants=>{try{if(!Array.isArray(selectedVariants)||selectedVariants.length<2)return null;const selectedSkus=new Set(selectedVariants.map(variant=>variant?.sku).filter(Boolean));if(!selectedSkus.size||!this.config.aggregate_media_galleries)return null;for(const gallery of Object.values(this.config.aggregate_media_galleries)){if(!gallery.media_json_url||!gallery.represented_products_count||gallery.represented_products_count!==selectedVariants.length)continue;if(Array.from(selectedSkus).every(sku=>gallery.represented_skus&&gallery.represented_skus.includes(sku)))return gallery}return null}catch(error){return console.error("\u274C CYO: Error matching aggregate media gallery:",error),null}};getAggregateMediaUrlWithMetadata=()=>{try{const selectedVariants=[],selectedProductIds=new Set,selectedSkus=new Set;for(let stepIndex=0;stepIndex<=this.currentStepIndex;stepIndex++){const step=this.config.steps[stepIndex];if(step){const selection=this.getSelectionForStep(step);selection&&selection.variant&&selection.variant.sku&&(selectedVariants.push(selection.variant),selectedProductIds.add(selection.product.id.toString()),selectedSkus.add(selection.variant.sku))}}if(selectedVariants.length<2)return this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Need at least 2 selections for aggregate media, found ${selectedVariants.length}`),null;this.allowDebug()&&(console.log(`\u{1F5BC}\uFE0F CYO: Looking for aggregate media with ${selectedProductIds.size} product IDs and ${selectedSkus.size} SKUs`),console.log(`\u{1F5BC}\uFE0F CYO: Selected product IDs: [${Array.from(selectedProductIds).join(", ")}]`),console.log(`\u{1F5BC}\uFE0F CYO: Selected SKUs: [${Array.from(selectedSkus).join(", ")}]`));const matchedAggregateGallery=this.findAggregateMediaMatchForVariants(selectedVariants);return matchedAggregateGallery?(this.allowDebug()&&console.log(`\u{1F5BC}\uFE0F CYO: Found matching aggregate media gallery: ${matchedAggregateGallery.id||matchedAggregateGallery.handle||"unknown"}`,matchedAggregateGallery),{mediaUrl:matchedAggregateGallery.media_json_url,aggregateGallery:matchedAggregateGallery}):(this.allowDebug()&&(console.log("\u{1F5BC}\uFE0F CYO: No aggregate media gallery found matching the selection criteria"),this.config.aggregate_media_galleries&&console.log(`\u{1F5BC}\uFE0F CYO: Searched through ${Object.keys(this.config.aggregate_media_galleries).length} galleries`)),null)}catch(error){return console.error("\u274C CYO: Error getting aggregate media URL with metadata:",error),null}}}customElements.define("cyo-product",CYOProduct)} 300//# sourceMappingURL=/cdn/shop/t/1833/assets/cyo-product.js.map?v=19570976109369550701790511950
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.