@vio-live/web-sdk 0.19.0 → 0.21.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/dist/{chunk-NUNGU6LL.js → chunk-MRJR6DG5.js} +326 -38
- package/dist/chunk-MRJR6DG5.js.map +1 -0
- package/dist/{chunk-CMNTHF66.js → chunk-WTVGVDZX.js} +86 -18
- package/dist/chunk-WTVGVDZX.js.map +1 -0
- package/dist/core/index.d.ts +118 -5
- package/dist/core/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +3 -3
- package/dist/{tokens-IrVSMVcA.d.ts → tokens-Dkbfcd1L.d.ts} +12 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-CMNTHF66.js.map +0 -1
- package/dist/chunk-NUNGU6LL.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 } from './chunk-
|
|
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 } from './chunk-WTVGVDZX.js';
|
|
2
2
|
import { LitElement, css, html } from 'lit';
|
|
3
3
|
import { property, state, query } from 'lit/decorators.js';
|
|
4
4
|
|
|
@@ -885,6 +885,192 @@ function isMethodEnabled(available, ...names) {
|
|
|
885
885
|
);
|
|
886
886
|
}
|
|
887
887
|
|
|
888
|
+
// src/ui/dialog-focus.ts
|
|
889
|
+
var DialogFocus = class {
|
|
890
|
+
constructor(opts) {
|
|
891
|
+
this.opts = opts;
|
|
892
|
+
this.opener = null;
|
|
893
|
+
this.active = false;
|
|
894
|
+
/** The element inside the dialog that had focus last — where a pull-back continues from. */
|
|
895
|
+
this.lastInside = null;
|
|
896
|
+
this.onKeydown = (e) => {
|
|
897
|
+
if (e.defaultPrevented) return;
|
|
898
|
+
if (e.key === "Escape" || e.key === "Esc") {
|
|
899
|
+
if (this.opts.canClose && !this.opts.canClose()) return;
|
|
900
|
+
e.preventDefault();
|
|
901
|
+
e.stopPropagation();
|
|
902
|
+
this.opts.close();
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
if (e.key !== "Tab" || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
906
|
+
const container = this.opts.container();
|
|
907
|
+
if (!container) return;
|
|
908
|
+
const items = tabbableIn(container);
|
|
909
|
+
if (items.length === 0) {
|
|
910
|
+
e.preventDefault();
|
|
911
|
+
focusElement(container);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const active = deepActiveElement();
|
|
915
|
+
const index = active ? items.indexOf(active) : -1;
|
|
916
|
+
e.preventDefault();
|
|
917
|
+
const count = items.length;
|
|
918
|
+
const next = index === -1 ? e.shiftKey ? count - 1 : 0 : (index + (e.shiftKey ? -1 : 1) + count) % count;
|
|
919
|
+
focusElement(items[next]);
|
|
920
|
+
};
|
|
921
|
+
/**
|
|
922
|
+
* Focus moved somewhere. Inside the dialog: remember where. Into another
|
|
923
|
+
* open Vio dialog: theirs. Onto the page: the browser walked out of the
|
|
924
|
+
* dialog on its own (Safari leaving a widget iframe) — continue from the
|
|
925
|
+
* element that had focus, backwards when the page element sits before
|
|
926
|
+
* the host in document order.
|
|
927
|
+
*/
|
|
928
|
+
this.onFocusIn = (e) => {
|
|
929
|
+
if (!this.opts.host.isConnected) return;
|
|
930
|
+
const path = e.composedPath();
|
|
931
|
+
if (path.includes(this.opts.host)) {
|
|
932
|
+
const active = deepActiveElement();
|
|
933
|
+
this.lastInside = active instanceof HTMLElement ? active : null;
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (path.some((n) => isOpenVioDialog(n, this.opts.host))) return;
|
|
937
|
+
const container = this.opts.container();
|
|
938
|
+
if (!container) return;
|
|
939
|
+
const items = tabbableIn(container);
|
|
940
|
+
if (items.length === 0) {
|
|
941
|
+
focusElement(container);
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const target = e.target instanceof Node ? e.target : null;
|
|
945
|
+
const backwards = !!target && precedes(target, this.opts.host);
|
|
946
|
+
const index = this.lastInside ? items.indexOf(this.lastInside) : -1;
|
|
947
|
+
const count = items.length;
|
|
948
|
+
const next = backwards ? index <= 0 ? count - 1 : index - 1 : index === -1 || index === count - 1 ? 0 : index + 1;
|
|
949
|
+
focusElement(items[next]);
|
|
950
|
+
};
|
|
951
|
+
/** Tab pressed while focus is on the page (or the body): enter the dialog. */
|
|
952
|
+
this.onDocumentKeydown = (e) => {
|
|
953
|
+
if (!this.opts.host.isConnected) return;
|
|
954
|
+
if (e.defaultPrevented || e.key !== "Tab" || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
955
|
+
const active = deepActiveElement();
|
|
956
|
+
if (active && isWithin(active, this.opts.host)) return;
|
|
957
|
+
if (active && hasOpenVioDialogAbove(active, this.opts.host)) return;
|
|
958
|
+
const container = this.opts.container();
|
|
959
|
+
if (!container) return;
|
|
960
|
+
e.preventDefault();
|
|
961
|
+
e.stopPropagation();
|
|
962
|
+
const items = tabbableIn(container);
|
|
963
|
+
focusElement(items.length === 0 ? container : e.shiftKey ? items[items.length - 1] : items[0]);
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Call from `updated()` when `open` changed. Lit reports `open` as changed
|
|
968
|
+
* on the first render too (from undefined to its initial value): with the
|
|
969
|
+
* same value twice this is a no-op, so that first call does nothing.
|
|
970
|
+
*/
|
|
971
|
+
update(open) {
|
|
972
|
+
if (open === this.active) return;
|
|
973
|
+
this.active = open;
|
|
974
|
+
if (open) this.opened();
|
|
975
|
+
else this.closed();
|
|
976
|
+
}
|
|
977
|
+
opened() {
|
|
978
|
+
this.opener = deepActiveElement();
|
|
979
|
+
this.lastInside = null;
|
|
980
|
+
this.opts.host.addEventListener("keydown", this.onKeydown);
|
|
981
|
+
document.addEventListener("focusin", this.onFocusIn, true);
|
|
982
|
+
document.addEventListener("keydown", this.onDocumentKeydown, true);
|
|
983
|
+
const container = this.opts.container();
|
|
984
|
+
if (container) focusInto(container);
|
|
985
|
+
}
|
|
986
|
+
closed() {
|
|
987
|
+
this.opts.host.removeEventListener("keydown", this.onKeydown);
|
|
988
|
+
document.removeEventListener("focusin", this.onFocusIn, true);
|
|
989
|
+
document.removeEventListener("keydown", this.onDocumentKeydown, true);
|
|
990
|
+
const opener = this.opener;
|
|
991
|
+
this.opener = null;
|
|
992
|
+
const active = deepActiveElement();
|
|
993
|
+
if (!active || !isWithin(active, this.opts.host)) return;
|
|
994
|
+
if (opener && opener.isConnected && isRestorable(opener)) {
|
|
995
|
+
focusElement(opener);
|
|
996
|
+
} else if (active instanceof HTMLElement) {
|
|
997
|
+
active.blur();
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
function isOpenVioDialog(node, host) {
|
|
1002
|
+
return node instanceof Element && node !== host && node.tagName.startsWith("VIO-") && node.hasAttribute("open");
|
|
1003
|
+
}
|
|
1004
|
+
function hasOpenVioDialogAbove(node, host) {
|
|
1005
|
+
let n = node;
|
|
1006
|
+
while (n) {
|
|
1007
|
+
if (isOpenVioDialog(n, host)) return true;
|
|
1008
|
+
n = n.parentNode ?? (n instanceof ShadowRoot ? n.host : null);
|
|
1009
|
+
}
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
function precedes(a, b) {
|
|
1013
|
+
return (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
|
|
1014
|
+
}
|
|
1015
|
+
function deepActiveElement() {
|
|
1016
|
+
if (typeof document === "undefined") return null;
|
|
1017
|
+
let el = document.activeElement;
|
|
1018
|
+
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
1019
|
+
return el;
|
|
1020
|
+
}
|
|
1021
|
+
var TABBABLE_CANDIDATES = "a[href], area[href], button, input, select, textarea, iframe, summary, [tabindex], [contenteditable]";
|
|
1022
|
+
function tabbableIn(container) {
|
|
1023
|
+
const out = [];
|
|
1024
|
+
walkChildren(container, out);
|
|
1025
|
+
return out;
|
|
1026
|
+
}
|
|
1027
|
+
function walkChildren(parent, out) {
|
|
1028
|
+
for (const child of Array.from(parent.children)) {
|
|
1029
|
+
if (child instanceof HTMLSlotElement) {
|
|
1030
|
+
const assigned = child.assignedElements({ flatten: true });
|
|
1031
|
+
if (assigned.length > 0) {
|
|
1032
|
+
for (const el of assigned) visit(el, out);
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
visit(child, out);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
function visit(el, out) {
|
|
1040
|
+
if (isTabbable(el)) out.push(el);
|
|
1041
|
+
if (el.shadowRoot) walkChildren(el.shadowRoot, out);
|
|
1042
|
+
else walkChildren(el, out);
|
|
1043
|
+
}
|
|
1044
|
+
function isTabbable(el) {
|
|
1045
|
+
if (!(el instanceof HTMLElement) || !el.matches(TABBABLE_CANDIDATES)) return false;
|
|
1046
|
+
const tabindex = el.getAttribute("tabindex");
|
|
1047
|
+
if (tabindex !== null && Number(tabindex) < 0) return false;
|
|
1048
|
+
if (el.hasAttribute("disabled")) return false;
|
|
1049
|
+
if (el instanceof HTMLInputElement && el.type === "hidden") return false;
|
|
1050
|
+
if (el.getAttribute("contenteditable") === "false" && !el.matches("a[href], button, input, select, textarea, iframe, [tabindex]")) return false;
|
|
1051
|
+
if (el.hidden || el.getAttribute("aria-hidden") === "true") return false;
|
|
1052
|
+
if (typeof el.checkVisibility === "function" && !el.checkVisibility()) return false;
|
|
1053
|
+
return true;
|
|
1054
|
+
}
|
|
1055
|
+
function focusInto(container) {
|
|
1056
|
+
const first = tabbableIn(container)[0];
|
|
1057
|
+
focusElement(first ?? container);
|
|
1058
|
+
}
|
|
1059
|
+
function focusElement(el) {
|
|
1060
|
+
el.focus({ preventScroll: true });
|
|
1061
|
+
}
|
|
1062
|
+
function isRestorable(el) {
|
|
1063
|
+
return el instanceof HTMLElement && el !== document.body && el !== document.documentElement;
|
|
1064
|
+
}
|
|
1065
|
+
function isWithin(node, ancestor) {
|
|
1066
|
+
let n = node;
|
|
1067
|
+
while (n) {
|
|
1068
|
+
if (n === ancestor) return true;
|
|
1069
|
+
n = n.parentNode ?? (n instanceof ShadowRoot ? n.host : null);
|
|
1070
|
+
}
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
888
1074
|
// src/ui/components/vio-product-detail.ts
|
|
889
1075
|
var STRIPE_LOGO_SRC = "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
890
1076
|
'<svg width="360" height="150" viewBox="0 0 360 150" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M360 77.4001C360 51.8001 347.6 31.6001 323.9 31.6001C300.1 31.6001 285.7 51.8001 285.7 77.2001C285.7 107.3 302.7 122.5 327.1 122.5C339 122.5 348 119.8 354.8 116V96.0001C348 99.4001 340.2 101.5 330.3 101.5C320.6 101.5 312 98.1001 310.9 86.3001H359.8C359.8 85.0001 360 79.8001 360 77.4001ZM310.6 67.9001C310.6 56.6001 317.5 51.9001 323.8 51.9001C329.9 51.9001 336.4 56.6001 336.4 67.9001H310.6Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M247.1 31.6001C237.3 31.6001 231 36.2001 227.5 39.4001L226.2 33.2001H204.2V149.8L229.2 144.5L229.3 116.2C232.9 118.8 238.2 122.5 247 122.5C264.9 122.5 281.2 108.1 281.2 76.4001C281.1 47.4001 264.6 31.6001 247.1 31.6001ZM241.1 100.5C235.2 100.5 231.7 98.4001 229.3 95.8001L229.2 58.7001C231.8 55.8001 235.4 53.8001 241.1 53.8001C250.2 53.8001 256.5 64.0001 256.5 77.1001C256.5 90.5001 250.3 100.5 241.1 100.5Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M169.8 25.7L194.9 20.3V0L169.8 5.3V25.7Z" fill="#533AFD"/><path d="M194.9 33.3H169.8V120.8H194.9V33.3Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M142.9 40.7L141.3 33.3H119.7V120.8H144.7V61.5C150.6 53.8 160.6 55.2 163.7 56.3V33.3C160.5 32.1 148.8 29.9 142.9 40.7Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M92.8999 11.6001L68.4999 16.8001L68.3999 96.9001C68.3999 111.7 79.4999 122.6 94.2999 122.6C102.5 122.6 108.5 121.1 111.8 119.3V99.0001C108.6 100.3 92.7999 104.9 92.7999 90.1001V54.6001H111.8V33.3001H92.7999L92.8999 11.6001Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M25.3 58.7001C25.3 54.8001 28.5 53.3001 33.8 53.3001C41.4 53.3001 51 55.6001 58.6 59.7001V36.2001C50.3 32.9001 42.1 31.6001 33.8 31.6001C13.5 31.6001 0 42.2001 0 59.9001C0 87.5001 38 83.1001 38 95.0001C38 99.6001 34 101.1 28.4 101.1C20.1 101.1 9.5 97.7001 1.1 93.1001V116.9C10.4 120.9 19.8 122.6 28.4 122.6C49.2 122.6 63.5 112.3 63.5 94.4001C63.4 64.6001 25.3 69.9001 25.3 58.7001Z" fill="#533AFD"/></svg>'
|
|
@@ -916,6 +1102,12 @@ var VioProductDetail = class extends LitElement {
|
|
|
916
1102
|
this.optMapCache = /* @__PURE__ */ new WeakMap();
|
|
917
1103
|
/** Pre-prepared Apple Pay handle — show() fires synchronously on tap. */
|
|
918
1104
|
this.applePayHandle = null;
|
|
1105
|
+
/** Keyboard and focus while open: Escape closes, Tab stays inside, focus returns to the opener. */
|
|
1106
|
+
this.dialogFocus = new DialogFocus({
|
|
1107
|
+
host: this,
|
|
1108
|
+
container: () => this.renderRoot.querySelector(".modal"),
|
|
1109
|
+
close: () => this.close()
|
|
1110
|
+
});
|
|
919
1111
|
this.boundProductClick = (e) => {
|
|
920
1112
|
if (!this.autoOpen) return;
|
|
921
1113
|
const ev = e;
|
|
@@ -959,6 +1151,8 @@ var VioProductDetail = class extends LitElement {
|
|
|
959
1151
|
overflow-y: auto;
|
|
960
1152
|
}
|
|
961
1153
|
:host([open]) .modal { transform: translateY(0); }
|
|
1154
|
+
/* Focus lands on the panel itself only as a fallback — no ring for it. */
|
|
1155
|
+
.modal:focus { outline: none; }
|
|
962
1156
|
|
|
963
1157
|
.handle { display: none; }
|
|
964
1158
|
|
|
@@ -967,7 +1161,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
967
1161
|
.modal {
|
|
968
1162
|
top: auto;
|
|
969
1163
|
height: 92vh;
|
|
970
|
-
border-radius: 16px 16px 0 0;
|
|
1164
|
+
border-radius: var(--vio-radius-xl, 16px) var(--vio-radius-xl, 16px) 0 0;
|
|
971
1165
|
box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.08);
|
|
972
1166
|
}
|
|
973
1167
|
.handle {
|
|
@@ -981,7 +1175,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
981
1175
|
width: 40px;
|
|
982
1176
|
height: 4px;
|
|
983
1177
|
background: var(--vio-color-border, #e5e5e5);
|
|
984
|
-
border-radius: 2px;
|
|
1178
|
+
border-radius: var(--vio-radius-sm, 2px);
|
|
985
1179
|
}
|
|
986
1180
|
}
|
|
987
1181
|
|
|
@@ -1346,9 +1540,9 @@ var VioProductDetail = class extends LitElement {
|
|
|
1346
1540
|
);
|
|
1347
1541
|
background-size: 200% 100%;
|
|
1348
1542
|
animation: vio-skeleton-shimmer 1.4s ease-in-out infinite;
|
|
1349
|
-
border-radius: 8px;
|
|
1543
|
+
border-radius: var(--vio-radius-lg, 8px);
|
|
1350
1544
|
}
|
|
1351
|
-
.sk-image { width: 100%; aspect-ratio: 1; border-radius: 12px; }
|
|
1545
|
+
.sk-image { width: 100%; aspect-ratio: 1; border-radius: var(--vio-radius-lg, 12px); }
|
|
1352
1546
|
.sk-line { height: 14px; }
|
|
1353
1547
|
.sk-brand { width: 38%; height: 10px; margin-top: 6px; }
|
|
1354
1548
|
.sk-title { width: 85%; height: 26px; }
|
|
@@ -1382,6 +1576,9 @@ var VioProductDetail = class extends LitElement {
|
|
|
1382
1576
|
document.removeEventListener("vio:product-click", this.boundProductClick);
|
|
1383
1577
|
super.disconnectedCallback();
|
|
1384
1578
|
}
|
|
1579
|
+
updated(changed) {
|
|
1580
|
+
if (changed.has("open")) this.dialogFocus.update(this.open);
|
|
1581
|
+
}
|
|
1385
1582
|
show() {
|
|
1386
1583
|
this.open = true;
|
|
1387
1584
|
}
|
|
@@ -1938,7 +2135,7 @@ var VioProductDetail = class extends LitElement {
|
|
|
1938
2135
|
render() {
|
|
1939
2136
|
return html`
|
|
1940
2137
|
<div class="backdrop" @click=${this.close}></div>
|
|
1941
|
-
<div class="modal" role="dialog" aria-label="Produkt">
|
|
2138
|
+
<div class="modal" role="dialog" aria-modal="true" aria-label="Produkt" tabindex="-1">
|
|
1942
2139
|
<div class="handle" @click=${this.close} aria-hidden="true"></div>
|
|
1943
2140
|
<div class="topbar">
|
|
1944
2141
|
<span class="topbar-brand">${this.headerName()}</span>
|
|
@@ -2247,6 +2444,12 @@ var VioCart = class extends LitElement {
|
|
|
2247
2444
|
this.preparedTotal = -1;
|
|
2248
2445
|
/** In-flight guard for loadAvailablePaymentMethods. */
|
|
2249
2446
|
this.loadingPaymentMethods = false;
|
|
2447
|
+
/** Keyboard and focus while open: Escape closes, Tab stays inside, focus returns to the opener. */
|
|
2448
|
+
this.dialogFocus = new DialogFocus({
|
|
2449
|
+
host: this,
|
|
2450
|
+
container: () => this.renderRoot.querySelector(".drawer"),
|
|
2451
|
+
close: () => this.close()
|
|
2452
|
+
});
|
|
2250
2453
|
this.boundOnCartChange = (e) => {
|
|
2251
2454
|
const detail = e.detail;
|
|
2252
2455
|
this.carts = detail.cartsBySponsor;
|
|
@@ -2289,6 +2492,8 @@ var VioCart = class extends LitElement {
|
|
|
2289
2492
|
box-shadow: -8px 0 24px rgba(0, 0, 0, 0.06);
|
|
2290
2493
|
}
|
|
2291
2494
|
:host([open]) .drawer { transform: translateX(0); }
|
|
2495
|
+
/* Focus lands on the drawer itself only as a fallback — no ring for it. */
|
|
2496
|
+
.drawer:focus { outline: none; }
|
|
2292
2497
|
|
|
2293
2498
|
.handle { display: none; }
|
|
2294
2499
|
|
|
@@ -2301,7 +2506,7 @@ var VioCart = class extends LitElement {
|
|
|
2301
2506
|
bottom: 0;
|
|
2302
2507
|
width: 100%;
|
|
2303
2508
|
height: 88vh;
|
|
2304
|
-
border-radius: 16px 16px 0 0;
|
|
2509
|
+
border-radius: var(--vio-radius-xl, 16px) var(--vio-radius-xl, 16px) 0 0;
|
|
2305
2510
|
transform: translateY(100%);
|
|
2306
2511
|
box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.08);
|
|
2307
2512
|
}
|
|
@@ -2316,7 +2521,7 @@ var VioCart = class extends LitElement {
|
|
|
2316
2521
|
width: 40px;
|
|
2317
2522
|
height: 4px;
|
|
2318
2523
|
background: var(--vio-color-border, #e5e5e5);
|
|
2319
|
-
border-radius: 2px;
|
|
2524
|
+
border-radius: var(--vio-radius-sm, 2px);
|
|
2320
2525
|
}
|
|
2321
2526
|
}
|
|
2322
2527
|
|
|
@@ -2409,7 +2614,7 @@ var VioCart = class extends LitElement {
|
|
|
2409
2614
|
height: 24px;
|
|
2410
2615
|
border: 1px solid var(--vio-color-border, #e5e5e5);
|
|
2411
2616
|
background: #fff;
|
|
2412
|
-
border-radius: 2px;
|
|
2617
|
+
border-radius: var(--vio-radius-sm, 2px);
|
|
2413
2618
|
cursor: pointer;
|
|
2414
2619
|
font-size: 12px;
|
|
2415
2620
|
color: var(--vio-color-text, #0a0a0a);
|
|
@@ -2466,7 +2671,7 @@ var VioCart = class extends LitElement {
|
|
|
2466
2671
|
background: #000;
|
|
2467
2672
|
color: #fff;
|
|
2468
2673
|
border: none;
|
|
2469
|
-
border-radius: 8px;
|
|
2674
|
+
border-radius: var(--vio-radius-lg, 8px);
|
|
2470
2675
|
font-size: 19px;
|
|
2471
2676
|
font-weight: 500;
|
|
2472
2677
|
line-height: 1;
|
|
@@ -2488,7 +2693,7 @@ var VioCart = class extends LitElement {
|
|
|
2488
2693
|
background: #ffb3c7;
|
|
2489
2694
|
color: #0a0a0a;
|
|
2490
2695
|
border: none;
|
|
2491
|
-
border-radius: 8px;
|
|
2696
|
+
border-radius: var(--vio-radius-lg, 8px);
|
|
2492
2697
|
font-size: 16px;
|
|
2493
2698
|
font-weight: 600;
|
|
2494
2699
|
cursor: pointer;
|
|
@@ -2509,7 +2714,7 @@ var VioCart = class extends LitElement {
|
|
|
2509
2714
|
background: #ff5b24;
|
|
2510
2715
|
color: #fff;
|
|
2511
2716
|
border: none;
|
|
2512
|
-
border-radius: 8px;
|
|
2717
|
+
border-radius: var(--vio-radius-lg, 8px);
|
|
2513
2718
|
cursor: pointer;
|
|
2514
2719
|
display: flex;
|
|
2515
2720
|
align-items: center;
|
|
@@ -2533,7 +2738,7 @@ var VioCart = class extends LitElement {
|
|
|
2533
2738
|
background: #635bff;
|
|
2534
2739
|
color: #fff;
|
|
2535
2740
|
border: none;
|
|
2536
|
-
border-radius: 8px;
|
|
2741
|
+
border-radius: var(--vio-radius-lg, 8px);
|
|
2537
2742
|
font-size: 16px;
|
|
2538
2743
|
font-weight: 600;
|
|
2539
2744
|
cursor: pointer;
|
|
@@ -2671,6 +2876,7 @@ var VioCart = class extends LitElement {
|
|
|
2671
2876
|
return isMethodEnabled(this.availableMethods, ...names);
|
|
2672
2877
|
}
|
|
2673
2878
|
updated(changed) {
|
|
2879
|
+
if (changed.has("open")) this.dialogFocus.update(this.open);
|
|
2674
2880
|
if (changed.has("open") && this.open) {
|
|
2675
2881
|
this.confirmedOrder = null;
|
|
2676
2882
|
this.preparedTotal = -1;
|
|
@@ -2850,7 +3056,7 @@ var VioCart = class extends LitElement {
|
|
|
2850
3056
|
const sponsorCarts = [...this.carts.values()].filter((c) => c.items.length > 0);
|
|
2851
3057
|
return html`
|
|
2852
3058
|
<div class="backdrop" @click=${this.close}></div>
|
|
2853
|
-
<aside class="drawer" role="dialog" aria-label=${this.heading}>
|
|
3059
|
+
<aside class="drawer" role="dialog" aria-modal="true" aria-label=${this.heading} tabindex="-1">
|
|
2854
3060
|
<div class="handle" @click=${this.close} aria-hidden="true"></div>
|
|
2855
3061
|
<div class="header">
|
|
2856
3062
|
<h2 class="heading">${this.confirmedOrder ? "Takk!" : this.heading}</h2>
|
|
@@ -3044,6 +3250,38 @@ __decorateClass([
|
|
|
3044
3250
|
__decorateClass([
|
|
3045
3251
|
state()
|
|
3046
3252
|
], VioCart.prototype, "confirmedOrder", 2);
|
|
3253
|
+
|
|
3254
|
+
// src/ui/checkout-errors.ts
|
|
3255
|
+
var EMPTY_CART_MESSAGE = "Handlekurven er tom. Legg til et produkt og pr\xF8v igjen.";
|
|
3256
|
+
var CART_CHANGED_MESSAGE = "Handlekurven ble endret i en annen fane. Last siden p\xE5 nytt og pr\xF8v igjen.";
|
|
3257
|
+
var CART_PAID_MESSAGE = "Denne handlekurven er allerede betalt. Start en ny handlekurv.";
|
|
3258
|
+
var PAYMENT_START_FAILED_MESSAGE = "Betalingen kunne ikke startes. Pr\xF8v igjen, eller velg en annen betalingsm\xE5te.";
|
|
3259
|
+
var SHIPS_APART = "kan ikke sendes sammen";
|
|
3260
|
+
function friendlyPaymentError(raw, method) {
|
|
3261
|
+
const text = String(raw ?? "");
|
|
3262
|
+
const lower = text.toLowerCase();
|
|
3263
|
+
if (lower.includes("got 0") || lower.includes("amount must be a positive")) {
|
|
3264
|
+
return EMPTY_CART_MESSAGE;
|
|
3265
|
+
}
|
|
3266
|
+
if (lower.includes("replaced by a newer") || text.includes("CHECKOUT_SUPERSEDED")) {
|
|
3267
|
+
return CART_CHANGED_MESSAGE;
|
|
3268
|
+
}
|
|
3269
|
+
if (lower.includes("already been paid") || text.includes("CART_ALREADY_PAID")) {
|
|
3270
|
+
return CART_PAID_MESSAGE;
|
|
3271
|
+
}
|
|
3272
|
+
if (text.includes(SHIPS_APART)) return norwegianSentence(text);
|
|
3273
|
+
return PAYMENT_START_FAILED_MESSAGE;
|
|
3274
|
+
}
|
|
3275
|
+
function norwegianSentence(text) {
|
|
3276
|
+
const at = text.indexOf(SHIPS_APART);
|
|
3277
|
+
const prefixEnd = text.lastIndexOf(": ", at);
|
|
3278
|
+
return (prefixEnd === -1 ? text : text.slice(prefixEnd + 2)).trim();
|
|
3279
|
+
}
|
|
3280
|
+
function errorText(err) {
|
|
3281
|
+
return err instanceof Error ? err.message : String(err);
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
// src/ui/components/vio-checkout.ts
|
|
3047
3285
|
var STRIPE_LOGO_SRC3 = "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
3048
3286
|
'<svg width="360" height="150" viewBox="0 0 360 150" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M360 77.4001C360 51.8001 347.6 31.6001 323.9 31.6001C300.1 31.6001 285.7 51.8001 285.7 77.2001C285.7 107.3 302.7 122.5 327.1 122.5C339 122.5 348 119.8 354.8 116V96.0001C348 99.4001 340.2 101.5 330.3 101.5C320.6 101.5 312 98.1001 310.9 86.3001H359.8C359.8 85.0001 360 79.8001 360 77.4001ZM310.6 67.9001C310.6 56.6001 317.5 51.9001 323.8 51.9001C329.9 51.9001 336.4 56.6001 336.4 67.9001H310.6Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M247.1 31.6001C237.3 31.6001 231 36.2001 227.5 39.4001L226.2 33.2001H204.2V149.8L229.2 144.5L229.3 116.2C232.9 118.8 238.2 122.5 247 122.5C264.9 122.5 281.2 108.1 281.2 76.4001C281.1 47.4001 264.6 31.6001 247.1 31.6001ZM241.1 100.5C235.2 100.5 231.7 98.4001 229.3 95.8001L229.2 58.7001C231.8 55.8001 235.4 53.8001 241.1 53.8001C250.2 53.8001 256.5 64.0001 256.5 77.1001C256.5 90.5001 250.3 100.5 241.1 100.5Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M169.8 25.7L194.9 20.3V0L169.8 5.3V25.7Z" fill="#533AFD"/><path d="M194.9 33.3H169.8V120.8H194.9V33.3Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M142.9 40.7L141.3 33.3H119.7V120.8H144.7V61.5C150.6 53.8 160.6 55.2 163.7 56.3V33.3C160.5 32.1 148.8 29.9 142.9 40.7Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M92.8999 11.6001L68.4999 16.8001L68.3999 96.9001C68.3999 111.7 79.4999 122.6 94.2999 122.6C102.5 122.6 108.5 121.1 111.8 119.3V99.0001C108.6 100.3 92.7999 104.9 92.7999 90.1001V54.6001H111.8V33.3001H92.7999L92.8999 11.6001Z" fill="#533AFD"/><path fill-rule="evenodd" clip-rule="evenodd" d="M25.3 58.7001C25.3 54.8001 28.5 53.3001 33.8 53.3001C41.4 53.3001 51 55.6001 58.6 59.7001V36.2001C50.3 32.9001 42.1 31.6001 33.8 31.6001C13.5 31.6001 0 42.2001 0 59.9001C0 87.5001 38 83.1001 38 95.0001C38 99.6001 34 101.1 28.4 101.1C20.1 101.1 9.5 97.7001 1.1 93.1001V116.9C10.4 120.9 19.8 122.6 28.4 122.6C49.2 122.6 63.5 112.3 63.5 94.4001C63.4 64.6001 25.3 69.9001 25.3 58.7001Z" fill="#533AFD"/></svg>'
|
|
3049
3287
|
);
|
|
@@ -3155,6 +3393,16 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3155
3393
|
};
|
|
3156
3394
|
/** In-flight guard for loadAvailablePaymentMethods. */
|
|
3157
3395
|
this.loadingPaymentMethods = false;
|
|
3396
|
+
/**
|
|
3397
|
+
* Keyboard and focus while open: Escape closes — not while a payment is
|
|
3398
|
+
* in flight — Tab stays inside, focus returns to the opener.
|
|
3399
|
+
*/
|
|
3400
|
+
this.dialogFocus = new DialogFocus({
|
|
3401
|
+
host: this,
|
|
3402
|
+
container: () => this.renderRoot.querySelector(".modal"),
|
|
3403
|
+
close: () => this.close(),
|
|
3404
|
+
canClose: () => !this.paymentInFlight
|
|
3405
|
+
});
|
|
3158
3406
|
this.paymentMethodsResolved = false;
|
|
3159
3407
|
/** Guards `autoSelectSoleMethod` to ONE attempt per opening — see there. */
|
|
3160
3408
|
this.autoSelectAttempted = false;
|
|
@@ -3233,10 +3481,17 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3233
3481
|
};
|
|
3234
3482
|
this.boundOnPaymentError = (e) => {
|
|
3235
3483
|
const detail = e.detail;
|
|
3236
|
-
|
|
3484
|
+
if (typeof console !== "undefined") {
|
|
3485
|
+
console.warn("[VioCheckout] payment-error:", detail.method, detail.error);
|
|
3486
|
+
}
|
|
3487
|
+
this.paymentError = detail.method === "klarna" ? `Klarna-betalingen kunne ikke fullf\xF8res: ${detail.error}` : friendlyPaymentError(detail.error, detail.method);
|
|
3237
3488
|
this.open = true;
|
|
3238
3489
|
};
|
|
3239
3490
|
}
|
|
3491
|
+
/** A payment is being started or confirmed right now: the overlay must not close under it. */
|
|
3492
|
+
get paymentInFlight() {
|
|
3493
|
+
return this.stripePaying || this.stripeLoading || this.vippsLoading || this.klarnaAuthorizing || this.applePayInProgress;
|
|
3494
|
+
}
|
|
3240
3495
|
static {
|
|
3241
3496
|
this.styles = css`
|
|
3242
3497
|
:host { display: contents; }
|
|
@@ -3265,6 +3520,8 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3265
3520
|
overflow-y: auto;
|
|
3266
3521
|
}
|
|
3267
3522
|
:host([open]) .modal { transform: translateY(0); }
|
|
3523
|
+
/* Focus lands on the panel itself only as a fallback — no ring for it. */
|
|
3524
|
+
.modal:focus { outline: none; }
|
|
3268
3525
|
|
|
3269
3526
|
/* Confirmation drawer — compact bottom sheet, not the full-screen overlay. */
|
|
3270
3527
|
.modal.as-drawer {
|
|
@@ -3894,6 +4151,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3894
4151
|
const vippsStatus = await Vio.checkout.getVippsStatus(checkoutId, sponsorId || void 0);
|
|
3895
4152
|
const state6 = String(vippsStatus?.state ?? "").toUpperCase();
|
|
3896
4153
|
sawStatus = true;
|
|
4154
|
+
if (vippsStatus?.duplicate_of) return { outcome: "duplicate", sawStatus };
|
|
3897
4155
|
if (state6 === "AUTHORIZED") return { outcome: "paid", sawStatus };
|
|
3898
4156
|
if (state6 === "CREATED") continue;
|
|
3899
4157
|
return { outcome: "failed", sawStatus };
|
|
@@ -3926,6 +4184,9 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3926
4184
|
detail: { method: vioMethod, sponsorId, orderId: checkoutId }
|
|
3927
4185
|
})
|
|
3928
4186
|
);
|
|
4187
|
+
} else if (outcome === "duplicate") {
|
|
4188
|
+
this.paymentError = CART_PAID_MESSAGE;
|
|
4189
|
+
this.open = true;
|
|
3929
4190
|
} else if (outcome === "failed") {
|
|
3930
4191
|
this.paymentError = "Betalingen ble avbrutt eller feilet. Vennligst pr\xF8v igjen.";
|
|
3931
4192
|
this.open = true;
|
|
@@ -3996,7 +4257,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
3996
4257
|
this.verifyingReturn = null;
|
|
3997
4258
|
if (order?.status === "checkout_complete" && order.html_snippet) {
|
|
3998
4259
|
const spId = this.checkoutState?.sponsorId ?? 0;
|
|
3999
|
-
this.showProviderReceipt("kustom", spId, order);
|
|
4260
|
+
this.showProviderReceipt("kustom", spId, order, kustomReturn.checkoutId);
|
|
4000
4261
|
await this.updateComplete;
|
|
4001
4262
|
const container = this.lightContainer("vio-kustom-checkout-container", "vio-kustom");
|
|
4002
4263
|
Vio.checkout.renderKustomSnippet(container, order.html_snippet);
|
|
@@ -4042,12 +4303,12 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4042
4303
|
const result = { order: { orderId: order.order_id }, chargedTotal: order.total_price };
|
|
4043
4304
|
this.qliroMountedOrderId = order.order_id;
|
|
4044
4305
|
if (order.html_snippet) {
|
|
4045
|
-
this.showProviderReceipt("qliro", spId, result);
|
|
4306
|
+
this.showProviderReceipt("qliro", spId, result, checkoutId);
|
|
4046
4307
|
await this.updateComplete;
|
|
4047
4308
|
const container = this.lightContainer("vio-qliro-checkout-container", "vio-qliro");
|
|
4048
4309
|
Vio.checkout.renderKustomSnippet(container, order.html_snippet);
|
|
4049
4310
|
} else {
|
|
4050
|
-
this.confirmOrder("qliro", spId, result);
|
|
4311
|
+
this.confirmOrder("qliro", spId, result, checkoutId);
|
|
4051
4312
|
}
|
|
4052
4313
|
} else if (order?.html_snippet) {
|
|
4053
4314
|
this.qliroMountedOrderId = order.order_id;
|
|
@@ -4098,9 +4359,12 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4098
4359
|
Vio.checkout.renderKustomSnippet(container, order.html_snippet);
|
|
4099
4360
|
}
|
|
4100
4361
|
if (order.status === "PurchaseCompleted") {
|
|
4101
|
-
this.showProviderReceipt(
|
|
4102
|
-
|
|
4103
|
-
|
|
4362
|
+
this.showProviderReceipt(
|
|
4363
|
+
"walley",
|
|
4364
|
+
this.checkoutState?.sponsorId ?? 0,
|
|
4365
|
+
{ orderId: order.order_id },
|
|
4366
|
+
checkoutId
|
|
4367
|
+
);
|
|
4104
4368
|
}
|
|
4105
4369
|
}
|
|
4106
4370
|
} catch (err) {
|
|
@@ -4196,6 +4460,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4196
4460
|
const checkout = await Vio.checkout.getCheckout(checkoutId, sponsorId || void 0);
|
|
4197
4461
|
const status = String(checkout?.status ?? "").toLowerCase();
|
|
4198
4462
|
sawStatus = true;
|
|
4463
|
+
if (checkout?.duplicate_of) {
|
|
4464
|
+
outcome = "duplicate";
|
|
4465
|
+
break;
|
|
4466
|
+
}
|
|
4199
4467
|
if (_VioCheckout.FAILED_STATUSES.has(status)) {
|
|
4200
4468
|
outcome = "failed";
|
|
4201
4469
|
break;
|
|
@@ -4260,6 +4528,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4260
4528
|
super.disconnectedCallback();
|
|
4261
4529
|
}
|
|
4262
4530
|
updated(changed) {
|
|
4531
|
+
if (changed.has("open")) this.dialogFocus.update(this.open);
|
|
4263
4532
|
if (changed.has("open") && this.open && this.items.length > 0 && this.availableShippingsList.length === 0) {
|
|
4264
4533
|
void this.loadAvailableShippings();
|
|
4265
4534
|
}
|
|
@@ -4518,7 +4787,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4518
4787
|
if (typeof console !== "undefined") {
|
|
4519
4788
|
console.warn("[VioCheckout] Klarna Payments mount failed:", err);
|
|
4520
4789
|
}
|
|
4521
|
-
this.paymentError =
|
|
4790
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
4522
4791
|
} finally {
|
|
4523
4792
|
this.klarnaMounting = false;
|
|
4524
4793
|
}
|
|
@@ -4701,7 +4970,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4701
4970
|
}
|
|
4702
4971
|
this.stripeLoading = true;
|
|
4703
4972
|
void Vio.checkout.startStripePayment(this.checkoutState?.sponsorId, this.form).catch((err) => {
|
|
4704
|
-
|
|
4973
|
+
if (typeof console !== "undefined") {
|
|
4974
|
+
console.warn("[VioCheckout] Stripe payment could not start:", err);
|
|
4975
|
+
}
|
|
4976
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
4705
4977
|
}).finally(() => {
|
|
4706
4978
|
this.stripeLoading = false;
|
|
4707
4979
|
});
|
|
@@ -4709,7 +4981,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4709
4981
|
if (method === "vipps") {
|
|
4710
4982
|
this.vippsLoading = true;
|
|
4711
4983
|
void this.startVippsFromCheckout().catch((err) => {
|
|
4712
|
-
|
|
4984
|
+
if (typeof console !== "undefined") {
|
|
4985
|
+
console.warn("[VioCheckout] Vipps payment could not start:", err);
|
|
4986
|
+
}
|
|
4987
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
4713
4988
|
}).finally(() => {
|
|
4714
4989
|
this.vippsLoading = false;
|
|
4715
4990
|
});
|
|
@@ -4744,11 +5019,11 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4744
5019
|
* the confirmation screen, emits `vio:payment-success`, and clears the
|
|
4745
5020
|
* paid sponsor's cart so the badge + drawer reflect the purchase.
|
|
4746
5021
|
*/
|
|
4747
|
-
confirmOrder(method, sponsorId, result) {
|
|
5022
|
+
confirmOrder(method, sponsorId, result, returnCheckoutId) {
|
|
4748
5023
|
const r = result ?? {};
|
|
4749
5024
|
const shippingPrice = this.shippingMajor();
|
|
4750
5025
|
const email = String(this.form.email ?? "").trim();
|
|
4751
|
-
const checkoutId = this.checkoutState?.checkoutId;
|
|
5026
|
+
const checkoutId = returnCheckoutId || this.checkoutState?.checkoutId;
|
|
4752
5027
|
const providerOrderId = r.order?.orderId != null ? String(r.order.orderId) : "";
|
|
4753
5028
|
this.confirmedOrder = {
|
|
4754
5029
|
items: [...this.items],
|
|
@@ -4765,7 +5040,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4765
5040
|
new CustomEvent("vio:payment-success", {
|
|
4766
5041
|
bubbles: true,
|
|
4767
5042
|
composed: true,
|
|
4768
|
-
|
|
5043
|
+
// `checkoutId` is Vio's own reference for the purchase — what the
|
|
5044
|
+
// redirect path already sends as `orderId`; analytics falls back to it
|
|
5045
|
+
// when the provider's result carries no order id.
|
|
5046
|
+
detail: { method, sponsorId, result, checkoutId }
|
|
4769
5047
|
})
|
|
4770
5048
|
);
|
|
4771
5049
|
Vio.cart.clearSponsorCart(sponsorId);
|
|
@@ -4877,7 +5155,9 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4877
5155
|
<div
|
|
4878
5156
|
class="modal ${this.express ? "as-side" : this.orderConfirmed ? "as-confirm" : ""}"
|
|
4879
5157
|
role="dialog"
|
|
5158
|
+
aria-modal="true"
|
|
4880
5159
|
aria-label=${this.heading}
|
|
5160
|
+
tabindex="-1"
|
|
4881
5161
|
>
|
|
4882
5162
|
<div class="handle" @click=${this.close} aria-hidden="true"></div>
|
|
4883
5163
|
<div class="topbar">
|
|
@@ -4913,15 +5193,16 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
4913
5193
|
* sponsor's cart cleared — but the screen is the provider's receipt, not our
|
|
4914
5194
|
* "Takk!": two receipts for one purchase is one too many.
|
|
4915
5195
|
*/
|
|
4916
|
-
showProviderReceipt(method, sponsorId, result) {
|
|
5196
|
+
showProviderReceipt(method, sponsorId, result, returnCheckoutId) {
|
|
4917
5197
|
this.providerReceipt = method;
|
|
4918
5198
|
this.confirmedMethod = method;
|
|
4919
5199
|
this.open = true;
|
|
5200
|
+
const checkoutId = returnCheckoutId || this.checkoutState?.checkoutId;
|
|
4920
5201
|
this.dispatchEvent(
|
|
4921
5202
|
new CustomEvent("vio:payment-success", {
|
|
4922
5203
|
bubbles: true,
|
|
4923
5204
|
composed: true,
|
|
4924
|
-
detail: { method, sponsorId, result }
|
|
5205
|
+
detail: { method, sponsorId, result, checkoutId }
|
|
4925
5206
|
})
|
|
4926
5207
|
);
|
|
4927
5208
|
if (sponsorId) {
|
|
@@ -5090,7 +5371,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5090
5371
|
if (typeof console !== "undefined") {
|
|
5091
5372
|
console.warn("[VioCheckout] Kustom mount failed:", err);
|
|
5092
5373
|
}
|
|
5093
|
-
this.paymentError =
|
|
5374
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
5094
5375
|
Vio.checkout.selectPaymentMethod("");
|
|
5095
5376
|
} finally {
|
|
5096
5377
|
this.kustomMounting = false;
|
|
@@ -5210,7 +5491,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5210
5491
|
if (typeof console !== "undefined") {
|
|
5211
5492
|
console.warn("[VioCheckout] Qliro mount failed:", err);
|
|
5212
5493
|
}
|
|
5213
|
-
this.paymentError =
|
|
5494
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
5214
5495
|
Vio.checkout.selectPaymentMethod("");
|
|
5215
5496
|
} finally {
|
|
5216
5497
|
this.qliroMounting = false;
|
|
@@ -5267,7 +5548,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5267
5548
|
if (typeof console !== "undefined") {
|
|
5268
5549
|
console.warn("[VioCheckout] Walley mount failed:", err);
|
|
5269
5550
|
}
|
|
5270
|
-
this.paymentError =
|
|
5551
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
5271
5552
|
Vio.checkout.selectPaymentMethod("");
|
|
5272
5553
|
} finally {
|
|
5273
5554
|
this.walleyMounting = false;
|
|
@@ -5342,7 +5623,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5342
5623
|
if (typeof console !== "undefined") {
|
|
5343
5624
|
console.warn("[VioCheckout] Nexi mount failed:", err);
|
|
5344
5625
|
}
|
|
5345
|
-
this.paymentError =
|
|
5626
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
5346
5627
|
Vio.checkout.selectPaymentMethod("");
|
|
5347
5628
|
} finally {
|
|
5348
5629
|
this.nexiMounting = false;
|
|
@@ -5529,7 +5810,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5529
5810
|
this.adyenMountedKey = this.embedPurchaseKey();
|
|
5530
5811
|
} catch (err) {
|
|
5531
5812
|
this.unmountAdyen();
|
|
5532
|
-
this.paymentError = err instanceof AdyenOriginError ? "Betaling er ikke aktivert for denne siden enn\xE5. Ta kontakt med butikken." :
|
|
5813
|
+
this.paymentError = err instanceof AdyenOriginError ? "Betaling er ikke aktivert for denne siden enn\xE5. Ta kontakt med butikken." : friendlyPaymentError(errorText(err));
|
|
5533
5814
|
if (typeof console !== "undefined") console.warn("[VioCheckout] Adyen mount failed:", err);
|
|
5534
5815
|
} finally {
|
|
5535
5816
|
this.adyenMounting = false;
|
|
@@ -5639,7 +5920,10 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5639
5920
|
},
|
|
5640
5921
|
onLoadError: (message) => {
|
|
5641
5922
|
this.unmountStripe();
|
|
5642
|
-
|
|
5923
|
+
if (typeof console !== "undefined") {
|
|
5924
|
+
console.warn("[VioCheckout] Stripe Payment Element failed to load:", message);
|
|
5925
|
+
}
|
|
5926
|
+
this.paymentError = friendlyPaymentError(message, "stripe");
|
|
5643
5927
|
}
|
|
5644
5928
|
});
|
|
5645
5929
|
if (this.embedSession() !== mountedFor || this.checkoutState?.paymentMethod !== "stripe" || !this.open) {
|
|
@@ -5658,7 +5942,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5658
5942
|
this.stripeMountedKey = this.embedPurchaseKey();
|
|
5659
5943
|
} catch (err) {
|
|
5660
5944
|
this.unmountStripe();
|
|
5661
|
-
this.paymentError =
|
|
5945
|
+
this.paymentError = friendlyPaymentError(errorText(err));
|
|
5662
5946
|
if (typeof console !== "undefined") console.warn("[VioCheckout] Stripe mount failed:", err);
|
|
5663
5947
|
} finally {
|
|
5664
5948
|
this.stripeMounting = false;
|
|
@@ -5687,6 +5971,9 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5687
5971
|
const settled = checkoutId ? await this.waitForStripeOrder(checkoutId, spId) : "pending";
|
|
5688
5972
|
if (settled === "paid") {
|
|
5689
5973
|
this.confirmOrder("stripe", spId, { chargedTotal: charged });
|
|
5974
|
+
} else if (settled === "duplicate") {
|
|
5975
|
+
this.stripeSettled = false;
|
|
5976
|
+
this.paymentError = CART_PAID_MESSAGE;
|
|
5690
5977
|
} else if (settled === "failed") {
|
|
5691
5978
|
this.stripeSettled = false;
|
|
5692
5979
|
this.paymentError = "Betalingen ble avbrutt eller feilet. Vennligst pr\xF8v igjen.";
|
|
@@ -5712,6 +5999,7 @@ var _VioCheckout = class _VioCheckout extends LitElement {
|
|
|
5712
5999
|
try {
|
|
5713
6000
|
const checkout = await Vio.checkout.getCheckout(checkoutId, sponsorId || void 0);
|
|
5714
6001
|
const status = String(checkout?.status ?? "").toLowerCase();
|
|
6002
|
+
if (checkout?.duplicate_of) return "duplicate";
|
|
5715
6003
|
if (_VioCheckout.FAILED_STATUSES.has(status)) return "failed";
|
|
5716
6004
|
if (_VioCheckout.PAID_STATUSES.has(status)) return "paid";
|
|
5717
6005
|
} catch (err) {
|
|
@@ -6377,5 +6665,5 @@ function registerVioElements() {
|
|
|
6377
6665
|
}
|
|
6378
6666
|
|
|
6379
6667
|
export { VioCart, VioCheckout, VioProduct, VioProductCarousel, VioProductDetail, VioTokens, applyVioTheme, registerVioElements };
|
|
6380
|
-
//# sourceMappingURL=chunk-
|
|
6381
|
-
//# sourceMappingURL=chunk-
|
|
6668
|
+
//# sourceMappingURL=chunk-MRJR6DG5.js.map
|
|
6669
|
+
//# sourceMappingURL=chunk-MRJR6DG5.js.map
|