@flopay/react 1.1.4 → 1.1.6

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/dist/index.cjs CHANGED
@@ -1284,6 +1284,14 @@ var FLOPAY_KEYFRAMES = `
1284
1284
  }
1285
1285
  `;
1286
1286
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
1287
+ var BUTTONS_PANEL_HIDDEN_STYLE = {
1288
+ visibility: "hidden",
1289
+ position: "absolute",
1290
+ pointerEvents: "none",
1291
+ width: "100%",
1292
+ height: 0,
1293
+ overflow: "hidden"
1294
+ };
1287
1295
  function getButtonMethodLabel(method) {
1288
1296
  switch (method) {
1289
1297
  case "paypal":
@@ -1759,12 +1767,14 @@ function SplitCardFormInner({
1759
1767
  showApplePay = true,
1760
1768
  showGooglePay = true,
1761
1769
  layout = "default",
1770
+ theme,
1762
1771
  buttonsTheme,
1763
1772
  buttonsStyles: buttonsStylesOverride,
1773
+ appearance: appearanceOverride,
1764
1774
  cardButtonContent,
1765
1775
  cardBackButtonContent,
1766
1776
  cardTitleContent,
1767
- showSecurityFooter = true,
1777
+ showSecurityFooter: _showSecurityFooter,
1768
1778
  onButtonClick,
1769
1779
  onBeforeButtonClick,
1770
1780
  enableAVS: enableAVSProp,
@@ -1839,8 +1849,9 @@ function SplitCardFormInner({
1839
1849
  }, [paypalDirectRetry]);
1840
1850
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
1841
1851
  const displayError = externalError ?? error;
1852
+ const themeBundle = (0, import_react8.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
1842
1853
  const bStyles = (0, import_react8.useMemo)(() => {
1843
- const base = (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
1854
+ const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
1844
1855
  if (!buttonsStylesOverride) return base;
1845
1856
  return {
1846
1857
  ...base,
@@ -1852,7 +1863,8 @@ function SplitCardFormInner({
1852
1863
  submitButton: { ...base.submitButton, ...buttonsStylesOverride.submitButton },
1853
1864
  title: { ...base.title, ...buttonsStylesOverride.title }
1854
1865
  };
1855
- }, [buttonsTheme, buttonsStylesOverride]);
1866
+ }, [themeBundle, buttonsTheme, buttonsStylesOverride]);
1867
+ const appearance = appearanceOverride ?? themeBundle?.appearance;
1856
1868
  const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
1857
1869
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
1858
1870
  const isSelfContained = !onTokenizedBody;
@@ -2380,17 +2392,24 @@ function SplitCardFormInner({
2380
2392
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
2381
2393
  }
2382
2394
  const isButtons = layout === "buttons";
2383
- const resolvedBorder = isButtons ? bStyles.cardInputBorder ?? "#e5e7eb" : "#A4A4FF";
2384
- const cardBg = isButtons ? bStyles.cardFormContainer?.backgroundColor ?? "white" : "#EDEDFF";
2385
- const cardInputBg = isButtons ? bStyles.cardInputBackground ?? "white" : "white";
2395
+ const appearanceVars = appearance?.variables;
2396
+ const SDK_DEFAULT_WHITES = /* @__PURE__ */ new Set(["#FFFFFF", "#ffffff", "#fff", "#FFF", "white"]);
2397
+ const appearanceColorBg = appearanceVars?.colorBackground;
2398
+ const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
2399
+ const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
2400
+ const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
2401
+ const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
2386
2402
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
2387
2403
  const hideTitle = isEmptySlotContent(cardTitleContent);
2388
- const nameInputOverrides = isButtons ? bStyles.nameInput : void 0;
2389
- const resolvedInputFontSize = bStyles.cardInputFontSize ?? toCssSize(nameInputOverrides?.fontSize) ?? "16px";
2390
- const resolvedInputFontFamily = typeof nameInputOverrides?.fontFamily === "string" ? nameInputOverrides.fontFamily : "Poppins, sans-serif";
2404
+ const nameInputOverrides = bStyles.nameInput;
2405
+ const resolvedInputFontSize = bStyles.cardInputFontSize ?? toCssSize(nameInputOverrides?.fontSize) ?? appearanceVars?.fontSizeBase ?? "16px";
2406
+ const resolvedInputFontFamily = typeof nameInputOverrides?.fontFamily === "string" ? nameInputOverrides.fontFamily : appearanceVars?.fontFamily ?? "Poppins, sans-serif";
2391
2407
  const resolvedInputFontWeight = toCssWeight(nameInputOverrides?.fontWeight) ?? 400;
2392
- const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? "#262833";
2408
+ const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
2393
2409
  const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
2410
+ const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
2411
+ const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
2412
+ const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
2394
2413
  const sharedInputTypography = {
2395
2414
  fontSize: resolvedInputFontSize,
2396
2415
  fontFamily: resolvedInputFontFamily,
@@ -2420,12 +2439,14 @@ function SplitCardFormInner({
2420
2439
  invalid: { color: "#ef4444" }
2421
2440
  }
2422
2441
  };
2442
+ const containerOverrides = bStyles.cardFormContainer ?? {};
2443
+ const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
2444
+ const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
2423
2445
  const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
2424
2446
  backgroundColor: cardBg,
2425
- borderRadius: "8px",
2426
- padding: isButtons ? "0" : "1rem",
2427
- ...isButtons ? bStyles.cardFormContainer : {},
2428
- ...isButtons ? { padding: bStyles.cardFormContainer?.padding ?? "0" } : {},
2447
+ borderRadius: containerRadius,
2448
+ ...containerOverrides,
2449
+ padding: containerPadding,
2429
2450
  ...sharedInputPlaceholderVars
2430
2451
  }, children: [
2431
2452
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
@@ -2489,7 +2510,14 @@ function SplitCardFormInner({
2489
2510
  ...bStyles.title
2490
2511
  }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) })
2491
2512
  ] }),
2492
- !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { textAlign: "center", fontWeight: 600, fontSize: "1.1rem", padding: "0.5rem 0", color: "#262833" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
2513
+ !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
2514
+ textAlign: "center",
2515
+ fontWeight: 600,
2516
+ fontSize: "1.1rem",
2517
+ padding: "0.5rem 0",
2518
+ color: resolvedTitleColor,
2519
+ ...bStyles.title
2520
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
2493
2521
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
2494
2522
  backgroundColor: cardInputBg,
2495
2523
  border: `1px solid ${resolvedBorder}`,
@@ -2746,7 +2774,7 @@ function SplitCardFormInner({
2746
2774
  display: "flex",
2747
2775
  alignItems: "center",
2748
2776
  gap: "0.5rem",
2749
- ...isButtons && bStyles.errorBanner ? bStyles.errorBanner : {}
2777
+ ...bStyles.errorBanner ? bStyles.errorBanner : {}
2750
2778
  }, children: [
2751
2779
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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" }) }),
2752
2780
  displayError
@@ -2761,29 +2789,19 @@ function SplitCardFormInner({
2761
2789
  width: "100%",
2762
2790
  padding: "0.875rem",
2763
2791
  marginTop: "1rem",
2764
- backgroundColor: "#4A49FF",
2792
+ backgroundColor: resolvedPrimaryColor,
2765
2793
  color: "white",
2766
2794
  border: "none",
2767
- borderRadius: "8px",
2768
- fontSize: isButtons && bStyles.submitButtonFontSize ? bStyles.submitButtonFontSize : "1rem",
2795
+ borderRadius: resolvedBorderRadius,
2796
+ fontSize: bStyles.submitButtonFontSize ?? "1rem",
2769
2797
  fontWeight: 600,
2770
2798
  cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
2771
2799
  opacity: !formReady || isSubmitting ? 0.5 : 1,
2772
- ...isButtons ? bStyles.submitButton : {}
2800
+ ...bStyles.submitButton
2773
2801
  },
2774
2802
  children: isSubmitting ? "PROCESSING..." : submitLabel
2775
2803
  }
2776
- ),
2777
- !isButtons && showSecurityFooter && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
2778
- backgroundColor: "#EFF9F0",
2779
- borderRadius: "8px",
2780
- padding: "0.75rem",
2781
- marginTop: "0.75rem",
2782
- textAlign: "center",
2783
- fontSize: "0.85rem",
2784
- fontWeight: 600,
2785
- color: "#7DAD3A"
2786
- }, children: "Secure Card Checkout" })
2804
+ )
2787
2805
  ] });
