@solvapay/react 1.3.0 → 1.4.0-preview-ecd61384a4e849717e13d47ab2daa086cdcd91c5
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 +28 -0
- package/dist/adapters/auth.js +1 -0
- package/dist/adapters/auth0.js +1 -0
- package/dist/adapters/session-auth.js +1 -0
- package/dist/{chunk-DW5FJUUG.js → chunk-6RR4J74H.js} +214 -24
- package/dist/chunk-GFWMLRR3.js +3224 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/{chunk-4ISNB3JU.js → chunk-SUHDOG7Q.js} +1 -1
- package/dist/{index-BwwdMBdt.d.ts → index-CDvQcobx.d.cts} +21 -2
- package/dist/{index-kXLvp7EU.d.cts → index-w_VMlKm5.d.ts} +21 -2
- package/dist/index.cjs +2216 -363
- package/dist/index.d.cts +34 -5
- package/dist/index.d.ts +34 -5
- package/dist/index.js +66 -3
- package/dist/mcp/index.cjs +216 -29
- package/dist/mcp/index.d.cts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +3 -2
- package/dist/primitives/index.cjs +2101 -362
- package/dist/primitives/index.d.cts +180 -5
- package/dist/primitives/index.d.ts +180 -5
- package/dist/primitives/index.js +73 -2
- package/dist/{shared-lIhc8DS3.d.ts → shared-D8raw1Nv.d.ts} +143 -12
- package/dist/{shared-BNZAIWkU.d.cts → shared-LcjvX4fD.d.cts} +143 -12
- package/dist/styles.css +513 -0
- package/dist/webapi-K5XBCEO6.js +3775 -0
- package/package.json +5 -5
- package/dist/chunk-K7ZUJI26.js +0 -1527
|
@@ -0,0 +1,3224 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AmountPicker,
|
|
3
|
+
MandateText,
|
|
4
|
+
MissingProductRefError,
|
|
5
|
+
MissingProviderError,
|
|
6
|
+
PaymentForm,
|
|
7
|
+
PlanSelector,
|
|
8
|
+
Slot,
|
|
9
|
+
SolvaPayContext,
|
|
10
|
+
Spinner,
|
|
11
|
+
TopupForm,
|
|
12
|
+
buildDefaultCheckoutPlanFilter,
|
|
13
|
+
composeEventHandlers,
|
|
14
|
+
createHttpTransport,
|
|
15
|
+
createTransportCacheKey,
|
|
16
|
+
formatContinueLabel,
|
|
17
|
+
formatPrice,
|
|
18
|
+
getMinorUnitsPerMajor,
|
|
19
|
+
interpolate,
|
|
20
|
+
isPaygPlan,
|
|
21
|
+
planSortByPaygFirstThenAsc,
|
|
22
|
+
shortCycle,
|
|
23
|
+
useActivation,
|
|
24
|
+
useAmountPicker,
|
|
25
|
+
useAmountPickerCopy,
|
|
26
|
+
useBalance,
|
|
27
|
+
useCheckoutFlow,
|
|
28
|
+
useCopy,
|
|
29
|
+
useLocale,
|
|
30
|
+
usePlan,
|
|
31
|
+
usePlanSelection,
|
|
32
|
+
usePlans,
|
|
33
|
+
useProduct,
|
|
34
|
+
usePurchase,
|
|
35
|
+
useSolvaPay,
|
|
36
|
+
useTopupAmountSelector,
|
|
37
|
+
withPaymentElementDefaults
|
|
38
|
+
} from "./chunk-6RR4J74H.js";
|
|
39
|
+
|
|
40
|
+
// src/TopupForm.tsx
|
|
41
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
42
|
+
var TopupForm2 = (props) => {
|
|
43
|
+
const { className, buttonClassName, submitButtonText, ...rootProps } = props;
|
|
44
|
+
const rootClass = ["solvapay-topup-form", className].filter(Boolean).join(" ");
|
|
45
|
+
const buttonClass = ["solvapay-topup-form-submit", buttonClassName].filter(Boolean).join(" ");
|
|
46
|
+
return /* @__PURE__ */ jsxs(TopupForm.Root, { ...rootProps, className: rootClass, children: [
|
|
47
|
+
/* @__PURE__ */ jsx(TopupForm.PaymentElement, {}),
|
|
48
|
+
/* @__PURE__ */ jsx(TopupForm.Error, { className: "solvapay-topup-form-error" }),
|
|
49
|
+
/* @__PURE__ */ jsx(TopupForm.Loading, { className: "solvapay-topup-form-loading" }),
|
|
50
|
+
/* @__PURE__ */ jsx(TopupForm.SubmitButton, { className: buttonClass, children: submitButtonText })
|
|
51
|
+
] });
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/primitives/ProductBadge.tsx
|
|
55
|
+
import { forwardRef, useContext, useEffect, useState } from "react";
|
|
56
|
+
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
57
|
+
var ProductBadgeImpl = forwardRef(function ProductBadge({ asChild, children, ...rest }, forwardedRef) {
|
|
58
|
+
const solva = useContext(SolvaPayContext);
|
|
59
|
+
if (!solva) throw new MissingProviderError("ProductBadge");
|
|
60
|
+
const { purchases, loading, hasPaidPurchase, activePurchase } = usePurchase();
|
|
61
|
+
const copy = useCopy();
|
|
62
|
+
const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!loading) setHasLoadedOnce(true);
|
|
65
|
+
}, [loading]);
|
|
66
|
+
const planToDisplay = activePurchase?.productName ?? null;
|
|
67
|
+
const shouldShow = planToDisplay !== null && (!loading || hasLoadedOnce);
|
|
68
|
+
if (!shouldShow) return null;
|
|
69
|
+
const commonProps = {
|
|
70
|
+
"data-solvapay-product-badge": "",
|
|
71
|
+
"data-loading": loading ? "" : void 0,
|
|
72
|
+
"data-has-purchase": activePurchase ? "" : void 0,
|
|
73
|
+
"data-has-paid-purchase": hasPaidPurchase ? "" : void 0,
|
|
74
|
+
role: "status",
|
|
75
|
+
"aria-live": "polite",
|
|
76
|
+
"aria-busy": loading,
|
|
77
|
+
"aria-label": interpolate(copy.product.currentProductLabel, { name: planToDisplay }),
|
|
78
|
+
...rest
|
|
79
|
+
};
|
|
80
|
+
if (asChild) {
|
|
81
|
+
return (
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
/* @__PURE__ */ jsx2(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx2(Fragment, { children: planToDisplay }) })
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
void purchases;
|
|
87
|
+
return (
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
89
|
+
/* @__PURE__ */ jsx2("div", { ref: forwardedRef, ...commonProps, children: children ?? planToDisplay })
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
var ProductBadge2 = ProductBadgeImpl;
|
|
93
|
+
var PlanBadge = ProductBadgeImpl;
|
|
94
|
+
|
|
95
|
+
// src/primitives/PurchaseGate.tsx
|
|
96
|
+
import {
|
|
97
|
+
createContext,
|
|
98
|
+
forwardRef as forwardRef2,
|
|
99
|
+
useContext as useContext2,
|
|
100
|
+
useMemo
|
|
101
|
+
} from "react";
|
|
102
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
103
|
+
var PurchaseGateContext = createContext(null);
|
|
104
|
+
function useGateCtx(part) {
|
|
105
|
+
const ctx = useContext2(PurchaseGateContext);
|
|
106
|
+
if (!ctx) {
|
|
107
|
+
throw new Error(`PurchaseGate.${part} must be rendered inside <PurchaseGate.Root>.`);
|
|
108
|
+
}
|
|
109
|
+
return ctx;
|
|
110
|
+
}
|
|
111
|
+
var Root = forwardRef2(function PurchaseGateRoot({ requirePlan, requireProduct, asChild, children, ...rest }, forwardedRef) {
|
|
112
|
+
const solva = useContext2(SolvaPayContext);
|
|
113
|
+
if (!solva) throw new MissingProviderError("PurchaseGate");
|
|
114
|
+
const { purchases, loading, hasProduct, error } = usePurchase();
|
|
115
|
+
const productToCheck = requireProduct || requirePlan;
|
|
116
|
+
const hasAccess = productToCheck ? hasProduct(productToCheck) : purchases.some((p) => p.status === "active");
|
|
117
|
+
const state = loading ? "loading" : hasAccess ? "allowed" : "blocked";
|
|
118
|
+
const ctx = useMemo(
|
|
119
|
+
() => ({ state, loading, hasAccess, error }),
|
|
120
|
+
[state, loading, hasAccess, error]
|
|
121
|
+
);
|
|
122
|
+
const Comp = asChild ? Slot : "div";
|
|
123
|
+
return /* @__PURE__ */ jsx3(PurchaseGateContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx3(
|
|
124
|
+
Comp,
|
|
125
|
+
{
|
|
126
|
+
ref: forwardedRef,
|
|
127
|
+
"data-solvapay-purchase-gate": "",
|
|
128
|
+
"data-state": state,
|
|
129
|
+
...rest,
|
|
130
|
+
children
|
|
131
|
+
}
|
|
132
|
+
) });
|
|
133
|
+
});
|
|
134
|
+
var Allowed = forwardRef2(function PurchaseGateAllowed({ asChild, children, ...rest }, forwardedRef) {
|
|
135
|
+
const ctx = useGateCtx("Allowed");
|
|
136
|
+
if (ctx.state !== "allowed") return null;
|
|
137
|
+
const Comp = asChild ? Slot : "div";
|
|
138
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-allowed": "", ...rest, children });
|
|
139
|
+
});
|
|
140
|
+
var Blocked = forwardRef2(function PurchaseGateBlocked({ asChild, children, ...rest }, forwardedRef) {
|
|
141
|
+
const ctx = useGateCtx("Blocked");
|
|
142
|
+
if (ctx.state !== "blocked") return null;
|
|
143
|
+
const Comp = asChild ? Slot : "div";
|
|
144
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-blocked": "", ...rest, children });
|
|
145
|
+
});
|
|
146
|
+
var Loading = forwardRef2(function PurchaseGateLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
147
|
+
const ctx = useGateCtx("Loading");
|
|
148
|
+
if (ctx.state !== "loading") return null;
|
|
149
|
+
const Comp = asChild ? Slot : "div";
|
|
150
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-loading": "", ...rest, children });
|
|
151
|
+
});
|
|
152
|
+
var ErrorSlot = forwardRef2(function PurchaseGateError({ asChild, children, ...rest }, forwardedRef) {
|
|
153
|
+
const ctx = useGateCtx("Error");
|
|
154
|
+
if (!ctx.error) return null;
|
|
155
|
+
const Comp = asChild ? Slot : "div";
|
|
156
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-error": "", role: "alert", ...rest, children: children ?? ctx.error.message });
|
|
157
|
+
});
|
|
158
|
+
var PurchaseGateRoot2 = Root;
|
|
159
|
+
var PurchaseGateAllowed2 = Allowed;
|
|
160
|
+
var PurchaseGateBlocked2 = Blocked;
|
|
161
|
+
var PurchaseGateLoading2 = Loading;
|
|
162
|
+
var PurchaseGateError2 = ErrorSlot;
|
|
163
|
+
var PurchaseGate = {
|
|
164
|
+
Root,
|
|
165
|
+
Allowed,
|
|
166
|
+
Blocked,
|
|
167
|
+
Loading,
|
|
168
|
+
Error: ErrorSlot
|
|
169
|
+
};
|
|
170
|
+
function usePurchaseGate() {
|
|
171
|
+
return useGateCtx("usePurchaseGate");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/primitives/ActivationFlow.tsx
|
|
175
|
+
import {
|
|
176
|
+
createContext as createContext2,
|
|
177
|
+
forwardRef as forwardRef3,
|
|
178
|
+
useCallback,
|
|
179
|
+
useContext as useContext3,
|
|
180
|
+
useEffect as useEffect2,
|
|
181
|
+
useMemo as useMemo2,
|
|
182
|
+
useRef,
|
|
183
|
+
useState as useState2
|
|
184
|
+
} from "react";
|
|
185
|
+
import { Fragment as Fragment2, jsx as jsx4 } from "react/jsx-runtime";
|
|
186
|
+
var ActivationFlowContext = createContext2(null);
|
|
187
|
+
function useFlowCtx(part) {
|
|
188
|
+
const ctx = useContext3(ActivationFlowContext);
|
|
189
|
+
if (!ctx) {
|
|
190
|
+
throw new Error(`ActivationFlow.${part} must be rendered inside <ActivationFlow.Root>.`);
|
|
191
|
+
}
|
|
192
|
+
return ctx;
|
|
193
|
+
}
|
|
194
|
+
var Root2 = forwardRef3(function ActivationFlowRoot({
|
|
195
|
+
productRef,
|
|
196
|
+
planRef: planRefProp,
|
|
197
|
+
onSuccess,
|
|
198
|
+
onError,
|
|
199
|
+
retryDelayMs = 1500,
|
|
200
|
+
retryBackoffMs = 2e3,
|
|
201
|
+
asChild,
|
|
202
|
+
children,
|
|
203
|
+
...rest
|
|
204
|
+
}, forwardedRef) {
|
|
205
|
+
const solva = useContext3(SolvaPayContext);
|
|
206
|
+
if (!solva) throw new MissingProviderError("ActivationFlow");
|
|
207
|
+
if (!productRef) throw new MissingProductRefError("ActivationFlow");
|
|
208
|
+
const planSelection = usePlanSelection();
|
|
209
|
+
const resolvedPlanRef = planRefProp ?? planSelection?.selectedPlanRef ?? void 0;
|
|
210
|
+
const { plan } = usePlan({ planRef: resolvedPlanRef, productRef });
|
|
211
|
+
const { activate, state, error, result, reset } = useActivation();
|
|
212
|
+
const currency = plan?.currency ?? "USD";
|
|
213
|
+
const amountSelector = useTopupAmountSelector({ currency });
|
|
214
|
+
const { adjustBalance, creditsPerMinorUnit, displayExchangeRate } = useBalance();
|
|
215
|
+
const [step, setStep] = useState2("summary");
|
|
216
|
+
const calledSuccessRef = useRef(false);
|
|
217
|
+
const retryTimeoutRef = useRef(null);
|
|
218
|
+
useEffect2(() => {
|
|
219
|
+
if (state === "activated" && !calledSuccessRef.current) {
|
|
220
|
+
calledSuccessRef.current = true;
|
|
221
|
+
setStep("activated");
|
|
222
|
+
if (result) {
|
|
223
|
+
const activationResult = { kind: "activated", result };
|
|
224
|
+
onSuccess?.(activationResult);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}, [state, result, onSuccess]);
|
|
228
|
+
useEffect2(() => {
|
|
229
|
+
if (state === "topup_required" && (step === "summary" || step === "activating")) {
|
|
230
|
+
setStep("selectAmount");
|
|
231
|
+
}
|
|
232
|
+
}, [state, step]);
|
|
233
|
+
useEffect2(() => {
|
|
234
|
+
if ((state === "error" || state === "payment_required") && error) {
|
|
235
|
+
setStep("error");
|
|
236
|
+
if (state === "error") onError?.(new Error(error));
|
|
237
|
+
}
|
|
238
|
+
}, [state, error, onError]);
|
|
239
|
+
const handleActivate = useCallback(async () => {
|
|
240
|
+
if (!resolvedPlanRef) return;
|
|
241
|
+
setStep("activating");
|
|
242
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
243
|
+
}, [activate, productRef, resolvedPlanRef]);
|
|
244
|
+
const goToTopupPayment = useCallback(() => {
|
|
245
|
+
if (amountSelector.validate()) setStep("topupPayment");
|
|
246
|
+
}, [amountSelector]);
|
|
247
|
+
const backToSelectAmount = useCallback(() => {
|
|
248
|
+
setStep("selectAmount");
|
|
249
|
+
}, []);
|
|
250
|
+
const retryActivation = useCallback(async () => {
|
|
251
|
+
if (!resolvedPlanRef) return;
|
|
252
|
+
setStep("retrying");
|
|
253
|
+
const amountMinor2 = Math.round(
|
|
254
|
+
(amountSelector.resolvedAmount || 0) * getMinorUnitsPerMajor(currency)
|
|
255
|
+
);
|
|
256
|
+
const rate = displayExchangeRate ?? 1;
|
|
257
|
+
if (creditsPerMinorUnit) {
|
|
258
|
+
adjustBalance(Math.floor(amountMinor2 / rate * creditsPerMinorUnit));
|
|
259
|
+
}
|
|
260
|
+
await new Promise((r) => setTimeout(r, retryDelayMs));
|
|
261
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
262
|
+
}, [
|
|
263
|
+
resolvedPlanRef,
|
|
264
|
+
amountSelector.resolvedAmount,
|
|
265
|
+
currency,
|
|
266
|
+
displayExchangeRate,
|
|
267
|
+
creditsPerMinorUnit,
|
|
268
|
+
adjustBalance,
|
|
269
|
+
retryDelayMs,
|
|
270
|
+
activate,
|
|
271
|
+
productRef
|
|
272
|
+
]);
|
|
273
|
+
const handleTopupSuccess = useCallback(async () => {
|
|
274
|
+
await retryActivation();
|
|
275
|
+
}, [retryActivation]);
|
|
276
|
+
useEffect2(() => {
|
|
277
|
+
if (step !== "retrying") return;
|
|
278
|
+
if (state !== "topup_required") return;
|
|
279
|
+
if (!resolvedPlanRef) return;
|
|
280
|
+
retryTimeoutRef.current = setTimeout(async () => {
|
|
281
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
282
|
+
}, retryBackoffMs);
|
|
283
|
+
return () => {
|
|
284
|
+
if (retryTimeoutRef.current) clearTimeout(retryTimeoutRef.current);
|
|
285
|
+
};
|
|
286
|
+
}, [step, state, resolvedPlanRef, retryBackoffMs, activate, productRef]);
|
|
287
|
+
const resetFlow = useCallback(() => {
|
|
288
|
+
reset();
|
|
289
|
+
calledSuccessRef.current = false;
|
|
290
|
+
setStep("summary");
|
|
291
|
+
}, [reset]);
|
|
292
|
+
const amountMinor = Math.round(
|
|
293
|
+
(amountSelector.resolvedAmount || 0) * getMinorUnitsPerMajor(currency)
|
|
294
|
+
);
|
|
295
|
+
const ctx = useMemo2(
|
|
296
|
+
() => ({
|
|
297
|
+
step,
|
|
298
|
+
plan,
|
|
299
|
+
productRef,
|
|
300
|
+
planRef: resolvedPlanRef ?? "",
|
|
301
|
+
amountSelector,
|
|
302
|
+
amountMinor,
|
|
303
|
+
// Deprecated alias — same value as amountMinor so legacy consumers
|
|
304
|
+
// keep working after the zero-decimal fix (previously this was
|
|
305
|
+
// `resolvedAmount * 100`, which over-billed JPY/KRW by 100x).
|
|
306
|
+
amountCents: amountMinor,
|
|
307
|
+
currency,
|
|
308
|
+
activate: handleActivate,
|
|
309
|
+
reset: resetFlow,
|
|
310
|
+
goToTopupPayment,
|
|
311
|
+
backToSelectAmount,
|
|
312
|
+
onTopupSuccess: handleTopupSuccess,
|
|
313
|
+
error,
|
|
314
|
+
onError
|
|
315
|
+
}),
|
|
316
|
+
[
|
|
317
|
+
step,
|
|
318
|
+
plan,
|
|
319
|
+
productRef,
|
|
320
|
+
resolvedPlanRef,
|
|
321
|
+
amountSelector,
|
|
322
|
+
amountMinor,
|
|
323
|
+
currency,
|
|
324
|
+
handleActivate,
|
|
325
|
+
resetFlow,
|
|
326
|
+
goToTopupPayment,
|
|
327
|
+
backToSelectAmount,
|
|
328
|
+
handleTopupSuccess,
|
|
329
|
+
error,
|
|
330
|
+
onError
|
|
331
|
+
]
|
|
332
|
+
);
|
|
333
|
+
const Comp = asChild ? Slot : "div";
|
|
334
|
+
return /* @__PURE__ */ jsx4(ActivationFlowContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx4(
|
|
335
|
+
Comp,
|
|
336
|
+
{
|
|
337
|
+
ref: forwardedRef,
|
|
338
|
+
"data-solvapay-activation-flow": "",
|
|
339
|
+
"data-state": step,
|
|
340
|
+
...rest,
|
|
341
|
+
children
|
|
342
|
+
}
|
|
343
|
+
) });
|
|
344
|
+
});
|
|
345
|
+
function matchStep(step, allowed) {
|
|
346
|
+
return allowed.includes(step);
|
|
347
|
+
}
|
|
348
|
+
var Summary = forwardRef3(function ActivationFlowSummary({ asChild, children, ...rest }, forwardedRef) {
|
|
349
|
+
const ctx = useFlowCtx("Summary");
|
|
350
|
+
if (!matchStep(ctx.step, ["summary", "activating"])) return null;
|
|
351
|
+
const Comp = asChild ? Slot : "div";
|
|
352
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-summary": "", ...rest, children });
|
|
353
|
+
});
|
|
354
|
+
var ActivateButton = forwardRef3(
|
|
355
|
+
function ActivationFlowActivateButton({ asChild, onClick, children, ...rest }, forwardedRef) {
|
|
356
|
+
const ctx = useFlowCtx("ActivateButton");
|
|
357
|
+
const copy = useCopy();
|
|
358
|
+
if (!matchStep(ctx.step, ["summary", "activating"])) return null;
|
|
359
|
+
const isActivating = ctx.step === "activating";
|
|
360
|
+
const disabled = isActivating;
|
|
361
|
+
const commonProps = {
|
|
362
|
+
"data-solvapay-activation-flow-activate": "",
|
|
363
|
+
"data-state": isActivating ? "activating" : "idle",
|
|
364
|
+
"aria-busy": isActivating,
|
|
365
|
+
disabled,
|
|
366
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
367
|
+
void ctx.activate();
|
|
368
|
+
}),
|
|
369
|
+
...rest
|
|
370
|
+
};
|
|
371
|
+
const label = isActivating ? copy.activationFlow.activatingLabel : copy.activationFlow.activateButton;
|
|
372
|
+
if (asChild) {
|
|
373
|
+
return (
|
|
374
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
375
|
+
/* @__PURE__ */ jsx4(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx4(Fragment2, { children: label }) })
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return /* @__PURE__ */ jsx4("button", { ref: forwardedRef, type: "button", ...commonProps, children: children ?? label });
|
|
379
|
+
}
|
|
380
|
+
);
|
|
381
|
+
var AmountPickerMount = ({ children }) => {
|
|
382
|
+
const ctx = useFlowCtx("AmountPicker");
|
|
383
|
+
if (ctx.step !== "selectAmount") return null;
|
|
384
|
+
return /* @__PURE__ */ jsx4("div", { "data-solvapay-activation-flow-amount-picker": "", children: /* @__PURE__ */ jsx4(AmountPicker.Root, { currency: ctx.currency, selector: ctx.amountSelector, children }) });
|
|
385
|
+
};
|
|
386
|
+
var ContinueButton = forwardRef3(
|
|
387
|
+
function ActivationFlowContinueButton({ asChild, onClick, children, ...rest }, forwardedRef) {
|
|
388
|
+
const ctx = useFlowCtx("ContinueButton");
|
|
389
|
+
const copy = useCopy();
|
|
390
|
+
if (ctx.step !== "selectAmount") return null;
|
|
391
|
+
const disabled = !ctx.amountSelector.resolvedAmount;
|
|
392
|
+
const commonProps = {
|
|
393
|
+
"data-solvapay-activation-flow-continue": "",
|
|
394
|
+
"data-state": disabled ? "disabled" : "idle",
|
|
395
|
+
disabled,
|
|
396
|
+
"aria-disabled": disabled || void 0,
|
|
397
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
398
|
+
ctx.goToTopupPayment();
|
|
399
|
+
}),
|
|
400
|
+
...rest
|
|
401
|
+
};
|
|
402
|
+
if (asChild) {
|
|
403
|
+
return (
|
|
404
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
405
|
+
/* @__PURE__ */ jsx4(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx4(Fragment2, { children: copy.activationFlow.continueToPayment }) })
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
return /* @__PURE__ */ jsx4("button", { ref: forwardedRef, type: "button", ...commonProps, children: children ?? copy.activationFlow.continueToPayment });
|
|
409
|
+
}
|
|
410
|
+
);
|
|
411
|
+
var Retrying = forwardRef3(function ActivationFlowRetrying({ asChild, children, ...rest }, forwardedRef) {
|
|
412
|
+
const ctx = useFlowCtx("Retrying");
|
|
413
|
+
if (ctx.step !== "retrying") return null;
|
|
414
|
+
const Comp = asChild ? Slot : "div";
|
|
415
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-retrying": "", ...rest, children });
|
|
416
|
+
});
|
|
417
|
+
var Activated = forwardRef3(function ActivationFlowActivated({ asChild, children, ...rest }, forwardedRef) {
|
|
418
|
+
const ctx = useFlowCtx("Activated");
|
|
419
|
+
if (ctx.step !== "activated") return null;
|
|
420
|
+
const Comp = asChild ? Slot : "div";
|
|
421
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-activated": "", ...rest, children });
|
|
422
|
+
});
|
|
423
|
+
var Loading2 = forwardRef3(function ActivationFlowLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
424
|
+
const ctx = useFlowCtx("Loading");
|
|
425
|
+
if (ctx.plan) return null;
|
|
426
|
+
const Comp = asChild ? Slot : "div";
|
|
427
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-loading": "", ...rest, children });
|
|
428
|
+
});
|
|
429
|
+
var ErrorSlot2 = forwardRef3(function ActivationFlowError({ asChild, children, ...rest }, forwardedRef) {
|
|
430
|
+
const ctx = useFlowCtx("Error");
|
|
431
|
+
if (ctx.step !== "error") return null;
|
|
432
|
+
const Comp = asChild ? Slot : "div";
|
|
433
|
+
return /* @__PURE__ */ jsx4(
|
|
434
|
+
Comp,
|
|
435
|
+
{
|
|
436
|
+
ref: forwardedRef,
|
|
437
|
+
role: "alert",
|
|
438
|
+
"data-solvapay-activation-flow-error": "",
|
|
439
|
+
...rest,
|
|
440
|
+
children: children ?? ctx.error
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
});
|
|
444
|
+
var ActivationFlowRoot2 = Root2;
|
|
445
|
+
var ActivationFlowSummary2 = Summary;
|
|
446
|
+
var ActivationFlowActivateButton2 = ActivateButton;
|
|
447
|
+
var ActivationFlowAmountPicker = AmountPickerMount;
|
|
448
|
+
var ActivationFlowContinueButton2 = ContinueButton;
|
|
449
|
+
var ActivationFlowRetrying2 = Retrying;
|
|
450
|
+
var ActivationFlowActivated2 = Activated;
|
|
451
|
+
var ActivationFlowLoading2 = Loading2;
|
|
452
|
+
var ActivationFlowError2 = ErrorSlot2;
|
|
453
|
+
var ActivationFlow = {
|
|
454
|
+
Root: Root2,
|
|
455
|
+
Summary,
|
|
456
|
+
ActivateButton,
|
|
457
|
+
AmountPicker: AmountPickerMount,
|
|
458
|
+
ContinueButton,
|
|
459
|
+
Retrying,
|
|
460
|
+
Activated,
|
|
461
|
+
Loading: Loading2,
|
|
462
|
+
Error: ErrorSlot2
|
|
463
|
+
};
|
|
464
|
+
function useActivationFlow() {
|
|
465
|
+
return useFlowCtx("useActivationFlow");
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// src/primitives/CreditGate.tsx
|
|
469
|
+
import {
|
|
470
|
+
createContext as createContext3,
|
|
471
|
+
forwardRef as forwardRef4,
|
|
472
|
+
useContext as useContext4,
|
|
473
|
+
useMemo as useMemo3
|
|
474
|
+
} from "react";
|
|
475
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
476
|
+
var CreditGateContext = createContext3(null);
|
|
477
|
+
function useGateCtx2(part) {
|
|
478
|
+
const ctx = useContext4(CreditGateContext);
|
|
479
|
+
if (!ctx) {
|
|
480
|
+
throw new Error(`CreditGate.${part} must be rendered inside <CreditGate.Root>.`);
|
|
481
|
+
}
|
|
482
|
+
return ctx;
|
|
483
|
+
}
|
|
484
|
+
var Root3 = forwardRef4(function CreditGateRoot({
|
|
485
|
+
minCredits = 1,
|
|
486
|
+
productRef,
|
|
487
|
+
topupAmount = 1e3,
|
|
488
|
+
topupCurrency = "usd",
|
|
489
|
+
asChild,
|
|
490
|
+
children,
|
|
491
|
+
...rest
|
|
492
|
+
}, forwardedRef) {
|
|
493
|
+
const solva = useContext4(SolvaPayContext);
|
|
494
|
+
if (!solva) throw new MissingProviderError("CreditGate");
|
|
495
|
+
const { credits, loading } = useBalance();
|
|
496
|
+
const { product } = useProduct(productRef);
|
|
497
|
+
const hasCredits = credits != null && credits >= minCredits;
|
|
498
|
+
const state = loading && credits == null ? "loading" : hasCredits ? "allowed" : "blocked";
|
|
499
|
+
const ctx = useMemo3(
|
|
500
|
+
() => ({
|
|
501
|
+
state,
|
|
502
|
+
loading,
|
|
503
|
+
hasCredits,
|
|
504
|
+
balance: credits,
|
|
505
|
+
productName: product?.name ?? null,
|
|
506
|
+
topupAmount,
|
|
507
|
+
topupCurrency
|
|
508
|
+
}),
|
|
509
|
+
[state, loading, hasCredits, credits, product?.name, topupAmount, topupCurrency]
|
|
510
|
+
);
|
|
511
|
+
const Comp = asChild ? Slot : "div";
|
|
512
|
+
return /* @__PURE__ */ jsx5(CreditGateContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx5(
|
|
513
|
+
Comp,
|
|
514
|
+
{
|
|
515
|
+
ref: forwardedRef,
|
|
516
|
+
"data-solvapay-credit-gate": "",
|
|
517
|
+
"data-state": state,
|
|
518
|
+
...rest,
|
|
519
|
+
children
|
|
520
|
+
}
|
|
521
|
+
) });
|
|
522
|
+
});
|
|
523
|
+
var Heading = forwardRef4(function CreditGateHeading({ asChild, children, ...rest }, forwardedRef) {
|
|
524
|
+
const ctx = useGateCtx2("Heading");
|
|
525
|
+
const copy = useCopy();
|
|
526
|
+
if (ctx.state !== "blocked") return null;
|
|
527
|
+
const Comp = asChild ? Slot : "h3";
|
|
528
|
+
return /* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-heading": "", ...rest, children: children ?? copy.creditGate.lowBalanceHeading });
|
|
529
|
+
});
|
|
530
|
+
var Subheading = forwardRef4(function CreditGateSubheading({ asChild, children, ...rest }, forwardedRef) {
|
|
531
|
+
const ctx = useGateCtx2("Subheading");
|
|
532
|
+
const copy = useCopy();
|
|
533
|
+
if (ctx.state !== "blocked") return null;
|
|
534
|
+
const text = interpolate(copy.creditGate.lowBalanceSubheading, {
|
|
535
|
+
product: ctx.productName ?? "this product"
|
|
536
|
+
});
|
|
537
|
+
const Comp = asChild ? Slot : "p";
|
|
538
|
+
return /* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-subheading": "", ...rest, children: children ?? text });
|
|
539
|
+
});
|
|
540
|
+
var Topup = ({ amount, currency }) => {
|
|
541
|
+
const ctx = useGateCtx2("Topup");
|
|
542
|
+
if (ctx.state !== "blocked") return null;
|
|
543
|
+
return /* @__PURE__ */ jsx5(
|
|
544
|
+
TopupForm2,
|
|
545
|
+
{
|
|
546
|
+
amount: amount ?? ctx.topupAmount,
|
|
547
|
+
currency: currency ?? ctx.topupCurrency
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
};
|
|
551
|
+
var Loading3 = forwardRef4(function CreditGateLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
552
|
+
const ctx = useGateCtx2("Loading");
|
|
553
|
+
if (ctx.state !== "loading") return null;
|
|
554
|
+
const Comp = asChild ? Slot : "div";
|
|
555
|
+
return (
|
|
556
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
557
|
+
/* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-loading": "", ...rest, children })
|
|
558
|
+
);
|
|
559
|
+
});
|
|
560
|
+
var ErrorSlot3 = forwardRef4(function CreditGateError({ asChild, children, ...rest }, forwardedRef) {
|
|
561
|
+
if (!children) return null;
|
|
562
|
+
const Comp = asChild ? Slot : "div";
|
|
563
|
+
return (
|
|
564
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
565
|
+
/* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-error": "", role: "alert", ...rest, children })
|
|
566
|
+
);
|
|
567
|
+
});
|
|
568
|
+
var CreditGateRoot2 = Root3;
|
|
569
|
+
var CreditGateHeading2 = Heading;
|
|
570
|
+
var CreditGateSubheading2 = Subheading;
|
|
571
|
+
var CreditGateTopup = Topup;
|
|
572
|
+
var CreditGateLoading2 = Loading3;
|
|
573
|
+
var CreditGateError2 = ErrorSlot3;
|
|
574
|
+
var CreditGate = {
|
|
575
|
+
Root: Root3,
|
|
576
|
+
Heading,
|
|
577
|
+
Subheading,
|
|
578
|
+
Topup,
|
|
579
|
+
Loading: Loading3,
|
|
580
|
+
Error: ErrorSlot3
|
|
581
|
+
};
|
|
582
|
+
function useCreditGate() {
|
|
583
|
+
return useGateCtx2("useCreditGate");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// src/hooks/useAutoRecharge.ts
|
|
587
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
588
|
+
|
|
589
|
+
// src/hooks/autoRechargeCache.ts
|
|
590
|
+
var autoRechargeCache = /* @__PURE__ */ new Map();
|
|
591
|
+
var CACHE_DURATION = 5 * 60 * 1e3;
|
|
592
|
+
function autoRechargeCacheKeyFor(config) {
|
|
593
|
+
return createTransportCacheKey(config, config?.api?.autoRecharge || "/api/auto-recharge");
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/hooks/useAutoRecharge.ts
|
|
597
|
+
function mergeAutoRechargeConfig(config, display) {
|
|
598
|
+
return display ? { ...config, display } : config;
|
|
599
|
+
}
|
|
600
|
+
async function fetchAutoRecharge(config) {
|
|
601
|
+
const transport = config?.transport ?? createHttpTransport(config);
|
|
602
|
+
if (!transport.getAutoRecharge) return null;
|
|
603
|
+
const response = await transport.getAutoRecharge();
|
|
604
|
+
if (!response.config) return null;
|
|
605
|
+
return mergeAutoRechargeConfig(response.config, response.display);
|
|
606
|
+
}
|
|
607
|
+
function useAutoRecharge() {
|
|
608
|
+
const { _config } = useSolvaPay();
|
|
609
|
+
const key = autoRechargeCacheKeyFor(_config);
|
|
610
|
+
const [config, setConfig] = useState3(
|
|
611
|
+
() => autoRechargeCache.get(key)?.config ?? null
|
|
612
|
+
);
|
|
613
|
+
const [loading, setLoading] = useState3(() => {
|
|
614
|
+
const cached = autoRechargeCache.get(key);
|
|
615
|
+
return !cached || !cached.config && !cached.promise;
|
|
616
|
+
});
|
|
617
|
+
const [saving, setSaving] = useState3(false);
|
|
618
|
+
const [disabling, setDisabling] = useState3(false);
|
|
619
|
+
const [error, setError] = useState3(null);
|
|
620
|
+
const requestSeq = useRef2(0);
|
|
621
|
+
const load = useCallback2(
|
|
622
|
+
async (force = false) => {
|
|
623
|
+
const seq = requestSeq.current;
|
|
624
|
+
const cached = autoRechargeCache.get(key);
|
|
625
|
+
const now = Date.now();
|
|
626
|
+
if (!force && cached?.config && now - cached.timestamp < CACHE_DURATION) {
|
|
627
|
+
if (seq !== requestSeq.current) return;
|
|
628
|
+
setConfig(cached.config);
|
|
629
|
+
setLoading(false);
|
|
630
|
+
setError(null);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (!force && cached?.promise) {
|
|
634
|
+
setLoading(true);
|
|
635
|
+
try {
|
|
636
|
+
const value = await cached.promise;
|
|
637
|
+
if (seq !== requestSeq.current) return;
|
|
638
|
+
setConfig(value);
|
|
639
|
+
setError(null);
|
|
640
|
+
} catch (caught) {
|
|
641
|
+
if (seq !== requestSeq.current) return;
|
|
642
|
+
setError(caught instanceof Error ? caught : new Error(String(caught)));
|
|
643
|
+
} finally {
|
|
644
|
+
if (seq === requestSeq.current) {
|
|
645
|
+
setLoading(false);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
setLoading(true);
|
|
651
|
+
setError(null);
|
|
652
|
+
const promise = fetchAutoRecharge(_config);
|
|
653
|
+
autoRechargeCache.set(key, {
|
|
654
|
+
config: cached?.config ?? null,
|
|
655
|
+
promise,
|
|
656
|
+
timestamp: now
|
|
657
|
+
});
|
|
658
|
+
try {
|
|
659
|
+
const value = await promise;
|
|
660
|
+
if (seq !== requestSeq.current) return;
|
|
661
|
+
autoRechargeCache.set(key, { config: value, promise: null, timestamp: Date.now() });
|
|
662
|
+
setConfig(value);
|
|
663
|
+
} catch (caught) {
|
|
664
|
+
if (seq !== requestSeq.current) return;
|
|
665
|
+
const err = caught instanceof Error ? caught : new Error(String(caught));
|
|
666
|
+
autoRechargeCache.set(key, { config: null, promise: null, timestamp: Date.now() });
|
|
667
|
+
setError(err);
|
|
668
|
+
} finally {
|
|
669
|
+
if (seq === requestSeq.current) {
|
|
670
|
+
setLoading(false);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
[_config, key]
|
|
675
|
+
);
|
|
676
|
+
useEffect3(() => {
|
|
677
|
+
void load();
|
|
678
|
+
}, [load]);
|
|
679
|
+
const refresh = useCallback2(
|
|
680
|
+
async (force = true) => {
|
|
681
|
+
await load(force);
|
|
682
|
+
},
|
|
683
|
+
[load]
|
|
684
|
+
);
|
|
685
|
+
const save = useCallback2(
|
|
686
|
+
async (input) => {
|
|
687
|
+
const transport = _config?.transport ?? createHttpTransport(_config);
|
|
688
|
+
if (!transport.saveAutoRecharge) {
|
|
689
|
+
throw new Error("saveAutoRecharge is not available on this transport");
|
|
690
|
+
}
|
|
691
|
+
setSaving(true);
|
|
692
|
+
setError(null);
|
|
693
|
+
const seq = ++requestSeq.current;
|
|
694
|
+
try {
|
|
695
|
+
const result = await transport.saveAutoRecharge(input);
|
|
696
|
+
if (seq !== requestSeq.current) return result;
|
|
697
|
+
const nextConfig = mergeAutoRechargeConfig(result.config, result.display);
|
|
698
|
+
autoRechargeCache.set(key, {
|
|
699
|
+
config: nextConfig,
|
|
700
|
+
promise: null,
|
|
701
|
+
timestamp: Date.now()
|
|
702
|
+
});
|
|
703
|
+
setConfig(nextConfig);
|
|
704
|
+
return result;
|
|
705
|
+
} catch (caught) {
|
|
706
|
+
const err = caught instanceof Error ? caught : new Error(String(caught));
|
|
707
|
+
setError(err);
|
|
708
|
+
throw err;
|
|
709
|
+
} finally {
|
|
710
|
+
setSaving(false);
|
|
711
|
+
}
|
|
712
|
+
},
|
|
713
|
+
[_config, key]
|
|
714
|
+
);
|
|
715
|
+
const disable = useCallback2(async () => {
|
|
716
|
+
const transport = _config?.transport ?? createHttpTransport(_config);
|
|
717
|
+
if (!transport.disableAutoRecharge) {
|
|
718
|
+
throw new Error("disableAutoRecharge is not available on this transport");
|
|
719
|
+
}
|
|
720
|
+
setDisabling(true);
|
|
721
|
+
setError(null);
|
|
722
|
+
const seq = ++requestSeq.current;
|
|
723
|
+
try {
|
|
724
|
+
const result = await transport.disableAutoRecharge();
|
|
725
|
+
if (seq === requestSeq.current) {
|
|
726
|
+
setConfig((current) => {
|
|
727
|
+
const disabledConfig = current ? { ...current, enabled: false } : null;
|
|
728
|
+
autoRechargeCache.set(key, {
|
|
729
|
+
config: disabledConfig,
|
|
730
|
+
promise: null,
|
|
731
|
+
timestamp: Date.now()
|
|
732
|
+
});
|
|
733
|
+
return disabledConfig;
|
|
734
|
+
});
|
|
735
|
+
await refresh(true);
|
|
736
|
+
setConfig((current) => {
|
|
737
|
+
const disabledConfig = current ? { ...current, enabled: false } : null;
|
|
738
|
+
autoRechargeCache.set(key, {
|
|
739
|
+
config: disabledConfig,
|
|
740
|
+
promise: null,
|
|
741
|
+
timestamp: Date.now()
|
|
742
|
+
});
|
|
743
|
+
return disabledConfig;
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
return result;
|
|
747
|
+
} catch (caught) {
|
|
748
|
+
const err = caught instanceof Error ? caught : new Error(String(caught));
|
|
749
|
+
setError(err);
|
|
750
|
+
throw err;
|
|
751
|
+
} finally {
|
|
752
|
+
setDisabling(false);
|
|
753
|
+
}
|
|
754
|
+
}, [_config, key, refresh]);
|
|
755
|
+
return { config, loading, saving, disabling, error, refresh, save, disable };
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// src/utils/credit-estimation.ts
|
|
759
|
+
import { creditsToDisplayMinorUnits } from "@solvapay/core";
|
|
760
|
+
function estimateCredits(resolvedAmountMajor, currency, creditsPerMinorUnit, displayExchangeRate) {
|
|
761
|
+
if (resolvedAmountMajor == null || resolvedAmountMajor <= 0) return null;
|
|
762
|
+
if (creditsPerMinorUnit == null || creditsPerMinorUnit <= 0) return null;
|
|
763
|
+
const rate = displayExchangeRate ?? 1;
|
|
764
|
+
const resolvedAmountMinor = Math.round(resolvedAmountMajor * getMinorUnitsPerMajor(currency));
|
|
765
|
+
return Math.round(resolvedAmountMinor / rate * creditsPerMinorUnit);
|
|
766
|
+
}
|
|
767
|
+
function estimateCurrencyMajorFromCredits(credits, currency, creditsPerMinorUnit, displayExchangeRate) {
|
|
768
|
+
if (credits == null || credits <= 0) return null;
|
|
769
|
+
if (creditsPerMinorUnit == null || creditsPerMinorUnit <= 0) return null;
|
|
770
|
+
const rate = displayExchangeRate ?? 1;
|
|
771
|
+
const displayMinor = creditsToDisplayMinorUnits({
|
|
772
|
+
credits,
|
|
773
|
+
creditsPerMinorUnit,
|
|
774
|
+
displayExchangeRate: rate,
|
|
775
|
+
displayCurrency: currency
|
|
776
|
+
});
|
|
777
|
+
if (displayMinor === null) return null;
|
|
778
|
+
return displayMinor / getMinorUnitsPerMajor(currency);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/helpers/stripe-minimums.ts
|
|
782
|
+
var STRIPE_MINIMUM_MINOR = {
|
|
783
|
+
USD: 50,
|
|
784
|
+
EUR: 50,
|
|
785
|
+
GBP: 30,
|
|
786
|
+
SEK: 300,
|
|
787
|
+
NOK: 300,
|
|
788
|
+
DKK: 250,
|
|
789
|
+
CHF: 50,
|
|
790
|
+
CAD: 50,
|
|
791
|
+
AUD: 50,
|
|
792
|
+
JPY: 50,
|
|
793
|
+
KRW: 500
|
|
794
|
+
};
|
|
795
|
+
var DEFAULT_MINIMUM_MINOR = 50;
|
|
796
|
+
function getStripeMinimumMinor(currency) {
|
|
797
|
+
return STRIPE_MINIMUM_MINOR[currency.toUpperCase()] ?? DEFAULT_MINIMUM_MINOR;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// src/helpers/auto-recharge-form.ts
|
|
801
|
+
var DEFAULT_VALIDATION_MESSAGES = {
|
|
802
|
+
invalidThreshold: "Enter a valid balance threshold.",
|
|
803
|
+
thresholdTooLow: "Balance threshold must be greater than zero.",
|
|
804
|
+
minTopupAmount: "Top-up amount must be at least {amount}.",
|
|
805
|
+
topupBelowThreshold: "Top-up amount must be at least your balance threshold ({amount})."
|
|
806
|
+
};
|
|
807
|
+
function amountAnchors(thresholdValue, topupValue, unit = "currency") {
|
|
808
|
+
return {
|
|
809
|
+
thresholdBaseValue: thresholdValue,
|
|
810
|
+
thresholdBaseUnit: unit,
|
|
811
|
+
topupBaseValue: topupValue,
|
|
812
|
+
topupBaseUnit: unit
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
function createDefaultAutoRechargeForm(currency, defaultTopupMajor, defaultThresholdMajor) {
|
|
816
|
+
const topup = defaultTopupMajor != null && defaultTopupMajor > 0 ? String(defaultTopupMajor) : "10";
|
|
817
|
+
const threshold = defaultThresholdMajor != null && defaultThresholdMajor >= 0 ? String(defaultThresholdMajor) : "5";
|
|
818
|
+
return {
|
|
819
|
+
enabled: false,
|
|
820
|
+
thresholdAmountMajor: threshold,
|
|
821
|
+
thresholdUnit: "currency",
|
|
822
|
+
topupAmountMajor: topup,
|
|
823
|
+
topupUnit: "currency",
|
|
824
|
+
...amountAnchors(threshold, topup, "currency")
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
function parsePositiveNumber(value) {
|
|
828
|
+
const trimmed = value.trim();
|
|
829
|
+
if (trimmed.length === 0) return null;
|
|
830
|
+
const parsed = Number(trimmed);
|
|
831
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return null;
|
|
832
|
+
return parsed;
|
|
833
|
+
}
|
|
834
|
+
function parseNonNegativeNumber(value) {
|
|
835
|
+
const trimmed = value.trim();
|
|
836
|
+
if (trimmed.length === 0) return null;
|
|
837
|
+
const parsed = Number(trimmed);
|
|
838
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
839
|
+
return parsed;
|
|
840
|
+
}
|
|
841
|
+
function validateAutoRechargeForm(form, currency, conversion, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
842
|
+
if (!form.enabled) {
|
|
843
|
+
return {
|
|
844
|
+
ok: true,
|
|
845
|
+
payload: {
|
|
846
|
+
enabled: false,
|
|
847
|
+
triggerType: "balance",
|
|
848
|
+
currency: currency.toUpperCase()
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
const payload = {
|
|
853
|
+
enabled: true,
|
|
854
|
+
triggerType: "balance",
|
|
855
|
+
currency: currency.toUpperCase()
|
|
856
|
+
};
|
|
857
|
+
const minorPerMajor = getMinorUnitsPerMajor(currency);
|
|
858
|
+
const minMinor = getStripeMinimumMinor(currency);
|
|
859
|
+
const thresholdRaw = parseNonNegativeNumber(form.thresholdAmountMajor);
|
|
860
|
+
if (thresholdRaw == null) {
|
|
861
|
+
return { ok: false, error: messages.invalidThreshold };
|
|
862
|
+
}
|
|
863
|
+
if (form.thresholdUnit === "credits") {
|
|
864
|
+
const major = estimateCurrencyMajorFromCredits(
|
|
865
|
+
thresholdRaw,
|
|
866
|
+
currency,
|
|
867
|
+
conversion?.creditsPerMinorUnit,
|
|
868
|
+
conversion?.displayExchangeRate
|
|
869
|
+
);
|
|
870
|
+
if (major == null) {
|
|
871
|
+
return { ok: false, error: messages.invalidThreshold };
|
|
872
|
+
}
|
|
873
|
+
payload.thresholdAmountMajor = major;
|
|
874
|
+
} else {
|
|
875
|
+
payload.thresholdAmountMajor = thresholdRaw;
|
|
876
|
+
}
|
|
877
|
+
if (payload.thresholdAmountMajor == null || payload.thresholdAmountMajor <= 0) {
|
|
878
|
+
return { ok: false, error: messages.thresholdTooLow };
|
|
879
|
+
}
|
|
880
|
+
const amountRaw = parsePositiveNumber(form.topupAmountMajor);
|
|
881
|
+
if (amountRaw == null) {
|
|
882
|
+
return {
|
|
883
|
+
ok: false,
|
|
884
|
+
error: interpolate(messages.minTopupAmount, {
|
|
885
|
+
amount: formatPrice(minMinor, currency, { free: "" })
|
|
886
|
+
})
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
const amountMajor = form.topupUnit === "credits" ? estimateCurrencyMajorFromCredits(
|
|
890
|
+
amountRaw,
|
|
891
|
+
currency,
|
|
892
|
+
conversion?.creditsPerMinorUnit,
|
|
893
|
+
conversion?.displayExchangeRate
|
|
894
|
+
) : amountRaw;
|
|
895
|
+
if (amountMajor == null || Math.round(amountMajor * minorPerMajor) < minMinor) {
|
|
896
|
+
return {
|
|
897
|
+
ok: false,
|
|
898
|
+
error: interpolate(messages.minTopupAmount, {
|
|
899
|
+
amount: formatPrice(minMinor, currency, { free: "" })
|
|
900
|
+
})
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
payload.topupAmountMajor = amountMajor;
|
|
904
|
+
if (amountMajor < payload.thresholdAmountMajor) {
|
|
905
|
+
return {
|
|
906
|
+
ok: false,
|
|
907
|
+
error: interpolate(messages.topupBelowThreshold, {
|
|
908
|
+
amount: formatPrice(
|
|
909
|
+
Math.round(payload.thresholdAmountMajor * minorPerMajor),
|
|
910
|
+
currency,
|
|
911
|
+
{ free: "" }
|
|
912
|
+
)
|
|
913
|
+
})
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
return { ok: true, payload };
|
|
917
|
+
}
|
|
918
|
+
function triggerAmountMajorFromConfig(config) {
|
|
919
|
+
const topupCurrency = config.topup.currency.toUpperCase();
|
|
920
|
+
const minorPerMajor = getMinorUnitsPerMajor(topupCurrency);
|
|
921
|
+
const { thresholdAmountMinor } = config.trigger;
|
|
922
|
+
if (!Number.isFinite(thresholdAmountMinor) || thresholdAmountMinor < 0) {
|
|
923
|
+
return null;
|
|
924
|
+
}
|
|
925
|
+
return thresholdAmountMinor / minorPerMajor;
|
|
926
|
+
}
|
|
927
|
+
function configToAutoRechargeInput(config, options) {
|
|
928
|
+
if (!config.enabled) return null;
|
|
929
|
+
const display = options?.display ?? config.display;
|
|
930
|
+
const currency = (display?.currency ?? config.topup.currency ?? options?.currency ?? "USD").toUpperCase();
|
|
931
|
+
if (display?.thresholdAmountMajor != null && display.topupAmountMajor != null) {
|
|
932
|
+
return {
|
|
933
|
+
enabled: true,
|
|
934
|
+
triggerType: "balance",
|
|
935
|
+
thresholdAmountMajor: display.thresholdAmountMajor,
|
|
936
|
+
topupAmountMajor: display.topupAmountMajor,
|
|
937
|
+
currency
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
const thresholdMajor = triggerAmountMajorFromConfig(config);
|
|
941
|
+
const topupAmountMajor = config.topup.amountMinor / getMinorUnitsPerMajor(currency);
|
|
942
|
+
if (thresholdMajor == null || !Number.isFinite(topupAmountMajor) || topupAmountMajor <= 0) {
|
|
943
|
+
return null;
|
|
944
|
+
}
|
|
945
|
+
return {
|
|
946
|
+
enabled: true,
|
|
947
|
+
triggerType: "balance",
|
|
948
|
+
thresholdAmountMajor: Math.max(0, thresholdMajor),
|
|
949
|
+
topupAmountMajor,
|
|
950
|
+
currency
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function configToForm(config, currency) {
|
|
954
|
+
const base = createDefaultAutoRechargeForm(currency);
|
|
955
|
+
const display = config.display;
|
|
956
|
+
if (display?.thresholdAmountMajor != null && display.topupAmountMajor != null) {
|
|
957
|
+
const thresholdStr2 = String(Math.max(0, display.thresholdAmountMajor));
|
|
958
|
+
const topupStr2 = String(display.topupAmountMajor);
|
|
959
|
+
return {
|
|
960
|
+
...base,
|
|
961
|
+
enabled: config.enabled,
|
|
962
|
+
thresholdAmountMajor: thresholdStr2,
|
|
963
|
+
topupAmountMajor: topupStr2,
|
|
964
|
+
...amountAnchors(thresholdStr2, topupStr2, "currency")
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
const thresholdMajor = triggerAmountMajorFromConfig(config);
|
|
968
|
+
const thresholdStr = thresholdMajor != null ? String(Math.max(0, thresholdMajor)) : "0";
|
|
969
|
+
const topupStr = String(config.topup.amountMinor / getMinorUnitsPerMajor(currency));
|
|
970
|
+
return {
|
|
971
|
+
...base,
|
|
972
|
+
enabled: config.enabled,
|
|
973
|
+
thresholdAmountMajor: thresholdStr,
|
|
974
|
+
topupAmountMajor: topupStr,
|
|
975
|
+
...amountAnchors(thresholdStr, topupStr, "currency")
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
function formatAmountWithUnit(value, unit, currency) {
|
|
979
|
+
const num = Number(value);
|
|
980
|
+
if (!value || !Number.isFinite(num)) return "\u2014";
|
|
981
|
+
if (unit === "credits") {
|
|
982
|
+
return `${new Intl.NumberFormat().format(num)} credits`;
|
|
983
|
+
}
|
|
984
|
+
return formatPrice(Math.round(num * getMinorUnitsPerMajor(currency)), currency, { free: "" });
|
|
985
|
+
}
|
|
986
|
+
function buildSummaryLine(form, currency) {
|
|
987
|
+
if (!form.enabled) return null;
|
|
988
|
+
const thresholdDisplay = formatAmountWithUnit(
|
|
989
|
+
form.thresholdAmountMajor,
|
|
990
|
+
form.thresholdUnit,
|
|
991
|
+
currency
|
|
992
|
+
);
|
|
993
|
+
const fixedDisplay = formatAmountWithUnit(form.topupAmountMajor, form.topupUnit, currency);
|
|
994
|
+
return `When my balance falls below ${thresholdDisplay}, add ${fixedDisplay}.`;
|
|
995
|
+
}
|
|
996
|
+
function convertAmountForUnitFlip(value, fromUnit, toUnit, currency, creditsPerMinorUnit, displayExchangeRate) {
|
|
997
|
+
if (fromUnit === toUnit) return value;
|
|
998
|
+
const parsed = Number(value);
|
|
999
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return value;
|
|
1000
|
+
if (fromUnit === "currency" && toUnit === "credits") {
|
|
1001
|
+
const credits = estimateCredits(parsed, currency, creditsPerMinorUnit, displayExchangeRate);
|
|
1002
|
+
return credits != null ? String(credits) : value;
|
|
1003
|
+
}
|
|
1004
|
+
const major = estimateCurrencyMajorFromCredits(
|
|
1005
|
+
parsed,
|
|
1006
|
+
currency,
|
|
1007
|
+
creditsPerMinorUnit,
|
|
1008
|
+
displayExchangeRate
|
|
1009
|
+
);
|
|
1010
|
+
return major != null ? String(major) : value;
|
|
1011
|
+
}
|
|
1012
|
+
function flipUnitValue(anchor, targetUnit, currency, creditsPerMinorUnit, displayExchangeRate) {
|
|
1013
|
+
if (targetUnit === anchor.unit) {
|
|
1014
|
+
return { value: anchor.value, unit: anchor.unit };
|
|
1015
|
+
}
|
|
1016
|
+
const converted = convertAmountForUnitFlip(
|
|
1017
|
+
anchor.value,
|
|
1018
|
+
anchor.unit,
|
|
1019
|
+
targetUnit,
|
|
1020
|
+
currency,
|
|
1021
|
+
creditsPerMinorUnit,
|
|
1022
|
+
displayExchangeRate
|
|
1023
|
+
);
|
|
1024
|
+
return { value: converted, unit: targetUnit };
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// src/primitives/AutoRecharge.tsx
|
|
1028
|
+
import {
|
|
1029
|
+
createContext as createContext4,
|
|
1030
|
+
forwardRef as forwardRef5,
|
|
1031
|
+
useCallback as useCallback3,
|
|
1032
|
+
useContext as useContext5,
|
|
1033
|
+
useEffect as useEffect4,
|
|
1034
|
+
useId,
|
|
1035
|
+
useMemo as useMemo4,
|
|
1036
|
+
useRef as useRef3,
|
|
1037
|
+
useState as useState4
|
|
1038
|
+
} from "react";
|
|
1039
|
+
import { createPortal } from "react-dom";
|
|
1040
|
+
import {
|
|
1041
|
+
Elements,
|
|
1042
|
+
PaymentElement as StripePaymentElement,
|
|
1043
|
+
useElements,
|
|
1044
|
+
useStripe
|
|
1045
|
+
} from "@stripe/react-stripe-js";
|
|
1046
|
+
import { loadStripe } from "@stripe/stripe-js";
|
|
1047
|
+
|
|
1048
|
+
// src/primitives/autoRechargeActivation.ts
|
|
1049
|
+
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1050
|
+
async function waitForAutoRechargeActivation({
|
|
1051
|
+
refresh,
|
|
1052
|
+
getStatus,
|
|
1053
|
+
attempts = 5,
|
|
1054
|
+
delayMs = 800,
|
|
1055
|
+
sleep = defaultSleep
|
|
1056
|
+
}) {
|
|
1057
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
1058
|
+
await refresh(true);
|
|
1059
|
+
if (getStatus() === "active") return true;
|
|
1060
|
+
if (attempt < attempts - 1) await sleep(delayMs);
|
|
1061
|
+
}
|
|
1062
|
+
return getStatus() === "active";
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/primitives/setupIntentReturn.ts
|
|
1066
|
+
var SETUP_INTENT_PARAMS = ["setup_intent", "setup_intent_client_secret", "redirect_status"];
|
|
1067
|
+
function readSetupIntentClientSecret(search) {
|
|
1068
|
+
return new URLSearchParams(search).get("setup_intent_client_secret");
|
|
1069
|
+
}
|
|
1070
|
+
function stripSetupIntentParams() {
|
|
1071
|
+
if (typeof window === "undefined") return;
|
|
1072
|
+
const url = new URL(window.location.href);
|
|
1073
|
+
let changed = false;
|
|
1074
|
+
for (const param of SETUP_INTENT_PARAMS) {
|
|
1075
|
+
if (url.searchParams.has(param)) {
|
|
1076
|
+
url.searchParams.delete(param);
|
|
1077
|
+
changed = true;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
if (!changed) return;
|
|
1081
|
+
const query = url.searchParams.toString();
|
|
1082
|
+
window.history.replaceState({}, "", `${url.pathname}${query ? `?${query}` : ""}${url.hash}`);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
// src/primitives/AutoRecharge.tsx
|
|
1086
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1087
|
+
var AutoRechargeContext = createContext4(null);
|
|
1088
|
+
function useAutoRechargeCtx(part) {
|
|
1089
|
+
const ctx = useContext5(AutoRechargeContext);
|
|
1090
|
+
if (!ctx) {
|
|
1091
|
+
throw new Error(`AutoRecharge.${part} must be rendered inside <AutoRecharge.Root>.`);
|
|
1092
|
+
}
|
|
1093
|
+
return ctx;
|
|
1094
|
+
}
|
|
1095
|
+
function getCurrencySymbol(currency) {
|
|
1096
|
+
try {
|
|
1097
|
+
const parts = new Intl.NumberFormat("en", { style: "currency", currency }).formatToParts(0);
|
|
1098
|
+
const sym = parts.find((p) => p.type === "currency");
|
|
1099
|
+
return sym?.value ?? currency.toUpperCase();
|
|
1100
|
+
} catch {
|
|
1101
|
+
return currency.toUpperCase();
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
var stripePromiseCache = /* @__PURE__ */ new Map();
|
|
1105
|
+
function getStripeCacheKey(publishableKey, accountId) {
|
|
1106
|
+
return accountId ? `${publishableKey}:${accountId}` : publishableKey;
|
|
1107
|
+
}
|
|
1108
|
+
var Root4 = forwardRef5(function AutoRechargeRoot({
|
|
1109
|
+
currency = "USD",
|
|
1110
|
+
defaultThresholdAmountMajor,
|
|
1111
|
+
defaultTopupAmountMajor,
|
|
1112
|
+
open: openProp,
|
|
1113
|
+
defaultOpen = false,
|
|
1114
|
+
onOpenChange,
|
|
1115
|
+
onSetupRequired,
|
|
1116
|
+
onSaved,
|
|
1117
|
+
onDisabled,
|
|
1118
|
+
deferCardSetup = false,
|
|
1119
|
+
onPendingConfig,
|
|
1120
|
+
asChild,
|
|
1121
|
+
children,
|
|
1122
|
+
className,
|
|
1123
|
+
...rest
|
|
1124
|
+
}, forwardedRef) {
|
|
1125
|
+
const solva = useContext5(SolvaPayContext);
|
|
1126
|
+
if (!solva) throw new MissingProviderError("AutoRecharge");
|
|
1127
|
+
const autoRecharge = useAutoRecharge();
|
|
1128
|
+
const { creditsPerMinorUnit, displayExchangeRate } = useBalance();
|
|
1129
|
+
const copy = useCopy();
|
|
1130
|
+
const titleId = useId();
|
|
1131
|
+
const triggerRef = useRef3(null);
|
|
1132
|
+
const defaultTopup = defaultTopupAmountMajor ?? defaultThresholdAmountMajor ?? void 0;
|
|
1133
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState4(defaultOpen);
|
|
1134
|
+
const isControlled = openProp !== void 0;
|
|
1135
|
+
const open = isControlled ? openProp : uncontrolledOpen;
|
|
1136
|
+
const setOpen = useCallback3(
|
|
1137
|
+
(next) => {
|
|
1138
|
+
if (!isControlled) {
|
|
1139
|
+
setUncontrolledOpen(next);
|
|
1140
|
+
}
|
|
1141
|
+
onOpenChange?.(next);
|
|
1142
|
+
},
|
|
1143
|
+
[isControlled, onOpenChange]
|
|
1144
|
+
);
|
|
1145
|
+
const registerTriggerRef = useCallback3((node) => {
|
|
1146
|
+
triggerRef.current = node;
|
|
1147
|
+
}, []);
|
|
1148
|
+
const focusTrigger = useCallback3(() => {
|
|
1149
|
+
triggerRef.current?.focus();
|
|
1150
|
+
}, []);
|
|
1151
|
+
const [form, setForm] = useState4(
|
|
1152
|
+
() => autoRecharge.config ? configToForm(autoRecharge.config, currency) : createDefaultAutoRechargeForm(currency, defaultTopup)
|
|
1153
|
+
);
|
|
1154
|
+
const [validationError, setValidationError] = useState4(null);
|
|
1155
|
+
const [statusMessage, setStatusMessage] = useState4(null);
|
|
1156
|
+
const [setup, setSetup] = useState4(null);
|
|
1157
|
+
const latestConfigRef = useRef3(autoRecharge.config);
|
|
1158
|
+
useEffect4(() => {
|
|
1159
|
+
latestConfigRef.current = autoRecharge.config;
|
|
1160
|
+
}, [autoRecharge.config]);
|
|
1161
|
+
useEffect4(() => {
|
|
1162
|
+
if (autoRecharge.config) {
|
|
1163
|
+
setForm(configToForm(autoRecharge.config, currency));
|
|
1164
|
+
}
|
|
1165
|
+
}, [autoRecharge.config, currency]);
|
|
1166
|
+
const canToggleUnits = creditsPerMinorUnit != null && creditsPerMinorUnit > 0;
|
|
1167
|
+
const rate = displayExchangeRate ?? 1;
|
|
1168
|
+
const isApproximate = rate !== 1;
|
|
1169
|
+
const emitValidation = useCallback3(
|
|
1170
|
+
(next) => {
|
|
1171
|
+
const result = validateAutoRechargeForm(
|
|
1172
|
+
next,
|
|
1173
|
+
currency,
|
|
1174
|
+
{ creditsPerMinorUnit, displayExchangeRate },
|
|
1175
|
+
copy.autoRecharge
|
|
1176
|
+
);
|
|
1177
|
+
if (!result.ok) {
|
|
1178
|
+
setValidationError(result.error);
|
|
1179
|
+
return null;
|
|
1180
|
+
}
|
|
1181
|
+
setValidationError(null);
|
|
1182
|
+
return result.payload;
|
|
1183
|
+
},
|
|
1184
|
+
[currency, creditsPerMinorUnit, displayExchangeRate, copy.autoRecharge]
|
|
1185
|
+
);
|
|
1186
|
+
const updateForm = useCallback3(
|
|
1187
|
+
(patch) => {
|
|
1188
|
+
setForm((prev) => {
|
|
1189
|
+
const next = { ...prev, ...patch };
|
|
1190
|
+
emitValidation(next);
|
|
1191
|
+
return next;
|
|
1192
|
+
});
|
|
1193
|
+
},
|
|
1194
|
+
[emitValidation]
|
|
1195
|
+
);
|
|
1196
|
+
const resetForm = useCallback3(() => {
|
|
1197
|
+
if (autoRecharge.config) {
|
|
1198
|
+
setForm(configToForm(autoRecharge.config, currency));
|
|
1199
|
+
} else {
|
|
1200
|
+
setForm(createDefaultAutoRechargeForm(currency, defaultTopup));
|
|
1201
|
+
}
|
|
1202
|
+
setValidationError(null);
|
|
1203
|
+
}, [autoRecharge.config, currency, defaultTopup]);
|
|
1204
|
+
const flipUnit = useCallback3(
|
|
1205
|
+
(valueKey, unitKey, baseValueKey, baseUnitKey, currentUnit) => {
|
|
1206
|
+
const nextUnit = currentUnit === "currency" ? "credits" : "currency";
|
|
1207
|
+
setForm((prev) => {
|
|
1208
|
+
const anchor = { value: prev[baseValueKey], unit: prev[baseUnitKey] };
|
|
1209
|
+
const flipped = flipUnitValue(
|
|
1210
|
+
anchor,
|
|
1211
|
+
nextUnit,
|
|
1212
|
+
currency,
|
|
1213
|
+
creditsPerMinorUnit,
|
|
1214
|
+
displayExchangeRate
|
|
1215
|
+
);
|
|
1216
|
+
const next = {
|
|
1217
|
+
...prev,
|
|
1218
|
+
[unitKey]: flipped.unit,
|
|
1219
|
+
[valueKey]: flipped.value
|
|
1220
|
+
};
|
|
1221
|
+
emitValidation(next);
|
|
1222
|
+
return next;
|
|
1223
|
+
});
|
|
1224
|
+
},
|
|
1225
|
+
[currency, creditsPerMinorUnit, displayExchangeRate, emitValidation]
|
|
1226
|
+
);
|
|
1227
|
+
const fixedTopupHint = useMemo4(() => {
|
|
1228
|
+
const parsed = Number(form.topupAmountMajor);
|
|
1229
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return null;
|
|
1230
|
+
if (form.topupUnit === "currency") {
|
|
1231
|
+
const credits = estimateCredits(parsed, currency, creditsPerMinorUnit, displayExchangeRate);
|
|
1232
|
+
if (credits == null) return null;
|
|
1233
|
+
return { credits, approximate: isApproximate };
|
|
1234
|
+
}
|
|
1235
|
+
const major = estimateCurrencyMajorFromCredits(
|
|
1236
|
+
parsed,
|
|
1237
|
+
currency,
|
|
1238
|
+
creditsPerMinorUnit,
|
|
1239
|
+
displayExchangeRate
|
|
1240
|
+
);
|
|
1241
|
+
if (major == null) return null;
|
|
1242
|
+
return { major, approximate: isApproximate };
|
|
1243
|
+
}, [
|
|
1244
|
+
form.topupAmountMajor,
|
|
1245
|
+
form.topupUnit,
|
|
1246
|
+
currency,
|
|
1247
|
+
creditsPerMinorUnit,
|
|
1248
|
+
displayExchangeRate,
|
|
1249
|
+
isApproximate
|
|
1250
|
+
]);
|
|
1251
|
+
const summaryLine = useMemo4(() => buildSummaryLine(form, currency), [form, currency]);
|
|
1252
|
+
const savedSummaryLine = useMemo4(() => {
|
|
1253
|
+
if (!autoRecharge.config?.enabled) return null;
|
|
1254
|
+
return buildSummaryLine(
|
|
1255
|
+
configToForm(autoRecharge.config, currency),
|
|
1256
|
+
currency
|
|
1257
|
+
);
|
|
1258
|
+
}, [autoRecharge.config, currency]);
|
|
1259
|
+
const save = useCallback3(async () => {
|
|
1260
|
+
const payload = emitValidation(form);
|
|
1261
|
+
if (!payload) return;
|
|
1262
|
+
const saveInput = deferCardSetup ? { ...payload, deferSetupIntent: true } : payload;
|
|
1263
|
+
const result = await autoRecharge.save(saveInput);
|
|
1264
|
+
if (result.setupClientSecret) {
|
|
1265
|
+
setSetup(result);
|
|
1266
|
+
setStatusMessage(copy.autoRecharge.setupRequiredMessage);
|
|
1267
|
+
await onSetupRequired?.(result);
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
setSetup(null);
|
|
1271
|
+
if (deferCardSetup) {
|
|
1272
|
+
await onPendingConfig?.(payload);
|
|
1273
|
+
}
|
|
1274
|
+
setStatusMessage(
|
|
1275
|
+
payload.enabled ? copy.autoRecharge.savedMessage : copy.autoRecharge.disabledMessage
|
|
1276
|
+
);
|
|
1277
|
+
setOpen(false);
|
|
1278
|
+
await onSaved?.(result);
|
|
1279
|
+
}, [
|
|
1280
|
+
autoRecharge,
|
|
1281
|
+
copy.autoRecharge,
|
|
1282
|
+
deferCardSetup,
|
|
1283
|
+
emitValidation,
|
|
1284
|
+
form,
|
|
1285
|
+
onPendingConfig,
|
|
1286
|
+
onSaved,
|
|
1287
|
+
onSetupRequired,
|
|
1288
|
+
setOpen
|
|
1289
|
+
]);
|
|
1290
|
+
const disable = useCallback3(async () => {
|
|
1291
|
+
await autoRecharge.disable();
|
|
1292
|
+
setStatusMessage(copy.autoRecharge.disabledMessage);
|
|
1293
|
+
setSetup(null);
|
|
1294
|
+
await onDisabled?.();
|
|
1295
|
+
}, [autoRecharge, copy.autoRecharge, onDisabled]);
|
|
1296
|
+
const completeSetup = useCallback3(async () => {
|
|
1297
|
+
const activated = await waitForAutoRechargeActivation({
|
|
1298
|
+
refresh: autoRecharge.refresh,
|
|
1299
|
+
getStatus: () => latestConfigRef.current?.status
|
|
1300
|
+
});
|
|
1301
|
+
setSetup(null);
|
|
1302
|
+
if (!form.enabled) return;
|
|
1303
|
+
if (activated) {
|
|
1304
|
+
setStatusMessage(copy.autoRecharge.savedMessage);
|
|
1305
|
+
setOpen(false);
|
|
1306
|
+
} else {
|
|
1307
|
+
setStatusMessage(copy.autoRecharge.setupAwaitingConfirmation);
|
|
1308
|
+
}
|
|
1309
|
+
}, [autoRecharge, copy.autoRecharge, form.enabled, setOpen]);
|
|
1310
|
+
const dataState = setup ? "setup" : autoRecharge.error ? "error" : autoRecharge.loading ? "loading" : autoRecharge.saving ? "saving" : autoRecharge.disabling ? "disabling" : "idle";
|
|
1311
|
+
const ctx = useMemo4(
|
|
1312
|
+
() => ({
|
|
1313
|
+
form,
|
|
1314
|
+
updateForm,
|
|
1315
|
+
resetForm,
|
|
1316
|
+
validationError,
|
|
1317
|
+
currency,
|
|
1318
|
+
config: autoRecharge.config,
|
|
1319
|
+
loading: autoRecharge.loading,
|
|
1320
|
+
saving: autoRecharge.saving,
|
|
1321
|
+
disabling: autoRecharge.disabling,
|
|
1322
|
+
error: autoRecharge.error,
|
|
1323
|
+
statusMessage,
|
|
1324
|
+
setup,
|
|
1325
|
+
dataState,
|
|
1326
|
+
creditsPerMinorUnit,
|
|
1327
|
+
displayExchangeRate,
|
|
1328
|
+
canToggleUnits,
|
|
1329
|
+
isApproximate,
|
|
1330
|
+
summaryLine,
|
|
1331
|
+
savedSummaryLine,
|
|
1332
|
+
deferCardSetup,
|
|
1333
|
+
fixedTopupHint: fixedTopupHint && "credits" in fixedTopupHint ? String(fixedTopupHint.credits) : fixedTopupHint && "major" in fixedTopupHint ? formatPrice(
|
|
1334
|
+
Math.round(fixedTopupHint.major * getMinorUnitsPerMajor(currency)),
|
|
1335
|
+
currency,
|
|
1336
|
+
{ free: "" }
|
|
1337
|
+
) : null,
|
|
1338
|
+
open,
|
|
1339
|
+
setOpen,
|
|
1340
|
+
titleId,
|
|
1341
|
+
registerTriggerRef,
|
|
1342
|
+
focusTrigger,
|
|
1343
|
+
save,
|
|
1344
|
+
disable,
|
|
1345
|
+
completeSetup,
|
|
1346
|
+
flipUnit
|
|
1347
|
+
}),
|
|
1348
|
+
[
|
|
1349
|
+
form,
|
|
1350
|
+
updateForm,
|
|
1351
|
+
resetForm,
|
|
1352
|
+
validationError,
|
|
1353
|
+
currency,
|
|
1354
|
+
autoRecharge.config,
|
|
1355
|
+
autoRecharge.loading,
|
|
1356
|
+
autoRecharge.saving,
|
|
1357
|
+
autoRecharge.disabling,
|
|
1358
|
+
autoRecharge.error,
|
|
1359
|
+
statusMessage,
|
|
1360
|
+
setup,
|
|
1361
|
+
dataState,
|
|
1362
|
+
creditsPerMinorUnit,
|
|
1363
|
+
displayExchangeRate,
|
|
1364
|
+
canToggleUnits,
|
|
1365
|
+
isApproximate,
|
|
1366
|
+
summaryLine,
|
|
1367
|
+
savedSummaryLine,
|
|
1368
|
+
deferCardSetup,
|
|
1369
|
+
fixedTopupHint,
|
|
1370
|
+
open,
|
|
1371
|
+
setOpen,
|
|
1372
|
+
titleId,
|
|
1373
|
+
registerTriggerRef,
|
|
1374
|
+
focusTrigger,
|
|
1375
|
+
save,
|
|
1376
|
+
disable,
|
|
1377
|
+
completeSetup,
|
|
1378
|
+
flipUnit
|
|
1379
|
+
]
|
|
1380
|
+
);
|
|
1381
|
+
const Comp = asChild ? Slot : "section";
|
|
1382
|
+
return /* @__PURE__ */ jsx6(AutoRechargeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx6(
|
|
1383
|
+
Comp,
|
|
1384
|
+
{
|
|
1385
|
+
ref: forwardedRef,
|
|
1386
|
+
className,
|
|
1387
|
+
"aria-label": "Automatic credit top-up",
|
|
1388
|
+
"data-solvapay-auto-recharge": "",
|
|
1389
|
+
"data-state": dataState,
|
|
1390
|
+
...rest,
|
|
1391
|
+
children
|
|
1392
|
+
}
|
|
1393
|
+
) });
|
|
1394
|
+
});
|
|
1395
|
+
var Loading4 = forwardRef5(
|
|
1396
|
+
function AutoRechargeLoading({ className, children, ...rest }, forwardedRef) {
|
|
1397
|
+
const ctx = useAutoRechargeCtx("Loading");
|
|
1398
|
+
if (!ctx.loading) return null;
|
|
1399
|
+
return /* @__PURE__ */ jsx6("p", { ref: forwardedRef, className, "data-solvapay-auto-recharge-loading": "", ...rest, children: children ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1400
|
+
/* @__PURE__ */ jsx6(Spinner, { size: "sm" }),
|
|
1401
|
+
" Loading auto-recharge settings\u2026"
|
|
1402
|
+
] }) });
|
|
1403
|
+
}
|
|
1404
|
+
);
|
|
1405
|
+
var Card = forwardRef5(function AutoRechargeCard({ className, children, ...rest }, forwardedRef) {
|
|
1406
|
+
return /* @__PURE__ */ jsx6(
|
|
1407
|
+
"section",
|
|
1408
|
+
{
|
|
1409
|
+
ref: forwardedRef,
|
|
1410
|
+
className,
|
|
1411
|
+
"data-solvapay-auto-recharge-card": "",
|
|
1412
|
+
...rest,
|
|
1413
|
+
children
|
|
1414
|
+
}
|
|
1415
|
+
);
|
|
1416
|
+
});
|
|
1417
|
+
var CardHeading = forwardRef5(
|
|
1418
|
+
function AutoRechargeCardHeading({ className, children, ...rest }, forwardedRef) {
|
|
1419
|
+
const copy = useCopy();
|
|
1420
|
+
return /* @__PURE__ */ jsx6(
|
|
1421
|
+
"h3",
|
|
1422
|
+
{
|
|
1423
|
+
ref: forwardedRef,
|
|
1424
|
+
className,
|
|
1425
|
+
"data-solvapay-auto-recharge-card-heading": "",
|
|
1426
|
+
...rest,
|
|
1427
|
+
children: children ?? copy.autoRecharge.heading
|
|
1428
|
+
}
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
);
|
|
1432
|
+
var CardSummary = forwardRef5(
|
|
1433
|
+
function AutoRechargeCardSummary({ className, children, ...rest }, forwardedRef) {
|
|
1434
|
+
const ctx = useAutoRechargeCtx("CardSummary");
|
|
1435
|
+
const copy = useCopy();
|
|
1436
|
+
const text = ctx.savedSummaryLine ?? copy.autoRecharge.notConfiguredHint;
|
|
1437
|
+
return /* @__PURE__ */ jsx6(
|
|
1438
|
+
"p",
|
|
1439
|
+
{
|
|
1440
|
+
ref: forwardedRef,
|
|
1441
|
+
className,
|
|
1442
|
+
"data-solvapay-auto-recharge-card-summary": "",
|
|
1443
|
+
...rest,
|
|
1444
|
+
children: children ?? text
|
|
1445
|
+
}
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
);
|
|
1449
|
+
var Trigger = forwardRef5(function AutoRechargeTrigger({ asChild, onClick, children, className, ...rest }, forwardedRef) {
|
|
1450
|
+
const ctx = useAutoRechargeCtx("Trigger");
|
|
1451
|
+
const copy = useCopy();
|
|
1452
|
+
const hasExistingConfig = Boolean(ctx.config?.enabled);
|
|
1453
|
+
const label = hasExistingConfig ? copy.autoRecharge.modifyTriggerLabel : copy.autoRecharge.setupTriggerLabel;
|
|
1454
|
+
const setRefs = (node) => {
|
|
1455
|
+
ctx.registerTriggerRef(node);
|
|
1456
|
+
if (typeof forwardedRef === "function") {
|
|
1457
|
+
forwardedRef(node);
|
|
1458
|
+
} else if (forwardedRef) {
|
|
1459
|
+
forwardedRef.current = node;
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
const commonProps = {
|
|
1463
|
+
"data-solvapay-auto-recharge-trigger": "",
|
|
1464
|
+
type: "button",
|
|
1465
|
+
"aria-haspopup": "dialog",
|
|
1466
|
+
"aria-expanded": ctx.open,
|
|
1467
|
+
disabled: ctx.loading,
|
|
1468
|
+
onClick: composeEventHandlers(onClick, (event) => {
|
|
1469
|
+
event.preventDefault();
|
|
1470
|
+
ctx.resetForm();
|
|
1471
|
+
ctx.setOpen(true);
|
|
1472
|
+
}),
|
|
1473
|
+
className,
|
|
1474
|
+
...rest
|
|
1475
|
+
};
|
|
1476
|
+
if (asChild) {
|
|
1477
|
+
return /* @__PURE__ */ jsx6(Slot, { ref: setRefs, ...commonProps, children: children ?? label });
|
|
1478
|
+
}
|
|
1479
|
+
return /* @__PURE__ */ jsx6("button", { ref: setRefs, ...commonProps, children: children ?? label });
|
|
1480
|
+
});
|
|
1481
|
+
var Overlay = forwardRef5(
|
|
1482
|
+
function AutoRechargeOverlay({ onClick, className, ...rest }, forwardedRef) {
|
|
1483
|
+
const ctx = useAutoRechargeCtx("Overlay");
|
|
1484
|
+
return /* @__PURE__ */ jsx6(
|
|
1485
|
+
"div",
|
|
1486
|
+
{
|
|
1487
|
+
ref: forwardedRef,
|
|
1488
|
+
className,
|
|
1489
|
+
"data-solvapay-auto-recharge-overlay": "",
|
|
1490
|
+
"aria-hidden": "true",
|
|
1491
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
1492
|
+
ctx.resetForm();
|
|
1493
|
+
ctx.setOpen(false);
|
|
1494
|
+
ctx.focusTrigger();
|
|
1495
|
+
}),
|
|
1496
|
+
...rest
|
|
1497
|
+
}
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
);
|
|
1501
|
+
var Content = forwardRef5(function AutoRechargeContent({ className, children, ...rest }, forwardedRef) {
|
|
1502
|
+
const ctx = useAutoRechargeCtx("Content");
|
|
1503
|
+
const panelRef = useRef3(null);
|
|
1504
|
+
useEffect4(() => {
|
|
1505
|
+
if (!ctx.open) return;
|
|
1506
|
+
const handleKeyDown = (event) => {
|
|
1507
|
+
if (event.key === "Escape") {
|
|
1508
|
+
ctx.resetForm();
|
|
1509
|
+
ctx.setOpen(false);
|
|
1510
|
+
ctx.focusTrigger();
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1514
|
+
const focusTarget = panelRef.current?.querySelector(
|
|
1515
|
+
'button:not([disabled]), input:not([disabled]), [href], [tabindex]:not([tabindex="-1"])'
|
|
1516
|
+
);
|
|
1517
|
+
focusTarget?.focus();
|
|
1518
|
+
return () => {
|
|
1519
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1520
|
+
};
|
|
1521
|
+
}, [ctx.open, ctx.resetForm, ctx.setOpen, ctx.focusTrigger]);
|
|
1522
|
+
if (!ctx.open || typeof document === "undefined") return null;
|
|
1523
|
+
return createPortal(
|
|
1524
|
+
/* @__PURE__ */ jsxs2("div", { "data-solvapay-auto-recharge-portal": "", children: [
|
|
1525
|
+
/* @__PURE__ */ jsx6(Overlay, {}),
|
|
1526
|
+
/* @__PURE__ */ jsx6(
|
|
1527
|
+
"div",
|
|
1528
|
+
{
|
|
1529
|
+
ref: (node) => {
|
|
1530
|
+
panelRef.current = node;
|
|
1531
|
+
if (typeof forwardedRef === "function") {
|
|
1532
|
+
forwardedRef(node);
|
|
1533
|
+
} else if (forwardedRef) {
|
|
1534
|
+
forwardedRef.current = node;
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
role: "dialog",
|
|
1538
|
+
"aria-modal": "true",
|
|
1539
|
+
"aria-labelledby": ctx.titleId,
|
|
1540
|
+
className,
|
|
1541
|
+
"data-solvapay-auto-recharge-content": "",
|
|
1542
|
+
...rest,
|
|
1543
|
+
children
|
|
1544
|
+
}
|
|
1545
|
+
)
|
|
1546
|
+
] }),
|
|
1547
|
+
document.body
|
|
1548
|
+
);
|
|
1549
|
+
});
|
|
1550
|
+
var Title = forwardRef5(
|
|
1551
|
+
function AutoRechargeTitle({ className, children, ...rest }, forwardedRef) {
|
|
1552
|
+
const ctx = useAutoRechargeCtx("Title");
|
|
1553
|
+
const copy = useCopy();
|
|
1554
|
+
return /* @__PURE__ */ jsx6(
|
|
1555
|
+
"h2",
|
|
1556
|
+
{
|
|
1557
|
+
ref: forwardedRef,
|
|
1558
|
+
id: ctx.titleId,
|
|
1559
|
+
className,
|
|
1560
|
+
"data-solvapay-auto-recharge-title": "",
|
|
1561
|
+
...rest,
|
|
1562
|
+
children: children ?? copy.autoRecharge.settingsHeading
|
|
1563
|
+
}
|
|
1564
|
+
);
|
|
1565
|
+
}
|
|
1566
|
+
);
|
|
1567
|
+
var EnableQuestion = forwardRef5(
|
|
1568
|
+
function AutoRechargeEnableQuestion({ className, children, ...rest }, forwardedRef) {
|
|
1569
|
+
const copy = useCopy();
|
|
1570
|
+
return /* @__PURE__ */ jsx6("p", { ref: forwardedRef, className, "data-solvapay-auto-recharge-question": "", ...rest, children: children ?? copy.autoRecharge.enableQuestion });
|
|
1571
|
+
}
|
|
1572
|
+
);
|
|
1573
|
+
var EnableSentence = forwardRef5(
|
|
1574
|
+
function AutoRechargeEnableSentence({ className, children, ...rest }, forwardedRef) {
|
|
1575
|
+
const copy = useCopy();
|
|
1576
|
+
return /* @__PURE__ */ jsx6(
|
|
1577
|
+
"label",
|
|
1578
|
+
{
|
|
1579
|
+
ref: forwardedRef,
|
|
1580
|
+
className,
|
|
1581
|
+
"data-solvapay-auto-recharge-enable-sentence": "",
|
|
1582
|
+
...rest,
|
|
1583
|
+
children: children ?? copy.autoRecharge.enableSentence
|
|
1584
|
+
}
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
);
|
|
1588
|
+
var EnableRow = forwardRef5(
|
|
1589
|
+
function AutoRechargeEnableRow({ className, children, ...rest }, forwardedRef) {
|
|
1590
|
+
const enableId = useId();
|
|
1591
|
+
return /* @__PURE__ */ jsx6(
|
|
1592
|
+
"div",
|
|
1593
|
+
{
|
|
1594
|
+
ref: forwardedRef,
|
|
1595
|
+
className,
|
|
1596
|
+
"data-solvapay-auto-recharge-enable-row": "",
|
|
1597
|
+
...rest,
|
|
1598
|
+
children: children ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1599
|
+
/* @__PURE__ */ jsx6(EnableSwitch, { appearance: "checkbox", id: enableId }),
|
|
1600
|
+
/* @__PURE__ */ jsx6(EnableSentence, { htmlFor: enableId })
|
|
1601
|
+
] })
|
|
1602
|
+
}
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
);
|
|
1606
|
+
var CancelButton = forwardRef5(
|
|
1607
|
+
function AutoRechargeCancelButton({ asChild, onClick, children, className, ...rest }, forwardedRef) {
|
|
1608
|
+
const ctx = useAutoRechargeCtx("CancelButton");
|
|
1609
|
+
const copy = useCopy();
|
|
1610
|
+
const commonProps = {
|
|
1611
|
+
"data-solvapay-auto-recharge-cancel": "",
|
|
1612
|
+
type: "button",
|
|
1613
|
+
onClick: composeEventHandlers(onClick, (event) => {
|
|
1614
|
+
event.preventDefault();
|
|
1615
|
+
ctx.resetForm();
|
|
1616
|
+
ctx.setOpen(false);
|
|
1617
|
+
ctx.focusTrigger();
|
|
1618
|
+
}),
|
|
1619
|
+
className,
|
|
1620
|
+
...rest
|
|
1621
|
+
};
|
|
1622
|
+
if (asChild) {
|
|
1623
|
+
return /* @__PURE__ */ jsx6(
|
|
1624
|
+
Slot,
|
|
1625
|
+
{
|
|
1626
|
+
ref: forwardedRef,
|
|
1627
|
+
...commonProps,
|
|
1628
|
+
children: children ?? copy.autoRecharge.cancelButton
|
|
1629
|
+
}
|
|
1630
|
+
);
|
|
1631
|
+
}
|
|
1632
|
+
return /* @__PURE__ */ jsx6("button", { ref: forwardedRef, ...commonProps, children: children ?? copy.autoRecharge.cancelButton });
|
|
1633
|
+
}
|
|
1634
|
+
);
|
|
1635
|
+
var Header = forwardRef5(
|
|
1636
|
+
function AutoRechargeHeader({ className, ...rest }, forwardedRef) {
|
|
1637
|
+
const copy = useCopy();
|
|
1638
|
+
const headingId = useId();
|
|
1639
|
+
return /* @__PURE__ */ jsxs2(
|
|
1640
|
+
"header",
|
|
1641
|
+
{
|
|
1642
|
+
ref: forwardedRef,
|
|
1643
|
+
className,
|
|
1644
|
+
"data-solvapay-auto-recharge-header": "",
|
|
1645
|
+
...rest,
|
|
1646
|
+
children: [
|
|
1647
|
+
/* @__PURE__ */ jsxs2("section", { "data-solvapay-auto-recharge-heading-group": "", children: [
|
|
1648
|
+
/* @__PURE__ */ jsx6("h3", { id: headingId, "data-solvapay-auto-recharge-heading": "", children: copy.autoRecharge.heading }),
|
|
1649
|
+
/* @__PURE__ */ jsx6(Description, {})
|
|
1650
|
+
] }),
|
|
1651
|
+
/* @__PURE__ */ jsx6(EnableSwitch, { "aria-labelledby": headingId })
|
|
1652
|
+
]
|
|
1653
|
+
}
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
);
|
|
1657
|
+
var Description = forwardRef5(
|
|
1658
|
+
function AutoRechargeDescription({ className, children, ...rest }, forwardedRef) {
|
|
1659
|
+
const copy = useCopy();
|
|
1660
|
+
return /* @__PURE__ */ jsx6(
|
|
1661
|
+
"p",
|
|
1662
|
+
{
|
|
1663
|
+
ref: forwardedRef,
|
|
1664
|
+
className,
|
|
1665
|
+
"data-solvapay-auto-recharge-description": "",
|
|
1666
|
+
...rest,
|
|
1667
|
+
children: children ?? copy.autoRecharge.description
|
|
1668
|
+
}
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
);
|
|
1672
|
+
var EnableSwitch = forwardRef5(
|
|
1673
|
+
function AutoRechargeEnableSwitch({ asChild, appearance = "switch", onChange, className, ...rest }, forwardedRef) {
|
|
1674
|
+
const ctx = useAutoRechargeCtx("EnableSwitch");
|
|
1675
|
+
const copy = useCopy();
|
|
1676
|
+
const commonProps = {
|
|
1677
|
+
"data-solvapay-auto-recharge-enable": "",
|
|
1678
|
+
"data-appearance": appearance,
|
|
1679
|
+
type: "checkbox",
|
|
1680
|
+
...appearance === "switch" ? { role: "switch", "aria-checked": ctx.form.enabled } : {},
|
|
1681
|
+
checked: ctx.form.enabled,
|
|
1682
|
+
"aria-label": copy.autoRecharge.enableLabel,
|
|
1683
|
+
disabled: ctx.loading || ctx.saving || ctx.disabling || !!ctx.setup,
|
|
1684
|
+
onChange: composeEventHandlers(onChange, (event) => {
|
|
1685
|
+
ctx.updateForm({ enabled: event.currentTarget.checked });
|
|
1686
|
+
}),
|
|
1687
|
+
className,
|
|
1688
|
+
...rest
|
|
1689
|
+
};
|
|
1690
|
+
if (asChild) {
|
|
1691
|
+
return /* @__PURE__ */ jsx6(
|
|
1692
|
+
Slot,
|
|
1693
|
+
{
|
|
1694
|
+
ref: forwardedRef,
|
|
1695
|
+
...commonProps
|
|
1696
|
+
}
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
return /* @__PURE__ */ jsx6("input", { ref: forwardedRef, ...commonProps });
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1702
|
+
var Fields = forwardRef5(
|
|
1703
|
+
function AutoRechargeFields({ className, children, ...rest }, forwardedRef) {
|
|
1704
|
+
const ctx = useAutoRechargeCtx("Fields");
|
|
1705
|
+
const copy = useCopy();
|
|
1706
|
+
if (!ctx.form.enabled) return null;
|
|
1707
|
+
return /* @__PURE__ */ jsxs2(
|
|
1708
|
+
"fieldset",
|
|
1709
|
+
{
|
|
1710
|
+
ref: forwardedRef,
|
|
1711
|
+
className,
|
|
1712
|
+
disabled: ctx.saving || ctx.disabling,
|
|
1713
|
+
"data-solvapay-auto-recharge-fields": "",
|
|
1714
|
+
"data-solvapay-auto-recharge-body": "",
|
|
1715
|
+
"data-state": "open",
|
|
1716
|
+
...rest,
|
|
1717
|
+
children: [
|
|
1718
|
+
/* @__PURE__ */ jsx6("legend", { className: "sr-only", children: copy.autoRecharge.heading }),
|
|
1719
|
+
children ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1720
|
+
/* @__PURE__ */ jsx6(Summary2, {}),
|
|
1721
|
+
/* @__PURE__ */ jsx6(ThresholdField, {}),
|
|
1722
|
+
/* @__PURE__ */ jsx6(TopupField, {}),
|
|
1723
|
+
/* @__PURE__ */ jsx6(ValidationError, {})
|
|
1724
|
+
] })
|
|
1725
|
+
]
|
|
1726
|
+
}
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
);
|
|
1730
|
+
var Setup = forwardRef5(
|
|
1731
|
+
function AutoRechargeSetup({ className, children, ...rest }, forwardedRef) {
|
|
1732
|
+
const ctx = useAutoRechargeCtx("Setup");
|
|
1733
|
+
if (!ctx.setup?.setupClientSecret) return null;
|
|
1734
|
+
return /* @__PURE__ */ jsx6(
|
|
1735
|
+
"div",
|
|
1736
|
+
{
|
|
1737
|
+
ref: forwardedRef,
|
|
1738
|
+
className,
|
|
1739
|
+
"data-solvapay-auto-recharge-setup-panel": "",
|
|
1740
|
+
...rest,
|
|
1741
|
+
children: children ?? /* @__PURE__ */ jsx6(CardSetup, { setup: ctx.setup, onComplete: ctx.completeSetup })
|
|
1742
|
+
}
|
|
1743
|
+
);
|
|
1744
|
+
}
|
|
1745
|
+
);
|
|
1746
|
+
var Body = forwardRef5(
|
|
1747
|
+
function AutoRechargeBody({ className, children, ...rest }, forwardedRef) {
|
|
1748
|
+
const ctx = useAutoRechargeCtx("Body");
|
|
1749
|
+
if (ctx.setup?.setupClientSecret) {
|
|
1750
|
+
return /* @__PURE__ */ jsx6(Setup, { className });
|
|
1751
|
+
}
|
|
1752
|
+
if (!ctx.form.enabled) return null;
|
|
1753
|
+
return /* @__PURE__ */ jsx6(Fields, { ref: forwardedRef, className, ...rest, children: children ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1754
|
+
/* @__PURE__ */ jsx6(Summary2, {}),
|
|
1755
|
+
/* @__PURE__ */ jsx6(ThresholdField, {}),
|
|
1756
|
+
/* @__PURE__ */ jsx6(TopupField, {}),
|
|
1757
|
+
/* @__PURE__ */ jsx6(ValidationError, {}),
|
|
1758
|
+
/* @__PURE__ */ jsx6(Actions, {})
|
|
1759
|
+
] }) });
|
|
1760
|
+
}
|
|
1761
|
+
);
|
|
1762
|
+
var Summary2 = forwardRef5(
|
|
1763
|
+
function AutoRechargeSummary({ className, children, ...rest }, forwardedRef) {
|
|
1764
|
+
const ctx = useAutoRechargeCtx("Summary");
|
|
1765
|
+
if (!ctx.summaryLine) return null;
|
|
1766
|
+
return /* @__PURE__ */ jsx6("p", { ref: forwardedRef, className, "data-solvapay-auto-recharge-summary": "", ...rest, children: children ?? ctx.summaryLine });
|
|
1767
|
+
}
|
|
1768
|
+
);
|
|
1769
|
+
var AmountField = forwardRef5(function AutoRechargeAmountField({ field, showLabel = true, asChild, onChange, className, ...rest }, forwardedRef) {
|
|
1770
|
+
const ctx = useAutoRechargeCtx("AmountField");
|
|
1771
|
+
const copy = useCopy();
|
|
1772
|
+
const fieldConfig = {
|
|
1773
|
+
threshold: {
|
|
1774
|
+
label: copy.autoRecharge.thresholdLabel,
|
|
1775
|
+
ariaLabel: copy.autoRecharge.thresholdAriaLabel,
|
|
1776
|
+
unitToggleLabel: "balance threshold",
|
|
1777
|
+
value: ctx.form.thresholdAmountMajor,
|
|
1778
|
+
unit: ctx.form.thresholdUnit,
|
|
1779
|
+
unitKey: "thresholdUnit",
|
|
1780
|
+
valueKey: "thresholdAmountMajor",
|
|
1781
|
+
baseValueKey: "thresholdBaseValue",
|
|
1782
|
+
baseUnitKey: "thresholdBaseUnit",
|
|
1783
|
+
mode: ctx.form.thresholdUnit === "currency" ? "currency" : "number",
|
|
1784
|
+
onValue: (value) => ctx.updateForm({
|
|
1785
|
+
thresholdAmountMajor: value,
|
|
1786
|
+
thresholdBaseValue: value,
|
|
1787
|
+
thresholdBaseUnit: ctx.form.thresholdUnit
|
|
1788
|
+
})
|
|
1789
|
+
},
|
|
1790
|
+
fixed: {
|
|
1791
|
+
label: copy.autoRecharge.fixedAmountLabel,
|
|
1792
|
+
ariaLabel: copy.autoRecharge.fixedAmountAriaLabel,
|
|
1793
|
+
unitToggleLabel: "fixed top-up amount",
|
|
1794
|
+
value: ctx.form.topupAmountMajor,
|
|
1795
|
+
unit: ctx.form.topupUnit,
|
|
1796
|
+
unitKey: "topupUnit",
|
|
1797
|
+
valueKey: "topupAmountMajor",
|
|
1798
|
+
baseValueKey: "topupBaseValue",
|
|
1799
|
+
baseUnitKey: "topupBaseUnit",
|
|
1800
|
+
mode: ctx.form.topupUnit === "currency" ? "currency" : "number",
|
|
1801
|
+
onValue: (value) => ctx.updateForm({
|
|
1802
|
+
topupAmountMajor: value,
|
|
1803
|
+
topupBaseValue: value,
|
|
1804
|
+
topupBaseUnit: ctx.form.topupUnit
|
|
1805
|
+
})
|
|
1806
|
+
}
|
|
1807
|
+
}[field];
|
|
1808
|
+
const inputId = useId();
|
|
1809
|
+
const prefix = fieldConfig.mode === "currency" ? getCurrencySymbol(ctx.currency) : void 0;
|
|
1810
|
+
const handleChange = (event) => {
|
|
1811
|
+
const raw = event.target.value;
|
|
1812
|
+
const next = fieldConfig.mode === "currency" ? raw.replace(/[^0-9.]/g, "") : raw.replace(/[^0-9]/g, "");
|
|
1813
|
+
fieldConfig.onValue(next);
|
|
1814
|
+
};
|
|
1815
|
+
const inputProps = {
|
|
1816
|
+
id: inputId,
|
|
1817
|
+
"data-solvapay-auto-recharge-amount": "",
|
|
1818
|
+
"data-field": field,
|
|
1819
|
+
type: "text",
|
|
1820
|
+
inputMode: fieldConfig.mode === "currency" ? "decimal" : "numeric",
|
|
1821
|
+
placeholder: fieldConfig.mode === "currency" ? "0.00" : "0",
|
|
1822
|
+
value: fieldConfig.value,
|
|
1823
|
+
"aria-label": fieldConfig.ariaLabel,
|
|
1824
|
+
onChange: composeEventHandlers(onChange, handleChange),
|
|
1825
|
+
className,
|
|
1826
|
+
...rest
|
|
1827
|
+
};
|
|
1828
|
+
const slotRef = forwardedRef;
|
|
1829
|
+
return /* @__PURE__ */ jsxs2("p", { "data-solvapay-auto-recharge-field": "", "data-field": field, children: [
|
|
1830
|
+
showLabel ? /* @__PURE__ */ jsx6("label", { htmlFor: inputId, children: fieldConfig.label }) : null,
|
|
1831
|
+
/* @__PURE__ */ jsxs2("span", { "data-solvapay-auto-recharge-amount-row": "", children: [
|
|
1832
|
+
prefix ? /* @__PURE__ */ jsx6("span", { "data-solvapay-auto-recharge-currency-prefix": "", "aria-hidden": "true", children: prefix }) : null,
|
|
1833
|
+
asChild ? /* @__PURE__ */ jsx6(Slot, { ref: slotRef, ...inputProps }) : /* @__PURE__ */ jsx6("input", { ref: forwardedRef, ...inputProps }),
|
|
1834
|
+
ctx.canToggleUnits ? /* @__PURE__ */ jsx6(
|
|
1835
|
+
UnitToggle,
|
|
1836
|
+
{
|
|
1837
|
+
unit: fieldConfig.unit,
|
|
1838
|
+
fieldLabel: fieldConfig.unitToggleLabel,
|
|
1839
|
+
onToggle: () => ctx.flipUnit(
|
|
1840
|
+
fieldConfig.valueKey,
|
|
1841
|
+
fieldConfig.unitKey,
|
|
1842
|
+
fieldConfig.baseValueKey,
|
|
1843
|
+
fieldConfig.baseUnitKey,
|
|
1844
|
+
fieldConfig.unit
|
|
1845
|
+
)
|
|
1846
|
+
}
|
|
1847
|
+
) : null
|
|
1848
|
+
] })
|
|
1849
|
+
] });
|
|
1850
|
+
});
|
|
1851
|
+
var ThresholdField = forwardRef5(
|
|
1852
|
+
function AutoRechargeThresholdField({ className, ...rest }, ref) {
|
|
1853
|
+
return /* @__PURE__ */ jsx6("section", { ref, className, ...rest, children: /* @__PURE__ */ jsx6(AmountField, { field: "threshold" }) });
|
|
1854
|
+
}
|
|
1855
|
+
);
|
|
1856
|
+
var TopupField = forwardRef5(
|
|
1857
|
+
function AutoRechargeTopupField({ className, ...rest }, ref) {
|
|
1858
|
+
return /* @__PURE__ */ jsxs2(
|
|
1859
|
+
"section",
|
|
1860
|
+
{
|
|
1861
|
+
ref,
|
|
1862
|
+
className,
|
|
1863
|
+
"data-solvapay-auto-recharge-topup-field": "",
|
|
1864
|
+
...rest,
|
|
1865
|
+
children: [
|
|
1866
|
+
/* @__PURE__ */ jsx6(AmountField, { field: "fixed" }),
|
|
1867
|
+
/* @__PURE__ */ jsx6(Hint, {})
|
|
1868
|
+
]
|
|
1869
|
+
}
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
1872
|
+
);
|
|
1873
|
+
var UnitToggle = forwardRef5(function AutoRechargeUnitToggle({ unit, fieldLabel, onToggle, className, ...rest }, forwardedRef) {
|
|
1874
|
+
const ctx = useAutoRechargeCtx("UnitToggle");
|
|
1875
|
+
const targetUnitLabel = unit === "currency" ? "credits" : "currency";
|
|
1876
|
+
return /* @__PURE__ */ jsx6(
|
|
1877
|
+
"button",
|
|
1878
|
+
{
|
|
1879
|
+
ref: forwardedRef,
|
|
1880
|
+
type: "button",
|
|
1881
|
+
className,
|
|
1882
|
+
"data-solvapay-auto-recharge-unit-toggle": "",
|
|
1883
|
+
"aria-label": `Switch ${fieldLabel} to ${targetUnitLabel}`,
|
|
1884
|
+
onClick: onToggle,
|
|
1885
|
+
...rest,
|
|
1886
|
+
children: unit === "currency" ? ctx.currency.toUpperCase() : "credits"
|
|
1887
|
+
}
|
|
1888
|
+
);
|
|
1889
|
+
});
|
|
1890
|
+
var Hint = forwardRef5(
|
|
1891
|
+
function AutoRechargeHint({ className, ...rest }, forwardedRef) {
|
|
1892
|
+
const ctx = useAutoRechargeCtx("Hint");
|
|
1893
|
+
const copy = useCopy();
|
|
1894
|
+
const hint = ctx.fixedTopupHint;
|
|
1895
|
+
if (!hint) return null;
|
|
1896
|
+
const isCreditsHint = ctx.form.topupUnit === "currency";
|
|
1897
|
+
const text = isCreditsHint ? interpolate(
|
|
1898
|
+
ctx.isApproximate ? copy.autoRecharge.creditsPerRechargeApprox : copy.autoRecharge.creditsPerRecharge,
|
|
1899
|
+
{ credits: new Intl.NumberFormat().format(Number(hint)) }
|
|
1900
|
+
) : interpolate(
|
|
1901
|
+
ctx.isApproximate ? copy.autoRecharge.currencyPerRechargeApprox : copy.autoRecharge.currencyPerRecharge,
|
|
1902
|
+
{ amount: hint }
|
|
1903
|
+
);
|
|
1904
|
+
return /* @__PURE__ */ jsx6("p", { ref: forwardedRef, className, "data-solvapay-auto-recharge-hint": "", ...rest, children: text });
|
|
1905
|
+
}
|
|
1906
|
+
);
|
|
1907
|
+
var ValidationError = forwardRef5(function AutoRechargeValidationError({ className, ...rest }, forwardedRef) {
|
|
1908
|
+
const ctx = useAutoRechargeCtx("ValidationError");
|
|
1909
|
+
if (!ctx.validationError) return null;
|
|
1910
|
+
return /* @__PURE__ */ jsx6(
|
|
1911
|
+
"p",
|
|
1912
|
+
{
|
|
1913
|
+
ref: forwardedRef,
|
|
1914
|
+
role: "alert",
|
|
1915
|
+
"aria-live": "polite",
|
|
1916
|
+
className,
|
|
1917
|
+
"data-solvapay-auto-recharge-validation-error": "",
|
|
1918
|
+
...rest,
|
|
1919
|
+
children: ctx.validationError
|
|
1920
|
+
}
|
|
1921
|
+
);
|
|
1922
|
+
});
|
|
1923
|
+
var Actions = forwardRef5(
|
|
1924
|
+
function AutoRechargeActions({ className, children, ...rest }, forwardedRef) {
|
|
1925
|
+
return /* @__PURE__ */ jsx6(
|
|
1926
|
+
"menu",
|
|
1927
|
+
{
|
|
1928
|
+
ref: forwardedRef,
|
|
1929
|
+
className,
|
|
1930
|
+
"data-solvapay-auto-recharge-actions": "",
|
|
1931
|
+
...rest,
|
|
1932
|
+
children: children ?? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1933
|
+
/* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6(CancelButton, {}) }),
|
|
1934
|
+
/* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6(SaveButton, {}) })
|
|
1935
|
+
] })
|
|
1936
|
+
}
|
|
1937
|
+
);
|
|
1938
|
+
}
|
|
1939
|
+
);
|
|
1940
|
+
var SaveButton = forwardRef5(function AutoRechargeSaveButton({ asChild, onClick, children, className, ...rest }, forwardedRef) {
|
|
1941
|
+
const ctx = useAutoRechargeCtx("SaveButton");
|
|
1942
|
+
const copy = useCopy();
|
|
1943
|
+
const dataState = ctx.saving ? "processing" : ctx.validationError ? "disabled" : "idle";
|
|
1944
|
+
const commonProps = {
|
|
1945
|
+
"data-solvapay-auto-recharge-save": "",
|
|
1946
|
+
"data-state": dataState,
|
|
1947
|
+
type: "button",
|
|
1948
|
+
disabled: ctx.saving || ctx.disabling || !!ctx.validationError,
|
|
1949
|
+
"aria-busy": ctx.saving,
|
|
1950
|
+
onClick: composeEventHandlers(onClick, (event) => {
|
|
1951
|
+
event.preventDefault();
|
|
1952
|
+
void ctx.save();
|
|
1953
|
+
}),
|
|
1954
|
+
className,
|
|
1955
|
+
...rest
|
|
1956
|
+
};
|
|
1957
|
+
const content = ctx.saving ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
1958
|
+
/* @__PURE__ */ jsx6(Spinner, { size: "sm" }),
|
|
1959
|
+
" ",
|
|
1960
|
+
copy.cta.processing
|
|
1961
|
+
] }) : children ?? copy.autoRecharge.saveButton;
|
|
1962
|
+
if (asChild) {
|
|
1963
|
+
return /* @__PURE__ */ jsx6(
|
|
1964
|
+
Slot,
|
|
1965
|
+
{
|
|
1966
|
+
ref: forwardedRef,
|
|
1967
|
+
...commonProps,
|
|
1968
|
+
children: content
|
|
1969
|
+
}
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
return /* @__PURE__ */ jsx6("button", { ref: forwardedRef, ...commonProps, children: content });
|
|
1973
|
+
});
|
|
1974
|
+
var DisableButton = forwardRef5(
|
|
1975
|
+
function AutoRechargeDisableButton({ asChild, onClick, children, className, ...rest }, forwardedRef) {
|
|
1976
|
+
const ctx = useAutoRechargeCtx("DisableButton");
|
|
1977
|
+
const copy = useCopy();
|
|
1978
|
+
if (!ctx.config) return null;
|
|
1979
|
+
const commonProps = {
|
|
1980
|
+
"data-solvapay-auto-recharge-disable": "",
|
|
1981
|
+
type: "button",
|
|
1982
|
+
disabled: ctx.saving || ctx.disabling,
|
|
1983
|
+
"aria-busy": ctx.disabling,
|
|
1984
|
+
onClick: composeEventHandlers(onClick, (event) => {
|
|
1985
|
+
event.preventDefault();
|
|
1986
|
+
void ctx.disable();
|
|
1987
|
+
}),
|
|
1988
|
+
className,
|
|
1989
|
+
...rest
|
|
1990
|
+
};
|
|
1991
|
+
if (asChild) {
|
|
1992
|
+
return /* @__PURE__ */ jsx6(
|
|
1993
|
+
Slot,
|
|
1994
|
+
{
|
|
1995
|
+
ref: forwardedRef,
|
|
1996
|
+
...commonProps,
|
|
1997
|
+
children: children ?? copy.autoRecharge.disableButton
|
|
1998
|
+
}
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
2001
|
+
return /* @__PURE__ */ jsx6("button", { ref: forwardedRef, ...commonProps, children: children ?? copy.autoRecharge.disableButton });
|
|
2002
|
+
}
|
|
2003
|
+
);
|
|
2004
|
+
var ErrorSlot4 = forwardRef5(
|
|
2005
|
+
function AutoRechargeError({ className, children, ...rest }, forwardedRef) {
|
|
2006
|
+
const ctx = useAutoRechargeCtx("Error");
|
|
2007
|
+
if (!ctx.error) return null;
|
|
2008
|
+
return /* @__PURE__ */ jsx6(
|
|
2009
|
+
"p",
|
|
2010
|
+
{
|
|
2011
|
+
ref: forwardedRef,
|
|
2012
|
+
role: "alert",
|
|
2013
|
+
"aria-live": "polite",
|
|
2014
|
+
className,
|
|
2015
|
+
"data-solvapay-auto-recharge-error": "",
|
|
2016
|
+
...rest,
|
|
2017
|
+
children: children ?? ctx.error.message
|
|
2018
|
+
}
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
2021
|
+
);
|
|
2022
|
+
var StatusMessage = forwardRef5(
|
|
2023
|
+
function AutoRechargeStatusMessage({ className, children, ...rest }, forwardedRef) {
|
|
2024
|
+
const ctx = useAutoRechargeCtx("StatusMessage");
|
|
2025
|
+
if (!ctx.statusMessage) return null;
|
|
2026
|
+
return /* @__PURE__ */ jsx6(
|
|
2027
|
+
"p",
|
|
2028
|
+
{
|
|
2029
|
+
ref: forwardedRef,
|
|
2030
|
+
"aria-live": "polite",
|
|
2031
|
+
className,
|
|
2032
|
+
"data-solvapay-auto-recharge-status-message": "",
|
|
2033
|
+
...rest,
|
|
2034
|
+
children: children ?? ctx.statusMessage
|
|
2035
|
+
}
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
);
|
|
2039
|
+
var Status = forwardRef5(
|
|
2040
|
+
function AutoRechargeStatus({ className, ...rest }, forwardedRef) {
|
|
2041
|
+
const ctx = useAutoRechargeCtx("Status");
|
|
2042
|
+
const copy = useCopy();
|
|
2043
|
+
const status = ctx.config?.status;
|
|
2044
|
+
if (!status || status === "active" || status === "disabled" || status === "pending_setup") {
|
|
2045
|
+
return null;
|
|
2046
|
+
}
|
|
2047
|
+
const label = status === "failed" ? copy.autoRecharge.statusFailed : null;
|
|
2048
|
+
if (!label) return null;
|
|
2049
|
+
return /* @__PURE__ */ jsx6(
|
|
2050
|
+
"span",
|
|
2051
|
+
{
|
|
2052
|
+
ref: forwardedRef,
|
|
2053
|
+
className,
|
|
2054
|
+
"data-solvapay-auto-recharge-status": "",
|
|
2055
|
+
"data-status": status,
|
|
2056
|
+
...rest,
|
|
2057
|
+
children: label
|
|
2058
|
+
}
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
);
|
|
2062
|
+
function CardSetupInner({ onComplete }) {
|
|
2063
|
+
const copy = useCopy();
|
|
2064
|
+
const stripe = useStripe();
|
|
2065
|
+
const elements = useElements();
|
|
2066
|
+
const [processing, setProcessing] = useState4(false);
|
|
2067
|
+
const [error, setError] = useState4(null);
|
|
2068
|
+
useEffect4(() => {
|
|
2069
|
+
if (!stripe) return;
|
|
2070
|
+
const clientSecret = readSetupIntentClientSecret(window.location.search);
|
|
2071
|
+
if (!clientSecret) return;
|
|
2072
|
+
let cancelled = false;
|
|
2073
|
+
void (async () => {
|
|
2074
|
+
setProcessing(true);
|
|
2075
|
+
const { setupIntent, error: retrieveError } = await stripe.retrieveSetupIntent(clientSecret);
|
|
2076
|
+
if (cancelled) return;
|
|
2077
|
+
stripSetupIntentParams();
|
|
2078
|
+
if (retrieveError || !setupIntent) {
|
|
2079
|
+
setError(copy.autoRecharge.setupAuthFailed);
|
|
2080
|
+
setProcessing(false);
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
if (setupIntent.status === "succeeded" || setupIntent.status === "processing") {
|
|
2084
|
+
await onComplete();
|
|
2085
|
+
} else {
|
|
2086
|
+
setError(copy.autoRecharge.setupAuthFailed);
|
|
2087
|
+
}
|
|
2088
|
+
if (!cancelled) setProcessing(false);
|
|
2089
|
+
})();
|
|
2090
|
+
return () => {
|
|
2091
|
+
cancelled = true;
|
|
2092
|
+
};
|
|
2093
|
+
}, [stripe, onComplete, copy.autoRecharge]);
|
|
2094
|
+
const handleSubmit = async (event) => {
|
|
2095
|
+
event.preventDefault();
|
|
2096
|
+
if (!stripe || !elements) {
|
|
2097
|
+
setError("Stripe is still loading. Please wait.");
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
setProcessing(true);
|
|
2101
|
+
setError(null);
|
|
2102
|
+
const { error: submitError } = await elements.submit();
|
|
2103
|
+
if (submitError) {
|
|
2104
|
+
setError(submitError.message ?? "Card authorization failed");
|
|
2105
|
+
setProcessing(false);
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2108
|
+
const { error: confirmError } = await stripe.confirmSetup({
|
|
2109
|
+
elements,
|
|
2110
|
+
confirmParams: {
|
|
2111
|
+
return_url: typeof window !== "undefined" ? window.location.href : "/"
|
|
2112
|
+
},
|
|
2113
|
+
redirect: "if_required"
|
|
2114
|
+
});
|
|
2115
|
+
if (confirmError) {
|
|
2116
|
+
setError(confirmError.message ?? "Card authorization failed");
|
|
2117
|
+
setProcessing(false);
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
2120
|
+
await onComplete();
|
|
2121
|
+
setProcessing(false);
|
|
2122
|
+
};
|
|
2123
|
+
return /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, "data-solvapay-auto-recharge-setup": "", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx6("h4", { children: copy.autoRecharge.setupHeading }),
|
|
2125
|
+
/* @__PURE__ */ jsx6("p", { children: copy.autoRecharge.setupDescription }),
|
|
2126
|
+
/* @__PURE__ */ jsx6(StripePaymentElement, { options: withPaymentElementDefaults() }),
|
|
2127
|
+
error ? /* @__PURE__ */ jsx6("p", { role: "alert", "aria-live": "polite", "data-solvapay-auto-recharge-setup-error": "", children: error }) : null,
|
|
2128
|
+
/* @__PURE__ */ jsx6(
|
|
2129
|
+
"button",
|
|
2130
|
+
{
|
|
2131
|
+
type: "submit",
|
|
2132
|
+
disabled: processing || !stripe,
|
|
2133
|
+
"data-solvapay-auto-recharge-setup-submit": "",
|
|
2134
|
+
children: processing ? copy.autoRecharge.setupProcessing : copy.autoRecharge.setupSubmit
|
|
2135
|
+
}
|
|
2136
|
+
)
|
|
2137
|
+
] });
|
|
2138
|
+
}
|
|
2139
|
+
function CardSetup({ setup, onComplete }) {
|
|
2140
|
+
const stripePromise = useMemo4(() => {
|
|
2141
|
+
if (!setup.publishableKey || !setup.setupClientSecret) return null;
|
|
2142
|
+
const options = {
|
|
2143
|
+
...setup.stripeAccountId ? { stripeAccount: setup.stripeAccountId } : {},
|
|
2144
|
+
developerTools: { assistant: { enabled: false } }
|
|
2145
|
+
};
|
|
2146
|
+
const cacheKey = getStripeCacheKey(setup.publishableKey, setup.stripeAccountId);
|
|
2147
|
+
const cached = stripePromiseCache.get(cacheKey);
|
|
2148
|
+
if (cached) return cached;
|
|
2149
|
+
const promise = loadStripe(setup.publishableKey, options);
|
|
2150
|
+
stripePromiseCache.set(cacheKey, promise);
|
|
2151
|
+
return promise;
|
|
2152
|
+
}, [setup.publishableKey, setup.setupClientSecret, setup.stripeAccountId]);
|
|
2153
|
+
if (!stripePromise || !setup.setupClientSecret) {
|
|
2154
|
+
return /* @__PURE__ */ jsxs2("p", { "data-solvapay-auto-recharge-setup-loading": "", children: [
|
|
2155
|
+
/* @__PURE__ */ jsx6(Spinner, { size: "sm" }),
|
|
2156
|
+
" Loading card form\u2026"
|
|
2157
|
+
] });
|
|
2158
|
+
}
|
|
2159
|
+
return /* @__PURE__ */ jsx6(
|
|
2160
|
+
Elements,
|
|
2161
|
+
{
|
|
2162
|
+
stripe: stripePromise,
|
|
2163
|
+
options: { clientSecret: setup.setupClientSecret },
|
|
2164
|
+
children: /* @__PURE__ */ jsx6(CardSetupInner, { onComplete })
|
|
2165
|
+
},
|
|
2166
|
+
setup.setupClientSecret
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
var AutoRechargeRoot2 = Root4;
|
|
2170
|
+
var AutoRechargeLoading2 = Loading4;
|
|
2171
|
+
var AutoRechargeCard2 = Card;
|
|
2172
|
+
var AutoRechargeCardHeading2 = CardHeading;
|
|
2173
|
+
var AutoRechargeCardSummary2 = CardSummary;
|
|
2174
|
+
var AutoRechargeTrigger2 = Trigger;
|
|
2175
|
+
var AutoRechargeOverlay2 = Overlay;
|
|
2176
|
+
var AutoRechargeContent2 = Content;
|
|
2177
|
+
var AutoRechargeTitle2 = Title;
|
|
2178
|
+
var AutoRechargeEnableQuestion2 = EnableQuestion;
|
|
2179
|
+
var AutoRechargeEnableSentence2 = EnableSentence;
|
|
2180
|
+
var AutoRechargeEnableRow2 = EnableRow;
|
|
2181
|
+
var AutoRechargeCancelButton2 = CancelButton;
|
|
2182
|
+
var AutoRechargeHeader2 = Header;
|
|
2183
|
+
var AutoRechargeDescription2 = Description;
|
|
2184
|
+
var AutoRechargeEnableSwitch2 = EnableSwitch;
|
|
2185
|
+
var AutoRechargeFields2 = Fields;
|
|
2186
|
+
var AutoRechargeSetup2 = Setup;
|
|
2187
|
+
var AutoRechargeBody2 = Body;
|
|
2188
|
+
var AutoRechargeSummary2 = Summary2;
|
|
2189
|
+
var AutoRechargeThresholdField2 = ThresholdField;
|
|
2190
|
+
var AutoRechargeTopupField2 = TopupField;
|
|
2191
|
+
var AutoRechargeAmountField2 = AmountField;
|
|
2192
|
+
var AutoRechargeUnitToggle2 = UnitToggle;
|
|
2193
|
+
var AutoRechargeHint2 = Hint;
|
|
2194
|
+
var AutoRechargeValidationError2 = ValidationError;
|
|
2195
|
+
var AutoRechargeActions2 = Actions;
|
|
2196
|
+
var AutoRechargeSaveButton2 = SaveButton;
|
|
2197
|
+
var AutoRechargeDisableButton2 = DisableButton;
|
|
2198
|
+
var AutoRechargeError2 = ErrorSlot4;
|
|
2199
|
+
var AutoRechargeStatusMessage2 = StatusMessage;
|
|
2200
|
+
var AutoRechargeStatus2 = Status;
|
|
2201
|
+
var AutoRechargeCardSetup = CardSetup;
|
|
2202
|
+
var AutoRecharge = {
|
|
2203
|
+
Root: Root4,
|
|
2204
|
+
Loading: Loading4,
|
|
2205
|
+
Card,
|
|
2206
|
+
CardHeading,
|
|
2207
|
+
CardSummary,
|
|
2208
|
+
Trigger,
|
|
2209
|
+
Overlay,
|
|
2210
|
+
Content,
|
|
2211
|
+
Title,
|
|
2212
|
+
EnableQuestion,
|
|
2213
|
+
EnableSentence,
|
|
2214
|
+
EnableRow,
|
|
2215
|
+
CancelButton,
|
|
2216
|
+
Header,
|
|
2217
|
+
Description,
|
|
2218
|
+
EnableSwitch,
|
|
2219
|
+
Fields,
|
|
2220
|
+
Setup,
|
|
2221
|
+
Body,
|
|
2222
|
+
Summary: Summary2,
|
|
2223
|
+
ThresholdField,
|
|
2224
|
+
TopupField,
|
|
2225
|
+
AmountField,
|
|
2226
|
+
UnitToggle,
|
|
2227
|
+
Hint,
|
|
2228
|
+
ValidationError,
|
|
2229
|
+
Actions,
|
|
2230
|
+
SaveButton,
|
|
2231
|
+
DisableButton,
|
|
2232
|
+
Error: ErrorSlot4,
|
|
2233
|
+
StatusMessage,
|
|
2234
|
+
Status,
|
|
2235
|
+
CardSetup
|
|
2236
|
+
};
|
|
2237
|
+
function useAutoRechargeForm() {
|
|
2238
|
+
return useAutoRechargeCtx("useAutoRechargeForm");
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// src/hooks/usePaywallResolver.ts
|
|
2242
|
+
import { useCallback as useCallback4, useMemo as useMemo5 } from "react";
|
|
2243
|
+
function balanceCoversNextUnit(balance, credits) {
|
|
2244
|
+
if (!balance) return false;
|
|
2245
|
+
if (typeof balance.remainingUnits === "number" && balance.remainingUnits > 0) {
|
|
2246
|
+
return true;
|
|
2247
|
+
}
|
|
2248
|
+
if (credits != null && balance.creditsPerUnit && credits >= balance.creditsPerUnit) {
|
|
2249
|
+
return true;
|
|
2250
|
+
}
|
|
2251
|
+
return false;
|
|
2252
|
+
}
|
|
2253
|
+
function usePaywallResolver(content) {
|
|
2254
|
+
const { activePurchase, hasPaidPurchase, refetch: refetchPurchase } = usePurchase();
|
|
2255
|
+
const { credits, refetch: refetchBalance } = useBalance();
|
|
2256
|
+
const resolved = useMemo5(() => {
|
|
2257
|
+
if (!content) return false;
|
|
2258
|
+
const productMatches = !content.product || activePurchase?.productRef === content.product || activePurchase?.productName === content.product;
|
|
2259
|
+
if (content.kind === "payment_required") {
|
|
2260
|
+
if (hasPaidPurchase && productMatches) return true;
|
|
2261
|
+
return balanceCoversNextUnit(content.balance, credits);
|
|
2262
|
+
}
|
|
2263
|
+
if (balanceCoversNextUnit(content.balance, credits)) return true;
|
|
2264
|
+
return Boolean(productMatches && activePurchase?.status === "active");
|
|
2265
|
+
}, [content, hasPaidPurchase, activePurchase, credits]);
|
|
2266
|
+
const refetch = useCallback4(async () => {
|
|
2267
|
+
await Promise.all([
|
|
2268
|
+
refetchPurchase().catch(() => void 0),
|
|
2269
|
+
refetchBalance().catch(() => void 0)
|
|
2270
|
+
]);
|
|
2271
|
+
}, [refetchPurchase, refetchBalance]);
|
|
2272
|
+
return { resolved, refetch };
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
// src/primitives/PaywallNotice.tsx
|
|
2276
|
+
import {
|
|
2277
|
+
createContext as createContext6,
|
|
2278
|
+
forwardRef as forwardRef7,
|
|
2279
|
+
useCallback as useCallback5,
|
|
2280
|
+
useContext as useContext7,
|
|
2281
|
+
useEffect as useEffect5,
|
|
2282
|
+
useMemo as useMemo7,
|
|
2283
|
+
useRef as useRef4
|
|
2284
|
+
} from "react";
|
|
2285
|
+
|
|
2286
|
+
// src/primitives/checkout/index.tsx
|
|
2287
|
+
import { createContext as createContext5, forwardRef as forwardRef6, useContext as useContext6, useMemo as useMemo6 } from "react";
|
|
2288
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2289
|
+
var CheckoutContext = createContext5(null);
|
|
2290
|
+
function useCheckoutContext(part) {
|
|
2291
|
+
const ctx = useContext6(CheckoutContext);
|
|
2292
|
+
if (!ctx) {
|
|
2293
|
+
throw new Error(`CheckoutSteps.${part} must be rendered inside <CheckoutSteps.Root>.`);
|
|
2294
|
+
}
|
|
2295
|
+
return ctx;
|
|
2296
|
+
}
|
|
2297
|
+
function useCheckoutSteps() {
|
|
2298
|
+
return useCheckoutContext("useCheckoutSteps");
|
|
2299
|
+
}
|
|
2300
|
+
var Root5 = forwardRef6(function CheckoutStepsRoot(props, forwardedRef) {
|
|
2301
|
+
const {
|
|
2302
|
+
productRef,
|
|
2303
|
+
returnUrl: _returnUrl,
|
|
2304
|
+
flow: externalFlow,
|
|
2305
|
+
initialStep,
|
|
2306
|
+
initialPlanRef,
|
|
2307
|
+
initialAmountMinor,
|
|
2308
|
+
autoSelectFirstPaid = false,
|
|
2309
|
+
topupCurrency,
|
|
2310
|
+
filter,
|
|
2311
|
+
sortBy = planSortByPaygFirstThenAsc,
|
|
2312
|
+
popularPlanRef,
|
|
2313
|
+
currentPlanRef,
|
|
2314
|
+
onPlanSelect,
|
|
2315
|
+
onAmountSelect,
|
|
2316
|
+
onPurchaseSuccess,
|
|
2317
|
+
onError,
|
|
2318
|
+
className,
|
|
2319
|
+
children
|
|
2320
|
+
} = props;
|
|
2321
|
+
if (externalFlow) {
|
|
2322
|
+
return /* @__PURE__ */ jsx7("div", { ref: forwardedRef, "data-solvapay-checkout": "", className, children: /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: externalFlow, children }) });
|
|
2323
|
+
}
|
|
2324
|
+
return /* @__PURE__ */ jsx7(
|
|
2325
|
+
RootWithPlanSelector,
|
|
2326
|
+
{
|
|
2327
|
+
productRef,
|
|
2328
|
+
filter,
|
|
2329
|
+
sortBy,
|
|
2330
|
+
popularPlanRef,
|
|
2331
|
+
currentPlanRef,
|
|
2332
|
+
autoSelectFirstPaid,
|
|
2333
|
+
initialPlanRef,
|
|
2334
|
+
forwardedRef,
|
|
2335
|
+
className,
|
|
2336
|
+
initialStep,
|
|
2337
|
+
initialAmountMinor,
|
|
2338
|
+
topupCurrency,
|
|
2339
|
+
onPlanSelect,
|
|
2340
|
+
onAmountSelect,
|
|
2341
|
+
onPurchaseSuccess,
|
|
2342
|
+
onError,
|
|
2343
|
+
children
|
|
2344
|
+
}
|
|
2345
|
+
);
|
|
2346
|
+
});
|
|
2347
|
+
function RootWithPlanSelector({
|
|
2348
|
+
productRef,
|
|
2349
|
+
filter,
|
|
2350
|
+
sortBy,
|
|
2351
|
+
popularPlanRef,
|
|
2352
|
+
currentPlanRef,
|
|
2353
|
+
autoSelectFirstPaid,
|
|
2354
|
+
initialPlanRef,
|
|
2355
|
+
forwardedRef,
|
|
2356
|
+
className,
|
|
2357
|
+
initialStep,
|
|
2358
|
+
initialAmountMinor,
|
|
2359
|
+
topupCurrency,
|
|
2360
|
+
onPlanSelect,
|
|
2361
|
+
onAmountSelect,
|
|
2362
|
+
onPurchaseSuccess,
|
|
2363
|
+
onError,
|
|
2364
|
+
children
|
|
2365
|
+
}) {
|
|
2366
|
+
const { plans } = usePlans({ productRef });
|
|
2367
|
+
const resolvedFilter = useMemo6(
|
|
2368
|
+
() => filter ?? buildDefaultCheckoutPlanFilter(plans),
|
|
2369
|
+
[filter, plans]
|
|
2370
|
+
);
|
|
2371
|
+
return /* @__PURE__ */ jsx7(
|
|
2372
|
+
PlanSelector.Root,
|
|
2373
|
+
{
|
|
2374
|
+
productRef,
|
|
2375
|
+
filter: resolvedFilter,
|
|
2376
|
+
sortBy,
|
|
2377
|
+
popularPlanRef,
|
|
2378
|
+
currentPlanRef,
|
|
2379
|
+
autoSelectFirstPaid,
|
|
2380
|
+
initialPlanRef,
|
|
2381
|
+
children: /* @__PURE__ */ jsx7(
|
|
2382
|
+
FlowProvider,
|
|
2383
|
+
{
|
|
2384
|
+
productRef,
|
|
2385
|
+
forwardedRef,
|
|
2386
|
+
className,
|
|
2387
|
+
initialStep,
|
|
2388
|
+
initialAmountMinor,
|
|
2389
|
+
topupCurrency,
|
|
2390
|
+
onPlanSelect,
|
|
2391
|
+
onAmountSelect,
|
|
2392
|
+
onPurchaseSuccess,
|
|
2393
|
+
onError,
|
|
2394
|
+
children
|
|
2395
|
+
}
|
|
2396
|
+
)
|
|
2397
|
+
}
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
function FlowProvider({
|
|
2401
|
+
productRef,
|
|
2402
|
+
initialStep,
|
|
2403
|
+
initialAmountMinor,
|
|
2404
|
+
topupCurrency,
|
|
2405
|
+
onPlanSelect,
|
|
2406
|
+
onAmountSelect,
|
|
2407
|
+
onPurchaseSuccess,
|
|
2408
|
+
onError,
|
|
2409
|
+
className,
|
|
2410
|
+
forwardedRef,
|
|
2411
|
+
children
|
|
2412
|
+
}) {
|
|
2413
|
+
const flow = useCheckoutFlow({
|
|
2414
|
+
productRef,
|
|
2415
|
+
initialStep,
|
|
2416
|
+
initialAmountMinor,
|
|
2417
|
+
topupCurrency,
|
|
2418
|
+
onPlanSelect,
|
|
2419
|
+
onAmountSelect,
|
|
2420
|
+
onPurchaseSuccess,
|
|
2421
|
+
onError
|
|
2422
|
+
});
|
|
2423
|
+
return /* @__PURE__ */ jsx7("div", { ref: forwardedRef, "data-solvapay-checkout": "", "data-step": flow.step, className, children: /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: flow, children }) });
|
|
2424
|
+
}
|
|
2425
|
+
function IfStep({ step, children }) {
|
|
2426
|
+
const flow = useCheckoutContext("IfStep");
|
|
2427
|
+
const matches = Array.isArray(step) ? step.includes(flow.step) : flow.step === step;
|
|
2428
|
+
if (!matches) return null;
|
|
2429
|
+
return /* @__PURE__ */ jsx7(Fragment4, { children });
|
|
2430
|
+
}
|
|
2431
|
+
var StepHeading = forwardRef6(function CheckoutStepsStepHeading({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2432
|
+
const flow = useCheckoutContext("StepHeading");
|
|
2433
|
+
const copy = useCopy();
|
|
2434
|
+
const paywallCtx = usePaywallNoticeOptional();
|
|
2435
|
+
if (flow.step === "success") return null;
|
|
2436
|
+
const defaultText = resolveStepHeading(flow.step, copy, paywallCtx?.content ?? null);
|
|
2437
|
+
const Comp = asChild ? Slot : "h3";
|
|
2438
|
+
return /* @__PURE__ */ jsx7(
|
|
2439
|
+
Comp,
|
|
2440
|
+
{
|
|
2441
|
+
ref: forwardedRef,
|
|
2442
|
+
"data-solvapay-checkout-step-heading": "",
|
|
2443
|
+
"data-step": flow.step,
|
|
2444
|
+
className: className ?? "solvapay-checkout-step-heading",
|
|
2445
|
+
...rest,
|
|
2446
|
+
children: children ?? defaultText
|
|
2447
|
+
}
|
|
2448
|
+
);
|
|
2449
|
+
});
|
|
2450
|
+
var StepMessage = forwardRef6(function CheckoutStepsStepMessage({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2451
|
+
const flow = useCheckoutContext("StepMessage");
|
|
2452
|
+
const copy = useCopy();
|
|
2453
|
+
const paywallCtx = usePaywallNoticeOptional();
|
|
2454
|
+
if (flow.step === "success") return null;
|
|
2455
|
+
const defaultText = resolveStepMessage(flow, copy, paywallCtx?.content ?? null);
|
|
2456
|
+
if (!defaultText && children == null) return null;
|
|
2457
|
+
const Comp = asChild ? Slot : "p";
|
|
2458
|
+
return /* @__PURE__ */ jsx7(
|
|
2459
|
+
Comp,
|
|
2460
|
+
{
|
|
2461
|
+
ref: forwardedRef,
|
|
2462
|
+
"data-solvapay-checkout-step-message": "",
|
|
2463
|
+
"data-step": flow.step,
|
|
2464
|
+
className: className ?? "solvapay-checkout-step-message",
|
|
2465
|
+
...rest,
|
|
2466
|
+
children: children ?? defaultText
|
|
2467
|
+
}
|
|
2468
|
+
);
|
|
2469
|
+
});
|
|
2470
|
+
function resolveStepHeading(step, copy, content) {
|
|
2471
|
+
if (step === "amount") return copy.checkout.stepHeading.amount;
|
|
2472
|
+
if (step === "payment") return copy.checkout.stepHeading.payment;
|
|
2473
|
+
if (step === "plan") {
|
|
2474
|
+
if (content) {
|
|
2475
|
+
if (content.kind === "payment_required") return copy.paywall.paymentRequiredHeading;
|
|
2476
|
+
if (content.kind === "activation_required") {
|
|
2477
|
+
return isTopupGate(content) ? copy.paywall.topupRequiredHeading : copy.paywall.activationRequiredHeading;
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
return copy.checkout.stepHeading.plan;
|
|
2481
|
+
}
|
|
2482
|
+
return "";
|
|
2483
|
+
}
|
|
2484
|
+
function resolveStepMessage(flow, copy, content) {
|
|
2485
|
+
if (flow.step === "plan") {
|
|
2486
|
+
if (content) return resolvePaywallMessage(content, copy.paywall);
|
|
2487
|
+
return copy.checkout.stepMessage.plan;
|
|
2488
|
+
}
|
|
2489
|
+
if (flow.step === "amount") return copy.checkout.stepMessage.amount;
|
|
2490
|
+
if (flow.step === "payment") {
|
|
2491
|
+
if (flow.branch === "payg") return copy.checkout.stepMessage.paymentPayg;
|
|
2492
|
+
const plan = flow.selectedPlan;
|
|
2493
|
+
if (flow.branch === "recurring" && plan) {
|
|
2494
|
+
const planName = plan.name ?? "your";
|
|
2495
|
+
if (plan.billingCycle) {
|
|
2496
|
+
return interpolate(copy.checkout.stepMessage.paymentRecurring, { planName });
|
|
2497
|
+
}
|
|
2498
|
+
return copy.checkout.stepMessage.paymentOneTime;
|
|
2499
|
+
}
|
|
2500
|
+
return copy.checkout.stepMessage.paymentOneTime;
|
|
2501
|
+
}
|
|
2502
|
+
return "";
|
|
2503
|
+
}
|
|
2504
|
+
function PlanGrid({ className, children }) {
|
|
2505
|
+
return /* @__PURE__ */ jsx7(PlanSelector.Grid, { className: className ?? "solvapay-checkout-plan-grid", children: children ?? /* @__PURE__ */ jsxs3(PlanSelector.Card, { className: "solvapay-checkout-plan-card", children: [
|
|
2506
|
+
/* @__PURE__ */ jsx7(PlanSelector.CardBadge, { className: "solvapay-checkout-plan-card-badge" }),
|
|
2507
|
+
/* @__PURE__ */ jsx7(PlanSelector.CardName, { className: "solvapay-checkout-plan-card-name" }),
|
|
2508
|
+
/* @__PURE__ */ jsx7(PlanSelector.CardPrice, { className: "solvapay-checkout-plan-card-price" }),
|
|
2509
|
+
/* @__PURE__ */ jsx7(PlanSelector.CardInterval, { className: "solvapay-checkout-plan-card-interval" })
|
|
2510
|
+
] }) });
|
|
2511
|
+
}
|
|
2512
|
+
var PlanContinueButton = forwardRef6(
|
|
2513
|
+
function PlanContinueButton2({ className, children, onClick, disabled, ...rest }, ref) {
|
|
2514
|
+
const flow = useCheckoutContext("PlanContinueButton");
|
|
2515
|
+
const locale = useLocale();
|
|
2516
|
+
const selectedPlanShape = flow.selectedPlan;
|
|
2517
|
+
const isDisabled = disabled || !flow.selectedPlanRef || flow.status === "activating";
|
|
2518
|
+
const label = children ?? formatContinueLabel(selectedPlanShape, locale);
|
|
2519
|
+
return /* @__PURE__ */ jsx7(
|
|
2520
|
+
"button",
|
|
2521
|
+
{
|
|
2522
|
+
ref,
|
|
2523
|
+
type: "button",
|
|
2524
|
+
className: className ?? "solvapay-checkout-continue-button",
|
|
2525
|
+
disabled: isDisabled,
|
|
2526
|
+
"aria-disabled": isDisabled || void 0,
|
|
2527
|
+
"data-solvapay-checkout-continue": "",
|
|
2528
|
+
onClick: (e) => {
|
|
2529
|
+
onClick?.(e);
|
|
2530
|
+
if (e.defaultPrevented) return;
|
|
2531
|
+
void flow.advance();
|
|
2532
|
+
},
|
|
2533
|
+
...rest,
|
|
2534
|
+
children: label
|
|
2535
|
+
}
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
);
|
|
2539
|
+
function AmountPicker2({ className, children }) {
|
|
2540
|
+
const flow = useCheckoutContext("AmountPicker");
|
|
2541
|
+
if (!flow.topupCurrencyReady || flow.topupCurrency == null) {
|
|
2542
|
+
return /* @__PURE__ */ jsx7(
|
|
2543
|
+
"div",
|
|
2544
|
+
{
|
|
2545
|
+
className: className ?? "solvapay-amount-picker",
|
|
2546
|
+
"data-state": "loading",
|
|
2547
|
+
"aria-busy": "true",
|
|
2548
|
+
children: /* @__PURE__ */ jsx7("div", { className: "solvapay-amount-picker-pills", children: [0, 1, 2, 3].map((i) => /* @__PURE__ */ jsx7(
|
|
2549
|
+
"span",
|
|
2550
|
+
{
|
|
2551
|
+
className: "solvapay-amount-picker-pill",
|
|
2552
|
+
"data-state": "disabled",
|
|
2553
|
+
"aria-hidden": "true"
|
|
2554
|
+
},
|
|
2555
|
+
i
|
|
2556
|
+
)) })
|
|
2557
|
+
}
|
|
2558
|
+
);
|
|
2559
|
+
}
|
|
2560
|
+
return /* @__PURE__ */ jsx7(
|
|
2561
|
+
AmountPicker.Root,
|
|
2562
|
+
{
|
|
2563
|
+
currency: flow.topupCurrency,
|
|
2564
|
+
emit: "minor",
|
|
2565
|
+
className: className ?? "solvapay-amount-picker",
|
|
2566
|
+
onChange: (value) => {
|
|
2567
|
+
if (typeof value === "number") {
|
|
2568
|
+
flow.selectAmount(value);
|
|
2569
|
+
}
|
|
2570
|
+
},
|
|
2571
|
+
children: children ?? /* @__PURE__ */ jsx7(DefaultAmountTree, {})
|
|
2572
|
+
}
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
function DefaultAmountTree() {
|
|
2576
|
+
const ctx = useAmountPicker();
|
|
2577
|
+
const { selectAmountLabel, customAmountLabel, creditEstimate } = useAmountPickerCopy();
|
|
2578
|
+
return /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
2579
|
+
/* @__PURE__ */ jsx7("p", { className: "solvapay-amount-picker-label", children: selectAmountLabel }),
|
|
2580
|
+
/* @__PURE__ */ jsx7("div", { className: "solvapay-amount-picker-pills", children: ctx.quickAmounts.map((amount) => /* @__PURE__ */ jsx7(
|
|
2581
|
+
AmountPicker.Option,
|
|
2582
|
+
{
|
|
2583
|
+
amount,
|
|
2584
|
+
className: "solvapay-amount-picker-pill"
|
|
2585
|
+
},
|
|
2586
|
+
amount
|
|
2587
|
+
)) }),
|
|
2588
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-amount-picker-custom-wrapper", children: [
|
|
2589
|
+
/* @__PURE__ */ jsx7("p", { className: "solvapay-amount-picker-custom-label", children: customAmountLabel }),
|
|
2590
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-amount-picker-custom-row", children: [
|
|
2591
|
+
/* @__PURE__ */ jsx7("span", { className: "solvapay-amount-picker-currency-symbol", children: ctx.currencySymbol }),
|
|
2592
|
+
/* @__PURE__ */ jsx7(
|
|
2593
|
+
AmountPicker.Custom,
|
|
2594
|
+
{
|
|
2595
|
+
className: "solvapay-amount-picker-custom-input",
|
|
2596
|
+
placeholder: "0.00"
|
|
2597
|
+
}
|
|
2598
|
+
)
|
|
2599
|
+
] })
|
|
2600
|
+
] }),
|
|
2601
|
+
/* @__PURE__ */ jsx7(
|
|
2602
|
+
"p",
|
|
2603
|
+
{
|
|
2604
|
+
className: "solvapay-amount-picker-credit-estimate",
|
|
2605
|
+
"aria-hidden": ctx.estimatedCredits == null || void 0,
|
|
2606
|
+
children: ctx.estimatedCredits != null ? creditEstimate(ctx.estimatedCredits) : "\xA0"
|
|
2607
|
+
}
|
|
2608
|
+
)
|
|
2609
|
+
] });
|
|
2610
|
+
}
|
|
2611
|
+
var AmountContinueButton = forwardRef6(
|
|
2612
|
+
function AmountContinueButton2({ className, children, onClick, disabled, ...rest }, ref) {
|
|
2613
|
+
const flow = useCheckoutContext("AmountContinueButton");
|
|
2614
|
+
const locale = useLocale();
|
|
2615
|
+
const currency = flow.topupCurrency;
|
|
2616
|
+
const amountMinor = flow.selectedAmountMinor;
|
|
2617
|
+
const ready = flow.topupCurrencyReady && currency != null;
|
|
2618
|
+
const isDisabled = disabled || !ready || amountMinor == null;
|
|
2619
|
+
const label = children ?? (ready && currency != null && amountMinor != null ? `Continue \u2014 ${formatPrice(amountMinor, currency, { locale })}` : "Continue");
|
|
2620
|
+
return /* @__PURE__ */ jsx7(
|
|
2621
|
+
"button",
|
|
2622
|
+
{
|
|
2623
|
+
ref,
|
|
2624
|
+
type: "button",
|
|
2625
|
+
className: className ?? "solvapay-checkout-continue-button",
|
|
2626
|
+
disabled: isDisabled,
|
|
2627
|
+
"aria-disabled": isDisabled || void 0,
|
|
2628
|
+
"data-solvapay-checkout-continue": "",
|
|
2629
|
+
onClick: (e) => {
|
|
2630
|
+
onClick?.(e);
|
|
2631
|
+
if (e.defaultPrevented) return;
|
|
2632
|
+
void flow.advance();
|
|
2633
|
+
},
|
|
2634
|
+
...rest,
|
|
2635
|
+
children: label
|
|
2636
|
+
}
|
|
2637
|
+
);
|
|
2638
|
+
}
|
|
2639
|
+
);
|
|
2640
|
+
function Payment({ className }) {
|
|
2641
|
+
const flow = useCheckoutContext("Payment");
|
|
2642
|
+
if (flow.branch === "payg") {
|
|
2643
|
+
return /* @__PURE__ */ jsx7(PaygPayment, { className });
|
|
2644
|
+
}
|
|
2645
|
+
if (flow.branch === "recurring") {
|
|
2646
|
+
return /* @__PURE__ */ jsx7(RecurringPayment, { className });
|
|
2647
|
+
}
|
|
2648
|
+
return null;
|
|
2649
|
+
}
|
|
2650
|
+
function PaygPayment({ className }) {
|
|
2651
|
+
const flow = useCheckoutContext("Payment");
|
|
2652
|
+
const locale = useLocale();
|
|
2653
|
+
const { creditsPerMinorUnit, displayExchangeRate } = useBalance();
|
|
2654
|
+
const returnUrl = useReturnUrl();
|
|
2655
|
+
const selectedPlanShape = flow.selectedPlan;
|
|
2656
|
+
const amountMinor = flow.selectedAmountMinor;
|
|
2657
|
+
const currency = flow.topupCurrency;
|
|
2658
|
+
if (!selectedPlanShape || amountMinor == null || currency == null) return null;
|
|
2659
|
+
const creditsAdded = creditsPerMinorUnit != null && creditsPerMinorUnit > 0 ? Math.floor(amountMinor / (displayExchangeRate ?? 1) * creditsPerMinorUnit) : null;
|
|
2660
|
+
return /* @__PURE__ */ jsxs3("div", { className: className ?? "solvapay-checkout-payment", "data-branch": "payg", children: [
|
|
2661
|
+
/* @__PURE__ */ jsx7("div", { className: "solvapay-checkout-order-summary", "data-variant": "payg", children: /* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-order-summary-row", children: [
|
|
2662
|
+
/* @__PURE__ */ jsx7("span", { children: creditsAdded != null ? `${creditsAdded.toLocaleString(locale)} credits` : formatPrice(amountMinor, currency, { locale }) }),
|
|
2663
|
+
creditsAdded != null ? /* @__PURE__ */ jsx7("span", { children: formatPrice(amountMinor, currency, { locale }) }) : null
|
|
2664
|
+
] }) }),
|
|
2665
|
+
/* @__PURE__ */ jsxs3(
|
|
2666
|
+
TopupForm.Root,
|
|
2667
|
+
{
|
|
2668
|
+
amount: amountMinor,
|
|
2669
|
+
currency,
|
|
2670
|
+
returnUrl,
|
|
2671
|
+
className: "solvapay-checkout-topup-form",
|
|
2672
|
+
onSuccess: (intent, extras) => flow.notifyPaymentSuccess(intent, extras),
|
|
2673
|
+
children: [
|
|
2674
|
+
/* @__PURE__ */ jsx7(TopupForm.Loading, {}),
|
|
2675
|
+
/* @__PURE__ */ jsx7(TopupForm.PaymentElement, {}),
|
|
2676
|
+
/* @__PURE__ */ jsx7(TopupForm.Error, { className: "solvapay-checkout-error" }),
|
|
2677
|
+
/* @__PURE__ */ jsx7(MandateText, { mode: "topup", amountMinor, currency }),
|
|
2678
|
+
/* @__PURE__ */ jsxs3(TopupForm.SubmitButton, { className: "solvapay-checkout-pay-button", children: [
|
|
2679
|
+
"Pay ",
|
|
2680
|
+
formatPrice(amountMinor, currency, { locale })
|
|
2681
|
+
] })
|
|
2682
|
+
]
|
|
2683
|
+
}
|
|
2684
|
+
)
|
|
2685
|
+
] });
|
|
2686
|
+
}
|
|
2687
|
+
function RecurringPayment({ className }) {
|
|
2688
|
+
const flow = useCheckoutContext("Payment");
|
|
2689
|
+
const locale = useLocale();
|
|
2690
|
+
const returnUrl = useReturnUrl();
|
|
2691
|
+
const productRef = useProductRef();
|
|
2692
|
+
const selectedPlanShape = flow.selectedPlan;
|
|
2693
|
+
if (!selectedPlanShape || !flow.selectedPlanRef) return null;
|
|
2694
|
+
const currency = (selectedPlanShape.currency ?? "USD").toUpperCase();
|
|
2695
|
+
const amountMinor = selectedPlanShape.price ?? 0;
|
|
2696
|
+
const cycle = selectedPlanShape.billingCycle;
|
|
2697
|
+
const planName = selectedPlanShape.name ?? "Plan";
|
|
2698
|
+
const isRecurring = !!cycle;
|
|
2699
|
+
const formattedAmount = formatPrice(amountMinor, currency, { locale });
|
|
2700
|
+
const priceLine = isRecurring ? `${formattedAmount}/${shortCycle(cycle)}` : formattedAmount;
|
|
2701
|
+
return /* @__PURE__ */ jsxs3("div", { className: className ?? "solvapay-checkout-payment", "data-branch": "recurring", children: [
|
|
2702
|
+
/* @__PURE__ */ jsx7("div", { className: "solvapay-checkout-order-summary", "data-variant": "recurring", children: /* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-order-summary-row", children: [
|
|
2703
|
+
/* @__PURE__ */ jsx7("span", { children: planName }),
|
|
2704
|
+
/* @__PURE__ */ jsx7("span", { children: priceLine })
|
|
2705
|
+
] }) }),
|
|
2706
|
+
/* @__PURE__ */ jsxs3(
|
|
2707
|
+
PaymentForm.Root,
|
|
2708
|
+
{
|
|
2709
|
+
planRef: flow.selectedPlanRef,
|
|
2710
|
+
productRef,
|
|
2711
|
+
returnUrl,
|
|
2712
|
+
requireTermsAcceptance: false,
|
|
2713
|
+
onSuccess: (intent) => flow.notifyPaymentSuccess(intent),
|
|
2714
|
+
children: [
|
|
2715
|
+
/* @__PURE__ */ jsx7(PaymentForm.Loading, {}),
|
|
2716
|
+
/* @__PURE__ */ jsx7(PaymentForm.PaymentElement, {}),
|
|
2717
|
+
/* @__PURE__ */ jsx7(PaymentForm.Error, { className: "solvapay-checkout-error" }),
|
|
2718
|
+
/* @__PURE__ */ jsx7(PaymentForm.MandateText, {}),
|
|
2719
|
+
/* @__PURE__ */ jsx7(PaymentForm.SubmitButton, { className: "solvapay-checkout-pay-button", children: isRecurring ? `Subscribe \u2014 ${priceLine}` : `Pay ${formattedAmount}` })
|
|
2720
|
+
]
|
|
2721
|
+
}
|
|
2722
|
+
)
|
|
2723
|
+
] });
|
|
2724
|
+
}
|
|
2725
|
+
var CheckoutEnvContext = createContext5(null);
|
|
2726
|
+
function useReturnUrl() {
|
|
2727
|
+
return useContext6(CheckoutEnvContext)?.returnUrl ?? "";
|
|
2728
|
+
}
|
|
2729
|
+
function useProductRef() {
|
|
2730
|
+
return useContext6(CheckoutEnvContext)?.productRef ?? "";
|
|
2731
|
+
}
|
|
2732
|
+
var BackLink = forwardRef6(function CheckoutStepsBackLink({ label, glyph = "\u2190", className, onClick, ...rest }, ref) {
|
|
2733
|
+
const flow = useCheckoutContext("BackLink");
|
|
2734
|
+
if (!flow.canGoBack) return null;
|
|
2735
|
+
const resolvedLabel = label ?? (flow.step === "payment" && flow.branch === "payg" ? "Change amount" : flow.step === "payment" && flow.branch === "recurring" ? "Change plan" : "Back");
|
|
2736
|
+
return /* @__PURE__ */ jsxs3(
|
|
2737
|
+
"button",
|
|
2738
|
+
{
|
|
2739
|
+
ref,
|
|
2740
|
+
type: "button",
|
|
2741
|
+
className: ["solvapay-checkout-back-link", className].filter(Boolean).join(" "),
|
|
2742
|
+
"data-solvapay-checkout-back": "",
|
|
2743
|
+
onClick: (e) => {
|
|
2744
|
+
onClick?.(e);
|
|
2745
|
+
if (e.defaultPrevented) return;
|
|
2746
|
+
flow.back();
|
|
2747
|
+
},
|
|
2748
|
+
...rest,
|
|
2749
|
+
children: [
|
|
2750
|
+
/* @__PURE__ */ jsx7("span", { className: "solvapay-checkout-back-link-glyph", "aria-hidden": "true", children: glyph }),
|
|
2751
|
+
/* @__PURE__ */ jsx7("span", { className: "solvapay-checkout-back-link-label", children: resolvedLabel })
|
|
2752
|
+
]
|
|
2753
|
+
}
|
|
2754
|
+
);
|
|
2755
|
+
});
|
|
2756
|
+
function Success({ className, children }) {
|
|
2757
|
+
const flow = useCheckoutContext("Success");
|
|
2758
|
+
const locale = useLocale();
|
|
2759
|
+
if (flow.step !== "success" || !flow.successMeta) return null;
|
|
2760
|
+
if (children) {
|
|
2761
|
+
return /* @__PURE__ */ jsx7("div", { className: className ?? "solvapay-checkout-success", children });
|
|
2762
|
+
}
|
|
2763
|
+
const meta = flow.successMeta;
|
|
2764
|
+
if (meta.branch === "payg") {
|
|
2765
|
+
return /* @__PURE__ */ jsxs3("div", { className: className ?? "solvapay-checkout-success", "data-branch": "payg", children: [
|
|
2766
|
+
/* @__PURE__ */ jsx7("div", { className: "solvapay-checkout-success-check", "aria-hidden": "true", children: "\u2713" }),
|
|
2767
|
+
/* @__PURE__ */ jsx7("h2", { className: "solvapay-checkout-success-heading", children: "Credits added" }),
|
|
2768
|
+
/* @__PURE__ */ jsx7("p", { className: "solvapay-checkout-success-subheading", children: "Pay as you go plan is active." }),
|
|
2769
|
+
/* @__PURE__ */ jsxs3("dl", { className: "solvapay-checkout-receipt", "data-variant": "payg", children: [
|
|
2770
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2771
|
+
/* @__PURE__ */ jsx7("dt", { children: "Amount" }),
|
|
2772
|
+
/* @__PURE__ */ jsx7("dd", { children: formatPrice(meta.amountMinor, meta.currency, { locale }) })
|
|
2773
|
+
] }),
|
|
2774
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2775
|
+
/* @__PURE__ */ jsx7("dt", { children: "Credits" }),
|
|
2776
|
+
/* @__PURE__ */ jsxs3("dd", { children: [
|
|
2777
|
+
"+",
|
|
2778
|
+
meta.creditsAdded.toLocaleString(locale)
|
|
2779
|
+
] })
|
|
2780
|
+
] }),
|
|
2781
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2782
|
+
/* @__PURE__ */ jsx7("dt", { children: "Plan" }),
|
|
2783
|
+
/* @__PURE__ */ jsx7("dd", { children: meta.plan.name ?? "Pay as you go" })
|
|
2784
|
+
] }),
|
|
2785
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2786
|
+
/* @__PURE__ */ jsx7("dt", { children: "Rate" }),
|
|
2787
|
+
/* @__PURE__ */ jsx7("dd", { children: meta.rateLabel })
|
|
2788
|
+
] })
|
|
2789
|
+
] })
|
|
2790
|
+
] });
|
|
2791
|
+
}
|
|
2792
|
+
return /* @__PURE__ */ jsxs3("div", { className: className ?? "solvapay-checkout-success", "data-branch": "recurring", children: [
|
|
2793
|
+
/* @__PURE__ */ jsx7("div", { className: "solvapay-checkout-success-check", "aria-hidden": "true", children: "\u2713" }),
|
|
2794
|
+
/* @__PURE__ */ jsxs3("h2", { className: "solvapay-checkout-success-heading", children: [
|
|
2795
|
+
meta.plan.name ?? "Plan",
|
|
2796
|
+
" active"
|
|
2797
|
+
] }),
|
|
2798
|
+
/* @__PURE__ */ jsx7("p", { className: "solvapay-checkout-success-subheading", children: "Subscription is live and credits are ready." }),
|
|
2799
|
+
/* @__PURE__ */ jsxs3("dl", { className: "solvapay-checkout-receipt", "data-variant": "recurring", children: [
|
|
2800
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2801
|
+
/* @__PURE__ */ jsx7("dt", { children: "Plan" }),
|
|
2802
|
+
/* @__PURE__ */ jsx7("dd", { children: meta.plan.name ?? "Plan" })
|
|
2803
|
+
] }),
|
|
2804
|
+
meta.creditsIncluded > 0 ? /* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2805
|
+
/* @__PURE__ */ jsx7("dt", { children: "Credits" }),
|
|
2806
|
+
/* @__PURE__ */ jsxs3("dd", { children: [
|
|
2807
|
+
"+",
|
|
2808
|
+
meta.creditsIncluded.toLocaleString(locale)
|
|
2809
|
+
] })
|
|
2810
|
+
] }) : null,
|
|
2811
|
+
/* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2812
|
+
/* @__PURE__ */ jsx7("dt", { children: "Charged today" }),
|
|
2813
|
+
/* @__PURE__ */ jsx7("dd", { children: formatPrice(meta.chargedTodayMinor, meta.currency, { locale }) })
|
|
2814
|
+
] }),
|
|
2815
|
+
meta.nextRenewalLabel ? /* @__PURE__ */ jsxs3("div", { className: "solvapay-checkout-receipt-row", children: [
|
|
2816
|
+
/* @__PURE__ */ jsx7("dt", { children: "Next renewal" }),
|
|
2817
|
+
/* @__PURE__ */ jsx7("dd", { children: meta.nextRenewalLabel })
|
|
2818
|
+
] }) : null
|
|
2819
|
+
] })
|
|
2820
|
+
] });
|
|
2821
|
+
}
|
|
2822
|
+
var RootWithEnv = forwardRef6(
|
|
2823
|
+
function CheckoutStepsRootWithEnv(props, forwardedRef) {
|
|
2824
|
+
const env = useMemo6(
|
|
2825
|
+
() => ({ returnUrl: props.returnUrl, productRef: props.productRef }),
|
|
2826
|
+
[props.returnUrl, props.productRef]
|
|
2827
|
+
);
|
|
2828
|
+
return /* @__PURE__ */ jsx7(CheckoutEnvContext.Provider, { value: env, children: /* @__PURE__ */ jsx7(Root5, { ...props, ref: forwardedRef }) });
|
|
2829
|
+
}
|
|
2830
|
+
);
|
|
2831
|
+
var CheckoutSteps = {
|
|
2832
|
+
Root: RootWithEnv,
|
|
2833
|
+
IfStep,
|
|
2834
|
+
StepHeading,
|
|
2835
|
+
StepMessage,
|
|
2836
|
+
PlanGrid,
|
|
2837
|
+
PlanContinueButton,
|
|
2838
|
+
AmountPicker: AmountPicker2,
|
|
2839
|
+
AmountContinueButton,
|
|
2840
|
+
Payment,
|
|
2841
|
+
BackLink,
|
|
2842
|
+
Success
|
|
2843
|
+
};
|
|
2844
|
+
var CheckoutStepsRoot2 = RootWithEnv;
|
|
2845
|
+
var CheckoutStepsIfStep = IfStep;
|
|
2846
|
+
var CheckoutStepsStepHeading2 = StepHeading;
|
|
2847
|
+
var CheckoutStepsStepMessage2 = StepMessage;
|
|
2848
|
+
var CheckoutStepsPlanGrid = PlanGrid;
|
|
2849
|
+
var CheckoutStepsPlanContinueButton = PlanContinueButton;
|
|
2850
|
+
var CheckoutStepsAmountPicker = AmountPicker2;
|
|
2851
|
+
var CheckoutStepsAmountContinueButton = AmountContinueButton;
|
|
2852
|
+
var CheckoutStepsPayment = Payment;
|
|
2853
|
+
var CheckoutStepsBackLink2 = BackLink;
|
|
2854
|
+
var CheckoutStepsSuccess = Success;
|
|
2855
|
+
|
|
2856
|
+
// src/primitives/PaywallNotice.tsx
|
|
2857
|
+
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2858
|
+
var PaywallNoticeContext = createContext6(null);
|
|
2859
|
+
function usePaywallNoticeCtx(part) {
|
|
2860
|
+
const ctx = useContext7(PaywallNoticeContext);
|
|
2861
|
+
if (!ctx) {
|
|
2862
|
+
throw new Error(`PaywallNotice.${part} must be rendered inside <PaywallNotice.Root>.`);
|
|
2863
|
+
}
|
|
2864
|
+
return ctx;
|
|
2865
|
+
}
|
|
2866
|
+
var Root6 = forwardRef7(function PaywallNoticeRoot({ content, onResolved, classNames, asChild, children, ...rest }, forwardedRef) {
|
|
2867
|
+
const { resolved, refetch } = usePaywallResolver(content);
|
|
2868
|
+
const classNamesResolved = useMemo7(() => classNames ?? {}, [classNames]);
|
|
2869
|
+
const onResolvedRef = useRef4(onResolved);
|
|
2870
|
+
useEffect5(() => {
|
|
2871
|
+
onResolvedRef.current = onResolved;
|
|
2872
|
+
}, [onResolved]);
|
|
2873
|
+
const hasResolvedRef = useRef4(false);
|
|
2874
|
+
const signalResolved = useCallback5(() => {
|
|
2875
|
+
if (hasResolvedRef.current) return;
|
|
2876
|
+
hasResolvedRef.current = true;
|
|
2877
|
+
onResolvedRef.current?.();
|
|
2878
|
+
}, []);
|
|
2879
|
+
useEffect5(() => {
|
|
2880
|
+
if (resolved) signalResolved();
|
|
2881
|
+
}, [resolved, signalResolved]);
|
|
2882
|
+
const ctx = useMemo7(
|
|
2883
|
+
() => ({
|
|
2884
|
+
content,
|
|
2885
|
+
resolved,
|
|
2886
|
+
refetch,
|
|
2887
|
+
onResolved: signalResolved,
|
|
2888
|
+
classNames: classNamesResolved
|
|
2889
|
+
}),
|
|
2890
|
+
[content, resolved, refetch, signalResolved, classNamesResolved]
|
|
2891
|
+
);
|
|
2892
|
+
const Comp = asChild ? Slot : "div";
|
|
2893
|
+
return /* @__PURE__ */ jsx8(PaywallNoticeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx8(
|
|
2894
|
+
Comp,
|
|
2895
|
+
{
|
|
2896
|
+
ref: forwardedRef,
|
|
2897
|
+
"data-solvapay-paywall-notice": "",
|
|
2898
|
+
"data-kind": content.kind,
|
|
2899
|
+
"data-state": resolved ? "resolved" : "pending",
|
|
2900
|
+
className: classNamesResolved.root,
|
|
2901
|
+
...rest,
|
|
2902
|
+
children
|
|
2903
|
+
}
|
|
2904
|
+
) });
|
|
2905
|
+
});
|
|
2906
|
+
var Heading2 = forwardRef7(function PaywallNoticeHeading({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2907
|
+
const ctx = usePaywallNoticeCtx("Heading");
|
|
2908
|
+
const copy = useCopy();
|
|
2909
|
+
const defaultText = ctx.resolved ? copy.paywall.resolvedHeading : ctx.content.kind === "payment_required" ? copy.paywall.paymentRequiredHeading : isTopupGate(ctx.content) ? copy.paywall.topupRequiredHeading : copy.paywall.activationRequiredHeading;
|
|
2910
|
+
const Comp = asChild ? Slot : "h2";
|
|
2911
|
+
return /* @__PURE__ */ jsx8(
|
|
2912
|
+
Comp,
|
|
2913
|
+
{
|
|
2914
|
+
ref: forwardedRef,
|
|
2915
|
+
"data-solvapay-paywall-heading": "",
|
|
2916
|
+
className: className ?? ctx.classNames.heading,
|
|
2917
|
+
...rest,
|
|
2918
|
+
children: children ?? defaultText
|
|
2919
|
+
}
|
|
2920
|
+
);
|
|
2921
|
+
});
|
|
2922
|
+
var Message = forwardRef7(function PaywallNoticeMessage({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2923
|
+
const ctx = usePaywallNoticeCtx("Message");
|
|
2924
|
+
const copy = useCopy();
|
|
2925
|
+
const Comp = asChild ? Slot : "p";
|
|
2926
|
+
const defaultText = resolvePaywallMessage(ctx.content, copy.paywall);
|
|
2927
|
+
return /* @__PURE__ */ jsx8(
|
|
2928
|
+
Comp,
|
|
2929
|
+
{
|
|
2930
|
+
ref: forwardedRef,
|
|
2931
|
+
"data-solvapay-paywall-message": "",
|
|
2932
|
+
className: className ?? ctx.classNames.message,
|
|
2933
|
+
...rest,
|
|
2934
|
+
children: children ?? defaultText
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
});
|
|
2938
|
+
function isTopupGate(content) {
|
|
2939
|
+
if (content.kind !== "activation_required") return false;
|
|
2940
|
+
const plans = content.plans;
|
|
2941
|
+
if (!plans || plans.length === 0) return false;
|
|
2942
|
+
return plans.every((p) => isPaygPlan(p));
|
|
2943
|
+
}
|
|
2944
|
+
function resolvePaywallMessage(content, paywallCopy) {
|
|
2945
|
+
const productName = content.kind === "payment_required" || content.kind === "activation_required" ? content.productDetails?.name : void 0;
|
|
2946
|
+
const forProduct = productName ? interpolate(paywallCopy.paymentRequiredProductSuffix, { product: productName }) : "";
|
|
2947
|
+
if (content.kind === "payment_required") {
|
|
2948
|
+
const balance = content.balance;
|
|
2949
|
+
if (!balance) {
|
|
2950
|
+
return interpolate(paywallCopy.paymentRequiredMessageNoBalance, { forProduct });
|
|
2951
|
+
}
|
|
2952
|
+
const remaining = balance.remainingUnits ?? 0;
|
|
2953
|
+
if (remaining <= 0) {
|
|
2954
|
+
return interpolate(paywallCopy.paymentRequiredMessage, { forProduct });
|
|
2955
|
+
}
|
|
2956
|
+
return interpolate(paywallCopy.paymentRequiredMessageRemaining, {
|
|
2957
|
+
remaining: String(remaining),
|
|
2958
|
+
pluralSuffix: remaining === 1 ? "" : "s",
|
|
2959
|
+
forProduct
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
if (content.kind === "activation_required") {
|
|
2963
|
+
if (isTopupGate(content)) {
|
|
2964
|
+
return interpolate(paywallCopy.topupRequiredMessage, { forProduct });
|
|
2965
|
+
}
|
|
2966
|
+
return interpolate(paywallCopy.activationRequiredMessage, { forProduct });
|
|
2967
|
+
}
|
|
2968
|
+
return content.message ?? "";
|
|
2969
|
+
}
|
|
2970
|
+
var ProductContext = forwardRef7(function PaywallNoticeProductContext({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2971
|
+
const ctx = usePaywallNoticeCtx("ProductContext");
|
|
2972
|
+
const copy = useCopy();
|
|
2973
|
+
const product = ctx.content.kind === "activation_required" ? ctx.content.productDetails : void 0;
|
|
2974
|
+
if (!product?.name) return null;
|
|
2975
|
+
const label = interpolate(copy.paywall.productContext, { product: product.name });
|
|
2976
|
+
const Comp = asChild ? Slot : "div";
|
|
2977
|
+
return /* @__PURE__ */ jsx8(
|
|
2978
|
+
Comp,
|
|
2979
|
+
{
|
|
2980
|
+
ref: forwardedRef,
|
|
2981
|
+
"data-solvapay-paywall-product-context": "",
|
|
2982
|
+
className: className ?? ctx.classNames.productContext,
|
|
2983
|
+
...rest,
|
|
2984
|
+
children: children ?? label
|
|
2985
|
+
}
|
|
2986
|
+
);
|
|
2987
|
+
});
|
|
2988
|
+
var Balance = forwardRef7(function PaywallNoticeBalance({ asChild, children, className, ...rest }, forwardedRef) {
|
|
2989
|
+
const ctx = usePaywallNoticeCtx("Balance");
|
|
2990
|
+
const copy = useCopy();
|
|
2991
|
+
const balance = ctx.content.balance;
|
|
2992
|
+
if (ctx.content.kind !== "activation_required" || !balance) return null;
|
|
2993
|
+
const label = interpolate(copy.paywall.balanceLine, {
|
|
2994
|
+
available: String(balance.remainingUnits ?? 0),
|
|
2995
|
+
required: String(balance.creditsPerUnit ?? 1)
|
|
2996
|
+
});
|
|
2997
|
+
const Comp = asChild ? Slot : "div";
|
|
2998
|
+
return /* @__PURE__ */ jsx8(
|
|
2999
|
+
Comp,
|
|
3000
|
+
{
|
|
3001
|
+
ref: forwardedRef,
|
|
3002
|
+
"data-solvapay-paywall-balance": "",
|
|
3003
|
+
className: className ?? ctx.classNames.balance,
|
|
3004
|
+
...rest,
|
|
3005
|
+
children: children ?? label
|
|
3006
|
+
}
|
|
3007
|
+
);
|
|
3008
|
+
});
|
|
3009
|
+
function Plans({ className, children }) {
|
|
3010
|
+
const ctx = usePaywallNoticeCtx("Plans");
|
|
3011
|
+
if (ctx.content.kind !== "activation_required") return null;
|
|
3012
|
+
if (!ctx.content.product) return null;
|
|
3013
|
+
const defaultClass = className ?? ctx.classNames.plans ?? "solvapay-paywall-plans";
|
|
3014
|
+
return /* @__PURE__ */ jsx8("div", { "data-solvapay-paywall-plans": "", className: defaultClass, children: /* @__PURE__ */ jsx8(PlanSelector.Root, { productRef: ctx.content.product, filter: hidesFreePlan, children: children ?? /* @__PURE__ */ jsxs4(Fragment5, { children: [
|
|
3015
|
+
/* @__PURE__ */ jsx8(PlanSelector.Grid, { children: /* @__PURE__ */ jsxs4(PlanSelector.Card, { children: [
|
|
3016
|
+
/* @__PURE__ */ jsx8(PlanSelector.CardBadge, {}),
|
|
3017
|
+
/* @__PURE__ */ jsx8(PlanSelector.CardName, {}),
|
|
3018
|
+
/* @__PURE__ */ jsx8(PlanSelector.CardPrice, {}),
|
|
3019
|
+
/* @__PURE__ */ jsx8(PlanSelector.CardInterval, {})
|
|
3020
|
+
] }) }),
|
|
3021
|
+
/* @__PURE__ */ jsx8(PlanSelector.Loading, {}),
|
|
3022
|
+
/* @__PURE__ */ jsx8(PlanSelector.Error, {})
|
|
3023
|
+
] }) }) });
|
|
3024
|
+
}
|
|
3025
|
+
function hidesFreePlan(plan) {
|
|
3026
|
+
return plan.requiresPayment !== false;
|
|
3027
|
+
}
|
|
3028
|
+
var HostedCheckoutLink = forwardRef7(function PaywallNoticeHostedCheckoutLink({ asChild, children, className, ...rest }, forwardedRef) {
|
|
3029
|
+
const ctx = usePaywallNoticeCtx("HostedCheckoutLink");
|
|
3030
|
+
const copy = useCopy();
|
|
3031
|
+
const href = ctx.content.checkoutUrl;
|
|
3032
|
+
if (!href) return null;
|
|
3033
|
+
const Comp = asChild ? Slot : "a";
|
|
3034
|
+
return /* @__PURE__ */ jsx8(
|
|
3035
|
+
Comp,
|
|
3036
|
+
{
|
|
3037
|
+
ref: forwardedRef,
|
|
3038
|
+
href,
|
|
3039
|
+
target: "_blank",
|
|
3040
|
+
rel: "noopener noreferrer",
|
|
3041
|
+
"data-solvapay-paywall-hosted-link": "",
|
|
3042
|
+
className: className ?? ctx.classNames.hostedLink,
|
|
3043
|
+
...rest,
|
|
3044
|
+
children: children ?? copy.paywall.hostedCheckoutButton
|
|
3045
|
+
}
|
|
3046
|
+
);
|
|
3047
|
+
});
|
|
3048
|
+
function EmbeddedCheckout({ returnUrl, topupCurrency, className }) {
|
|
3049
|
+
const ctx = usePaywallNoticeCtx("EmbeddedCheckout");
|
|
3050
|
+
const productRef = ctx.content.product;
|
|
3051
|
+
const { plans } = usePlans({ productRef: productRef ?? void 0 });
|
|
3052
|
+
const filter = useMemo7(() => buildDefaultCheckoutPlanFilter(plans), [plans]);
|
|
3053
|
+
if (!productRef) return null;
|
|
3054
|
+
const resolvedClassName = className ?? ctx.classNames.embeddedCheckout ?? "solvapay-paywall-embedded-checkout";
|
|
3055
|
+
const headingClassName = ctx.classNames.heading ?? "solvapay-paywall-step-heading";
|
|
3056
|
+
const messageClassName = ctx.classNames.message ?? "solvapay-paywall-step-message";
|
|
3057
|
+
return /* @__PURE__ */ jsxs4(
|
|
3058
|
+
CheckoutSteps.Root,
|
|
3059
|
+
{
|
|
3060
|
+
productRef,
|
|
3061
|
+
returnUrl,
|
|
3062
|
+
filter,
|
|
3063
|
+
topupCurrency,
|
|
3064
|
+
onPurchaseSuccess: () => {
|
|
3065
|
+
void ctx.refetch();
|
|
3066
|
+
ctx.onResolved?.();
|
|
3067
|
+
},
|
|
3068
|
+
className: resolvedClassName,
|
|
3069
|
+
children: [
|
|
3070
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.StepHeading, { className: headingClassName }),
|
|
3071
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.StepMessage, { className: messageClassName }),
|
|
3072
|
+
/* @__PURE__ */ jsxs4(CheckoutSteps.IfStep, { step: "plan", children: [
|
|
3073
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.PlanGrid, {}),
|
|
3074
|
+
/* @__PURE__ */ jsx8(PlanSelector.Loading, {}),
|
|
3075
|
+
/* @__PURE__ */ jsx8(PlanSelector.Error, {}),
|
|
3076
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.PlanContinueButton, {})
|
|
3077
|
+
] }),
|
|
3078
|
+
/* @__PURE__ */ jsxs4(CheckoutSteps.IfStep, { step: "amount", children: [
|
|
3079
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.BackLink, {}),
|
|
3080
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.AmountPicker, {}),
|
|
3081
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.AmountContinueButton, {})
|
|
3082
|
+
] }),
|
|
3083
|
+
/* @__PURE__ */ jsxs4(CheckoutSteps.IfStep, { step: "payment", children: [
|
|
3084
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.BackLink, {}),
|
|
3085
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.Payment, {})
|
|
3086
|
+
] }),
|
|
3087
|
+
/* @__PURE__ */ jsx8(CheckoutSteps.IfStep, { step: "success", children: /* @__PURE__ */ jsx8(CheckoutSteps.Success, {}) })
|
|
3088
|
+
]
|
|
3089
|
+
}
|
|
3090
|
+
);
|
|
3091
|
+
}
|
|
3092
|
+
var Retry = forwardRef7(function PaywallNoticeRetry({ asChild, children, className, onClick, ...rest }, forwardedRef) {
|
|
3093
|
+
const ctx = usePaywallNoticeCtx("Retry");
|
|
3094
|
+
const copy = useCopy();
|
|
3095
|
+
const Comp = asChild ? Slot : "button";
|
|
3096
|
+
return /* @__PURE__ */ jsx8(
|
|
3097
|
+
Comp,
|
|
3098
|
+
{
|
|
3099
|
+
ref: forwardedRef,
|
|
3100
|
+
type: "button",
|
|
3101
|
+
disabled: !ctx.resolved,
|
|
3102
|
+
"data-solvapay-paywall-retry": "",
|
|
3103
|
+
"data-state": ctx.resolved ? "ready" : "waiting",
|
|
3104
|
+
className: className ?? ctx.classNames.retryButton,
|
|
3105
|
+
onClick: (e) => {
|
|
3106
|
+
onClick?.(e);
|
|
3107
|
+
if (!e.defaultPrevented && ctx.resolved) ctx.onResolved?.();
|
|
3108
|
+
},
|
|
3109
|
+
...rest,
|
|
3110
|
+
children: children ?? copy.paywall.retryButton
|
|
3111
|
+
}
|
|
3112
|
+
);
|
|
3113
|
+
});
|
|
3114
|
+
var PaywallNotice = Object.assign(Root6, {
|
|
3115
|
+
Root: Root6,
|
|
3116
|
+
Heading: Heading2,
|
|
3117
|
+
Message,
|
|
3118
|
+
ProductContext,
|
|
3119
|
+
Plans,
|
|
3120
|
+
Balance,
|
|
3121
|
+
HostedCheckoutLink,
|
|
3122
|
+
EmbeddedCheckout,
|
|
3123
|
+
Retry
|
|
3124
|
+
});
|
|
3125
|
+
function usePaywallNotice() {
|
|
3126
|
+
return usePaywallNoticeCtx("usePaywallNotice");
|
|
3127
|
+
}
|
|
3128
|
+
function usePaywallNoticeOptional() {
|
|
3129
|
+
return useContext7(PaywallNoticeContext);
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
export {
|
|
3133
|
+
TopupForm2 as TopupForm,
|
|
3134
|
+
ProductBadge2 as ProductBadge,
|
|
3135
|
+
PlanBadge,
|
|
3136
|
+
PurchaseGateRoot2 as PurchaseGateRoot,
|
|
3137
|
+
PurchaseGateAllowed2 as PurchaseGateAllowed,
|
|
3138
|
+
PurchaseGateBlocked2 as PurchaseGateBlocked,
|
|
3139
|
+
PurchaseGateLoading2 as PurchaseGateLoading,
|
|
3140
|
+
PurchaseGateError2 as PurchaseGateError,
|
|
3141
|
+
PurchaseGate,
|
|
3142
|
+
usePurchaseGate,
|
|
3143
|
+
ActivationFlowRoot2 as ActivationFlowRoot,
|
|
3144
|
+
ActivationFlowSummary2 as ActivationFlowSummary,
|
|
3145
|
+
ActivationFlowActivateButton2 as ActivationFlowActivateButton,
|
|
3146
|
+
ActivationFlowAmountPicker,
|
|
3147
|
+
ActivationFlowContinueButton2 as ActivationFlowContinueButton,
|
|
3148
|
+
ActivationFlowRetrying2 as ActivationFlowRetrying,
|
|
3149
|
+
ActivationFlowActivated2 as ActivationFlowActivated,
|
|
3150
|
+
ActivationFlowLoading2 as ActivationFlowLoading,
|
|
3151
|
+
ActivationFlowError2 as ActivationFlowError,
|
|
3152
|
+
ActivationFlow,
|
|
3153
|
+
useActivationFlow,
|
|
3154
|
+
CreditGateRoot2 as CreditGateRoot,
|
|
3155
|
+
CreditGateHeading2 as CreditGateHeading,
|
|
3156
|
+
CreditGateSubheading2 as CreditGateSubheading,
|
|
3157
|
+
CreditGateTopup,
|
|
3158
|
+
CreditGateLoading2 as CreditGateLoading,
|
|
3159
|
+
CreditGateError2 as CreditGateError,
|
|
3160
|
+
CreditGate,
|
|
3161
|
+
useCreditGate,
|
|
3162
|
+
useAutoRecharge,
|
|
3163
|
+
configToAutoRechargeInput,
|
|
3164
|
+
AutoRechargeRoot2 as AutoRechargeRoot,
|
|
3165
|
+
AutoRechargeLoading2 as AutoRechargeLoading,
|
|
3166
|
+
AutoRechargeCard2 as AutoRechargeCard,
|
|
3167
|
+
AutoRechargeCardHeading2 as AutoRechargeCardHeading,
|
|
3168
|
+
AutoRechargeCardSummary2 as AutoRechargeCardSummary,
|
|
3169
|
+
AutoRechargeTrigger2 as AutoRechargeTrigger,
|
|
3170
|
+
AutoRechargeOverlay2 as AutoRechargeOverlay,
|
|
3171
|
+
AutoRechargeContent2 as AutoRechargeContent,
|
|
3172
|
+
AutoRechargeTitle2 as AutoRechargeTitle,
|
|
3173
|
+
AutoRechargeEnableQuestion2 as AutoRechargeEnableQuestion,
|
|
3174
|
+
AutoRechargeEnableSentence2 as AutoRechargeEnableSentence,
|
|
3175
|
+
AutoRechargeEnableRow2 as AutoRechargeEnableRow,
|
|
3176
|
+
AutoRechargeCancelButton2 as AutoRechargeCancelButton,
|
|
3177
|
+
AutoRechargeHeader2 as AutoRechargeHeader,
|
|
3178
|
+
AutoRechargeDescription2 as AutoRechargeDescription,
|
|
3179
|
+
AutoRechargeEnableSwitch2 as AutoRechargeEnableSwitch,
|
|
3180
|
+
AutoRechargeFields2 as AutoRechargeFields,
|
|
3181
|
+
AutoRechargeSetup2 as AutoRechargeSetup,
|
|
3182
|
+
AutoRechargeBody2 as AutoRechargeBody,
|
|
3183
|
+
AutoRechargeSummary2 as AutoRechargeSummary,
|
|
3184
|
+
AutoRechargeThresholdField2 as AutoRechargeThresholdField,
|
|
3185
|
+
AutoRechargeTopupField2 as AutoRechargeTopupField,
|
|
3186
|
+
AutoRechargeAmountField2 as AutoRechargeAmountField,
|
|
3187
|
+
AutoRechargeUnitToggle2 as AutoRechargeUnitToggle,
|
|
3188
|
+
AutoRechargeHint2 as AutoRechargeHint,
|
|
3189
|
+
AutoRechargeValidationError2 as AutoRechargeValidationError,
|
|
3190
|
+
AutoRechargeActions2 as AutoRechargeActions,
|
|
3191
|
+
AutoRechargeSaveButton2 as AutoRechargeSaveButton,
|
|
3192
|
+
AutoRechargeDisableButton2 as AutoRechargeDisableButton,
|
|
3193
|
+
AutoRechargeError2 as AutoRechargeError,
|
|
3194
|
+
AutoRechargeStatusMessage2 as AutoRechargeStatusMessage,
|
|
3195
|
+
AutoRechargeStatus2 as AutoRechargeStatus,
|
|
3196
|
+
AutoRechargeCardSetup,
|
|
3197
|
+
AutoRecharge,
|
|
3198
|
+
useAutoRechargeForm,
|
|
3199
|
+
usePaywallResolver,
|
|
3200
|
+
Root6 as Root,
|
|
3201
|
+
Heading2 as Heading,
|
|
3202
|
+
Message,
|
|
3203
|
+
ProductContext,
|
|
3204
|
+
Balance,
|
|
3205
|
+
Plans,
|
|
3206
|
+
HostedCheckoutLink,
|
|
3207
|
+
EmbeddedCheckout,
|
|
3208
|
+
Retry,
|
|
3209
|
+
PaywallNotice,
|
|
3210
|
+
usePaywallNotice,
|
|
3211
|
+
useCheckoutSteps,
|
|
3212
|
+
CheckoutSteps,
|
|
3213
|
+
CheckoutStepsRoot2 as CheckoutStepsRoot,
|
|
3214
|
+
CheckoutStepsIfStep,
|
|
3215
|
+
CheckoutStepsStepHeading2 as CheckoutStepsStepHeading,
|
|
3216
|
+
CheckoutStepsStepMessage2 as CheckoutStepsStepMessage,
|
|
3217
|
+
CheckoutStepsPlanGrid,
|
|
3218
|
+
CheckoutStepsPlanContinueButton,
|
|
3219
|
+
CheckoutStepsAmountPicker,
|
|
3220
|
+
CheckoutStepsAmountContinueButton,
|
|
3221
|
+
CheckoutStepsPayment,
|
|
3222
|
+
CheckoutStepsBackLink2 as CheckoutStepsBackLink,
|
|
3223
|
+
CheckoutStepsSuccess
|
|
3224
|
+
};
|