@vio-live/web-sdk 0.9.0 → 0.10.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.
@@ -2554,10 +2554,33 @@ function renderKustomSnippet(container, htmlSnippet) {
2554
2554
  }
2555
2555
 
2556
2556
  // src/core/checkout/payments/qliro.ts
2557
+ function readVioTheme() {
2558
+ if (typeof globalThis === "undefined") return void 0;
2559
+ const doc = globalThis.document;
2560
+ const getComputed = globalThis.getComputedStyle;
2561
+ if (!doc?.documentElement || typeof getComputed !== "function") return void 0;
2562
+ let style;
2563
+ try {
2564
+ style = getComputed(doc.documentElement);
2565
+ } catch {
2566
+ return void 0;
2567
+ }
2568
+ const read = (name) => {
2569
+ const value = style?.getPropertyValue?.(name)?.trim();
2570
+ return value || void 0;
2571
+ };
2572
+ const theme = {
2573
+ accent: read("--vio-color-accent"),
2574
+ surface: read("--vio-color-surface"),
2575
+ radiusMd: read("--vio-radius-md"),
2576
+ radiusLg: read("--vio-radius-lg")
2577
+ };
2578
+ return Object.values(theme).some(Boolean) ? theme : void 0;
2579
+ }
2557
2580
  var CREATE_PAYMENT_QLIRO_MUTATION = `
2558
- mutation CreatePaymentQliro($checkoutId: String!, $countryCode: String!, $href: String!, $email: String) {
2581
+ mutation CreatePaymentQliro($checkoutId: String!, $countryCode: String!, $href: String!, $email: String, $theme: QliroThemeInput) {
2559
2582
  Payment {
2560
- CreatePaymentQliro(checkout_id: $checkoutId, country_code: $countryCode, href: $href, email: $email) {
2583
+ CreatePaymentQliro(checkout_id: $checkoutId, country_code: $countryCode, href: $href, email: $email, theme: $theme) {
2561
2584
  order_id
2562
2585
  status
2563
2586
  html_snippet
@@ -2591,6 +2614,139 @@ async function getQliroOrder(checkoutId, options) {
2591
2614
  return json?.data?.Payment?.GetQliroOrder ?? null;
2592
2615
  }
2593
2616
 
2617
+ // src/core/checkout/payments/qliro-sync.ts
2618
+ var SYNC_PAYMENT_QLIRO_MUTATION = `
2619
+ mutation SyncPaymentQliro($checkoutId: String!) {
2620
+ Payment {
2621
+ SyncPaymentQliro(checkout_id: $checkoutId) {
2622
+ order_id
2623
+ update_version
2624
+ total_price
2625
+ }
2626
+ }
2627
+ }
2628
+ `;
2629
+ async function syncPaymentQliro(checkoutId, options) {
2630
+ const json = await executeCartGraphQL(SYNC_PAYMENT_QLIRO_MUTATION, { checkoutId }, options);
2631
+ return json?.data?.Payment?.SyncPaymentQliro ?? null;
2632
+ }
2633
+ var DEFAULT_UNLOCK_TIMEOUT_MS = 15e3;
2634
+ function installQliroListeners(options) {
2635
+ const { checkoutId, queryOptions, onEvent } = options;
2636
+ const unlockTimeoutMs = options.unlockTimeoutMs ?? DEFAULT_UNLOCK_TIMEOUT_MS;
2637
+ const win = globalThis;
2638
+ let q1 = null;
2639
+ let destroyed = false;
2640
+ let pending = null;
2641
+ const emit = (event) => {
2642
+ try {
2643
+ onEvent?.(event);
2644
+ } catch {
2645
+ }
2646
+ };
2647
+ const settle = () => {
2648
+ if (!pending) return;
2649
+ clearTimeout(pending.timer);
2650
+ const { resolve } = pending;
2651
+ pending = null;
2652
+ try {
2653
+ q1?.unlock();
2654
+ } catch {
2655
+ }
2656
+ resolve();
2657
+ };
2658
+ const acknowledges = (echo, version) => {
2659
+ if (version === null) return false;
2660
+ return !echo || echo === version;
2661
+ };
2662
+ const settleIfAcknowledged = () => {
2663
+ if (!pending) return;
2664
+ if (pending.echoes.some((echo) => acknowledges(echo, pending.version))) {
2665
+ settle();
2666
+ }
2667
+ };
2668
+ const previousQ1Ready = win.q1Ready;
2669
+ win.q1Ready = (instance) => {
2670
+ try {
2671
+ previousQ1Ready?.(instance);
2672
+ } catch {
2673
+ }
2674
+ if (destroyed) return;
2675
+ q1 = instance;
2676
+ instance.onCheckoutLoaded(() => emit({ type: "loaded" }));
2677
+ instance.onOrderUpdated((order) => {
2678
+ if (!pending) return;
2679
+ const echoed = order?.merchantUpdateVersion ?? order?.MerchantUpdateVersion ?? null;
2680
+ pending.echoes.push(echoed);
2681
+ settleIfAcknowledged();
2682
+ });
2683
+ instance.onShippingMethodChanged(
2684
+ (shipping) => emit({ type: "shipping-changed", shipping })
2685
+ );
2686
+ instance.onShippingPriceChanged(
2687
+ (price, totalPrice) => emit({ type: "shipping-price-changed", price, totalPrice })
2688
+ );
2689
+ instance.onCustomerInfoChanged(
2690
+ (customer) => emit({ type: "customer-changed", customer })
2691
+ );
2692
+ instance.onPaymentMethodChanged(
2693
+ (paymentMethod) => emit({ type: "payment-method-changed", paymentMethod })
2694
+ );
2695
+ instance.onPaymentDeclined(
2696
+ (reason, message) => emit({ type: "payment-declined", reason, message })
2697
+ );
2698
+ instance.onSessionExpired(() => {
2699
+ emit({ type: "session-expired" });
2700
+ void controller.sync();
2701
+ });
2702
+ };
2703
+ const controller = {
2704
+ async sync() {
2705
+ if (destroyed) return null;
2706
+ if (pending) settle();
2707
+ try {
2708
+ q1?.lock();
2709
+ } catch {
2710
+ }
2711
+ const settled = new Promise((resolve) => {
2712
+ pending = {
2713
+ version: null,
2714
+ echoes: [],
2715
+ resolve,
2716
+ timer: setTimeout(settle, unlockTimeoutMs)
2717
+ };
2718
+ });
2719
+ let result = null;
2720
+ try {
2721
+ result = await syncPaymentQliro(checkoutId, queryOptions);
2722
+ } catch (error) {
2723
+ emit({ type: "sync-failed", error });
2724
+ settle();
2725
+ await settled;
2726
+ return null;
2727
+ }
2728
+ if (destroyed || !result?.update_version || !q1) {
2729
+ settle();
2730
+ await settled;
2731
+ return result;
2732
+ }
2733
+ if (pending) {
2734
+ pending.version = result.update_version;
2735
+ settleIfAcknowledged();
2736
+ }
2737
+ await settled;
2738
+ return result;
2739
+ },
2740
+ destroy() {
2741
+ destroyed = true;
2742
+ settle();
2743
+ if (win.q1Ready) win.q1Ready = previousQ1Ready;
2744
+ q1 = null;
2745
+ }
2746
+ };
2747
+ return controller;
2748
+ }
2749
+
2594
2750
  // src/core/checkout/payments/walley.ts
2595
2751
  var CREATE_PAYMENT_WALLEY_MUTATION = `
