@nevios/storefront-kit 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- import * as React10 from 'react';
1
+ import * as React19 from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import { imageSrcSet } from '@nevios/storefront-js';
3
+ import { imageSrcSet, StorefrontError } from '@nevios/storefront-js';
4
4
 
5
5
  // src/provider.tsx
6
- var StorefrontContext = React10.createContext(null);
6
+ var StorefrontContext = React19.createContext(null);
7
7
  function NeviosProvider({ client, children }) {
8
8
  return /* @__PURE__ */ jsx(StorefrontContext.Provider, { value: client, children });
9
9
  }
10
10
  function useStorefront() {
11
- const client = React10.useContext(StorefrontContext);
11
+ const client = React19.useContext(StorefrontContext);
12
12
  if (!client) {
13
13
  throw new Error(
14
14
  "useStorefront must be used inside <NeviosProvider>. Wrap your app root with it."
@@ -17,7 +17,7 @@ function useStorefront() {
17
17
  return client;
18
18
  }
19
19
  function useStorefrontOptional() {
20
- return React10.useContext(StorefrontContext);
20
+ return React19.useContext(StorefrontContext);
21
21
  }
22
22
  var DEFAULTS = {
23
23
  brand: "#111111",
@@ -53,7 +53,7 @@ function ThemeProvider({
53
53
  as: Tag = "div"
54
54
  }) {
55
55
  const style = themeToCssVars(theme);
56
- return React10.createElement(
56
+ return React19.createElement(
57
57
  Tag,
58
58
  { "data-nevios-theme": "", style },
59
59
  children
@@ -179,6 +179,37 @@ var en = {
179
179
  "order.terminal.cancelled": "This order was cancelled.",
180
180
  "order.terminal.refunded": "This order was refunded.",
181
181
  "order.terminal.returned": "This order was returned.",
182
+ // payment page — the four situations it can be in
183
+ "payment.title": "Pay for order {order}",
184
+ "payment.amountDue": "Amount due",
185
+ "payment.methodLabel": "Payment method",
186
+ "payment.payNow": "Pay now",
187
+ "payment.finish": "Finish payment",
188
+ "payment.loading": "Loading payment\u2026",
189
+ "payment.loadError": "Couldn't load this payment.",
190
+ "payment.actionError": "That didn't go through. Please try again.",
191
+ // …paid
192
+ "payment.paidTitle": "Paid",
193
+ "payment.paidBody": "Order {order} is paid. Nothing further is needed.",
194
+ "payment.paidAmount": "Paid",
195
+ // …returning from a gateway, callback still in flight
196
+ "payment.verifyingTitle": "Checking your payment\u2026",
197
+ "payment.verifyingBody": "This takes a few seconds. Don't pay again \u2014 we'll update this page.",
198
+ // …locked, one sentence per reason
199
+ "payment.blockedTitle": "This order can't be paid",
200
+ "payment.blocked.orderCancelled": "This order was cancelled, so there is nothing to pay.",
201
+ "payment.blocked.alreadyPaid": "This order is already paid.",
202
+ "payment.blocked.authorizationHeld": "Your bank is holding the funds for this order. Once the payment settles this page will show it as paid.",
203
+ "payment.blocked.documentIssued": "An invoice has been issued for this order, so the amount is fixed. Contact us to change how you pay.",
204
+ // …bank transfer
205
+ "payment.account": "Account",
206
+ "payment.beneficiary": "Beneficiary",
207
+ "payment.variableSymbol": "Variable symbol",
208
+ "payment.amount": "Amount",
209
+ "payment.copy": "Copy",
210
+ "payment.copied": "Copied",
211
+ "payment.qrAlt": "QR code for the payment",
212
+ "payment.qrCaption": "Scan in your banking app",
182
213
  // error pages
183
214
  "error.notFound.title": "Page not found",
184
215
  "error.notFound.body": "This page doesn't exist or isn't available in your region.",
@@ -195,6 +226,20 @@ var en = {
195
226
  "account.signOut": "Sign out",
196
227
  "account.greeting": "Signed in as {email}",
197
228
  "account.orders": "Your orders",
229
+ "account.loadError": "Could not load your account. Please try again.",
230
+ "account.retry": "Try again",
231
+ "account.loadMore": "Load more",
232
+ "account.signInError": "Could not request a sign-in link. Please try again shortly.",
233
+ "account.security": "Account security",
234
+ "account.newEmail": "New email",
235
+ "account.changeEmail": "Verify new email",
236
+ "account.recentLogin": "Sign in again by email before making this change.",
237
+ "account.sessions": "Sessions",
238
+ "account.currentSession": "Current session",
239
+ "account.revokeSession": "Sign out",
240
+ "account.closeAccount": "Close account",
241
+ "account.closeWarning": "Closing your account signs out all devices and disables account access. Orders and invoices are retained. Contact the shop to restore access.",
242
+ "account.confirmClose": "Confirm account closure",
198
243
  "account.noOrders": "No orders yet.",
199
244
  "account.addresses": "Saved addresses",
200
245
  "account.noAddresses": "No saved addresses yet.",
@@ -335,6 +380,33 @@ var cs = {
335
380
  "order.terminal.cancelled": "Tato objedn\xE1vka byla zru\u0161ena.",
336
381
  "order.terminal.refunded": "Tato objedn\xE1vka byla refundov\xE1na.",
337
382
  "order.terminal.returned": "Tato objedn\xE1vka byla vr\xE1cena.",
383
+ // platební stránka — čtyři situace, ve kterých může být
384
+ "payment.title": "Zaplatit objedn\xE1vku {order}",
385
+ "payment.amountDue": "K \xFAhrad\u011B",
386
+ "payment.methodLabel": "Zp\u016Fsob platby",
387
+ "payment.payNow": "Zaplatit",
388
+ "payment.finish": "Dokon\u010Dit platbu",
389
+ "payment.loading": "Na\u010D\xEDt\xE1n\xED platby\u2026",
390
+ "payment.loadError": "Platbu se nepoda\u0159ilo na\u010D\xEDst.",
391
+ "payment.actionError": "Nepovedlo se to. Zkuste to pros\xEDm znovu.",
392
+ "payment.paidTitle": "Zaplaceno",
393
+ "payment.paidBody": "Objedn\xE1vka {order} je zaplacen\xE1. Nic dal\u0161\xEDho d\u011Blat nemus\xEDte.",
394
+ "payment.paidAmount": "Uhrazeno",
395
+ "payment.verifyingTitle": "Ov\u011B\u0159ujeme platbu\u2026",
396
+ "payment.verifyingBody": "Chvilku to trv\xE1. Nepla\u0165te pros\xEDm znovu \u2014 str\xE1nka se sama aktualizuje.",
397
+ "payment.blockedTitle": "Tuhle objedn\xE1vku te\u010F zaplatit nejde",
398
+ "payment.blocked.orderCancelled": "Objedn\xE1vka byla zru\u0161en\xE1, tak\u017Ee nen\xED co platit.",
399
+ "payment.blocked.alreadyPaid": "Objedn\xE1vka je u\u017E zaplacen\xE1.",
400
+ "payment.blocked.authorizationHeld": "Banka na tuhle objedn\xE1vku dr\u017E\xED pen\xEDze. Jakmile se platba dokon\u010D\xED, uvid\xEDte to tady.",
401
+ "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.",
402
+ "payment.account": "\xDA\u010Det",
403
+ "payment.beneficiary": "P\u0159\xEDjemce",
404
+ "payment.variableSymbol": "Variabiln\xED symbol",
405
+ "payment.amount": "\u010C\xE1stka",
406
+ "payment.copy": "Kop\xEDrovat",
407
+ "payment.copied": "Zkop\xEDrov\xE1no",
408
+ "payment.qrAlt": "QR k\xF3d k platb\u011B",
409
+ "payment.qrCaption": "Na\u010Dt\u011Bte v bankovn\xED aplikaci",
338
410
  "error.notFound.title": "Str\xE1nka nenalezena",
339
411
  "error.notFound.body": "Tato str\xE1nka neexistuje nebo nen\xED ve va\u0161em regionu dostupn\xE1.",
340
412
  "error.generic.title": "N\u011Bco se pokazilo",
@@ -349,6 +421,20 @@ var cs = {
349
421
  "account.signOut": "Odhl\xE1sit se",
350
422
  "account.greeting": "P\u0159ihl\xE1\u0161en jako {email}",
351
423
  "account.orders": "Va\u0161e objedn\xE1vky",
424
+ "account.loadError": "\xDAdaje se nepoda\u0159ilo na\u010D\xEDst. Zkuste to znovu.",
425
+ "account.retry": "Zkusit znovu",
426
+ "account.loadMore": "Na\u010D\xEDst dal\u0161\xED",
427
+ "account.signInError": "P\u0159ihl\xE1\u0161en\xED se nepoda\u0159ilo zah\xE1jit. Zkuste to za chv\xEDli znovu.",
428
+ "account.security": "Zabezpe\u010Den\xED \xFA\u010Dtu",
429
+ "account.newEmail": "Nov\xFD e-mail",
430
+ "account.changeEmail": "Ov\u011B\u0159it nov\xFD e-mail",
431
+ "account.recentLogin": "Pro tuto zm\u011Bnu se nejprve znovu p\u0159ihlaste p\u0159es e-mail.",
432
+ "account.sessions": "P\u0159ihl\xE1\u0161en\xED",
433
+ "account.currentSession": "Toto p\u0159ihl\xE1\u0161en\xED",
434
+ "account.revokeSession": "Odhl\xE1sit",
435
+ "account.closeAccount": "Uzav\u0159\xEDt \xFA\u010Det",
436
+ "account.closeWarning": "Uzav\u0159en\xEDm \xFA\u010Dtu ukon\u010D\xEDte p\u0159\xEDstup a odhl\xE1s\xEDte v\u0161echna za\u0159\xEDzen\xED. Objedn\xE1vky a doklady z\u016Fstanou zachov\xE1ny. Obnoven\xED p\u0159\xEDstupu \u0159e\u0161\xED podpora obchodu.",
437
+ "account.confirmClose": "Potvrdit uzav\u0159en\xED \xFA\u010Dtu",
352
438
  "account.noOrders": "Zat\xEDm \u017E\xE1dn\xE9 objedn\xE1vky.",
353
439
  "account.addresses": "Ulo\u017Een\xE9 adresy",
354
440
  "account.noAddresses": "Zat\xEDm \u017E\xE1dn\xE9 ulo\u017Een\xE9 adresy.",
@@ -433,13 +519,13 @@ function makeI18n(locale, messages) {
433
519
  return { locale, messages, t };
434
520
  }
435
521
  var DEFAULT_I18N = makeI18n("en", en);
436
- var I18nContext = React10.createContext(null);
522
+ var I18nContext = React19.createContext(null);
437
523
  function I18nProvider({
438
524
  locale,
439
525
  messages,
440
526
  children
441
527
  }) {
442
- const value = React10.useMemo(() => {
528
+ const value = React19.useMemo(() => {
443
529
  const lang = langOf(locale);
444
530
  if (locale && !(lang in BUNDLED) && !messages) {
445
531
  devWarn(
@@ -453,7 +539,7 @@ function I18nProvider({
453
539
  return /* @__PURE__ */ jsx(I18nContext.Provider, { value, children });
454
540
  }
455
541
  function useI18n() {
456
- return React10.useContext(I18nContext) ?? DEFAULT_I18N;
542
+ return React19.useContext(I18nContext) ?? DEFAULT_I18N;
457
543
  }
458
544
  function useT() {
459
545
  return useI18n().t;
@@ -577,7 +663,7 @@ function ProductCard({ product, href, locale }) {
577
663
  var MAIN_WIDTHS = [600, 800, 1e3];
578
664
  var THUMB_WIDTHS = [56, 112];
579
665
  function ProductGallery({ media, alt }) {
580
- const [active, setActive] = React10.useState(0);
666
+ const [active, setActive] = React19.useState(0);
581
667
  const imageBase = useStorefrontOptional()?.imageBase;
582
668
  if (media.length === 0) {
583
669
  return /* @__PURE__ */ jsx(
@@ -665,10 +751,10 @@ function matchVariant(product, selected) {
665
751
  ) ?? null;
666
752
  }
667
753
  function VariantPicker({ product, onChange }) {
668
- const [selected, setSelected] = React10.useState(
754
+ const [selected, setSelected] = React19.useState(
669
755
  () => product.variants[0]?.options ?? []
670
756
  );
671
- React10.useEffect(() => {
757
+ React19.useEffect(() => {
672
758
  onChange?.(matchVariant(product, selected));
673
759
  }, [product, selected]);
674
760
  if (product.options.length === 0) return null;
@@ -709,8 +795,8 @@ function BackInStockForm({
709
795
  }) {
710
796
  const t = useT();
711
797
  const client = useStorefront();
712
- const [email, setEmail] = React10.useState(defaultEmail);
713
- const [state, setState] = React10.useState("idle");
798
+ const [email, setEmail] = React19.useState(defaultEmail);
799
+ const [state, setState] = React19.useState("idle");
714
800
  if (!variant || variant.availability?.status !== "out_of_stock") return null;
715
801
  async function submit(e) {
716
802
  e.preventDefault();
@@ -810,7 +896,7 @@ function ProductDetailPage({
810
896
  locale,
811
897
  addToCart
812
898
  }) {
813
- const [variant, setVariant] = React10.useState(
899
+ const [variant, setVariant] = React19.useState(
814
900
  product.variants[0] ?? null
815
901
  );
816
902
  return /* @__PURE__ */ jsxs(
@@ -1042,12 +1128,12 @@ function TagFilter({ tags, selected = [], onChange }) {
1042
1128
  }) })
1043
1129
  ] });
1044
1130
  }
1045
- var CartContext = React10.createContext(null);
1131
+ var CartContext = React19.createContext(null);
1046
1132
  function CartProvider({ children }) {
1047
1133
  const client = useStorefront();
1048
- const [cart, setCart] = React10.useState(null);
1049
- const [loading, setLoading] = React10.useState(false);
1050
- const run = React10.useCallback(
1134
+ const [cart, setCart] = React19.useState(null);
1135
+ const [loading, setLoading] = React19.useState(false);
1136
+ const run = React19.useCallback(
1051
1137
  async (op) => {
1052
1138
  setLoading(true);
1053
1139
  try {
@@ -1060,7 +1146,7 @@ function CartProvider({ children }) {
1060
1146
  },
1061
1147
  []
1062
1148
  );
1063
- const refresh = React10.useCallback(async () => {
1149
+ const refresh = React19.useCallback(async () => {
1064
1150
  setLoading(true);
1065
1151
  try {
1066
1152
  setCart(await client.cart.get());
@@ -1068,10 +1154,10 @@ function CartProvider({ children }) {
1068
1154
  setLoading(false);
1069
1155
  }
1070
1156
  }, [client]);
1071
- React10.useEffect(() => {
1157
+ React19.useEffect(() => {
1072
1158
  void refresh();
1073
1159
  }, [refresh]);
1074
- const value = React10.useMemo(
1160
+ const value = React19.useMemo(
1075
1161
  () => ({
1076
1162
  cart,
1077
1163
  loading,
@@ -1086,7 +1172,7 @@ function CartProvider({ children }) {
1086
1172
  return /* @__PURE__ */ jsx(CartContext.Provider, { value, children });
1087
1173
  }
1088
1174
  function useCart() {
1089
- const ctx = React10.useContext(CartContext);
1175
+ const ctx = React19.useContext(CartContext);
1090
1176
  if (!ctx) {
1091
1177
  throw new Error("useCart must be used inside <CartProvider>.");
1092
1178
  }
@@ -1100,8 +1186,8 @@ function AddToCart({
1100
1186
  }) {
1101
1187
  const t = useT();
1102
1188
  const { addLine } = useCart();
1103
- const [busy, setBusy] = React10.useState(false);
1104
- const [error, setError] = React10.useState(null);
1189
+ const [busy, setBusy] = React19.useState(false);
1190
+ const [error, setError] = React19.useState(null);
1105
1191
  const disabled = variant == null || busy;
1106
1192
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
1107
1193
  /* @__PURE__ */ jsx(
@@ -1142,6 +1228,7 @@ function AddToCart({
1142
1228
  }
1143
1229
  function CartLineItem({ line, locale }) {
1144
1230
  const t = useT();
1231
+ const loc = useFormatLocale(locale);
1145
1232
  const { updateLine, removeLine } = useCart();
1146
1233
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.85rem", alignItems: "flex-start", padding: "0.75rem 0" }, children: [
1147
1234
  /* @__PURE__ */ jsx(
@@ -1213,7 +1300,7 @@ function CartLineItem({ line, locale }) {
1213
1300
  )
1214
1301
  ] })
1215
1302
  ] }),
1216
- /* @__PURE__ */ jsx("div", { style: { fontWeight: 500, whiteSpace: "nowrap" }, children: formatCents(line.line_total_cents, line.unit_price.currency, locale) })
1303
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 500, whiteSpace: "nowrap" }, children: formatCents(line.line_total_cents, line.unit_price.currency, loc) })
1217
1304
  ] });
1218
1305
  }
1219
1306
  function StepBtn({ label, onClick }) {
@@ -1245,6 +1332,7 @@ function CartSummary({
1245
1332
  locale
1246
1333
  }) {
1247
1334
  const tr = useT();
1335
+ const loc = useFormatLocale(locale);
1248
1336
  const { cart } = useCart();
1249
1337
  if (cart == null) return null;
1250
1338
  const t = cart.totals;
@@ -1265,10 +1353,10 @@ function CartSummary({
1265
1353
  opacity: empty ? 0.55 : 1
1266
1354
  };
1267
1355
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
1268
- /* @__PURE__ */ jsx(Row, { label: tr("cart.subtotal"), value: formatCents(t.subtotal_with_tax_cents, t.currency, locale) }),
1269
- t.tax_cents > 0 ? /* @__PURE__ */ jsx(Row, { label: tr("cart.tax"), value: formatCents(t.tax_cents, t.currency, locale), muted: true }) : null,
1356
+ /* @__PURE__ */ jsx(Row, { label: tr("cart.subtotal"), value: formatCents(t.subtotal_with_tax_cents, t.currency, loc) }),
1357
+ t.tax_cents > 0 ? /* @__PURE__ */ jsx(Row, { label: tr("cart.tax"), value: formatCents(t.tax_cents, t.currency, loc), muted: true }) : null,
1270
1358
  /* @__PURE__ */ jsx("div", { style: { height: 1, background: "var(--nv-border)" } }),
1271
- /* @__PURE__ */ jsx(Row, { label: tr("cart.total"), value: formatCents(t.total_cents, t.currency, locale), strong: true }),
1359
+ /* @__PURE__ */ jsx(Row, { label: tr("cart.total"), value: formatCents(t.total_cents, t.currency, loc), strong: true }),
1272
1360
  checkoutHref && !empty ? /* @__PURE__ */ jsx("a", { href: checkoutHref, style: ctaStyle, children: cta }) : /* @__PURE__ */ jsx("button", { type: "button", disabled: empty, onClick: onCheckout, style: ctaStyle, children: cta })
1273
1361
  ] });
1274
1362
  }
@@ -1375,15 +1463,15 @@ function CartDrawer({
1375
1463
  }
1376
1464
  );
1377
1465
  }
1378
- var CheckoutContext = React10.createContext(null);
1466
+ var CheckoutContext = React19.createContext(null);
1379
1467
  function CheckoutProvider({
1380
1468
  children
1381
1469
  }) {
1382
1470
  const client = useStorefront();
1383
- const [checkout, setCheckout] = React10.useState(null);
1384
- const [loading, setLoading] = React10.useState(false);
1385
- const [error, setError] = React10.useState(null);
1386
- const run = React10.useCallback(
1471
+ const [checkout, setCheckout] = React19.useState(null);
1472
+ const [loading, setLoading] = React19.useState(false);
1473
+ const [error, setError] = React19.useState(null);
1474
+ const run = React19.useCallback(
1387
1475
  async (op, store) => {
1388
1476
  setLoading(true);
1389
1477
  try {
@@ -1401,7 +1489,7 @@ function CheckoutProvider({
1401
1489
  },
1402
1490
  []
1403
1491
  );
1404
- const refresh = React10.useCallback(async () => {
1492
+ const refresh = React19.useCallback(async () => {
1405
1493
  setLoading(true);
1406
1494
  try {
1407
1495
  setCheckout(await client.checkout.get());
@@ -1410,10 +1498,10 @@ function CheckoutProvider({
1410
1498
  setLoading(false);
1411
1499
  }
1412
1500
  }, [client]);
1413
- React10.useEffect(() => {
1501
+ React19.useEffect(() => {
1414
1502
  void refresh();
1415
1503
  }, [refresh]);
1416
- const pay = React10.useCallback(
1504
+ const pay = React19.useCallback(
1417
1505
  async (opts = {}) => {
1418
1506
  const co = checkout;
1419
1507
  if (!co) throw new Error("pay() called before a checkout exists");
@@ -1436,7 +1524,7 @@ function CheckoutProvider({
1436
1524
  },
1437
1525
  [checkout, client, run]
1438
1526
  );
1439
- const value = React10.useMemo(
1527
+ const value = React19.useMemo(
1440
1528
  () => ({
1441
1529
  checkout,
1442
1530
  loading,
@@ -1461,7 +1549,7 @@ function CheckoutProvider({
1461
1549
  return /* @__PURE__ */ jsx(CheckoutContext.Provider, { value, children });
1462
1550
  }
1463
1551
  function useCheckout() {
1464
- const ctx = React10.useContext(CheckoutContext);
1552
+ const ctx = React19.useContext(CheckoutContext);
1465
1553
  if (!ctx) {
1466
1554
  throw new Error("useCheckout must be used inside <CheckoutProvider>.");
1467
1555
  }
@@ -1620,10 +1708,25 @@ function AddressForm({
1620
1708
  }) {
1621
1709
  const t = useT();
1622
1710
  const { checkout, setAddress, loading } = useCheckout();
1623
- const [form, setForm] = React10.useState(
1711
+ const [form, setForm] = React19.useState(
1624
1712
  () => seed(checkout?.email ?? null, checkout?.shipping_address ?? null)
1625
1713
  );
1626
- const set = (key) => (e) => setForm((f) => ({ ...f, [key]: e.target.value }));
1714
+ const touched = React19.useRef(/* @__PURE__ */ new Set());
1715
+ React19.useEffect(() => {
1716
+ const prefill = checkout?.customer_prefill;
1717
+ const addresses = prefill?.addresses.filter((a) => !a.is_pickup);
1718
+ const saved = addresses?.find((a) => a.is_default) ?? addresses?.[0];
1719
+ const address = checkout?.shipping_address ?? (saved ? { ...saved, postal_code: saved.zip } : null);
1720
+ const defaults = seed(checkout?.email ?? prefill?.email ?? null, address);
1721
+ defaults.first_name || (defaults.first_name = prefill?.first_name ?? "");
1722
+ defaults.last_name || (defaults.last_name = prefill?.last_name ?? "");
1723
+ defaults.phone || (defaults.phone = prefill?.phone ?? "");
1724
+ setForm((current) => Object.fromEntries(Object.entries(current).map(([key, value]) => [key, touched.current.has(key) ? value : value || defaults[key]])));
1725
+ }, [checkout?.token]);
1726
+ const set = (key) => (e) => {
1727
+ touched.current.add(key);
1728
+ setForm((f) => ({ ...f, [key]: e.target.value }));
1729
+ };
1627
1730
  async function submit(e) {
1628
1731
  e.preventDefault();
1629
1732
  const { email, ...rest } = form;
@@ -1671,13 +1774,14 @@ function ShippingPicker({
1671
1774
  locale
1672
1775
  }) {
1673
1776
  const t = useT();
1777
+ const loc = useFormatLocale(locale);
1674
1778
  const { checkout, shippingQuotes, setShippingMethod, loading } = useCheckout();
1675
1779
  const heading = title ?? t("checkout.shippingMethod");
1676
- const [quotes, setQuotes] = React10.useState(null);
1677
- const [selected, setSelected] = React10.useState(null);
1678
- const [fetching, setFetching] = React10.useState(true);
1780
+ const [quotes, setQuotes] = React19.useState(null);
1781
+ const [selected, setSelected] = React19.useState(null);
1782
+ const [fetching, setFetching] = React19.useState(true);
1679
1783
  const addressKey = checkout?.shipping_address ? `${checkout.shipping_address.country_code}:${checkout.shipping_address.postal_code}` : null;
1680
- React10.useEffect(() => {
1784
+ React19.useEffect(() => {
1681
1785
  let live = true;
1682
1786
  setFetching(true);
1683
1787
  shippingQuotes().then((qs) => {
@@ -1705,17 +1809,13 @@ function ShippingPicker({
1705
1809
  }
1706
1810
  return /* @__PURE__ */ jsxs(Section, { title: heading, children: [
1707
1811
  /* @__PURE__ */ jsx("div", { role: "radiogroup", style: { display: "flex", flexDirection: "column", gap: "0.6rem" }, children: quotes.map((q) => {
1708
- const days = estDays(q, t);
1709
1812
  return /* @__PURE__ */ jsx(
1710
1813
  SelectRow,
1711
1814
  {
1712
1815
  selected: selected === q.rate_id,
1713
1816
  onSelect: () => setSelected(q.rate_id),
1714
- trailing: q.is_free ? t("common.free") : formatCents(q.price_cents, q.currency, locale),
1715
- children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", flexDirection: "column" }, children: [
1716
- /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: q.label }),
1717
- days ? /* @__PURE__ */ jsx("span", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: days }) : null
1718
- ] })
1817
+ trailing: q.is_free ? t("common.free") : formatCents(q.price_cents, q.currency, loc),
1818
+ children: /* @__PURE__ */ jsx("span", { style: { display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: q.label }) })
1719
1819
  },
1720
1820
  q.rate_id
1721
1821
  );
@@ -1723,14 +1823,38 @@ function ShippingPicker({
1723
1823
  /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { onClick: submit, busy: loading, disabled: selected == null, children: submitLabel ?? t("checkout.continueToPayment") }) })
1724
1824
  ] });
1725
1825
  }
1726
- function estDays(q, t) {
1727
- const { estimated_days_min: lo, estimated_days_max: hi } = q;
1728
- if (lo == null && hi == null) return null;
1729
- if (lo != null && hi != null) {
1730
- return lo === hi ? t("shipping.days", { count: lo }) : t("shipping.daysRange", { min: lo, max: hi });
1731
- }
1732
- const n = lo ?? hi;
1733
- return t("shipping.days", { count: n });
1826
+ function PaymentMethodPicker({
1827
+ methods,
1828
+ value,
1829
+ onSelect,
1830
+ currency,
1831
+ locale,
1832
+ disabled,
1833
+ label
1834
+ }) {
1835
+ const loc = useFormatLocale(locale);
1836
+ return /* @__PURE__ */ jsx(
1837
+ "div",
1838
+ {
1839
+ role: "radiogroup",
1840
+ "aria-label": label,
1841
+ style: { display: "flex", flexDirection: "column", gap: "0.6rem" },
1842
+ children: methods.map((m) => /* @__PURE__ */ jsx(
1843
+ SelectRow,
1844
+ {
1845
+ selected: value === m.method,
1846
+ disabled,
1847
+ onSelect: () => onSelect(m.method),
1848
+ trailing: m.surcharge_cents > 0 ? `+${formatCents(m.surcharge_cents, currency, loc)}` : void 0,
1849
+ children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", flexDirection: "column" }, children: [
1850
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: m.display_label }),
1851
+ m.display_description ? /* @__PURE__ */ jsx("span", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: m.display_description }) : null
1852
+ ] })
1853
+ },
1854
+ m.method
1855
+ ))
1856
+ }
1857
+ );
1734
1858
  }
1735
1859
  function PaymentSection({
1736
1860
  title,
@@ -1742,10 +1866,10 @@ function PaymentSection({
1742
1866
  const t = useT();
1743
1867
  const heading = title ?? t("checkout.payment");
1744
1868
  const { checkout, paymentMethods, setPaymentMethod, pay, loading } = useCheckout();
1745
- const [methods, setMethods] = React10.useState(null);
1746
- const [fetching, setFetching] = React10.useState(true);
1869
+ const [methods, setMethods] = React19.useState(null);
1870
+ const [fetching, setFetching] = React19.useState(true);
1747
1871
  const selected = checkout?.payment_method ?? null;
1748
- React10.useEffect(() => {
1872
+ React19.useEffect(() => {
1749
1873
  let live = true;
1750
1874
  setFetching(true);
1751
1875
  paymentMethods().then((ms) => {
@@ -1772,19 +1896,17 @@ function PaymentSection({
1772
1896
  return /* @__PURE__ */ jsx(Section, { title: heading, children: /* @__PURE__ */ jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("checkout.noPayment") }) });
1773
1897
  }
1774
1898
  return /* @__PURE__ */ jsxs(Section, { title: heading, children: [
1775
- /* @__PURE__ */ jsx("div", { role: "radiogroup", style: { display: "flex", flexDirection: "column", gap: "0.6rem" }, children: methods.map((m) => /* @__PURE__ */ jsx(
1776
- SelectRow,
1899
+ /* @__PURE__ */ jsx(
1900
+ PaymentMethodPicker,
1777
1901
  {
1778
- selected: selected === m.method,
1779
- onSelect: () => void setPaymentMethod(m.method),
1780
- trailing: m.surcharge_cents > 0 && checkout ? `+${formatCents(m.surcharge_cents, checkout.totals.currency, locale)}` : void 0,
1781
- children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", flexDirection: "column" }, children: [
1782
- /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: m.display_label }),
1783
- m.display_description ? /* @__PURE__ */ jsx("span", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: m.display_description }) : null
1784
- ] })
1785
- },
1786
- m.method
1787
- )) }),
1902
+ methods,
1903
+ value: selected,
1904
+ onSelect: (method) => void setPaymentMethod(method),
1905
+ currency: checkout?.totals.currency ?? "CZK",
1906
+ locale,
1907
+ label: heading
1908
+ }
1909
+ ),
1788
1910
  /* @__PURE__ */ jsxs("div", { children: [
1789
1911
  /* @__PURE__ */ jsx(Button, { onClick: placeOrder, busy: loading, disabled: selected == null, children: isGateway ? t("checkout.payNow") : t("checkout.placeOrder") }),
1790
1912
  isGateway ? /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)", marginTop: "0.6rem" }, children: t("checkout.gatewayRedirectNote") }) : null
@@ -1797,12 +1919,13 @@ function OrderSummary({
1797
1919
  locale
1798
1920
  }) {
1799
1921
  const tr = useT();
1922
+ const loc = useFormatLocale(locale);
1800
1923
  const ctx = useCheckout();
1801
1924
  const checkout = override ?? ctx.checkout;
1802
1925
  if (checkout == null) return null;
1803
1926
  const t = checkout.totals;
1804
1927
  const c = t.currency;
1805
- const money = (cents) => formatCents(cents, c, locale);
1928
+ const money = (cents) => formatCents(cents, c, loc);
1806
1929
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
1807
1930
  !totalsOnly && checkout.line_items.length > 0 ? /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.75rem" }, children: checkout.line_items.map((li) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
1808
1931
  li.image_url ? /* @__PURE__ */ jsx(
@@ -1883,16 +2006,16 @@ function CheckoutFlow({
1883
2006
  }) {
1884
2007
  const t = useT();
1885
2008
  const { checkout, loading, create } = useCheckout();
1886
- const [step, setStep] = React10.useState("address");
1887
- const [bootstrapped, setBootstrapped] = React10.useState(false);
1888
- React10.useEffect(() => {
2009
+ const [step, setStep] = React19.useState("address");
2010
+ const [bootstrapped, setBootstrapped] = React19.useState(false);
2011
+ React19.useEffect(() => {
1889
2012
  if (checkout || !cartToken || bootstrapped) return;
1890
2013
  setBootstrapped(true);
1891
2014
  void create(cartToken).catch(() => {
1892
2015
  });
1893
2016
  }, [checkout, cartToken, bootstrapped, create]);
1894
2017
  const serverStep = reachedStep(checkout);
1895
- React10.useEffect(() => {
2018
+ React19.useEffect(() => {
1896
2019
  setStep((cur) => rank(serverStep) > rank(cur) ? serverStep : cur);
1897
2020
  }, [serverStep]);
1898
2021
  if (checkout?.order_id) {
@@ -2013,10 +2136,10 @@ function DefaultConfirmation({ checkout }) {
2013
2136
  }
2014
2137
  function useOrderStatus(statusToken, initial) {
2015
2138
  const client = useStorefront();
2016
- const [order, setOrder] = React10.useState(initial ?? null);
2017
- const [loading, setLoading] = React10.useState(false);
2018
- const [error, setError] = React10.useState(null);
2019
- const load = React10.useCallback(async () => {
2139
+ const [order, setOrder] = React19.useState(initial ?? null);
2140
+ const [loading, setLoading] = React19.useState(false);
2141
+ const [error, setError] = React19.useState(null);
2142
+ const load = React19.useCallback(async () => {
2020
2143
  if (!statusToken) return;
2021
2144
  setLoading(true);
2022
2145
  try {
@@ -2028,12 +2151,85 @@ function useOrderStatus(statusToken, initial) {
2028
2151
  setLoading(false);
2029
2152
  }
2030
2153
  }, [client, statusToken]);
2031
- React10.useEffect(() => {
2154
+ React19.useEffect(() => {
2032
2155
  if (initial) return;
2033
2156
  void load();
2034
2157
  }, [load, initial]);
2035
2158
  return { order, loading, error, reload: () => void load() };
2036
2159
  }
2160
+ function usePayment(token, initial) {
2161
+ const client = useStorefront();
2162
+ const [payment, setPayment] = React19.useState(initial ?? null);
2163
+ const [methods, setMethods] = React19.useState([]);
2164
+ const [loading, setLoading] = React19.useState(false);
2165
+ const [busy, setBusy] = React19.useState(false);
2166
+ const [error, setError] = React19.useState(null);
2167
+ const load = React19.useCallback(async () => {
2168
+ if (!token) return;
2169
+ setLoading(true);
2170
+ try {
2171
+ const [state, list] = await Promise.all([
2172
+ client.payment.get(token),
2173
+ client.payment.methods(token)
2174
+ ]);
2175
+ setPayment(state);
2176
+ setMethods(list);
2177
+ setError(null);
2178
+ } catch (e) {
2179
+ setError(e instanceof Error ? e : new Error(String(e)));
2180
+ } finally {
2181
+ setLoading(false);
2182
+ }
2183
+ }, [client, token]);
2184
+ React19.useEffect(() => {
2185
+ if (!token) return;
2186
+ if (initial && initial.token === token) {
2187
+ setPayment(initial);
2188
+ client.payment.methods(token).then(setMethods).catch(() => setMethods([]));
2189
+ return;
2190
+ }
2191
+ void load();
2192
+ }, [token, load]);
2193
+ const selectMethod = React19.useCallback(
2194
+ async (method) => {
2195
+ if (!token) return null;
2196
+ setBusy(true);
2197
+ try {
2198
+ const next = await client.payment.selectMethod(token, method);
2199
+ setPayment(next);
2200
+ setError(null);
2201
+ return next;
2202
+ } catch (e) {
2203
+ setError(e instanceof Error ? e : new Error(String(e)));
2204
+ return null;
2205
+ } finally {
2206
+ setBusy(false);
2207
+ }
2208
+ },
2209
+ [client, token]
2210
+ );
2211
+ const startPayment = React19.useCallback(
2212
+ async (input) => {
2213
+ if (!token) return null;
2214
+ setBusy(true);
2215
+ try {
2216
+ const result = await client.payment.start(token, {
2217
+ return_url: input?.returnUrl,
2218
+ cancel_url: input?.cancelUrl
2219
+ });
2220
+ setError(null);
2221
+ return result.redirect_url;
2222
+ } catch (e) {
2223
+ setError(e instanceof Error ? e : new Error(String(e)));
2224
+ return null;
2225
+ } finally {
2226
+ setBusy(false);
2227
+ }
2228
+ },
2229
+ [client, token]
2230
+ );
2231
+ return { payment, methods, loading, busy, error, reload: load, selectMethod, startPayment };
2232
+ }
2037
2233
  var PHASE_RANK = {
2038
2234
  placed: 0,
2039
2235
  paid: 1,
@@ -2129,6 +2325,7 @@ function OrderLines({
2129
2325
  order,
2130
2326
  locale
2131
2327
  }) {
2328
+ const loc = useFormatLocale(locale);
2132
2329
  return /* @__PURE__ */ jsxs("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
2133
2330
  order.line_items.map((li) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
2134
2331
  li.image_url ? /* @__PURE__ */ jsx(
@@ -2149,11 +2346,11 @@ function OrderLines({
2149
2346
  li.quantity
2150
2347
  ] })
2151
2348
  ] }),
2152
- /* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(li.total_with_tax_cents, order.currency, locale) })
2349
+ /* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(li.total_with_tax_cents, order.currency, loc) })
2153
2350
  ] }, li.id)),
2154
2351
  order.fee_lines.map((f, i) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "0.75rem", alignItems: "center" }, children: [
2155
2352
  /* @__PURE__ */ jsx("span", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx("span", { style: { display: "block", fontWeight: 500 }, children: f.title }) }),
2156
- /* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(f.total_with_tax_cents, order.currency, locale) })
2353
+ /* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatCents(f.total_with_tax_cents, order.currency, loc) })
2157
2354
  ] }, `fee-${i}`))
2158
2355
  ] });
2159
2356
  }
@@ -2162,9 +2359,10 @@ function OrderTotals({
2162
2359
  locale
2163
2360
  }) {
2164
2361
  const tr = useT();
2362
+ const loc = useFormatLocale(locale);
2165
2363
  const t = order.totals;
2166
2364
  const c = order.currency;
2167
- const money = (cents) => formatCents(cents, c, locale);
2365
+ const money = (cents) => formatCents(cents, c, loc);
2168
2366
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
2169
2367
  /* @__PURE__ */ jsx(Row3, { label: tr("totals.subtotal"), value: money(t.subtotal_cents) }),
2170
2368
  t.discount_cents > 0 ? /* @__PURE__ */ jsx(Row3, { label: tr("totals.discount"), value: `\u2212${money(t.discount_cents)}`, muted: true }) : null,
@@ -2270,6 +2468,7 @@ function OrderStatusPage({
2270
2468
  statusToken,
2271
2469
  order: initial,
2272
2470
  onContactSupport,
2471
+ payHref,
2273
2472
  locale
2274
2473
  }) {
2275
2474
  const t = useT();
@@ -2321,6 +2520,7 @@ function OrderStatusPage({
2321
2520
  /* @__PURE__ */ jsxs(Card, { title: t("order.payment"), children: [
2322
2521
  /* @__PURE__ */ jsx(Line, { label: t("order.method"), value: order.payment.method ?? "\u2014" }),
2323
2522
  /* @__PURE__ */ jsx(Line, { label: t("order.status"), value: order.payment.status }),
2523
+ order.payment.token && payHref ? /* @__PURE__ */ jsx("a", { href: payHref(order.payment.token), style: { color: "var(--nv-brand)", fontWeight: 500 }, children: t("payment.finish") }) : null,
2324
2524
  order.payment.invoice_available && order.payment.invoice_url ? /* @__PURE__ */ jsx("a", { href: order.payment.invoice_url, style: { color: "var(--nv-brand)" }, children: t("order.downloadInvoice") }) : null
2325
2525
  ] }),
2326
2526
  order.actions.can_contact_support && onContactSupport ? /* @__PURE__ */ jsx(
@@ -2372,27 +2572,291 @@ function Line({ label, value }) {
2372
2572
  /* @__PURE__ */ jsx("span", { style: { textAlign: "right" }, children: value })
2373
2573
  ] });
2374
2574
  }
2375
- var AccountContext = React10.createContext(null);
2575
+ function TransferInstructions({
2576
+ instructions: i,
2577
+ locale
2578
+ }) {
2579
+ const t = useT();
2580
+ const loc = useFormatLocale(locale);
2581
+ const account = i.iban || i.account_number;
2582
+ return /* @__PURE__ */ jsxs(
2583
+ "div",
2584
+ {
2585
+ style: {
2586
+ display: "flex",
2587
+ flexWrap: "wrap",
2588
+ gap: "1.25rem",
2589
+ alignItems: "flex-start",
2590
+ padding: "1rem",
2591
+ borderRadius: "var(--nv-radius)",
2592
+ border: "1px solid var(--nv-border)"
2593
+ },
2594
+ children: [
2595
+ /* @__PURE__ */ jsxs("dl", { style: { flex: "1 1 15rem", margin: 0, display: "flex", flexDirection: "column", gap: "0.7rem" }, children: [
2596
+ account ? /* @__PURE__ */ jsx(CopyRow, { label: t("payment.account"), value: account }) : null,
2597
+ i.beneficiary_name ? /* @__PURE__ */ jsx(Row4, { label: t("payment.beneficiary"), value: i.beneficiary_name }) : null,
2598
+ /* @__PURE__ */ jsx(CopyRow, { label: t("payment.variableSymbol"), value: i.variable_symbol }),
2599
+ /* @__PURE__ */ jsx(
2600
+ Row4,
2601
+ {
2602
+ label: t("payment.amount"),
2603
+ value: formatCents(i.amount_cents, i.currency, loc),
2604
+ strong: true
2605
+ }
2606
+ )
2607
+ ] }),
2608
+ i.qr_svg_data_uri ? /* @__PURE__ */ jsxs("figure", { style: { margin: 0, textAlign: "center" }, children: [
2609
+ /* @__PURE__ */ jsx(
2610
+ "img",
2611
+ {
2612
+ src: i.qr_svg_data_uri,
2613
+ alt: t("payment.qrAlt"),
2614
+ width: 148,
2615
+ height: 148,
2616
+ style: { display: "block", borderRadius: "var(--nv-radius)" }
2617
+ }
2618
+ ),
2619
+ /* @__PURE__ */ jsx("figcaption", { style: { fontSize: "0.75rem", color: "var(--nv-muted)", marginTop: "0.4rem" }, children: t("payment.qrCaption") })
2620
+ ] }) : null,
2621
+ i.instructions ? /* @__PURE__ */ jsx("p", { style: { flexBasis: "100%", margin: 0, fontSize: "0.8125rem", color: "var(--nv-muted)" }, children: i.instructions }) : null
2622
+ ]
2623
+ }
2624
+ );
2625
+ }
2626
+ function Row4({
2627
+ label,
2628
+ value,
2629
+ strong
2630
+ }) {
2631
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.1rem" }, children: [
2632
+ /* @__PURE__ */ jsx("dt", { style: { fontSize: "0.75rem", color: "var(--nv-muted)" }, children: label }),
2633
+ /* @__PURE__ */ jsx(
2634
+ "dd",
2635
+ {
2636
+ style: {
2637
+ margin: 0,
2638
+ fontWeight: strong ? 600 : 500,
2639
+ fontVariantNumeric: "tabular-nums"
2640
+ },
2641
+ children: value
2642
+ }
2643
+ )
2644
+ ] });
2645
+ }
2646
+ function CopyRow({ label, value }) {
2647
+ const t = useT();
2648
+ const [copied, setCopied] = React19.useState(false);
2649
+ React19.useEffect(() => {
2650
+ if (!copied) return;
2651
+ const id = setTimeout(() => setCopied(false), 1800);
2652
+ return () => clearTimeout(id);
2653
+ }, [copied]);
2654
+ async function copy() {
2655
+ try {
2656
+ await navigator.clipboard.writeText(value);
2657
+ setCopied(true);
2658
+ } catch {
2659
+ }
2660
+ }
2661
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.1rem" }, children: [
2662
+ /* @__PURE__ */ jsx("dt", { style: { fontSize: "0.75rem", color: "var(--nv-muted)" }, children: label }),
2663
+ /* @__PURE__ */ jsxs("dd", { style: { margin: 0, display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
2664
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 500, fontVariantNumeric: "tabular-nums" }, children: value }),
2665
+ /* @__PURE__ */ jsx(
2666
+ "button",
2667
+ {
2668
+ type: "button",
2669
+ onClick: () => void copy(),
2670
+ style: {
2671
+ font: "inherit",
2672
+ fontSize: "0.75rem",
2673
+ cursor: "pointer",
2674
+ padding: "0.15rem 0.5rem",
2675
+ borderRadius: "var(--nv-radius)",
2676
+ border: "1px solid var(--nv-border)",
2677
+ background: "transparent",
2678
+ color: "var(--nv-muted)"
2679
+ },
2680
+ children: copied ? t("payment.copied") : t("payment.copy")
2681
+ }
2682
+ )
2683
+ ] })
2684
+ ] });
2685
+ }
2686
+ var HANDOFF_TTL_MS = 30 * 60 * 1e3;
2687
+ var POLL_MS = 2e3;
2688
+ var POLL_ATTEMPTS = 6;
2689
+ var BLOCKED_MESSAGE = {
2690
+ order_cancelled: "payment.blocked.orderCancelled",
2691
+ already_paid: "payment.blocked.alreadyPaid",
2692
+ authorization_held: "payment.blocked.authorizationHeld",
2693
+ document_issued: "payment.blocked.documentIssued"
2694
+ };
2695
+ function handoffKey(token) {
2696
+ return `nv_payment_handoff_${token}`;
2697
+ }
2698
+ function rememberHandoff(token) {
2699
+ try {
2700
+ sessionStorage.setItem(handoffKey(token), String(Date.now()));
2701
+ } catch {
2702
+ }
2703
+ }
2704
+ function consumeHandoff(token) {
2705
+ try {
2706
+ const raw = sessionStorage.getItem(handoffKey(token));
2707
+ if (!raw) return false;
2708
+ const fresh = Date.now() - Number(raw) < HANDOFF_TTL_MS;
2709
+ if (!fresh) sessionStorage.removeItem(handoffKey(token));
2710
+ return fresh;
2711
+ } catch {
2712
+ return false;
2713
+ }
2714
+ }
2715
+ function forgetHandoff(token) {
2716
+ try {
2717
+ sessionStorage.removeItem(handoffKey(token));
2718
+ } catch {
2719
+ }
2720
+ }
2721
+ function PaymentPage({
2722
+ token,
2723
+ payment: initial,
2724
+ returnUrl,
2725
+ cancelUrl,
2726
+ statusHref,
2727
+ locale,
2728
+ onPaid
2729
+ }) {
2730
+ const t = useT();
2731
+ const loc = useFormatLocale(locale);
2732
+ const { payment, methods, loading, busy, error, reload, selectMethod, startPayment } = usePayment(token, initial);
2733
+ const [verifying, setVerifying] = React19.useState(false);
2734
+ React19.useEffect(() => {
2735
+ if (token) setVerifying(consumeHandoff(token));
2736
+ }, [token]);
2737
+ const settled = payment != null && !payment.can_pay && payment.blocked_reason === "already_paid";
2738
+ React19.useEffect(() => {
2739
+ if (!verifying || !token || settled) return;
2740
+ let attempts = 0;
2741
+ const id = setInterval(() => {
2742
+ attempts += 1;
2743
+ if (attempts > POLL_ATTEMPTS) {
2744
+ setVerifying(false);
2745
+ forgetHandoff(token);
2746
+ clearInterval(id);
2747
+ return;
2748
+ }
2749
+ void reload();
2750
+ }, POLL_MS);
2751
+ return () => clearInterval(id);
2752
+ }, [verifying, token, settled, reload]);
2753
+ React19.useEffect(() => {
2754
+ if (!settled || !token || !payment) return;
2755
+ setVerifying(false);
2756
+ forgetHandoff(token);
2757
+ onPaid?.(payment);
2758
+ }, [settled, token, payment, onPaid]);
2759
+ if (!token) return null;
2760
+ if (payment == null) {
2761
+ return /* @__PURE__ */ jsx(Shell2, { children: /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "var(--nv-muted)" }, children: loading ? t("payment.loading") : t("payment.loadError") }) });
2762
+ }
2763
+ const money = (cents) => formatCents(cents, payment.currency, loc);
2764
+ if (settled) {
2765
+ return /* @__PURE__ */ jsxs(Shell2, { title: t("payment.paidTitle"), children: [
2766
+ /* @__PURE__ */ jsx("p", { style: { margin: 0 }, children: t("payment.paidBody", { order: payment.order_name ?? payment.order_number }) }),
2767
+ /* @__PURE__ */ jsx(Amount, { label: t("payment.paidAmount"), value: money(payment.total_cents) }),
2768
+ statusHref ? /* @__PURE__ */ jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
2769
+ ] });
2770
+ }
2771
+ if (payment.blocked_reason) {
2772
+ return /* @__PURE__ */ jsxs(Shell2, { title: t("payment.blockedTitle"), children: [
2773
+ /* @__PURE__ */ jsx("p", { style: { margin: 0 }, children: t(BLOCKED_MESSAGE[payment.blocked_reason]) }),
2774
+ statusHref ? /* @__PURE__ */ jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
2775
+ ] });
2776
+ }
2777
+ if (verifying) {
2778
+ return /* @__PURE__ */ jsx(Shell2, { title: t("payment.verifyingTitle"), children: /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "var(--nv-muted)" }, children: t("payment.verifyingBody") }) });
2779
+ }
2780
+ const isBank = payment.category === "bank";
2781
+ const isGateway = payment.category === "gateway";
2782
+ async function pay() {
2783
+ if (!token) return;
2784
+ rememberHandoff(token);
2785
+ const url = await startPayment({ returnUrl, cancelUrl });
2786
+ if (url) {
2787
+ window.location.assign(url);
2788
+ return;
2789
+ }
2790
+ forgetHandoff(token);
2791
+ await reload();
2792
+ }
2793
+ return /* @__PURE__ */ jsxs(Shell2, { title: t("payment.title", { order: payment.order_name ?? payment.order_number }), children: [
2794
+ /* @__PURE__ */ jsx(Amount, { label: t("payment.amountDue"), value: money(payment.amount_due_cents) }),
2795
+ methods.length > 0 ? /* @__PURE__ */ jsx(
2796
+ PaymentMethodPicker,
2797
+ {
2798
+ methods,
2799
+ value: payment.method,
2800
+ onSelect: (method) => void selectMethod(method),
2801
+ currency: payment.currency,
2802
+ locale: loc,
2803
+ disabled: busy,
2804
+ label: t("payment.methodLabel")
2805
+ }
2806
+ ) : null,
2807
+ isBank && payment.instructions ? /* @__PURE__ */ jsx(TransferInstructions, { instructions: payment.instructions, locale: loc }) : null,
2808
+ !isBank ? /* @__PURE__ */ jsxs("div", { children: [
2809
+ /* @__PURE__ */ jsx(Button, { onClick: () => void pay(), busy, children: t("payment.payNow") }),
2810
+ isGateway ? /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8125rem", color: "var(--nv-muted)", marginTop: "0.6rem" }, children: t("checkout.gatewayRedirectNote") }) : null
2811
+ ] }) : null,
2812
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", style: { margin: 0, color: "var(--nv-danger, #b3261e)" }, children: t("payment.actionError") }) : null,
2813
+ statusHref ? /* @__PURE__ */ jsx(Link, { href: statusHref, children: t("order.trackOrder") }) : null
2814
+ ] });
2815
+ }
2816
+ function Shell2({
2817
+ title,
2818
+ children
2819
+ }) {
2820
+ return /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "34rem" }, children: [
2821
+ title ? /* @__PURE__ */ jsx("h1", { style: { margin: 0, fontSize: "1.25rem", fontWeight: 600 }, children: title }) : null,
2822
+ children
2823
+ ] });
2824
+ }
2825
+ function Amount({ label, value }) {
2826
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline" }, children: [
2827
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--nv-muted)" }, children: label }),
2828
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: "1.35rem", fontVariantNumeric: "tabular-nums" }, children: value })
2829
+ ] });
2830
+ }
2831
+ function Link({ href, children }) {
2832
+ return /* @__PURE__ */ jsx("a", { href, style: { color: "var(--nv-brand)", fontSize: "0.875rem" }, children });
2833
+ }
2834
+ var AccountContext = React19.createContext(null);
2376
2835
  function AccountProvider({ children }) {
2377
2836
  const client = useStorefront();
2378
- const [customer, setCustomer] = React10.useState(null);
2379
- const [loading, setLoading] = React10.useState(true);
2380
- const refresh = React10.useCallback(async () => {
2837
+ const [customer, setCustomer] = React19.useState(null);
2838
+ const [loading, setLoading] = React19.useState(true);
2839
+ const [error, setError] = React19.useState(false);
2840
+ const refresh = React19.useCallback(async () => {
2381
2841
  setLoading(true);
2842
+ setError(false);
2382
2843
  try {
2383
2844
  setCustomer(await client.account.me());
2845
+ } catch {
2846
+ setError(true);
2384
2847
  } finally {
2385
2848
  setLoading(false);
2386
2849
  }
2387
2850
  }, [client]);
2388
- React10.useEffect(() => {
2851
+ React19.useEffect(() => {
2389
2852
  void refresh();
2390
2853
  }, [refresh]);
2391
- const value = React10.useMemo(
2854
+ const value = React19.useMemo(
2392
2855
  () => ({
2393
2856
  customer,
2394
2857
  signedIn: customer != null,
2395
2858
  loading,
2859
+ error,
2396
2860
  requestMagicLink: (email) => client.account.requestMagicLink(email),
2397
2861
  verify: async (token) => {
2398
2862
  const c = await client.account.verify(token);
@@ -2405,12 +2869,12 @@ function AccountProvider({ children }) {
2405
2869
  },
2406
2870
  refresh
2407
2871
  }),
2408
- [customer, loading, client, refresh]
2872
+ [customer, loading, error, client, refresh]
2409
2873
  );
2410
2874
  return /* @__PURE__ */ jsx(AccountContext.Provider, { value, children });
2411
2875
  }
2412
2876
  function useAccount() {
2413
- const ctx = React10.useContext(AccountContext);
2877
+ const ctx = React19.useContext(AccountContext);
2414
2878
  if (!ctx) {
2415
2879
  throw new Error("useAccount must be used inside <AccountProvider>.");
2416
2880
  }
@@ -2418,9 +2882,9 @@ function useAccount() {
2418
2882
  }
2419
2883
  function useMagicLinkVerify(token) {
2420
2884
  const { verify } = useAccount();
2421
- const [status, setStatus] = React10.useState("idle");
2422
- const done = React10.useRef(false);
2423
- React10.useEffect(() => {
2885
+ const [status, setStatus] = React19.useState("idle");
2886
+ const done = React19.useRef(false);
2887
+ React19.useEffect(() => {
2424
2888
  if (!token || done.current) return;
2425
2889
  done.current = true;
2426
2890
  setStatus("verifying");
@@ -2431,18 +2895,22 @@ function useMagicLinkVerify(token) {
2431
2895
  function LoginForm({ verifyPath = "/account/verify", onSent }) {
2432
2896
  const t = useT();
2433
2897
  const { requestMagicLink } = useAccount();
2434
- const [email, setEmail] = React10.useState("");
2435
- const [busy, setBusy] = React10.useState(false);
2436
- const [sent, setSent] = React10.useState(false);
2437
- const [devLink, setDevLink] = React10.useState(null);
2898
+ const [email, setEmail] = React19.useState("");
2899
+ const [busy, setBusy] = React19.useState(false);
2900
+ const [sent, setSent] = React19.useState(false);
2901
+ const [error, setError] = React19.useState(false);
2902
+ const [devLink, setDevLink] = React19.useState(null);
2438
2903
  async function submit(e) {
2439
2904
  e.preventDefault();
2440
2905
  setBusy(true);
2906
+ setError(false);
2441
2907
  try {
2442
2908
  const r = await requestMagicLink(email);
2443
2909
  setSent(true);
2444
2910
  if (r.devToken) setDevLink(`${verifyPath}?token=${encodeURIComponent(r.devToken)}`);
2445
2911
  onSent?.(email);
2912
+ } catch {
2913
+ setError(true);
2446
2914
  } finally {
2447
2915
  setBusy(false);
2448
2916
  }
@@ -2481,6 +2949,7 @@ function LoginForm({ verifyPath = "/account/verify", onSent }) {
2481
2949
  }
2482
2950
  )
2483
2951
  ] }),
2952
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", children: t("account.signInError") }) : null,
2484
2953
  /* @__PURE__ */ jsx(
2485
2954
  "button",
2486
2955
  {
@@ -2542,20 +3011,47 @@ function OrderHistory({
2542
3011
  const loc = useFormatLocale(locale);
2543
3012
  const { signedIn } = useAccount();
2544
3013
  const client = useStorefront();
2545
- const [orders, setOrders] = React10.useState(null);
2546
- const [reordering, setReordering] = React10.useState(null);
2547
- const [notice, setNotice] = React10.useState(null);
2548
- React10.useEffect(() => {
3014
+ const [orders, setOrders] = React19.useState(null);
3015
+ const [error, setError] = React19.useState(false);
3016
+ const [nextCursor, setNextCursor] = React19.useState(null);
3017
+ const [pageLoading, setPageLoading] = React19.useState(false);
3018
+ const [reload, setReload] = React19.useState(0);
3019
+ const [reordering, setReordering] = React19.useState(null);
3020
+ const [notice, setNotice] = React19.useState(null);
3021
+ React19.useEffect(() => {
2549
3022
  let live = true;
2550
3023
  if (!signedIn) {
2551
3024
  setOrders([]);
2552
3025
  return;
2553
3026
  }
2554
- client.account.orders().then((o) => live && setOrders(o)).catch(() => live && setOrders([]));
3027
+ setError(false);
3028
+ setOrders(null);
3029
+ client.account.ordersPage().then((page) => {
3030
+ if (live) {
3031
+ setOrders(page.orders);
3032
+ setNextCursor(page.nextCursor);
3033
+ }
3034
+ }).catch(() => {
3035
+ if (live) setError(true);
3036
+ });
2555
3037
  return () => {
2556
3038
  live = false;
2557
3039
  };
2558
- }, [signedIn, client]);
3040
+ }, [signedIn, client, reload]);
3041
+ async function loadMore() {
3042
+ if (!nextCursor || pageLoading) return;
3043
+ setPageLoading(true);
3044
+ setError(false);
3045
+ try {
3046
+ const page = await client.account.ordersPage({ beforeId: nextCursor });
3047
+ setOrders((previous) => [...previous ?? [], ...page.orders]);
3048
+ setNextCursor(page.nextCursor);
3049
+ } catch {
3050
+ setError(true);
3051
+ } finally {
3052
+ setPageLoading(false);
3053
+ }
3054
+ }
2559
3055
  async function reorder(statusToken) {
2560
3056
  setReordering(statusToken);
2561
3057
  setNotice(null);
@@ -2576,7 +3072,11 @@ function OrderHistory({
2576
3072
  }
2577
3073
  return /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
2578
3074
  /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "1.1rem", fontWeight: 600 }, children: t("account.orders") }),
2579
- orders == null ? /* @__PURE__ */ jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("common.loadingShort") }) : orders.length === 0 ? /* @__PURE__ */ jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("account.noOrders") }) : /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.5rem" }, children: orders.map((o) => /* @__PURE__ */ jsxs(
3075
+ error ? /* @__PURE__ */ jsxs("div", { role: "alert", children: [
3076
+ /* @__PURE__ */ jsx("p", { children: t("account.loadError") }),
3077
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => orders ? void loadMore() : setReload((x) => x + 1), children: t("account.retry") })
3078
+ ] }) : null,
3079
+ orders == null ? error ? null : /* @__PURE__ */ jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("common.loadingShort") }) : orders.length === 0 ? /* @__PURE__ */ jsx("p", { style: { color: "var(--nv-muted)", margin: 0 }, children: t("account.noOrders") }) : /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "0.5rem" }, children: orders.map((o) => /* @__PURE__ */ jsxs(
2580
3080
  "li",
2581
3081
  {
2582
3082
  style: {
@@ -2623,12 +3123,13 @@ function OrderHistory({
2623
3123
  ]
2624
3124
  },
2625
3125
  o.status_token
2626
- )) })
3126
+ )) }),
3127
+ nextCursor ? /* @__PURE__ */ jsx("button", { type: "button", disabled: pageLoading, onClick: () => void loadMore(), children: pageLoading ? t("common.loadingShort") : t("account.loadMore") }) : null
2627
3128
  ] });
2628
3129
  }
2629
3130
  function AddressForm2({ initial, onSubmit, onCancel, busy }) {
2630
3131
  const t = useT();
2631
- const [form, setForm] = React10.useState(() => ({
3132
+ const [form, setForm] = React19.useState(() => ({
2632
3133
  first_name: initial?.first_name ?? "",
2633
3134
  last_name: initial?.last_name ?? "",
2634
3135
  company: initial?.company ?? "",
@@ -2726,17 +3227,17 @@ function AddressBook() {
2726
3227
  const t = useT();
2727
3228
  const { signedIn } = useAccount();
2728
3229
  const client = useStorefront();
2729
- const [addresses, setAddresses] = React10.useState(null);
2730
- const [mode, setMode] = React10.useState({ kind: "list" });
2731
- const [busy, setBusy] = React10.useState(false);
2732
- const load = React10.useCallback(() => {
3230
+ const [addresses, setAddresses] = React19.useState(null);
3231
+ const [mode, setMode] = React19.useState({ kind: "list" });
3232
+ const [busy, setBusy] = React19.useState(false);
3233
+ const load = React19.useCallback(() => {
2733
3234
  if (!signedIn) {
2734
3235
  setAddresses([]);
2735
3236
  return;
2736
3237
  }
2737
3238
  client.account.addresses().then(setAddresses).catch(() => setAddresses([]));
2738
3239
  }, [signedIn, client]);
2739
- React10.useEffect(() => {
3240
+ React19.useEffect(() => {
2740
3241
  load();
2741
3242
  }, [load]);
2742
3243
  async function run(fn) {
@@ -2790,10 +3291,10 @@ function ProfileEditor() {
2790
3291
  const t = useT();
2791
3292
  const client = useStorefront();
2792
3293
  const { customer, refresh } = useAccount();
2793
- const [editing, setEditing] = React10.useState(false);
2794
- const [busy, setBusy] = React10.useState(false);
2795
- const [error, setError] = React10.useState(false);
2796
- const [form, setForm] = React10.useState({});
3294
+ const [editing, setEditing] = React19.useState(false);
3295
+ const [busy, setBusy] = React19.useState(false);
3296
+ const [error, setError] = React19.useState(false);
3297
+ const [form, setForm] = React19.useState({});
2797
3298
  if (!customer) return null;
2798
3299
  function startEdit() {
2799
3300
  setForm({
@@ -2870,6 +3371,79 @@ function ProfileEditor() {
2870
3371
  ] })
2871
3372
  ] });
2872
3373
  }
3374
+ function AccountSecurity() {
3375
+ const client = useStorefront();
3376
+ const account = useAccount();
3377
+ const t = useT();
3378
+ const [sessions, setSessions] = React19.useState(null);
3379
+ const [email, setEmail] = React19.useState("");
3380
+ const [busy, setBusy] = React19.useState(false);
3381
+ const [notice, setNotice] = React19.useState(null);
3382
+ const [confirmClose, setConfirmClose] = React19.useState(false);
3383
+ const [retry, setRetry] = React19.useState(0);
3384
+ React19.useEffect(() => {
3385
+ let live = true;
3386
+ if (account.signedIn) client.account.sessions().then((s) => {
3387
+ if (live) setSessions(s);
3388
+ }).catch(() => {
3389
+ if (live) setNotice(t("account.loadError"));
3390
+ });
3391
+ return () => {
3392
+ live = false;
3393
+ };
3394
+ }, [client, account.signedIn, retry, t]);
3395
+ async function act(operation) {
3396
+ setBusy(true);
3397
+ setNotice(null);
3398
+ try {
3399
+ await operation();
3400
+ } catch (e) {
3401
+ setNotice(e instanceof StorefrontError && e.status === 401 ? t("account.recentLogin") : t("account.loadError"));
3402
+ } finally {
3403
+ setBusy(false);
3404
+ }
3405
+ }
3406
+ if (!account.signedIn) return null;
3407
+ return /* @__PURE__ */ jsxs("section", { style: { display: "grid", gap: "0.75rem" }, children: [
3408
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "1.1rem", fontWeight: 600 }, children: t("account.security") }),
3409
+ notice ? /* @__PURE__ */ jsx("p", { role: "status", children: notice }) : null,
3410
+ /* @__PURE__ */ jsxs(
3411
+ "form",
3412
+ {
3413
+ style: { display: "flex", gap: "0.75rem", flexWrap: "wrap", alignItems: "end" },
3414
+ onSubmit: (e) => {
3415
+ e.preventDefault();
3416
+ void act(async () => {
3417
+ await client.account.requestEmailChange(email);
3418
+ setNotice(t("account.checkEmail"));
3419
+ });
3420
+ },
3421
+ children: [
3422
+ /* @__PURE__ */ jsx(Field, { label: t("account.newEmail"), type: "email", required: true, value: email, onChange: (e) => setEmail(e.target.value) }),
3423
+ /* @__PURE__ */ jsx(Button, { type: "submit", busy, children: t("account.changeEmail") })
3424
+ ]
3425
+ }
3426
+ ),
3427
+ /* @__PURE__ */ jsx("h3", { children: t("account.sessions") }),
3428
+ sessions ? sessions.map((s) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem", justifyContent: "space-between" }, children: [
3429
+ /* @__PURE__ */ jsx("span", { children: s.current ? t("account.currentSession") : /* @__PURE__ */ jsx("time", { dateTime: s.created_at, children: s.created_at.slice(0, 10) }) }),
3430
+ /* @__PURE__ */ jsx(Button, { busy, onClick: () => void act(async () => {
3431
+ await client.account.revokeSession(s.id);
3432
+ if (s.current) await account.logout();
3433
+ else setSessions((old) => old?.filter((row) => row.id !== s.id) ?? null);
3434
+ }), children: t("account.revokeSession") })
3435
+ ] }, s.id)) : /* @__PURE__ */ jsx(Button, { onClick: () => setRetry((x) => x + 1), children: t("account.retry") }),
3436
+ confirmClose ? /* @__PURE__ */ jsxs("div", { children: [
3437
+ /* @__PURE__ */ jsx("p", { children: t("account.closeWarning") }),
3438
+ /* @__PURE__ */ jsx(Button, { busy, onClick: () => void act(async () => {
3439
+ await client.account.close();
3440
+ await account.refresh();
3441
+ }), children: t("account.confirmClose") }),
3442
+ " ",
3443
+ /* @__PURE__ */ jsx(Button, { disabled: busy, onClick: () => setConfirmClose(false), children: t("account.cancel") })
3444
+ ] }) : /* @__PURE__ */ jsx(Button, { disabled: busy, onClick: () => setConfirmClose(true), children: t("account.closeAccount") })
3445
+ ] });
3446
+ }
2873
3447
  function serializeJsonLd(data) {
2874
3448
  return JSON.stringify(data).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
2875
3449
  }
@@ -2974,6 +3548,6 @@ function OrganizationJsonLd({
2974
3548
  return /* @__PURE__ */ jsx(JsonLd, { data });
2975
3549
  }
2976
3550
 
2977
- export { AccountDashboard, AccountProvider, AddToCart, AddressBook, AddressForm, AvailabilityFilter, BackInStockForm, BreadcrumbJsonLd, CartDrawer, CartLineItem, CartProvider, CartSummary, CheckoutFlow, CheckoutProvider, CollectionPage, I18nProvider, JsonLd, LoginForm, MarketSwitcher, NeviosProvider, OrderConfirmation, OrderHistory, OrderStatusPage, OrderSummary, OrganizationJsonLd, PaymentSection, PriceMoney, PriceRangeFilter, ProductCard, ProductDetailPage, ProductGallery, ProductJsonLd, ProfileEditor, ShippingPicker, SortSelect, StockBadge, TagFilter, ThemeProvider, VariantPicker, absoluteUrl, bundledMessages, cs, en, formatCents, formatMoney, serializeJsonLd, stripHtml, themeToCssVars, useAccount, useCart, useCheckout, useI18n, useMagicLinkVerify, useOrderStatus, useStorefront, useStorefrontOptional, useT };
3551
+ export { AccountDashboard, AccountProvider, AccountSecurity, AddToCart, AddressBook, AddressForm, AvailabilityFilter, BackInStockForm, BreadcrumbJsonLd, CartDrawer, CartLineItem, CartProvider, CartSummary, CheckoutFlow, CheckoutProvider, CollectionPage, I18nProvider, JsonLd, LoginForm, MarketSwitcher, NeviosProvider, OrderConfirmation, OrderHistory, OrderLines, OrderStatusPage, OrderSummary, OrderTotals, OrganizationJsonLd, PaymentMethodPicker, PaymentPage, PaymentSection, PhaseTimeline, PriceMoney, PriceRangeFilter, ProductCard, ProductDetailPage, ProductGallery, ProductJsonLd, ProfileEditor, ShippingPicker, SortSelect, StatusBanner, StockBadge, TagFilter, ThemeProvider, TransferInstructions, VariantPicker, absoluteUrl, bundledMessages, cs, en, formatCents, formatMoney, isTerminal, serializeJsonLd, stripHtml, themeToCssVars, useAccount, useCart, useCheckout, useI18n, useMagicLinkVerify, useOrderStatus, usePayment, useStorefront, useStorefrontOptional, useT };
2978
3552
  //# sourceMappingURL=index.js.map
2979
3553
  //# sourceMappingURL=index.js.map