@nevios/storefront-kit 1.0.0 → 1.2.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 +78 -0
- package/dist/index.cjs +459 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +184 -3
- package/dist/index.d.ts +184 -3
- package/dist/index.js +451 -22
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -201,6 +201,37 @@ var en = {
|
|
|
201
201
|
"order.terminal.cancelled": "This order was cancelled.",
|
|
202
202
|
"order.terminal.refunded": "This order was refunded.",
|
|
203
203
|
"order.terminal.returned": "This order was returned.",
|
|
204
|
+
// payment page — the four situations it can be in
|
|
205
|
+
"payment.title": "Pay for order {order}",
|
|
206
|
+
"payment.amountDue": "Amount due",
|
|
207
|
+
"payment.methodLabel": "Payment method",
|
|
208
|
+
"payment.payNow": "Pay now",
|
|
209
|
+
"payment.finish": "Finish payment",
|
|
210
|
+
"payment.loading": "Loading payment\u2026",
|
|
211
|
+
"payment.loadError": "Couldn't load this payment.",
|
|
212
|
+
"payment.actionError": "That didn't go through. Please try again.",
|
|
213
|
+
// …paid
|
|
214
|
+
"payment.paidTitle": "Paid",
|
|
215
|
+
"payment.paidBody": "Order {order} is paid. Nothing further is needed.",
|
|
216
|
+
"payment.paidAmount": "Paid",
|
|
217
|
+
// …returning from a gateway, callback still in flight
|
|
218
|
+
"payment.verifyingTitle": "Checking your payment\u2026",
|
|
219
|
+
"payment.verifyingBody": "This takes a few seconds. Don't pay again \u2014 we'll update this page.",
|
|
220
|
+
// …locked, one sentence per reason
|
|
221
|
+
"payment.blockedTitle": "This order can't be paid",
|
|
222
|
+
"payment.blocked.orderCancelled": "This order was cancelled, so there is nothing to pay.",
|
|
223
|
+
"payment.blocked.alreadyPaid": "This order is already paid.",
|
|
224
|
+
"payment.blocked.authorizationHeld": "Your bank is holding the funds for this order. Once the payment settles this page will show it as paid.",
|
|
225
|
+
"payment.blocked.documentIssued": "An invoice has been issued for this order, so the amount is fixed. Contact us to change how you pay.",
|
|
226
|
+
// …bank transfer
|
|
227
|
+
"payment.account": "Account",
|
|
228
|
+
"payment.beneficiary": "Beneficiary",
|
|
229
|
+
"payment.variableSymbol": "Variable symbol",
|
|
230
|
+
"payment.amount": "Amount",
|
|
231
|
+
"payment.copy": "Copy",
|
|
232
|
+
"payment.copied": "Copied",
|
|
233
|
+
"payment.qrAlt": "QR code for the payment",
|
|
234
|
+
"payment.qrCaption": "Scan in your banking app",
|
|
204
235
|
// error pages
|
|
205
236
|
"error.notFound.title": "Page not found",
|
|
206
237
|
"error.notFound.body": "This page doesn't exist or isn't available in your region.",
|
|
@@ -357,6 +388,33 @@ var cs = {
|
|
|
357
388
|
"order.terminal.cancelled": "Tato objedn\xE1vka byla zru\u0161ena.",
|
|
358
389
|
"order.terminal.refunded": "Tato objedn\xE1vka byla refundov\xE1na.",
|
|
359
390
|
"order.terminal.returned": "Tato objedn\xE1vka byla vr\xE1cena.",
|
|
391
|
+
// platební stránka — čtyři situace, ve kterých může být
|
|
392
|
+
"payment.title": "Zaplatit objedn\xE1vku {order}",
|
|
393
|
+
"payment.amountDue": "K \xFAhrad\u011B",
|
|
394
|
+
"payment.methodLabel": "Zp\u016Fsob platby",
|
|
395
|
+
"payment.payNow": "Zaplatit",
|
|
396
|
+
"payment.finish": "Dokon\u010Dit platbu",
|
|
397
|
+
"payment.loading": "Na\u010D\xEDt\xE1n\xED platby\u2026",
|
|
398
|
+
"payment.loadError": "Platbu se nepoda\u0159ilo na\u010D\xEDst.",
|
|
399
|
+
"payment.actionError": "Nepovedlo se to. Zkuste to pros\xEDm znovu.",
|
|
400
|
+
"payment.paidTitle": "Zaplaceno",
|
|
401
|
+
"payment.paidBody": "Objedn\xE1vka {order} je zaplacen\xE1. Nic dal\u0161\xEDho d\u011Blat nemus\xEDte.",
|
|
402
|
+
"payment.paidAmount": "Uhrazeno",
|
|
403
|
+
"payment.verifyingTitle": "Ov\u011B\u0159ujeme platbu\u2026",
|
|
404
|
+
"payment.verifyingBody": "Chvilku to trv\xE1. Nepla\u0165te pros\xEDm znovu \u2014 str\xE1nka se sama aktualizuje.",
|
|
405
|
+
"payment.blockedTitle": "Tuhle objedn\xE1vku te\u010F zaplatit nejde",
|
|
406
|
+
"payment.blocked.orderCancelled": "Objedn\xE1vka byla zru\u0161en\xE1, tak\u017Ee nen\xED co platit.",
|
|
407
|
+
"payment.blocked.alreadyPaid": "Objedn\xE1vka je u\u017E zaplacen\xE1.",
|
|
408
|
+
"payment.blocked.authorizationHeld": "Banka na tuhle objedn\xE1vku dr\u017E\xED pen\xEDze. Jakmile se platba dokon\u010D\xED, uvid\xEDte to tady.",
|
|
409
|
+
"payment.blocked.documentIssued": "K objedn\xE1vce je vystaven\xE1 faktura, tak\u017Ee je \u010D\xE1stka pevn\xE1. Pokud chcete platit jinak, ozv\u011Bte se n\xE1m.",
|
|
410
|
+
"payment.account": "\xDA\u010Det",
|
|
411
|
+
"payment.beneficiary": "P\u0159\xEDjemce",
|
|
412
|
+
"payment.variableSymbol": "Variabiln\xED symbol",
|
|
413
|
+
"payment.amount": "\u010C\xE1stka",
|
|
414
|
+
"payment.copy": "Kop\xEDrovat",
|
|
415
|
+
"payment.copied": "Zkop\xEDrov\xE1no",
|
|
416
|
+
"payment.qrAlt": "QR k\xF3d k platb\u011B",
|
|
417
|
+
"payment.qrCaption": "Na\u010Dt\u011Bte v bankovn\xED aplikaci",
|
|
360
418
|
"error.notFound.title": "Str\xE1nka nenalezena",
|
|
361
419
|
"error.notFound.body": "Tato str\xE1nka neexistuje nebo nen\xED ve va\u0161em regionu dostupn\xE1.",
|
|
362
420
|
"error.generic.title": "N\u011Bco se pokazilo",
|
|
@@ -1164,6 +1222,7 @@ function AddToCart({
|
|
|
1164
1222
|
}
|
|
1165
1223
|
function CartLineItem({ line, locale }) {
|
|
1166
1224
|
const t = useT();
|
|
1225
|
+
const loc = useFormatLocale(locale);
|
|
1167
1226
|
const { updateLine, removeLine } = useCart();
|
|
1168
1227
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.85rem", alignItems: "flex-start", padding: "0.75rem 0" }, children: [
|
|
1169
1228
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1235,7 +1294,7 @@ function CartLineItem({ line, locale }) {
|
|
|
1235
1294
|
)
|
|
1236
1295
|
] })
|
|
1237
1296
|
] }),
|
|
1238
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500, whiteSpace: "nowrap" }, children: formatCents(line.line_total_cents, line.unit_price.currency,
|
|
1297
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 500, whiteSpace: "nowrap" }, children: formatCents(line.line_total_cents, line.unit_price.currency, loc) })
|
|
1239
1298
|
] });
|
|
1240
1299
|
}
|
|
1241
1300
|
function StepBtn({ label, onClick }) {
|
|
@@ -1267,6 +1326,7 @@ function CartSummary({
|
|
|
1267
1326
|
locale
|
|
1268
1327
|
}) {
|
|
1269
1328
|
const tr = useT();
|
|
1329
|
+
const loc = useFormatLocale(locale);
|
|
1270
1330
|
const { cart } = useCart();
|
|
1271
1331
|
if (cart == null) return null;
|
|
1272
1332
|
const t = cart.totals;
|
|
@@ -1287,10 +1347,10 @@ function CartSummary({
|
|
|
1287
1347
|
opacity: empty ? 0.55 : 1
|
|
1288
1348
|
};
|
|
1289
1349
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
1290
|
-
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.subtotal"), value: formatCents(t.subtotal_with_tax_cents, t.currency,
|
|
1291
|
-
t.tax_cents > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.tax"), value: formatCents(t.tax_cents, t.currency,
|
|
1350
|
+
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.subtotal"), value: formatCents(t.subtotal_with_tax_cents, t.currency, loc) }),
|
|
1351
|
+
t.tax_cents > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.tax"), value: formatCents(t.tax_cents, t.currency, loc), muted: true }) : null,
|
|
1292
1352
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: 1, background: "var(--nv-border)" } }),
|
|
1293
|
-
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.total"), value: formatCents(t.total_cents, t.currency,
|
|
1353
|
+
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: tr("cart.total"), value: formatCents(t.total_cents, t.currency, loc), strong: true }),
|
|
1294
1354
|
checkoutHref && !empty ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: checkoutHref, style: ctaStyle, children: cta }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: empty, onClick: onCheckout, style: ctaStyle, children: cta })
|
|
1295
1355
|
] });
|
|
1296
1356
|
}
|
|
@@ -1693,6 +1753,7 @@ function ShippingPicker({
|
|
|
1693
1753
|
locale
|
|
1694
1754
|
}) {
|
|
1695
1755
|
const t = useT();
|
|
1756
|
+
const loc = useFormatLocale(locale);
|
|
1696
1757
|
const { checkout, shippingQuotes, setShippingMethod, loading } = useCheckout();
|
|
1697
1758
|
const heading = title ?? t("checkout.shippingMethod");
|
|
1698
1759
|
const [quotes, setQuotes] = React10__namespace.useState(null);
|
|
@@ -1733,7 +1794,7 @@ function ShippingPicker({
|
|
|
1733
1794
|
{
|
|
1734
1795
|
selected: selected === q.rate_id,
|
|
1735
1796
|
onSelect: () => setSelected(q.rate_id),
|
|
1736
|
-
trailing: q.is_free ? t("common.free") : formatCents(q.price_cents, q.currency,
|
|
1797
|
+
trailing: q.is_free ? t("common.free") : formatCents(q.price_cents, q.currency, loc),
|
|
1737
1798
|
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", flexDirection: "column" }, children: [
|
|
1738
1799
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: q.label }),
|
|
1739
1800
|
days ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: days }) : null
|
|
@@ -1754,6 +1815,39 @@ function estDays(q, t) {
|
|
|
1754
1815
|
const n = lo ?? hi;
|
|
1755
1816
|
return t("shipping.days", { count: n });
|
|
1756
1817
|
}
|
|
1818
|
+
function PaymentMethodPicker({
|
|
1819
|
+
methods,
|
|
1820
|
+
value,
|
|
1821
|
+
onSelect,
|
|
1822
|
+
currency,
|
|
1823
|
+
locale,
|
|
1824
|
+
disabled,
|
|
1825
|
+
label
|
|
1826
|
+
}) {
|
|
1827
|
+
const loc = useFormatLocale(locale);
|
|
1828
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1829
|
+
"div",
|
|
1830
|
+
{
|
|
1831
|
+
role: "radiogroup",
|
|
1832
|
+
"aria-label": label,
|
|
1833
|
+
style: { display: "flex", flexDirection: "column", gap: "0.6rem" },
|
|
1834
|
+
children: methods.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1835
|
+
SelectRow,
|
|
1836
|
+
{
|
|
1837
|
+
selected: value === m.method,
|
|
1838
|
+
disabled,
|
|
1839
|
+
onSelect: () => onSelect(m.method),
|
|
1840
|
+
trailing: m.surcharge_cents > 0 ? `+${formatCents(m.surcharge_cents, currency, loc)}` : void 0,
|
|
1841
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", flexDirection: "column" }, children: [
|
|
1842
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: m.display_label }),
|
|
1843
|
+
m.display_description ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: m.display_description }) : null
|
|
1844
|
+
] })
|
|
1845
|
+
},
|
|
1846
|
+
m.method
|
|
1847
|
+
))
|
|
1848
|
+
}
|
|
1849
|
+
);
|
|
1850
|
+
}
|
|
1757
1851
|
function PaymentSection({
|
|
1758
1852
|
title,
|
|
1759
1853
|
returnUrl,
|
|
@@ -1794,19 +1888,17 @@ function PaymentSection({
|
|
|
1794
1888
|
return /* @__PURE__ */ jsxRuntime.jsx(Section, { title: heading, children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("checkout.noPayment") }) });
|
|
1795
1889
|
}
|
|
1796
1890
|
return /* @__PURE__ */ jsxRuntime.jsxs(Section, { title: heading, children: [
|
|
1797
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1798
|
-
|
|
1891
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1892
|
+
PaymentMethodPicker,
|
|
1799
1893
|
{
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
m.method
|
|
1809
|
-
)) }),
|
|
1894
|
+
methods,
|
|
1895
|
+
value: selected,
|
|
1896
|
+
onSelect: (method) => void setPaymentMethod(method),
|
|
1897
|
+
currency: checkout?.totals.currency ?? "CZK",
|
|
1898
|
+
locale,
|
|
1899
|
+
label: heading
|
|
1900
|
+
}
|
|
1901
|
+
),
|
|
1810
1902
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1811
1903
|
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: placeOrder, busy: loading, disabled: selected == null, children: isGateway ? t("checkout.payNow") : t("checkout.placeOrder") }),
|
|
1812
1904
|
isGateway ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)", marginTop: "0.6rem" }, children: t("checkout.gatewayRedirectNote") }) : null
|
|
@@ -1819,12 +1911,13 @@ function OrderSummary({
|
|
|
1819
1911
|
locale
|
|
1820
1912
|
}) {
|
|
1821
1913
|
const tr = useT();
|
|
1914
|
+
const loc = useFormatLocale(locale);
|
|
1822
1915
|
const ctx = useCheckout();
|
|
1823
1916
|
const checkout = override ?? ctx.checkout;
|
|
1824
1917
|
if (checkout == null) return null;
|
|
1825
1918
|
const t = checkout.totals;
|
|
1826
1919
|
const c = t.currency;
|
|
1827
|
-
const money = (cents) => formatCents(cents, c,
|
|
1920
|
+
const money = (cents) => formatCents(cents, c, loc);
|
|
1828
1921
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
|
|
1829
1922
|
!totalsOnly && checkout.line_items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.75rem" }, children: checkout.line_items.map((li) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
|
|
1830
1923
|
li.image_url ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2056,6 +2149,79 @@ function useOrderStatus(statusToken, initial) {
|
|
|
2056
2149
|
}, [load, initial]);
|
|
2057
2150
|
return { order, loading, error, reload: () => void load() };
|
|
2058
2151
|
}
|
|
2152
|
+
function usePayment(token, initial) {
|
|
2153
|
+
const client = useStorefront();
|
|
2154
|
+
const [payment, setPayment] = React10__namespace.useState(initial ?? null);
|
|
2155
|
+
const [methods, setMethods] = React10__namespace.useState([]);
|
|
2156
|
+
const [loading, setLoading] = React10__namespace.useState(false);
|
|
2157
|
+
const [busy, setBusy] = React10__namespace.useState(false);
|
|
2158
|
+
const [error, setError] = React10__namespace.useState(null);
|
|
2159
|
+
const load = React10__namespace.useCallback(async () => {
|
|
2160
|
+
if (!token) return;
|
|
2161
|
+
setLoading(true);
|
|
2162
|
+
try {
|
|
2163
|
+
const [state, list] = await Promise.all([
|
|
2164
|
+
client.payment.get(token),
|
|
2165
|
+
client.payment.methods(token)
|
|
2166
|
+
]);
|
|
2167
|
+
setPayment(state);
|
|
2168
|
+
setMethods(list);
|
|
2169
|
+
setError(null);
|
|
2170
|
+
} catch (e) {
|
|
2171
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
2172
|
+
} finally {
|
|
2173
|
+
setLoading(false);
|
|
2174
|
+
}
|
|
2175
|
+
}, [client, token]);
|
|
2176
|
+
React10__namespace.useEffect(() => {
|
|
2177
|
+
if (!token) return;
|
|
2178
|
+
if (initial && initial.token === token) {
|
|
2179
|
+
setPayment(initial);
|
|
2180
|
+
client.payment.methods(token).then(setMethods).catch(() => setMethods([]));
|
|
2181
|
+
return;
|
|
2182
|
+
}
|
|
2183
|
+
void load();
|
|
2184
|
+
}, [token, load]);
|
|
2185
|
+
const selectMethod = React10__namespace.useCallback(
|
|
2186
|
+
async (method) => {
|
|
2187
|
+
if (!token) return null;
|
|
2188
|
+
setBusy(true);
|
|
2189
|
+
try {
|
|
2190
|
+
const next = await client.payment.selectMethod(token, method);
|
|
2191
|
+
setPayment(next);
|
|
2192
|
+
setError(null);
|
|
2193
|
+
return next;
|
|
2194
|
+
} catch (e) {
|
|
2195
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
2196
|
+
return null;
|
|
2197
|
+
} finally {
|
|
2198
|
+
setBusy(false);
|
|
2199
|
+
}
|
|
2200
|
+
},
|
|
2201
|
+
[client, token]
|
|
2202
|
+
);
|
|
2203
|
+
const startPayment = React10__namespace.useCallback(
|
|
2204
|
+
async (input) => {
|
|
2205
|
+
if (!token) return null;
|
|
2206
|
+
setBusy(true);
|
|
2207
|
+
try {
|
|
2208
|
+
const result = await client.payment.start(token, {
|
|
2209
|
+
return_url: input?.returnUrl,
|
|
2210
|
+
cancel_url: input?.cancelUrl
|
|
2211
|
+
});
|
|
2212
|
+
setError(null);
|
|
2213
|
+
return result.redirect_url;
|
|
2214
|
+
} catch (e) {
|
|
2215
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
2216
|
+
return null;
|
|
2217
|
+
} finally {
|
|
2218
|
+
setBusy(false);
|
|
2219
|
+
}
|
|
2220
|
+
},
|
|
2221
|
+
[client, token]
|
|
2222
|
+
);
|
|
2223
|
+
return { payment, methods, loading, busy, error, reload: load, selectMethod, startPayment };
|
|
2224
|
+
}
|
|
2059
2225
|
var PHASE_RANK = {
|
|
2060
2226
|
placed: 0,
|
|
2061
2227
|
paid: 1,
|
|
@@ -2151,6 +2317,7 @@ function OrderLines({
|
|
|
2151
2317
|
order,
|
|
2152
2318
|
locale
|
|
2153
2319
|
}) {
|
|
2320
|
+
const loc = useFormatLocale(locale);
|
|
2154
2321
|
return /* @__PURE__ */ jsxRuntime.jsxs("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
2155
2322
|
order.line_items.map((li) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
|
|
2156
2323
|
li.image_url ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2171,11 +2338,11 @@ function OrderLines({
|
|
|
2171
2338
|
li.quantity
|
|
2172
2339
|
] })
|
|
2173
2340
|
] }),
|
|
2174
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(li.total_with_tax_cents, order.currency,
|
|
2341
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(li.total_with_tax_cents, order.currency, loc) })
|
|
2175
2342
|
] }, li.id)),
|
|
2176
2343
|
order.fee_lines.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
|
|
2177
2344
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "block", fontWeight: 500 }, children: f.title }) }),
|
|
2178
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(f.total_with_tax_cents, order.currency,
|
|
2345
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(f.total_with_tax_cents, order.currency, loc) })
|
|
2179
2346
|
] }, `fee-${i}`))
|
|
2180
2347
|
] });
|
|
2181
2348
|
}
|
|
@@ -2184,9 +2351,10 @@ function OrderTotals({
|
|
|
2184
2351
|
locale
|
|
2185
2352
|
}) {
|
|
2186
2353
|
const tr = useT();
|
|
2354
|
+
const loc = useFormatLocale(locale);
|
|
2187
2355
|
const t = order.totals;
|
|
2188
2356
|
const c = order.currency;
|
|
2189
|
-
const money = (cents) => formatCents(cents, c,
|
|
2357
|
+
const money = (cents) => formatCents(cents, c, loc);
|
|
2190
2358
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2191
2359
|
/* @__PURE__ */ jsxRuntime.jsx(Row3, { label: tr("totals.subtotal"), value: money(t.subtotal_cents) }),
|
|
2192
2360
|
t.discount_cents > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Row3, { label: tr("totals.discount"), value: `\u2212${money(t.discount_cents)}`, muted: true }) : null,
|
|
@@ -2292,6 +2460,7 @@ function OrderStatusPage({
|
|
|
2292
2460
|
statusToken,
|
|
2293
2461
|
order: initial,
|
|
2294
2462
|
onContactSupport,
|
|
2463
|
+
payHref,
|
|
2295
2464
|
locale
|
|
2296
2465
|
}) {
|
|
2297
2466
|
const t = useT();
|
|
@@ -2343,6 +2512,7 @@ function OrderStatusPage({
|
|
|
2343
2512
|
/* @__PURE__ */ jsxRuntime.jsxs(Card, { title: t("order.payment"), children: [
|
|
2344
2513
|
/* @__PURE__ */ jsxRuntime.jsx(Line, { label: t("order.method"), value: order.payment.method ?? "\u2014" }),
|
|
2345
2514
|
/* @__PURE__ */ jsxRuntime.jsx(Line, { label: t("order.status"), value: order.payment.status }),
|
|
2515
|
+
order.payment.token && payHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: payHref(order.payment.token), style: { color: "var(--nv-brand)", fontWeight: 500 }, children: t("payment.finish") }) : null,
|
|
2346
2516
|
order.payment.invoice_available && order.payment.invoice_url ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: order.payment.invoice_url, style: { color: "var(--nv-brand)" }, children: t("order.downloadInvoice") }) : null
|
|
2347
2517
|
] }),
|
|
2348
2518
|
order.actions.can_contact_support && onContactSupport ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2394,6 +2564,265 @@ function Line({ label, value }) {
|
|
|
2394
2564
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { textAlign: "right" }, children: value })
|
|
2395
2565
|
] });
|
|
2396
2566
|
}
|
|
2567
|
+
function TransferInstructions({
|
|
2568
|
+
instructions: i,
|
|
2569
|
+
locale
|
|
2570
|
+
}) {
|
|
2571
|
+
const t = useT();
|
|
2572
|
+
const loc = useFormatLocale(locale);
|
|
2573
|
+
const account = i.iban || i.account_number;
|
|
2574
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2575
|
+
"div",
|
|
2576
|
+
{
|
|
2577
|
+
style: {
|
|
2578
|
+
display: "flex",
|
|
2579
|
+
flexWrap: "wrap",
|
|
2580
|
+
gap: "1.25rem",
|
|
2581
|
+
alignItems: "flex-start",
|
|
2582
|
+
padding: "1rem",
|
|
2583
|
+
borderRadius: "var(--nv-radius)",
|
|
2584
|
+
border: "1px solid var(--nv-border)"
|
|
2585
|
+
},
|
|
2586
|
+
children: [
|
|
2587
|
+
/* @__PURE__ */ jsxRuntime.jsxs("dl", { style: { flex: "1 1 15rem", margin: 0, display: "flex", flexDirection: "column", gap: "0.7rem" }, children: [
|
|
2588
|
+
account ? /* @__PURE__ */ jsxRuntime.jsx(CopyRow, { label: t("payment.account"), value: account }) : null,
|
|
2589
|
+
i.beneficiary_name ? /* @__PURE__ */ jsxRuntime.jsx(Row4, { label: t("payment.beneficiary"), value: i.beneficiary_name }) : null,
|
|
2590
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyRow, { label: t("payment.variableSymbol"), value: i.variable_symbol }),
|
|
2591
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2592
|
+
Row4,
|
|
2593
|
+
{
|
|
2594
|
+
label: t("payment.amount"),
|
|
2595
|
+
value: formatCents(i.amount_cents, i.currency, loc),
|
|
2596
|
+
strong: true
|
|
2597
|
+
}
|
|
2598
|
+
)
|
|
2599
|
+
] }),
|
|
2600
|
+
i.qr_svg_data_uri ? /* @__PURE__ */ jsxRuntime.jsxs("figure", { style: { margin: 0, textAlign: "center" }, children: [
|
|
2601
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2602
|
+
"img",
|
|
2603
|
+
{
|
|
2604
|
+
src: i.qr_svg_data_uri,
|
|
2605
|
+
alt: t("payment.qrAlt"),
|
|
2606
|
+
width: 148,
|
|
2607
|
+
height: 148,
|
|
2608
|
+
style: { display: "block", borderRadius: "var(--nv-radius)" }
|
|
2609
|
+
}
|
|
2610
|
+
),
|
|
2611
|
+
/* @__PURE__ */ jsxRuntime.jsx("figcaption", { style: { fontSize: "0.75rem", color: "var(--nv-muted)", marginTop: "0.4rem" }, children: t("payment.qrCaption") })
|
|
2612
|
+
] }) : null,
|
|
2613
|
+
i.instructions ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { flexBasis: "100%", margin: 0, fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: i.instructions }) : null
|
|
2614
|
+
]
|
|
2615
|
+
}
|
|
2616
|
+
);
|
|
2617
|
+
}
|
|
2618
|
+
function Row4({
|
|
2619
|
+
label,
|
|
2620
|
+
value,
|
|
2621
|
+
strong
|
|
2622
|
+
}) {
|
|
2623
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.1rem" }, children: [
|
|
2624
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { style: { fontSize: "0.75rem", color: "var(--nv-muted)" }, children: label }),
|
|
2625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2626
|
+
"dd",
|
|
2627
|
+
{
|
|
2628
|
+
style: {
|
|
2629
|
+
margin: 0,
|
|
2630
|
+
fontWeight: strong ? 600 : 500,
|
|
2631
|
+
fontVariantNumeric: "tabular-nums"
|
|
2632
|
+
},
|
|
2633
|
+
children: value
|
|
2634
|
+
}
|
|
2635
|
+
)
|
|
2636
|
+
] });
|
|
2637
|
+
}
|
|
2638
|
+
function CopyRow({ label, value }) {
|
|
2639
|
+
const t = useT();
|
|
2640
|
+
const [copied, setCopied] = React10__namespace.useState(false);
|
|
2641
|
+
React10__namespace.useEffect(() => {
|
|
2642
|
+
if (!copied) return;
|
|
2643
|
+
const id = setTimeout(() => setCopied(false), 1800);
|
|
2644
|
+
return () => clearTimeout(id);
|
|
2645
|
+
}, [copied]);
|
|
2646
|
+
async function copy() {
|
|
2647
|
+
try {
|
|
2648
|
+
await navigator.clipboard.writeText(value);
|
|
2649
|
+
setCopied(true);
|
|
2650
|
+
} catch {
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.1rem" }, children: [
|
|
2654
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { style: { fontSize: "0.75rem", color: "var(--nv-muted)" }, children: label }),
|
|
2655
|
+
/* @__PURE__ */ jsxRuntime.jsxs("dd", { style: { margin: 0, display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
2656
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, fontVariantNumeric: "tabular-nums" }, children: value }),
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2658
|
+
"button",
|
|
2659
|
+
{
|
|
2660
|
+
type: "button",
|
|
2661
|
+
onClick: () => void copy(),
|
|
2662
|
+
style: {
|
|
2663
|
+
font: "inherit",
|
|
2664
|
+
fontSize: "0.75rem",
|
|
2665
|
+
cursor: "pointer",
|
|
2666
|
+
padding: "0.15rem 0.5rem",
|
|
2667
|
+
borderRadius: "var(--nv-radius)",
|
|
2668
|
+
border: "1px solid var(--nv-border)",
|
|
2669
|
+
background: "transparent",
|
|
2670
|
+
color: "var(--nv-muted)"
|
|
2671
|
+
},
|
|
2672
|
+
children: copied ? t("payment.copied") : t("payment.copy")
|
|
2673
|
+
}
|
|
2674
|
+
)
|
|
2675
|
+
] })
|
|
2676
|
+
] });
|
|
2677
|
+
}
|
|
2678
|
+
var HANDOFF_TTL_MS = 30 * 60 * 1e3;
|
|
2679
|
+
var POLL_MS = 2e3;
|
|
2680
|
+
var POLL_ATTEMPTS = 6;
|
|
2681
|
+
var BLOCKED_MESSAGE = {
|
|
2682
|
+
order_cancelled: "payment.blocked.orderCancelled",
|
|
2683
|
+
already_paid: "payment.blocked.alreadyPaid",
|
|
2684
|
+
authorization_held: "payment.blocked.authorizationHeld",
|
|
2685
|
+
document_issued: "payment.blocked.documentIssued"
|
|
2686
|
+
};
|
|
2687
|
+
function handoffKey(token) {
|
|
2688
|
+
return `nv_payment_handoff_${token}`;
|
|
2689
|
+
}
|
|
2690
|
+
function rememberHandoff(token) {
|
|
2691
|
+
try {
|
|
2692
|
+
sessionStorage.setItem(handoffKey(token), String(Date.now()));
|
|
2693
|
+
} catch {
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
function consumeHandoff(token) {
|
|
2697
|
+
try {
|
|
2698
|
+
const raw = sessionStorage.getItem(handoffKey(token));
|
|
2699
|
+
if (!raw) return false;
|
|
2700
|
+
const fresh = Date.now() - Number(raw) < HANDOFF_TTL_MS;
|
|
2701
|
+
if (!fresh) sessionStorage.removeItem(handoffKey(token));
|
|
2702
|
+
return fresh;
|
|
2703
|
+
} catch {
|
|
2704
|
+
return false;
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
function forgetHandoff(token) {
|
|
2708
|
+
try {
|
|
2709
|
+
sessionStorage.removeItem(handoffKey(token));
|
|
2710
|
+
} catch {
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
function PaymentPage({
|
|
2714
|
+
token,
|
|
2715
|
+
payment: initial,
|
|
2716
|
+
returnUrl,
|
|
2717
|
+
cancelUrl,
|
|
2718
|
+
statusHref,
|
|
2719
|
+
locale,
|
|
2720
|
+
onPaid
|
|
2721
|
+
}) {
|
|
2722
|
+
const t = useT();
|
|
2723
|
+
const loc = useFormatLocale(locale);
|
|
2724
|
+
const { payment, methods, loading, busy, error, reload, selectMethod, startPayment } = usePayment(token, initial);
|
|
2725
|
+
const [verifying, setVerifying] = React10__namespace.useState(false);
|
|
2726
|
+
React10__namespace.useEffect(() => {
|
|
2727
|
+
if (token) setVerifying(consumeHandoff(token));
|
|
2728
|
+
}, [token]);
|
|
2729
|
+
const settled = payment != null && !payment.can_pay && payment.blocked_reason === "already_paid";
|
|
2730
|
+
React10__namespace.useEffect(() => {
|
|
2731
|
+
if (!verifying || !token || settled) return;
|
|
2732
|
+
let attempts = 0;
|
|
2733
|
+
const id = setInterval(() => {
|
|
2734
|
+
attempts += 1;
|
|
2735
|
+
if (attempts > POLL_ATTEMPTS) {
|
|
2736
|
+
setVerifying(false);
|
|
2737
|
+
forgetHandoff(token);
|
|
2738
|
+
clearInterval(id);
|
|
2739
|
+
return;
|
|
2740
|
+
}
|
|
2741
|
+
void reload();
|
|
2742
|
+
}, POLL_MS);
|
|
2743
|
+
return () => clearInterval(id);
|
|
2744
|
+
}, [verifying, token, settled, reload]);
|
|
2745
|
+
React10__namespace.useEffect(() => {
|
|
2746
|
+
if (!settled || !token || !payment) return;
|
|
2747
|
+
setVerifying(false);
|
|
2748
|
+
forgetHandoff(token);
|
|
2749
|
+
onPaid?.(payment);
|
|
2750
|
+
}, [settled, token, payment, onPaid]);
|
|
2751
|
+
if (!token) return null;
|
|
2752
|
+
if (payment == null) {
|
|
2753
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Shell2, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "var(--nv-muted)" }, children: loading ? t("payment.loading") : t("payment.loadError") }) });
|
|
2754
|
+
}
|
|
2755
|
+
const money = (cents) => formatCents(cents, payment.currency, loc);
|
|
2756
|
+
if (settled) {
|
|
2757
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Shell2, { title: t("payment.paidTitle"), children: [
|
|
2758
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0 }, children: t("payment.paidBody", { order: payment.order_name ?? payment.order_number }) }),
|
|
2759
|
+
/* @__PURE__ */ jsxRuntime.jsx(Amount, { label: t("payment.paidAmount"), value: money(payment.total_cents) }),
|
|
2760
|
+
statusHref ? /* @__PURE__ */ jsxRuntime.jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
|
|
2761
|
+
] });
|
|
2762
|
+
}
|
|
2763
|
+
if (payment.blocked_reason) {
|
|
2764
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Shell2, { title: t("payment.blockedTitle"), children: [
|
|
2765
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0 }, children: t(BLOCKED_MESSAGE[payment.blocked_reason]) }),
|
|
2766
|
+
statusHref ? /* @__PURE__ */ jsxRuntime.jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
|
|
2767
|
+
] });
|
|
2768
|
+
}
|
|
2769
|
+
if (verifying) {
|
|
2770
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Shell2, { title: t("payment.verifyingTitle"), children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "var(--nv-muted)" }, children: t("payment.verifyingBody") }) });
|
|
2771
|
+
}
|
|
2772
|
+
const isBank = payment.category === "bank";
|
|
2773
|
+
const isGateway = payment.category === "gateway";
|
|
2774
|
+
async function pay() {
|
|
2775
|
+
if (!token) return;
|
|
2776
|
+
rememberHandoff(token);
|
|
2777
|
+
const url = await startPayment({ returnUrl, cancelUrl });
|
|
2778
|
+
if (url) {
|
|
2779
|
+
window.location.assign(url);
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
forgetHandoff(token);
|
|
2783
|
+
await reload();
|
|
2784
|
+
}
|
|
2785
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Shell2, { title: t("payment.title", { order: payment.order_name ?? payment.order_number }), children: [
|
|
2786
|
+
/* @__PURE__ */ jsxRuntime.jsx(Amount, { label: t("payment.amountDue"), value: money(payment.amount_due_cents) }),
|
|
2787
|
+
methods.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2788
|
+
PaymentMethodPicker,
|
|
2789
|
+
{
|
|
2790
|
+
methods,
|
|
2791
|
+
value: payment.method,
|
|
2792
|
+
onSelect: (method) => void selectMethod(method),
|
|
2793
|
+
currency: payment.currency,
|
|
2794
|
+
locale: loc,
|
|
2795
|
+
disabled: busy,
|
|
2796
|
+
label: t("payment.methodLabel")
|
|
2797
|
+
}
|
|
2798
|
+
) : null,
|
|
2799
|
+
isBank && payment.instructions ? /* @__PURE__ */ jsxRuntime.jsx(TransferInstructions, { instructions: payment.instructions, locale: loc }) : null,
|
|
2800
|
+
!isBank ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => void pay(), busy, children: t("payment.payNow") }),
|
|
2802
|
+
isGateway ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)", marginTop: "0.6rem" }, children: t("checkout.gatewayRedirectNote") }) : null
|
|
2803
|
+
] }) : null,
|
|
2804
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", style: { margin: 0, color: "var(--nv-danger, #b3261e)" }, children: t("payment.actionError") }) : null,
|
|
2805
|
+
statusHref ? /* @__PURE__ */ jsxRuntime.jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
|
|
2806
|
+
] });
|
|
2807
|
+
}
|
|
2808
|
+
function Shell2({
|
|
2809
|
+
title,
|
|
2810
|
+
children
|
|
2811
|
+
}) {
|
|
2812
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "34rem" }, children: [
|
|
2813
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { margin: 0, fontSize: "1.25rem", fontWeight: 600 }, children: title }) : null,
|
|
2814
|
+
children
|
|
2815
|
+
] });
|
|
2816
|
+
}
|
|
2817
|
+
function Amount({ label, value }) {
|
|
2818
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline" }, children: [
|
|
2819
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--nv-muted)" }, children: label }),
|
|
2820
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { style: { fontSize: "1.35rem", fontVariantNumeric: "tabular-nums" }, children: value })
|
|
2821
|
+
] });
|
|
2822
|
+
}
|
|
2823
|
+
function Link({ href, children }) {
|
|
2824
|
+
return /* @__PURE__ */ jsxRuntime.jsx("a", { href, style: { color: "var(--nv-brand)", fontSize: "0.875rem" }, children });
|
|
2825
|
+
}
|
|
2397
2826
|
var AccountContext = React10__namespace.createContext(null);
|
|
2398
2827
|
function AccountProvider({ children }) {
|
|
2399
2828
|
const client = useStorefront();
|
|
@@ -3018,10 +3447,15 @@ exports.MarketSwitcher = MarketSwitcher;
|
|
|
3018
3447
|
exports.NeviosProvider = NeviosProvider;
|
|
3019
3448
|
exports.OrderConfirmation = OrderConfirmation;
|
|
3020
3449
|
exports.OrderHistory = OrderHistory;
|
|
3450
|
+
exports.OrderLines = OrderLines;
|
|
3021
3451
|
exports.OrderStatusPage = OrderStatusPage;
|
|
3022
3452
|
exports.OrderSummary = OrderSummary;
|
|
3453
|
+
exports.OrderTotals = OrderTotals;
|
|
3023
3454
|
exports.OrganizationJsonLd = OrganizationJsonLd;
|
|
3455
|
+
exports.PaymentMethodPicker = PaymentMethodPicker;
|
|
3456
|
+
exports.PaymentPage = PaymentPage;
|
|
3024
3457
|
exports.PaymentSection = PaymentSection;
|
|
3458
|
+
exports.PhaseTimeline = PhaseTimeline;
|
|
3025
3459
|
exports.PriceMoney = PriceMoney;
|
|
3026
3460
|
exports.PriceRangeFilter = PriceRangeFilter;
|
|
3027
3461
|
exports.ProductCard = ProductCard;
|
|
@@ -3031,9 +3465,11 @@ exports.ProductJsonLd = ProductJsonLd;
|
|
|
3031
3465
|
exports.ProfileEditor = ProfileEditor;
|
|
3032
3466
|
exports.ShippingPicker = ShippingPicker;
|
|
3033
3467
|
exports.SortSelect = SortSelect;
|
|
3468
|
+
exports.StatusBanner = StatusBanner;
|
|
3034
3469
|
exports.StockBadge = StockBadge;
|
|
3035
3470
|
exports.TagFilter = TagFilter;
|
|
3036
3471
|
exports.ThemeProvider = ThemeProvider;
|
|
3472
|
+
exports.TransferInstructions = TransferInstructions;
|
|
3037
3473
|
exports.VariantPicker = VariantPicker;
|
|
3038
3474
|
exports.absoluteUrl = absoluteUrl;
|
|
3039
3475
|
exports.bundledMessages = bundledMessages;
|
|
@@ -3041,6 +3477,7 @@ exports.cs = cs;
|
|
|
3041
3477
|
exports.en = en;
|
|
3042
3478
|
exports.formatCents = formatCents;
|
|
3043
3479
|
exports.formatMoney = formatMoney;
|
|
3480
|
+
exports.isTerminal = isTerminal;
|
|
3044
3481
|
exports.serializeJsonLd = serializeJsonLd;
|
|
3045
3482
|
exports.stripHtml = stripHtml;
|
|
3046
3483
|
exports.themeToCssVars = themeToCssVars;
|
|
@@ -3050,6 +3487,7 @@ exports.useCheckout = useCheckout;
|
|
|
3050
3487
|
exports.useI18n = useI18n;
|
|
3051
3488
|
exports.useMagicLinkVerify = useMagicLinkVerify;
|
|
3052
3489
|
exports.useOrderStatus = useOrderStatus;
|
|
3490
|
+
exports.usePayment = usePayment;
|
|
3053
3491
|
exports.useStorefront = useStorefront;
|
|
3054
3492
|
exports.useStorefrontOptional = useStorefrontOptional;
|
|
3055
3493
|
exports.useT = useT;
|