@flopay/react 0.3.15 → 0.3.17
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/README.md +6 -4
- package/dist/index.cjs +63 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.mjs +63 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -131,14 +131,16 @@ Use `onButtonClick` to track button interactions, `onDecline` to track declines/
|
|
|
131
131
|
createSession={{
|
|
132
132
|
clientId: 'your-client-id',
|
|
133
133
|
items: [{ providerItemId: 'product-1', providerItemName: 'Widget', totalAmount: 29.99, currency: 'EUR' }],
|
|
134
|
-
account: { userId: 'user_1' },
|
|
134
|
+
account: { userId: 'user_1', email: 'test@email.com' },
|
|
135
135
|
successUrl: '/success',
|
|
136
136
|
cancelUrl: '/cancel',
|
|
137
137
|
}}
|
|
138
|
-
onBeforeButtonClick={async ({ method }) => {
|
|
138
|
+
onBeforeButtonClick={async ({ method, createSession }) => {
|
|
139
139
|
if (method !== 'card') return;
|
|
140
140
|
|
|
141
|
-
const email = await openEmailCaptureModal(
|
|
141
|
+
const email = await openEmailCaptureModal({
|
|
142
|
+
initialEmail: createSession?.account.email ?? '',
|
|
143
|
+
});
|
|
142
144
|
if (!email) return false;
|
|
143
145
|
|
|
144
146
|
return {
|
|
@@ -178,7 +180,7 @@ Skip the backend API route — create the session directly in the component:
|
|
|
178
180
|
|
|
179
181
|
The component POSTs to the billing API, gets the full session back, and renders the form — zero backend code needed.
|
|
180
182
|
|
|
181
|
-
When you use `onBeforeButtonClick`, `createSession.account.email`
|
|
183
|
+
When you use `onBeforeButtonClick`, `createSession.account.email` should still be present when checkout renders. If you only have a temporary address such as `test@email.com`, pass it first and replace it in `onBeforeButtonClick` before the card flow continues. PayPal and wallet buttons still bootstrap normally, but this hook does not run for them, so collect any data those methods require before the user uses them.
|
|
182
184
|
|
|
183
185
|
### Advanced: Manual Provider Setup
|
|
184
186
|
|
package/dist/index.cjs
CHANGED
|
@@ -405,6 +405,52 @@ function toCssWeight(value) {
|
|
|
405
405
|
if (typeof value === "number" || typeof value === "string") return value;
|
|
406
406
|
return void 0;
|
|
407
407
|
}
|
|
408
|
+
function resolveExpressCheckoutLoadState(event, methods) {
|
|
409
|
+
const available = event.availablePaymentMethods;
|
|
410
|
+
if (!available) return "unavailable";
|
|
411
|
+
return methods.some((method) => available[method]) ? "ready" : "unavailable";
|
|
412
|
+
}
|
|
413
|
+
function ExpressCheckoutReadySwap({
|
|
414
|
+
state,
|
|
415
|
+
placeholderTestId,
|
|
416
|
+
children
|
|
417
|
+
}) {
|
|
418
|
+
if (state === "unavailable") return null;
|
|
419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
421
|
+
"div",
|
|
422
|
+
{
|
|
423
|
+
"data-testid": placeholderTestId,
|
|
424
|
+
"aria-hidden": state === "ready",
|
|
425
|
+
style: {
|
|
426
|
+
position: "absolute",
|
|
427
|
+
inset: 0,
|
|
428
|
+
height: 44,
|
|
429
|
+
borderRadius: 8,
|
|
430
|
+
background: "#e5e7eb",
|
|
431
|
+
animation: state === "ready" ? void 0 : "flopay-pulse 1.5s ease-in-out infinite",
|
|
432
|
+
opacity: state === "ready" ? 0 : 1,
|
|
433
|
+
transform: state === "ready" ? "scale(0.985)" : "scale(1)",
|
|
434
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
435
|
+
pointerEvents: "none"
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
440
|
+
"div",
|
|
441
|
+
{
|
|
442
|
+
style: {
|
|
443
|
+
minHeight: 44,
|
|
444
|
+
opacity: state === "ready" ? 1 : 0,
|
|
445
|
+
transform: state === "ready" ? "translateY(0)" : "translateY(2px)",
|
|
446
|
+
transition: "opacity 140ms ease-out, transform 140ms ease-out",
|
|
447
|
+
pointerEvents: state === "ready" ? "auto" : "none"
|
|
448
|
+
},
|
|
449
|
+
children
|
|
450
|
+
}
|
|
451
|
+
)
|
|
452
|
+
] });
|
|
453
|
+
}
|
|
408
454
|
function ProcessingOverlay({ status, errorMessage }) {
|
|
409
455
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
410
456
|
position: "fixed",
|
|
@@ -522,7 +568,7 @@ function PayPalButtonInner({
|
|
|
522
568
|
}) {
|
|
523
569
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
524
570
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
525
|
-
const [
|
|
571
|
+
const [loadState, setLoadState] = (0, import_react6.useState)("loading");
|
|
526
572
|
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
527
573
|
const paypalResumeAttempted = (0, import_react6.useRef)(false);
|
|
528
574
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
@@ -634,12 +680,11 @@ function PayPalButtonInner({
|
|
|
634
680
|
}
|
|
635
681
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]);
|
|
636
682
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
637
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
638
684
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
639
685
|
{
|
|
640
|
-
onReady: () =>
|
|
641
|
-
onLoadError: () =>
|
|
642
|
-
},
|
|
686
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
|
|
687
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
643
688
|
onConfirm: handlePayPalConfirm,
|
|
644
689
|
onCancel: () => {
|
|
645
690
|
onDecline?.(buildDeclineEvent("paypal", "PayPal checkout was cancelled."));
|
|
@@ -671,7 +716,7 @@ function WalletButtonInner({
|
|
|
671
716
|
}) {
|
|
672
717
|
const stripe = (0, import_react_stripe_js.useStripe)();
|
|
673
718
|
const elements = (0, import_react_stripe_js.useElements)();
|
|
674
|
-
const [
|
|
719
|
+
const [loadState, setLoadState] = (0, import_react6.useState)("loading");
|
|
675
720
|
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
676
721
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
677
722
|
const lastWalletMethodRef = (0, import_react6.useRef)("card");
|
|
@@ -737,12 +782,11 @@ function WalletButtonInner({
|
|
|
737
782
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline]
|
|
738
783
|
);
|
|
739
784
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
740
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
741
786
|
import_react_stripe_js.ExpressCheckoutElement,
|
|
742
787
|
{
|
|
743
|
-
onReady: () =>
|
|
744
|
-
onLoadError: () =>
|
|
745
|
-
},
|
|
788
|
+
onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["applePay", "googlePay"])),
|
|
789
|
+
onLoadError: () => setLoadState("unavailable"),
|
|
746
790
|
onClick: (event) => {
|
|
747
791
|
lastWalletMethodRef.current = event.expressPaymentType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
748
792
|
event.resolve();
|
|
@@ -786,6 +830,7 @@ function SplitCardFormInner({
|
|
|
786
830
|
isProcessing: externalProcessing,
|
|
787
831
|
error: externalError,
|
|
788
832
|
onErrorChange,
|
|
833
|
+
onFullNameChange,
|
|
789
834
|
onFirstNameChange,
|
|
790
835
|
onLastNameChange,
|
|
791
836
|
showPayPal = true,
|
|
@@ -904,10 +949,11 @@ function SplitCardFormInner({
|
|
|
904
949
|
const showWallets = showApplePay || showGooglePay;
|
|
905
950
|
const handleNameChange = (0, import_react6.useCallback)((value) => {
|
|
906
951
|
setFullName(value);
|
|
952
|
+
onFullNameChange?.(value);
|
|
907
953
|
const parts = value.trim().split(/\s+/);
|
|
908
954
|
onFirstNameChange?.(parts[0] ?? "");
|
|
909
955
|
onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
|
|
910
|
-
}, [onFirstNameChange, onLastNameChange]);
|
|
956
|
+
}, [onFullNameChange, onFirstNameChange, onLastNameChange]);
|
|
911
957
|
const runBeforeCardButtonClick = (0, import_react6.useCallback)(async () => {
|
|
912
958
|
if (!onBeforeButtonClick) return true;
|
|
913
959
|
try {
|
|
@@ -1669,6 +1715,9 @@ function FloPayCheckout({
|
|
|
1669
1715
|
onComplete,
|
|
1670
1716
|
onError,
|
|
1671
1717
|
onDecline,
|
|
1718
|
+
onFullNameChange,
|
|
1719
|
+
onCountryChange,
|
|
1720
|
+
onZipChange,
|
|
1672
1721
|
showPayPal = true,
|
|
1673
1722
|
showApplePay = true,
|
|
1674
1723
|
showGooglePay = true,
|
|
@@ -2267,6 +2316,7 @@ function FloPayCheckout({
|
|
|
2267
2316
|
onComplete,
|
|
2268
2317
|
onError,
|
|
2269
2318
|
onDecline,
|
|
2319
|
+
onFullNameChange,
|
|
2270
2320
|
showPayPal,
|
|
2271
2321
|
showApplePay,
|
|
2272
2322
|
showGooglePay,
|
|
@@ -2281,6 +2331,8 @@ function FloPayCheckout({
|
|
|
2281
2331
|
enableAVS,
|
|
2282
2332
|
avsLayout,
|
|
2283
2333
|
country: session?.customer?.country,
|
|
2334
|
+
onCountryChange,
|
|
2335
|
+
onZipChange,
|
|
2284
2336
|
submitLabel,
|
|
2285
2337
|
className
|
|
2286
2338
|
}
|