@flopay/react 0.1.6 → 0.3.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 +715 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -4
- package/dist/index.d.ts +61 -4
- package/dist/index.mjs +696 -177
- 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, getPostalCodeLabel, COUNTRY_OPTIONS } 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,15 @@ function SplitCardFormInner({
|
|
|
512
539
|
showApplePay = true,
|
|
513
540
|
showGooglePay = true,
|
|
514
541
|
layout = "default",
|
|
542
|
+
buttonsTheme,
|
|
543
|
+
buttonsStyles: buttonsStylesOverride,
|
|
544
|
+
onButtonClick,
|
|
545
|
+
enableAVS = false,
|
|
546
|
+
avsLayout: avsLayoutProp = "row",
|
|
547
|
+
country: countryProp,
|
|
548
|
+
zip: zipProp,
|
|
549
|
+
onCountryChange,
|
|
550
|
+
onZipChange,
|
|
515
551
|
totalAmount = 0,
|
|
516
552
|
currency = "usd",
|
|
517
553
|
innerRef
|
|
@@ -521,14 +557,42 @@ function SplitCardFormInner({
|
|
|
521
557
|
const contextBillingUrl = useBillingApiUrl();
|
|
522
558
|
const [processing, setProcessing] = useState2(false);
|
|
523
559
|
const [error, setError] = useState2(null);
|
|
524
|
-
const [showCardForm, setShowCardForm] = useState2(false);
|
|
525
560
|
const [is3DSActive, setIs3DSActive] = useState2(false);
|
|
561
|
+
const [selectedCountry, setSelectedCountry] = useState2(countryProp ?? "US");
|
|
562
|
+
const [zipCode, setZipCode] = useState2(zipProp ?? "");
|
|
563
|
+
const zipCodeRef = useRef2(zipProp ?? "");
|
|
564
|
+
const selectedCountryRef = useRef2(countryProp ?? "US");
|
|
565
|
+
const [viewState, setViewState] = useState2("buttons");
|
|
566
|
+
const showCardForm = viewState === "expanding" || viewState === "card";
|
|
567
|
+
const TRANSITION_MS = 280;
|
|
568
|
+
const expandToCard = useCallback(() => {
|
|
569
|
+
setViewState("expanding");
|
|
570
|
+
setTimeout(() => setViewState("card"), TRANSITION_MS);
|
|
571
|
+
}, []);
|
|
572
|
+
const collapseToButtons = useCallback(() => {
|
|
573
|
+
setViewState("collapsing");
|
|
574
|
+
setTimeout(() => setViewState("buttons"), TRANSITION_MS);
|
|
575
|
+
}, []);
|
|
526
576
|
const [fullName, setFullName] = useState2("");
|
|
527
577
|
const [formReady, setFormReady] = useState2(false);
|
|
528
578
|
const [overlayStatus, setOverlayStatus] = useState2(null);
|
|
529
579
|
const processingRef = useRef2(false);
|
|
530
580
|
const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
|
|
531
581
|
const displayError = externalError ?? error;
|
|
582
|
+
const bStyles = useMemo2(() => {
|
|
583
|
+
const base = resolveButtonsLayoutTheme(buttonsTheme);
|
|
584
|
+
if (!buttonsStylesOverride) return base;
|
|
585
|
+
return {
|
|
586
|
+
...base,
|
|
587
|
+
...buttonsStylesOverride,
|
|
588
|
+
cardButton: { ...base.cardButton, ...buttonsStylesOverride.cardButton },
|
|
589
|
+
cardFormContainer: { ...base.cardFormContainer, ...buttonsStylesOverride.cardFormContainer },
|
|
590
|
+
backButton: { ...base.backButton, ...buttonsStylesOverride.backButton },
|
|
591
|
+
backButtonIcon: { ...base.backButtonIcon, ...buttonsStylesOverride.backButtonIcon },
|
|
592
|
+
submitButton: { ...base.submitButton, ...buttonsStylesOverride.submitButton },
|
|
593
|
+
title: { ...base.title, ...buttonsStylesOverride.title }
|
|
594
|
+
};
|
|
595
|
+
}, [buttonsTheme, buttonsStylesOverride]);
|
|
532
596
|
const isSubmitting = externalProcessing ?? processing;
|
|
533
597
|
const isSelfContained = !onTokenizedBody;
|
|
534
598
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
@@ -585,7 +649,8 @@ function SplitCardFormInner({
|
|
|
585
649
|
userId: userId ?? "",
|
|
586
650
|
email: email ?? "",
|
|
587
651
|
firstName: firstName ?? fullName.trim().split(/\s+/)[0] ?? "",
|
|
588
|
-
lastName: lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? ""
|
|
652
|
+
lastName: lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? "",
|
|
653
|
+
...enableAVS ? { zip: zipCodeRef.current, country: selectedCountryRef.current } : {}
|
|
589
654
|
},
|
|
590
655
|
chv
|
|
591
656
|
})
|
|
@@ -740,18 +805,30 @@ function SplitCardFormInner({
|
|
|
740
805
|
async (e) => {
|
|
741
806
|
e.preventDefault();
|
|
742
807
|
if (!flopay || !elements || isSubmitting || processingRef.current) return;
|
|
808
|
+
onButtonClick?.("card");
|
|
743
809
|
setProcessing(true);
|
|
744
810
|
setOverlayStatus("processing");
|
|
745
811
|
updateError(null);
|
|
746
812
|
let handedOff = false;
|
|
747
813
|
try {
|
|
814
|
+
if (enableAVS && !zipCodeRef.current.trim()) {
|
|
815
|
+
updateError(getPostalCodeLabel(selectedCountryRef.current) + " is required");
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
748
818
|
const submitResult = await flopay.submitElements();
|
|
749
819
|
if (submitResult.error) {
|
|
750
820
|
updateError(submitResult.error.message);
|
|
751
821
|
onError?.(submitResult.error);
|
|
752
822
|
return;
|
|
753
823
|
}
|
|
754
|
-
const
|
|
824
|
+
const billingDetails = enableAVS ? {
|
|
825
|
+
name: fullName,
|
|
826
|
+
address: {
|
|
827
|
+
country: selectedCountryRef.current,
|
|
828
|
+
postal_code: zipCodeRef.current
|
|
829
|
+
}
|
|
830
|
+
} : void 0;
|
|
831
|
+
const pmResult = await flopay.createPaymentMethod(billingDetails);
|
|
755
832
|
if (pmResult.error || !pmResult.paymentMethodId) {
|
|
756
833
|
updateError(pmResult.error?.message ?? "Failed to create payment method.");
|
|
757
834
|
return;
|
|
@@ -807,15 +884,25 @@ function SplitCardFormInner({
|
|
|
807
884
|
return /* @__PURE__ */ jsx3("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
|
|
808
885
|
}
|
|
809
886
|
const isButtons = layout === "buttons";
|
|
810
|
-
const
|
|
811
|
-
const cardBg = isButtons ? "white" : "#EDEDFF";
|
|
887
|
+
const resolvedBorder = isButtons ? bStyles.cardInputBorder ?? "#e5e7eb" : "#A4A4FF";
|
|
888
|
+
const cardBg = isButtons ? bStyles.cardFormContainer?.backgroundColor ?? "white" : "#EDEDFF";
|
|
889
|
+
const cardInputBg = isButtons ? bStyles.cardInputBackground ?? "white" : "white";
|
|
890
|
+
const stripeElementStyle = isButtons && (bStyles.cardInputColor || bStyles.cardInputPlaceholderColor || bStyles.cardInputFontSize) ? {
|
|
891
|
+
style: {
|
|
892
|
+
base: {
|
|
893
|
+
...bStyles.cardInputColor ? { color: bStyles.cardInputColor } : {},
|
|
894
|
+
...bStyles.cardInputFontSize ? { fontSize: bStyles.cardInputFontSize } : {},
|
|
895
|
+
...bStyles.cardInputPlaceholderColor ? { "::placeholder": { color: bStyles.cardInputPlaceholderColor } } : {}
|
|
896
|
+
},
|
|
897
|
+
invalid: { color: "#ef4444" }
|
|
898
|
+
}
|
|
899
|
+
} : {};
|
|
812
900
|
const cardFormBlock = /* @__PURE__ */ jsxs("div", { style: {
|
|
813
901
|
backgroundColor: cardBg,
|
|
814
902
|
borderRadius: "8px",
|
|
815
903
|
padding: isButtons ? "0" : "1rem",
|
|
816
|
-
...isButtons
|
|
817
|
-
|
|
818
|
-
} : {}
|
|
904
|
+
...isButtons ? bStyles.cardFormContainer : {},
|
|
905
|
+
...isButtons ? { padding: bStyles.cardFormContainer?.padding ?? "0" } : {}
|
|
819
906
|
}, children: [
|
|
820
907
|
isButtons && showCardForm && /* @__PURE__ */ jsxs("div", { style: {
|
|
821
908
|
display: "flex",
|
|
@@ -826,7 +913,7 @@ function SplitCardFormInner({
|
|
|
826
913
|
"button",
|
|
827
914
|
{
|
|
828
915
|
type: "button",
|
|
829
|
-
onClick:
|
|
916
|
+
onClick: collapseToButtons,
|
|
830
917
|
style: {
|
|
831
918
|
display: "inline-flex",
|
|
832
919
|
alignItems: "center",
|
|
@@ -835,17 +922,12 @@ function SplitCardFormInner({
|
|
|
835
922
|
border: "none",
|
|
836
923
|
cursor: "pointer",
|
|
837
924
|
color: "#4b5563",
|
|
838
|
-
fontSize: "0.85rem",
|
|
925
|
+
fontSize: bStyles.backButtonFontSize ?? "0.85rem",
|
|
839
926
|
fontWeight: 500,
|
|
840
927
|
padding: 0,
|
|
841
928
|
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";
|
|
929
|
+
flexShrink: 0,
|
|
930
|
+
...bStyles.backButton
|
|
849
931
|
},
|
|
850
932
|
"aria-label": "Back to payment methods",
|
|
851
933
|
children: [
|
|
@@ -857,44 +939,53 @@ function SplitCardFormInner({
|
|
|
857
939
|
height: 28,
|
|
858
940
|
borderRadius: "50%",
|
|
859
941
|
backgroundColor: "#f3f4f6",
|
|
860
|
-
transition: "background-color 0.15s"
|
|
942
|
+
transition: "background-color 0.15s",
|
|
943
|
+
...bStyles.backButtonIcon
|
|
861
944
|
}, 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
945
|
"Go back"
|
|
863
946
|
]
|
|
864
947
|
}
|
|
865
948
|
),
|
|
866
|
-
/* @__PURE__ */ jsx3("div", { style: {
|
|
949
|
+
/* @__PURE__ */ jsx3("div", { style: {
|
|
950
|
+
flex: 1,
|
|
951
|
+
textAlign: "center",
|
|
952
|
+
fontWeight: 600,
|
|
953
|
+
fontSize: bStyles.titleFontSize ?? "1.05rem",
|
|
954
|
+
color: "#262833",
|
|
955
|
+
paddingRight: 80,
|
|
956
|
+
...bStyles.title
|
|
957
|
+
}, children: "Secure card checkout" })
|
|
867
958
|
] }),
|
|
868
959
|
!isButtons && /* @__PURE__ */ jsx3("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: "Secure card checkout" }),
|
|
869
960
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
870
|
-
backgroundColor:
|
|
871
|
-
border: `1px solid ${
|
|
961
|
+
backgroundColor: cardInputBg,
|
|
962
|
+
border: `1px solid ${resolvedBorder}`,
|
|
872
963
|
borderTopLeftRadius: "8px",
|
|
873
964
|
borderTopRightRadius: "8px",
|
|
874
965
|
padding: "10px"
|
|
875
|
-
}, children: /* @__PURE__ */ jsx3(CardNumberElement, { onReady: () => setFormReady(true) }) }),
|
|
966
|
+
}, children: /* @__PURE__ */ jsx3(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
|
|
876
967
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex" }, children: [
|
|
877
968
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
878
969
|
flex: 1,
|
|
879
|
-
backgroundColor:
|
|
880
|
-
border: `1px solid ${
|
|
970
|
+
backgroundColor: cardInputBg,
|
|
971
|
+
border: `1px solid ${resolvedBorder}`,
|
|
881
972
|
borderTop: "none",
|
|
882
973
|
borderRight: "none",
|
|
883
974
|
borderBottomLeftRadius: "8px",
|
|
884
975
|
padding: "10px"
|
|
885
|
-
}, children: /* @__PURE__ */ jsx3(CardExpiryElement, {}) }),
|
|
976
|
+
}, children: /* @__PURE__ */ jsx3(CardExpiryElement, { options: stripeElementStyle }) }),
|
|
886
977
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
887
978
|
flex: 1,
|
|
888
|
-
backgroundColor:
|
|
889
|
-
border: `1px solid ${
|
|
979
|
+
backgroundColor: cardInputBg,
|
|
980
|
+
border: `1px solid ${resolvedBorder}`,
|
|
890
981
|
borderTop: "none",
|
|
891
982
|
borderBottomRightRadius: "8px",
|
|
892
983
|
padding: "10px"
|
|
893
|
-
}, children: /* @__PURE__ */ jsx3(CardCvcElement, {}) })
|
|
984
|
+
}, children: /* @__PURE__ */ jsx3(CardCvcElement, { options: stripeElementStyle }) })
|
|
894
985
|
] }),
|
|
895
986
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
896
|
-
backgroundColor:
|
|
897
|
-
border: `1px solid ${
|
|
987
|
+
backgroundColor: cardInputBg,
|
|
988
|
+
border: `1px solid ${resolvedBorder}`,
|
|
898
989
|
borderRadius: "8px",
|
|
899
990
|
marginTop: "0.5rem",
|
|
900
991
|
padding: "10px"
|
|
@@ -911,12 +1002,91 @@ function SplitCardFormInner({
|
|
|
911
1002
|
width: "100%",
|
|
912
1003
|
border: "none",
|
|
913
1004
|
outline: "none",
|
|
914
|
-
|
|
1005
|
+
background: "transparent",
|
|
1006
|
+
fontSize: bStyles.cardInputFontSize ?? "16px",
|
|
915
1007
|
fontFamily: "Poppins, sans-serif",
|
|
916
|
-
color: "#262833"
|
|
1008
|
+
color: bStyles.cardInputColor ?? "#262833",
|
|
1009
|
+
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
917
1010
|
}
|
|
918
1011
|
}
|
|
919
1012
|
) }),
|
|
1013
|
+
enableAVS && /* @__PURE__ */ jsxs("div", { style: {
|
|
1014
|
+
display: "flex",
|
|
1015
|
+
flexDirection: avsLayoutProp === "column" ? "column" : "row",
|
|
1016
|
+
gap: avsLayoutProp === "column" ? "0.5rem" : "0",
|
|
1017
|
+
marginTop: "0.5rem"
|
|
1018
|
+
}, children: [
|
|
1019
|
+
/* @__PURE__ */ jsx3("div", { style: {
|
|
1020
|
+
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
1021
|
+
backgroundColor: cardInputBg,
|
|
1022
|
+
border: `1px solid ${resolvedBorder}`,
|
|
1023
|
+
padding: "10px",
|
|
1024
|
+
...avsLayoutProp === "row" ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
|
|
1025
|
+
...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
|
|
1026
|
+
}, children: /* @__PURE__ */ jsx3(
|
|
1027
|
+
"select",
|
|
1028
|
+
{
|
|
1029
|
+
value: selectedCountry,
|
|
1030
|
+
onChange: (e) => {
|
|
1031
|
+
selectedCountryRef.current = e.target.value;
|
|
1032
|
+
setSelectedCountry(e.target.value);
|
|
1033
|
+
onCountryChange?.(e.target.value);
|
|
1034
|
+
},
|
|
1035
|
+
disabled: isSubmitting,
|
|
1036
|
+
autoComplete: "country",
|
|
1037
|
+
"data-testid": "flopay-country",
|
|
1038
|
+
style: {
|
|
1039
|
+
width: "100%",
|
|
1040
|
+
border: "none",
|
|
1041
|
+
outline: "none",
|
|
1042
|
+
background: "transparent",
|
|
1043
|
+
fontSize: bStyles.cardInputFontSize ?? "16px",
|
|
1044
|
+
fontFamily: "Poppins, sans-serif",
|
|
1045
|
+
color: bStyles.cardInputColor ?? "#262833",
|
|
1046
|
+
cursor: "pointer",
|
|
1047
|
+
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
1048
|
+
},
|
|
1049
|
+
children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs("option", { value: c.code, children: [
|
|
1050
|
+
c.flag,
|
|
1051
|
+
" ",
|
|
1052
|
+
c.name
|
|
1053
|
+
] }, c.code))
|
|
1054
|
+
}
|
|
1055
|
+
) }),
|
|
1056
|
+
/* @__PURE__ */ jsx3("div", { style: {
|
|
1057
|
+
flex: avsLayoutProp === "row" ? 1 : void 0,
|
|
1058
|
+
backgroundColor: cardInputBg,
|
|
1059
|
+
border: `1px solid ${resolvedBorder}`,
|
|
1060
|
+
padding: "10px",
|
|
1061
|
+
...avsLayoutProp === "row" ? { borderRadius: "0", borderTopRightRadius: "8px", borderBottomRightRadius: "8px" } : { borderRadius: "8px" },
|
|
1062
|
+
...isButtons && bStyles.zipInput ? bStyles.zipInput : {}
|
|
1063
|
+
}, children: /* @__PURE__ */ jsx3(
|
|
1064
|
+
"input",
|
|
1065
|
+
{
|
|
1066
|
+
placeholder: getPostalCodeLabel(selectedCountry),
|
|
1067
|
+
autoComplete: "postal-code",
|
|
1068
|
+
value: zipCode,
|
|
1069
|
+
onChange: (e) => {
|
|
1070
|
+
zipCodeRef.current = e.target.value;
|
|
1071
|
+
setZipCode(e.target.value);
|
|
1072
|
+
onZipChange?.(e.target.value);
|
|
1073
|
+
},
|
|
1074
|
+
disabled: isSubmitting,
|
|
1075
|
+
required: true,
|
|
1076
|
+
"data-testid": "flopay-zip",
|
|
1077
|
+
style: {
|
|
1078
|
+
width: "100%",
|
|
1079
|
+
border: "none",
|
|
1080
|
+
outline: "none",
|
|
1081
|
+
background: "transparent",
|
|
1082
|
+
fontSize: bStyles.cardInputFontSize ?? "16px",
|
|
1083
|
+
fontFamily: "Poppins, sans-serif",
|
|
1084
|
+
color: bStyles.cardInputColor ?? "#262833",
|
|
1085
|
+
...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
) })
|
|
1089
|
+
] }),
|
|
920
1090
|
displayError && /* @__PURE__ */ jsxs("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
921
1091
|
margin: "0.75rem 0",
|
|
922
1092
|
padding: "0.625rem 0.875rem",
|
|
@@ -928,7 +1098,8 @@ function SplitCardFormInner({
|
|
|
928
1098
|
fontWeight: 600,
|
|
929
1099
|
display: "flex",
|
|
930
1100
|
alignItems: "center",
|
|
931
|
-
gap: "0.5rem"
|
|
1101
|
+
gap: "0.5rem",
|
|
1102
|
+
...isButtons && bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
932
1103
|
}, children: [
|
|
933
1104
|
/* @__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
1105
|
displayError
|
|
@@ -947,10 +1118,11 @@ function SplitCardFormInner({
|
|
|
947
1118
|
color: "white",
|
|
948
1119
|
border: "none",
|
|
949
1120
|
borderRadius: "8px",
|
|
950
|
-
fontSize: "1rem",
|
|
1121
|
+
fontSize: isButtons && bStyles.submitButtonFontSize ? bStyles.submitButtonFontSize : "1rem",
|
|
951
1122
|
fontWeight: 600,
|
|
952
1123
|
cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
|
|
953
|
-
opacity: !formReady || isSubmitting ? 0.5 : 1
|
|
1124
|
+
opacity: !formReady || isSubmitting ? 0.5 : 1,
|
|
1125
|
+
...isButtons ? bStyles.submitButton : {}
|
|
954
1126
|
},
|
|
955
1127
|
children: isSubmitting ? "PROCESSING..." : submitLabel
|
|
956
1128
|
}
|
|
@@ -967,103 +1139,119 @@ function SplitCardFormInner({
|
|
|
967
1139
|
}, children: "Secure Card Checkout" })
|
|
968
1140
|
] });
|
|
969
1141
|
if (layout === "buttons") {
|
|
1142
|
+
const isButtonsView = viewState === "buttons" || viewState === "expanding";
|
|
1143
|
+
const isCardView = viewState === "expanding" || viewState === "card" || viewState === "collapsing";
|
|
1144
|
+
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;
|
|
1145
|
+
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
1146
|
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1147
|
+
/* @__PURE__ */ jsx3(FloPayKeyframes, {}),
|
|
971
1148
|
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,
|
|
1149
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "grid" }, children: [
|
|
1150
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
1151
|
+
gridArea: "1 / 1",
|
|
1055
1152
|
display: "flex",
|
|
1056
|
-
|
|
1057
|
-
gap: "0.5rem"
|
|
1153
|
+
flexDirection: "column",
|
|
1154
|
+
gap: "0.5rem",
|
|
1155
|
+
// When card form is showing (and not transitioning), hide but keep mounted
|
|
1156
|
+
...!isButtonsView && !buttonsAnim ? { visibility: "hidden", position: "absolute", pointerEvents: "none", width: "100%" } : {},
|
|
1157
|
+
...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
|
|
1058
1158
|
}, children: [
|
|
1059
|
-
/* @__PURE__ */ jsx3(
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1159
|
+
showPayPal && stripeInstance ? /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx3(
|
|
1160
|
+
PayPalButtonInner,
|
|
1161
|
+
{
|
|
1162
|
+
sessionId,
|
|
1163
|
+
email,
|
|
1164
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
1165
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
1166
|
+
onErrorChange: updateError,
|
|
1167
|
+
isProcessing: isSubmitting,
|
|
1168
|
+
onButtonClick
|
|
1169
|
+
}
|
|
1170
|
+
) }) : showPayPal ? /* @__PURE__ */ jsx3("div", { style: { height: 44, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
1171
|
+
showWallets && stripeInstance ? /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx3(
|
|
1172
|
+
WalletButtonInner,
|
|
1173
|
+
{
|
|
1174
|
+
sessionId,
|
|
1175
|
+
email,
|
|
1176
|
+
billingApiUrl: resolvedBillingApiUrl,
|
|
1177
|
+
showApplePay,
|
|
1178
|
+
showGooglePay,
|
|
1179
|
+
onTokenizedBody: dispatchTokenizedBody,
|
|
1180
|
+
onErrorChange: updateError,
|
|
1181
|
+
onButtonClick
|
|
1182
|
+
}
|
|
1183
|
+
) }) : showWallets ? /* @__PURE__ */ jsx3("div", { style: { height: 44, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
|
|
1184
|
+
/* @__PURE__ */ jsxs(
|
|
1185
|
+
"button",
|
|
1186
|
+
{
|
|
1187
|
+
type: "button",
|
|
1188
|
+
onClick: () => {
|
|
1189
|
+
onButtonClick?.("card");
|
|
1190
|
+
expandToCard();
|
|
1191
|
+
},
|
|
1192
|
+
style: {
|
|
1193
|
+
width: "100%",
|
|
1194
|
+
padding: "0.9rem 1rem",
|
|
1195
|
+
backgroundColor: "white",
|
|
1196
|
+
color: "#262833",
|
|
1197
|
+
border: "1px solid #d1d5db",
|
|
1198
|
+
borderRadius: "8px",
|
|
1199
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1200
|
+
fontWeight: 600,
|
|
1201
|
+
cursor: "pointer",
|
|
1202
|
+
display: "flex",
|
|
1203
|
+
alignItems: "center",
|
|
1204
|
+
justifyContent: "center",
|
|
1205
|
+
gap: "0.625rem",
|
|
1206
|
+
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1207
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1208
|
+
position: "relative",
|
|
1209
|
+
...bStyles.cardButton
|
|
1210
|
+
},
|
|
1211
|
+
onMouseDown: (e) => {
|
|
1212
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
1213
|
+
},
|
|
1214
|
+
onMouseUp: (e) => {
|
|
1215
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
1216
|
+
},
|
|
1217
|
+
children: [
|
|
1218
|
+
/* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1219
|
+
/* @__PURE__ */ jsx3("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
1220
|
+
/* @__PURE__ */ jsx3("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
1221
|
+
] }),
|
|
1222
|
+
"Credit / Debit Card",
|
|
1223
|
+
/* @__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" }) })
|
|
1224
|
+
]
|
|
1225
|
+
}
|
|
1226
|
+
),
|
|
1227
|
+
displayError && viewState === "buttons" && /* @__PURE__ */ jsxs("div", { role: "alert", "data-testid": "flopay-error", style: {
|
|
1228
|
+
margin: "0.25rem 0",
|
|
1229
|
+
padding: "0.625rem 0.875rem",
|
|
1230
|
+
background: "#FEF2F2",
|
|
1231
|
+
border: "1px solid #FECACA",
|
|
1232
|
+
borderRadius: "8px",
|
|
1233
|
+
color: "#991B1B",
|
|
1234
|
+
fontSize: "0.85rem",
|
|
1235
|
+
fontWeight: 600,
|
|
1236
|
+
display: "flex",
|
|
1237
|
+
alignItems: "center",
|
|
1238
|
+
gap: "0.5rem",
|
|
1239
|
+
...bStyles.errorBanner ? bStyles.errorBanner : {}
|
|
1240
|
+
}, children: [
|
|
1241
|
+
/* @__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" }) }),
|
|
1242
|
+
displayError
|
|
1243
|
+
] })
|
|
1244
|
+
] }),
|
|
1245
|
+
isCardView && /* @__PURE__ */ jsx3("div", { style: {
|
|
1246
|
+
gridArea: "1 / 1",
|
|
1247
|
+
...cardAnim ? { animation: cardAnim } : {},
|
|
1248
|
+
...viewState === "collapsing" ? { pointerEvents: "none" } : {}
|
|
1249
|
+
}, children: cardFormBlock })
|
|
1250
|
+
] })
|
|
1064
1251
|
] });
|
|
1065
1252
|
}
|
|
1066
1253
|
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
|
|
1254
|
+
/* @__PURE__ */ jsx3(FloPayKeyframes, {}),
|
|
1067
1255
|
overlayStatus && /* @__PURE__ */ jsx3(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
|
|
1068
1256
|
showWallets && stripeInstance && /* @__PURE__ */ jsx3(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx3(
|
|
1069
1257
|
WalletButtonInner,
|
|
@@ -1107,7 +1295,8 @@ function SplitCardFormInner({
|
|
|
1107
1295
|
// src/flopay-checkout.tsx
|
|
1108
1296
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1109
1297
|
function FloPayCheckout({
|
|
1110
|
-
sessionId,
|
|
1298
|
+
sessionId: sessionIdProp,
|
|
1299
|
+
createSession: createSessionParams,
|
|
1111
1300
|
billingApiUrl,
|
|
1112
1301
|
appearance,
|
|
1113
1302
|
locale,
|
|
@@ -1120,6 +1309,11 @@ function FloPayCheckout({
|
|
|
1120
1309
|
showApplePay = true,
|
|
1121
1310
|
showGooglePay = true,
|
|
1122
1311
|
layout,
|
|
1312
|
+
buttonsTheme,
|
|
1313
|
+
buttonsStyles,
|
|
1314
|
+
onButtonClick,
|
|
1315
|
+
enableAVS,
|
|
1316
|
+
avsLayout,
|
|
1123
1317
|
submitLabel,
|
|
1124
1318
|
className,
|
|
1125
1319
|
children,
|
|
@@ -1133,6 +1327,7 @@ function FloPayCheckout({
|
|
|
1133
1327
|
const [flopay, setFloPay] = useState3(null);
|
|
1134
1328
|
const flopayRef = useRef3(null);
|
|
1135
1329
|
const [session, setSession] = useState3(null);
|
|
1330
|
+
const [resolvedSessionId, setResolvedSessionId] = useState3(sessionIdProp ?? "");
|
|
1136
1331
|
const [isLoading, setIsLoading] = useState3(true);
|
|
1137
1332
|
const [loadError, setLoadError] = useState3(null);
|
|
1138
1333
|
const [currentMode, setCurrentMode] = useState3("full");
|
|
@@ -1155,7 +1350,7 @@ function FloPayCheckout({
|
|
|
1155
1350
|
"x-user-id": sess.customer?.id ?? ""
|
|
1156
1351
|
},
|
|
1157
1352
|
body: JSON.stringify({
|
|
1158
|
-
sessionId,
|
|
1353
|
+
sessionId: resolvedSessionId,
|
|
1159
1354
|
tokenizedData: { id: void 0 },
|
|
1160
1355
|
accountData: {
|
|
1161
1356
|
userId: sess.customer?.id ?? "",
|
|
@@ -1189,7 +1384,7 @@ function FloPayCheckout({
|
|
|
1189
1384
|
"api_error"
|
|
1190
1385
|
);
|
|
1191
1386
|
},
|
|
1192
|
-
[resolvedBillingUrl,
|
|
1387
|
+
[resolvedBillingUrl, resolvedSessionId]
|
|
1193
1388
|
);
|
|
1194
1389
|
const handleRedirectResult = useCallback2(
|
|
1195
1390
|
async (redirectResult, sess, options) => {
|
|
@@ -1234,16 +1429,169 @@ function FloPayCheckout({
|
|
|
1234
1429
|
}
|
|
1235
1430
|
return false;
|
|
1236
1431
|
},
|
|
1237
|
-
[resolvedBillingUrl,
|
|
1432
|
+
[resolvedBillingUrl, resolvedSessionId]
|
|
1433
|
+
);
|
|
1434
|
+
const inflightRef = useRef3(/* @__PURE__ */ new Map());
|
|
1435
|
+
const initializedHashRef = useRef3(null);
|
|
1436
|
+
function hashCreateParams(params) {
|
|
1437
|
+
const key = JSON.stringify({
|
|
1438
|
+
c: params?.clientId,
|
|
1439
|
+
i: params?.items?.map((x) => `${x.providerItemId}:${x.totalAmount}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
1440
|
+
s: params?.subscriptions?.map((x) => `${x.providerPlanId}:${x.totalAmount}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
1441
|
+
e: params?.account.email,
|
|
1442
|
+
m: params?.checkoutMode ?? "full"
|
|
1443
|
+
});
|
|
1444
|
+
let h = 0;
|
|
1445
|
+
for (let i = 0; i < key.length; i++) {
|
|
1446
|
+
h = (h << 5) - h + key.charCodeAt(i) | 0;
|
|
1447
|
+
}
|
|
1448
|
+
return `flopay_session_${Math.abs(h).toString(36)}`;
|
|
1449
|
+
}
|
|
1450
|
+
const createSessionHash = useMemo3(
|
|
1451
|
+
() => createSessionParams ? hashCreateParams(createSessionParams) : "",
|
|
1452
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1453
|
+
[
|
|
1454
|
+
createSessionParams?.clientId,
|
|
1455
|
+
createSessionParams?.account?.email,
|
|
1456
|
+
createSessionParams?.checkoutMode,
|
|
1457
|
+
JSON.stringify(createSessionParams?.items),
|
|
1458
|
+
JSON.stringify(createSessionParams?.subscriptions)
|
|
1459
|
+
]
|
|
1238
1460
|
);
|
|
1461
|
+
const createSessionParamsRef = useRef3(createSessionParams);
|
|
1462
|
+
createSessionParamsRef.current = createSessionParams;
|
|
1239
1463
|
useEffect4(() => {
|
|
1240
1464
|
let cancelled = false;
|
|
1241
|
-
setIsLoading(true);
|
|
1242
1465
|
setLoadError(null);
|
|
1466
|
+
if (createSessionHash) {
|
|
1467
|
+
if (initializedHashRef.current === createSessionHash) return;
|
|
1468
|
+
const params = createSessionParamsRef.current;
|
|
1469
|
+
const totalAmount = [
|
|
1470
|
+
...(params.items ?? []).map((i) => i.overrideAmount ?? i.totalAmount ?? 0),
|
|
1471
|
+
...(params.subscriptions ?? []).map((s) => s.overrideAmount ?? s.totalAmount ?? 0)
|
|
1472
|
+
].reduce((sum, v) => sum + v, 0);
|
|
1473
|
+
const currency = params.items?.[0]?.currency ?? params.subscriptions?.[0]?.currency ?? "USD";
|
|
1474
|
+
const syntheticSession = {
|
|
1475
|
+
id: "",
|
|
1476
|
+
clientSecret: "",
|
|
1477
|
+
mode: "payment",
|
|
1478
|
+
amount: Math.round(totalAmount * 100),
|
|
1479
|
+
currency,
|
|
1480
|
+
status: "open",
|
|
1481
|
+
customer: {
|
|
1482
|
+
id: params.account.userId,
|
|
1483
|
+
email: params.account.email,
|
|
1484
|
+
firstName: params.account.firstName,
|
|
1485
|
+
lastName: params.account.lastName
|
|
1486
|
+
},
|
|
1487
|
+
successUrl: params.successUrl,
|
|
1488
|
+
cancelUrl: params.cancelUrl,
|
|
1489
|
+
checkoutMode: params.checkoutMode ?? "full",
|
|
1490
|
+
items: (params.items ?? []).map((i, idx) => ({
|
|
1491
|
+
uuid: `synthetic-item-${idx}`,
|
|
1492
|
+
checkoutSessionId: "",
|
|
1493
|
+
providerItemId: i.providerItemId,
|
|
1494
|
+
providerItemName: i.providerItemName ?? i.providerItemId,
|
|
1495
|
+
quantity: i.quantity ?? 1,
|
|
1496
|
+
totalAmount: i.totalAmount,
|
|
1497
|
+
overrideAmount: i.overrideAmount ?? null,
|
|
1498
|
+
currency: i.currency ?? currency
|
|
1499
|
+
})),
|
|
1500
|
+
subscriptions: (params.subscriptions ?? []).map((s, idx) => ({
|
|
1501
|
+
uuid: `synthetic-sub-${idx}`,
|
|
1502
|
+
checkoutSessionId: "",
|
|
1503
|
+
providerPlanId: s.providerPlanId,
|
|
1504
|
+
providerPlanName: s.providerPlanName ?? s.providerPlanId,
|
|
1505
|
+
quantity: s.quantity ?? 1,
|
|
1506
|
+
totalAmount: s.totalAmount,
|
|
1507
|
+
overrideAmount: s.overrideAmount ?? null,
|
|
1508
|
+
currency: s.currency ?? currency
|
|
1509
|
+
}))
|
|
1510
|
+
};
|
|
1511
|
+
setSession(syntheticSession);
|
|
1512
|
+
setCurrentMode(params.checkoutMode ?? checkoutModeProp ?? "full");
|
|
1513
|
+
setIsLoading(false);
|
|
1514
|
+
const cacheKey = createSessionHash;
|
|
1515
|
+
async function resolveSession() {
|
|
1516
|
+
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1517
|
+
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
1518
|
+
let realResult = null;
|
|
1519
|
+
if (sid) {
|
|
1520
|
+
try {
|
|
1521
|
+
realResult = await api.getUnifiedCheckoutSession(sid);
|
|
1522
|
+
if (realResult.data.session?.status === "complete") {
|
|
1523
|
+
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
1524
|
+
sid = null;
|
|
1525
|
+
realResult = null;
|
|
1526
|
+
}
|
|
1527
|
+
} catch {
|
|
1528
|
+
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
1529
|
+
sid = null;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
if (!sid) {
|
|
1533
|
+
realResult = await api.createAndFetchSession(createSessionParamsRef.current);
|
|
1534
|
+
sid = realResult.data.session?.id ?? "";
|
|
1535
|
+
if (sid && typeof window !== "undefined") {
|
|
1536
|
+
window.sessionStorage.setItem(cacheKey, sid);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
return { sid: sid ?? "", result: realResult };
|
|
1540
|
+
}
|
|
1541
|
+
(async () => {
|
|
1542
|
+
try {
|
|
1543
|
+
let promise = inflightRef.current.get(cacheKey);
|
|
1544
|
+
if (!promise) {
|
|
1545
|
+
promise = resolveSession();
|
|
1546
|
+
inflightRef.current.set(cacheKey, promise);
|
|
1547
|
+
}
|
|
1548
|
+
let resolved;
|
|
1549
|
+
try {
|
|
1550
|
+
resolved = await promise;
|
|
1551
|
+
} finally {
|
|
1552
|
+
inflightRef.current.delete(cacheKey);
|
|
1553
|
+
}
|
|
1554
|
+
if (cancelled) return;
|
|
1555
|
+
const { sid, result: realResult } = resolved;
|
|
1556
|
+
if (realResult) {
|
|
1557
|
+
setUnified(realResult);
|
|
1558
|
+
if (realResult.data.session) setSession(realResult.data.session);
|
|
1559
|
+
}
|
|
1560
|
+
if (sid) {
|
|
1561
|
+
setResolvedSessionId(sid);
|
|
1562
|
+
}
|
|
1563
|
+
let pk;
|
|
1564
|
+
if (realResult?.provider === "stripe") {
|
|
1565
|
+
pk = realResult.data.stripe?.publishableKey;
|
|
1566
|
+
}
|
|
1567
|
+
if (!pk) pk = fallbackPublishableKey;
|
|
1568
|
+
if (!pk) {
|
|
1569
|
+
throw new FloPayError2(
|
|
1570
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1571
|
+
"validation_error"
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
const instance = await loadFloPay(pk, { billingApiUrl: resolvedBillingUrl, locale });
|
|
1575
|
+
if (!cancelled) {
|
|
1576
|
+
flopayRef.current = instance;
|
|
1577
|
+
setFloPay(instance);
|
|
1578
|
+
initializedHashRef.current = cacheKey;
|
|
1579
|
+
}
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
if (cancelled) return;
|
|
1582
|
+
const floPayErr = err instanceof FloPayError2 ? err : new FloPayError2(err instanceof Error ? err.message : "Failed to create session", "api_error");
|
|
1583
|
+
setLoadError(floPayErr);
|
|
1584
|
+
}
|
|
1585
|
+
})();
|
|
1586
|
+
return () => {
|
|
1587
|
+
cancelled = true;
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
setIsLoading(true);
|
|
1243
1591
|
async function init() {
|
|
1244
1592
|
try {
|
|
1245
1593
|
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1246
|
-
const result = await api.getUnifiedCheckoutSession(
|
|
1594
|
+
const result = await api.getUnifiedCheckoutSession(resolvedSessionId);
|
|
1247
1595
|
if (cancelled) return;
|
|
1248
1596
|
setUnified(result);
|
|
1249
1597
|
const sess = result.data.session ?? null;
|
|
@@ -1261,7 +1609,7 @@ function FloPayCheckout({
|
|
|
1261
1609
|
const hasPayPalRedirectParams = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent");
|
|
1262
1610
|
if (effectiveMode === "auto" && !autoCheckoutAttempted.current && !hasPayPalRedirectParams) {
|
|
1263
1611
|
autoCheckoutAttempted.current = true;
|
|
1264
|
-
const stripeInitPromise = initStripe(result
|
|
1612
|
+
const stripeInitPromise = initStripe(result);
|
|
1265
1613
|
try {
|
|
1266
1614
|
const redirectResult = await processPaymentForMode(sess);
|
|
1267
1615
|
if (!redirectResult) {
|
|
@@ -1272,9 +1620,7 @@ function FloPayCheckout({
|
|
|
1272
1620
|
await stripeInitPromise;
|
|
1273
1621
|
const handled = await handleRedirectResult(redirectResult, sess, { attempt3DS: true });
|
|
1274
1622
|
if (!cancelled) {
|
|
1275
|
-
if (!handled)
|
|
1276
|
-
setCurrentMode("full");
|
|
1277
|
-
}
|
|
1623
|
+
if (!handled) setCurrentMode("full");
|
|
1278
1624
|
setIsLoading(false);
|
|
1279
1625
|
}
|
|
1280
1626
|
return;
|
|
@@ -1286,19 +1632,16 @@ function FloPayCheckout({
|
|
|
1286
1632
|
return;
|
|
1287
1633
|
}
|
|
1288
1634
|
}
|
|
1289
|
-
await initStripe(result
|
|
1635
|
+
await initStripe(result);
|
|
1290
1636
|
if (!cancelled) setIsLoading(false);
|
|
1291
1637
|
} catch (err) {
|
|
1292
1638
|
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
|
-
);
|
|
1639
|
+
const floPayErr = err instanceof FloPayError2 ? err : new FloPayError2(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
|
|
1297
1640
|
setLoadError(floPayErr);
|
|
1298
1641
|
setIsLoading(false);
|
|
1299
1642
|
}
|
|
1300
1643
|
}
|
|
1301
|
-
async function initStripe(result
|
|
1644
|
+
async function initStripe(result) {
|
|
1302
1645
|
let publishableKey;
|
|
1303
1646
|
if (result.provider === "stripe") {
|
|
1304
1647
|
publishableKey = result.data.stripe?.publishableKey;
|
|
@@ -1321,7 +1664,7 @@ function FloPayCheckout({
|
|
|
1321
1664
|
return () => {
|
|
1322
1665
|
cancelled = true;
|
|
1323
1666
|
};
|
|
1324
|
-
}, [
|
|
1667
|
+
}, [resolvedSessionId, createSessionHash, resolvedBillingUrl, fallbackPublishableKey, locale, checkoutModeProp]);
|
|
1325
1668
|
const handleConfirmCheckout = useCallback2(async () => {
|
|
1326
1669
|
if (confirmProcessing || !session) return;
|
|
1327
1670
|
setConfirmProcessing(true);
|
|
@@ -1373,32 +1716,32 @@ function FloPayCheckout({
|
|
|
1373
1716
|
[session, isLoading, loadError, currentMode]
|
|
1374
1717
|
);
|
|
1375
1718
|
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
|
-
|
|
1719
|
+
if (loadingNode) return /* @__PURE__ */ jsx4(Fragment2, { children: loadingNode });
|
|
1720
|
+
if (layout === "buttons") {
|
|
1721
|
+
const skeletonBar = (h) => /* @__PURE__ */ jsx4("div", { style: {
|
|
1722
|
+
height: h,
|
|
1723
|
+
borderRadius: 8,
|
|
1724
|
+
background: "#e5e7eb",
|
|
1725
|
+
animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
|
|
1726
|
+
} });
|
|
1727
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
1728
|
+
showPayPal && skeletonBar(44),
|
|
1729
|
+
(showApplePay || showGooglePay) && skeletonBar(44),
|
|
1730
|
+
skeletonBar(48),
|
|
1731
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
1732
|
+
] });
|
|
1733
|
+
}
|
|
1734
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
|
|
1735
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1736
|
+
width: 24,
|
|
1737
|
+
height: 24,
|
|
1738
|
+
border: "2px solid #e5e7eb",
|
|
1739
|
+
borderTopColor: "#6b7280",
|
|
1740
|
+
borderRadius: "50%",
|
|
1741
|
+
animation: "spin 0.6s linear infinite"
|
|
1742
|
+
} }),
|
|
1743
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
1744
|
+
] });
|
|
1402
1745
|
}
|
|
1403
1746
|
if (loadError) {
|
|
1404
1747
|
if (errorNode) return /* @__PURE__ */ jsx4(Fragment2, { children: errorNode(loadError) });
|
|
@@ -1415,6 +1758,19 @@ function FloPayCheckout({
|
|
|
1415
1758
|
}
|
|
1416
1759
|
);
|
|
1417
1760
|
}
|
|
1761
|
+
if ((!flopay || !providerOptions) && createSessionParams && layout === "buttons") {
|
|
1762
|
+
return /* @__PURE__ */ jsx4(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx4(
|
|
1763
|
+
InterimButtonsView,
|
|
1764
|
+
{
|
|
1765
|
+
onButtonClick,
|
|
1766
|
+
showPayPal,
|
|
1767
|
+
showApplePay,
|
|
1768
|
+
showGooglePay,
|
|
1769
|
+
buttonsTheme,
|
|
1770
|
+
buttonsStyles
|
|
1771
|
+
}
|
|
1772
|
+
) });
|
|
1773
|
+
}
|
|
1418
1774
|
if (!flopay || !providerOptions) return /* @__PURE__ */ jsx4(Fragment2, {});
|
|
1419
1775
|
if (currentMode === "confirm") {
|
|
1420
1776
|
return /* @__PURE__ */ jsx4(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx4(FloPayProvider, { flopay, options: providerOptions, children: /* @__PURE__ */ jsxs2("div", { className, children: [
|
|
@@ -1475,7 +1831,7 @@ function FloPayCheckout({
|
|
|
1475
1831
|
children ? /* @__PURE__ */ jsx4(
|
|
1476
1832
|
SessionInjector,
|
|
1477
1833
|
{
|
|
1478
|
-
sessionId,
|
|
1834
|
+
sessionId: resolvedSessionId,
|
|
1479
1835
|
billingApiUrl: resolvedBillingUrl,
|
|
1480
1836
|
session,
|
|
1481
1837
|
children
|
|
@@ -1483,7 +1839,7 @@ function FloPayCheckout({
|
|
|
1483
1839
|
) : /* @__PURE__ */ jsx4(
|
|
1484
1840
|
SplitCardForm,
|
|
1485
1841
|
{
|
|
1486
|
-
sessionId,
|
|
1842
|
+
sessionId: resolvedSessionId,
|
|
1487
1843
|
email: session?.customer?.email,
|
|
1488
1844
|
userId: session?.customer?.id,
|
|
1489
1845
|
firstName: session?.customer?.firstName,
|
|
@@ -1496,6 +1852,13 @@ function FloPayCheckout({
|
|
|
1496
1852
|
showApplePay,
|
|
1497
1853
|
showGooglePay,
|
|
1498
1854
|
layout,
|
|
1855
|
+
buttonsTheme,
|
|
1856
|
+
buttonsStyles,
|
|
1857
|
+
onButtonClick,
|
|
1858
|
+
enableAVS,
|
|
1859
|
+
avsLayout,
|
|
1860
|
+
country: session?.customer?.country,
|
|
1861
|
+
zip: session?.customer?.zip,
|
|
1499
1862
|
submitLabel,
|
|
1500
1863
|
className
|
|
1501
1864
|
}
|
|
@@ -1526,6 +1889,162 @@ function SessionInjector({
|
|
|
1526
1889
|
return React4.cloneElement(child, injected);
|
|
1527
1890
|
}) });
|
|
1528
1891
|
}
|
|
1892
|
+
function InterimButtonsView({
|
|
1893
|
+
onButtonClick,
|
|
1894
|
+
showPayPal,
|
|
1895
|
+
showApplePay,
|
|
1896
|
+
showGooglePay,
|
|
1897
|
+
buttonsTheme,
|
|
1898
|
+
buttonsStyles: stylesOverride
|
|
1899
|
+
}) {
|
|
1900
|
+
const [showCardForm, setShowCardForm] = useState3(false);
|
|
1901
|
+
const bStyles = useMemo3(() => {
|
|
1902
|
+
const base = resolveButtonsLayoutTheme2(buttonsTheme);
|
|
1903
|
+
if (!stylesOverride) return base;
|
|
1904
|
+
return {
|
|
1905
|
+
...base,
|
|
1906
|
+
...stylesOverride,
|
|
1907
|
+
cardButton: { ...base.cardButton, ...stylesOverride.cardButton },
|
|
1908
|
+
cardFormContainer: { ...base.cardFormContainer, ...stylesOverride.cardFormContainer },
|
|
1909
|
+
submitButton: { ...base.submitButton, ...stylesOverride.submitButton },
|
|
1910
|
+
title: { ...base.title, ...stylesOverride.title }
|
|
1911
|
+
};
|
|
1912
|
+
}, [buttonsTheme, stylesOverride]);
|
|
1913
|
+
const skeleton = (h) => /* @__PURE__ */ jsx4("div", { style: {
|
|
1914
|
+
height: h,
|
|
1915
|
+
borderRadius: 8,
|
|
1916
|
+
background: "#e5e7eb",
|
|
1917
|
+
animation: "flopay-interim-pulse 1.5s ease-in-out infinite"
|
|
1918
|
+
} });
|
|
1919
|
+
if (showCardForm) {
|
|
1920
|
+
const inputBorder = bStyles.cardInputBorder ?? "#e5e7eb";
|
|
1921
|
+
const inputBg = bStyles.cardInputBackground ?? "white";
|
|
1922
|
+
return /* @__PURE__ */ jsxs2("div", { style: {
|
|
1923
|
+
backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
|
|
1924
|
+
borderRadius: "8px",
|
|
1925
|
+
animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
|
|
1926
|
+
overflow: "hidden",
|
|
1927
|
+
...bStyles.cardFormContainer
|
|
1928
|
+
}, children: [
|
|
1929
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
|
|
1930
|
+
/* @__PURE__ */ jsxs2(
|
|
1931
|
+
"button",
|
|
1932
|
+
{
|
|
1933
|
+
type: "button",
|
|
1934
|
+
onClick: () => setShowCardForm(false),
|
|
1935
|
+
style: {
|
|
1936
|
+
display: "inline-flex",
|
|
1937
|
+
alignItems: "center",
|
|
1938
|
+
gap: "0.5rem",
|
|
1939
|
+
background: "none",
|
|
1940
|
+
border: "none",
|
|
1941
|
+
cursor: "pointer",
|
|
1942
|
+
color: "#4b5563",
|
|
1943
|
+
fontSize: "0.85rem",
|
|
1944
|
+
fontWeight: 500,
|
|
1945
|
+
padding: 0,
|
|
1946
|
+
flexShrink: 0,
|
|
1947
|
+
...bStyles.backButton
|
|
1948
|
+
},
|
|
1949
|
+
children: [
|
|
1950
|
+
/* @__PURE__ */ jsx4("span", { style: {
|
|
1951
|
+
display: "inline-flex",
|
|
1952
|
+
alignItems: "center",
|
|
1953
|
+
justifyContent: "center",
|
|
1954
|
+
width: 28,
|
|
1955
|
+
height: 28,
|
|
1956
|
+
borderRadius: "50%",
|
|
1957
|
+
backgroundColor: "#f3f4f6",
|
|
1958
|
+
...bStyles.backButtonIcon
|
|
1959
|
+
}, 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" }) }) }),
|
|
1960
|
+
"Go back"
|
|
1961
|
+
]
|
|
1962
|
+
}
|
|
1963
|
+
),
|
|
1964
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1965
|
+
flex: 1,
|
|
1966
|
+
textAlign: "center",
|
|
1967
|
+
fontWeight: 600,
|
|
1968
|
+
fontSize: "1.05rem",
|
|
1969
|
+
color: "#262833",
|
|
1970
|
+
paddingRight: 80,
|
|
1971
|
+
...bStyles.title
|
|
1972
|
+
}, children: "Secure card checkout" })
|
|
1973
|
+
] }),
|
|
1974
|
+
/* @__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" } }) }),
|
|
1975
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex" }, children: [
|
|
1976
|
+
/* @__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" } }) }),
|
|
1977
|
+
/* @__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" } }) })
|
|
1978
|
+
] }),
|
|
1979
|
+
/* @__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" } }) }),
|
|
1980
|
+
/* @__PURE__ */ jsx4("div", { style: {
|
|
1981
|
+
height: 50,
|
|
1982
|
+
borderRadius: 8,
|
|
1983
|
+
marginTop: 16,
|
|
1984
|
+
background: "#c8c8ff",
|
|
1985
|
+
animation: "flopay-interim-pulse 1.5s ease-in-out infinite",
|
|
1986
|
+
...bStyles.submitButton,
|
|
1987
|
+
opacity: 0.5
|
|
1988
|
+
} }),
|
|
1989
|
+
/* @__PURE__ */ jsx4("style", { children: `
|
|
1990
|
+
@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
1991
|
+
@keyframes flopay-interim-expand {
|
|
1992
|
+
0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
|
|
1993
|
+
40% { opacity: 1; }
|
|
1994
|
+
100% { opacity: 1; max-height: 600px; transform: translateY(0); }
|
|
1995
|
+
}
|
|
1996
|
+
` })
|
|
1997
|
+
] });
|
|
1998
|
+
}
|
|
1999
|
+
return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
|
|
2000
|
+
showPayPal && skeleton(44),
|
|
2001
|
+
(showApplePay || showGooglePay) && skeleton(44),
|
|
2002
|
+
/* @__PURE__ */ jsxs2(
|
|
2003
|
+
"button",
|
|
2004
|
+
{
|
|
2005
|
+
type: "button",
|
|
2006
|
+
onClick: () => {
|
|
2007
|
+
onButtonClick?.("card");
|
|
2008
|
+
setShowCardForm(true);
|
|
2009
|
+
},
|
|
2010
|
+
style: {
|
|
2011
|
+
width: "100%",
|
|
2012
|
+
padding: "0.9rem 1rem",
|
|
2013
|
+
backgroundColor: "white",
|
|
2014
|
+
color: "#262833",
|
|
2015
|
+
border: "1px solid #d1d5db",
|
|
2016
|
+
borderRadius: "8px",
|
|
2017
|
+
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
2018
|
+
fontWeight: 600,
|
|
2019
|
+
cursor: "pointer",
|
|
2020
|
+
display: "flex",
|
|
2021
|
+
alignItems: "center",
|
|
2022
|
+
justifyContent: "center",
|
|
2023
|
+
gap: "0.625rem",
|
|
2024
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
2025
|
+
transition: "transform 0.1s",
|
|
2026
|
+
position: "relative",
|
|
2027
|
+
...bStyles.cardButton
|
|
2028
|
+
},
|
|
2029
|
+
onMouseDown: (e) => {
|
|
2030
|
+
e.currentTarget.style.transform = "scale(0.985)";
|
|
2031
|
+
},
|
|
2032
|
+
onMouseUp: (e) => {
|
|
2033
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
2034
|
+
},
|
|
2035
|
+
children: [
|
|
2036
|
+
/* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2037
|
+
/* @__PURE__ */ jsx4("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
2038
|
+
/* @__PURE__ */ jsx4("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
2039
|
+
] }),
|
|
2040
|
+
"Credit / Debit Card",
|
|
2041
|
+
/* @__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" }) })
|
|
2042
|
+
]
|
|
2043
|
+
}
|
|
2044
|
+
),
|
|
2045
|
+
/* @__PURE__ */ jsx4("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
|
|
2046
|
+
] });
|
|
2047
|
+
}
|
|
1529
2048
|
|
|
1530
2049
|
// src/checkout-form.tsx
|
|
1531
2050
|
import { FloPayError as FloPayError3 } from "@flopay/shared";
|