@usethrottle/auth 0.2.1 → 0.2.3

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.
@@ -8,10 +8,10 @@ import {
8
8
  useOrders,
9
9
  useSavedCards,
10
10
  useSubscriptions
11
- } from "../../chunk-HGBAIM6B.js";
11
+ } from "../../chunk-2DREGJUF.js";
12
12
  import {
13
13
  messageForError
14
- } from "../../chunk-AIXBUDOT.js";
14
+ } from "../../chunk-ST77QX7X.js";
15
15
  import {
16
16
  ThrottleAuthError,
17
17
  ThrottleAuthProvider,
@@ -21,10 +21,10 @@ import {
21
21
  memoryStorage,
22
22
  useAuth,
23
23
  useAuthContext
24
- } from "../../chunk-SZ427BQ3.js";
24
+ } from "../../chunk-NCSTIPJF.js";
25
25
 
26
26
  // src/react/components/provider.tsx
27
- import { createContext as createContext5, useCallback as useCallback3, useContext as useContext5, useMemo as useMemo3, useRef as useRef6, useState as useState19 } from "react";
27
+ import { createContext as createContext5, useCallback as useCallback3, useContext as useContext5, useMemo as useMemo3, useRef as useRef8, useState as useState21 } from "react";
28
28
 
29
29
  // src/react/components/appearance.tsx
30
30
  import { createContext, useContext, useMemo } from "react";
