@solvapay/react 1.0.9-preview.1 → 1.0.9
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 +209 -0
- package/CONTRIBUTING.md +117 -0
- package/README.md +426 -24
- package/dist/adapters/auth.d.cts +13 -0
- package/dist/adapters/auth.d.ts +13 -0
- package/dist/adapters/auth.js +1 -0
- package/dist/chunk-37R5NZGF.js +4824 -0
- package/dist/chunk-HWVJL5X6.js +429 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-R2ZPZ7VM.js +597 -0
- package/dist/chunk-ZAV7CQ4G.js +361 -0
- package/dist/index-WBjulQHf.d.cts +3656 -0
- package/dist/index-onWNU7iT.d.ts +3656 -0
- package/dist/index.cjs +5556 -1143
- package/dist/index.d.cts +618 -708
- package/dist/index.d.ts +618 -708
- package/dist/index.js +597 -1664
- package/dist/mcp/index.cjs +8096 -0
- package/dist/mcp/index.d.cts +1013 -0
- package/dist/mcp/index.d.ts +1013 -0
- package/dist/mcp/index.js +2724 -0
- package/dist/mcp/styles.css +1020 -0
- package/dist/primitives/index.cjs +5316 -0
- package/dist/primitives/index.d.cts +721 -0
- package/dist/primitives/index.d.ts +721 -0
- package/dist/primitives/index.js +232 -0
- package/dist/styles.css +1115 -0
- package/dist/useUsage-BmOYXxgG.d.cts +413 -0
- package/dist/useUsage-nD7zwSbG.d.ts +413 -0
- package/dist/webapi-K5XBCEO6.js +3775 -0
- package/package.json +37 -6
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AmountPicker,
|
|
3
|
+
MissingProductRefError,
|
|
4
|
+
MissingProviderError,
|
|
5
|
+
Slot,
|
|
6
|
+
SolvaPayContext,
|
|
7
|
+
TopupForm,
|
|
8
|
+
composeEventHandlers,
|
|
9
|
+
getMinorUnitsPerMajor,
|
|
10
|
+
interpolate,
|
|
11
|
+
useActivation,
|
|
12
|
+
useBalance,
|
|
13
|
+
useCopy,
|
|
14
|
+
usePlan,
|
|
15
|
+
usePlanSelection,
|
|
16
|
+
useProduct,
|
|
17
|
+
usePurchase,
|
|
18
|
+
useTopupAmountSelector
|
|
19
|
+
} from "./chunk-37R5NZGF.js";
|
|
20
|
+
|
|
21
|
+
// src/TopupForm.tsx
|
|
22
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
|
+
var TopupForm2 = (props) => {
|
|
24
|
+
const { className, buttonClassName, submitButtonText, ...rootProps } = props;
|
|
25
|
+
const rootClass = ["solvapay-topup-form", className].filter(Boolean).join(" ");
|
|
26
|
+
const buttonClass = ["solvapay-topup-form-submit", buttonClassName].filter(Boolean).join(" ");
|
|
27
|
+
return /* @__PURE__ */ jsxs(TopupForm.Root, { ...rootProps, className: rootClass, children: [
|
|
28
|
+
/* @__PURE__ */ jsx(TopupForm.PaymentElement, {}),
|
|
29
|
+
/* @__PURE__ */ jsx(TopupForm.Error, { className: "solvapay-topup-form-error" }),
|
|
30
|
+
/* @__PURE__ */ jsx(TopupForm.Loading, { className: "solvapay-topup-form-loading" }),
|
|
31
|
+
/* @__PURE__ */ jsx(TopupForm.SubmitButton, { className: buttonClass, children: submitButtonText })
|
|
32
|
+
] });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/primitives/ProductBadge.tsx
|
|
36
|
+
import { forwardRef, useContext, useEffect, useState } from "react";
|
|
37
|
+
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
38
|
+
var ProductBadgeImpl = forwardRef(function ProductBadge({ asChild, children, ...rest }, forwardedRef) {
|
|
39
|
+
const solva = useContext(SolvaPayContext);
|
|
40
|
+
if (!solva) throw new MissingProviderError("ProductBadge");
|
|
41
|
+
const { purchases, loading, hasPaidPurchase, activePurchase } = usePurchase();
|
|
42
|
+
const copy = useCopy();
|
|
43
|
+
const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!loading) setHasLoadedOnce(true);
|
|
46
|
+
}, [loading]);
|
|
47
|
+
const planToDisplay = activePurchase?.productName ?? null;
|
|
48
|
+
const shouldShow = planToDisplay !== null && (!loading || hasLoadedOnce);
|
|
49
|
+
if (!shouldShow) return null;
|
|
50
|
+
const commonProps = {
|
|
51
|
+
"data-solvapay-product-badge": "",
|
|
52
|
+
"data-loading": loading ? "" : void 0,
|
|
53
|
+
"data-has-purchase": activePurchase ? "" : void 0,
|
|
54
|
+
"data-has-paid-purchase": hasPaidPurchase ? "" : void 0,
|
|
55
|
+
role: "status",
|
|
56
|
+
"aria-live": "polite",
|
|
57
|
+
"aria-busy": loading,
|
|
58
|
+
"aria-label": interpolate(copy.product.currentProductLabel, { name: planToDisplay }),
|
|
59
|
+
...rest
|
|
60
|
+
};
|
|
61
|
+
if (asChild) {
|
|
62
|
+
return (
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
|
+
/* @__PURE__ */ jsx2(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx2(Fragment, { children: planToDisplay }) })
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
void purchases;
|
|
68
|
+
return (
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
+
/* @__PURE__ */ jsx2("div", { ref: forwardedRef, ...commonProps, children: children ?? planToDisplay })
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
var ProductBadge2 = ProductBadgeImpl;
|
|
74
|
+
var PlanBadge = ProductBadgeImpl;
|
|
75
|
+
|
|
76
|
+
// src/primitives/PurchaseGate.tsx
|
|
77
|
+
import {
|
|
78
|
+
createContext,
|
|
79
|
+
forwardRef as forwardRef2,
|
|
80
|
+
useContext as useContext2,
|
|
81
|
+
useMemo
|
|
82
|
+
} from "react";
|
|
83
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
84
|
+
var PurchaseGateContext = createContext(null);
|
|
85
|
+
function useGateCtx(part) {
|
|
86
|
+
const ctx = useContext2(PurchaseGateContext);
|
|
87
|
+
if (!ctx) {
|
|
88
|
+
throw new Error(`PurchaseGate.${part} must be rendered inside <PurchaseGate.Root>.`);
|
|
89
|
+
}
|
|
90
|
+
return ctx;
|
|
91
|
+
}
|
|
92
|
+
var Root = forwardRef2(function PurchaseGateRoot({ requirePlan, requireProduct, asChild, children, ...rest }, forwardedRef) {
|
|
93
|
+
const solva = useContext2(SolvaPayContext);
|
|
94
|
+
if (!solva) throw new MissingProviderError("PurchaseGate");
|
|
95
|
+
const { purchases, loading, hasProduct, error } = usePurchase();
|
|
96
|
+
const productToCheck = requireProduct || requirePlan;
|
|
97
|
+
const hasAccess = productToCheck ? hasProduct(productToCheck) : purchases.some((p) => p.status === "active");
|
|
98
|
+
const state = loading ? "loading" : hasAccess ? "allowed" : "blocked";
|
|
99
|
+
const ctx = useMemo(
|
|
100
|
+
() => ({ state, loading, hasAccess, error }),
|
|
101
|
+
[state, loading, hasAccess, error]
|
|
102
|
+
);
|
|
103
|
+
const Comp = asChild ? Slot : "div";
|
|
104
|
+
return /* @__PURE__ */ jsx3(PurchaseGateContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx3(
|
|
105
|
+
Comp,
|
|
106
|
+
{
|
|
107
|
+
ref: forwardedRef,
|
|
108
|
+
"data-solvapay-purchase-gate": "",
|
|
109
|
+
"data-state": state,
|
|
110
|
+
...rest,
|
|
111
|
+
children
|
|
112
|
+
}
|
|
113
|
+
) });
|
|
114
|
+
});
|
|
115
|
+
var Allowed = forwardRef2(function PurchaseGateAllowed({ asChild, children, ...rest }, forwardedRef) {
|
|
116
|
+
const ctx = useGateCtx("Allowed");
|
|
117
|
+
if (ctx.state !== "allowed") return null;
|
|
118
|
+
const Comp = asChild ? Slot : "div";
|
|
119
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-allowed": "", ...rest, children });
|
|
120
|
+
});
|
|
121
|
+
var Blocked = forwardRef2(function PurchaseGateBlocked({ asChild, children, ...rest }, forwardedRef) {
|
|
122
|
+
const ctx = useGateCtx("Blocked");
|
|
123
|
+
if (ctx.state !== "blocked") return null;
|
|
124
|
+
const Comp = asChild ? Slot : "div";
|
|
125
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-blocked": "", ...rest, children });
|
|
126
|
+
});
|
|
127
|
+
var Loading = forwardRef2(function PurchaseGateLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
128
|
+
const ctx = useGateCtx("Loading");
|
|
129
|
+
if (ctx.state !== "loading") return null;
|
|
130
|
+
const Comp = asChild ? Slot : "div";
|
|
131
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-loading": "", ...rest, children });
|
|
132
|
+
});
|
|
133
|
+
var ErrorSlot = forwardRef2(function PurchaseGateError({ asChild, children, ...rest }, forwardedRef) {
|
|
134
|
+
const ctx = useGateCtx("Error");
|
|
135
|
+
if (!ctx.error) return null;
|
|
136
|
+
const Comp = asChild ? Slot : "div";
|
|
137
|
+
return /* @__PURE__ */ jsx3(Comp, { ref: forwardedRef, "data-solvapay-purchase-gate-error": "", role: "alert", ...rest, children: children ?? ctx.error.message });
|
|
138
|
+
});
|
|
139
|
+
var PurchaseGateRoot2 = Root;
|
|
140
|
+
var PurchaseGateAllowed2 = Allowed;
|
|
141
|
+
var PurchaseGateBlocked2 = Blocked;
|
|
142
|
+
var PurchaseGateLoading2 = Loading;
|
|
143
|
+
var PurchaseGateError2 = ErrorSlot;
|
|
144
|
+
var PurchaseGate = {
|
|
145
|
+
Root,
|
|
146
|
+
Allowed,
|
|
147
|
+
Blocked,
|
|
148
|
+
Loading,
|
|
149
|
+
Error: ErrorSlot
|
|
150
|
+
};
|
|
151
|
+
function usePurchaseGate() {
|
|
152
|
+
return useGateCtx("usePurchaseGate");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/primitives/ActivationFlow.tsx
|
|
156
|
+
import {
|
|
157
|
+
createContext as createContext2,
|
|
158
|
+
forwardRef as forwardRef3,
|
|
159
|
+
useCallback,
|
|
160
|
+
useContext as useContext3,
|
|
161
|
+
useEffect as useEffect2,
|
|
162
|
+
useMemo as useMemo2,
|
|
163
|
+
useRef,
|
|
164
|
+
useState as useState2
|
|
165
|
+
} from "react";
|
|
166
|
+
import { Fragment as Fragment2, jsx as jsx4 } from "react/jsx-runtime";
|
|
167
|
+
var ActivationFlowContext = createContext2(null);
|
|
168
|
+
function useFlowCtx(part) {
|
|
169
|
+
const ctx = useContext3(ActivationFlowContext);
|
|
170
|
+
if (!ctx) {
|
|
171
|
+
throw new Error(`ActivationFlow.${part} must be rendered inside <ActivationFlow.Root>.`);
|
|
172
|
+
}
|
|
173
|
+
return ctx;
|
|
174
|
+
}
|
|
175
|
+
var Root2 = forwardRef3(function ActivationFlowRoot({
|
|
176
|
+
productRef,
|
|
177
|
+
planRef: planRefProp,
|
|
178
|
+
onSuccess,
|
|
179
|
+
onError,
|
|
180
|
+
retryDelayMs = 1500,
|
|
181
|
+
retryBackoffMs = 2e3,
|
|
182
|
+
asChild,
|
|
183
|
+
children,
|
|
184
|
+
...rest
|
|
185
|
+
}, forwardedRef) {
|
|
186
|
+
const solva = useContext3(SolvaPayContext);
|
|
187
|
+
if (!solva) throw new MissingProviderError("ActivationFlow");
|
|
188
|
+
if (!productRef) throw new MissingProductRefError("ActivationFlow");
|
|
189
|
+
const planSelection = usePlanSelection();
|
|
190
|
+
const resolvedPlanRef = planRefProp ?? planSelection?.selectedPlanRef ?? void 0;
|
|
191
|
+
const { plan } = usePlan({ planRef: resolvedPlanRef, productRef });
|
|
192
|
+
const { activate, state, error, result, reset } = useActivation();
|
|
193
|
+
const currency = plan?.currency ?? "USD";
|
|
194
|
+
const amountSelector = useTopupAmountSelector({ currency });
|
|
195
|
+
const { adjustBalance, creditsPerMinorUnit, displayExchangeRate } = useBalance();
|
|
196
|
+
const [step, setStep] = useState2("summary");
|
|
197
|
+
const calledSuccessRef = useRef(false);
|
|
198
|
+
const retryTimeoutRef = useRef(null);
|
|
199
|
+
useEffect2(() => {
|
|
200
|
+
if (state === "activated" && !calledSuccessRef.current) {
|
|
201
|
+
calledSuccessRef.current = true;
|
|
202
|
+
setStep("activated");
|
|
203
|
+
if (result) {
|
|
204
|
+
const activationResult = { kind: "activated", result };
|
|
205
|
+
onSuccess?.(activationResult);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}, [state, result, onSuccess]);
|
|
209
|
+
useEffect2(() => {
|
|
210
|
+
if (state === "topup_required" && (step === "summary" || step === "activating")) {
|
|
211
|
+
setStep("selectAmount");
|
|
212
|
+
}
|
|
213
|
+
}, [state, step]);
|
|
214
|
+
useEffect2(() => {
|
|
215
|
+
if ((state === "error" || state === "payment_required") && error) {
|
|
216
|
+
setStep("error");
|
|
217
|
+
if (state === "error") onError?.(new Error(error));
|
|
218
|
+
}
|
|
219
|
+
}, [state, error, onError]);
|
|
220
|
+
const handleActivate = useCallback(async () => {
|
|
221
|
+
if (!resolvedPlanRef) return;
|
|
222
|
+
setStep("activating");
|
|
223
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
224
|
+
}, [activate, productRef, resolvedPlanRef]);
|
|
225
|
+
const goToTopupPayment = useCallback(() => {
|
|
226
|
+
if (amountSelector.validate()) setStep("topupPayment");
|
|
227
|
+
}, [amountSelector]);
|
|
228
|
+
const backToSelectAmount = useCallback(() => {
|
|
229
|
+
setStep("selectAmount");
|
|
230
|
+
}, []);
|
|
231
|
+
const retryActivation = useCallback(async () => {
|
|
232
|
+
if (!resolvedPlanRef) return;
|
|
233
|
+
setStep("retrying");
|
|
234
|
+
const amountMinor2 = Math.round(
|
|
235
|
+
(amountSelector.resolvedAmount || 0) * getMinorUnitsPerMajor(currency)
|
|
236
|
+
);
|
|
237
|
+
const rate = displayExchangeRate ?? 1;
|
|
238
|
+
if (creditsPerMinorUnit) {
|
|
239
|
+
adjustBalance(Math.floor(amountMinor2 / rate * creditsPerMinorUnit));
|
|
240
|
+
}
|
|
241
|
+
await new Promise((r) => setTimeout(r, retryDelayMs));
|
|
242
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
243
|
+
}, [
|
|
244
|
+
resolvedPlanRef,
|
|
245
|
+
amountSelector.resolvedAmount,
|
|
246
|
+
currency,
|
|
247
|
+
displayExchangeRate,
|
|
248
|
+
creditsPerMinorUnit,
|
|
249
|
+
adjustBalance,
|
|
250
|
+
retryDelayMs,
|
|
251
|
+
activate,
|
|
252
|
+
productRef
|
|
253
|
+
]);
|
|
254
|
+
const handleTopupSuccess = useCallback(async () => {
|
|
255
|
+
await retryActivation();
|
|
256
|
+
}, [retryActivation]);
|
|
257
|
+
useEffect2(() => {
|
|
258
|
+
if (step !== "retrying") return;
|
|
259
|
+
if (state !== "topup_required") return;
|
|
260
|
+
if (!resolvedPlanRef) return;
|
|
261
|
+
retryTimeoutRef.current = setTimeout(async () => {
|
|
262
|
+
await activate({ productRef, planRef: resolvedPlanRef });
|
|
263
|
+
}, retryBackoffMs);
|
|
264
|
+
return () => {
|
|
265
|
+
if (retryTimeoutRef.current) clearTimeout(retryTimeoutRef.current);
|
|
266
|
+
};
|
|
267
|
+
}, [step, state, resolvedPlanRef, retryBackoffMs, activate, productRef]);
|
|
268
|
+
const resetFlow = useCallback(() => {
|
|
269
|
+
reset();
|
|
270
|
+
calledSuccessRef.current = false;
|
|
271
|
+
setStep("summary");
|
|
272
|
+
}, [reset]);
|
|
273
|
+
const amountMinor = Math.round(
|
|
274
|
+
(amountSelector.resolvedAmount || 0) * getMinorUnitsPerMajor(currency)
|
|
275
|
+
);
|
|
276
|
+
const ctx = useMemo2(
|
|
277
|
+
() => ({
|
|
278
|
+
step,
|
|
279
|
+
plan,
|
|
280
|
+
productRef,
|
|
281
|
+
planRef: resolvedPlanRef ?? "",
|
|
282
|
+
amountSelector,
|
|
283
|
+
amountMinor,
|
|
284
|
+
// Deprecated alias — same value as amountMinor so legacy consumers
|
|
285
|
+
// keep working after the zero-decimal fix (previously this was
|
|
286
|
+
// `resolvedAmount * 100`, which over-billed JPY/KRW by 100x).
|
|
287
|
+
amountCents: amountMinor,
|
|
288
|
+
currency,
|
|
289
|
+
activate: handleActivate,
|
|
290
|
+
reset: resetFlow,
|
|
291
|
+
goToTopupPayment,
|
|
292
|
+
backToSelectAmount,
|
|
293
|
+
onTopupSuccess: handleTopupSuccess,
|
|
294
|
+
error,
|
|
295
|
+
onError
|
|
296
|
+
}),
|
|
297
|
+
[
|
|
298
|
+
step,
|
|
299
|
+
plan,
|
|
300
|
+
productRef,
|
|
301
|
+
resolvedPlanRef,
|
|
302
|
+
amountSelector,
|
|
303
|
+
amountMinor,
|
|
304
|
+
currency,
|
|
305
|
+
handleActivate,
|
|
306
|
+
resetFlow,
|
|
307
|
+
goToTopupPayment,
|
|
308
|
+
backToSelectAmount,
|
|
309
|
+
handleTopupSuccess,
|
|
310
|
+
error,
|
|
311
|
+
onError
|
|
312
|
+
]
|
|
313
|
+
);
|
|
314
|
+
const Comp = asChild ? Slot : "div";
|
|
315
|
+
return /* @__PURE__ */ jsx4(ActivationFlowContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx4(
|
|
316
|
+
Comp,
|
|
317
|
+
{
|
|
318
|
+
ref: forwardedRef,
|
|
319
|
+
"data-solvapay-activation-flow": "",
|
|
320
|
+
"data-state": step,
|
|
321
|
+
...rest,
|
|
322
|
+
children
|
|
323
|
+
}
|
|
324
|
+
) });
|
|
325
|
+
});
|
|
326
|
+
function matchStep(step, allowed) {
|
|
327
|
+
return allowed.includes(step);
|
|
328
|
+
}
|
|
329
|
+
var Summary = forwardRef3(function ActivationFlowSummary({ asChild, children, ...rest }, forwardedRef) {
|
|
330
|
+
const ctx = useFlowCtx("Summary");
|
|
331
|
+
if (!matchStep(ctx.step, ["summary", "activating"])) return null;
|
|
332
|
+
const Comp = asChild ? Slot : "div";
|
|
333
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-summary": "", ...rest, children });
|
|
334
|
+
});
|
|
335
|
+
var ActivateButton = forwardRef3(
|
|
336
|
+
function ActivationFlowActivateButton({ asChild, onClick, children, ...rest }, forwardedRef) {
|
|
337
|
+
const ctx = useFlowCtx("ActivateButton");
|
|
338
|
+
const copy = useCopy();
|
|
339
|
+
if (!matchStep(ctx.step, ["summary", "activating"])) return null;
|
|
340
|
+
const isActivating = ctx.step === "activating";
|
|
341
|
+
const disabled = isActivating;
|
|
342
|
+
const commonProps = {
|
|
343
|
+
"data-solvapay-activation-flow-activate": "",
|
|
344
|
+
"data-state": isActivating ? "activating" : "idle",
|
|
345
|
+
"aria-busy": isActivating,
|
|
346
|
+
disabled,
|
|
347
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
348
|
+
void ctx.activate();
|
|
349
|
+
}),
|
|
350
|
+
...rest
|
|
351
|
+
};
|
|
352
|
+
const label = isActivating ? copy.activationFlow.activatingLabel : copy.activationFlow.activateButton;
|
|
353
|
+
if (asChild) {
|
|
354
|
+
return (
|
|
355
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
356
|
+
/* @__PURE__ */ jsx4(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx4(Fragment2, { children: label }) })
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return /* @__PURE__ */ jsx4("button", { ref: forwardedRef, type: "button", ...commonProps, children: children ?? label });
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
var AmountPickerMount = ({ children }) => {
|
|
363
|
+
const ctx = useFlowCtx("AmountPicker");
|
|
364
|
+
if (ctx.step !== "selectAmount") return null;
|
|
365
|
+
return /* @__PURE__ */ jsx4("div", { "data-solvapay-activation-flow-amount-picker": "", children: /* @__PURE__ */ jsx4(AmountPicker.Root, { currency: ctx.currency, selector: ctx.amountSelector, children }) });
|
|
366
|
+
};
|
|
367
|
+
var ContinueButton = forwardRef3(
|
|
368
|
+
function ActivationFlowContinueButton({ asChild, onClick, children, ...rest }, forwardedRef) {
|
|
369
|
+
const ctx = useFlowCtx("ContinueButton");
|
|
370
|
+
const copy = useCopy();
|
|
371
|
+
if (ctx.step !== "selectAmount") return null;
|
|
372
|
+
const disabled = !ctx.amountSelector.resolvedAmount;
|
|
373
|
+
const commonProps = {
|
|
374
|
+
"data-solvapay-activation-flow-continue": "",
|
|
375
|
+
"data-state": disabled ? "disabled" : "idle",
|
|
376
|
+
disabled,
|
|
377
|
+
"aria-disabled": disabled || void 0,
|
|
378
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
379
|
+
ctx.goToTopupPayment();
|
|
380
|
+
}),
|
|
381
|
+
...rest
|
|
382
|
+
};
|
|
383
|
+
if (asChild) {
|
|
384
|
+
return (
|
|
385
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
386
|
+
/* @__PURE__ */ jsx4(Slot, { ref: forwardedRef, ...commonProps, children: children ?? /* @__PURE__ */ jsx4(Fragment2, { children: copy.activationFlow.continueToPayment }) })
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
return /* @__PURE__ */ jsx4("button", { ref: forwardedRef, type: "button", ...commonProps, children: children ?? copy.activationFlow.continueToPayment });
|
|
390
|
+
}
|
|
391
|
+
);
|
|
392
|
+
var Retrying = forwardRef3(function ActivationFlowRetrying({ asChild, children, ...rest }, forwardedRef) {
|
|
393
|
+
const ctx = useFlowCtx("Retrying");
|
|
394
|
+
if (ctx.step !== "retrying") return null;
|
|
395
|
+
const Comp = asChild ? Slot : "div";
|
|
396
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-retrying": "", ...rest, children });
|
|
397
|
+
});
|
|
398
|
+
var Activated = forwardRef3(function ActivationFlowActivated({ asChild, children, ...rest }, forwardedRef) {
|
|
399
|
+
const ctx = useFlowCtx("Activated");
|
|
400
|
+
if (ctx.step !== "activated") return null;
|
|
401
|
+
const Comp = asChild ? Slot : "div";
|
|
402
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-activated": "", ...rest, children });
|
|
403
|
+
});
|
|
404
|
+
var Loading2 = forwardRef3(function ActivationFlowLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
405
|
+
const ctx = useFlowCtx("Loading");
|
|
406
|
+
if (ctx.plan) return null;
|
|
407
|
+
const Comp = asChild ? Slot : "div";
|
|
408
|
+
return /* @__PURE__ */ jsx4(Comp, { ref: forwardedRef, "data-solvapay-activation-flow-loading": "", ...rest, children });
|
|
409
|
+
});
|
|
410
|
+
var ErrorSlot2 = forwardRef3(function ActivationFlowError({ asChild, children, ...rest }, forwardedRef) {
|
|
411
|
+
const ctx = useFlowCtx("Error");
|
|
412
|
+
if (ctx.step !== "error") return null;
|
|
413
|
+
const Comp = asChild ? Slot : "div";
|
|
414
|
+
return /* @__PURE__ */ jsx4(
|
|
415
|
+
Comp,
|
|
416
|
+
{
|
|
417
|
+
ref: forwardedRef,
|
|
418
|
+
role: "alert",
|
|
419
|
+
"data-solvapay-activation-flow-error": "",
|
|
420
|
+
...rest,
|
|
421
|
+
children: children ?? ctx.error
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
});
|
|
425
|
+
var ActivationFlowRoot2 = Root2;
|
|
426
|
+
var ActivationFlowSummary2 = Summary;
|
|
427
|
+
var ActivationFlowActivateButton2 = ActivateButton;
|
|
428
|
+
var ActivationFlowAmountPicker = AmountPickerMount;
|
|
429
|
+
var ActivationFlowContinueButton2 = ContinueButton;
|
|
430
|
+
var ActivationFlowRetrying2 = Retrying;
|
|
431
|
+
var ActivationFlowActivated2 = Activated;
|
|
432
|
+
var ActivationFlowLoading2 = Loading2;
|
|
433
|
+
var ActivationFlowError2 = ErrorSlot2;
|
|
434
|
+
var ActivationFlow = {
|
|
435
|
+
Root: Root2,
|
|
436
|
+
Summary,
|
|
437
|
+
ActivateButton,
|
|
438
|
+
AmountPicker: AmountPickerMount,
|
|
439
|
+
ContinueButton,
|
|
440
|
+
Retrying,
|
|
441
|
+
Activated,
|
|
442
|
+
Loading: Loading2,
|
|
443
|
+
Error: ErrorSlot2
|
|
444
|
+
};
|
|
445
|
+
function useActivationFlow() {
|
|
446
|
+
return useFlowCtx("useActivationFlow");
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// src/primitives/CreditGate.tsx
|
|
450
|
+
import {
|
|
451
|
+
createContext as createContext3,
|
|
452
|
+
forwardRef as forwardRef4,
|
|
453
|
+
useContext as useContext4,
|
|
454
|
+
useMemo as useMemo3
|
|
455
|
+
} from "react";
|
|
456
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
457
|
+
var CreditGateContext = createContext3(null);
|
|
458
|
+
function useGateCtx2(part) {
|
|
459
|
+
const ctx = useContext4(CreditGateContext);
|
|
460
|
+
if (!ctx) {
|
|
461
|
+
throw new Error(`CreditGate.${part} must be rendered inside <CreditGate.Root>.`);
|
|
462
|
+
}
|
|
463
|
+
return ctx;
|
|
464
|
+
}
|
|
465
|
+
var Root3 = forwardRef4(function CreditGateRoot({
|
|
466
|
+
minCredits = 1,
|
|
467
|
+
productRef,
|
|
468
|
+
topupAmount = 1e3,
|
|
469
|
+
topupCurrency = "usd",
|
|
470
|
+
asChild,
|
|
471
|
+
children,
|
|
472
|
+
...rest
|
|
473
|
+
}, forwardedRef) {
|
|
474
|
+
const solva = useContext4(SolvaPayContext);
|
|
475
|
+
if (!solva) throw new MissingProviderError("CreditGate");
|
|
476
|
+
const { credits, loading } = useBalance();
|
|
477
|
+
const { product } = useProduct(productRef);
|
|
478
|
+
const hasCredits = credits != null && credits >= minCredits;
|
|
479
|
+
const state = loading && credits == null ? "loading" : hasCredits ? "allowed" : "blocked";
|
|
480
|
+
const ctx = useMemo3(
|
|
481
|
+
() => ({
|
|
482
|
+
state,
|
|
483
|
+
loading,
|
|
484
|
+
hasCredits,
|
|
485
|
+
balance: credits,
|
|
486
|
+
productName: product?.name ?? null,
|
|
487
|
+
topupAmount,
|
|
488
|
+
topupCurrency
|
|
489
|
+
}),
|
|
490
|
+
[state, loading, hasCredits, credits, product?.name, topupAmount, topupCurrency]
|
|
491
|
+
);
|
|
492
|
+
const Comp = asChild ? Slot : "div";
|
|
493
|
+
return /* @__PURE__ */ jsx5(CreditGateContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx5(
|
|
494
|
+
Comp,
|
|
495
|
+
{
|
|
496
|
+
ref: forwardedRef,
|
|
497
|
+
"data-solvapay-credit-gate": "",
|
|
498
|
+
"data-state": state,
|
|
499
|
+
...rest,
|
|
500
|
+
children
|
|
501
|
+
}
|
|
502
|
+
) });
|
|
503
|
+
});
|
|
504
|
+
var Heading = forwardRef4(function CreditGateHeading({ asChild, children, ...rest }, forwardedRef) {
|
|
505
|
+
const ctx = useGateCtx2("Heading");
|
|
506
|
+
const copy = useCopy();
|
|
507
|
+
if (ctx.state !== "blocked") return null;
|
|
508
|
+
const Comp = asChild ? Slot : "h3";
|
|
509
|
+
return /* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-heading": "", ...rest, children: children ?? copy.creditGate.lowBalanceHeading });
|
|
510
|
+
});
|
|
511
|
+
var Subheading = forwardRef4(function CreditGateSubheading({ asChild, children, ...rest }, forwardedRef) {
|
|
512
|
+
const ctx = useGateCtx2("Subheading");
|
|
513
|
+
const copy = useCopy();
|
|
514
|
+
if (ctx.state !== "blocked") return null;
|
|
515
|
+
const text = interpolate(copy.creditGate.lowBalanceSubheading, {
|
|
516
|
+
product: ctx.productName ?? "this product"
|
|
517
|
+
});
|
|
518
|
+
const Comp = asChild ? Slot : "p";
|
|
519
|
+
return /* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-subheading": "", ...rest, children: children ?? text });
|
|
520
|
+
});
|
|
521
|
+
var Topup = ({ amount, currency }) => {
|
|
522
|
+
const ctx = useGateCtx2("Topup");
|
|
523
|
+
if (ctx.state !== "blocked") return null;
|
|
524
|
+
return /* @__PURE__ */ jsx5(
|
|
525
|
+
TopupForm2,
|
|
526
|
+
{
|
|
527
|
+
amount: amount ?? ctx.topupAmount,
|
|
528
|
+
currency: currency ?? ctx.topupCurrency
|
|
529
|
+
}
|
|
530
|
+
);
|
|
531
|
+
};
|
|
532
|
+
var Loading3 = forwardRef4(function CreditGateLoading({ asChild, children, ...rest }, forwardedRef) {
|
|
533
|
+
const ctx = useGateCtx2("Loading");
|
|
534
|
+
if (ctx.state !== "loading") return null;
|
|
535
|
+
const Comp = asChild ? Slot : "div";
|
|
536
|
+
return (
|
|
537
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
538
|
+
/* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-loading": "", ...rest, children })
|
|
539
|
+
);
|
|
540
|
+
});
|
|
541
|
+
var ErrorSlot3 = forwardRef4(function CreditGateError({ asChild, children, ...rest }, forwardedRef) {
|
|
542
|
+
if (!children) return null;
|
|
543
|
+
const Comp = asChild ? Slot : "div";
|
|
544
|
+
return (
|
|
545
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
546
|
+
/* @__PURE__ */ jsx5(Comp, { ref: forwardedRef, "data-solvapay-credit-gate-error": "", role: "alert", ...rest, children })
|
|
547
|
+
);
|
|
548
|
+
});
|
|
549
|
+
var CreditGateRoot2 = Root3;
|
|
550
|
+
var CreditGateHeading2 = Heading;
|
|
551
|
+
var CreditGateSubheading2 = Subheading;
|
|
552
|
+
var CreditGateTopup = Topup;
|
|
553
|
+
var CreditGateLoading2 = Loading3;
|
|
554
|
+
var CreditGateError2 = ErrorSlot3;
|
|
555
|
+
var CreditGate = {
|
|
556
|
+
Root: Root3,
|
|
557
|
+
Heading,
|
|
558
|
+
Subheading,
|
|
559
|
+
Topup,
|
|
560
|
+
Loading: Loading3,
|
|
561
|
+
Error: ErrorSlot3
|
|
562
|
+
};
|
|
563
|
+
function useCreditGate() {
|
|
564
|
+
return useGateCtx2("useCreditGate");
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export {
|
|
568
|
+
TopupForm2 as TopupForm,
|
|
569
|
+
ProductBadge2 as ProductBadge,
|
|
570
|
+
PlanBadge,
|
|
571
|
+
PurchaseGateRoot2 as PurchaseGateRoot,
|
|
572
|
+
PurchaseGateAllowed2 as PurchaseGateAllowed,
|
|
573
|
+
PurchaseGateBlocked2 as PurchaseGateBlocked,
|
|
574
|
+
PurchaseGateLoading2 as PurchaseGateLoading,
|
|
575
|
+
PurchaseGateError2 as PurchaseGateError,
|
|
576
|
+
PurchaseGate,
|
|
577
|
+
usePurchaseGate,
|
|
578
|
+
ActivationFlowRoot2 as ActivationFlowRoot,
|
|
579
|
+
ActivationFlowSummary2 as ActivationFlowSummary,
|
|
580
|
+
ActivationFlowActivateButton2 as ActivationFlowActivateButton,
|
|
581
|
+
ActivationFlowAmountPicker,
|
|
582
|
+
ActivationFlowContinueButton2 as ActivationFlowContinueButton,
|
|
583
|
+
ActivationFlowRetrying2 as ActivationFlowRetrying,
|
|
584
|
+
ActivationFlowActivated2 as ActivationFlowActivated,
|
|
585
|
+
ActivationFlowLoading2 as ActivationFlowLoading,
|
|
586
|
+
ActivationFlowError2 as ActivationFlowError,
|
|
587
|
+
ActivationFlow,
|
|
588
|
+
useActivationFlow,
|
|
589
|
+
CreditGateRoot2 as CreditGateRoot,
|
|
590
|
+
CreditGateHeading2 as CreditGateHeading,
|
|
591
|
+
CreditGateSubheading2 as CreditGateSubheading,
|
|
592
|
+
CreditGateTopup,
|
|
593
|
+
CreditGateLoading2 as CreditGateLoading,
|
|
594
|
+
CreditGateError2 as CreditGateError,
|
|
595
|
+
CreditGate,
|
|
596
|
+
useCreditGate
|
|
597
|
+
};
|