@flopay/react 0.3.14 → 0.3.15
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 +1 -1
- package/dist/index.cjs +79 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +80 -113
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -206,7 +206,7 @@ import {
|
|
|
206
206
|
useStripe as useStripeRaw
|
|
207
207
|
} from "@stripe/react-stripe-js";
|
|
208
208
|
import { resolveButtonsLayoutTheme, getPostalCodeLabel, COUNTRY_OPTIONS } from "@flopay/shared";
|
|
209
|
-
import { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
209
|
+
import { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
210
210
|
|
|
211
211
|
// src/hooks.ts
|
|
212
212
|
import { useContext as useContext2 } from "react";
|
|
@@ -307,15 +307,6 @@ function buildSyntheticSession(params, checkoutModeOverride) {
|
|
|
307
307
|
}))
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
|
-
function ensureInlineSessionReady(params) {
|
|
311
|
-
if (!params.account.email?.trim()) {
|
|
312
|
-
throw new FloPayError(
|
|
313
|
-
"Email is required before continuing with card checkout.",
|
|
314
|
-
"validation_error",
|
|
315
|
-
{ param: "createSession.account.email" }
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
310
|
function mergeAccountPatch(base, patch) {
|
|
320
311
|
if (!patch) return base;
|
|
321
312
|
return {
|
|
@@ -777,6 +768,7 @@ function SplitCardFormInner({
|
|
|
777
768
|
}) {
|
|
778
769
|
const flopay = useFloPay();
|
|
779
770
|
const elements = useElements();
|
|
771
|
+
const checkout = useContext3(CheckoutContext);
|
|
780
772
|
const contextBillingUrl = useBillingApiUrl();
|
|
781
773
|
const [processing, setProcessing] = useState2(false);
|
|
782
774
|
const [error, setError] = useState2(null);
|
|
@@ -822,7 +814,8 @@ function SplitCardFormInner({
|
|
|
822
814
|
title: { ...base.title, ...buttonsStylesOverride.title }
|
|
823
815
|
};
|
|
824
816
|
}, [buttonsTheme, buttonsStylesOverride]);
|
|
825
|
-
const
|
|
817
|
+
const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
|
|
818
|
+
const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
|
|
826
819
|
const isSelfContained = !onTokenizedBody;
|
|
827
820
|
const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
|
|
828
821
|
const resolvedAccount = useMemo2(() => mergeAccountPatch({
|
|
@@ -881,8 +874,11 @@ function SplitCardFormInner({
|
|
|
881
874
|
if (result === false) {
|
|
882
875
|
return false;
|
|
883
876
|
}
|
|
884
|
-
if (result
|
|
885
|
-
|
|
877
|
+
if (result && typeof result === "object") {
|
|
878
|
+
await checkout.applyInlineSessionPatch?.(result);
|
|
879
|
+
if (result.account) {
|
|
880
|
+
setAccountPatch((prev) => ({ ...prev ?? {}, ...result.account }));
|
|
881
|
+
}
|
|
886
882
|
}
|
|
887
883
|
return true;
|
|
888
884
|
} catch (err) {
|
|
@@ -894,7 +890,7 @@ function SplitCardFormInner({
|
|
|
894
890
|
onError?.(floPayErr);
|
|
895
891
|
return false;
|
|
896
892
|
}
|
|
897
|
-
}, [onBeforeButtonClick, sessionId, updateError, onError]);
|
|
893
|
+
}, [checkout.applyInlineSessionPatch, onBeforeButtonClick, sessionId, updateError, onError]);
|
|
898
894
|
const processPaymentInternal = useCallback(
|
|
899
895
|
async (tokenizedBody) => {
|
|
900
896
|
if (processingRef.current) return;
|
|
@@ -1503,11 +1499,13 @@ function SplitCardFormInner({
|
|
|
1503
1499
|
{
|
|
1504
1500
|
type: "button",
|
|
1505
1501
|
onClick: async () => {
|
|
1502
|
+
if (isSubmitting) return;
|
|
1506
1503
|
const shouldContinue = await runBeforeCardButtonClick();
|
|
1507
1504
|
if (!shouldContinue) return;
|
|
1508
1505
|
onButtonClick?.("card");
|
|
1509
1506
|
expandToCard();
|
|
1510
1507
|
},
|
|
1508
|
+
disabled: isSubmitting,
|
|
1511
1509
|
style: {
|
|
1512
1510
|
width: "100%",
|
|
1513
1511
|
padding: "0.9rem 1rem",
|
|
@@ -1517,7 +1515,7 @@ function SplitCardFormInner({
|
|
|
1517
1515
|
borderRadius: "8px",
|
|
1518
1516
|
fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
|
|
1519
1517
|
fontWeight: 600,
|
|
1520
|
-
cursor: "pointer",
|
|
1518
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
1521
1519
|
display: "flex",
|
|
1522
1520
|
alignItems: "center",
|
|
1523
1521
|
justifyContent: "center",
|
|
@@ -1525,6 +1523,7 @@ function SplitCardFormInner({
|
|
|
1525
1523
|
transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
|
|
1526
1524
|
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
1527
1525
|
position: "relative",
|
|
1526
|
+
opacity: isSubmitting ? 0.6 : 1,
|
|
1528
1527
|
...bStyles.cardButton
|
|
1529
1528
|
},
|
|
1530
1529
|
onMouseDown: (e) => {
|
|
@@ -1608,6 +1607,12 @@ function SplitCardFormInner({
|
|
|
1608
1607
|
|
|
1609
1608
|
// src/flopay-checkout.tsx
|
|
1610
1609
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1610
|
+
function hasInlineSessionPatchData(patch) {
|
|
1611
|
+
if (!patch) return false;
|
|
1612
|
+
return Boolean(
|
|
1613
|
+
patch.account && Object.keys(patch.account).length > 0 || patch.couponCodes !== void 0 || patch.tagsData !== void 0 || patch.utmMetadata !== void 0
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1611
1616
|
function FloPayCheckout({
|
|
1612
1617
|
sessionId: sessionIdProp,
|
|
1613
1618
|
createSession: createSessionParams,
|
|
@@ -1655,7 +1660,6 @@ function FloPayCheckout({
|
|
|
1655
1660
|
const [createSessionPatch, setCreateSessionPatch] = useState3(void 0);
|
|
1656
1661
|
const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState3("");
|
|
1657
1662
|
const [cardBootstrapPending, setCardBootstrapPending] = useState3(false);
|
|
1658
|
-
const [deferredCardOpen, setDeferredCardOpen] = useState3(false);
|
|
1659
1663
|
const autoCheckoutAttempted = useRef3(false);
|
|
1660
1664
|
const onCompleteRef = useRef3(onComplete);
|
|
1661
1665
|
onCompleteRef.current = onComplete;
|
|
@@ -1790,9 +1794,6 @@ function FloPayCheckout({
|
|
|
1790
1794
|
);
|
|
1791
1795
|
const inflightRef = useRef3(/* @__PURE__ */ new Map());
|
|
1792
1796
|
const initializedHashRef = useRef3(null);
|
|
1793
|
-
const deferInlineSessionUntilCardClick = Boolean(
|
|
1794
|
-
effectiveCreateSession && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
1795
|
-
);
|
|
1796
1797
|
function hashCreateParams(params) {
|
|
1797
1798
|
const key = JSON.stringify({
|
|
1798
1799
|
c: params?.clientId,
|
|
@@ -1822,7 +1823,6 @@ function FloPayCheckout({
|
|
|
1822
1823
|
setResolvedSessionId(sessionIdProp ?? "");
|
|
1823
1824
|
}, [sessionIdProp]);
|
|
1824
1825
|
async function resolveInlineSession(params, cacheKey) {
|
|
1825
|
-
ensureInlineSessionReady(params);
|
|
1826
1826
|
const api = new PaymentAPI(resolvedBillingUrl);
|
|
1827
1827
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
1828
1828
|
let realResult = null;
|
|
@@ -1867,104 +1867,64 @@ function FloPayCheckout({
|
|
|
1867
1867
|
} finally {
|
|
1868
1868
|
inflightRef.current.delete(cacheKey);
|
|
1869
1869
|
}
|
|
1870
|
-
if (patch) {
|
|
1871
|
-
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1872
|
-
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1873
|
-
}
|
|
1874
|
-
const { sid, result: realResult } = resolved;
|
|
1875
|
-
setUnified(realResult);
|
|
1876
|
-
if (realResult.data.session) {
|
|
1877
|
-
setSession(realResult.data.session);
|
|
1878
|
-
}
|
|
1879
|
-
if (sid) {
|
|
1880
|
-
setResolvedSessionId(sid);
|
|
1881
|
-
}
|
|
1882
|
-
let publishableKey;
|
|
1883
|
-
if (realResult.provider === "stripe") {
|
|
1884
|
-
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1885
|
-
}
|
|
1886
|
-
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1887
|
-
if (!publishableKey) {
|
|
1888
|
-
throw new FloPayError3(
|
|
1889
|
-
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1890
|
-
"validation_error"
|
|
1891
|
-
);
|
|
1892
|
-
}
|
|
1893
|
-
const instance = await loadFloPay(publishableKey, {
|
|
1894
|
-
billingApiUrl: resolvedBillingUrl,
|
|
1895
|
-
locale
|
|
1896
|
-
});
|
|
1897
|
-
flopayRef.current = instance;
|
|
1898
|
-
setFloPay(instance);
|
|
1899
1870
|
initializedHashRef.current = cacheKey;
|
|
1900
|
-
|
|
1871
|
+
try {
|
|
1872
|
+
if (patch) {
|
|
1873
|
+
setCreateSessionPatchBaseHash(baseCreateSessionHash);
|
|
1874
|
+
setCreateSessionPatch((prev) => mergeInlineSessionPatches(prev, patch));
|
|
1875
|
+
}
|
|
1876
|
+
const { sid, result: realResult } = resolved;
|
|
1877
|
+
setUnified(realResult);
|
|
1878
|
+
if (realResult.data.session) {
|
|
1879
|
+
setSession(realResult.data.session);
|
|
1880
|
+
}
|
|
1881
|
+
if (sid) {
|
|
1882
|
+
setResolvedSessionId(sid);
|
|
1883
|
+
}
|
|
1884
|
+
let publishableKey;
|
|
1885
|
+
if (realResult.provider === "stripe") {
|
|
1886
|
+
publishableKey = realResult.data.stripe?.publishableKey;
|
|
1887
|
+
}
|
|
1888
|
+
if (!publishableKey) publishableKey = fallbackPublishableKey;
|
|
1889
|
+
if (!publishableKey) {
|
|
1890
|
+
throw new FloPayError3(
|
|
1891
|
+
"No publishable key found. Provide fallbackPublishableKey or ensure the session includes gatewayData.publishableKey.",
|
|
1892
|
+
"validation_error"
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
const instance = await loadFloPay(publishableKey, {
|
|
1896
|
+
billingApiUrl: resolvedBillingUrl,
|
|
1897
|
+
locale
|
|
1898
|
+
});
|
|
1899
|
+
flopayRef.current = instance;
|
|
1900
|
+
setFloPay(instance);
|
|
1901
|
+
setIsLoading(false);
|
|
1902
|
+
} catch (err) {
|
|
1903
|
+
if (initializedHashRef.current === cacheKey) {
|
|
1904
|
+
initializedHashRef.current = null;
|
|
1905
|
+
}
|
|
1906
|
+
throw err;
|
|
1907
|
+
}
|
|
1901
1908
|
return resolved;
|
|
1902
1909
|
},
|
|
1903
1910
|
[fallbackPublishableKey, locale, resolvedBillingUrl]
|
|
1904
1911
|
);
|
|
1905
|
-
const
|
|
1906
|
-
if (cardBootstrapPending) return;
|
|
1907
|
-
setLoadError(null);
|
|
1912
|
+
const handleInlineSessionPatch = useCallback2(async (patch) => {
|
|
1913
|
+
if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) return;
|
|
1908
1914
|
setCardBootstrapPending(true);
|
|
1909
1915
|
try {
|
|
1910
|
-
const beforeClickResult = await onBeforeButtonClick?.({
|
|
1911
|
-
method: "card",
|
|
1912
|
-
createSession: effectiveCreateSession
|
|
1913
|
-
});
|
|
1914
|
-
if (beforeClickResult === false) {
|
|
1915
|
-
setDeferredCardOpen(false);
|
|
1916
|
-
return;
|
|
1917
|
-
}
|
|
1918
|
-
const patch = beforeClickResult && typeof beforeClickResult === "object" ? beforeClickResult : void 0;
|
|
1919
|
-
const baseParams = createSessionParamsRef.current;
|
|
1920
|
-
if (!baseParams) {
|
|
1921
|
-
throw new FloPayError3(
|
|
1922
|
-
"createSession is required to bootstrap checkout.",
|
|
1923
|
-
"validation_error"
|
|
1924
|
-
);
|
|
1925
|
-
}
|
|
1926
|
-
ensureInlineSessionReady(mergeInlineSessionPatch(baseParams, patch));
|
|
1927
|
-
setDeferredCardOpen(true);
|
|
1928
|
-
onButtonClick?.("card");
|
|
1929
1916
|
await bootstrapInlineSession(patch);
|
|
1930
|
-
} catch (err) {
|
|
1931
|
-
setDeferredCardOpen(false);
|
|
1932
|
-
const floPayErr = err instanceof FloPayError3 ? err : new FloPayError3(
|
|
1933
|
-
err instanceof Error ? err.message : "Failed to start card checkout.",
|
|
1934
|
-
"api_error"
|
|
1935
|
-
);
|
|
1936
|
-
setLoadError(floPayErr);
|
|
1937
|
-
onErrorRef.current?.(floPayErr);
|
|
1938
1917
|
} finally {
|
|
1939
1918
|
setCardBootstrapPending(false);
|
|
1940
1919
|
}
|
|
1941
1920
|
}, [
|
|
1942
1921
|
bootstrapInlineSession,
|
|
1943
|
-
|
|
1944
|
-
cardBootstrapPending,
|
|
1945
|
-
effectiveCreateSession,
|
|
1946
|
-
onButtonClick,
|
|
1947
|
-
onBeforeButtonClick
|
|
1922
|
+
cardBootstrapPending
|
|
1948
1923
|
]);
|
|
1949
1924
|
useEffect4(() => {
|
|
1950
1925
|
let cancelled = false;
|
|
1951
1926
|
setLoadError(null);
|
|
1952
1927
|
if (createSessionHash) {
|
|
1953
|
-
if (deferInlineSessionUntilCardClick) {
|
|
1954
|
-
if (initializedHashRef.current !== createSessionHash) {
|
|
1955
|
-
setSession(null);
|
|
1956
|
-
setUnified(null);
|
|
1957
|
-
setFloPay(null);
|
|
1958
|
-
setResolvedSessionId("");
|
|
1959
|
-
setDeferredCardOpen(false);
|
|
1960
|
-
flopayRef.current = null;
|
|
1961
|
-
}
|
|
1962
|
-
setCurrentMode(createSessionParamsRef.current?.checkoutMode ?? checkoutModeProp ?? "full");
|
|
1963
|
-
setIsLoading(false);
|
|
1964
|
-
return () => {
|
|
1965
|
-
cancelled = true;
|
|
1966
|
-
};
|
|
1967
|
-
}
|
|
1968
1928
|
if (initializedHashRef.current === createSessionHash) return;
|
|
1969
1929
|
const params = createSessionParamsRef.current;
|
|
1970
1930
|
setSession(buildSyntheticSession(params, checkoutModeProp));
|
|
@@ -2060,7 +2020,7 @@ function FloPayCheckout({
|
|
|
2060
2020
|
return () => {
|
|
2061
2021
|
cancelled = true;
|
|
2062
2022
|
};
|
|
2063
|
-
}, [resolvedSessionId, createSessionHash, checkoutModeProp,
|
|
2023
|
+
}, [resolvedSessionId, createSessionHash, checkoutModeProp, bootstrapInlineSession]);
|
|
2064
2024
|
const handleConfirmCheckout = useCallback2(async () => {
|
|
2065
2025
|
if (confirmProcessing || !session) return;
|
|
2066
2026
|
setConfirmProcessing(true);
|
|
@@ -2103,17 +2063,29 @@ function FloPayCheckout({
|
|
|
2103
2063
|
}
|
|
2104
2064
|
return opts;
|
|
2105
2065
|
}, [unified, session, appearance, resolvedBillingUrl]);
|
|
2066
|
+
const shouldHandleInlineSessionPatch = Boolean(
|
|
2067
|
+
createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && (effectiveCreateSession?.checkoutMode ?? checkoutModeProp ?? "full") === "full"
|
|
2068
|
+
);
|
|
2106
2069
|
const checkoutValue = useMemo3(
|
|
2107
2070
|
() => ({
|
|
2108
2071
|
session,
|
|
2109
2072
|
loading: isLoading,
|
|
2110
2073
|
error: loadError,
|
|
2111
|
-
checkoutMode: currentMode
|
|
2074
|
+
checkoutMode: currentMode,
|
|
2075
|
+
applyInlineSessionPatch: shouldHandleInlineSessionPatch ? handleInlineSessionPatch : void 0,
|
|
2076
|
+
inlineSessionPatchProcessing: cardBootstrapPending
|
|
2112
2077
|
}),
|
|
2113
|
-
[
|
|
2078
|
+
[
|
|
2079
|
+
session,
|
|
2080
|
+
isLoading,
|
|
2081
|
+
loadError,
|
|
2082
|
+
currentMode,
|
|
2083
|
+
shouldHandleInlineSessionPatch,
|
|
2084
|
+
handleInlineSessionPatch,
|
|
2085
|
+
cardBootstrapPending
|
|
2086
|
+
]
|
|
2114
2087
|
);
|
|
2115
2088
|
const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && (!flopay || !providerOptions);
|
|
2116
|
-
const shouldKeepDeferredInterimVisible = shouldShowInterimButtons && deferInlineSessionUntilCardClick;
|
|
2117
2089
|
if (isLoading) {
|
|
2118
2090
|
if (loadingNode) return /* @__PURE__ */ jsx5(Fragment3, { children: loadingNode });
|
|
2119
2091
|
if (layout === "buttons") {
|
|
@@ -2142,7 +2114,7 @@ function FloPayCheckout({
|
|
|
2142
2114
|
/* @__PURE__ */ jsx5("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
2143
2115
|
] });
|
|
2144
2116
|
}
|
|
2145
|
-
if (loadError
|
|
2117
|
+
if (loadError) {
|
|
2146
2118
|
if (errorNode) return /* @__PURE__ */ jsx5(Fragment3, { children: errorNode(loadError) });
|
|
2147
2119
|
return /* @__PURE__ */ jsx5(
|
|
2148
2120
|
"div",
|
|
@@ -2162,13 +2134,9 @@ function FloPayCheckout({
|
|
|
2162
2134
|
InterimButtonsView,
|
|
2163
2135
|
{
|
|
2164
2136
|
onButtonClick,
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
errorMessage: shouldKeepDeferredInterimVisible ? loadError?.message ?? null : null,
|
|
2169
|
-
showPayPal: deferInlineSessionUntilCardClick ? false : showPayPal,
|
|
2170
|
-
showApplePay: deferInlineSessionUntilCardClick ? false : showApplePay,
|
|
2171
|
-
showGooglePay: deferInlineSessionUntilCardClick ? false : showGooglePay,
|
|
2137
|
+
showPayPal,
|
|
2138
|
+
showApplePay,
|
|
2139
|
+
showGooglePay,
|
|
2172
2140
|
buttonsTheme,
|
|
2173
2141
|
buttonsStyles,
|
|
2174
2142
|
cardButtonContent,
|
|
@@ -2269,7 +2237,6 @@ function FloPayCheckout({
|
|
|
2269
2237
|
enableAVS,
|
|
2270
2238
|
avsLayout,
|
|
2271
2239
|
country: session?.customer?.country,
|
|
2272
|
-
initialCardOpen: deferredCardOpen,
|
|
2273
2240
|
submitLabel,
|
|
2274
2241
|
className
|
|
2275
2242
|
}
|