@solvapay/react 2.2.2 → 2.3.0-preview-e77af6c08d8a185342e1a74903c8545b94a9f51d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  ExternalLinkGlyph,
3
3
  LaunchCustomerPortalButton,
4
- paymentMethodCache,
5
- usePaymentMethod
6
- } from "../chunk-4UFQDYG5.js";
4
+ paymentMethodCache
5
+ } from "../chunk-QWK3LMGG.js";
7
6
  import {
8
7
  AmountPicker,
9
8
  BalanceBadge,
@@ -17,12 +16,9 @@ import {
17
16
  SolvaPayProvider,
18
17
  TopupForm,
19
18
  UsageMeter,
20
- buildSummaryLine,
21
- configToForm,
22
19
  createDefaultAutoRechargeForm,
23
20
  createTransportCacheKey,
24
21
  estimateCredits,
25
- formatAmountWithUnit,
26
22
  formatContinueLabel,
27
23
  formatCycleSuffix,
28
24
  formatPaygRate,
@@ -43,7 +39,6 @@ import {
43
39
  seedUsageSnapshot,
44
40
  useActivation,
45
41
  useAmountPicker,
46
- useAutoRecharge,
47
42
  useBalance,
48
43
  useCheckoutFlow,
49
44
  useCopy,
@@ -62,7 +57,7 @@ import {
62
57
  useTransport,
63
58
  useUsage,
64
59
  validateAutoRechargeForm
65
- } from "../chunk-GPP4MY3I.js";
60
+ } from "../chunk-JXH36VLL.js";
66
61
  import "../chunk-UMXOAUW7.js";
67
62
  import "../chunk-MLKGABMK.js";
68
63
 
@@ -133,19 +128,54 @@ import { MCP_TOOL_NAMES as MCP_TOOL_NAMES3 } from "@solvapay/mcp-core";
133
128
  // src/mcp/useStripeProbe.ts
134
129
  import { useEffect, useState } from "react";
135
130
  import { loadStripe } from "@stripe/stripe-js";
136
- var STRIPE_LOAD_TIMEOUT_MS = 3e3;
137
- var ELEMENT_MOUNT_TIMEOUT_MS = 2e3;
131
+ var STRIPE_LOAD_TIMEOUT_MS = 1e4;
132
+ var ELEMENT_MOUNT_TIMEOUT_MS = 6e3;
133
+ var CACHEABLE_BLOCKED_REASONS = /* @__PURE__ */ new Set([
134
+ "csp-frame-src",
135
+ "loaderror",
136
+ "load-rejected",
137
+ "load-null-instance",
138
+ "elements-create-threw"
139
+ ]);
140
+ var stripeProbeCache = /* @__PURE__ */ new Map();
141
+ function resetStripeProbeCacheForTests() {
142
+ stripeProbeCache.clear();
143
+ }
144
+ function readCachedProbe(publishableKey) {
145
+ if (!publishableKey) return "blocked";
146
+ return stripeProbeCache.get(publishableKey) ?? "loading";
147
+ }
148
+ function cacheProbeVerdict(publishableKey, next, reason) {
149
+ if (next === "ready") {
150
+ stripeProbeCache.set(publishableKey, "ready");
151
+ return;
152
+ }
153
+ if (next === "blocked" && reason && CACHEABLE_BLOCKED_REASONS.has(reason)) {
154
+ stripeProbeCache.set(publishableKey, "blocked");
155
+ }
156
+ }
138
157
  function useStripeProbe(publishableKey) {
139
- const [state, setState] = useState(
140
- publishableKey ? "loading" : "blocked"
141
- );
158
+ const [state, setState] = useState(() => readCachedProbe(publishableKey));
142
159
  useEffect(() => {
143
160
  if (typeof document === "undefined") return;
144
161
  if (!publishableKey) {
162
+ console.warn("[solvapay-mcp] stripe probe blocked", {
163
+ reason: "no-publishable-key",
164
+ elapsedMs: 0,
165
+ loadMs: null
166
+ });
145
167
  setState("blocked");
146
168
  return;
147
169
  }
170
+ const cached = stripeProbeCache.get(publishableKey);
171
+ if (cached) {
172
+ setState(cached);
173
+ return;
174
+ }
148
175
  setState("loading");
176
+ const startedAt = Date.now();
177
+ let loadResolvedAt = null;
178
+ let mountStartedAt = null;
149
179
  let cancelled = false;
150
180
  let resolved = false;
151
181
  let cspBlockedStripeFrame = false;
@@ -183,7 +213,7 @@ function useStripeProbe(publishableKey) {
183
213
  sourceFile: event.sourceFile
184
214
  }
185
215
  );
186
- resolve("blocked");
216
+ resolve("blocked", "csp-frame-src");
187
217
  };
188
218
  document.addEventListener("securitypolicyviolation", onCspViolation);
189
219
  const teardown = () => {
@@ -201,24 +231,46 @@ function useStripeProbe(publishableKey) {
201
231
  host = null;
202
232
  }
203
233
  };
204
- const resolve = (next) => {
234
+ const logBlocked = (reason) => {
235
+ console.warn("[solvapay-mcp] stripe probe blocked", {
236
+ reason,
237
+ elapsedMs: Date.now() - startedAt,
238
+ loadMs: loadResolvedAt !== null ? loadResolvedAt - startedAt : null
239
+ });
240
+ };
241
+ const logReady = () => {
242
+ const now = Date.now();
243
+ console.warn("[solvapay-mcp] stripe probe ready", {
244
+ elapsedMs: now - startedAt,
245
+ loadMs: loadResolvedAt !== null ? loadResolvedAt - startedAt : null,
246
+ mountMs: mountStartedAt !== null ? now - mountStartedAt : null
247
+ });
248
+ };
249
+ const resolve = (next, reason) => {
205
250
  if (cancelled || resolved) return;
206
251
  resolved = true;
252
+ if (next === "ready") {
253
+ logReady();
254
+ } else if (reason) {
255
+ logBlocked(reason);
256
+ }
257
+ cacheProbeVerdict(publishableKey, next, reason);
207
258
  teardown();
208
259
  setState(next);
209
260
  };
210
261
  loadTimeoutId = setTimeout(() => {
211
262
  loadTimeoutId = null;
212
- resolve("blocked");
263
+ resolve("blocked", "load-timeout");
213
264
  }, STRIPE_LOAD_TIMEOUT_MS);
214
265
  loadStripe(publishableKey, { developerTools: { assistant: { enabled: false } } }).then((stripe) => {
266
+ loadResolvedAt = Date.now();
215
267
  if (cancelled || resolved) return;
216
268
  if (loadTimeoutId !== null) {
217
269
  clearTimeout(loadTimeoutId);
218
270
  loadTimeoutId = null;
219
271
  }
220
272
  if (!stripe) {
221
- resolve("blocked");
273
+ resolve("blocked", "load-null-instance");
222
274
  return;
223
275
  }
224
276
  try {
@@ -233,22 +285,24 @@ function useStripeProbe(publishableKey) {
233
285
  if (cspBlockedStripeFrame) return;
234
286
  resolve("ready");
235
287
  });
236
- element.on("loaderror", () => resolve("blocked"));
288
+ element.on("loaderror", () => resolve("blocked", "loaderror"));
237
289
  elementTimeoutId = setTimeout(() => {
238
290
  elementTimeoutId = null;
239
- resolve("blocked");
291
+ resolve("blocked", "mount-timeout");
240
292
  }, ELEMENT_MOUNT_TIMEOUT_MS);
293
+ mountStartedAt = Date.now();
241
294
  element.mount(host);
242
295
  } catch {
243
- resolve("blocked");
296
+ resolve("blocked", "elements-create-threw");
244
297
  }
245
298
  }).catch(() => {
299
+ loadResolvedAt = Date.now();
246
300
  if (cancelled || resolved) return;
247
301
  if (loadTimeoutId !== null) {
248
302
  clearTimeout(loadTimeoutId);
249
303
  loadTimeoutId = null;
250
304
  }
251
- resolve("blocked");
305
+ resolve("blocked", "load-rejected");
252
306
  });
253
307
  return () => {
254
308
  cancelled = true;
@@ -516,7 +570,8 @@ function parseBootstrapFromToolResult(result, toolName, fallbackView) {
516
570
  merchant: structured?.merchant ?? {},
517
571
  product: structured?.product ?? { reference: ref },
518
572
  plans: Array.isArray(structured?.plans) ? structured.plans : [],
519
- customer: structured?.customer ?? null
573
+ customer: structured?.customer ?? null,
574
+ ...typeof structured?.autoRechargeUrl === "string" ? { autoRechargeUrl: structured.autoRechargeUrl } : {}
520
575
  };
521
576
  }
522
577
  function waitForInitialToolResult(app, options = {}) {
@@ -648,11 +703,11 @@ function seedMcpCaches(initial, config) {
648
703
  }
649
704
 
650
705
  // src/mcp/McpApp.tsx
651
- import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState11 } from "react";
706
+ import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef8, useState as useState12 } from "react";
652
707
  import { VIEW_FOR_TOOL as VIEW_FOR_TOOL2 } from "@solvapay/mcp-core";
653
708
 
654
709
  // src/mcp/McpAppShell.tsx
655
- import { useCallback as useCallback5, useState as useState9 } from "react";
710
+ import { useCallback as useCallback5, useState as useState10 } from "react";
656
711
 
657
712
  // src/mcp/account-state.ts
658
713
  import {
@@ -1969,7 +2024,8 @@ function CreditAccountPanel({
1969
2024
  locale,
1970
2025
  classNames,
1971
2026
  onTopup,
1972
- onAutoRecharge,
2027
+ autoRecharge,
2028
+ autoRechargeUrl,
1973
2029
  onChangePlan,
1974
2030
  showPortalCta
1975
2031
  }) {
@@ -1977,8 +2033,7 @@ function CreditAccountPanel({
1977
2033
  const copy = useCopy();
1978
2034
  const balance = useBalance();
1979
2035
  const { merchant } = useMerchant();
1980
- const { config: autoRecharge } = useAutoRecharge();
1981
- const { paymentMethod } = usePaymentMethod();
2036
+ const handleExternalClick = useExternalLinkClick();
1982
2037
  const { displayMode } = useDisplayMode();
1983
2038
  const isFullscreen = displayMode === "fullscreen";
1984
2039
  const history = useHistory({
@@ -1996,10 +2051,13 @@ function CreditAccountPanel({
1996
2051
  paidPlanCount
1997
2052
  });
1998
2053
  const showChangePlan = Boolean(onChangePlan && (actions.changePlan || actions.upgrade));
1999
- const autoRechargeOn = Boolean(autoRecharge?.enabled);
2000
- const hasReusableCard = paymentMethod?.kind === "card" && paymentMethod.reusable;
2001
- const autoRechargeAction = onAutoRecharge && (autoRechargeOn || hasReusableCard) ? onAutoRecharge : void 0;
2002
- const autoRechargeActionLabel = autoRechargeOn ? copy.account.manage : copy.account.turnOn;
2054
+ const status = autoRecharge?.status;
2055
+ const enabled = autoRecharge?.enabled === true;
2056
+ const failed = status === "failed";
2057
+ const pendingSetup = enabled && status === "pending_setup";
2058
+ const title = failed ? copy.autoRecharge.statusFailed : pendingSetup ? copy.account.autoRechargePending : enabled ? copy.account.autoRechargeOn : copy.account.autoRechargeOff;
2059
+ const caption = !enabled && !failed ? accountState === "D" ? copy.account.autoRechargeOffFixCaption : copy.account.autoRechargeOffCaption : null;
2060
+ const actionLabel = failed ? copy.account.fixCard : enabled ? copy.account.manage : copy.account.turnOn;
2003
2061
  return /* @__PURE__ */ jsxs5("div", { className: "solvapay-mcp-account", children: [
2004
2062
  /* @__PURE__ */ jsxs5("div", { className: cx2.card, children: [
2005
2063
  /* @__PURE__ */ jsx8(
@@ -2028,10 +2086,24 @@ function CreditAccountPanel({
2028
2086
  onTopup ? /* @__PURE__ */ jsx8("button", { type: "button", className: cx2.button, onClick: onTopup, children: copy.account.addFunds }) : null,
2029
2087
  /* @__PURE__ */ jsxs5(SplitRow, { children: [
2030
2088
  /* @__PURE__ */ jsxs5("div", { className: "solvapay-mcp-auto-recharge-copy", children: [
2031
- /* @__PURE__ */ jsx8("p", { children: autoRechargeOn ? copy.account.autoRechargeOn : copy.account.autoRechargeOff }),
2032
- !autoRechargeOn ? /* @__PURE__ */ jsx8("p", { className: cx2.muted, children: accountState === "D" ? copy.account.autoRechargeOffFixCaption : copy.account.autoRechargeOffCaption }) : null
2089
+ /* @__PURE__ */ jsx8("p", { children: title }),
2090
+ caption ? /* @__PURE__ */ jsx8("p", { className: cx2.muted, children: caption }) : null
2033
2091
  ] }),
2034
- autoRechargeAction ? /* @__PURE__ */ jsx8("button", { type: "button", className: cx2.linkButton, onClick: autoRechargeAction, children: autoRechargeActionLabel }) : null
2092
+ autoRechargeUrl ? /* @__PURE__ */ jsxs5(
2093
+ "a",
2094
+ {
2095
+ href: autoRechargeUrl,
2096
+ target: "_blank",
2097
+ rel: "noopener noreferrer",
2098
+ className: cx2.linkButton,
2099
+ "aria-label": `${actionLabel} (opens in a new tab)`,
2100
+ onClick: handleExternalClick,
2101
+ children: [
2102
+ actionLabel,
2103
+ /* @__PURE__ */ jsx8(ExternalLinkGlyph, {})
2104
+ ]
2105
+ }
2106
+ ) : null
2035
2107
  ] }),
2036
2108
  showPortalCta && !isFullscreen ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
2037
2109
  /* @__PURE__ */ jsx8("p", { className: cx2.muted, "data-solvapay-mcp-portal-hint": "", children: copy.currentPlan.portalHint }),
@@ -2621,7 +2693,8 @@ function McpAccountView({
2621
2693
  productRef,
2622
2694
  classNames,
2623
2695
  onTopup,
2624
- onAutoRecharge,
2696
+ autoRecharge,
2697
+ autoRechargeUrl,
2625
2698
  onChangePlan,
2626
2699
  plans
2627
2700
  }) {
@@ -2665,7 +2738,8 @@ function McpAccountView({
2665
2738
  locale,
2666
2739
  classNames,
2667
2740
  onTopup,
2668
- onAutoRecharge,
2741
+ autoRecharge,
2742
+ autoRechargeUrl,
2669
2743
  onChangePlan,
2670
2744
  showPortalCta
2671
2745
  }
@@ -2724,8 +2798,11 @@ function McpAccountView({
2724
2798
  );
2725
2799
  }
2726
2800
 
2727
- // src/mcp/views/McpAutoRechargeView.tsx
2728
- import { useState as useState5 } from "react";
2801
+ // src/mcp/views/checkout/EmbeddedCheckout.tsx
2802
+ import { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5, useState as useState8 } from "react";
2803
+
2804
+ // src/mcp/views/checkout/steps/PlanStep.tsx
2805
+ import { memo } from "react";
2729
2806
 
2730
2807
  // src/mcp/views/BackLink.tsx
2731
2808
  import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
@@ -2745,256 +2822,8 @@ function BackLink({ label, glyph = "\u2190", className, onClick, ...rest }) {
2745
2822
  );
2746
2823
  }
2747
2824
 
2748
- // src/mcp/views/autoRecharge/McpAutoRechargeFields.tsx
2749
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2750
- function currencySymbol(currency) {
2751
- try {
2752
- const parts = new Intl.NumberFormat("en", {
2753
- style: "currency",
2754
- currency,
2755
- currencyDisplay: "narrowSymbol"
2756
- }).formatToParts(0);
2757
- return parts.find((part) => part.type === "currency")?.value ?? currency.toUpperCase();
2758
- } catch {
2759
- return currency.toUpperCase();
2760
- }
2761
- }
2762
- function McpAutoRechargeFields({
2763
- form,
2764
- onChange,
2765
- currency,
2766
- validationError,
2767
- creditsPerMinorUnit,
2768
- displayExchangeRate
2769
- }) {
2770
- const copy = useCopy();
2771
- const prefix = currencySymbol(currency);
2772
- const suffix = currency.toUpperCase();
2773
- const credits = estimateCredits(
2774
- Number(form.topupAmountMajor),
2775
- currency,
2776
- creditsPerMinorUnit,
2777
- displayExchangeRate
2778
- );
2779
- const explainer = credits != null ? interpolate(copy.autoRechargeView.explainer, {
2780
- credits: new Intl.NumberFormat().format(credits)
2781
- }) : copy.autoRechargeView.explainerNoEstimate;
2782
- return /* @__PURE__ */ jsxs9("div", { className: "solvapay-mcp-auto-recharge-fields", children: [
2783
- /* @__PURE__ */ jsx14(
2784
- Field,
2785
- {
2786
- id: "mcp-auto-recharge-threshold",
2787
- label: copy.autoRechargeView.thresholdLabel,
2788
- value: form.thresholdAmountMajor,
2789
- prefix,
2790
- suffix,
2791
- onChange: (thresholdAmountMajor) => onChange({ ...form, thresholdAmountMajor })
2792
- }
2793
- ),
2794
- /* @__PURE__ */ jsx14(
2795
- Field,
2796
- {
2797
- id: "mcp-auto-recharge-topup",
2798
- label: copy.autoRechargeView.topupLabel,
2799
- value: form.topupAmountMajor,
2800
- prefix,
2801
- suffix,
2802
- onChange: (topupAmountMajor) => onChange({ ...form, topupAmountMajor })
2803
- }
2804
- ),
2805
- /* @__PURE__ */ jsx14(
2806
- Field,
2807
- {
2808
- id: "mcp-auto-recharge-cap",
2809
- label: copy.autoRechargeView.maxMonthlySpendLabel,
2810
- value: form.maxMonthlySpendMajor,
2811
- prefix,
2812
- suffix,
2813
- placeholder: copy.autoRechargeView.maxMonthlySpendPlaceholder,
2814
- onChange: (maxMonthlySpendMajor) => onChange({ ...form, maxMonthlySpendMajor })
2815
- }
2816
- ),
2817
- /* @__PURE__ */ jsx14("p", { className: "solvapay-mcp-auto-recharge-fields-explainer", children: explainer }),
2818
- validationError ? /* @__PURE__ */ jsx14("p", { className: "solvapay-mcp-auto-recharge-fields-error", role: "alert", children: validationError }) : null
2819
- ] });
2820
- }
2821
-
2822
- // src/mcp/views/McpAutoRechargeView.tsx
2823
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2824
- var FALLBACK_CURRENCY = "USD";
2825
- function resolveCurrency(displayCurrency, merchantCurrency) {
2826
- if (displayCurrency) return displayCurrency.toUpperCase();
2827
- if (merchantCurrency) return merchantCurrency.toUpperCase();
2828
- return FALLBACK_CURRENCY;
2829
- }
2830
- function McpAutoRechargeView({ classNames, onBack }) {
2831
- const cx2 = resolveMcpClassNames(classNames);
2832
- const copy = useCopy();
2833
- const { merchant, loading: merchantLoading } = useMerchant();
2834
- const { displayCurrency, creditsPerMinorUnit, displayExchangeRate } = useBalance();
2835
- const { config, loading, saving, disabling, error, save, disable } = useAutoRecharge();
2836
- const currency = resolveCurrency(displayCurrency, merchant?.defaultCurrency);
2837
- const conversion = { creditsPerMinorUnit, displayExchangeRate };
2838
- const [form, setForm] = useState5(() => ({
2839
- ...createDefaultAutoRechargeForm(currency),
2840
- enabled: true
2841
- }));
2842
- const [hydrated, setHydrated] = useState5(false);
2843
- const [validationError, setValidationError] = useState5(null);
2844
- const [setupError, setSetupError] = useState5(null);
2845
- if (!loading && !hydrated) {
2846
- setHydrated(true);
2847
- if (config?.enabled) {
2848
- setForm({ ...configToForm(config, currency), enabled: true });
2849
- }
2850
- }
2851
- const editing = Boolean(config?.enabled);
2852
- const summary = buildSummaryLine(form, currency);
2853
- const thresholdDisplay = formatAmountWithUnit(
2854
- form.thresholdAmountMajor,
2855
- form.thresholdUnit,
2856
- currency
2857
- );
2858
- if (loading || merchantLoading) {
2859
- return /* @__PURE__ */ jsx15("section", { className: cx2.card, "aria-label": "Loading auto-recharge", children: /* @__PURE__ */ jsx15("p", { children: "Loading auto-recharge\u2026" }) });
2860
- }
2861
- const handleSave = async () => {
2862
- const result = validateAutoRechargeForm(
2863
- { ...form, enabled: true },
2864
- currency,
2865
- conversion,
2866
- copy.autoRecharge
2867
- );
2868
- if (!result.ok) {
2869
- setValidationError(result.error);
2870
- return;
2871
- }
2872
- setValidationError(null);
2873
- setSetupError(null);
2874
- try {
2875
- const response = await save(result.payload);
2876
- if (response.setupClientSecret) {
2877
- setSetupError(copy.autoRechargeView.setupUnexpected);
2878
- return;
2879
- }
2880
- onBack?.();
2881
- } catch {
2882
- }
2883
- };
2884
- const handleDisable = async () => {
2885
- setSetupError(null);
2886
- try {
2887
- await disable();
2888
- onBack?.();
2889
- } catch {
2890
- }
2891
- };
2892
- const loudError = setupError ?? (error ? error.message : null);
2893
- return /* @__PURE__ */ jsx15("section", { className: cx2.card, "aria-label": copy.autoRechargeView.heading, children: /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-view", children: [
2894
- onBack ? /* @__PURE__ */ jsx15(BackLink, { label: copy.autoRechargeView.back, onClick: onBack }) : null,
2895
- /* @__PURE__ */ jsxs10("div", { className: cx2.stack, children: [
2896
- /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-heading", children: [
2897
- /* @__PURE__ */ jsx15("h2", { className: cx2.heading, children: copy.autoRechargeView.heading }),
2898
- editing ? /* @__PURE__ */ jsx15(StatusDot, { label: copy.autoRechargeView.statusOn }) : null
2899
- ] }),
2900
- editing ? null : /* @__PURE__ */ jsx15("p", { className: cx2.muted, children: copy.autoRechargeView.description }),
2901
- summary ? /* @__PURE__ */ jsx15("p", { className: "solvapay-mcp-auto-recharge-summary", children: summary }) : null
2902
- ] }),
2903
- /* @__PURE__ */ jsx15(Section, { children: /* @__PURE__ */ jsx15(
2904
- McpAutoRechargeFields,
2905
- {
2906
- form,
2907
- onChange: (next) => {
2908
- setValidationError(null);
2909
- setForm(next);
2910
- },
2911
- currency,
2912
- validationError,
2913
- creditsPerMinorUnit,
2914
- displayExchangeRate
2915
- }
2916
- ) }),
2917
- loudError ? /* @__PURE__ */ jsx15("p", { className: cx2.error, role: "alert", children: loudError }) : null,
2918
- editing ? /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-actions-stack", children: [
2919
- /* @__PURE__ */ jsx15(
2920
- "button",
2921
- {
2922
- type: "button",
2923
- className: cx2.button,
2924
- disabled: saving || disabling,
2925
- onClick: () => {
2926
- void handleSave();
2927
- },
2928
- children: copy.autoRechargeView.save
2929
- }
2930
- ),
2931
- /* @__PURE__ */ jsx15(
2932
- "button",
2933
- {
2934
- type: "button",
2935
- className: cx2.button,
2936
- "data-variant": "secondary",
2937
- disabled: saving || disabling,
2938
- onClick: onBack,
2939
- children: copy.autoRechargeView.cancel
2940
- }
2941
- ),
2942
- /* @__PURE__ */ jsx15(
2943
- "button",
2944
- {
2945
- type: "button",
2946
- className: `${cx2.linkButton} solvapay-mcp-auto-recharge-turn-off`.trim(),
2947
- disabled: saving || disabling,
2948
- onClick: () => {
2949
- void handleDisable();
2950
- },
2951
- children: copy.autoRechargeView.turnOff
2952
- }
2953
- )
2954
- ] }) : /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-footer", children: [
2955
- /* @__PURE__ */ jsx15("p", { className: cx2.muted, children: interpolate(copy.autoRechargeView.footerCaption, {
2956
- threshold: thresholdDisplay
2957
- }) }),
2958
- /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-actions", children: [
2959
- /* @__PURE__ */ jsx15(
2960
- "button",
2961
- {
2962
- type: "button",
2963
- className: cx2.button,
2964
- "data-variant": "secondary",
2965
- disabled: saving,
2966
- onClick: onBack,
2967
- children: copy.autoRechargeView.cancel
2968
- }
2969
- ),
2970
- /* @__PURE__ */ jsx15(
2971
- "button",
2972
- {
2973
- type: "button",
2974
- className: cx2.button,
2975
- disabled: saving,
2976
- onClick: () => {
2977
- void handleSave();
2978
- },
2979
- children: copy.autoRechargeView.turnOn
2980
- }
2981
- )
2982
- ] })
2983
- ] })
2984
- ] }) });
2985
- }
2986
-
2987
- // src/mcp/views/McpCheckoutView.tsx
2988
- import React11, { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef4, useState as useState7 } from "react";
2989
-
2990
- // src/mcp/views/checkout/EmbeddedCheckout.tsx
2991
- import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef3 } from "react";
2992
-
2993
- // src/mcp/views/checkout/steps/PlanStep.tsx
2994
- import { memo } from "react";
2995
-
2996
2825
  // src/mcp/views/checkout/CheckoutPlanRow.tsx
2997
- import { jsx as jsx16 } from "react/jsx-runtime";
2826
+ import { jsx as jsx14 } from "react/jsx-runtime";
2998
2827
  function CheckoutPlanRow({
2999
2828
  plan,
3000
2829
  locale,
@@ -3011,7 +2840,7 @@ function CheckoutPlanRow({
3011
2840
  const state = resolvePlanRowState({ current, selected, free });
3012
2841
  const priceLabel = formatPlanPriceLabel(plan, locale, selectedOption);
3013
2842
  const description = descriptionOverride ?? planWhatItGives(plan, locale, balance);
3014
- return /* @__PURE__ */ jsx16(
2843
+ return /* @__PURE__ */ jsx14(
3015
2844
  PlanRow,
3016
2845
  {
3017
2846
  name: plan.name ?? plan.reference,
@@ -3051,7 +2880,7 @@ function planWhatItGives(plan, locale, balance) {
3051
2880
  }
3052
2881
 
3053
2882
  // src/mcp/views/checkout/steps/PlanStep.tsx
3054
- import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2883
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
3055
2884
  var PlanStep = memo(function PlanStep2({
3056
2885
  fromPaywall,
3057
2886
  paywallKind,
@@ -3071,14 +2900,14 @@ var PlanStep = memo(function PlanStep2({
3071
2900
  const pricingOption = selectedPlan ? getSelectedOption(selectedPlan) : void 0;
3072
2901
  const ctaLabel = formatContinueLabel(selectedPlanShape, locale, pricingOption);
3073
2902
  const showPreface = fromPaywall && !hideUpgradeBanner && paywallKind !== "payment_required";
3074
- return /* @__PURE__ */ jsxs11(Fragment5, { children: [
3075
- onBack ? /* @__PURE__ */ jsx17(BackLink, { label: copy.checkout.backToAccount, onClick: onBack }) : null,
3076
- showPreface ? /* @__PURE__ */ jsx17("p", { className: cx2.muted, role: "status", children: "This tool needs a paid plan. Pick one to get started." }) : null,
3077
- /* @__PURE__ */ jsxs11("div", { className: "solvapay-mcp-plan-step-header", children: [
3078
- /* @__PURE__ */ jsx17("h2", { className: cx2.heading, children: "Choose a plan" }),
3079
- /* @__PURE__ */ jsx17(PlanSelector.CurrencySwitcher, { className: "solvapay-plan-selector-currency-switcher" })
2903
+ return /* @__PURE__ */ jsxs9(Fragment5, { children: [
2904
+ onBack ? /* @__PURE__ */ jsx15(BackLink, { label: copy.checkout.backToAccount, onClick: onBack }) : null,
2905
+ showPreface ? /* @__PURE__ */ jsx15("p", { className: cx2.muted, role: "status", children: "This tool needs a paid plan. Pick one to get started." }) : null,
2906
+ /* @__PURE__ */ jsxs9("div", { className: "solvapay-mcp-plan-step-header", children: [
2907
+ /* @__PURE__ */ jsx15("h2", { className: cx2.heading, children: "Choose a plan" }),
2908
+ /* @__PURE__ */ jsx15(PlanSelector.CurrencySwitcher, { className: "solvapay-plan-selector-currency-switcher" })
3080
2909
  ] }),
3081
- /* @__PURE__ */ jsx17("div", { className: "solvapay-mcp-plan-list", children: plans.map((plan) => /* @__PURE__ */ jsx17(
2910
+ /* @__PURE__ */ jsx15("div", { className: "solvapay-mcp-plan-list", children: plans.map((plan) => /* @__PURE__ */ jsx15(
3082
2911
  CheckoutPlanRow,
3083
2912
  {
3084
2913
  plan,
@@ -3092,10 +2921,10 @@ var PlanStep = memo(function PlanStep2({
3092
2921
  },
3093
2922
  plan.reference
3094
2923
  )) }),
3095
- /* @__PURE__ */ jsx17(PlanSelector.Loading, { className: "solvapay-plan-selector-loading" }),
3096
- /* @__PURE__ */ jsx17(PlanSelector.Error, { className: "solvapay-plan-selector-error" }),
3097
- activationError ? /* @__PURE__ */ jsx17("p", { className: cx2.error, role: "alert", children: activationError }) : null,
3098
- /* @__PURE__ */ jsx17(
2924
+ /* @__PURE__ */ jsx15(PlanSelector.Loading, { className: "solvapay-plan-selector-loading" }),
2925
+ /* @__PURE__ */ jsx15(PlanSelector.Error, { className: "solvapay-plan-selector-error" }),
2926
+ activationError ? /* @__PURE__ */ jsx15("p", { className: cx2.error, role: "alert", children: activationError }) : null,
2927
+ /* @__PURE__ */ jsx15(
3099
2928
  "button",
3100
2929
  {
3101
2930
  type: "button",
@@ -3106,7 +2935,7 @@ var PlanStep = memo(function PlanStep2({
3106
2935
  children: ctaLabel
3107
2936
  }
3108
2937
  ),
3109
- onStayOnFree ? /* @__PURE__ */ jsx17(
2938
+ onStayOnFree ? /* @__PURE__ */ jsx15(
3110
2939
  "button",
3111
2940
  {
3112
2941
  type: "button",
@@ -3120,7 +2949,143 @@ var PlanStep = memo(function PlanStep2({
3120
2949
  });
3121
2950
 
3122
2951
  // src/mcp/views/checkout/steps/AmountStep.tsx
3123
- import { memo as memo2, useState as useState6 } from "react";
2952
+ import { memo as memo2, useRef as useRef3, useState as useState6 } from "react";
2953
+
2954
+ // src/mcp/views/autoRecharge/McpInlineAutoRecharge.tsx
2955
+ import { forwardRef, useImperativeHandle, useState as useState5 } from "react";
2956
+
2957
+ // src/mcp/views/autoRecharge/McpAutoRechargeFields.tsx
2958
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2959
+ function currencySymbol(currency) {
2960
+ try {
2961
+ const parts = new Intl.NumberFormat("en", {
2962
+ style: "currency",
2963
+ currency,
2964
+ currencyDisplay: "narrowSymbol"
2965
+ }).formatToParts(0);
2966
+ return parts.find((part) => part.type === "currency")?.value ?? currency.toUpperCase();
2967
+ } catch {
2968
+ return currency.toUpperCase();
2969
+ }
2970
+ }
2971
+ function McpAutoRechargeFields({
2972
+ form,
2973
+ onChange,
2974
+ currency,
2975
+ validationError,
2976
+ creditsPerMinorUnit,
2977
+ displayExchangeRate
2978
+ }) {
2979
+ const copy = useCopy();
2980
+ const prefix = currencySymbol(currency);
2981
+ const suffix = currency.toUpperCase();
2982
+ const credits = estimateCredits(
2983
+ Number(form.topupAmountMajor),
2984
+ currency,
2985
+ creditsPerMinorUnit,
2986
+ displayExchangeRate
2987
+ );
2988
+ const explainer = credits != null ? interpolate(copy.autoRechargeView.explainer, {
2989
+ credits: new Intl.NumberFormat().format(credits)
2990
+ }) : copy.autoRechargeView.explainerNoEstimate;
2991
+ return /* @__PURE__ */ jsxs10("div", { className: "solvapay-mcp-auto-recharge-fields", children: [
2992
+ /* @__PURE__ */ jsx16(
2993
+ Field,
2994
+ {
2995
+ id: "mcp-auto-recharge-threshold",
2996
+ label: copy.autoRechargeView.thresholdLabel,
2997
+ value: form.thresholdAmountMajor,
2998
+ prefix,
2999
+ suffix,
3000
+ onChange: (thresholdAmountMajor) => onChange({ ...form, thresholdAmountMajor })
3001
+ }
3002
+ ),
3003
+ /* @__PURE__ */ jsx16(
3004
+ Field,
3005
+ {
3006
+ id: "mcp-auto-recharge-topup",
3007
+ label: copy.autoRechargeView.topupLabel,
3008
+ value: form.topupAmountMajor,
3009
+ prefix,
3010
+ suffix,
3011
+ onChange: (topupAmountMajor) => onChange({ ...form, topupAmountMajor })
3012
+ }
3013
+ ),
3014
+ /* @__PURE__ */ jsx16(
3015
+ Field,
3016
+ {
3017
+ id: "mcp-auto-recharge-cap",
3018
+ label: copy.autoRechargeView.maxMonthlySpendLabel,
3019
+ value: form.maxMonthlySpendMajor,
3020
+ prefix,
3021
+ suffix,
3022
+ placeholder: copy.autoRechargeView.maxMonthlySpendPlaceholder,
3023
+ onChange: (maxMonthlySpendMajor) => onChange({ ...form, maxMonthlySpendMajor })
3024
+ }
3025
+ ),
3026
+ /* @__PURE__ */ jsx16("p", { className: "solvapay-mcp-auto-recharge-fields-explainer", children: explainer }),
3027
+ validationError ? /* @__PURE__ */ jsx16("p", { className: "solvapay-mcp-auto-recharge-fields-error", role: "alert", children: validationError }) : null
3028
+ ] });
3029
+ }
3030
+
3031
+ // src/mcp/views/autoRecharge/McpInlineAutoRecharge.tsx
3032
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
3033
+ var McpInlineAutoRecharge = forwardRef(function McpInlineAutoRecharge2({ currency, creditsPerMinorUnit, displayExchangeRate }, ref) {
3034
+ const copy = useCopy();
3035
+ const [form, setForm] = useState5(() => createDefaultAutoRechargeForm(currency));
3036
+ const [error, setError] = useState5(null);
3037
+ useImperativeHandle(ref, () => ({
3038
+ validate: () => {
3039
+ const result = validateAutoRechargeForm(
3040
+ form,
3041
+ currency,
3042
+ { creditsPerMinorUnit, displayExchangeRate },
3043
+ copy.autoRecharge
3044
+ );
3045
+ if (!result.ok) {
3046
+ setError(result.error);
3047
+ return { ok: false };
3048
+ }
3049
+ setError(null);
3050
+ return {
3051
+ ok: true,
3052
+ payload: result.payload.enabled ? result.payload : void 0
3053
+ };
3054
+ }
3055
+ }));
3056
+ return /* @__PURE__ */ jsxs11("div", { className: "solvapay-mcp-auto-recharge-inline", children: [
3057
+ /* @__PURE__ */ jsxs11(SplitRow, { children: [
3058
+ /* @__PURE__ */ jsx17("p", { children: copy.autoRechargeView.heading }),
3059
+ /* @__PURE__ */ jsx17(
3060
+ Toggle,
3061
+ {
3062
+ checked: form.enabled,
3063
+ label: copy.autoRechargeView.heading,
3064
+ onChange: (enabled) => {
3065
+ setError(null);
3066
+ setForm((current) => ({ ...current, enabled }));
3067
+ }
3068
+ }
3069
+ )
3070
+ ] }),
3071
+ form.enabled ? /* @__PURE__ */ jsx17(
3072
+ McpAutoRechargeFields,
3073
+ {
3074
+ form,
3075
+ onChange: (next) => {
3076
+ setError(null);
3077
+ setForm(next);
3078
+ },
3079
+ currency,
3080
+ validationError: error,
3081
+ creditsPerMinorUnit,
3082
+ displayExchangeRate
3083
+ }
3084
+ ) : null
3085
+ ] });
3086
+ });
3087
+
3088
+ // src/mcp/views/checkout/steps/AmountStep.tsx
3124
3089
  import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
3125
3090
  var AmountStep = memo2(function AmountStep2({
3126
3091
  topupCurrency,
@@ -3132,6 +3097,8 @@ var AmountStep = memo2(function AmountStep2({
3132
3097
  }) {
3133
3098
  const currency = (topupCurrency ?? "USD").toUpperCase();
3134
3099
  const locale = useHostLocale();
3100
+ const { creditsPerMinorUnit, displayExchangeRate } = useBalance();
3101
+ const autoRechargeRef = useRef3(null);
3135
3102
  const [stagedAmountMinor, setStagedAmountMinor] = useState6(null);
3136
3103
  const currencies = topupCurrencies ?? [];
3137
3104
  const showCurrencySwitch = currencies.length > 1 && !!onCurrencyChange;
@@ -3162,11 +3129,27 @@ var AmountStep = memo2(function AmountStep2({
3162
3129
  children: [
3163
3130
  /* @__PURE__ */ jsx18(PresetAmountRow, { cx: cx2, currencyDisplay }),
3164
3131
  /* @__PURE__ */ jsx18(CustomAmountRow, { rowClassName: cx2.amountCustom, currencyDisplay }),
3132
+ /* @__PURE__ */ jsx18(
3133
+ McpInlineAutoRecharge,
3134
+ {
3135
+ ref: autoRechargeRef,
3136
+ currency,
3137
+ creditsPerMinorUnit,
3138
+ displayExchangeRate
3139
+ }
3140
+ ),
3165
3141
  /* @__PURE__ */ jsx18(
3166
3142
  AmountPicker.Confirm,
3167
3143
  {
3168
3144
  className: cx2.button,
3169
- onConfirm: (amountMinor) => onContinue(amountMinor),
3145
+ onConfirm: (amountMinor) => {
3146
+ const result = autoRechargeRef.current?.validate();
3147
+ if (result == null) {
3148
+ throw new Error("AmountStep: auto-recharge form is not mounted");
3149
+ }
3150
+ if (!result.ok) return;
3151
+ onContinue(amountMinor, result.payload);
3152
+ },
3170
3153
  children: stagedAmountMinor ? `Continue \u2014 ${formatPrice(stagedAmountMinor, currency, { locale, currencyDisplay })}` : "Continue"
3171
3154
  }
3172
3155
  )
@@ -3292,12 +3275,18 @@ function McpPaymentHeader({
3292
3275
  ] });
3293
3276
  }
3294
3277
 
3278
+ // src/mcp/views/paymentElementOptions.ts
3279
+ var MCP_PAYMENT_ELEMENT_OPTIONS = {
3280
+ terms: { card: "never" }
3281
+ };
3282
+
3295
3283
  // src/mcp/views/checkout/steps/PaygPaymentStep.tsx
3296
3284
  import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3297
3285
  var PaygPaymentStep = memo3(function PaygPaymentStep2({
3298
3286
  plan: _plan,
3299
3287
  amountMinor,
3300
3288
  topupCurrency,
3289
+ autoRecharge,
3301
3290
  returnUrl,
3302
3291
  onBack,
3303
3292
  onSuccess,
@@ -3314,6 +3303,7 @@ var PaygPaymentStep = memo3(function PaygPaymentStep2({
3314
3303
  {
3315
3304
  amount: amountMinor,
3316
3305
  currency,
3306
+ autoRecharge,
3317
3307
  returnUrl,
3318
3308
  onSuccess: (_intent, extras) => onSuccess(extras),
3319
3309
  children: /* @__PURE__ */ jsxs15(McpHostedLayout, { children: [
@@ -3337,11 +3327,19 @@ var PaygPaymentStep = memo3(function PaygPaymentStep2({
3337
3327
  ),
3338
3328
  /* @__PURE__ */ jsxs15("div", { className: cx2.topupForm, children: [
3339
3329
  /* @__PURE__ */ jsx22(TopupForm.Loading, {}),
3340
- /* @__PURE__ */ jsx22(TopupForm.PaymentElement, {}),
3330
+ /* @__PURE__ */ jsx22(TopupForm.PaymentElement, { options: MCP_PAYMENT_ELEMENT_OPTIONS }),
3341
3331
  /* @__PURE__ */ jsx22(TopupForm.BusinessDetails.Root, { className: cx2.businessDetails, children: /* @__PURE__ */ jsx22(TopupForm.BusinessDetails.Fields, {}) }),
3342
3332
  /* @__PURE__ */ jsx22(TopupForm.Error, { className: cx2.error }),
3343
3333
  /* @__PURE__ */ jsx22(TopupForm.SubmitButton, { className: cx2.button, children: /* @__PURE__ */ jsx22(PaygChargeCta, { amountMinor, currency }) }),
3344
- /* @__PURE__ */ jsx22(MandateText, { mode: "topup", amountMinor, currency })
3334
+ /* @__PURE__ */ jsx22(
3335
+ MandateText,
3336
+ {
3337
+ mode: "topup",
3338
+ amountMinor,
3339
+ currency,
3340
+ savesPaymentMethod: autoRecharge != null
3341
+ }
3342
+ )
3345
3343
  ] })
3346
3344
  ] })
3347
3345
  ] })
@@ -3519,271 +3517,14 @@ var SuccessStep = memo5(function SuccessStep2({ meta, cx: cx2 }) {
3519
3517
  ] });
3520
3518
  });
3521
3519
 
3522
- // src/mcp/views/checkout/EmbeddedCheckout.tsx
3523
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
3524
- function EmbeddedCheckout({
3525
- productRef,
3526
- returnUrl,
3527
- onPurchaseSuccess,
3528
- fromPaywall,
3529
- paywallKind,
3530
- hideUpgradeBanner,
3531
- plans,
3532
- onClose,
3533
- onBack,
3534
- initialPlanRef,
3535
- autoAdvance,
3536
- cx: cx2,
3537
- children
3538
- }) {
3539
- const { loading, isRefetching, activePurchase } = usePurchase();
3540
- const currentPlanRef = activePurchase?.planSnapshot?.reference ?? null;
3541
- const paidPlans = useMemo3(() => {
3542
- const list = plans ?? [];
3543
- return list.filter((p) => p.requiresPayment !== false);
3544
- }, [plans]);
3545
- const paygPlanRef = useMemo3(() => {
3546
- const payg = paidPlans.find((p) => isPayg(p));
3547
- return payg?.reference ?? void 0;
3548
- }, [paidPlans]);
3549
- const planFilter = useMemo3(
3550
- () => (plan) => plan.requiresPayment !== false || plan.reference === currentPlanRef,
3551
- [currentPlanRef]
3552
- );
3553
- if (loading) {
3554
- return /* @__PURE__ */ jsx25("div", { className: cx2.card, children: /* @__PURE__ */ jsx25("p", { children: "Loading checkout\u2026" }) });
3555
- }
3556
- return /* @__PURE__ */ jsxs18("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
3557
- /* @__PURE__ */ jsx25(
3558
- PlanSelector.Root,
3559
- {
3560
- productRef,
3561
- filter: planFilter,
3562
- sortBy: planSortByPaygFirstThenAsc,
3563
- popularPlanRef: paygPlanRef,
3564
- currentPlanRef,
3565
- autoSelectFirstPaid: Boolean(paygPlanRef),
3566
- initialPlanRef,
3567
- className: "solvapay-plan-selector",
3568
- children: /* @__PURE__ */ jsx25(
3569
- McpCheckoutBody,
3570
- {
3571
- productRef,
3572
- returnUrl,
3573
- onPurchaseSuccess,
3574
- fromPaywall,
3575
- paywallKind,
3576
- hideUpgradeBanner,
3577
- onClose,
3578
- onBack,
3579
- initialPlanRef,
3580
- autoAdvance,
3581
- cx: cx2
3582
- }
3583
- )
3584
- }
3585
- ),
3586
- children
3587
- ] });
3588
- }
3589
- function McpCheckoutBody({
3590
- productRef,
3591
- returnUrl,
3592
- onPurchaseSuccess,
3593
- fromPaywall,
3594
- paywallKind,
3595
- hideUpgradeBanner,
3596
- onClose,
3597
- onBack,
3598
- initialPlanRef,
3599
- autoAdvance,
3600
- cx: cx2
3601
- }) {
3602
- const bridge = useMcpBridge();
3603
- const locale = useHostLocale();
3604
- const flow = useCheckoutFlow({
3605
- productRef,
3606
- // `notifyModelContext` for plan commit fires from the explicit
3607
- // Continue handler below — not on `selectPlan` — so a stray
3608
- // selection doesn't burn a host emit before the user opts in.
3609
- onPurchaseSuccess: (meta) => {
3610
- if (meta.branch === "payg" && meta.amountMinor != null && meta.currency != null) {
3611
- void bridge.notifyModelContext({
3612
- text: `Activated ${meta.plan.name ?? "plan"} with ${formatPrice(
3613
- meta.amountMinor,
3614
- meta.currency,
3615
- { locale }
3616
- )} in credits.`
3617
- });
3618
- void bridge.notifySuccess({
3619
- kind: "topup",
3620
- amountMinor: meta.amountMinor,
3621
- currency: meta.currency
3622
- });
3623
- } else {
3624
- void bridge.notifyModelContext({
3625
- text: `Activated ${meta.plan.name ?? "plan"}.`
3626
- });
3627
- void bridge.notifySuccess({
3628
- kind: "plan-activated",
3629
- planName: meta.plan.name ?? null
3630
- });
3631
- }
3632
- onPurchaseSuccess?.();
3633
- }
3634
- });
3635
- const onStayOnFree = useCallback3(() => {
3636
- void bridge.sendMessage({ text: "Sticking with the free tier for now." });
3637
- onClose?.();
3638
- }, [bridge, onClose]);
3639
- const selectedPlanShape = flow.selectedPlan;
3640
- const onPlanContinue = useCallback3(() => {
3641
- if (selectedPlanShape) {
3642
- void bridge.notifyModelContext({
3643
- text: `User selected ${selectedPlanShape.name ?? "a plan"}.`
3644
- });
3645
- }
3646
- void flow.advance();
3647
- }, [bridge, flow, selectedPlanShape]);
3648
- const autoAdvancedRef = useRef3(false);
3649
- useEffect5(() => {
3650
- if (!autoAdvance || autoAdvancedRef.current) return;
3651
- if (flow.step !== "plan") return;
3652
- if (flow.selectedPlanRef !== initialPlanRef) return;
3653
- autoAdvancedRef.current = true;
3654
- onPlanContinue();
3655
- }, [autoAdvance, flow.selectedPlanRef, flow.step, initialPlanRef, onPlanContinue]);
3656
- if (flow.step === "plan") {
3657
- const waitingForSelection = Boolean(autoAdvance) && !flow.selectedPlanRef;
3658
- const matchingPending = Boolean(autoAdvance) && flow.selectedPlanRef === initialPlanRef && flow.status === "activating";
3659
- if (waitingForSelection || matchingPending) {
3660
- return /* @__PURE__ */ jsx25("p", { children: "Loading checkout\u2026" });
3661
- }
3662
- return /* @__PURE__ */ jsx25(
3663
- PlanStep,
3664
- {
3665
- fromPaywall,
3666
- paywallKind,
3667
- hideUpgradeBanner,
3668
- onContinue: onPlanContinue,
3669
- onStayOnFree: fromPaywall && onClose ? onStayOnFree : void 0,
3670
- onBack,
3671
- isActivating: flow.status === "activating",
3672
- activationError: flow.error,
3673
- cx: cx2
3674
- }
3675
- );
3676
- }
3677
- if (flow.step === "amount") {
3678
- if (!selectedPlanShape) {
3679
- return null;
3680
- }
3681
- return /* @__PURE__ */ jsx25(
3682
- AmountStep,
3683
- {
3684
- plan: selectedPlanShape,
3685
- topupCurrency: flow.topupCurrency,
3686
- topupCurrencies: flow.topupCurrencies,
3687
- onCurrencyChange: flow.setTopupCurrency,
3688
- onBack: () => flow.back(),
3689
- onContinue: (amountMinor) => {
3690
- flow.selectAmount(amountMinor);
3691
- void flow.advance();
3692
- },
3693
- cx: cx2
3694
- }
3695
- );
3696
- }
3697
- if (flow.step === "payment") {
3698
- if (flow.branch === "payg" && selectedPlanShape && flow.selectedAmountMinor != null) {
3699
- return /* @__PURE__ */ jsx25(
3700
- PaygPaymentStep,
3701
- {
3702
- plan: selectedPlanShape,
3703
- amountMinor: flow.selectedAmountMinor,
3704
- topupCurrency: flow.topupCurrency,
3705
- returnUrl,
3706
- onBack: () => flow.back(),
3707
- onSuccess: (extras) => flow.notifyPaymentSuccess(void 0, extras),
3708
- cx: cx2
3709
- }
3710
- );
3711
- }
3712
- if (flow.branch === "recurring" && selectedPlanShape && flow.selectedPlanRef) {
3713
- return /* @__PURE__ */ jsx25(
3714
- RecurringPaymentStep,
3715
- {
3716
- plan: selectedPlanShape,
3717
- planRef: flow.selectedPlanRef,
3718
- productRef,
3719
- returnUrl,
3720
- onBack: () => flow.back(),
3721
- onSuccess: (intent) => flow.notifyPaymentSuccess(intent),
3722
- cx: cx2
3723
- }
3724
- );
3725
- }
3726
- return null;
3727
- }
3728
- if (flow.step === "success" && flow.successMeta) {
3729
- return /* @__PURE__ */ jsx25(SuccessStep, { meta: flow.successMeta, cx: cx2 });
3730
- }
3731
- return null;
3732
- }
3733
-
3734
- // src/mcp/views/McpCheckoutView.tsx
3735
- import { Fragment as Fragment11, jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
3520
+ // src/mcp/views/checkout/HostedCheckout.tsx
3521
+ import React10, { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef4, useState as useState7 } from "react";
3522
+ import { Fragment as Fragment11, jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
3736
3523
  var POLL_INTERVAL_MS = 3e3;
3737
3524
  var AWAITING_TIMEOUT_MS = 10 * 60 * 1e3;
3738
- function McpCheckoutView({
3739
- productRef,
3740
- publishableKey = null,
3741
- returnUrl,
3742
- onPurchaseSuccess,
3743
- onRequestTopup: _onRequestTopup,
3744
- fromPaywall = false,
3745
- paywallKind,
3746
- plans,
3747
- onClose,
3748
- onBack,
3749
- initialPlanRef,
3750
- autoAdvance,
3751
- classNames,
3752
- children
3753
- }) {
3754
- const cx2 = resolveMcpClassNames(classNames);
3755
- const probe = useStripeProbe(publishableKey);
3756
- if (probe === "loading") {
3757
- return /* @__PURE__ */ jsxs19("div", { className: cx2.card, children: [
3758
- /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" }),
3759
- children
3760
- ] });
3761
- }
3762
- if (probe === "ready") {
3763
- return /* @__PURE__ */ jsx26(
3764
- EmbeddedCheckout,
3765
- {
3766
- productRef,
3767
- returnUrl,
3768
- onPurchaseSuccess,
3769
- fromPaywall,
3770
- paywallKind,
3771
- plans,
3772
- onClose,
3773
- onBack,
3774
- initialPlanRef,
3775
- autoAdvance,
3776
- cx: cx2,
3777
- classNames,
3778
- children
3779
- }
3780
- );
3781
- }
3782
- return /* @__PURE__ */ jsx26(HostedCheckout, { productRef, onPurchaseSuccess, cx: cx2, children });
3783
- }
3784
3525
  function useHostedUrl(enabled, fetcher, label) {
3785
3526
  const [state, setState] = useState7({ status: "idle" });
3786
- useEffect6(() => {
3527
+ useEffect5(() => {
3787
3528
  if (!enabled) {
3788
3529
  setState({ status: "idle" });
3789
3530
  return;
@@ -3804,7 +3545,7 @@ function useHostedUrl(enabled, fetcher, label) {
3804
3545
  }, [enabled, fetcher, label]);
3805
3546
  return state;
3806
3547
  }
3807
- var HostedLinkButton = React11.memo(function HostedLinkButton2({
3548
+ var HostedLinkButton = React10.memo(function HostedLinkButton2({
3808
3549
  state,
3809
3550
  loadingLabel,
3810
3551
  readyLabel,
@@ -3813,7 +3554,7 @@ var HostedLinkButton = React11.memo(function HostedLinkButton2({
3813
3554
  }) {
3814
3555
  const handleExternalClick = useExternalLinkClick();
3815
3556
  if (state.status === "ready") {
3816
- return /* @__PURE__ */ jsx26(
3557
+ return /* @__PURE__ */ jsx25(
3817
3558
  "a",
3818
3559
  {
3819
3560
  className: "solvapay-mcp-hosted-link",
@@ -3825,19 +3566,19 @@ var HostedLinkButton = React11.memo(function HostedLinkButton2({
3825
3566
  onLaunch?.(state.href);
3826
3567
  handleExternalClick(event);
3827
3568
  },
3828
- children: /* @__PURE__ */ jsxs19("button", { type: "button", className: cx2.button, children: [
3569
+ children: /* @__PURE__ */ jsxs18("button", { type: "button", className: cx2.button, children: [
3829
3570
  readyLabel,
3830
- /* @__PURE__ */ jsx26(ExternalLinkGlyph, {})
3571
+ /* @__PURE__ */ jsx25(ExternalLinkGlyph, {})
3831
3572
  ] })
3832
3573
  }
3833
3574
  );
3834
3575
  }
3835
- return /* @__PURE__ */ jsx26("button", { type: "button", className: cx2.button, disabled: true, children: state.status === "error" ? "Unavailable" : loadingLabel });
3576
+ return /* @__PURE__ */ jsx25("button", { type: "button", className: cx2.button, disabled: true, children: state.status === "error" ? "Unavailable" : loadingLabel });
3836
3577
  });
3837
3578
  function Spinner() {
3838
- return /* @__PURE__ */ jsx26("span", { className: "solvapay-mcp-spinner", "aria-hidden": "true" });
3579
+ return /* @__PURE__ */ jsx25("span", { className: "solvapay-mcp-spinner", "aria-hidden": "true" });
3839
3580
  }
3840
- var AwaitingBody = React11.memo(function AwaitingBody2({
3581
+ var AwaitingBody = React10.memo(function AwaitingBody2({
3841
3582
  href,
3842
3583
  timedOut,
3843
3584
  onReopen,
@@ -3845,13 +3586,13 @@ var AwaitingBody = React11.memo(function AwaitingBody2({
3845
3586
  cx: cx2
3846
3587
  }) {
3847
3588
  const handleExternalClick = useExternalLinkClick();
3848
- return /* @__PURE__ */ jsxs19(Fragment11, { children: [
3849
- /* @__PURE__ */ jsxs19("div", { className: cx2.awaitingHeader, children: [
3850
- /* @__PURE__ */ jsx26(Spinner, {}),
3851
- /* @__PURE__ */ jsx26("h2", { className: cx2.heading, children: timedOut ? "Still waiting for payment" : "Waiting for payment\u2026" })
3589
+ return /* @__PURE__ */ jsxs18(Fragment11, { children: [
3590
+ /* @__PURE__ */ jsxs18("div", { className: cx2.awaitingHeader, children: [
3591
+ /* @__PURE__ */ jsx25(Spinner, {}),
3592
+ /* @__PURE__ */ jsx25("h2", { className: cx2.heading, children: timedOut ? "Still waiting for payment" : "Waiting for payment\u2026" })
3852
3593
  ] }),
3853
- /* @__PURE__ */ jsx26("p", { className: cx2.muted, children: timedOut ? "We haven't seen your purchase yet. If you completed payment, give it another moment \u2014 otherwise reopen checkout or cancel." : "Complete payment in the other tab. Your purchase will show up here automatically." }),
3854
- /* @__PURE__ */ jsx26(
3594
+ /* @__PURE__ */ jsx25("p", { className: cx2.muted, children: timedOut ? "We haven't seen your purchase yet. If you completed payment, give it another moment \u2014 otherwise reopen checkout or cancel." : "Complete payment in the other tab. Your purchase will show up here automatically." }),
3595
+ /* @__PURE__ */ jsx25(
3855
3596
  "a",
3856
3597
  {
3857
3598
  className: "solvapay-mcp-hosted-link",
@@ -3863,16 +3604,16 @@ var AwaitingBody = React11.memo(function AwaitingBody2({
3863
3604
  onReopen();
3864
3605
  handleExternalClick(event);
3865
3606
  },
3866
- children: /* @__PURE__ */ jsxs19("button", { type: "button", className: cx2.button, children: [
3607
+ children: /* @__PURE__ */ jsxs18("button", { type: "button", className: cx2.button, children: [
3867
3608
  "Reopen checkout",
3868
- /* @__PURE__ */ jsx26(ExternalLinkGlyph, {})
3609
+ /* @__PURE__ */ jsx25(ExternalLinkGlyph, {})
3869
3610
  ] })
3870
3611
  }
3871
3612
  ),
3872
- /* @__PURE__ */ jsx26("button", { type: "button", className: cx2.linkButton, onClick: onCancel, children: "Didn't complete? Cancel" })
3613
+ /* @__PURE__ */ jsx25("button", { type: "button", className: cx2.linkButton, onClick: onCancel, children: "Didn't complete? Cancel" })
3873
3614
  ] });
3874
3615
  });
3875
- var CancelledBody = React11.memo(function CancelledBody2({
3616
+ var CancelledBody = React10.memo(function CancelledBody2({
3876
3617
  productName,
3877
3618
  endDate,
3878
3619
  daysLeft,
@@ -3881,25 +3622,25 @@ var CancelledBody = React11.memo(function CancelledBody2({
3881
3622
  onLaunch,
3882
3623
  cx: cx2
3883
3624
  }) {
3884
- return /* @__PURE__ */ jsxs19(Fragment11, { children: [
3885
- /* @__PURE__ */ jsxs19("h2", { className: cx2.heading, children: [
3625
+ return /* @__PURE__ */ jsxs18(Fragment11, { children: [
3626
+ /* @__PURE__ */ jsxs18("h2", { className: cx2.heading, children: [
3886
3627
  "Your ",
3887
3628
  productName,
3888
3629
  " purchase is cancelled"
3889
3630
  ] }),
3890
- endDate && formattedEndDate ? /* @__PURE__ */ jsxs19("div", { className: cx2.notice, children: [
3891
- /* @__PURE__ */ jsx26("p", { children: /* @__PURE__ */ jsxs19("strong", { children: [
3631
+ endDate && formattedEndDate ? /* @__PURE__ */ jsxs18("div", { className: cx2.notice, children: [
3632
+ /* @__PURE__ */ jsx25("p", { children: /* @__PURE__ */ jsxs18("strong", { children: [
3892
3633
  "Access expires ",
3893
3634
  formattedEndDate
3894
3635
  ] }) }),
3895
- daysLeft !== null && daysLeft > 0 && /* @__PURE__ */ jsxs19("p", { className: cx2.muted, children: [
3636
+ daysLeft !== null && daysLeft > 0 && /* @__PURE__ */ jsxs18("p", { className: cx2.muted, children: [
3896
3637
  daysLeft,
3897
3638
  " ",
3898
3639
  daysLeft === 1 ? "day" : "days",
3899
3640
  " remaining"
3900
3641
  ] })
3901
- ] }) : /* @__PURE__ */ jsx26("p", { className: cx2.muted, children: "Your purchase access has ended." }),
3902
- /* @__PURE__ */ jsx26(
3642
+ ] }) : /* @__PURE__ */ jsx25("p", { className: cx2.muted, children: "Your purchase access has ended." }),
3643
+ /* @__PURE__ */ jsx25(
3903
3644
  HostedLinkButton,
3904
3645
  {
3905
3646
  state: checkout,
@@ -3909,14 +3650,19 @@ var CancelledBody = React11.memo(function CancelledBody2({
3909
3650
  cx: cx2
3910
3651
  }
3911
3652
  ),
3912
- checkout.status === "error" && /* @__PURE__ */ jsx26("p", { className: cx2.error, role: "alert", children: checkout.message })
3653
+ checkout.status === "error" && /* @__PURE__ */ jsx25("p", { className: cx2.error, role: "alert", children: checkout.message })
3913
3654
  ] });
3914
3655
  });
3915
- var UpgradeBody = React11.memo(function UpgradeBody2({ checkout, onLaunch, cx: cx2 }) {
3916
- return /* @__PURE__ */ jsxs19(Fragment11, { children: [
3917
- /* @__PURE__ */ jsx26("h2", { className: cx2.heading, children: "Upgrade your plan" }),
3918
- /* @__PURE__ */ jsx26("p", { className: cx2.muted, children: "The SolvaPay checkout opens in a new tab. Return here after payment and your purchase will show up automatically." }),
3919
- /* @__PURE__ */ jsx26(
3656
+ var UpgradeBody = React10.memo(function UpgradeBody2({
3657
+ planName,
3658
+ checkout,
3659
+ onLaunch,
3660
+ cx: cx2
3661
+ }) {
3662
+ return /* @__PURE__ */ jsxs18(Fragment11, { children: [
3663
+ /* @__PURE__ */ jsx25("h2", { className: cx2.heading, children: planName ? `Complete your ${planName} purchase` : "Upgrade your plan" }),
3664
+ /* @__PURE__ */ jsx25("p", { className: cx2.muted, children: "The SolvaPay checkout opens in a new tab. Return here after payment and your purchase will show up automatically." }),
3665
+ /* @__PURE__ */ jsx25(
3920
3666
  HostedLinkButton,
3921
3667
  {
3922
3668
  state: checkout,
@@ -3926,11 +3672,13 @@ var UpgradeBody = React11.memo(function UpgradeBody2({ checkout, onLaunch, cx: c
3926
3672
  cx: cx2
3927
3673
  }
3928
3674
  ),
3929
- checkout.status === "error" && /* @__PURE__ */ jsx26("p", { className: cx2.error, role: "alert", children: checkout.message })
3675
+ checkout.status === "error" && /* @__PURE__ */ jsx25("p", { className: cx2.error, role: "alert", children: checkout.message })
3930
3676
  ] });
3931
3677
  });
3932
3678
  function HostedCheckout({
3933
3679
  productRef,
3680
+ planRef,
3681
+ planName,
3934
3682
  onPurchaseSuccess,
3935
3683
  cx: cx2,
3936
3684
  children
@@ -3942,23 +3690,26 @@ function HostedCheckout({
3942
3690
  const [awaitingTimedOut, setAwaitingTimedOut] = useState7(false);
3943
3691
  const [hasLoadedOnce, setHasLoadedOnce] = useState7(false);
3944
3692
  const onPurchaseSuccessRef = useRef4(onPurchaseSuccess);
3945
- useEffect6(() => {
3693
+ useEffect5(() => {
3946
3694
  onPurchaseSuccessRef.current = onPurchaseSuccess;
3947
3695
  }, [onPurchaseSuccess]);
3948
- useEffect6(() => {
3696
+ useEffect5(() => {
3949
3697
  if (!loading && !hasLoadedOnce) setHasLoadedOnce(true);
3950
3698
  }, [loading, hasLoadedOnce]);
3951
- const fetchCheckoutUrl = useCallback4(async () => {
3952
- const { checkoutUrl } = await transport.createCheckoutSession({ productRef });
3699
+ const fetchCheckoutUrl = useCallback3(async () => {
3700
+ const { checkoutUrl } = await transport.createCheckoutSession({
3701
+ productRef,
3702
+ ...planRef ? { planRef } : {}
3703
+ });
3953
3704
  return { href: checkoutUrl };
3954
- }, [productRef, transport]);
3705
+ }, [planRef, productRef, transport]);
3955
3706
  const checkout = useHostedUrl(hasLoadedOnce, fetchCheckoutUrl, "checkout session");
3956
- const safeRefetch = useCallback4(() => {
3707
+ const safeRefetch = useCallback3(() => {
3957
3708
  refetch().catch((err) => {
3958
3709
  console.warn("[solvapay-mcp] refetch failed", err);
3959
3710
  });
3960
3711
  }, [refetch]);
3961
- useEffect6(() => {
3712
+ useEffect5(() => {
3962
3713
  const onFocus = () => safeRefetch();
3963
3714
  const onVisibility = () => {
3964
3715
  if (document.visibilityState === "visible") safeRefetch();
@@ -3970,7 +3721,7 @@ function HostedCheckout({
3970
3721
  document.removeEventListener("visibilitychange", onVisibility);
3971
3722
  };
3972
3723
  }, [safeRefetch]);
3973
- useEffect6(() => {
3724
+ useEffect5(() => {
3974
3725
  if (!awaiting) return;
3975
3726
  const interval = window.setInterval(() => {
3976
3727
  if (document.visibilityState === "hidden") return;
@@ -3984,7 +3735,7 @@ function HostedCheckout({
3984
3735
  window.clearTimeout(timeout);
3985
3736
  };
3986
3737
  }, [awaiting, safeRefetch]);
3987
- useEffect6(() => {
3738
+ useEffect5(() => {
3988
3739
  if (!awaiting) return;
3989
3740
  if (!hasPaidPurchase) return;
3990
3741
  const newRef = activePurchase?.reference ?? null;
@@ -3995,7 +3746,7 @@ function HostedCheckout({
3995
3746
  onPurchaseSuccessRef.current?.();
3996
3747
  }
3997
3748
  }, [awaiting, hasPaidPurchase, activePurchase?.reference]);
3998
- const beginAwaiting = useCallback4(
3749
+ const beginAwaiting = useCallback3(
3999
3750
  (href) => {
4000
3751
  setAwaiting({
4001
3752
  baselineActiveRef: activePurchase?.reference ?? null,
@@ -4007,27 +3758,27 @@ function HostedCheckout({
4007
3758
  },
4008
3759
  [activePurchase?.reference, hasPaidPurchase]
4009
3760
  );
4010
- const cancelAwaiting = useCallback4(() => {
3761
+ const cancelAwaiting = useCallback3(() => {
4011
3762
  setAwaiting(null);
4012
3763
  setAwaitingTimedOut(false);
4013
3764
  }, []);
4014
- const dismissTimeout = useCallback4(() => {
3765
+ const dismissTimeout = useCallback3(() => {
4015
3766
  setAwaitingTimedOut(false);
4016
3767
  }, []);
4017
3768
  const cancelledProductName = cancelledPurchase?.productName ?? null;
4018
3769
  const cancelledEndDate = cancelledPurchase?.endDate;
4019
- const cancelledDaysLeft = useMemo4(
3770
+ const cancelledDaysLeft = useMemo3(
4020
3771
  () => cancelledEndDate ? getDaysUntilExpiration(cancelledEndDate) : null,
4021
3772
  [cancelledEndDate, getDaysUntilExpiration]
4022
3773
  );
4023
- const cancelledFormattedEndDate = useMemo4(
3774
+ const cancelledFormattedEndDate = useMemo3(
4024
3775
  () => cancelledEndDate ? formatDate(cancelledEndDate) : null,
4025
3776
  [cancelledEndDate, formatDate]
4026
3777
  );
4027
3778
  const awaitingHref = awaiting?.href ?? null;
4028
- const inner = useMemo4(() => {
3779
+ const inner = useMemo3(() => {
4029
3780
  if (awaiting && awaitingHref) {
4030
- return /* @__PURE__ */ jsx26(
3781
+ return /* @__PURE__ */ jsx25(
4031
3782
  AwaitingBody,
4032
3783
  {
4033
3784
  href: awaitingHref,
@@ -4039,7 +3790,7 @@ function HostedCheckout({
4039
3790
  );
4040
3791
  }
4041
3792
  if (shouldShowCancelledNotice && cancelledProductName) {
4042
- return /* @__PURE__ */ jsx26(
3793
+ return /* @__PURE__ */ jsx25(
4043
3794
  CancelledBody,
4044
3795
  {
4045
3796
  productName: cancelledProductName,
@@ -4052,7 +3803,7 @@ function HostedCheckout({
4052
3803
  }
4053
3804
  );
4054
3805
  }
4055
- return /* @__PURE__ */ jsx26(UpgradeBody, { checkout, onLaunch: beginAwaiting, cx: cx2 });
3806
+ return /* @__PURE__ */ jsx25(UpgradeBody, { planName, checkout, onLaunch: beginAwaiting, cx: cx2 });
4056
3807
  }, [
4057
3808
  awaiting,
4058
3809
  awaitingHref,
@@ -4066,19 +3817,297 @@ function HostedCheckout({
4066
3817
  cancelledFormattedEndDate,
4067
3818
  checkout,
4068
3819
  beginAwaiting,
3820
+ planName,
4069
3821
  cx2
4070
3822
  ]);
4071
3823
  if (loading) {
4072
- return /* @__PURE__ */ jsx26("div", { className: cx2.card, children: /* @__PURE__ */ jsx26("p", { children: "Loading purchase\u2026" }) });
3824
+ return /* @__PURE__ */ jsx25("div", { className: cx2.card, children: /* @__PURE__ */ jsx25("p", { children: "Loading purchase\u2026" }) });
4073
3825
  }
4074
- return /* @__PURE__ */ jsxs19("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
3826
+ return /* @__PURE__ */ jsxs18("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
4075
3827
  inner,
4076
3828
  children
4077
3829
  ] });
4078
3830
  }
4079
3831
 
3832
+ // src/mcp/views/checkout/EmbeddedCheckout.tsx
3833
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
3834
+ function EmbeddedCheckout({
3835
+ productRef,
3836
+ returnUrl,
3837
+ onPurchaseSuccess,
3838
+ fromPaywall,
3839
+ paywallKind,
3840
+ hideUpgradeBanner,
3841
+ plans,
3842
+ onClose,
3843
+ onBack,
3844
+ initialPlanRef,
3845
+ autoAdvance,
3846
+ stripeProbe,
3847
+ cx: cx2,
3848
+ children
3849
+ }) {
3850
+ const { loading, isRefetching, activePurchase } = usePurchase();
3851
+ const currentPlanRef = activePurchase?.planSnapshot?.reference ?? null;
3852
+ const paidPlans = useMemo4(() => {
3853
+ const list = plans ?? [];
3854
+ return list.filter((p) => p.requiresPayment !== false);
3855
+ }, [plans]);
3856
+ const paygPlanRef = useMemo4(() => {
3857
+ const payg = paidPlans.find((p) => isPayg(p));
3858
+ return payg?.reference ?? void 0;
3859
+ }, [paidPlans]);
3860
+ const planFilter = useMemo4(
3861
+ () => (plan) => plan.requiresPayment !== false || plan.reference === currentPlanRef,
3862
+ [currentPlanRef]
3863
+ );
3864
+ if (loading) {
3865
+ return /* @__PURE__ */ jsx26("div", { className: cx2.card, children: /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" }) });
3866
+ }
3867
+ return /* @__PURE__ */ jsxs19("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
3868
+ /* @__PURE__ */ jsx26(
3869
+ PlanSelector.Root,
3870
+ {
3871
+ productRef,
3872
+ filter: planFilter,
3873
+ sortBy: planSortByPaygFirstThenAsc,
3874
+ popularPlanRef: paygPlanRef,
3875
+ currentPlanRef,
3876
+ autoSelectFirstPaid: Boolean(paygPlanRef),
3877
+ initialPlanRef,
3878
+ className: "solvapay-plan-selector",
3879
+ children: /* @__PURE__ */ jsx26(
3880
+ McpCheckoutBody,
3881
+ {
3882
+ productRef,
3883
+ returnUrl,
3884
+ onPurchaseSuccess,
3885
+ fromPaywall,
3886
+ paywallKind,
3887
+ hideUpgradeBanner,
3888
+ onClose,
3889
+ onBack,
3890
+ initialPlanRef,
3891
+ autoAdvance,
3892
+ stripeProbe,
3893
+ cx: cx2
3894
+ }
3895
+ )
3896
+ }
3897
+ ),
3898
+ children
3899
+ ] });
3900
+ }
3901
+ function McpCheckoutBody({
3902
+ productRef,
3903
+ returnUrl,
3904
+ onPurchaseSuccess,
3905
+ fromPaywall,
3906
+ paywallKind,
3907
+ hideUpgradeBanner,
3908
+ onClose,
3909
+ onBack,
3910
+ initialPlanRef,
3911
+ autoAdvance,
3912
+ stripeProbe,
3913
+ cx: cx2
3914
+ }) {
3915
+ const bridge = useMcpBridge();
3916
+ const locale = useHostLocale();
3917
+ const flow = useCheckoutFlow({
3918
+ productRef,
3919
+ // `notifyModelContext` for plan commit fires from the explicit
3920
+ // Continue handler below — not on `selectPlan` — so a stray
3921
+ // selection doesn't burn a host emit before the user opts in.
3922
+ onPurchaseSuccess: (meta) => {
3923
+ if (meta.branch === "payg" && meta.amountMinor != null && meta.currency != null) {
3924
+ void bridge.notifyModelContext({
3925
+ text: `Activated ${meta.plan.name ?? "plan"} with ${formatPrice(
3926
+ meta.amountMinor,
3927
+ meta.currency,
3928
+ { locale }
3929
+ )} in credits.`
3930
+ });
3931
+ void bridge.notifySuccess({
3932
+ kind: "topup",
3933
+ amountMinor: meta.amountMinor,
3934
+ currency: meta.currency
3935
+ });
3936
+ } else {
3937
+ void bridge.notifyModelContext({
3938
+ text: `Activated ${meta.plan.name ?? "plan"}.`
3939
+ });
3940
+ void bridge.notifySuccess({
3941
+ kind: "plan-activated",
3942
+ planName: meta.plan.name ?? null
3943
+ });
3944
+ }
3945
+ onPurchaseSuccess?.();
3946
+ }
3947
+ });
3948
+ const onStayOnFree = useCallback4(() => {
3949
+ void bridge.sendMessage({ text: "Sticking with the free tier for now." });
3950
+ onClose?.();
3951
+ }, [bridge, onClose]);
3952
+ const selectedPlanShape = flow.selectedPlan;
3953
+ const [autoRecharge, setAutoRecharge] = useState8();
3954
+ const onPlanContinue = useCallback4(() => {
3955
+ if (selectedPlanShape) {
3956
+ void bridge.notifyModelContext({
3957
+ text: `User selected ${selectedPlanShape.name ?? "a plan"}.`
3958
+ });
3959
+ }
3960
+ void flow.advance();
3961
+ }, [bridge, flow, selectedPlanShape]);
3962
+ const autoAdvancedRef = useRef5(false);
3963
+ useEffect6(() => {
3964
+ if (!autoAdvance || autoAdvancedRef.current) return;
3965
+ if (flow.step !== "plan") return;
3966
+ if (flow.selectedPlanRef !== initialPlanRef) return;
3967
+ autoAdvancedRef.current = true;
3968
+ onPlanContinue();
3969
+ }, [autoAdvance, flow.selectedPlanRef, flow.step, initialPlanRef, onPlanContinue]);
3970
+ if (flow.step === "plan") {
3971
+ const waitingForSelection = Boolean(autoAdvance) && !flow.selectedPlanRef;
3972
+ const matchingPending = Boolean(autoAdvance) && flow.selectedPlanRef === initialPlanRef && flow.status === "activating";
3973
+ if (waitingForSelection || matchingPending) {
3974
+ return /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" });
3975
+ }
3976
+ return /* @__PURE__ */ jsx26(
3977
+ PlanStep,
3978
+ {
3979
+ fromPaywall,
3980
+ paywallKind,
3981
+ hideUpgradeBanner,
3982
+ onContinue: onPlanContinue,
3983
+ onStayOnFree: fromPaywall && onClose ? onStayOnFree : void 0,
3984
+ onBack,
3985
+ isActivating: flow.status === "activating",
3986
+ activationError: flow.error,
3987
+ cx: cx2
3988
+ }
3989
+ );
3990
+ }
3991
+ if (flow.step === "amount") {
3992
+ if (!selectedPlanShape) {
3993
+ return null;
3994
+ }
3995
+ return /* @__PURE__ */ jsx26(
3996
+ AmountStep,
3997
+ {
3998
+ plan: selectedPlanShape,
3999
+ topupCurrency: flow.topupCurrency,
4000
+ topupCurrencies: flow.topupCurrencies,
4001
+ onCurrencyChange: (code) => {
4002
+ setAutoRecharge(void 0);
4003
+ flow.setTopupCurrency(code);
4004
+ },
4005
+ onBack: () => flow.back(),
4006
+ onContinue: (amountMinor, nextAutoRecharge) => {
4007
+ setAutoRecharge(nextAutoRecharge);
4008
+ flow.selectAmount(amountMinor);
4009
+ void flow.advance();
4010
+ },
4011
+ cx: cx2
4012
+ }
4013
+ );
4014
+ }
4015
+ if (flow.step === "payment") {
4016
+ if (stripeProbe === "loading") {
4017
+ return /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" });
4018
+ }
4019
+ if (stripeProbe === "blocked") {
4020
+ return /* @__PURE__ */ jsx26(
4021
+ HostedCheckout,
4022
+ {
4023
+ productRef,
4024
+ planRef: flow.selectedPlanRef ?? void 0,
4025
+ planName: selectedPlanShape?.name ?? void 0,
4026
+ onPurchaseSuccess,
4027
+ cx: cx2
4028
+ }
4029
+ );
4030
+ }
4031
+ if (flow.branch === "payg" && selectedPlanShape && flow.selectedAmountMinor != null) {
4032
+ return /* @__PURE__ */ jsx26(
4033
+ PaygPaymentStep,
4034
+ {
4035
+ plan: selectedPlanShape,
4036
+ amountMinor: flow.selectedAmountMinor,
4037
+ topupCurrency: flow.topupCurrency,
4038
+ autoRecharge,
4039
+ returnUrl,
4040
+ onBack: () => flow.back(),
4041
+ onSuccess: (extras) => flow.notifyPaymentSuccess(void 0, extras),
4042
+ cx: cx2
4043
+ }
4044
+ );
4045
+ }
4046
+ if (flow.branch === "recurring" && selectedPlanShape && flow.selectedPlanRef) {
4047
+ return /* @__PURE__ */ jsx26(
4048
+ RecurringPaymentStep,
4049
+ {
4050
+ plan: selectedPlanShape,
4051
+ planRef: flow.selectedPlanRef,
4052
+ productRef,
4053
+ returnUrl,
4054
+ onBack: () => flow.back(),
4055
+ onSuccess: (intent) => flow.notifyPaymentSuccess(intent),
4056
+ cx: cx2
4057
+ }
4058
+ );
4059
+ }
4060
+ return null;
4061
+ }
4062
+ if (flow.step === "success" && flow.successMeta) {
4063
+ return /* @__PURE__ */ jsx26(SuccessStep, { meta: flow.successMeta, cx: cx2 });
4064
+ }
4065
+ return null;
4066
+ }
4067
+
4068
+ // src/mcp/views/McpCheckoutView.tsx
4069
+ import { jsx as jsx27 } from "react/jsx-runtime";
4070
+ function McpCheckoutView({
4071
+ productRef,
4072
+ publishableKey = null,
4073
+ returnUrl,
4074
+ onPurchaseSuccess,
4075
+ onRequestTopup: _onRequestTopup,
4076
+ fromPaywall = false,
4077
+ paywallKind,
4078
+ plans,
4079
+ onClose,
4080
+ onBack,
4081
+ initialPlanRef,
4082
+ autoAdvance,
4083
+ classNames,
4084
+ children
4085
+ }) {
4086
+ const cx2 = resolveMcpClassNames(classNames);
4087
+ const probe = useStripeProbe(publishableKey);
4088
+ return /* @__PURE__ */ jsx27(
4089
+ EmbeddedCheckout,
4090
+ {
4091
+ productRef,
4092
+ returnUrl,
4093
+ onPurchaseSuccess,
4094
+ fromPaywall,
4095
+ paywallKind,
4096
+ plans,
4097
+ onClose,
4098
+ onBack,
4099
+ initialPlanRef,
4100
+ autoAdvance,
4101
+ stripeProbe: probe,
4102
+ cx: cx2,
4103
+ classNames,
4104
+ children
4105
+ }
4106
+ );
4107
+ }
4108
+
4080
4109
  // src/mcp/views/McpTopupView.tsx
4081
- import { useState as useState8 } from "react";
4110
+ import { useRef as useRef6, useState as useState9 } from "react";
4082
4111
 
4083
4112
  // src/mcp/format-compact-credits.ts
4084
4113
  function formatCompactCredits(credits, locale = "en-US") {
@@ -4095,7 +4124,7 @@ function formatCompactCredits(credits, locale = "en-US") {
4095
4124
  }
4096
4125
 
4097
4126
  // src/mcp/views/McpTopupView.tsx
4098
- import { Fragment as Fragment12, jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
4127
+ import { Fragment as Fragment12, jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
4099
4128
  var FALLBACK_TOPUP_CURRENCY = "USD";
4100
4129
  function resolveDefaultCurrency(merchant) {
4101
4130
  if (merchant?.defaultCurrency) {
@@ -4121,18 +4150,15 @@ function McpTopupView({
4121
4150
  const cx2 = resolveMcpClassNames(classNames);
4122
4151
  const probe = useStripeProbe(publishableKey);
4123
4152
  const { merchant, loading: merchantLoading } = useMerchant();
4124
- if (probe === "loading" || merchantLoading) {
4125
- return /* @__PURE__ */ jsx27("section", { className: cx2.card, "aria-label": "Loading top-up", children: /* @__PURE__ */ jsx27("p", { children: "Loading top-up\u2026" }) });
4126
- }
4127
- if (probe === "blocked") {
4128
- return /* @__PURE__ */ jsx27(HostedTopupFallback, { cx: cx2, onBack });
4153
+ if (merchantLoading) {
4154
+ return /* @__PURE__ */ jsx28("section", { className: cx2.card, "aria-label": "Loading top-up", children: /* @__PURE__ */ jsx28("p", { children: "Loading top-up\u2026" }) });
4129
4155
  }
4130
4156
  const defaultCurrency = resolveDefaultCurrency(merchant ?? void 0);
4131
4157
  const fromMerchant = (merchant?.supportedTopupCurrencies ?? []).map((code) => code.toUpperCase()).filter(Boolean);
4132
4158
  const topupCurrencies = Array.from(
4133
4159
  new Set(fromMerchant.length > 0 ? fromMerchant : [defaultCurrency])
4134
4160
  );
4135
- return /* @__PURE__ */ jsx27(
4161
+ return /* @__PURE__ */ jsx28(
4136
4162
  EmbeddedTopup,
4137
4163
  {
4138
4164
  returnUrl,
@@ -4140,6 +4166,7 @@ function McpTopupView({
4140
4166
  topupCurrencies,
4141
4167
  onTopupSuccess,
4142
4168
  onBack,
4169
+ stripeProbe: probe,
4143
4170
  cx: cx2
4144
4171
  }
4145
4172
  );
@@ -4150,18 +4177,15 @@ function EmbeddedTopup({
4150
4177
  topupCurrencies,
4151
4178
  onTopupSuccess,
4152
4179
  onBack,
4180
+ stripeProbe,
4153
4181
  cx: cx2
4154
4182
  }) {
4155
- const [screen, setScreen] = useState8({ step: "amount" });
4156
- const [selectedCurrency, setSelectedCurrency] = useState8(defaultCurrency);
4183
+ const [screen, setScreen] = useState9({ step: "amount" });
4184
+ const [selectedCurrency, setSelectedCurrency] = useState9(defaultCurrency);
4157
4185
  const currency = selectedCurrency;
4158
4186
  const showCurrencySwitch = topupCurrencies.length > 1;
4159
4187
  const { adjustBalance, credits, creditsPerMinorUnit, displayCurrency, displayExchangeRate } = useBalance();
4160
- const copy = useCopy();
4161
- const [autoRechargeForm, setAutoRechargeForm] = useState8(
4162
- () => createDefaultAutoRechargeForm(currency)
4163
- );
4164
- const [autoRechargeError, setAutoRechargeError] = useState8(null);
4188
+ const autoRechargeRef = useRef6(null);
4165
4189
  const locale = useHostLocale();
4166
4190
  const { notifyModelContext, notifySuccess } = useMcpBridge();
4167
4191
  const topupSelector = useTopupAmountSelector({ currency });
@@ -4173,30 +4197,40 @@ function EmbeddedTopup({
4173
4197
  topupSelector.reset();
4174
4198
  };
4175
4199
  if (screen.step === "success") {
4176
- const displayAmount = formatPrice(screen.amountMinor, currency, { locale, free: "" });
4200
+ const estimate = estimateTopupCredits(
4201
+ screen.amountMinor,
4202
+ currency,
4203
+ displayCurrency,
4204
+ creditsPerMinorUnit,
4205
+ displayExchangeRate
4206
+ );
4177
4207
  return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Top-up success", children: [
4178
- onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4179
- /* @__PURE__ */ jsxs20("header", { className: cx2.balanceRow, children: [
4180
- /* @__PURE__ */ jsx27("h2", { className: cx2.heading, children: "Credits added" }),
4181
- /* @__PURE__ */ jsx27(BalanceBadge, {})
4182
- ] }),
4183
- /* @__PURE__ */ jsxs20("p", { className: cx2.muted, children: [
4184
- displayAmount,
4185
- " landed in your balance."
4186
- ] }),
4187
- /* @__PURE__ */ jsx27("button", { type: "button", className: cx2.button, onClick: () => setScreen({ step: "amount" }), children: "Add more credits" }),
4188
- /* @__PURE__ */ jsx27(
4189
- LaunchCustomerPortalButton,
4190
- {
4191
- className: cx2.button,
4192
- loadingClassName: cx2.button,
4193
- errorClassName: cx2.button
4194
- }
4195
- )
4208
+ /* @__PURE__ */ jsx28("div", { className: "solvapay-mcp-checkout-success-check", "aria-hidden": "true", children: "\u2713" }),
4209
+ /* @__PURE__ */ jsx28("h2", { className: cx2.heading, children: "Credits added" }),
4210
+ /* @__PURE__ */ jsxs20("dl", { className: "solvapay-mcp-checkout-receipt", "data-variant": "payg", children: [
4211
+ /* @__PURE__ */ jsxs20("div", { className: "solvapay-mcp-checkout-receipt-row", children: [
4212
+ /* @__PURE__ */ jsx28("dt", { children: "Amount" }),
4213
+ /* @__PURE__ */ jsx28("dd", { children: formatPrice(screen.amountMinor, currency, { locale, free: "" }) })
4214
+ ] }),
4215
+ estimate.kind === "available" ? /* @__PURE__ */ jsxs20("div", { className: "solvapay-mcp-checkout-receipt-row", children: [
4216
+ /* @__PURE__ */ jsx28("dt", { children: "Credits" }),
4217
+ /* @__PURE__ */ jsxs20("dd", { children: [
4218
+ "+",
4219
+ estimate.credits.toLocaleString(locale)
4220
+ ] })
4221
+ ] }) : null
4222
+ ] })
4196
4223
  ] });
4197
4224
  }
4198
4225
  if (screen.step === "payment") {
4226
+ if (stripeProbe === "loading") {
4227
+ return /* @__PURE__ */ jsx28("section", { className: cx2.card, "aria-label": "Loading top-up", children: /* @__PURE__ */ jsx28("p", { children: "Loading top-up\u2026" }) });
4228
+ }
4229
+ if (stripeProbe === "blocked") {
4230
+ return /* @__PURE__ */ jsx28(HostedTopupFallback, { cx: cx2, onChangeAmount: () => setScreen({ step: "amount" }) });
4231
+ }
4199
4232
  const committedAmountMinor = screen.amountMinor;
4233
+ const savesCard = screen.autoRecharge != null;
4200
4234
  const creditEstimate = estimateTopupCredits(
4201
4235
  committedAmountMinor,
4202
4236
  currency,
@@ -4209,7 +4243,7 @@ function EmbeddedTopup({
4209
4243
  creditEstimate.kind === "available" ? `Adds ${creditEstimate.credits.toLocaleString(locale)} credits` : void 0,
4210
4244
  formattedBalance ? `Balance ${formattedBalance} credits` : void 0
4211
4245
  ].filter((part) => part != null);
4212
- return /* @__PURE__ */ jsx27("section", { className: cx2.card, "aria-label": "Top-up payment", children: /* @__PURE__ */ jsx27(
4246
+ return /* @__PURE__ */ jsx28("section", { className: cx2.card, "aria-label": "Top-up payment", children: /* @__PURE__ */ jsx28(
4213
4247
  TopupForm.Root,
4214
4248
  {
4215
4249
  amount: committedAmountMinor,
@@ -4235,14 +4269,14 @@ function EmbeddedTopup({
4235
4269
  onTopupSuccess?.(committedAmountMinor);
4236
4270
  },
4237
4271
  children: /* @__PURE__ */ jsxs20(McpHostedLayout, { children: [
4238
- /* @__PURE__ */ jsx27(McpSummaryRail, { children: /* @__PURE__ */ jsxs20("section", { className: cx2.stack, children: [
4239
- /* @__PURE__ */ jsx27("p", { className: cx2.muted, children: "Total due today" }),
4240
- /* @__PURE__ */ jsx27("p", { className: cx2.topupAmountHero, children: /* @__PURE__ */ jsx27(TopupChargeAmount, { amountMinor: committedAmountMinor, currency }) }),
4241
- contextParts.length > 0 ? /* @__PURE__ */ jsx27("p", { className: cx2.topupBalanceContext, children: contextParts.join(" \xB7 ") }) : null,
4242
- isFullscreen ? /* @__PURE__ */ jsx27(TopupForm.Summary.Rows, { className: cx2.taxSummary }) : /* @__PURE__ */ jsx27(TopupForm.Summary.TaxNote, { className: cx2.muted })
4272
+ /* @__PURE__ */ jsx28(McpSummaryRail, { children: /* @__PURE__ */ jsxs20("section", { className: cx2.stack, children: [
4273
+ /* @__PURE__ */ jsx28("p", { className: cx2.muted, children: "Total due today" }),
4274
+ /* @__PURE__ */ jsx28("p", { className: cx2.topupAmountHero, children: /* @__PURE__ */ jsx28(TopupChargeAmount, { amountMinor: committedAmountMinor, currency }) }),
4275
+ contextParts.length > 0 ? /* @__PURE__ */ jsx28("p", { className: cx2.topupBalanceContext, children: contextParts.join(" \xB7 ") }) : null,
4276
+ isFullscreen ? /* @__PURE__ */ jsx28(TopupForm.Summary.Rows, { className: cx2.taxSummary }) : /* @__PURE__ */ jsx28(TopupForm.Summary.TaxNote, { className: cx2.muted })
4243
4277
  ] }) }),
4244
4278
  /* @__PURE__ */ jsxs20(McpHostedBody, { children: [
4245
- /* @__PURE__ */ jsx27(
4279
+ /* @__PURE__ */ jsx28(
4246
4280
  McpPaymentHeader,
4247
4281
  {
4248
4282
  backLabel: "Change amount",
@@ -4250,16 +4284,24 @@ function EmbeddedTopup({
4250
4284
  }
4251
4285
  ),
4252
4286
  /* @__PURE__ */ jsxs20("div", { className: cx2.topupForm, children: [
4253
- /* @__PURE__ */ jsx27(TopupForm.Loading, {}),
4254
- /* @__PURE__ */ jsx27(TopupForm.PaymentElement, {}),
4255
- /* @__PURE__ */ jsx27(TopupForm.BusinessDetails.Root, { className: cx2.businessDetails, children: /* @__PURE__ */ jsx27(TopupForm.BusinessDetails.Fields, {}) }),
4256
- /* @__PURE__ */ jsx27(TopupForm.Error, { className: cx2.error }),
4287
+ /* @__PURE__ */ jsx28(TopupForm.Loading, {}),
4288
+ /* @__PURE__ */ jsx28(TopupForm.PaymentElement, { options: MCP_PAYMENT_ELEMENT_OPTIONS }),
4289
+ /* @__PURE__ */ jsx28(TopupForm.BusinessDetails.Root, { className: cx2.businessDetails, children: /* @__PURE__ */ jsx28(TopupForm.BusinessDetails.Fields, {}) }),
4290
+ /* @__PURE__ */ jsx28(TopupForm.Error, { className: cx2.error }),
4257
4291
  /* @__PURE__ */ jsxs20(TopupForm.SubmitButton, { className: cx2.button, children: [
4258
4292
  "Top up",
4259
4293
  " ",
4260
- /* @__PURE__ */ jsx27(TopupChargeAmount, { amountMinor: committedAmountMinor, currency })
4294
+ /* @__PURE__ */ jsx28(TopupChargeAmount, { amountMinor: committedAmountMinor, currency })
4261
4295
  ] }),
4262
- /* @__PURE__ */ jsx27(MandateText, { mode: "topup", amountMinor: committedAmountMinor, currency })
4296
+ /* @__PURE__ */ jsx28(
4297
+ MandateText,
4298
+ {
4299
+ mode: "topup",
4300
+ amountMinor: committedAmountMinor,
4301
+ currency,
4302
+ savesPaymentMethod: savesCard
4303
+ }
4304
+ )
4263
4305
  ] })
4264
4306
  ] })
4265
4307
  ] })
@@ -4275,7 +4317,7 @@ function EmbeddedTopup({
4275
4317
  selector: topupSelector,
4276
4318
  className: cx2.amountPicker,
4277
4319
  children: [
4278
- isFullscreen ? null : /* @__PURE__ */ jsx27(
4320
+ isFullscreen ? null : /* @__PURE__ */ jsx28(
4279
4321
  AmountStepHeader,
4280
4322
  {
4281
4323
  cx: cx2,
@@ -4285,65 +4327,38 @@ function EmbeddedTopup({
4285
4327
  onCurrencyChange: handleCurrencyChange
4286
4328
  }
4287
4329
  ),
4288
- /* @__PURE__ */ jsx27(PresetAmountGrid, { currencyDisplay, locale }),
4289
- /* @__PURE__ */ jsx27(
4330
+ /* @__PURE__ */ jsx28(PresetAmountGrid, { currencyDisplay, locale }),
4331
+ /* @__PURE__ */ jsx28(
4290
4332
  CustomAmountRow2,
4291
4333
  {
4292
4334
  rowClassName: cx2.amountCustom,
4293
4335
  currencyDisplay
4294
4336
  }
4295
4337
  ),
4296
- /* @__PURE__ */ jsxs20("div", { className: "solvapay-mcp-auto-recharge-inline", children: [
4297
- /* @__PURE__ */ jsxs20(SplitRow, { children: [
4298
- /* @__PURE__ */ jsx27("p", { children: copy.autoRechargeView.heading }),
4299
- /* @__PURE__ */ jsx27(
4300
- Toggle,
4301
- {
4302
- checked: autoRechargeForm.enabled,
4303
- label: copy.autoRechargeView.heading,
4304
- onChange: (enabled) => {
4305
- setAutoRechargeError(null);
4306
- setAutoRechargeForm((current) => ({ ...current, enabled }));
4307
- }
4308
- }
4309
- )
4310
- ] }),
4311
- autoRechargeForm.enabled ? /* @__PURE__ */ jsx27(
4312
- McpAutoRechargeFields,
4313
- {
4314
- form: autoRechargeForm,
4315
- onChange: (next) => {
4316
- setAutoRechargeError(null);
4317
- setAutoRechargeForm(next);
4318
- },
4319
- currency,
4320
- validationError: autoRechargeError,
4321
- creditsPerMinorUnit,
4322
- displayExchangeRate
4323
- }
4324
- ) : null
4325
- ] }),
4326
- /* @__PURE__ */ jsx27(AmountDueSummary, { locale, currency }),
4327
- /* @__PURE__ */ jsx27(
4338
+ /* @__PURE__ */ jsx28(
4339
+ McpInlineAutoRecharge,
4340
+ {
4341
+ ref: autoRechargeRef,
4342
+ currency,
4343
+ creditsPerMinorUnit,
4344
+ displayExchangeRate
4345
+ }
4346
+ ),
4347
+ /* @__PURE__ */ jsx28(AmountDueSummary, { locale, currency }),
4348
+ /* @__PURE__ */ jsx28(
4328
4349
  AmountPicker.Confirm,
4329
4350
  {
4330
4351
  className: cx2.button,
4331
4352
  onConfirm: (amountMinor) => {
4332
- const result = validateAutoRechargeForm(
4333
- autoRechargeForm,
4334
- currency,
4335
- { creditsPerMinorUnit, displayExchangeRate },
4336
- copy.autoRecharge
4337
- );
4338
- if (!result.ok) {
4339
- setAutoRechargeError(result.error);
4340
- return;
4353
+ const result = autoRechargeRef.current?.validate();
4354
+ if (result == null) {
4355
+ throw new Error("McpTopupView: auto-recharge form is not mounted");
4341
4356
  }
4342
- setAutoRechargeError(null);
4357
+ if (!result.ok) return;
4343
4358
  setScreen({
4344
4359
  step: "payment",
4345
4360
  amountMinor,
4346
- autoRecharge: result.payload.enabled ? result.payload : void 0
4361
+ autoRecharge: result.payload
4347
4362
  });
4348
4363
  void notifyModelContext({
4349
4364
  text: `User confirmed topup of ${formatPrice(amountMinor, currency, {
@@ -4359,8 +4374,8 @@ function EmbeddedTopup({
4359
4374
  }
4360
4375
  );
4361
4376
  if (isFullscreen) {
4362
- return /* @__PURE__ */ jsx27("section", { className: cx2.card, "aria-label": "Add credits", children: /* @__PURE__ */ jsxs20(McpHostedLayout, { children: [
4363
- /* @__PURE__ */ jsx27(McpSummaryRail, { children: /* @__PURE__ */ jsx27(
4377
+ return /* @__PURE__ */ jsx28("section", { className: cx2.card, "aria-label": "Add credits", children: /* @__PURE__ */ jsxs20(McpHostedLayout, { children: [
4378
+ /* @__PURE__ */ jsx28(McpSummaryRail, { children: /* @__PURE__ */ jsx28(
4364
4379
  AmountStepHeader,
4365
4380
  {
4366
4381
  cx: cx2,
@@ -4372,13 +4387,13 @@ function EmbeddedTopup({
4372
4387
  }
4373
4388
  ) }),
4374
4389
  /* @__PURE__ */ jsxs20(McpHostedBody, { children: [
4375
- onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4390
+ onBack ? /* @__PURE__ */ jsx28(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4376
4391
  amountForm
4377
4392
  ] })
4378
4393
  ] }) });
4379
4394
  }
4380
4395
  return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Add credits", children: [
4381
- onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4396
+ onBack ? /* @__PURE__ */ jsx28(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4382
4397
  amountForm
4383
4398
  ] });
4384
4399
  }
@@ -4389,7 +4404,7 @@ function TopupChargeAmount({
4389
4404
  const locale = useHostLocale();
4390
4405
  const { taxBreakdown } = useTopupForm();
4391
4406
  const minor = chargeAmountMinor(taxBreakdown, amountMinor);
4392
- return /* @__PURE__ */ jsx27(Fragment12, { children: formatPrice(minor, taxBreakdown?.currency ?? currency, { locale, free: "" }) });
4407
+ return /* @__PURE__ */ jsx28(Fragment12, { children: formatPrice(minor, taxBreakdown?.currency ?? currency, { locale, free: "" }) });
4393
4408
  }
4394
4409
  function AmountStepHeader({
4395
4410
  cx: cx2,
@@ -4404,26 +4419,26 @@ function AmountStepHeader({
4404
4419
  const formattedBalance = credits != null ? new Intl.NumberFormat(locale).format(credits) : void 0;
4405
4420
  return /* @__PURE__ */ jsxs20("header", { className: rail ? cx2.stack : void 0, children: [
4406
4421
  rail ? /* @__PURE__ */ jsxs20(Fragment12, { children: [
4407
- /* @__PURE__ */ jsx27(Eyebrow, { variant: "rail", children: "Add credits" }),
4422
+ /* @__PURE__ */ jsx28(Eyebrow, { variant: "rail", children: "Add credits" }),
4408
4423
  formattedBalance ? /* @__PURE__ */ jsxs20("p", { className: cx2.muted, children: [
4409
4424
  "Balance ",
4410
4425
  formattedBalance,
4411
4426
  " credits"
4412
4427
  ] }) : null
4413
4428
  ] }) : /* @__PURE__ */ jsxs20("div", { className: cx2.balanceRow, children: [
4414
- /* @__PURE__ */ jsx27("h2", { className: cx2.heading, children: "Add credits" }),
4415
- /* @__PURE__ */ jsx27(BalanceBadge, {})
4429
+ /* @__PURE__ */ jsx28("h2", { className: cx2.heading, children: "Add credits" }),
4430
+ /* @__PURE__ */ jsx28(BalanceBadge, {})
4416
4431
  ] }),
4417
4432
  showCurrencySwitch ? /* @__PURE__ */ jsxs20("label", { className: "solvapay-mcp-step-header", children: [
4418
- /* @__PURE__ */ jsx27("span", { className: cx2.muted, children: "Pay in" }),
4419
- /* @__PURE__ */ jsx27(
4433
+ /* @__PURE__ */ jsx28("span", { className: cx2.muted, children: "Pay in" }),
4434
+ /* @__PURE__ */ jsx28(
4420
4435
  "select",
4421
4436
  {
4422
4437
  className: "solvapay-mcp-currency-switch",
4423
4438
  value: currency,
4424
4439
  onChange: (event) => onCurrencyChange(event.target.value),
4425
4440
  "aria-label": "Topup currency",
4426
- children: topupCurrencies.map((code) => /* @__PURE__ */ jsx27("option", { value: code, children: code }, code))
4441
+ children: topupCurrencies.map((code) => /* @__PURE__ */ jsx28("option", { value: code, children: code }, code))
4427
4442
  }
4428
4443
  )
4429
4444
  ] }) : null
@@ -4435,7 +4450,7 @@ function PresetAmountGrid({
4435
4450
  }) {
4436
4451
  const { quickAmounts, currency, creditsPerMinorUnit, displayExchangeRate } = useAmountPicker();
4437
4452
  const { displayCurrency } = useBalance();
4438
- return /* @__PURE__ */ jsx27("div", { className: "solvapay-mcp-preset-grid", "aria-label": "Quick amounts", children: quickAmounts.map((amount) => {
4453
+ return /* @__PURE__ */ jsx28("div", { className: "solvapay-mcp-preset-grid", "aria-label": "Quick amounts", children: quickAmounts.map((amount) => {
4439
4454
  const minor = amount * getMinorUnitsPerMajor(currency);
4440
4455
  const label = formatPrice(minor, currency, {
4441
4456
  locale,
@@ -4450,21 +4465,21 @@ function PresetAmountGrid({
4450
4465
  displayExchangeRate
4451
4466
  );
4452
4467
  return /* @__PURE__ */ jsxs20(AmountPicker.Option, { amount, className: "solvapay-mcp-preset-tile", children: [
4453
- /* @__PURE__ */ jsx27("span", { className: "solvapay-mcp-preset-tile-amount", children: label }),
4454
- /* @__PURE__ */ jsx27("span", { className: "solvapay-mcp-preset-tile-credits", children: estimate.kind === "available" ? formatCompactCredits(estimate.credits, locale) : "" })
4468
+ /* @__PURE__ */ jsx28("span", { className: "solvapay-mcp-preset-tile-amount", children: label }),
4469
+ /* @__PURE__ */ jsx28("span", { className: "solvapay-mcp-preset-tile-credits", children: estimate.kind === "available" ? formatCompactCredits(estimate.credits, locale) : "" })
4455
4470
  ] }, amount);
4456
4471
  }) });
4457
4472
  }
4458
4473
  function AmountDueSummary({ locale, currency }) {
4459
4474
  const { resolvedAmountMinor } = useAmountPicker();
4460
4475
  const displayAmount = resolvedAmountMinor != null ? formatPrice(resolvedAmountMinor, currency, { locale, free: "" }) : formatPrice(0, currency, { locale, free: "" });
4461
- return /* @__PURE__ */ jsx27(
4476
+ return /* @__PURE__ */ jsx28(
4462
4477
  AmountLadder,
4463
4478
  {
4464
4479
  rows: [
4465
4480
  {
4466
4481
  label: "Total due today",
4467
- value: /* @__PURE__ */ jsx27("span", { className: "solvapay-mcp-topup-total", children: displayAmount })
4482
+ value: /* @__PURE__ */ jsx28("span", { className: "solvapay-mcp-topup-total", children: displayAmount })
4468
4483
  }
4469
4484
  ]
4470
4485
  }
@@ -4477,16 +4492,19 @@ function CustomAmountRow2({
4477
4492
  const { currencySymbol: currencySymbol2, currency } = useAmountPicker();
4478
4493
  const prefix = currencyDisplay === "code" ? currency.toUpperCase() : currencySymbol2;
4479
4494
  return /* @__PURE__ */ jsxs20("label", { className: rowClassName, children: [
4480
- /* @__PURE__ */ jsx27("span", { className: "solvapay-mcp-amount-currency-symbol", children: prefix }),
4481
- /* @__PURE__ */ jsx27(AmountPicker.Custom, { className: "solvapay-mcp-amount-custom-input", placeholder: "0.00" })
4495
+ /* @__PURE__ */ jsx28("span", { className: "solvapay-mcp-amount-currency-symbol", children: prefix }),
4496
+ /* @__PURE__ */ jsx28(AmountPicker.Custom, { className: "solvapay-mcp-amount-custom-input", placeholder: "0.00" })
4482
4497
  ] });
4483
4498
  }
4484
- function HostedTopupFallback({ cx: cx2, onBack }) {
4499
+ function HostedTopupFallback({
4500
+ cx: cx2,
4501
+ onChangeAmount
4502
+ }) {
4485
4503
  return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Add credits", children: [
4486
- onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
4487
- /* @__PURE__ */ jsx27("h2", { className: cx2.heading, children: "Add credits" }),
4488
- /* @__PURE__ */ jsx27("p", { className: cx2.muted, children: "This host doesn't allow embedded payments. Open the SolvaPay portal in a new tab to complete your top-up there." }),
4489
- /* @__PURE__ */ jsx27(
4504
+ /* @__PURE__ */ jsx28(BackLink, { label: "Change amount", onClick: onChangeAmount }),
4505
+ /* @__PURE__ */ jsx28("h2", { className: cx2.heading, children: "Add credits" }),
4506
+ /* @__PURE__ */ jsx28("p", { className: cx2.muted, children: "This host doesn't allow embedded payments. Open the SolvaPay portal in a new tab to complete your top-up there." }),
4507
+ /* @__PURE__ */ jsx28(
4490
4508
  LaunchCustomerPortalButton,
4491
4509
  {
4492
4510
  className: cx2.button,
@@ -4499,7 +4517,7 @@ function HostedTopupFallback({ cx: cx2, onBack }) {
4499
4517
  }
4500
4518
 
4501
4519
  // src/mcp/McpAppShell.tsx
4502
- import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
4520
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
4503
4521
  function resolveSurface(bootstrapView) {
4504
4522
  switch (bootstrapView) {
4505
4523
  case "checkout":
@@ -4526,8 +4544,8 @@ function McpAppShell({
4526
4544
  onRefreshBootstrap,
4527
4545
  onClose
4528
4546
  }) {
4529
- const [overrideView, setOverrideView] = useState9(null);
4530
- const [overridePlanRef, setOverridePlanRef] = useState9();
4547
+ const [overrideView, setOverrideView] = useState10(null);
4548
+ const [overridePlanRef, setOverridePlanRef] = useState10();
4531
4549
  const handleSurfaceChange = useCallback5((next, intent) => {
4532
4550
  setOverrideView(next);
4533
4551
  setOverridePlanRef(intent?.planRef);
@@ -4537,7 +4555,7 @@ function McpAppShell({
4537
4555
  const showFooter = footer ?? true;
4538
4556
  const surface = effectiveView === "account" || effectiveView === "auto-recharge" ? "management" : "payment";
4539
4557
  return /* @__PURE__ */ jsxs21("div", { className: "solvapay-mcp-shell", children: [
4540
- /* @__PURE__ */ jsx28(McpHostedColumn, { surface, children: /* @__PURE__ */ jsx28(McpHostedLayout, { children: /* @__PURE__ */ jsx28("div", { className: "solvapay-mcp-shell-body", children: /* @__PURE__ */ jsx28(
4558
+ /* @__PURE__ */ jsx29(McpHostedColumn, { surface, children: /* @__PURE__ */ jsx29(McpHostedLayout, { children: /* @__PURE__ */ jsx29("div", { className: "solvapay-mcp-shell-body", children: /* @__PURE__ */ jsx29(
4541
4559
  McpViewRouter,
4542
4560
  {
4543
4561
  view: effectiveView,
@@ -4550,12 +4568,12 @@ function McpAppShell({
4550
4568
  onClose
4551
4569
  }
4552
4570
  ) }) }) }),
4553
- showFooter ? /* @__PURE__ */ jsx28(ShellFooter, { classNames }) : null
4571
+ showFooter ? /* @__PURE__ */ jsx29(ShellFooter, { classNames }) : null
4554
4572
  ] });
4555
4573
  }
4556
4574
  function ShellFooter({ classNames }) {
4557
4575
  const cx2 = resolveMcpClassNames(classNames);
4558
- return /* @__PURE__ */ jsx28("footer", { className: `solvapay-mcp-shell-footer ${cx2.muted}`.trim(), children: /* @__PURE__ */ jsx28(LegalFooter, { attribution: "provided" }) });
4576
+ return /* @__PURE__ */ jsx29("footer", { className: `solvapay-mcp-shell-footer ${cx2.muted}`.trim(), children: /* @__PURE__ */ jsx29(LegalFooter, { attribution: "provided" }) });
4559
4577
  }
4560
4578
  function McpViewRouter({
4561
4579
  view,
@@ -4571,14 +4589,12 @@ function McpViewRouter({
4571
4589
  const CheckoutView = views?.checkout ?? McpCheckoutView;
4572
4590
  const AccountView = views?.account ?? McpAccountView;
4573
4591
  const TopupView = views?.topup ?? McpTopupView;
4574
- const AutoRechargeView = views?.autoRecharge ?? McpAutoRechargeView;
4575
4592
  const goCheckout = onSurfaceChange ? (planRef) => onSurfaceChange("checkout", typeof planRef === "string" ? { planRef } : void 0) : void 0;
4576
4593
  const goTopup = onSurfaceChange ? () => onSurfaceChange("topup") : void 0;
4577
4594
  const goAccount = onSurfaceChange ? () => onSurfaceChange("account") : void 0;
4578
- const goAutoRecharge = onSurfaceChange ? () => onSurfaceChange("auto-recharge") : void 0;
4579
4595
  switch (view) {
4580
4596
  case "checkout":
4581
- return /* @__PURE__ */ jsx28(
4597
+ return /* @__PURE__ */ jsx29(
4582
4598
  CheckoutView,
4583
4599
  {
4584
4600
  productRef,
@@ -4594,23 +4610,23 @@ function McpViewRouter({
4594
4610
  autoAdvance: Boolean(overridePlanRef)
4595
4611
  }
4596
4612
  );
4613
+ case "auto-recharge":
4597
4614
  case "account":
4598
- return /* @__PURE__ */ jsx28(
4615
+ return /* @__PURE__ */ jsx29(
4599
4616
  AccountView,
4600
4617
  {
4601
4618
  classNames,
4602
4619
  product: bootstrap.product,
4603
4620
  productRef,
4604
4621
  onTopup: goTopup,
4605
- onAutoRecharge: goAutoRecharge,
4622
+ autoRecharge: bootstrap.customer?.autoRecharge ?? null,
4623
+ autoRechargeUrl: bootstrap.autoRechargeUrl ?? null,
4606
4624
  onChangePlan: goCheckout,
4607
4625
  plans: bootstrap.plans
4608
4626
  }
4609
4627
  );
4610
- case "auto-recharge":
4611
- return /* @__PURE__ */ jsx28(AutoRechargeView, { classNames, onBack: goAccount });
4612
4628
  case "topup":
4613
- return /* @__PURE__ */ jsx28(
4629
+ return /* @__PURE__ */ jsx29(
4614
4630
  TopupView,
4615
4631
  {
4616
4632
  publishableKey: stripePublishableKey,
@@ -4625,21 +4641,21 @@ function McpViewRouter({
4625
4641
  }
4626
4642
 
4627
4643
  // src/mcp/views/AppHeader.tsx
4628
- import { useContext as useContext4, useLayoutEffect, useRef as useRef5, useState as useState10 } from "react";
4644
+ import { useContext as useContext4, useLayoutEffect, useRef as useRef7, useState as useState11 } from "react";
4629
4645
 
4630
4646
  // src/mcp/hooks/useHostInfo.tsx
4631
4647
  import { createContext as createContext3, useContext as useContext3 } from "react";
4632
- import { jsx as jsx29 } from "react/jsx-runtime";
4648
+ import { jsx as jsx30 } from "react/jsx-runtime";
4633
4649
  var McpHostInfoContext = createContext3(null);
4634
4650
  function McpHostInfoProvider({ hostName, children }) {
4635
- return /* @__PURE__ */ jsx29(McpHostInfoContext.Provider, { value: hostName, children });
4651
+ return /* @__PURE__ */ jsx30(McpHostInfoContext.Provider, { value: hostName, children });
4636
4652
  }
4637
4653
  function useHostName() {
4638
4654
  return useContext3(McpHostInfoContext);
4639
4655
  }
4640
4656
 
4641
4657
  // src/mcp/views/AppHeader.tsx
4642
- import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
4658
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
4643
4659
  var HOSTS_WITH_MERCHANT_CHROME = /chatgpt|openai|claude/i;
4644
4660
  function useMerchantSafe() {
4645
4661
  const ctx = useContext4(SolvaPayContext);
@@ -4676,9 +4692,9 @@ function AppHeader({
4676
4692
  const hostName = useHostName();
4677
4693
  const name = merchant?.displayName ?? "SolvaPay";
4678
4694
  const iconUrl = merchant?.iconUrl ?? merchant?.logoUrl ?? null;
4679
- const [imgFailed, setImgFailed] = useState10(false);
4680
- const [imgLoaded, setImgLoaded] = useState10(false);
4681
- const imgRef = useRef5(null);
4695
+ const [imgFailed, setImgFailed] = useState11(false);
4696
+ const [imgLoaded, setImgLoaded] = useState11(false);
4697
+ const imgRef = useRef7(null);
4682
4698
  useLayoutEffect(() => {
4683
4699
  const el = imgRef.current;
4684
4700
  const cached = el ? el.complete && el.naturalHeight > 0 : false;
@@ -4693,7 +4709,7 @@ function AppHeader({
4693
4709
  const hasIconUrl = iconUrl !== null && !imgFailed;
4694
4710
  const showInitials = !hasIconUrl || !imgLoaded;
4695
4711
  return /* @__PURE__ */ jsxs22("header", { className: rootClass, children: [
4696
- hasIconUrl ? /* @__PURE__ */ jsx30(
4712
+ hasIconUrl ? /* @__PURE__ */ jsx31(
4697
4713
  "img",
4698
4714
  {
4699
4715
  ref: imgRef,
@@ -4705,14 +4721,14 @@ function AppHeader({
4705
4721
  onError: () => setImgFailed(true)
4706
4722
  }
4707
4723
  ) : null,
4708
- showInitials ? /* @__PURE__ */ jsx30("span", { className: cx2.appHeaderInitials, "aria-hidden": "true", children: getInitials(name) }) : null,
4709
- /* @__PURE__ */ jsx30("span", { className: cx2.appHeaderName, children: name }),
4710
- children ? /* @__PURE__ */ jsx30("span", { className: "solvapay-mcp-app-header-slot", children }) : null
4724
+ showInitials ? /* @__PURE__ */ jsx31("span", { className: cx2.appHeaderInitials, "aria-hidden": "true", children: getInitials(name) }) : null,
4725
+ /* @__PURE__ */ jsx31("span", { className: cx2.appHeaderName, children: name }),
4726
+ children ? /* @__PURE__ */ jsx31("span", { className: "solvapay-mcp-app-header-slot", children }) : null
4711
4727
  ] });
4712
4728
  }
4713
4729
 
4714
4730
  // src/mcp/McpApp.tsx
4715
- import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
4731
+ import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
4716
4732
  function bootstrapToInitial(bs) {
4717
4733
  return {
4718
4734
  customerRef: bs.customer?.ref ?? null,
@@ -4738,15 +4754,15 @@ function McpApp({
4738
4754
  messageOnSuccess
4739
4755
  }) {
4740
4756
  const cx2 = resolveMcpClassNames(classNames);
4741
- const [bootstrap, setBootstrap] = useState11(null);
4742
- const [initError, setInitError] = useState11(null);
4743
- const [hostName, setHostName] = useState11(null);
4744
- const [displayModeState, setDisplayModeState] = useState11(
4757
+ const [bootstrap, setBootstrap] = useState12(null);
4758
+ const [initError, setInitError] = useState12(null);
4759
+ const [hostName, setHostName] = useState12(null);
4760
+ const [displayModeState, setDisplayModeState] = useState12(
4745
4761
  DEFAULT_DISPLAY_MODE_STATE
4746
4762
  );
4747
- const pendingBootstrapFetchRef = useRef6(0);
4748
- const applyContextRef = useRef6(applyContext);
4749
- const onInitErrorRef = useRef6(onInitError);
4763
+ const pendingBootstrapFetchRef = useRef8(0);
4764
+ const applyContextRef = useRef8(applyContext);
4765
+ const onInitErrorRef = useRef8(onInitError);
4750
4766
  useEffect7(() => {
4751
4767
  applyContextRef.current = applyContext;
4752
4768
  }, [applyContext]);
@@ -4906,7 +4922,7 @@ function McpApp({
4906
4922
  };
4907
4923
  return resolved;
4908
4924
  }, [transport, initial, app]);
4909
- const seededInitialRef = useRef6(null);
4925
+ const seededInitialRef = useRef8(null);
4910
4926
  if (initial && seededInitialRef.current !== initial) {
4911
4927
  seedMcpCaches(initial, providerConfig);
4912
4928
  seededInitialRef.current = initial;
@@ -4934,14 +4950,14 @@ function McpApp({
4934
4950
  );
4935
4951
  const effectiveOnClose = onClose ?? defaultOnClose;
4936
4952
  const effectiveBootstrap = bootstrap && productRefOverride ? { ...bootstrap, productRef: productRefOverride } : bootstrap;
4937
- return /* @__PURE__ */ jsx31(McpHostInfoProvider, { hostName, children: /* @__PURE__ */ jsx31(McpDisplayModeProvider, { value: displayModeState, children: /* @__PURE__ */ jsxs23(
4953
+ return /* @__PURE__ */ jsx32(McpHostInfoProvider, { hostName, children: /* @__PURE__ */ jsx32(McpDisplayModeProvider, { value: displayModeState, children: /* @__PURE__ */ jsxs23(
4938
4954
  "main",
4939
4955
  {
4940
4956
  className: "solvapay-mcp-main",
4941
4957
  "data-display-mode": displayModeState.displayMode,
4942
4958
  style: hostSafeAreaPadding(displayModeState.safeAreaInsets),
4943
4959
  children: [
4944
- /* @__PURE__ */ jsx31("div", { className: "solvapay-mcp-chrome-row", children: displayModeState.displayMode !== "fullscreen" ? /* @__PURE__ */ jsx31(
4960
+ /* @__PURE__ */ jsx32("div", { className: "solvapay-mcp-chrome-row", children: displayModeState.displayMode !== "fullscreen" ? /* @__PURE__ */ jsx32(
4945
4961
  AppHeader,
4946
4962
  {
4947
4963
  classNames,
@@ -4949,16 +4965,16 @@ function McpApp({
4949
4965
  }
4950
4966
  ) : null }),
4951
4967
  initError ? /* @__PURE__ */ jsxs23("div", { className: `${cx2.card} ${cx2.error}`.trim(), children: [
4952
- /* @__PURE__ */ jsx31("h2", { className: cx2.heading, children: "Unable to load SolvaPay" }),
4953
- /* @__PURE__ */ jsx31("p", { children: initError })
4968
+ /* @__PURE__ */ jsx32("h2", { className: cx2.heading, children: "Unable to load SolvaPay" }),
4969
+ /* @__PURE__ */ jsx32("p", { children: initError })
4954
4970
  ] }) : !effectiveBootstrap ? (
4955
4971
  // Intent-tool / fallback entries show a loading card while the
4956
4972
  // in-flight `fetchMcpBootstrap` call resolves. Data-tool iframe
4957
4973
  // entries no longer exist (payable merchant tools don't advertise
4958
4974
  // `_meta.ui.resourceUri`) so this is always legitimate user
4959
4975
  // feedback for an in-flight tool call.
4960
- /* @__PURE__ */ jsx31("div", { className: cx2.card, children: /* @__PURE__ */ jsx31("p", { children: "Loading\u2026" }) })
4961
- ) : /* @__PURE__ */ jsx31(SolvaPayProvider, { config: providerConfig, children: /* @__PURE__ */ jsx31(McpBridgeProvider, { app, messageOnSuccess, children: /* @__PURE__ */ jsx31(
4976
+ /* @__PURE__ */ jsx32("div", { className: cx2.card, children: /* @__PURE__ */ jsx32("p", { children: "Loading\u2026" }) })
4977
+ ) : /* @__PURE__ */ jsx32(SolvaPayProvider, { config: providerConfig, children: /* @__PURE__ */ jsx32(McpBridgeProvider, { app, messageOnSuccess, children: /* @__PURE__ */ jsx32(
4962
4978
  McpAppShell,
4963
4979
  {
4964
4980
  bootstrap: effectiveBootstrap,
@@ -4995,7 +5011,6 @@ export {
4995
5011
  McpAccountView,
4996
5012
  McpApp,
4997
5013
  McpAppShell,
4998
- McpAutoRechargeView,
4999
5014
  McpBridgeProvider,
5000
5015
  McpCheckoutView,
5001
5016
  McpDisplayModeProvider,
@@ -5038,6 +5053,7 @@ export {
5038
5053
  planConsequence,
5039
5054
  readDisplayModeState,
5040
5055
  remainingCap,
5056
+ resetStripeProbeCacheForTests,
5041
5057
  resolveAccountState,
5042
5058
  resolveActivationStrategy,
5043
5059
  resolveActivityStrip,