2596
2752
  mutation CreatePaymentWalley($checkoutId: String!, $countryCode: String!, $href: String!, $email: String) {
@@ -2866,6 +3022,8 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
2866
3022
  this.applePayPublishableKey = null;
2867
3023
  this.applePayConnectedAccount = null;
2868
3024
  this.klarnaAvailableCache = null;
3025
+ /** Live q1 listeners while a Qliro widget is mounted. */
3026
+ this.qliroController = null;
2869
3027
  this.klarnaOrderInFlight = false;
2870
3028
  /** Last backend shippings fetched (per-supplier), for UI reuse. */
2871
3029
  this.lastFetchedShippings = [];
@@ -3210,7 +3368,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
3210
3368
  const opts = await getCartGraphQLOptions(spId);
3211
3369
  let checkoutId = this.state?.checkoutId;
3212
3370
  if (!checkoutId) {
3213
- const checkoutRes = await createCheckout(cartId, opts);
3371
+ const checkoutRes = await this.createCheckout(spId);
3214
3372
  checkoutId = checkoutRes?.id;
3215
3373
  if (checkoutId && this.state) {
3216
3374
  this.state = { ...this.state, checkoutId };
@@ -3260,7 +3418,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
3260
3418
  const opts = await getCartGraphQLOptions(spId);
3261
3419
  let checkoutId = this.state?.checkoutId;
3262
3420
  if (!checkoutId) {
3263
- const checkoutRes = await createCheckout(cartId, opts);
3421
+ const checkoutRes = await this.createCheckout(spId);
3264
3422
  checkoutId = checkoutRes?.id;
3265
3423
  if (checkoutId && this.state) {
3266
3424
  this.state = { ...this.state, checkoutId };
@@ -3275,16 +3433,56 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
3275
3433
  checkoutId,
3276
3434
  countryCode: getGlobalCountryCode(),
3277
3435
  href,
3278
- email: this.state?.address?.email || void 0
3436
+ email: this.state?.address?.email || void 0,
3437
+ // Qliro cannot be restyled once rendered, so the host page's theme has
3438
+ // to travel with the order.
3439
+ theme: readVioTheme()
3279
3440
  },
3280
3441
  opts
3281
3442
  );
3282
3443
  if (!order?.html_snippet) {
3283
3444
  throw new Error("Qliro order creation failed: missing html_snippet");
3284
3445
  }
3446
+ this.qliroController?.destroy();
3447
+ this.qliroController = installQliroListeners({
3448
+ checkoutId,
3449
+ queryOptions: opts,
3450
+ onEvent: (event) => this.onQliroEvent(event)
3451
+ });
3285
3452
  renderKustomSnippet(container, order.html_snippet);
3286
3453
  return order;
3287
3454
  }
3455
+ /**
3456
+ * Everything the customer does inside the Qliro iframe, re-published as a
3457
+ * DOM event so a host page can follow a checkout it cannot see into.
3458
+ */
3459
+ onQliroEvent(event) {
3460
+ this.dispatchEvent(
3461
+ new CustomEvent("qliro-event", {
3462
+ detail: event,
3463
+ bubbles: true,
3464
+ composed: true
3465
+ })
3466
+ );
3467
+ if (event.type === "shipping-changed" || event.type === "shipping-price-changed") {
3468
+ this.emit();
3469
+ }
3470
+ }
3471
+ /**
3472
+ * Push the current cart onto the open Qliro order.
3473
+ *
3474
+ * Call it after changing the cart while the widget is open: it holds
3475
+ * `q1.lock()` across the round trip and unlocks once Qliro confirms it is
3476
+ * showing the new version. A no-op when no Qliro widget is mounted.
3477
+ */
3478
+ async syncQliroOrder() {
3479
+ return await this.qliroController?.sync() ?? null;
3480
+ }
3481
+ /** Drop the Qliro listeners and release any lock still held. */
3482
+ destroyQliroListeners() {
3483
+ this.qliroController?.destroy();
3484
+ this.qliroController = null;
3485
+ }
3288
3486
  /** Re-read the Qliro order owned by a checkout — the confirmation trip. */
3289
3487
  async getQliroOrder(checkoutId, sponsorId) {
3290
3488
  const opts = await getCartGraphQLOptions(sponsorId ?? this.state?.sponsorId);
@@ -3308,7 +3506,7 @@ var CheckoutManager = class _CheckoutManager extends EventTarget {
3308
3506
  const opts = await getCartGraphQLOptions(spId);
3309
3507
  let checkoutId = this.state?.checkoutId;
3310
3508
  if (!checkoutId) {
3311
- const checkoutRes = await createCheckout(cartId, opts);
3509
+ const checkoutRes = await this.createCheckout(spId);
3312
3510
  checkoutId = checkoutRes?.id;
3313
3511
  if (checkoutId && this.state) {
3314
3512
  this.state = { ...this.state, checkoutId };
@@ -4154,7 +4352,7 @@ function toSmallestUnit(amount, currency) {
4154
4352
  }
4155
4353
 
4156
4354
  // src/core/version.ts
4157
- var SDK_VERSION = "0.9.0";
4355
+ var SDK_VERSION = "0.9.1";
4158
4356
 
4159
4357
  // src/core/analytics/analytics-manager.ts
4160
4358
  var SESSION_TTL_MS = 30 * 60 * 1e3;
@@ -4780,5 +4978,5 @@ var _vioGlobal = globalThis;
4780
4978
  var Vio = _vioGlobal.__VIO_FACADE__ ?? (_vioGlobal.__VIO_FACADE__ = new VioFacade());
4781
4979
 
4782
4980
  export { ADD_ITEM_MUTATION, AnalyticsManager, CREATE_CART_MUTATION, CREATE_CHECKOUT_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, SDK_VERSION, UPDATE_CHECKOUT_MUTATION, UPDATE_ITEM_MUTATION, UPDATE_SHIPPINGS_BY_SUPPLIER_MUTATION, Vio, VioApi, VioApiError, __decorateClass, addItem, checkApplePayAvailability, createCart, createCheckout, createCommerceClient, createPaymentStripe, createPaymentVipps, createVioApi, deleteItem, displayPrice, executeCartGraphQL, formatPrice, getAvailablePaymentMethods, getCart, getCartGraphQLOptions, getCheckout, getCustomerSessionId, getGlobalCurrency, getLineItemsBySupplier, getVippsStatus, primaryImageUrl, showApplePaySheet, updateCheckout, updateItem, updateShippingsBySupplier };
4783
- //# sourceMappingURL=chunk-SNIF67UB.js.map
4784
- //# sourceMappingURL=chunk-SNIF67UB.js.map
4981
+ //# sourceMappingURL=chunk-PX27CQGX.js.map
4982
+ //# sourceMappingURL=chunk-PX27CQGX.js.map