@vio-live/web-sdk 0.26.0 → 0.27.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.
- package/README.md +68 -0
- package/dist/chunk-67QESEV2.js +3 -0
- package/dist/{chunk-NCP76AXW.js.map → chunk-67QESEV2.js.map} +1 -1
- package/dist/{chunk-A3LN5JEM.js → chunk-GLAKUYQA.js} +263 -28
- package/dist/chunk-GLAKUYQA.js.map +1 -0
- package/dist/{chunk-5KWICUME.js → chunk-HJRIPCWB.js} +265 -34
- package/dist/chunk-HJRIPCWB.js.map +1 -0
- package/dist/core/index.d.ts +132 -5
- package/dist/core/index.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +3 -3
- package/dist/{tokens-Bn7fK9ta.d.ts → tokens-CihuCU2l.d.ts} +56 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-5KWICUME.js.map +0 -1
- package/dist/chunk-A3LN5JEM.js.map +0 -1
- package/dist/chunk-NCP76AXW.js +0 -3
package/README.md
CHANGED
|
@@ -453,6 +453,74 @@ confirmation screen never waits. A host with its own checkout passes `buyerRef`
|
|
|
453
453
|
(`requireConsent` until `setConsent(true)`) `buyer_id` is not sent at all: a visit
|
|
454
454
|
measured with ephemeral ids carries no stable identifier of a person.
|
|
455
455
|
|
|
456
|
+
## Sponsor identity — name and logo
|
|
457
|
+
|
|
458
|
+
The elements say **who sells**: the sponsor's (brand's) display name and logo.
|
|
459
|
+
|
|
460
|
+
| Where | What it shows |
|
|
461
|
+
|---|---|
|
|
462
|
+
| `<vio-product-detail>` | a small brand header at the top of the detail — the logo (the name as its `alt`), or the name — for the sponsor the product was fetched with |
|
|
463
|
+
| `<vio-checkout>` header | «Du handler hos ‹logo \| name›» — the checkout's sponsor («Du har handlet hos …» over a provider's own receipt) |
|
|
464
|
+
| `<vio-checkout>` confirmation | «Takk for bestillingen! Du har handlet hos Careless.» next to the order number, with the logo above when there is one |
|
|
465
|
+
| `<vio-cart>` / carousel | the sponsor label over a sponsor's lines, the `retailer` line of a carousel's cards (by name) |
|
|
466
|
+
|
|
467
|
+
No logo → the name. A logo that fails to load → the name. Nothing known → nothing
|
|
468
|
+
(the product detail shows no header; the confirmation keeps «Takk for bestillingen!»
|
|
469
|
+
without the sentence). The marks are styled with the `--vio-*` tokens and exposed as
|
|
470
|
+
`part="sponsor"` (`vio-checkout::part(sponsor)`).
|
|
471
|
+
|
|
472
|
+
**One rule.** `Vio.sponsorIdentity(sponsorId, { checkoutId? })` answers
|
|
473
|
+
`{ id, name, logoUrl, avatarUrl } | null` — and every element uses it:
|
|
474
|
+
|
|
475
|
+
1. the live bootstrap's sponsor blocks: the config's `primarySponsor` and
|
|
476
|
+
`secondarySponsors`, then every `campaigns[]` entry's primary and secondaries,
|
|
477
|
+
first match (a surface with no active campaign still names its channel brands);
|
|
478
|
+
2. when the bootstrap does not know the id (not loaded yet, a redirect return): what
|
|
479
|
+
this tab remembered of the checkout — when the SDK creates a checkout it keeps
|
|
480
|
+
`checkoutId → { sponsorId, name, logoUrl }` in `sessionStorage`
|
|
481
|
+
(`vio.checkoutSponsor.v1`, the last 20 checkouts; it works, for that page,
|
|
482
|
+
without storage) — then the latest remembered checkout of that sponsor;
|
|
483
|
+
3. the cart's `sponsorName`;
|
|
484
|
+
4. `null`.
|
|
485
|
+
|
|
486
|
+
With only `{ checkoutId }` the sponsor is the one remembered for that checkout. URLs
|
|
487
|
+
are kept as given; an empty `logoUrl` is `null`. `sponsorIdentityFrom(bootstrap,
|
|
488
|
+
sponsorId)` is the pure step 1, exported from `/core`.
|
|
489
|
+
|
|
490
|
+
**From the checkout, never from the page.** In the checkout and on its confirmation
|
|
491
|
+
the sponsor is the **checkout's** — the cart's sponsor, the one the order is with —
|
|
492
|
+
from the checkout state or the return URL (`vio_sponsor`, `checkout_id`), never
|
|
493
|
+
`Vio.attribution()`: an article of one brand may sell another brand's product. Back
|
|
494
|
+
from Vipps the confirmation names the brand from the memory at once, or from the
|
|
495
|
+
bootstrap as soon as it lands (the thanks is shown first, the name follows).
|
|
496
|
+
|
|
497
|
+
**For hosts.** `vio:checkout-open` and `vio:payment-success` carry
|
|
498
|
+
`sponsor: { id, name, logoUrl }` in their detail when it can be named (the key is
|
|
499
|
+
absent otherwise), and `Vio.checkout.getOrderReference(checkoutId, sponsorId?)`
|
|
500
|
+
answers `{ orderNumber, buyerRef, sponsor? }` by the same rule. The SDK cleans its
|
|
501
|
+
return parameters from the URL once it has used them, so its own confirmation does
|
|
502
|
+
not come back on a reload — a host that wants a confirmation page that survives one
|
|
503
|
+
keeps the two ids in its own URL and asks again:
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
// On the purchase: keep what the confirmation needs in YOUR url.
|
|
507
|
+
document.addEventListener('vio:payment-success', (e) => {
|
|
508
|
+
const d = (e as CustomEvent).detail
|
|
509
|
+
const checkoutId = String(d.checkoutId ?? d.orderId ?? '')
|
|
510
|
+
history.replaceState(null, '', `/takk?checkout=${checkoutId}&sponsor=${d.sponsorId ?? ''}`)
|
|
511
|
+
render(d.sponsor)
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
// On /takk (also after a reload, or in another browser):
|
|
515
|
+
const params = new URLSearchParams(location.search)
|
|
516
|
+
const ref = await Vio.checkout.getOrderReference(params.get('checkout') ?? '', Number(params.get('sponsor')) || undefined)
|
|
517
|
+
render(ref.sponsor, ref.orderNumber) // waits for Vio.init (up to 2 s) and the bootstrap; never throws
|
|
518
|
+
|
|
519
|
+
function render(sponsor?: { name: string; logoUrl: string | null }, orderNumber?: number | null) {
|
|
520
|
+
// «Takk for bestillingen! Du har handlet hos {sponsor.name}.» — the logo when sponsor.logoUrl
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
456
524
|
## Theming
|
|
457
525
|
|
|
458
526
|
Every component reads its colors and fonts from `--vio-*` CSS custom properties
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-67QESEV2.js"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Vio, __decorateClass, primaryImageUrl, displayPrice, toCampaignId, getGlobalCurrency, ensureVippsButton, formatPrice, buyerRefOf, nexiReturnPaymentId, readNexiPending, kustomReturnOutcome, KUSTOM_RETURN_QUERY_KEYS, ADYEN_RETURN_METHOD, adyenReturnParams, ADYEN_RETURN_QUERY_KEYS, adyenReturnOutcome, gatewayHasBuyerRef, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, normalizeScope, campaignCandidates } from './chunk-
|
|
2
|
-
import { LitElement, css, html } from 'lit';
|
|
1
|
+
import { Vio, __decorateClass, primaryImageUrl, displayPrice, toCampaignId, getGlobalCurrency, ensureVippsButton, formatPrice, buyerRefOf, nexiReturnPaymentId, readNexiPending, kustomReturnOutcome, KUSTOM_RETURN_QUERY_KEYS, ADYEN_RETURN_METHOD, adyenReturnParams, ADYEN_RETURN_QUERY_KEYS, adyenReturnOutcome, gatewayHasBuyerRef, rememberedCheckoutSponsor, checkoutSponsorOf, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, sponsorIdentityFrom, Configuration, normalizeScope, campaignCandidates } from './chunk-HJRIPCWB.js';
|
|
2
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
3
3
|
import { property, state, query } from 'lit/decorators.js';
|
|
4
4
|
|
|
5
5
|
// src/ui/tokens.ts
|
|
@@ -705,6 +705,54 @@ __decorateClass([
|
|
|
705
705
|
__decorateClass([
|
|
706
706
|
state()
|
|
707
707
|
], VioProduct.prototype, "justAdded", 2);
|
|
708
|
+
function resolveSponsorIdentity(sponsorId, checkoutId) {
|
|
709
|
+
try {
|
|
710
|
+
if (typeof Vio.sponsorIdentity === "function") return Vio.sponsorIdentity(sponsorId, { checkoutId });
|
|
711
|
+
return sponsorIdentityFrom(Vio.bootstrapCache, sponsorId);
|
|
712
|
+
} catch {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
function sponsorDetail(sponsorId, checkoutId) {
|
|
717
|
+
const sponsor = checkoutSponsorOf(resolveSponsorIdentity(sponsorId, checkoutId));
|
|
718
|
+
return sponsor ? { sponsor } : {};
|
|
719
|
+
}
|
|
720
|
+
var failedLogos = /* @__PURE__ */ new Set();
|
|
721
|
+
function usableLogo(identity) {
|
|
722
|
+
const url = identity?.logoUrl;
|
|
723
|
+
return url && !failedLogos.has(url) ? url : null;
|
|
724
|
+
}
|
|
725
|
+
function renderSponsorMark(host, identity, classes) {
|
|
726
|
+
if (!identity) return nothing;
|
|
727
|
+
const logo = usableLogo(identity);
|
|
728
|
+
if (logo) {
|
|
729
|
+
return html`<img
|
|
730
|
+
class=${classes.logo}
|
|
731
|
+
src=${logo}
|
|
732
|
+
alt=${identity.name}
|
|
733
|
+
decoding="async"
|
|
734
|
+
@error=${() => {
|
|
735
|
+
failedLogos.add(logo);
|
|
736
|
+
host.requestUpdate();
|
|
737
|
+
}}
|
|
738
|
+
/>`;
|
|
739
|
+
}
|
|
740
|
+
return identity.name ? html`<span class=${classes.name}>${identity.name}</span>` : nothing;
|
|
741
|
+
}
|
|
742
|
+
var INIT_WAIT_MS = 1e4;
|
|
743
|
+
async function whenBootstrapped() {
|
|
744
|
+
try {
|
|
745
|
+
if (Vio.bootstrapCache) return true;
|
|
746
|
+
if (!Configuration.isInitialized) await Configuration.whenReady(INIT_WAIT_MS);
|
|
747
|
+
if (!Configuration.isInitialized || typeof Vio.bootstrap !== "function") return false;
|
|
748
|
+
await Vio.bootstrap();
|
|
749
|
+
return !!Vio.bootstrapCache;
|
|
750
|
+
} catch {
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// src/ui/components/vio-product-carousel.ts
|
|
708
756
|
var VioProductCarousel = class extends LitElement {
|
|
709
757
|
constructor() {
|
|
710
758
|
super(...arguments);
|
|
@@ -1077,7 +1125,7 @@ var VioProductCarousel = class extends LitElement {
|
|
|
1077
1125
|
if (this.fetched && this.fetched.length > 0) {
|
|
1078
1126
|
return html`${this.fetched.map(({ product: p, sponsorId }) => {
|
|
1079
1127
|
const img = primaryImageUrl(p) ?? "";
|
|
1080
|
-
const retailer =
|
|
1128
|
+
const retailer = resolveSponsorIdentity(sponsorId)?.name || p.brand || "";
|
|
1081
1129
|
return html`
|
|
1082
1130
|
<vio-product
|
|
1083
1131
|
product-id=${String(p.id)}
|
|
@@ -1195,12 +1243,6 @@ __decorateClass([
|
|
|
1195
1243
|
__decorateClass([
|
|
1196
1244
|
state()
|
|
1197
1245
|
], VioProductCarousel.prototype, "fetchError", 2);
|
|
1198
|
-
function sponsorNameFromBootstrap(sponsorId) {
|
|
1199
|
-
const boot = Vio.bootstrapCache;
|
|
1200
|
-
if (!boot) return void 0;
|
|
1201
|
-
if (boot.primarySponsor?.id === sponsorId) return boot.primarySponsor.name;
|
|
1202
|
-
return boot.secondarySponsors?.find((s) => s.id === sponsorId)?.name;
|
|
1203
|
-
}
|
|
1204
1246
|
|
|
1205
1247
|
// src/core/checkout/method-taxonomy.ts
|
|
1206
1248
|
function normalizeMethodName(name) {
|
|
@@ -1701,6 +1743,29 @@ var VioProductDetail = class extends LitElement {
|
|
|
1701
1743
|
}
|
|
1702
1744
|
.gallery-thumb.active { border-color: var(--vio-color-text, #0a0a0a); }
|
|
1703
1745
|
|
|
1746
|
+
/* Who sells it: the sponsor's logo, or its name — small, above everything. */
|
|
1747
|
+
.sponsor-header {
|
|
1748
|
+
grid-column: 1 / -1;
|
|
1749
|
+
display: flex;
|
|
1750
|
+
align-items: center;
|
|
1751
|
+
min-height: 24px;
|
|
1752
|
+
}
|
|
1753
|
+
.sponsor-logo {
|
|
1754
|
+
display: block;
|
|
1755
|
+
width: auto;
|
|
1756
|
+
height: auto;
|
|
1757
|
+
max-height: 28px;
|
|
1758
|
+
max-width: 160px;
|
|
1759
|
+
object-fit: contain;
|
|
1760
|
+
}
|
|
1761
|
+
.sponsor-name {
|
|
1762
|
+
font-size: 12px;
|
|
1763
|
+
text-transform: uppercase;
|
|
1764
|
+
letter-spacing: var(--vio-tracking-label, 0.1em);
|
|
1765
|
+
color: var(--vio-color-text-secondary, #666);
|
|
1766
|
+
font-weight: 600;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1704
1769
|
/* Info column */
|
|
1705
1770
|
.info { display: flex; flex-direction: column; gap: 24px; }
|
|
1706
1771
|
.brand {
|
|
@@ -2384,9 +2449,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2384
2449
|
addCurrentToCart() {
|
|
2385
2450
|
if (!this.product) return void 0;
|
|
2386
2451
|
const variant = this.selectedVariant();
|
|
2387
|
-
const
|
|
2388
|
-
const secondaries = Vio.bootstrapCache?.secondarySponsors ?? [];
|
|
2389
|
-
const sponsorName = sponsor?.id === this.sponsorId ? sponsor.name : secondaries.find((s) => s.id === this.sponsorId)?.name;
|
|
2452
|
+
const sponsorName = resolveSponsorIdentity(this.sponsorId)?.name || void 0;
|
|
2390
2453
|
const { campaignId, slot, contentId, componentTemplateId, contentUrl, contentTitle } = this.attribution();
|
|
2391
2454
|
Vio.cart.addProduct({
|
|
2392
2455
|
product: this.product,
|
|
@@ -2437,7 +2500,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2437
2500
|
new CustomEvent("vio:checkout-open", {
|
|
2438
2501
|
bubbles: true,
|
|
2439
2502
|
composed: true,
|
|
2440
|
-
detail: { sponsorId: this.sponsorId, paymentMethod: "klarna", express: true, ...this.attribution() }
|
|
2503
|
+
detail: { sponsorId: this.sponsorId, paymentMethod: "klarna", express: true, ...this.attribution(), ...sponsorDetail(this.sponsorId) }
|
|
2441
2504
|
})
|
|
2442
2505
|
);
|
|
2443
2506
|
} finally {
|
|
@@ -2467,7 +2530,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2467
2530
|
new CustomEvent("vio:checkout-open", {
|
|
2468
2531
|
bubbles: true,
|
|
2469
2532
|
composed: true,
|
|
2470
|
-
detail: { sponsorId: this.sponsorId, express: false, ...this.attribution() }
|
|
2533
|
+
detail: { sponsorId: this.sponsorId, express: false, ...this.attribution(), ...sponsorDetail(this.sponsorId) }
|
|
2471
2534
|
})
|
|
2472
2535
|
);
|
|
2473
2536
|
}
|
|
@@ -2503,7 +2566,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2503
2566
|
new CustomEvent("vio:checkout-open", {
|
|
2504
2567
|
bubbles: true,
|
|
2505
2568
|
composed: true,
|
|
2506
|
-
detail: { sponsorId: this.sponsorId, paymentMethod: "vipps", express: false, ...this.attribution() }
|
|
2569
|
+
detail: { sponsorId: this.sponsorId, paymentMethod: "vipps", express: false, ...this.attribution(), ...sponsorDetail(this.sponsorId) }
|
|
2507
2570
|
})
|
|
2508
2571
|
);
|
|
2509
2572
|
}
|
|
@@ -2516,7 +2579,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2516
2579
|
new CustomEvent("vio:checkout-open", {
|
|
2517
2580
|
bubbles: true,
|
|
2518
2581
|
composed: true,
|
|
2519
|
-
detail: { sponsorId: this.sponsorId, paymentMethod: "stripe", express: false, ...this.attribution() }
|
|
2582
|
+
detail: { sponsorId: this.sponsorId, paymentMethod: "stripe", express: false, ...this.attribution(), ...sponsorDetail(this.sponsorId) }
|
|
2520
2583
|
})
|
|
2521
2584
|
);
|
|
2522
2585
|
}
|
|
@@ -2556,6 +2619,21 @@ var VioProductDetail = class extends LitElement {
|
|
|
2556
2619
|
this.sellerName = name;
|
|
2557
2620
|
this.sellerSettled = true;
|
|
2558
2621
|
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Who sells the product: the brand of the sponsor it was fetched with —
|
|
2624
|
+
* its logo, with the name as `alt`. Without a logo that loads, the topbar
|
|
2625
|
+
* already names the seller (its Company name, else the brand), so the name
|
|
2626
|
+
* goes here only when the topbar names nobody once the seller is known —
|
|
2627
|
+
* never the same name twice. Nothing at all when no identity is known.
|
|
2628
|
+
*/
|
|
2629
|
+
renderSponsorHeader() {
|
|
2630
|
+
const identity = resolveSponsorIdentity(this.sponsorId);
|
|
2631
|
+
if (!identity) return nothing;
|
|
2632
|
+
if (!usableLogo(identity) && (!this.sellerSettled || this.headerName())) return nothing;
|
|
2633
|
+
const mark = renderSponsorMark(this, identity, { logo: "sponsor-logo", name: "sponsor-name" });
|
|
2634
|
+
if (mark === nothing) return nothing;
|
|
2635
|
+
return html`<div class="sponsor-header" part="sponsor">${mark}</div>`;
|
|
2636
|
+
}
|
|
2559
2637
|
render() {
|
|
2560
2638
|
return html`
|
|
2561
2639
|
<div class="backdrop" @click=${this.close}></div>
|
|
@@ -2595,6 +2673,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2595
2673
|
const activeImage = this.activeImage;
|
|
2596
2674
|
return html`
|
|
2597
2675
|
<div class="body">
|
|
2676
|
+
${this.renderSponsorHeader()}
|
|
2598
2677
|
<div class="gallery">
|
|
2599
2678
|
<div class="gallery-main">
|
|
2600
2679
|
${activeImage?.url ? html`<img src=${activeImage.url} alt=${p.title} />` : ""}
|
|
@@ -2780,8 +2859,8 @@ var VioProductDetail = class extends LitElement {
|
|
|
2780
2859
|
})}`;
|
|
2781
2860
|
}
|
|
2782
2861
|
/** Best-effort HTML strip for description. */
|
|
2783
|
-
stripHtml(
|
|
2784
|
-
return
|
|
2862
|
+
stripHtml(html7) {
|
|
2863
|
+
return html7.replace(/<br\s*\/?>/gi, "\n").replace(/<\/p>/gi, "\n\n").replace(/<[^>]+>/g, "").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").trim();
|
|
2785
2864
|
}
|
|
2786
2865
|
};
|
|
2787
2866
|
__decorateClass([
|
|
@@ -3356,6 +3435,8 @@ var VioCart = class extends LitElement {
|
|
|
3356
3435
|
const handle = this.applePayHandle;
|
|
3357
3436
|
if (!handle || !handle.available || this.itemCount === 0) return;
|
|
3358
3437
|
const snapshot = this.buildConfirmation();
|
|
3438
|
+
const sponsorIds = [...this.carts.keys()];
|
|
3439
|
+
const sponsor = sponsorIds.length === 1 ? sponsorDetail(sponsorIds[0]) : {};
|
|
3359
3440
|
void handle.show().then((result) => {
|
|
3360
3441
|
if (!result) return;
|
|
3361
3442
|
this.confirmedOrder = snapshot;
|
|
@@ -3367,7 +3448,7 @@ var VioCart = class extends LitElement {
|
|
|
3367
3448
|
new CustomEvent("vio:payment-success", {
|
|
3368
3449
|
bubbles: true,
|
|
3369
3450
|
composed: true,
|
|
3370
|
-
detail: { method: "apple-pay", result, ...buyerRef ? { buyerRef } : {} }
|
|
3451
|
+
detail: { method: "apple-pay", result, ...buyerRef ? { buyerRef } : {}, ...sponsor }
|
|
3371
3452
|
})
|
|
3372
3453
|
);
|
|
3373
3454
|
});
|
|
@@ -3403,7 +3484,7 @@ var VioCart = class extends LitElement {
|
|
|
3403
3484
|
new CustomEvent("vio:checkout-open", {
|
|
3404
3485
|
bubbles: true,
|
|
3405
3486
|
composed: true,
|
|
3406
|
-
detail: { sponsorId: firstSponsorId, paymentMethod: "klarna", express: true }
|
|
3487
|
+
detail: { sponsorId: firstSponsorId, paymentMethod: "klarna", express: true, ...sponsorDetail(firstSponsorId) }
|
|
3407
3488
|
})
|
|
3408
3489
|
);
|
|
3409
3490
|
}
|
|
@@ -3424,7 +3505,7 @@ var VioCart = class extends LitElement {
|
|
|
3424
3505
|
new CustomEvent("vio:checkout-open", {
|
|
3425
3506
|
bubbles: true,
|
|
3426
3507
|
composed: true,
|
|
3427
|
-
detail: { sponsorId: firstSponsorId, express: false }
|
|
3508
|
+
detail: { sponsorId: firstSponsorId, express: false, ...sponsorDetail(firstSponsorId) }
|
|
3428
3509
|
})
|
|
3429
3510
|
);
|
|
3430
3511
|
}
|
|
@@ -3461,7 +3542,7 @@ var VioCart = class extends LitElement {
|
|
|
3461
3542
|
new CustomEvent("vio:checkout-open", {
|
|
3462
3543
|
bubbles: true,
|
|
3463
3544
|
composed: true,
|
|
3464
|
-
detail: { sponsorId, paymentMethod: "vipps", express: false }
|
|
3545
|
+
detail: { sponsorId, paymentMethod: "vipps", express: false, ...sponsorDetail(sponsorId) }
|
|
3465
3546
|
})
|
|
3466
3547
|
);
|
|
3467
3548
|
}
|
|
@@ -3474,10 +3555,14 @@ var VioCart = class extends LitElement {
|
|
|
3474
3555
|
new CustomEvent("vio:checkout-open", {
|
|
3475
3556
|
bubbles: true,
|
|
3476
3557
|
composed: true,
|
|
3477
|
-
detail: { sponsorId: firstSponsorId, paymentMethod: "stripe", express: false }
|
|
3558
|
+
detail: { sponsorId: firstSponsorId, paymentMethod: "stripe", express: false, ...sponsorDetail(firstSponsorId) }
|
|
3478
3559
|
})
|
|
3479
3560
|
);
|
|
3480
3561
|
}
|
|
3562
|
+
/** The name over a sponsor's lines: the brand's display name by the one rule, else what the cart kept. */
|
|
3563
|
+
sponsorLabel(cart) {
|
|
3564
|
+
return resolveSponsorIdentity(cart.sponsorId)?.name || cart.sponsorName || "";
|
|
3565
|
+
}
|
|
3481
3566
|
get totalAcrossSponsors() {
|
|
3482
3567
|
let sum = 0;
|
|
3483
3568
|
for (const cart of this.carts.values()) {
|
|
@@ -3518,7 +3603,7 @@ var VioCart = class extends LitElement {
|
|
|
3518
3603
|
${sponsorCarts.map(
|
|
3519
3604
|
(cart) => html`
|
|
3520
3605
|
<div class="sponsor-group">
|
|
3521
|
-
${cart
|
|
3606
|
+
${this.sponsorLabel(cart) ? html`<div class="sponsor-label">${this.sponsorLabel(cart)}</div>` : ""}
|
|
3522
3607
|
${cart.items.map(
|
|
3523
3608
|
(item) => html`
|
|
3524
3609
|
<div class="item">
|
|
@@ -3755,6 +3840,9 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3755
3840
|
this.verifyingReturn = null;
|
|
3756
3841
|
/** The checkout whose confirmation is on screen — see fillOrderNumber. */
|
|
3757
3842
|
this.confirmedCheckoutId = null;
|
|
3843
|
+
this.orderSponsor = null;
|
|
3844
|
+
/** The bootstrap that names the checkout's sponsor was asked for (once per checkout) — see watchSponsorBootstrap. */
|
|
3845
|
+
this.sponsorBootstrapAsked = false;
|
|
3758
3846
|
this.confirmedOrder = null;
|
|
3759
3847
|
/** Active Klarna Payments widget handle + the subtotal it was mounted for. */
|
|
3760
3848
|
this.klarnaHandle = null;
|
|
@@ -3905,6 +3993,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3905
3993
|
this.paymentNotice = null;
|
|
3906
3994
|
this.verifyingReturn = null;
|
|
3907
3995
|
this.confirmedCheckoutId = null;
|
|
3996
|
+
this.orderSponsor = null;
|
|
3997
|
+
this.sponsorBootstrapAsked = false;
|
|
3908
3998
|
this.express = false;
|
|
3909
3999
|
this.availableMethods = null;
|
|
3910
4000
|
this.paymentMethodsResolved = false;
|
|
@@ -4090,6 +4180,33 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4090
4180
|
font-weight: 400;
|
|
4091
4181
|
margin: 0;
|
|
4092
4182
|
}
|
|
4183
|
+
.topbar-title {
|
|
4184
|
+
display: flex;
|
|
4185
|
+
flex-direction: column;
|
|
4186
|
+
gap: 4px;
|
|
4187
|
+
min-width: 0;
|
|
4188
|
+
}
|
|
4189
|
+
/* Who the shopper buys from — the checkout's sponsor, compact under the heading. */
|
|
4190
|
+
.topbar-sponsor {
|
|
4191
|
+
margin: 0;
|
|
4192
|
+
display: flex;
|
|
4193
|
+
align-items: center;
|
|
4194
|
+
gap: 6px;
|
|
4195
|
+
font-size: 12px;
|
|
4196
|
+
line-height: 1.3;
|
|
4197
|
+
color: var(--vio-color-text-secondary, #666);
|
|
4198
|
+
}
|
|
4199
|
+
.topbar-sponsor-logo {
|
|
4200
|
+
display: block;
|
|
4201
|
+
width: auto;
|
|
4202
|
+
height: 18px;
|
|
4203
|
+
max-width: 120px;
|
|
4204
|
+
object-fit: contain;
|
|
4205
|
+
}
|
|
4206
|
+
.topbar-sponsor-name {
|
|
4207
|
+
color: var(--vio-color-text, #0a0a0a);
|
|
4208
|
+
font-weight: 600;
|
|
4209
|
+
}
|
|
4093
4210
|
.close {
|
|
4094
4211
|
background: none;
|
|
4095
4212
|
border: none;
|
|
@@ -4419,6 +4536,23 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4419
4536
|
font-weight: 400;
|
|
4420
4537
|
margin: 0;
|
|
4421
4538
|
}
|
|
4539
|
+
/* The brand the order is with: its logo over the thanks, its name in it. */
|
|
4540
|
+
.confirm-brand { display: flex; align-items: center; }
|
|
4541
|
+
.confirm-brand-logo {
|
|
4542
|
+
display: block;
|
|
4543
|
+
width: auto;
|
|
4544
|
+
height: auto;
|
|
4545
|
+
max-height: 32px;
|
|
4546
|
+
max-width: 160px;
|
|
4547
|
+
object-fit: contain;
|
|
4548
|
+
}
|
|
4549
|
+
.confirm-sponsor {
|
|
4550
|
+
font-size: 14px;
|
|
4551
|
+
line-height: 1.4;
|
|
4552
|
+
color: var(--vio-color-text, #0a0a0a);
|
|
4553
|
+
margin: 4px 0 0;
|
|
4554
|
+
}
|
|
4555
|
+
.confirm-sponsor strong { font-weight: 600; }
|
|
4422
4556
|
.confirm-text {
|
|
4423
4557
|
font-size: 14px;
|
|
4424
4558
|
color: var(--vio-color-text-secondary, #666);
|
|
@@ -4619,6 +4753,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4619
4753
|
* Vipps-specific (GetVippsStatus) return-verification paths. */
|
|
4620
4754
|
applyReturnOutcome(outcome, sawStatus, vioMethod, sponsorId, checkoutId) {
|
|
4621
4755
|
if (outcome === "paid") {
|
|
4756
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4622
4757
|
if (sponsorId > 0) Vio.cart.clearSponsorCart(sponsorId);
|
|
4623
4758
|
this.confirmedOrder = {
|
|
4624
4759
|
items: [],
|
|
@@ -4679,6 +4814,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4679
4814
|
if (kustomReturn?.kind === "confirmation") {
|
|
4680
4815
|
const kustomOrderId = kustomReturn.orderId;
|
|
4681
4816
|
this.returningFrom = "kustom";
|
|
4817
|
+
this.setOrderSponsor(sponsorId, kustomReturn.checkoutId);
|
|
4682
4818
|
if (!this.checkoutState) {
|
|
4683
4819
|
const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
|
|
4684
4820
|
if (spIdToUse) {
|
|
@@ -4722,6 +4858,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4722
4858
|
if (!vioPayment && !checkoutId) return;
|
|
4723
4859
|
if (urlParams.get("payment_processor") === "QLIRO" && checkoutId) {
|
|
4724
4860
|
this.returningFrom = "qliro";
|
|
4861
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4725
4862
|
if (!this.checkoutState) {
|
|
4726
4863
|
const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
|
|
4727
4864
|
if (spIdToUse) {
|
|
@@ -4776,6 +4913,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4776
4913
|
}
|
|
4777
4914
|
if (urlParams.get("payment_processor") === "WALLEY" && checkoutId) {
|
|
4778
4915
|
this.returningFrom = "walley";
|
|
4916
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4779
4917
|
if (!this.checkoutState) {
|
|
4780
4918
|
const spIdToUse = sponsorId || [...Vio.cart.getAllCarts().keys()][0] || 0;
|
|
4781
4919
|
if (spIdToUse) {
|
|
@@ -4832,6 +4970,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4832
4970
|
this.cleanReturnQueryParams(ADYEN_RETURN_QUERY_KEYS);
|
|
4833
4971
|
if (!adyenReturn) return;
|
|
4834
4972
|
this.returningFrom = "adyen";
|
|
4973
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4835
4974
|
this.adyenSettled = true;
|
|
4836
4975
|
this.autoSelectAttempted = true;
|
|
4837
4976
|
if (!this.checkoutState) {
|
|
@@ -4888,6 +5027,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4888
5027
|
}
|
|
4889
5028
|
}
|
|
4890
5029
|
}
|
|
5030
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4891
5031
|
this.open = true;
|
|
4892
5032
|
this.verifyingReturn = "Bekrefter betalingen med Vipps\u2026";
|
|
4893
5033
|
const { outcome, sawStatus } = await this.pollVippsStatus(checkoutId, sponsorId);
|
|
@@ -4898,6 +5038,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4898
5038
|
let outcome = "pending";
|
|
4899
5039
|
let sawStatus = false;
|
|
4900
5040
|
if (checkoutId) {
|
|
5041
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
4901
5042
|
this.open = true;
|
|
4902
5043
|
this.verifyingReturn = "Bekrefter betalingen\u2026";
|
|
4903
5044
|
for (const delayMs of _VioCheckout.RETURN_VERIFY_DELAYS_MS) {
|
|
@@ -4996,6 +5137,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4996
5137
|
this.unmountStripe();
|
|
4997
5138
|
this.paymentError = null;
|
|
4998
5139
|
}
|
|
5140
|
+
this.watchSponsorBootstrap();
|
|
4999
5141
|
if (!this.isConnected) return;
|
|
5000
5142
|
void this.mountKlarnaIfNeeded();
|
|
5001
5143
|
void this.mountKustomIfNeeded();
|
|
@@ -5472,6 +5614,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5472
5614
|
const email = String(this.form.email ?? "").trim();
|
|
5473
5615
|
const checkoutId = returnCheckoutId || this.checkoutState?.checkoutId;
|
|
5474
5616
|
const providerOrderId = r.order?.orderId != null ? String(r.order.orderId) : "";
|
|
5617
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
5475
5618
|
this.confirmedOrder = {
|
|
5476
5619
|
items: [...this.items],
|
|
5477
5620
|
currency: this.checkoutState?.currency ?? "",
|
|
@@ -5518,13 +5661,17 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5518
5661
|
*/
|
|
5519
5662
|
async emitPaymentSuccess(detail, checkoutId, sponsorId, afterwards) {
|
|
5520
5663
|
let done = false;
|
|
5664
|
+
const sponsorAtStart = this.sponsorOfOrder(sponsorId, checkoutId);
|
|
5521
5665
|
const finish = (buyerRef) => {
|
|
5522
5666
|
if (done) return;
|
|
5523
5667
|
done = true;
|
|
5668
|
+
const named = this.sponsorOfOrder(sponsorId, checkoutId);
|
|
5669
|
+
const sponsor = named.sponsor ? named : sponsorAtStart;
|
|
5670
|
+
const withSponsor = sponsor.sponsor ? { ...detail, ...sponsor } : detail;
|
|
5524
5671
|
const event = new CustomEvent("vio:payment-success", {
|
|
5525
5672
|
bubbles: true,
|
|
5526
5673
|
composed: true,
|
|
5527
|
-
detail: buyerRef ? { ...
|
|
5674
|
+
detail: buyerRef ? { ...withSponsor, buyerRef } : withSponsor
|
|
5528
5675
|
});
|
|
5529
5676
|
this.dispatchEvent(event);
|
|
5530
5677
|
if (!this.isConnected && typeof window !== "undefined") {
|
|
@@ -5712,7 +5859,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5712
5859
|
>
|
|
5713
5860
|
<div class="handle" @click=${this.close} aria-hidden="true"></div>
|
|
5714
5861
|
<div class="topbar">
|
|
5715
|
-
<
|
|
5862
|
+
<div class="topbar-title">
|
|
5863
|
+
<h2 class="heading">${this.orderConfirmed ? "Takk!" : this.heading}</h2>
|
|
5864
|
+
${this.renderTopbarSponsor()}
|
|
5865
|
+
</div>
|
|
5716
5866
|
<button class="close" @click=${this.close} aria-label="Lukk">×</button>
|
|
5717
5867
|
</div>
|
|
5718
5868
|
|
|
@@ -5722,6 +5872,82 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5722
5872
|
</div>
|
|
5723
5873
|
`;
|
|
5724
5874
|
}
|
|
5875
|
+
/**
|
|
5876
|
+
* Remember whose order this is and how it is named right now, before the
|
|
5877
|
+
* cart that names it is cleared. Whose: the sponsor this tab remembered for
|
|
5878
|
+
* the checkout when it was created (exact for that checkout id), else the
|
|
5879
|
+
* one given (the return URL's `vio_sponsor`, the state it was paid in),
|
|
5880
|
+
* else the open state's — a return without `vio_sponsor` (Qliro, Walley)
|
|
5881
|
+
* re-opens the state with whichever cart comes first, which is a guess.
|
|
5882
|
+
*/
|
|
5883
|
+
setOrderSponsor(sponsorId, checkoutId) {
|
|
5884
|
+
try {
|
|
5885
|
+
const checkout = checkoutId || void 0;
|
|
5886
|
+
const id = rememberedCheckoutSponsor(checkout)?.sponsorId ?? (sponsorId && sponsorId > 0 ? sponsorId : void 0) ?? this.checkoutState?.sponsorId;
|
|
5887
|
+
if (!id) return;
|
|
5888
|
+
const named = checkoutSponsorOf(resolveSponsorIdentity(id, checkout));
|
|
5889
|
+
const previous = this.orderSponsor;
|
|
5890
|
+
const snapshot = named ?? (previous && previous.sponsorId === id ? previous.snapshot : void 0);
|
|
5891
|
+
this.orderSponsor = { sponsorId: id, ...checkout ? { checkoutId: checkout } : {}, ...snapshot ? { snapshot } : {} };
|
|
5892
|
+
} catch {
|
|
5893
|
+
}
|
|
5894
|
+
}
|
|
5895
|
+
/**
|
|
5896
|
+
* Who this checkout is with, as a shopper sees it: the order being
|
|
5897
|
+
* confirmed / verified (`orderSponsor`), else the open checkout's own
|
|
5898
|
+
* sponsor (`checkoutState.sponsorId`) — named by `Vio.sponsorIdentity`,
|
|
5899
|
+
* which falls back to this tab's memory of the checkout and the cart; the
|
|
5900
|
+
* name taken before the cart was cleared last. Never the page's
|
|
5901
|
+
* attribution. `null` when nothing names it.
|
|
5902
|
+
*/
|
|
5903
|
+
checkoutSponsorIdentity() {
|
|
5904
|
+
const o = this.orderSponsor;
|
|
5905
|
+
if (o) return checkoutSponsorOf(resolveSponsorIdentity(o.sponsorId, o.checkoutId)) ?? o.snapshot ?? null;
|
|
5906
|
+
const s = this.checkoutState;
|
|
5907
|
+
return s?.sponsorId ? checkoutSponsorOf(resolveSponsorIdentity(s.sponsorId, s.checkoutId)) ?? null : null;
|
|
5908
|
+
}
|
|
5909
|
+
/**
|
|
5910
|
+
* `{ sponsor }` for the payment event — the same sponsor the screen names
|
|
5911
|
+
* (`orderSponsor`, set by every path right before it emits): named now, else
|
|
5912
|
+
* as named before the cart was cleared; `{}` when nothing names it.
|
|
5913
|
+
*/
|
|
5914
|
+
sponsorOfOrder(sponsorId, checkoutId) {
|
|
5915
|
+
try {
|
|
5916
|
+
const o = this.orderSponsor;
|
|
5917
|
+
const sameOrder = !!o && (o.checkoutId ?? void 0) === (checkoutId || void 0);
|
|
5918
|
+
const id = sameOrder ? o.sponsorId : sponsorId > 0 ? sponsorId : void 0;
|
|
5919
|
+
const live = sponsorDetail(id, checkoutId);
|
|
5920
|
+
if (live.sponsor) return live;
|
|
5921
|
+
if (sameOrder && o.snapshot) return { sponsor: o.snapshot };
|
|
5922
|
+
} catch {
|
|
5923
|
+
}
|
|
5924
|
+
return {};
|
|
5925
|
+
}
|
|
5926
|
+
/**
|
|
5927
|
+
* Ask once per checkout for the bootstrap when it is not there yet and a
|
|
5928
|
+
* sponsor has to be named (a redirect return renders before it), then
|
|
5929
|
+
* render again — the name and the logo appear when it lands.
|
|
5930
|
+
*/
|
|
5931
|
+
watchSponsorBootstrap() {
|
|
5932
|
+
if (this.sponsorBootstrapAsked || !this.open || Vio.bootstrapCache) return;
|
|
5933
|
+
if (!this.orderSponsor && !this.checkoutState?.sponsorId) return;
|
|
5934
|
+
this.sponsorBootstrapAsked = true;
|
|
5935
|
+
void whenBootstrapped().then(() => this.requestUpdate());
|
|
5936
|
+
}
|
|
5937
|
+
/**
|
|
5938
|
+
* The checkout's sponsor in the header — «Du handler hos <logo|name>»
|
|
5939
|
+
* («Du har handlet hos» on a provider's receipt). Not on our own
|
|
5940
|
+
* confirmation, which says it in its body.
|
|
5941
|
+
*/
|
|
5942
|
+
renderTopbarSponsor() {
|
|
5943
|
+
if (this.orderConfirmed) return nothing;
|
|
5944
|
+
const sponsor = this.checkoutSponsorIdentity();
|
|
5945
|
+
const mark = renderSponsorMark(this, sponsor, { logo: "topbar-sponsor-logo", name: "topbar-sponsor-name" });
|
|
5946
|
+
if (mark === nothing) return nothing;
|
|
5947
|
+
return html`<p class="topbar-sponsor" part="sponsor">
|
|
5948
|
+
<span>${this.providerReceipt ? "Du har handlet hos" : "Du handler hos"}</span> ${mark}
|
|
5949
|
+
</p>`;
|
|
5950
|
+
}
|
|
5725
5951
|
/**
|
|
5726
5952
|
* The provider's receipt on its own. It must not depend on the cart: the
|
|
5727
5953
|
* payment step is rendered from the cart, and clearing the cart after a
|
|
@@ -5749,6 +5975,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5749
5975
|
this.confirmedMethod = method;
|
|
5750
5976
|
this.open = true;
|
|
5751
5977
|
const checkoutId = returnCheckoutId || this.checkoutState?.checkoutId;
|
|
5978
|
+
this.setOrderSponsor(sponsorId, checkoutId);
|
|
5752
5979
|
void this.emitPaymentSuccess(
|
|
5753
5980
|
{ method, sponsorId, result, checkoutId },
|
|
5754
5981
|
checkoutId,
|
|
@@ -5777,12 +6004,17 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5777
6004
|
details.push(["Betalingsm\xE5te", o?.paidWith || this.methodLabel(this.confirmedMethod)]);
|
|
5778
6005
|
if (o?.providerRef) details.push([o.providerRef.label, o.providerRef.value]);
|
|
5779
6006
|
if (email) details.push(["Kvittering til", email]);
|
|
6007
|
+
const sponsor = this.checkoutSponsorIdentity();
|
|
5780
6008
|
return html`
|
|
5781
6009
|
<section class="confirmation">
|
|
6010
|
+
${usableLogo(sponsor) ? html`<div class="confirm-brand" part="sponsor">
|
|
6011
|
+
${renderSponsorMark(this, sponsor, { logo: "confirm-brand-logo", name: "confirm-brand-name" })}
|
|
6012
|
+
</div>` : ""}
|
|
5782
6013
|
<header class="confirm-head">
|
|
5783
6014
|
<div class="confirm-check" aria-hidden="true">✓</div>
|
|
5784
6015
|
<div>
|
|
5785
6016
|
<h3 class="confirm-title">Takk for bestillingen!</h3>
|
|
6017
|
+
${sponsor?.name ? html`<p class="confirm-sponsor">Du har handlet hos <strong>${sponsor.name}</strong>.</p>` : ""}
|
|
5786
6018
|
<p class="confirm-text">
|
|
5787
6019
|
Betalingen er bekreftet.${email ? html` Du får en ordrebekreftelse på e-post.` : ""}
|
|
5788
6020
|
</p>
|
|
@@ -7075,6 +7307,9 @@ __decorateClass([
|
|
|
7075
7307
|
__decorateClass([
|
|
7076
7308
|
state()
|
|
7077
7309
|
], _VioCheckout.prototype, "verifyingReturn", 2);
|
|
7310
|
+
__decorateClass([
|
|
7311
|
+
state()
|
|
7312
|
+
], _VioCheckout.prototype, "orderSponsor", 2);
|
|
7078
7313
|
__decorateClass([
|
|
7079
7314
|
state()
|
|
7080
7315
|
], _VioCheckout.prototype, "confirmedOrder", 2);
|
|
@@ -7211,5 +7446,5 @@ function registerVioElements() {
|
|
|
7211
7446
|
}
|
|
7212
7447
|
|
|
7213
7448
|
export { VioCart, VioCheckout, VioProduct, VioProductCarousel, VioProductDetail, VioTokens, applyVioTheme, registerVioElements };
|
|
7214
|
-
//# sourceMappingURL=chunk-
|
|
7215
|
-
//# sourceMappingURL=chunk-
|
|
7449
|
+
//# sourceMappingURL=chunk-GLAKUYQA.js.map
|
|
7450
|
+
//# sourceMappingURL=chunk-GLAKUYQA.js.map
|