@vio-live/web-sdk 0.23.1 → 0.26.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 +191 -21
- package/dist/{chunk-BRJMT7P4.js → chunk-5KWICUME.js} +1321 -333
- package/dist/chunk-5KWICUME.js.map +1 -0
- package/dist/{chunk-UVDOKFGD.js → chunk-A3LN5JEM.js} +235 -58
- package/dist/chunk-A3LN5JEM.js.map +1 -0
- package/dist/chunk-NCP76AXW.js +3 -0
- package/dist/{chunk-45YKS5UG.js.map → chunk-NCP76AXW.js.map} +1 -1
- package/dist/core/index.d.ts +1284 -596
- 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-DDfZuHF6.d.ts → tokens-Bn7fK9ta.d.ts} +72 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -3
- package/package.json +2 -1
- package/dist/chunk-45YKS5UG.js +0 -3
- package/dist/chunk-BRJMT7P4.js.map +0 -1
- package/dist/chunk-UVDOKFGD.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Vio, __decorateClass, primaryImageUrl, displayPrice, getGlobalCurrency, ensureVippsButton, formatPrice, nexiReturnPaymentId, readNexiPending, kustomReturnOutcome, KUSTOM_RETURN_QUERY_KEYS, ADYEN_RETURN_METHOD, adyenReturnParams, ADYEN_RETURN_QUERY_KEYS, adyenReturnOutcome, AdyenOriginError, normalizeSlotId, autoSlotDisplayName, autoSlotId, normalizeScope } from './chunk-
|
|
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-5KWICUME.js';
|
|
2
2
|
import { LitElement, css, html } from 'lit';
|
|
3
3
|
import { property, state, query } from 'lit/decorators.js';
|
|
4
4
|
|
|
@@ -171,6 +171,8 @@ var SCOPE_ATTR = "vio-scope";
|
|
|
171
171
|
var SCOPE_NAME_ATTR = "vio-scope-name";
|
|
172
172
|
var SCOPE_DATA_ATTR = "data-vio-scope";
|
|
173
173
|
var SCOPE_NAME_DATA_ATTR = "data-vio-scope-name";
|
|
174
|
+
var CAMPAIGN_ATTR = "vio-campaign";
|
|
175
|
+
var CAMPAIGN_DATA_ATTR = "data-vio-campaign";
|
|
174
176
|
var liveAutoIds = (() => {
|
|
175
177
|
const g = globalThis;
|
|
176
178
|
return g.__VIO_LIVE_SLOT_IDS__ ?? (g.__VIO_LIVE_SLOT_IDS__ = /* @__PURE__ */ new Map());
|
|
@@ -192,6 +194,14 @@ var SlotRegistration = class {
|
|
|
192
194
|
get effective() {
|
|
193
195
|
return this.identity?.id ?? "";
|
|
194
196
|
}
|
|
197
|
+
/** The element's own page campaign (`vio-campaign` / ancestor `data-vio-campaign`); undefined → `Vio.init`'s applies. */
|
|
198
|
+
get campaignId() {
|
|
199
|
+
return this.identity?.campaignId;
|
|
200
|
+
}
|
|
201
|
+
/** The element's page-campaign candidates in order (own, ancestor) — the hint for `Vio.attribution` / `campaignForSlot`. */
|
|
202
|
+
get campaignHint() {
|
|
203
|
+
return this.identity?.campaignCandidates ?? [];
|
|
204
|
+
}
|
|
195
205
|
/** On connect: read the scope from the DOM, then register. */
|
|
196
206
|
connect(attrs) {
|
|
197
207
|
this.connected = true;
|
|
@@ -216,7 +226,7 @@ var SlotRegistration = class {
|
|
|
216
226
|
this.unregister();
|
|
217
227
|
if (!next) return;
|
|
218
228
|
try {
|
|
219
|
-
this.release = typeof Vio.registerSlot
|
|
229
|
+
this.release = typeof Vio.registerSlot !== "function" ? null : next.campaignId !== void 0 ? Vio.registerSlot(next.id, next.displayName, next.campaignId, { kind: this.kind }) : Vio.registerSlot(next.id, next.displayName, { kind: this.kind });
|
|
220
230
|
this.identity = next;
|
|
221
231
|
} catch {
|
|
222
232
|
this.release = null;
|
|
@@ -227,13 +237,20 @@ var SlotRegistration = class {
|
|
|
227
237
|
resolve(attrs) {
|
|
228
238
|
const explicit = normalizeSlotId(attrs.vioSlot);
|
|
229
239
|
const name = typeof attrs.vioSlotName === "string" && attrs.vioSlotName.trim() ? attrs.vioSlotName.trim() : void 0;
|
|
240
|
+
const campaignCandidates2 = campaignCandidatesOf(this.host, attrs);
|
|
241
|
+
const campaignId = campaignCandidates2[0];
|
|
230
242
|
if (explicit) {
|
|
231
243
|
this.releaseAuto();
|
|
232
|
-
return { id: explicit, displayName: name };
|
|
244
|
+
return { id: explicit, displayName: name, campaignId, campaignCandidates: campaignCandidates2 };
|
|
233
245
|
}
|
|
234
246
|
if (!this.connected) return null;
|
|
235
247
|
const auto = this.claimAuto();
|
|
236
|
-
return {
|
|
248
|
+
return {
|
|
249
|
+
id: auto.id,
|
|
250
|
+
displayName: name ?? autoSlotDisplayName(this.kind, auto.number - 1, this.scopeName),
|
|
251
|
+
campaignId,
|
|
252
|
+
campaignCandidates: campaignCandidates2
|
|
253
|
+
};
|
|
237
254
|
}
|
|
238
255
|
/** Unregister whatever is registered and free the auto number. */
|
|
239
256
|
clear() {
|
|
@@ -275,7 +292,12 @@ var SlotRegistration = class {
|
|
|
275
292
|
};
|
|
276
293
|
function sameIdentity(a, b) {
|
|
277
294
|
if (!a || !b) return a === b;
|
|
278
|
-
return a.id === b.id && a.displayName === b.displayName;
|
|
295
|
+
return a.id === b.id && a.displayName === b.displayName && a.campaignId === b.campaignId;
|
|
296
|
+
}
|
|
297
|
+
function campaignCandidatesOf(el, attrs) {
|
|
298
|
+
const own = attrs && attrs.vioCampaign !== void 0 && attrs.vioCampaign !== null ? attrs.vioCampaign : el.vioCampaign !== void 0 ? el.vioCampaign : el.getAttribute(CAMPAIGN_ATTR);
|
|
299
|
+
const ancestor = closestAcrossShadow(el, `[${CAMPAIGN_DATA_ATTR}]`)?.getAttribute(CAMPAIGN_DATA_ATTR);
|
|
300
|
+
return campaignCandidates([own, ancestor]);
|
|
279
301
|
}
|
|
280
302
|
function scopeOf(el, attrs) {
|
|
281
303
|
const own = attrs && typeof attrs.vioScope === "string" ? attrs.vioScope : typeof el.vioScope === "string" ? el.vioScope ?? "" : el.getAttribute(SCOPE_ATTR) ?? "";
|
|
@@ -314,8 +336,10 @@ var VioProduct = class extends LitElement {
|
|
|
314
336
|
this.vioSlotName = "";
|
|
315
337
|
this.vioScope = "";
|
|
316
338
|
this.vioScopeName = "";
|
|
339
|
+
this.vioCampaign = "";
|
|
317
340
|
this.vioContentId = "";
|
|
318
341
|
this.vioContentTitle = "";
|
|
342
|
+
this.componentTemplateId = "";
|
|
319
343
|
this.slotRegistration = new SlotRegistration(this, "card");
|
|
320
344
|
this.hasVariants = false;
|
|
321
345
|
this.variants = void 0;
|
|
@@ -330,9 +354,13 @@ var VioProduct = class extends LitElement {
|
|
|
330
354
|
get effectiveSlot() {
|
|
331
355
|
return this.slotRegistration.effective;
|
|
332
356
|
}
|
|
357
|
+
/** The element's own page campaign (`vio-campaign` / ancestor), if any; `Vio.init`'s applies otherwise. */
|
|
358
|
+
get effectiveCampaignId() {
|
|
359
|
+
return this.slotRegistration.campaignId;
|
|
360
|
+
}
|
|
333
361
|
/** The slot campaign's sponsor as the string the attributes use ('' when unknown). */
|
|
334
362
|
sponsorFromAttribution() {
|
|
335
|
-
const id = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot).sponsorId : void 0;
|
|
363
|
+
const id = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot, { campaignId: this.slotRegistration.campaignHint }).sponsorId : void 0;
|
|
336
364
|
return id !== void 0 ? String(id) : "";
|
|
337
365
|
}
|
|
338
366
|
slotAttributes() {
|
|
@@ -340,7 +368,8 @@ var VioProduct = class extends LitElement {
|
|
|
340
368
|
vioSlot: this.vioSlot,
|
|
341
369
|
vioSlotName: this.vioSlotName,
|
|
342
370
|
vioScope: this.vioScope,
|
|
343
|
-
vioScopeName: this.vioScopeName
|
|
371
|
+
vioScopeName: this.vioScopeName,
|
|
372
|
+
vioCampaign: this.vioCampaign
|
|
344
373
|
};
|
|
345
374
|
}
|
|
346
375
|
/**
|
|
@@ -349,9 +378,13 @@ var VioProduct = class extends LitElement {
|
|
|
349
378
|
* set `vio-content-id` / `vio-content-title` on this card.
|
|
350
379
|
*/
|
|
351
380
|
attribution() {
|
|
352
|
-
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot, {
|
|
381
|
+
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot, {
|
|
382
|
+
sponsorId: this.sponsorId || void 0,
|
|
383
|
+
campaignId: this.slotRegistration.campaignHint
|
|
384
|
+
}) : { slot: this.effectiveSlot || void 0 };
|
|
353
385
|
return {
|
|
354
386
|
...base,
|
|
387
|
+
componentTemplateId: this.componentTemplateId || "product-card",
|
|
355
388
|
...this.vioContentId ? { contentId: this.vioContentId } : {},
|
|
356
389
|
...this.vioContentTitle ? { contentTitle: this.vioContentTitle } : {}
|
|
357
390
|
};
|
|
@@ -479,7 +512,7 @@ var VioProduct = class extends LitElement {
|
|
|
479
512
|
}
|
|
480
513
|
updated(changed) {
|
|
481
514
|
if (changed.has("productId") || changed.has("sponsorId")) this.updateInCart();
|
|
482
|
-
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName")) {
|
|
515
|
+
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName") || changed.has("vioCampaign")) {
|
|
483
516
|
this.slotRegistration.sync(this.slotAttributes());
|
|
484
517
|
}
|
|
485
518
|
}
|
|
@@ -550,11 +583,15 @@ var VioProduct = class extends LitElement {
|
|
|
550
583
|
// The host's sponsor-id wins; without one, the slot's campaign sponsor.
|
|
551
584
|
sponsorId: this.sponsorId || this.sponsorFromAttribution(),
|
|
552
585
|
// The host adds to the cart: pass this through as `origin` so the
|
|
553
|
-
// purchase is attributed to this place
|
|
586
|
+
// purchase is attributed to this place, campaign, kind of element
|
|
587
|
+
// and page — the cart keeps it and Commerce receives it (ADR-0035).
|
|
554
588
|
origin: {
|
|
555
589
|
campaignId: attribution.campaignId,
|
|
556
590
|
slot: attribution.slot,
|
|
557
|
-
contentId: attribution.contentId
|
|
591
|
+
contentId: attribution.contentId,
|
|
592
|
+
componentKind: attribution.componentTemplateId,
|
|
593
|
+
contentUrl: attribution.contentUrl,
|
|
594
|
+
contentTitle: attribution.contentTitle
|
|
558
595
|
}
|
|
559
596
|
}
|
|
560
597
|
})
|
|
@@ -635,12 +672,18 @@ __decorateClass([
|
|
|
635
672
|
__decorateClass([
|
|
636
673
|
property({ type: String, attribute: "vio-scope-name" })
|
|
637
674
|
], VioProduct.prototype, "vioScopeName", 2);
|
|
675
|
+
__decorateClass([
|
|
676
|
+
property({ type: String, attribute: "vio-campaign" })
|
|
677
|
+
], VioProduct.prototype, "vioCampaign", 2);
|
|
638
678
|
__decorateClass([
|
|
639
679
|
property({ type: String, attribute: "vio-content-id" })
|
|
640
680
|
], VioProduct.prototype, "vioContentId", 2);
|
|
641
681
|
__decorateClass([
|
|
642
682
|
property({ type: String, attribute: "vio-content-title" })
|
|
643
683
|
], VioProduct.prototype, "vioContentTitle", 2);
|
|
684
|
+
__decorateClass([
|
|
685
|
+
property({ type: String, attribute: "component-template-id" })
|
|
686
|
+
], VioProduct.prototype, "componentTemplateId", 2);
|
|
644
687
|
__decorateClass([
|
|
645
688
|
property({ type: Boolean, attribute: "has-variants" })
|
|
646
689
|
], VioProduct.prototype, "hasVariants", 2);
|
|
@@ -679,6 +722,7 @@ var VioProductCarousel = class extends LitElement {
|
|
|
679
722
|
this.vioSlotName = "";
|
|
680
723
|
this.vioScope = "";
|
|
681
724
|
this.vioScopeName = "";
|
|
725
|
+
this.vioCampaign = "";
|
|
682
726
|
this.vioContentId = "";
|
|
683
727
|
this.vioContentTitle = "";
|
|
684
728
|
this.slotRegistration = new SlotRegistration(this, "carousel");
|
|
@@ -697,19 +741,28 @@ var VioProductCarousel = class extends LitElement {
|
|
|
697
741
|
get effectiveSlot() {
|
|
698
742
|
return this.slotRegistration.effective;
|
|
699
743
|
}
|
|
744
|
+
/** The element's own page campaign (`vio-campaign` / ancestor), if any; `Vio.init`'s applies otherwise. */
|
|
745
|
+
get effectiveCampaignId() {
|
|
746
|
+
return this.slotRegistration.campaignId;
|
|
747
|
+
}
|
|
700
748
|
slotAttributes() {
|
|
701
749
|
return {
|
|
702
750
|
vioSlot: this.vioSlot,
|
|
703
751
|
vioSlotName: this.vioSlotName,
|
|
704
752
|
vioScope: this.vioScope,
|
|
705
|
-
vioScopeName: this.vioScopeName
|
|
753
|
+
vioScopeName: this.vioScopeName,
|
|
754
|
+
vioCampaign: this.vioCampaign
|
|
706
755
|
};
|
|
707
756
|
}
|
|
708
757
|
/** Attribution every analytics event of this carousel carries (`Vio.attribution` + the content overrides). */
|
|
709
758
|
attribution() {
|
|
710
|
-
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot, {
|
|
759
|
+
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.effectiveSlot, {
|
|
760
|
+
sponsorId: this.sponsorId > 0 ? this.sponsorId : void 0,
|
|
761
|
+
campaignId: this.slotRegistration.campaignHint
|
|
762
|
+
}) : { slot: this.effectiveSlot || void 0 };
|
|
711
763
|
return {
|
|
712
764
|
...base,
|
|
765
|
+
componentTemplateId: "product-carousel",
|
|
713
766
|
...this.vioContentId ? { contentId: this.vioContentId } : {},
|
|
714
767
|
...this.vioContentTitle ? { contentTitle: this.vioContentTitle } : {}
|
|
715
768
|
};
|
|
@@ -874,10 +927,10 @@ var VioProductCarousel = class extends LitElement {
|
|
|
874
927
|
super.disconnectedCallback();
|
|
875
928
|
}
|
|
876
929
|
updated(changed) {
|
|
877
|
-
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName")) {
|
|
930
|
+
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName") || changed.has("vioCampaign")) {
|
|
878
931
|
this.slotRegistration.sync(this.slotAttributes());
|
|
879
932
|
}
|
|
880
|
-
const propChanged = changed.has("productRefs") || changed.has("productIds") || changed.has("commerceKey") || changed.has("sponsorId") || changed.has("vioSlot");
|
|
933
|
+
const propChanged = changed.has("productRefs") || changed.has("productIds") || changed.has("commerceKey") || changed.has("sponsorId") || changed.has("vioSlot") || changed.has("vioCampaign");
|
|
881
934
|
if (propChanged && (this.productRefs.trim() || this.productIds.trim())) {
|
|
882
935
|
void this.autoFetch();
|
|
883
936
|
}
|
|
@@ -889,7 +942,7 @@ var VioProductCarousel = class extends LitElement {
|
|
|
889
942
|
*/
|
|
890
943
|
effectiveSponsorId() {
|
|
891
944
|
if (this.sponsorId > 0) return this.sponsorId;
|
|
892
|
-
const fromSlot = typeof Vio.campaignForSlot === "function" ? Number(Vio.campaignForSlot(this.effectiveSlot || null)?.primarySponsor?.id) : NaN;
|
|
945
|
+
const fromSlot = typeof Vio.campaignForSlot === "function" ? Number(Vio.campaignForSlot(this.effectiveSlot || null, { campaignId: this.slotRegistration.campaignHint })?.primarySponsor?.id) : NaN;
|
|
893
946
|
return Number.isFinite(fromSlot) && fromSlot > 0 ? fromSlot : 0;
|
|
894
947
|
}
|
|
895
948
|
async autoFetch() {
|
|
@@ -951,7 +1004,6 @@ var VioProductCarousel = class extends LitElement {
|
|
|
951
1004
|
this,
|
|
952
1005
|
{
|
|
953
1006
|
sponsorId: this.sponsorId > 0 ? this.sponsorId : void 0,
|
|
954
|
-
componentTemplateId: "product-carousel",
|
|
955
1007
|
// The slot is the real location id; the label only stands in for it.
|
|
956
1008
|
locationId: this.effectiveSlot || this.label || void 0,
|
|
957
1009
|
...this.attribution()
|
|
@@ -979,7 +1031,6 @@ var VioProductCarousel = class extends LitElement {
|
|
|
979
1031
|
Vio.analytics.track("view_item_list", {
|
|
980
1032
|
context: {
|
|
981
1033
|
sponsorId: sponsorId > 0 ? sponsorId : void 0,
|
|
982
|
-
componentTemplateId: "product-carousel",
|
|
983
1034
|
locationId: this.effectiveSlot || this.label || void 0,
|
|
984
1035
|
...this.attribution()
|
|
985
1036
|
},
|
|
@@ -1038,6 +1089,8 @@ var VioProductCarousel = class extends LitElement {
|
|
|
1038
1089
|
image-url=${img}
|
|
1039
1090
|
?has-variants=${(p.variants?.length ?? 0) > 1}
|
|
1040
1091
|
.vioSlot=${this.effectiveSlot}
|
|
1092
|
+
.componentTemplateId=${"product-carousel"}
|
|
1093
|
+
.vioCampaign=${this.effectiveCampaignId !== void 0 ? String(this.effectiveCampaignId) : ""}
|
|
1041
1094
|
.vioContentId=${this.vioContentId}
|
|
1042
1095
|
.vioContentTitle=${this.vioContentTitle}
|
|
1043
1096
|
></vio-product>
|
|
@@ -1121,6 +1174,9 @@ __decorateClass([
|
|
|
1121
1174
|
__decorateClass([
|
|
1122
1175
|
property({ type: String, attribute: "vio-scope-name" })
|
|
1123
1176
|
], VioProductCarousel.prototype, "vioScopeName", 2);
|
|
1177
|
+
__decorateClass([
|
|
1178
|
+
property({ type: String, attribute: "vio-campaign" })
|
|
1179
|
+
], VioProductCarousel.prototype, "vioCampaign", 2);
|
|
1124
1180
|
__decorateClass([
|
|
1125
1181
|
property({ type: String, attribute: "vio-content-id" })
|
|
1126
1182
|
], VioProductCarousel.prototype, "vioContentId", 2);
|
|
@@ -1369,6 +1425,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
1369
1425
|
this.vioSlotName = "";
|
|
1370
1426
|
this.vioScope = "";
|
|
1371
1427
|
this.vioScopeName = "";
|
|
1428
|
+
this.vioCampaign = "";
|
|
1372
1429
|
this.vioContentId = "";
|
|
1373
1430
|
this.vioContentTitle = "";
|
|
1374
1431
|
this.slotRegistration = new SlotRegistration(this, "detail");
|
|
@@ -1376,6 +1433,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
1376
1433
|
this.eventSlot = "";
|
|
1377
1434
|
this.eventContentId = "";
|
|
1378
1435
|
this.eventContentTitle = "";
|
|
1436
|
+
this.eventCampaignId = void 0;
|
|
1379
1437
|
this.eventProductId = "";
|
|
1380
1438
|
this.product = null;
|
|
1381
1439
|
this.sellerName = null;
|
|
@@ -1410,11 +1468,16 @@ var VioProductDetail = class extends LitElement {
|
|
|
1410
1468
|
const slot = typeof ev.detail.slot === "string" ? ev.detail.slot.trim() : "";
|
|
1411
1469
|
let sponsorIdNum = parseInt(ev.detail.sponsorId, 10);
|
|
1412
1470
|
if (Number.isNaN(sponsorIdNum) || sponsorIdNum <= 0) {
|
|
1413
|
-
const fromSlot = typeof Vio.campaignForSlot === "function" ? Number(
|
|
1471
|
+
const fromSlot = typeof Vio.campaignForSlot === "function" ? Number(
|
|
1472
|
+
Vio.campaignForSlot(slot || this.effectiveSlot || null, {
|
|
1473
|
+
campaignId: [ev.detail.campaignId, ...this.slotRegistration.campaignHint]
|
|
1474
|
+
})?.primarySponsor?.id
|
|
1475
|
+
) : NaN;
|
|
1414
1476
|
if (!Number.isFinite(fromSlot) || fromSlot <= 0) return;
|
|
1415
1477
|
sponsorIdNum = fromSlot;
|
|
1416
1478
|
}
|
|
1417
1479
|
this.eventSlot = slot;
|
|
1480
|
+
this.eventCampaignId = toCampaignId(ev.detail.campaignId);
|
|
1418
1481
|
this.eventProductId = String(ev.detail.productId);
|
|
1419
1482
|
this.eventContentId = ev.detail.contentId !== void 0 && ev.detail.contentId !== null ? String(ev.detail.contentId).trim() : "";
|
|
1420
1483
|
this.eventContentTitle = typeof ev.detail.contentTitle === "string" ? ev.detail.contentTitle.trim() : "";
|
|
@@ -1433,25 +1496,39 @@ var VioProductDetail = class extends LitElement {
|
|
|
1433
1496
|
get effectiveSlot() {
|
|
1434
1497
|
return this.slotRegistration.effective;
|
|
1435
1498
|
}
|
|
1499
|
+
/** The element's own page campaign (`vio-campaign` / ancestor), if any; `Vio.init`'s applies otherwise. */
|
|
1500
|
+
get effectiveCampaignId() {
|
|
1501
|
+
return this.slotRegistration.campaignId;
|
|
1502
|
+
}
|
|
1436
1503
|
/** The slot the open product is attributed to: the opening card's, else this element's. */
|
|
1437
1504
|
get activeSlot() {
|
|
1438
1505
|
return this.fromCard && this.eventSlot || this.effectiveSlot;
|
|
1439
1506
|
}
|
|
1507
|
+
/** The page-campaign candidates of the open product: the opening card's, then this element's own and its ancestor's. */
|
|
1508
|
+
get activeCampaignHint() {
|
|
1509
|
+
const own = this.slotRegistration.campaignHint;
|
|
1510
|
+
return this.fromCard && this.eventCampaignId !== void 0 ? [this.eventCampaignId, ...own] : own;
|
|
1511
|
+
}
|
|
1440
1512
|
slotAttributes() {
|
|
1441
1513
|
return {
|
|
1442
1514
|
vioSlot: this.vioSlot,
|
|
1443
1515
|
vioSlotName: this.vioSlotName,
|
|
1444
1516
|
vioScope: this.vioScope,
|
|
1445
|
-
vioScopeName: this.vioScopeName
|
|
1517
|
+
vioScopeName: this.vioScopeName,
|
|
1518
|
+
vioCampaign: this.vioCampaign
|
|
1446
1519
|
};
|
|
1447
1520
|
}
|
|
1448
1521
|
/** Attribution every event of the open product carries (`Vio.attribution` of the opening card's slot, else this element's). */
|
|
1449
1522
|
attribution() {
|
|
1450
|
-
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.activeSlot, {
|
|
1523
|
+
const base = typeof Vio.attribution === "function" ? Vio.attribution(this.activeSlot, {
|
|
1524
|
+
sponsorId: this.sponsorId > 0 ? this.sponsorId : void 0,
|
|
1525
|
+
campaignId: this.activeCampaignHint
|
|
1526
|
+
}) : { slot: this.activeSlot || void 0 };
|
|
1451
1527
|
const contentId = this.fromCard && this.eventContentId || this.vioContentId;
|
|
1452
1528
|
const contentTitle = this.fromCard && this.eventContentTitle || this.vioContentTitle;
|
|
1453
1529
|
return {
|
|
1454
1530
|
...base,
|
|
1531
|
+
componentTemplateId: "product-detail",
|
|
1455
1532
|
...contentId ? { contentId } : {},
|
|
1456
1533
|
...contentTitle ? { contentTitle } : {}
|
|
1457
1534
|
};
|
|
@@ -1914,7 +1991,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
1914
1991
|
}
|
|
1915
1992
|
updated(changed) {
|
|
1916
1993
|
if (changed.has("open")) this.dialogFocus.update(this.open);
|
|
1917
|
-
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName")) {
|
|
1994
|
+
if (changed.has("vioSlot") || changed.has("vioSlotName") || changed.has("vioScope") || changed.has("vioScopeName") || changed.has("vioCampaign")) {
|
|
1918
1995
|
this.slotRegistration.sync(this.slotAttributes());
|
|
1919
1996
|
}
|
|
1920
1997
|
}
|
|
@@ -1928,6 +2005,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
1928
2005
|
this.eventSlot = "";
|
|
1929
2006
|
this.eventContentId = "";
|
|
1930
2007
|
this.eventContentTitle = "";
|
|
2008
|
+
this.eventCampaignId = void 0;
|
|
1931
2009
|
this.eventProductId = "";
|
|
1932
2010
|
this.product = null;
|
|
1933
2011
|
this.sellerName = null;
|
|
@@ -1987,7 +2065,6 @@ var VioProductDetail = class extends LitElement {
|
|
|
1987
2065
|
Vio.analytics.track("view_item", {
|
|
1988
2066
|
context: {
|
|
1989
2067
|
sponsorId: this.sponsorId > 0 ? Number(this.sponsorId) : void 0,
|
|
1990
|
-
componentTemplateId: "product-detail",
|
|
1991
2068
|
...this.attribution()
|
|
1992
2069
|
},
|
|
1993
2070
|
commerce: {
|
|
@@ -2028,7 +2105,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
2028
2105
|
}
|
|
2029
2106
|
/** Which buy buttons to render — backend-configured per sponsor. */
|
|
2030
2107
|
async loadAvailablePaymentMethods() {
|
|
2031
|
-
const spId = this.sponsorId || (typeof Vio.campaignForSlot === "function" ? Number(Vio.campaignForSlot(this.activeSlot || null)?.primarySponsor?.id) : 0) || globalThis.__VIO_SPONSOR_ID__;
|
|
2108
|
+
const spId = this.sponsorId || (typeof Vio.campaignForSlot === "function" ? Number(Vio.campaignForSlot(this.activeSlot || null, { campaignId: this.activeCampaignHint })?.primarySponsor?.id) : 0) || globalThis.__VIO_SPONSOR_ID__;
|
|
2032
2109
|
if (!spId) return;
|
|
2033
2110
|
try {
|
|
2034
2111
|
const methods = await Vio.checkout.getAvailablePaymentMethods(spId);
|
|
@@ -2310,14 +2387,14 @@ var VioProductDetail = class extends LitElement {
|
|
|
2310
2387
|
const sponsor = Vio.bootstrapCache?.primarySponsor;
|
|
2311
2388
|
const secondaries = Vio.bootstrapCache?.secondarySponsors ?? [];
|
|
2312
2389
|
const sponsorName = sponsor?.id === this.sponsorId ? sponsor.name : secondaries.find((s) => s.id === this.sponsorId)?.name;
|
|
2313
|
-
const { campaignId, slot, contentId } = this.attribution();
|
|
2390
|
+
const { campaignId, slot, contentId, componentTemplateId, contentUrl, contentTitle } = this.attribution();
|
|
2314
2391
|
Vio.cart.addProduct({
|
|
2315
2392
|
product: this.product,
|
|
2316
2393
|
sponsorId: this.sponsorId,
|
|
2317
2394
|
sponsorName,
|
|
2318
2395
|
quantity: this.quantity,
|
|
2319
2396
|
variantId: variant?.id,
|
|
2320
|
-
origin: { campaignId, slot, contentId }
|
|
2397
|
+
origin: { campaignId, slot, contentId, componentKind: componentTemplateId, contentUrl, contentTitle }
|
|
2321
2398
|
});
|
|
2322
2399
|
return variant?.id;
|
|
2323
2400
|
}
|
|
@@ -2734,6 +2811,9 @@ __decorateClass([
|
|
|
2734
2811
|
__decorateClass([
|
|
2735
2812
|
property({ type: String, attribute: "vio-scope-name" })
|
|
2736
2813
|
], VioProductDetail.prototype, "vioScopeName", 2);
|
|
2814
|
+
__decorateClass([
|
|
2815
|
+
property({ type: String, attribute: "vio-campaign" })
|
|
2816
|
+
], VioProductDetail.prototype, "vioCampaign", 2);
|
|
2737
2817
|
__decorateClass([
|
|
2738
2818
|
property({ type: String, attribute: "vio-content-id" })
|
|
2739
2819
|
], VioProductDetail.prototype, "vioContentId", 2);
|
|
@@ -3282,11 +3362,12 @@ var VioCart = class extends LitElement {
|
|
|
3282
3362
|
for (const sponsorId of [...this.carts.keys()]) {
|
|
3283
3363
|
Vio.cart.clearSponsorCart(sponsorId);
|
|
3284
3364
|
}
|
|
3365
|
+
const buyerRef = buyerRefOf({ result });
|
|
3285
3366
|
this.dispatchEvent(
|
|
3286
3367
|
new CustomEvent("vio:payment-success", {
|
|
3287
3368
|
bubbles: true,
|
|
3288
3369
|
composed: true,
|
|
3289
|
-
detail: { method: "apple-pay", result }
|
|
3370
|
+
detail: { method: "apple-pay", result, ...buyerRef ? { buyerRef } : {} }
|
|
3290
3371
|
})
|
|
3291
3372
|
);
|
|
3292
3373
|
});
|
|
@@ -3856,6 +3937,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3856
3937
|
this.paymentError = detail.method === "klarna" ? `Klarna-betalingen kunne ikke fullf\xF8res: ${detail.error}` : friendlyPaymentError(detail.error, detail.method);
|
|
3857
3938
|
this.open = true;
|
|
3858
3939
|
};
|
|
3940
|
+
/** Payment events still waiting for their buyer reference: settled early (without it) when the page hides or the element leaves. */
|
|
3941
|
+
this.pendingSuccessEmits = /* @__PURE__ */ new Set();
|
|
3859
3942
|
}
|
|
3860
3943
|
/** A payment is being started or confirmed right now: the overlay must not close under it. */
|
|
3861
3944
|
get paymentInFlight() {
|
|
@@ -4546,13 +4629,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4546
4629
|
this.orderConfirmed = true;
|
|
4547
4630
|
this.open = true;
|
|
4548
4631
|
void this.fillOrderNumber(checkoutId, sponsorId);
|
|
4549
|
-
this.
|
|
4550
|
-
new CustomEvent("vio:payment-success", {
|
|
4551
|
-
bubbles: true,
|
|
4552
|
-
composed: true,
|
|
4553
|
-
detail: { method: vioMethod, sponsorId, orderId: checkoutId }
|
|
4554
|
-
})
|
|
4555
|
-
);
|
|
4632
|
+
void this.emitPaymentSuccess({ method: vioMethod, sponsorId, orderId: checkoutId }, checkoutId, sponsorId);
|
|
4556
4633
|
} else if (outcome === "duplicate") {
|
|
4557
4634
|
this.paymentError = CART_PAID_MESSAGE;
|
|
4558
4635
|
this.open = true;
|
|
@@ -4894,6 +4971,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4894
4971
|
this.unmountKlarna();
|
|
4895
4972
|
this.unmountNexi();
|
|
4896
4973
|
this.unmountAdyen();
|
|
4974
|
+
for (const settle of [...this.pendingSuccessEmits]) settle();
|
|
4897
4975
|
super.disconnectedCallback();
|
|
4898
4976
|
}
|
|
4899
4977
|
updated(changed) {
|
|
@@ -5405,18 +5483,122 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5405
5483
|
this.confirmedMethod = method;
|
|
5406
5484
|
this.orderConfirmed = true;
|
|
5407
5485
|
this.open = true;
|
|
5408
|
-
this.
|
|
5409
|
-
|
|
5486
|
+
void this.fillOrderNumber(checkoutId, sponsorId);
|
|
5487
|
+
void this.emitPaymentSuccess(
|
|
5488
|
+
{ method, sponsorId, result, checkoutId },
|
|
5489
|
+
checkoutId,
|
|
5490
|
+
sponsorId,
|
|
5491
|
+
() => Vio.cart.clearSponsorCart(sponsorId)
|
|
5492
|
+
);
|
|
5493
|
+
}
|
|
5494
|
+
static {
|
|
5495
|
+
/** Longest `vio:payment-success` waits for the checkout's buyer reference, and when it asks a second time. */
|
|
5496
|
+
this.BUYER_REF_WAIT_MS = 2500;
|
|
5497
|
+
}
|
|
5498
|
+
static {
|
|
5499
|
+
this.BUYER_REF_RETRY_AT_MS = 1200;
|
|
5500
|
+
}
|
|
5501
|
+
/**
|
|
5502
|
+
* `vio:payment-success` for the host and analytics — with the buyer
|
|
5503
|
+
* reference (`buyerRef`: shopcart's keyed hash of the email → analytics
|
|
5504
|
+
* `buyer_id`) when the checkout can say it. An emitter whose own answer
|
|
5505
|
+
* carried it (Apple Pay, Klarna native) sends at once; the others (a
|
|
5506
|
+
* redirect return, Stripe / Adyen / Nexi in the drawer, a provider's
|
|
5507
|
+
* receipt) ask the checkout — at once and, while it has neither order nor
|
|
5508
|
+
* reference, again at 1.2 s, since a webhook may write the checkout a
|
|
5509
|
+
* moment after the redirect — within 2.5 s, and
|
|
5510
|
+
* send without it when the answer is late or empty. Nothing is asked when
|
|
5511
|
+
* it cannot help (the gateway has no `buyer_ref` yet; a confirmation that
|
|
5512
|
+
* already answered). Only the event waits — the screen is already the
|
|
5513
|
+
* confirmation — and not past the page: when the page hides (`pagehide`,
|
|
5514
|
+
* `visibilitychange`) or the element leaves, the event goes out at once
|
|
5515
|
+
* without the reference. Exactly one event per call. `afterwards` runs
|
|
5516
|
+
* right after the event, so a path keeps the order it always had (the cart
|
|
5517
|
+
* is cleared after the event).
|
|
5518
|
+
*/
|
|
5519
|
+
async emitPaymentSuccess(detail, checkoutId, sponsorId, afterwards) {
|
|
5520
|
+
let done = false;
|
|
5521
|
+
const finish = (buyerRef) => {
|
|
5522
|
+
if (done) return;
|
|
5523
|
+
done = true;
|
|
5524
|
+
const event = new CustomEvent("vio:payment-success", {
|
|
5410
5525
|
bubbles: true,
|
|
5411
5526
|
composed: true,
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5527
|
+
detail: buyerRef ? { ...detail, buyerRef } : detail
|
|
5528
|
+
});
|
|
5529
|
+
this.dispatchEvent(event);
|
|
5530
|
+
if (!this.isConnected && typeof window !== "undefined") {
|
|
5531
|
+
window.dispatchEvent(new CustomEvent("vio:payment-success", { detail: event.detail }));
|
|
5532
|
+
}
|
|
5533
|
+
try {
|
|
5534
|
+
afterwards?.();
|
|
5535
|
+
} catch {
|
|
5536
|
+
}
|
|
5537
|
+
};
|
|
5538
|
+
const known = buyerRefOf(detail);
|
|
5539
|
+
if (known || !checkoutId || !this.shouldAskBuyerRef(detail)) {
|
|
5540
|
+
finish(known);
|
|
5541
|
+
return;
|
|
5542
|
+
}
|
|
5543
|
+
const settleEarly = () => finish();
|
|
5544
|
+
const onVisibility = () => {
|
|
5545
|
+
if (typeof document !== "undefined" && document.visibilityState === "hidden") settleEarly();
|
|
5546
|
+
};
|
|
5547
|
+
this.pendingSuccessEmits.add(settleEarly);
|
|
5548
|
+
window.addEventListener("pagehide", settleEarly);
|
|
5549
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
5550
|
+
try {
|
|
5551
|
+
finish(await this.askBuyerRef(checkoutId, sponsorId, () => done));
|
|
5552
|
+
} catch {
|
|
5553
|
+
finish();
|
|
5554
|
+
} finally {
|
|
5555
|
+
this.pendingSuccessEmits.delete(settleEarly);
|
|
5556
|
+
window.removeEventListener("pagehide", settleEarly);
|
|
5557
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
5558
|
+
}
|
|
5559
|
+
}
|
|
5560
|
+
/** Whether asking the checkout for the buyer reference can still help. */
|
|
5561
|
+
shouldAskBuyerRef(detail) {
|
|
5562
|
+
if (typeof Vio.checkout.getOrderReference !== "function") return false;
|
|
5563
|
+
if (!gatewayHasBuyerRef()) return false;
|
|
5564
|
+
if ((detail.method === "apple-pay" || detail.method === "klarna") && detail.result) return false;
|
|
5565
|
+
return true;
|
|
5566
|
+
}
|
|
5567
|
+
/**
|
|
5568
|
+
* The buyer reference of a checkout: asked at once and, when that answer
|
|
5569
|
+
* failed or has neither the reference nor an order yet (the webhook has not
|
|
5570
|
+
* written the checkout), again at 1.2 s — all within 2.5 s. An order
|
|
5571
|
+
* without a reference is a settled answer: the backend has none, asking
|
|
5572
|
+
* again cannot help. `undefined` when the time is up, when the answer
|
|
5573
|
+
* stopped mattering (`stopped()`) or on failure.
|
|
5574
|
+
*/
|
|
5575
|
+
async askBuyerRef(checkoutId, sponsorId, stopped) {
|
|
5576
|
+
const started = Date.now();
|
|
5577
|
+
const remaining = () => _VioCheckout.BUYER_REF_WAIT_MS - (Date.now() - started);
|
|
5578
|
+
let deadline;
|
|
5579
|
+
const timeUp = new Promise((resolve) => {
|
|
5580
|
+
deadline = setTimeout(() => resolve(null), _VioCheckout.BUYER_REF_WAIT_MS);
|
|
5581
|
+
});
|
|
5582
|
+
try {
|
|
5583
|
+
for (const at of [0, _VioCheckout.BUYER_REF_RETRY_AT_MS]) {
|
|
5584
|
+
const wait = Math.min(at - (Date.now() - started), remaining());
|
|
5585
|
+
if (wait > 0) await Promise.race([new Promise((resolve) => setTimeout(resolve, wait)), timeUp]);
|
|
5586
|
+
if (stopped() || remaining() <= 0) return void 0;
|
|
5587
|
+
try {
|
|
5588
|
+
const reference = await Promise.race([
|
|
5589
|
+
Vio.checkout.getOrderReference(checkoutId, sponsorId || void 0),
|
|
5590
|
+
timeUp
|
|
5591
|
+
]);
|
|
5592
|
+
if (reference === null) return void 0;
|
|
5593
|
+
if (reference.buyerRef) return reference.buyerRef;
|
|
5594
|
+
if (reference.orderNumber !== null) return void 0;
|
|
5595
|
+
} catch {
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
return void 0;
|
|
5599
|
+
} finally {
|
|
5600
|
+
clearTimeout(deadline);
|
|
5601
|
+
}
|
|
5420
5602
|
}
|
|
5421
5603
|
static {
|
|
5422
5604
|
/** Waits between asks for the Vio order number: the order is often born a
|
|
@@ -5567,19 +5749,14 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5567
5749
|
this.confirmedMethod = method;
|
|
5568
5750
|
this.open = true;
|
|
5569
5751
|
const checkoutId = returnCheckoutId || this.checkoutState?.checkoutId;
|
|
5570
|
-
this.
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
);
|
|
5577
|
-
if (sponsorId) {
|
|
5578
|
-
try {
|
|
5579
|
-
Vio.cart.clearSponsorCart(sponsorId);
|
|
5580
|
-
} catch {
|
|
5752
|
+
void this.emitPaymentSuccess(
|
|
5753
|
+
{ method, sponsorId, result, checkoutId },
|
|
5754
|
+
checkoutId,
|
|
5755
|
+
sponsorId,
|
|
5756
|
+
() => {
|
|
5757
|
+
if (sponsorId) Vio.cart.clearSponsorCart(sponsorId);
|
|
5581
5758
|
}
|
|
5582
|
-
|
|
5759
|
+
);
|
|
5583
5760
|
}
|
|
5584
5761
|
/** Back from the payment page, asking whether it was paid — and nothing
|
|
5585
5762
|
* else on screen while we do. */
|
|
@@ -7034,5 +7211,5 @@ function registerVioElements() {
|
|
|
7034
7211
|
}
|
|
7035
7212
|
|
|
7036
7213
|
export { VioCart, VioCheckout, VioProduct, VioProductCarousel, VioProductDetail, VioTokens, applyVioTheme, registerVioElements };
|
|
7037
|
-
//# sourceMappingURL=chunk-
|
|
7038
|
-
//# sourceMappingURL=chunk-
|
|
7214
|
+
//# sourceMappingURL=chunk-A3LN5JEM.js.map
|
|
7215
|
+
//# sourceMappingURL=chunk-A3LN5JEM.js.map
|