2788
2806
  if (layout === "buttons") {
2789
2807
  const isButtonsView = viewState === "buttons" || viewState === "expanding";
@@ -2795,173 +2813,181 @@ function SplitCardFormInner({
2795
2813
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayKeyframes, {}),
2796
2814
  overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
2797
2815
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "grid" }, children: [
2798
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
2799
- gridArea: "1 / 1",
2800
- display: "flex",
2801
- flexDirection: "column",
2802
- gap: "0.5rem",
2803
- // When card form is showing (and not transitioning), hide but keep mounted
2804
- ...!isButtonsView && !buttonsAnim ? { visibility: "hidden", position: "absolute", pointerEvents: "none", width: "100%" } : {},
2805
- ...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
2806
- }, children: [
2807
- debug && showPayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2808
- "pre",
2809
- {
2810
- "data-testid": "flopay-direct-paypal-gate-debug",
2811
- style: {
2812
- margin: 0,
2813
- padding: "6px 8px",
2814
- background: "#eef2ff",
2815
- border: "1px solid #c7d2fe",
2816
- borderRadius: 6,
2817
- color: "#111827",
2818
- font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
2819
- whiteSpace: "pre-wrap",
2820
- wordBreak: "break-word"
2821
- },
2822
- children: [
2823
- "FloPay/DirectPayPal-debug (parent gate)",
2824
- ` showPayPal=${showPayPal}`,
2825
- ` directPaypalConfigured=${directPaypalConfigured}`,
2826
- ` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
2827
- ` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
2828
- ` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
2829
- ` hasPaypalStripeInstance=${!!paypalStripeInstance}`
2830
- ].join("\n")
2831
- }
2832
- ),
2833
- shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2834
- paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2835
- "div",
2836
- {
2837
- "data-testid": "flopay-paypal-direct-retry-notice",
2838
- style: {
2839
- padding: "8px 10px",
2840
- background: "#fef3c7",
2841
- border: "1px solid #fcd34d",
2842
- borderRadius: 6,
2843
- color: "#78350f",
2844
- fontSize: 13,
2845
- lineHeight: 1.4
2846
- },
2847
- children: "Please confirm your PayPal payment to complete checkout."
2848
- }
2849
- ),
2850
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2851
- DirectPayPalButton,
2852
- {
2853
- sessionId,
2854
- billingApiUrl: resolvedBillingApiUrl,
2855
- email: resolvedAccount.email,
2856
- clientId: directPaypal.clientId,
2857
- environment: directPaypal.environment,
2858
- currency: currency.toUpperCase(),
2859
- isSubscription,
2860
- onTokenizedBody: dispatchTokenizedBody,
2861
- onComplete,
2862
- onErrorChange: updateError,
2863
- onDecline,
2864
- onButtonClick,
2865
- runBeforeButtonClick,
2866
- isProcessing: isSubmitting,
2867
- onLoadStateChange: setDirectPaypalReady,
2868
- session: session ?? null,
2869
- existingOrderId: paypalDirectRetry?.orderId,
2870
- debug
2871
- },
2872
- paypalDirectRetry?.orderId ?? "fresh"
2873
- )
2874
- ] }),
2875
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2876
- PayPalButtonInner,
2877
- {
2878
- sessionId,
2879
- email: resolvedAccount.email,
2880
- billingApiUrl: resolvedBillingApiUrl,
2881
- onTokenizedBody: dispatchTokenizedBody,
2882
- onErrorChange: updateError,
2883
- isProcessing: isSubmitting,
2884
- onButtonClick,
2885
- onDecline,
2886
- runBeforeButtonClick,
2887
- onLoadStateChange: setPaypalLoadState
2888
- }
2889
- ) }),
2890
- shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2891
- WalletButtonInner,
2892
- {
2893
- sessionId,
2894
- email: resolvedAccount.email,
2895
- billingApiUrl: resolvedBillingApiUrl,
2896
- showApplePay,
2897
- showGooglePay,
2898
- onTokenizedBody: dispatchTokenizedBody,
2899
- onErrorChange: updateError,
2900
- onButtonClick,
2901
- onDecline,
2902
- runBeforeButtonClick,
2903
- onLoadStateChange: setWalletLoadState
2904
- }
2905
- ) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
2906
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2907
- "button",
2908
- {
2909
- type: "button",
2910
- onClick: async () => {
2911
- if (isSubmitting) return;
2912
- const beforeClick = await runBeforeButtonClick("card");
2913
- if (!beforeClick.proceed) return;
2914
- onButtonClick?.("card");
2915
- expandToCard();
2916
- },
2917
- disabled: isSubmitting,
2918
- style: {
2919
- width: "100%",
2920
- ...cardButtonSizing,
2921
- backgroundColor: "white",
2922
- color: "#262833",
2923
- border: "1px solid #d1d5db",
2816
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2817
+ "div",
2818
+ {
2819
+ "data-testid": "flopay-buttons-panel",
2820
+ "aria-hidden": !isButtonsView && !buttonsAnim ? true : void 0,
2821
+ style: {
2822
+ gridArea: "1 / 1",
2823
+ display: "flex",
2824
+ flexDirection: "column",
2825
+ gap: "0.5rem",
2826
+ // When card form is showing (and not transitioning), hide but keep mounted.
2827
+ ...!isButtonsView && !buttonsAnim ? BUTTONS_PANEL_HIDDEN_STYLE : {},
2828
+ ...buttonsAnim ? { animation: buttonsAnim, pointerEvents: "none" } : {}
2829
+ },
2830
+ children: [
2831
+ debug && showPayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2832
+ "pre",
2833
+ {
2834
+ "data-testid": "flopay-direct-paypal-gate-debug",
2835
+ style: {
2836
+ margin: 0,
2837
+ padding: "6px 8px",
2838
+ background: "#eef2ff",
2839
+ border: "1px solid #c7d2fe",
2840
+ borderRadius: 6,
2841
+ color: "#111827",
2842
+ font: "11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace",
2843
+ whiteSpace: "pre-wrap",
2844
+ wordBreak: "break-word"
2845
+ },
2846
+ children: [
2847
+ "FloPay/DirectPayPal-debug (parent gate)",
2848
+ ` showPayPal=${showPayPal}`,
2849
+ ` directPaypalConfigured=${directPaypalConfigured}`,
2850
+ ` inAppBrowserDetected=${String(inAppBrowserDetected)}`,
2851
+ ` shouldRenderDirectPayPal=${shouldRenderDirectPayPal}`,
2852
+ ` shouldRenderStripePayPal=${shouldRenderStripePayPal}`,
2853
+ ` hasPaypalStripeInstance=${!!paypalStripeInstance}`
2854
+ ].join("\n")
2855
+ }
2856
+ ),
2857
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2858
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2859
+ "div",
2860
+ {
2861
+ "data-testid": "flopay-paypal-direct-retry-notice",
2862
+ style: {
2863
+ padding: "8px 10px",
2864
+ background: "#fef3c7",
2865
+ border: "1px solid #fcd34d",
2866
+ borderRadius: 6,
2867
+ color: "#78350f",
2868
+ fontSize: 13,
2869
+ lineHeight: 1.4
2870
+ },
2871
+ children: "Please confirm your PayPal payment to complete checkout."
2872
+ }
2873
+ ),
2874
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2875
+ DirectPayPalButton,
2876
+ {
2877
+ sessionId,
2878
+ billingApiUrl: resolvedBillingApiUrl,
2879
+ email: resolvedAccount.email,
2880
+ clientId: directPaypal.clientId,
2881
+ environment: directPaypal.environment,
2882
+ currency: currency.toUpperCase(),
2883
+ isSubscription,
2884
+ onTokenizedBody: dispatchTokenizedBody,
2885
+ onComplete,
2886
+ onErrorChange: updateError,
2887
+ onDecline,
2888
+ onButtonClick,
2889
+ runBeforeButtonClick,
2890
+ isProcessing: isSubmitting,
2891
+ onLoadStateChange: setDirectPaypalReady,
2892
+ session: session ?? null,
2893
+ existingOrderId: paypalDirectRetry?.orderId,
2894
+ debug
2895
+ },
2896
+ paypalDirectRetry?.orderId ?? "fresh"
2897
+ )
2898
+ ] }),
2899
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2900
+ PayPalButtonInner,
2901
+ {
2902
+ sessionId,
2903
+ email: resolvedAccount.email,
2904
+ billingApiUrl: resolvedBillingApiUrl,
2905
+ onTokenizedBody: dispatchTokenizedBody,
2906
+ onErrorChange: updateError,
2907
+ isProcessing: isSubmitting,
2908
+ onButtonClick,
2909
+ onDecline,
2910
+ runBeforeButtonClick,
2911
+ onLoadStateChange: setPaypalLoadState
2912
+ }
2913
+ ) }),
2914
+ shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2915
+ WalletButtonInner,
2916
+ {
2917
+ sessionId,
2918
+ email: resolvedAccount.email,
2919
+ billingApiUrl: resolvedBillingApiUrl,
2920
+ showApplePay,
2921
+ showGooglePay,
2922
+ onTokenizedBody: dispatchTokenizedBody,
2923
+ onErrorChange: updateError,
2924
+ onButtonClick,
2925
+ onDecline,
2926
+ runBeforeButtonClick,
2927
+ onLoadStateChange: setWalletLoadState
2928
+ }
2929
+ ) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: 8, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
2930
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2931
+ "button",
2932
+ {
2933
+ type: "button",
2934
+ onClick: async () => {
2935
+ if (isSubmitting) return;
2936
+ const beforeClick = await runBeforeButtonClick("card");
2937
+ if (!beforeClick.proceed) return;
2938
+ onButtonClick?.("card");
2939
+ expandToCard();
2940
+ },
2941
+ disabled: isSubmitting,
2942
+ style: {
2943
+ width: "100%",
2944
+ ...cardButtonSizing,
2945
+ backgroundColor: "white",
2946
+ color: "#262833",
2947
+ border: "1px solid #d1d5db",
2948
+ borderRadius: "8px",
2949
+ fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
2950
+ fontWeight: 600,
2951
+ cursor: isSubmitting ? "not-allowed" : "pointer",
2952
+ display: "flex",
2953
+ alignItems: "center",
2954
+ justifyContent: "center",
2955
+ gap: "0.625rem",
2956
+ transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
2957
+ boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
2958
+ position: "relative",
2959
+ opacity: isSubmitting ? 0.6 : 1,
2960
+ ...bStyles.cardButton
2961
+ },
2962
+ onMouseDown: (e) => {
2963
+ e.currentTarget.style.transform = "scale(0.985)";
2964
+ },
2965
+ onMouseUp: (e) => {
2966
+ e.currentTarget.style.transform = "scale(1)";
2967
+ },
2968
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
2969
+ }
2970
+ ),
2971
+ displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
2972
+ margin: "0.25rem 0",
2973
+ padding: "0.625rem 0.875rem",
2974
+ background: "#FEF2F2",
2975
+ border: "1px solid #FECACA",
2924
2976
  borderRadius: "8px",
2925
- fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
2977
+ color: "#991B1B",
2978
+ fontSize: "0.85rem",
2926
2979
  fontWeight: 600,
2927
- cursor: isSubmitting ? "not-allowed" : "pointer",
2928
2980
  display: "flex",
2929
2981
  alignItems: "center",
2930
- justifyContent: "center",
2931
- gap: "0.625rem",
2932
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
2933
- boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
2934
- position: "relative",
2935
- opacity: isSubmitting ? 0.6 : 1,
2936
- ...bStyles.cardButton
2937
- },
2938
- onMouseDown: (e) => {
2939
- e.currentTarget.style.transform = "scale(0.985)";
2940
- },
2941
- onMouseUp: (e) => {
2942
- e.currentTarget.style.transform = "scale(1)";
2943
- },
2944
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
2945
- }
2946
- ),
2947
- displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
2948
- margin: "0.25rem 0",
2949
- padding: "0.625rem 0.875rem",
2950
- background: "#FEF2F2",
2951
- border: "1px solid #FECACA",
2952
- borderRadius: "8px",
2953
- color: "#991B1B",
2954
- fontSize: "0.85rem",
2955
- fontWeight: 600,
2956
- display: "flex",
2957
- alignItems: "center",
2958
- gap: "0.5rem",
2959
- ...bStyles.errorBanner ? bStyles.errorBanner : {}
2960
- }, children: [
2961
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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" }) }),
2962
- displayError
2963
- ] })
2964
- ] }),
2982
+ gap: "0.5rem",
2983
+ ...bStyles.errorBanner ? bStyles.errorBanner : {}
2984
+ }, children: [
2985
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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" }) }),
2986
+ displayError
2987
+ ] })
2988
+ ]
2989
+ }
2990
+ ),
2965
2991
  isCardView && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
2966
2992
  gridArea: "1 / 1",
2967
2993
  ...cardAnim ? { animation: cardAnim } : {},
@@ -3300,105 +3326,6 @@ async function processSavedPaymentForMode({
3300
3326
  }
3301
3327
  );
3302
3328
  }
3303
- async function processSavedPaymentWithIntent({
3304
- billingApiUrl,
3305
- sessionId,
3306
- session,
3307
- paymentMethodId,
3308
- flopay,
3309
- returnUrl
3310
- }) {
3311
- const customerEmail = session.customer?.email ?? session.accountData?.email ?? "";
3312
- if (!customerEmail) {
3313
- throw Object.assign(
3314
- new import_shared7.FloPayError("Customer email is required to create a payment intent.", "validation_error", {
3315
- param: "email"
3316
- }),
3317
- { checkoutMethod: "card" }
3318
- );
3319
- }
3320
- const api = new import_js3.PaymentAPI(billingApiUrl);
3321
- const intentResponse = await retryOnceOnFetchFailure(() => api.createPaymentIntent(
3322
- sessionId,
3323
- customerEmail,
3324
- paymentMethodId
3325
- ));
3326
- const intentJson = await intentResponse.json().catch(() => null);
3327
- if (!intentResponse.ok) {
3328
- const intentError = buildFloPayApiError(
3329
- intentJson,
3330
- "Failed to create payment intent."
3331
- );
3332
- throw Object.assign(
3333
- intentError,
3334
- { checkoutMethod: "card" }
3335
- );
3336
- }
3337
- const intentClientSecret = getRedirectTokenFromProcessResponse(intentJson, {
3338
- requirePaymentIntentClientSecret: true
3339
- });
3340
- if (!intentClientSecret) {
3341
- throw Object.assign(
3342
- new import_shared7.FloPayError("No client secret in payment intent response.", "api_error"),
3343
- { checkoutMethod: "card" }
3344
- );
3345
- }
3346
- const confirmResult = await flopay.confirmCardPayment({
3347
- clientSecret: intentClientSecret,
3348
- paymentMethodId
3349
- });
3350
- if (confirmResult.error) {
3351
- throw Object.assign(
3352
- confirmResult.error,
3353
- { checkoutMethod: "card" }
3354
- );
3355
- }
3356
- const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3357
- const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3358
- rawProvider,
3359
- intentClientSecret
3360
- );
3361
- const confirmedPaymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3362
- const confirmedPaymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? paymentMethodId;
3363
- if (!confirmedPaymentIntentId || confirmResult.status !== "succeeded" && confirmResult.status !== "processing" && confirmResult.status !== "requires_capture") {
3364
- throw Object.assign(
3365
- new import_shared7.FloPayError(
3366
- `Unfortunately, your payment could not be processed. Please try again using a different payment method or contact your bank for assistance. If the issue persists, feel free to reach out to us for support.`,
3367
- "api_error",
3368
- {
3369
- code: confirmResult.status === "requires_action" ? "authentication_required" : void 0
3370
- }
3371
- ),
3372
- { checkoutMethod: "card" }
3373
- );
3374
- }
3375
- const followUp = await processSavedPaymentForMode({
3376
- billingApiUrl,
3377
- sessionId,
3378
- session,
3379
- tokenizedData: {
3380
- id: confirmedPaymentMethodId,
3381
- type: "card",
3382
- threeDSecureActionResultTokenId: confirmedPaymentIntentId
3383
- },
3384
- returnUrl
3385
- });
3386
- const finalResult = followUp.type === "success" ? followUp.result : await handleSavedPaymentRedirectResult(followUp, {
3387
- flopay,
3388
- paypalFlopay: null,
3389
- attempt3DS: true,
3390
- billingApiUrl,
3391
- sessionId,
3392
- session,
3393
- returnUrl
3394
- });
3395
- return {
3396
- ...finalResult,
3397
- paymentIntentId: finalResult.paymentIntentId ?? confirmedPaymentIntentId,
3398
- paymentMethodId: finalResult.paymentMethodId ?? confirmedPaymentMethodId,
3399
- checkoutMethod: finalResult.checkoutMethod ?? "card"
3400
- };
3401
- }
3402
3329
  async function handleSavedPaymentRedirectResult(redirectResult, {
3403
3330
  flopay,
3404
3331
  paypalFlopay,
@@ -3720,7 +3647,7 @@ function FloPayCheckout({
3720
3647
  sessionId: sessionIdProp,
3721
3648
  createSession: createSessionParams,
3722
3649
  billingApiUrl,
3723
- appearance,
3650
+ appearance: appearanceOverride,
3724
3651
  locale,
3725
3652
  loading: loadingNode,
3726
3653
  error: errorNode,
@@ -3735,12 +3662,13 @@ function FloPayCheckout({
3735
3662
  showGooglePay = true,
3736
3663
  debug = false,
3737
3664
  layout,
3665
+ theme,
3738
3666
  buttonsTheme,
3739
3667
  buttonsStyles,
3740
3668
  cardButtonContent,
3741
3669
  cardBackButtonContent,
3742
3670
  cardTitleContent,
3743
- showSecurityFooter = true,
3671
+ showSecurityFooter: _showSecurityFooter,
3744
3672
  onButtonClick,
3745
3673
  onBeforeButtonClick,
3746
3674
  enableAVS,
@@ -3755,6 +3683,8 @@ function FloPayCheckout({
3755
3683
  onSessionCompleted
3756
3684
  }) {
3757
3685
  const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
3686
+ const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
3687
+ const appearance = appearanceOverride ?? themeBundle?.appearance;
3758
3688
  const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
3759
3689
  const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
3760
3690
  const [unified, setUnified] = (0, import_react9.useState)(null);
@@ -4517,6 +4447,7 @@ function FloPayCheckout({
4517
4447
  showPayPal,
4518
4448
  showApplePay,
4519
4449
  showGooglePay,
4450
+ theme,
4520
4451
  buttonsTheme,
4521
4452
  buttonsStyles,
4522
4453
  cardButtonContent,
@@ -4661,12 +4592,13 @@ function FloPayCheckout({
4661
4592
  showApplePay,
4662
4593
  showGooglePay,
4663
4594
  layout,
4595
+ theme,
4664
4596
  buttonsTheme,
4665
4597
  buttonsStyles,
4598
+ appearance,
4666
4599
  cardButtonContent,
4667
4600
  cardBackButtonContent,
4668
4601
  cardTitleContent,
4669
- showSecurityFooter,
4670
4602
  onButtonClick,
4671
4603
  onBeforeButtonClick,
4672
4604
  enableAVS,
@@ -4723,6 +4655,7 @@ function InterimButtonsView({
4723
4655
  showPayPal,
4724
4656
  showApplePay,
4725
4657
  showGooglePay,
4658
+ theme,
4726
4659
  buttonsTheme,
4727
4660
  buttonsStyles: stylesOverride,
4728
4661
  cardButtonContent,
@@ -4736,8 +4669,9 @@ function InterimButtonsView({
4736
4669
  setShowCardForm(cardOpen);
4737
4670
  }
4738
4671
  }, [cardOpen, isCardOpenControlled]);
4672
+ const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
4739
4673
  const bStyles = (0, import_react9.useMemo)(() => {
4740
- const base = (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
4674
+ const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
4741
4675
  if (!stylesOverride) return base;
4742
4676
  return {
4743
4677
  ...base,
@@ -4749,7 +4683,7 @@ function InterimButtonsView({
4749
4683
  submitButton: { ...base.submitButton, ...stylesOverride.submitButton },
4750
4684
  title: { ...base.title, ...stylesOverride.title }
4751
4685
  };
4752
- }, [buttonsTheme, stylesOverride]);
4686
+ }, [themeBundle, buttonsTheme, stylesOverride]);
4753
4687
  const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4754
4688
  height: h,
4755
4689
  borderRadius: 8,
@@ -5448,7 +5382,6 @@ var import_js7 = require("@flopay/js");
5448
5382
  var import_shared11 = require("@flopay/shared");
5449
5383
  var import_jsx_runtime10 = require("react/jsx-runtime");
5450
5384
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
5451
- var PAYPAL_RESUME_STORAGE_KEY2 = "flopay_automatic_payment_button_resume";
5452
5385
  function sleep2(ms) {
5453
5386
  return new Promise((resolve) => setTimeout(resolve, ms));
5454
5387
  }
@@ -5461,9 +5394,6 @@ function coerceError(err, fallbackMessage) {
5461
5394
  "api_error"
5462
5395
  );
5463
5396
  }
5464
- function canUseStorage2() {
5465
- return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
5466
- }
5467
5397
  function shouldShowFallbackCheckout(error, sessionId) {
5468
5398
  if (!sessionId) return false;
5469
5399
  if (error.type === "validation_error") return false;
@@ -5472,47 +5402,6 @@ function shouldShowFallbackCheckout(error, sessionId) {
5472
5402
  }
5473
5403
  return true;
5474
5404
  }
5475
- function readPayPalResumeState2() {
5476
- if (!canUseStorage2()) return null;
5477
- try {
5478
- const raw = window.sessionStorage.getItem(PAYPAL_RESUME_STORAGE_KEY2);
5479
- if (!raw) return null;
5480
- return JSON.parse(raw);
5481
- } catch {
5482
- return null;
5483
- }
5484
- }
5485
- function persistPayPalResumeState2(state) {
5486
- if (!canUseStorage2()) return;
5487
- try {
5488
- window.sessionStorage.setItem(PAYPAL_RESUME_STORAGE_KEY2, JSON.stringify(state));
5489
- } catch (error) {
5490
- console.warn("[FloPayAutomaticPaymentButton] Failed to persist PayPal resume state.", error);
5491
- }
5492
- }
5493
- function clearPayPalResumeState2() {
5494
- if (!canUseStorage2()) return;
5495
- try {
5496
- window.sessionStorage.removeItem(PAYPAL_RESUME_STORAGE_KEY2);
5497
- } catch (error) {
5498
- console.warn("[FloPayAutomaticPaymentButton] Failed to clear PayPal resume state.", error);
5499
- }
5500
- }
5501
- function clearPayPalRedirectParams2() {
5502
- if (typeof window === "undefined") return;
5503
- const url = new URL(window.location.href);
5504
- const keys = ["payment_intent", "payment_intent_client_secret", "redirect_status"];
5505
- let changed = false;
5506
- for (const key of keys) {
5507
- if (url.searchParams.has(key)) {
5508
- url.searchParams.delete(key);
5509
- changed = true;
5510
- }
5511
- }
5512
- if (changed) {
5513
- window.history.replaceState({}, "", url.toString());
5514
- }
5515
- }
5516
5405
  function resolveCreateSessionDraft(props) {
5517
5406
  if (props.createSession) {
5518
5407
  return {
@@ -5539,8 +5428,10 @@ function resolveCreateSessionDraft(props) {
5539
5428
  function FloPayAutomaticPaymentButton({
5540
5429
  sessionId,
5541
5430
  createSession,
5542
- paymentMethodId,
5543
- checkoutMethod,
5431
+ // Deprecated — accepted for back-compat and silently ignored. Backend
5432
+ // resolves the customer's latest payment method server-side.
5433
+ paymentMethodId: _deprecatedPaymentMethodId,
5434
+ checkoutMethod: _deprecatedCheckoutMethod,
5544
5435
  clientId,
5545
5436
  items,
5546
5437
  subscriptions,
@@ -5552,6 +5443,7 @@ function FloPayAutomaticPaymentButton({
5552
5443
  utmMetadata,
5553
5444
  billingApiUrl,
5554
5445
  locale,
5446
+ theme,
5555
5447
  buttonsTheme,
5556
5448
  buttonsStyles: stylesOverride,
5557
5449
  onSuccess,
@@ -5597,20 +5489,7 @@ function FloPayAutomaticPaymentButton({
5597
5489
  const [overlayStatus, setOverlayStatus] = (0, import_react12.useState)(null);
5598
5490
  const [overlayError, setOverlayError] = (0, import_react12.useState)(null);
5599
5491
  const [fallbackSession, setFallbackSession] = (0, import_react12.useState)(null);
5600
- const automaticPaymentToken = (0, import_react12.useMemo)(
5601
- () => paymentMethodId ? {
5602
- id: paymentMethodId,
5603
- // Saved PayPal `user_payment_method` records are submitted with
5604
- // `type: 'paypal'` so the backend routes the upsell through the
5605
- // direct PayPal gateway's vaulted-token flow. Card and wallet PMs
5606
- // continue to use `type: 'card'`.
5607
- type: checkoutMethod === "paypal" ? "paypal" : "card",
5608
- ...checkoutMethod === "paypal" ? { isPaypal: true } : {}
5609
- } : void 0,
5610
- [checkoutMethod, paymentMethodId]
5611
- );
5612
5492
  const isMountedRef = (0, import_react12.useRef)(true);
5613
- const resumeAttemptedRef = (0, import_react12.useRef)(false);
5614
5493
  const fallbackSessionRef = (0, import_react12.useRef)(fallbackSession);
5615
5494
  const onSuccessRef = (0, import_react12.useRef)(onSuccess);
5616
5495
  const onErrorRef = (0, import_react12.useRef)(onError);
@@ -5691,10 +5570,6 @@ function FloPayAutomaticPaymentButton({
5691
5570
  });
5692
5571
  }
5693
5572
  try {
5694
- let paymentResult = null;
5695
- const redirectResult = getRedirectResultFromCheckoutProcessError(apiResult.autoProcessingError);
5696
- const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && (apiResult.autoProcessingAttempted === true || !!apiResult.autoProcessingError || !!redirectResult);
5697
- const shouldRetryPayPalClientSide = checkoutMethod === "paypal" && automaticPaymentToken?.isPaypal === true && options?.fromCreateSession === true;
5698
5573
  if (apiResult.autoProcessingPending) {
5699
5574
  const api = new import_js7.PaymentAPI(resolvedBillingUrl);
5700
5575
  const completed = await api.waitForCheckoutSessionCompletion(apiResult.autoProcessingPending.sessionId, {
@@ -5707,50 +5582,14 @@ function FloPayAutomaticPaymentButton({
5707
5582
  });
5708
5583
  }
5709
5584
  await showSuccess({
5710
- result: {
5711
- status: "succeeded",
5712
- paymentMethodId: paymentMethodId ?? void 0,
5713
- checkoutMethod
5714
- },
5585
+ result: { status: "succeeded" },
5715
5586
  session: completedSession,
5716
5587
  sessionId: completedSession.id || resolvedSessionId,
5717
5588
  autoCompleted: false
5718
5589
  });
5719
5590
  return;
5720
5591
  }
5721
- if (redirectResult) {
5722
- const {
5723
- publishableKey,
5724
- paypalPublishableKey
5725
- } = resolveSavedPaymentPublishableKeys(apiResult);
5726
- if (redirectResult.type === "paypal_redirect_required" && publishableKey) {
5727
- persistPayPalResumeState2({
5728
- sessionId: session.id || resolvedSessionId,
5729
- publishableKey,
5730
- paypalPublishableKey
5731
- });
5732
- }
5733
- const {
5734
- flopay,
5735
- paypalFlopay
5736
- } = await loadSavedPaymentProviders({
5737
- publishableKey,
5738
- paypalPublishableKey,
5739
- billingApiUrl: resolvedBillingUrl,
5740
- locale
5741
- });
5742
- paymentResult = await handleSavedPaymentRedirectResult(redirectResult, {
5743
- flopay,
5744
- paypalFlopay,
5745
- attempt3DS: true,
5746
- billingApiUrl: resolvedBillingUrl,
5747
- sessionId: session.id || resolvedSessionId,
5748
- session
5749
- });
5750
- if (redirectResult.type === "paypal_redirect_required") {
5751
- clearPayPalResumeState2();
5752
- }
5753
- } else if (apiResult.autoProcessingError && !shouldRetryPayPalClientSide) {
5592
+ if (apiResult.autoProcessingError) {
5754
5593
  throw checkoutProcessErrorToFloPayError(
5755
5594
  apiResult.autoProcessingError,
5756
5595
  "Automatic payment failed. Please try again.",
@@ -5758,7 +5597,22 @@ function FloPayAutomaticPaymentButton({
5758
5597
  checkoutMethod: apiResult.autoProcessingError.checkoutMethod
5759
5598
  }
5760
5599
  );
5761
- } else if (shouldTreatCreateSessionFlowAsServerAutoAttempt && !shouldRetryPayPalClientSide) {
5600
+ }
5601
+ if (options?.fromCreateSession && apiResult.autoProcessingAttempted === true) {
5602
+ throw checkoutProcessErrorToFloPayError(
5603
+ {
5604
+ type: "unknown",
5605
+ message: "Automatic payment failed. Please try again."
5606
+ },
5607
+ "Automatic payment failed. Please try again."
5608
+ );
5609
+ }
5610
+ const result = await processSavedPaymentForMode({
5611
+ billingApiUrl: resolvedBillingUrl,
5612
+ sessionId: resolvedSessionId ?? session.id,
5613
+ session
5614
+ });
5615
+ if (result.type !== "success") {
5762
5616
  throw checkoutProcessErrorToFloPayError(
5763
5617
  {
5764
5618
  type: "unknown",
@@ -5766,121 +5620,16 @@ function FloPayAutomaticPaymentButton({
5766
5620
  },
5767
5621
  "Automatic payment failed. Please try again."
5768
5622
  );
5769
- } else {
5770
- const result = await processSavedPaymentForMode({
5771
- billingApiUrl: resolvedBillingUrl,
5772
- sessionId: resolvedSessionId ?? session.id,
5773
- session,
5774
- tokenizedData: automaticPaymentToken
5775
- });
5776
- paymentResult = result.type === "success" ? result.result : null;
5777
- if (result.type !== "success") {
5778
- const {
5779
- publishableKey,
5780
- paypalPublishableKey
5781
- } = resolveSavedPaymentPublishableKeys(apiResult);
5782
- if (result.type === "paypal_redirect_required" && publishableKey) {
5783
- persistPayPalResumeState2({
5784
- sessionId: session.id || resolvedSessionId,
5785
- publishableKey,
5786
- paypalPublishableKey
5787
- });
5788
- }
5789
- const {
5790
- flopay,
5791
- paypalFlopay
5792
- } = await loadSavedPaymentProviders({
5793
- publishableKey,
5794
- paypalPublishableKey,
5795
- billingApiUrl: resolvedBillingUrl,
5796
- locale
5797
- });
5798
- paymentResult = await handleSavedPaymentRedirectResult(result, {
5799
- flopay,
5800
- paypalFlopay,
5801
- attempt3DS: true,
5802
- billingApiUrl: resolvedBillingUrl,
5803
- sessionId: session.id || resolvedSessionId,
5804
- session
5805
- });
5806
- if (result.type === "paypal_redirect_required") {
5807
- clearPayPalResumeState2();
5808
- }
5809
- }
5810
5623
  }
5811
5624
  await showSuccess({
5812
- result: paymentResult ? {
5813
- ...paymentResult,
5814
- paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId,
5815
- checkoutMethod: paymentResult.checkoutMethod ?? checkoutMethod
5816
- } : {
5817
- status: "succeeded",
5818
- paymentMethodId: paymentMethodId ?? void 0,
5819
- checkoutMethod
5820
- },
5625
+ result: result.result,
5821
5626
  session,
5822
5627
  sessionId: session.id || resolvedSessionId,
5823
5628
  autoCompleted: false
5824
5629
  });
5825
5630
  } catch (err) {
5826
- let floPayErr = normalizeSavedPaymentError(err);
5631
+ const floPayErr = normalizeSavedPaymentError(err);
5827
5632
  const fallbackSessionId = session.id || resolvedSessionId;
5828
- const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && apiResult.autoProcessingAttempted === true;
5829
- if (!shouldTreatCreateSessionFlowAsServerAutoAttempt && floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
5830
- try {
5831
- const {
5832
- publishableKey,
5833
- paypalPublishableKey
5834
- } = resolveSavedPaymentPublishableKeys(apiResult);
5835
- const {
5836
- flopay
5837
- } = await loadSavedPaymentProviders({
5838
- publishableKey,
5839
- paypalPublishableKey,
5840
- billingApiUrl: resolvedBillingUrl,
5841
- locale
5842
- });
5843
- if (!flopay) {
5844
- throw new import_shared11.FloPayError(
5845
- "Stripe is not available for 3DS authentication.",
5846
- "api_error",
5847
- { code: "authentication_required" }
5848
- );
5849
- }
5850
- const paymentResult = await processSavedPaymentWithIntent({
5851
- billingApiUrl: resolvedBillingUrl,
5852
- sessionId: fallbackSessionId,
5853
- session,
5854
- paymentMethodId: automaticPaymentToken.id,
5855
- flopay
5856
- });
5857
- await showSuccess({
5858
- result: {
5859
- ...paymentResult,
5860
- paymentMethodId: paymentResult.paymentMethodId ?? paymentMethodId,
5861
- checkoutMethod: paymentResult.checkoutMethod ?? checkoutMethod
5862
- },
5863
- session,
5864
- sessionId: fallbackSessionId,
5865
- autoCompleted: false
5866
- });
5867
- return;
5868
- } catch (intentRecoveryErr) {
5869
- floPayErr = normalizeSavedPaymentError(intentRecoveryErr);
5870
- }
5871
- }
5872
- const inResumeWindow = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent_client_secret") && !!readPayPalResumeState2();
5873
- if (floPayErr.code === "payment_intent_unexpected_state" && inResumeWindow) {
5874
- return;
5875
- }
5876
- const isSilentFallbackCase = (floPayErr.code === "paypal_requires_user_interaction" || floPayErr.code === "payment_intent_unexpected_state") && shouldShowFallbackCheckout(floPayErr, fallbackSessionId) && !!fallbackSessionId && isMountedRef.current;
5877
- if (isSilentFallbackCase) {
5878
- setFallbackSession({
5879
- sessionId: fallbackSessionId,
5880
- errorMessage: ""
5881
- });
5882
- return;
5883
- }
5884
5633
  await showError(floPayErr, {
5885
5634
  emitDecline: true,
5886
5635
  method: floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD
@@ -5893,10 +5642,6 @@ function FloPayAutomaticPaymentButton({
5893
5642
  }
5894
5643
  }
5895
5644
  }, [
5896
- checkoutMethod,
5897
- locale,
5898
- automaticPaymentToken,
5899
- paymentMethodId,
5900
5645
  resolvedBillingUrl,
5901
5646
  showError,
5902
5647
  showSuccess
@@ -5943,8 +5688,7 @@ function FloPayAutomaticPaymentButton({
5943
5688
  }
5944
5689
  try {
5945
5690
  const result = await api.createAndFetchSession({
5946
- ...createSessionDraft,
5947
- ...automaticPaymentToken ? { tokenizedData: automaticPaymentToken } : {}
5691
+ ...createSessionDraft
5948
5692
  });
5949
5693
  await processResolvedSession(result, result.data.session?.id ?? null, {
5950
5694
  fromCreateSession: true
@@ -5999,146 +5743,16 @@ function FloPayAutomaticPaymentButton({
5999
5743
  const handleFallbackDecline = (0, import_react12.useCallback)((decline) => {
6000
5744
  onDeclineRef.current?.(decline);
6001
5745
  }, []);
6002
- (0, import_react12.useEffect)(() => {
6003
- if (typeof window === "undefined" || resumeAttemptedRef.current) {
6004
- return;
6005
- }
6006
- const params = new URLSearchParams(window.location.search);
6007
- const clientSecret = params.get("payment_intent_client_secret");
6008
- if (!clientSecret) {
6009
- return;
6010
- }
6011
- const resumeState = readPayPalResumeState2();
6012
- if (!resumeState) {
6013
- return;
6014
- }
6015
- resumeAttemptedRef.current = true;
6016
- void (async () => {
6017
- setIsProcessing(true);
6018
- setOverlayError(null);
6019
- setOverlayStatus("processing");
6020
- try {
6021
- if (params.get("redirect_status") === "failed") {
6022
- throw Object.assign(
6023
- new import_shared11.FloPayError("PayPal payment was declined. Please try again.", "api_error"),
6024
- { checkoutMethod: "paypal" }
6025
- );
6026
- }
6027
- const {
6028
- flopay,
6029
- paypalFlopay
6030
- } = await loadSavedPaymentProviders({
6031
- publishableKey: resumeState.publishableKey,
6032
- paypalPublishableKey: resumeState.paypalPublishableKey,
6033
- billingApiUrl: resolvedBillingUrl,
6034
- locale
6035
- });
6036
- const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
6037
- if (!paypalStripe) {
6038
- throw Object.assign(
6039
- new import_shared11.FloPayError("PayPal is not available.", "api_error"),
6040
- { checkoutMethod: "paypal" }
6041
- );
6042
- }
6043
- const { paymentIntent, error } = await paypalStripe.retrievePaymentIntent(clientSecret);
6044
- if (error) {
6045
- throw Object.assign(
6046
- new import_shared11.FloPayError(
6047
- error.message ?? "Failed to retrieve PayPal payment status.",
6048
- "api_error",
6049
- { code: error.code }
6050
- ),
6051
- { checkoutMethod: "paypal" }
6052
- );
6053
- }
6054
- const resultStatus = mapPayPalIntentStatusToPaymentResult(paymentIntent?.status);
6055
- if (!paymentIntent || resultStatus === "failed") {
6056
- throw Object.assign(
6057
- new import_shared11.FloPayError("PayPal payment was not completed. Please try again.", "api_error"),
6058
- { checkoutMethod: "paypal" }
6059
- );
6060
- }
6061
- const paymentMethodId2 = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
6062
- if (!resumeState.sessionId) {
6063
- throw Object.assign(
6064
- new import_shared11.FloPayError("Missing session id on PayPal resume.", "api_error"),
6065
- { checkoutMethod: "paypal" }
6066
- );
6067
- }
6068
- const api = new import_js7.PaymentAPI(resolvedBillingUrl);
6069
- const sessionResult = await api.getUnifiedCheckoutSession(resumeState.sessionId);
6070
- let resumeSession = sessionResult.data.session;
6071
- if (!resumeSession) {
6072
- throw Object.assign(
6073
- new import_shared11.FloPayError("Could not load session to capture PayPal payment.", "api_error"),
6074
- { checkoutMethod: "paypal" }
6075
- );
6076
- }
6077
- let finalResultStatus = resultStatus;
6078
- if (resumeSession.status !== "complete") {
6079
- const processResult = await processSavedPaymentForMode({
6080
- billingApiUrl: resolvedBillingUrl,
6081
- sessionId: resumeState.sessionId,
6082
- session: resumeSession,
6083
- tokenizedData: {
6084
- id: paymentMethodId2 ?? paymentIntent.id,
6085
- type: "card",
6086
- threeDSecureActionResultTokenId: paymentIntent.id,
6087
- isPaypal: true
6088
- }
6089
- });
6090
- if (processResult.type !== "success") {
6091
- throw Object.assign(
6092
- new import_shared11.FloPayError("Failed to finalize PayPal payment.", "api_error"),
6093
- { checkoutMethod: "paypal" }
6094
- );
6095
- }
6096
- finalResultStatus = processResult.result.status;
6097
- try {
6098
- const refreshed = await api.getUnifiedCheckoutSession(resumeState.sessionId);
6099
- if (refreshed.data.session) {
6100
- resumeSession = refreshed.data.session;
6101
- }
6102
- } catch {
6103
- }
6104
- }
6105
- await showSuccess({
6106
- result: {
6107
- status: finalResultStatus,
6108
- paymentIntentId: paymentIntent.id,
6109
- paymentMethodId: paymentMethodId2,
6110
- checkoutMethod: "paypal"
6111
- },
6112
- session: resumeSession,
6113
- sessionId: resumeState.sessionId,
6114
- autoCompleted: false
6115
- });
6116
- } catch (err) {
6117
- const floPayErr = normalizeSavedPaymentError(err);
6118
- await showError(floPayErr, {
6119
- emitDecline: true,
6120
- method: floPayErr.checkoutMethod ?? "paypal"
6121
- });
6122
- } finally {
6123
- clearPayPalResumeState2();
6124
- clearPayPalRedirectParams2();
6125
- if (isMountedRef.current) {
6126
- setOverlayStatus(null);
6127
- setOverlayError(null);
6128
- setIsProcessing(false);
6129
- }
6130
- }
6131
- })();
6132
- }, [locale, resolvedBillingUrl, showError, showSuccess]);
5746
+ const themeBundle = (0, import_react12.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
6133
5747
  const bStyles = (0, import_react12.useMemo)(() => {
6134
- const base = (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
5748
+ const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
6135
5749
  if (!stylesOverride) return base;
6136
5750
  return {
6137
5751
  ...base,
6138
5752
  ...stylesOverride,
6139
5753
  cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
6140
5754
  };
6141
- }, [buttonsTheme, stylesOverride]);
5755
+ }, [themeBundle, buttonsTheme, stylesOverride]);
6142
5756
  const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
6143
5757
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
6144
5758
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -6235,9 +5849,12 @@ function FloPayAutomaticPaymentButton({
6235
5849
  sessionId: fallbackSession.sessionId,
6236
5850
  checkoutMode: "full",
6237
5851
  billingApiUrl: resolvedBillingUrl,
5852
+ locale,
5853
+ theme,
5854
+ buttonsTheme,
5855
+ buttonsStyles: stylesOverride,
6238
5856
  initialErrorMessage: fallbackSession.errorMessage,
6239
5857
  cardTitleContent: null,
6240
- showSecurityFooter: false,
6241
5858
  onComplete: handleFallbackComplete,
6242
5859
  onError: handleFallbackError,
6243
5860
  onDecline: handleFallbackDecline