@vio-live/web-sdk 0.28.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -207,9 +207,9 @@ function slotDeclarationKey(location2, pageCampaignId) {
207
207
  const kind = normalizeSlotKind(location2.kind);
208
208
  return location2.id + (location2.displayName ? `${location2.displayName}` : "") + (campaignId !== void 0 ? `${campaignId}` : "") + (kind !== void 0 ? `${kind}` : "");
209
209
  }
210
- function pendingSlotKeys(memory, keys, now = Date.now(), ttl = SLOT_DECLARATION_TTL_MS) {
210
+ function pendingSlotKeys(memory2, keys, now = Date.now(), ttl = SLOT_DECLARATION_TTL_MS) {
211
211
  return keys.filter((key) => {
212
- const at = memory?.[key];
212
+ const at = memory2?.[key];
213
213
  if (typeof at !== "number" || !Number.isFinite(at)) return true;
214
214
  return now - at >= ttl || now < at;
215
215
  });
@@ -218,8 +218,8 @@ function slotKeyId(key) {
218
218
  const cut4 = key.search(/[\u001f\u001e\u001d]/);
219
219
  return cut4 >= 0 ? key.slice(0, cut4) : key;
220
220
  }
221
- function rememberSlotKeys(memory, keys, at, cap = SLOT_DECLARATION_MEMORY_CAP) {
222
- const next = { ...memory ?? {} };
221
+ function rememberSlotKeys(memory2, keys, at, cap = SLOT_DECLARATION_MEMORY_CAP) {
222
+ const next = { ...memory2 ?? {} };
223
223
  const ids = new Set(keys.map(slotKeyId));
224
224
  for (const existing of Object.keys(next)) {
225
225
  if (ids.has(slotKeyId(existing)) && !keys.includes(existing)) delete next[existing];
@@ -258,10 +258,10 @@ function readSlotDeclaration(storageKey) {
258
258
  return {};
259
259
  }
260
260
  }
261
- function writeSlotDeclaration(storageKey, memory) {
261
+ function writeSlotDeclaration(storageKey, memory2) {
262
262
  try {
263
263
  if (typeof localStorage === "undefined") return;
264
- localStorage.setItem(storageKey, JSON.stringify(memory));
264
+ localStorage.setItem(storageKey, JSON.stringify(memory2));
265
265
  } catch {
266
266
  }
267
267
  }
@@ -466,6 +466,51 @@ function createVioApi(options) {
466
466
  return new VioApi(options);
467
467
  }
468
468
 
469
+ // src/core/safe-storage.ts
470
+ var memory = {
471
+ local: /* @__PURE__ */ new Map(),
472
+ session: /* @__PURE__ */ new Map()
473
+ };
474
+ function area(kind) {
475
+ try {
476
+ const s = globalThis[kind === "local" ? "localStorage" : "sessionStorage"];
477
+ return s && typeof s.getItem === "function" ? s : null;
478
+ } catch {
479
+ return null;
480
+ }
481
+ }
482
+ function storageGet(kind, key) {
483
+ const kept = memory[kind];
484
+ if (kept.has(key)) return kept.get(key) ?? null;
485
+ const s = area(kind);
486
+ if (!s) return null;
487
+ try {
488
+ return s.getItem(key);
489
+ } catch {
490
+ return null;
491
+ }
492
+ }
493
+ function storageSet(kind, key, value, opts = {}) {
494
+ try {
495
+ const s = area(kind);
496
+ if (s) {
497
+ s.setItem(key, value);
498
+ memory[kind].delete(key);
499
+ return true;
500
+ }
501
+ } catch {
502
+ }
503
+ if (opts.memory !== false) memory[kind].set(key, value);
504
+ return false;
505
+ }
506
+ function storageRemove(kind, key) {
507
+ memory[kind].delete(key);
508
+ try {
509
+ area(kind)?.removeItem(key);
510
+ } catch {
511
+ }
512
+ }
513
+
469
514
  // src/core/types.ts
470
515
  function displayPrice(product) {
471
516
  const p = product.price;
@@ -475,37 +520,24 @@ function displayPrice(product) {
475
520
  function getGlobalCountryCode() {
476
521
  const g = globalThis;
477
522
  if (g.__VIO_COUNTRY__) return g.__VIO_COUNTRY__;
478
- if (typeof localStorage !== "undefined") {
479
- try {
480
- const v = localStorage.getItem("vio.country");
481
- if (v) return v;
482
- } catch {
483
- }
484
- }
523
+ const stored = storageGet("local", "vio.country");
524
+ if (stored) return stored;
485
525
  return "NO";
486
526
  }
487
527
  function getGlobalLocale() {
488
528
  const g = globalThis;
489
529
  if (g.__VIO_LOCALE__) return g.__VIO_LOCALE__;
490
- if (typeof localStorage !== "undefined") {
491
- try {
492
- const v = localStorage.getItem("vio.locale");
493
- if (v) return v;
494
- } catch {
495
- }
496
- }
530
+ const stored = storageGet("local", "vio.locale");
531
+ if (stored) return stored;
497
532
  return "nb-NO";
498
533
  }
499
534
  function getGlobalSymbol(currency) {
500
535
  const activeCurrency = currency || getGlobalCurrency();
501
536
  const g = globalThis;
502
537
  if (!currency && g.__VIO_SYMBOL__) return g.__VIO_SYMBOL__;
503
- if (!currency && typeof localStorage !== "undefined") {
504
- try {
505
- const v = localStorage.getItem("vio.symbol");
506
- if (v) return v;
507
- } catch {
508
- }
538
+ if (!currency) {
539
+ const v = storageGet("local", "vio.symbol");
540
+ if (v) return v;
509
541
  }
510
542
  const curr = String(activeCurrency).toUpperCase();
511
543
  if (curr === "NOK" || curr === "DKK") return "Kr";
@@ -519,13 +551,8 @@ function getGlobalSymbol(currency) {
519
551
  function getGlobalCurrency() {
520
552
  const g = globalThis;
521
553
  if (g.__VIO_CURRENCY__) return g.__VIO_CURRENCY__;
522
- if (typeof localStorage !== "undefined") {
523
- try {
524
- const v = localStorage.getItem("vio.currency");
525
- if (v) return v;
526
- } catch {
527
- }
528
- }
554
+ const stored = storageGet("local", "vio.currency");
555
+ if (stored) return stored;
529
556
  return "NOK";
530
557
  }
531
558
  var validatedLocales = /* @__PURE__ */ new Map();
@@ -665,6 +692,80 @@ var GET_PRODUCT_SELLER = (
665
692
  }
666
693
  `
667
694
  );
695
+ var GET_PRODUCT_SHIPPING = (
696
+ /* GraphQL */
697
+ `
698
+ query GetProductShipping(
699
+ $productIds: [Int!]
700
+ $useCache: Boolean!
701
+ $currency: String
702
+ $shippingCountryCode: String
703
+ ) {
704
+ Channel {
705
+ GetProductsByIds(
706
+ product_ids: $productIds
707
+ useCache: $useCache
708
+ currency: $currency
709
+ shipping_country_code: $shippingCountryCode
710
+ ) {
711
+ id
712
+ product_shipping {
713
+ id
714
+ name
715
+ description
716
+ default
717
+ shipping_country {
718
+ country
719
+ price {
720
+ amount
721
+ amount_incl_taxes
722
+ currency_code
723
+ }
724
+ }
725
+ }
726
+ }
727
+ }
728
+ }
729
+ `
730
+ );
731
+ var GET_PRODUCT_SHIPPING_WITH_LOGO = (
732
+ /* GraphQL */
733
+ `
734
+ query GetProductShippingWithLogo(
735
+ $productIds: [Int!]
736
+ $useCache: Boolean!
737
+ $currency: String
738
+ $shippingCountryCode: String
739
+ ) {
740
+ Channel {
741
+ GetProductsByIds(
742
+ product_ids: $productIds
743
+ useCache: $useCache
744
+ currency: $currency
745
+ shipping_country_code: $shippingCountryCode
746
+ ) {
747
+ id
748
+ product_shipping {
749
+ id
750
+ name
751
+ description
752
+ logo_url
753
+ default
754
+ shipping_country {
755
+ country
756
+ price {
757
+ amount
758
+ amount_incl_taxes
759
+ currency_code
760
+ }
761
+ }
762
+ }
763
+ }
764
+ }
765
+ }
766
+ `
767
+ );
768
+ var gatewayHasShippingLogo;
668
769
  var ChannelProduct = class {
669
770
  constructor(client) {
670
771
  this.client = client;
@@ -704,7 +805,64 @@ var ChannelProduct = class {
704
805
  return null;
705
806
  }
706
807
  }
808
+ /**
809
+ * The product's shipping rates for the page's market (or `country`),
810
+ * cheapest first; `[]` when it has none there, `null` when they could not
811
+ * be read. Never throws. Never from the cache, for the reason given at
812
+ * getSellerCompany.
813
+ */
814
+ async getShippingRates(productId, options = {}) {
815
+ const country = options.country || getGlobalCountryCode();
816
+ const variables = {
817
+ productIds: [productId],
818
+ useCache: false,
819
+ currency: options.currency ?? getGlobalCurrency(),
820
+ shippingCountryCode: country
821
+ };
822
+ try {
823
+ let data;
824
+ if (gatewayHasShippingLogo === false) {
825
+ data = await this.client.request(GET_PRODUCT_SHIPPING, variables);
826
+ } else {
827
+ try {
828
+ data = await this.client.request(GET_PRODUCT_SHIPPING_WITH_LOGO, variables);
829
+ gatewayHasShippingLogo = true;
830
+ } catch (err) {
831
+ if (!/logo_url/.test(String(err?.message ?? ""))) throw err;
832
+ gatewayHasShippingLogo = false;
833
+ data = await this.client.request(GET_PRODUCT_SHIPPING, variables);
834
+ }
835
+ }
836
+ const product = data.Channel?.GetProductsByIds?.[0];
837
+ if (!product) return null;
838
+ return shippingRatesFor(product.product_shipping, country);
839
+ } catch {
840
+ return null;
841
+ }
842
+ }
707
843
  };
844
+ function shippingRatesFor(productShipping, country) {
845
+ if (!Array.isArray(productShipping)) return [];
846
+ const want = String(country || "").trim().toUpperCase();
847
+ const out = [];
848
+ for (const s of productShipping) {
849
+ const countries = Array.isArray(s?.shipping_country) ? s.shipping_country : [];
850
+ const row = countries.find((c) => String(c?.country ?? "").trim().toUpperCase() === want);
851
+ const price = row?.price;
852
+ const amount = typeof price?.amount_incl_taxes === "number" ? price.amount_incl_taxes : price?.amount;
853
+ if (typeof amount !== "number" || !Number.isFinite(amount) || amount < 0) continue;
854
+ out.push({
855
+ id: String(s.id ?? ""),
856
+ name: String(s.name ?? ""),
857
+ price: amount,
858
+ currency: String(price?.currency_code ?? ""),
859
+ default: s.default === true,
860
+ description: typeof s.description === "string" ? s.description.trim() : "",
861
+ logoUrl: httpsUrlOrEmpty(s.logo_url ?? s.logoUrl)
862
+ });
863
+ }
864
+ return out.sort((a, b) => a.price - b.price);
865
+ }
708
866
  var Channel = class {
709
867
  constructor(client) {
710
868
  this.product = new ChannelProduct(client);
@@ -723,6 +881,11 @@ var CommerceClient = class {
723
881
  function createCommerceClient(options) {
724
882
  return new CommerceClient(options);
725
883
  }
884
+ function httpsUrlOrEmpty(value) {
885
+ if (typeof value !== "string") return "";
886
+ const url = value.trim();
887
+ return /^https:\/\/[^\s]+$/i.test(url) ? url : "";
888
+ }
726
889
 
727
890
  // src/core/content.ts
728
891
  var CONTENT_ID_QUERY = "vio_content";
@@ -1890,11 +2053,10 @@ async function getCartGraphQLOptions(sponsorId) {
1890
2053
  }
1891
2054
  var CUSTOMER_SESSION_KEY = "vio.customer_session_id.v1";
1892
2055
  function getCustomerSessionId() {
1893
- if (typeof localStorage === "undefined") return "cs_session_default";
1894
- let id = localStorage.getItem(CUSTOMER_SESSION_KEY);
2056
+ let id = storageGet("local", CUSTOMER_SESSION_KEY);
1895
2057
  if (!id) {
1896
2058
  id = "cs_" + Math.random().toString(36).slice(2, 11) + Date.now().toString(36);
1897
- localStorage.setItem(CUSTOMER_SESSION_KEY, id);
2059
+ storageSet("local", CUSTOMER_SESSION_KEY, id);
1898
2060
  }
1899
2061
  return id;
1900
2062
  }
@@ -2214,7 +2376,36 @@ var CartManager = class extends EventTarget {
2214
2376
  /** Quantity intents for lines whose backend id hasn't arrived yet — replayed
2215
2377
  * when the AddItem response reconciles (keyed by product::variant). */
2216
2378
  this.pendingQtyIntents = /* @__PURE__ */ new Map();
2379
+ /**
2380
+ * Another tab of the site wrote the carts: adopt what it wrote, sponsor by
2381
+ * sponsor — its lines and its backend cart id, or nothing when it cleared
2382
+ * the cart (a payment) — except for a sponsor this tab is mid-write for:
2383
+ * its own answer lands in a moment and is persisted then, over whatever
2384
+ * the other tab had. `key` is null when the other tab cleared the whole
2385
+ * storage. Says `change` (the drawer) and `vio:cart-updated` per sponsor
2386
+ * that changed (`source: 'storage'`); nothing when nothing did.
2387
+ */
2388
+ this.onStorage = (e) => {
2389
+ if (e.key !== null && e.key !== STORAGE_KEY) return;
2390
+ const stored = this.loadFromStorage();
2391
+ const changed = [];
2392
+ for (const sponsorId of /* @__PURE__ */ new Set([...this.cartsBySponsor.keys(), ...stored.keys()])) {
2393
+ if (this.hasMutationsInFlight(sponsorId) || this.cartIdPromises.has(sponsorId)) continue;
2394
+ const mine = this.cartsBySponsor.get(sponsorId);
2395
+ const theirs = stored.get(sponsorId);
2396
+ if (JSON.stringify(mine ?? null) === JSON.stringify(theirs ?? null)) continue;
2397
+ if (theirs) this.cartsBySponsor.set(sponsorId, theirs);
2398
+ else this.cartsBySponsor.delete(sponsorId);
2399
+ changed.push(sponsorId);
2400
+ }
2401
+ if (changed.length === 0) return;
2402
+ this.emit();
2403
+ for (const sponsorId of changed) this.emitCartUpdated(sponsorId, "storage");
2404
+ };
2217
2405
  this.cartsBySponsor = this.loadFromStorage();
2406
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
2407
+ window.addEventListener("storage", this.onStorage);
2408
+ }
2218
2409
  }
2219
2410
  nextSeq(sponsorId) {
2220
2411
  const n = (this.mutationSeq.get(sponsorId) ?? 0) + 1;
@@ -2374,6 +2565,9 @@ var CartManager = class extends EventTarget {
2374
2565
  * Overwrite local cart state with the backend cart response (source of
2375
2566
  * truth). `opts.settling` is the mutation whose answer this is: it does not
2376
2567
  * count as "in flight" for the origins (see `hasMutationsInFlight`).
2568
+ * `opts.authoritative` is a GetCart taken with nothing of this tab's in
2569
+ * flight (`refreshFromServer`): an empty answer then means the cart IS
2570
+ * empty, and the local lines go — not an add still on its way.
2377
2571
  */
2378
2572
  updateFromBackendCart(sponsorId, backendCart, opts = {}) {
2379
2573
  const cart = this.cartsBySponsor.get(sponsorId);
@@ -2389,7 +2583,7 @@ var CartManager = class extends EventTarget {
2389
2583
  const removedBeforeSync = [];
2390
2584
  if (Array.isArray(backendCart.line_items)) {
2391
2585
  const existingItems = cart.items || [];
2392
- if (backendCart.line_items.length === 0 && existingItems.length > 0) {
2586
+ if (backendCart.line_items.length === 0 && existingItems.length > 0 && !opts.authoritative) {
2393
2587
  this.persist();
2394
2588
  this.emit();
2395
2589
  return;
@@ -2743,6 +2937,60 @@ var CartManager = class extends EventTarget {
2743
2937
  if (resCart) this.updateFromBackendCart(sponsorId, resCart);
2744
2938
  return resCart;
2745
2939
  }
2940
+ /**
2941
+ * The cart as the server has it, for the moment a checkout is about to be
2942
+ * built on it: what the shopper is about to pay must be what the page shows.
2943
+ * Waits for this tab's own mutations (their answers are the server's too),
2944
+ * then applies GetCart as it is — a line another tab added, one it removed,
2945
+ * an empty cart — and tells the page: `change` for the drawer, and
2946
+ * `vio:cart-updated` on `document` (`source: 'server'`) for a host that
2947
+ * draws its own. A mutation that starts while the server is answering makes
2948
+ * that answer old: it is asked once more. Nothing to ask without a backend
2949
+ * cart. A GetCart that fails leaves the local state as it was and does not
2950
+ * throw — the checkout then goes on with the lines the last mutation
2951
+ * answered, as it always did. Resolves with the sponsor's cart.
2952
+ */
2953
+ async refreshFromServer(sponsorId) {
2954
+ for (let attempt = 0; attempt < 2; attempt++) {
2955
+ await this.waitForCartMutations(sponsorId);
2956
+ const cart = this.cartsBySponsor.get(sponsorId);
2957
+ if (!cart?.cartId) return cart;
2958
+ let resCart;
2959
+ try {
2960
+ const gqlOpts = await getCartGraphQLOptions(sponsorId);
2961
+ resCart = await getCart(cart.cartId, gqlOpts);
2962
+ } catch (err) {
2963
+ if (typeof console !== "undefined") {
2964
+ console.warn("[CartManager] GetCart before the checkout failed \u2014 the local cart stands", err);
2965
+ }
2966
+ return cart;
2967
+ }
2968
+ if (this.hasMutationsInFlight(sponsorId)) continue;
2969
+ const backendCart = resCart;
2970
+ if (backendCart && Array.isArray(backendCart.line_items)) {
2971
+ this.updateFromBackendCart(sponsorId, backendCart, { authoritative: true });
2972
+ this.emitCartUpdated(sponsorId, "server");
2973
+ }
2974
+ return this.cartsBySponsor.get(sponsorId);
2975
+ }
2976
+ return this.cartsBySponsor.get(sponsorId);
2977
+ }
2978
+ /** `vio:cart-updated` on `document` — see `CartUpdatedDetail`. */
2979
+ emitCartUpdated(sponsorId, source) {
2980
+ if (typeof document === "undefined") return;
2981
+ const cart = this.cartsBySponsor.get(sponsorId);
2982
+ const items = (cart?.items ?? []).map((item) => ({ ...item }));
2983
+ const detail = {
2984
+ sponsorId,
2985
+ cartId: cart?.cartId,
2986
+ items,
2987
+ itemCount: items.reduce((count, item) => count + item.quantity, 0),
2988
+ subtotal: items.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0),
2989
+ currency: cart?.currency || getGlobalCurrency(),
2990
+ source
2991
+ };
2992
+ document.dispatchEvent(new CustomEvent("vio:cart-updated", { bubbles: true, detail }));
2993
+ }
2746
2994
  /** Line items grouped by supplier (shipping is per-supplier server-side). */
2747
2995
  async fetchLineItemsBySupplier(sponsorId) {
2748
2996
  const cart = this.cartsBySponsor.get(sponsorId);
@@ -2795,19 +3043,23 @@ var CartManager = class extends EventTarget {
2795
3043
  return formatPrice(this.totalAcrossSponsors, this.primaryCurrency);
2796
3044
  }
2797
3045
  // MARK: - Persistence
3046
+ /**
3047
+ * Keep the carts for the next page and the other tabs. Where storage
3048
+ * refuses (in-app browsers, private modes) nothing throws (safe-storage.ts):
3049
+ * the carts stay in this manager's own map, the add to cart and the
3050
+ * checkout go on, and the cart just does not survive a reload there.
3051
+ */
2798
3052
  persist() {
2799
- if (typeof localStorage === "undefined") return;
2800
3053
  try {
2801
3054
  const obj = {};
2802
3055
  for (const [k, v] of this.cartsBySponsor) obj[String(k)] = v;
2803
- localStorage.setItem(STORAGE_KEY, JSON.stringify(obj));
3056
+ storageSet("local", STORAGE_KEY, JSON.stringify(obj), { memory: false });
2804
3057
  } catch {
2805
3058
  }
2806
3059
  }
2807
3060
  loadFromStorage() {
2808
- if (typeof localStorage === "undefined") return /* @__PURE__ */ new Map();
2809
3061
  try {
2810
- const raw = localStorage.getItem(STORAGE_KEY);
3062
+ const raw = storageGet("local", STORAGE_KEY);
2811
3063
  if (!raw) return /* @__PURE__ */ new Map();
2812
3064
  const obj = JSON.parse(raw);
2813
3065
  const map = /* @__PURE__ */ new Map();
@@ -2969,13 +3221,15 @@ function sponsorIdentityFrom(boot, sponsorId) {
2969
3221
  if (!name && !logoUrl) return null;
2970
3222
  const termsUrl = pageUrlOrNull(sponsor.termsUrl);
2971
3223
  const refundPolicyUrl = pageUrlOrNull(sponsor.refundPolicyUrl);
3224
+ const highlights = highlightsOf(sponsor.highlights);
2972
3225
  return {
2973
3226
  id,
2974
3227
  name,
2975
3228
  logoUrl,
2976
3229
  avatarUrl: urlOrNull(sponsor.avatarUrl),
2977
3230
  ...termsUrl ? { termsUrl } : {},
2978
- ...refundPolicyUrl ? { refundPolicyUrl } : {}
3231
+ ...refundPolicyUrl ? { refundPolicyUrl } : {},
3232
+ ...highlights.length ? { highlights } : {}
2979
3233
  };
2980
3234
  } catch {
2981
3235
  return null;
@@ -3070,6 +3324,20 @@ function rememberedSponsor(sponsorId) {
3070
3324
  return null;
3071
3325
  }
3072
3326
  }
3327
+ function highlightsOf(value) {
3328
+ if (!Array.isArray(value)) return [];
3329
+ const out = [];
3330
+ for (const item of value) {
3331
+ if (!item || typeof item !== "object") continue;
3332
+ const { icon, title, text: text3 } = item;
3333
+ const t = typeof title === "string" ? title.trim() : "";
3334
+ if (!t) continue;
3335
+ const body = typeof text3 === "string" ? text3.trim() : "";
3336
+ out.push({ icon: typeof icon === "string" ? icon.trim() : "", title: t, ...body ? { text: body } : {} });
3337
+ if (out.length === 3) break;
3338
+ }
3339
+ return out;
3340
+ }
3073
3341
 
3074
3342
  // src/core/checkout/payments/apple-pay.ts
3075
3343
  var STRIPE_JS_URL = "https://js.stripe.com/v3";
@@ -3267,7 +3535,7 @@ async function prepareApplePay(config) {
3267
3535
  }
3268
3536
 
3269
3537
  // src/core/version.ts
3270
- var SDK_VERSION = "0.28.0";
3538
+ var SDK_VERSION = "0.32.0";
3271
3539
 
3272
3540
  // src/core/checkout/payments/stripe-embedded.ts
3273
3541
  var CREATE_PAYMENT_INTENT_STRIPE_MUTATION = `
@@ -3433,11 +3701,8 @@ async function mountKlarnaExpressButton(opts) {
3433
3701
  const returnUrl = opts.returnUrl ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : "");
3434
3702
  let settled = false;
3435
3703
  button.on("click", () => {
3436
- if (opts.pendingKey && opts.pendingContext && typeof sessionStorage !== "undefined") {
3437
- try {
3438
- sessionStorage.setItem(opts.pendingKey, JSON.stringify(opts.pendingContext));
3439
- } catch {
3440
- }
3704
+ if (opts.pendingKey && opts.pendingContext) {
3705
+ storageSet("session", opts.pendingKey, JSON.stringify(opts.pendingContext));
3441
3706
  }
3442
3707
  const promise = sdk.Payment.initiate(() => ({
3443
3708
  currency: opts.paymentRequest.currency,
@@ -4515,6 +4780,74 @@ function adyenReturnOutcome(payment) {
4515
4780
  }
4516
4781
  }
4517
4782
 
4783
+ // src/core/checkout/phone.ts
4784
+ var CALLING_CODES = {
4785
+ NO: "47",
4786
+ SE: "46",
4787
+ DK: "45",
4788
+ FI: "358",
4789
+ IS: "354",
4790
+ DE: "49",
4791
+ GB: "44",
4792
+ UK: "44",
4793
+ IE: "353",
4794
+ NL: "31",
4795
+ BE: "32",
4796
+ FR: "33",
4797
+ ES: "34",
4798
+ PT: "351",
4799
+ IT: "39",
4800
+ AT: "43",
4801
+ CH: "41",
4802
+ PL: "48",
4803
+ EE: "372",
4804
+ LV: "371",
4805
+ LT: "370",
4806
+ CZ: "420",
4807
+ SK: "421",
4808
+ HU: "36",
4809
+ US: "1",
4810
+ CA: "1"
4811
+ };
4812
+ var KNOWN_CODES = [...new Set(Object.values(CALLING_CODES))].sort((a, b) => b.length - a.length);
4813
+ var NATIONAL_LENGTH = {
4814
+ "47": [8, 8],
4815
+ "45": [8, 8],
4816
+ "46": [7, 9],
4817
+ "358": [6, 10],
4818
+ "49": [10, 11],
4819
+ "44": [10, 10],
4820
+ "1": [10, 10]
4821
+ };
4822
+ function callingCodeFor(country) {
4823
+ return CALLING_CODES[String(country ?? "").trim().toUpperCase()] ?? null;
4824
+ }
4825
+ function parsePhone(raw, country) {
4826
+ const typed = String(raw ?? "").trim().replace(/[\s\-().]/g, "");
4827
+ if (!typed) return null;
4828
+ let code = null;
4829
+ let national;
4830
+ if (/^(\+|00)/.test(typed)) {
4831
+ const digits = typed.replace(/^(\+|00)/, "");
4832
+ if (!/^\d+$/.test(digits)) return null;
4833
+ code = KNOWN_CODES.find((c) => digits.startsWith(c)) ?? null;
4834
+ if (!code) return null;
4835
+ national = digits.slice(code.length);
4836
+ } else {
4837
+ if (!/^\d+$/.test(typed)) return null;
4838
+ code = callingCodeFor(country);
4839
+ if (!code) return null;
4840
+ national = typed;
4841
+ }
4842
+ if (national.startsWith("0") && code !== "47" && code !== "45") national = national.slice(1);
4843
+ const [min, max] = NATIONAL_LENGTH[code] ?? [6, 12];
4844
+ if (national.length < min || national.length > max) return null;
4845
+ return { phone: national, phone_code: code };
4846
+ }
4847
+ function isValidPhone(raw, country) {
4848
+ return parsePhone(raw, country) !== null;
4849
+ }
4850
+
4518
4851
  // src/core/checkout/checkout-manager.ts
4519
4852
  function describeError(err) {
4520
4853
  if (err instanceof Error) return err.message;
@@ -4532,6 +4865,7 @@ function describeError(err) {
4532
4865
  }
4533
4866
  return String(err);
4534
4867
  }
4868
+ var KLARNA_CONFIRMED_KEY = "vio.klarna.confirmed.v1";
4535
4869
  var KLARNA_PENDING_KEY = "vio.klarna.pending.v1";
4536
4870
  var KLARNA_SHIPPING_OPTIONS = [
4537
4871
  {
@@ -4695,15 +5029,20 @@ function buildCheckoutAddress(address) {
4695
5029
  const zip = address.postalCode || address.postal_code || address.zip || null;
4696
5030
  const country_code = address.countryCode || address.country_code || address.country || getGlobalCountryCode();
4697
5031
  if (!firstName && !lastName && !address1 && !city && !zip) return null;
5032
+ const phone = parsePhone(address.phone, country_code);
4698
5033
  return {
4699
5034
  first_name: firstName,
4700
5035
  last_name: lastName,
4701
5036
  address1,
4702
5037
  city,
4703
5038
  zip,
4704
- country_code
5039
+ country_code,
5040
+ ...phone ? { phone: phone.phone, phone_code: phone.phone_code } : {}
4705
5041
  };
4706
5042
  }
5043
+ function isCompleteCheckoutAddress(a) {
5044
+ return !!a && ["first_name", "last_name", "address1", "city", "zip"].every((k) => String(a[k] ?? "").trim().length > 0);
5045
+ }
4707
5046
  function adyenReturnUrl(params) {
4708
5047
  let page = null;
4709
5048
  if (typeof window !== "undefined" && window.location?.href) {
@@ -4729,6 +5068,11 @@ function adyenReturnUrl(params) {
4729
5068
  bare.search = "";
4730
5069
  return build(bare);
4731
5070
  }
5071
+ function paymentMethodName(method) {
5072
+ if (typeof method !== "string") return void 0;
5073
+ const name = method.trim().toLowerCase().replace(/\s+/g, "-");
5074
+ return name || void 0;
5075
+ }
4732
5076
  function resolveHttpsReturnUrl(overrideUrl, params = null) {
4733
5077
  let url = overrideUrl ?? void 0;
4734
5078
  if (!url && typeof window !== "undefined" && window.location) {
@@ -4763,6 +5107,18 @@ function resolveHttpsReturnUrl(overrideUrl, params = null) {
4763
5107
  async function executeKlarnaGraphQL(query, variables, sponsorId) {
4764
5108
  return executeCartGraphQL(query, variables, await getCartGraphQLOptions(sponsorId));
4765
5109
  }
5110
+ function usesStripe(methods) {
5111
+ if (!Array.isArray(methods)) return false;
5112
+ return methods.some((m) => {
5113
+ if (String(m?.name ?? "").toLowerCase() !== "stripe") return false;
5114
+ const config = Array.isArray(m?.config) ? m.config : [];
5115
+ const key = config.find((c) => c?.name === "publishableKey")?.value;
5116
+ return typeof key === "string" && key.startsWith("pk_");
5117
+ });
5118
+ }
5119
+ function cartTotal(items) {
5120
+ return items.reduce((sum, i) => sum + (Number(i.unitPrice) || 0) * (Number(i.quantity) || 0), 0);
5121
+ }
4766
5122
  var CheckoutManager = class _CheckoutManager extends EventTarget {
4767
5123
  constructor(cartManager, deps = {}) {
4768
5124
  super();
@@ -4771,6 +5127,8 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4771
5127
  this.currentStateValue = null;
4772
5128
  /** The last checkout + identity written to the memory — the state is set on every keystroke of the form. */
4773
5129
  this.lastRememberedSponsor = "";
5130
+ /** Backend checkouts this page load announced with `vio:checkout-created`: one event each. */
5131
+ this.announcedCheckouts = /* @__PURE__ */ new Set();
4774
5132
  /** Counts `open()` calls — see CheckoutState.session. */
4775
5133
  this.sessionSeq = 0;
4776
5134
  this.applePayAvailableCache = null;
@@ -4809,10 +5167,17 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4809
5167
  this.paymentMethodsCache = /* @__PURE__ */ new Map();
4810
5168
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4811
5169
  this.paymentMethodsPromises = /* @__PURE__ */ new Map();
5170
+ /** What the open checkout's cart looked like when it was last emitted. */
5171
+ this.lastCartSignature = null;
4812
5172
  /** In-flight `getOrderReference` per checkout id (see there). */
4813
5173
  this.referenceInFlight = /* @__PURE__ */ new Map();
4814
5174
  this.kustomController = null;
4815
- preloadStripeJs();
5175
+ if (Configuration.isInitialized && Configuration.get()?.stripePublishableKey) {
5176
+ preloadStripeJs();
5177
+ }
5178
+ if (typeof cartManager.addEventListener === "function") {
5179
+ cartManager.addEventListener("change", () => this.onCartChange());
5180
+ }
4816
5181
  }
4817
5182
  /**
4818
5183
  * Every write of the state goes through here: a state that names its
@@ -4826,11 +5191,29 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4826
5191
  this.currentStateValue = next;
4827
5192
  if (next?.checkoutId && next.sponsorId) this.rememberSponsorOfCheckout(next.checkoutId, next.sponsorId);
4828
5193
  }
5194
+ /** The open checkout's lines as a signature, to tell a real change from an echo. */
5195
+ cartSignature(sponsorId) {
5196
+ return (this.cartManager.getCart(sponsorId)?.items ?? []).map((i) => `${i.productId}:${i.variantId ?? ""}:${i.quantity}:${i.unitPrice}`).join("|");
5197
+ }
5198
+ /** The open checkout follows its cart: subtotal recomputed and `change` said when the lines differ. */
5199
+ onCartChange() {
5200
+ const state = this.state;
5201
+ if (!state) return;
5202
+ const subtotal = this.cartManager.subtotalForSponsor(state.sponsorId);
5203
+ const signature = this.cartSignature(state.sponsorId);
5204
+ if (subtotal === state.subtotal && signature === this.lastCartSignature) return;
5205
+ this.lastCartSignature = signature;
5206
+ this.state = { ...state, subtotal };
5207
+ this.emit();
5208
+ }
4829
5209
  open(sponsorId) {
4830
5210
  const cart = this.cartManager.getCart(sponsorId);
4831
5211
  if (!cart || cart.items.length === 0) {
4832
5212
  throw new Error(`[VioCheckout] sponsor ${sponsorId} has no cart items`);
4833
5213
  }
5214
+ if (!(cartTotal(cart.items) > 0)) {
5215
+ throw new Error(`[VioCheckout] sponsor ${sponsorId} has a cart that totals 0`);
5216
+ }
4834
5217
  this.state = {
4835
5218
  sponsorId,
4836
5219
  session: ++this.sessionSeq,
@@ -4839,6 +5222,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4839
5222
  // the host may have switched currency since the cart was created.
4840
5223
  currency: getGlobalCurrency()
4841
5224
  };
5225
+ this.lastCartSignature = this.cartSignature(sponsorId);
4842
5226
  this.emit();
4843
5227
  return this.state;
4844
5228
  }
@@ -4863,9 +5247,15 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4863
5247
  return void 0;
4864
5248
  }
4865
5249
  }
4866
- /** Create the backend checkout for the sponsor's cart (auto-accepts terms); born attributed when the facade knows the attribution. */
4867
- async createCheckout(sponsorId) {
5250
+ /**
5251
+ * Create the backend checkout for the sponsor's cart (auto-accepts terms);
5252
+ * born attributed when the facade knows the attribution. `paymentMethod` is
5253
+ * the method it is created to pay with, when the caller knows it (else the
5254
+ * state's): it goes on `vio:checkout-created`.
5255
+ */
5256
+ async createCheckout(sponsorId, paymentMethod) {
4868
5257
  await this.cartManager.waitForCartMutations(sponsorId);
5258
+ await this.cartManager.refreshFromServer(sponsorId);
4869
5259
  const cart = this.cartManager.getCart(sponsorId);
4870
5260
  let cartId = cart?.cartId;
4871
5261
  if (!cartId) {
@@ -4885,6 +5275,9 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4885
5275
  checkout
4886
5276
  };
4887
5277
  this.emit();
5278
+ this.announceCheckout(checkout.id, sponsorId, paymentMethod ?? this.state?.paymentMethod, {
5279
+ campaignId: attribution?.campaign_id
5280
+ });
4888
5281
  try {
4889
5282
  const updated = await updateCheckout(
4890
5283
  {
@@ -4907,6 +5300,50 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
4907
5300
  }
4908
5301
  return checkout;
4909
5302
  }
5303
+ /**
5304
+ * `vio:checkout-created` on `window` — `{ sponsorId, checkoutId,
5305
+ * paymentMethod, campaignId?, redirect }` — the moment a backend checkout
5306
+ * exists for a payment, before anything is asked of the provider. Analytics
5307
+ * answers it with `add_payment_info` (ADR-0039: the one link from the
5308
+ * order Commerce confirms back to this browser's session); `redirect: true`
5309
+ * when the page is about to leave for the provider. Once per checkout per
5310
+ * page load; never throws.
5311
+ */
5312
+ announceCheckout(checkoutId, sponsorId, paymentMethod, opts = {}) {
5313
+ if (!checkoutId || this.announcedCheckouts.has(checkoutId)) return;
5314
+ this.announcedCheckouts.add(checkoutId);
5315
+ if (typeof window === "undefined" || typeof window.dispatchEvent !== "function") return;
5316
+ const method = paymentMethodName(paymentMethod);
5317
+ try {
5318
+ window.dispatchEvent(
5319
+ new CustomEvent("vio:checkout-created", {
5320
+ detail: {
5321
+ sponsorId,
5322
+ checkoutId,
5323
+ ...method ? { paymentMethod: method } : {},
5324
+ ...typeof opts.campaignId === "number" ? { campaignId: opts.campaignId } : {},
5325
+ redirect: opts.redirect === true
5326
+ }
5327
+ })
5328
+ );
5329
+ } catch {
5330
+ }
5331
+ }
5332
+ /**
5333
+ * Nothing is created or paid for a cart that is empty or totals 0 — as
5334
+ * the SERVER has it (the callers read it from the server first). Throws,
5335
+ * so a payment button ends in its error path, never at a provider asking
5336
+ * for 0 kr.
5337
+ */
5338
+ assertPayableCart(sponsorId) {
5339
+ const cart = this.cartManager.getCart(sponsorId);
5340
+ if (!cart || !Array.isArray(cart.items) || cart.items.length === 0) {
5341
+ throw new Error(`[CheckoutManager] the cart of sponsor ${sponsorId} is empty \u2014 nothing to pay`);
5342
+ }
5343
+ if (!(cartTotal(cart.items) > 0)) {
5344
+ throw new Error(`[CheckoutManager] the cart of sponsor ${sponsorId} totals 0 \u2014 nothing to pay`);
5345
+ }
5346
+ }
4910
5347
  /** Update the backend checkout (terms are re-asserted unless overridden; the attribution rides along unless the caller gives its own). */
4911
5348
  async updateCheckout(variables, sponsorId) {
4912
5349
  const spId = sponsorId ?? this.state?.sponsorId;
@@ -5037,6 +5474,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5037
5474
  const opts = await getCartGraphQLOptions(spId);
5038
5475
  const res = await getAvailablePaymentMethods(opts);
5039
5476
  if (res) this.paymentMethodsCache.set(spId, res);
5477
+ if (usesStripe(res)) preloadStripeJs();
5040
5478
  return res;
5041
5479
  } finally {
5042
5480
  this.paymentMethodsPromises.delete(spId);
@@ -5136,10 +5574,21 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5136
5574
  * backend cart + checkout exist, push email/address onto the checkout, and
5137
5575
  * return everything the payment mutation needs.
5138
5576
  */
5139
- async prepareRedirectPayment(sponsorId, formData, extraUpdateVars = {}) {
5577
+ async prepareRedirectPayment(sponsorId, formData, extraUpdateVars = {}, leaving = false, vippsWithAddress = false) {
5140
5578
  const spId = sponsorId ?? this.state?.sponsorId;
5141
5579
  if (!spId) throw new Error("[CheckoutManager] no sponsor for payment");
5142
5580
  await this.cartManager.waitForCartMutations(spId);
5581
+ await this.cartManager.refreshFromServer(spId);
5582
+ this.assertPayableCart(spId);
5583
+ const isVipps = extraUpdateVars?.paymentMethod === "Vipps";
5584
+ const addr = typeof formData === "object" && formData !== null ? formData : this.state?.address;
5585
+ const built = buildCheckoutAddress(addr);
5586
+ if (isVipps && vippsWithAddress && !(isCompleteCheckoutAddress(built) && built?.phone)) {
5587
+ throw new Error(
5588
+ "[CheckoutManager] the standard Vipps payment needs the complete delivery address (name, street, postcode, city and a mobile number) \u2014 no payment started"
5589
+ );
5590
+ }
5591
+ const addressObj = !isVipps ? built : vippsWithAddress ? built : null;
5143
5592
  const cart = this.cartManager.getCart(spId);
5144
5593
  let cartId = cart?.cartId;
5145
5594
  if (!cartId) {
@@ -5154,13 +5603,14 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5154
5603
  if (!checkoutId) {
5155
5604
  const checkoutRes = attribution ? await createCheckout(cartId, opts, { attribution }) : await createCheckout(cartId, opts);
5156
5605
  checkoutId = checkoutRes?.id;
5606
+ this.announceCheckout(checkoutId, spId, String(extraUpdateVars.paymentMethod ?? "") || this.state?.paymentMethod, {
5607
+ redirect: leaving,
5608
+ campaignId: attribution?.campaign_id
5609
+ });
5157
5610
  }
5158
5611
  if (!checkoutId) {
5159
5612
  throw new Error("[CheckoutManager] no backend checkout \u2014 cannot start the payment");
5160
5613
  }
5161
- const isVipps = extraUpdateVars?.paymentMethod === "Vipps";
5162
- const addr = typeof formData === "object" && formData !== null ? formData : this.state?.address;
5163
- const addressObj = !isVipps ? buildCheckoutAddress(addr) : null;
5164
5614
  const emailVal = (typeof formData === "string" ? formData : formData?.email) || this.state?.address?.email || "";
5165
5615
  const hasEmail = !!emailVal && emailVal.includes("@");
5166
5616
  if (!hasEmail && !isVipps) {
@@ -5222,7 +5672,8 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5222
5672
  const { spId, checkoutId, emailVal, opts } = await this.prepareRedirectPayment(
5223
5673
  sponsorId,
5224
5674
  formData,
5225
- { paymentMethod: "Stripe" }
5675
+ { paymentMethod: "Stripe" },
5676
+ true
5226
5677
  );
5227
5678
  const successUrl = resolveHttpsReturnUrl(null, {
5228
5679
  vio_payment: "success",
@@ -5254,6 +5705,11 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5254
5705
  * so the caller can open the ordinary checkout instead. Without the flag
5255
5706
  * the backend decides: Express while the cart has no delivery yet, a
5256
5707
  * plain payment once the shopper chose one in our form.
5708
+ *
5709
+ * `express: false` is the checkout's standard path (2026-10-28): the
5710
+ * form's address — name, street, mobile — goes on the checkout before the
5711
+ * payment is created, and the delivery already chosen on the cart is what
5712
+ * Vipps charges for.
5257
5713
  */
5258
5714
  async startVippsPayment(sponsorId, formData, options = {}) {
5259
5715
  const waitFor = sponsorId ?? this.state?.sponsorId;
@@ -5261,7 +5717,9 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5261
5717
  const { spId, checkoutId, emailVal, opts } = await this.prepareRedirectPayment(
5262
5718
  sponsorId,
5263
5719
  formData,
5264
- { paymentMethod: "Vipps" }
5720
+ { paymentMethod: "Vipps" },
5721
+ true,
5722
+ options.express === false
5265
5723
  );
5266
5724
  const returnUrl = resolveHttpsReturnUrl(null, {
5267
5725
  vio_payment: "success",
@@ -5318,7 +5776,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5318
5776
  const opts = await getCartGraphQLOptions(spId);
5319
5777
  let checkoutId = this.state?.checkoutId;
5320
5778
  if (!checkoutId) {
5321
- const checkoutRes = await this.createCheckout(spId);
5779
+ const checkoutRes = await this.createCheckout(spId, "kustom");
5322
5780
  checkoutId = checkoutRes?.id;
5323
5781
  if (checkoutId && this.state) {
5324
5782
  this.state = { ...this.state, checkoutId };
@@ -5394,7 +5852,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5394
5852
  const opts = await getCartGraphQLOptions(spId);
5395
5853
  let checkoutId = this.state?.checkoutId;
5396
5854
  if (!checkoutId) {
5397
- const checkoutRes = await this.createCheckout(spId);
5855
+ const checkoutRes = await this.createCheckout(spId, "qliro");
5398
5856
  checkoutId = checkoutRes?.id;
5399
5857
  if (checkoutId && this.state) {
5400
5858
  this.state = { ...this.state, checkoutId };
@@ -5482,7 +5940,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5482
5940
  const opts = await getCartGraphQLOptions(spId);
5483
5941
  let checkoutId = this.state?.checkoutId;
5484
5942
  if (!checkoutId) {
5485
- const checkoutRes = await this.createCheckout(spId);
5943
+ const checkoutRes = await this.createCheckout(spId, "walley");
5486
5944
  checkoutId = checkoutRes?.id;
5487
5945
  if (checkoutId && this.state) {
5488
5946
  this.state = { ...this.state, checkoutId };
@@ -5551,7 +6009,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
5551
6009
  if (this.state) this.state = { ...this.state, checkoutId };
5552
6010
  }
5553
6011
  if (!checkoutId) {
5554
- const checkoutRes = await this.createCheckout(spId);
6012
+ const checkoutRes = await this.createCheckout(spId, "nexi");
5555
6013
  checkoutId = checkoutRes?.id;
5556
6014
  if (checkoutId && this.state) {
5557
6015
  this.state = { ...this.state, checkoutId };
@@ -6116,7 +6574,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6116
6574
  return async (raw) => {
6117
6575
  let checkoutId = this.state?.checkoutId;
6118
6576
  if (!checkoutId) {
6119
- const created = await this.createCheckout(spId);
6577
+ const created = await this.createCheckout(spId, "apple-pay");
6120
6578
  checkoutId = created?.id ?? this.state?.checkoutId;
6121
6579
  }
6122
6580
  if (!checkoutId) {
@@ -6348,7 +6806,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6348
6806
  }
6349
6807
  let checkoutId = ctx.checkoutId ?? this.state.checkoutId;
6350
6808
  try {
6351
- const checkoutRes = await this.createCheckout(sponsorId);
6809
+ const checkoutRes = await this.createCheckout(sponsorId, "klarna");
6352
6810
  if (checkoutRes?.id) {
6353
6811
  checkoutId = checkoutRes.id;
6354
6812
  ctx.checkoutId = checkoutRes.id;
@@ -6400,6 +6858,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6400
6858
  if (nativeRes.checkout_id) {
6401
6859
  ctx.checkoutId = nativeRes.checkout_id;
6402
6860
  this.state = { ...this.state, checkoutId: nativeRes.checkout_id };
6861
+ this.announceCheckout(nativeRes.checkout_id, sponsorId, "klarna");
6403
6862
  }
6404
6863
  if (nativeRes.session_id) {
6405
6864
  ctx.sessionId = nativeRes.session_id;
@@ -6497,7 +6956,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6497
6956
  try {
6498
6957
  let checkoutId = ctx.checkoutId ?? this.state.checkoutId;
6499
6958
  try {
6500
- const checkoutRes = await this.createCheckout(sponsorId);
6959
+ const checkoutRes = await this.createCheckout(sponsorId, "klarna");
6501
6960
  if (checkoutRes?.id) {
6502
6961
  checkoutId = checkoutRes.id;
6503
6962
  ctx.checkoutId = checkoutRes.id;
@@ -6543,6 +7002,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6543
7002
  if (nativeRes.checkout_id) {
6544
7003
  ctx.checkoutId = nativeRes.checkout_id;
6545
7004
  this.state = { ...this.state, checkoutId: nativeRes.checkout_id };
7005
+ this.announceCheckout(nativeRes.checkout_id, sponsorId, "klarna");
6546
7006
  }
6547
7007
  if (nativeRes.session_id) {
6548
7008
  ctx.sessionId = nativeRes.session_id;
@@ -6596,14 +7056,13 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6596
7056
  * the SDK's resumed `complete` event — finish creating the order + confirm.
6597
7057
  */
6598
7058
  async resumeKlarnaReturn() {
6599
- if (typeof sessionStorage === "undefined") return;
6600
- const raw = sessionStorage.getItem(KLARNA_PENDING_KEY);
7059
+ const raw = storageGet("session", KLARNA_PENDING_KEY);
6601
7060
  if (!raw) return;
6602
7061
  let pending2;
6603
7062
  try {
6604
7063
  pending2 = JSON.parse(raw);
6605
7064
  } catch {
6606
- sessionStorage.removeItem(KLARNA_PENDING_KEY);
7065
+ storageRemove("session", KLARNA_PENDING_KEY);
6607
7066
  return;
6608
7067
  }
6609
7068
  const fromUrl = readKlarnaTokenFromUrl();
@@ -6661,7 +7120,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6661
7120
  async completeKlarnaOrder(authorizationToken, ctx, result) {
6662
7121
  if (this.klarnaOrderInFlight) return;
6663
7122
  this.klarnaOrderInFlight = true;
6664
- if (typeof sessionStorage !== "undefined" && sessionStorage.getItem("vio.klarna.confirmed.v1") === authorizationToken) {
7123
+ if (storageGet("session", KLARNA_CONFIRMED_KEY) === authorizationToken) {
6665
7124
  this.klarnaOrderInFlight = false;
6666
7125
  return;
6667
7126
  }
@@ -6689,10 +7148,8 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
6689
7148
  }
6690
7149
  const orderData = confirmRes.order || confirmRes;
6691
7150
  const buyerRef = normalizeBuyerRef(confirmRes[BUYER_REF_FIELD]);
6692
- if (typeof sessionStorage !== "undefined") {
6693
- sessionStorage.setItem("vio.klarna.confirmed.v1", authorizationToken);
6694
- sessionStorage.removeItem(KLARNA_PENDING_KEY);
6695
- }
7151
+ storageSet("session", KLARNA_CONFIRMED_KEY, authorizationToken);
7152
+ storageRemove("session", KLARNA_PENDING_KEY);
6696
7153
  const state = this.state ?? { sponsorId: ctx.sponsorId, subtotal: ctx.orderAmount, currency: ctx.currency };
6697
7154
  this.dispatchEvent(
6698
7155
  new CustomEvent("payment-complete", {
@@ -6934,6 +7391,54 @@ function safeCall(fn) {
6934
7391
  }
6935
7392
  }
6936
7393
 
7394
+ // src/core/analytics/internal-traffic.ts
7395
+ var INTERNAL_KEY = "vio.internal.v1";
7396
+ var INTERNAL_PARAM = "vio_internal";
7397
+ function defaultInternalEnvironment() {
7398
+ return {
7399
+ location: typeof location !== "undefined" ? location : null,
7400
+ storage: localStorageOrNull()
7401
+ };
7402
+ }
7403
+ function resolveInternal(env = defaultInternalEnvironment()) {
7404
+ const param = internalParam(env.location?.search);
7405
+ if (param !== void 0) {
7406
+ writeInternal(param, env.storage);
7407
+ return param;
7408
+ }
7409
+ return readInternal(env.storage);
7410
+ }
7411
+ function readInternal(storage2 = defaultInternalEnvironment().storage) {
7412
+ try {
7413
+ return storage2?.getItem(INTERNAL_KEY) === "1";
7414
+ } catch {
7415
+ return false;
7416
+ }
7417
+ }
7418
+ function writeInternal(internal, storage2 = defaultInternalEnvironment().storage) {
7419
+ try {
7420
+ if (internal) storage2?.setItem(INTERNAL_KEY, "1");
7421
+ else storage2?.removeItem?.(INTERNAL_KEY);
7422
+ } catch {
7423
+ }
7424
+ }
7425
+ function internalParam(search) {
7426
+ try {
7427
+ const value = new URLSearchParams(typeof search === "string" ? search : "").get(INTERNAL_PARAM)?.trim();
7428
+ if (value === "1") return true;
7429
+ if (value === "0") return false;
7430
+ } catch {
7431
+ }
7432
+ return void 0;
7433
+ }
7434
+ function localStorageOrNull() {
7435
+ try {
7436
+ return typeof window !== "undefined" && window.localStorage ? window.localStorage : null;
7437
+ } catch {
7438
+ return null;
7439
+ }
7440
+ }
7441
+
6937
7442
  // src/core/cart/slices.ts
6938
7443
  function cartSlicesFrom(lines, resolveCampaign, fallbackCurrency) {
6939
7444
  if (!Array.isArray(lines) || lines.length === 0) return [];
@@ -7010,6 +7515,7 @@ var FLUSH_AT_COUNT = 20;
7010
7515
  var MAX_QUEUE = 500;
7011
7516
  var RETRY_BACKOFF_MS = [2e3, 4e3, 8e3];
7012
7517
  var ANON_KEY = "vio.anon.v1";
7518
+ var MAX_ITEMS = 100;
7013
7519
  var SESSION_KEY = "vio.session.v1";
7014
7520
  var IMPRESSION_THRESHOLD = 0.5;
7015
7521
  var IMPRESSION_DWELL_MS = 1e3;
@@ -7017,7 +7523,14 @@ var AnalyticsManager = class extends EventTarget {
7017
7523
  constructor() {
7018
7524
  super(...arguments);
7019
7525
  this.started = false;
7020
- this.options = { host: "custom", collector: true, dataLayer: false, debug: false, autoTrack: true };
7526
+ this.options = {
7527
+ host: "custom",
7528
+ collector: true,
7529
+ dataLayer: false,
7530
+ debug: false,
7531
+ autoTrack: true,
7532
+ privateContent: false
7533
+ };
7021
7534
  this.queue = [];
7022
7535
  this.flushTimer = null;
7023
7536
  this.retryAttempt = 0;
@@ -7038,8 +7551,18 @@ var AnalyticsManager = class extends EventTarget {
7038
7551
  this.client = null;
7039
7552
  /** The landing it was read from — persisted later when consent arrives after the first event. */
7040
7553
  this.landing = null;
7554
+ /**
7555
+ * Internal traffic (ADR-0041): `client.internal: true` on every event while
7556
+ * set. Read once (`?vio_internal=1|0`, else `localStorage`) at `Vio.init()`
7557
+ * or on the first event; `setInternal()` changes it. `null` = not read yet.
7558
+ */
7559
+ this.internal = null;
7560
+ /** The console line for testers goes out once per page load. */
7561
+ this.internalAnnounced = false;
7041
7562
  /** Checkouts (`c:<id>`) and orders (`o:<number>`) this page load reported a `purchase` for: one each. */
7042
7563
  this.purchased = /* @__PURE__ */ new Set();
7564
+ /** Checkouts this page load reported an `add_payment_info` for: one each. */
7565
+ this.paymentInfoReported = /* @__PURE__ */ new Set();
7043
7566
  /** Purchases still waiting for Vio's order number: each sends at once, with what it has, when called. */
7044
7567
  this.pendingPurchases = /* @__PURE__ */ new Set();
7045
7568
  /** Between `pagehide` and `pageshow` (bfcache): nothing waits, it all goes out now. */
@@ -7085,7 +7608,8 @@ var AnalyticsManager = class extends EventTarget {
7085
7608
  collector: options.collector ?? this.options.collector,
7086
7609
  dataLayer: options.dataLayer ?? this.options.dataLayer,
7087
7610
  debug: options.debug ?? this.options.debug,
7088
- autoTrack: options.autoTrack ?? this.options.autoTrack
7611
+ autoTrack: options.autoTrack ?? this.options.autoTrack,
7612
+ privateContent: options.privateContent ?? this.options.privateContent
7089
7613
  };
7090
7614
  if (options.sessionId) this.externalSessionId = options.sessionId;
7091
7615
  if (this.started || !hasDom()) return;
@@ -7107,7 +7631,7 @@ var AnalyticsManager = class extends EventTarget {
7107
7631
  this.teardown.push(() => window.removeEventListener("pageshow", onPageShow));
7108
7632
  if (typeof document !== "undefined" && typeof document.addEventListener === "function") {
7109
7633
  const onVisibility = () => {
7110
- if (document.visibilityState !== "hidden" || this.pendingPurchases.size === 0) return;
7634
+ if (document.visibilityState !== "hidden") return;
7111
7635
  this.settlePendingPurchases();
7112
7636
  this.flushWithBeacon();
7113
7637
  };
@@ -7128,6 +7652,43 @@ var AnalyticsManager = class extends EventTarget {
7128
7652
  identify(externalUserId) {
7129
7653
  this.externalUserId = externalUserId ?? void 0;
7130
7654
  }
7655
+ /**
7656
+ * Mark (or unmark) this browser as Vio's own traffic (ADR-0041): while
7657
+ * marked, every event carries `client.internal: true` and the collector's
7658
+ * reads leave it out. Remembered in `localStorage` (`vio.internal.v1`) —
7659
+ * the same mark `?vio_internal=1` / `?vio_internal=0` sets on any page.
7660
+ */
7661
+ setInternal(internal) {
7662
+ this.internal = internal === true;
7663
+ writeInternal(this.internal);
7664
+ this.announceInternal();
7665
+ }
7666
+ /** Whether this browser is marked as internal traffic (reads the mark the first time). */
7667
+ get isInternal() {
7668
+ return this.syncInternal();
7669
+ }
7670
+ /**
7671
+ * Read the mark: the page's `?vio_internal=1|0` (remembered), else what the
7672
+ * browser remembers. Once per page load — `Vio.init()` calls it so a page
7673
+ * with the parameter marks the browser even if it never starts analytics;
7674
+ * `force` reads again.
7675
+ */
7676
+ syncInternal(force = false) {
7677
+ if (this.internal === null || force) {
7678
+ this.internal = hasDom() ? resolveInternal() : readInternal(null);
7679
+ this.announceInternal();
7680
+ }
7681
+ return this.internal;
7682
+ }
7683
+ /** One console line when marked, so a tester can see the mark took. */
7684
+ announceInternal() {
7685
+ if (!this.internal || this.internalAnnounced) return;
7686
+ this.internalAnnounced = true;
7687
+ try {
7688
+ console.info("[Vio.analytics] this browser is marked as internal traffic (vio_internal=1): its events are not counted. Open any page with ?vio_internal=0 to undo.");
7689
+ } catch {
7690
+ }
7691
+ }
7131
7692
  /** Queue one event. Works pre-init and pre-start (SSR: no-op). */
7132
7693
  track(name, opts = {}) {
7133
7694
  if (!hasDom()) return;
@@ -7172,7 +7733,7 @@ var AnalyticsManager = class extends EventTarget {
7172
7733
  this.ensureSession();
7173
7734
  if (this.impressedComponents.has(key)) return;
7174
7735
  this.impressedComponents.add(key);
7175
- this.track(name, { context });
7736
+ this.track(name, { context, commerce: impressionCommerce(opts.commerce) });
7176
7737
  opts.onImpression?.();
7177
7738
  observer.disconnect();
7178
7739
  }, IMPRESSION_DWELL_MS);
@@ -7253,26 +7814,28 @@ var AnalyticsManager = class extends EventTarget {
7253
7814
  // one is usually the tracking tail, not the page. The other host-given
7254
7815
  // fields (broadcastId, componentTemplateId, errorCode, variant, …) are
7255
7816
  // the host's responsibility: the SDK does not touch them.
7256
- content_url: capContentUrl(ctx.contentUrl ?? (typeof location !== "undefined" ? location.href : void 0)),
7817
+ // Con `privateContent` ninguno de los tres sale del dispositivo.
7818
+ content_url: this.options.privateContent ? void 0 : capContentUrl(ctx.contentUrl ?? (typeof location !== "undefined" ? location.href : void 0)),
7257
7819
  // The host's own content id — its join key back onto its reporting.
7258
7820
  // Explicit on the event when it fits, else what the SDK resolved for
7259
7821
  // the page (already capped per source), else nothing.
7260
- content_id: explicitContentId ?? fitsId(content.id),
7822
+ content_id: this.options.privateContent ? void 0 : explicitContentId ?? fitsId(content.id),
7261
7823
  // Deletion-proof reporting: sources have no trash bin — the title
7262
7824
  // snapshotted at event time keeps reports legible if content dies.
7263
7825
  error_code: ctx.errorCode,
7264
- content_title: capTitle(
7826
+ content_title: this.options.privateContent ? void 0 : capTitle(
7265
7827
  ctx.contentTitle ?? content.title ?? (typeof document !== "undefined" && document.title ? document.title : void 0)
7266
7828
  ),
7267
7829
  variant: ctx.variant
7268
7830
  });
7269
7831
  const com = opts.commerce;
7270
7832
  const commerce = com ? compact({
7271
- items: com.items?.map(
7833
+ // The collector rejects an event with more lines than its cap, whole.
7834
+ items: com.items?.slice(0, MAX_ITEMS).map(
7272
7835
  (i) => compact({
7273
7836
  product_id: String(i.productId),
7274
- name: i.name,
7275
- brand: i.brand,
7837
+ name: this.options.privateContent ? void 0 : i.name,
7838
+ brand: this.options.privateContent ? void 0 : i.brand,
7276
7839
  variant_id: i.variantId !== void 0 ? String(i.variantId) : void 0,
7277
7840
  price: i.price,
7278
7841
  quantity: i.quantity
@@ -7289,7 +7852,8 @@ var AnalyticsManager = class extends EventTarget {
7289
7852
  // ids does not carry a stable identifier of a person either.
7290
7853
  buyer_id: this.canPersist ? normalizeBuyerRef(com.buyerId) : void 0
7291
7854
  }) : void 0;
7292
- const client = this.clientBlock();
7855
+ const base = this.clientBlock();
7856
+ const client = this.syncInternal() ? { ...base ?? {}, internal: true } : base;
7293
7857
  return {
7294
7858
  event_id: uuid(),
7295
7859
  name,
@@ -7520,6 +8084,34 @@ var AnalyticsManager = class extends EventTarget {
7520
8084
  ...snap || buyerId !== void 0 ? { commerce: { ...snap ?? {}, ...buyer } } : {}
7521
8085
  });
7522
8086
  });
8087
+ on("vio:checkout-created", (ev) => {
8088
+ const d = ev.detail ?? {};
8089
+ const checkoutId = firstId(d.checkoutId);
8090
+ if (!checkoutId || this.paymentInfoReported.has(checkoutId)) return;
8091
+ this.paymentInfoReported.add(checkoutId);
8092
+ const sponsorId = toNumber(d.sponsorId);
8093
+ const base = { sponsorId, campaignId: campaignOf(d), slot: slotOf(d), ...contentOf(d) };
8094
+ const payment = {
8095
+ checkoutId,
8096
+ ...typeof d.paymentMethod === "string" && d.paymentMethod ? { paymentMethod: d.paymentMethod } : {}
8097
+ };
8098
+ const { slices, explicit } = this.cartSlices(sponsorId);
8099
+ if (slices.length > 1) {
8100
+ for (const slice of slices) {
8101
+ this.track("add_payment_info", {
8102
+ context: this.sliceContext(slice, base),
8103
+ commerce: { ...sliceCommerce(slice), ...payment },
8104
+ props: { slice: slice.slice, slices: slice.slices }
8105
+ });
8106
+ }
8107
+ } else {
8108
+ this.track("add_payment_info", {
8109
+ context: this.singleSliceContext(slices[0], explicit, base),
8110
+ commerce: { ...this.cartCommerce(sponsorId) ?? {}, ...payment }
8111
+ });
8112
+ }
8113
+ if (d.redirect === true) this.flushWithBeacon();
8114
+ });
7523
8115
  on("vio:payment-success", (ev) => {
7524
8116
  const d = ev.detail ?? {};
7525
8117
  const ids = purchaseIdsOf(d);
@@ -7600,6 +8192,7 @@ var AnalyticsManager = class extends EventTarget {
7600
8192
  }
7601
8193
  this.record(event);
7602
8194
  }
8195
+ this.sendNow();
7603
8196
  };
7604
8197
  const ask = ids.orderIdKind === "checkout" ? this.orderReferenceAsker(ids.checkoutId, sponsorId) : null;
7605
8198
  if (!ask) {
@@ -7608,7 +8201,6 @@ var AnalyticsManager = class extends EventTarget {
7608
8201
  }
7609
8202
  if (this.isPageHidden()) {
7610
8203
  send();
7611
- this.flushWithBeacon();
7612
8204
  return;
7613
8205
  }
7614
8206
  let done = false;
@@ -7622,6 +8214,14 @@ var AnalyticsManager = class extends EventTarget {
7622
8214
  this.pendingPurchases.add(settleNow);
7623
8215
  void waitForOrderNumber(ask, () => done).then(settle, () => settle());
7624
8216
  }
8217
+ /**
8218
+ * Sends the queue now, not at the next tick: by beacon when the page is
8219
+ * hidden or going away (a request may not survive it), else by fetch.
8220
+ */
8221
+ sendNow() {
8222
+ if (this.isPageHidden()) this.flushWithBeacon();
8223
+ else void this.flush();
8224
+ }
7625
8225
  /** Sends every purchase still waiting for its order number, at once, with what it has. */
7626
8226
  settlePendingPurchases() {
7627
8227
  for (const settle of [...this.pendingPurchases]) settle();
@@ -7782,6 +8382,15 @@ function safeStorageSet(key, value) {
7782
8382
  } catch {
7783
8383
  }
7784
8384
  }
8385
+ function impressionCommerce(read) {
8386
+ if (!read) return void 0;
8387
+ try {
8388
+ const commerce = read();
8389
+ return commerce?.items?.length ? commerce : void 0;
8390
+ } catch {
8391
+ return void 0;
8392
+ }
8393
+ }
7785
8394
  function compact(obj) {
7786
8395
  const out = {};
7787
8396
  for (const [k, v] of Object.entries(obj)) {
@@ -7957,6 +8566,7 @@ function pushGa4(event) {
7957
8566
  "add_to_cart",
7958
8567
  "view_cart",
7959
8568
  "begin_checkout",
8569
+ "add_payment_info",
7960
8570
  "purchase"
7961
8571
  ]);
7962
8572
  if (!commerceNames.has(event.name)) return;
@@ -7970,6 +8580,7 @@ function pushGa4(event) {
7970
8580
  currency: commerce.currency,
7971
8581
  value: commerce.value,
7972
8582
  transaction_id: commerce.order_id,
8583
+ payment_type: event.name === "add_payment_info" ? commerce.payment_method : void 0,
7973
8584
  items: commerce.items?.map(
7974
8585
  (i) => compact({
7975
8586
  item_id: i.product_id,
@@ -8113,6 +8724,10 @@ var VioFacade = class {
8113
8724
  this.surfaceMode = null;
8114
8725
  this.surfaceRequest = null;
8115
8726
  this.preloadPrivacyMode();
8727
+ try {
8728
+ this.analytics.syncInternal(true);
8729
+ } catch {
8730
+ }
8116
8731
  this.checkoutManager?.clearPaymentMethodsCache();
8117
8732
  if (this.slotDeclareTimer) {
8118
8733
  clearTimeout(this.slotDeclareTimer);
@@ -8304,9 +8919,9 @@ var VioFacade = class {
8304
8919
  for (const l of all) {
8305
8920
  if (l.campaignId !== void 0 && l.campaignId === pageCampaignId) delete l.campaignId;
8306
8921
  }
8307
- const memory = readSlotDeclaration(storageKey);
8922
+ const memory2 = readSlotDeclaration(storageKey);
8308
8923
  const keyOf = (l) => slotDeclarationKey(l, pageCampaignId);
8309
- const pending2 = new Set(pendingSlotKeys(memory, all.map(keyOf), now));
8924
+ const pending2 = new Set(pendingSlotKeys(memory2, all.map(keyOf), now));
8310
8925
  let locations = opts.force ? all : all.filter((l) => pending2.has(keyOf(l)));
8311
8926
  if (locations.length === 0) return null;
8312
8927
  if (locations.length > MAX_LOCATIONS_PER_DECLARATION) {
@@ -8339,11 +8954,11 @@ var VioFacade = class {
8339
8954
  if (result?.mode === "merge") {
8340
8955
  const unhandled = this.campaignNotTakenUp(result, locations, pageCampaignId);
8341
8956
  const settled = keys.filter((k) => !unhandled.has(k));
8342
- let next = rememberSlotKeys(memory, settled, now);
8957
+ let next = rememberSlotKeys(memory2, settled, now);
8343
8958
  if (unhandled.size > 0) next = rememberSlotKeys(next, [...unhandled], failedAt(now));
8344
8959
  writeSlotDeclaration(storageKey, next);
8345
8960
  } else {
8346
- writeSlotDeclaration(storageKey, rememberSlotKeys(memory, keys, failedAt(now)));
8961
+ writeSlotDeclaration(storageKey, rememberSlotKeys(memory2, keys, failedAt(now)));
8347
8962
  warn(
8348
8963
  "slots declared but the server ignored mode=merge (old server); not caching, will retry next load"
8349
8964
  );
@@ -8793,6 +9408,6 @@ function vippsButtonAttributes(verb = "buy", opts = {}) {
8793
9408
  };
8794
9409
  }
8795
9410
 
8796
- export { ADD_ITEM_MUTATION, ADYEN_RETURN_METHOD, ADYEN_RETURN_QUERY_KEYS, AdyenOriginError, AnalyticsManager, BUYER_REF_MAX_LENGTH, CHECKOUT_ATTRIBUTION_CAPS, CHECKOUT_SPONSOR_STORAGE_KEY, CLIENT_LANDING_URL_MAX_LENGTH, CONTENT_URL_MAX_LENGTH, CREATE_CART_MUTATION, CREATE_CHECKOUT_MUTATION, CREATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, CREATE_PAYMENT_STRIPE_MUTATION, CREATE_PAYMENT_VIPPS_MUTATION, CartManager, CheckoutManager, CommerceClient, Configuration, DELETE_ITEM_MUTATION, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, GRAPHQL_INT_MAX, KUSTOM_RETURN_QUERY_KEYS, LINE_ORIGIN_CAPS, SDK_VERSION, UPDATE_CHECKOUT_MUTATION, UPDATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, UPDATE_ITEM_MUTATION, UPDATE_ITEM_WITH_ORIGIN_MUTATION, UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION, VIPPS_BUTTON_SCRIPT, VIPPS_BUTTON_TAG, Vio, VioApi, VioApiError, __decorateClass, activeCampaignEntry, addItem, adyenReturnOutcome, adyenReturnParams, autoSlotDisplayName, autoSlotId, buyerRefOf, campaignCandidates, capContentUrl, cartSlicesFrom, checkApplePayAvailability, checkoutAttributionOf, checkoutSponsorOf, componentKindOf, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, deleteItem, displayPrice, dominantCampaignOf, ensureVippsButton, entryContextOf, executeCartGraphQL, formatPrice, gatewayHas, gatewayHasBuyerRef, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCheckoutReference, getCustomerSessionId, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, isUnknownFeatureError, isUnknownTokenError, kustomReturnOutcome, landingUrl, lineOriginWire, lineOrigins, nexiReturnPaymentId, normalizeBuyerRef, normalizeOrigin, normalizeScope, normalizeSlotId, normalizeSlotKind, originAndPath, primaryImageUrl, purchaseFromPaymentSuccess, purchaseIdsOf, readNexiPending, rememberedCheckoutSponsor, resetGatewayFeatures, resolveCampaignId, resolveClientContext, resolveContent, resolveLanding, resolveSlotCampaign, sameOrigin, showApplePaySheet, sponsorCampaignEntry, sponsorIdentityFrom, storedLanding, toCampaignId, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes, withGatewayFeature };
8797
- //# sourceMappingURL=chunk-AFJ5M53F.js.map
8798
- //# sourceMappingURL=chunk-AFJ5M53F.js.map
9411
+ export { ADD_ITEM_MUTATION, ADYEN_RETURN_METHOD, ADYEN_RETURN_QUERY_KEYS, AdyenOriginError, AnalyticsManager, BUYER_REF_MAX_LENGTH, CHECKOUT_ATTRIBUTION_CAPS, CHECKOUT_SPONSOR_STORAGE_KEY, CLIENT_LANDING_URL_MAX_LENGTH, CONTENT_URL_MAX_LENGTH, CREATE_CART_MUTATION, CREATE_CHECKOUT_MUTATION, CREATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, CREATE_PAYMENT_STRIPE_MUTATION, CREATE_PAYMENT_VIPPS_MUTATION, CartManager, CheckoutManager, CommerceClient, Configuration, DELETE_ITEM_MUTATION, GET_AVAILABLE_PAYMENT_METHODS_QUERY, GET_CART_QUERY, GET_CHECKOUT_QUERY, GET_LINE_ITEMS_BY_SUPPLIER_QUERY, GET_VIPPS_STATUS_QUERY, GRAPHQL_INT_MAX, INTERNAL_KEY, INTERNAL_PARAM, KUSTOM_RETURN_QUERY_KEYS, LINE_ORIGIN_CAPS, SDK_VERSION, UPDATE_CHECKOUT_MUTATION, UPDATE_CHECKOUT_WITH_ATTRIBUTION_MUTATION, UPDATE_ITEM_MUTATION, UPDATE_ITEM_WITH_ORIGIN_MUTATION, UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION, VIPPS_BUTTON_SCRIPT, VIPPS_BUTTON_TAG, Vio, VioApi, VioApiError, __decorateClass, activeCampaignEntry, addItem, adyenReturnOutcome, adyenReturnParams, autoSlotDisplayName, autoSlotId, buyerRefOf, campaignCandidates, capContentUrl, cartSlicesFrom, checkApplePayAvailability, checkoutAttributionOf, checkoutSponsorOf, componentKindOf, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, deleteItem, displayPrice, dominantCampaignOf, ensureVippsButton, entryContextOf, executeCartGraphQL, formatPrice, gatewayHas, gatewayHasBuyerRef, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCheckoutReference, getCustomerSessionId, getGlobalCountryCode, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, isUnknownFeatureError, isUnknownTokenError, isValidPhone, kustomReturnOutcome, landingUrl, lineOriginWire, lineOrigins, nexiReturnPaymentId, normalizeBuyerRef, normalizeOrigin, normalizeScope, normalizeSlotId, normalizeSlotKind, originAndPath, primaryImageUrl, purchaseFromPaymentSuccess, purchaseIdsOf, readInternal, readNexiPending, rememberedCheckoutSponsor, resetGatewayFeatures, resolveCampaignId, resolveClientContext, resolveContent, resolveInternal, resolveLanding, resolveSlotCampaign, sameOrigin, showApplePaySheet, sponsorCampaignEntry, sponsorIdentityFrom, storageGet, storedLanding, toCampaignId, updateCheckout, updateItem, updateShippingsBySupplier, vippsButtonAttributes, withGatewayFeature, writeInternal };
9412
+ //# sourceMappingURL=chunk-IR4XYTZL.js.map
9413
+ //# sourceMappingURL=chunk-IR4XYTZL.js.map