1import { 2 init_select_box_v2 3} from "./chunk-R4YB6JIA.js"; 4import { 5 AVAILABLE_KLARNA_COUNTRIES, 6 CheckoutCriticalError, 7 CheckoutExistingOrders, 8 CheckoutSubmit, 9 ERROR_CODES, 10 ErrorTypes, 11 PaypalStates, 12 addressToString, 13 backfillAddressesId, 14 buildComputed, 15 collectLeads, 16 create, 17 decodeVirtualInstallmentId, 18 displayAndLogCriticalError, 19 encodeVirtualInstallmentId, 20 fieldsForCountry, 21 hasPhysicalProducts, 22 initializeUtilities, 23 isSavedAddress, 24 makeCurrentPageFetcher, 25 numberOfStepsInCheckout, 26 parseAddressByFields, 27 resolveInitialPaymentType, 28 scrollToFirstVisibleError, 29 setupOrderSummaries 30} from "./chunk-SYANC6RH.js"; 31import "./chunk-W3RKY5WP.js"; 32import { 33 CFFetch, 34 CFFetcherError, 35 CFFetcherErrorTypes, 36 Fetcher, 37 MANUALLY_ABORTED, 38 init_fetcher, 39 isBackendError, 40 isFetcherError, 41 isResponseError 42} from "./chunk-YSVSPNWW.js"; 43import "./chunk-372FPXG6.js"; 44import { 45 atom, 46 batched, 47 computed, 48 deepEqual, 49 formatNumberToCurrency, 50 init_general, 51 init_nanostores, 52 isElementVisibleOnViewport, 53 map, 54 onMount 55} from "./chunk-BY72GGKB.js"; 56import { 57 addError, 58 resetInputErrors 59} from "./chunk-4AIF3XZW.js"; 60import { 61 init_radio_v1 62} from "./chunk-TLMSI2UF.js"; 63import { 64 init_checkbox_v1, 65 init_input_v1 66} from "./chunk-FQR6BHZQ.js"; 67import { 68 IntlTel_initPhoneInput, 69 init_cf_utils, 70 uuidv4 71} from "./chunk-KIZY5IRN.js"; 72import { 73 init_modal_v1 74} from "./chunk-5NUE6T5P.js"; 75import { 76 CF2Component, 77 init_runtime, 78 registerComponent 79} from "./chunk-NQUHJ6NR.js"; 80import { 81 __privateAdd, 82 __privateGet, 83 __privateMethod, 84 __privateSet, 85 __publicField, 86 init_define_process 87} from "./chunk-RFSPGZ3L.js"; 88
89// projects/lib/packages/yggdrasil-blueprints/__generated__/packs/rebilly-checkout.ts 90init_define_process(); 91
92// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-saved-multiple-payments-preview-v1.ts 93init_define_process(); 94init_runtime(); 95var CheckoutSavedMultiplePaymentsPreviewV1 = class extends CF2Component { 96 constructor(el, runtimeSel) { 97 super(el, runtimeSel); 98 } 99 mount() { 100 Checkout.computed.paymentMethod.subscribe((payment_method) => { 101 this.current_payment_method = payment_method || { type: "new-payment" }; 102 this.render(); 103 }); 104 } 105 remove() { 106 this.element.innerHTML = ""; 107 } 108 render(initializeChildrenInstances = false) { 109 const is_server = true; 110 const current_payment_method = this.current_payment_method ?? null; 111 const checkoutSavedMultiplePaymentsTexts = this.checkoutSavedMultiplePaymentsTexts ?? null; 112 let html = ""; 113 { 114 if (current_payment_method?.type == "new-payment") { 115 html += `<div class="elSelectText">${checkoutSavedMultiplePaymentsTexts?.addNewPaymentMethod}</div>`; 116 } else if (current_payment_method?.type == "payment-card") { 117 html += `<div class="elSelectText"><i class="fab fa-cc-${current_payment_method?.icon}"></i><span class="elSelectTextMaskedNumber"> ${current_payment_method?.details}</span></div>`; 118 } else if (current_payment_method?.type == "paypal") { 119 html += `<div class="elSelectText"><i class="fab fa-paypal"></i>${current_payment_method?.details}</div>`; 120 } else if (current_payment_method?.type == "Klarna") { 121 html += `<div class="elSelectText"><svg xmlns="http://www.w3.org/2000/svg" width="78" viewBox="-67.935 -25.275 588.77 151.65"><path d="M79.7 0H57.4c0 18.3-8.4 35-23 46l-8.8 6.6 34.2 46.6h28.1L56.4 56.3C71.3 41.5 79.7 21.5 79.7 0zM0 0h22.8v99.2H0zm94.5 0H116v99.2H94.5zm210.1 28.7c-8.2 0-16 2.5-21.2 9.6v-7.7H263v68.6h20.7v-36c0-10.4 7-15.5 15.4-15.5 9 0 14.2 5.4 14.2 15.4v36.2h20.5V55.6c0-16-12.7-26.9-29.2-26.9zM181 30.6V35c-5.8-4-12.8-6.3-20.4-6.3-20 0-36.2 16.2-36.2 36.2 0 20 16.2 36.2 36.2 36.2 7.6 0 14.6-2.3 20.4-6.3v4.4h20.5V30.6zm-18.7 51.9c-10.3 0-18.6-7.9-18.6-17.6 0-9.7 8.3-17.6 18.6-17.6s18.6 7.9 18.6 17.6c0 9.7-8.3 17.6-18.6 17.6zm71-43v-8.9h-21v68.6h21.1v-32c0-10.8 11.7-16.6 19.8-16.6h.2v-20c-8.3 0-16 3.6-20.1 8.9zm164.3-8.9V35c-5.8-4-12.8-6.3-20.4-6.3-20 0-36.2 16.2-36.2 36.2 0 20 16.2 36.2 36.2 36.2 7.6 0 14.6-2.3 20.4-6.3v4.4h20.5V30.6zm-18.7 51.9c-10.3 0-18.6-7.9-18.6-17.6 0-9.7 8.3-17.6 18.6-17.6s18.6 7.9 18.6 17.6c.1 9.7-8.3 17.6-18.6 17.6zM434 32.6c0-1-.7-1.6-1.8-1.6h-1.9v5.2h.9v-1.9h1l.8 1.9h1l-.9-2.1c.6-.3.9-.8.9-1.5zm-1.8.8h-1v-1.6h1c.6 0 .9.3.9.8s-.2.8-.9.8z"></path><path d="M431.9 28.8c-2.7 0-4.9 2.2-4.9 4.9.1 2.7 2.2 4.9 4.9 4.9s4.9-2.2 4.9-4.9-2.2-4.9-4.9-4.9zm0 8.9c-2.2 0-3.9-1.8-3.9-4s1.8-4 3.9-4c2.2 0 3.9 1.8 3.9 4s-1.8 4-3.9 4zm8.1 37.2c-7.1 0-12.9 5.8-12.9 12.9 0 7.1 5.8 12.9 12.9 12.9 7.1 0 12.9-5.8 12.9-12.9 0-7.2-5.8-12.9-12.9-12.9z"></path></svg></div>`; 122 } 123 } 124 this.replaceContent(html); 125 if (initializeChildrenInstances) { 126 const scopeToYggRender = this.element.querySelectorAll("[ygg-render]").length > 0; 127 const options = { scopeToYggRender }; 128 CF2Component.hydrateTree(this.element, options); 129 } 130 } 131}; 132registerComponent("CheckoutSavedMultiplePaymentsPreview/V1", CheckoutSavedMultiplePaymentsPreviewV1); 133window["CheckoutSavedMultiplePaymentsPreviewV1"] = CheckoutSavedMultiplePaymentsPreviewV1; 134
135// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-threeds-frame-v1.ts 136init_define_process(); 137init_runtime(); 138var CheckoutThreedsFrameV1 = class extends CF2Component { 139 constructor(el, runtimeSel) { 140 super(el, runtimeSel); 141 } 142 mount() { 143 Checkout.store.threeds.listen((threeds) => { 144 if (threeds.show) { 145 const approvalUrl = threeds.approvalUrl; 146 const iframe = document.createElement("iframe"); 147 const orderStautsIframe = "/cf_order_status?disable-dispatch=true"; 148 iframe.onload = (evt) => { 149 if (evt.target.src.includes(orderStautsIframe)) { 150 this.element.classList.remove("elHide"); 151 iframe.src = approvalUrl; 152 } 153 }; 154 this.element.innerHTML = ""; 155 this.element.appendChild(iframe); 156 iframe.src = orderStautsIframe; 157 } else { 158 this.element.classList.add("elHide"); 159 this.element.innerHTML = ""; 160 } 161 }); 162 } 163}; 164registerComponent("CheckoutThreedsFrame/V1", CheckoutThreedsFrameV1); 165window["CheckoutThreedsFrameV1"] = CheckoutThreedsFrameV1; 166
167// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-address-form-v1.ts 168init_define_process(); 169init_nanostores(); 170init_input_v1(); 171init_select_box_v2(); 172
173// projects/lib/packages/yggdrasil-blueprints/src/Elements/Utils/address-autocomplete.ts 174init_define_process(); 175init_cf_utils(); 176init_fetcher(); 177var CFAddressAutocomplete = class { 178 constructor(input, options) { 179 __publicField(this, "input"); 180 __publicField(this, "addressForm"); 181 __publicField(this, "options"); 182 __publicField(this, "sessionToken"); 183 __publicField(this, "resultsContainer"); 184 __publicField(this, "debounceTimer"); 185 __publicField(this, "currentIndex", -1); 186 __publicField(this, "predictionsFetcher", null); 187 __publicField(this, "placeDetailsFetcher", null); 188 this.input = input; 189 this.addressForm = input.closest('[data-page-element="CheckoutAddressForm/V1"]'); 190 this.options = { 191 types: ["address"], 192 debounceMs: 400, 193 ...options 194 }; 195 this.sessionToken = uuidv4(); 196 this.createResultsContainer(); 197 this.attachListeners(); 198 } 199 createResultsContainer() { 200 this.resultsContainer = document.createElement("div"); 201 this.resultsContainer.className = "cf-autocomplete-results"; 202 const parentStyle = window.getComputedStyle(this.input.parentElement); 203 if (parentStyle.position === "static") { 204 this.input.parentElement.style.position = "relative"; 205 } 206 this.input.parentElement.appendChild(this.resultsContainer); 207 } 208 attachListeners() { 209 this.input.addEventListener("input", () => this.handleInput()); 210 this.input.addEventListener("keydown", (e) => this.handleKeydown(e)); 211 this.input.addEventListener("blur", () => { 212 clearTimeout(this.debounceTimer); 213 if (this.predictionsFetcher) { 214 this.predictionsFetcher.abort(); 215 } 216 setTimeout(() => this.hideResults(), 300); 217 }); 218 this.input.addEventListener("focus", () => { 219 if (this.resultsContainer.children.length > 0) { 220 this.showResults(); 221 } 222 }); 223 } 224 handleInput() { 225 clearTimeout(this.debounceTimer); 226 const value = this.input.value.trim(); 227 if (value.length < 3) { 228 this.resultsContainer.innerHTML = ""; 229 this.hideResults(); 230 return; 231 } 232 this.debounceTimer = setTimeout(() => { 233 this.fetchPredictions(value); 234 }, this.options.debounceMs); 235 } 236 handleKeydown(e) { 237 const items = this.resultsContainer.children; 238 if (items.length === 0) return; 239 switch (e.key) { 240 case "ArrowDown": 241 e.preventDefault(); 242 this.currentIndex = Math.min(this.currentIndex + 1, items.length - 1); 243 this.updateSelection(); 244 break; 245 case "ArrowUp": 246 e.preventDefault(); 247 this.currentIndex = Math.max(this.currentIndex - 1, -1); 248 this.updateSelection(); 249 break; 250 case "Enter": 251 e.preventDefault(); 252 e.stopPropagation(); 253 if (this.currentIndex >= 0) { 254 ; 255 items[this.currentIndex].click(); 256 } 257 break; 258 case "Escape": 259 this.hideResults(); 260 break; 261 } 262 } 263 updateSelection() { 264 const items = this.resultsContainer.children; 265 Array.from(items).forEach((item, index) => { 266 if (index === this.currentIndex) { 267 item.classList.add("cf-autocomplete-selected"); 268 } else { 269 item.classList.remove("cf-autocomplete-selected"); 270 } 271 }); 272 } 273 async fetchPredictions(input) { 274 if (!this.predictionsFetcher) this.predictionsFetcher = new Fetcher(); 275 const params = new URLSearchParams({ 276 input, 277 types: this.options.types.join(","), 278 session_token: this.sessionToken 279 }); 280 this.predictionsFetcher.fetch( 281 `/user_pages/api/v1/address_autocomplete/predictions?${params}`, 282 { 283 headers: { "Content-Type": "application/json" } 284 }, 285 { retries: 3, shouldCaptureServerError: true, onlyOneInflightRequest: true } 286 ).then((res) => { 287 if (res instanceof Response && res.ok) { 288 return res.json(); 289 } 290 throw new Error("Address autocomplete error"); 291 }).then((data) => { 292 if (data.predictions && data.predictions.length > 0) { 293 this.renderPredictions(data.predictions); 294 } else { 295 this.hideResults(); 296 } 297 }).catch((error) => { 298 if (error === MANUALLY_ABORTED) { 299 return; 300 } 301 console.error("Address autocomplete error:", error); 302 this.hideResults(); 303 }); 304 } 305 async fetchPlaceDetails(placeId) { 306 if (!this.placeDetailsFetcher) this.placeDetailsFetcher = new Fetcher(); 307 const params = new URLSearchParams({ 308 place_id: placeId, 309 session_token: this.sessionToken 310 }); 311 return this.placeDetailsFetcher.fetch( 312 `/user_pages/api/v1/address_autocomplete/place_details?${params}`, 313 { 314 headers: { "Content-Type": "application/json" } 315 }, 316 { retries: 3, shouldCaptureServerError: true, onlyOneInflightRequest: true } 317 ).then((res) => { 318 if (res instanceof Response && res.ok) { 319 return res.json(); 320 } 321 throw new Error("Place details request failed"); 322 }).then((data) => { 323 return data.place_details; 324 }).catch((error) => { 325 if (error === MANUALLY_ABORTED) { 326 return null; 327 } 328 console.error("Place details fetch error:", error); 329 }); 330 } 331 renderPredictions(predictions) { 332 this.resultsContainer.innerHTML = ""; 333 this.currentIndex = -1; 334 predictions.forEach((prediction, index) => { 335 const item = document.createElement("div"); 336 item.className = "cf-autocomplete-item"; 337 item.dataset.placeId = prediction.place_id; 338 if (prediction.structured_formatting) { 339 const mainText = this.highlightMatches( 340 prediction.structured_formatting.main_text, 341 prediction.structured_formatting.main_text_matched_substrings || [] 342 ); 343 const secondaryText = prediction.structured_formatting.secondary_text ? this.highlightMatches( 344 prediction.structured_formatting.secondary_text, 345 prediction.structured_formatting.secondary_text_matched_substrings || [] 346 ) : ""; 347 const mainSpan = document.createElement("span"); 348 mainSpan.className = "cf-autocomplete-main"; 349 mainSpan.innerHTML = mainText; 350 item.appendChild(mainSpan); 351 if (secondaryText) { 352 const secondarySpan = document.createElement("span"); 353 secondarySpan.className = "cf-autocomplete-secondary"; 354 secondarySpan.innerHTML = secondaryText; 355 item.appendChild(secondarySpan); 356 } 357 } else { 358 item.textContent = prediction.description; 359 } 360 item.addEventListener("mouseenter", () => { 361 this.currentIndex = index; 362 this.updateSelection(); 363 }); 364 item.addEventListener("click", () => this.selectPlace(prediction)); 365 this.resultsContainer.appendChild(item); 366 }); 367 this.showResults(); 368 } 369 highlightMatches(text, matches) { 370 if (!matches || matches.length === 0) { 371 return this.escapeHtml(text); 372 } 373 let result = ""; 374 let lastIndex = 0; 375 const sortedMatches = matches.sort((a, b) => a.offset - b.offset);
376 sortedMatches.forEach((match) => { 377 const { offset, length } = match; 378 result += this.escapeHtml(text.substring(lastIndex, offset)); 379 result += `<strong class="cf-autocomplete-highlight">${this.escapeHtml( 380 text.substring(offset, offset + length) 381 )}</strong>`; 382 lastIndex = offset + length; 383 }); 384 result += this.escapeHtml(text.substring(lastIndex)); 385 return result; 386 } 387 escapeHtml(text) { 388 const div = document.createElement("div"); 389 div.textContent = text; 390 return div.innerHTML; 391 } 392 async selectPlace(prediction) { 393 this.addressForm.querySelector('[data-page-element="Spinner/V1"]').setAttribute("data-loader", "true"); 394 const placeDetails = await this.fetchPlaceDetails(prediction.place_id); 395 if (placeDetails) { 396 this.options.onPlaceSelected(placeDetails); 397 this.sessionToken = uuidv4(); 398 this.resultsContainer.innerHTML = ""; 399 this.currentIndex = -1; 400 this.hideResults(); 401 } 402 this.addressForm.querySelector('[data-page-element="Spinner/V1"]').setAttribute("data-loader", "false"); 403 } 404 showResults() { 405 this.resultsContainer.classList.add("cf-autocomplete-visible"); 406 this.resultsContainer.style.width = `${this.input.offsetWidth}px`; 407 } 408 hideResults() { 409 this.resultsContainer.classList.remove("cf-autocomplete-visible"); 410 } 411 destroy() { 412 this.resultsContainer.remove(); 413 this.input.removeEventListener("input", () => this.handleInput()); 414 this.input.removeEventListener("keydown", (e) => this.handleKeydown(e)); 415 } 416}; 417
418// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-address-form-v1.ts 419init_runtime(); 420var CheckoutAddressFormV1 = class extends CF2Component { 421 constructor(el, runtimeSel) { 422 super(el, runtimeSel); 423 } 424 mount() { 425 if (this.useCheckoutStore) { 426 this.store = Checkout.store[this.type]; 427 this.fields = Checkout.store[`${this.type}Fields`]; 428 this.showAllErrors = Checkout.store.showAllErrors[this.type]; 429 this.formErrors = Checkout.computed[`${this.type}Errors`]; 430 } else { 431 this.store = map({}); 432 this.fields = atom([...Checkout.store[`${this.type}Fields`].get()]); 433 this.showAllErrors = atom(false); 434 this.formErrors = computed([this.store, this.showAllErrors], (store, showAllErrors) => { 435 const fields = this.fields.get(); 436 return Checkout.utils.addressErrors(store, showAllErrors, fields); 437 }); 438 const initializeFromSavedContact = () => { 439 const values = this.store.get(); 440 const fields = this.fields.get(); 441 const fieldsValues = parseAddressByFields(values, fields); 442 this.store.set(fieldsValues); 443 const { country, state } = this.store.get(); 444 if (country) { 445 this.setInputValue("country", country); 446 } 447 if (state && this.hasState()) { 448 this.setInputValue("state", state); 449 } 450 }; 451 Checkout.store.state.listen((newState) => { 452 if (newState == Checkout.StoreStates.INITIALIZED) { 453 initializeFromSavedContact(); 454 } 455 }); 456 Checkout.store.checkout.mode.listen((newMode) => { 457 if (newMode === "saved") { 458 initializeFromSavedContact(); 459 } 460 }); 461 this.store.listen((address) => { 462 const fields = this.fields.get(); 463 const addressFields = fieldsForCountry(fields, address.country); 464 this.fields.set(addressFields); 465 }); 466 } 467 this.store.listen((fieldValues) => { 468 this.fields.get().forEach((prop) => { 469 this.setInputValue(prop, fieldValues[prop]); 470 }); 471 }); 472 this.formErrors.subscribe((errors) => { 473 if (!this.disableInputValidationOnBlur) { 474 this.checkErrors(errors); 475 } else { 476 if (this.showAllErrors.get()) this.checkErrors(errors); 477 } 478 }); 479 this.setupAutocomplete(); 480 this.setupInputListeners(); 481 } 482 hasState() { 483 return this.fields.get().includes("state"); 484 } 485 hasPostalCode(fields) { 486 return (fields ?? this.fields.get()).includes("zip"); 487 } 488 checkErrors(errors) { 489 const errorWrapper = this.element.querySelector(".elCheckoutFormErrors"); 490 errorWrapper.classList.add("elHide"); 491 this.fields.get().forEach((prop) => { 492 const input = this.getInputFromName(prop); 493 resetInputErrors(input); 494 }); 495 if (Checkout.utils.hasErrors(errors)) { 496 const fieldErrors = errors.fields; 497 if (fieldErrors) { 498 const errors2 = []; 499 Object.entries(fieldErrors).forEach(([field, error]) => { 500 const { message } = error; 501 errors2.push(message); 502 const input = this.getInputFromName(field); 503 addError(input); 504 }); 505 if (errors2.length) { 506 const listErrors = `<ul>${errors2.map((err) => `<li>${err}</li>`).join("")}</ul>`; 507 errorWrapper.innerHTML = listErrors; 508 errorWrapper.classList.remove("elHide"); 509 } else { 510 errorWrapper.classList.add("elHide"); 511 } 512 } 513 } 514 } 515 getInputFromName(name) { 516 return this.element.querySelector(`[name='${this.type}_${name}']`); 517 } 518 getWrapperElement(prop) { 519 const input = this.getInputFromName(prop); 520 return input.closest(".elFormItemWrapper"); 521 } 522 setInputValue(fieldName, value) { 523 const input = this.getInputFromName(fieldName); 524 value = value?.trim(); 525 if (value) { 526 if (fieldName === "country") { 527 !this.populatedCountries && this.populateCountries(); 528 this.populatedCountries = true; 529 if (this.hasState()) this.populateStates(); 530 } 531 input.value = value; 532 $(input).parents(".elFormItemWrapper").addClass("hasValue"); 533 } else { 534 input.value = ""; 535 $(input).parents(".elFormItemWrapper").removeClass("hasValue"); 536 } 537 } 538 setupAutocomplete() { 539 const addressInput = this.getInputFromName("address"); 540 if (!addressInput) return; 541 const autocomplete = new CFAddressAutocomplete(addressInput, { 542 types: ["address"], 543 onPlaceSelected: (place) => { 544 const valueByComponentType = place.address_components.reduce((acc, component) => { 545 const type = component.types; 546 if (type.includes("locality")) { 547 acc["locality"] = component.long_name; 548 } else if (type.includes("administrative_area_level_2")) { 549 acc["administrative_area_level_2"] = component.long_name; 550 } else if (type.includes("administrative_area_level_1")) { 551 acc["administrative_area_level_1"] = component.short_name; 552 } else if (type.includes("country")) { 553 acc["country"] = component.short_name; 554 } else if (type.includes("postal_code")) { 555 acc["postal_code"] = component.long_name; 556 } 557 return acc; 558 }, {}); 559 const address = { address: place.name }; 560 address.country = valueByComponentType["country"]; 561 const stateMap = this.stateMap(address.country); 562 const stateValue = valueByComponentType["administrative_area_level_1"]; 563 address.state = stateMap.mapByCode[stateValue] ? stateValue : stateMap.mapByGoogleName[stateValue]; 564 if (!address.state) { 565 address.state = this.firstStateFromCountry(address.country); 566 } 567 address.city = valueByComponentType["locality"] || valueByComponentType["administrative_area_level_2"]; 568 address.zip = valueByComponentType["postal_code"]; 569 this.store.set(address); 570 this.validateFormFields(); 571 } 572 }); 573 } 574 updateFields(country) { 575 const addressFields = fieldsForCountry(this.fields.get(), country); 576 this.fields.set(addressFields); 577 } 578 setupInputListeners() {
579 this.fields.get().forEach((prop) => { 580 const input = this.getInputFromName(prop); 581 if (input !== null) { 582 if (prop === "state" || prop === "country") { 583 input.addEventListener("input", () => { 584 if (prop === "country") { 585 const firstStateValue = this.firstStateFromCountry(input.value); 586 if (this.hasState()) { 587 this.store.set({ 588 ...this.store.get(), 589 country: input.value, 590 state: firstStateValue 591 }); 592 } else { 593 this.store.set({ 594 ...this.hasPostalCode() ? this.store.get() : {}, 595 country: input.value 596 }); 597 } 598 } else { 599 const value = input.value; 600 setTimeout(() => { 601 this.store.setKey(prop, value); 602 }); 603 } 604 }); 605 } else { 606 input.addEventListener("blur", () => { 607 this.store.setKey(prop, input.value); 608 if (!this.disableInputValidationOnBlur) { 609 this.checkErrors(this.formErrors.get()); 610 } else { 611 if (this.showAllErrors.get()) this.checkErrors(this.formErrors.get()); 612 } 613 }); 614 } 615 } 616 }); 617 this.fields.listen((fields) => { 618 this.updatePostalCode(fields); 619 }); 620 this.updatePostalCode(); 621 } 622 updatePostalCode(fields) { 623 const hasPostalCode = this.hasPostalCode(fields); 624 const zipInputWrapper = this.getWrapperElement("zip"); 625 const countryWrapper = this.getWrapperElement("country"); 626 if (this.locale === "ja") { 627 if (hasPostalCode) { 628 zipInputWrapper.classList.remove("elHide"); 629 countryWrapper.classList.add("inputNoBorderTop"); 630 countryWrapper.classList.remove("elInputOuterTopLeftCorner"); 631 countryWrapper.classList.remove("elInputOuterTopRightCorner"); 632 } else { 633 zipInputWrapper.classList.add("elHide"); 634 countryWrapper.classList.remove("inputNoBorderTop"); 635 countryWrapper.classList.add("elInputOuterTopLeftCorner"); 636 countryWrapper.classList.add("elInputOuterTopRightCorner"); 637 } 638 } else { 639 if (hasPostalCode) { 640 zipInputWrapper.classList.remove("elHide"); 641 countryWrapper.classList.remove("elInputOuterBottomLeftCorner"); 642 countryWrapper.classList.remove("elInputOuterBottomRightCorner"); 643 } else { 644 zipInputWrapper.classList.add("elHide"); 645 countryWrapper.classList.add("elInputOuterBottomLeftCorner"); 646 countryWrapper.classList.add("elInputOuterBottomRightCorner"); 647 } 648 } 649 } 650 validateFormFields() { 651 const address = this.store.get(); 652 const errors = Checkout.utils.addressErrors(address, true, this.fields.get()); 653 if (Checkout.utils.hasErrors(errors)) { 654 this.showAllErrors.set(true); 655 return false; 656 } else { 657 return true; 658 } 659 } 660 populateCountries() { 661 const topMapping = ["US", "CA", "GB", "IE", "AU", "NZ"]; 662 const topHash = topMapping.reduce((acc, val) => { 663 acc[val] = true; 664 return acc; 665 }, {}); 666 const topOptions = topMapping.map((iso2) => ({ iso2 })); 667 const remainingOptions = []; 668 Checkout.allCountries.forEach((item) => { 669 if (topHash[item.iso2]) { 670 const option = topOptions.find((option2) => option2.iso2 == item.iso2); 671 option.name = item.name; 672 } else { 673 remainingOptions.push(item); 674 } 675 }); 676 let html = ""; 677 topOptions.forEach((item) => html += `<option value="${item.iso2}" > ${item.name} </option>`); 678 remainingOptions.forEach((item) => html += `<option value="${item.iso2}" > ${item.name} </option>`); 679 const countrySelect = this.getInputFromName("country"); 680 countrySelect.innerHTML = html; 681 } 682 populateStates() { 683 const countryValue = this.store.get().country; 684 const statesSelect = this.getInputFromName("state"); 685 let html = ""; 686 const countryData = Checkout.allCountries.find((country) => countryValue == country.iso2); 687 countryData.regions.forEach((region, index) => { 688 html += `<option value="${region.state_code}" > ${region.name} </option>`; 689 }); 690 const firstStateValue = countryData.regions?.[0]?.state_code; 691 if (firstStateValue) { 692 $(statesSelect).parents(".elFormItemWrapper").show(); 693 statesSelect.innerHTML = html; 694 } else { 695 $(statesSelect).parents(".elFormItemWrapper").hide(); 696 statesSelect.innerHTML = ""; 697 } 698 } 699 stateMap(countryValue) { 700 const stateMap = { 701 mapByCode: {}, 702 mapByGoogleName: {} 703 }; 704 const countryData = Checkout.allCountries.find((country) => countryValue == country.iso2); 705 countryData.regions.forEach((region, index) => { 706 stateMap.mapByCode[region.state_code] = true; 707 stateMap.mapByGoogleName[region.google_name] = region.state_code; 708 }); 709 return stateMap; 710 } 711 firstStateFromCountry(countryValue) { 712 const countryData = Checkout.allCountries.find((country) => country.iso2 == countryValue); 713 return countryData.regions?.[0]?.state_code; 714 } 715}; 716registerComponent("CheckoutAddressForm/V1", CheckoutAddressFormV1); 717window["CheckoutAddressFormV1"] = CheckoutAddressFormV1; 718
719// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-billing-address-v1.ts 720init_define_process(); 721init_checkbox_v1(); 722init_runtime(); 723var CheckoutBillingAddressV1 = class extends CF2Component { 724 constructor(el, runtimeSel) { 725 super(el, runtimeSel); 726 } 727 mount() { 728 this.type = "billing"; 729 this.getCheckbox().addEventListener("change", (evt) => { 730 evt.stopPropagation(); 731 const value = !!evt.target.checked; 732 Checkout.store.billingSameAsShipping.set(value); 733 if (!value) { 734 const shippingData = Checkout.store.shipping.get(); 735 const newBillingData = parseAddressByFields(shippingData, this.fields, false); 736 Checkout.store.billing.set(newBillingData); 737 } 738 }); 739 Checkout.store.billingSameAsShipping.listen((value) => { 740 this.getCheckbox().checked = value; 741 if (value) { 742 this.hideForm(); 743 } else { 744 this.showForm(); 745 } 746 }); 747 nanostores.computed( 748 [Checkout.computed.hasPhysicalProducts, Checkout.store.billingSameAsShipping], 749 (hasPhysicalProducts2, billingSameAsShipping) => ({ hasPhysicalProducts: hasPhysicalProducts2, billingSameAsShipping }) 750 ).subscribe(({ hasPhysicalProducts: hasPhysicalProducts2, billingSameAsShipping }) => { 751 if (hasPhysicalProducts2) { 752 this.showBillingSameAsShipping(); 753 if (billingSameAsShipping) { 754 this.hideForm(); 755 } else { 756 this.showForm(); 757 } 758 } else { 759 this.hideBillingSameAsShipping(); 760 this.showForm(); 761 } 762 }); 763 nanostores.computed([Checkout.store.payment.type], (paymentType) => paymentType != "apple-pay").subscribe((display) => { 764 if (display) { 765 this.show(); 766 } else { 767 this.hide(); 768 } 769 }); 770 } 771 show() { 772 this.element.classList.remove("elHide"); 773 } 774 hide() { 775 this.element.classList.add("elHide"); 776 } 777 showForm() { 778 this.element.querySelector(".elBillingForm").classList.remove("elHide"); 779 } 780 hideForm() { 781 this.element.querySelector(".elBillingForm").classList.add("elHide"); 782 } 783 getCheckboxContainer() { 784 return this.element.querySelector(".elShippingSameAsBillingContainer"); 785 } 786 getCheckbox() { 787 return this.getCheckboxContainer().querySelector("input"); 788 } 789 showBillingSameAsShipping() { 790 this.getCheckboxContainer().classList.remove("elHide"); 791 } 792 hideBillingSameAsShipping() { 793 this.getCheckboxContainer().classList.add("elHide"); 794 } 795}; 796registerComponent("CheckoutBillingAddress/V1", CheckoutBillingAddressV1); 797window["CheckoutBillingAddressV1"] = CheckoutBillingAddressV1; 798
799// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-shipping-address-v1.ts 800init_define_process(); 801init_runtime(); 802var CheckoutShippingAddressV1 = class extends CF2Component { 803 constructor(el, runtimeSel) { 804 super(el, runtimeSel); 805 } 806 mount() { 807 this.contentEl = this.element.querySelector("div"); 808 const shouldDisplay = nanostores.computed([ 809 Checkout.computed.isNewDigitalWalletPayment, 810 Checkout.computed.hasPhysicalProducts 811 ], (isNewDigitalWalletPayment, hasPhysicalProducts2) => { 812 return hasPhysicalProducts2 && !isNewDigitalWalletPayment; 813 }); 814 shouldDisplay.subscribe((display) => { 815 if (display) { 816 this.show(); 817 } else { 818 this.hide(); 819 } 820 }); 821 } 822 show() { 823 this.element.classList.remove("elHide"); 824 } 825 hide() { 826 this.element.classList.add("elHide"); 827 } 828}; 829registerComponent("CheckoutShippingAddress/V1", CheckoutShippingAddressV1); 830window["CheckoutShippingAddressV1"] = CheckoutShippingAddressV1; 831
832// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-login-v2.ts 833init_define_process(); 834init_nanostores(); 835init_input_v1(); 836init_cf_utils(); 837
838// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-auth.ts 839init_define_process(); 840init_nanostores(); 841var PhoneVerificationOtpStates = /* @__PURE__ */ new Set([ 842 13 /* RequestingAnotherPhoneVerificationCode */, 843 16 /* SubmittingPhoneVerificationCode */, 844 17 /* PhoneVerificationSubmitError */, 845 14 /* SentPhoneVerificationOtp */, 846 19 /* FailedPhoneVerification */ 847]); 848var PhoneVerificationRequestStates = /* @__PURE__ */ new Set([ 849 11 /* SuggestingPhoneVerification */, 850 12 /* RequestingPhoneVerification */, 851 15 /* FailedRequestPhoneVerification */ 852]); 853var PhoneVerificationDialogStates = new Set( 854 [18 /* PhoneVerificationSucceeded */].concat([...PhoneVerificationRequestStates]).concat([...PhoneVerificationOtpStates]) 855); 856var AuthDialogStates = /* @__PURE__ */ new Set([ 857 4 /* AwaitingOtp */, 858 5 /* FetchingOtpValidation */, 859 6 /* InvalidOtp */, 860 8 /* FetchingResendOtp */, 861 9 /* FailedResendOtp */, 862 // AuthMode.TryingAutoPhoneVerification, 863 ...PhoneVerificationDialogStates 864]); 865var AuthFlow = { 866 ["*"]: { 867 submitOtp: 5 /* FetchingOtpValidation */, 868 resendOtp: 8 /* FetchingResendOtp */, 869 changeOtpSource: 8 /* FetchingResendOtp */, 870 continueAsGuest: 21 /* ContinuingAsGuest */ 871 }, 872 [0 /* Initializing */]: { 873 alreadySaved: 1 /* AlreadySavedMode */, 874 noUser: 2 /* AwaitingEmail */ 875 }, 876 [2 /* AwaitingEmail */]: { 877 gotEmail: 3 /* FetchingEmailCheck */ 878 }, 879 [3 /* FetchingEmailCheck */]: { 880 sentOtp: 4 /* AwaitingOtp */, 881 unrecognized: 21 /* ContinuingAsGuest */ 882 }, 883 [4 /* AwaitingOtp */]: { 884 submitOtp: 5 /* FetchingOtpValidation */, 885 resendOtp: 8 /* FetchingResendOtp */ 886 }, 887 [5 /* FetchingOtpValidation */]: { 888 validOtp: 7 /* ValidOtp */, 889 invalidOtp: 6 /* InvalidOtp */ 890 }, 891 [7 /* ValidOtp */]: { 892 continueAsSaved: 20 /* ContinuingAsSaved */, 893 suggestPhoneVerification: 11 /* SuggestingPhoneVerification */ 894 }, 895 [6 /* InvalidOtp */]: { 896 resendOtp: 8 /* FetchingResendOtp */ 897 }, 898 [8 /* FetchingResendOtp */]: { 899 sentOtp: 4 /* AwaitingOtp */, 900 resendFailed: 9 /* FailedResendOtp */ 901 }, 902 [9 /* FailedResendOtp */]: {}, 903 // phone verification flow 904 [11 /* SuggestingPhoneVerification */]: { 905 skipPhoneVerification: 20 /* ContinuingAsSaved */, 906 requestPhoneVerification: 12 /* RequestingPhoneVerification */ 907 }, 908 [12 /* RequestingPhoneVerification */]: { 909 skipPhoneVerification: 20 /* ContinuingAsSaved */, 910 sentPhoneVerificationOtp: 14 /* SentPhoneVerificationOtp */, 911 failStartPhoneVerification: 15 /* FailedRequestPhoneVerification */, 912 requestPhoneVerification: 12 /* RequestingPhoneVerification */ 913 }, 914 [15 /* FailedRequestPhoneVerification */]: { 915 skipPhoneVerification: 20 /* ContinuingAsSaved */, 916 requestPhoneVerification: 12 /* RequestingPhoneVerification */ 917 }, 918 [13 /* RequestingAnotherPhoneVerificationCode */]: { 919 skipPhoneVerification: 20 /* ContinuingAsSaved */, 920 sentPhoneVerificationOtp: 14 /* SentPhoneVerificationOtp */, 921 failStartPhoneVerification: 15 /* FailedRequestPhoneVerification */, 922 requestPhoneVerification: 13 /* RequestingAnotherPhoneVerificationCode */ 923 }, 924 [14 /* SentPhoneVerificationOtp */]: { 925 skipPhoneVerification: 20 /* ContinuingAsSaved */, 926 requestPhoneVerification: 13 /* RequestingAnotherPhoneVerificationCode */, 927 submitPhoneVerificationCode: 16 /* SubmittingPhoneVerificationCode */ 928 }, 929 [16 /* SubmittingPhoneVerificationCode */]: { 930 skipPhoneVerification: 20 /* ContinuingAsSaved */, 931 verificationSucceeded: 18 /* PhoneVerificationSucceeded */, 932 verificationFailed: 19 /* FailedPhoneVerification */, 933 verificationSubmitError: 17 /* PhoneVerificationSubmitError */ 934 }, 935 [19 /* FailedPhoneVerification */]: { 936 skipPhoneVerification: 20 /* ContinuingAsSaved */, 937 submitPhoneVerificationCode: 16 /* SubmittingPhoneVerificationCode */, 938 requestPhoneVerification: 13 /* RequestingAnotherPhoneVerificationCode */ 939 }, 940 [18 /* PhoneVerificationSucceeded */]: { 941 continueAsSaved: 20 /* ContinuingAsSaved */ 942 } 943}; 944var CheckoutAuth = class { 945 static initializeOneClickCheckoutFlow() { 946 globalThis.Checkout.auth = this; 947 this.store = globalThis.Checkout.store.auth = { 948 flow: map({ 949 from: void 0, 950 event: void 0, 951 to: 0 /* Initializing */ 952 }), 953 otpRequestFailure: map({ 954 time: void 0, 955 retry_in: 0, 956 error: void 0 957 }), 958 otpLoginSource: atom(void 0), 959 phoneVerificationRequest: map({ 960 time: void 0, 961 count: 0, 962 rejections: 0, 963 error: void 0 964 }), 965 phoneVerificationOtp: map({ 966 time: void 0, 967 count: 0, 968 rejections: 0, 969 error: void 0 970 }) 971 }; 972 this.store.mode = computed(this.store.flow, (change) => change.to); 973 const requireLogin = computed([this.store.mode], (mode) => AuthDialogStates.has(mode)), otpLoginOptions = computed(globalThis.Checkout.store.contact_pending_auth, (partialContact) => { 974 const options = []; 975 if (partialContact) {
976 if (partialContact.is_phone_verified === true) { 977 options.push("phone_number"); 978 } 979 if (partialContact.email) { 980 options.push("email"); 981 } 982 } 983 return options; 984 }), suggestingPhoneVerification = computed([this.store.mode], (mode) => PhoneVerificationDialogStates.has(mode)), showingPhoneVerificationRequest = computed([this.store.mode], (mode) => PhoneVerificationRequestStates.has(mode)), showingPhoneOtp = computed([this.store.mode], (mode) => PhoneVerificationOtpStates.has(mode)), validGuestEmail = computed( 985 [ 986 globalThis.Checkout.store.checkout.mode, 987 globalThis.Checkout.store.contact, 988 globalThis.Checkout.computed.contactErrors, 989 globalThis.Checkout.computed.hideContactInformationForm 990 ], 991 (mode, { email }, errors, hideContactInformationForm) => mode === "guest" && !errors?.fields?.email && !hideContactInformationForm && email 992 ), submittingPhoneVerification = computed( 993 globalThis.Checkout.store.auth.mode, 994 (mode) => mode === 16 /* SubmittingPhoneVerificationCode */ 995 ), RequestingPhoneVerification = computed( 996 globalThis.Checkout.store.auth.mode, 997 (mode) => mode === 12 /* RequestingPhoneVerification */ 998 ), phoneVerificationMessages = computed( 999 globalThis.Checkout.store.auth.mode, 1000 (mode) => mode === 12 /* RequestingPhoneVerification */ ? "Requesting a new code..." : ( 1001 // // TODO 1002 // mode === AuthMode.SentAnotherPhoneVerificationOtp ? 1003 // "Resent code. Please check your messages." : 1004 "" 1005 ) 1006 ), phoneVerificationRequestErrorMsg = computed(globalThis.Checkout.store.auth.mode, (mode) => { 1007 if ([15 /* FailedRequestPhoneVerification */].includes(mode)) { 1008 const { numberTaken, errors } = globalThis.Checkout.store.auth.flow.get().data; 1009 if (numberTaken) { 1010 return "Sorry, that phone number is already taken"; 1011 } 1012 if (errors) { 1013 return `Error: ${errors}`; 1014 } 1015 return "Unknown error. Please check your connection and try again."; 1016 } 1017 return ""; 1018 }), phoneVerificationErrorMsg = computed(globalThis.Checkout.store.auth.mode, (mode) => { 1019 if (mode === 19 /* FailedPhoneVerification */) { 1020 return "Invalid code. Please check and try again."; 1021 } 1022 if ([17 /* PhoneVerificationSubmitError */].includes(mode)) { 1023 return "Unknown error. Please check your connection and try again."; 1024 } 1025 return ""; 1026 }), submittingOtp = computed(globalThis.Checkout.store.auth.mode, (mode) => mode === 5 /* FetchingOtpValidation */), requestingAnotherOtp = computed(globalThis.Checkout.store.auth.mode, (mode) => { 1027 return mode === 8 /* FetchingResendOtp */; 1028 }), resentOtp = atom(false), otpRequestError = computed(globalThis.Checkout.store.auth.otpRequestFailure, ({ error }) => error); 1029 otpLoginOptions.subscribe((options) => { 1030 if (options && this.store.otpLoginSource.get() === void 0) { 1031 this.store.otpLoginSource.set(options[0]); 1032 } 1033 }); 1034 const retrySeconds = atom(0); 1035 onMount(retrySeconds, () => { 1036 let ticking; 1037 const unsub = this.store.otpRequestFailure.subscribe(({ time, retry_in }) => { 1038 stop(); 1039 if (!retry_in) return; 1040 const t = /* @__PURE__ */ new Date(); 1041 t.setSeconds(t.getSeconds() + retry_in); 1042 const update = () => { 1043 const now = Date.now(); 1044 let diff = t.getTime() - now; 1045 if (diff <= 0) { 1046 diff = 0; 1047 stop(); 1048 } 1049 retrySeconds.set(Math.ceil(diff / 1e3)); 1050 }; 1051 update(); 1052 ticking = setInterval(update, 1e3); 1053 }); 1054 return () => { 1055 unsub(); 1056 stop(); 1057 }; 1058 function stop() { 1059 if (ticking) { 1060 clearInterval(ticking); 1061 ticking = void 0; 1062 } 1063 } 1064 }); 1065 this.computed = globalThis.Checkout.computed.auth = { 1066 validGuestEmail, 1067 requireLogin, 1068 otpLoginOptions, 1069 showingPhoneOtp, 1070 submittingOtp, 1071 requestingAnotherOtp, 1072 retrySeconds, 1073 resentOtp, 1074 otpRequestError, 1075 suggestingPhoneVerification, 1076 showingPhoneVerificationRequest, 1077 submittingPhoneVerification, 1078 RequestingPhoneVerification, 1079 phoneVerificationRequestErrorMsg, 1080 phoneVerificationMessages, 1081 phoneVerificationErrorMsg 1082 }; 1083 globalThis.Checkout.store.checkout.mode.listen((mode) => { 1084 if (mode === "guest") { 1085 this.continueAsGuest(); 1086 this.fetchSignOff().catch((error) => { 1087 console.log("error signing off", error); 1088 }); 1089 } 1090 }); 1091 this.store.flow.listen((change) => {
1092 this.onFlowChange(change); 1093 }); 1094 const uniqueEmailsFound = /* @__PURE__ */ new Set(); 1095 this.computed.validGuestEmail.subscribe((email) => { 1096 if (!email || uniqueEmailsFound.has(email)) return; 1097 uniqueEmailsFound.add(email); 1098 this.send("gotEmail"); 1099 this.fetchAuthentication(email); 1100 }); 1101 if (globalThis.Checkout.store.checkout.mode.get() === "saved") { 1102 this.send("alreadySaved"); 1103 } else { 1104 this.send("noUser"); 1105 } 1106 } 1107 static onFlowChange({ to, data }) { 1108 if (to === 7 /* ValidOtp */) { 1109 const { source } = data; 1110 const lacksVerifiedPhone = source === "email" && globalThis.Checkout.store.contact_pending_auth.get().is_phone_verified !== true && !sessionStorage.getItem("skipped-phone-verification"); 1111 const nextEvent = lacksVerifiedPhone ? "suggestPhoneVerification" : "continueAsSaved"; 1112 Promise.resolve().then(() => this.send(nextEvent)); 1113 } 1114 } 1115 static send(eventId, data) { 1116 const modeName = this.store.mode.get(); 1117 const modeConfig = AuthFlow[modeName]; 1118 const nextMode = modeConfig && modeConfig[eventId] || AuthFlow["*"][eventId]; 1119 if (nextMode) { 1120 this.store.flow.set({ 1121 from: this.store.mode.get(), 1122 event: eventId, 1123 to: nextMode, 1124 data 1125 }); 1126 } 1127 } 1128 static requestPhoneVerification() { 1129 const count = globalThis.Checkout.auth.store.phoneVerificationRequest.get().count ?? 0; 1130 globalThis.Checkout.auth.store.phoneVerificationRequest.setKey("count", count + 1); 1131 this.fetchAddVerificationNumber().then((result) => { 1132 if (result.ok) { 1133 globalThis.Checkout.auth.store.phoneVerificationRequest.setKey("error", void 0); 1134 this.send("sentPhoneVerificationOtp"); 1135 } else { 1136 const count2 = globalThis.Checkout.auth.store.phoneVerificationRequest.get().rejections ?? 0; 1137 globalThis.Checkout.auth.store.phoneVerificationRequest.setKey("rejections", count2 + 1); 1138 this.send("failStartPhoneVerification", result); 1139 } 1140 }).catch((err) => { 1141 console.log("request phone verification failed", err); 1142 globalThis.Checkout.auth.store.phoneVerificationRequest.setKey("error", err); 1143 this.send("failStartPhoneVerification"); 1144 }); 1145 this.send("requestPhoneVerification"); 1146 } 1147 /* 1148 /user_pages/api/v1/contacts/request_authentication.json 1149 Param: email 1150 Response: 1151 📌 400: {result: false, errors: 'Invalid email'} 1152 📌 404 (contact not found): {result: false} 1153 ✅ 200: {result: true, contact: 1154 {first_name: '', email: '', uuid: '', masked_phone: '', is_verified: '', is_phone_verified: '' }} 1155 */ 1156 static fetchAuthentication(email) { 1157 fetch("/user_pages/api/v1/contacts/request_authentication.json?" + new URLSearchParams({ email }), { 1158 method: "GET" 1159 }).then((res) => { 1160 if (res.ok) { 1161 return res.json().then(({ result, contact }) => { 1162 const sentOTP = !!result; 1163 if (sentOTP) { 1164 globalThis.Checkout.store.contact_pending_auth.set({ ...contact ?? {}, authenticated: false }); 1165 this.send("sentOtp"); 1166 } 1167 }); 1168 } 1169 }).catch((err) => { 1170 console.log("fetch exception", err); 1171 }); 1172 } 1173 static submitOtp(code) { 1174 this.send("submitOtp"); 1175 this.fetchValidateCode(code); 1176 } 1177 static resendCode(optionalSource) { 1178 this.send("resendOtp", { optionalSource }); 1179 return this.fetchResendCode(optionalSource); 1180 } 1181 static fetchResendCode(optionalSource) { 1182 const { email } = globalThis.Checkout.store.contact_pending_auth.get(); 1183 const source = optionalSource || globalThis.Checkout.auth.store.otpLoginSource.get(); 1184 this.store.otpRequestFailure.set({ 1185 time: -1, 1186 retry_in: 0 1187 }); 1188 return fetch("/user_pages/api/v1/contacts/resend_otp.json", { 1189 method: "POST", 1190 headers: { "Content-Type": "application/json" }, 1191 body: JSON.stringify({ 1192 source: optionalSource || source, 1193 email 1194 }) 1195 }).then((res) => { 1196 if (res.ok) { 1197 globalThis.Checkout.auth.store.otpLoginSource.set(source); 1198 } 1199 return res; 1200 }).then((res) => this.fetchedResendCode(res)).catch((err) => { 1201 this.fetchedResendCode(void 0, err); 1202 }); 1203 } 1204 static fetchedResendCode(res, error) { 1205 let sent; 1206 const fail = ({ retry_in, error: error2 } = {}) => { 1207 const time = /* @__PURE__ */ new Date(); 1208 this.store.otpRequestFailure.set({ 1209 time, 1210 retry_in, 1211 error: error2 1212 }); 1213 this.send("resendFailed", { retry_in, time, error: error2 }); 1214 }; 1215 if (res) { 1216 if (res.ok) { 1217 return res.json().then((props) => { 1218 const { result } = props; 1219 sent = result; 1220 if (sent) { 1221 this.send("sentOtp"); 1222 } else { 1223 fail(); 1224 } 1225 }); 1226 } else { 1227 if (res.status === 400) { 1228 return res.json().then((props) => { 1229 const { retry_in } = props; 1230 fail({ retry_in }); 1231 }).catch(fail); 1232 } 1233 } 1234 } 1235 fail({ error }); 1236 } 1237 /* 1238 PATCH: /user_pages/api/v1/contacts/validate_and_sign_in.json 1239 2a. Param: {otp: '', email: '', source: 'email' | 'phone_number' } 1240 2b. Response 1241 404 (contact not found): {result: false} 1242 400 (invalid OTP): {result: false} 1243 200: {result: true, contact: {first_name: ‘’, email: ‘’, uuid: ‘’, masked_phone: ‘’, 1244 is_verified: ‘’, is_phone_verified: ‘’, payment_methods: [], shipping_addresses: [], billing_addresses: [] }} 1245 */ 1246 static fetchValidateCode(otp) { 1247 const { email } = globalThis.Checkout.store.contact_pending_auth.get(); 1248 const source = globalThis.Checkout.auth.store.otpLoginSource.get(); 1249 fetch("/user_pages/api/v1/contacts/validate_and_sign_in", { 1250 method: "POST", 1251 credentials: "include", 1252 headers: { "Content-Type": "application/json" }, 1253 body: JSON.stringify({ 1254 email, 1255 otp, 1256 source 1257 }) 1258 }).then((res) => { 1259 if (res.ok) { 1260 return res.json().then((data) => { 1261 const { result, contact } = data; 1262 if (result) { 1263 this.backfillContactFields(contact); 1264 CheckoutExistingOrders.fetch().then(() => { 1265 const isSelectedCartItemUpdatable = globalThis.Checkout.computed.checkoutCart.get().items.some((i) => i.type); 1266 if (isSelectedCartItemUpdatable) { 1267 globalThis.Checkout.store.checkout.lastModeIndependentOfCartItems.set("saved"); 1268 } else { 1269 globalThis.Checkout.store.checkout.mode.set("saved"); 1270 } 1271 this.send("validOtp", { source }); 1272 }); 1273 } else { 1274 this.otpFailed(); 1275 } 1276 }); 1277 } else { 1278 this.otpFailed(); 1279 } 1280 }).catch((err) => { 1281 console.log("fetch auth exception", err); 1282 this.otpFailed(); 1283 }); 1284 } 1285 static fetchAddVerificationNumber() { 1286 console.log("fetchAddVerificationNumber"); 1287 const { email, phone_number } = globalThis.Checkout.store.contact.get(); 1288 return fetch("/user_pages/api/v1/contacts/request_otp_to_add_new_number", { 1289 method: "POST", 1290 headers: { "Content-Type": "application/json" }, 1291 body: JSON.stringify({ 1292 email, 1293 phone_number 1294 }) 1295 }).then((res) => { 1296 if (res.ok) { 1297 return res; 1298 } 1299 return res.json().then(({ result, errors }) => { 1300 const errorResult = { 1301 ok: false, 1302 errors, 1303 numberTaken: errors === "Phone number already taken" 1304 }; 1305 return errorResult; 1306 }); 1307 }); 1308 } 1309 static submitVerifyPhoneCode(otp) { 1310 const { email, phone_number } = globalThis.Checkout.store.contact.get(); 1311 this.send("submitPhoneVerificationCode"); 1312 const fail = (err) => { 1313 }; 1314 return fetch("/user_pages/api/v1/contacts/validate_and_associate_phone_number", { 1315 method: "POST", 1316 headers: { "Content-Type": "application/json" }, 1317 credentials: "same-origin", 1318 body: JSON.stringify({ 1319 email, 1320 phone_number, 1321 otp 1322 }) 1323 }).then((res) => { 1324 if (res.ok) { 1325 this.send("verificationSucceeded"); 1326 } else { 1327 this.send("verificationFailed"); 1328 } 1329 }).catch((err) => { 1330 console.log("fetch auth exception", err); 1331 this.send("verificationSubmitError", { error: err }); 1332 }); 1333 } 1334 static continueAsGuest() { 1335 this.send("continueAsGuest"); 1336 } 1337 static fetchSignOff() { 1338 return fetch("/contacts/sign_out", { 1339 method: "DELETE", 1340 headers: { "Content-Type": "application/json" }, 1341 credentials: "same-origin" 1342 }).then((res) => { 1343 if (!res.ok) { 1344 console.log("sign_out failed", res); 1345 throw new Error("Sign out failed"); 1346 } 1347 return res; 1348 }); 1349 } 1350 static otpFailed() { 1351 this.send("invalidOtp"); 1352 } 1353 static backfillContactFields(data) { 1354 const { 1355 email, 1356 first_name, 1357 last_name, 1358 phone_number, 1359 uuid, 1360 is_phone_verified, 1361 masked_phone, 1362 payment_methods, 1363 billing_addresses, 1364 shipping_addresses 1365 } = data; 1366 let newBilling = {}; 1367 if (billing_addresses && billing_addresses.length > 0) { 1368 const backfilled_billing_addresses = backfillAddressesId(billing_addresses); 1369 newBilling = backfilled_billing_addresses[0]; 1370 globalThis.Checkout.store.billing.set(newBilling); 1371 globalThis.Checkout.store.billing_addresses.set(backfilled_billing_addresses); 1372 } else { 1373 globalThis.Checkout.store.billing_addresses.set([]); 1374 } 1375 let newShipping = {}; 1376 if (shipping_addresses && shipping_addresses.length > 0) { 1377 const backfilled_shipping_addresses = backfillAddressesId(shipping_addresses); 1378 newShipping = backfilled_shipping_addresses[0]; 1379 globalThis.Checkout.store.shipping.set(newShipping); 1380 globalThis.Checkout.store.shipping_addresses.set(backfilled_shipping_addresses); 1381 } else { 1382 globalThis.Checkout.store.shipping_addresses.set([]); 1383 } 1384 globalThis.Checkout.store.billingSameAsShipping.set(Boolean(newBilling.id && newBilling.id == newShipping.id)); 1385 if (payment_methods && payment_methods.length > 0) { 1386 globalThis.Checkout.store.paymentMethods.set([ 1387 ...globalThis.Checkout.store.paymentMethods.get() || [], 1388 ...payment_methods 1389 ]); 1390 if (!globalThis.Checkout.store.payment.id.get()) { 1391 globalThis.Checkout.store.payment.id.set(payment_methods[0].id); 1392 globalThis.Checkout.store.payment.type.set( 1393 resolveInitialPaymentType(payment_methods[0].type, globalThis.globalResourceData.enabledPayments) 1394 ); 1395 } 1396 globalThis.Checkout.store.contact.set({ 1397 ...globalThis.Checkout.store.contact.get(), 1398 email, 1399 first_name, 1400 last_name, 1401 phone_number 1402 }); 1403 globalThis.Checkout.store.contact_pending_auth.set({ 1404 ...globalThis.Checkout.store.contact.get(), 1405 email, 1406 first_name, 1407 last_name, 1408 phone_number, 1409 uuid, 1410 is_phone_verified, 1411 masked_phone, 1412 authenticated: true 1413 }); 1414 } 1415 } 1416 static skipPhoneVerification() { 1417 sessionStorage.setItem("skipped-phone-verification", "true"); 1418 this.send("skipPhoneVerification"); 1419 } 1420 static continueAfterPhoneVerification() { 1421 this.send("continueAsSaved"); 1422 } 1423}; 1424__publicField(CheckoutAuth, "store"); 1425__publicField(CheckoutAuth, "computed"); 1426
1427// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-login-v2.ts 1428init_general(); 1429init_runtime(); 1430var CheckoutLoginV22 = class extends CF2Component { 1431 constructor(el, runtimeSel) { 1432 super(el, runtimeSel); 1433 } 1434 mount() { 1435 CheckoutAuth.initializeOneClickCheckoutFlow(); 1436 this.mountPhoneVerificationSubform(); 1437 this.firstNameInput = this.element.querySelector(".elCheckoutLogin_FirstName"); 1438 this.deviceInfo = this.element.querySelector(".elCheckoutLogin_DeviceInfo"); 1439 this.alternateOtp = this.element.querySelector(".elCheckoutLogin_AlternateSource"); 1440 this.alternateOtpDeviceInfo = this.element.querySelector(".elCheckoutLogin_AlternateDeviceInfo"); 1441 const resendCodeEl = this.element.querySelector(".elResendCode"); 1442 const continueAsGuest = this.element.querySelector(".elLinkContinueAsGuest"); 1443 const getOtpSourceDescription = (source) => { 1444 const partialContact = Checkout.store.contact_pending_auth.get(); 1445 if (!partialContact) return ""; 1446 return source === "email" ? this.checkoutLoginTexts.emailAddress : source === "phone_number" ? `${this.checkoutLoginTexts.phoneNumberEndingIn} ${partialContact.masked_phone}` : source; 1447 }; 1448 const otpSource = Checkout.auth.store.otpLoginSource; 1449 const alternateOtpSource = computed([ 1450 otpSource, 1451 Checkout.auth.computed.otpLoginOptions 1452 ], (otpSource2, otpOptions) => { 1453 return otpOptions.find((option) => option !== otpSource2); 1454 }); 1455 this.bindText(this.firstNameInput, computed(Checkout.store.contact, (contact) => contact?.first_name)); 1456 this.bindText(this.deviceInfo, otpSource, (otpSource2) => { 1457 return getOtpSourceDescription(otpSource2); 1458 }); 1459 this.bindVisibility(this.alternateOtp, computed(alternateOtpSource, (alt) => !!alt)); 1460 this.bindText(this.alternateOtpDeviceInfo, alternateOtpSource, getOtpSourceDescription); 1461 this.element.querySelector('[href="#change-otp-source"]').addEventListener("click", (ev) => { 1462 ev.preventDefault(); 1463 const source = alternateOtpSource.get(); 1464 CheckoutAuth.resendCode(source); 1465 }); 1466 this.loginOtpInput = this.bindOtpInput(this.element.querySelector(".elCheckoutLoginInputContent .elOtpInput"), (code) => { 1467 CheckoutAuth.submitOtp(code); 1468 }); 1469 this.loginOtpSubmit = this.element.querySelector('.elCheckoutLoginForm [href="#submit-otp-code"]'); 1470 this.bindSubmitting(this.loginOtpSubmit.parentElement, CheckoutAuth.computed.submittingOtp); 1471 this.loginOtpSubmit.addEventListener("click", (ev) => { 1472 ev.preventDefault(); 1473 this.loginOtpInput.submit(); 1474 }); 1475 this.checkoutLoginInfo = this.element.querySelector(".elOtpInfo p span"); 1476 this.checkoutLoginError = this.element.querySelector(".elOtpError p span"); 1477 this.checkoutLoginStatus = this.element.querySelector(".elOtpSendStatus p span"); 1478 this.element.querySelector(".elLinkResendCode")?.addEventListener("click", () => { 1479 this.setErrorMessage(""); 1480 CheckoutAuth.resendCode(); 1481 }); 1482 continueAsGuest?.addEventListener("click", () => { 1483 if (Checkout.store.checkout.mode.get() !== "guest") { 1484 Checkout.store.checkout.mode.set("guest"); 1485 } else { 1486 CheckoutAuth.continueAsGuest(); 1487 } 1488 }); 1489 CheckoutAuth.store.flow.listen((change) => { 1490 this.onFlowChange(change); 1491 }); 1492 Checkout.store.state.listen((state) => { 1493 if (state === Checkout.StoreStates.INITIALIZED) { 1494 this.initializePhoneNumber(); 1495 } 1496 }); 1497 Checkout.store.checkout.mode.listen((state) => { 1498 if (state === "saved") { 1499 this.initializePhoneNumber(); 1500 } 1501 }); 1502 this.bindText(this.checkoutLoginInfo, CheckoutAuth.computed.requestingAnotherOtp, (active) => { 1503 return active ? this.checkoutLoginTexts.requestingNewCode : ``; 1504 }); 1505 this.bindText(this.element.querySelector(".elResendOtpWaitTime"), CheckoutAuth.computed.retrySeconds, (seconds) => seconds.toString()); 1506 this.bindVisibility(resendCodeEl, CheckoutAuth.computed.retrySeconds, (seconds) => !(seconds > 0)); 1507 this.bindVisibility(this.element.querySelector(".elWaitToResendOtp"), CheckoutAuth.computed.retrySeconds, (seconds) => seconds > 0); 1508 CheckoutAuth.store.otpRequestFailure.subscribe(({ error }) => { 1509 if (error) { 1510 this.notifyNetworkError(error); 1511 } 1512 }); 1513 this.bindVisibility(this.element.querySelector(".elCheckoutLoginForm"), CheckoutAuth.computed.suggestingPhoneVerification, false); 1514 this.bindVisibility(this.element.querySelector(".elCheckoutPhoneVerificationContainer"), CheckoutAuth.computed.suggestingPhoneVerification); 1515 this.bindVisibility(this.element.querySelector(".elCheckoutPhoneVerificationOtpInputContent"), CheckoutAuth.computed.showingPhoneOtp); 1516 } 1517 mountPhoneVerificationSubform() { 1518 this.phoneVerificationOtpInput = this.bindOtpInput( 1519 this.element.querySelector(".elCheckoutPhoneVerificationOtpInputContent .elOtpInput"), 1520 (code) => CheckoutAuth.submitVerifyPhoneCode(code) 1521 ); 1522 this.phoneVerificationOtpSubmit = this.element.querySelector('.elCheckoutPhoneVerificationForm [href="#submit-otp-code"]'); 1523 this.bindSubmitting(this.phoneVerificationOtpSubmit.parentElement, CheckoutAuth.computed.submittingPhoneVerification); 1524 this.phoneVerificationOtpSubmit.addEventListener("click", (ev) => { 1525 ev.preventDefault(); 1526 this.phoneVerificationOtpInput.submit(); 1527 }); 1528 this.element.querySelector(".elContinueAfterPhoneVerification").addEventListener("click", (evt) => { 1529 evt.preventDefault(); 1530 CheckoutAuth.continueAfterPhoneVerification(); 1531 }); 1532 Array.from(this.element.querySelectorAll(".elSkipPhoneVerification")).forEac
1532h((el) => { 1533 el.addEventListener("click", (ev) => { 1534 ev.preventDefault(); 1535 CheckoutAuth.skipPhoneVerification(); 1536 }); 1537 }); 1538 this.element.querySelector(".elVerifyPhoneButton > a").addEventListener("click", (ev) => { 1539 ev.preventDefault(); 1540 CheckoutAuth.requestPhoneVerification(); 1541 }); 1542 this.bindSubmitting(this.element.querySelector(".elVerifyPhoneButton"), CheckoutAuth.computed.RequestingPhoneVerification); 1543 this.element.querySelector(".elLinkRerequestPhoneVerification").addEventListener("click", (ev) => { 1544 ev.preventDefault(); 1545 CheckoutAuth.requestPhoneVerification(); 1546 }); 1547 CheckoutAuth.computed.phoneVerificationRequestErrorMsg.subscribe((msg) => { 1548 $(this.element.querySelector(".elPhoneVerificationRequestError")).text(msg); 1549 }); 1550 CheckoutAuth.computed.phoneVerificationErrorMsg.subscribe((msg) => { 1551 $(this.element.querySelector(".elPhoneVerificationOtpError")).text(msg); 1552 if (msg) { 1553 this.phoneVerificationOtpInput.clear(); 1554 this.phoneVerificationOtpInput.focus(); 1555 } 1556 }); 1557 this.bindText(this.element.querySelector(".elPhoneVerificationMessages"), CheckoutAuth.computed.phoneVerificationMessages); 1558 CheckoutAuth.computed.RequestingPhoneVerification.subscribe((pending) => { 1559 this.element.querySelector(".elLinkRerequestPhoneVerification").href = pending ? "" : "#"; 1560 if (pending === false) { 1561 this.phoneVerificationOtpInput.focus(); 1562 } 1563 }); 1564 this.bindVisibility(this.element.querySelector(".elCheckoutPhoneVerificationForm"), CheckoutAuth.computed.showingPhoneOtp); 1565 this.bindVisibility(this.element.querySelector(".elPhoneVerificationRequest"), CheckoutAuth.computed.showingPhoneVerificationRequest); 1566 } 1567 show() { 1568 const { first_name, masked_phone, is_phone_verified } = Checkout.store.contact_pending_auth.get(); 1569 const checkoutElement = this.element.closest(".elCheckout"); 1570 this.element.classList.remove("hide"); 1571 this.resetLoginOtpInputs(); 1572 this.resetMessages(); 1573 } 1574 hide() { 1575 this.element.classList.add("hide"); 1576 } 1577 setElText(el, text) { 1578 jQuery(el).text(text); 1579 } 1580 bindText(el, store, fn) { 1581 return store.subscribe((value) => { 1582 const text = fn ? fn(value) : value; 1583 this.setElText(el, text?.toString() || ""); 1584 }); 1585 } 1586 bindVisibility(el, store, test) { 1587 return store.subscribe((value) => { 1588 let visible = test !== void 0 ? typeof test === "function" ? test(value) : test === value : value; 1589 el.hidden = !visible; 1590 }); 1591 } 1592 onInvalidOtp() { 1593 this.setErrorMessage(this.checkoutLoginTexts.invalidOtp); 1594 this.resetLoginOtpInputs(); 1595 } 1596 onResentCode() { 1597 this.loginOtpInput.focus(); 1598 } 1599 notifyNetworkError(error) { 1600 this.setErrorMessage(this.checkoutLoginTexts.networkError); 1601 } 1602 // TODO: factor out depencency on event and state strings 1603 // use computeds and prefer matching states to events 1604 onFlowChange({ event, from, to }) { 1605 if (event === "submitOtp") { 1606 this.onSubmittingOtp(); 1607 } 1608 if (event === "resentOtp") { 1609 this.onResentCode(); 1610 } 1611 if (event === "invalidOtp") { 1612 this.onInvalidOtp(); 1613 } 1614 if (event === "resendFailed") { 1615 const { error, retry_in } = to; 1616 if (error) { 1617 this.notifyNetworkError(); 1618 } else if (retry_in) { 1619 this.loginOtpInput.focus(); 1620 } 1621 } 1622 if (event === "verificationSucceeded") { 1623 this.element.querySelector(".elCheckoutPhoneVerificationConfirmation").hidden = false; 1624 this.element.querySelector(".elCheckoutPhoneVerificationForm").hidden = true; 1625 } 1626 } 1627 bindOtpInput(input, onSubmit) { 1628 const maxLength = Number(input.getAttribute("maxlength")); 1629 const getCode = () => { 1630 return input.value; 1631 }; 1632 const submitIfValid = () => { 1633 const code = getCode(); 1634 if (code.length === maxLength) { 1635 onSubmit(code); 1636 } 1637 }; 1638 input.addEventListener("keydown", (evt) => { 1639 if (evt.isComposing || evt.keyCode === 229) return; 1640 if (evt.key === "Tab") { 1641 return; 1642 } 1643 if (evt.key === "Enter") { 1644 evt.preventDefault(); 1645 evt.stopPropagation(); 1646 submitIfValid(); 1647 return; 1648 } 1649 if (evt.key === "Backspace" || evt.keycode === 37) { 1650 if (input.value.length === maxLength) { 1651 submitIfValid(); 1652 } 1653 } 1654 }); 1655 input.addEventListener("input", () => { 1656 input.style.setProperty("--_otp-digit", input.selectionStart); 1657 if (input.value.length === maxLength) { 1658 submitIfValid(); 1659 } 1660 }); 1661 function setEnabled(enabled) { 1662 input.disabled = !enabled; 1663 } 1664 function focus(index = 0) { 1665 input.style.setProperty("--_otp-digit", index); 1666 input.focus(); 1667 } 1668 function clear() { 1669 input.style.setProperty("--_otp-digit", 0); 1670 input.value = ""; 1671 } 1672 return { input, getCode, setEnabled, clear, focus, submit: submitIfValid }; 1673 } 1674 onSubmittingOtp() { 1675 this.resetMessages(); 1676 } 1677 resetLoginOtpInputs() { 1678 this.loginOtpInput.clear(); 1679 const checkoutElement = this.element.closest(".elCheckout"); 1680 if (isElementVisibleOnViewport(checkoutElement, 20)) this.loginOtpInput.focus(); 1681 } 1682 // maybe keep 1683 resetMessages() { 1684 this.setErrorMessage(""); 1685 } 1686 setErrorMessage(message) { 1687 this.checkoutLoginError.innerHTML = message; 1688 } 1689 bindLoader(el, store, test) { 1690 return store.subscribe((value) => { 1691 let visible = test !== void 0 ? typeof test === "function" ? test(value) : test === value : value; 1692 if (visible) { 1693 el.dataset.loader = true; 1694 } else { 1695 delete el.dataset.loader; 1696 } 1697 }); 1698 } 1699 bindSubmitting(button, store) { 1700 const elButton = button.querySelector(".elButton"); 1701 const buttonMain = button.querySelector(".elButtonMain"); 1702 const buttonMainText = buttonMain.querySelector(".elButtonMainText"); 1703 const spinner = buttonMain.querySelector(".elButtonSpinner"); 1704 const buttonText = buttonMainText.innerHTML; 1705 const submittingText = elButton.getAttribute("data-param-submittingtext") || "Submitting..."; 1706 store.listen((submitting) => { 1707 if (submitting) { 1708 spinner.style.display = "inline-block"; 1709 buttonMainText.innerHTML = submittingText; 1710 } else { 1711 spinner.style.removeProperty("display"); 1712 buttonMainText.innerHTML = buttonText; 1713 button.querySelector(".elButtonSub").innerHTML = ""; 1714 } 1715 }); 1716 } 1717 bindDisabled(el, store, test) { 1718 return store.subscribe((value) => { 1719 let disabled = test !== void 0 ? typeof test === "function" ? test(value) : test === value : value; 1720 el.disabled = disabled; 1721 }); 1722 } 1723 // #region phone number form 1724 // ported from contact-form-v1 1725 getInputFromName(name) { 1726 return this.element.querySelector(`[name='${name}']`); 1727 } 1728 // TODO: The intlTelInput setup should be handled by the Input/V1 blueprint 1729 initializePhoneNumber() { 1730 const phoneInput = this.getInputFromName("phone_number"); 1731 const initialCountry = Checkout.store.shipping.get().country; 1732 IntlTel_initPhoneInput(phoneInput, { initialCountry }); 1733 phoneInput.addEventListener("countrychange", () => { 1734 Checkout.store.contact.setKey("phone_number", phoneInput.iti.getNumber()); 1735 }); 1736 phoneInput.addEventListener("blur", () => { 1737 const value = phoneInput.iti.getNumber(); 1738 Checkout.store.contact.setKey("phone_number", value); 1739 }); 1740 const $phoneNumber = computed(Checkout.store.contact, ({ phone_number }) => phone_number); 1741 $phoneNumber.subscribe((phone_number) => { 1742 phoneInput.iti.setNumber(phone_number || ""); 1743 if (phone_number) { 1744 $(phoneInput).parents(".elFormItemWrapper").addClass("hasValue"); 1745 } else { 1746 $(phoneInput).parents(".elFormItemWrapper").removeClass("hasValue"); 1747 } 1748 }); 1749 const $phoneError = computed(Checkout.computed.contactErrors, (errors) => { 1750 this.checkForm(Checkout.computed.contactErrors.get()); 1751 return errors?.fields?.phone_number; 1752 }); 1753 const $disableSubmit = computed([$phoneNumber, $phoneError], (phone_number, error) => { 1754 return !phone_number || error; 1755 }); 1756 Checkout.computed.contactErrors.subscribe((contactErrors) => { 1757 this.checkForm(contactErrors); 1758 }); 1759 $disableSubmit.subscribe((disable) => { 1760 this.element.querySelector(".elVerifyPhoneButton > a").dataset.disabled = disable; 1761 }); 1762 } 1763 checkForm(contactErrors) { 1764 const fields = ["phone_number"]; 1765 fields.forEach((prop) => { 1766 const input = this.getInputFromName(prop); 1767 resetInputErrors(input); 1768 }); 1769 if (Checkout.utils.hasErrors(contactErrors)) { 1770 const fieldErrors = contactErrors.fields; 1771 if (fieldErrors) { 1772 fields.forEach((field) => { 1773 const error = fieldErrors[field]; 1774 if (error) { 1775 const { message } = error; 1776 const input = this.getInputFromName(field); 1777 addError(input, message); 1778 } 1779 }); 1780 } 1781 } 1782 } 1783 // #endregion phone number form 1784}; 1785registerComponent("CheckoutLogin/V2", CheckoutLoginV22); 1786window["CheckoutLoginV2"] = CheckoutLoginV22; 1787
1788// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-multiple-payments-v2.ts 1789init_define_process(); 1790init_general(); 1791init_nanostores(); 1792init_runtime(); 1793var CheckoutMultiplePaymentsV2 = class extends CF2Component { 1794 constructor(el, runtimeSel) { 1795 super(el, runtimeSel); 1796 __publicField(this, "devices", { 1797 "payment-card": void 0, 1798 paypal: void 0, 1799 "apple-pay": void 0, 1800 Klarna: void 0 1801 }); 1802 __publicField(this, "CARD_FIELDS", ["number", "cvv", "date"]); 1803 __publicField(this, "selectedPaymentTab", batched( 1804 [Checkout.store.payment.type, Checkout.store.payment.virtualInstallmentId], 1805 (paymentType, virtualInstallmentId) => { 1806 return paymentType === "payment-card" && virtualInstallmentId !== null ? "splitit" : paymentType; 1807 } 1808 )); 1809 } 1810 mount() { 1811 this.cleanupPaymentOption("Klarna", () => !AVAILABLE_KLARNA_COUNTRIES.includes(globalThis.cfVisitorData.country)); 1812 this.cleanupPaymentOption("apple-pay", () => !window.ApplePaySession); 1813 const form = document.querySelector("#cfAR"); 1814 form.querySelectorAll("input[data-rebilly]").forEach((cfARInput) => { 1815 const dataRebillyAttribute = cfARInput.getAttribute("data-rebilly"); 1816 const dataCfFormField = cfARInput.getAttribute("data-cf-form-field"); 1817 const pageInputField = document.querySelector(`input[name="${dataCfFormField}"], select[name="${dataCfFormField}"]`); 1818 if (!pageInputField) { 1819 cfARInput?.removeAttribute("data-rebilly"); 1820 } else { 1821 pageInputField?.setAttribute("data-rebilly", dataRebillyAttribute); 1822 } 1823 }); 1824 Checkout.computed.modeLeaveEnterEvent.subscribe((ev) => { 1825 const { leave, next, enter, previous } = ev; 1826 const paymentState = Checkout.store.payment.state.get(); 1827 if (paymentState == Checkout.PaymentStates.INITIALIZED) { 1828 if (leave && leave === this.mode) { 1829 this.unmountAllPaymentMethods(); 1830 } 1831 if (enter === this.mode && previous) { 1832 this.mountRebillyElement(); 1833 } 1834 } 1835 }); 1836 Checkout.store.payment.state.listen((state) => { 1837 const checkoutMode = Checkout.store.checkout.mode.get(); 1838 switch (state) { 1839 case Checkout.PaymentStates.LOADING: { 1840 if (this.mode == "guest") this.showLoader(); 1841 break; 1842 } 1843 case Checkout.PaymentStates.INITIALIZED: { 1844 if (this.mode == "guest") this.hideLoader(); 1845 this.element.setAttribute("data-initialized", "true"); 1846 this.unmountAllPaymentMethods(); 1847 if (this.mode == Checkout.store.checkout.mode.get()) this.mountRebillyElement(); 1848 break; 1849 } 1850 } 1851 }); 1852 Checkout.computed.paymentErrors.subscribe((errors) => { 1853 const errorWrapper = this.element.querySelector(".elCheckoutFormErrors"); 1854 errorWrapper.classList.add("elHide"); 1855 this.element.classList.remove("hasPaymentError"); 1856 if (Checkout.utils.hasErrors(errors)) { 1857 const isFocused = this.element.querySelector(".payment-card-fields-container-focus"); 1858 const isMobile = this.element.clientWidth <= 770; 1859 if (!isFocused || isMobile) { 1860 this.element.classList.add("hasPaymentError"); 1861 } 1862 const fieldsErrors = errors.fields; 1863 if (fieldsErrors) { 1864 const errors2 = []; 1865 Object.entries(fieldsErrors).forEach(([field, error]) => { 1866 const { message } = error; 1867 errors2.push(message); 1868 }); 1869 if (errors2.length) { 1870 const listErrors = `<ul>${errors2.map((err) => `<li>${err}</li>`).join("")}</ul>`; 1871 errorWrapper.innerHTML = listErrors; 1872 errorWrapper.classList.remove("elHide"); 1873 } else { 1874 errorWrapper.classList.add("elHide"); 1875 } 1876 } 1877 } 1878 }); 1879 Checkout.store.payment.type.listen((type) => { 1880 const paymentState = Checkout.store.payment.state.get(); 1881 this.showPaymentType(type); 1882 this.unmountAllPaymentMethods(); 1883 if (type == "paypal" && Checkout.store.payment.paypal.state.get().state == Checkout.PaypalStates.PAYMENT_METHOD_APPROVED) return; 1884 if (this.mode == Checkout.store.checkout.mode.get()) { 1885 if (paymentState === Checkout.PaymentStates.INITIALIZED) { 1886 this.mountRebillyElement(); 1887 } 1888 } 1889 }); 1890 Checkout.store.submitting.listen((value) => { 1891 const paymentType = Checkout.store.payment.type.get(); 1892 const failedSubmit = value.state == Checkout.SubmittingStates.ERROR; 1893 if (failedSubmit && paymentType == "apple-pay" && this.mode == Checkout.store.checkout.mode.get()) { 1894 this.unmountAllPaymentMethods(); 1895 this.mountRebillyElement(); 1896 } 1897 }); 1898 if (this.enabledPayments.includes("paypal")) { 1899 this.addPaypalEventListeners(); 1900 } 1901 this.addPaymentEventListeners(); 1902 this.initializeInstallments(); 1903 this.showPaymentType(this.selectedPaymentTab.get()); 1904 } 1905 cleanupPaymentOption(paymentType, cleanupCallback) { 1906 const paymentIndex = this.enabledPayments.findIndex((v) => v == paymentType); 1907 if (cleanupCallback() && paymentIndex >= 0) { 1908 this.enabledPayments.splice(paymentIndex, 1); 1909 } 1910 const paymentElements = this.element.querySelectorAll(`[data-
1910payment-type="${paymentType}"]`); 1911 if (!paymentElements.length) return; 1912 if (cleanupCallback() || !this.enabledPayments.includes(paymentType)) { 1913 paymentElements.forEach((el) => el.remove()); 1914 if (this.enabledPayments.length <= 1) { 1915 this.element.querySelector(".pai-payment-methods")?.remove(); 1916 } 1917 } else { 1918 paymentElements.forEach((el) => el.classList.remove("elHide")); 1919 } 1920 } 1921 showLoader() { 1922 this.element.querySelector(".elPAILoader").dataset.loader = true; 1923 } 1924 hideLoader() { 1925 this.element.querySelector(".elPAILoader").dataset.loader = false; 1926 } 1927 addPaypalEventListeners() { 1928 Checkout.store.payment.paypal.state.listen((paypalState) => { 1929 switch (paypalState.state) { 1930 case Checkout.PaypalStates.IDLE: { 1931 this.paypalPreventClick(); 1932 this.paypalInitializeContent(); 1933 break; 1934 } 1935 case Checkout.PaypalStates.INITIALIZED: { 1936 this.paypalAllowClick(); 1937 this.paypalInitializeContent(); 1938 break; 1939 } 1940 case Checkout.PaypalStates.ERROR: { 1941 this.paypalPreventClick(); 1942 switch (paypalState.code) { 1943 case Checkout.ErrorTypes.PAYPAL_DECLINED_ERROR: { 1944 const paypalStatus = this.getPaypalContent().querySelector(".paypal-status"); 1945 paypalStatus.setAttribute("data-type", "error"); 1946 paypalStatus.innerText = this.checkoutMultiplePaymentsTexts.paypalDeclined; 1947 break; 1948 } 1949 case Checkout.ErrorTypes.PAYPAL_CUSTOM_ERROR: { 1950 const paypalStatus = this.getPaypalContent().querySelector(".paypal-status"); 1951 paypalStatus.setAttribute("data-type", "error"); 1952 paypalStatus.innerText = paypalState.message; 1953 break; 1954 } 1955 } 1956 break; 1957 } 1958 case Checkout.PaypalStates.PAYMENT_METHOD_APPROVED: { 1959 this.getPaypalContent().querySelector(".paypal-content-button-container").classList.add("elHide"); 1960 const paypalStatus = this.getPaypalContent().querySelector(".paypal-status"); 1961 paypalStatus.setAttribute("data-type", "success"); 1962 paypalStatus.innerHTML = `<i class="fas fa-check"></i> ${this.checkoutMultiplePaymentsTexts.yourPaymentIsConfigured}`; 1963 break; 1964 } 1965 } 1966 }); 1967 } 1968 getPaypalContent() { 1969 return this.element.querySelector(".paypal-content"); 1970 } 1971 paypalInitializeContent() { 1972 this.getPaypalContent().querySelector(".paypal-status").innerHTML = ""; 1973 this.getPaypalContent().querySelector(".paypal-content-button-container").classList.remove("elHide"); 1974 } 1975 paypalPreventClick() { 1976 this.getPaypalContent().querySelector(".elSpinnerWrapper").dataset.loader = true; 1977 } 1978 paypalAllowClick() { 1979 this.getPaypalContent().querySelector(".elSpinnerWrapper").dataset.loader = false;
1980 } 1981 showPaymentType(type) { 1982 const paymentFields = this.element.querySelectorAll(".pai-payment-field"); 1983 paymentFields.forEach((element) => { 1984 element.dataset.active = element.dataset.paymentType == type; 1985 }); 1986 const paymentContents = this.element.querySelectorAll(".pai-payment-content"); 1987 paymentContents.forEach((element) => { 1988 element.dataset.active = element.dataset.paymentType == type; 1989 }); 1990 } 1991 addPaymentEventListeners() { 1992 const paymentFields = this.element.querySelectorAll(".pai-payment-field"); 1993 paymentFields.forEach((element) => { 1994 element.addEventListener("click", (evt) => { 1995 evt.preventDefault(); 1996 const paymentType = element.dataset.paymentType; 1997 const actualPaymentType = element.dataset.actualPaymentType; 1998 if (this.selectedPaymentTab.get() === paymentType) { 1999 return; 2000 } 2001 if (Checkout.store.payment.type.get() == "payment-card" && !Object.values(this.devices["payment-card"] ?? {}).every((v) => v?.element?.mounted)) return; 2002 if (this.enabledPayments.includes("paypal") && Checkout.store.payment.paypal.state.get().state != Checkout.PaypalStates.PAYMENT_METHOD_APPROVED) { 2003 Checkout.store.payment.paypal.state.set({ state: Checkout.PaypalStates.IDLE }); 2004 } 2005 Checkout.store.payment["payment-card"].events.set({}); 2006 Checkout.store.payment.type.set(actualPaymentType ?? paymentType); 2007 if (paymentType === "splitit") { 2008 this.syncInstallments(true); 2009 } else { 2010 Checkout.store.payment.virtualInstallmentId.set(null); 2011 } 2012 }); 2013 }); 2014 } 2015 unmountPaymentMethod(type) { 2016 switch (type) { 2017 case "apple-pay": { 2018 if (!this.devices["apple-pay"]) break; 2019 this.devices["apple-pay"].unmount(); 2020 this.devices["apple-pay"] = void 0; 2021 break; 2022 } 2023 case "paypal": { 2024 if (!this.devices.paypal) break; 2025 this.devices.paypal.unmount(); 2026 this.devices.paypal = void 0; 2027 break; 2028 } 2029 case "payment-card": { 2030 if (!this.devices["payment-card"]) break; 2031 ["number", "cvv", "date"].forEach((key) => { 2032 this.devices["payment-card"][key].element.mounted && this.devices["payment-card"][key].destroy(); 2033 }); 2034 this.devices["payment-card"] = void 0; 2035 break; 2036 } 2037 case "Klarna": { 2038 if (!this.devices.Klarna) break; 2039 this.devices.Klarna.unmount(); 2040 this.devices.Klarna = void 0; 2041 break; 2042 } 2043 } 2044 } 2045 unmountPaymentMethods(types) { 2046 types.forEach((type) => { 2047 this.unmountPaymentMethod(type); 2048 }); 2049 } 2050 unmountAllPaymentMethods() { 2051 this.unmountPaymentMethods(this.enabledPayments); 2052 } 2053 mountRebillyElement() { 2054 const Rebilly = globalThis.Rebilly; 2055 const paymentType = Checkout.store.payment.type.get(); 2056 if (paymentType == "apple-pay" && !this.devices["apple-pay"]) { 2057 this.devices["apple-pay"] = Rebilly.applePay.mount(`[data-wrapper-checkout-state="${this.mode}"] .apple-pay-button`); 2058 } 2059 if (paymentType == "payment-card" && !this.devices["payment-card"]?.number) { 2060 const activeContent = this.element.querySelector(`.pai-payment-content[data-active="true"]`); 2061 const paymentCardWrapper = activeContent?.querySelector(".payment-card-fields-container"); 2062 if (!paymentCardWrapper) return; 2063 this.devices["payment-card"] = {}; 2064 let lastEvent; 2065 const mountNameMapper = { 2066 number: "cardNumber", 2067 cvv: "cardCvv", 2068 date: "cardExpiration" 2069 }; 2070 this.CARD_FIELDS.forEach((key) => { 2071 const mountPoint = paymentCardWrapper.querySelector(`.payment-card-${key}-mount`); 2072 const rebillyField = Rebilly.card.mount(mountPoint, mountNameMapper[key]); 2073 const fieldElement = rebillyField.element.element.querySelector(".rebilly-framepay"); 2074 rebillyField.on("focus", (ev) => { 2075 this.element.classList.remove("hasPaymentError"); 2076 fieldElement.classList.add(`payment-card-field-focus`); 2077 paymentCardWrapper.classList.add("payment-card-fields-container-focus"); 2078 Checkout.store.payment["payment-card"].events.setKey(key, void 0); 2079 lastEvent = null; 2080 }); 2081 rebillyField.on("change", (ev) => { 2082 lastEvent = ev; 2083 }); 2084 rebillyField.on("blur", (ev) => { 2085 fieldElement.classList.remove(`payment-card-field-focus`); 2086 paymentCardWrapper.classList.remove("payment-card-fields-container-focus"); 2087 Checkout.store.payment["payment-card"].events.setKey(key, lastEvent); 2088 }); 2089 this.devices["payment-card"][key] = rebillyField; 2090 }); 2091 } else if (paymentType == "paypal") { 2092 this.devices.paypal = Rebilly.paypal.mount(`[data-wrapper-checkout-state="${this.mode}
2092"] .paypal-mount`, { extraData: Checkout.PaypalCallbacks }); 2093 } else if (paymentType == "Klarna") { 2094 this.devices.Klarna = Rebilly.klarna.mount(`[data-wrapper-checkout-state="${this.mode}"] .klarna-mount`); 2095 } 2096 } 2097 initializeInstallments() { 2098 if (!this.enabledPayments.includes("splitit")) return; 2099 const installmentsContainer = this.element.querySelector(".installments-container"); 2100 const installmentsButton = this.element.querySelector(".installments-custom-dropdown-button"); 2101 const dropdownOptions = this.element.querySelector(".installments-dropdown-options"); 2102 const arrow = this.element.querySelector(".installments-dropdown-arrow"); 2103 if (this.mode === Checkout.store.checkout.mode.get()) { 2104 const initialInstallmentsInput = this.element.querySelector('input[name="initial_installments_value"]'); 2105 if (initialInstallmentsInput) { 2106 const value = initialInstallmentsInput.value; 2107 Checkout.store.payment.virtualInstallmentId.set(value); 2108 this.syncInstallments(); 2109 } 2110 } 2111 Checkout.computed.checkoutCart.listen((cart) => { 2112 if (this.mode !== Checkout.store.checkout.mode.get()) return; 2113 this.syncInstallments(); 2114 }); 2115 Checkout.store.summary.listen((summaryState) => { 2116 if (this.mode !== Checkout.store.checkout.mode.get()) return; 2117 this.syncInstallments(); 2118 }); 2119 installmentsButton.addEventListener("click", (evt) => { 2120 evt.preventDefault(); 2121 evt.stopPropagation(); 2122 const isOpen = dropdownOptions.style.display === "block"; 2123 dropdownOptions.style.display = isOpen ? "none" : "block"; 2124 arrow.classList.toggle("open", !isOpen); 2125 }); 2126 document.addEventListener("click", (evt) => { 2127 const isClickInside = installmentsContainer.contains(evt.target); 2128 if (!isClickInside && dropdownOptions.style.display === "block") { 2129 this.closeinstallmentsDropdown(); 2130 } 2131 }); 2132 this.selectedPaymentTab.listen((selectedTab, oldSelectedTab) => { 2133 this.showPaymentType(selectedTab); 2134 if (this.mode !== Checkout.store.checkout.mode.get()) return; 2135 const shouldRemount = Checkout.store.payment.state.get() == Checkout.PaymentStates.INITIALIZED && (selectedTab == "splitit" || oldSelectedTab == "payment-card" || (selectedTab == "payment-card" || oldSelectedTab == "splitit")); 2136 if (shouldRemount) { 2137 if (this.devices["payment-card"]) { 2138 this.unmountPaymentMethod("payment-card"); 2139 } 2140 this.mountRebillyElement(); 2141 } 2142 }); 2143 } 2144 syncInstallments(forceSelection = false) { 2145 const installmentsContainer = this.element.querySelector(".installments-container"); 2146 const dropdownOptions = this.element.querySelector(".installments-dropdown-options"); 2147 const cart = Checkout.computed.checkoutCart.get(); 2148 const hasRecurringPrice = cart.items.some(({ price_id }) => { 2149 const price = globalThis.globalResourceData.pricesById[price_id]; 2150 return price.is_recurring; 2151 }); 2152 const hasFreeTrial = cart.items.some(({ price_id }) => { 2153 const price = globalThis.globalResourceData.pricesById[price_id]; 2154 return price.initial_price_cents === 0 || !price.initial_price_cents; 2155 }); 2156 const hasNonBumpProducts = cart.items.some(({ product_id }) => { 2157 return !globalThis.Checkout.productsById[product_id]?.bump; 2158 }); 2159 if (hasRecurringPrice || hasFreeTrial || cart.items.length === 0 || !hasNonBumpProducts) { 2160 this.disableInstallments(); 2161 return; 2162 } 2163 let totalAmount = 0; 2164 let currencySymbol = Checkout.products[0].variants[0].currency; 2165 const summaryState = Checkout.store.summary.get(); 2166 if (summaryState?.data?.total?.amount) { 2167 const summaryData = summaryState.data; 2168 totalAmount = summaryData.total.amount; 2169 if (summaryData.currency_symbol) { 2170 currencySymbol = summaryData.currency_symbol; 2171 } 2172 } else { 2173 const cartItems = Checkout.computed.checkoutCart.get().items; 2174 if (!cartItems || cartItems.length === 0) { 2175 this.disableInstallments(); 2176 return; 2177 }
2178 Object.values(cartItems).forEach((item) => { 2179 const priceId = item.price_id; 2180 const quantity = item.quantity || 1; 2181 const priceData = globalResourceData.pricesById?.[priceId]; 2182 if (priceData?.initial_price_cents) { 2183 totalAmount += priceData.initial_price_cents / 100 * quantity; 2184 } 2185 }); 2186 } 2187 if (totalAmount <= 0) { 2188 this.disableInstallments(); 2189 return; 2190 } 2191 const currentVirtualId = Checkout.store.payment.virtualInstallmentId.get(); 2192 const installmentsTab = this.element.querySelector('[data-payment-type="splitit"]'); 2193 const installmentsContent = this.element.querySelector(".installments-content"); 2194 installmentsTab.classList.remove("elHide"); 2195 installmentsContent.classList.remove("elHide"); 2196 const tabSelector = this.element.querySelector(".pai-payment-methods"); 2197 tabSelector?.classList.remove("elHide"); 2198 if (!currentVirtualId && !forceSelection) { 2199 this.disableInstallments(false); 2200 return; 2201 } 2202 const installmentOptions = globalResourceData.installments.map((inst) => ({ 2203 duration: inst.duration, 2204 type: inst.installment_type 2205 })); 2206 let optionsHTML = ""; 2207 installmentOptions.forEach(({ duration, type }) => { 2208 if (duration >= 2 && duration <= 12) { 2209 const amountPerInstallment = Math.floor(totalAmount / duration * 100) / 100; 2210 const formattedAmount = formatNumberToCurrency(currencySymbol, amountPerInstallment); 2211 const scheduleText = "every month"; 2212 const virtualId = encodeVirtualInstallmentId(duration, type); 2213 optionsHTML += ` 2214 <div class="installments-dropdown-option" data-virtual-id="${virtualId}" data-count="${duration}" data-amount="${amountPerInstallment}" data-currency="${currencySymbol}" data-type="${type}"> 2215 <div> 2216 <div class="installments-option-text">${duration} payments</div> 2217 <div class="installments-option-schedule">${scheduleText}</div> 2218 </div> 2219 <div class="installments-dropdown-option-amount">${formattedAmount}</div> 2220 </div> 2221 `; 2222 } 2223 }); 2224 dropdownOptions.innerHTML = optionsHTML; 2225 dropdownOptions.querySelectorAll(".installments-dropdown-option").forEach((option) => { 2226 option.addEventListener("click", () => { 2227 const count = parseInt(option.getAttribute("data-count"), 10); 2228 const amount = parseFloat(option.getAttribute("data-amount")); 2229 const currency = option.getAttribute("data-currency"); 2230 const type = option.getAttribute("data-type"); 2231 this.selectInstallmentPlan(count, amount, currency, type); 2232 }); 2233 }); 2234 const currentVirtualIdParsed = decodeVirtualInstallmentId(currentVirtualId); 2235 if (installmentOptions.length > 0) { 2236 const isCurrentValid = currentVirtualIdParsed && installmentOptions.some( 2237 (opt) => opt.duration === currentVirtualIdParsed.duration && opt.type === currentVirtualIdParsed.type 2238 ); 2239 const shouldPreserveSelection = !forceSelection && isCurrentValid; 2240 if (shouldPreserveSelection && currentVirtualIdParsed) { 2241 const currentAmount = Math.floor(totalAmount / currentVirtualIdParsed.duration * 100) / 100; 2242 this.selectInstallmentPlan(currentVirtualIdParsed.duration, currentAmount, currencySymbol, currentVirtualIdParsed.type); 2243 } else { 2244 const first = installmentOptions[0]; 2245 const firstAmount = Math.floor(totalAmount / first.duration * 100) / 100; 2246 this.selectInstallmentPlan(first.duration, firstAmount, currencySymbol, first.type); 2247 } 2248 } 2249 } 2250 closeinstallmentsDropdown() { 2251 const dropdownOptions = this.element.querySelector(".installments-dropdown-options"); 2252 const arrow = this.element.querySelector(".installments-dropdown-arrow"); 2253 dropdownOptions.style.display = "none"; 2254 arrow.classList.remove("open"); 2255 } 2256 selectInstallmentPlan(count, amount, currencySymbol, type = "monthly") { 2257 const selectedText = this.element.querySelector(".installments-selected-text"); 2258 const selectedSchedule = this.element.querySelector(".installments-selected-schedule"); 2259 const formattedAmount = formatNumberToCurrency(currencySymbol, amount); 2260 selectedText.textContent = `${count} payments`; 2261 selectedSchedule.textContent = formattedAmount; 2262 const previewAmount = this.element.querySelector(".installments-preview-amount"); 2263 const previewSchedule = this.element.querySelector(".installments-preview-schedule"); 2264 previewAmount.textContent = formattedAmount; 2265 const scheduleText = "per month"; 2266 previewSchedule.textContent = `${scheduleText} \xD7 ${count} payments`; 2267 const scheduleContainer = this.element.querySelector(".installments-payment-schedule"); 2268 const today = /* @__PURE__ */ new Date(); 2269 const dates = this.getinstallmentsDates(today, count, type); 2270 let html = "";
2271 dates.forEach((date, index) => { 2272 const displayDate = index === 0 ? "Today" : date.toLocaleDateString("en-US", { month: "short", day: "numeric" }); 2273 html += ` 2274 <div class="installments-schedule-item"> 2275 <span>Payment ${index + 1} (${displayDate})</span> 2276 <span class="installments-schedule-amount">${formattedAmount}</span> 2277 </div> 2278 `; 2279 }); 2280 scheduleContainer.innerHTML = html; 2281 const virtualId = encodeVirtualInstallmentId(count, type); 2282 Checkout.store.payment.virtualInstallmentId.set(virtualId); 2283 this.closeinstallmentsDropdown(); 2284 } 2285 getinstallmentsDates(startDateObj, count, type = "monthly") { 2286 const result = []; 2287 if (type === "monthly") { 2288 const startDay = startDateObj.getDate(); 2289 const startMonth = startDateObj.getMonth(); 2290 const startYear = startDateObj.getFullYear(); 2291 for (let i = 0; i < count; i++) { 2292 const newDate = new Date(startYear, startMonth + i, startDay); 2293 if (newDate.getDate() !== startDay) { 2294 newDate.setDate(0); 2295 } 2296 result.push(newDate); 2297 } 2298 } 2299 return result; 2300 } 2301 disableInstallments(hideTab = true) { 2302 const installmentsTab = this.element.querySelector('[data-payment-type="splitit"]'); 2303 const installmentsContent = this.element.querySelector(".installments-content"); 2304 installmentsContent.classList.add("elHide"); 2305 Checkout.store.payment.virtualInstallmentId.set(null); 2306 if (hideTab) { 2307 installmentsTab.classList.add("elHide"); 2308 if (this.enabledPayments.length === 2) { 2309 const tabSelector = this.element.querySelector(".pai-payment-methods"); 2310 if (tabSelector) { 2311 tabSelector.classList.add("elHide"); 2312 } 2313 } 2314 } 2315 } 2316}; 2317registerComponent("CheckoutMultiplePayments/V2", CheckoutMultiplePaymentsV2); 2318window["CheckoutMultiplePaymentsV2"] = CheckoutMultiplePaymentsV2; 2319
2320// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-express-payments-v1.ts 2321init_define_process(); 2322init_runtime(); 2323var CheckoutExpressPaymentsV1 = class extends CF2Component { 2324 constructor(el, runtimeSel) { 2325 super(el, runtimeSel); 2326 __publicField(this, "devices", { 2327 "apple-pay": void 0 2328 }); 2329 } 2330 mount() { 2331 this.enabledPayments = this.enabledPayments ?? []; 2332 this.cleanupApplePayOption(); 2333 const form = document.querySelector("#cfAR"); 2334 form.querySelectorAll("input[data-rebilly]").forEach((cfARInput) => { 2335 const dataRebillyAttribute = cfARInput.getAttribute("data-rebilly"); 2336 const dataCfFormField = cfARInput.getAttribute("data-cf-form-field"); 2337 const pageInputField = document.querySelector('input[name="' + dataCfFormField + '"]'); 2338 if (!pageInputField) { 2339 cfARInput?.removeAttribute("data-rebilly"); 2340 } else { 2341 pageInputField?.setAttribute("data-rebilly", dataRebillyAttribute); 2342 } 2343 }); 2344 Checkout.computed.modeLeaveEnterEvent.subscribe((ev) => { 2345 const { leave, next, enter, previous } = ev; 2346 const paymentState = Checkout.store.payment.state.get(); 2347 if (paymentState == Checkout.PaymentStates.INITIALIZED) { 2348 if (leave && leave === this.mode) { 2349 this.unmountAllPaymentMethods(); 2350 } 2351 if (enter === this.mode && previous) { 2352 this.mountExpressRebillyElements(); 2353 } 2354 } 2355 }); 2356 Checkout.store.payment.state.listen((state) => { 2357 const checkoutMode = Checkout.store.checkout.mode.get(); 2358 switch (state) { 2359 case Checkout.PaymentStates.LOADING: { 2360 if (this.mode == "guest") this.showLoader(); 2361 break; 2362 } 2363 case Checkout.PaymentStates.INITIALIZED: { 2364 if (this.mode == "guest") this.hideLoader(); 2365 this.element.setAttribute("data-initialized", "true"); 2366 this.unmountAllPaymentMethods(); 2367 if (this.mode == Checkout.store.checkout.mode.get()) this.mountExpressRebillyElements(); 2368 break; 2369 } 2370 } 2371 }); 2372 } 2373 cleanupApplePayOption() { 2374 const applePayIndex = this.enabledPayments.findIndex((v) => v == "apple-pay"); 2375 if (!window.ApplePaySession && applePayIndex >= 0) { 2376 this.enabledPayments.splice(applePayIndex, 1); 2377 } 2378 const applePayElement = this.element.querySelector(".apple-pay-button-wrapper"); 2379 if (!applePayElement) return; 2380 if (!window.ApplePaySession || !this.enabledPayments.includes("apple-pay")) { 2381 const isApplePayActive = applePayElement.getAttribute("data-active") == "true"; 2382 applePayElement.remove(); 2383 if (this.enabledPayments.length <= 1) { 2384 this.element.querySelector(".pai-express-payment-methods")?.remove(); 2385 this.element.querySelector(".elCheckoutExpressPaymentSeperator")?.remove(); 2386 } 2387 } 2388 } 2389 showLoader() { 2390 this.element.querySelector(".elPAILoader").dataset.loader = true; 2391 } 2392 hideLoader() { 2393 this.element.querySelector(".elPAILoader").dataset.loader = false;
2394 } 2395 unmountPaymentMethod(type) { 2396 switch (type) { 2397 case "apple-pay": { 2398 if (!this.devices["apple-pay"]) break; 2399 this.devices["apple-pay"].unmount(); 2400 this.devices["apple-pay"] = void 0; 2401 break; 2402 } 2403 } 2404 } 2405 unmountPaymentMethods(types) { 2406 types.forEach((type) => { 2407 this.unmountPaymentMethod(type); 2408 }); 2409 } 2410 unmountAllPaymentMethods() { 2411 this.unmountPaymentMethods(this.enabledPayments); 2412 } 2413 mountExpressRebillyElements() { 2414 const Rebilly = globalThis.Rebilly; 2415 Object.values(this.enabledPayments).forEach((paymentType) => { 2416 if (paymentType == "apple-pay" && !this.devices["apple-pay"]) { 2417 this.devices["apple-pay"] = Rebilly.applePay.mount(`[data-wrapper-checkout-state="${this.mode}"] .elExpressPaymentMethods .apple-pay-button`); 2418 } 2419 }); 2420 } 2421}; 2422registerComponent("CheckoutExpressPayments/V1", CheckoutExpressPaymentsV1); 2423window["CheckoutExpressPaymentsV1"] = CheckoutExpressPaymentsV1; 2424
2425// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-contact-form-v1.ts 2426init_define_process(); 2427init_input_v1(); 2428init_cf_utils(); 2429
2430// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-subscription-duplicates.ts 2431init_define_process(); 2432init_nanostores(); 2433var CheckoutSubscriptionDuplicates = class { 2434 static initialize() { 2435 if (this.initialized) return; 2436 this.store = { 2437 mode: atom(0 /* Idle */), 2438 duplicateInfo: atom(null), 2439 checkedEmails: atom(/* @__PURE__ */ new Set()), 2440 lastError: atom(null) 2441 }; 2442 this.computed = { 2443 showingDuplicates: computed(this.store.mode, (mode) => mode === 2 /* FoundDuplicates */), 2444 hasError: computed(this.store.mode, (mode) => mode === 4 /* Error */), 2445 duplicateSubscription: computed(this.store.duplicateInfo, (info) => info?.subscription || null) 2446 }; 2447 this.setupEmailMonitoring(); 2448 this.initialized = true; 2449 } 2450 static setupEmailMonitoring() { 2451 const validGuestEmail = computed( 2452 [ 2453 globalThis.Checkout.store.checkout.mode, 2454 globalThis.Checkout.store.contact, 2455 globalThis.Checkout.computed.contactErrors, 2456 globalThis.Checkout.computed.hideContactInformationForm 2457 ], 2458 (mode, { email }, errors, hideContactInformationForm) => mode === "guest" && !errors?.fields?.email && !hideContactInformationForm && email 2459 ); 2460 validGuestEmail.subscribe((email) => { 2461 if (!email) return; 2462 const checkedEmails = this.store.checkedEmails.get(); 2463 if (checkedEmails.has(email)) return; 2464 checkedEmails.add(email); 2465 this.store.checkedEmails.set(new Set(checkedEmails)); 2466 this.checkForDuplicateSubscriptions(email); 2467 }); 2468 } 2469 static async checkForDuplicateSubscriptions(email) { 2470 try { 2471 this.store.mode.set(1 /* CheckingDuplicates */); 2472 this.store.lastError.set(null); 2473 const response = await fetch( 2474 "/user_pages/api/v1/contacts/check_subscription_duplicates.json?" + new URLSearchParams({ email }), 2475 { 2476 method: "GET", 2477 headers: { 2478 "Content-Type": "application/json" 2479 } 2480 } 2481 ); 2482 if (!response.ok) { 2483 if (response.status === 404) { 2484 this.store.duplicateInfo.set({ 2485 hasMatches: false, 2486 subscription: null 2487 }); 2488 this.store.mode.set(3 /* NoDuplicatesFound */); 2489 return; 2490 } 2491 throw new Error(`HTTP ${response.status}: ${response.statusText}`); 2492 } 2493 const data = await response.json(); 2494 if (data.result && data.duplicate_subscription) { 2495 this.store.duplicateInfo.set({ 2496 hasMatches: true, 2497 subscription: data.duplicate_subscription 2498 }); 2499 this.store.mode.set(2 /* FoundDuplicates */); 2500 } else { 2501 this.store.duplicateInfo.set({ 2502 hasMatches: false, 2503 subscription: null 2504 }); 2505 this.store.mode.set(3 /* NoDuplicatesFound */); 2506 } 2507 } catch (error) { 2508 console.error("Subscription duplicate check failed:", error); 2509 this.store.lastError.set(error.message || "Unknown error occurred"); 2510 this.store.mode.set(4 /* Error */); 2511 } 2512 } 2513 static dismissDuplicates() { 2514 this.store.mode.set(0 /* Idle */); 2515 this.store.duplicateInfo.set(null); 2516 } 2517 static reset() { 2518 this.store.mode.set(0 /* Idle */); 2519 this.store.duplicateInfo.set(null); 2520 this.store.checkedEmails.set(/* @__PURE__ */ new Set()); 2521 this.store.lastError.set(null); 2522 } 2523}; 2524__publicField(CheckoutSubscriptionDuplicates, "store"); 2525__publicField(CheckoutSubscriptionDuplicates, "computed"); 2526__publicField(CheckoutSubscriptionDuplicates, "initialized", false); 2527
2528// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-contact-form-v1.ts 2529init_runtime(); 2530var CheckoutContactFormV1 = class extends CF2Component { 2531 constructor(el, runtimeSel) { 2532 super(el, runtimeSel); 2533 } 2534 mount() { 2535 Checkout.store.contact.listen((contactData) => { 2536 this.fields.forEach((prop) => { 2537 const input = this.getInputFromName(prop); 2538 const inputValue = input.value; 2539 const newValue = contactData[prop]; 2540 if (newValue) { 2541 if (prop === "phone_number") { 2542 input.iti.setNumber(newValue); 2543 } else { 2544 input.value = newValue; 2545 } 2546 $(input).parents(".elFormItemWrapper").addClass("hasValue"); 2547 } else { 2548 input.value = ""; 2549 $(input).parents(".elFormItemWrapper").removeClass("hasValue"); 2550 } 2551 }); 2552 }); 2553 this.fields.forEach((prop) => { 2554 const input = this.getInputFromName(prop); 2555 input.addEventListener("blur", () => { 2556 let value; 2557 if (prop === "phone_number") { 2558 value = input.iti.getNumber(); 2559 } else { 2560 value = input.value; 2561 } 2562 Checkout.store.contact.setKey(prop, value); 2563 window.cfGarlicUtils.store(prop, value); 2564 if (!this.disableInputValidationOnBlur) { 2565 this.checkForm(Checkout.computed.contactErrors.get()); 2566 } else { 2567 if (Checkout.store.showAllErrors.contact.get()) this.checkForm(Checkout.computed.contactErrors.get()); 2568 } 2569 }); 2570 }); 2571 Checkout.computed.contactErrors.subscribe((contactErrors) => { 2572 if (!this.disableInputValidationOnBlur) { 2573 this.checkForm(contactErrors); 2574 } else { 2575 if (Checkout.store.showAllErrors.contact.get()) this.checkForm(contactErrors); 2576 } 2577 }); 2578 Checkout.store.phoneNumberInitialized.listen((phoneNumberInitialized) => { 2579 if (phoneNumberInitialized) { 2580 this.initializePhoneNumber(); 2581 } 2582 }); 2583 Checkout.computed.hideContactInformationForm.subscribe((hideContactInformationForm) => { 2584 if (hideContactInformationForm) { 2585 this.element.classList.add("elHide"); 2586 } else { 2587 this.element.classList.remove("elHide"); 2588 } 2589 }); 2590 if (this.enableSubscriptionDuplicateDetection) { 2591 CheckoutSubscriptionDuplicates.initialize(); 2592 const duplicateRow = this.element.querySelector(".elSubscriptionDuplicateRow"); 2593 const manageLink = this.element.querySelector(".elManageSubscriptionLink"); 2594 if (CheckoutSubscriptionDuplicates.computed && CheckoutSubscriptionDuplicates.computed.showingDuplicates) { 2595 CheckoutSubscriptionDuplicates.computed.showingDuplicates.subscribe((showingDuplicates) => { 2596 if (duplicateRow) { 2597 if (showingDuplicates) { 2598 duplicateRow.classList.remove("elHide"); 2599 } else { 2600 duplicateRow.classList.add("elHide"); 2601 } 2602 } 2603 }); 2604 } 2605 if (manageLink && CheckoutSubscriptionDuplicates.computed && CheckoutSubscriptionDuplicates.computed.duplicateSubscription) { 2606 manageLink.addEventListener("click", (e) => { 2607 e.preventDefault(); 2608 const subscription = CheckoutSubscriptionDuplicates.computed.duplicateSubscription.get(); 2609 if (subscription) { 2610 window.open(subscription.customer_center_url, "_blank"); 2611 } 2612 }); 2613 } 2614 const textElement = this.element.querySelector(".elSubscriptionDuplicateText"); 2615 if (textElement && CheckoutSubscriptionDuplicates.computed && CheckoutSubscriptionDuplicates.computed.duplicateSubscription) { 2616 CheckoutSubscriptionDuplicates.computed.duplicateSubscription.subscribe((subscription) => { 2617 if (subscription && subscription.product_name) { 2618 textElement.textContent = `${this.checkoutContactFormTexts.existingSubscriptionFor} '${subscription.product_name}' ${this.checkoutContactFormTexts.thatBelongsToYou}`; 2619 } 2620 }); 2621 } 2622 } 2623 } 2624 checkForm(contactErrors) { 2625 const errorWrapper = this.element.querySelector(".elCheckoutFormErrors"); 2626 errorWrapper.classList.add("elHide"); 2627 this.fields.forEach((prop) => { 2628 const input = this.getInputFromName(prop); 2629 resetInputErrors(input); 2630 }); 2631 if (Checkout.utils.hasErrors(contactErrors)) { 2632 const fieldErrors = contactErrors.fields; 2633 if (fieldErrors) { 2634 const errors = [];
2635 Object.entries(fieldErrors).forEach(([field, error]) => { 2636 const { message } = error; 2637 errors.push(message); 2638 const input = this.getInputFromName(field); 2639 addError(input); 2640 }); 2641 if (errors.length) { 2642 const listErrors = `<ul>${errors.map((err) => `<li>${err}</li>`).join("")}</ul>`; 2643 errorWrapper.innerHTML = listErrors; 2644 errorWrapper.classList.remove("elHide"); 2645 } else { 2646 errorWrapper.classList.add("elHide"); 2647 } 2648 } 2649 } 2650 } 2651 getInputFromName(name) { 2652 return this.element.querySelector(`[name='${name}']`); 2653 } 2654 // TODO: The intlTelInput setup should be handled by the Input/V1 blueprint 2655 initializePhoneNumber() { 2656 const phoneInput = this.getInputFromName("phone_number"); 2657 if (!phoneInput) return; 2658 const initialCountry = Checkout.store.shipping.get().country; 2659 IntlTel_initPhoneInput(phoneInput, { initialCountry: initialCountry.toLowerCase() }); 2660 phoneInput.addEventListener("countrychange", () => { 2661 Checkout.store.contact.setKey("phone_number", phoneInput.iti.getNumber()); 2662 }); 2663 } 2664}; 2665registerComponent("CheckoutContactForm/V1", CheckoutContactFormV1); 2666window["CheckoutContactFormV1"] = CheckoutContactFormV1; 2667
2668// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-saved-address-form-v1.ts 2669init_define_process(); 2670init_radio_v1(); 2671init_runtime(); 2672var CheckoutSavedAddressFormV1 = class extends CF2Component { 2673 constructor(el, runtimeSel) { 2674 super(el, runtimeSel); 2675 } 2676 mount() { 2677 this.bindNewAddressClick(); 2678 this.bindAddressClick(); 2679 Checkout.store[`${this.type}_addresses`].listen((addresses) => { 2680 this.addresses = addresses; 2681 if (addresses && addresses.length > 0) { 2682 this.addresses = addresses; 2683 this.renderAddresses(addresses); 2684 this.getAddNewAddressButton().classList.remove("elHide"); 2685 this.getAddNewAddressElement().classList.remove("elCheckoutStandaloneSavedAddNewAddress"); 2686 this.getAddNewAddressElement().classList.add("elHide"); 2687 } else { 2688 this.getAddressInputByValue("new-address").checked = true; 2689 this.showAddNewAddressForm(); 2690 } 2691 }); 2692 } 2693 bindNewAddressClick() { 2694 this.getAddNewAddressButton().addEventListener("click", (evt) => { 2695 evt.preventDefault(); 2696 this.getAddressInputByValue("new-address").checked = true; 2697 this.showAddNewAddressForm(); 2698 }); 2699 } 2700 getAddressFormValues() { 2701 return this.getComponent("CheckoutAddressForm/V1").store.get(); 2702 } 2703 validateNewAddressForm() { 2704 return this.getComponent("CheckoutAddressForm/V1").validateFormFields(); 2705 } 2706 showAddNewAddressForm() { 2707 this.getAddNewAddressButton().classList.add("elHide"); 2708 this.getAddNewAddressElement().classList.remove("elHide"); 2709 } 2710 getAddNewAddressElement() { 2711 return this.element.querySelector(".elCheckoutSavedAddNewAddress"); 2712 } 2713 getAddNewAddressButton() { 2714 return this.element.querySelector(".elCheckoutSavedAddNewAddressContainer"); 2715 } 2716 getAddressInputByValue(value) { 2717 return this.element.querySelector(`input[value="${value}"]`); 2718 } 2719 getSavedAddressById(id) { 2720 return this.addresses.find((addr) => addr.id == id); 2721 } 2722 getSelectedAddressId() { 2723 return this.element.querySelector(`input[name="selected-${this.type}-address"]:checked`).value; 2724 } 2725 isNewAddress() { 2726 return this.getSelectedAddressId() === "new-address"; 2727 } 2728 bindAddressClick() { 2729 Array.from( 2730 this.element.querySelector(".elCheckoutAddressList").querySelectorAll(".elCheckoutSavedAddressContainer") 2731 ).forEach((addressContainer) => { 2732 const elRadio = addressContainer.parentElement.querySelector('[type="radio"]'); 2733 addressContainer.addEventListener("click", (ev) => { 2734 ev.preventDefault(); 2735 elRadio.checked = true; 2736 }); 2737 }); 2738 } 2739 renderAddresses(addresses = []) { 2740 if (addresses.length === 0) return; 2741 const el = this.element.querySelector(".elCheckoutAddressList"); 2742 $(el).html(` 2743 ${addresses.map((address, index) => { 2744 const { id, city, state, zip, country } = address; 2745 const { type } = this; 2746 const checked = index === 0; 2747 const fieldsOrder = this.locale == "ja" ? [zip, country, state, city] : [city, state, zip, country]; 2748 const addressGoesFirst = this.locale !== "ja"; 2749 const address12Html = address.address ? `<span class="elCheckoutSavedAddressInfo"> 2750 ${[address.address, address.address2].filter((x) => x).join(", ")} 2751 </span>` : ""; 2752 const fullAddressHtml = ` 2753 ${addressGoesFirst ? address12Html : ""} 2754 <span class="elCheckoutSavedAddressDetails"> 2755 ${fieldsOrder.filter((x) => x).join(", ")} 2756 </span> 2757 ${addressGoesFirst ? "" : address12Html} 2758 `; 2759 return ` 2760 <div class="elCheckoutSavedAddressContainer"> 2761 <div data-page-element="Radio/V1" class="elRadioWrapper"> 2762 <label class="elRadioLabel"> 2763 <input type="radio" value="${address.id}" name="selected-${type}-address" ${checked ? "checked" : ""} class="elRadioInput"> 2764 <div class="elRadio"> 2765 <div class="elRadioIcon"> 2766 </div> 2767 </div> 2768 <span class="elRadioText"></span> 2769 </label> 2770 </div> 2771 <div class="elCheckoutSavedAddress"> 2772 ${fullAddressHtml} 2773 </div> 2774 </div> 2775 `; 2776 }).join("\n")} 2777 `);
2778 this.bindAddressClick(); 2779 } 2780}; 2781registerComponent("CheckoutSavedAddressForm/V1", CheckoutSavedAddressFormV1); 2782window["CheckoutSavedAddressFormV1"] = CheckoutSavedAddressFormV1; 2783
2784// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-saved-billing-address-v1.ts 2785init_define_process(); 2786init_nanostores(); 2787init_modal_v1(); 2788init_checkbox_v1(); 2789init_runtime(); 2790var CheckoutSavedBillingAddressV1 = class extends CF2Component { 2791 constructor(el, runtimeSel) { 2792 super(el, runtimeSel); 2793 } 2794 mount() { 2795 this.currentBillingSameAsShipping = atom(Checkout.store.billingSameAsShipping.get()); 2796 this.modalShow = atom(false); 2797 this.getOpenModalButton().addEventListener("click", (evt) => { 2798 evt.preventDefault(); 2799 this.modalShow.set(true); 2800 }); 2801 this.getCloseButton().addEventListener("click", (evt) => { 2802 evt.preventDefault(); 2803 this.modalShow.set(false); 2804 }); 2805 this.getModal().onClose = () => { 2806 this.modalShow.set(false); 2807 }; 2808 this.getCheckbox().addEventListener("change", (evt) => { 2809 evt.stopPropagation(); 2810 this.currentBillingSameAsShipping.set(!!evt.target.checked); 2811 }); 2812 this.getUpdateButton().addEventListener("click", (evt) => { 2813 evt.preventDefault(); 2814 this.updateAddress(); 2815 }); 2816 this.modalShow.listen((value) => { 2817 if (value) { 2818 this.showModal(); 2819 } else { 2820 this.hideModal(); 2821 const storeBillingSameAsShipping = Checkout.store.billingSameAsShipping.get(); 2822 if (!storeBillingSameAsShipping) { 2823 const currentAddress = Checkout.store.billing.get(); 2824 const id = currentAddress?.id ?? "new-address";
2825 this.getSavedAddressForm().getAddressInputByValue(id).checked = true; 2826 } 2827 } 2828 }); 2829 Checkout.store.billingSameAsShipping.listen((value) => { 2830 this.currentBillingSameAsShipping.set(value); 2831 }); 2832 this.currentBillingSameAsShipping.listen((value) => { 2833 this.getCheckbox().checked = value; 2834 if (value) { 2835 this.hideSelectAddressForm(); 2836 } else { 2837 this.showSelectAddressForm(); 2838 } 2839 }); 2840 const computedSavedBillingAddress = computed([ 2841 Checkout.store.billing, 2842 Checkout.store.shipping, 2843 Checkout.store.billingSameAsShipping 2844 ], (billing, shipping, billingSameAsShipping) => { 2845 return billingSameAsShipping ? shipping : billing; 2846 }); 2847 computedSavedBillingAddress.listen((savedAddress) => { 2848 this.refreshDetailsElement(savedAddress); 2849 }); 2850 Checkout.computed.hasPhysicalProducts.subscribe((hasPhysicalProducts2) => { 2851 if (hasPhysicalProducts2) { 2852 this.showBillingSameAsShipping(); 2853 if (Checkout.store.billingSameAsShipping.get()) { 2854 this.hideSelectAddressForm(); 2855 } else { 2856 this.showSelectAddressForm(); 2857 } 2858 } else { 2859 this.hideBillingSameAsShipping(); 2860 this.showSelectAddressForm(); 2861 } 2862 }); 2863 this.listenToBillingApiErrors(); 2864 Checkout.computed.isNewDigitalWalletPayment.subscribe((isNewDigitalWalletPayment) => { 2865 if (isNewDigitalWalletPayment) { 2866 this.hide(); 2867 } else { 2868 this.show(); 2869 } 2870 }); 2871 } 2872 updateAddress() { 2873 const savedAddrComp = this.getSavedAddressForm(); 2874 const cart = Checkout.computed.checkoutCart.get(); 2875 if (hasPhysicalProducts(cart) && this.currentBillingSameAsShipping.get()) { 2876 Checkout.store.billingSameAsShipping.set(true); 2877 const shippingData = Checkout.store.shipping.get(); 2878 Checkout.store.billing.set(shippingData); 2879 this.modalShow.set(false); 2880 } else { 2881 if (savedAddrComp.isNewAddress()) { 2882 if (savedAddrComp.validateNewAddressForm()) { 2883 Checkout.store.billingSameAsShipping.set(false); 2884 const newAddress = savedAddrComp.getAddressFormValues(); 2885 Checkout.store.billing.set(newAddress); 2886 this.modalShow.set(false); 2887 } 2888 } else { 2889 Checkout.store.billingSameAsShipping.set(false); 2890 const selectedAddressId = savedAddrComp.getSelectedAddressId(); 2891 const newAddress = savedAddrComp.getSavedAddressById(selectedAddressId); 2892 if (newAddress) { 2893 Checkout.store.billing.set(newAddress); 2894 } 2895 this.modalShow.set(false); 2896 } 2897 } 2898 } 2899 refreshDetailsElement(address) { 2900 const detailsTextElement = this.element.querySelector(".elSavedDetailsText"); 2901 const detailsIconElement = this.element.querySelector(".elSavedDetailsIcon"); 2902 if (address && Object.keys(address).length) { 2903 const billingSameAsShipping = Checkout.store.billingSameAsShipping.get(); 2904 const addressByFields = billingSameAsShipping ? address : parseAddressByFields(address, this.fields, false); 2905 const formattedText = addressToString(address); 2906 detailsTextElement.innerHTML = formattedText; 2907 detailsTextElement.classList.remove("elError"); 2908 detailsIconElement.classList.remove("elError"); 2909 } else { 2910 detailsTextElement.innerHTML = this.checkoutSavedBillingAddressFormTexts.requiresAddressConfiguration; 2911 detailsTextElement.classList.add("elError"); 2912 detailsIconElement.classList.add("elError"); 2913 } 2914 } 2915 getModal() { 2916 return this.getComponent("Modal/V1"); 2917 } 2918 getOpenModalButton() { 2919 return this.element.querySelector(".elSavedDetailsEdit"); 2920 } 2921 showModal() { 2922 this.getModal().element.style.display = "flex"; 2923 } 2924 hideModal() { 2925 this.getModal().element.style.display = "none"; 2926 } 2927 hideSelectAddressForm() { 2928 this.getSelectAddressForm().classList.add("elHide"); 2929 } 2930 showSelectAddressForm() { 2931 this.getSelectAddressForm().classList.remove("elHide"); 2932 } 2933 getSelectAddressForm() { 2934 return this.getModal().element.querySelector(".elCheckoutSelectAddressWrapper"); 2935 } 2936 getUpdateButton() { 2937 return this.getModal().element.querySelector(".elButton"); 2938 } 2939 getCheckbox() { 2940 return this.getBillingSameAsShippingCheckbox().querySelector("input"); 2941 } 2942 getCloseButton() { 2943 return this.getModal().element.querySelector(".elCheckoutModalFormClose"); 2944 } 2945 getSavedAddressForm() { 2946 return this.getComponent("CheckoutSavedAddressForm/V1"); 2947 } 2948 getBillingSameAsShippingCheckbox() { 2949 return this.element.querySelector(".elShippingSameAsBillingContainer"); 2950 } 2951 showBillingSameAsShipping() { 2952 return this.getBillingSameAsShippingCheckbox().classList.remove("elHide"); 2953 } 2954 hideBillingSameAsShipping() { 2955 return this.getBillingSameAsShippingCheckbox().classList.add("elHide"); 2956 } 2957 listenToBillingApiErrors() { 2958 Checkout.store.billingApiErrorsByField.listen((apiErrors) => { 2959 const errorWrapper = this.element.querySelector(".elCheckoutFormErrors");
2960 const savedDetailsContainer = this.element.querySelector(".elSavedDetailsContainer"); 2961 errorWrapper.classList.add("elHide"); 2962 savedDetailsContainer.classList.remove("errorBillingAddress"); 2963 if (apiErrors) { 2964 const errors = []; 2965 Object.entries(apiErrors).forEach(([field, error]) => { 2966 const { message } = error; 2967 errors.push(message); 2968 }); 2969 if (errors.length) { 2970 const listErrors = `<ul>${errors.map((err) => `<li>${err}</li>`).join("")}</ul>`; 2971 errorWrapper.innerHTML = listErrors; 2972 errorWrapper.classList.remove("elHide"); 2973 savedDetailsContainer.classList.add("errorBillingAddress"); 2974 } 2975 } 2976 }); 2977 } 2978 show() { 2979 this.element.classList.remove("elHide"); 2980 } 2981 hide() { 2982 this.element.classList.add("elHide"); 2983 } 2984}; 2985registerComponent("CheckoutSavedBillingAddress/V1", CheckoutSavedBillingAddressV1); 2986window["CheckoutSavedBillingAddressV1"] = CheckoutSavedBillingAddressV1; 2987
2988// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-saved-contact-details-v1.ts 2989init_define_process(); 2990init_nanostores(); 2991init_modal_v1(); 2992init_radio_v1(); 2993init_runtime(); 2994var CheckoutSavedContactDetailsV1 = class extends CF2Component { 2995 constructor(el, runtimeSel) { 2996 super(el, runtimeSel); 2997 } 2998 mount() { 2999 this.modalShow = atom(false); 3000 this.getOpenModalButton().addEventListener("click", (evt) => { 3001 evt.preventDefault(); 3002 this.modalShow.set(true); 3003 }); 3004 this.getCloseButton().addEventListener("click", (evt) => { 3005 evt.preventDefault(); 3006 this.modalShow.set(false); 3007 }); 3008 this.getModal().onClose = () => { 3009 this.modalShow.set(false); 3010 }; 3011 this.getButtonElement().addEventListener("click", (evt) => { 3012 evt.preventDefault(); 3013 this.updateAddress(); 3014 }); 3015 this.modalShow.listen((value) => { 3016 if (value) { 3017 this.showModal(); 3018 } else { 3019 this.hideModal(); 3020 const currentAddress = Checkout.store.shipping.get(); 3021 const id = currentAddress?.id ?? "new-address";
3022 this.getSavedAddressForm().getAddressInputByValue(id).checked = true; 3023 } 3024 }); 3025 Checkout.store.shipping.listen((shipping) => { 3026 const shippingAddressLength = this.getSavedContainerWrapper().getAttribute("data-contact-shipping-addresses-length"); 3027 if (!shipping.id == null && (!shippingAddressLength || shippingAddressLength == "0")) { 3028 this.getSavedContainerWrapper().setAttribute("data-contact-shipping-addresses-length", "1"); 3029 } 3030 this.refreshAddress(shipping); 3031 }); 3032 Checkout.store.contact_pending_auth.listen((contact_pending_auth) => { 3033 const authenticated = contact_pending_auth.authenticated; 3034 this.setShowContactDetails(!authenticated); 3035 }); 3036 Checkout.store.contact.listen((contact) => { 3037 const { email, first_name, last_name, phone_number } = contact; 3038 this.element.querySelector(".contact_email").innerHTML = email || ""; 3039 this.element.querySelector(".contact_first_name").innerHTML = first_name || ""; 3040 this.element.querySelector(".contact_last_name").innerHTML = last_name || ""; 3041 this.element.querySelector(".elSavedPhone").innerHTML = phone_number ? ` 3042 <i class="fas fa-phone"></i> 3043 <span class="contact_phone_number"> ${contact.phone_number} </span> 3044 ` : ``; 3045 }); 3046 Checkout.store.checkout.mode.subscribe((mode) => {
3047 this.getSavedContainerWrapper().dataset.mode = mode; 3048 }); 3049 Checkout.computed.hasPhysicalProducts.subscribe((hasPhysicalProducts2) => { 3050 const defaultLabel = "Shipping Information"; 3051 const formDetailsLabel = this.element.querySelector(".elCheckoutFormLabel"); 3052 if (!formDetailsLabel) return; 3053 this.getSavedContainerWrapper().dataset["selectedProductType"] = hasPhysicalProducts2 ? "physical" : "digital"; 3054 if (hasPhysicalProducts2) { 3055 formDetailsLabel.innerHTML = this.shippingHeadline || defaultLabel; 3056 } else { 3057 formDetailsLabel.innerHTML = this.showContactDetails() ? this.contactHeadline : this.shippingHeadline; 3058 } 3059 }); 3060 Checkout.computed.isNewDigitalWalletPayment.subscribe((isNewDigitalWalletPayment) => { 3061 if (isNewDigitalWalletPayment) { 3062 this.hide(); 3063 } else { 3064 this.show(); 3065 } 3066 }); 3067 Checkout.store.shipping_addresses.listen((shippingAddresses) => { 3068 this.getSavedContainerWrapper().setAttribute("data-contact-shipping-addresses-length", shippingAddresses.length); 3069 }); 3070 } 3071 hide() { 3072 this.element.classList.add("elHide"); 3073 } 3074 show() { 3075 this.element.classList.remove("elHide"); 3076 } 3077 updateAddress() { 3078 const savedAddrComp = this.getSavedAddressForm(); 3079 if (savedAddrComp.isNewAddress()) { 3080 if (savedAddrComp.validateNewAddressForm()) { 3081 const newAddress = savedAddrComp.getAddressFormValues(); 3082 Checkout.store.shipping.set(newAddress); 3083 this.modalShow.set(false); 3084 } 3085 } else { 3086 const selectedAddressId = savedAddrComp.getSelectedAddressId(); 3087 const newAddress = savedAddrComp.getSavedAddressById(selectedAddressId); 3088 if (newAddress) { 3089 Checkout.store.shipping.set(newAddress); 3090 } 3091 this.modalShow.set(false); 3092 } 3093 } 3094 refreshAddress(address) { 3095 const detailsTextElement = this.element.querySelector(".elSavedDetailsText"); 3096 const detailsIconElement = this.element.querySelector(".elSavedDetailsIcon"); 3097 if (address && address.address) { 3098 const formattedText = addressToString(address); 3099 detailsTextElement.innerHTML = formattedText; 3100 detailsTextElement.classList.remove("elError"); 3101 detailsIconElement.classList.remove("elError"); 3102 } 3103 } 3104 getModal() { 3105 return this.getComponent("Modal/V1"); 3106 } 3107 getOpenModalButton() { 3108 return this.element.querySelector(".elSavedDetailsEdit"); 3109 } 3110 showModal() { 3111 this.getModal().element.style.display = "flex"; 3112 } 3113 hideModal() { 3114 this.getModal().element.style.display = "none"; 3115 } 3116 getSavedAddressForm() { 3117 return this.getComponent("CheckoutSavedAddressForm/V1"); 3118 } 3119 getButtonElement() { 3120 return this.getModal().element.querySelector(".elButton"); 3121 } 3122 getCloseButton() { 3123 return this.getModal().element.querySelector(".elCheckoutModalFormClose"); 3124 } 3125 getSavedContainerWrapper() { 3126 return this.element.querySelector(".elCheckoutSavedContactDetailsWrapper"); 3127 } 3128 showContactDetails() { 3129 return this.getSavedContainerWrapper().getAttribute("data-show-contact-details"); 3130 } 3131 setShowContactDetails(value) { 3132 this.getSavedContainerWrapper().setAttribute("data-show-contact-details", value); 3133 } 3134}; 3135registerComponent("CheckoutSavedContactDetails/V1", CheckoutSavedContactDetailsV1); 3136window["CheckoutSavedContactDetailsV1"] = CheckoutSavedContactDetailsV1; 3137
3138// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/checkout-saved-multiple-payments-v1.ts 3139init_define_process(); 3140init_modal_v1(); 3141init_runtime(); 3142var CheckoutSavedMultiplePaymentsV1 = class extends CF2Component { 3143 constructor(el, runtimeSel) { 3144 super(el, runtimeSel); 3145 } 3146 mount() { 3147 this.paymentSelect = this.element.querySelector('[name="payment_method"]'); 3148 this.paymentSelect.addEventListener("change", (evt) => { 3149 evt.preventDefault(); 3150 const paymentId = evt.target.value == "new-payment" ? null : evt.target.value; 3151 Checkout.store.payment.id.set(paymentId); 3152 }); 3153 if (this.paymentSelect.value == "new-payment") { 3154 const multiplePaymentsWrapper = this.element.querySelector(".elCheckoutMultiplePaymentsWrapper"); 3155 multiplePaymentsWrapper.classList.remove("elHide"); 3156 } 3157 Checkout.computed.paymentMethod.listen((paymentMethod) => { 3158 const multiplePaymentsWrapper = this.element.querySelector(".elCheckoutMultiplePaymentsWrapper"); 3159 this.paymentMethod = paymentMethod; 3160 if (paymentMethod) { 3161 multiplePaymentsWrapper.classList.add("elHide"); 3162 } else { 3163 multiplePaymentsWrapper.classList.remove("elHide"); 3164 } 3165 }); 3166 Checkout.store.paymentMethods.listen((payment_methods) => { 3167 this.contact = { 3168 payment_methods 3169 }; 3170 this.rerenderSelect(); 3171 }); 3172 Checkout.store.payment.state.listen((state) => { 3173 if (state == Checkout.PaymentStates.LOADING) { 3174 this.showLoader(); 3175 } else if (state == Checkout.PaymentStates.INITIALIZED) { 3176 this.hideLoader(); 3177 } 3178 }); 3179 } 3180 showLoader() { 3181 this.element.querySelector(".elPAISavedLoader").dataset.loader = true; 3182 } 3183 hideLoader() { 3184 this.element.querySelector(".elPAISavedLoader").dataset.loader = false;
3185 } 3186 rerenderSelect() { 3187 const selectedId = Checkout.store.payment.id.get(); 3188 this.paymentSelect.innerHTML = ` 3189 ${this.contact.payment_methods.map((payment_method) => { 3190 const checked = payment_method.id === selectedId; 3191 let label = ""; 3192 if (payment_method.type === "payment-card") { 3193 label = payment_method.details; 3194 } else if (payment_method.type === "paypal") { 3195 label = `Paypal - ${payment_method.details}`; 3196 } else if (payment_method.type === "Klarna") { 3197 label = `Klarna - ${payment_method.details}`; 3198 } 3199 return `<option value="${payment_method.id}" ${checked ? "checked" : ""}> ${label} </option>`; 3200 })} 3201 <option value="new-payment">${this.checkoutSavedMultiplePaymentsTexts.addNewPaymentMethod}</option> 3202 `; 3203 } 3204}; 3205registerComponent("CheckoutSavedMultiplePayments/V1", CheckoutSavedMultiplePaymentsV1); 3206window["CheckoutSavedMultiplePaymentsV1"] = CheckoutSavedMultiplePaymentsV1; 3207
3208// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/rebilly-checkout.ts 3209init_define_process(); 3210
3211// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-summary.ts 3212init_define_process(); 3213init_general(); 3214
3215// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-machine.ts 3216init_define_process(); 3217
3218// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-digital-wallet.ts 3219init_define_process(); 3220var _CheckoutDigitalWallet_static, updateRebillyWithCallback_fn; 3221var CheckoutDigitalWallet = class { 3222 static initialize() { 3223 globalThis.Rebilly.on("token-ready", (data, extraData) => { 3224 const paymentType = globalThis.Checkout.store.payment.type.get(); 3225 const paymentMethod = data.method; 3226 const paymentInstrumentMethod = data.paymentInstrument?.type; 3227 CheckoutSummary.skipOrderSummaryUpdateWithCb(() => { 3228 if (paymentMethod == "digital-wallet" && paymentInstrumentMethod == "Apple Pay") { 3229 let rebillyShippingAddress; 3230 const shippingAddress = extraData?.shippingDetails?.address; 3231 const billingAddress = data.billingAddress; 3232 if (globalThis.Checkout.computed.hasPhysicalProducts.get()) { 3233 rebillyShippingAddress = { 3234 address: shippingAddress.addressLines?.[0], 3235 address_2: shippingAddress.addressLines?.[1], 3236 country: shippingAddress.countryCode.toUpperCase(), 3237 city: shippingAddress.locality, 3238 zip: shippingAddress.postalCode, 3239 state: shippingAddress.administrativeArea 3240 }; 3241 } 3242 const rebillyBillingAddress = { 3243 address: billingAddress.address, 3244 address_2: billingAddress.address2, 3245 country: billingAddress.country.toUpperCase(), 3246 city: billingAddress.city, 3247 zip: billingAddress.postalCode, 3248 state: billingAddress.region 3249 }; 3250 const payload = CheckoutSubmit.buildPayloadFromStore({ 3251 contact: this.getContact(shippingAddress, billingAddress), 3252 turnstileToken: globalThis.Checkout.turnstileToken, 3253 shippingAddress: rebillyShippingAddress, 3254 billingAddress: rebillyBillingAddress, 3255 paymentMethodDetails: { 3256 payment_method_id: null, 3257 payment_method_type: "apple-pay", 3258 rebilly_token: data.id 3259 }, 3260 selectedShippingOption: this.transactionShippingOption ?? {}, 3261 skipBillingAddress: false 3262 }); 3263 CheckoutSubmit.submit(payload); 3264 } else { 3265 globalThis.Checkout.store.payment[paymentType].token.set(data.id); 3266 } 3267 }); 3268 }); 3269 globalThis.Rebilly.on("shipping-address-changed", (shippingAddress, updateShippingOptions) => { 3270 this.transactionShipping = { 3271 address: shippingAddress.addressLines?.[0], 3272 address_2: shippingAddress.addressLines?.[1], 3273 country: shippingAddress.countryCode.toUpperCase(), 3274 city: shippingAddress.locality, 3275 zip: shippingAddress.postalCode, 3276 state: shippingAddress.administrativeArea 3277 }; 3278 __privateMethod(this, _CheckoutDigitalWallet_static, updateRebillyWithCallback_fn).call(this, updateShippingOptions); 3279 }); 3280 globalThis.Rebilly.on("shipping-option-changed", (selectedShippingOption, updateTransaction) => { 3281 CheckoutSummary.skipOrderSummaryUpdateWithCb(() => { 3282 this.transactionShippingOption = this.shippingOptions.find( 3283 (s) => CheckoutSubmit.generateShippingOptionId(s) == selectedShippingOption.id 3284 ); 3285 }); 3286 __privateMethod(this, _CheckoutDigitalWallet_static, updateRebillyWithCallback_fn).call(this, updateTransaction); 3287 }); 3288 globalThis.Rebilly.on("billing-address-changed", (billingAddress, updateTransaction) => { 3289 if (billingAddress) { 3290 this.transactionBilling = { 3291 address: billingAddress.addressLines?.[0], 3292 address_2: billingAddress.addressLines?.[1], 3293 country: billingAddress.countryCode.toUpperCase(), 3294 city: billingAddress.locality, 3295 zip: billingAddress.postalCode, 3296 state: billingAddress.administrativeArea 3297 }; 3298 } 3299 __privateMethod(this, _CheckoutDigitalWallet_static, updateRebillyWithCallback_fn).call(this, updateTransaction); 3300 }); 3301 } 3302 static getContact(shippingAddress, billingAddress) { 3303 if (globalThis.Checkout.store.checkout.mode.get() == "guest" && numberOfStepsInCheckout() == 1) { 3304 const { emailAddress: shippingEmail, familyName: shippingLN, givenName: shippingFN } = shippingAddress ?? {}; 3305 const { firstName: billingFN, lastName: billingLN } = billingAddress; 3306 if (globalThis.sessionData.contact.email) { 3307 const { email, first_name, last_name, phone_number } = globalThis.sessionData.contact; 3308 return { 3309 email, 3310 first_name, 3311 last_name, 3312 phone_number 3313 }; 3314 } else { 3315 return { 3316 email: shippingEmail, 3317 first_name: [shippingFN, billingFN].find(Boolean), 3318 last_name: [shippingLN, billingLN].find(Boolean), 3319 phone_number: globalThis.Checkout.store.contact.get().phone_number 3320 }; 3321 } 3322 } 3323 return globalThis.Checkout.store.contact.get(); 3324 } 3325}; 3326_CheckoutDigitalWallet_static = new WeakSet(); 3327updateRebillyWithCallback_fn = function(updateCallback) { 3328 const cart = globalThis.Checkout.computed.checkoutCart.get(); 3329 const shippingEnabled = hasPhysicalProducts(cart); 3330 CheckoutSummary.fetchOrderSummaryForExpress(cart, { 3331 billingAddress: this.transactionBilling ?? {}, 3332 shippingAddress: this.transactionShipping ?? (shippingEnabled ? this.transactionBilling : {}) ?? {}, 3333 shippingOption: this.transactionShippingOption ?? {}, 3334 billingSameAsShipping: false 3335 }).then(({ summary, data }) => { 3336 const { shipping_quotes_response } = summary; 3337 this.shippingOptions = shipping_quotes_response?.options ?? []; 3338 const transactionData = CheckoutSubmit.buildDigitalWalletTransactionData( 3339 data, 3340 cart, 3341 shippingEnabled, 3342 this.shippingOptions 3343 ); 3344 updateCallback(transactionData); 3345 }).catch((e) => { 3346 console.error(e); 3347 updateCallback({ status: "fail" }); 3348 }); 3349}; 3350__privateAdd(CheckoutDigitalWallet, _CheckoutDigitalWallet_static); 3351__publicField(CheckoutDigitalWallet, "transactionShipping"); 3352__publicField(CheckoutDigitalWallet, "transactionShippingOption"); 3353__publicField(CheckoutDigitalWallet, "transactionBilling"); 3354__publicField(CheckoutDigitalWallet, "shippingOptions"); 3355__publicField(CheckoutDigitalWallet, "totalSteps"); 3356
3357// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-paypal.ts 3358init_define_process(); 3359var paypalApproved = () => globalThis.Checkout.store.payment.paypal.state.get()?.state == PaypalStates.PAYMENT_METHOD_APPROVED && !!globalThis.Checkout.store.payment.paypal.token.get(); 3360var resetPaypalErrorState = () => { 3361 if (paypalApproved()) return; 3362 globalThis.Checkout.store.payment.paypal.state.set({ state: PaypalStates.INITIALIZED }); 3363}; 3364var buildPaypalCallbacks = () => ({ 3365 onInit: () => { 3366 console.log("[PayPal] - onInit called"); 3367 if (paypalApproved()) return; 3368 globalThis.Checkout.store.payment.paypal.state.set({ state: PaypalStates.INITIALIZED }); 3369 }, 3370 onApprove: (data, actions) => { 3371 console.log("[PayPal] - onApprove called", data, actions); 3372 globalThis.Checkout.store.payment.paypal.state.set({ 3373 state: PaypalStates.PAYMENT_METHOD_APPROVED 3374 }); 3375 }, 3376 onError: (data, actions) => { 3377 console.log("[PayPal] - onError called", data, actions); 3378 if (paypalApproved()) return; 3379 globalThis.Checkout.store.payment.paypal.state.set({ 3380 state: PaypalStates.ERROR, 3381 code: ErrorTypes.PAYPAL_CUSTOM_ERROR, 3382 message: "Something unexpected happened" 3383 }); 3384 }, 3385 onCancel: (data, actions) => { 3386 console.log("[PayPal] - onCancel called", data, actions); 3387 if (paypalApproved()) return; 3388 globalThis.Checkout.store.payment.paypal.state.set({ 3389 state: PaypalStates.ERROR, 3390 code: ErrorTypes.PAYPAL_DECLINED_ERROR 3391 }); 3392 }, 3393 onClick: (data, actions) => { 3394 console.log("[PayPal] - onClick called", data, actions); 3395 if (paypalApproved()) return; 3396 globalThis.Checkout.store.payment.paypal.state.set({ 3397 state: PaypalStates.ADDING_PAYMENT_METHOD 3398 }); 3399 } 3400}); 3401
3402// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-machine.ts 3403init_nanostores(); 3404init_fetcher(); 3405var INITIALIAZE_PAI_TIMEOUT = 6e4; 3406var FRAMEPAY_SCRIPT_URL = "https://framepay.payments.ai/rebilly.js"; 3407var FRAMEPAY_CSS_URL = "https://framepay.payments.ai/rebilly.css"; 3408var TimeoutError = class extends Error { 3409}; 3410var buildPAIContext = (extra = {}) => ({ 3411 phase: "pai-init", 3412 visibilityState: typeof document !== "undefined" ? document.visibilityState : null, 3413 pageUrl: typeof location !== "undefined" ? location.href : null, 3414 rebillyLoaded: !!globalThis.Rebilly, 3415 rebillyInitialized: !!globalThis.Rebilly?.initialized, 3416 ...extra 3417}); 3418var buildPAIError = (code, cause, extraContext = {}) => { 3419 const error = new CheckoutCriticalError(code, { cause }); 3420 error.context = buildPAIContext(extraContext); 3421 return error; 3422}; 3423var extractRebillyErrorFields = (e) => ({ 3424 rebillyErrorCode: e?.code ?? e?.data?.code ?? null, 3425 rebillyErrorMessage: e?.data?.message ?? e?.message ?? null 3426}); 3427var loadPAIDeps = (addLoader = true) => { 3428 if (globalThis.Rebilly?.initialized) return Promise.resolve(); 3429 if (globalThis.Checkout.store.payment.state.get() != globalThis.Checkout.PaymentStates.START) return void 0; 3430 const startedAt = performance.now(); 3431 globalThis.Checkout.store.payment.state.set(globalThis.Checkout.PaymentStates.INITIALIZING); 3432 if (addLoader) globalThis.Checkout.store.payment.state.set(globalThis.Checkout.PaymentStates.LOADING); 3433 const js = document.createElement("script"); 3434 js.src = FRAMEPAY_SCRIPT_URL; 3435 const onFailure = () => { 3436 resetPAIConfigState(); 3437 globalThis.Checkout.store.payment.state.set(globalThis.Checkout.PaymentStates.START); 3438 }; 3439 const promise = new Promise((resolve, reject) => { 3440 js.onload = () => { 3441 const scriptLoadMs = Math.round(performance.now() - startedAt); 3442 intializePAI().then(() => { 3443 const summary = globalThis.Checkout.store.summary.get(); 3444 const cart = globalThis.Checkout.computed.checkoutCart.get(); 3445 const summaryData = summary.data?.line_items?.length ? summary.data : CheckoutSummary.lastPreviewedSummary; 3446 return CheckoutSummary.updateRebillyTransactionDataPromise(summaryData, cart).then(() => { 3447 resolve(); 3448 }); 3449 }).catch((e) => { 3450 const retries = initializePAIConfigRetries; 3451 const isPaiInitFailure = !(e instanceof CheckoutCriticalError) || e.context?.phase === "pai-init"; 3452 if (isPaiInitFailure) { 3453 onFailure(); 3454 } 3455 const elapsedMs = Math.round(performance.now() - startedAt); 3456 if (e instanceof CheckoutCriticalError) { 3457 if (e.context?.phase === "pai-init") { 3458 e.context = { ...e.context, elapsedMs, scriptLoadMs, retries }; 3459 } 3460 reject(e); 3461 return; 3462 } 3463 const errorType = e instanceof TimeoutError ? ERROR_CODES.PAI_INITIALIZATION_TIMEOUT_ERROR : ERROR_CODES.UNEXPECTED_INITIALIZATION_ERROR; 3464 reject( 3465 buildPAIError(errorType, e, { 3466 elapsedMs, 3467 scriptLoadMs, 3468 retries, 3469 ...extractRebillyErrorFields(e) 3470 }) 3471 ); 3472 }); 3473 }; 3474 js.onerror = () => { 3475 const retries = initializePAIConfigRetries; 3476 const elapsedMs = Math.round(performance.now() - startedAt); 3477 onFailure(); 3478 reject( 3479 buildPAIError(ERROR_CODES.PAI_INITIALIZATION_SCRIPT_ERROR, new Error("framepay JS onError load"), { 3480 elapsedMs, 3481 retries, 3482 scriptSrc: FRAMEPAY_SCRIPT_URL 3483 }) 3484 ); 3485 }; 3486 }); 3487 document.head.appendChild(js); 3488 const css = document.createElement("link"); 3489 css.href = FRAMEPAY_CSS_URL; 3490 css.rel = "stylesheet"; 3491 document.head.appendChild(css); 3492 return promise; 3493}; 3494var resetPAIConfigState = () => { 3495 initializePAIConfigPromise = void 0; 3496 if (initializePAIConfigNetworkTimeout) { 3497 clearTimeout(initializePAIConfigNetworkTimeout); 3498 initializePAIConfigNetworkTimeout = void 0; 3499 } 3500 initializePAIConfigRetries = 0; 3501}; 3502var initializeTurnstile = () => { 3503 const turnstilejs = document.createElement("script"); 3504 turnstilejs.src = "https://challenges.cloudflare.com/turnstile/v0/api.js"; 3505 turnstilejs.onload = () => {
3506 const key = window.turnstileSiteKey; 3507 window.turnstile.render("#cf-turnstile", { 3508 sitekey: key, 3509 callback: function(token) { 3510 globalThis.Checkout.turnstileToken = token; 3511 } 3512 }); 3513 }; 3514 turnstilejs.onerror = (e) => { 3515 console.error("Turnstile error", e); 3516 }; 3517 document.head.appendChild(turnstilejs); 3518}; 3519function toPascalCase(kebabCase) { 3520 return kebabCase.replace(/(^\w|-\w)/g, (text) => { 3521 return text.replace(/-/, "").toUpperCase(); 3522 }); 3523} 3524var rebillyErrorClasses = {}; 3525var hasGeneratedRebillyErrorClasses; 3526function generateRebillyErrorClasses() { 3527 if (hasGeneratedRebillyErrorClasses) return; 3528 hasGeneratedRebillyErrorClasses = true; 3529 const errorGenerator = (name) => ({ 3530 [name]: class extends Error { 3531 constructor(data) { 3532 super(); 3533 __publicField(this, "data"); 3534 this.data = data; 3535 } 3536 } 3537 })[name]; 3538 Object.values(globalThis.Rebilly.errorCodes).forEach((errorCode) => { 3539 const errorClassName = toPascalCase(errorCode); 3540 rebillyErrorClasses[errorClassName] = errorGenerator(errorClassName); 3541 }); 3542} 3543var initializePAIConfigPromise; 3544var initializePAIConfigNetworkTimeout; 3545var initializePAIConfigRetries = 0; 3546var initializePAIConfig = (rebillyConfig) => { 3547 if (initializePAIConfigPromise) return initializePAIConfigPromise; 3548 initializePAIConfigPromise = new Promise((resolve, reject) => { 3549 let timeout = null; 3550 const armTimeout = () => { 3551 if (timeout) clearTimeout(timeout); 3552 timeout = setTimeout(() => { 3553 reject(new TimeoutError(`Timeout error: Rebilly took more than ${INITIALIAZE_PAI_TIMEOUT}ms to load`)); 3554 }, INITIALIAZE_PAI_TIMEOUT); 3555 }; 3556 const cancelTimeout = () => { 3557 if (timeout) clearTimeout(timeout); 3558 timeout = null; 3559 }; 3560 armTimeout(); 3561 globalThis.Rebilly.on("ready", () => { 3562 if (initializePAIConfigNetworkTimeout) clearTimeout(initializePAIConfigNetworkTimeout); 3563 cancelTimeout(); 3564 try { 3565 globalThis.Checkout.store.payment.state.set(globalThis.Checkout.PaymentStates.INITIALIZED); 3566 resolve(); 3567 } catch (e) { 3568 reject(e); 3569 } 3570 }); 3571 globalThis.Rebilly.on("error", (rebillyError) => { 3572 generateRebillyErrorClasses(); 3573 const errorClassName = rebillyError.code && typeof rebillyError.code == "string" ? toPascalCase(rebillyError.code) : null; 3574 if (!errorClassName || !rebillyErrorClasses[errorClassName]) { 3575 cancelTimeout(); 3576 reject(rebillyError); 3577 return; 3578 } 3579 const error = new rebillyErrorClasses[errorClassName](rebillyError); 3580 if (rebillyError.code == "network-error") { 3581 if (initializePAIConfigRetries < 5) { 3582 armTimeout(); 3583 initializePAIConfigNetworkTimeout = setTimeout(() => { 3584 globalThis.Rebilly.initialize(rebillyConfig); 3585 initializePAIConfigRetries++; 3586 }, 2e3 * initializePAIConfigRetries); 3587 } else { 3588 cancelTimeout(); 3589 reject(error); 3590 } 3591 } else if (rebillyError.code == "already-initialized") { 3592 cancelTimeout(); 3593 resolve(); 3594 } else { 3595 cancelTimeout(); 3596 reject(error); 3597 } 3598 }); 3599 }); 3600 globalThis.Rebilly.initialize(rebillyConfig); 3601 return initializePAIConfigPromise; 3602}; 3603var intializePAI = () => { 3604 globalThis.Checkout.PaypalCallbacks = buildPaypalCallbacks(); 3605 const checkoutElement = document.querySelector('[data-page-element="Checkout/V2"]'); 3606 const checkoutComponent = checkoutElement.cf2_instance; 3607 const inputColor = getComputedStyle(checkoutElement).getPropertyValue("--input-color"); 3608 const fontFamily = getComputedStyle(checkoutElement).getPropertyValue("--multiple-payments-font-family"); 3609 const fontSize = getComputedStyle(checkoutElement).getPropertyValue("--multiple-payments-font-size"); 3610 const rebillyKeys = document.getElementById("payment-gateway-keys"); 3611 if (!rebillyKeys) { 3612 return Promise.reject( 3613 buildPAIError(ERROR_CODES.PAI_INITIALIZATION_CONFIG_ERROR, new Error("payment-gateway-keys element not found")) 3614 ); 3615 } 3616 const publishableKey = rebillyKeys.getAttribute("data-rebilly-publishable-key"); 3617 const organizationId = rebillyKeys.getAttribute("data-rebilly-organization-id");
3618 const websiteId = rebillyKeys.getAttribute("data-rebilly-website-id"); 3619 const currency = rebillyKeys.getAttribute("data-rebilly-currency"); 3620 if (!publishableKey) { 3621 return Promise.reject( 3622 buildPAIError(ERROR_CODES.PAI_INITIALIZATION_CONFIG_ERROR, new Error("Missing required Rebilly publishable key"), { 3623 hasPublishableKey: !!publishableKey, 3624 hasOrganizationId: !!organizationId, 3625 hasWebsiteId: !!websiteId 3626 }) 3627 ); 3628 } 3629 const placeholders = checkoutComponent.cardPaymentPlaceholders; 3630 const rebillyConfig = { 3631 publishableKey, 3632 organizationId, 3633 kountAccountId: "700000", 3634 // This is for capturing kount fraud sessions 3635 websiteId, 3636 // NOTE: need to add below otherwise this error happens: transactionData must contain an amount to fetch methods 3637 transactionData: { 3638 currency: currency || "USD", 3639 amount: 1, 3640 label: "Product Purchase" 3641 }, 3642 icon: { 3643 color: inputColor 3644 }, 3645 style: { 3646 base: { 3647 color: inputColor, 3648 fontFamily, 3649 fontSize, 3650 "::placeholder": { 3651 color: inputColor, 3652 fontFamily, 3653 fontSize 3654 } 3655 } 3656 }, 3657 placeholders: { 3658 card: { 3659 number: placeholders.number, 3660 ...placeholders.expiration.includes("/") ? { 3661 expirationSeparator: "/", 3662 expirationMonth: placeholders.expiration.split("/")[0], 3663 expirationYear: placeholders.expiration.split("/")[1] 3664 } : { 3665 expiration: placeholders.expiration 3666 }, 3667 cvv: placeholders.cvv 3668 } 3669 } 3670 }; 3671 CheckoutDigitalWallet.initialize(); 3672 return initializePAIConfig(rebillyConfig); 3673}; 3674var initializeCountries = (options) => { 3675 return globalThis.CFFetch( 3676 "/cf_countries_states.json", 3677 { 3678 headers: { "Content-Type": "application/json" } 3679 }, 3680 { retries: 3, shouldCaptureServerError: true } 3681 ).then(function(res) { 3682 return res.json(); 3683 }).catch((e) => { 3684 throw new CheckoutCriticalError(ERROR_CODES.FETCH_COUNTRIES_STATES_ERROR, { 3685 cause: e 3686 }); 3687 }).then((countryStateReqResponse) => { 3688 globalThis.Checkout.allCountries = countryStateReqResponse.result; 3689 const defaultCountryCode = "US"; 3690 const countryData = globalThis.Checkout.allCountries.find((c) => c.iso2 == globalThis.cfVisitorData.country) ?? globalThis.Checkout.allCountries.find((c) => c.iso2 == defaultCountryCode); 3691 const stateData = countryData.regions?.find((r) => r.iso2 == globalThis.cfVisitorData.regionCode) ?? countryData.regions?.[0]; 3692 const country = countryData.iso2; 3693 const state = stateData?.state_code; 3694 globalThis.Checkout.contactLocale = { 3695 country, 3696 state 3697 }; 3698 const initialShipping = globalThis.Checkout.store.shipping.get(); 3699 globalThis.Checkout.store.shipping.set({ 3700 ...initialShipping ?? {}, 3701 country: initialShipping?.country ?? country, 3702 state: initialShipping?.state ?? state 3703 }); 3704 let initialBilling = globalThis.Checkout.store.billing.get(); 3705 if (globalThis.Checkout.store.checkout.mode.get() == "guest") { 3706 initialBilling = parseAddressByFields(initialBilling, options.billingFields); 3707 } 3708 globalThis.Checkout.store.billing.set(initialBilling); 3709 globalThis.Checkout.store.phoneNumberInitialized.set(true); 3710 }); 3711}; 3712var checkFeatureFlags = () => { 3713 return CFFetch("/user_pages/api/v1/checkouts/feature_flags.json", {}, { retries: 3, shouldCaptureServerError: true }).then((res) => { 3714 return res.json(); 3715 }).then((res) => { 3716 globalThis.Checkout.store.featureFlags.isShippingEnabled.set(res.feature_flags.is_shipping_enabled); 3717 }).catch((e) => { 3718 throw new CheckoutCriticalError(ERROR_CODES.FETCH_FEATURE_FLAGS_ERROR, { 3719 cause: e 3720 }); 3721 }); 3722}; 3723var initializeMachine = (options) => { 3724 globalThis.Checkout.store.state.listen((newState) => { 3725 switch (newState) { 3726 case globalThis.Checkout.StoreStates.INITIALIZING: { 3727 const isGuest = globalThis.Checkout.store.checkout.mode.get() == "guest"; 3728 const isSaved = globalThis.Checkout.store.checkout.mode.get() == "saved"; 3729 const isOTO = globalThis.Checkout.store.checkout.mode.get() == "oto"; 3730 const paymentMethods = globalThis.Checkout.store.paymentMethods.get(); 3731 const oneStepCheckout = document.querySelector('[data-page-element="Checkout/V2"][data-total-steps="1"]'); 3732 const expressPaymentAvailable = globalThis.globalResourceData.expressEnabledPayments && globalThis.globalResourceData.expressEnabledPayments.length > 0; 3733 const shouldIntializePAI = oneStepCheckout && isGuest || !paymentMethods.length && (isSaved || isOTO) || expressPaymentAvailable && isSaved;
3734 const shouldInitializeTurnstile = window.turnstileSiteKey && window.turnstileSiteKey.length; 3735 if (shouldInitializeTurnstile) initializeTurnstile(); 3736 Promise.all( 3737 [ 3738 checkFeatureFlags(), 3739 shouldIntializePAI && loadPAIDeps(false), 3740 initializeCountries(options), 3741 !isGuest && Object.keys(globalThis.Checkout.productsById).length > 0 && CheckoutExistingOrders.fetch() 3742 ].filter((v) => !!v) 3743 ).then(() => { 3744 globalThis.Checkout.store.state.set(globalThis.Checkout.StoreStates.INITIALIZED); 3745 }).catch((e) => { 3746 if (e instanceof CheckoutCriticalError) { 3747 displayAndLogCriticalError(e); 3748 } else { 3749 const initializationError = new CheckoutCriticalError(ERROR_CODES.UNEXPECTED_INITIALIZATION_ERROR, { 3750 cause: e 3751 }); 3752 displayAndLogCriticalError(initializationError); 3753 } 3754 }); 3755 break; 3756 } 3757 case globalThis.Checkout.StoreStates.INITIALIZED: { 3758 CheckoutSummary.sendOrderPreview(); 3759 setTimeout(() => { 3760 globalThis.Checkout.store.state.set(globalThis.Checkout.StoreStates.FILLING_FORM); 3761 }); 3762 break; 3763 } 3764 case globalThis.Checkout.StoreStates.FILLING_FORM: { 3765 break; 3766 } 3767 case globalThis.Checkout.StoreStates.SUBMITTED: { 3768 break; 3769 } 3770 } 3771 }); 3772 globalThis.Checkout.store.submitting.listen((submitting) => { 3773 const state = submitting.state; 3774 switch (state) { 3775 case globalThis.Checkout.SubmittingStates.ERROR: { 3776 globalThis.Checkout.store.state.set(globalThis.Checkout.StoreStates.FILLING_FORM); 3777 break; 3778 } 3779 case globalThis.Checkout.SubmittingStates.DONE: { 3780 globalThis.Checkout.store.state.set(globalThis.Checkout.StoreStates.SUBMITTED); 3781 break; 3782 } 3783 } 3784 }); 3785 globalThis.Checkout.store.billing.listen((billing) => { 3786 const fields = globalThis.Checkout.store.billingFields.get(); 3787 const addressFields = fieldsForCountry(fields, billing.country); 3788 globalThis.Checkout.store.billingFields.set(addressFields); 3789 }); 3790 globalThis.Checkout.store.payment.paypal.state.listen((submitting) => { 3791 const state = submitting.state; 3792 switch (state) { 3793 case globalThis.Checkout.PaypalStates.ERROR: { 3794 setTimeout(resetPaypalErrorState, 3e3); 3795 break; 3796 } 3797 } 3798 }); 3799 globalThis.Checkout.store.checkout.mode.listen((mode) => { 3800 if (mode === "guest") { 3801 const cart = globalThis.Checkout.computed.checkoutCart.get(); 3802 CheckoutExistingOrders.clearUpdatableOrders(cart.items[0]?.product_id); 3803 globalThis.Checkout.store.contact.set({}); 3804 globalThis.Checkout.store.shipping.set({ 3805 country: globalThis.Checkout.contactLocale.country, 3806 state: globalThis.Checkout.contactLocale.state 3807 }); 3808 const newBillingData = parseAddressByFields(globalThis.Checkout.contactLocale, options.billingFields); 3809 globalThis.Checkout.store.billing.set(newBillingData); 3810 globalThis.Checkout.store.payment.id.set(null); 3811 } 3812 }); 3813 globalThis.Checkout.store.payment.id.listen((newPaymentId) => { 3814 if (!newPaymentId) loadPAIDeps()?.catch((e) => displayAndLogCriticalError(e)); 3815 }); 3816 globalThis.Checkout.computed.isOTORetrialPayment.listen((isOTORetrialPayment) => { 3817 if (isOTORetrialPayment) loadPAIDeps()?.catch((e) => displayAndLogCriticalError(e)); 3818 }); 3819 const checkoutStatesChangedByCartItems = { 3820 [globalThis.Checkout.CheckoutStates.UPGRADE_DOWNGRADE]: true, 3821 [globalThis.Checkout.CheckoutStates.REACTIVATE]: true 3822 }; 3823 computed([globalThis.Checkout.computed.modeLeaveEnterEvent, globalThis.Checkout.store.state], (ev, state) => { 3824 if ([globalThis.Checkout.StoreStates.START, globalThis.Checkout.StoreStates.INITIALIZING].includes(state)) return; 3825 const { enter } = ev; 3826 if (enter && !checkoutStatesChangedByCartItems[enter]) { 3827 globalThis.Checkout.store.checkout.lastModeIndependentOfCartItems.set(enter); 3828 } 3829 const oneStepCheckout = document.querySelector('[data-page-element="Checkout/V2"][data-total-steps="1"]'); 3830 if (enter === "guest" && oneStepCheckout) { 3831 loadPAIDeps()?.catch((e) => displayAndLogCriticalError(e)); 3832 } 3833 if (enter === "saved") { 3834 const contactPaymentMethod = globalThis.Checkout.store.paymentMethods.get(); 3835 if (!contactPaymentMethod?.length) { 3836 loadPAIDeps()?.catch((e) => displayAndLogCriticalError(e)); 3837 } 3838 } 3839 }).subscribe(() => { 3840 }); 3841 globalThis.Checkout.computed.checkoutCart.listen((cart) => { 3842 const currentMode = globalThis.Checkout.store.checkout.mode.get();
3843 let cartState; 3844 cart.items.forEach(({ type }) => { 3845 if (type) { 3846 if (cartState) { 3847 throw new Error(`Cart has more than one item of type ${type}`); 3848 } 3849 cartState = type; 3850 } 3851 }); 3852 if (cartState && cartState != currentMode) { 3853 globalThis.Checkout.store.checkout.mode.set(cartState); 3854 } else if (!cartState && [globalThis.Checkout.CheckoutStates.UPGRADE_DOWNGRADE, globalThis.Checkout.CheckoutStates.REACTIVATE].includes( 3855 currentMode 3856 )) { 3857 const lastModeIndependentOfCartItems = globalThis.Checkout.store.checkout.lastModeIndependentOfCartItems.get(); 3858 if (lastModeIndependentOfCartItems && lastModeIndependentOfCartItems != currentMode) { 3859 globalThis.Checkout.store.checkout.mode.set(lastModeIndependentOfCartItems); 3860 } 3861 } 3862 }); 3863 let lastBilling; 3864 globalThis.Checkout.store.billing.listen((billing) => { 3865 if (globalThis.Checkout.store.billingApiErrorsByField.get()) globalThis.Checkout.store.billingApiErrorsByField.set(); 3866 const backfilledBillingFromApi = options.billingFields.length == 2 && Object.keys(billing).length > 2; 3867 const updatedZipForSameAddress = !billing.id && lastBilling?.zip != billing.zip; 3868 if (backfilledBillingFromApi && updatedZipForSameAddress) { 3869 const newBillingAddress = { 3870 country: billing.country, 3871 zip: billing.zip 3872 }; 3873 globalThis.Checkout.store.billing.set(newBillingAddress); 3874 } 3875 lastBilling = billing; 3876 }); 3877}; 3878
3879// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/Services/checkout-summary.ts 3880init_fetcher(); 3881var PreviewError = class extends Error { 3882 constructor(message, details) { 3883 super(message); 3884 __publicField(this, "details"); 3885 this.name = this.constructor.name; 3886 this.details = details; 3887 if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor); 3888 } 3889}; 3890var orderPreviewFetcher = makeCurrentPageFetcher(); 3891var _sendOrderPreviewTimer, _lastOrderPreviewData, _lastRebillyUpdate, _couponStateBeforeApplying, _skipOrderSummaryUpdate, _previewPending, _lastPreviewedSummary, _CheckoutSummary_static, setLoadingShippingOptions_fn, validAddress_fn, backfillBillingAddress_fn, processOrderPreviewResponseForSummary_fn, buildRecurringSummary_fn, buildCartDetails_fn, buildOrderPreviewPayload_fn, buildAddressParams_fn; 3892var CheckoutSummary = class { 3893 static skipOrderSummaryUpdateWithCb(cb) { 3894 __privateSet(this, _skipOrderSummaryUpdate, true); 3895 cb(); 3896 __privateSet(this, _skipOrderSummaryUpdate, false); 3897 } 3898 static sendOrderPreview(options) { 3899 const cart = globalThis.Checkout.computed.checkoutCart.get(); 3900 const isCouponValidation = !!options?.isCouponValidation; 3901 const forceRebillyUpdate = !!options?.forceRebillyUpdate; 3902 const revalidateCoupon = !!options?.revalidateCoupon; 3903 if (__privateGet(this, _skipOrderSummaryUpdate)) { 3904 return; 3905 } 3906 if (!cart.items?.length) { 3907 if (globalThis.Checkout.store.coupons.appliedCode.get() || globalThis.Checkout.store.coupons.currentCode.get()) { 3908 globalThis.Checkout.store.coupons.appliedCode.set(""); 3909 globalThis.Checkout.store.coupons.currentCode.set(""); 3910 globalThis.Checkout.store.coupons.state.set(globalThis.Checkout.CouponStates.READY); 3911 } 3912 if (globalThis.Checkout.store.summary.get().state != globalThis.Checkout.SummaryStates.WAITING) { 3913 globalThis.Checkout.store.summary.set({ state: globalThis.Checkout.SummaryStates.WAITING }); 3914 } 3915 __privateSet(this, _lastOrderPreviewData, null); 3916 this.disableIsUpdatingRebilly(); 3917 return; 3918 } 3919 const billingFields = globalThis.Checkout.store.billingFields?.get(); 3920 const shippingFields = globalThis.Checkout.store.shippingFields?.get(); 3921 const checkoutResourcePage = globalThis.globalResourceData.resourceName == "checkout"; 3922 const shouldUpdateSummaryData = isCouponValidation || checkoutResourcePage || globalThis.Checkout.utils.hasValidDataForOrderPreview({ billingFields, shippingFields }); 3923 const hasDigitalPayment = globalThis.globalResourceData.enabledPayments.includes("apple-pay") || globalThis.globalResourceData.expressEnabledPayments.includes("apple-pay"); 3924 const shouldRevalidateAppliedCoupon = revalidateCoupon && !isCouponValidation && !!globalThis.Checkout.store.coupons.appliedCode.get(); 3925 if (!shouldUpdateSummaryData && !hasDigitalPayment) { 3926 if (globalThis.Checkout.store.summary.get().state != globalThis.Checkout.SummaryStates.WAITING) { 3927 globalThis.Checkout.store.summary.set({ state: globalThis.Checkout.SummaryStates.WAITING }); 3928 } 3929 __privateSet(this, _lastOrderPreviewData, null); 3930 if (!shouldRevalidateAppliedCoupon) return; 3931 } 3932 const dataToPreview = __privateMethod(this, _CheckoutSummary_static, buildOrderPreviewPayload_fn).call(this, cart, { 3933 billingAddress: globalThis.Checkout.store.billing.get(), 3934 shippingAddress: globalThis.Checkout.store.shipping.get(), 3935 shippingOption: globalThis.Checkout.store.shippingOption.get(), 3936 billingSameAsShipping: globalThis.Checkout.store.billingSameAsShipping.get() 3937 }, { 3938 skipBillingAddress: globalThis.Checkout.utils.skipBillingAddress(globalThis.Checkout.store) 3939 }); 3940 if (!isCouponValidation && deepEqual(dataToPreview, __privateGet(this, _lastOrderPreviewData))) { 3941 if (forceRebillyUpdate) { 3942 this.updateRebillyTransactionData(globalThis.Checkout.store.summary.get().data, cart, forceRebillyUpdate); 3943 } 3944 return; 3945 } 3946 if (__privateGet(this, _sendOrderPreviewTimer)) clearTimeout(__privateGet(this, _sendOrderPreviewTimer)); 3947 if (globalThis.Checkout.store.summary.get().state != globalThis.Checkout.SummaryStates.
3947CALCULATING) { 3948 if (globalThis.Checkout.store.payment.type.get() == "apple-pay") { 3949 globalThis.Checkout.store.isUpdatingRebilly.set(true); 3950 } 3951 if (shouldUpdateSummaryData) { 3952 globalThis.Checkout.store.summary.set({ state: globalThis.Checkout.SummaryStates.CALCULATING }); 3953 } 3954 } 3955 const couponStateBeforeApplying = globalThis.Checkout.store.coupons.state.get(); 3956 if (isCouponValidation && couponStateBeforeApplying != globalThis.Checkout.CouponStates.APPLYING) { 3957 __privateSet(this, _couponStateBeforeApplying, couponStateBeforeApplying); 3958 globalThis.Checkout.store.coupons.state.set(globalThis.Checkout.CouponStates.APPLYING); 3959 } 3960 const validShippingAddress = !!globalThis.Checkout.utils.hasValidDataForShippingOptions({ shippingFields }); 3961 const validBillingAddress = !!globalThis.Checkout.utils.hasValidDataForTaxes({ billingFields }); 3962 if (validShippingAddress) { 3963 __privateMethod(this, _CheckoutSummary_static, setLoadingShippingOptions_fn).call(this, dataToPreview); 3964 } 3965 clearTimeout(__privateGet(this, _sendOrderPreviewTimer)); 3966 __privateSet(this, _previewPending, true); 3967 __privateSet(this, _sendOrderPreviewTimer, setTimeout(() => { 3968 return this.fetchOrderPreview(cart, { 3969 shouldSetShippingOptions: validShippingAddress, 3970 shouldSetTax: validBillingAddress, 3971 shouldUpdateSummaryData 3972 }).catch((e) => { 3973 this.disableIsUpdatingRebilly(); 3974 throw e; 3975 }).finally(() => { 3976 __privateSet(this, _previewPending, false); 3977 }); 3978 }, 500)); 3979 } 3980 static async fetchOrderPreview(cart, options) { 3981 options = options ?? {}; 3982 const shouldUpdateSummaryData = options.shouldUpdateSummaryData ?? true; 3983 const dataToPreview = __privateMethod(this, _CheckoutSummary_static, buildOrderPreviewPayload_fn).call(this, cart, { 3984 billingAddress: globalThis.Checkout.store.billing.get(), 3985 shippingAddress: globalThis.Checkout.store.shipping.get(), 3986 shippingOption: globalThis.Checkout.store.shippingOption.get(), 3987 billingSameAsShipping: globalThis.Checkout.store.billingSameAsShipping.get() 3988 }, { 3989 skipBillingAddress: globalThis.Checkout.utils.skipBillingAddress(globalThis.Checkout.store) 3990 }); 3991 __privateSet(this, _lastOrderPreviewData, dataToPreview); 3992 const criticalErrors = globalThis.Checkout.store.criticalErrors.get(); 3993 globalThis.Checkout.store.criticalErrors.set([ 3994 ...criticalErrors.filter((error) => error.code != ERROR_CODES.ORDER_RECURRING_INTERVAL_MISMATCH) 3995 ]); 3996 const summaryData = await orderPreviewFetcher.post("/order_preview", dataToPreview); 3997 if (isResponseError(summaryData)) { 3998 if (isFetcherError(summaryData)) { 3999 const previewError = summaryData.error; 4000 const timedOut = previewError instanceof CFFetcherError && previewError.type == CFFetcherErrorTypes.TIMEOUT_ERROR; 4001 if (previewError != MANUALLY_ABORTED && !timedOut) { 4002 const errorData = summaryData; 4003 throw new PreviewError(errorData.error); 4004 } 4005 if (timedOut) { 4006 globalThis.Checkout.store.loadingShipping.set(false); 4007 this.disableIsUpdatingRebilly(); 4008 __privateSet(this, _lastOrderPreviewData, null); 4009 if (globalThis.Checkout.store.coupons.state.get() == globalThis.Checkout.CouponStates.APPLYING) { 4010 globalThis.Checkout.store.coupons.state.set(__privateGet(this, _couponStateBeforeApplying)); 4011 } 4012 if (shouldUpdateSummaryData) { 4013 globalThis.Checkout.store.summary.set({ state: globalThis.Checkout.SummaryStates.WAITING }); 4014 } 4015 } 4016 } else if (isBackendError(summaryData)) { 4017 globalThis.Checkout.store.loadingShipping.set(false); 4018 const error = summaryData.error; 4019 const errorDetails = error?.details?.[0]; 4020 let newSummaryState; 4021 if (errorDetails?.type == "InvalidPostalCodeError") { 4022 newSummaryState = { 4023 state: globalThis.Checkout.SummaryStates.WAITING 4024 }; 4025 globalThis.Checkout.store.showAllErrors.billing.set(true); 4026 globalThis.Checkout.store.billingApiErrorsByField.set({ zip: { message: errorDetails.message } }); 4027 this.disableIsUpdatingRebilly(); 4028 } else if (errorDetails?.type == "InvalidCouponError") { 4029 globalThis.Checkout.store.coupons.appliedCode.set(""); 4030 globalThis.Checkout.store.coupons.currentCode.set(""); 4031 globalThis.Checkout.store.coupons.errorMessage.set(errorDetails.message); 4032 globalThis.Checkout.store.coupons.state.set(globalThis.Checkout.CouponStates.ERROR); 4033 const summaryData2 = __privateMethod(this, _CheckoutSummary_static, processOrderPreviewResponseForSummary_fn).c
4033all(this, errorDetails.preview, { 4034 shouldSetShippingOptions: options?.shouldSetShippingOptions, 4035 shouldSetTax: options?.shouldSetTax 4036 }); 4037 newSummaryState = { 4038 state: globalThis.Checkout.SummaryStates.OK, 4039 data: summaryData2 4040 }; 4041 this.updateRebillyTransactionData(summaryData2, cart); 4042 } else { 4043 globalThis.Checkout.store.coupons.state.set(__privateGet(this, _couponStateBeforeApplying)); 4044 newSummaryState = { state: globalThis.Checkout.SummaryStates.ERROR }; 4045 if (errorDetails?.type == "RecurringMismatch") { 4046 const criticalErrors2 = globalThis.Checkout.store.criticalErrors.get(); 4047 globalThis.Checkout.store.criticalErrors.set([ 4048 ...criticalErrors2, 4049 { code: ERROR_CODES.ORDER_RECURRING_INTERVAL_MISMATCH } 4050 ]); 4051 } else if (errorDetails?.message) { 4052 newSummaryState = { 4053 state: globalThis.Checkout.SummaryStates.ERROR, 4054 error: { message: errorDetails?.message } 4055 }; 4056 } 4057 this.disableIsUpdatingRebilly(); 4058 } 4059 if (shouldUpdateSummaryData && newSummaryState) { 4060 globalThis.Checkout.store.summary.set(newSummaryState); 4061 } 4062 } 4063 } else { 4064 const { shipping_quotes_response, selected_shipping_option } = summaryData; 4065 if (options?.shouldSetShippingOptions) { 4066 this.skipOrderSummaryUpdateWithCb(() => { 4067 globalThis.Checkout.store.shippingOptions.set(shipping_quotes_response?.options ?? []); 4068 globalThis.Checkout.store.shippingOption.set(selected_shipping_option); 4069 globalThis.Checkout.store.loadingShipping.set(false); 4070 __privateMethod(this, _CheckoutSummary_static, backfillBillingAddress_fn).call(this, summaryData); 4071 }); 4072 } 4073 const reconciledCode = globalThis.Checkout.store.coupons.currentCode.get() || globalThis.Checkout.store.coupons.appliedCode.get(); 4074 const couponCodeApplied = summaryData.discounts?.find( 4075 (discount) => discount.code?.toUpperCase() == reconciledCode?.toUpperCase() 4076 ); 4077 if (couponCodeApplied) { 4078 globalThis.Checkout.store.coupons.appliedCode.set(reconciledCode); 4079 globalThis.Checkout.store.coupons.state.set(globalThis.Checkout.CouponStates.APPLIED); 4080 } else { 4081 if (reconciledCode) { 4082 globalThis.Checkout.store.coupons.appliedCode.set(""); 4083 globalThis.Checkout.store.coupons.currentCode.set(""); 4084 } 4085 globalThis.Checkout.store.coupons.state.set(globalThis.Checkout.CouponStates.READY); 4086 } 4087 const newSummaryState = { 4088 state: globalThis.Checkout.SummaryStates.OK, 4089 data: __privateMethod(this, _CheckoutSummary_static, processOrderPreviewResponseForSummary_fn).call(this, summaryData, { 4090 shouldSetShippingOptions: options?.shouldSetShippingOptions, 4091 shouldSetTax: options?.shouldSetTax 4092 }) 4093 }; 4094 if (shouldUpdateSummaryData) { 4095 globalThis.Checkout.store.summary.set(newSummaryState); 4096 } 4097 __privateSet(this, _lastPreviewedSummary, newSummaryState.data); 4098 this.updateRebillyTransactionData(newSummaryState.data, cart); 4099 } 4100 } 4101 static async fetchOrderSummaryForExpress(cart, payload) { 4102 const dataToPreview = __privateMethod(this, _CheckoutSummary_static, buildOrderPreviewPayload_fn).call(this, cart, { 4103 billingAddress: payload.billingAddress, 4104 shippingAddress: payload.shippingAddress, 4105 shippingOption: payload.shippingOption, 4106 billingSameAsShipping: payload.billingSameAsShipping 4107 }, { 4108 skipBillingAddress: false 4109 }); 4110 const summaryData = await orderPreviewFetcher.post("/order_preview", dataToPreview); 4111 if (isResponseError(summaryData)) { 4112 if (isFetcherError(summaryData)) { 4113 throw new PreviewError(summaryData.error); 4114 } else if (isBackendError(summaryData)) { 4115 throw new PreviewError(summaryData.error.error, summaryData.error.details); 4116 } 4117 } else { 4118 const validShippingAddress = __privateMethod(this, _CheckoutSummary_static, validAddress_fn).call(this, payload.shippingAddress); 4119 const validBillingAddress = __privateMethod(this, _CheckoutSummary_static, validAddress_fn).call(this, payload.billingAddress); 4120 return { 4121 summary: summaryData, 4122 data: __privateMethod(this, _CheckoutSummary_static, processOrderPreviewResponseForSummary_fn).c
4122all(this, summaryData, { 4123 shouldSetShippingOptions: validShippingAddress, 4124 shouldSetTax: validBillingAddress 4125 }) 4126 }; 4127 } 4128 } 4129 static disableIsUpdatingRebilly() { 4130 globalThis.Checkout.store.isUpdatingRebilly.set(false); 4131 } 4132 static get lastPreviewedSummary() { 4133 return __privateGet(this, _lastPreviewedSummary); 4134 } 4135 static updateRebillyTransactionData(summary, cart, forceRebillyUpdate = false) { 4136 this.updateRebillyTransactionDataPromise(summary, cart, forceRebillyUpdate).catch((e) => { 4137 this.disableIsUpdatingRebilly(); 4138 if (e instanceof CheckoutCriticalError) displayAndLogCriticalError(e); 4139 }); 4140 } 4141 static updateRebillyTransactionDataPromise(summary, cart, forceRebillyUpdate = false) { 4142 const mode = globalThis.Checkout.store.checkout.mode.get(); 4143 const shippingEnabled = globalThis.Checkout.utils.hasPhysicalProducts(); 4144 const paymentType = globalThis.Checkout.store.payment.type.get(); 4145 const lineItems = summary?.line_items ?? []; 4146 const RebillyFullyInitialized = globalThis.Checkout.store.payment.state.get() == globalThis.Checkout.PaymentStates.INITIALIZED; 4147 if (mode == globalThis.Checkout.CheckoutStates.UPGRADE_DOWNGRADE || !lineItems.length || !RebillyFullyInitialized) { 4148 if (!__privateGet(this, _previewPending)) { 4149 this.disableIsUpdatingRebilly(); 4150 } 4151 return Promise.resolve(); 4152 } 4153 const transactionData = this.buildTransactionData(summary, cart, shippingEnabled, paymentType); 4154 if (!forceRebillyUpdate && deepEqual(__privateGet(this, _lastRebillyUpdate), transactionData)) { 4155 this.disableIsUpdatingRebilly(); 4156 return Promise.resolve(); 4157 } 4158 return globalThis.Rebilly.update({ transactionData }).then(() => { 4159 this.disableIsUpdatingRebilly(); 4160 __privateSet(this, _lastRebillyUpdate, transactionData); 4161 }).catch((e) => { 4162 const error = new CheckoutCriticalError(ERROR_CODES.READY_TO_PAY_UPDATE_ERROR, { cause: e }); 4163 error.context = { 4164 phase: "ready-to-pay-update", 4165 paymentType, 4166 mode, 4167 currency: transactionData.currency, 4168 amount: transactionData.amount, 4169 lineItemCount: transactionData.lineItems.length, 4170 requestShipping: transactionData.requestShipping, 4171 ...extractRebillyErrorFields(e) 4172 }; 4173 throw error; 4174 }); 4175 } 4176 static buildTransactionData(summaryData, cart, shippingEnabled, paymentType) { 4177 const { currency, line_items } = summaryData; 4178 const lineItems = line_items.map(({ price, description }, index) => { 4179 let label; 4180 if (line_items.length == cart.items.length) { 4181 const variantId = cart.items[index].variant_id; 4182 const variant = globalThis.Checkout.variantsById[variantId]; 4183 label = variant.name; 4184 } else { 4185 label = description; 4186 } 4187 return { 4188 label, 4189 amount: price 4190 }; 4191 }); 4192 let amount = summaryData.subtotal.amount; 4193 if (paymentType === "Klarna") { 4194 amount = summaryData.total.amount; 4195 } 4196 return { 4197 currency, 4198 amount, 4199 label: "Total Purchase", 4200 lineItems, 4201 requestShipping: shippingEnabled 4202 }; 4203 } 4204}; 4205_sendOrderPreviewTimer = new WeakMap(); 4206_lastOrderPreviewData = new WeakMap(); 4207_lastRebillyUpdate = new WeakMap(); 4208_couponStateBeforeApplying = new WeakMap(); 4209_skipOrderSummaryUpdate = new WeakMap(); 4210_previewPending = new WeakMap(); 4211_lastPreviewedSummary = new WeakMap(); 4212_CheckoutSummary_static = new WeakSet(); 4213setLoadingShippingOptions_fn = function(dataToPreview) { 4214 const { selected_shipping_option: _tmpShippingOption1, ...dataToPreviewWithoutShippingOption } = dataToPreview?.order ?? {}; 4215 const { selected_shipping_option: _tmpShippingOption2, ...lastOrderPreviewDataWithoutShippingOption } = __privateGet(this, _lastOrderPreviewData)?.order ?? {}; 4216 if (!deepEqual(dataToPreviewWithoutShippingOption, lastOrderPreviewDataWithoutShippingOption)) { 4217 globalThis.Checkout.store.loadingShipping.set(true); 4218 } 4219}; 4220validAddress_fn = function(address) { 4221 return !!address?.zip && !!address?.country; 4222}; 4223backfillBillingAddress_fn = function(summaryData) { 4224 const checkoutBilling = globalThis.Checkout.store.billing.get(); 4225 if (summaryData.billing_address) { 4226 const { city: summaryCity, region: summaryRegion } = summaryData.billing_address; 4227 if (!checkoutBilling.city || !checkoutBilling.state) { 4228 globalThis.Checkout.store.billing.set({ 4229 ...checkoutBilling, 4230 ...!checkoutBilling.city ? { city: summaryCity } : {}, 4231 ...!checkoutBilling.state ? { state: summaryRegion } : {} 4232 }); 4233 } 4234 } 4235}; 4236processOrderPreviewResponseForSummary_fn = function(summaryData, options) { 4237 const recurring = __privateMethod(this, _CheckoutSummary_static, buildRecurringSummary_fn).c
4237all(this, summaryData); 4238 return { 4239 currency: summaryData.currency, 4240 currency_symbol: summaryData.currency_symbol, 4241 line_items: summaryData.line_items, 4242 total: { 4243 amount: parseFloat(summaryData.total_amount?.amount), 4244 formatted: summaryData.total_amount_formatted 4245 }, 4246 discount: { 4247 amount: parseFloat(summaryData.discount_amount.amount), 4248 formatted: summaryData.discount_amount_formatted 4249 }, 4250 discounts: (summaryData.discounts ?? []).map((discount) => { 4251 return { 4252 name: discount.name, 4253 code: discount.code, 4254 amount_formatted: "-" + formatNumberToCurrency(summaryData.currency_symbol, discount.amount) 4255 }; 4256 }), 4257 subtotal: { 4258 amount: parseFloat(summaryData.subtotal_amount.amount), 4259 formatted: summaryData.subtotal_amount_formatted 4260 }, 4261 ...options?.shouldSetShippingOptions ? { 4262 shipping: { 4263 amount: parseFloat(summaryData.shipping_amount.amount), 4264 formatted: summaryData.shipping_amount_formatted 4265 } 4266 } : { shipping: {} }, 4267 ...options?.shouldSetTax ? { 4268 tax: { 4269 amount: parseFloat(summaryData.tax_amount.amount), 4270 formatted: summaryData.tax_amount_formatted 4271 } 4272 } : { tax: {} }, 4273 ...summaryData.upcoming_invoice?.interim_amount ? { 4274 interim: { 4275 amount: parseFloat(summaryData.upcoming_invoice.interim_amount.amount), 4276 formatted: summaryData.upcoming_invoice.interim_amount_formatted 4277 } 4278 } : {}, 4279 ...summaryData.upcoming_invoice ? { 4280 upcoming_invoice: { 4281 line_items: summaryData.upcoming_invoice.line_items.filter((i) => i.interim).map((item) => { 4282 return { 4283 variant_name: item.variant_name, 4284 quantity: item.quantity, 4285 amount: parseFloat(item.amount.amount), 4286 formatted: item.amount_formatted 4287 }; 4288 }) 4289 } 4290 } : {}, 4291 ...recurring ? { recurring } : {} 4292 }; 4293}; 4294buildRecurringSummary_fn = function(summaryData) { 4295 if (!summaryData.recurring_total_amount) return void 0; 4296 const recurringTotal = parseFloat(summaryData.recurring_total_amount.amount); 4297 const recurringDiscount = parseFloat(summaryData.recurring_discount_amount?.amount ?? "0"); 4298 const displayedTotal = summaryData.upcoming_invoice?.interim_amount ? parseFloat(summaryData.upcoming_invoice.interim_amount.amount) : parseFloat(summaryData.total_amount?.amount); 4299 return { 4300 showThen: Math.abs(recurringTotal - displayedTotal) > 1e-3, 4301 total: { amount: recurringTotal, formatted: summaryData.recurring_total_amount_formatted }, 4302 discount: { amount: recurringDiscount, formatted: summaryData.recurring_discount_amount_formatted }, 4303 interval: summaryData.recurring_interval ?? "", 4304 before_formatted: recurringDiscount > 0 ? summaryData.recurring_total_before_discount_formatted ?? "" : "" 4305 }; 4306}; 4307buildCartDetails_fn = function(cart) { 4308 const orderId = cart.order_id; 4309 const lineItems = cart.items.map(({ price_id, line_item_id, variant_id, quantity }) => { 4310 const data = { 4311 variant_id, 4312 price_id, 4313 ...line_item_id ? { line_item_id } : {}, 4314 quantity 4315 }; 4316 return data; 4317 }); 4318 return { order_id: orderId, line_items: lineItems }; 4319}; 4320buildOrderPreviewPayload_fn = function(cart, payload, options) { 4321 const couponState = globalThis.Checkout.store.coupons.state.get(); 4322 let couponCode; 4323 if (couponState == globalThis.Checkout.CouponStates.APPLYING) { 4324 couponCode = globalThis.Checkout.store.coupons.currentCode.get(); 4325 } else { 4326 couponCode = globalThis.Checkout.store.coupons.appliedCode.get(); 4327 } 4328 const selected_shipping_option = payload.shippingOption; 4329 return { 4330 order: { 4331 full_preview: true, 4332 should_backfill_billing_address: true, 4333 coupon_codes: couponCode, 4334 ...selected_shipping_option?.amount ? { selected_shipping_option } : {}, 4335 ...__privateMethod(this, _CheckoutSummary_static, buildAddressParams_fn).call(this, cart, { 4336 billingAddress: payload.billingAddress, 4337 shippingAddress: payload.shippingAddress, 4338 billingSameAsShipping: payload.billingSameAsShipping 4339 }, options), 4340 ...__privateMethod(this, _CheckoutSummary_static, buildCartDetails_fn).call(this, cart) 4341 } 4342 }; 4343}; 4344buildAddressParams_fn = function(cart, addressParams, options) { 4345 const billing = addressParams.billingAddress; 4346 const shipping = addressParams.shippingAddress; 4347 const mode = globalThis.Checkout.store.checkout.mode.get(); 4348 if (mode === globalThis.Checkout.CheckoutStates.UPGRADE_DOWNGRADE && !hasPhysicalProducts(cart)) { 4349 return; 4350 } 4351 let billingData, shippingData; 4352 if (mode !== globalThis.Checkout.CheckoutStates.UPGRADE_DOWNGRADE) { 4353 if (isSavedAddress(billing)) { 4354 billingData = { 4355 id: billing.id 4356 }; 4357 } else { 4358 billingData = { 4359 address_one: billing.address, 4360 address_two: billing.address_2, 4361 city: billing.city, 4362 state: billing.state, 4363 country: billing.country, 4364 postal_code: billing.zip 4365 }; 4366 } 4367 } 4368 if (isSavedAddress(shipping)) { 4369 shippingData = { 4370 id: shipping.id, 4371 address_one: shipping.address, 4372 address_two: shipping.address_2, 4373 city: shipping.city, 4374 state: shipping.state, 4375 country: shipping.country, 4376 postal_code: shipping.zip 4377 }; 4378 } else { 4379 shippingData = { 4380 address_one: shipping.address, 4381 address_two: shipping.address_2, 4382 city: shipping.city, 4383 state: shipping.state, 4384 country: shipping.country, 4385 postal_code: shipping.zip 4386 }; 4387 } 4388 if (hasPhysicalProducts(cart)) { 4389 const billingSameAsShippingData = addressParams.billingSameAsShipping; 4390 if (options.skipBillingAddress) { 4391 return { delivery_address: shippingData }; 4392 } 4393 if (mode == globalThis.Checkout.CheckoutStates.OTO) { 4394 return { 4395 delivery_address: shippingData, 4396 billing_address: billingData 4397 }; 4398 } 4399 if (billingSameAsShippingData) { 4400 return { 4401 delivery_address: shippingData, 4402 billing_address: shippingData 4403 }; 4404 } else { 4405 return { 4406 delivery_address: shippingData, 4407 billing_address: billingData 4408 }; 4409 } 4410 } else { 4411 if (options.skipBillingAddress) return; 4412 return { billing_address: billingData }; 4413 } 4414}; 4415__privateAdd(CheckoutSummary, _CheckoutSummary_static); 4416__privateAdd(CheckoutSummary, _sendOrderPreviewTimer); 4417__privateAdd(CheckoutSummary, _lastOrderPreviewData); 4418__privateAdd(CheckoutSummary, _lastRebillyUpdate); 4419__privateAdd(CheckoutSummary, _couponStateBeforeApplying); 4420__privateAdd(CheckoutSummary, _skipOrderSummaryUpdate); 4421__privateAdd(CheckoutSummary, _previewPending, false); 4422// Last summary a preview actually computed, cached even when the store is not written
4423// (invalid/absent billing on a wallet checkout keeps shouldUpdateSummaryData false). The 4424// post-init wallet update reads this so it can push the real amount instead of the 4425// amount:1 placeholder (ENG-6708 / ENG-6871). 4426__privateAdd(CheckoutSummary, _lastPreviewedSummary); 4427
4428// projects/lib/packages/yggdrasil-blueprints/src/Elements/Checkout/V2/CheckoutMultiStep/V2/checkoutFormUtils.ts 4429init_define_process(); 4430function formBySteps(formStructure) { 4431 return Object.entries(formStructure).reduce((acc1, item) => { 4432 const [totalSteps, form] = item; 4433 acc1[totalSteps] = {}; 4434 form.reduce((acc2, form2, index) => { 4435 form2.forEach((field) => { 4436 acc2[field] = index; 4437 }); 4438 return acc2; 4439 }, acc1[totalSteps]); 4440 return acc1; 4441 }, {}); 4442} 4443
4444// projects/lib/packages/yggdrasil-blueprints/__generated__/blueprints/rebilly-checkout.ts 4445init_nanostores(); 4446init_runtime(); 4447var RebillyCheckout = class extends CF2Component { 4448 constructor(el, runtimeSel) { 4449 super(el, runtimeSel); 4450 __publicField(this, "FORM_STRUCTURE_BY_TOTAL_STEPS", { 4451 2: [["contact", "shipping"], ["products", "shippingOption", "billing", "payment", "tos", "summary"]], 4452 3: [["products"], ["contact", "shipping"], ["shippingOption", "billing", "payment", "tos", "summary"]] 4453 }); 4454 __publicField(this, "FORM_BY_STEP", formBySteps(this.FORM_STRUCTURE_BY_TOTAL_STEPS)); 4455 __publicField(this, "_lazyInitPending"); 4456 } 4457 _initializeStore() { 4458 Checkout.isCheckoutResource = globalThis.globalResourceData.resourceName == "checkout"; 4459 globalResourceData.enabledPayments = !window.ApplePaySession ? globalResourceData.enabledPayments.filter((v) => v != "apple-pay") : globalResourceData.enabledPayments; 4460 globalResourceData.enabledPayments = !AVAILABLE_KLARNA_COUNTRIES.includes(globalThis.cfVisitorData.country) ? globalResourceData.enabledPayments.filter((paymentType) => paymentType != "Klarna") : globalResourceData.enabledPayments; 4461 globalResourceData.expressEnabledPayments = !window.ApplePaySession ? globalResourceData.expressEnabledPayments.filter((v) => v != "apple-pay") : globalResourceData.expressEnabledPayments; 4462 if (!globalResourceData.expressEnabledPayments.includes("apple-pay")) { 4463 (this.element.querySelectorAll(".elExpressCheckoutForCart") ?? []).forEach((item) => item.remove()); 4464 } 4465 const billingFields = this.billingEnabled ? this.billingFields : []; 4466 Checkout.store = create(billingFields, this.shippingFields, globalResourceData.enabledPayments, globalResourceData.expressEnabledPayments); 4467 Checkout.computed = buildComputed(Checkout.store, this.contactFields, this.shippingFields, this.totalSteps); 4468 if (document.querySelectorAll('[data-page-element="Checkout/V2"]').length > 1) { 4469 const error = new CheckoutCriticalError(ERROR_CODES.MULTIPLE_CHECKOUT_PRESENT); 4470 displayAndLogCriticalError(error); 4471 return; 4472 } 4473 initializeUtilities(Checkout.store, Checkout.computed); 4474 } 4475 _initializeMachine() { 4476 const billingFields = this.billingEnabled ? this.billingFields : []; 4477 initializeMachine({ 4478 hasPhoneNumber: this.contactFields.includes("phone_number"), 4479 billingFields, 4480 shippingFields: this.shippingFields 4481 }); 4482 } 4483 initialize() { 4484 this._initializeStore(); 4485 if (this.lazyLoadCheckout) { 4486 this._lazyInitPending = true; 4487 return; 4488 } 4489 this._initializeMachine(); 4490 } 4491 backfillContactDataFromGarlic_Mutable(contactData) { 4492 Object.keys(contactData).reduce((acc, field) => { 4493 if (!contactData[field]) { 4494 const val = window.cfGarlicUtils.retrieve(field); 4495 if (field?.length) acc[field] = val; 4496 } 4497 return acc; 4498 }, contactData); 4499 } 4500 updateCheckoutMode(mode) { 4501 const containerMapping = Object.values(Checkout.CheckoutStates).reduce((acc, item) => { 4502 acc[item] = this.element.querySelector(`[data-wrapper-checkout-state="${item}"]`); 4503 return acc; 4504 }, {}); 4505 const currentContainer = containerMapping[mode]; 4506 for (let container of Object.values(containerMapping)) { 4507 if (container == currentContainer) { 4508 currentContainer.classList.remove("elHide"); 4509 } else { 4510 container.classList.add("elHide"); 4511 } 4512 } 4513 } 4514 mount() { 4515 if (this._lazyInitPending) { 4516 return; 4517 } 4518 this._doMount(); 4519 } 4520 _performLazyInit() { 4521 this._lazyInitPending = false; 4522 this._initializeMachine(); 4523 this._doMount(); 4524 } 4525 _doMount() { 4526 const contactData = this.contactFields.reduce((acc, field) => { 4527 acc[field] = Checkout.initialContactData[field]; 4528 return acc; 4529 }, {}); 4530 this.backfillContactDataFromGarlic_Mutable(contactData); 4531 Checkout.computed.checkoutCart.listen(() => { 4532 CheckoutSummary.sendOrderPreview({ revalidateCoupon: true }); 4533 }); 4534 [Checkout.store.billing, Checkout.store.shipping, Checkout.store.shippingOption].forEac
4534h((store) => { 4535 store?.listen(() => { 4536 CheckoutSummary.sendOrderPreview(); 4537 }); 4538 }); 4539 [Checkout.store.payment.type].forEach((store) => { 4540 store?.listen((newValue, oldValue) => { 4541 const shouldForceRebillyUpdate = newValue === "Klarna" || oldValue === "Klarna"; 4542 CheckoutSummary.sendOrderPreview({ forceRebillyUpdate: shouldForceRebillyUpdate }); 4543 }); 4544 }); 4545 if (!this.disableOTP) { 4546 const checkoutLogin = this.getComponentGroup(CheckoutLoginV2); 4547 Checkout.auth.computed.requireLogin.listen((requireLogin) => { 4548 if (requireLogin) { 4549 this.element.querySelector(`[data-wrapper-checkout-state="${Checkout.store.checkout.mode.get()}"]`).classList.add("elHide"); 4550 checkoutLogin.show(); 4551 } else { 4552 this.updateCheckoutMode(Checkout.store.checkout.mode.get()); 4553 checkoutLogin.hide(); 4554 } 4555 }); 4556 } 4557 Checkout.store.checkout.mode.listen((mode) => { 4558 this.updateCheckoutMode(mode); 4559 }); 4560 this.listenAndUpdateCheckoutErrors(); 4561 Checkout.store.tos.present.set(this.showTos); 4562 Checkout.store.state.listen((state) => { 4563 if ([Checkout.StoreStates.START, Checkout.StoreStates.INITIALIZING, Checkout.StoreStates.INITIALIZED].includes(state)) { 4564 this.element.querySelector(".elSpinnerWrapper").dataset.loader = true; 4565 if (state === Checkout.StoreStates.INITIALIZED) { 4566 Checkout.store.contact.set(contactData); 4567 } 4568 } else { 4569 if (this.element.querySelector('[data-page-element="CheckoutConfigurationError/V1"]').querySelector(".elHide")) { 4570 delete this.element.querySelector(".elSpinnerWrapper").dataset.loader; 4571 } 4572 } 4573 }); 4574 this.element.querySelectorAll('[href="#!checkout-as-guest"]').forEach((el) => { 4575 el.addEventListener("click", (evt) => { 4576 evt.preventDefault(); 4577 Checkout.store.checkout.mode.set("guest"); 4578 }); 4579 }); 4580 Checkout.computed.hasShippingEnabled.subscribe((hasShippingEnabled) => { 4581 if (!hasShippingEnabled && Checkout.store.shippingOption.value) { 4582 Checkout.store.shippingOption.set(null); 4583 } 4584 }); 4585 Checkout.computed.hideShipping.subscribe((hideShipping) => { 4586 this.element.querySelector(".elCheckoutWrapper").setAttribute("data-shipping-enabled", hideShipping ? "false" : "true"); 4587 }); 4588 Checkout.store.state.set(Checkout.StoreStates.INITIALIZING); 4589 setupOrderSummaries(this); 4590 this.element.querySelectorAll("input, select").forEach((el) => { 4591 el.addEventListener("focus", () => { 4592 Checkout.store.submitting.set({ state: Checkout.SubmittingStates.IDLE }); 4593 }); 4594 }); 4595 const trackableStores = [ 4596 Checkout.store.contact, 4597 Checkout.store.shipping, 4598 Checkout.store.billing, 4599 Checkout.store.billingSameAsShipping, 4600 Checkout.store.tos.accepted, 4601 Checkout.store.shippingOption, 4602 // Checkout.store.payment.state, 4603 Checkout.store.payment.id, 4604 Checkout.store.payment.type, 4605 Checkout.store.payment["payment-card"].events, 4606 Checkout.store.payment["payment-card"].token, 4607 Checkout.store.payment.paypal.state, 4608 Checkout.store.payment.paypal.token, 4609 Checkout.computed.checkoutCart 4610 ]; 4611 trackableStores.forEach((store) => { 4612 store.listen((v) => { 4613 Checkout.store.submitting.set({ state: Checkout.SubmittingStates.IDLE }); 4614 }); 4615 }); 4616 Checkout.computed.isOTORetrialPayment.listen((isOTORetrialPayment) => { 4617 if (isOTORetrialPayment) { 4618 this.element.querySelector(".elCheckoutOtoPayment").classList.remove("elHide"); 4619 } 4620 }); 4621 this.setHandlers(CheckoutMultiStepV2, { 4622 onValidateStep: (step) => { 4623 const valid = this.validateStep(step); 4624 if (!valid) { 4625 scrollToFirstVisibleError(); 4626 } 4627 return valid; 4628 }, 4629 onStepChange: (oldStep, currentStep) => { 4630 const currentFormStructure = this.FORM_STRUCTURE_BY_TOTAL_STEPS[this.totalSteps][currentStep]; 4631 if (currentFormStructure.includes("payment")) { 4632 loadPAIDeps()?.catch((e) => displayAndLogCriticalError(e)); 4633 } 4634 const oldFormStructure = this.FORM_STRUCTURE_BY_TOTAL_STEPS[this.totalSteps][oldStep]; 4635 if (oldFormStructure.includes("contact")) { 4636 const contactDetails = Checkout.store.contact.get(); 4637 collectLeads(contactDetails); 4638 } 4639 } 4640 }); 4641 this.setHandlers(CheckoutSubmitButtonV1, { 4642 // NOTE: returned so the button can tell a finished attempt from one that is 4643 // still running, and unlock itself when we never got as far as the POST. 4644 onSubmit: (element) => CheckoutSubmit.submitFromButtonClick(element, () => scrollToFirstVisibleError()) 4645 }); 4646 this.setHandlers(CheckoutTosV1, { 4647 onAcceptedChange: (accepted) => { 4648 Checkout.store.tos.accepted.set(accepted); 4649 } 4650 }); 4651 window.addEventListener("ON_APPLY_COUPON", (event) => { 4652 CheckoutSummary.sendOrderPreview(event.detail); 4653 }); 4654 window.addEventListener("ON_CLEAR_COUPON", (event) => { 4655 CheckoutSummary.sendOrderPreview(event.detail); 4656 }); 4657 this.setupShippingProfileSelect(); 4658 this.setupSubmittingListeners(); 4659 } 4660 setupShippingProfileSelect() { 4661 const shippingProfileSelects = this.getComponentGroup(CheckoutShippingProfileSelectV1, { 4662 onSelectOption: (option) => { 4663 Checkout.store.shippingOption.set(option); 4664 } 4665 }); 4666 const renderDeps = computed([ 4667 Checkout.store.shippingOptions, 4668 Checkout.computed.hasValidShippingAddress, 4669 Checkout.store.loadingShipping, 4670 Checkout.store.summary 4671 ], (...args) => args); 4672 renderDeps.listen(([shippingOptions, hasValidShippingAddress, loadingShipping, summary]) => { 4673 const shippingOption = Checkout.store.shippingOption.get(); 4674 const summaryHasError = summary.state === "error"; 4675 shippingProfileSelects.update({ shippingOption, shippingOptions, hasValidShippingAddress, loadingShipping, summaryHasError }); 4676 }); 4677 Checkout.store.shippingOption.listen((shippingOption) => { 4678 shippingProfileSelects.setOption(shippingOption); 4679 }); 4680 Checkout.computed.isNewDigitalWalletPayment.subscribe((isNewDigitalWalletPayment) => { 4681 if (isNewDigitalWalletPayment) { 4682 shippingProfileSelects.hide(); 4683 } else { 4684 shippingProfileSelects.show(); 4685 } 4686 }); 4687 } 4688 setupSubmittingListeners() { 4689 const checkoutLoading = this.getComponentGroup(CheckoutLoadingV1); 4690 const submitButtons = this.getComponentGroup(CheckoutSubmitButtonV1); 4691 const submitNotification = this.getComponentGroup(CheckoutSubmitNotificationV1); 4692 computed([Checkout.store.submitting, Checkout.store.summary, Checkout.store.state], (submitting, summary, machineState) => { 4693 const state = submitting.state; 4694 const attemptOwnsButton = machineState === Checkout.StoreStates.SUBMITTING || machineState === Checkout.StoreStates.SUBMITTED; 4695 switch (state) { 4696 case Checkout.SubmittingStates.IDLE: { 4697 if (attemptOwnsButton) break; 4698 checkoutLoading.hide(); 4699 switch (summary.state) {
4700 case Checkout.SummaryStates.CALCULATING: { 4701 submitButtons.setLoading(); 4702 break; 4703 } 4704 default: { 4705 submitButtons.setButtonInitialHTML(); 4706 submitNotification.setStatus("", ""); 4707 } 4708 } 4709 break; 4710 } 4711 case Checkout.SubmittingStates.START: { 4712 checkoutLoading.show(); 4713 submitButtons.setSubmittingText(); 4714 submitNotification.setStatus("", ""); 4715 break; 4716 } 4717 case Checkout.SubmittingStates.WAITING_ON_QUEUE: { 4718 checkoutLoading.show(); 4719 checkoutLoading.showWaitingOnQueueText(`${this.rebillyCheckoutTexts.waitingOnQueue} (${this.rebillyCheckoutTexts.retryingIn} ${submitting.remainingSeconds}${this.rebillyCheckoutTexts.seconds})`); 4720 submitNotification.setStatus(`${this.rebillyCheckoutTexts.waitingOnQueue}`, `(${this.rebillyCheckoutTexts.retryingIn} ${submitting.remainingSeconds}${this.rebillyCheckoutTexts.seconds})`); 4721 break; 4722 } 4723 case Checkout.SubmittingStates.ERROR: { 4724 checkoutLoading.hide(); 4725 submitButtons.setButtonInitialHTML(); 4726 switch (submitting.code) { 4727 case Checkout.ErrorTypes.REBILLY_ERROR: 4728 case Checkout.ErrorTypes.SERVER_ERROR: 4729 case Checkout.ErrorTypes.UNHANDLED_SERVER_RESPONSE: 4730 case Checkout.ErrorTypes.EXCEEDED_MAX_RETRIES: { 4731 submitNotification.setStatus(`${this.rebillyCheckoutTexts.failedToSubmit}`, `${this.rebillyCheckoutTexts.retryAgainInFewSeconds}`, submitting.message ? submitting.message : ""); 4732 break; 4733 } 4734 case Checkout.ErrorTypes.THREEDS_DECLINED_ERROR: { 4735 submitNotification.setStatus(`${this.rebillyCheckoutTexts.failedToSubmit}`, `${this.rebillyCheckoutTexts.transactionDeclined}`); 4736 break; 4737 } 4738 case Checkout.ErrorTypes.SERVER_ERROR_WITH_MESSAGE: { 4739 submitNotification.setStatus(`${this.rebillyCheckoutTexts.failedToSubmit}`, submitting.message); 4740 break; 4741 } 4742 case Checkout.ErrorTypes.THREEDS_DECLINED_CUSTOM_ERROR: { 4743 submitNotification.setStatus(`${this.rebillyCheckoutTexts.failedToSubmit}`, submitting.message); 4744 break; 4745 } 4746 } 4747 break; 4748 } 4749 } 4750 }).subscribe(() => { 4751 }); 4752 } 4753 validateStep(step) { 4754 const currentStep = Checkout.store.checkout.step.get(); 4755 const currentFormStructure = this.FORM_STRUCTURE_BY_TOTAL_STEPS[this.totalSteps][currentStep]; 4756 const errors = currentFormStructure.reduce((acc, formName) => { 4757 Checkout.store.showAllErrors[formName].set(true); 4758 const error = Checkout.computed.errorsByName[formName].get(); 4759 if (Checkout.utils.hasErrors(error)) { 4760 acc.push(error); 4761 } 4762 return acc; 4763 }, []); 4764 return errors.length == 0; 4765 } 4766 listenAndUpdateCheckoutErrors() { 4767 Object.entries(Checkout.computed.errorsByName).forEach(([name, computed3]) => { 4768 computed3.subscribe((error) => { 4769 Object.values(Checkout.CheckoutStates).forEach((mode) => { 4770 let formStructure = []; 4771 let currentErrorElement = null; 4772 if (mode == "guest" && this.totalSteps != 1) { 4773 const currentStep = Checkout.store.checkout.step.get(); 4774 let currentStepWithError = currentStep; 4775 currentErrorElement = this.element.querySelector('.elMultiStepBody[data-step-state="active"]').querySelector(".checkout-general-errors-wrapper"); 4776 const stepForField = this.FORM_BY_STEP[this.totalSteps][name]; 4777 if (stepForField != void 0) { 4778 if (Checkout.utils.hasErrors(error) && stepForField < currentStep) { 4779 Checkout.store.checkout.step.set(stepForField); 4780 scrollToFirstVisibleError(); 4781 } 4782 currentErrorElement = this.element.querySelector(`.elMultiStepBody[data-step-number="${stepForField + 1}"]`).querySelector(".checkout-general-errors-wrapper"); 4783 currentStepWithError = stepForField; 4784 } 4785 formStructure = this.FORM_STRUCTURE_BY_TOTAL_STEPS[this.totalSteps][currentStepWithError]; 4786 } else { 4787 formStructure = ["shippingOption", "products", "tos", "payment", "billing", "summary"]; 4788 currentErrorElement = this.element.querySelector(`[data-wrapper-checkout-state="${mode}"]`).querySelector(".checkout-general-errors-wrapper"); 4789 } 4790 const errors = formStructure.reduce((acc, formName) => { 4791 const error2 = Checkout.computed.errorsByName[formName].get(); 4792 if (Checkout.utils.hasErrors(error2)) { 4793 acc.push({ name: formName, errors: error2 }); 4794 } 4795 return acc; 4796 }, []); 4797 if (!errors || errors?.length == 0) { 4798 currentErrorElement.classList.add("elHide"); 4799 } else { 4800 const error2 = errors[0]; 4801 if (error2.errors?.globalErrors?.[0]?.message) { 4802 const errorMessage = error2.errors.globalErrors[0].message; 4803 currentErrorElement.querySelector("span").innerHTML = errorMessage; 4804 currentErrorElement.classList.remove("elHide"); 4805 } else { 4806 currentErrorElement.classList.add("elHide"); 4807 } 4808 } 4809 }); 4810 }); 4811 }); 4812 } 4813 getCart() { 4814 return globalThis.Checkout.computed.checkoutCart.get(); 4815 } 4816 submitOTO(redirectOverride) { 4817 return new Promise((resolve) => { 4818 let settled = false;
4819 let unlisten; 4820 const finish = (result) => { 4821 if (settled) return; 4822 settled = true; 4823 unlisten && unlisten(); 4824 resolve(result); 4825 }; 4826 unlisten = globalThis.Checkout.store.submitting.listen((submitting) => { 4827 if (submitting.state === globalThis.Checkout.SubmittingStates.DONE) { 4828 finish({ ok: true }); 4829 } else if (submitting.state === globalThis.Checkout.SubmittingStates.ERROR) { 4830 finish({ ok: false, actionable: submitting.actionable !== false, message: submitting.message }); 4831 } 4832 }); 4833 CheckoutSubmit.submitFromButtonClick(this.element, () => scrollToFirstVisibleError(), redirectOverride); 4834 if (globalThis.Checkout.store.state.get() !== globalThis.Checkout.StoreStates.SUBMITTING) { 4835 finish({ ok: false, actionable: true }); 4836 } 4837 }); 4838 } 4839}; 4840registerComponent("RebillyCheckout", RebillyCheckout); 4841window["RebillyCheckout"] = RebillyCheckout; 4842//# sourceMappingURL=rebilly-checkout-FZAQEHSF.js.map
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.