@solvapay/react 2.2.2-preview-cf2672297243fbf98ba33872a7348aca170e7b01 → 2.2.2
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/CHANGELOG.md +1 -16
- package/dist/{UsageMeter-CCWxdw12.d.ts → UsageMeter-BZWfC5KX.d.ts} +1 -1
- package/dist/{UsageMeter-wjQ1xFpP.d.cts → UsageMeter-BiujMmVR.d.cts} +1 -1
- package/dist/{chunk-3OR5EEP4.js → chunk-4UFQDYG5.js} +1 -1
- package/dist/{chunk-JVBZHE7B.js → chunk-GPP4MY3I.js} +205 -33
- package/dist/{chunk-C4QZGH7X.js → chunk-KUH3SNWZ.js} +41 -225
- package/dist/{index-CLYaY7rM.d.cts → index-B5QUesJE.d.cts} +1 -1
- package/dist/{index-ZnFJaFNZ.d.ts → index-BAYpUp5R.d.ts} +1 -1
- package/dist/index.cjs +2 -4
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/mcp/index.cjs +2232 -1890
- package/dist/mcp/index.d.cts +23 -36
- package/dist/mcp/index.d.ts +23 -36
- package/dist/mcp/index.js +772 -766
- package/dist/primitives/index.cjs +2 -4
- package/dist/primitives/index.d.cts +5 -5
- package/dist/primitives/index.d.ts +5 -5
- package/dist/primitives/index.js +2 -2
- package/dist/{useUsage-BpIrBHDT.d.cts → useUsage-CRd_E6J3.d.cts} +52 -37
- package/dist/{useUsage-SizdkzW3.d.ts → useUsage-DSPWQ37m.d.ts} +52 -37
- package/package.json +4 -4
package/dist/mcp/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ExternalLinkGlyph,
|
|
3
3
|
LaunchCustomerPortalButton,
|
|
4
|
-
paymentMethodCache
|
|
5
|
-
|
|
4
|
+
paymentMethodCache,
|
|
5
|
+
usePaymentMethod
|
|
6
|
+
} from "../chunk-4UFQDYG5.js";
|
|
6
7
|
import {
|
|
7
8
|
AmountPicker,
|
|
8
9
|
BalanceBadge,
|
|
@@ -16,9 +17,12 @@ import {
|
|
|
16
17
|
SolvaPayProvider,
|
|
17
18
|
TopupForm,
|
|
18
19
|
UsageMeter,
|
|
20
|
+
buildSummaryLine,
|
|
21
|
+
configToForm,
|
|
19
22
|
createDefaultAutoRechargeForm,
|
|
20
23
|
createTransportCacheKey,
|
|
21
24
|
estimateCredits,
|
|
25
|
+
formatAmountWithUnit,
|
|
22
26
|
formatContinueLabel,
|
|
23
27
|
formatCycleSuffix,
|
|
24
28
|
formatPaygRate,
|
|
@@ -39,6 +43,7 @@ import {
|
|
|
39
43
|
seedUsageSnapshot,
|
|
40
44
|
useActivation,
|
|
41
45
|
useAmountPicker,
|
|
46
|
+
useAutoRecharge,
|
|
42
47
|
useBalance,
|
|
43
48
|
useCheckoutFlow,
|
|
44
49
|
useCopy,
|
|
@@ -57,7 +62,7 @@ import {
|
|
|
57
62
|
useTransport,
|
|
58
63
|
useUsage,
|
|
59
64
|
validateAutoRechargeForm
|
|
60
|
-
} from "../chunk-
|
|
65
|
+
} from "../chunk-GPP4MY3I.js";
|
|
61
66
|
import "../chunk-UMXOAUW7.js";
|
|
62
67
|
import "../chunk-MLKGABMK.js";
|
|
63
68
|
|
|
@@ -128,54 +133,19 @@ import { MCP_TOOL_NAMES as MCP_TOOL_NAMES3 } from "@solvapay/mcp-core";
|
|
|
128
133
|
// src/mcp/useStripeProbe.ts
|
|
129
134
|
import { useEffect, useState } from "react";
|
|
130
135
|
import { loadStripe } from "@stripe/stripe-js";
|
|
131
|
-
var STRIPE_LOAD_TIMEOUT_MS =
|
|
132
|
-
var ELEMENT_MOUNT_TIMEOUT_MS =
|
|
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
|
-
}
|
|
136
|
+
var STRIPE_LOAD_TIMEOUT_MS = 3e3;
|
|
137
|
+
var ELEMENT_MOUNT_TIMEOUT_MS = 2e3;
|
|
157
138
|
function useStripeProbe(publishableKey) {
|
|
158
|
-
const [state, setState] = useState(
|
|
139
|
+
const [state, setState] = useState(
|
|
140
|
+
publishableKey ? "loading" : "blocked"
|
|
141
|
+
);
|
|
159
142
|
useEffect(() => {
|
|
160
143
|
if (typeof document === "undefined") return;
|
|
161
144
|
if (!publishableKey) {
|
|
162
|
-
console.warn("[solvapay-mcp] stripe probe blocked", {
|
|
163
|
-
reason: "no-publishable-key",
|
|
164
|
-
elapsedMs: 0,
|
|
165
|
-
loadMs: null
|
|
166
|
-
});
|
|
167
145
|
setState("blocked");
|
|
168
146
|
return;
|
|
169
147
|
}
|
|
170
|
-
const cached = stripeProbeCache.get(publishableKey);
|
|
171
|
-
if (cached) {
|
|
172
|
-
setState(cached);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
148
|
setState("loading");
|
|
176
|
-
const startedAt = Date.now();
|
|
177
|
-
let loadResolvedAt = null;
|
|
178
|
-
let mountStartedAt = null;
|
|
179
149
|
let cancelled = false;
|
|
180
150
|
let resolved = false;
|
|
181
151
|
let cspBlockedStripeFrame = false;
|
|
@@ -213,7 +183,7 @@ function useStripeProbe(publishableKey) {
|
|
|
213
183
|
sourceFile: event.sourceFile
|
|
214
184
|
}
|
|
215
185
|
);
|
|
216
|
-
resolve("blocked"
|
|
186
|
+
resolve("blocked");
|
|
217
187
|
};
|
|
218
188
|
document.addEventListener("securitypolicyviolation", onCspViolation);
|
|
219
189
|
const teardown = () => {
|
|
@@ -231,46 +201,24 @@ function useStripeProbe(publishableKey) {
|
|
|
231
201
|
host = null;
|
|
232
202
|
}
|
|
233
203
|
};
|
|
234
|
-
const
|
|
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) => {
|
|
204
|
+
const resolve = (next) => {
|
|
250
205
|
if (cancelled || resolved) return;
|
|
251
206
|
resolved = true;
|
|
252
|
-
if (next === "ready") {
|
|
253
|
-
logReady();
|
|
254
|
-
} else if (reason) {
|
|
255
|
-
logBlocked(reason);
|
|
256
|
-
}
|
|
257
|
-
cacheProbeVerdict(publishableKey, next, reason);
|
|
258
207
|
teardown();
|
|
259
208
|
setState(next);
|
|
260
209
|
};
|
|
261
210
|
loadTimeoutId = setTimeout(() => {
|
|
262
211
|
loadTimeoutId = null;
|
|
263
|
-
resolve("blocked"
|
|
212
|
+
resolve("blocked");
|
|
264
213
|
}, STRIPE_LOAD_TIMEOUT_MS);
|
|
265
214
|
loadStripe(publishableKey, { developerTools: { assistant: { enabled: false } } }).then((stripe) => {
|
|
266
|
-
loadResolvedAt = Date.now();
|
|
267
215
|
if (cancelled || resolved) return;
|
|
268
216
|
if (loadTimeoutId !== null) {
|
|
269
217
|
clearTimeout(loadTimeoutId);
|
|
270
218
|
loadTimeoutId = null;
|
|
271
219
|
}
|
|
272
220
|
if (!stripe) {
|
|
273
|
-
resolve("blocked"
|
|
221
|
+
resolve("blocked");
|
|
274
222
|
return;
|
|
275
223
|
}
|
|
276
224
|
try {
|
|
@@ -285,24 +233,22 @@ function useStripeProbe(publishableKey) {
|
|
|
285
233
|
if (cspBlockedStripeFrame) return;
|
|
286
234
|
resolve("ready");
|
|
287
235
|
});
|
|
288
|
-
element.on("loaderror", () => resolve("blocked"
|
|
236
|
+
element.on("loaderror", () => resolve("blocked"));
|
|
289
237
|
elementTimeoutId = setTimeout(() => {
|
|
290
238
|
elementTimeoutId = null;
|
|
291
|
-
resolve("blocked"
|
|
239
|
+
resolve("blocked");
|
|
292
240
|
}, ELEMENT_MOUNT_TIMEOUT_MS);
|
|
293
|
-
mountStartedAt = Date.now();
|
|
294
241
|
element.mount(host);
|
|
295
242
|
} catch {
|
|
296
|
-
resolve("blocked"
|
|
243
|
+
resolve("blocked");
|
|
297
244
|
}
|
|
298
245
|
}).catch(() => {
|
|
299
|
-
loadResolvedAt = Date.now();
|
|
300
246
|
if (cancelled || resolved) return;
|
|
301
247
|
if (loadTimeoutId !== null) {
|
|
302
248
|
clearTimeout(loadTimeoutId);
|
|
303
249
|
loadTimeoutId = null;
|
|
304
250
|
}
|
|
305
|
-
resolve("blocked"
|
|
251
|
+
resolve("blocked");
|
|
306
252
|
});
|
|
307
253
|
return () => {
|
|
308
254
|
cancelled = true;
|
|
@@ -570,8 +516,7 @@ function parseBootstrapFromToolResult(result, toolName, fallbackView) {
|
|
|
570
516
|
merchant: structured?.merchant ?? {},
|
|
571
517
|
product: structured?.product ?? { reference: ref },
|
|
572
518
|
plans: Array.isArray(structured?.plans) ? structured.plans : [],
|
|
573
|
-
customer: structured?.customer ?? null
|
|
574
|
-
...typeof structured?.autoRechargeUrl === "string" ? { autoRechargeUrl: structured.autoRechargeUrl } : {}
|
|
519
|
+
customer: structured?.customer ?? null
|
|
575
520
|
};
|
|
576
521
|
}
|
|
577
522
|
function waitForInitialToolResult(app, options = {}) {
|
|
@@ -703,11 +648,11 @@ function seedMcpCaches(initial, config) {
|
|
|
703
648
|
}
|
|
704
649
|
|
|
705
650
|
// src/mcp/McpApp.tsx
|
|
706
|
-
import { useEffect as useEffect7, useMemo as useMemo5, useRef as
|
|
651
|
+
import { useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState11 } from "react";
|
|
707
652
|
import { VIEW_FOR_TOOL as VIEW_FOR_TOOL2 } from "@solvapay/mcp-core";
|
|
708
653
|
|
|
709
654
|
// src/mcp/McpAppShell.tsx
|
|
710
|
-
import { useCallback as useCallback5, useState as
|
|
655
|
+
import { useCallback as useCallback5, useState as useState9 } from "react";
|
|
711
656
|
|
|
712
657
|
// src/mcp/account-state.ts
|
|
713
658
|
import {
|
|
@@ -2024,8 +1969,7 @@ function CreditAccountPanel({
|
|
|
2024
1969
|
locale,
|
|
2025
1970
|
classNames,
|
|
2026
1971
|
onTopup,
|
|
2027
|
-
|
|
2028
|
-
autoRechargeUrl,
|
|
1972
|
+
onAutoRecharge,
|
|
2029
1973
|
onChangePlan,
|
|
2030
1974
|
showPortalCta
|
|
2031
1975
|
}) {
|
|
@@ -2033,7 +1977,8 @@ function CreditAccountPanel({
|
|
|
2033
1977
|
const copy = useCopy();
|
|
2034
1978
|
const balance = useBalance();
|
|
2035
1979
|
const { merchant } = useMerchant();
|
|
2036
|
-
const
|
|
1980
|
+
const { config: autoRecharge } = useAutoRecharge();
|
|
1981
|
+
const { paymentMethod } = usePaymentMethod();
|
|
2037
1982
|
const { displayMode } = useDisplayMode();
|
|
2038
1983
|
const isFullscreen = displayMode === "fullscreen";
|
|
2039
1984
|
const history = useHistory({
|
|
@@ -2051,13 +1996,10 @@ function CreditAccountPanel({
|
|
|
2051
1996
|
paidPlanCount
|
|
2052
1997
|
});
|
|
2053
1998
|
const showChangePlan = Boolean(onChangePlan && (actions.changePlan || actions.upgrade));
|
|
2054
|
-
const
|
|
2055
|
-
const
|
|
2056
|
-
const
|
|
2057
|
-
const
|
|
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;
|
|
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;
|
|
2061
2003
|
return /* @__PURE__ */ jsxs5("div", { className: "solvapay-mcp-account", children: [
|
|
2062
2004
|
/* @__PURE__ */ jsxs5("div", { className: cx2.card, children: [
|
|
2063
2005
|
/* @__PURE__ */ jsx8(
|
|
@@ -2086,24 +2028,10 @@ function CreditAccountPanel({
|
|
|
2086
2028
|
onTopup ? /* @__PURE__ */ jsx8("button", { type: "button", className: cx2.button, onClick: onTopup, children: copy.account.addFunds }) : null,
|
|
2087
2029
|
/* @__PURE__ */ jsxs5(SplitRow, { children: [
|
|
2088
2030
|
/* @__PURE__ */ jsxs5("div", { className: "solvapay-mcp-auto-recharge-copy", children: [
|
|
2089
|
-
/* @__PURE__ */ jsx8("p", { children:
|
|
2090
|
-
|
|
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
|
|
2091
2033
|
] }),
|
|
2092
|
-
|
|
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
|
|
2034
|
+
autoRechargeAction ? /* @__PURE__ */ jsx8("button", { type: "button", className: cx2.linkButton, onClick: autoRechargeAction, children: autoRechargeActionLabel }) : null
|
|
2107
2035
|
] }),
|
|
2108
2036
|
showPortalCta && !isFullscreen ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2109
2037
|
/* @__PURE__ */ jsx8("p", { className: cx2.muted, "data-solvapay-mcp-portal-hint": "", children: copy.currentPlan.portalHint }),
|
|
@@ -2693,8 +2621,7 @@ function McpAccountView({
|
|
|
2693
2621
|
productRef,
|
|
2694
2622
|
classNames,
|
|
2695
2623
|
onTopup,
|
|
2696
|
-
|
|
2697
|
-
autoRechargeUrl,
|
|
2624
|
+
onAutoRecharge,
|
|
2698
2625
|
onChangePlan,
|
|
2699
2626
|
plans
|
|
2700
2627
|
}) {
|
|
@@ -2738,8 +2665,7 @@ function McpAccountView({
|
|
|
2738
2665
|
locale,
|
|
2739
2666
|
classNames,
|
|
2740
2667
|
onTopup,
|
|
2741
|
-
|
|
2742
|
-
autoRechargeUrl,
|
|
2668
|
+
onAutoRecharge,
|
|
2743
2669
|
onChangePlan,
|
|
2744
2670
|
showPortalCta
|
|
2745
2671
|
}
|
|
@@ -2798,11 +2724,8 @@ function McpAccountView({
|
|
|
2798
2724
|
);
|
|
2799
2725
|
}
|
|
2800
2726
|
|
|
2801
|
-
// src/mcp/views/
|
|
2802
|
-
import {
|
|
2803
|
-
|
|
2804
|
-
// src/mcp/views/checkout/steps/PlanStep.tsx
|
|
2805
|
-
import { memo } from "react";
|
|
2727
|
+
// src/mcp/views/McpAutoRechargeView.tsx
|
|
2728
|
+
import { useState as useState5 } from "react";
|
|
2806
2729
|
|
|
2807
2730
|
// src/mcp/views/BackLink.tsx
|
|
2808
2731
|
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -2822,8 +2745,256 @@ function BackLink({ label, glyph = "\u2190", className, onClick, ...rest }) {
|
|
|
2822
2745
|
);
|
|
2823
2746
|
}
|
|
2824
2747
|
|
|
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
|
+
|
|
2825
2996
|
// src/mcp/views/checkout/CheckoutPlanRow.tsx
|
|
2826
|
-
import { jsx as
|
|
2997
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
2827
2998
|
function CheckoutPlanRow({
|
|
2828
2999
|
plan,
|
|
2829
3000
|
locale,
|
|
@@ -2840,7 +3011,7 @@ function CheckoutPlanRow({
|
|
|
2840
3011
|
const state = resolvePlanRowState({ current, selected, free });
|
|
2841
3012
|
const priceLabel = formatPlanPriceLabel(plan, locale, selectedOption);
|
|
2842
3013
|
const description = descriptionOverride ?? planWhatItGives(plan, locale, balance);
|
|
2843
|
-
return /* @__PURE__ */
|
|
3014
|
+
return /* @__PURE__ */ jsx16(
|
|
2844
3015
|
PlanRow,
|
|
2845
3016
|
{
|
|
2846
3017
|
name: plan.name ?? plan.reference,
|
|
@@ -2880,7 +3051,7 @@ function planWhatItGives(plan, locale, balance) {
|
|
|
2880
3051
|
}
|
|
2881
3052
|
|
|
2882
3053
|
// src/mcp/views/checkout/steps/PlanStep.tsx
|
|
2883
|
-
import { Fragment as Fragment5, jsx as
|
|
3054
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2884
3055
|
var PlanStep = memo(function PlanStep2({
|
|
2885
3056
|
fromPaywall,
|
|
2886
3057
|
paywallKind,
|
|
@@ -2900,14 +3071,14 @@ var PlanStep = memo(function PlanStep2({
|
|
|
2900
3071
|
const pricingOption = selectedPlan ? getSelectedOption(selectedPlan) : void 0;
|
|
2901
3072
|
const ctaLabel = formatContinueLabel(selectedPlanShape, locale, pricingOption);
|
|
2902
3073
|
const showPreface = fromPaywall && !hideUpgradeBanner && paywallKind !== "payment_required";
|
|
2903
|
-
return /* @__PURE__ */
|
|
2904
|
-
onBack ? /* @__PURE__ */
|
|
2905
|
-
showPreface ? /* @__PURE__ */
|
|
2906
|
-
/* @__PURE__ */
|
|
2907
|
-
/* @__PURE__ */
|
|
2908
|
-
/* @__PURE__ */
|
|
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" })
|
|
2909
3080
|
] }),
|
|
2910
|
-
/* @__PURE__ */
|
|
3081
|
+
/* @__PURE__ */ jsx17("div", { className: "solvapay-mcp-plan-list", children: plans.map((plan) => /* @__PURE__ */ jsx17(
|
|
2911
3082
|
CheckoutPlanRow,
|
|
2912
3083
|
{
|
|
2913
3084
|
plan,
|
|
@@ -2921,10 +3092,10 @@ var PlanStep = memo(function PlanStep2({
|
|
|
2921
3092
|
},
|
|
2922
3093
|
plan.reference
|
|
2923
3094
|
)) }),
|
|
2924
|
-
/* @__PURE__ */
|
|
2925
|
-
/* @__PURE__ */
|
|
2926
|
-
activationError ? /* @__PURE__ */
|
|
2927
|
-
/* @__PURE__ */
|
|
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(
|
|
2928
3099
|
"button",
|
|
2929
3100
|
{
|
|
2930
3101
|
type: "button",
|
|
@@ -2935,7 +3106,7 @@ var PlanStep = memo(function PlanStep2({
|
|
|
2935
3106
|
children: ctaLabel
|
|
2936
3107
|
}
|
|
2937
3108
|
),
|
|
2938
|
-
onStayOnFree ? /* @__PURE__ */
|
|
3109
|
+
onStayOnFree ? /* @__PURE__ */ jsx17(
|
|
2939
3110
|
"button",
|
|
2940
3111
|
{
|
|
2941
3112
|
type: "button",
|
|
@@ -2949,143 +3120,7 @@ var PlanStep = memo(function PlanStep2({
|
|
|
2949
3120
|
});
|
|
2950
3121
|
|
|
2951
3122
|
// src/mcp/views/checkout/steps/AmountStep.tsx
|
|
2952
|
-
import { memo as memo2,
|
|
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
|
|
3123
|
+
import { memo as memo2, useState as useState6 } from "react";
|
|
3089
3124
|
import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3090
3125
|
var AmountStep = memo2(function AmountStep2({
|
|
3091
3126
|
topupCurrency,
|
|
@@ -3097,8 +3132,6 @@ var AmountStep = memo2(function AmountStep2({
|
|
|
3097
3132
|
}) {
|
|
3098
3133
|
const currency = (topupCurrency ?? "USD").toUpperCase();
|
|
3099
3134
|
const locale = useHostLocale();
|
|
3100
|
-
const { creditsPerMinorUnit, displayExchangeRate } = useBalance();
|
|
3101
|
-
const autoRechargeRef = useRef3(null);
|
|
3102
3135
|
const [stagedAmountMinor, setStagedAmountMinor] = useState6(null);
|
|
3103
3136
|
const currencies = topupCurrencies ?? [];
|
|
3104
3137
|
const showCurrencySwitch = currencies.length > 1 && !!onCurrencyChange;
|
|
@@ -3129,27 +3162,11 @@ var AmountStep = memo2(function AmountStep2({
|
|
|
3129
3162
|
children: [
|
|
3130
3163
|
/* @__PURE__ */ jsx18(PresetAmountRow, { cx: cx2, currencyDisplay }),
|
|
3131
3164
|
/* @__PURE__ */ jsx18(CustomAmountRow, { rowClassName: cx2.amountCustom, currencyDisplay }),
|
|
3132
|
-
/* @__PURE__ */ jsx18(
|
|
3133
|
-
McpInlineAutoRecharge,
|
|
3134
|
-
{
|
|
3135
|
-
ref: autoRechargeRef,
|
|
3136
|
-
currency,
|
|
3137
|
-
creditsPerMinorUnit,
|
|
3138
|
-
displayExchangeRate
|
|
3139
|
-
}
|
|
3140
|
-
),
|
|
3141
3165
|
/* @__PURE__ */ jsx18(
|
|
3142
3166
|
AmountPicker.Confirm,
|
|
3143
3167
|
{
|
|
3144
3168
|
className: cx2.button,
|
|
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
|
-
},
|
|
3169
|
+
onConfirm: (amountMinor) => onContinue(amountMinor),
|
|
3153
3170
|
children: stagedAmountMinor ? `Continue \u2014 ${formatPrice(stagedAmountMinor, currency, { locale, currencyDisplay })}` : "Continue"
|
|
3154
3171
|
}
|
|
3155
3172
|
)
|
|
@@ -3281,7 +3298,6 @@ var PaygPaymentStep = memo3(function PaygPaymentStep2({
|
|
|
3281
3298
|
plan: _plan,
|
|
3282
3299
|
amountMinor,
|
|
3283
3300
|
topupCurrency,
|
|
3284
|
-
autoRecharge,
|
|
3285
3301
|
returnUrl,
|
|
3286
3302
|
onBack,
|
|
3287
3303
|
onSuccess,
|
|
@@ -3298,7 +3314,6 @@ var PaygPaymentStep = memo3(function PaygPaymentStep2({
|
|
|
3298
3314
|
{
|
|
3299
3315
|
amount: amountMinor,
|
|
3300
3316
|
currency,
|
|
3301
|
-
autoRecharge,
|
|
3302
3317
|
returnUrl,
|
|
3303
3318
|
onSuccess: (_intent, extras) => onSuccess(extras),
|
|
3304
3319
|
children: /* @__PURE__ */ jsxs15(McpHostedLayout, { children: [
|
|
@@ -3504,14 +3519,271 @@ var SuccessStep = memo5(function SuccessStep2({ meta, cx: cx2 }) {
|
|
|
3504
3519
|
] });
|
|
3505
3520
|
});
|
|
3506
3521
|
|
|
3507
|
-
// src/mcp/views/checkout/
|
|
3508
|
-
import
|
|
3509
|
-
|
|
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";
|
|
3510
3736
|
var POLL_INTERVAL_MS = 3e3;
|
|
3511
3737
|
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
|
+
}
|
|
3512
3784
|
function useHostedUrl(enabled, fetcher, label) {
|
|
3513
3785
|
const [state, setState] = useState7({ status: "idle" });
|
|
3514
|
-
|
|
3786
|
+
useEffect6(() => {
|
|
3515
3787
|
if (!enabled) {
|
|
3516
3788
|
setState({ status: "idle" });
|
|
3517
3789
|
return;
|
|
@@ -3532,7 +3804,7 @@ function useHostedUrl(enabled, fetcher, label) {
|
|
|
3532
3804
|
}, [enabled, fetcher, label]);
|
|
3533
3805
|
return state;
|
|
3534
3806
|
}
|
|
3535
|
-
var HostedLinkButton =
|
|
3807
|
+
var HostedLinkButton = React11.memo(function HostedLinkButton2({
|
|
3536
3808
|
state,
|
|
3537
3809
|
loadingLabel,
|
|
3538
3810
|
readyLabel,
|
|
@@ -3541,7 +3813,7 @@ var HostedLinkButton = React10.memo(function HostedLinkButton2({
|
|
|
3541
3813
|
}) {
|
|
3542
3814
|
const handleExternalClick = useExternalLinkClick();
|
|
3543
3815
|
if (state.status === "ready") {
|
|
3544
|
-
return /* @__PURE__ */
|
|
3816
|
+
return /* @__PURE__ */ jsx26(
|
|
3545
3817
|
"a",
|
|
3546
3818
|
{
|
|
3547
3819
|
className: "solvapay-mcp-hosted-link",
|
|
@@ -3553,19 +3825,19 @@ var HostedLinkButton = React10.memo(function HostedLinkButton2({
|
|
|
3553
3825
|
onLaunch?.(state.href);
|
|
3554
3826
|
handleExternalClick(event);
|
|
3555
3827
|
},
|
|
3556
|
-
children: /* @__PURE__ */
|
|
3828
|
+
children: /* @__PURE__ */ jsxs19("button", { type: "button", className: cx2.button, children: [
|
|
3557
3829
|
readyLabel,
|
|
3558
|
-
/* @__PURE__ */
|
|
3830
|
+
/* @__PURE__ */ jsx26(ExternalLinkGlyph, {})
|
|
3559
3831
|
] })
|
|
3560
3832
|
}
|
|
3561
3833
|
);
|
|
3562
3834
|
}
|
|
3563
|
-
return /* @__PURE__ */
|
|
3835
|
+
return /* @__PURE__ */ jsx26("button", { type: "button", className: cx2.button, disabled: true, children: state.status === "error" ? "Unavailable" : loadingLabel });
|
|
3564
3836
|
});
|
|
3565
3837
|
function Spinner() {
|
|
3566
|
-
return /* @__PURE__ */
|
|
3838
|
+
return /* @__PURE__ */ jsx26("span", { className: "solvapay-mcp-spinner", "aria-hidden": "true" });
|
|
3567
3839
|
}
|
|
3568
|
-
var AwaitingBody =
|
|
3840
|
+
var AwaitingBody = React11.memo(function AwaitingBody2({
|
|
3569
3841
|
href,
|
|
3570
3842
|
timedOut,
|
|
3571
3843
|
onReopen,
|
|
@@ -3573,13 +3845,13 @@ var AwaitingBody = React10.memo(function AwaitingBody2({
|
|
|
3573
3845
|
cx: cx2
|
|
3574
3846
|
}) {
|
|
3575
3847
|
const handleExternalClick = useExternalLinkClick();
|
|
3576
|
-
return /* @__PURE__ */
|
|
3577
|
-
/* @__PURE__ */
|
|
3578
|
-
/* @__PURE__ */
|
|
3579
|
-
/* @__PURE__ */
|
|
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" })
|
|
3580
3852
|
] }),
|
|
3581
|
-
/* @__PURE__ */
|
|
3582
|
-
/* @__PURE__ */
|
|
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(
|
|
3583
3855
|
"a",
|
|
3584
3856
|
{
|
|
3585
3857
|
className: "solvapay-mcp-hosted-link",
|
|
@@ -3591,16 +3863,16 @@ var AwaitingBody = React10.memo(function AwaitingBody2({
|
|
|
3591
3863
|
onReopen();
|
|
3592
3864
|
handleExternalClick(event);
|
|
3593
3865
|
},
|
|
3594
|
-
children: /* @__PURE__ */
|
|
3866
|
+
children: /* @__PURE__ */ jsxs19("button", { type: "button", className: cx2.button, children: [
|
|
3595
3867
|
"Reopen checkout",
|
|
3596
|
-
/* @__PURE__ */
|
|
3868
|
+
/* @__PURE__ */ jsx26(ExternalLinkGlyph, {})
|
|
3597
3869
|
] })
|
|
3598
3870
|
}
|
|
3599
3871
|
),
|
|
3600
|
-
/* @__PURE__ */
|
|
3872
|
+
/* @__PURE__ */ jsx26("button", { type: "button", className: cx2.linkButton, onClick: onCancel, children: "Didn't complete? Cancel" })
|
|
3601
3873
|
] });
|
|
3602
3874
|
});
|
|
3603
|
-
var CancelledBody =
|
|
3875
|
+
var CancelledBody = React11.memo(function CancelledBody2({
|
|
3604
3876
|
productName,
|
|
3605
3877
|
endDate,
|
|
3606
3878
|
daysLeft,
|
|
@@ -3609,25 +3881,25 @@ var CancelledBody = React10.memo(function CancelledBody2({
|
|
|
3609
3881
|
onLaunch,
|
|
3610
3882
|
cx: cx2
|
|
3611
3883
|
}) {
|
|
3612
|
-
return /* @__PURE__ */
|
|
3613
|
-
/* @__PURE__ */
|
|
3884
|
+
return /* @__PURE__ */ jsxs19(Fragment11, { children: [
|
|
3885
|
+
/* @__PURE__ */ jsxs19("h2", { className: cx2.heading, children: [
|
|
3614
3886
|
"Your ",
|
|
3615
3887
|
productName,
|
|
3616
3888
|
" purchase is cancelled"
|
|
3617
3889
|
] }),
|
|
3618
|
-
endDate && formattedEndDate ? /* @__PURE__ */
|
|
3619
|
-
/* @__PURE__ */
|
|
3890
|
+
endDate && formattedEndDate ? /* @__PURE__ */ jsxs19("div", { className: cx2.notice, children: [
|
|
3891
|
+
/* @__PURE__ */ jsx26("p", { children: /* @__PURE__ */ jsxs19("strong", { children: [
|
|
3620
3892
|
"Access expires ",
|
|
3621
3893
|
formattedEndDate
|
|
3622
3894
|
] }) }),
|
|
3623
|
-
daysLeft !== null && daysLeft > 0 && /* @__PURE__ */
|
|
3895
|
+
daysLeft !== null && daysLeft > 0 && /* @__PURE__ */ jsxs19("p", { className: cx2.muted, children: [
|
|
3624
3896
|
daysLeft,
|
|
3625
3897
|
" ",
|
|
3626
3898
|
daysLeft === 1 ? "day" : "days",
|
|
3627
3899
|
" remaining"
|
|
3628
3900
|
] })
|
|
3629
|
-
] }) : /* @__PURE__ */
|
|
3630
|
-
/* @__PURE__ */
|
|
3901
|
+
] }) : /* @__PURE__ */ jsx26("p", { className: cx2.muted, children: "Your purchase access has ended." }),
|
|
3902
|
+
/* @__PURE__ */ jsx26(
|
|
3631
3903
|
HostedLinkButton,
|
|
3632
3904
|
{
|
|
3633
3905
|
state: checkout,
|
|
@@ -3637,19 +3909,14 @@ var CancelledBody = React10.memo(function CancelledBody2({
|
|
|
3637
3909
|
cx: cx2
|
|
3638
3910
|
}
|
|
3639
3911
|
),
|
|
3640
|
-
checkout.status === "error" && /* @__PURE__ */
|
|
3912
|
+
checkout.status === "error" && /* @__PURE__ */ jsx26("p", { className: cx2.error, role: "alert", children: checkout.message })
|
|
3641
3913
|
] });
|
|
3642
3914
|
});
|
|
3643
|
-
var UpgradeBody =
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
}) {
|
|
3649
|
-
return /* @__PURE__ */ jsxs18(Fragment11, { children: [
|
|
3650
|
-
/* @__PURE__ */ jsx25("h2", { className: cx2.heading, children: planName ? `Complete your ${planName} purchase` : "Upgrade your plan" }),
|
|
3651
|
-
/* @__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." }),
|
|
3652
|
-
/* @__PURE__ */ jsx25(
|
|
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(
|
|
3653
3920
|
HostedLinkButton,
|
|
3654
3921
|
{
|
|
3655
3922
|
state: checkout,
|
|
@@ -3659,13 +3926,11 @@ var UpgradeBody = React10.memo(function UpgradeBody2({
|
|
|
3659
3926
|
cx: cx2
|
|
3660
3927
|
}
|
|
3661
3928
|
),
|
|
3662
|
-
checkout.status === "error" && /* @__PURE__ */
|
|
3929
|
+
checkout.status === "error" && /* @__PURE__ */ jsx26("p", { className: cx2.error, role: "alert", children: checkout.message })
|
|
3663
3930
|
] });
|
|
3664
3931
|
});
|
|
3665
3932
|
function HostedCheckout({
|
|
3666
3933
|
productRef,
|
|
3667
|
-
planRef,
|
|
3668
|
-
planName,
|
|
3669
3934
|
onPurchaseSuccess,
|
|
3670
3935
|
cx: cx2,
|
|
3671
3936
|
children
|
|
@@ -3677,26 +3942,23 @@ function HostedCheckout({
|
|
|
3677
3942
|
const [awaitingTimedOut, setAwaitingTimedOut] = useState7(false);
|
|
3678
3943
|
const [hasLoadedOnce, setHasLoadedOnce] = useState7(false);
|
|
3679
3944
|
const onPurchaseSuccessRef = useRef4(onPurchaseSuccess);
|
|
3680
|
-
|
|
3945
|
+
useEffect6(() => {
|
|
3681
3946
|
onPurchaseSuccessRef.current = onPurchaseSuccess;
|
|
3682
3947
|
}, [onPurchaseSuccess]);
|
|
3683
|
-
|
|
3948
|
+
useEffect6(() => {
|
|
3684
3949
|
if (!loading && !hasLoadedOnce) setHasLoadedOnce(true);
|
|
3685
3950
|
}, [loading, hasLoadedOnce]);
|
|
3686
|
-
const fetchCheckoutUrl =
|
|
3687
|
-
const { checkoutUrl } = await transport.createCheckoutSession({
|
|
3688
|
-
productRef,
|
|
3689
|
-
...planRef ? { planRef } : {}
|
|
3690
|
-
});
|
|
3951
|
+
const fetchCheckoutUrl = useCallback4(async () => {
|
|
3952
|
+
const { checkoutUrl } = await transport.createCheckoutSession({ productRef });
|
|
3691
3953
|
return { href: checkoutUrl };
|
|
3692
|
-
}, [
|
|
3954
|
+
}, [productRef, transport]);
|
|
3693
3955
|
const checkout = useHostedUrl(hasLoadedOnce, fetchCheckoutUrl, "checkout session");
|
|
3694
|
-
const safeRefetch =
|
|
3956
|
+
const safeRefetch = useCallback4(() => {
|
|
3695
3957
|
refetch().catch((err) => {
|
|
3696
3958
|
console.warn("[solvapay-mcp] refetch failed", err);
|
|
3697
3959
|
});
|
|
3698
3960
|
}, [refetch]);
|
|
3699
|
-
|
|
3961
|
+
useEffect6(() => {
|
|
3700
3962
|
const onFocus = () => safeRefetch();
|
|
3701
3963
|
const onVisibility = () => {
|
|
3702
3964
|
if (document.visibilityState === "visible") safeRefetch();
|
|
@@ -3708,7 +3970,7 @@ function HostedCheckout({
|
|
|
3708
3970
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
3709
3971
|
};
|
|
3710
3972
|
}, [safeRefetch]);
|
|
3711
|
-
|
|
3973
|
+
useEffect6(() => {
|
|
3712
3974
|
if (!awaiting) return;
|
|
3713
3975
|
const interval = window.setInterval(() => {
|
|
3714
3976
|
if (document.visibilityState === "hidden") return;
|
|
@@ -3722,7 +3984,7 @@ function HostedCheckout({
|
|
|
3722
3984
|
window.clearTimeout(timeout);
|
|
3723
3985
|
};
|
|
3724
3986
|
}, [awaiting, safeRefetch]);
|
|
3725
|
-
|
|
3987
|
+
useEffect6(() => {
|
|
3726
3988
|
if (!awaiting) return;
|
|
3727
3989
|
if (!hasPaidPurchase) return;
|
|
3728
3990
|
const newRef = activePurchase?.reference ?? null;
|
|
@@ -3733,7 +3995,7 @@ function HostedCheckout({
|
|
|
3733
3995
|
onPurchaseSuccessRef.current?.();
|
|
3734
3996
|
}
|
|
3735
3997
|
}, [awaiting, hasPaidPurchase, activePurchase?.reference]);
|
|
3736
|
-
const beginAwaiting =
|
|
3998
|
+
const beginAwaiting = useCallback4(
|
|
3737
3999
|
(href) => {
|
|
3738
4000
|
setAwaiting({
|
|
3739
4001
|
baselineActiveRef: activePurchase?.reference ?? null,
|
|
@@ -3745,27 +4007,27 @@ function HostedCheckout({
|
|
|
3745
4007
|
},
|
|
3746
4008
|
[activePurchase?.reference, hasPaidPurchase]
|
|
3747
4009
|
);
|
|
3748
|
-
const cancelAwaiting =
|
|
4010
|
+
const cancelAwaiting = useCallback4(() => {
|
|
3749
4011
|
setAwaiting(null);
|
|
3750
4012
|
setAwaitingTimedOut(false);
|
|
3751
4013
|
}, []);
|
|
3752
|
-
const dismissTimeout =
|
|
4014
|
+
const dismissTimeout = useCallback4(() => {
|
|
3753
4015
|
setAwaitingTimedOut(false);
|
|
3754
4016
|
}, []);
|
|
3755
4017
|
const cancelledProductName = cancelledPurchase?.productName ?? null;
|
|
3756
4018
|
const cancelledEndDate = cancelledPurchase?.endDate;
|
|
3757
|
-
const cancelledDaysLeft =
|
|
4019
|
+
const cancelledDaysLeft = useMemo4(
|
|
3758
4020
|
() => cancelledEndDate ? getDaysUntilExpiration(cancelledEndDate) : null,
|
|
3759
4021
|
[cancelledEndDate, getDaysUntilExpiration]
|
|
3760
4022
|
);
|
|
3761
|
-
const cancelledFormattedEndDate =
|
|
4023
|
+
const cancelledFormattedEndDate = useMemo4(
|
|
3762
4024
|
() => cancelledEndDate ? formatDate(cancelledEndDate) : null,
|
|
3763
4025
|
[cancelledEndDate, formatDate]
|
|
3764
4026
|
);
|
|
3765
4027
|
const awaitingHref = awaiting?.href ?? null;
|
|
3766
|
-
const inner =
|
|
4028
|
+
const inner = useMemo4(() => {
|
|
3767
4029
|
if (awaiting && awaitingHref) {
|
|
3768
|
-
return /* @__PURE__ */
|
|
4030
|
+
return /* @__PURE__ */ jsx26(
|
|
3769
4031
|
AwaitingBody,
|
|
3770
4032
|
{
|
|
3771
4033
|
href: awaitingHref,
|
|
@@ -3777,7 +4039,7 @@ function HostedCheckout({
|
|
|
3777
4039
|
);
|
|
3778
4040
|
}
|
|
3779
4041
|
if (shouldShowCancelledNotice && cancelledProductName) {
|
|
3780
|
-
return /* @__PURE__ */
|
|
4042
|
+
return /* @__PURE__ */ jsx26(
|
|
3781
4043
|
CancelledBody,
|
|
3782
4044
|
{
|
|
3783
4045
|
productName: cancelledProductName,
|
|
@@ -3790,7 +4052,7 @@ function HostedCheckout({
|
|
|
3790
4052
|
}
|
|
3791
4053
|
);
|
|
3792
4054
|
}
|
|
3793
|
-
return /* @__PURE__ */
|
|
4055
|
+
return /* @__PURE__ */ jsx26(UpgradeBody, { checkout, onLaunch: beginAwaiting, cx: cx2 });
|
|
3794
4056
|
}, [
|
|
3795
4057
|
awaiting,
|
|
3796
4058
|
awaitingHref,
|
|
@@ -3804,297 +4066,19 @@ function HostedCheckout({
|
|
|
3804
4066
|
cancelledFormattedEndDate,
|
|
3805
4067
|
checkout,
|
|
3806
4068
|
beginAwaiting,
|
|
3807
|
-
planName,
|
|
3808
4069
|
cx2
|
|
3809
4070
|
]);
|
|
3810
4071
|
if (loading) {
|
|
3811
|
-
return /* @__PURE__ */
|
|
3812
|
-
}
|
|
3813
|
-
return /* @__PURE__ */ jsxs18("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
|
|
3814
|
-
inner,
|
|
3815
|
-
children
|
|
3816
|
-
] });
|
|
3817
|
-
}
|
|
3818
|
-
|
|
3819
|
-
// src/mcp/views/checkout/EmbeddedCheckout.tsx
|
|
3820
|
-
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3821
|
-
function EmbeddedCheckout({
|
|
3822
|
-
productRef,
|
|
3823
|
-
returnUrl,
|
|
3824
|
-
onPurchaseSuccess,
|
|
3825
|
-
fromPaywall,
|
|
3826
|
-
paywallKind,
|
|
3827
|
-
hideUpgradeBanner,
|
|
3828
|
-
plans,
|
|
3829
|
-
onClose,
|
|
3830
|
-
onBack,
|
|
3831
|
-
initialPlanRef,
|
|
3832
|
-
autoAdvance,
|
|
3833
|
-
stripeProbe,
|
|
3834
|
-
cx: cx2,
|
|
3835
|
-
children
|
|
3836
|
-
}) {
|
|
3837
|
-
const { loading, isRefetching, activePurchase } = usePurchase();
|
|
3838
|
-
const currentPlanRef = activePurchase?.planSnapshot?.reference ?? null;
|
|
3839
|
-
const paidPlans = useMemo4(() => {
|
|
3840
|
-
const list = plans ?? [];
|
|
3841
|
-
return list.filter((p) => p.requiresPayment !== false);
|
|
3842
|
-
}, [plans]);
|
|
3843
|
-
const paygPlanRef = useMemo4(() => {
|
|
3844
|
-
const payg = paidPlans.find((p) => isPayg(p));
|
|
3845
|
-
return payg?.reference ?? void 0;
|
|
3846
|
-
}, [paidPlans]);
|
|
3847
|
-
const planFilter = useMemo4(
|
|
3848
|
-
() => (plan) => plan.requiresPayment !== false || plan.reference === currentPlanRef,
|
|
3849
|
-
[currentPlanRef]
|
|
3850
|
-
);
|
|
3851
|
-
if (loading) {
|
|
3852
|
-
return /* @__PURE__ */ jsx26("div", { className: cx2.card, children: /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" }) });
|
|
4072
|
+
return /* @__PURE__ */ jsx26("div", { className: cx2.card, children: /* @__PURE__ */ jsx26("p", { children: "Loading purchase\u2026" }) });
|
|
3853
4073
|
}
|
|
3854
4074
|
return /* @__PURE__ */ jsxs19("div", { className: cx2.card, "data-refreshing": isRefetching ? "true" : void 0, children: [
|
|
3855
|
-
|
|
3856
|
-
PlanSelector.Root,
|
|
3857
|
-
{
|
|
3858
|
-
productRef,
|
|
3859
|
-
filter: planFilter,
|
|
3860
|
-
sortBy: planSortByPaygFirstThenAsc,
|
|
3861
|
-
popularPlanRef: paygPlanRef,
|
|
3862
|
-
currentPlanRef,
|
|
3863
|
-
autoSelectFirstPaid: Boolean(paygPlanRef),
|
|
3864
|
-
initialPlanRef,
|
|
3865
|
-
className: "solvapay-plan-selector",
|
|
3866
|
-
children: /* @__PURE__ */ jsx26(
|
|
3867
|
-
McpCheckoutBody,
|
|
3868
|
-
{
|
|
3869
|
-
productRef,
|
|
3870
|
-
returnUrl,
|
|
3871
|
-
onPurchaseSuccess,
|
|
3872
|
-
fromPaywall,
|
|
3873
|
-
paywallKind,
|
|
3874
|
-
hideUpgradeBanner,
|
|
3875
|
-
onClose,
|
|
3876
|
-
onBack,
|
|
3877
|
-
initialPlanRef,
|
|
3878
|
-
autoAdvance,
|
|
3879
|
-
stripeProbe,
|
|
3880
|
-
cx: cx2
|
|
3881
|
-
}
|
|
3882
|
-
)
|
|
3883
|
-
}
|
|
3884
|
-
),
|
|
4075
|
+
inner,
|
|
3885
4076
|
children
|
|
3886
4077
|
] });
|
|
3887
4078
|
}
|
|
3888
|
-
function McpCheckoutBody({
|
|
3889
|
-
productRef,
|
|
3890
|
-
returnUrl,
|
|
3891
|
-
onPurchaseSuccess,
|
|
3892
|
-
fromPaywall,
|
|
3893
|
-
paywallKind,
|
|
3894
|
-
hideUpgradeBanner,
|
|
3895
|
-
onClose,
|
|
3896
|
-
onBack,
|
|
3897
|
-
initialPlanRef,
|
|
3898
|
-
autoAdvance,
|
|
3899
|
-
stripeProbe,
|
|
3900
|
-
cx: cx2
|
|
3901
|
-
}) {
|
|
3902
|
-
const bridge = useMcpBridge();
|
|
3903
|
-
const locale = useHostLocale();
|
|
3904
|
-
const flow = useCheckoutFlow({
|
|
3905
|
-
productRef,
|
|
3906
|
-
// `notifyModelContext` for plan commit fires from the explicit
|
|
3907
|
-
// Continue handler below — not on `selectPlan` — so a stray
|
|
3908
|
-
// selection doesn't burn a host emit before the user opts in.
|
|
3909
|
-
onPurchaseSuccess: (meta) => {
|
|
3910
|
-
if (meta.branch === "payg" && meta.amountMinor != null && meta.currency != null) {
|
|
3911
|
-
void bridge.notifyModelContext({
|
|
3912
|
-
text: `Activated ${meta.plan.name ?? "plan"} with ${formatPrice(
|
|
3913
|
-
meta.amountMinor,
|
|
3914
|
-
meta.currency,
|
|
3915
|
-
{ locale }
|
|
3916
|
-
)} in credits.`
|
|
3917
|
-
});
|
|
3918
|
-
void bridge.notifySuccess({
|
|
3919
|
-
kind: "topup",
|
|
3920
|
-
amountMinor: meta.amountMinor,
|
|
3921
|
-
currency: meta.currency
|
|
3922
|
-
});
|
|
3923
|
-
} else {
|
|
3924
|
-
void bridge.notifyModelContext({
|
|
3925
|
-
text: `Activated ${meta.plan.name ?? "plan"}.`
|
|
3926
|
-
});
|
|
3927
|
-
void bridge.notifySuccess({
|
|
3928
|
-
kind: "plan-activated",
|
|
3929
|
-
planName: meta.plan.name ?? null
|
|
3930
|
-
});
|
|
3931
|
-
}
|
|
3932
|
-
onPurchaseSuccess?.();
|
|
3933
|
-
}
|
|
3934
|
-
});
|
|
3935
|
-
const onStayOnFree = useCallback4(() => {
|
|
3936
|
-
void bridge.sendMessage({ text: "Sticking with the free tier for now." });
|
|
3937
|
-
onClose?.();
|
|
3938
|
-
}, [bridge, onClose]);
|
|
3939
|
-
const selectedPlanShape = flow.selectedPlan;
|
|
3940
|
-
const [autoRecharge, setAutoRecharge] = useState8();
|
|
3941
|
-
const onPlanContinue = useCallback4(() => {
|
|
3942
|
-
if (selectedPlanShape) {
|
|
3943
|
-
void bridge.notifyModelContext({
|
|
3944
|
-
text: `User selected ${selectedPlanShape.name ?? "a plan"}.`
|
|
3945
|
-
});
|
|
3946
|
-
}
|
|
3947
|
-
void flow.advance();
|
|
3948
|
-
}, [bridge, flow, selectedPlanShape]);
|
|
3949
|
-
const autoAdvancedRef = useRef5(false);
|
|
3950
|
-
useEffect6(() => {
|
|
3951
|
-
if (!autoAdvance || autoAdvancedRef.current) return;
|
|
3952
|
-
if (flow.step !== "plan") return;
|
|
3953
|
-
if (flow.selectedPlanRef !== initialPlanRef) return;
|
|
3954
|
-
autoAdvancedRef.current = true;
|
|
3955
|
-
onPlanContinue();
|
|
3956
|
-
}, [autoAdvance, flow.selectedPlanRef, flow.step, initialPlanRef, onPlanContinue]);
|
|
3957
|
-
if (flow.step === "plan") {
|
|
3958
|
-
const waitingForSelection = Boolean(autoAdvance) && !flow.selectedPlanRef;
|
|
3959
|
-
const matchingPending = Boolean(autoAdvance) && flow.selectedPlanRef === initialPlanRef && flow.status === "activating";
|
|
3960
|
-
if (waitingForSelection || matchingPending) {
|
|
3961
|
-
return /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" });
|
|
3962
|
-
}
|
|
3963
|
-
return /* @__PURE__ */ jsx26(
|
|
3964
|
-
PlanStep,
|
|
3965
|
-
{
|
|
3966
|
-
fromPaywall,
|
|
3967
|
-
paywallKind,
|
|
3968
|
-
hideUpgradeBanner,
|
|
3969
|
-
onContinue: onPlanContinue,
|
|
3970
|
-
onStayOnFree: fromPaywall && onClose ? onStayOnFree : void 0,
|
|
3971
|
-
onBack,
|
|
3972
|
-
isActivating: flow.status === "activating",
|
|
3973
|
-
activationError: flow.error,
|
|
3974
|
-
cx: cx2
|
|
3975
|
-
}
|
|
3976
|
-
);
|
|
3977
|
-
}
|
|
3978
|
-
if (flow.step === "amount") {
|
|
3979
|
-
if (!selectedPlanShape) {
|
|
3980
|
-
return null;
|
|
3981
|
-
}
|
|
3982
|
-
return /* @__PURE__ */ jsx26(
|
|
3983
|
-
AmountStep,
|
|
3984
|
-
{
|
|
3985
|
-
plan: selectedPlanShape,
|
|
3986
|
-
topupCurrency: flow.topupCurrency,
|
|
3987
|
-
topupCurrencies: flow.topupCurrencies,
|
|
3988
|
-
onCurrencyChange: (code) => {
|
|
3989
|
-
setAutoRecharge(void 0);
|
|
3990
|
-
flow.setTopupCurrency(code);
|
|
3991
|
-
},
|
|
3992
|
-
onBack: () => flow.back(),
|
|
3993
|
-
onContinue: (amountMinor, nextAutoRecharge) => {
|
|
3994
|
-
setAutoRecharge(nextAutoRecharge);
|
|
3995
|
-
flow.selectAmount(amountMinor);
|
|
3996
|
-
void flow.advance();
|
|
3997
|
-
},
|
|
3998
|
-
cx: cx2
|
|
3999
|
-
}
|
|
4000
|
-
);
|
|
4001
|
-
}
|
|
4002
|
-
if (flow.step === "payment") {
|
|
4003
|
-
if (stripeProbe === "loading") {
|
|
4004
|
-
return /* @__PURE__ */ jsx26("p", { children: "Loading checkout\u2026" });
|
|
4005
|
-
}
|
|
4006
|
-
if (stripeProbe === "blocked") {
|
|
4007
|
-
return /* @__PURE__ */ jsx26(
|
|
4008
|
-
HostedCheckout,
|
|
4009
|
-
{
|
|
4010
|
-
productRef,
|
|
4011
|
-
planRef: flow.selectedPlanRef ?? void 0,
|
|
4012
|
-
planName: selectedPlanShape?.name ?? void 0,
|
|
4013
|
-
onPurchaseSuccess,
|
|
4014
|
-
cx: cx2
|
|
4015
|
-
}
|
|
4016
|
-
);
|
|
4017
|
-
}
|
|
4018
|
-
if (flow.branch === "payg" && selectedPlanShape && flow.selectedAmountMinor != null) {
|
|
4019
|
-
return /* @__PURE__ */ jsx26(
|
|
4020
|
-
PaygPaymentStep,
|
|
4021
|
-
{
|
|
4022
|
-
plan: selectedPlanShape,
|
|
4023
|
-
amountMinor: flow.selectedAmountMinor,
|
|
4024
|
-
topupCurrency: flow.topupCurrency,
|
|
4025
|
-
autoRecharge,
|
|
4026
|
-
returnUrl,
|
|
4027
|
-
onBack: () => flow.back(),
|
|
4028
|
-
onSuccess: (extras) => flow.notifyPaymentSuccess(void 0, extras),
|
|
4029
|
-
cx: cx2
|
|
4030
|
-
}
|
|
4031
|
-
);
|
|
4032
|
-
}
|
|
4033
|
-
if (flow.branch === "recurring" && selectedPlanShape && flow.selectedPlanRef) {
|
|
4034
|
-
return /* @__PURE__ */ jsx26(
|
|
4035
|
-
RecurringPaymentStep,
|
|
4036
|
-
{
|
|
4037
|
-
plan: selectedPlanShape,
|
|
4038
|
-
planRef: flow.selectedPlanRef,
|
|
4039
|
-
productRef,
|
|
4040
|
-
returnUrl,
|
|
4041
|
-
onBack: () => flow.back(),
|
|
4042
|
-
onSuccess: (intent) => flow.notifyPaymentSuccess(intent),
|
|
4043
|
-
cx: cx2
|
|
4044
|
-
}
|
|
4045
|
-
);
|
|
4046
|
-
}
|
|
4047
|
-
return null;
|
|
4048
|
-
}
|
|
4049
|
-
if (flow.step === "success" && flow.successMeta) {
|
|
4050
|
-
return /* @__PURE__ */ jsx26(SuccessStep, { meta: flow.successMeta, cx: cx2 });
|
|
4051
|
-
}
|
|
4052
|
-
return null;
|
|
4053
|
-
}
|
|
4054
|
-
|
|
4055
|
-
// src/mcp/views/McpCheckoutView.tsx
|
|
4056
|
-
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
4057
|
-
function McpCheckoutView({
|
|
4058
|
-
productRef,
|
|
4059
|
-
publishableKey = null,
|
|
4060
|
-
returnUrl,
|
|
4061
|
-
onPurchaseSuccess,
|
|
4062
|
-
onRequestTopup: _onRequestTopup,
|
|
4063
|
-
fromPaywall = false,
|
|
4064
|
-
paywallKind,
|
|
4065
|
-
plans,
|
|
4066
|
-
onClose,
|
|
4067
|
-
onBack,
|
|
4068
|
-
initialPlanRef,
|
|
4069
|
-
autoAdvance,
|
|
4070
|
-
classNames,
|
|
4071
|
-
children
|
|
4072
|
-
}) {
|
|
4073
|
-
const cx2 = resolveMcpClassNames(classNames);
|
|
4074
|
-
const probe = useStripeProbe(publishableKey);
|
|
4075
|
-
return /* @__PURE__ */ jsx27(
|
|
4076
|
-
EmbeddedCheckout,
|
|
4077
|
-
{
|
|
4078
|
-
productRef,
|
|
4079
|
-
returnUrl,
|
|
4080
|
-
onPurchaseSuccess,
|
|
4081
|
-
fromPaywall,
|
|
4082
|
-
paywallKind,
|
|
4083
|
-
plans,
|
|
4084
|
-
onClose,
|
|
4085
|
-
onBack,
|
|
4086
|
-
initialPlanRef,
|
|
4087
|
-
autoAdvance,
|
|
4088
|
-
stripeProbe: probe,
|
|
4089
|
-
cx: cx2,
|
|
4090
|
-
classNames,
|
|
4091
|
-
children
|
|
4092
|
-
}
|
|
4093
|
-
);
|
|
4094
|
-
}
|
|
4095
4079
|
|
|
4096
4080
|
// src/mcp/views/McpTopupView.tsx
|
|
4097
|
-
import {
|
|
4081
|
+
import { useState as useState8 } from "react";
|
|
4098
4082
|
|
|
4099
4083
|
// src/mcp/format-compact-credits.ts
|
|
4100
4084
|
function formatCompactCredits(credits, locale = "en-US") {
|
|
@@ -4111,7 +4095,7 @@ function formatCompactCredits(credits, locale = "en-US") {
|
|
|
4111
4095
|
}
|
|
4112
4096
|
|
|
4113
4097
|
// src/mcp/views/McpTopupView.tsx
|
|
4114
|
-
import { Fragment as Fragment12, jsx as
|
|
4098
|
+
import { Fragment as Fragment12, jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4115
4099
|
var FALLBACK_TOPUP_CURRENCY = "USD";
|
|
4116
4100
|
function resolveDefaultCurrency(merchant) {
|
|
4117
4101
|
if (merchant?.defaultCurrency) {
|
|
@@ -4137,15 +4121,18 @@ function McpTopupView({
|
|
|
4137
4121
|
const cx2 = resolveMcpClassNames(classNames);
|
|
4138
4122
|
const probe = useStripeProbe(publishableKey);
|
|
4139
4123
|
const { merchant, loading: merchantLoading } = useMerchant();
|
|
4140
|
-
if (merchantLoading) {
|
|
4141
|
-
return /* @__PURE__ */
|
|
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 });
|
|
4142
4129
|
}
|
|
4143
4130
|
const defaultCurrency = resolveDefaultCurrency(merchant ?? void 0);
|
|
4144
4131
|
const fromMerchant = (merchant?.supportedTopupCurrencies ?? []).map((code) => code.toUpperCase()).filter(Boolean);
|
|
4145
4132
|
const topupCurrencies = Array.from(
|
|
4146
4133
|
new Set(fromMerchant.length > 0 ? fromMerchant : [defaultCurrency])
|
|
4147
4134
|
);
|
|
4148
|
-
return /* @__PURE__ */
|
|
4135
|
+
return /* @__PURE__ */ jsx27(
|
|
4149
4136
|
EmbeddedTopup,
|
|
4150
4137
|
{
|
|
4151
4138
|
returnUrl,
|
|
@@ -4153,7 +4140,6 @@ function McpTopupView({
|
|
|
4153
4140
|
topupCurrencies,
|
|
4154
4141
|
onTopupSuccess,
|
|
4155
4142
|
onBack,
|
|
4156
|
-
stripeProbe: probe,
|
|
4157
4143
|
cx: cx2
|
|
4158
4144
|
}
|
|
4159
4145
|
);
|
|
@@ -4164,15 +4150,18 @@ function EmbeddedTopup({
|
|
|
4164
4150
|
topupCurrencies,
|
|
4165
4151
|
onTopupSuccess,
|
|
4166
4152
|
onBack,
|
|
4167
|
-
stripeProbe,
|
|
4168
4153
|
cx: cx2
|
|
4169
4154
|
}) {
|
|
4170
|
-
const [screen, setScreen] =
|
|
4171
|
-
const [selectedCurrency, setSelectedCurrency] =
|
|
4155
|
+
const [screen, setScreen] = useState8({ step: "amount" });
|
|
4156
|
+
const [selectedCurrency, setSelectedCurrency] = useState8(defaultCurrency);
|
|
4172
4157
|
const currency = selectedCurrency;
|
|
4173
4158
|
const showCurrencySwitch = topupCurrencies.length > 1;
|
|
4174
4159
|
const { adjustBalance, credits, creditsPerMinorUnit, displayCurrency, displayExchangeRate } = useBalance();
|
|
4175
|
-
const
|
|
4160
|
+
const copy = useCopy();
|
|
4161
|
+
const [autoRechargeForm, setAutoRechargeForm] = useState8(
|
|
4162
|
+
() => createDefaultAutoRechargeForm(currency)
|
|
4163
|
+
);
|
|
4164
|
+
const [autoRechargeError, setAutoRechargeError] = useState8(null);
|
|
4176
4165
|
const locale = useHostLocale();
|
|
4177
4166
|
const { notifyModelContext, notifySuccess } = useMcpBridge();
|
|
4178
4167
|
const topupSelector = useTopupAmountSelector({ currency });
|
|
@@ -4184,38 +4173,29 @@ function EmbeddedTopup({
|
|
|
4184
4173
|
topupSelector.reset();
|
|
4185
4174
|
};
|
|
4186
4175
|
if (screen.step === "success") {
|
|
4187
|
-
const
|
|
4188
|
-
screen.amountMinor,
|
|
4189
|
-
currency,
|
|
4190
|
-
displayCurrency,
|
|
4191
|
-
creditsPerMinorUnit,
|
|
4192
|
-
displayExchangeRate
|
|
4193
|
-
);
|
|
4176
|
+
const displayAmount = formatPrice(screen.amountMinor, currency, { locale, free: "" });
|
|
4194
4177
|
return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Top-up success", children: [
|
|
4195
|
-
/* @__PURE__ */
|
|
4196
|
-
/* @__PURE__ */
|
|
4197
|
-
|
|
4198
|
-
/* @__PURE__ */
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
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
|
+
)
|
|
4210
4196
|
] });
|
|
4211
4197
|
}
|
|
4212
4198
|
if (screen.step === "payment") {
|
|
4213
|
-
if (stripeProbe === "loading") {
|
|
4214
|
-
return /* @__PURE__ */ jsx28("section", { className: cx2.card, "aria-label": "Loading top-up", children: /* @__PURE__ */ jsx28("p", { children: "Loading top-up\u2026" }) });
|
|
4215
|
-
}
|
|
4216
|
-
if (stripeProbe === "blocked") {
|
|
4217
|
-
return /* @__PURE__ */ jsx28(HostedTopupFallback, { cx: cx2, onChangeAmount: () => setScreen({ step: "amount" }) });
|
|
4218
|
-
}
|
|
4219
4199
|
const committedAmountMinor = screen.amountMinor;
|
|
4220
4200
|
const creditEstimate = estimateTopupCredits(
|
|
4221
4201
|
committedAmountMinor,
|
|
@@ -4229,7 +4209,7 @@ function EmbeddedTopup({
|
|
|
4229
4209
|
creditEstimate.kind === "available" ? `Adds ${creditEstimate.credits.toLocaleString(locale)} credits` : void 0,
|
|
4230
4210
|
formattedBalance ? `Balance ${formattedBalance} credits` : void 0
|
|
4231
4211
|
].filter((part) => part != null);
|
|
4232
|
-
return /* @__PURE__ */
|
|
4212
|
+
return /* @__PURE__ */ jsx27("section", { className: cx2.card, "aria-label": "Top-up payment", children: /* @__PURE__ */ jsx27(
|
|
4233
4213
|
TopupForm.Root,
|
|
4234
4214
|
{
|
|
4235
4215
|
amount: committedAmountMinor,
|
|
@@ -4255,14 +4235,14 @@ function EmbeddedTopup({
|
|
|
4255
4235
|
onTopupSuccess?.(committedAmountMinor);
|
|
4256
4236
|
},
|
|
4257
4237
|
children: /* @__PURE__ */ jsxs20(McpHostedLayout, { children: [
|
|
4258
|
-
/* @__PURE__ */
|
|
4259
|
-
/* @__PURE__ */
|
|
4260
|
-
/* @__PURE__ */
|
|
4261
|
-
contextParts.length > 0 ? /* @__PURE__ */
|
|
4262
|
-
isFullscreen ? /* @__PURE__ */
|
|
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 })
|
|
4263
4243
|
] }) }),
|
|
4264
4244
|
/* @__PURE__ */ jsxs20(McpHostedBody, { children: [
|
|
4265
|
-
/* @__PURE__ */
|
|
4245
|
+
/* @__PURE__ */ jsx27(
|
|
4266
4246
|
McpPaymentHeader,
|
|
4267
4247
|
{
|
|
4268
4248
|
backLabel: "Change amount",
|
|
@@ -4270,16 +4250,16 @@ function EmbeddedTopup({
|
|
|
4270
4250
|
}
|
|
4271
4251
|
),
|
|
4272
4252
|
/* @__PURE__ */ jsxs20("div", { className: cx2.topupForm, children: [
|
|
4273
|
-
/* @__PURE__ */
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
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 }),
|
|
4277
4257
|
/* @__PURE__ */ jsxs20(TopupForm.SubmitButton, { className: cx2.button, children: [
|
|
4278
4258
|
"Top up",
|
|
4279
4259
|
" ",
|
|
4280
|
-
/* @__PURE__ */
|
|
4260
|
+
/* @__PURE__ */ jsx27(TopupChargeAmount, { amountMinor: committedAmountMinor, currency })
|
|
4281
4261
|
] }),
|
|
4282
|
-
/* @__PURE__ */
|
|
4262
|
+
/* @__PURE__ */ jsx27(MandateText, { mode: "topup", amountMinor: committedAmountMinor, currency })
|
|
4283
4263
|
] })
|
|
4284
4264
|
] })
|
|
4285
4265
|
] })
|
|
@@ -4295,7 +4275,7 @@ function EmbeddedTopup({
|
|
|
4295
4275
|
selector: topupSelector,
|
|
4296
4276
|
className: cx2.amountPicker,
|
|
4297
4277
|
children: [
|
|
4298
|
-
isFullscreen ? null : /* @__PURE__ */
|
|
4278
|
+
isFullscreen ? null : /* @__PURE__ */ jsx27(
|
|
4299
4279
|
AmountStepHeader,
|
|
4300
4280
|
{
|
|
4301
4281
|
cx: cx2,
|
|
@@ -4305,38 +4285,65 @@ function EmbeddedTopup({
|
|
|
4305
4285
|
onCurrencyChange: handleCurrencyChange
|
|
4306
4286
|
}
|
|
4307
4287
|
),
|
|
4308
|
-
/* @__PURE__ */
|
|
4309
|
-
/* @__PURE__ */
|
|
4288
|
+
/* @__PURE__ */ jsx27(PresetAmountGrid, { currencyDisplay, locale }),
|
|
4289
|
+
/* @__PURE__ */ jsx27(
|
|
4310
4290
|
CustomAmountRow2,
|
|
4311
4291
|
{
|
|
4312
4292
|
rowClassName: cx2.amountCustom,
|
|
4313
4293
|
currencyDisplay
|
|
4314
4294
|
}
|
|
4315
4295
|
),
|
|
4316
|
-
/* @__PURE__ */
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
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(
|
|
4327
4328
|
AmountPicker.Confirm,
|
|
4328
4329
|
{
|
|
4329
4330
|
className: cx2.button,
|
|
4330
4331
|
onConfirm: (amountMinor) => {
|
|
4331
|
-
const result =
|
|
4332
|
-
|
|
4333
|
-
|
|
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;
|
|
4334
4341
|
}
|
|
4335
|
-
|
|
4342
|
+
setAutoRechargeError(null);
|
|
4336
4343
|
setScreen({
|
|
4337
4344
|
step: "payment",
|
|
4338
4345
|
amountMinor,
|
|
4339
|
-
autoRecharge: result.payload
|
|
4346
|
+
autoRecharge: result.payload.enabled ? result.payload : void 0
|
|
4340
4347
|
});
|
|
4341
4348
|
void notifyModelContext({
|
|
4342
4349
|
text: `User confirmed topup of ${formatPrice(amountMinor, currency, {
|
|
@@ -4352,8 +4359,8 @@ function EmbeddedTopup({
|
|
|
4352
4359
|
}
|
|
4353
4360
|
);
|
|
4354
4361
|
if (isFullscreen) {
|
|
4355
|
-
return /* @__PURE__ */
|
|
4356
|
-
/* @__PURE__ */
|
|
4362
|
+
return /* @__PURE__ */ jsx27("section", { className: cx2.card, "aria-label": "Add credits", children: /* @__PURE__ */ jsxs20(McpHostedLayout, { children: [
|
|
4363
|
+
/* @__PURE__ */ jsx27(McpSummaryRail, { children: /* @__PURE__ */ jsx27(
|
|
4357
4364
|
AmountStepHeader,
|
|
4358
4365
|
{
|
|
4359
4366
|
cx: cx2,
|
|
@@ -4365,13 +4372,13 @@ function EmbeddedTopup({
|
|
|
4365
4372
|
}
|
|
4366
4373
|
) }),
|
|
4367
4374
|
/* @__PURE__ */ jsxs20(McpHostedBody, { children: [
|
|
4368
|
-
onBack ? /* @__PURE__ */
|
|
4375
|
+
onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
|
|
4369
4376
|
amountForm
|
|
4370
4377
|
] })
|
|
4371
4378
|
] }) });
|
|
4372
4379
|
}
|
|
4373
4380
|
return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Add credits", children: [
|
|
4374
|
-
onBack ? /* @__PURE__ */
|
|
4381
|
+
onBack ? /* @__PURE__ */ jsx27(BackLink, { label: "Back to my account", onClick: onBack }) : null,
|
|
4375
4382
|
amountForm
|
|
4376
4383
|
] });
|
|
4377
4384
|
}
|
|
@@ -4382,7 +4389,7 @@ function TopupChargeAmount({
|
|
|
4382
4389
|
const locale = useHostLocale();
|
|
4383
4390
|
const { taxBreakdown } = useTopupForm();
|
|
4384
4391
|
const minor = chargeAmountMinor(taxBreakdown, amountMinor);
|
|
4385
|
-
return /* @__PURE__ */
|
|
4392
|
+
return /* @__PURE__ */ jsx27(Fragment12, { children: formatPrice(minor, taxBreakdown?.currency ?? currency, { locale, free: "" }) });
|
|
4386
4393
|
}
|
|
4387
4394
|
function AmountStepHeader({
|
|
4388
4395
|
cx: cx2,
|
|
@@ -4397,26 +4404,26 @@ function AmountStepHeader({
|
|
|
4397
4404
|
const formattedBalance = credits != null ? new Intl.NumberFormat(locale).format(credits) : void 0;
|
|
4398
4405
|
return /* @__PURE__ */ jsxs20("header", { className: rail ? cx2.stack : void 0, children: [
|
|
4399
4406
|
rail ? /* @__PURE__ */ jsxs20(Fragment12, { children: [
|
|
4400
|
-
/* @__PURE__ */
|
|
4407
|
+
/* @__PURE__ */ jsx27(Eyebrow, { variant: "rail", children: "Add credits" }),
|
|
4401
4408
|
formattedBalance ? /* @__PURE__ */ jsxs20("p", { className: cx2.muted, children: [
|
|
4402
4409
|
"Balance ",
|
|
4403
4410
|
formattedBalance,
|
|
4404
4411
|
" credits"
|
|
4405
4412
|
] }) : null
|
|
4406
4413
|
] }) : /* @__PURE__ */ jsxs20("div", { className: cx2.balanceRow, children: [
|
|
4407
|
-
/* @__PURE__ */
|
|
4408
|
-
/* @__PURE__ */
|
|
4414
|
+
/* @__PURE__ */ jsx27("h2", { className: cx2.heading, children: "Add credits" }),
|
|
4415
|
+
/* @__PURE__ */ jsx27(BalanceBadge, {})
|
|
4409
4416
|
] }),
|
|
4410
4417
|
showCurrencySwitch ? /* @__PURE__ */ jsxs20("label", { className: "solvapay-mcp-step-header", children: [
|
|
4411
|
-
/* @__PURE__ */
|
|
4412
|
-
/* @__PURE__ */
|
|
4418
|
+
/* @__PURE__ */ jsx27("span", { className: cx2.muted, children: "Pay in" }),
|
|
4419
|
+
/* @__PURE__ */ jsx27(
|
|
4413
4420
|
"select",
|
|
4414
4421
|
{
|
|
4415
4422
|
className: "solvapay-mcp-currency-switch",
|
|
4416
4423
|
value: currency,
|
|
4417
4424
|
onChange: (event) => onCurrencyChange(event.target.value),
|
|
4418
4425
|
"aria-label": "Topup currency",
|
|
4419
|
-
children: topupCurrencies.map((code) => /* @__PURE__ */
|
|
4426
|
+
children: topupCurrencies.map((code) => /* @__PURE__ */ jsx27("option", { value: code, children: code }, code))
|
|
4420
4427
|
}
|
|
4421
4428
|
)
|
|
4422
4429
|
] }) : null
|
|
@@ -4428,7 +4435,7 @@ function PresetAmountGrid({
|
|
|
4428
4435
|
}) {
|
|
4429
4436
|
const { quickAmounts, currency, creditsPerMinorUnit, displayExchangeRate } = useAmountPicker();
|
|
4430
4437
|
const { displayCurrency } = useBalance();
|
|
4431
|
-
return /* @__PURE__ */
|
|
4438
|
+
return /* @__PURE__ */ jsx27("div", { className: "solvapay-mcp-preset-grid", "aria-label": "Quick amounts", children: quickAmounts.map((amount) => {
|
|
4432
4439
|
const minor = amount * getMinorUnitsPerMajor(currency);
|
|
4433
4440
|
const label = formatPrice(minor, currency, {
|
|
4434
4441
|
locale,
|
|
@@ -4443,21 +4450,21 @@ function PresetAmountGrid({
|
|
|
4443
4450
|
displayExchangeRate
|
|
4444
4451
|
);
|
|
4445
4452
|
return /* @__PURE__ */ jsxs20(AmountPicker.Option, { amount, className: "solvapay-mcp-preset-tile", children: [
|
|
4446
|
-
/* @__PURE__ */
|
|
4447
|
-
/* @__PURE__ */
|
|
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) : "" })
|
|
4448
4455
|
] }, amount);
|
|
4449
4456
|
}) });
|
|
4450
4457
|
}
|
|
4451
4458
|
function AmountDueSummary({ locale, currency }) {
|
|
4452
4459
|
const { resolvedAmountMinor } = useAmountPicker();
|
|
4453
4460
|
const displayAmount = resolvedAmountMinor != null ? formatPrice(resolvedAmountMinor, currency, { locale, free: "" }) : formatPrice(0, currency, { locale, free: "" });
|
|
4454
|
-
return /* @__PURE__ */
|
|
4461
|
+
return /* @__PURE__ */ jsx27(
|
|
4455
4462
|
AmountLadder,
|
|
4456
4463
|
{
|
|
4457
4464
|
rows: [
|
|
4458
4465
|
{
|
|
4459
4466
|
label: "Total due today",
|
|
4460
|
-
value: /* @__PURE__ */
|
|
4467
|
+
value: /* @__PURE__ */ jsx27("span", { className: "solvapay-mcp-topup-total", children: displayAmount })
|
|
4461
4468
|
}
|
|
4462
4469
|
]
|
|
4463
4470
|
}
|
|
@@ -4470,19 +4477,16 @@ function CustomAmountRow2({
|
|
|
4470
4477
|
const { currencySymbol: currencySymbol2, currency } = useAmountPicker();
|
|
4471
4478
|
const prefix = currencyDisplay === "code" ? currency.toUpperCase() : currencySymbol2;
|
|
4472
4479
|
return /* @__PURE__ */ jsxs20("label", { className: rowClassName, children: [
|
|
4473
|
-
/* @__PURE__ */
|
|
4474
|
-
/* @__PURE__ */
|
|
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" })
|
|
4475
4482
|
] });
|
|
4476
4483
|
}
|
|
4477
|
-
function HostedTopupFallback({
|
|
4478
|
-
cx: cx2,
|
|
4479
|
-
onChangeAmount
|
|
4480
|
-
}) {
|
|
4484
|
+
function HostedTopupFallback({ cx: cx2, onBack }) {
|
|
4481
4485
|
return /* @__PURE__ */ jsxs20("section", { className: cx2.card, "aria-label": "Add credits", children: [
|
|
4482
|
-
/* @__PURE__ */
|
|
4483
|
-
/* @__PURE__ */
|
|
4484
|
-
/* @__PURE__ */
|
|
4485
|
-
/* @__PURE__ */
|
|
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(
|
|
4486
4490
|
LaunchCustomerPortalButton,
|
|
4487
4491
|
{
|
|
4488
4492
|
className: cx2.button,
|
|
@@ -4495,7 +4499,7 @@ function HostedTopupFallback({
|
|
|
4495
4499
|
}
|
|
4496
4500
|
|
|
4497
4501
|
// src/mcp/McpAppShell.tsx
|
|
4498
|
-
import { jsx as
|
|
4502
|
+
import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4499
4503
|
function resolveSurface(bootstrapView) {
|
|
4500
4504
|
switch (bootstrapView) {
|
|
4501
4505
|
case "checkout":
|
|
@@ -4522,8 +4526,8 @@ function McpAppShell({
|
|
|
4522
4526
|
onRefreshBootstrap,
|
|
4523
4527
|
onClose
|
|
4524
4528
|
}) {
|
|
4525
|
-
const [overrideView, setOverrideView] =
|
|
4526
|
-
const [overridePlanRef, setOverridePlanRef] =
|
|
4529
|
+
const [overrideView, setOverrideView] = useState9(null);
|
|
4530
|
+
const [overridePlanRef, setOverridePlanRef] = useState9();
|
|
4527
4531
|
const handleSurfaceChange = useCallback5((next, intent) => {
|
|
4528
4532
|
setOverrideView(next);
|
|
4529
4533
|
setOverridePlanRef(intent?.planRef);
|
|
@@ -4533,7 +4537,7 @@ function McpAppShell({
|
|
|
4533
4537
|
const showFooter = footer ?? true;
|
|
4534
4538
|
const surface = effectiveView === "account" || effectiveView === "auto-recharge" ? "management" : "payment";
|
|
4535
4539
|
return /* @__PURE__ */ jsxs21("div", { className: "solvapay-mcp-shell", children: [
|
|
4536
|
-
/* @__PURE__ */
|
|
4540
|
+
/* @__PURE__ */ jsx28(McpHostedColumn, { surface, children: /* @__PURE__ */ jsx28(McpHostedLayout, { children: /* @__PURE__ */ jsx28("div", { className: "solvapay-mcp-shell-body", children: /* @__PURE__ */ jsx28(
|
|
4537
4541
|
McpViewRouter,
|
|
4538
4542
|
{
|
|
4539
4543
|
view: effectiveView,
|
|
@@ -4546,12 +4550,12 @@ function McpAppShell({
|
|
|
4546
4550
|
onClose
|
|
4547
4551
|
}
|
|
4548
4552
|
) }) }) }),
|
|
4549
|
-
showFooter ? /* @__PURE__ */
|
|
4553
|
+
showFooter ? /* @__PURE__ */ jsx28(ShellFooter, { classNames }) : null
|
|
4550
4554
|
] });
|
|
4551
4555
|
}
|
|
4552
4556
|
function ShellFooter({ classNames }) {
|
|
4553
4557
|
const cx2 = resolveMcpClassNames(classNames);
|
|
4554
|
-
return /* @__PURE__ */
|
|
4558
|
+
return /* @__PURE__ */ jsx28("footer", { className: `solvapay-mcp-shell-footer ${cx2.muted}`.trim(), children: /* @__PURE__ */ jsx28(LegalFooter, { attribution: "provided" }) });
|
|
4555
4559
|
}
|
|
4556
4560
|
function McpViewRouter({
|
|
4557
4561
|
view,
|
|
@@ -4567,12 +4571,14 @@ function McpViewRouter({
|
|
|
4567
4571
|
const CheckoutView = views?.checkout ?? McpCheckoutView;
|
|
4568
4572
|
const AccountView = views?.account ?? McpAccountView;
|
|
4569
4573
|
const TopupView = views?.topup ?? McpTopupView;
|
|
4574
|
+
const AutoRechargeView = views?.autoRecharge ?? McpAutoRechargeView;
|
|
4570
4575
|
const goCheckout = onSurfaceChange ? (planRef) => onSurfaceChange("checkout", typeof planRef === "string" ? { planRef } : void 0) : void 0;
|
|
4571
4576
|
const goTopup = onSurfaceChange ? () => onSurfaceChange("topup") : void 0;
|
|
4572
4577
|
const goAccount = onSurfaceChange ? () => onSurfaceChange("account") : void 0;
|
|
4578
|
+
const goAutoRecharge = onSurfaceChange ? () => onSurfaceChange("auto-recharge") : void 0;
|
|
4573
4579
|
switch (view) {
|
|
4574
4580
|
case "checkout":
|
|
4575
|
-
return /* @__PURE__ */
|
|
4581
|
+
return /* @__PURE__ */ jsx28(
|
|
4576
4582
|
CheckoutView,
|
|
4577
4583
|
{
|
|
4578
4584
|
productRef,
|
|
@@ -4588,23 +4594,23 @@ function McpViewRouter({
|
|
|
4588
4594
|
autoAdvance: Boolean(overridePlanRef)
|
|
4589
4595
|
}
|
|
4590
4596
|
);
|
|
4591
|
-
case "auto-recharge":
|
|
4592
4597
|
case "account":
|
|
4593
|
-
return /* @__PURE__ */
|
|
4598
|
+
return /* @__PURE__ */ jsx28(
|
|
4594
4599
|
AccountView,
|
|
4595
4600
|
{
|
|
4596
4601
|
classNames,
|
|
4597
4602
|
product: bootstrap.product,
|
|
4598
4603
|
productRef,
|
|
4599
4604
|
onTopup: goTopup,
|
|
4600
|
-
|
|
4601
|
-
autoRechargeUrl: bootstrap.autoRechargeUrl ?? null,
|
|
4605
|
+
onAutoRecharge: goAutoRecharge,
|
|
4602
4606
|
onChangePlan: goCheckout,
|
|
4603
4607
|
plans: bootstrap.plans
|
|
4604
4608
|
}
|
|
4605
4609
|
);
|
|
4610
|
+
case "auto-recharge":
|
|
4611
|
+
return /* @__PURE__ */ jsx28(AutoRechargeView, { classNames, onBack: goAccount });
|
|
4606
4612
|
case "topup":
|
|
4607
|
-
return /* @__PURE__ */
|
|
4613
|
+
return /* @__PURE__ */ jsx28(
|
|
4608
4614
|
TopupView,
|
|
4609
4615
|
{
|
|
4610
4616
|
publishableKey: stripePublishableKey,
|
|
@@ -4619,21 +4625,21 @@ function McpViewRouter({
|
|
|
4619
4625
|
}
|
|
4620
4626
|
|
|
4621
4627
|
// src/mcp/views/AppHeader.tsx
|
|
4622
|
-
import { useContext as useContext4, useLayoutEffect, useRef as
|
|
4628
|
+
import { useContext as useContext4, useLayoutEffect, useRef as useRef5, useState as useState10 } from "react";
|
|
4623
4629
|
|
|
4624
4630
|
// src/mcp/hooks/useHostInfo.tsx
|
|
4625
4631
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
4626
|
-
import { jsx as
|
|
4632
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
4627
4633
|
var McpHostInfoContext = createContext3(null);
|
|
4628
4634
|
function McpHostInfoProvider({ hostName, children }) {
|
|
4629
|
-
return /* @__PURE__ */
|
|
4635
|
+
return /* @__PURE__ */ jsx29(McpHostInfoContext.Provider, { value: hostName, children });
|
|
4630
4636
|
}
|
|
4631
4637
|
function useHostName() {
|
|
4632
4638
|
return useContext3(McpHostInfoContext);
|
|
4633
4639
|
}
|
|
4634
4640
|
|
|
4635
4641
|
// src/mcp/views/AppHeader.tsx
|
|
4636
|
-
import { jsx as
|
|
4642
|
+
import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4637
4643
|
var HOSTS_WITH_MERCHANT_CHROME = /chatgpt|openai|claude/i;
|
|
4638
4644
|
function useMerchantSafe() {
|
|
4639
4645
|
const ctx = useContext4(SolvaPayContext);
|
|
@@ -4670,9 +4676,9 @@ function AppHeader({
|
|
|
4670
4676
|
const hostName = useHostName();
|
|
4671
4677
|
const name = merchant?.displayName ?? "SolvaPay";
|
|
4672
4678
|
const iconUrl = merchant?.iconUrl ?? merchant?.logoUrl ?? null;
|
|
4673
|
-
const [imgFailed, setImgFailed] =
|
|
4674
|
-
const [imgLoaded, setImgLoaded] =
|
|
4675
|
-
const imgRef =
|
|
4679
|
+
const [imgFailed, setImgFailed] = useState10(false);
|
|
4680
|
+
const [imgLoaded, setImgLoaded] = useState10(false);
|
|
4681
|
+
const imgRef = useRef5(null);
|
|
4676
4682
|
useLayoutEffect(() => {
|
|
4677
4683
|
const el = imgRef.current;
|
|
4678
4684
|
const cached = el ? el.complete && el.naturalHeight > 0 : false;
|
|
@@ -4687,7 +4693,7 @@ function AppHeader({
|
|
|
4687
4693
|
const hasIconUrl = iconUrl !== null && !imgFailed;
|
|
4688
4694
|
const showInitials = !hasIconUrl || !imgLoaded;
|
|
4689
4695
|
return /* @__PURE__ */ jsxs22("header", { className: rootClass, children: [
|
|
4690
|
-
hasIconUrl ? /* @__PURE__ */
|
|
4696
|
+
hasIconUrl ? /* @__PURE__ */ jsx30(
|
|
4691
4697
|
"img",
|
|
4692
4698
|
{
|
|
4693
4699
|
ref: imgRef,
|
|
@@ -4699,14 +4705,14 @@ function AppHeader({
|
|
|
4699
4705
|
onError: () => setImgFailed(true)
|
|
4700
4706
|
}
|
|
4701
4707
|
) : null,
|
|
4702
|
-
showInitials ? /* @__PURE__ */
|
|
4703
|
-
/* @__PURE__ */
|
|
4704
|
-
children ? /* @__PURE__ */
|
|
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
|
|
4705
4711
|
] });
|
|
4706
4712
|
}
|
|
4707
4713
|
|
|
4708
4714
|
// src/mcp/McpApp.tsx
|
|
4709
|
-
import { jsx as
|
|
4715
|
+
import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
4710
4716
|
function bootstrapToInitial(bs) {
|
|
4711
4717
|
return {
|
|
4712
4718
|
customerRef: bs.customer?.ref ?? null,
|
|
@@ -4732,15 +4738,15 @@ function McpApp({
|
|
|
4732
4738
|
messageOnSuccess
|
|
4733
4739
|
}) {
|
|
4734
4740
|
const cx2 = resolveMcpClassNames(classNames);
|
|
4735
|
-
const [bootstrap, setBootstrap] =
|
|
4736
|
-
const [initError, setInitError] =
|
|
4737
|
-
const [hostName, setHostName] =
|
|
4738
|
-
const [displayModeState, setDisplayModeState] =
|
|
4741
|
+
const [bootstrap, setBootstrap] = useState11(null);
|
|
4742
|
+
const [initError, setInitError] = useState11(null);
|
|
4743
|
+
const [hostName, setHostName] = useState11(null);
|
|
4744
|
+
const [displayModeState, setDisplayModeState] = useState11(
|
|
4739
4745
|
DEFAULT_DISPLAY_MODE_STATE
|
|
4740
4746
|
);
|
|
4741
|
-
const pendingBootstrapFetchRef =
|
|
4742
|
-
const applyContextRef =
|
|
4743
|
-
const onInitErrorRef =
|
|
4747
|
+
const pendingBootstrapFetchRef = useRef6(0);
|
|
4748
|
+
const applyContextRef = useRef6(applyContext);
|
|
4749
|
+
const onInitErrorRef = useRef6(onInitError);
|
|
4744
4750
|
useEffect7(() => {
|
|
4745
4751
|
applyContextRef.current = applyContext;
|
|
4746
4752
|
}, [applyContext]);
|
|
@@ -4900,7 +4906,7 @@ function McpApp({
|
|
|
4900
4906
|
};
|
|
4901
4907
|
return resolved;
|
|
4902
4908
|
}, [transport, initial, app]);
|
|
4903
|
-
const seededInitialRef =
|
|
4909
|
+
const seededInitialRef = useRef6(null);
|
|
4904
4910
|
if (initial && seededInitialRef.current !== initial) {
|
|
4905
4911
|
seedMcpCaches(initial, providerConfig);
|
|
4906
4912
|
seededInitialRef.current = initial;
|
|
@@ -4928,14 +4934,14 @@ function McpApp({
|
|
|
4928
4934
|
);
|
|
4929
4935
|
const effectiveOnClose = onClose ?? defaultOnClose;
|
|
4930
4936
|
const effectiveBootstrap = bootstrap && productRefOverride ? { ...bootstrap, productRef: productRefOverride } : bootstrap;
|
|
4931
|
-
return /* @__PURE__ */
|
|
4937
|
+
return /* @__PURE__ */ jsx31(McpHostInfoProvider, { hostName, children: /* @__PURE__ */ jsx31(McpDisplayModeProvider, { value: displayModeState, children: /* @__PURE__ */ jsxs23(
|
|
4932
4938
|
"main",
|
|
4933
4939
|
{
|
|
4934
4940
|
className: "solvapay-mcp-main",
|
|
4935
4941
|
"data-display-mode": displayModeState.displayMode,
|
|
4936
4942
|
style: hostSafeAreaPadding(displayModeState.safeAreaInsets),
|
|
4937
4943
|
children: [
|
|
4938
|
-
/* @__PURE__ */
|
|
4944
|
+
/* @__PURE__ */ jsx31("div", { className: "solvapay-mcp-chrome-row", children: displayModeState.displayMode !== "fullscreen" ? /* @__PURE__ */ jsx31(
|
|
4939
4945
|
AppHeader,
|
|
4940
4946
|
{
|
|
4941
4947
|
classNames,
|
|
@@ -4943,16 +4949,16 @@ function McpApp({
|
|
|
4943
4949
|
}
|
|
4944
4950
|
) : null }),
|
|
4945
4951
|
initError ? /* @__PURE__ */ jsxs23("div", { className: `${cx2.card} ${cx2.error}`.trim(), children: [
|
|
4946
|
-
/* @__PURE__ */
|
|
4947
|
-
/* @__PURE__ */
|
|
4952
|
+
/* @__PURE__ */ jsx31("h2", { className: cx2.heading, children: "Unable to load SolvaPay" }),
|
|
4953
|
+
/* @__PURE__ */ jsx31("p", { children: initError })
|
|
4948
4954
|
] }) : !effectiveBootstrap ? (
|
|
4949
4955
|
// Intent-tool / fallback entries show a loading card while the
|
|
4950
4956
|
// in-flight `fetchMcpBootstrap` call resolves. Data-tool iframe
|
|
4951
4957
|
// entries no longer exist (payable merchant tools don't advertise
|
|
4952
4958
|
// `_meta.ui.resourceUri`) so this is always legitimate user
|
|
4953
4959
|
// feedback for an in-flight tool call.
|
|
4954
|
-
/* @__PURE__ */
|
|
4955
|
-
) : /* @__PURE__ */
|
|
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(
|
|
4956
4962
|
McpAppShell,
|
|
4957
4963
|
{
|
|
4958
4964
|
bootstrap: effectiveBootstrap,
|
|
@@ -4989,6 +4995,7 @@ export {
|
|
|
4989
4995
|
McpAccountView,
|
|
4990
4996
|
McpApp,
|
|
4991
4997
|
McpAppShell,
|
|
4998
|
+
McpAutoRechargeView,
|
|
4992
4999
|
McpBridgeProvider,
|
|
4993
5000
|
McpCheckoutView,
|
|
4994
5001
|
McpDisplayModeProvider,
|
|
@@ -5031,7 +5038,6 @@ export {
|
|
|
5031
5038
|
planConsequence,
|
|
5032
5039
|
readDisplayModeState,
|
|
5033
5040
|
remainingCap,
|
|
5034
|
-
resetStripeProbeCacheForTests,
|
|
5035
5041
|
resolveAccountState,
|
|
5036
5042
|
resolveActivationStrategy,
|
|
5037
5043
|
resolveActivityStrip,
|