@@ -125,6 +125,7 @@ var VARIABLE_PROPERTY = {
125
125
  colorMuted: "--throttle-color-muted",
126
126
  colorMutedForeground: "--throttle-color-muted-foreground",
127
127
  colorBorder: "--throttle-color-border",
128
+ colorBorderControl: "--throttle-color-border-control",
128
129
  colorDanger: "--throttle-color-danger",
129
130
  colorDangerSurface: "--throttle-color-danger-surface",
130
131
  colorDangerBorder: "--throttle-color-danger-border",
@@ -139,6 +140,12 @@ var VARIABLE_PROPERTY = {
139
140
  borderRadius: "--throttle-radius",
140
141
  borderWidth: "--throttle-border-width",
141
142
  spacing: "--throttle-spacing",
143
+ // The account dashboard's own surface and outer padding. Separate from
144
+ // colorBackground/colorSurface because a merchant embedding the dashboard
145
+ // in their page usually wants it to paint nothing at all, while still
146
+ // theming the cards inside it.
147
+ accountSurface: "--throttle-color-account-surface",
148
+ accountPadding: "--throttle-account-padding",
142
149
  shadowCard: "--throttle-shadow-card",
143
150
  shadowPopover: "--throttle-shadow-popover",
144
151
  transition: "--throttle-transition",
@@ -273,6 +280,8 @@ var THROTTLE_ELEMENT_KEYS = [
273
280
  "paymentMethodsPanel.item",
274
281
  "paymentMethodsPanel.defaultButton",
275
282
  "paymentMethodsPanel.deleteButton",
283
+ "paymentMethodsPanel.addButton",
284
+ "paymentMethodsPanel.addDialog",
276
285
  "paymentMethodsPanel.table",
277
286
  "paymentMethodsPanel.row",
278
287
  "ordersPanel.root",
@@ -501,8 +510,9 @@ var enUS = {
501
510
  },
502
511
  paymentMethods: {
503
512
  empty: "No saved cards",
504
- // True today and still true once a buyer-plane add-card route exists.
505
- emptyDescription: "Cards you use at checkout will be saved here.",
513
+ emptyDescription: "Add a card here, or one will be saved when you check out.",
514
+ addButton: "Add card",
515
+ addTitle: "Add a card",
506
516
  // Shown whenever the panel is empty with no error and the buyer is not
507
517
  // verified — including simply being signed out — matching the copy
508
518
  // orders/invoices/subscriptions already show in that state.
@@ -693,6 +703,19 @@ var THROTTLE_STYLES = `
693
703
  --throttle-color-muted: #eceef2;
694
704
  --throttle-color-muted-foreground: #5b6472;
695
705
  --throttle-color-border: #e2e8f0;
706
+ /* The boundary of an INTERACTIVE control, which WCAG 1.4.11 requires to
707
+ reach 3:1 against its adjacent colour \u2014 an input identified only by a
708
+ 1.23:1 hairline is not identifiable at all. Decorative separators (card
709
+ edges, table rules, dividers) keep --throttle-color-border: they do not
710
+ identify a control, so the requirement does not apply and darkening
711
+ them would only add noise. */
712
+ /* The account dashboard paints nothing by default so it can drop into a
713
+ merchant's page without fighting their background. The accountSurface and
714
+ accountPadding appearance variables opt back into a card.
715
+ No backticks in this comment: the sheet is a TS template literal. */
716
+ --throttle-color-account-surface: transparent;
717
+ --throttle-account-padding: 0;
718
+ --throttle-color-border-control: #8b93a1;
696
719
  --throttle-color-danger: #c2321f;
697
720
  --throttle-color-danger-surface: #fef2f2;
698
721
  --throttle-color-danger-border: #fecaca;
@@ -745,6 +768,7 @@ var THROTTLE_STYLES = `
745
768
  --throttle-color-muted: #21262d;
746
769
  --throttle-color-muted-foreground: #9aa4b2;
747
770
  --throttle-color-border: #30363d;
771
+ --throttle-color-border-control: #5c6570;
748
772
  --throttle-color-danger: #ff6b58;
749
773
  --throttle-color-danger-surface: #2a1513;
750
774
  --throttle-color-danger-border: #5c2b25;
@@ -767,6 +791,7 @@ var THROTTLE_STYLES = `
767
791
  --throttle-color-muted: #21262d;
768
792
  --throttle-color-muted-foreground: #9aa4b2;
769
793
  --throttle-color-border: #30363d;
794
+ --throttle-color-border-control: #5c6570;
770
795
  --throttle-color-danger: #ff6b58;
771
796
  --throttle-color-danger-surface: #2a1513;
772
797
  --throttle-color-danger-border: #5c2b25;
@@ -814,7 +839,7 @@ var THROTTLE_STYLES = `
814
839
  font-size: var(--throttle-font-size);
815
840
  color: var(--throttle-color-foreground);
816
841
  background: var(--throttle-color-background);
817
- border: var(--throttle-border-width) solid var(--throttle-color-border);
842
+ border: var(--throttle-border-width) solid var(--throttle-color-border-control);
818
843
  border-radius: var(--throttle-radius-sm);
819
844
  /* padding-block stays 0 so min-height alone owns the height, exactly as
820
845
  .throttle-button does. With 12px vertical padding the box computed to
@@ -838,7 +863,13 @@ var THROTTLE_STYLES = `
838
863
  /* Always mounted, so it reserves its line whether or not there is an error:
839
864
  an error appearing on submit must not push the submit button out from
840
865
  under the buyer's pointer. */
841
- .throttle-field__error { color: var(--throttle-color-danger); font-size: var(--throttle-font-size-xs); min-height: 1rem; line-height: 1rem; }
866
+ .throttle-field__error { color: var(--throttle-color-danger); font-size: var(--throttle-font-size-xs); line-height: 1rem; }
867
+ /* Reserved a full line under EVERY input even with nothing to say, which
868
+ with the stack gap put 28px of dead space beneath each field, on every
869
+ form and all seven account panels. The element stays mounted when empty
870
+ because role=alert only announces changes to a live region that was
871
+ already there; it just stops occupying a line. */
872
+ .throttle-field__error:empty { display: none; }
842
873
 
843
874
  .throttle-field-group {
844
875
  display: flex;
@@ -869,7 +900,7 @@ var THROTTLE_STYLES = `
869
900
  .throttle-button:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--throttle-color-background), 0 0 0 4px var(--throttle-color-primary); }
870
901
  .throttle-button--primary { background: var(--throttle-color-primary); color: var(--throttle-color-primary-foreground); width: 100%; }
871
902
  .throttle-button--primary:hover:not(:disabled) { filter: brightness(0.92); }
872
- .throttle-button--secondary { background: var(--throttle-color-surface); color: var(--throttle-color-foreground); border-color: var(--throttle-color-border); }
903
+ .throttle-button--secondary { background: var(--throttle-color-surface); color: var(--throttle-color-foreground); border-color: var(--throttle-color-border-control); }
873
904
  .throttle-button--secondary:hover:not(:disabled) { background: var(--throttle-color-muted); }
874
905
  .throttle-button--danger { background: transparent; color: var(--throttle-color-danger); border-color: var(--throttle-color-border); }
875
906
  .throttle-button--danger:hover:not(:disabled) { background: color-mix(in srgb, var(--throttle-color-danger) 10%, transparent); }
@@ -897,6 +928,11 @@ var THROTTLE_STYLES = `
897
928
  animation: throttle-spin 700ms linear infinite;
898
929
  }
899
930
  @keyframes throttle-spin { to { transform: rotate(360deg); } }
931
+ .throttle-button--loading { position: relative; }
932
+ .throttle-button__label { display: inline-flex; align-items: center; justify-content: center; gap: var(--throttle-space-2); }
933
+ .throttle-button__label--hidden { visibility: hidden; }
934
+ .throttle-spinner--centred { position: absolute; top: 50%; left: 50%; margin: -0.5em 0 0 -0.5em; }
935
+
900
936
  @media (prefers-reduced-motion: reduce) { .throttle-spinner { animation-duration: 2.4s; } }
901
937
 
902
938
  .throttle-skeleton {
@@ -979,7 +1015,9 @@ var THROTTLE_STYLES = `
979
1015
  /* Paints its own ground. A UserButton in a navbar should stay transparent, but
980
1016
  the dashboard is a large surface of themed text: in dark theme its foreground
981
1017
  is near-white, so on a light host page it was rendering white-on-white. */
982
- .throttle-account-root { container-type: inline-size; background: var(--throttle-color-background); color: var(--throttle-color-foreground); }
1018
+ .throttle-cardframe { width: 100%; min-height: 420px; border: 0; display: block; }
1019
+ .throttle-centre { display: flex; align-items: center; justify-content: center; min-height: 160px; }
1020
+ .throttle-account-root { container-type: inline-size; background: var(--throttle-color-account-surface); color: var(--throttle-color-foreground); padding: var(--throttle-account-padding); }
983
1021
  .throttle-account { display: flex; gap: var(--throttle-space-5); align-items: flex-start; }
984
1022
  .throttle-account__content { flex: 1; min-width: 0; }
985
1023
  .throttle-tabs__rail { flex: none; width: 220px; display: flex; flex-direction: column; gap: 2px; }
@@ -1159,11 +1197,12 @@ function CardFooter(props) {
1159
1197
 
1160
1198
  // src/react/components/primitives/Spinner.tsx
1161
1199
  import { jsx as jsx6 } from "react/jsx-runtime";
1162
- function Spinner() {
1200
+ function Spinner({ centred } = {}) {
1163
1201
  const a = useAppearance();
1164
1202
  const Slot = a.slots.Spinner;
1165
1203
  if (Slot) return /* @__PURE__ */ jsx6(Slot, {});
1166
- return /* @__PURE__ */ jsx6("span", { ...a.el("spinner", "throttle-spinner"), "aria-hidden": "true" });
1204
+ const cls = `throttle-spinner${centred ? " throttle-spinner--centred" : ""}`;
1205
+ return /* @__PURE__ */ jsx6("span", { ...a.el("spinner", cls), "aria-hidden": "true" });
1167
1206
  }
1168
1207
 
1169
1208
  // src/react/components/primitives/Button.tsx
@@ -1172,7 +1211,7 @@ function Button({ variant = "primary", size = "default", elementKey, loading, ch
1172
1211
  const a = useAppearance();
1173
1212
  const Slot = a.slots.Button;
1174
1213
  if (Slot) return /* @__PURE__ */ jsx7(Slot, { variant, loading, ...rest, children });
1175
- const base = `throttle-button throttle-button--${variant}${size === "xs" ? " throttle-button--xs" : ""}`;
1214
+ const base = `throttle-button throttle-button--${variant}${size === "xs" ? " throttle-button--xs" : ""}${loading ? " throttle-button--loading" : ""}`;
1176
1215
  return /* @__PURE__ */ jsxs2(
1177
1216
  "button",
1178
1217
  {
@@ -1180,9 +1219,10 @@ function Button({ variant = "primary", size = "default", elementKey, loading, ch
1180
1219
  ...rest,
1181
1220
  ...a.el(elementKey ?? "button", base),
1182
1221
  disabled: rest.disabled || loading,
1222
+ "aria-busy": loading ? true : void 0,
1183
1223
  children: [
1184
- loading ? /* @__PURE__ */ jsx7(Spinner, {}) : null,
1185
- children
1224
+ loading ? /* @__PURE__ */ jsx7(Spinner, { centred: true }) : null,
1225
+ /* @__PURE__ */ jsx7("span", { className: `throttle-button__label${loading ? " throttle-button__label--hidden" : ""}`, children })
1186
1226
  ]
1187
1227
  }
1188
1228
  );
@@ -1292,14 +1332,14 @@ function Modal(props) {
1292
1332
  e.preventDefault();
1293
1333
  return;
1294
1334
  }
1295
- const first = items[0];
1335
+ const first2 = items[0];
1296
1336
  const last = items[items.length - 1];
1297
- if (e.shiftKey && document.activeElement === first) {
1337
+ if (e.shiftKey && document.activeElement === first2) {
1298
1338
  e.preventDefault();
1299
1339
  last.focus();
1300
1340
  } else if (!e.shiftKey && document.activeElement === last) {
1301
1341
  e.preventDefault();
1302
- first.focus();
1342
+ first2.focus();
1303
1343
  }
1304
1344
  };
1305
1345
  document.addEventListener("keydown", onKeyDown);
@@ -2105,10 +2145,10 @@ function AuthModal(props) {
2105
2145
  }
2106
2146
 
2107
2147
  // src/react/components/account/AccountModal.tsx
2108
- import { useId as useId5 } from "react";
2148
+ import { useId as useId6 } from "react";
2109
2149
 
2110
2150
  // src/react/components/account/AccountDashboard.tsx
2111
- import { useEffect as useEffect8, useId as useId4, useState as useState18 } from "react";
2151
+ import { useEffect as useEffect9, useId as useId5, useState as useState20 } from "react";
2112
2152
 
2113
2153
  // src/react/components/account/VerifyEmailBanner.tsx
2114
2154
  import { useState as useState11 } from "react";
@@ -2224,7 +2264,7 @@ var ACCOUNT_ICONS = {
2224
2264
  };
2225
2265
 
2226
2266
  // src/react/components/account/ProfilePanel.tsx
2227
- import { useEffect as useEffect6, useState as useState12 } from "react";
2267
+ import { useEffect as useEffect6, useState as useState12, useRef as useRef5 } from "react";
2228
2268
 
2229
2269
  // src/react/components/account/PanelState.tsx
2230
2270
  import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
@@ -2260,16 +2300,16 @@ function ProfilePanel(props) {
2260
2300
  const { status } = useAuth();
2261
2301
  const resource = useCustomer();
2262
2302
  const { submitting, error, notice, run } = useAction();
2263
- const [form, setForm] = useState12({ firstName: "", lastName: "", phone: "", company: "", acceptsMarketing: false });
2303
+ const [form, setForm] = useState12({ firstName: "", lastName: "", phone: "", company: "" });
2304
+ const edited = useRef5(false);
2264
2305
  useEffect6(() => {
2265
2306
  const c = resource.data;
2266
- if (!c) return;
2307
+ if (!c || edited.current) return;
2267
2308
  setForm({
2268
2309
  firstName: c.firstName ?? "",
2269
2310
  lastName: c.lastName ?? "",
2270
2311
  phone: c.phone ?? "",
2271
- company: c.company ?? "",
2272
- acceptsMarketing: Boolean(c.acceptsMarketing)
2312
+ company: c.company ?? ""
2273
2313
  });
2274
2314
  }, [resource.data]);
2275
2315
  if (status === "unauthenticated") return null;
@@ -2287,12 +2327,12 @@ function ProfilePanel(props) {
2287
2327
  onSubmit: (e) => {
2288
2328
  e.preventDefault();
2289
2329
  void run(async () => {
2330
+ edited.current = false;
2290
2331
  await resource.update({
2291
2332
  firstName: form.firstName,
2292
2333
  lastName: form.lastName,
2293
2334
  phone: form.phone,
2294
- company: form.company || null,
2295
- acceptsMarketing: form.acceptsMarketing
2335
+ company: form.company || null
2296
2336
  });
2297
2337
  return t.profile.savedNotice;
2298
2338
  });
@@ -2316,7 +2356,10 @@ function ProfilePanel(props) {
2316
2356
  label: t.profile.firstName,
2317
2357
  value: form.firstName,
2318
2358
  autoComplete: "given-name",
2319
- onChange: (v) => setForm((f) => ({ ...f, firstName: v }))
2359
+ onChange: (v) => {
2360
+ edited.current = true;
2361
+ setForm((f) => ({ ...f, firstName: v }));
2362
+ }
2320
2363
  }
2321
2364
  ),
2322
2365
  /* @__PURE__ */ jsx29(
@@ -2325,7 +2368,10 @@ function ProfilePanel(props) {
2325
2368
  label: t.profile.lastName,
2326
2369
  value: form.lastName,
2327
2370
  autoComplete: "family-name",
2328
- onChange: (v) => setForm((f) => ({ ...f, lastName: v }))
2371
+ onChange: (v) => {
2372
+ edited.current = true;
2373
+ setForm((f) => ({ ...f, lastName: v }));
2374
+ }
2329
2375
  }
2330
2376
  ),
2331
2377
  /* @__PURE__ */ jsx29(
@@ -2335,7 +2381,10 @@ function ProfilePanel(props) {
2335
2381
  type: "tel",
2336
2382
  value: form.phone,
2337
2383
  autoComplete: "tel",
2338
- onChange: (v) => setForm((f) => ({ ...f, phone: v }))
2384
+ onChange: (v) => {
2385
+ edited.current = true;
2386
+ setForm((f) => ({ ...f, phone: v }));
2387
+ }
2339
2388
  }
2340
2389
  ),
2341
2390
  /* @__PURE__ */ jsx29(
@@ -2344,20 +2393,12 @@ function ProfilePanel(props) {
2344
2393
  label: t.profile.company,
2345
2394
  value: form.company,
2346
2395
  autoComplete: "organization",
2347
- onChange: (v) => setForm((f) => ({ ...f, company: v }))
2396
+ onChange: (v) => {
2397
+ edited.current = true;
2398
+ setForm((f) => ({ ...f, company: v }));
2399
+ }
2348
2400
  }
2349
2401
  ),
2350
- /* @__PURE__ */ jsxs20("label", { className: "throttle-row", children: [
2351
- /* @__PURE__ */ jsx29(
2352
- "input",
2353
- {
2354
- type: "checkbox",
2355
- checked: form.acceptsMarketing,
2356
- onChange: (e) => setForm((f) => ({ ...f, acceptsMarketing: e.target.checked }))
2357
- }
2358
- ),
2359
- /* @__PURE__ */ jsx29("span", { children: t.profile.acceptsMarketing })
2360
- ] }),
2361
2402
  error ? /* @__PURE__ */ jsx29(Alert, { tone: "error", children: error }) : null,
2362
2403
  notice ? /* @__PURE__ */ jsx29(Alert, { tone: "success", children: notice }) : null,
2363
2404
  /* @__PURE__ */ jsx29(Button, { type: "submit", loading: submitting, elementKey: "profilePanel.submitButton", children: t.profile.saveButton })
@@ -2510,7 +2551,7 @@ function AddressesPanel(props) {
2510
2551
  })
2511
2552
  }
2512
2553
  ) : /* @__PURE__ */ jsxs22(Fragment5, { children: [
2513
- /* @__PURE__ */ jsx31(Button, { elementKey: "addressesPanel.addButton", variant: "secondary", onClick: () => setEditing("new"), children: t.addresses.addButton }),
2554
+ /* @__PURE__ */ jsx31("div", { children: /* @__PURE__ */ jsx31(Button, { elementKey: "addressesPanel.addButton", variant: "secondary", onClick: () => setEditing("new"), children: t.addresses.addButton }) }),
2514
2555
  /* @__PURE__ */ jsx31(
2515
2556
  PanelState,
2516
2557
  {
@@ -2617,7 +2658,102 @@ function AddressesPanel(props) {
2617
2658
  }
2618
2659
 
2619
2660
  // src/react/components/account/PaymentMethodsPanel.tsx
2661
+ import { useState as useState16 } from "react";
2662
+
2663
+ // src/react/components/account/AddCardDialog.tsx
2664
+ import { useEffect as useEffect7, useId as useId4, useRef as useRef6, useState as useState15 } from "react";
2620
2665
  import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
2666
+ function AddCardDialog(props) {
2667
+ const { account } = useAuth();
2668
+ const titleId = useId4();
2669
+ const { t } = useCopy(props.localization);
2670
+ const [src, setSrc] = useState15(null);
2671
+ const [error, setError] = useState15(null);
2672
+ const [busy, setBusy] = useState15(false);
2673
+ const onAdded = useRef6(props.onAdded);
2674
+ const onClose = useRef6(props.onClose);
2675
+ onAdded.current = props.onAdded;
2676
+ onClose.current = props.onClose;
2677
+ useEffect7(() => {
2678
+ if (!props.open) {
2679
+ setSrc(null);
2680
+ setError(null);
2681
+ return;
2682
+ }
2683
+ let live = true;
2684
+ setError(null);
2685
+ account.startCardSetup().then(
2686
+ (session) => {
2687
+ if (!live) return;
2688
+ let url = session.embedUrl;
2689
+ try {
2690
+ const u = new URL(session.embedUrl, window.location.origin);
2691
+ u.searchParams.set("parentOrigin", window.location.origin);
2692
+ url = u.toString();
2693
+ } catch {
2694
+ }
2695
+ setSrc(url);
2696
+ },
2697
+ (err) => {
2698
+ if (live) setError(messageForError(err));
2699
+ }
2700
+ );
2701
+ return () => {
2702
+ live = false;
2703
+ };
2704
+ }, [props.open, account]);
2705
+ useEffect7(() => {
2706
+ if (!src) return;
2707
+ const frameOrigin = (() => {
2708
+ try {
2709
+ return new URL(src).origin;
2710
+ } catch {
2711
+ return null;
2712
+ }
2713
+ })();
2714
+ if (!frameOrigin) return;
2715
+ async function onMessage(event) {
2716
+ if (event.origin !== frameOrigin) return;
2717
+ const data = event.data;
2718
+ if (!data || typeof data.type !== "string") return;
2719
+ if (data.type === "throttle.completed" && data.paymentId) {
2720
+ setBusy(true);
2721
+ try {
2722
+ await account.confirmCardSetup(data.paymentId);
2723
+ onAdded.current();
2724
+ onClose.current();
2725
+ } catch (err) {
2726
+ setError(messageForError(err));
2727
+ } finally {
2728
+ setBusy(false);
2729
+ }
2730
+ } else if (data.type === "throttle.error") {
2731
+ setError(data.message || t.common.somethingWentWrong);
2732
+ } else if (data.type === "throttle.cancelled") {
2733
+ onClose.current();
2734
+ }
2735
+ }
2736
+ window.addEventListener("message", onMessage);
2737
+ return () => window.removeEventListener("message", onMessage);
2738
+ }, [src, account, t]);
2739
+ if (!props.open) return null;
2740
+ return /* @__PURE__ */ jsxs23(Modal, { open: true, onClose: props.onClose, labelledBy: titleId, children: [
2741
+ /* @__PURE__ */ jsx32("h2", { id: titleId, children: t.paymentMethods.addTitle }),
2742
+ error ? /* @__PURE__ */ jsx32(Alert, { tone: "error", children: error }) : null,
2743
+ busy ? /* @__PURE__ */ jsx32("div", { className: "throttle-centre", children: /* @__PURE__ */ jsx32(Spinner, {}) }) : src ? /* @__PURE__ */ jsx32(
2744
+ "iframe",
2745
+ {
2746
+ className: "throttle-cardframe",
2747
+ src,
2748
+ title: t.paymentMethods.addTitle,
2749
+ sandbox: "allow-scripts allow-forms allow-same-origin"
2750
+ }
2751
+ ) : !error ? /* @__PURE__ */ jsx32("div", { className: "throttle-centre", children: /* @__PURE__ */ jsx32(Spinner, {}) }) : null
2752
+ ] });
2753
+ }
2754
+
2755
+ // src/react/components/account/PaymentMethodsPanel.tsx
2756
+ import { jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
2621
2757
  function PaymentMethodsPanel(props) {
2622
2758
  const a = useAppearance(props.appearance);
2623
2759
  const scoped = useAppearanceProviderValue(props.appearance);
@@ -2625,6 +2761,7 @@ function PaymentMethodsPanel(props) {
2625
2761
  const { emailVerified } = useAuth();
2626
2762
  const resource = useSavedCards();
2627
2763
  const { submitting, error, run } = useAction();
2764
+ const [adding, setAdding] = useState16(false);
2628
2765
  const variant = props.variant ?? "rows";
2629
2766
  const rowsVariant = variant === "rows";
2630
2767
  const listBase = rowsVariant ? "throttle-rows" : "throttle-stack";
@@ -2632,9 +2769,21 @@ function PaymentMethodsPanel(props) {
2632
2769
  const actionVariant = (base) => rowsVariant ? base === "danger" ? "linkDanger" : "link" : base;
2633
2770
  const cardLabel = (card) => `${(card.cardBrand ?? card.methodType).toUpperCase()} \u2022\u2022\u2022\u2022 ${card.cardLastFour ?? "____"}`;
2634
2771
  const expiryLabel = (card) => card.cardExpMonth && card.cardExpYear ? `${String(card.cardExpMonth).padStart(2, "0")}/${card.cardExpYear}` : "";
2635
- return /* @__PURE__ */ jsx32(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx32("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs23("div", { ...a.el("paymentMethodsPanel.root", "throttle-panel"), children: [
2636
- error ? /* @__PURE__ */ jsx32(Alert, { tone: "error", children: error }) : null,
2637
- /* @__PURE__ */ jsx32(
2772
+ return /* @__PURE__ */ jsx33(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx33("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs24("div", { ...a.el("paymentMethodsPanel.root", "throttle-panel"), children: [
2773
+ error ? /* @__PURE__ */ jsx33(Alert, { tone: "error", children: error }) : null,
2774
+ emailVerified ? /* @__PURE__ */ jsx33("div", { children: /* @__PURE__ */ jsx33(Button, { elementKey: "paymentMethodsPanel.addButton", variant: "secondary", onClick: () => setAdding(true), children: t.paymentMethods.addButton }) }) : null,
2775
+ /* @__PURE__ */ jsx33(
2776
+ AddCardDialog,
2777
+ {
2778
+ open: adding,
2779
+ onClose: () => setAdding(false),
2780
+ onAdded: () => {
2781
+ void resource.refetch();
2782
+ },
2783
+ localization: props.localization
2784
+ }
2785
+ ),
2786
+ /* @__PURE__ */ jsx33(
2638
2787
  PanelState,
2639
2788
  {
2640
2789
  resource,
@@ -2643,7 +2792,7 @@ function PaymentMethodsPanel(props) {
2643
2792
  isEmpty: (rows) => rows.length === 0,
2644
2793
  emptyTitle: t.paymentMethods.empty,
2645
2794
  emptyDescription: t.paymentMethods.emptyDescription,
2646
- children: (rows) => variant === "table" ? /* @__PURE__ */ jsx32(
2795
+ children: (rows) => variant === "table" ? /* @__PURE__ */ jsx33(
2647
2796
  DataTable,
2648
2797
  {
2649
2798
  tableKey: "paymentMethodsPanel.table",
@@ -2653,9 +2802,9 @@ function PaymentMethodsPanel(props) {
2653
2802
  columns: [
2654
2803
  { key: "card", label: t.paymentMethods.columnCard, render: (card) => cardLabel(card) },
2655
2804
  { key: "expires", label: t.paymentMethods.expires, render: (card) => expiryLabel(card) },
2656
- { key: "default", label: t.paymentMethods.defaultBadge, render: (card) => card.isDefault ? /* @__PURE__ */ jsx32(Badge, { tone: "success", children: t.paymentMethods.defaultBadge }) : null },
2657
- { key: "actions", label: t.common.actions, render: (card) => /* @__PURE__ */ jsxs23("div", { className: "throttle-actions", children: [
2658
- !card.isDefault ? /* @__PURE__ */ jsx32(
2805
+ { key: "default", label: t.paymentMethods.defaultBadge, render: (card) => card.isDefault ? /* @__PURE__ */ jsx33(Badge, { tone: "success", children: t.paymentMethods.defaultBadge }) : null },
2806
+ { key: "actions", label: t.common.actions, render: (card) => /* @__PURE__ */ jsxs24("div", { className: "throttle-actions", children: [
2807
+ !card.isDefault ? /* @__PURE__ */ jsx33(
2659
2808
  Button,
2660
2809
  {
2661
2810
  variant: "secondary",
@@ -2665,7 +2814,7 @@ function PaymentMethodsPanel(props) {
2665
2814
  children: t.paymentMethods.makeDefault
2666
2815
  }
2667
2816
  ) : null,
2668
- /* @__PURE__ */ jsx32(
2817
+ /* @__PURE__ */ jsx33(
2669
2818
  Button,
2670
2819
  {
2671
2820
  variant: "danger",
@@ -2681,13 +2830,13 @@ function PaymentMethodsPanel(props) {
2681
2830
  ] }) }
2682
2831
  ]
2683
2832
  }
2684
- ) : /* @__PURE__ */ jsx32("div", { ...a.el("paymentMethodsPanel.list", listBase), children: rows.map((card) => /* @__PURE__ */ jsxs23("div", { ...a.el("paymentMethodsPanel.item", itemBase), children: [
2685
- /* @__PURE__ */ jsxs23("div", { children: [
2686
- /* @__PURE__ */ jsxs23("div", { className: "throttle-row", children: [
2687
- /* @__PURE__ */ jsx32("strong", { children: cardLabel(card) }),
2688
- card.isDefault ? /* @__PURE__ */ jsx32(Badge, { tone: "success", children: t.paymentMethods.defaultBadge }) : null
2833
+ ) : /* @__PURE__ */ jsx33("div", { ...a.el("paymentMethodsPanel.list", listBase), children: rows.map((card) => /* @__PURE__ */ jsxs24("div", { ...a.el("paymentMethodsPanel.item", itemBase), children: [
2834
+ /* @__PURE__ */ jsxs24("div", { children: [
2835
+ /* @__PURE__ */ jsxs24("div", { className: "throttle-row", children: [
2836
+ /* @__PURE__ */ jsx33("strong", { children: cardLabel(card) }),
2837
+ card.isDefault ? /* @__PURE__ */ jsx33(Badge, { tone: "success", children: t.paymentMethods.defaultBadge }) : null
2689
2838
  ] }),
2690
- card.cardExpMonth && card.cardExpYear ? /* @__PURE__ */ jsxs23("p", { className: "throttle-muted", children: [
2839
+ card.cardExpMonth && card.cardExpYear ? /* @__PURE__ */ jsxs24("p", { className: "throttle-muted", children: [
2691
2840
  t.paymentMethods.expires,
2692
2841
  " ",
2693
2842
  String(card.cardExpMonth).padStart(2, "0"),
@@ -2695,8 +2844,8 @@ function PaymentMethodsPanel(props) {
2695
2844
  card.cardExpYear
2696
2845
  ] }) : null
2697
2846
  ] }),
2698
- /* @__PURE__ */ jsxs23("div", { className: "throttle-actions", children: [
2699
- !card.isDefault ? /* @__PURE__ */ jsx32(
2847
+ /* @__PURE__ */ jsxs24("div", { className: "throttle-actions", children: [
2848
+ !card.isDefault ? /* @__PURE__ */ jsx33(
2700
2849
  Button,
2701
2850
  {
2702
2851
  variant: actionVariant("secondary"),
@@ -2706,7 +2855,7 @@ function PaymentMethodsPanel(props) {
2706
2855
  children: t.paymentMethods.makeDefault
2707
2856
  }
2708
2857
  ) : null,
2709
- /* @__PURE__ */ jsx32(
2858
+ /* @__PURE__ */ jsx33(
2710
2859
  Button,
2711
2860
  {
2712
2861
  variant: actionVariant("danger"),
@@ -2727,7 +2876,7 @@ function PaymentMethodsPanel(props) {
2727
2876
  }
2728
2877
 
2729
2878
  // src/react/components/account/OrdersPanel.tsx
2730
- import { useState as useState15 } from "react";
2879
+ import { useState as useState17 } from "react";
2731
2880
 
2732
2881
  // src/react/components/format.ts
2733
2882
  function formatMoney(minorUnits, currency, locale) {
@@ -2759,7 +2908,7 @@ function formatDate(value, locale) {
2759
2908
  }
2760
2909
 
2761
2910
  // src/react/components/account/OrderStatus.tsx
2762
- import { Fragment as Fragment6, jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
2911
+ import { Fragment as Fragment6, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2763
2912
  function copyKey(wire) {
2764
2913
  return wire.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
2765
2914
  }
@@ -2767,25 +2916,25 @@ var ATTENTION_PAYMENT_STATES = /* @__PURE__ */ new Set(["pending", "failed", "di
2767
2916
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["cancelled", "closed", "void", "expired", "voided"]);
2768
2917
  function StatusBadge(props) {
2769
2918
  const label = props.labels[copyKey(props.status)] ?? props.status.replace(/_/g, " ");
2770
- return /* @__PURE__ */ jsx33(Badge, { tone: TERMINAL_STATUSES.has(props.status) ? "muted" : "neutral", children: label });
2919
+ return /* @__PURE__ */ jsx34(Badge, { tone: TERMINAL_STATUSES.has(props.status) ? "muted" : "neutral", children: label });
2771
2920
  }
2772
2921
  function OrderStatus(props) {
2773
2922
  const labels = props.t.orders.statusLabels;
2774
2923
  const payLabels = props.t.orders.paymentLabels;
2775
2924
  const lifecycle = labels[copyKey(props.status)] ?? props.status.replace(/_/g, " ");
2776
2925
  const money = props.paymentStatus ? payLabels[copyKey(props.paymentStatus)] : void 0;
2777
- return /* @__PURE__ */ jsxs24(Fragment6, { children: [
2778
- /* @__PURE__ */ jsx33(Badge, { tone: TERMINAL_STATUSES.has(props.status) ? "muted" : "neutral", children: lifecycle }),
2779
- money ? /* @__PURE__ */ jsx33(Badge, { tone: ATTENTION_PAYMENT_STATES.has(props.paymentStatus) ? "warning" : "neutral", children: money }) : null
2926
+ return /* @__PURE__ */ jsxs25(Fragment6, { children: [
2927
+ /* @__PURE__ */ jsx34(Badge, { tone: TERMINAL_STATUSES.has(props.status) ? "muted" : "neutral", children: lifecycle }),
2928
+ money ? /* @__PURE__ */ jsx34(Badge, { tone: ATTENTION_PAYMENT_STATES.has(props.paymentStatus) ? "warning" : "neutral", children: money }) : null
2780
2929
  ] });
2781
2930
  }
2782
2931
 
2783
2932
  // src/react/components/account/OrderDetail.tsx
2784
- import { Fragment as Fragment7, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2933
+ import { Fragment as Fragment7, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
2785
2934
  function Line(props) {
2786
- return /* @__PURE__ */ jsxs25("div", { className: "throttle-row", children: [
2787
- /* @__PURE__ */ jsx34("span", { className: "throttle-muted", children: props.label }),
2788
- /* @__PURE__ */ jsx34("span", { children: props.value })
2935
+ return /* @__PURE__ */ jsxs26("div", { className: "throttle-row", children: [
2936
+ /* @__PURE__ */ jsx35("span", { className: "throttle-muted", children: props.label }),
2937
+ /* @__PURE__ */ jsx35("span", { children: props.value })
2789
2938
  ] });
2790
2939
  }
2791
2940
  function OrderDetail(props) {
@@ -2793,27 +2942,35 @@ function OrderDetail(props) {
2793
2942
  const scoped = useAppearanceProviderValue(props.appearance);
2794
2943
  const { t, locale } = useCopy(props.localization);
2795
2944
  const resource = useOrder(props.orderId);
2796
- return /* @__PURE__ */ jsx34(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx34("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs25("div", { ...a.el("orderDetail.root", "throttle-panel"), children: [
2797
- props.onBack ? /* @__PURE__ */ jsx34(Button, { variant: "link", elementKey: "orderDetail.backButton", onClick: props.onBack, children: t.common.back }) : null,
2798
- /* @__PURE__ */ jsx34(
2945
+ return /* @__PURE__ */ jsx35(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx35("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs26("div", { ...a.el("orderDetail.root", "throttle-panel"), children: [
2946
+ props.onBack ? (
2947
+ // Wrapped on purpose. The panel is a column flex container, so a
2948
+ // direct child stretches to its full width however `width: auto`
2949
+ // the link variant is — the control rendered 748px wide with a
2950
+ // centred label. The wrapper takes the stretch; the button keeps
2951
+ // its own width. A CSS fix would need a compound selector, and
2952
+ // those outrank the merchant overrides in `appearance.elements`.
2953
+ /* @__PURE__ */ jsx35("div", { children: /* @__PURE__ */ jsx35(Button, { variant: "link", elementKey: "orderDetail.backButton", onClick: props.onBack, children: t.common.back }) })
2954
+ ) : null,
2955
+ /* @__PURE__ */ jsx35(
2799
2956
  PanelState,
2800
2957
  {
2801
2958
  resource,
2802
2959
  isEmpty: (o) => o === null,
2803
2960
  emptyTitle: t.orders.empty,
2804
2961
  skeletonRows: 5,
2805
- children: (order) => /* @__PURE__ */ jsxs25(Fragment7, { children: [
2806
- /* @__PURE__ */ jsxs25("div", { className: "throttle-row", children: [
2807
- /* @__PURE__ */ jsx34("h3", { children: order.orderNumber }),
2808
- /* @__PURE__ */ jsx34(OrderStatus, { status: order.status, paymentStatus: order.paymentStatus, t })
2962
+ children: (order) => /* @__PURE__ */ jsxs26(Fragment7, { children: [
2963
+ /* @__PURE__ */ jsxs26("div", { className: "throttle-row", children: [
2964
+ /* @__PURE__ */ jsx35("h3", { children: order.orderNumber }),
2965
+ /* @__PURE__ */ jsx35(OrderStatus, { status: order.status, paymentStatus: order.paymentStatus, t })
2809
2966
  ] }),
2810
- /* @__PURE__ */ jsx34("p", { className: "throttle-muted", children: formatDate(order.createdAt, locale) }),
2811
- /* @__PURE__ */ jsx34("div", { ...a.el("orderDetail.lineItems", "throttle-stack"), children: order.lineItems.map((item) => /* @__PURE__ */ jsxs25("div", { ...a.el("orderDetail.lineItem", "throttle-lineitem"), children: [
2812
- item.imageUrl ? /* @__PURE__ */ jsx34("img", { className: "throttle-lineitem__image", src: item.imageUrl, alt: "" }) : null,
2813
- /* @__PURE__ */ jsxs25("div", { style: { flex: 1 }, children: [
2814
- /* @__PURE__ */ jsx34("strong", { children: item.name }),
2815
- item.description ? /* @__PURE__ */ jsx34("p", { className: "throttle-muted", children: item.description }) : null,
2816
- /* @__PURE__ */ jsxs25("p", { className: "throttle-muted", children: [
2967
+ /* @__PURE__ */ jsx35("p", { className: "throttle-muted", children: formatDate(order.createdAt, locale) }),
2968
+ /* @__PURE__ */ jsx35("div", { ...a.el("orderDetail.lineItems", "throttle-stack"), children: order.lineItems.map((item) => /* @__PURE__ */ jsxs26("div", { ...a.el("orderDetail.lineItem", "throttle-lineitem"), children: [
2969
+ item.imageUrl ? /* @__PURE__ */ jsx35("img", { className: "throttle-lineitem__image", src: item.imageUrl, alt: "" }) : null,
2970
+ /* @__PURE__ */ jsxs26("div", { style: { flex: 1 }, children: [
2971
+ /* @__PURE__ */ jsx35("strong", { children: item.name }),
2972
+ item.description ? /* @__PURE__ */ jsx35("p", { className: "throttle-muted", children: item.description }) : null,
2973
+ /* @__PURE__ */ jsxs26("p", { className: "throttle-muted", children: [
2817
2974
  t.orders.quantity,
2818
2975
  " ",
2819
2976
  item.quantity,
@@ -2821,16 +2978,16 @@ function OrderDetail(props) {
2821
2978
  formatMoney(item.unitPrice, order.currency, locale)
2822
2979
  ] })
2823
2980
  ] }),
2824
- /* @__PURE__ */ jsx34("span", { children: formatMoney(item.total, order.currency, locale) })
2981
+ /* @__PURE__ */ jsx35("span", { children: formatMoney(item.total, order.currency, locale) })
2825
2982
  ] }, item.id)) }),
2826
- /* @__PURE__ */ jsxs25("div", { ...a.el("orderDetail.totals", "throttle-totals"), children: [
2827
- /* @__PURE__ */ jsx34(Line, { label: t.orders.subtotal, value: formatMoney(order.subtotal, order.currency, locale) }),
2828
- order.discountTotal ? /* @__PURE__ */ jsx34(Line, { label: t.orders.discount, value: formatMoney(-order.discountTotal, order.currency, locale) }) : null,
2829
- /* @__PURE__ */ jsx34(Line, { label: t.orders.shipping, value: formatMoney(order.shippingTotal, order.currency, locale) }),
2830
- /* @__PURE__ */ jsx34(Line, { label: t.orders.tax, value: formatMoney(order.taxTotal, order.currency, locale) }),
2831
- /* @__PURE__ */ jsx34(Line, { label: t.orders.total, value: formatMoney(order.total, order.currency, locale) })
2983
+ /* @__PURE__ */ jsxs26("div", { ...a.el("orderDetail.totals", "throttle-totals"), children: [
2984
+ /* @__PURE__ */ jsx35(Line, { label: t.orders.subtotal, value: formatMoney(order.subtotal, order.currency, locale) }),
2985
+ order.discountTotal ? /* @__PURE__ */ jsx35(Line, { label: t.orders.discount, value: formatMoney(-order.discountTotal, order.currency, locale) }) : null,
2986
+ /* @__PURE__ */ jsx35(Line, { label: t.orders.shipping, value: formatMoney(order.shippingTotal, order.currency, locale) }),
2987
+ /* @__PURE__ */ jsx35(Line, { label: t.orders.tax, value: formatMoney(order.taxTotal, order.currency, locale) }),
2988
+ /* @__PURE__ */ jsx35(Line, { label: t.orders.total, value: formatMoney(order.total, order.currency, locale) })
2832
2989
  ] }),
2833
- order.subscriptionId && props.onViewSubscription ? /* @__PURE__ */ jsx34(Button, { variant: "secondary", onClick: () => props.onViewSubscription(order.subscriptionId), children: t.orders.viewSubscription }) : null
2990
+ order.subscriptionId && props.onViewSubscription ? /* @__PURE__ */ jsx35(Button, { variant: "secondary", onClick: () => props.onViewSubscription(order.subscriptionId), children: t.orders.viewSubscription }) : null
2834
2991
  ] })
2835
2992
  }
2836
2993
  )
@@ -2838,20 +2995,20 @@ function OrderDetail(props) {
2838
2995
  }
2839
2996
 
2840
2997
  // src/react/components/account/OrdersPanel.tsx
2841
- import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
2998
+ import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
2842
2999
  function OrdersPanel(props) {
2843
3000
  const a = useAppearance(props.appearance);
2844
3001
  const scoped = useAppearanceProviderValue(props.appearance);
2845
3002
  const { t, locale } = useCopy(props.localization);
2846
3003
  const { emailVerified } = useAuth();
2847
3004
  const resource = useOrders();
2848
- const [openId, setOpenId] = useState15(null);
3005
+ const [openId, setOpenId] = useState17(null);
2849
3006
  const variant = props.variant ?? "table";
2850
3007
  const rowsVariant = variant === "rows";
2851
3008
  const listBase = rowsVariant ? "throttle-rows" : "throttle-stack";
2852
3009
  const itemBase = rowsVariant ? "throttle-rowitem" : "throttle-listitem";
2853
3010
  if (openId) {
2854
- return /* @__PURE__ */ jsx35(
3011
+ return /* @__PURE__ */ jsx36(
2855
3012
  OrderDetail,
2856
3013
  {
2857
3014
  orderId: openId,
@@ -2862,7 +3019,7 @@ function OrdersPanel(props) {
2862
3019
  }
2863
3020
  );
2864
3021
  }
2865
- return /* @__PURE__ */ jsx35(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx35("div", { ...a.rootProps, children: /* @__PURE__ */ jsx35("div", { ...a.el("ordersPanel.root", "throttle-panel"), children: /* @__PURE__ */ jsx35(
3022
+ return /* @__PURE__ */ jsx36(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx36("div", { ...a.rootProps, children: /* @__PURE__ */ jsx36("div", { ...a.el("ordersPanel.root", "throttle-panel"), children: /* @__PURE__ */ jsx36(
2866
3023
  PanelState,
2867
3024
  {
2868
3025
  resource,
@@ -2871,7 +3028,7 @@ function OrdersPanel(props) {
2871
3028
  isEmpty: (rows) => rows.length === 0,
2872
3029
  emptyTitle: t.orders.empty,
2873
3030
  emptyDescription: t.orders.emptyDescription,
2874
- children: (rows) => variant === "table" ? /* @__PURE__ */ jsx35(
3031
+ children: (rows) => variant === "table" ? /* @__PURE__ */ jsx36(
2875
3032
  DataTable,
2876
3033
  {
2877
3034
  tableKey: "ordersPanel.table",
@@ -2885,25 +3042,25 @@ function OrdersPanel(props) {
2885
3042
  {
2886
3043
  key: "status",
2887
3044
  label: t.orders.status,
2888
- render: (o) => /* @__PURE__ */ jsx35(OrderStatus, { status: o.status, paymentStatus: o.paymentStatus, t })
3045
+ render: (o) => /* @__PURE__ */ jsx36(OrderStatus, { status: o.status, paymentStatus: o.paymentStatus, t })
2889
3046
  },
2890
3047
  {
2891
3048
  key: "total",
2892
3049
  label: t.orders.total,
2893
- render: (o) => /* @__PURE__ */ jsx35("span", { className: "throttle-table__money", children: formatMoney(o.total, o.currency, locale) })
3050
+ render: (o) => /* @__PURE__ */ jsx36("span", { className: "throttle-table__money", children: formatMoney(o.total, o.currency, locale) })
2894
3051
  }
2895
3052
  ]
2896
3053
  }
2897
- ) : /* @__PURE__ */ jsx35("div", { ...a.el("ordersPanel.list", listBase), children: rows.map((o) => /* @__PURE__ */ jsxs26("div", { ...a.el("ordersPanel.item", itemBase), children: [
2898
- /* @__PURE__ */ jsxs26("div", { children: [
2899
- /* @__PURE__ */ jsxs26("div", { className: "throttle-row", children: [
2900
- /* @__PURE__ */ jsx35("strong", { children: o.orderNumber }),
2901
- /* @__PURE__ */ jsx35(OrderStatus, { status: o.status, paymentStatus: o.paymentStatus, t })
3054
+ ) : /* @__PURE__ */ jsx36("div", { ...a.el("ordersPanel.list", listBase), children: rows.map((o) => /* @__PURE__ */ jsxs27("div", { ...a.el("ordersPanel.item", itemBase), children: [
3055
+ /* @__PURE__ */ jsxs27("div", { children: [
3056
+ /* @__PURE__ */ jsxs27("div", { className: "throttle-row", children: [
3057
+ /* @__PURE__ */ jsx36("strong", { children: o.orderNumber }),
3058
+ /* @__PURE__ */ jsx36(OrderStatus, { status: o.status, paymentStatus: o.paymentStatus, t })
2902
3059
  ] }),
2903
- /* @__PURE__ */ jsx35("p", { className: "throttle-muted", children: formatDate(o.createdAt, locale) }),
2904
- /* @__PURE__ */ jsx35("p", { className: "throttle-muted", children: formatMoney(o.total, o.currency, locale) })
3060
+ /* @__PURE__ */ jsx36("p", { className: "throttle-muted", children: formatDate(o.createdAt, locale) }),
3061
+ /* @__PURE__ */ jsx36("p", { className: "throttle-muted", children: formatMoney(o.total, o.currency, locale) })
2905
3062
  ] }),
2906
- /* @__PURE__ */ jsx35("div", { className: "throttle-actions", children: /* @__PURE__ */ jsx35(
3063
+ /* @__PURE__ */ jsx36("div", { className: "throttle-actions", children: /* @__PURE__ */ jsx36(
2907
3064
  Button,
2908
3065
  {
2909
3066
  variant: rowsVariant ? "link" : "secondary",
@@ -2918,14 +3075,14 @@ function OrdersPanel(props) {
2918
3075
  }
2919
3076
 
2920
3077
  // src/react/components/account/InvoicesPanel.tsx
2921
- import { useState as useState16 } from "react";
3078
+ import { useState as useState18 } from "react";
2922
3079
 
2923
3080
  // src/react/components/account/InvoiceDetail.tsx
2924
- import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
3081
+ import { Fragment as Fragment8, jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
2925
3082
  function Line2(props) {
2926
- return /* @__PURE__ */ jsxs27("div", { className: "throttle-row", children: [
2927
- /* @__PURE__ */ jsx36("span", { className: "throttle-muted", children: props.label }),
2928
- /* @__PURE__ */ jsx36("span", { children: props.value })
3083
+ return /* @__PURE__ */ jsxs28("div", { className: "throttle-row", children: [
3084
+ /* @__PURE__ */ jsx37("span", { className: "throttle-muted", children: props.label }),
3085
+ /* @__PURE__ */ jsx37("span", { children: props.value })
2929
3086
  ] });
2930
3087
  }
2931
3088
  function InvoiceDetail(props) {
@@ -2935,25 +3092,33 @@ function InvoiceDetail(props) {
2935
3092
  const { account } = useAuth();
2936
3093
  const resource = useInvoice(props.invoiceId);
2937
3094
  const { submitting, error, run } = useAction();
2938
- return /* @__PURE__ */ jsx36(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx36("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs27("div", { ...a.el("invoiceDetail.root", "throttle-panel"), children: [
2939
- props.onBack ? /* @__PURE__ */ jsx36(Button, { variant: "link", elementKey: "invoiceDetail.backButton", onClick: props.onBack, children: t.common.back }) : null,
2940
- /* @__PURE__ */ jsx36(PanelState, { resource, isEmpty: (i) => i === null, emptyTitle: t.invoices.empty, skeletonRows: 4, children: (invoice) => /* @__PURE__ */ jsxs27(Fragment8, { children: [
2941
- /* @__PURE__ */ jsxs27("div", { className: "throttle-row", children: [
2942
- /* @__PURE__ */ jsx36("h3", { children: invoice.number }),
2943
- /* @__PURE__ */ jsx36(StatusBadge, { status: invoice.status, labels: t.invoices.statusLabels })
3095
+ return /* @__PURE__ */ jsx37(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx37("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs28("div", { ...a.el("invoiceDetail.root", "throttle-panel"), children: [
3096
+ props.onBack ? (
3097
+ // Wrapped on purpose. The panel is a column flex container, so a
3098
+ // direct child stretches to its full width however `width: auto`
3099
+ // the link variant is — the control rendered 748px wide with a
3100
+ // centred label. The wrapper takes the stretch; the button keeps
3101
+ // its own width. A CSS fix would need a compound selector, and
3102
+ // those outrank the merchant overrides in `appearance.elements`.
3103
+ /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsx37(Button, { variant: "link", elementKey: "invoiceDetail.backButton", onClick: props.onBack, children: t.common.back }) })
3104
+ ) : null,
3105
+ /* @__PURE__ */ jsx37(PanelState, { resource, isEmpty: (i) => i === null, emptyTitle: t.invoices.empty, skeletonRows: 4, children: (invoice) => /* @__PURE__ */ jsxs28(Fragment8, { children: [
3106
+ /* @__PURE__ */ jsxs28("div", { className: "throttle-row", children: [
3107
+ /* @__PURE__ */ jsx37("h3", { children: invoice.number }),
3108
+ /* @__PURE__ */ jsx37(StatusBadge, { status: invoice.status, labels: t.invoices.statusLabels })
2944
3109
  ] }),
2945
- /* @__PURE__ */ jsxs27("div", { ...a.el("invoiceDetail.totals", "throttle-totals"), children: [
2946
- /* @__PURE__ */ jsx36(Line2, { label: t.invoices.issued, value: formatDate(invoice.issuedAt, locale) }),
2947
- invoice.dueAt ? /* @__PURE__ */ jsx36(Line2, { label: t.invoices.due, value: formatDate(invoice.dueAt, locale) }) : null,
2948
- invoice.periodStart && invoice.periodEnd ? /* @__PURE__ */ jsx36(
3110
+ /* @__PURE__ */ jsxs28("div", { ...a.el("invoiceDetail.totals", "throttle-totals"), children: [
3111
+ /* @__PURE__ */ jsx37(Line2, { label: t.invoices.issued, value: formatDate(invoice.issuedAt, locale) }),
3112
+ invoice.dueAt ? /* @__PURE__ */ jsx37(Line2, { label: t.invoices.due, value: formatDate(invoice.dueAt, locale) }) : null,
3113
+ invoice.periodStart && invoice.periodEnd ? /* @__PURE__ */ jsx37(
2949
3114
  Line2,
2950
3115
  {
2951
3116
  label: t.invoices.period,
2952
3117
  value: `${formatDate(invoice.periodStart, locale)} \u2013 ${formatDate(invoice.periodEnd, locale)}`
2953
3118
  }
2954
3119
  ) : null,
2955
- /* @__PURE__ */ jsx36(Line2, { label: t.invoices.total, value: formatMoney(invoice.total, invoice.currency, locale) }),
2956
- invoice.amountRefunded ? /* @__PURE__ */ jsx36(
3120
+ /* @__PURE__ */ jsx37(Line2, { label: t.invoices.total, value: formatMoney(invoice.total, invoice.currency, locale) }),
3121
+ invoice.amountRefunded ? /* @__PURE__ */ jsx37(
2957
3122
  Line2,
2958
3123
  {
2959
3124
  label: t.invoices.refunded,
@@ -2961,8 +3126,8 @@ function InvoiceDetail(props) {
2961
3126
  }
2962
3127
  ) : null
2963
3128
  ] }),
2964
- error ? /* @__PURE__ */ jsx36(Alert, { tone: "error", children: error }) : null,
2965
- /* @__PURE__ */ jsx36(
3129
+ error ? /* @__PURE__ */ jsx37(Alert, { tone: "error", children: error }) : null,
3130
+ /* @__PURE__ */ jsx37(
2966
3131
  Button,
2967
3132
  {
2968
3133
  variant: "secondary",
@@ -2981,20 +3146,20 @@ function InvoiceDetail(props) {
2981
3146
  }
2982
3147
 
2983
3148
  // src/react/components/account/InvoicesPanel.tsx
2984
- import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
3149
+ import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
2985
3150
  function InvoicesPanel(props) {
2986
3151
  const a = useAppearance(props.appearance);
2987
3152
  const scoped = useAppearanceProviderValue(props.appearance);
2988
3153
  const { t, locale } = useCopy(props.localization);
2989
3154
  const { emailVerified } = useAuth();
2990
3155
  const resource = useInvoices();
2991
- const [openId, setOpenId] = useState16(null);
3156
+ const [openId, setOpenId] = useState18(null);
2992
3157
  const variant = props.variant ?? "table";
2993
3158
  const rowsVariant = variant === "rows";
2994
3159
  const listBase = rowsVariant ? "throttle-rows" : "throttle-stack";
2995
3160
  const itemBase = rowsVariant ? "throttle-rowitem" : "throttle-listitem";
2996
3161
  if (openId) {
2997
- return /* @__PURE__ */ jsx37(
3162
+ return /* @__PURE__ */ jsx38(
2998
3163
  InvoiceDetail,
2999
3164
  {
3000
3165
  invoiceId: openId,
@@ -3004,7 +3169,7 @@ function InvoicesPanel(props) {
3004
3169
  }
3005
3170
  );
3006
3171
  }
3007
- return /* @__PURE__ */ jsx37(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx37("div", { ...a.rootProps, children: /* @__PURE__ */ jsx37("div", { ...a.el("invoicesPanel.root", "throttle-panel"), children: /* @__PURE__ */ jsx37(
3172
+ return /* @__PURE__ */ jsx38(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx38("div", { ...a.rootProps, children: /* @__PURE__ */ jsx38("div", { ...a.el("invoicesPanel.root", "throttle-panel"), children: /* @__PURE__ */ jsx38(
3008
3173
  PanelState,
3009
3174
  {
3010
3175
  resource,
@@ -3013,7 +3178,7 @@ function InvoicesPanel(props) {
3013
3178
  isEmpty: (rows) => rows.length === 0,
3014
3179
  emptyTitle: t.invoices.empty,
3015
3180
  emptyDescription: t.invoices.emptyDescription,
3016
- children: (rows) => variant === "table" ? /* @__PURE__ */ jsx37(
3181
+ children: (rows) => variant === "table" ? /* @__PURE__ */ jsx38(
3017
3182
  DataTable,
3018
3183
  {
3019
3184
  tableKey: "invoicesPanel.table",
@@ -3024,24 +3189,24 @@ function InvoicesPanel(props) {
3024
3189
  columns: [
3025
3190
  { key: "number", label: t.invoices.number },
3026
3191
  { key: "issuedAt", label: t.invoices.issued, render: (i) => formatDate(i.issuedAt, locale) },
3027
- { key: "status", label: t.invoices.status, render: (i) => /* @__PURE__ */ jsx37(StatusBadge, { status: i.status, labels: t.invoices.statusLabels }) },
3192
+ { key: "status", label: t.invoices.status, render: (i) => /* @__PURE__ */ jsx38(StatusBadge, { status: i.status, labels: t.invoices.statusLabels }) },
3028
3193
  {
3029
3194
  key: "total",
3030
3195
  label: t.invoices.total,
3031
- render: (i) => /* @__PURE__ */ jsx37("span", { className: "throttle-table__money", children: formatMoney(i.total, i.currency, locale) })
3196
+ render: (i) => /* @__PURE__ */ jsx38("span", { className: "throttle-table__money", children: formatMoney(i.total, i.currency, locale) })
3032
3197
  }
3033
3198
  ]
3034
3199
  }
3035
- ) : /* @__PURE__ */ jsx37("div", { ...a.el("invoicesPanel.list", listBase), children: rows.map((i) => /* @__PURE__ */ jsxs28("div", { ...a.el("invoicesPanel.item", itemBase), children: [
3036
- /* @__PURE__ */ jsxs28("div", { children: [
3037
- /* @__PURE__ */ jsxs28("div", { className: "throttle-row", children: [
3038
- /* @__PURE__ */ jsx37("strong", { children: i.number }),
3039
- /* @__PURE__ */ jsx37(StatusBadge, { status: i.status, labels: t.invoices.statusLabels })
3200
+ ) : /* @__PURE__ */ jsx38("div", { ...a.el("invoicesPanel.list", listBase), children: rows.map((i) => /* @__PURE__ */ jsxs29("div", { ...a.el("invoicesPanel.item", itemBase), children: [
3201
+ /* @__PURE__ */ jsxs29("div", { children: [
3202
+ /* @__PURE__ */ jsxs29("div", { className: "throttle-row", children: [
3203
+ /* @__PURE__ */ jsx38("strong", { children: i.number }),
3204
+ /* @__PURE__ */ jsx38(StatusBadge, { status: i.status, labels: t.invoices.statusLabels })
3040
3205
  ] }),
3041
- /* @__PURE__ */ jsx37("p", { className: "throttle-muted", children: formatDate(i.issuedAt, locale) }),
3042
- /* @__PURE__ */ jsx37("p", { className: "throttle-muted", children: formatMoney(i.total, i.currency, locale) })
3206
+ /* @__PURE__ */ jsx38("p", { className: "throttle-muted", children: formatDate(i.issuedAt, locale) }),
3207
+ /* @__PURE__ */ jsx38("p", { className: "throttle-muted", children: formatMoney(i.total, i.currency, locale) })
3043
3208
  ] }),
3044
- /* @__PURE__ */ jsx37("div", { className: "throttle-actions", children: /* @__PURE__ */ jsx37(
3209
+ /* @__PURE__ */ jsx38("div", { className: "throttle-actions", children: /* @__PURE__ */ jsx38(
3045
3210
  Button,
3046
3211
  {
3047
3212
  variant: rowsVariant ? "link" : "secondary",
@@ -3056,7 +3221,7 @@ function InvoicesPanel(props) {
3056
3221
  }
3057
3222
 
3058
3223
  // src/react/components/account/SubscriptionsPanel.tsx
3059
- import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
3224
+ import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
3060
3225
  var CAN_PAUSE = /* @__PURE__ */ new Set(["active", "trialing"]);
3061
3226
  var CAN_RESUME = /* @__PURE__ */ new Set(["paused"]);
3062
3227
  var CAN_CANCEL = /* @__PURE__ */ new Set(["active", "trialing", "paused", "past_due", "unpaid"]);
@@ -3078,8 +3243,8 @@ function SubscriptionsPanel(props) {
3078
3243
  };
3079
3244
  const priceLabel = (sub) => `${formatMoney(sub.amount, sub.currency, locale)} / ${sub.interval}${sub.quantity > 1 ? ` \xD7 ${sub.quantity}` : ""}`;
3080
3245
  const renewsLabel = (sub) => formatDate(sub.status === "cancelled" ? sub.cancelledAt ?? sub.currentPeriodEnd : sub.currentPeriodEnd, locale);
3081
- const lifecycleActions = (sub, variantFor) => /* @__PURE__ */ jsxs29("div", { className: "throttle-actions", children: [
3082
- CAN_PAUSE.has(sub.status) ? /* @__PURE__ */ jsx38(
3246
+ const lifecycleActions = (sub, variantFor) => /* @__PURE__ */ jsxs30("div", { className: "throttle-actions", children: [
3247
+ CAN_PAUSE.has(sub.status) ? /* @__PURE__ */ jsx39(
3083
3248
  Button,
3084
3249
  {
3085
3250
  variant: variantFor("secondary"),
@@ -3089,7 +3254,7 @@ function SubscriptionsPanel(props) {
3089
3254
  children: t.subscriptions.pauseButton
3090
3255
  }
3091
3256
  ) : null,
3092
- CAN_RESUME.has(sub.status) ? /* @__PURE__ */ jsx38(
3257
+ CAN_RESUME.has(sub.status) ? /* @__PURE__ */ jsx39(
3093
3258
  Button,
3094
3259
  {
3095
3260
  variant: variantFor("secondary"),
@@ -3099,7 +3264,7 @@ function SubscriptionsPanel(props) {
3099
3264
  children: t.subscriptions.resumeButton
3100
3265
  }
3101
3266
  ) : null,
3102
- CAN_CANCEL.has(sub.status) && !sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx38(
3267
+ CAN_CANCEL.has(sub.status) && !sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx39(
3103
3268
  Button,
3104
3269
  {
3105
3270
  variant: variantFor("secondary"),
@@ -3109,7 +3274,7 @@ function SubscriptionsPanel(props) {
3109
3274
  children: t.subscriptions.cancelAtPeriodEnd
3110
3275
  }
3111
3276
  ) : null,
3112
- CAN_CANCEL.has(sub.status) ? /* @__PURE__ */ jsx38(
3277
+ CAN_CANCEL.has(sub.status) ? /* @__PURE__ */ jsx39(
3113
3278
  Button,
3114
3279
  {
3115
3280
  variant: variantFor("danger"),
@@ -3120,9 +3285,9 @@ function SubscriptionsPanel(props) {
3120
3285
  }
3121
3286
  ) : null
3122
3287
  ] });
3123
- return /* @__PURE__ */ jsx38(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx38("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs29("div", { ...a.el("subscriptionsPanel.root", "throttle-panel"), children: [
3124
- error ? /* @__PURE__ */ jsx38(Alert, { tone: "error", children: error }) : null,
3125
- /* @__PURE__ */ jsx38(
3288
+ return /* @__PURE__ */ jsx39(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx39("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs30("div", { ...a.el("subscriptionsPanel.root", "throttle-panel"), children: [
3289
+ error ? /* @__PURE__ */ jsx39(Alert, { tone: "error", children: error }) : null,
3290
+ /* @__PURE__ */ jsx39(
3126
3291
  PanelState,
3127
3292
  {
3128
3293
  resource,
@@ -3131,7 +3296,7 @@ function SubscriptionsPanel(props) {
3131
3296
  isEmpty: (rows) => rows.length === 0,
3132
3297
  emptyTitle: t.subscriptions.empty,
3133
3298
  emptyDescription: t.subscriptions.emptyDescription,
3134
- children: (rows) => variant === "table" ? /* @__PURE__ */ jsx38(
3299
+ children: (rows) => variant === "table" ? /* @__PURE__ */ jsx39(
3135
3300
  DataTable,
3136
3301
  {
3137
3302
  tableKey: "subscriptionsPanel.table",
@@ -3140,42 +3305,42 @@ function SubscriptionsPanel(props) {
3140
3305
  rows,
3141
3306
  columns: [
3142
3307
  { key: "plan", label: t.subscriptions.columnPlan, render: (sub) => sub.planName ?? sub.planReference },
3143
- { key: "price", label: t.subscriptions.columnPrice, render: (sub) => /* @__PURE__ */ jsx38("span", { className: "throttle-table__money", children: priceLabel(sub) }) },
3308
+ { key: "price", label: t.subscriptions.columnPrice, render: (sub) => /* @__PURE__ */ jsx39("span", { className: "throttle-table__money", children: priceLabel(sub) }) },
3144
3309
  { key: "renews", label: t.subscriptions.columnRenews, render: (sub) => renewsLabel(sub) },
3145
- { key: "status", label: t.subscriptions.columnStatus, render: (sub) => /* @__PURE__ */ jsxs29("div", { className: "throttle-row", children: [
3146
- /* @__PURE__ */ jsx38(StatusBadge, { status: sub.status, labels: t.subscriptions.statusLabels }),
3147
- sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx38(Badge, { tone: "warning", children: t.subscriptions.cancelScheduled }) : null
3310
+ { key: "status", label: t.subscriptions.columnStatus, render: (sub) => /* @__PURE__ */ jsxs30("div", { className: "throttle-row", children: [
3311
+ /* @__PURE__ */ jsx39(StatusBadge, { status: sub.status, labels: t.subscriptions.statusLabels }),
3312
+ sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx39(Badge, { tone: "warning", children: t.subscriptions.cancelScheduled }) : null
3148
3313
  ] }) },
3149
3314
  { key: "actions", label: t.common.actions, render: (sub) => lifecycleActions(sub, (base) => base) }
3150
3315
  ]
3151
3316
  }
3152
- ) : /* @__PURE__ */ jsx38("div", { ...a.el("subscriptionsPanel.list", listBase), children: rows.map((sub) => /* @__PURE__ */ jsxs29("div", { ...a.el("subscriptionsPanel.item", itemBase), children: [
3153
- /* @__PURE__ */ jsxs29("div", { children: [
3154
- /* @__PURE__ */ jsxs29("div", { className: "throttle-row", children: [
3155
- /* @__PURE__ */ jsx38("strong", { children: sub.planName ?? sub.planReference }),
3156
- /* @__PURE__ */ jsx38(StatusBadge, { status: sub.status, labels: t.subscriptions.statusLabels })
3317
+ ) : /* @__PURE__ */ jsx39("div", { ...a.el("subscriptionsPanel.list", listBase), children: rows.map((sub) => /* @__PURE__ */ jsxs30("div", { ...a.el("subscriptionsPanel.item", itemBase), children: [
3318
+ /* @__PURE__ */ jsxs30("div", { children: [
3319
+ /* @__PURE__ */ jsxs30("div", { className: "throttle-row", children: [
3320
+ /* @__PURE__ */ jsx39("strong", { children: sub.planName ?? sub.planReference }),
3321
+ /* @__PURE__ */ jsx39(StatusBadge, { status: sub.status, labels: t.subscriptions.statusLabels })
3157
3322
  ] }),
3158
- /* @__PURE__ */ jsxs29("p", { className: "throttle-muted", children: [
3323
+ /* @__PURE__ */ jsxs30("p", { className: "throttle-muted", children: [
3159
3324
  formatMoney(sub.amount, sub.currency, locale),
3160
3325
  " / ",
3161
3326
  sub.interval,
3162
3327
  sub.quantity > 1 ? ` \xD7 ${sub.quantity}` : ""
3163
3328
  ] }),
3164
- sub.status === "cancelled" ? /* @__PURE__ */ jsxs29("p", { className: "throttle-muted", children: [
3329
+ sub.status === "cancelled" ? /* @__PURE__ */ jsxs30("p", { className: "throttle-muted", children: [
3165
3330
  t.subscriptions.cancelledOn,
3166
3331
  " ",
3167
3332
  formatDate(sub.cancelledAt ?? sub.currentPeriodEnd, locale)
3168
- ] }) : /* @__PURE__ */ jsxs29("p", { className: "throttle-muted", children: [
3333
+ ] }) : /* @__PURE__ */ jsxs30("p", { className: "throttle-muted", children: [
3169
3334
  sub.cancelAtPeriodEnd ? t.subscriptions.endsOn : t.subscriptions.renewsOn,
3170
3335
  " ",
3171
3336
  formatDate(sub.currentPeriodEnd, locale)
3172
3337
  ] }),
3173
- sub.trialEnd ? /* @__PURE__ */ jsxs29("p", { className: "throttle-muted", children: [
3338
+ sub.trialEnd ? /* @__PURE__ */ jsxs30("p", { className: "throttle-muted", children: [
3174
3339
  t.subscriptions.trialEnds,
3175
3340
  " ",
3176
3341
  formatDate(sub.trialEnd, locale)
3177
3342
  ] }) : null,
3178
- sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx38(Badge, { tone: "warning", children: t.subscriptions.cancelScheduled }) : null
3343
+ sub.cancelAtPeriodEnd ? /* @__PURE__ */ jsx39(Badge, { tone: "warning", children: t.subscriptions.cancelScheduled }) : null
3179
3344
  ] }),
3180
3345
  lifecycleActions(sub, actionVariant)
3181
3346
  ] }, sub.id)) })
@@ -3185,8 +3350,40 @@ function SubscriptionsPanel(props) {
3185
3350
  }
3186
3351
 
3187
3352
  // src/react/components/account/SecurityPanel.tsx
3188
- import { useCallback as useCallback2, useEffect as useEffect7, useRef as useRef5, useState as useState17 } from "react";
3189
- import { Fragment as Fragment9, jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
3353
+ import { useCallback as useCallback2, useEffect as useEffect8, useRef as useRef7, useState as useState19 } from "react";
3354
+
3355
+ // src/react/components/account/device.ts
3356
+ var BROWSERS = [
3357
+ [/\bEdg(?:e|A|iOS)?\//, "Edge"],
3358
+ [/\bOPR\/|\bOpera\b/, "Opera"],
3359
+ // No leading \b: real agents ship prefixed builds (HeadlessChrome), and a
3360
+ // word boundary there sends them to the Safari rule instead.
3361
+ [/Chrome\/|CriOS\//, "Chrome"],
3362
+ [/\bFirefox\/|\bFxiOS\//, "Firefox"],
3363
+ [/\bSafari\//, "Safari"]
3364
+ ];
3365
+ var PLATFORMS = [
3366
+ [/\biPhone\b|\biPad\b|\biPod\b/, "iOS"],
3367
+ [/\bAndroid\b/, "Android"],
3368
+ [/\bMac OS X\b|\bMacintosh\b/, "macOS"],
3369
+ [/\bWindows\b/, "Windows"],
3370
+ [/\bLinux\b|\bX11\b/, "Linux"]
3371
+ ];
3372
+ function first(ua, table) {
3373
+ for (const [pattern, label] of table) if (pattern.test(ua)) return label;
3374
+ return null;
3375
+ }
3376
+ function describeDevice(userAgent) {
3377
+ const ua = (userAgent ?? "").trim();
3378
+ if (!ua) return "";
3379
+ const browser = first(ua, BROWSERS);
3380
+ if (!browser) return ua;
3381
+ const platform = first(ua, PLATFORMS);
3382
+ return platform ? `${browser} on ${platform}` : browser;
3383
+ }
3384
+
3385
+ // src/react/components/account/SecurityPanel.tsx
3386
+ import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
3190
3387
  function SecurityPanel(props) {
3191
3388
  const a = useAppearance(props.appearance);
3192
3389
  const scoped = useAppearanceProviderValue(props.appearance);
@@ -3196,13 +3393,13 @@ function SecurityPanel(props) {
3196
3393
  const rowsVariant = variant === "rows";
3197
3394
  const itemBase = rowsVariant ? "throttle-rowitem" : "throttle-listitem";
3198
3395
  const revokeVariant = rowsVariant ? "linkDanger" : "danger";
3199
- const [password, setPassword] = useState17("");
3396
+ const [password, setPassword] = useState19("");
3200
3397
  const passwordAction = useAction();
3201
3398
  const sessionAction = useAction();
3202
- const [sessions, setSessions] = useState17(null);
3203
- const [listError, setListError] = useState17(null);
3204
- const errorMessageRef = useRef5(errorMessage);
3205
- useEffect7(() => {
3399
+ const [sessions, setSessions] = useState19(null);
3400
+ const [listError, setListError] = useState19(null);
3401
+ const errorMessageRef = useRef7(errorMessage);
3402
+ useEffect8(() => {
3206
3403
  errorMessageRef.current = errorMessage;
3207
3404
  });
3208
3405
  const load = useCallback2(async () => {
@@ -3213,12 +3410,12 @@ function SecurityPanel(props) {
3213
3410
  setListError(errorMessageRef.current(err));
3214
3411
  }
3215
3412
  }, [auth]);
3216
- useEffect7(() => {
3413
+ useEffect8(() => {
3217
3414
  void load();
3218
3415
  }, [load]);
3219
3416
  const others = (sessions ?? []).filter((s) => !s.current);
3220
- return /* @__PURE__ */ jsx39(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx39("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs30("div", { ...a.el("securityPanel.root", "throttle-panel"), children: [
3221
- /* @__PURE__ */ jsxs30(
3417
+ return /* @__PURE__ */ jsx40(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx40("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs31("div", { ...a.el("securityPanel.root", "throttle-panel"), children: [
3418
+ /* @__PURE__ */ jsxs31(
3222
3419
  "form",
3223
3420
  {
3224
3421
  ...a.el("securityPanel.passwordForm", "throttle-stack"),
@@ -3231,8 +3428,8 @@ function SecurityPanel(props) {
3231
3428
  });
3232
3429
  },
3233
3430
  children: [
3234
- /* @__PURE__ */ jsx39("h3", { children: t.security.passwordTitle }),
3235
- /* @__PURE__ */ jsx39(
3431
+ /* @__PURE__ */ jsx40("h3", { children: t.security.passwordTitle }),
3432
+ /* @__PURE__ */ jsx40(
3236
3433
  Field,
3237
3434
  {
3238
3435
  label: t.security.newPassword,
@@ -3243,21 +3440,21 @@ function SecurityPanel(props) {
3243
3440
  onChange: setPassword
3244
3441
  }
3245
3442
  ),
3246
- passwordAction.error ? /* @__PURE__ */ jsx39(Alert, { tone: "error", children: passwordAction.error }) : null,
3247
- passwordAction.notice ? /* @__PURE__ */ jsx39(Alert, { tone: "success", children: passwordAction.notice }) : null,
3248
- /* @__PURE__ */ jsx39(Button, { type: "submit", loading: passwordAction.submitting, elementKey: "securityPanel.passwordButton", children: t.security.changeButton })
3443
+ passwordAction.error ? /* @__PURE__ */ jsx40(Alert, { tone: "error", children: passwordAction.error }) : null,
3444
+ passwordAction.notice ? /* @__PURE__ */ jsx40(Alert, { tone: "success", children: passwordAction.notice }) : null,
3445
+ /* @__PURE__ */ jsx40(Button, { type: "submit", loading: passwordAction.submitting, elementKey: "securityPanel.passwordButton", children: t.security.changeButton })
3249
3446
  ]
3250
3447
  }
3251
3448
  ),
3252
- /* @__PURE__ */ jsxs30("div", { ...a.el("securityPanel.sessionList", "throttle-stack"), children: [
3253
- /* @__PURE__ */ jsx39("h3", { children: t.security.sessionsTitle }),
3254
- listError ? /* @__PURE__ */ jsxs30(Fragment9, { children: [
3255
- /* @__PURE__ */ jsx39(Alert, { tone: "error", children: listError }),
3256
- /* @__PURE__ */ jsx39(Button, { variant: "secondary", onClick: () => void load(), children: t.common.retry })
3449
+ /* @__PURE__ */ jsxs31("div", { ...a.el("securityPanel.sessionList", "throttle-stack"), children: [
3450
+ /* @__PURE__ */ jsx40("h3", { children: t.security.sessionsTitle }),
3451
+ listError ? /* @__PURE__ */ jsxs31(Fragment9, { children: [
3452
+ /* @__PURE__ */ jsx40(Alert, { tone: "error", children: listError }),
3453
+ /* @__PURE__ */ jsx40(Button, { variant: "secondary", onClick: () => void load(), children: t.common.retry })
3257
3454
  ] }) : null,
3258
- sessionAction.error ? /* @__PURE__ */ jsx39(Alert, { tone: "error", children: sessionAction.error }) : null,
3259
- sessions === null && !listError ? /* @__PURE__ */ jsx39(Skeleton, { count: 2 }) : null,
3260
- sessions !== null && !listError && variant === "table" ? /* @__PURE__ */ jsx39(
3455
+ sessionAction.error ? /* @__PURE__ */ jsx40(Alert, { tone: "error", children: sessionAction.error }) : null,
3456
+ sessions === null && !listError ? /* @__PURE__ */ jsx40(Skeleton, { count: 2 }) : null,
3457
+ sessions !== null && !listError && variant === "table" ? /* @__PURE__ */ jsx40(
3261
3458
  DataTable,
3262
3459
  {
3263
3460
  tableKey: "securityPanel.table",
@@ -3265,12 +3462,12 @@ function SecurityPanel(props) {
3265
3462
  rowKey: (session) => session.id,
3266
3463
  rows: sessions,
3267
3464
  columns: [
3268
- { key: "device", label: t.security.columnDevice, render: (session) => /* @__PURE__ */ jsxs30("div", { className: "throttle-row", children: [
3269
- /* @__PURE__ */ jsx39("span", { children: session.userAgent || session.ipPrefix || session.id }),
3270
- session.current ? /* @__PURE__ */ jsx39(Badge, { tone: "success", children: t.security.thisDevice }) : null
3465
+ { key: "device", label: t.security.columnDevice, render: (session) => /* @__PURE__ */ jsxs31("div", { className: "throttle-row", children: [
3466
+ /* @__PURE__ */ jsx40("span", { children: describeDevice(session.userAgent) || session.ipPrefix || session.id }),
3467
+ session.current ? /* @__PURE__ */ jsx40(Badge, { tone: "success", children: t.security.thisDevice }) : null
3271
3468
  ] }) },
3272
3469
  { key: "lastActive", label: t.security.lastActive, render: (session) => formatDate(session.lastUsedAt, locale) },
3273
- { key: "actions", label: t.common.actions, render: (session) => !session.current ? /* @__PURE__ */ jsx39(
3470
+ { key: "actions", label: t.common.actions, render: (session) => !session.current ? /* @__PURE__ */ jsx40(
3274
3471
  Button,
3275
3472
  {
3276
3473
  variant: "danger",
@@ -3285,19 +3482,19 @@ function SecurityPanel(props) {
3285
3482
  ) : null }
3286
3483
  ]
3287
3484
  }
3288
- ) : (sessions ?? []).map((session) => /* @__PURE__ */ jsxs30("div", { ...a.el("securityPanel.sessionItem", itemBase), children: [
3289
- /* @__PURE__ */ jsxs30("div", { children: [
3290
- /* @__PURE__ */ jsxs30("div", { className: "throttle-row", children: [
3291
- /* @__PURE__ */ jsx39("strong", { children: session.userAgent || session.ipPrefix || session.id }),
3292
- session.current ? /* @__PURE__ */ jsx39(Badge, { tone: "success", children: t.security.thisDevice }) : null
3485
+ ) : (sessions ?? []).map((session) => /* @__PURE__ */ jsxs31("div", { ...a.el("securityPanel.sessionItem", itemBase), children: [
3486
+ /* @__PURE__ */ jsxs31("div", { children: [
3487
+ /* @__PURE__ */ jsxs31("div", { className: "throttle-row", children: [
3488
+ /* @__PURE__ */ jsx40("strong", { children: describeDevice(session.userAgent) || session.ipPrefix || session.id }),
3489
+ session.current ? /* @__PURE__ */ jsx40(Badge, { tone: "success", children: t.security.thisDevice }) : null
3293
3490
  ] }),
3294
- /* @__PURE__ */ jsxs30("p", { className: "throttle-muted", children: [
3491
+ /* @__PURE__ */ jsxs31("p", { className: "throttle-muted", children: [
3295
3492
  t.security.lastActive,
3296
3493
  " ",
3297
3494
  formatDate(session.lastUsedAt, locale)
3298
3495
  ] })
3299
3496
  ] }),
3300
- !session.current ? /* @__PURE__ */ jsx39(
3497
+ !session.current ? /* @__PURE__ */ jsx40(
3301
3498
  Button,
3302
3499
  {
3303
3500
  variant: revokeVariant,
@@ -3311,8 +3508,8 @@ function SecurityPanel(props) {
3311
3508
  }
3312
3509
  ) : null
3313
3510
  ] }, session.id)),
3314
- sessions !== null && others.length === 0 ? /* @__PURE__ */ jsx39("p", { className: "throttle-muted", children: t.security.sessionsEmpty }) : null,
3315
- others.length > 0 ? /* @__PURE__ */ jsx39(
3511
+ sessions !== null && others.length === 0 ? /* @__PURE__ */ jsx40("p", { className: "throttle-muted", children: t.security.sessionsEmpty }) : null,
3512
+ others.length > 0 ? /* @__PURE__ */ jsx40(
3316
3513
  Button,
3317
3514
  {
3318
3515
  variant: "danger",
@@ -3332,7 +3529,7 @@ function SecurityPanel(props) {
3332
3529
  }
3333
3530
 
3334
3531
  // src/react/components/account/AccountDashboard.tsx
3335
- import { Fragment as Fragment10, jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
3532
+ import { Fragment as Fragment10, jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
3336
3533
  var ACCOUNT_TABS = [
3337
3534
  "profile",
3338
3535
  "addresses",
@@ -3361,9 +3558,9 @@ function AccountDashboard(props) {
3361
3558
  const { status } = useAuth();
3362
3559
  const shown = props.tabs ?? [...ACCOUNT_TABS];
3363
3560
  const controlled = props.tab !== void 0;
3364
- const [internal, setInternal] = useState18(shown[0] ?? "profile");
3365
- const idBase = useId4();
3366
- useEffect8(() => {
3561
+ const [internal, setInternal] = useState20(shown[0] ?? "profile");
3562
+ const idBase = useId5();
3563
+ useEffect9(() => {
3367
3564
  if (props.routing !== "hash" || typeof window === "undefined") return;
3368
3565
  const apply = () => {
3369
3566
  const next = TAB_FOR_HASH[window.location.hash] ?? shown[0];
@@ -3384,7 +3581,7 @@ function AccountDashboard(props) {
3384
3581
  };
3385
3582
  const shared = { appearance: props.appearance, localization: props.localization };
3386
3583
  const sidebar = (props.layout ?? "sidebar") === "sidebar";
3387
- const nav = /* @__PURE__ */ jsx40(
3584
+ const nav = /* @__PURE__ */ jsx41(
3388
3585
  Tabs,
3389
3586
  {
3390
3587
  idBase,
@@ -3400,7 +3597,7 @@ function AccountDashboard(props) {
3400
3597
  }))
3401
3598
  }
3402
3599
  );
3403
- const panel = /* @__PURE__ */ jsxs31(
3600
+ const panel = /* @__PURE__ */ jsxs32(
3404
3601
  "div",
3405
3602
  {
3406
3603
  ...a.el("accountDashboard.panel", sidebar ? "throttle-account__content" : "throttle-tabs__panel"),
@@ -3409,36 +3606,36 @@ function AccountDashboard(props) {
3409
3606
  "aria-labelledby": `${idBase}-tab-${active}`,
3410
3607
  tabIndex: 0,
3411
3608
  children: [
3412
- active === "profile" ? /* @__PURE__ */ jsx40(ProfilePanel, { ...shared }) : null,
3413
- active === "addresses" ? /* @__PURE__ */ jsx40(AddressesPanel, { ...shared, variant: props.panelVariant }) : null,
3414
- active === "paymentMethods" ? /* @__PURE__ */ jsx40(PaymentMethodsPanel, { ...shared, variant: props.panelVariant }) : null,
3415
- active === "orders" ? /* @__PURE__ */ jsx40(OrdersPanel, { ...shared, variant: props.panelVariant, onViewSubscription: () => go("subscriptions") }) : null,
3416
- active === "invoices" ? /* @__PURE__ */ jsx40(InvoicesPanel, { ...shared, variant: props.panelVariant }) : null,
3417
- active === "subscriptions" ? /* @__PURE__ */ jsx40(SubscriptionsPanel, { ...shared, variant: props.panelVariant }) : null,
3418
- active === "security" ? /* @__PURE__ */ jsx40(SecurityPanel, { ...shared, variant: props.panelVariant }) : null
3609
+ active === "profile" ? /* @__PURE__ */ jsx41(ProfilePanel, { ...shared }) : null,
3610
+ active === "addresses" ? /* @__PURE__ */ jsx41(AddressesPanel, { ...shared, variant: props.panelVariant }) : null,
3611
+ active === "paymentMethods" ? /* @__PURE__ */ jsx41(PaymentMethodsPanel, { ...shared, variant: props.panelVariant }) : null,
3612
+ active === "orders" ? /* @__PURE__ */ jsx41(OrdersPanel, { ...shared, variant: props.panelVariant, onViewSubscription: () => go("subscriptions") }) : null,
3613
+ active === "invoices" ? /* @__PURE__ */ jsx41(InvoicesPanel, { ...shared, variant: props.panelVariant }) : null,
3614
+ active === "subscriptions" ? /* @__PURE__ */ jsx41(SubscriptionsPanel, { ...shared, variant: props.panelVariant }) : null,
3615
+ active === "security" ? /* @__PURE__ */ jsx41(SecurityPanel, { ...shared, variant: props.panelVariant }) : null
3419
3616
  ]
3420
3617
  }
3421
3618
  );
3422
- return /* @__PURE__ */ jsx40(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx40("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs31("div", { ...a.el("accountDashboard.root", "throttle-panel throttle-account-root"), children: [
3423
- /* @__PURE__ */ jsx40(VerifyEmailBanner, { ...shared }),
3424
- sidebar ? /* @__PURE__ */ jsxs31("div", { className: "throttle-account", children: [
3425
- /* @__PURE__ */ jsx40("div", { ...a.el("accountDashboard.sidebar"), children: nav }),
3619
+ return /* @__PURE__ */ jsx41(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx41("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs32("div", { ...a.el("accountDashboard.root", "throttle-panel throttle-account-root"), children: [
3620
+ /* @__PURE__ */ jsx41(VerifyEmailBanner, { ...shared }),
3621
+ sidebar ? /* @__PURE__ */ jsxs32("div", { className: "throttle-account", children: [
3622
+ /* @__PURE__ */ jsx41("div", { ...a.el("accountDashboard.sidebar"), children: nav }),
3426
3623
  panel
3427
- ] }) : /* @__PURE__ */ jsxs31(Fragment10, { children: [
3428
- /* @__PURE__ */ jsx40("div", { ...a.el("accountDashboard.tabs"), children: nav }),
3624
+ ] }) : /* @__PURE__ */ jsxs32(Fragment10, { children: [
3625
+ /* @__PURE__ */ jsx41("div", { ...a.el("accountDashboard.tabs"), children: nav }),
3429
3626
  panel
3430
3627
  ] })
3431
3628
  ] }) }) });
3432
3629
  }
3433
3630
 
3434
3631
  // src/react/components/account/AccountModal.tsx
3435
- import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
3632
+ import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
3436
3633
  function AccountModal(props) {
3437
3634
  const a = useAppearance(props.appearance);
3438
3635
  const scoped = useAppearanceProviderValue(props.appearance);
3439
3636
  const { t } = useCopy(props.localization);
3440
- const titleId = useId5();
3441
- return /* @__PURE__ */ jsx41(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsxs32(
3637
+ const titleId = useId6();
3638
+ return /* @__PURE__ */ jsx42(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsxs33(
3442
3639
  Modal,
3443
3640
  {
3444
3641
  open: props.open,
@@ -3448,15 +3645,15 @@ function AccountModal(props) {
3448
3645
  overlayKey: "accountModal.overlay",
3449
3646
  containerKey: "accountModal.container",
3450
3647
  children: [
3451
- /* @__PURE__ */ jsx41("div", { ...a.el("accountModal.header", "throttle-modal__header"), children: /* @__PURE__ */ jsx41("h2", { id: titleId, ...a.el("accountModal.title", "throttle-modal__title"), children: t.account.title }) }),
3452
- /* @__PURE__ */ jsx41("div", { ...a.el("accountModal.body", "throttle-modal__body"), children: /* @__PURE__ */ jsx41(AccountDashboard, { tabs: props.tabs, appearance: props.appearance, localization: props.localization }) })
3648
+ /* @__PURE__ */ jsx42("div", { ...a.el("accountModal.header", "throttle-modal__header"), children: /* @__PURE__ */ jsx42("h2", { id: titleId, ...a.el("accountModal.title", "throttle-modal__title"), children: t.account.title }) }),
3649
+ /* @__PURE__ */ jsx42("div", { ...a.el("accountModal.body", "throttle-modal__body"), children: /* @__PURE__ */ jsx42(AccountDashboard, { tabs: props.tabs, appearance: props.appearance, localization: props.localization }) })
3453
3650
  ]
3454
3651
  }
3455
3652
  ) });
3456
3653
  }
3457
3654
 
3458
3655
  // src/react/components/provider.tsx
3459
- import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
3656
+ import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
3460
3657
  var warned = /* @__PURE__ */ new Set();
3461
3658
  function warnOnce(key, message) {
3462
3659
  if (process.env.NODE_ENV === "production") return;
@@ -3501,14 +3698,14 @@ function ThrottleProvider(props) {
3501
3698
  __captureStepUp
3502
3699
  } = props;
3503
3700
  useInjectStyles(injectStyles);
3504
- const [stepUpOpen, setStepUpOpen] = useState19(false);
3505
- const resolveStepUp = useRef6(null);
3506
- const claimRef = useRef6(claimCartOnSignIn);
3701
+ const [stepUpOpen, setStepUpOpen] = useState21(false);
3702
+ const resolveStepUp = useRef8(null);
3703
+ const claimRef = useRef8(claimCartOnSignIn);
3507
3704
  claimRef.current = claimCartOnSignIn;
3508
- const [overlay, setOverlay] = useState19(null);
3509
- const overlayRestoreFocus = useRef6(null);
3510
- const [accountTabs, setAccountTabs] = useState19(void 0);
3511
- const onOverlaySuccess = useRef6(null);
3705
+ const [overlay, setOverlay] = useState21(null);
3706
+ const overlayRestoreFocus = useRef8(null);
3707
+ const [accountTabs, setAccountTabs] = useState21(void 0);
3708
+ const onOverlaySuccess = useRef8(null);
3512
3709
  const openSignIn = useCallback3((onSuccess) => {
3513
3710
  onOverlaySuccess.current = onSuccess ?? null;
3514
3711
  setOverlay("signIn");
@@ -3578,10 +3775,10 @@ function ThrottleProvider(props) {
3578
3775
  resolve?.(password);
3579
3776
  };
3580
3777
  const authOverlayOpen = overlay === "signIn" || overlay === "signUp";
3581
- return /* @__PURE__ */ jsx42(AppearanceProvider, { value: appearance ?? {}, children: /* @__PURE__ */ jsx42(LocalizationProvider, { value: localization ?? {}, children: /* @__PURE__ */ jsx42(BrandLogoProvider, { value: logo ?? null, children: /* @__PURE__ */ jsx42(ThrottleAuthProvider, { auth, publishableKey, children: /* @__PURE__ */ jsxs33(ThrottleUIContext.Provider, { value: ui, children: [
3778
+ return /* @__PURE__ */ jsx43(AppearanceProvider, { value: appearance ?? {}, children: /* @__PURE__ */ jsx43(LocalizationProvider, { value: localization ?? {}, children: /* @__PURE__ */ jsx43(BrandLogoProvider, { value: logo ?? null, children: /* @__PURE__ */ jsx43(ThrottleAuthProvider, { auth, publishableKey, children: /* @__PURE__ */ jsxs34(ThrottleUIContext.Provider, { value: ui, children: [
3582
3779
  children,
3583
- /* @__PURE__ */ jsx42(StepUpDialog, { open: stepUpOpen, onResolve: finishStepUp }),
3584
- /* @__PURE__ */ jsx42(
3780
+ /* @__PURE__ */ jsx43(StepUpDialog, { open: stepUpOpen, onResolve: finishStepUp }),
3781
+ /* @__PURE__ */ jsx43(
3585
3782
  AuthModal,
3586
3783
  {
3587
3784
  open: authOverlayOpen,
@@ -3592,23 +3789,23 @@ function ThrottleProvider(props) {
3592
3789
  },
3593
3790
  overlay === "signUp" ? "signUp" : "signIn"
3594
3791
  ),
3595
- /* @__PURE__ */ jsx42(AccountModal, { open: overlay === "account", onClose: closeOverlay, tabs: accountTabs, restoreFocusTo: overlayRestoreFocus.current })
3792
+ /* @__PURE__ */ jsx43(AccountModal, { open: overlay === "account", onClose: closeOverlay, tabs: accountTabs, restoreFocusTo: overlayRestoreFocus.current })
3596
3793
  ] }) }) }) }) });
3597
3794
  }
3598
3795
 
3599
3796
  // src/react/components/auth/SignInButton.tsx
3600
- import { cloneElement, isValidElement, useContext as useContext6, useState as useState20 } from "react";
3601
- import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
3797
+ import { cloneElement, isValidElement, useContext as useContext6, useState as useState22 } from "react";
3798
+ import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
3602
3799
  function SignInButton(props) {
3603
3800
  const a = useAppearance(props.appearance);
3604
3801
  const scoped = useAppearanceProviderValue(props.appearance);
3605
3802
  const { t } = useCopy(props.localization);
3606
3803
  const ui = useContext6(ThrottleUIContext);
3607
- const [localOpen, setLocalOpen] = useState20(false);
3804
+ const [localOpen, setLocalOpen] = useState22(false);
3608
3805
  const useShared = ui !== null && props.initialView === void 0;
3609
3806
  const label = props.children ?? t.signIn.submitButton;
3610
3807
  if (props.mode === "redirect") {
3611
- return /* @__PURE__ */ jsx43(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx43("span", { ...a.rootProps, children: /* @__PURE__ */ jsx43("a", { ...a.el("signInButton.root", "throttle-button throttle-button--primary"), href: props.url ?? "#", children: label }) }) });
3808
+ return /* @__PURE__ */ jsx44(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx44("span", { ...a.rootProps, children: /* @__PURE__ */ jsx44("a", { ...a.el("signInButton.root", "throttle-button throttle-button--primary"), href: props.url ?? "#", children: label }) }) });
3612
3809
  }
3613
3810
  const openModal = () => {
3614
3811
  if (useShared) ui.openSignIn(props.afterSignIn);
@@ -3618,10 +3815,10 @@ function SignInButton(props) {
3618
3815
  if (useShared) ui.close();
3619
3816
  else setLocalOpen(false);
3620
3817
  };
3621
- const trigger = props.asChild && isValidElement(props.children) ? cloneElement(props.children, { onClick: openModal }) : /* @__PURE__ */ jsx43(Button, { elementKey: "signInButton.root", onClick: openModal, children: label });
3622
- return /* @__PURE__ */ jsxs34(AppearanceProvider, { value: scoped, children: [
3623
- /* @__PURE__ */ jsx43("span", { ...a.rootProps, children: trigger }),
3624
- !useShared ? /* @__PURE__ */ jsx43(
3818
+ const trigger = props.asChild && isValidElement(props.children) ? cloneElement(props.children, { onClick: openModal }) : /* @__PURE__ */ jsx44(Button, { elementKey: "signInButton.root", onClick: openModal, children: label });
3819
+ return /* @__PURE__ */ jsxs35(AppearanceProvider, { value: scoped, children: [
3820
+ /* @__PURE__ */ jsx44("span", { ...a.rootProps, children: trigger }),
3821
+ !useShared ? /* @__PURE__ */ jsx44(
3625
3822
  AuthModal,
3626
3823
  {
3627
3824
  open: localOpen,
@@ -3639,18 +3836,18 @@ function SignInButton(props) {
3639
3836
  }
3640
3837
 
3641
3838
  // src/react/components/auth/SignUpButton.tsx
3642
- import { cloneElement as cloneElement2, isValidElement as isValidElement2, useContext as useContext7, useState as useState21 } from "react";
3643
- import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
3839
+ import { cloneElement as cloneElement2, isValidElement as isValidElement2, useContext as useContext7, useState as useState23 } from "react";
3840
+ import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
3644
3841
  function SignUpButton(props) {
3645
3842
  const a = useAppearance(props.appearance);
3646
3843
  const scoped = useAppearanceProviderValue(props.appearance);
3647
3844
  const { t } = useCopy(props.localization);
3648
3845
  const ui = useContext7(ThrottleUIContext);
3649
- const [localOpen, setLocalOpen] = useState21(false);
3846
+ const [localOpen, setLocalOpen] = useState23(false);
3650
3847
  const useShared = ui !== null && props.initialView === void 0;
3651
3848
  const label = props.children ?? t.signUp.submitButton;
3652
3849
  if (props.mode === "redirect") {
3653
- return /* @__PURE__ */ jsx44(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx44("span", { ...a.rootProps, children: /* @__PURE__ */ jsx44("a", { ...a.el("signUpButton.root", "throttle-button throttle-button--primary"), href: props.url ?? "#", children: label }) }) });
3850
+ return /* @__PURE__ */ jsx45(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx45("span", { ...a.rootProps, children: /* @__PURE__ */ jsx45("a", { ...a.el("signUpButton.root", "throttle-button throttle-button--primary"), href: props.url ?? "#", children: label }) }) });
3654
3851
  }
3655
3852
  const openModal = () => {
3656
3853
  if (useShared) ui.openSignUp(props.afterSignUp);
@@ -3660,10 +3857,10 @@ function SignUpButton(props) {
3660
3857
  if (useShared) ui.close();
3661
3858
  else setLocalOpen(false);
3662
3859
  };
3663
- const trigger = props.asChild && isValidElement2(props.children) ? cloneElement2(props.children, { onClick: openModal }) : /* @__PURE__ */ jsx44(Button, { elementKey: "signUpButton.root", onClick: openModal, children: label });
3664
- return /* @__PURE__ */ jsxs35(AppearanceProvider, { value: scoped, children: [
3665
- /* @__PURE__ */ jsx44("span", { ...a.rootProps, children: trigger }),
3666
- !useShared ? /* @__PURE__ */ jsx44(
3860
+ const trigger = props.asChild && isValidElement2(props.children) ? cloneElement2(props.children, { onClick: openModal }) : /* @__PURE__ */ jsx45(Button, { elementKey: "signUpButton.root", onClick: openModal, children: label });
3861
+ return /* @__PURE__ */ jsxs36(AppearanceProvider, { value: scoped, children: [
3862
+ /* @__PURE__ */ jsx45("span", { ...a.rootProps, children: trigger }),
3863
+ !useShared ? /* @__PURE__ */ jsx45(
3667
3864
  AuthModal,
3668
3865
  {
3669
3866
  open: localOpen,
@@ -3681,14 +3878,14 @@ function SignUpButton(props) {
3681
3878
  }
3682
3879
 
3683
3880
  // src/react/components/auth/SignOutButton.tsx
3684
- import { jsx as jsx45 } from "react/jsx-runtime";
3881
+ import { jsx as jsx46 } from "react/jsx-runtime";
3685
3882
  function SignOutButton(props) {
3686
3883
  const a = useAppearance();
3687
3884
  const { auth } = useAuth();
3688
3885
  const { t } = useCopy(props.localization);
3689
3886
  const { submitting, run } = useAction();
3690
3887
  const label = props.children ?? (props.everywhere ? t.userButton.signOutAll : t.userButton.signOut);
3691
- return /* @__PURE__ */ jsx45("span", { ...a.rootProps, children: /* @__PURE__ */ jsx45(
3888
+ return /* @__PURE__ */ jsx46("span", { ...a.rootProps, children: /* @__PURE__ */ jsx46(
3692
3889
  Button,
3693
3890
  {
3694
3891
  variant: "secondary",
@@ -3705,13 +3902,13 @@ function SignOutButton(props) {
3705
3902
  }
3706
3903
 
3707
3904
  // src/react/components/auth/SignInPage.tsx
3708
- import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
3905
+ import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3709
3906
  function SignInPage(props) {
3710
3907
  const a = useAppearance(props.appearance);
3711
3908
  const scoped = useAppearanceProviderValue(props.appearance);
3712
- return /* @__PURE__ */ jsx46(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx46("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs36("div", { ...a.el("signInPage.root", "throttle-page"), children: [
3713
- props.logo ? /* @__PURE__ */ jsx46("div", { ...a.el("signInPage.logo", "throttle-page__logo"), children: props.logo }) : null,
3714
- /* @__PURE__ */ jsx46(
3909
+ return /* @__PURE__ */ jsx47(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx47("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs37("div", { ...a.el("signInPage.root", "throttle-page"), children: [
3910
+ props.logo ? /* @__PURE__ */ jsx47("div", { ...a.el("signInPage.logo", "throttle-page__logo"), children: props.logo }) : null,
3911
+ /* @__PURE__ */ jsx47(
3715
3912
  SignIn,
3716
3913
  {
3717
3914
  onSuccess: props.onSuccess,
@@ -3721,18 +3918,18 @@ function SignInPage(props) {
3721
3918
  localization: props.localization
3722
3919
  }
3723
3920
  ),
3724
- props.footer ? /* @__PURE__ */ jsx46("div", { ...a.el("signInPage.footer", "throttle-page__footer"), children: props.footer }) : null
3921
+ props.footer ? /* @__PURE__ */ jsx47("div", { ...a.el("signInPage.footer", "throttle-page__footer"), children: props.footer }) : null
3725
3922
  ] }) }) });
3726
3923
  }
3727
3924
 
3728
3925
  // src/react/components/auth/SignUpPage.tsx
3729
- import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3926
+ import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
3730
3927
  function SignUpPage(props) {
3731
3928
  const a = useAppearance(props.appearance);
3732
3929
  const scoped = useAppearanceProviderValue(props.appearance);
3733
- return /* @__PURE__ */ jsx47(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx47("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs37("div", { ...a.el("signUpPage.root", "throttle-page"), children: [
3734
- props.logo ? /* @__PURE__ */ jsx47("div", { ...a.el("signUpPage.logo", "throttle-page__logo"), children: props.logo }) : null,
3735
- /* @__PURE__ */ jsx47(
3930
+ return /* @__PURE__ */ jsx48(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx48("div", { ...a.rootProps, children: /* @__PURE__ */ jsxs38("div", { ...a.el("signUpPage.root", "throttle-page"), children: [
3931
+ props.logo ? /* @__PURE__ */ jsx48("div", { ...a.el("signUpPage.logo", "throttle-page__logo"), children: props.logo }) : null,
3932
+ /* @__PURE__ */ jsx48(
3736
3933
  SignUp,
3737
3934
  {
3738
3935
  onSuccess: props.onSuccess,
@@ -3741,42 +3938,42 @@ function SignUpPage(props) {
3741
3938
  localization: props.localization
3742
3939
  }
3743
3940
  ),
3744
- props.footer ? /* @__PURE__ */ jsx47("div", { ...a.el("signUpPage.footer", "throttle-page__footer"), children: props.footer }) : null
3941
+ props.footer ? /* @__PURE__ */ jsx48("div", { ...a.el("signUpPage.footer", "throttle-page__footer"), children: props.footer }) : null
3745
3942
  ] }) }) });
3746
3943
  }
3747
3944
 
3748
3945
  // src/react/components/guards.tsx
3749
- import { Fragment as Fragment11, jsx as jsx48 } from "react/jsx-runtime";
3946
+ import { Fragment as Fragment11, jsx as jsx49 } from "react/jsx-runtime";
3750
3947
  function SignedIn(props) {
3751
3948
  const { status } = useAuth();
3752
- return status === "authenticated" ? /* @__PURE__ */ jsx48(Fragment11, { children: props.children }) : null;
3949
+ return status === "authenticated" ? /* @__PURE__ */ jsx49(Fragment11, { children: props.children }) : null;
3753
3950
  }
3754
3951
  function SignedOut(props) {
3755
3952
  const { status } = useAuth();
3756
- return status === "unauthenticated" ? /* @__PURE__ */ jsx48(Fragment11, { children: props.children }) : null;
3953
+ return status === "unauthenticated" ? /* @__PURE__ */ jsx49(Fragment11, { children: props.children }) : null;
3757
3954
  }
3758
3955
  function Protect(props) {
3759
3956
  const { status, emailVerified } = useAuth();
3760
3957
  if (status === "loading") return null;
3761
- if (status !== "authenticated") return /* @__PURE__ */ jsx48(Fragment11, { children: props.fallback ?? null });
3762
- if (props.requireVerified && !emailVerified) return /* @__PURE__ */ jsx48(Fragment11, { children: props.fallback ?? null });
3763
- return /* @__PURE__ */ jsx48(Fragment11, { children: props.children });
3958
+ if (status !== "authenticated") return /* @__PURE__ */ jsx49(Fragment11, { children: props.fallback ?? null });
3959
+ if (props.requireVerified && !emailVerified) return /* @__PURE__ */ jsx49(Fragment11, { children: props.fallback ?? null });
3960
+ return /* @__PURE__ */ jsx49(Fragment11, { children: props.children });
3764
3961
  }
3765
3962
 
3766
3963
  // src/react/components/UserButton.tsx
3767
- import { useContext as useContext8, useId as useId6, useRef as useRef7, useState as useState22 } from "react";
3768
- import { jsx as jsx49, jsxs as jsxs38 } from "react/jsx-runtime";
3964
+ import { useContext as useContext8, useId as useId7, useRef as useRef9, useState as useState24 } from "react";
3965
+ import { jsx as jsx50, jsxs as jsxs39 } from "react/jsx-runtime";
3769
3966
  function UserButtonRoot(props) {
3770
3967
  const a = useAppearance(props.appearance);
3771
3968
  const scoped = useAppearanceProviderValue(props.appearance);
3772
3969
  const { t } = useCopy(props.localization);
3773
3970
  const { auth, status, customer, emailVerified } = useAuth();
3774
3971
  const ui = useContext8(ThrottleUIContext);
3775
- const [localOpen, setLocalOpen] = useState22(false);
3972
+ const [localOpen, setLocalOpen] = useState24(false);
3776
3973
  const accountOpen = ui ? false : localOpen;
3777
- const titleId = useId6();
3778
- const rootRef = useRef7(null);
3779
- const openerRef = useRef7(null);
3974
+ const titleId = useId7();
3975
+ const rootRef = useRef9(null);
3976
+ const openerRef = useRef9(null);
3780
3977
  const openAccount = () => {
3781
3978
  const opener = rootRef.current?.querySelector('button[aria-haspopup="menu"]') ?? null;
3782
3979
  openerRef.current = opener;
@@ -3785,25 +3982,25 @@ function UserButtonRoot(props) {
3785
3982
  };
3786
3983
  if (status !== "authenticated" || !customer) return null;
3787
3984
  const name = [customer.firstName, customer.lastName].filter(Boolean).join(" ");
3788
- return /* @__PURE__ */ jsx49(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx49("span", { ...a.rootProps, children: /* @__PURE__ */ jsxs38("span", { ref: rootRef, ...a.el("userButton.root"), children: [
3789
- /* @__PURE__ */ jsxs38(
3985
+ return /* @__PURE__ */ jsx50(AppearanceProvider, { value: scoped, children: /* @__PURE__ */ jsx50("span", { ...a.rootProps, children: /* @__PURE__ */ jsxs39("span", { ref: rootRef, ...a.el("userButton.root"), children: [
3986
+ /* @__PURE__ */ jsxs39(
3790
3987
  Dropdown,
3791
3988
  {
3792
3989
  label: t.userButton.openMenu,
3793
3990
  triggerKey: "userButton.trigger",
3794
3991
  menuKey: "userButton.menu",
3795
- trigger: /* @__PURE__ */ jsx49(Avatar, { name, email: customer.email }),
3992
+ trigger: /* @__PURE__ */ jsx50(Avatar, { name, email: customer.email }),
3796
3993
  children: [
3797
- /* @__PURE__ */ jsx49("div", { ...a.el("userButton.identity", "throttle-dropdown__item"), children: /* @__PURE__ */ jsxs38("span", { children: [
3798
- /* @__PURE__ */ jsx49("span", { ...a.el("userButton.email"), children: customer.email }),
3799
- /* @__PURE__ */ jsx49("br", {}),
3800
- /* @__PURE__ */ jsx49(Badge, { tone: emailVerified ? "success" : "warning", elementKey: "userButton.badge", children: emailVerified ? t.userButton.verified : t.userButton.unverified })
3994
+ /* @__PURE__ */ jsx50("div", { ...a.el("userButton.identity", "throttle-dropdown__item"), children: /* @__PURE__ */ jsxs39("span", { children: [
3995
+ /* @__PURE__ */ jsx50("span", { ...a.el("userButton.email"), children: customer.email }),
3996
+ /* @__PURE__ */ jsx50("br", {}),
3997
+ /* @__PURE__ */ jsx50(Badge, { tone: emailVerified ? "success" : "warning", elementKey: "userButton.badge", children: emailVerified ? t.userButton.verified : t.userButton.unverified })
3801
3998
  ] }) }),
3802
- /* @__PURE__ */ jsx49(DropdownSeparator, {}),
3803
- props.mode === "navigate" ? /* @__PURE__ */ jsx49(DropdownItem, { itemKey: "userButton.manageButton", href: props.accountUrl ?? "#", children: t.userButton.manage }) : /* @__PURE__ */ jsx49(DropdownItem, { itemKey: "userButton.manageButton", onClick: openAccount, children: t.userButton.manage }),
3999
+ /* @__PURE__ */ jsx50(DropdownSeparator, {}),
4000
+ props.mode === "navigate" ? /* @__PURE__ */ jsx50(DropdownItem, { itemKey: "userButton.manageButton", href: props.accountUrl ?? "#", children: t.userButton.manage }) : /* @__PURE__ */ jsx50(DropdownItem, { itemKey: "userButton.manageButton", onClick: openAccount, children: t.userButton.manage }),
3804
4001
  props.children,
3805
- /* @__PURE__ */ jsx49(DropdownSeparator, {}),
3806
- /* @__PURE__ */ jsx49(
4002
+ /* @__PURE__ */ jsx50(DropdownSeparator, {}),
4003
+ /* @__PURE__ */ jsx50(
3807
4004
  DropdownItem,
3808
4005
  {
3809
4006
  itemKey: "userButton.signOutButton",
@@ -3811,7 +4008,7 @@ function UserButtonRoot(props) {
3811
4008
  children: t.userButton.signOut
3812
4009
  }
3813
4010
  ),
3814
- /* @__PURE__ */ jsx49(
4011
+ /* @__PURE__ */ jsx50(
3815
4012
  DropdownItem,
3816
4013
  {
3817
4014
  itemKey: "userButton.signOutAllButton",
@@ -3822,7 +4019,7 @@ function UserButtonRoot(props) {
3822
4019
  ]
3823
4020
  }
3824
4021
  ),
3825
- props.mode !== "navigate" && !ui ? /* @__PURE__ */ jsxs38(
4022
+ props.mode !== "navigate" && !ui ? /* @__PURE__ */ jsxs39(
3826
4023
  Modal,
3827
4024
  {
3828
4025
  open: accountOpen,
@@ -3830,8 +4027,8 @@ function UserButtonRoot(props) {
3830
4027
  labelledBy: titleId,
3831
4028
  restoreFocusTo: openerRef.current,
3832
4029
  children: [
3833
- /* @__PURE__ */ jsx49("h2", { id: titleId, style: { padding: "16px 16px 0", margin: 0 }, children: t.account.title }),
3834
- /* @__PURE__ */ jsx49("div", { style: { padding: 16 }, children: /* @__PURE__ */ jsx49(
4030
+ /* @__PURE__ */ jsx50("h2", { id: titleId, style: { padding: "16px 16px 0", margin: 0 }, children: t.account.title }),
4031
+ /* @__PURE__ */ jsx50("div", { style: { padding: 16 }, children: /* @__PURE__ */ jsx50(
3835
4032
  AccountDashboard,
3836
4033
  {
3837
4034
  tabs: props.tabs,
@@ -3845,13 +4042,13 @@ function UserButtonRoot(props) {
3845
4042
  ] }) }) });
3846
4043
  }
3847
4044
  function UserButtonLink(props) {
3848
- return /* @__PURE__ */ jsxs38(DropdownItem, { itemKey: "userButton.item", href: props.href, children: [
4045
+ return /* @__PURE__ */ jsxs39(DropdownItem, { itemKey: "userButton.item", href: props.href, children: [
3849
4046
  props.icon,
3850
4047
  props.label
3851
4048
  ] });
3852
4049
  }
3853
4050
  function UserButtonAction(props) {
3854
- return /* @__PURE__ */ jsxs38(DropdownItem, { itemKey: "userButton.item", onClick: props.onClick, children: [
4051
+ return /* @__PURE__ */ jsxs39(DropdownItem, { itemKey: "userButton.item", onClick: props.onClick, children: [
3855
4052
  props.icon,
3856
4053
  props.label
3857
4054
  ] });
@@ -3864,6 +4061,7 @@ export {
3864
4061
  ACCOUNT_TABS,
3865
4062
  AccountDashboard,
3866
4063
  AccountModal,
4064
+ AddCardDialog,
3867
4065
  AddressesPanel,
3868
4066
  AuthFlow,
3869
4067
  AuthModal,