@vio-live/web-sdk 0.2.0 → 0.3.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.
@@ -20,6 +20,14 @@ declare class VioProduct extends LitElement {
20
20
  /** Whether the product has selectable variants — the quick-add button then
21
21
  * opens the detail to pick one instead of adding directly. */
22
22
  hasVariants: boolean;
23
+ /** Optional raw variants/options from the host — extra signal that a
24
+ * variant must be picked before adding (selection is mandatory). */
25
+ variants: unknown[] | undefined;
26
+ options: unknown[] | undefined;
27
+ /** Image-only mode: hide the meta block (brand / name / price / retailer)
28
+ * and show just the image + the quick-add button. Click still opens the
29
+ * detail. */
30
+ hideMeta: boolean;
23
31
  /** True when this product currently sits in the cart (persistent mark). */
24
32
  private inCart;
25
33
  /** Total units of this product in the cart (shown as a count when > 1). */
@@ -111,6 +119,14 @@ declare class VioProductDetail extends LitElement {
111
119
  private adding;
112
120
  /** Apple Pay actually usable (real Stripe + registered domain) — set on load. */
113
121
  private applePayOk;
122
+ /** Payment method names enabled for the sponsor (backend-configured).
123
+ * null = not loaded yet → all buy buttons render; [] = none enabled. */
124
+ private availableMethods;
125
+ /** Race guard: only the latest fetch may write state (two quick taps on
126
+ * different cards would otherwise let the slow response win). */
127
+ private fetchSeq;
128
+ /** Memoised option maps per variant object (recomputed per product). */
129
+ private optMapCache;
114
130
  /** Pre-prepared Apple Pay handle — show() fires synchronously on tap. */
115
131
  private applePayHandle;
116
132
  private boundProductClick;
@@ -120,12 +136,44 @@ declare class VioProductDetail extends LitElement {
120
136
  show(): void;
121
137
  close(): void;
122
138
  private fetchProduct;
123
- /** Resolve the active variant from the selected option values. */
139
+ /** Which buy buttons to render — backend-configured per sponsor. */
140
+ private loadAvailablePaymentMethods;
141
+ /** Backend names arrive as e.g. "Apple Pay" — compare letters only. */
142
+ private methodEnabled;
143
+ /**
144
+ * Build an option-name → value map for a variant, from every shape the feeds
145
+ * ship: option1/2/3 columns, options/selected_options/variant arrays, plain
146
+ * object maps, and finally the title (value scan first, position fallback).
147
+ */
148
+ private getVariantOptionMap;
149
+ /** Option values a variant represents (map values ∪ title parts). */
150
+ private variantOptionValues;
151
+ /** Does a variant part represent this option value? Exact match, plus a
152
+ * whole-token match ONLY for numeric values ("30" matches "30 ml") — word
153
+ * subsets of text values are not matches ("Large" must NOT match
154
+ * "Extra Large"). */
155
+ private partMatchesValue;
156
+ /** Does a variant satisfy every currently-selected option value? */
157
+ private variantMatchesSelection;
158
+ /** Sellable quantity for a variant, across the stock field zoo. Boolean
159
+ * availability flags win; a numeric field wins next; `null` = the feed does
160
+ * not report stock for this variant (callers fall back to product stock —
161
+ * never assume "in stock" from absent data). */
162
+ private getVariantQty;
163
+ /** Variant stock with the product-level fallback applied (0 = not sellable). */
164
+ private variantSellableQty;
165
+ /** Resolve the active variant: full in-stock match → full match → best score
166
+ * (2 per mapped option match, 1 per title match, +0.5 if in stock). */
124
167
  private selectedVariant;
168
+ /** True if some in-stock variant carries this option value. */
169
+ private isValueAvailable;
125
170
  private get unitPrice();
126
171
  private get compareAt();
127
172
  private get availableQuantity();
128
173
  private stockLabel;
174
+ /** Pick an option value. If the exact combination doesn't exist, jump to an
175
+ * in-stock variant that carries the value and adopt its full option map
176
+ * (keeps the selection always resolvable to a real variant). */
129
177
  private selectOption;
130
178
  private allImages;
131
179
  private get activeImage();
@@ -139,6 +187,10 @@ declare class VioProductDetail extends LitElement {
139
187
  * loads immediately. Reuses the working Klarna Payments flow (no express SDK).
140
188
  */
141
189
  private buyWithKlarna;
190
+ /** Buy with Vipps — opens the checkout with Vipps preselected. */
191
+ private buyWithVipps;
192
+ /** Buy with Stripe — opens the checkout with Stripe preselected. */
193
+ private buyWithStripe;
142
194
  /**
143
195
  * Express buy with Apple Pay. Runs synchronously inside the click so the
144
196
  * Apple Pay sheet keeps the user gesture: add to cart → open checkout (sets
@@ -168,6 +220,9 @@ declare class VioCart extends LitElement {
168
220
  private itemCount;
169
221
  /** True when Apple Pay is usable (Safari + device + Stripe configured). */
170
222
  private applePayAvailable;
223
+ /** Payment method names enabled for the sponsor (backend-configured).
224
+ * null = not loaded yet → all buttons render; [] = none enabled. */
225
+ private availableMethods;
171
226
  /** Set after an Apple Pay express purchase — switches the drawer to the
172
227
  * confirmation screen (so the rest of the cart/checkout is not shown). */
173
228
  private confirmedOrder;
@@ -175,12 +230,19 @@ declare class VioCart extends LitElement {
175
230
  private applePayHandle;
176
231
  /** Cart total Apple Pay was last prepared for (avoids redundant prep). */
177
232
  private preparedTotal;
233
+ /** In-flight guard for loadAvailablePaymentMethods. */
234
+ private loadingPaymentMethods;
178
235
  private boundOnCartChange;
179
236
  static styles: lit.CSSResult;
180
237
  connectedCallback(): void;
181
238
  disconnectedCallback(): void;
182
239
  close(): void;
183
240
  show(): void;
241
+ /** Which payment buttons to render — backend-configured per sponsor.
242
+ * Falls back to showing everything if the query fails or none is set. */
243
+ private loadAvailablePaymentMethods;
244
+ /** Backend names arrive as e.g. "Apple Pay" — compare letters only. */
245
+ private methodEnabled;
184
246
  updated(changed: Map<string, unknown>): void;
185
247
  /** Pre-resolve the Apple Pay sheet for the current cart total. */
186
248
  private refreshApplePay;
@@ -193,6 +255,10 @@ declare class VioCart extends LitElement {
193
255
  * (betalingsmetode). The host's checkout-open handler closes this cart and
194
256
  * opens <vio-checkout> in express mode with Klarna preselected. */
195
257
  private onKlarnaExpress;
258
+ /** Vipps — opens the checkout with Vipps preselected. */
259
+ private onVipps;
260
+ /** Stripe — opens the checkout with Stripe preselected. */
261
+ private onStripe;
196
262
  private get totalAcrossSponsors();
197
263
  private get primaryCurrency();
198
264
  private onIncrement;
@@ -221,6 +287,8 @@ declare class VioCheckout extends LitElement {
221
287
  private orderConfirmed;
222
288
  private confirmedMethod;
223
289
  private paymentError;
290
+ /** Neutral (non-error) status line: "verifying payment…" / "still processing". */
291
+ private paymentNotice;
224
292
  /** Snapshot of the placed order, for the confirmation screen. */
225
293
  private confirmedOrder;
226
294
  /** Active Klarna Payments widget handle + the subtotal it was mounted for. */
@@ -234,24 +302,84 @@ declare class VioCheckout extends LitElement {
234
302
  private klarnaAuthorizing;
235
303
  /** Chosen shipping option id (express flow) — drives the Klarna order total. */
236
304
  private selectedShipping;
305
+ /** Real per-supplier shippings from the backend (empty → static fallback). */
306
+ private availableShippingsList;
307
+ /** Payment method names enabled for the sponsor (backend-configured).
308
+ * null = not loaded yet → all buttons render; [] = none enabled. */
309
+ private availableMethods;
310
+ /** Redirecting to the Stripe / Vipps hosted page. */
311
+ private stripeLoading;
312
+ private vippsLoading;
237
313
  private form;
314
+ /** In-flight guard for loadAvailablePaymentMethods. */
315
+ private loadingPaymentMethods;
316
+ /** In-flight + attempted guards for loadAvailableShippings (change events
317
+ * fire per keystroke — without these, typing an address hammers the API). */
318
+ private loadingShippings;
319
+ private shippingsAttempted;
238
320
  private boundOnCheckoutChange;
239
321
  private boundOnPaymentComplete;
240
322
  private boundOnPaymentError;
241
323
  static styles: lit.CSSResult;
242
324
  connectedCallback(): void;
325
+ /**
326
+ * Detect the redirect return from a hosted payment page (Stripe / Vipps /
327
+ * Klarna): the return URL carries vio_payment/vio_method/vio_sponsor. On
328
+ * success: clear that sponsor's cart, show the confirmation drawer, emit
329
+ * vio:payment-success (analytics/host hooks) and scrub the URL params.
330
+ */
331
+ /** Backend checkout statuses that mean the payment went through. */
332
+ private static readonly PAID_STATUSES;
333
+ /** Statuses that mean the payment definitively did NOT go through. */
334
+ private static readonly FAILED_STATUSES;
335
+ /** Waits between GetCheckout attempts — PSP webhooks (Vipps especially) can
336
+ * land seconds after the shopper is redirected back, so a single immediate
337
+ * check misreads a successful charge as unpaid. ~20s total. */
338
+ private static readonly RETURN_VERIFY_DELAYS_MS;
339
+ /** Vipps polling cadence — up to 2 minutes. Its webhook can lag well behind
340
+ * the redirect; this window was verified against a live checkout. */
341
+ private static readonly VIPPS_STATUS_MAX_ATTEMPTS;
342
+ private static readonly VIPPS_STATUS_DELAY_MS;
343
+ /**
344
+ * Vipps redirects to our return URL the same way on cancel as on success —
345
+ * the URL alone can't tell them apart, and the generic checkout status can
346
+ * lag behind Vipps' own webhook. Poll Vipps' own state directly instead:
347
+ * AUTHORIZED confirms, CREATED means still processing (keep polling),
348
+ * anything else (including an unrecognized state) is treated as failed —
349
+ * fail-closed by default rather than guessing.
350
+ */
351
+ private pollVippsStatus;
352
+ /** Shared outcome handler for both the generic (GetCheckout) and the
353
+ * Vipps-specific (GetVippsStatus) return-verification paths. */
354
+ private applyReturnOutcome;
355
+ private checkReturnPaymentStatus;
356
+ /** Remove our payment-return params from the URL without a reload. */
357
+ private cleanReturnQueryParams;
243
358
  disconnectedCallback(): void;
244
- updated(): void;
359
+ updated(changed: Map<string, unknown>): void;
245
360
  close(): void;
246
361
  show(): void;
362
+ /** Fetch the real per-supplier shippings and preselect + persist the first. */
363
+ private loadAvailableShippings;
364
+ /** Whether all mandatory Leveringsadresse fields are filled. */
365
+ private get isAddressValid();
366
+ /** Whether a valid shipping option is selected (when shippings exist). */
367
+ private get hasSelectedShipping();
368
+ /** Which payment buttons to render — backend-configured per sponsor. */
369
+ private loadAvailablePaymentMethods;
370
+ /** Backend names arrive as e.g. "Apple Pay" — compare letters only. */
371
+ private methodEnabled;
247
372
  private refreshApplePay;
248
373
  private refreshKlarna;
249
374
  /** Mount (or re-mount on amount change) the Klarna Payments widget. */
250
375
  private mountKlarnaIfNeeded;
251
376
  private unmountKlarna;
377
+ /** Shippings in effect: backend per-supplier when loaded, static otherwise. */
378
+ private get shippingList();
252
379
  /** Selected shipping option (express flow). */
253
380
  private get shippingOption();
254
- /** Pick a shipping option → re-mounts the Klarna widget with the new total. */
381
+ /** Pick a shipping option → re-mounts the Klarna widget with the new total.
382
+ * Also persists the choice on the backend cart (per supplier). */
255
383
  private onSelectShipping;
256
384
  /** Switch the Klarna widget to a different payment_method_category. */
257
385
  private onKlarnaCategory;
@@ -261,11 +389,9 @@ declare class VioCheckout extends LitElement {
261
389
  private onApplePay;
262
390
  private onPay;
263
391
  /**
264
- * Complete the order for the selected method (Vipps / Card / plain Klarna).
265
- * Apple Pay and Klarna Express finish inside their own sheet/popup, so they
266
- * never reach here. No real PSP is wired for Vipps/Card in this iteration —
267
- * the capture happens backend-side in the full flow — so this confirms the
268
- * order state-only and shows the confirmation screen.
392
+ * Complete the order for the selected method. Apple Pay and Klarna Express
393
+ * finish inside their own sheet/popup; Stripe and Vipps redirect to their
394
+ * hosted pages (via onPay). Anything else confirms state-only.
269
395
  */
270
396
  private onCompleteOrder;
271
397
  /**
@@ -279,7 +405,9 @@ declare class VioCheckout extends LitElement {
279
405
  /** True for methods that complete via a separate sheet/widget, not the CTA. */
280
406
  private isExpressMethod;
281
407
  private orderTotal;
282
- /** Shipping cost (major units) applied in express mode, else 0. */
408
+ /** Shipping cost (major units) whenever a shipping option is in effect —
409
+ * express always has one; the normal flow has one once the backend
410
+ * shippings loaded (the choice IS persisted on the cart and charged). */
283
411
  private shippingMajor;
284
412
  /** Total to charge — items + shipping (express). */
285
413
  private payTotalLabel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vio-live/web-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Vio Web SDK — in-site shoppable + native checkout, designed for editorial commerce sites",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",