@flopay/react 0.1.6 → 0.2.1
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 +42 -0
- package/dist/index.cjs +608 -194
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -4
- package/dist/index.d.ts +39 -4
- package/dist/index.mjs +589 -175
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -69,7 +69,7 @@ function FloPayProvider({
|
|
|
69
69
|
// src/flopay-checkout.tsx
|
|
70
70
|
import React4, { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
|
|
71
71
|
import { loadFloPay, PaymentAPI } from "@flopay/js";
|
|
72
|
-
import { FloPayError as FloPayError2, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData } from "@flopay/shared";
|
|
72
|
+
import { FloPayError as FloPayError2, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2 } from "@flopay/shared";
|
|
73
73
|
|
|
74
74
|
// src/elements.tsx
|
|
75
75
|
import { useEffect as useEffect2, useRef, useContext } from "react";
|
|
@@ -138,6 +138,7 @@ import {
|
|
|
138
138
|
useElements as useStripeElements,
|
|
139
139
|
useStripe as useStripeRaw
|
|
140
140
|
} from "@stripe/react-stripe-js";
|
|
141
|
+
import { resolveButtonsLayoutTheme } from "@flopay/shared";
|
|
141
142
|
import { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
142
143
|
|
|
143
144
|
// src/hooks.ts
|
|
@@ -163,6 +164,29 @@ function useBillingApiUrl() {
|
|
|
163
164
|
import { FloPayError } from "@flopay/shared";
|
|
164
165
|
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
165
166
|
var WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
167
|
+
var FLOPAY_KEYFRAMES = `
|
|
168
|
+
@keyframes flopay-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
169
|
+
@keyframes flopay-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
|
|
170
|
+
@keyframes flopay-buttons-enter {
|
|
171
|
+
0% { opacity: 0; transform: translateX(-16px) scale(0.97); }
|
|
172
|
+
100% { opacity: 1; transform: translateX(0) scale(1); }
|
|
173
|
+
}
|
|
174
|
+
@keyframes flopay-buttons-exit {
|
|
175
|
+
0% { opacity: 1; transform: translateX(0) scale(1); }
|
|
176
|
+
100% { opacity: 0; transform: translateX(-16px) scale(0.97); }
|
|
177
|
+
}
|
|
178
|
+
@keyframes flopay-card-enter {
|
|
179
|
+
0% { opacity: 0; transform: translateX(16px) scale(0.97); }
|
|
180
|
+
100% { opacity: 1; transform: translateX(0) scale(1); }
|
|
181
|
+
}
|
|
182
|
+
@keyframes flopay-card-exit {
|
|
183
|
+
0% { opacity: 1; transform: translateX(0) scale(1); }
|
|
184
|
+
100% { opacity: 0; transform: translateX(16px) scale(0.97); }
|
|
185
|
+
}
|
|
186
|
+
`;
|
|
187
|
+
function FloPayKeyframes() {
|
|
188
|
+
return /* @__PURE__ */ jsx3("style", { children: FLOPAY_KEYFRAMES });
|
|
189
|
+
}
|
|
166
190
|
function ProcessingOverlay({ status, errorMessage }) {
|
|
167
191
|
return /* @__PURE__ */ jsx3("div", { style: {
|
|
168
192
|
position: "fixed",
|
|
@@ -252,8 +276,6 @@ function ProcessingOverlay({ status, errorMessage }) {
|
|
|
252
276
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
253
277
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
254
278
|
@keyframes flopay-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
|
|
255
|
-
@keyframes flopay-expand { 0% { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(-8px); } 100% { opacity: 1; clip-path: inset(0 0 0 0); transform: translateY(0); } }
|
|
256
|
-
@keyframes flopay-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
|
|
257
279
|
` })
|
|
258
280
|
] }) });
|
|
259
281
|
}
|
|
@@ -268,7 +290,8 @@ function PayPalButtonInner({
|
|
|
268
290
|
billingApiUrl,
|
|
269
291
|
onTokenizedBody,
|
|
270
292
|
onErrorChange,
|
|
271
|
-
isProcessing = false
|
|
293
|
+
isProcessing = false,
|
|
294
|
+
onButtonClick
|
|
272
295
|
}) {
|
|
273
296
|
const stripe = useStripeRaw();
|
|
274
297
|
const elements = useStripeElements();
|
|
@@ -321,6 +344,7 @@ function PayPalButtonInner({
|
|
|
321
344
|
}, [stripe, onTokenizedBody, onErrorChange]);
|
|
322
345
|
const handlePayPalConfirm = useCallback(async (_event) => {
|
|
323
346
|
if (!stripe || !elements) return;
|
|
347
|
+
onButtonClick?.("paypal");
|
|
324
348
|
try {
|
|
325
349
|
setSubmitting(true);
|
|
326
350
|
onErrorChange?.(null);
|
|
@@ -375,7 +399,7 @@ function PayPalButtonInner({
|
|
|
375
399
|
}
|
|
376
400
|
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange]);
|
|
377
401
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
378
|
-
/* @__PURE__ */ jsx3("div", {
|
|
402
|
+
/* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsx3(
|
|
379
403
|
ExpressCheckoutElement,
|
|
380
404
|
{
|
|
381
405
|
onReady: () => setReady(true),
|
|
@@ -403,7 +427,8 @@ function WalletButtonInner({
|
|
|
403
427
|
showApplePay = true,
|
|
404
428
|
showGooglePay = true,
|
|
405
429
|
onTokenizedBody,
|
|
406
|
-
onErrorChange
|
|
430
|
+
onErrorChange,
|
|
431
|
+
onButtonClick
|
|
407
432
|
}) {
|
|
408
433
|
const stripe = useStripeRaw();
|
|
409
434
|
const elements = useStripeElements();
|
|
@@ -413,6 +438,8 @@ function WalletButtonInner({
|
|
|
413
438
|
const handleWalletConfirm = useCallback(
|
|
414
439
|
async (_event) => {
|
|
415
440
|
if (!stripe || !elements) return;
|
|
441
|
+
const walletType = _event.expressPaymentType;
|
|
442
|
+
onButtonClick?.(walletType === "apple_pay" ? "apple_pay" : "google_pay");
|
|
416
443
|
try {
|
|
417
444
|
setSubmitting(true);
|
|
418
445
|
onErrorChange?.(null);
|
|
@@ -465,7 +492,7 @@ function WalletButtonInner({
|
|
|
465
492
|
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange]
|
|
466
493
|
);
|
|
467
494
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
468
|
-
/* @__PURE__ */ jsx3("div", {
|
|
495
|
+
/* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsx3(
|
|
469
496
|
ExpressCheckoutElement,
|
|
470
497
|
{
|
|
471
498
|
onReady: () => setReady(true),
|
|
@@ -512,6 +539,9 @@ function SplitCardFormInner({
|
|
|
512
539
|
showApplePay = true,
|
|
513
540
|
showGooglePay = true,
|
|
514
541
|
layout = "default",
|
|
542
|
+
buttonsTheme,
|
|
543
|
+
buttonsStyles: buttonsStylesOverride,
|
|
544
|
+
onButtonClick,
|
|
515
545
|
totalAmount = 0,
|
|
516
546
|
currency = "usd",
|
|
517
547
|
innerRef
|
|
@@ -521,14 +551,38 @@ function SplitCardFormInner({
|
|
|
521
551
|
const contextBillingUrl = useBillingApiUrl();
|
|
522
552
|
const [processing, setProcessing] = useState2(false);
|
|
523
553
|
const [error, setError] = useState2(null);
|
|
524
|
-
const [showCardForm, setShowCardForm] = useState2(false);
|
|
525
554
|
const [is3DSActive, setIs3DSActive] = useState2(false);
|
|
555
|
+
const [viewState, setViewState] = useState2("buttons");
|
|
556
|
+
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
557
|
+
const TRANSITION_MS = 280;
|
|
558
|
+
const expandToCard = useCallback(() => {
|
|
559
|
+
setViewState("expanding");
|
|
560
|
+
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
561
|
+
}, []);
|
|
562
|
+
const collapseToButtons = useCallback(() => {
|
|
563
|
+
setViewState("collapsing");
|
|
564
|
+
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
565
|
+
}, []);
|
|
526
566
|
const [fullName, setFullName] = useState2("");
|
|
527
567
|
const [formReady, setFormReady] = useState2(false);
|
|
528
568
|
const [overlayStatus, setOverlayStatus] = useState2(null);
|
|
529
569
|
const processingRef = useRef2(false);
|
|
530
570
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
531
571
|
const displayError = externalError ?? error;
|
|
572
|
+
const bStyles = useMemo2(() => {
|
|
573
|
+
const base = resolveButtonsLayoutTheme(buttonsTheme);
|
|
574
|
+
if (!buttonsStylesOverride) return base;
|
|
575
|
+
return {
|
|
576
|
+
...base,
|
|
577
|
+
...buttonsStylesOverride,
|
|
578
|
+
cardButton: { ...base.cardButton, ...buttonsStylesOverride.cardButton },
|
|
579
|
+
cardFormContainer: { ...base.cardFormContainer, ...buttonsStylesOverride.cardFormContainer },
|
|
580
|
+
backButton: { ...base.backButton, ...buttonsStylesOverride.backButton },
|
|
581
|
+
backButtonIcon: { ...base.backButtonIcon, ...buttonsStylesOverride.backButtonIcon },
|
|
582
|
+
submitButton: { ...base.submitButton, ...buttonsStylesOverride.submitButton },
|
|
583
|
+
title: { ...base.title, ...buttonsStylesOverride.title }
|
|
584
|
+
};
|
|
585
|
+
}, [buttonsTheme, buttonsStylesOverride]);
|
|
532
586
|
const isSubmitting = externalProcessing ?? processing;
|
|
533
587
|
const isSelfContained = !onTokenizedBody;
|
|
534
588
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
@@ -740,6 +794,7 @@ function SplitCardFormInner({
|
|
|
740
794
|
async (e) => {
|
|
741
795
|
e.preventDefault();
|
|
742
796
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
797
|
+
onButtonClick?.("card");
|
|
743
798
|
setProcessing(true);
|
|
744
799
|
setOverlayStatus("processing");
|
|
745
800
|
updateError(null);
|
|
@@ -807,15 +862,25 @@ function SplitCardFormInner({
|
|
|
807
862
|
return /* @__PURE__ */ jsx3("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
808
863
|
}
|
|
809
864
|
const isButtons = layout === "buttons";
|
|
810
|
-
const
|
|
811
|
-
const cardBg = isButtons ? "white" : "#EDEDFF";
|
|
865
|
+
const resolvedBorder = isButtons ? bStyles.cardInputBorder ?? "#e5e7eb" : "#A4A4FF";
|
|
866
|
+
const cardBg = isButtons ? bStyles.cardFormContainer?.backgroundColor ?? "white" : "#EDEDFF";
|
|
867
|
+
const cardInputBg = isButtons ? bStyles.cardInputBackground ?? "white" : "white";
|
|
868
|
+
const stripeElementStyle = isButtons && (bStyles.cardInputColor || bStyles.cardInputPlaceholderColor || bStyles.cardInputFontSize) ? {
|
|
869
|
+
style: {
|
|
870
|
+
base: {
|
|
871
|
+
...bStyles.cardInputColor ? { color: bStyles.cardInputColor } : {},
|
|
872
|
+
...bStyles.cardInputFontSize ? { fontSize: bStyles.cardInputFontSize } : {},
|
|
873
|
+
...bStyles.cardInputPlaceholderColor ? { "::placeholder": { color: bStyles.cardInputPlaceholderColor } } : {}
|
|
874
|
+
},
|
|
875
|
+
invalid: { color: "#ef4444" }
|
|
876
|
+
}
|
|
877
|
+
} : {};
|
|
812
878
|
const cardFormBlock = /* @__PURE__ */ jsxs("div", { style: {
|
|
813
879
|
backgroundColor: cardBg,
|
|
814
880
|
borderRadius: "8px",
|
|
815
881
|
padding: isButtons ? "0" : "1rem",
|
|
816
|
-
...isButtons
|
|
817
|
-
|
|
818
|
-
} : {}
|
|
882
|
+
...isButtons ? bStyles.cardFormContainer : {},
|
|
883
|
+
...isButtons ? { padding: bStyles.cardFormContainer?.padding ?? "0" } : {}
|
|
819
884
|
}, children: [
|
|
820
885
|
isButtons && showCardForm && /* @__PURE__ */ jsxs("div", { style: {
|
|
821
886
|
display: "flex",
|
|
@@ -826,7 +891,7 @@ function SplitCardFormInner({
|
|
|
826
891
|
"button",
|
|
827
892
|
{
|
|
828
893
|
type: "button",
|
|
829
|
-
onClick:
|
|
894
|
+
onClick: collapseToButtons,
|
|
830
895
|
style: {
|
|
831
896
|
display: "inline-flex",
|
|
832
897
|
alignItems: "center",
|
|
@@ -835,17 +900,12 @@ function SplitCardFormInner({
|
|
|
835
900
|
border: "none",
|
|
836
901
|
cursor: "pointer",
|
|
837
902
|
color: "#4b5563",
|
|
838
|
-
fontSize: "0.85rem",
|
|
903
|
+
fontSize: bStyles.backButtonFontSize ?? "0.85rem",
|
|
839
904
|
fontWeight: 500,
|
|
840
905
|
padding: 0,
|
|
841
906
|
transition: "color 0.15s",
|
|
842
|
-
flexShrink: 0
|
|
843
|
-
|
|
844
|
-
onMouseOver: (e) => {
|
|
845
|
-
e.currentTarget.style.color = "#1f2937";
|
|
846
|
-
},
|
|
847
|
-
onMouseOut: (e) => {
|
|
848
|
-
e.currentTarget.style.color = "#4b5563";
|
|
907
|
+
flexShrink: 0,
|
|
908
|
+
...bStyles.backButton
|
|
849
909
|
},
|
|
850
910
|
"aria-label": "Back to payment methods",
|
|
851
911
|
children: [
|
|
@@ -857,44 +917,53 @@ function SplitCardFormInner({
|
|
|
857
917
|
height: 28,
|
|
858
918
|
borderRadius: "50%",
|
|
859
919
|
backgroundColor: "#f3f4f6",
|
|
860
|
-
transition: "background-color 0.15s"
|
|
920
|
+
transition: "background-color 0.15s",
|
|
921
|
+
...bStyles.backButtonIcon
|
|
861
922
|
}, children: /* @__PURE__ */ jsx3("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx3("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
862
923
|
"Go back"
|
|
863
924
|
]
|
|
864
925
|
}
|
|
865
926
|
),
|
|
866
|
-
/* @__PURE__ */ jsx3("div", { style: {
|
|
927
|
+
/* @__PURE__ */ jsx3("div", { style: {
|
|
928
|
+
flex: 1,
|
|
929
|
+
textAlign: "center",
|
|
930
|
+
fontWeight: 600,
|
|
931
|
+
fontSize: bStyles.titleFontSize ?? "1.05rem",
|
|
932
|
+
color: "#262833",
|
|
933
|
+
paddingRight: 80,
|
|
934
|
+
...bStyles.title
|
|
935
|
+
}, children: "Secure card checkout" })
|
|
867
936
|
] }),
|
|
868
937
|
!isButtons && /* @__PURE__ */ jsx3("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: "Secure card checkout" }),
|
|
869
938
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
870
|
-
backgroundColor:
|
|
871
|
-
border: `1px solid ${
|
|
939
|
+
backgroundColor: cardInputBg,
|
|
940
|
+
border: `1px solid ${resolvedBorder}`,
|
|
872
941
|
borderTopLeftRadius: "8px",
|
|
873
942
|
borderTopRightRadius: "8px",
|
|
874
943
|
padding: "10px"
|
|
875
|
-
}, children: /* @__PURE__ */ jsx3(CardNumberElement, { onReady: () => setFormReady(true) }) }),
|
|
944
|
+
}, children: /* @__PURE__ */ jsx3(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
876
945
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex" }, children: [
|
|
877
946
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
878
947
|
flex: 1,
|
|
879
|
-
backgroundColor:
|
|
880
|
-
border: `1px solid ${
|
|
948
|
+
backgroundColor: cardInputBg,
|
|
949
|
+
border: `1px solid ${resolvedBorder}`,
|
|
881
950
|
borderTop: "none",
|
|
882
951
|
borderRight: "none",
|
|
883
952
|
borderBottomLeftRadius: "8px",
|
|
884
953
|
padding: "10px"
|
|
885
|
-
}, children: /* @__PURE__ */ jsx3(CardExpiryElement, {}) }),
|
|
954
|
+
}, children: /* @__PURE__ */ jsx3(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
886
955
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
887
956
|
flex: 1,
|
|
888
|
-
backgroundColor:
|
|
889
|
-
border: `1px solid ${
|
|
957
|
+
backgroundColor: cardInputBg,
|
|
958
|
+
border: `1px solid ${resolvedBorder}`,
|
|
890
959
|
borderTop: "none",
|
|
891
960
|
borderBottomRightRadius: "8px",
|
|
892
961
|
padding: "10px"
|
|
893
|
-
}, children: /* @__PURE__ */ jsx3(CardCvcElement, {}) })
|
|
962
|
+
}, children: /* @__PURE__ */ jsx3(CardCvcElement, { options: stripeElementStyle }) })
|
|
894
963
|
] }),
|
|
895
964
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
896
|
-
backgroundColor:
|
|
897
|
-
border: `1px solid ${
|
|
965
|
+
backgroundColor: cardInputBg,
|
|
966
|
+
border: `1px solid ${resolvedBorder}`,
|
|
898
967
|
borderRadius: "8px",
|
|
899
968
|
marginTop: "0.5rem",
|
|
900
969
|
padding: "10px"
|
|
@@ -911,9 +980,11 @@ function SplitCardFormInner({
|
|
|
911
980
|
width: "100%",
|
|
912
981
|
border: "none",
|
|
913
982
|
outline: "none",
|
|
914
|
-
|
|
983
|
+
background: "transparent",
|
|
984
|
+
fontSize: bStyles.cardInputFontSize ?? "16px",
|
|
915
985
|
fontFamily: "Poppins, sans-serif",
|
|
916
|
-
color: "#262833"
|
|
986
|
+
color: bStyles.cardInputColor ?? "#262833",
|
|
987
|
+
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
917
988
|
}
|
|
918
989
|
}
|
|
919
990
|
) }),
|
|
@@ -928,7 +999,8 @@ function SplitCardFormInner({
|
|
|
928
999
|
fontWeight: 600,
|
|
929
1000
|
display: "flex",
|
|
930
1001
|
alignItems: "center",
|
|
931
|
-
gap: "0.5rem"
|
|
1002
|
+
gap: "0.5rem",
|
|
1003
|
+
...isButtons && bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
932
1004
|
}, children: [
|
|
933
1005
|
/* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx3("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
934
1006
|
displayError
|
|
@@ -947,10 +1019,11 @@ function SplitCardFormInner({
|
|
|
947
1019
|
color: "white",
|
|
948
1020
|
border: "none",
|
|
949
1021
|
borderRadius: "8px",
|
|
950
|
-
fontSize: "1rem",
|
|
1022
|
+
fontSize: isButtons && bStyles.submitButtonFontSize ? bStyles.submitButtonFontSize : "1rem",
|
|
951
1023
|
fontWeight: 600,
|
|
952
1024
|
cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
|
|
953
|
-
opacity: !formReady || isSubmitting ? 0.5 : 1
|
|
1025
|
+
opacity: !formReady || isSubmitting ? 0.5 : 1,
|
|
1026
|
+
...isButtons ? bStyles.submitButton : {}
|
|
954
1027
|
},
|
|
955
1028
|
children: isSubmitting ? "PROCESSING..." : submitLabel
|
|
956
1029
|
}
|
|
@@ -967,103 +1040,119 @@ function SplitCardFormInner({
|
|
|
967
1040
|
}, children: "Secure Card Checkout" })
|
|
968
1041
|
] });
|
|
969
1042
|
if (layout === "buttons") {
|
|
1043
|
+
const isButtonsView = viewState === "buttons" || viewState === "expanding";
|
|
1044
|
+
const isCardView = viewState === "expanding" || viewState === "card" || viewState === "collapsing";
|
|
1045
|
+
const buttonsAnim = viewState === "expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
|
|
1046
|
+
const cardAnim = viewState === "expanding" ? `flopay-card-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : viewState === "collapsing" ? `flopay-card-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : void 0;
|
|
970
1047
|
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1048
|
+
/* @__PURE__ */ jsx3(FloPayKeyframes, {}),
|
|
971
1049
|
overlayStatus && /* @__PURE__ */ jsx3(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
972
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
gap: "0.5rem"
|
|
976
|
-
}, children: [
|
|
977
|
-
showPayPal && stripeInstance && /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx3(
|
|
978
|
-
PayPalButtonInner,
|
|
979
|
-
{
|
|
980
|
-
sessionId,
|
|
981
|
-
email,
|
|
982
|
-
billingApiUrl: resolvedBillingApiUrl,
|
|
983
|
-
onTokenizedBody: dispatchTokenizedBody,
|
|
984
|
-
onErrorChange: updateError,
|
|
985
|
-
isProcessing: isSubmitting
|
|
986
|
-
}
|
|
987
|
-
) }),
|
|
988
|
-
showWallets && stripeInstance && /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx3(
|
|
989
|
-
WalletButtonInner,
|
|
990
|
-
{
|
|
991
|
-
sessionId,
|
|
992
|
-
email,
|
|
993
|
-
billingApiUrl: resolvedBillingApiUrl,
|
|
994
|
-
showApplePay,
|
|
995
|
-
showGooglePay,
|
|
996
|
-
onTokenizedBody: dispatchTokenizedBody,
|
|
997
|
-
onErrorChange: updateError
|
|
998
|
-
}
|
|
999
|
-
) }),
|
|
1000
|
-
/* @__PURE__ */ jsxs(
|
|
1001
|
-
"button",
|
|
1002
|
-
{
|
|
1003
|
-
type: "button",
|
|
1004
|
-
onClick: () => setShowCardForm(true),
|
|
1005
|
-
style: {
|
|
1006
|
-
width: "100%",
|
|
1007
|
-
padding: "0.9rem 1rem",
|
|
1008
|
-
backgroundColor: "white",
|
|
1009
|
-
color: "#262833",
|
|
1010
|
-
border: "1px solid #d1d5db",
|
|
1011
|
-
borderRadius: "8px",
|
|
1012
|
-
fontSize: "0.95rem",
|
|
1013
|
-
fontWeight: 600,
|
|
1014
|
-
cursor: "pointer",
|
|
1015
|
-
display: "flex",
|
|
1016
|
-
alignItems: "center",
|
|
1017
|
-
justifyContent: "center",
|
|
1018
|
-
gap: "0.625rem",
|
|
1019
|
-
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1020
|
-
boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
|
|
1021
|
-
},
|
|
1022
|
-
onMouseOver: (e) => {
|
|
1023
|
-
e.currentTarget.style.borderColor = "#A4A4FF";
|
|
1024
|
-
e.currentTarget.style.boxShadow = "0 0 0 1px #A4A4FF, 0 2px 8px rgba(74,73,255,0.08)";
|
|
1025
|
-
},
|
|
1026
|
-
onMouseOut: (e) => {
|
|
1027
|
-
e.currentTarget.style.borderColor = "#d1d5db";
|
|
1028
|
-
e.currentTarget.style.boxShadow = "0 1px 2px rgba(0,0,0,0.04)";
|
|
1029
|
-
},
|
|
1030
|
-
onMouseDown: (e) => {
|
|
1031
|
-
e.currentTarget.style.transform = "scale(0.985)";
|
|
1032
|
-
},
|
|
1033
|
-
onMouseUp: (e) => {
|
|
1034
|
-
e.currentTarget.style.transform = "scale(1)";
|
|
1035
|
-
},
|
|
1036
|
-
children: [
|
|
1037
|
-
/* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1038
|
-
/* @__PURE__ */ jsx3("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
1039
|
-
/* @__PURE__ */ jsx3("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
1040
|
-
] }),
|
|
1041
|
-
"Credit / Debit Card",
|
|
1042
|
-
/* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx3("path", { d: "M9 18l6-6-6-6" }) })
|
|
1043
|
-
]
|
|
1044
|
-
}
|
|
1045
|
-
),
|
|
1046
|
-
displayError && !showCardForm && /* @__PURE__ */ jsxs("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
1047
|
-
margin: "0.25rem 0",
|
|
1048
|
-
padding: "0.625rem 0.875rem",
|
|
1049
|
-
background: "#FEF2F2",
|
|
1050
|
-
border: "1px solid #FECACA",
|
|
1051
|
-
borderRadius: "8px",
|
|
1052
|
-
color: "#991B1B",
|
|
1053
|
-
fontSize: "0.85rem",
|
|
1054
|
-
fontWeight: 600,
|
|
1050
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "grid" }, children: [
|
|
1051
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
1052
|
+
gridArea: "1 / 1",
|
|
1055
1053
|
display: "flex",
|
|
1056
|
-
|
|
1057
|
-
gap: "0.5rem"
|
|
1054
|
+
flexDirection: "column",
|
|
1055
|
+
gap: "0.5rem",
|
|
1056
|
+
// When card form is showing (and not transitioning), hide but keep mounted
|
|
1057
|
+
...!isButtonsView && !buttonsAnim ? { visibility: "hidden", position: "absolute", pointerEvents: "none", width: "100%" } : {},
|
|
1058
|
+
...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
|
|
1058
1059
|
}, children: [
|
|
1059
|
-
/* @__PURE__ */ jsx3(
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1060
|
+
showPayPal && stripeInstance ? /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx3(
|
|
1061
|
+
PayPalButtonInner,
|
|
1062
|
+
{
|
|
1063
|
+
sessionId,
|
|
1064
|
+
email,
|
|
1065
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
1066
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
1067
|
+
onErrorChange: updateError,
|
|
1068
|
+
isProcessing: isSubmitting,
|
|
1069
|
+
onButtonClick
|
|
1070
|
+
}
|
|
1071
|
+
) }) : showPayPal ? /* @__PURE__ */ jsx3("div", { style: { height: 44, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
1072
|
+
showWallets && stripeInstance ? /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx3(
|
|
1073
|
+
WalletButtonInner,
|
|
1074
|
+
{
|
|
1075
|
+
sessionId,
|
|
1076
|
+
email,
|
|
1077
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
1078
|
+
showApplePay,
|
|
1079
|
+
showGooglePay,
|
|
1080
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
1081
|
+
onErrorChange: updateError,
|
|
1082
|
+
onButtonClick
|
|
1083
|
+
}
|
|
1084
|
+
) }) : showWallets ? /* @__PURE__ */ jsx3("div", { style: { height: 44, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
1085
|
+
/* @__PURE__ */ jsxs(
|
|
1086
|
+
"button",
|
|
1087
|
+
{
|
|
1088
|
+
type: "button",
|
|
1089
|
+
onClick: () => {
|
|
1090
|
+
onButtonClick?.("card");
|
|
1091
|
+
expandToCard();
|
|
1092
|
+
},
|
|
1093
|
+
style: {
|
|
1094
|
+
width: "100%",
|
|
1095
|
+
padding: "0.9rem 1rem",
|
|
1096
|
+
backgroundColor: "white",
|
|
1097
|
+
color: "#262833",
|
|
1098
|
+
border: "1px solid #d1d5db",
|
|
1099
|
+
borderRadius: "8px",
|
|
1100
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1101
|
+
fontWeight: 600,
|
|
1102
|
+
cursor: "pointer",
|
|
1103
|
+
display: "flex",
|
|
1104
|
+
alignItems: "center",
|
|
1105
|
+
justifyContent: "center",
|
|
1106
|
+
gap: "0.625rem",
|
|
1107
|
+
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1108
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1109
|
+
position: "relative",
|
|
1110
|
+
...bStyles.cardButton
|
|
1111
|
+
},
|
|
1112
|
+
onMouseDown: (e) => {
|
|
1113
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
1114
|
+
},
|
|
1115
|
+
onMouseUp: (e) => {
|
|
1116
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
1117
|
+
},
|
|
1118
|
+
children: [
|
|
1119
|
+
/* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1120
|
+
/* @__PURE__ */ jsx3("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
1121
|
+
/* @__PURE__ */ jsx3("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
1122
|
+
] }),
|
|
1123
|
+
"Credit / Debit Card",
|
|
1124
|
+
/* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { position: "absolute", right: "1rem" }, children: /* @__PURE__ */ jsx3("path", { d: "M9 18l6-6-6-6" }) })
|
|
1125
|
+
]
|
|
1126
|
+
}
|
|
1127
|
+
),
|
|
1128
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ jsxs("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
1129
|
+
margin: "0.25rem 0",
|
|
1130
|
+
padding: "0.625rem 0.875rem",
|
|
1131
|
+
background: "#FEF2F2",
|
|
1132
|
+
border: "1px solid #FECACA",
|
|
1133
|
+
borderRadius: "8px",
|
|
1134
|
+
color: "#991B1B",
|
|
1135
|
+
fontSize: "0.85rem",
|
|
1136
|
+
fontWeight: 600,
|
|
1137
|
+
display: "flex",
|
|
1138
|
+
alignItems: "center",
|
|
1139
|
+
gap: "0.5rem",
|
|
1140
|
+
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
1141
|
+
}, children: [
|
|
1142
|
+
/* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx3("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
1143
|
+
displayError
|
|
1144
|
+
] })
|
|
1145
|
+
] }),
|
|
1146
|
+
isCardView && /* @__PURE__ */ jsx3("div", { style: {
|
|
1147
|
+
gridArea: "1 / 1",
|
|
1148
|
+
...cardAnim ? { animation: cardAnim } : {},
|
|
1149
|
+
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
1150
|
+
}, children: cardFormBlock })
|
|
1151
|
+
] })
|
|
1064
1152
|
] });
|
|
1065
1153
|
}
|
|
1066
1154
|
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1155
|
+
/* @__PURE__ */ jsx3(FloPayKeyframes, {}),
|
|
1067
1156
|
overlayStatus && /* @__PURE__ */ jsx3(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
1068
1157
|
showWallets && stripeInstance && /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx3(
|
|
1069
1158
|
WalletButtonInner,
|
|
@@ -1107,7 +1196,8 @@ function SplitCardFormInner({
|
|
|
1107
1196
|
// src/flopay-checkout.tsx
|
|
1108
1197
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1109
1198
|
function FloPayCheckout({
|
|
1110
|
-
sessionId,
|
|
1199
|
+
sessionId: sessionIdProp,
|
|
1200
|
+
createSession: createSessionParams,
|
|
1111
1201
|
billingApiUrl,
|
|
1112
1202
|
appearance,
|
|
1113
1203
|
locale,
|
|
@@ -1120,6 +1210,9 @@ function FloPayCheckout({
|
|
|
1120
1210
|
showApplePay = true,
|
|
1121
1211
|
showGooglePay = true,
|
|
1122
1212
|
layout,
|
|
1213
|
+
buttonsTheme,
|
|
1214
|
+
buttonsStyles,
|
|
1215
|
+
onButtonClick,
|
|
1123
1216
|
submitLabel,
|
|
1124
1217
|
className,
|
|
1125
1218
|
children,
|
|
@@ -1133,6 +1226,7 @@ function FloPayCheckout({
|
|
|
1133
1226
|
const [flopay, setFloPay] = useState3(null);
|
|
1134
1227
|
const flopayRef = useRef3(null);
|
|
1135
1228
|
const [session, setSession] = useState3(null);
|
|
1229
|
+
const [resolvedSessionId, setResolvedSessionId] = useState3(sessionIdProp ?? "");
|
|
1136
1230
|
const [isLoading, setIsLoading] = useState3(true);
|
|
1137
1231
|
const [loadError, setLoadError] = useState3(null);
|
|
1138
1232
|
const [currentMode, setCurrentMode] = useState3("full");
|
|
@@ -1155,7 +1249,7 @@ function FloPayCheckout({
|
|
|
1155
1249
|
"x-user-id": sess.customer?.id ?? ""
|
|
1156
1250
|
},
|
|
1157
1251
|
body: JSON.stringify({
|
|
1158
|
-
sessionId,
|
|
1252
|
+
sessionId: resolvedSessionId,
|
|
1159
1253
|
tokenizedData: { id: void 0 },
|
|
1160
1254
|
accountData: {
|
|
1161
1255
|
userId: sess.customer?.id ?? "",
|
|
@@ -1189,7 +1283,7 @@ function FloPayCheckout({
|
|
|
1189
1283
|
"api_error"
|
|
1190
1284
|
);
|
|
1191
1285
|
},
|
|
1192
|
-
[resolvedBillingUrl,
|
|
1286
|
+
[resolvedBillingUrl, resolvedSessionId]
|
|
1193
1287
|
);
|
|
1194
1288
|
const handleRedirectResult = useCallback2(
|
|
1195
1289
|
async (redirectResult, sess, options) => {
|
|
@@ -1234,16 +1328,169 @@ function FloPayCheckout({
|
|
|
1234
1328
|
}
|
|
1235
1329
|
return false;
|
|
1236
1330
|
},
|
|
1237
|
-
[resolvedBillingUrl,
|
|
1331
|
+
[resolvedBillingUrl, resolvedSessionId]
|
|
1238
1332
|
);
|
|
1333
|
+
const inflightRef = useRef3(/* @__PURE__ */ new Map());
|
|
1334
|
+
const initializedHashRef = useRef3(null);
|
|
1335
|
+
function hashCreateParams(params) {
|
|
1336
|
+
const key = JSON.stringify({
|
|
1337
|
+
c: params?.clientId,
|
|
1338
|
+
i: params?.items?.map((x) => `${x.providerItemId}:${x.totalAmount}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
1339
|
+
s: params?.subscriptions?.map((x) => `${x.providerPlanId}:${x.totalAmount}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
1340
|
+
e: params?.account.email,
|
|
1341
|
+
m: params?.checkoutMode ?? "full"
|
|
1342
|
+
});
|
|
1343
|
+
let h = 0;
|
|
1344
|
+
for (let i = 0; i < key.length; i++) {
|
|
1345
|
+
h = (h << 5) - h + key.charCodeAt(i) | 0;
|
|
1346
|
+
}
|
|
1347
|
+
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
1348
|
+
}
|
|
1349
|
+
const createSessionHash = useMemo3(
|
|
1350
|
+
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
1351
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1352
|
+
[
|
|
1353
|
+
createSessionParams?.clientId,
|
|
1354
|
+
createSessionParams?.account?.email,
|
|
1355
|
+
createSessionParams?.checkoutMode,
|
|
1356
|
+
JSON.stringify(createSessionParams?.items),
|
|
1357
|
+
JSON.stringify(createSessionParams?.subscriptions)
|
|
1358
|
+
]
|
|
1359
|
+
);
|
|
1360
|
+
const createSessionParamsRef = useRef3(createSessionParams);
|
|
1361
|
+
createSessionParamsRef.current = createSessionParams;
|
|
1239
1362
|
useEffect4(() => {
|
|
1240
1363
|
let cancelled = false;
|
|
1241
|
-
setIsLoading(true);
|
|
1242
1364
|
setLoadError(null);
|
|
1365
|
+
if (createSessionHash) {
|
|
1366
|
+
if (initializedHashRef.current === createSessionHash) return;
|
|
1367
|
+
const params = createSessionParamsRef.current;
|
|
1368
|
+
const totalAmount = [
|
|
1369
|
+
...(params.items ?? []).map((i) => i.overrideAmount ?? i.totalAmount ?? 0),
|
|
1370
|
+
...(params.subscriptions ?? []).map((s) => s.overrideAmount ?? s.totalAmount ?? 0)
|
|
1371
|
+
].reduce((sum, v) => sum + v, 0);
|
|
1372
|
+
const currency = params.items?.[0]?.currency ?? params.subscriptions?.[0]?.currency ?? "USD";
|
|
1373
|
+
const syntheticSession = {
|
|
1374
|
+
id: "",
|
|
1375
|
+
clientSecret: "",
|
|
1376
|
+
mode: "payment",
|
|
1377
|
+
amount: Math.round(totalAmount * 100),
|
|
1378
|
+
currency,
|
|
1379
|
+
status: "open",
|
|
1380
|
+
customer: {
|
|
1381
|
+
id: params.account.userId,
|
|
1382
|
+
email: params.account.email,
|
|
1383
|
+
firstName: params.account.firstName,
|
|
1384
|
+
lastName: params.account.lastName
|
|
1385
|
+
},
|
|
1386
|
+
successUrl: params.successUrl,
|
|
1387
|
+
cancelUrl: params.cancelUrl,
|
|
1388
|
+
checkoutMode: params.checkoutMode ?? "full",
|
|
1389
|
+
items: (params.items ?? []).map((i, idx) => ({
|
|
1390
|
+
uuid: `synthetic-item-${idx}`,
|
|
1391
|
+
checkoutSessionId: "",
|
|
1392
|
+
providerItemId: i.providerItemId,
|
|
1393
|
+
providerItemName: i.providerItemName ?? i.providerItemId,
|
|
1394
|
+
quantity: i.quantity ?? 1,
|
|
1395
|
+
totalAmount: i.totalAmount,
|
|
1396
|
+
overrideAmount: i.overrideAmount ?? null,
|
|
1397
|
+
currency: i.currency ?? currency
|
|
1398
|
+
})),
|
|
1399
|
+
subscriptions: (params.subscriptions ?? []).map((s, idx) => ({
|
|
1400
|
+
uuid: `synthetic-sub-${idx}`,
|
|
1401
|
+
checkoutSessionId: "",
|
|
1402
|
+
providerPlanId: s.providerPlanId,
|
|
1403
|
+
providerPlanName: s.providerPlanName ?? s.providerPlanId,
|
|
1404
|
+
quantity: s.quantity ?? 1,
|
|
1405
|
+
totalAmount: s.totalAmount,
|
|
1406
|
+
overrideAmount: s.overrideAmount ?? null,
|
|
1407
|
+
currency: s.currency ?? currency
|
|
1408
|
+
}))
|
|
1409
|
+
};
|
|
1410
|
+
setSession(syntheticSession);
|
|
1411
|
+
setCurrentMode(params.checkoutMode ?? checkoutModeProp ?? "full");
|
|
1412
|
+
setIsLoading(false);
|
|
1413
|
+
const cacheKey = createSessionHash;
|
|
1414
|
+
async function resolveSession() {
|
|
1415
|
+
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1416
|
+
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
1417
|
+
let realResult = null;
|
|
1418
|
+
if (sid) {
|
|
1419
|
+
try {
|
|
1420
|
+
realResult = await api.getUnifiedCheckoutSession(sid);
|
|
1421
|
+
if (realResult.data.session?.status === "complete") {
|
|
1422
|
+
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
1423
|
+
sid = null;
|
|
1424
|
+
realResult = null;
|
|
1425
|
+
}
|
|
1426
|
+
} catch {
|
|
1427
|
+
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
1428
|
+
sid = null;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
if (!sid) {
|
|
1432
|
+
realResult = await api.createAndFetchSession(createSessionParamsRef.current);
|
|
1433
|
+
sid = realResult.data.session?.id ?? "";
|
|
1434
|
+
if (sid && typeof window !== "undefined") {
|
|
1435
|
+
window.sessionStorage.setItem(cacheKey, sid);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
return { sid: sid ?? "", result: realResult };
|
|
1439
|
+
}
|
|
1440
|
+
(async () => {
|
|
1441
|
+
try {
|
|
1442
|
+
let promise = inflightRef.current.get(cacheKey);
|
|
1443
|
+
if (!promise) {
|
|
1444
|
+
promise = resolveSession();
|
|
1445
|
+
inflightRef.current.set(cacheKey, promise);
|
|
1446
|
+
}
|
|
1447
|
+
let resolved;
|
|
1448
|
+
try {
|
|
1449
|
+
resolved = await promise;
|
|
1450
|
+
} finally {
|
|
1451
|
+
inflightRef.current.delete(cacheKey);
|
|
1452
|
+
}
|
|
1453
|
+
if (cancelled) return;
|
|
1454
|
+
const { sid, result: realResult } = resolved;
|
|
1455
|
+
if (realResult) {
|
|
1456
|
+
setUnified(realResult);
|
|
1457
|
+
if (realResult.data.session) setSession(realResult.data.session);
|
|
1458
|
+
}
|
|
1459
|
+
if (sid) {
|
|
1460
|
+
setResolvedSessionId(sid);
|
|
1461
|
+
}
|
|
1462
|
+
let pk;
|
|
1463
|
+
if (realResult?.provider === "stripe") {
|
|
1464
|
+
pk = realResult.data.stripe?.publishableKey;
|
|
1465
|
+
}
|
|
1466
|
+
if (!pk) pk = fallbackPublishableKey;
|
|
1467
|
+
if (!pk) {
|
|
1468
|
+
throw new FloPayError2(
|
|
1469
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1470
|
+
"validation_error"
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
const instance = await loadFloPay(pk, { billingApiUrl: resolvedBillingUrl, locale });
|
|
1474
|
+
if (!cancelled) {
|
|
1475
|
+
flopayRef.current = instance;
|
|
1476
|
+
setFloPay(instance);
|
|
1477
|
+
initializedHashRef.current = cacheKey;
|
|
1478
|
+
}
|
|
1479
|
+
} catch (err) {
|
|
1480
|
+
if (cancelled) return;
|
|
1481
|
+
const floPayErr = err instanceof FloPayError2 ? err : new FloPayError2(err instanceof Error ? err.message : "Failed to create session", "api_error");
|
|
1482
|
+
setLoadError(floPayErr);
|
|
1483
|
+
}
|
|
1484
|
+
})();
|
|
1485
|
+
return () => {
|
|
1486
|
+
cancelled = true;
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
setIsLoading(true);
|
|
1243
1490
|
async function init() {
|
|
1244
1491
|
try {
|
|
1245
1492
|
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1246
|
-
const result = await api.getUnifiedCheckoutSession(
|
|
1493
|
+
const result = await api.getUnifiedCheckoutSession(resolvedSessionId);
|
|
1247
1494
|
if (cancelled) return;
|
|
1248
1495
|
setUnified(result);
|
|
1249
1496
|
const sess = result.data.session ?? null;
|
|
@@ -1261,7 +1508,7 @@ function FloPayCheckout({
|
|
|
1261
1508
|
const hasPayPalRedirectParams = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent");
|
|
1262
1509
|
if (effectiveMode === "auto" && !autoCheckoutAttempted.current && !hasPayPalRedirectParams) {
|
|
1263
1510
|
autoCheckoutAttempted.current = true;
|
|
1264
|
-
const stripeInitPromise = initStripe(result
|
|
1511
|
+
const stripeInitPromise = initStripe(result);
|
|
1265
1512
|
try {
|
|
1266
1513
|
const redirectResult = await processPaymentForMode(sess);
|
|
1267
1514
|
if (!redirectResult) {
|
|
@@ -1272,9 +1519,7 @@ function FloPayCheckout({
|
|
|
1272
1519
|
await stripeInitPromise;
|
|
1273
1520
|
const handled = await handleRedirectResult(redirectResult, sess, { attempt3DS: true });
|
|
1274
1521
|
if (!cancelled) {
|
|
1275
|
-
if (!handled)
|
|
1276
|
-
setCurrentMode("full");
|
|
1277
|
-
}
|
|
1522
|
+
if (!handled) setCurrentMode("full");
|
|
1278
1523
|
setIsLoading(false);
|
|
1279
1524
|
}
|
|
1280
1525
|
return;
|
|
@@ -1286,19 +1531,16 @@ function FloPayCheckout({
|
|
|
1286
1531
|
return;
|
|
1287
1532
|
}
|
|
1288
1533
|
}
|
|
1289
|
-
await initStripe(result
|
|
1534
|
+
await initStripe(result);
|
|
1290
1535
|
if (!cancelled) setIsLoading(false);
|
|
1291
1536
|
} catch (err) {
|
|
1292
1537
|
if (cancelled) return;
|
|
1293
|
-
const floPayErr = err instanceof FloPayError2 ? err : new FloPayError2(
|
|
1294
|
-
err instanceof Error ? err.message : "Failed to initialize checkout",
|
|
1295
|
-
"api_error"
|
|
1296
|
-
);
|
|
1538
|
+
const floPayErr = err instanceof FloPayError2 ? err : new FloPayError2(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
1297
1539
|
setLoadError(floPayErr);
|
|
1298
1540
|
setIsLoading(false);
|
|
1299
1541
|
}
|
|
1300
1542
|
}
|
|
1301
|
-
async function initStripe(result
|
|
1543
|
+
async function initStripe(result) {
|
|
1302
1544
|
let publishableKey;
|
|
1303
1545
|
if (result.provider === "stripe") {
|
|
1304
1546
|
publishableKey = result.data.stripe?.publishableKey;
|
|
@@ -1321,7 +1563,7 @@ function FloPayCheckout({
|
|
|
1321
1563
|
return () => {
|
|
1322
1564
|
cancelled = true;
|
|
1323
1565
|
};
|
|
1324
|
-
}, [
|
|
1566
|
+
}, [resolvedSessionId, createSessionHash, resolvedBillingUrl, fallbackPublishableKey, locale, checkoutModeProp]);
|
|
1325
1567
|
const handleConfirmCheckout = useCallback2(async () => {
|
|
1326
1568
|
if (confirmProcessing || !session) return;
|
|
1327
1569
|
setConfirmProcessing(true);
|
|
@@ -1373,32 +1615,32 @@ function FloPayCheckout({
|
|
|
1373
1615
|
[session, isLoading, loadError, currentMode]
|
|
1374
1616
|
);
|
|
1375
1617
|
if (isLoading) {
|
|
1376
|
-
return /* @__PURE__ */ jsx4(Fragment2, { children: loadingNode
|
|
1377
|
-
|
|
1378
|
-
{
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1618
|
+
if (loadingNode) return /* @__PURE__ */ jsx4(Fragment2, { children: loadingNode });
|
|
1619
|
+
if (layout === "buttons") {
|
|
1620
|
+
const skeletonBar = (h) => /* @__PURE__ */ jsx4("div", { style: {
|
|
1621
|
+
height: h,
|
|
1622
|
+
borderRadius: 8,
|
|
1623
|
+
background: "#e5e7eb",
|
|
1624
|
+
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
1625
|
+
} });
|
|
1626
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
1627
|
+
showPayPal && skeletonBar(44),
|
|
1628
|
+
(showApplePay || showGooglePay) && skeletonBar(44),
|
|
1629
|
+
skeletonBar(48),
|
|
1630
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
1631
|
+
] });
|
|
1632
|
+
}
|
|
1633
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
1634
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1635
|
+
width: 24,
|
|
1636
|
+
height: 24,
|
|
1637
|
+
border: "2px solid #e5e7eb",
|
|
1638
|
+
borderTopColor: "#6b7280",
|
|
1639
|
+
borderRadius: "50%",
|
|
1640
|
+
animation: "spin 0.6s linear infinite"
|
|
1641
|
+
} }),
|
|
1642
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
1643
|
+
] });
|
|
1402
1644
|
}
|
|
1403
1645
|
if (loadError) {
|
|
1404
1646
|
if (errorNode) return /* @__PURE__ */ jsx4(Fragment2, { children: errorNode(loadError) });
|
|
@@ -1415,6 +1657,19 @@ function FloPayCheckout({
|
|
|
1415
1657
|
}
|
|
1416
1658
|
);
|
|
1417
1659
|
}
|
|
1660
|
+
if ((!flopay || !providerOptions) && createSessionParams && layout === "buttons") {
|
|
1661
|
+
return /* @__PURE__ */ jsx4(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx4(
|
|
1662
|
+
InterimButtonsView,
|
|
1663
|
+
{
|
|
1664
|
+
onButtonClick,
|
|
1665
|
+
showPayPal,
|
|
1666
|
+
showApplePay,
|
|
1667
|
+
showGooglePay,
|
|
1668
|
+
buttonsTheme,
|
|
1669
|
+
buttonsStyles
|
|
1670
|
+
}
|
|
1671
|
+
) });
|
|
1672
|
+
}
|
|
1418
1673
|
if (!flopay || !providerOptions) return /* @__PURE__ */ jsx4(Fragment2, {});
|
|
1419
1674
|
if (currentMode === "confirm") {
|
|
1420
1675
|
return /* @__PURE__ */ jsx4(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx4(FloPayProvider, { flopay, options: providerOptions, children: /* @__PURE__ */ jsxs2("div", { className, children: [
|
|
@@ -1475,7 +1730,7 @@ function FloPayCheckout({
|
|
|
1475
1730
|
children ? /* @__PURE__ */ jsx4(
|
|
1476
1731
|
SessionInjector,
|
|
1477
1732
|
{
|
|
1478
|
-
sessionId,
|
|
1733
|
+
sessionId: resolvedSessionId,
|
|
1479
1734
|
billingApiUrl: resolvedBillingUrl,
|
|
1480
1735
|
session,
|
|
1481
1736
|
children
|
|
@@ -1483,7 +1738,7 @@ function FloPayCheckout({
|
|
|
1483
1738
|
) : /* @__PURE__ */ jsx4(
|
|
1484
1739
|
SplitCardForm,
|
|
1485
1740
|
{
|
|
1486
|
-
sessionId,
|
|
1741
|
+
sessionId: resolvedSessionId,
|
|
1487
1742
|
email: session?.customer?.email,
|
|
1488
1743
|
userId: session?.customer?.id,
|
|
1489
1744
|
firstName: session?.customer?.firstName,
|
|
@@ -1496,6 +1751,9 @@ function FloPayCheckout({
|
|
|
1496
1751
|
showApplePay,
|
|
1497
1752
|
showGooglePay,
|
|
1498
1753
|
layout,
|
|
1754
|
+
buttonsTheme,
|
|
1755
|
+
buttonsStyles,
|
|
1756
|
+
onButtonClick,
|
|
1499
1757
|
submitLabel,
|
|
1500
1758
|
className
|
|
1501
1759
|
}
|
|
@@ -1526,6 +1784,162 @@ function SessionInjector({
|
|
|
1526
1784
|
return React4.cloneElement(child, injected);
|
|
1527
1785
|
}) });
|
|
1528
1786
|
}
|
|
1787
|
+
function InterimButtonsView({
|
|
1788
|
+
onButtonClick,
|
|
1789
|
+
showPayPal,
|
|
1790
|
+
showApplePay,
|
|
1791
|
+
showGooglePay,
|
|
1792
|
+
buttonsTheme,
|
|
1793
|
+
buttonsStyles: stylesOverride
|
|
1794
|
+
}) {
|
|
1795
|
+
const [showCardForm, setShowCardForm] = useState3(false);
|
|
1796
|
+
const bStyles = useMemo3(() => {
|
|
1797
|
+
const base = resolveButtonsLayoutTheme2(buttonsTheme);
|
|
1798
|
+
if (!stylesOverride) return base;
|
|
1799
|
+
return {
|
|
1800
|
+
...base,
|
|
1801
|
+
...stylesOverride,
|
|
1802
|
+
cardButton: { ...base.cardButton, ...stylesOverride.cardButton },
|
|
1803
|
+
cardFormContainer: { ...base.cardFormContainer, ...stylesOverride.cardFormContainer },
|
|
1804
|
+
submitButton: { ...base.submitButton, ...stylesOverride.submitButton },
|
|
1805
|
+
title: { ...base.title, ...stylesOverride.title }
|
|
1806
|
+
};
|
|
1807
|
+
}, [buttonsTheme, stylesOverride]);
|
|
1808
|
+
const skeleton = (h) => /* @__PURE__ */ jsx4("div", { style: {
|
|
1809
|
+
height: h,
|
|
1810
|
+
borderRadius: 8,
|
|
1811
|
+
background: "#e5e7eb",
|
|
1812
|
+
animation: "flopay-interim-pulse 1.5s ease-in-out infinite"
|
|
1813
|
+
} });
|
|
1814
|
+
if (showCardForm) {
|
|
1815
|
+
const inputBorder = bStyles.cardInputBorder ?? "#e5e7eb";
|
|
1816
|
+
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
1817
|
+
return /* @__PURE__ */ jsxs2("div", { style: {
|
|
1818
|
+
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
1819
|
+
borderRadius: "8px",
|
|
1820
|
+
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
1821
|
+
overflow: "hidden",
|
|
1822
|
+
...bStyles.cardFormContainer
|
|
1823
|
+
}, children: [
|
|
1824
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
1825
|
+
/* @__PURE__ */ jsxs2(
|
|
1826
|
+
"button",
|
|
1827
|
+
{
|
|
1828
|
+
type: "button",
|
|
1829
|
+
onClick: () => setShowCardForm(false),
|
|
1830
|
+
style: {
|
|
1831
|
+
display: "inline-flex",
|
|
1832
|
+
alignItems: "center",
|
|
1833
|
+
gap: "0.5rem",
|
|
1834
|
+
background: "none",
|
|
1835
|
+
border: "none",
|
|
1836
|
+
cursor: "pointer",
|
|
1837
|
+
color: "#4b5563",
|
|
1838
|
+
fontSize: "0.85rem",
|
|
1839
|
+
fontWeight: 500,
|
|
1840
|
+
padding: 0,
|
|
1841
|
+
flexShrink: 0,
|
|
1842
|
+
...bStyles.backButton
|
|
1843
|
+
},
|
|
1844
|
+
children: [
|
|
1845
|
+
/* @__PURE__ */ jsx4("span", { style: {
|
|
1846
|
+
display: "inline-flex",
|
|
1847
|
+
alignItems: "center",
|
|
1848
|
+
justifyContent: "center",
|
|
1849
|
+
width: 28,
|
|
1850
|
+
height: 28,
|
|
1851
|
+
borderRadius: "50%",
|
|
1852
|
+
backgroundColor: "#f3f4f6",
|
|
1853
|
+
...bStyles.backButtonIcon
|
|
1854
|
+
}, children: /* @__PURE__ */ jsx4("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("path", { d: "M15 18l-6-6 6-6" }) }) }),
|
|
1855
|
+
"Go back"
|
|
1856
|
+
]
|
|
1857
|
+
}
|
|
1858
|
+
),
|
|
1859
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1860
|
+
flex: 1,
|
|
1861
|
+
textAlign: "center",
|
|
1862
|
+
fontWeight: 600,
|
|
1863
|
+
fontSize: "1.05rem",
|
|
1864
|
+
color: "#262833",
|
|
1865
|
+
paddingRight: 80,
|
|
1866
|
+
...bStyles.title
|
|
1867
|
+
}, children: "Secure card checkout" })
|
|
1868
|
+
] }),
|
|
1869
|
+
/* @__PURE__ */ jsx4("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx4("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
1870
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex" }, children: [
|
|
1871
|
+
/* @__PURE__ */ jsx4("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderRight: "none", borderBottomLeftRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx4("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
1872
|
+
/* @__PURE__ */ jsx4("div", { style: { flex: 1, backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTop: "none", borderBottomRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx4("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
|
|
1873
|
+
] }),
|
|
1874
|
+
/* @__PURE__ */ jsx4("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx4("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
|
|
1875
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1876
|
+
height: 50,
|
|
1877
|
+
borderRadius: 8,
|
|
1878
|
+
marginTop: 16,
|
|
1879
|
+
background: "#c8c8ff",
|
|
1880
|
+
animation: "flopay-interim-pulse 1.5s ease-in-out infinite",
|
|
1881
|
+
...bStyles.submitButton,
|
|
1882
|
+
opacity: 0.5
|
|
1883
|
+
} }),
|
|
1884
|
+
/* @__PURE__ */ jsx4("style", { children: `
|
|
1885
|
+
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
1886
|
+
@keyframes flopay-interim-expand {
|
|
1887
|
+
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
1888
|
+
40% { opacity: 1; }
|
|
1889
|
+
100% { opacity: 1; max-height: 600px; transform: translateY(0); }
|
|
1890
|
+
}
|
|
1891
|
+
` })
|
|
1892
|
+
] });
|
|
1893
|
+
}
|
|
1894
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
1895
|
+
showPayPal && skeleton(44),
|
|
1896
|
+
(showApplePay || showGooglePay) && skeleton(44),
|
|
1897
|
+
/* @__PURE__ */ jsxs2(
|
|
1898
|
+
"button",
|
|
1899
|
+
{
|
|
1900
|
+
type: "button",
|
|
1901
|
+
onClick: () => {
|
|
1902
|
+
onButtonClick?.("card");
|
|
1903
|
+
setShowCardForm(true);
|
|
1904
|
+
},
|
|
1905
|
+
style: {
|
|
1906
|
+
width: "100%",
|
|
1907
|
+
padding: "0.9rem 1rem",
|
|
1908
|
+
backgroundColor: "white",
|
|
1909
|
+
color: "#262833",
|
|
1910
|
+
border: "1px solid #d1d5db",
|
|
1911
|
+
borderRadius: "8px",
|
|
1912
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1913
|
+
fontWeight: 600,
|
|
1914
|
+
cursor: "pointer",
|
|
1915
|
+
display: "flex",
|
|
1916
|
+
alignItems: "center",
|
|
1917
|
+
justifyContent: "center",
|
|
1918
|
+
gap: "0.625rem",
|
|
1919
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1920
|
+
transition: "transform 0.1s",
|
|
1921
|
+
position: "relative",
|
|
1922
|
+
...bStyles.cardButton
|
|
1923
|
+
},
|
|
1924
|
+
onMouseDown: (e) => {
|
|
1925
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
1926
|
+
},
|
|
1927
|
+
onMouseUp: (e) => {
|
|
1928
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
1929
|
+
},
|
|
1930
|
+
children: [
|
|
1931
|
+
/* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1932
|
+
/* @__PURE__ */ jsx4("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
1933
|
+
/* @__PURE__ */ jsx4("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
1934
|
+
] }),
|
|
1935
|
+
"Credit / Debit Card",
|
|
1936
|
+
/* @__PURE__ */ jsx4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { position: "absolute", right: "1rem" }, children: /* @__PURE__ */ jsx4("path", { d: "M9 18l6-6-6-6" }) })
|
|
1937
|
+
]
|
|
1938
|
+
}
|
|
1939
|
+
),
|
|
1940
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
1941
|
+
] });
|
|
1942
|
+
}
|
|
1529
1943
|
|
|
1530
1944
|
// src/checkout-form.tsx
|
|
1531
1945
|
import { FloPayError as FloPayError3 } from "@flopay/shared";
|