@flopay/react 1.2.7 → 1.3.0

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.mjs CHANGED
@@ -100,7 +100,7 @@ function FloPayProvider({
100
100
  }
101
101
 
102
102
  // src/flopay-checkout.tsx
103
- import React7, { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef4, useState as useState4 } from "react";
103
+ import React8, { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5, useState as useState4 } from "react";
104
104
  import { PaymentAPI as PaymentAPI4 } from "@flopay/js";
105
105
  import { SDK_VERSION, FloPayError as FloPayError5, resolveBillingApiUrl as resolveBillingApiUrl3, buildCheckoutDisplayData, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme2, resolveTheme as resolveTheme2 } from "@flopay/shared";
106
106
 
@@ -248,9 +248,7 @@ import {
248
248
  resolveAVSConfig,
249
249
  isAVSFieldVisible,
250
250
  getStateFromPostalCode,
251
- filterStripeMethodsByCurrency,
252
251
  filterStripeMethodsByCountry,
253
- filterStripeMethodsByAmount,
254
252
  getStripeMethodDisplayName,
255
253
  hasVendoredStripeMethodLogo,
256
254
  needsStripeMethodExplicitConfirm,
@@ -259,7 +257,80 @@ import {
259
257
  stripeExpressMethodToOptionKey
260
258
  } from "@flopay/shared";
261
259
  import { PaymentAPI as PaymentAPI2 } from "@flopay/js";
262
- import React6, { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
260
+
261
+ // src/vault-card-fields.tsx
262
+ import { useEffect as useEffect3, useRef as useRef2 } from "react";
263
+ import { jsx as jsx4 } from "react/jsx-runtime";
264
+ function VaultCardFields({
265
+ capture,
266
+ html,
267
+ messageToken,
268
+ expectedOrigin,
269
+ theme,
270
+ containerStyle,
271
+ onReady,
272
+ onError,
273
+ onValidation
274
+ }) {
275
+ const containerRef = useRef2(null);
276
+ const onReadyRef = useRef2(onReady);
277
+ const onErrorRef = useRef2(onError);
278
+ const onValidationRef = useRef2(onValidation);
279
+ onReadyRef.current = onReady;
280
+ onErrorRef.current = onError;
281
+ onValidationRef.current = onValidation;
282
+ const themeRef = useRef2(theme);
283
+ themeRef.current = theme;
284
+ useEffect3(() => {
285
+ const el = containerRef.current;
286
+ if (!el) return;
287
+ let active = true;
288
+ let readyEmitted = false;
289
+ const emitReadyOnce = () => {
290
+ if (!active || readyEmitted) return;
291
+ readyEmitted = true;
292
+ onReadyRef.current?.();
293
+ };
294
+ const offReady = capture.on("ready", () => {
295
+ emitReadyOnce();
296
+ });
297
+ const offError = capture.on("error", (event) => {
298
+ onErrorRef.current?.(event.message ?? "There was a problem loading the secure card form.");
299
+ });
300
+ const offValidation = capture.on("validation", (event) => {
301
+ onValidationRef.current?.(event.message ?? null);
302
+ });
303
+ const mountOptions = {
304
+ html,
305
+ ...messageToken ? { messageToken } : {},
306
+ ...expectedOrigin ? { expectedOrigin } : {},
307
+ ...themeRef.current ? { theme: themeRef.current } : {}
308
+ };
309
+ capture.mount(el, mountOptions).then(() => {
310
+ emitReadyOnce();
311
+ }).catch((err) => {
312
+ if (active) {
313
+ onErrorRef.current?.(
314
+ err instanceof Error ? err.message : "Failed to load the secure card form."
315
+ );
316
+ }
317
+ });
318
+ return () => {
319
+ active = false;
320
+ offReady();
321
+ offError();
322
+ offValidation();
323
+ capture.unmount();
324
+ };
325
+ }, [capture, html, messageToken, expectedOrigin]);
326
+ useEffect3(() => {
327
+ if (theme) capture.applyTheme?.(theme);
328
+ }, [capture, theme]);
329
+ return /* @__PURE__ */ jsx4("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
330
+ }
331
+
332
+ // src/split-card-form.tsx
333
+ import React7, { forwardRef, useCallback, useContext as useContext3, useEffect as useEffect5, useImperativeHandle, useMemo as useMemo3, useRef as useRef4, useState as useState3 } from "react";
263
334
 
264
335
  // src/hooks.ts
265
336
  import { useContext as useContext2 } from "react";
@@ -286,14 +357,14 @@ function useBillingApiUrl() {
286
357
 
287
358
  // src/processing-overlay.tsx
288
359
  import "react";
289
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
360
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
290
361
  var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
291
362
  var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
292
363
  function ProcessingOverlay({
293
364
  status,
294
365
  errorMessage
295
366
  }) {
296
- return /* @__PURE__ */ jsx4(
367
+ return /* @__PURE__ */ jsx5(
297
368
  "div",
298
369
  {
299
370
  "data-testid": "flopay-processing-overlay",
@@ -337,14 +408,14 @@ function ProcessingOverlay({
337
408
  xmlns: "http://www.w3.org/2000/svg",
338
409
  style: { animation: "flopay-spin 0.8s linear infinite" },
339
410
  children: [
340
- /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
341
- /* @__PURE__ */ jsx4("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
411
+ /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
412
+ /* @__PURE__ */ jsx5("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
342
413
  ]
343
414
  }
344
415
  ),
345
- status === "success" && /* @__PURE__ */ jsx4("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
346
- /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
347
- /* @__PURE__ */ jsx4(
416
+ status === "success" && /* @__PURE__ */ jsx5("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
417
+ /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
418
+ /* @__PURE__ */ jsx5(
348
419
  "path",
349
420
  {
350
421
  d: "M7 12.5l3 3 7-7",
@@ -360,9 +431,9 @@ function ProcessingOverlay({
360
431
  }
361
432
  )
362
433
  ] }) }),
363
- status === "error" && /* @__PURE__ */ jsx4("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
364
- /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
365
- /* @__PURE__ */ jsx4(
434
+ status === "error" && /* @__PURE__ */ jsx5("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ jsxs2("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
435
+ /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
436
+ /* @__PURE__ */ jsx5(
366
437
  "path",
367
438
  {
368
439
  d: "M8 8l8 8M16 8l-8 8",
@@ -394,7 +465,7 @@ function ProcessingOverlay({
394
465
  ]
395
466
  }
396
467
  ),
397
- status === "success" && /* @__PURE__ */ jsx4(
468
+ status === "success" && /* @__PURE__ */ jsx5(
398
469
  "p",
399
470
  {
400
471
  style: {
@@ -408,7 +479,7 @@ function ProcessingOverlay({
408
479
  children: "You will be automatically redirected, do not close or navigate away from this window."
409
480
  }
410
481
  ),
411
- status === "error" && errorMessage && /* @__PURE__ */ jsx4(
482
+ status === "error" && errorMessage && /* @__PURE__ */ jsx5(
412
483
  "p",
413
484
  {
414
485
  style: {
@@ -422,7 +493,7 @@ function ProcessingOverlay({
422
493
  children: errorMessage
423
494
  }
424
495
  ),
425
- /* @__PURE__ */ jsx4("style", { children: `
496
+ /* @__PURE__ */ jsx5("style", { children: `
426
497
  @keyframes flopay-spin { to { transform: rotate(360deg); } }
427
498
  @keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
428
499
  @keyframes flopay-draw { to { stroke-dashoffset: 0; } }
@@ -436,7 +507,7 @@ function ProcessingOverlay({
436
507
  }
437
508
 
438
509
  // src/checkout-utils.ts
439
- import { FloPayError } from "@flopay/shared";
510
+ import { FloPayError, isSetupIntentClientSecret } from "@flopay/shared";
440
511
  function mergeInlineSessionPatches(base, patch) {
441
512
  if (!patch) return base;
442
513
  if (!base) return patch;
@@ -605,6 +676,18 @@ function resolvePaymentIntentPaymentMethodId(paymentIntent) {
605
676
  }
606
677
  async function retrievePaymentIntentFromProvider(provider, clientSecret) {
607
678
  const retriever = provider;
679
+ if (isSetupIntentClientSecret(clientSecret)) {
680
+ if (!retriever?.retrieveSetupIntent) {
681
+ return null;
682
+ }
683
+ const { setupIntent, error: error2 } = await retriever.retrieveSetupIntent(clientSecret);
684
+ if (error2) {
685
+ throw new FloPayError(error2.message ?? "Failed to retrieve setup intent.", "api_error", {
686
+ ...error2.code ? { code: error2.code } : {}
687
+ });
688
+ }
689
+ return setupIntent ?? null;
690
+ }
608
691
  if (!retriever?.retrievePaymentIntent) {
609
692
  return null;
610
693
  }
@@ -616,6 +699,12 @@ async function retrievePaymentIntentFromProvider(provider, clientSecret) {
616
699
  }
617
700
  return paymentIntent ?? null;
618
701
  }
702
+ function resolveWalletElementsMode(amountInMinorUnits) {
703
+ if (typeof amountInMinorUnits !== "number" || !Number.isFinite(amountInMinorUnits) || amountInMinorUnits <= 0) {
704
+ return { mode: "setup" };
705
+ }
706
+ return { mode: "payment", amount: amountInMinorUnits };
707
+ }
619
708
  function resolveTokenizedPaymentMethodId(tokenizedBody) {
620
709
  const candidates = [
621
710
  tokenizedBody?.id,
@@ -678,11 +767,11 @@ function isInAppBrowser(userAgent) {
678
767
  }
679
768
 
680
769
  // src/direct-paypal-button.tsx
681
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
770
+ import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState2 } from "react";
682
771
  import { loadScript } from "@paypal/paypal-js";
683
772
  import { PaymentAPI } from "@flopay/js";
684
773
  import { FloPayError as FloPayError2, normalizeGatewayEnvironment } from "@flopay/shared";
685
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
774
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
686
775
  var DEFAULT_BUTTON_HEIGHT = 45;
687
776
  function DirectPayPalButton({
688
777
  sessionId,
@@ -705,7 +794,7 @@ function DirectPayPalButton({
705
794
  existingOrderId,
706
795
  debug = false
707
796
  }) {
708
- const containerRef = useRef2(null);
797
+ const containerRef = useRef3(null);
709
798
  const [ready, setReady] = useState2(false);
710
799
  const [failed, setFailed] = useState2(false);
711
800
  const [submitting, setSubmitting] = useState2(false);
@@ -715,52 +804,52 @@ function DirectPayPalButton({
715
804
  if (!debug) return;
716
805
  setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
717
806
  };
718
- const onTokenizedBodyRef = useRef2(onTokenizedBody);
719
- const onCompleteRef = useRef2(onComplete);
720
- const onErrorChangeRef = useRef2(onErrorChange);
721
- const onDeclineRef = useRef2(onDecline);
722
- const onButtonClickRef = useRef2(onButtonClick);
723
- const onLoadStateChangeRef = useRef2(onLoadStateChange);
724
- const runBeforeButtonClickRef = useRef2(runBeforeButtonClick);
725
- const sessionRef = useRef2(session);
726
- const emailRef = useRef2(email);
727
- const nonceRef = useRef2(nonce);
728
- const beforeClickRef = useRef2(null);
729
- useEffect3(() => {
807
+ const onTokenizedBodyRef = useRef3(onTokenizedBody);
808
+ const onCompleteRef = useRef3(onComplete);
809
+ const onErrorChangeRef = useRef3(onErrorChange);
810
+ const onDeclineRef = useRef3(onDecline);
811
+ const onButtonClickRef = useRef3(onButtonClick);
812
+ const onLoadStateChangeRef = useRef3(onLoadStateChange);
813
+ const runBeforeButtonClickRef = useRef3(runBeforeButtonClick);
814
+ const sessionRef = useRef3(session);
815
+ const emailRef = useRef3(email);
816
+ const nonceRef = useRef3(nonce);
817
+ const beforeClickRef = useRef3(null);
818
+ useEffect4(() => {
730
819
  onTokenizedBodyRef.current = onTokenizedBody;
731
820
  }, [onTokenizedBody]);
732
- useEffect3(() => {
821
+ useEffect4(() => {
733
822
  onCompleteRef.current = onComplete;
734
823
  }, [onComplete]);
735
- useEffect3(() => {
824
+ useEffect4(() => {
736
825
  onErrorChangeRef.current = onErrorChange;
737
826
  }, [onErrorChange]);
738
- useEffect3(() => {
827
+ useEffect4(() => {
739
828
  onDeclineRef.current = onDecline;
740
829
  }, [onDecline]);
741
- useEffect3(() => {
830
+ useEffect4(() => {
742
831
  onButtonClickRef.current = onButtonClick;
743
832
  }, [onButtonClick]);
744
- useEffect3(() => {
833
+ useEffect4(() => {
745
834
  onLoadStateChangeRef.current = onLoadStateChange;
746
835
  }, [onLoadStateChange]);
747
- useEffect3(() => {
836
+ useEffect4(() => {
748
837
  runBeforeButtonClickRef.current = runBeforeButtonClick;
749
838
  }, [runBeforeButtonClick]);
750
- useEffect3(() => {
839
+ useEffect4(() => {
751
840
  sessionRef.current = session;
752
841
  }, [session]);
753
- useEffect3(() => {
842
+ useEffect4(() => {
754
843
  emailRef.current = email;
755
844
  }, [email]);
756
- useEffect3(() => {
845
+ useEffect4(() => {
757
846
  nonceRef.current = nonce;
758
847
  }, [nonce]);
759
- useEffect3(() => {
848
+ useEffect4(() => {
760
849
  onLoadStateChangeRef.current?.(ready && !failed);
761
850
  }, [ready, failed]);
762
851
  const normalizedEnv = normalizeGatewayEnvironment(environment);
763
- useEffect3(() => {
852
+ useEffect4(() => {
764
853
  const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
765
854
  const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
766
855
  appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
@@ -1197,7 +1286,7 @@ ${debugLines.join("\n")}`
1197
1286
  }
1198
1287
  ) : null;
1199
1288
  if (failed) {
1200
- return debug ? /* @__PURE__ */ jsx5("div", { children: debugPanel }) : null;
1289
+ return debug ? /* @__PURE__ */ jsx6("div", { children: debugPanel }) : null;
1201
1290
  }
1202
1291
  return (
1203
1292
  // Single wrapper so the parent flex container sees exactly one flex item
@@ -1207,7 +1296,7 @@ ${debugLines.join("\n")}`
1207
1296
  /* @__PURE__ */ jsxs3("div", { children: [
1208
1297
  debugPanel,
1209
1298
  /* @__PURE__ */ jsxs3("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1210
- !ready && /* @__PURE__ */ jsx5(
1299
+ !ready && /* @__PURE__ */ jsx6(
1211
1300
  "div",
1212
1301
  {
1213
1302
  "data-testid": "flopay-direct-paypal-placeholder",
@@ -1221,7 +1310,7 @@ ${debugLines.join("\n")}`
1221
1310
  }
1222
1311
  }
1223
1312
  ),
1224
- /* @__PURE__ */ jsx5(
1313
+ /* @__PURE__ */ jsx6(
1225
1314
  "div",
1226
1315
  {
1227
1316
  ref: containerRef,
@@ -1240,11 +1329,29 @@ ${debugLines.join("\n")}`
1240
1329
  }
1241
1330
 
1242
1331
  // src/split-card-form.tsx
1243
- import { FloPayError as FloPayError3, resolveTheme } from "@flopay/shared";
1244
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1332
+ import { FloPayError as FloPayError3, isSetupIntentClientSecret as isSetupIntentClientSecret2, resolveTheme } from "@flopay/shared";
1333
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
1245
1334
  var STRIPE_RESUME_KEY = "flopay_stripe_resume";
1246
1335
  var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
1247
1336
  var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
1337
+ function toVaultMount(block) {
1338
+ if (!block?.html) return null;
1339
+ return {
1340
+ html: block.html,
1341
+ ...block.messageToken ? { messageToken: block.messageToken } : {},
1342
+ ...block.expectedOrigin ? { expectedOrigin: block.expectedOrigin } : {}
1343
+ };
1344
+ }
1345
+ function darkenHex(hex, amount = 0.12) {
1346
+ const match = /^#?([0-9a-fA-F]{6})$/.exec(hex.trim());
1347
+ if (!match) return hex;
1348
+ const value = parseInt(match[1], 16);
1349
+ const scale = Math.max(0, Math.min(1, 1 - amount));
1350
+ const r = Math.round((value >> 16 & 255) * scale);
1351
+ const g = Math.round((value >> 8 & 255) * scale);
1352
+ const b = Math.round((value & 255) * scale);
1353
+ return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}`;
1354
+ }
1248
1355
  var FLOPAY_KEYFRAMES = `
1249
1356
  .paypal-buttons { margin: 0 !important; vertical-align: top !important; }
1250
1357
  @keyframes flopay-spin { to { transform: rotate(360deg); } }
@@ -1269,18 +1376,20 @@ var FLOPAY_KEYFRAMES = `
1269
1376
  `;
1270
1377
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
1271
1378
  function derivePrimaryTileStyle(opts) {
1272
- if (!opts.themeBundle) {
1379
+ if (!opts.themeBundle && !opts.explicitPrimaryColor) {
1273
1380
  return {
1274
1381
  backgroundColor: "white",
1275
1382
  color: "#262833",
1276
1383
  border: "1px solid #d1d5db",
1277
- borderRadius: "8px",
1384
+ borderRadius: opts.resolvedBorderRadius,
1278
1385
  boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
1279
1386
  };
1280
1387
  }
1281
- const submit = opts.submitButtonStyle ?? {};
1388
+ const submit = opts.themeBundle ? opts.submitButtonStyle ?? {} : {};
1282
1389
  return {
1283
- backgroundColor: submit.backgroundColor ?? opts.resolvedPrimaryColor,
1390
+ // `colorPrimary` wins so a per-checkout override re-skins the card / auto-pay
1391
+ // buttons in lock-step with the submit CTA (which also keys off it).
1392
+ backgroundColor: opts.resolvedPrimaryColor,
1284
1393
  color: submit.color ?? "white",
1285
1394
  border: submit.border ?? "none",
1286
1395
  borderRadius: submit.borderRadius ?? opts.resolvedBorderRadius,
@@ -1314,7 +1423,7 @@ function normalizeBeforeButtonClickError(method, err) {
1314
1423
  );
1315
1424
  }
1316
1425
  function FloPayKeyframes() {
1317
- return /* @__PURE__ */ jsx6("style", { children: FLOPAY_KEYFRAMES });
1426
+ return /* @__PURE__ */ jsx7("style", { children: FLOPAY_KEYFRAMES });
1318
1427
  }
1319
1428
  function toCssSize(value) {
1320
1429
  if (typeof value === "number") return `${value}px`;
@@ -1337,7 +1446,7 @@ function ExpressCheckoutReadySwap({
1337
1446
  }) {
1338
1447
  if (state === "unavailable" || state === "load_error") return null;
1339
1448
  return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", minHeight: 44 }, children: [
1340
- /* @__PURE__ */ jsx6(
1449
+ /* @__PURE__ */ jsx7(
1341
1450
  "div",
1342
1451
  {
1343
1452
  "data-testid": placeholderTestId,
@@ -1356,7 +1465,7 @@ function ExpressCheckoutReadySwap({
1356
1465
  }
1357
1466
  }
1358
1467
  ),
1359
- /* @__PURE__ */ jsx6(
1468
+ /* @__PURE__ */ jsx7(
1360
1469
  "div",
1361
1470
  {
1362
1471
  style: {
@@ -1376,7 +1485,7 @@ function isExpressCheckoutRowVisible(state) {
1376
1485
  }
1377
1486
  var SplitCardForm = forwardRef(
1378
1487
  function SplitCardForm2(props, ref) {
1379
- return /* @__PURE__ */ jsx6(SplitCardFormInner, { ...props, innerRef: ref });
1488
+ return /* @__PURE__ */ jsx7(SplitCardFormInner, { ...props, innerRef: ref });
1380
1489
  }
1381
1490
  );
1382
1491
  function PayPalButtonInner({
@@ -1396,14 +1505,14 @@ function PayPalButtonInner({
1396
1505
  const stripe = useStripeRaw();
1397
1506
  const elements = useStripeElements();
1398
1507
  const [loadState, setLoadState] = useState3("loading");
1399
- useEffect4(() => {
1508
+ useEffect5(() => {
1400
1509
  onLoadStateChange?.(loadState);
1401
1510
  }, [loadState, onLoadStateChange]);
1402
1511
  const [submitting, setSubmitting] = useState3(false);
1403
- const paypalResumeAttempted = useRef3(false);
1404
- const beforeClickRef = useRef3(null);
1512
+ const paypalResumeAttempted = useRef4(false);
1513
+ const beforeClickRef = useRef4(null);
1405
1514
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1406
- useEffect4(() => {
1515
+ useEffect5(() => {
1407
1516
  if (!stripe || paypalResumeAttempted.current) return;
1408
1517
  const params = new URLSearchParams(window.location.search);
1409
1518
  const paymentIntentId = params.get("payment_intent");
@@ -1609,13 +1718,13 @@ function PayPalButtonInner({
1609
1718
  }
1610
1719
  }, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
1611
1720
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1612
- /* @__PURE__ */ jsx6(
1721
+ /* @__PURE__ */ jsx7(
1613
1722
  ExpressCheckoutReadySwap,
1614
1723
  {
1615
1724
  state: loadState,
1616
1725
  placeholderTestId: "flopay-paypal-placeholder",
1617
1726
  borderRadius: placeholderBorderRadius,
1618
- children: /* @__PURE__ */ jsx6(
1727
+ children: /* @__PURE__ */ jsx7(
1619
1728
  ExpressCheckoutElement,
1620
1729
  {
1621
1730
  onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
@@ -1642,7 +1751,7 @@ function PayPalButtonInner({
1642
1751
  )
1643
1752
  }
1644
1753
  ),
1645
- submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
1754
+ submitting && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: "processing" })
1646
1755
  ] });
1647
1756
  }
1648
1757
  function WalletButtonInner({
@@ -1662,13 +1771,13 @@ function WalletButtonInner({
1662
1771
  const stripe = useStripeRaw();
1663
1772
  const elements = useStripeElements();
1664
1773
  const [loadState, setLoadState] = useState3("loading");
1665
- useEffect4(() => {
1774
+ useEffect5(() => {
1666
1775
  onLoadStateChange?.(loadState);
1667
1776
  }, [loadState, onLoadStateChange]);
1668
1777
  const [submitting, setSubmitting] = useState3(false);
1669
1778
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1670
- const lastWalletMethodRef = useRef3("card");
1671
- const beforeClickRef = useRef3(null);
1779
+ const lastWalletMethodRef = useRef4("card");
1780
+ const beforeClickRef = useRef4(null);
1672
1781
  const handleWalletConfirm = useCallback(
1673
1782
  async (event) => {
1674
1783
  if (!stripe || !elements) return;
@@ -1733,10 +1842,7 @@ function WalletButtonInner({
1733
1842
  const intentJson = await intentResponse.json();
1734
1843
  const intentClientSecret = intentJson.data?.id;
1735
1844
  if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
1736
- const { error: confirmError, paymentIntent } = await stripe.confirmCardPayment(
1737
- intentClientSecret,
1738
- { payment_method: paymentMethod.id }
1739
- );
1845
+ const { error: confirmError, intentId } = isSetupIntentClientSecret2(intentClientSecret) ? await stripe.confirmCardSetup(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.setupIntent?.id })) : await stripe.confirmCardPayment(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.paymentIntent?.id }));
1740
1846
  if (confirmError) {
1741
1847
  const message = confirmError.message ?? "Wallet payment failed.";
1742
1848
  onErrorChange?.(message);
@@ -1748,7 +1854,7 @@ function WalletButtonInner({
1748
1854
  onTokenizedBody({
1749
1855
  id: paymentMethod.id,
1750
1856
  type: "card",
1751
- threeDSecureActionResultTokenId: paymentIntent?.id
1857
+ threeDSecureActionResultTokenId: intentId
1752
1858
  }, {
1753
1859
  accountPatch: prepared?.accountPatch,
1754
1860
  sessionId: effectiveSessionId,
@@ -1781,13 +1887,13 @@ function WalletButtonInner({
1781
1887
  [expressMethods]
1782
1888
  );
1783
1889
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1784
- /* @__PURE__ */ jsx6(
1890
+ /* @__PURE__ */ jsx7(
1785
1891
  ExpressCheckoutReadySwap,
1786
1892
  {
1787
1893
  state: loadState,
1788
1894
  placeholderTestId: "flopay-wallet-placeholder",
1789
1895
  borderRadius: placeholderBorderRadius,
1790
- children: /* @__PURE__ */ jsx6(
1896
+ children: /* @__PURE__ */ jsx7(
1791
1897
  ExpressCheckoutElement,
1792
1898
  {
1793
1899
  onReady: (event) => {
@@ -1826,7 +1932,7 @@ function WalletButtonInner({
1826
1932
  )
1827
1933
  }
1828
1934
  ),
1829
- submitting && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: "processing" })
1935
+ submitting && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: "processing" })
1830
1936
  ] });
1831
1937
  }
1832
1938
  function StripeMethodButton({
@@ -1847,7 +1953,7 @@ function StripeMethodButton({
1847
1953
  const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
1848
1954
  const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
1849
1955
  const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
1850
- return /* @__PURE__ */ jsx6(
1956
+ return /* @__PURE__ */ jsx7(
1851
1957
  "button",
1852
1958
  {
1853
1959
  type: "button",
@@ -1894,7 +2000,7 @@ function StripeMethodButton({
1894
2000
  // Pulse-skeleton parity with the wallet ECE: no spinner, just the
1895
2001
  // status text on top of the pulsing background. Keeps the loading
1896
2002
  // affordance shape-equivalent across both kinds of tile.
1897
- /* @__PURE__ */ jsx6("span", { style: { margin: "0 auto" }, children: `Connecting to ${getStripeMethodDisplayName(method)}\u2026` })
2003
+ /* @__PURE__ */ jsx7("span", { style: { margin: "0 auto" }, children: `Connecting to ${getStripeMethodDisplayName(method)}\u2026` })
1898
2004
  ) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
1899
2005
  /* @__PURE__ */ jsxs4(
1900
2006
  "span",
@@ -1909,7 +2015,7 @@ function StripeMethodButton({
1909
2015
  gap: hasVendoredStripeMethodLogo(method) ? 8 : 0
1910
2016
  },
1911
2017
  children: [
1912
- brand?.logoSvg && /* @__PURE__ */ jsx6(
2018
+ brand?.logoSvg && /* @__PURE__ */ jsx7(
1913
2019
  "span",
1914
2020
  {
1915
2021
  "aria-hidden": "true",
@@ -1928,11 +2034,11 @@ function StripeMethodButton({
1928
2034
  dangerouslySetInnerHTML: { __html: brand.logoSvg }
1929
2035
  }
1930
2036
  ),
1931
- /* @__PURE__ */ jsx6("span", { children: getStripeMethodDisplayName(method) })
2037
+ /* @__PURE__ */ jsx7("span", { children: getStripeMethodDisplayName(method) })
1932
2038
  ]
1933
2039
  }
1934
2040
  ),
1935
- hasNextStep && /* @__PURE__ */ jsx6(
2041
+ hasNextStep && /* @__PURE__ */ jsx7(
1936
2042
  "svg",
1937
2043
  {
1938
2044
  width: "14",
@@ -1952,7 +2058,7 @@ function StripeMethodButton({
1952
2058
  opacity: 0.7
1953
2059
  },
1954
2060
  "aria-hidden": "true",
1955
- children: /* @__PURE__ */ jsx6("path", { d: "M9 18l6-6-6-6" })
2061
+ children: /* @__PURE__ */ jsx7("path", { d: "M9 18l6-6-6-6" })
1956
2062
  }
1957
2063
  )
1958
2064
  ] })
@@ -1975,12 +2081,13 @@ function StripeMethodInlineForm({
1975
2081
  isProcessing,
1976
2082
  submitButtonColor,
1977
2083
  submitButtonBorderRadius,
1978
- submitButtonStyle
2084
+ submitButtonStyle,
2085
+ errorText
1979
2086
  }) {
1980
2087
  const stripe = useStripeRaw();
1981
2088
  const elements = useStripeElements();
1982
2089
  const [submitting, setSubmitting] = useState3(false);
1983
- const submittingRef = useRef3(false);
2090
+ const submittingRef = useRef4(false);
1984
2091
  const [isMethodComplete, setIsMethodComplete] = useState3(false);
1985
2092
  const [loadState, setLoadState] = useState3("loading");
1986
2093
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
@@ -2125,7 +2232,7 @@ function StripeMethodInlineForm({
2125
2232
  ]);
2126
2233
  void onCancel;
2127
2234
  return /* @__PURE__ */ jsxs4("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
2128
- /* @__PURE__ */ jsx6(
2235
+ /* @__PURE__ */ jsx7(
2129
2236
  PaymentElement2,
2130
2237
  {
2131
2238
  onReady: () => setLoadState("ready"),
@@ -2145,7 +2252,7 @@ function StripeMethodInlineForm({
2145
2252
  }
2146
2253
  }
2147
2254
  ),
2148
- /* @__PURE__ */ jsx6(
2255
+ /* @__PURE__ */ jsx7(
2149
2256
  "button",
2150
2257
  {
2151
2258
  type: "button",
@@ -2171,7 +2278,23 @@ function StripeMethodInlineForm({
2171
2278
  },
2172
2279
  children: submitting ? "Processing\u2026" : `Pay with ${getStripeMethodDisplayName(method)}`
2173
2280
  }
2174
- )
2281
+ ),
2282
+ errorText && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
2283
+ margin: "0.75rem 0 0",
2284
+ padding: "0.625rem 0.875rem",
2285
+ background: "#FEF2F2",
2286
+ border: "1px solid #FECACA",
2287
+ borderRadius: "8px",
2288
+ color: "#991B1B",
2289
+ fontSize: "0.85rem",
2290
+ fontWeight: 600,
2291
+ display: "flex",
2292
+ alignItems: "center",
2293
+ gap: "0.5rem"
2294
+ }, children: [
2295
+ /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("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" }) }),
2296
+ errorText
2297
+ ] })
2175
2298
  ] });
2176
2299
  }
2177
2300
  function StripePaymentElementInner({
@@ -2201,8 +2324,8 @@ function StripePaymentElementInner({
2201
2324
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2202
2325
  const [expandedMethod, setExpandedMethod] = useState3(null);
2203
2326
  const [submittingMethod, setSubmittingMethod] = useState3(null);
2204
- const submittingRef = useRef3(false);
2205
- useEffect4(() => {
2327
+ const submittingRef = useRef4(false);
2328
+ useEffect5(() => {
2206
2329
  if (paymentElementMethods.length > 0 && stripeInstance) {
2207
2330
  onLoadStateChange?.("ready");
2208
2331
  } else if (!stripeInstance) {
@@ -2370,7 +2493,7 @@ function StripePaymentElementInner({
2370
2493
  paymentMethodTypes: [localExpandedMethod]
2371
2494
  };
2372
2495
  }, [localExpandedMethod, paymentElementBaseOptions]);
2373
- return /* @__PURE__ */ jsx6(
2496
+ return /* @__PURE__ */ jsx7(
2374
2497
  "div",
2375
2498
  {
2376
2499
  "data-testid": "flopay-stripe-payment-element-region",
@@ -2379,8 +2502,8 @@ function StripePaymentElementInner({
2379
2502
  const isExpanded = expandedApmMethod === method;
2380
2503
  const isSubmittingThis = submittingMethod === method;
2381
2504
  const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
2382
- return /* @__PURE__ */ jsxs4(React6.Fragment, { children: [
2383
- /* @__PURE__ */ jsx6(
2505
+ return /* @__PURE__ */ jsxs4(React7.Fragment, { children: [
2506
+ /* @__PURE__ */ jsx7(
2384
2507
  StripeMethodButton,
2385
2508
  {
2386
2509
  method,
@@ -2397,12 +2520,12 @@ function StripePaymentElementInner({
2397
2520
  fontFamily: buttonAppearance?.fontFamily
2398
2521
  }
2399
2522
  ),
2400
- !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ jsx6(
2523
+ !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ jsx7(
2401
2524
  StripeElements,
2402
2525
  {
2403
2526
  stripe: stripeInstance,
2404
2527
  options: localInlineElementsOptions,
2405
- children: /* @__PURE__ */ jsx6(
2528
+ children: /* @__PURE__ */ jsx7(
2406
2529
  StripeMethodInlineForm,
2407
2530
  {
2408
2531
  method,
@@ -2455,6 +2578,7 @@ function SplitCardFormInner({
2455
2578
  showPayPal = true,
2456
2579
  showStripe = true,
2457
2580
  enabledPaymentMethods,
2581
+ enabledPaymentMethodCountries,
2458
2582
  showApplePay = true,
2459
2583
  showGooglePay = true,
2460
2584
  layout = "default",
@@ -2469,6 +2593,8 @@ function SplitCardFormInner({
2469
2593
  onButtonClick,
2470
2594
  onBeforeButtonClick,
2471
2595
  enableAVS: enableAVSProp,
2596
+ cardFieldOrder,
2597
+ cardPreFormSlot,
2472
2598
  avsLayout: avsLayoutProp = "row",
2473
2599
  country: countryProp,
2474
2600
  zip: zipProp,
@@ -2505,14 +2631,41 @@ function SplitCardFormInner({
2505
2631
  const [city, setCity] = useState3(cityProp ?? "");
2506
2632
  const [stateValue, setStateValue] = useState3(stateProp ?? "");
2507
2633
  const [accountPatch, setAccountPatch] = useState3({});
2508
- const zipCodeRef = useRef3(zipProp ?? "");
2509
- const selectedCountryRef = useRef3(countryProp ?? "US");
2510
- const addressLine1Ref = useRef3(addressLine1Prop ?? "");
2511
- const addressLine2Ref = useRef3(addressLine2Prop ?? "");
2512
- const cityRef = useRef3(cityProp ?? "");
2513
- const stateRef = useRef3(stateProp ?? "");
2634
+ const zipCodeRef = useRef4(zipProp ?? "");
2635
+ const selectedCountryRef = useRef4(countryProp ?? "US");
2636
+ const addressLine1Ref = useRef4(addressLine1Prop ?? "");
2637
+ const addressLine2Ref = useRef4(addressLine2Prop ?? "");
2638
+ const cityRef = useRef4(cityProp ?? "");
2639
+ const stateRef = useRef4(stateProp ?? "");
2514
2640
  const avsConfig = useMemo3(() => resolveAVSConfig(enableAVSProp), [enableAVSProp]);
2515
2641
  const enableAVS = avsConfig !== null;
2642
+ const vaultBlockReady = Boolean(session?.vault?.html);
2643
+ const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
2644
+ const vaultActive = Boolean(
2645
+ showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
2646
+ );
2647
+ const cardCapture = useMemo3(() => {
2648
+ if (!flopay || !vaultActive || !sessionId) return null;
2649
+ return flopay.cardCapture({ sessionId });
2650
+ }, [flopay, vaultActive, sessionId]);
2651
+ const { avsInvalid, invalidAvsFields } = useMemo3(() => {
2652
+ const none = { line1: false, city: false, state: false, zip: false };
2653
+ if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
2654
+ const cc = selectedCountry;
2655
+ const isEmpty = (field, value) => isAVSFieldVisible(field, cc) && !value.trim();
2656
+ const invalidAvsFields2 = {
2657
+ line1: isEmpty(avsConfig.address_line_1, addressLine1),
2658
+ city: isEmpty(avsConfig.city, city),
2659
+ state: isEmpty(avsConfig.state, stateValue),
2660
+ zip: isEmpty(avsConfig.postal_code, zipCode)
2661
+ };
2662
+ const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
2663
+ return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
2664
+ }, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, zipCode]);
2665
+ const [hasAttemptedSubmit, setHasAttemptedSubmit] = useState3(false);
2666
+ const [vaultMount, setVaultMount] = useState3(
2667
+ () => toVaultMount(session?.vault)
2668
+ );
2516
2669
  const [viewState, setViewState] = useState3(initialCardOpen ? "card" : "buttons");
2517
2670
  const [expandedApmMethod, setExpandedApmMethod] = useState3(null);
2518
2671
  const showCardForm = viewState === "expanding" || viewState === "card";
@@ -2537,7 +2690,7 @@ function SplitCardFormInner({
2537
2690
  setExpandedApmMethod(null);
2538
2691
  }, TRANSITION_MS);
2539
2692
  }, []);
2540
- useEffect4(() => {
2693
+ useEffect5(() => {
2541
2694
  if (layout === "buttons" && initialCardOpen) {
2542
2695
  setViewState("card");
2543
2696
  }
@@ -2545,10 +2698,10 @@ function SplitCardFormInner({
2545
2698
  const [fullName, setFullName] = useState3("");
2546
2699
  const [formReady, setFormReady] = useState3(false);
2547
2700
  const [overlayStatus, setOverlayStatus] = useState3(null);
2548
- const processingRef = useRef3(false);
2701
+ const processingRef = useRef4(false);
2549
2702
  const [paypalDirectRetry, setPaypalDirectRetry] = useState3(null);
2550
- const paypalDirectRetryRef = useRef3(paypalDirectRetry);
2551
- useEffect4(() => {
2703
+ const paypalDirectRetryRef = useRef4(paypalDirectRetry);
2704
+ useEffect5(() => {
2552
2705
  paypalDirectRetryRef.current = paypalDirectRetry;
2553
2706
  }, [paypalDirectRetry]);
2554
2707
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
@@ -2569,6 +2722,31 @@ function SplitCardFormInner({
2569
2722
  };
2570
2723
  }, [themeBundle, buttonsTheme, buttonsStylesOverride]);
2571
2724
  const appearance = appearanceOverride ?? themeBundle?.appearance;
2725
+ const vaultThemeColors = useMemo3(() => {
2726
+ const vars = appearance?.variables;
2727
+ const asString = (value) => typeof value === "string" && value ? value : void 0;
2728
+ const submitButtonStyle = bStyles.submitButton;
2729
+ const primary = asString(vars?.colorPrimary) ?? asString(submitButtonStyle?.backgroundColor) ?? "#4A49FF";
2730
+ const isButtonsLayout = layout === "buttons";
2731
+ const nameInput = bStyles.nameInput;
2732
+ return {
2733
+ primaryColor: primary,
2734
+ primaryHoverColor: asString(vars?.colorPrimaryHover) ?? darkenHex(primary, 0.12),
2735
+ inputBackgroundColor: asString(bStyles.cardInputBackground) ?? asString(vars?.colorBackground) ?? "#ffffff",
2736
+ textColor: asString(bStyles.cardInputColor) ?? asString(nameInput?.color) ?? asString(vars?.colorText) ?? "#262833",
2737
+ borderColor: asString(bStyles.cardInputBorder) ?? (isButtonsLayout ? "#e5e7eb" : "#A4A4FF"),
2738
+ placeholderColor: asString(bStyles.cardInputPlaceholderColor) ?? "#9ca3af",
2739
+ errorColor: asString(vars?.colorDanger) ?? "#dc2626",
2740
+ successColor: "#16a34a",
2741
+ fontFamily: asString(nameInput?.fontFamily) ?? asString(vars?.fontFamily) ?? "Poppins, sans-serif",
2742
+ fontSize: asString(bStyles.cardInputFontSize) ?? asString(vars?.fontSizeBase) ?? "16px",
2743
+ // `resolvedInputFontWeight` equivalent — sent as a string (the widget's
2744
+ // theme applier only honors string values) so vault inputs/placeholders
2745
+ // match the AVS fields' weight per theme (default 400).
2746
+ fontWeight: String(toCssWeight(nameInput?.fontWeight) ?? 400),
2747
+ borderRadius: asString(vars?.borderRadius) ?? "8px"
2748
+ };
2749
+ }, [appearance, bStyles, layout]);
2572
2750
  const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
2573
2751
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
2574
2752
  const isSelfContained = !onTokenizedBody;
@@ -2611,14 +2789,17 @@ function SplitCardFormInner({
2611
2789
  }
2612
2790
  };
2613
2791
  }, [appearance]);
2614
- const walletOptions = useMemo3(() => ({
2615
- mode: "payment",
2616
- amount: amountInCents,
2617
- currency: currency.toLowerCase(),
2618
- paymentMethodCreation: "manual",
2619
- captureMethod: "manual",
2620
- ...stripeAppearanceProp
2621
- }), [amountInCents, currency, stripeAppearanceProp]);
2792
+ const walletOptions = useMemo3(() => {
2793
+ const modeOptions = resolveWalletElementsMode(totalAmount);
2794
+ return {
2795
+ ...modeOptions,
2796
+ currency: currency.toLowerCase(),
2797
+ paymentMethodCreation: "manual",
2798
+ // captureMethod only applies to payment mode; Stripe rejects it in setup.
2799
+ ...modeOptions.mode === "payment" ? { captureMethod: "manual" } : {},
2800
+ ...stripeAppearanceProp
2801
+ };
2802
+ }, [totalAmount, currency, stripeAppearanceProp]);
2622
2803
  const paypalOptions = useMemo3(() => ({
2623
2804
  mode: "payment",
2624
2805
  amount: amountInCents,
@@ -2634,12 +2815,160 @@ function SplitCardFormInner({
2634
2815
  },
2635
2816
  [onErrorChange]
2636
2817
  );
2818
+ useEffect5(() => {
2819
+ if (!vaultActive || !cardCapture) return;
2820
+ cardCapture.setSubmitGate?.(avsInvalid);
2821
+ }, [vaultActive, cardCapture, avsInvalid]);
2822
+ useEffect5(() => {
2823
+ if (!vaultActive || !cardCapture) return;
2824
+ cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
2825
+ }, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
2826
+ useEffect5(() => {
2827
+ if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
2828
+ updateError(null);
2829
+ }
2830
+ }, [viewState, updateError]);
2637
2831
  const emitDecline = useCallback(
2638
2832
  (method, input, overrides) => {
2639
2833
  onDecline?.(buildDeclineEvent(method, input, overrides));
2640
2834
  },
2641
2835
  [onDecline]
2642
2836
  );
2837
+ useEffect5(() => {
2838
+ if (!vaultActive || !sessionId) {
2839
+ setVaultMount(null);
2840
+ return;
2841
+ }
2842
+ const embedded = toVaultMount(session?.vault);
2843
+ if (embedded) {
2844
+ setVaultMount(embedded);
2845
+ return;
2846
+ }
2847
+ setVaultMount(null);
2848
+ let active = true;
2849
+ new PaymentAPI2(baseUrl).getVaultCapture(sessionId, nonce).then((block) => {
2850
+ if (!active) return;
2851
+ const mount = toVaultMount(block);
2852
+ if (mount) {
2853
+ setVaultMount(mount);
2854
+ } else {
2855
+ updateError("Failed to load the secure card form.");
2856
+ }
2857
+ }).catch((err) => {
2858
+ if (active) {
2859
+ updateError(err instanceof Error ? err.message : "Failed to load the secure card form.");
2860
+ }
2861
+ });
2862
+ return () => {
2863
+ active = false;
2864
+ };
2865
+ }, [
2866
+ vaultActive,
2867
+ sessionId,
2868
+ session?.vault?.html,
2869
+ session?.vault?.messageToken,
2870
+ session?.vault?.expectedOrigin,
2871
+ baseUrl,
2872
+ nonce,
2873
+ updateError
2874
+ ]);
2875
+ useEffect5(() => {
2876
+ if (!vaultActive || !cardCapture) return;
2877
+ let cancelled = false;
2878
+ const offSubmitting = cardCapture.on("submitting", () => {
2879
+ setHasAttemptedSubmit(true);
2880
+ setOverlayStatus("processing");
2881
+ if (!sessionId || !nonce) return;
2882
+ const cc = selectedCountryRef.current || resolvedAccount.country || "US";
2883
+ const stateVisible = avsConfig ? isAVSFieldVisible(avsConfig.state, cc) : false;
2884
+ const line1Visible = avsConfig ? isAVSFieldVisible(avsConfig.address_line_1, cc) : false;
2885
+ const zipVisible = avsConfig ? isAVSFieldVisible(avsConfig.postal_code, cc) : false;
2886
+ const cityVisible = avsConfig ? isAVSFieldVisible(avsConfig.city, cc) : false;
2887
+ const line2Visible = avsConfig ? isAVSFieldVisible(avsConfig.address_line_2, cc) : false;
2888
+ const derivedState = line1Visible && !stateVisible && zipVisible ? getStateFromPostalCode(cc, zipCodeRef.current ?? "") : null;
2889
+ const stateValue2 = stateVisible ? stateRef.current : derivedState;
2890
+ void new PaymentAPI2(baseUrl).patchAccountSnapshot(sessionId, nonce, {
2891
+ accountData: {
2892
+ userId: resolvedAccount.userId ?? "",
2893
+ email: resolvedAccount.email ?? "",
2894
+ firstName: resolvedAccount.firstName ?? fullName.trim().split(/\s+/)[0] ?? "",
2895
+ lastName: resolvedAccount.lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? "",
2896
+ ...zipVisible && zipCodeRef.current ? { zip: zipCodeRef.current } : {},
2897
+ ...cityVisible && cityRef.current ? { city: cityRef.current } : {},
2898
+ ...stateValue2 ? { state: stateValue2 } : {},
2899
+ ...line1Visible && addressLine1Ref.current ? { addressLine1: addressLine1Ref.current } : {},
2900
+ ...line2Visible && addressLine2Ref.current ? { addressLine2: addressLine2Ref.current } : {},
2901
+ country: cc
2902
+ },
2903
+ ...avsCheckProp !== void 0 ? { avsCheck: avsCheckProp } : {},
2904
+ ...avsConfig ? {
2905
+ avsConfig: {
2906
+ country: isAVSFieldVisible(avsConfig.country, cc),
2907
+ postal_code: zipVisible,
2908
+ address_line_1: line1Visible,
2909
+ address_line_2: line2Visible,
2910
+ city: cityVisible,
2911
+ state: stateVisible
2912
+ }
2913
+ } : {}
2914
+ }).catch(() => {
2915
+ });
2916
+ });
2917
+ const offComplete = cardCapture.on("complete", async (event) => {
2918
+ markSessionRecentlyCompleted(event.sessionId ?? sessionId);
2919
+ setOverlayStatus("success");
2920
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
2921
+ if (cancelled) return;
2922
+ onComplete?.({
2923
+ status: "succeeded",
2924
+ paymentIntentId: event.intentId,
2925
+ checkoutMethod: "card"
2926
+ });
2927
+ });
2928
+ const offDecline = cardCapture.on("decline", async (event) => {
2929
+ const message = event.message ?? "Your payment was declined. Please try another card or contact your bank.";
2930
+ updateError(message);
2931
+ setOverlayStatus("error");
2932
+ emitDecline("card", message, event.declineReason ? { declineCode: event.declineReason } : void 0);
2933
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
2934
+ if (cancelled) return;
2935
+ setOverlayStatus(null);
2936
+ });
2937
+ const offError = cardCapture.on("error", async (event) => {
2938
+ const message = event.message ?? "There was a problem processing your payment. Please try again.";
2939
+ updateError(message);
2940
+ setOverlayStatus("error");
2941
+ onError?.(new FloPayError3(message, "api_error"));
2942
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
2943
+ if (cancelled) return;
2944
+ setOverlayStatus(null);
2945
+ });
2946
+ return () => {
2947
+ cancelled = true;
2948
+ offSubmitting();
2949
+ offComplete();
2950
+ offDecline();
2951
+ offError();
2952
+ };
2953
+ }, [
2954
+ vaultActive,
2955
+ cardCapture,
2956
+ sessionId,
2957
+ nonce,
2958
+ baseUrl,
2959
+ avsConfig,
2960
+ avsCheckProp,
2961
+ resolvedAccount.userId,
2962
+ resolvedAccount.email,
2963
+ resolvedAccount.firstName,
2964
+ resolvedAccount.lastName,
2965
+ resolvedAccount.country,
2966
+ fullName,
2967
+ onComplete,
2968
+ onError,
2969
+ updateError,
2970
+ emitDecline
2971
+ ]);
2643
2972
  const directPaypalConfigured = !!directPaypal?.clientId;
2644
2973
  const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
2645
2974
  const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
@@ -2663,17 +2992,18 @@ function SplitCardFormInner({
2663
2992
  }, [showApplePay, showGooglePay]);
2664
2993
  const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
2665
2994
  const showWallets = showStripe && walletExpressMethods.length > 0;
2666
- const paymentElementMethodsForCurrency = useMemo3(
2667
- () => filterStripeMethodsByAmount(
2668
- filterStripeMethodsByCountry(
2669
- filterStripeMethodsByCurrency(paymentElementMethods, currency),
2670
- countryProp
2671
- ),
2672
- currency,
2673
- amountInCents
2674
- ),
2675
- [paymentElementMethods, currency, countryProp, amountInCents]
2676
- );
2995
+ const apmCountry = enableAVS ? selectedCountry : countryProp;
2996
+ const paymentElementMethodsForCurrency = useMemo3(() => {
2997
+ const target = apmCountry?.trim().toUpperCase();
2998
+ if (!target) return paymentElementMethods;
2999
+ if (!enabledPaymentMethodCountries) {
3000
+ return filterStripeMethodsByCountry(paymentElementMethods, apmCountry);
3001
+ }
3002
+ return paymentElementMethods.filter((method) => {
3003
+ const allowed = enabledPaymentMethodCountries[method];
3004
+ return !allowed || allowed.length === 0 || allowed.includes(target);
3005
+ });
3006
+ }, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
2677
3007
  const paymentElementBaseOptions = useMemo3(() => ({
2678
3008
  mode: "payment",
2679
3009
  amount: amountInCents,
@@ -2686,7 +3016,7 @@ function SplitCardFormInner({
2686
3016
  const [paymentElementLoadState, setPaymentElementLoadState] = useState3("loading");
2687
3017
  const [directPaypalReady, setDirectPaypalReady] = useState3(false);
2688
3018
  const [inAppBrowserDetected, setInAppBrowserDetected] = useState3();
2689
- useEffect4(() => {
3019
+ useEffect5(() => {
2690
3020
  setInAppBrowserDetected(isInAppBrowser());
2691
3021
  }, []);
2692
3022
  const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
@@ -2698,8 +3028,8 @@ function SplitCardFormInner({
2698
3028
  const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
2699
3029
  const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
2700
3030
  const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
2701
- const validationFiredRef = useRef3(false);
2702
- useEffect4(() => {
3031
+ const validationFiredRef = useRef4(false);
3032
+ useEffect5(() => {
2703
3033
  if (validationFiredRef.current) return;
2704
3034
  if (!showStripe && !showPayPal) {
2705
3035
  validationFiredRef.current = true;
@@ -2719,8 +3049,8 @@ function SplitCardFormInner({
2719
3049
  updateError(err.message);
2720
3050
  }
2721
3051
  }, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
2722
- const deprecationLoggedRef = useRef3(false);
2723
- useEffect4(() => {
3052
+ const deprecationLoggedRef = useRef4(false);
3053
+ useEffect5(() => {
2724
3054
  if (deprecationLoggedRef.current) return;
2725
3055
  if (!hasEnabledMethods) return;
2726
3056
  const stale = [];
@@ -3046,8 +3376,8 @@ function SplitCardFormInner({
3046
3376
  }
3047
3377
  }
3048
3378
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
3049
- const stripeResumeAttemptedRef = useRef3(false);
3050
- useEffect4(() => {
3379
+ const stripeResumeAttemptedRef = useRef4(false);
3380
+ useEffect5(() => {
3051
3381
  if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
3052
3382
  const params = new URLSearchParams(window.location.search);
3053
3383
  const paymentIntentId = params.get("payment_intent");
@@ -3129,6 +3459,7 @@ function SplitCardFormInner({
3129
3459
  async (e) => {
3130
3460
  e.preventDefault();
3131
3461
  if (!flopay || !elements || isSubmitting || processingRef.current) return;
3462
+ if (vaultActive) return;
3132
3463
  if (layout !== "buttons") {
3133
3464
  onButtonClick?.("card");
3134
3465
  }
@@ -3156,11 +3487,13 @@ function SplitCardFormInner({
3156
3487
  return;
3157
3488
  }
3158
3489
  }
3159
- const submitResult = await flopay.submitElements();
3160
- if (submitResult.error) {
3161
- updateError(submitResult.error.message);
3162
- onError?.(submitResult.error);
3163
- return;
3490
+ if (!vaultActive) {
3491
+ const submitResult = await flopay.submitElements();
3492
+ if (submitResult.error) {
3493
+ updateError(submitResult.error.message);
3494
+ onError?.(submitResult.error);
3495
+ return;
3496
+ }
3164
3497
  }
3165
3498
  const billingAddress = {};
3166
3499
  const cc = selectedCountryRef.current;
@@ -3185,75 +3518,77 @@ function SplitCardFormInner({
3185
3518
  ...fullName.trim() ? { name: fullName.trim() } : {},
3186
3519
  ...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
3187
3520
  };
3188
- const pmResult = await flopay.createPaymentMethod(billingDetails);
3189
- if (pmResult.error || !pmResult.paymentMethodId) {
3190
- updateError(pmResult.error?.message ?? "Failed to create payment method.");
3191
- return;
3192
- }
3193
3521
  if (!sessionId || !resolvedAccount.email) {
3194
3522
  throw new FloPayError3("Missing sessionId or email", "validation_error");
3195
3523
  }
3196
- const intentHeaders = { "Content-Type": "application/json" };
3197
- if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
3198
- const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
3199
- method: "POST",
3200
- headers: intentHeaders,
3201
- body: JSON.stringify({
3202
- sessionId,
3203
- email: resolvedAccount.email,
3204
- paymentMethodType: pmResult.paymentMethodId,
3205
- isPaypal: false
3206
- })
3207
- });
3208
- if (!intentResponse.ok) {
3209
- const intentError = await buildFloPayApiErrorFromResponse(
3210
- intentResponse,
3211
- "Failed to create payment intent"
3524
+ {
3525
+ const pmResult = await flopay.createPaymentMethod(billingDetails);
3526
+ if (pmResult.error || !pmResult.paymentMethodId) {
3527
+ updateError(pmResult.error?.message ?? "Failed to create payment method.");
3528
+ return;
3529
+ }
3530
+ const intentHeaders = { "Content-Type": "application/json" };
3531
+ if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
3532
+ const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
3533
+ method: "POST",
3534
+ headers: intentHeaders,
3535
+ body: JSON.stringify({
3536
+ sessionId,
3537
+ email: resolvedAccount.email,
3538
+ paymentMethodType: pmResult.paymentMethodId,
3539
+ isPaypal: false
3540
+ })
3541
+ });
3542
+ if (!intentResponse.ok) {
3543
+ const intentError = await buildFloPayApiErrorFromResponse(
3544
+ intentResponse,
3545
+ "Failed to create payment intent"
3546
+ );
3547
+ setOverlayStatus("error");
3548
+ updateError(intentError.message);
3549
+ onError?.(intentError);
3550
+ emitDecline("card", intentError);
3551
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3552
+ return;
3553
+ }
3554
+ const intentJson = await intentResponse.json();
3555
+ const intentClientSecret = intentJson.data?.id;
3556
+ if (!intentClientSecret) throw new FloPayError3("No client_secret in payment intent response", "api_error");
3557
+ const confirmResult = await flopay.confirmCardPayment({
3558
+ clientSecret: intentClientSecret,
3559
+ paymentMethodId: pmResult.paymentMethodId
3560
+ });
3561
+ if (confirmResult.error) {
3562
+ setOverlayStatus("error");
3563
+ updateError(confirmResult.error.message);
3564
+ onError?.(confirmResult.error);
3565
+ emitDecline("card", confirmResult.error);
3566
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3567
+ return;
3568
+ }
3569
+ const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3570
+ const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3571
+ rawProvider,
3572
+ intentClientSecret
3212
3573
  );
3213
- setOverlayStatus("error");
3214
- updateError(intentError.message);
3215
- onError?.(intentError);
3216
- emitDecline("card", intentError);
3217
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3218
- return;
3219
- }
3220
- const intentJson = await intentResponse.json();
3221
- const intentClientSecret = intentJson.data?.id;
3222
- if (!intentClientSecret) throw new FloPayError3("No client_secret in payment intent response", "api_error");
3223
- const confirmResult = await flopay.confirmCardPayment({
3224
- clientSecret: intentClientSecret,
3225
- paymentMethodId: pmResult.paymentMethodId
3226
- });
3227
- if (confirmResult.error) {
3228
- setOverlayStatus("error");
3229
- updateError(confirmResult.error.message);
3230
- onError?.(confirmResult.error);
3231
- emitDecline("card", confirmResult.error);
3232
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3233
- return;
3234
- }
3235
- const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3236
- const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3237
- rawProvider,
3238
- intentClientSecret
3239
- );
3240
- const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3241
- const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
3242
- if (!paymentIntentId) {
3243
- const error2 = new FloPayError3("No payment intent returned after confirmation.", "api_error");
3244
- setOverlayStatus("error");
3245
- updateError(error2.message);
3246
- onError?.(error2);
3247
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3248
- return;
3574
+ const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3575
+ const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
3576
+ if (!paymentIntentId) {
3577
+ const error2 = new FloPayError3("No payment intent returned after confirmation.", "api_error");
3578
+ setOverlayStatus("error");
3579
+ updateError(error2.message);
3580
+ onError?.(error2);
3581
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3582
+ return;
3583
+ }
3584
+ handedOff = isSelfContained;
3585
+ dispatchTokenizedBody({
3586
+ id: paymentMethodId,
3587
+ type: "card",
3588
+ threeDSecureActionResultTokenId: paymentIntentId,
3589
+ originalPaymentMethodId: pmResult.paymentMethodId
3590
+ });
3249
3591
  }
3250
- handedOff = isSelfContained;
3251
- dispatchTokenizedBody({
3252
- id: paymentMethodId,
3253
- type: "card",
3254
- threeDSecureActionResultTokenId: paymentIntentId,
3255
- originalPaymentMethodId: pmResult.paymentMethodId
3256
- });
3257
3592
  } catch (err) {
3258
3593
  setOverlayStatus("error");
3259
3594
  updateError(err instanceof Error ? err.message : "An unexpected error occurred");
@@ -3265,11 +3600,11 @@ function SplitCardFormInner({
3265
3600
  }
3266
3601
  }
3267
3602
  },
3268
- [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3603
+ [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, vaultActive, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3269
3604
  );
3270
- const isReady = flopay !== null && elements !== null;
3605
+ const isReady = flopay !== null && (vaultActive || elements !== null);
3271
3606
  if (!isReady) {
3272
- return /* @__PURE__ */ jsx6("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3607
+ return /* @__PURE__ */ jsx7("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3273
3608
  }
3274
3609
  const isButtons = layout === "buttons";
3275
3610
  const appearanceVars = appearance?.variables;
@@ -3277,6 +3612,8 @@ function SplitCardFormInner({
3277
3612
  const appearanceColorBg = appearanceVars?.colorBackground;
3278
3613
  const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
3279
3614
  const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
3615
+ const resolvedDangerColor = appearanceVars?.colorDanger ?? "#dc2626";
3616
+ const avsBorderColor = (fieldInvalid) => hasAttemptedSubmit && fieldInvalid ? resolvedDangerColor : resolvedBorder;
3280
3617
  const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
3281
3618
  const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
3282
3619
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
@@ -3288,7 +3625,9 @@ function SplitCardFormInner({
3288
3625
  const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
3289
3626
  const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
3290
3627
  const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
3628
+ const buttonBorderRadius = appearanceVars?.borderRadius ?? bStyles.cardButton?.borderRadius ?? resolvedBorderRadius;
3291
3629
  const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
3630
+ const resolvedPrimaryHoverColor = appearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
3292
3631
  const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
3293
3632
  const sharedInputTypography = {
3294
3633
  fontSize: resolvedInputFontSize,
@@ -3322,14 +3661,73 @@ function SplitCardFormInner({
3322
3661
  const containerOverrides = bStyles.cardFormContainer ?? {};
3323
3662
  const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
3324
3663
  const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
3664
+ const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ jsx7(
3665
+ VaultCardFields,
3666
+ {
3667
+ capture: cardCapture,
3668
+ html: vaultMount.html,
3669
+ messageToken: vaultMount.messageToken,
3670
+ expectedOrigin: vaultMount.expectedOrigin,
3671
+ theme: vaultThemeColors,
3672
+ onReady: () => {
3673
+ setFormReady(true);
3674
+ if (!avsConfig || typeof document === "undefined") return;
3675
+ const focusFirstAvs = () => {
3676
+ const block = document.querySelector('[data-testid="flopay-avs-fields"]');
3677
+ const first = block?.querySelector(
3678
+ "input:not([disabled]), select:not([disabled])"
3679
+ );
3680
+ first?.focus();
3681
+ };
3682
+ focusFirstAvs();
3683
+ let tries = 0;
3684
+ const timer = window.setInterval(() => {
3685
+ tries += 1;
3686
+ const active = document.activeElement;
3687
+ const onIframe = !!active && active.tagName === "IFRAME" && active.id === "flopay_vault_form_iframe";
3688
+ if (onIframe) {
3689
+ focusFirstAvs();
3690
+ window.clearInterval(timer);
3691
+ } else if (tries >= 50) {
3692
+ window.clearInterval(timer);
3693
+ }
3694
+ }, 100);
3695
+ },
3696
+ onError: (message) => updateError(message),
3697
+ onValidation: (message) => {
3698
+ updateError(message);
3699
+ if (message) setOverlayStatus(null);
3700
+ }
3701
+ }
3702
+ ) : /* @__PURE__ */ jsx7(
3703
+ "div",
3704
+ {
3705
+ "data-testid": "flopay-vault-loading",
3706
+ style: {
3707
+ minHeight: 120,
3708
+ display: "flex",
3709
+ alignItems: "center",
3710
+ justifyContent: "center",
3711
+ color: "#6b7280",
3712
+ fontSize: 14
3713
+ },
3714
+ children: "Loading secure card form\u2026"
3715
+ }
3716
+ );
3325
3717
  const cardFormBlock = /* @__PURE__ */ jsxs4("div", { style: {
3326
3718
  backgroundColor: cardBg,
3327
3719
  borderRadius: containerRadius,
3328
3720
  ...containerOverrides,
3329
3721
  padding: containerPadding,
3330
- ...sharedInputPlaceholderVars
3722
+ ...sharedInputPlaceholderVars,
3723
+ // Flex column (BOTH layouts, so default and buttons>card never diverge) so
3724
+ // AVS can be ordered above the vault widget — its submit lives inside the
3725
+ // iframe, so AVS can't sit between fields and button; it goes above the
3726
+ // card form instead of after the button.
3727
+ display: "flex",
3728
+ flexDirection: "column"
3331
3729
  }, children: [
3332
- /* @__PURE__ */ jsx6("style", { children: `
3730
+ /* @__PURE__ */ jsx7("style", { children: `
3333
3731
  .flopay-shared-input::placeholder {
3334
3732
  color: var(--flopay-input-placeholder-color);
3335
3733
  opacity: 1;
@@ -3341,7 +3739,9 @@ function SplitCardFormInner({
3341
3739
  isButtons && showCardForm && /* @__PURE__ */ jsxs4("div", { style: {
3342
3740
  display: "flex",
3343
3741
  alignItems: "center",
3344
- padding: "0.75rem 0 0.625rem"
3742
+ padding: "0.75rem 0 0.625rem",
3743
+ // Keep the header on top when AVS is ordered above the card on vault.
3744
+ order: vaultActive ? -2 : 0
3345
3745
  }, children: [
3346
3746
  /* @__PURE__ */ jsxs4(
3347
3747
  "button",
@@ -3365,7 +3765,7 @@ function SplitCardFormInner({
3365
3765
  },
3366
3766
  "aria-label": "Back to payment methods",
3367
3767
  children: [
3368
- /* @__PURE__ */ jsx6("span", { style: {
3768
+ /* @__PURE__ */ jsx7("span", { style: {
3369
3769
  display: "inline-flex",
3370
3770
  alignItems: "center",
3371
3771
  justifyContent: "center",
@@ -3375,12 +3775,12 @@ function SplitCardFormInner({
3375
3775
  backgroundColor: "#f3f4f6",
3376
3776
  transition: "background-color 0.15s",
3377
3777
  ...bStyles.backButtonIcon
3378
- }, children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 18l-6-6 6-6" }) }) }),
3379
- /* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
3778
+ }, children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M15 18l-6-6 6-6" }) }) }),
3779
+ /* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
3380
3780
  ]
3381
3781
  }
3382
3782
  ),
3383
- hideTitle ? /* @__PURE__ */ jsx6("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx6("div", { style: {
3783
+ hideTitle ? /* @__PURE__ */ jsx7("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx7("div", { style: {
3384
3784
  flex: 1,
3385
3785
  textAlign: "center",
3386
3786
  fontWeight: 600,
@@ -3388,58 +3788,65 @@ function SplitCardFormInner({
3388
3788
  color: "#262833",
3389
3789
  paddingRight: 80,
3390
3790
  ...bStyles.title
3391
- }, children: /* @__PURE__ */ jsx6(TitleContentSlot, { content: cardTitleContent }) })
3791
+ }, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) })
3392
3792
  ] }),
3393
- !isButtons && !hideTitle && /* @__PURE__ */ jsx6("div", { style: {
3793
+ !isButtons && !hideTitle && /* @__PURE__ */ jsx7("div", { style: {
3394
3794
  textAlign: "center",
3395
3795
  fontWeight: 600,
3396
3796
  fontSize: "1.1rem",
3397
3797
  padding: "0.5rem 0",
3398
3798
  color: resolvedTitleColor,
3799
+ // Keep the title at the very top on the vault path. The card-form slot
3800
+ // (-2) and AVS block (-1) are ordered below it but above the card form.
3801
+ order: vaultActive ? -3 : 0,
3399
3802
  ...bStyles.title
3400
- }, children: /* @__PURE__ */ jsx6(TitleContentSlot, { content: cardTitleContent }) }),
3401
- /* @__PURE__ */ jsx6("div", { style: {
3402
- backgroundColor: cardInputBg,
3403
- border: `1px solid ${resolvedBorder}`,
3404
- borderTopLeftRadius: "8px",
3405
- borderTopRightRadius: "8px",
3406
- padding: "10px"
3407
- }, children: /* @__PURE__ */ jsx6(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
3408
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
3409
- /* @__PURE__ */ jsx6("div", { style: {
3410
- flex: 1,
3411
- backgroundColor: cardInputBg,
3412
- // Longhand only — mixing `border` shorthand with per-side
3413
- // overrides triggers React's "shorthand vs longhand" warning
3414
- // because render order isn't deterministic.
3415
- borderTop: "none",
3416
- borderRight: "none",
3417
- borderBottom: `1px solid ${resolvedBorder}`,
3418
- borderLeft: `1px solid ${resolvedBorder}`,
3419
- borderBottomLeftRadius: "8px",
3420
- padding: "10px"
3421
- }, children: /* @__PURE__ */ jsx6(CardExpiryElement, { options: stripeElementStyle }) }),
3422
- /* @__PURE__ */ jsx6("div", { style: {
3423
- flex: 1,
3803
+ }, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) }),
3804
+ !vaultActive && /* @__PURE__ */ jsxs4(Fragment2, { children: [
3805
+ /* @__PURE__ */ jsx7("div", { style: {
3424
3806
  backgroundColor: cardInputBg,
3425
- borderTop: "none",
3426
- borderRight: `1px solid ${resolvedBorder}`,
3427
- borderBottom: `1px solid ${resolvedBorder}`,
3428
- borderLeft: `1px solid ${resolvedBorder}`,
3429
- borderBottomRightRadius: "8px",
3807
+ border: `1px solid ${resolvedBorder}`,
3808
+ borderTopLeftRadius: resolvedBorderRadius,
3809
+ borderTopRightRadius: resolvedBorderRadius,
3430
3810
  padding: "10px"
3431
- }, children: /* @__PURE__ */ jsx6(CardCvcElement, { options: stripeElementStyle }) })
3811
+ }, children: /* @__PURE__ */ jsx7(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
3812
+ /* @__PURE__ */ jsxs4("div", { style: { display: "flex" }, children: [
3813
+ /* @__PURE__ */ jsx7("div", { style: {
3814
+ flex: 1,
3815
+ backgroundColor: cardInputBg,
3816
+ // Longhand only — mixing `border` shorthand with per-side
3817
+ // overrides triggers React's "shorthand vs longhand" warning
3818
+ // because render order isn't deterministic.
3819
+ borderTop: "none",
3820
+ borderRight: "none",
3821
+ borderBottom: `1px solid ${resolvedBorder}`,
3822
+ borderLeft: `1px solid ${resolvedBorder}`,
3823
+ borderBottomLeftRadius: resolvedBorderRadius,
3824
+ padding: "10px"
3825
+ }, children: /* @__PURE__ */ jsx7(CardExpiryElement, { options: stripeElementStyle }) }),
3826
+ /* @__PURE__ */ jsx7("div", { style: {
3827
+ flex: 1,
3828
+ backgroundColor: cardInputBg,
3829
+ borderTop: "none",
3830
+ borderRight: `1px solid ${resolvedBorder}`,
3831
+ borderBottom: `1px solid ${resolvedBorder}`,
3832
+ borderLeft: `1px solid ${resolvedBorder}`,
3833
+ borderBottomRightRadius: resolvedBorderRadius,
3834
+ padding: "10px"
3835
+ }, children: /* @__PURE__ */ jsx7(CardCvcElement, { options: stripeElementStyle }) })
3836
+ ] })
3432
3837
  ] }),
3433
- /* @__PURE__ */ jsx6("div", { style: {
3838
+ !vaultActive && /* @__PURE__ */ jsx7("div", { style: {
3434
3839
  backgroundColor: cardInputBg,
3435
3840
  border: `1px solid ${resolvedBorder}`,
3436
- borderRadius: "8px",
3841
+ borderRadius: resolvedBorderRadius,
3437
3842
  marginTop: "0.5rem",
3438
3843
  padding: "10px"
3439
- }, children: /* @__PURE__ */ jsx6(
3844
+ }, children: /* @__PURE__ */ jsx7(
3440
3845
  "input",
3441
3846
  {
3442
3847
  className: "flopay-shared-input",
3848
+ id: "flopay-cc-name",
3849
+ name: "cc-name",
3443
3850
  placeholder: "Full Name on Card",
3444
3851
  autoComplete: "cc-name",
3445
3852
  value: fullName,
@@ -3456,32 +3863,32 @@ function SplitCardFormInner({
3456
3863
  }
3457
3864
  }
3458
3865
  ) }),
3459
- avsConfig && (() => {
3866
+ avsConfig && /* @__PURE__ */ jsx7("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
3460
3867
  const cc = selectedCountry;
3461
- const inputWrapStyle = (extraStyle) => ({
3868
+ const inputWrapStyle = (invalid = false) => ({
3462
3869
  backgroundColor: cardInputBg,
3463
- border: `1px solid ${resolvedBorder}`,
3464
- borderRadius: "8px",
3870
+ border: `1px solid ${avsBorderColor(invalid)}`,
3871
+ borderRadius: resolvedBorderRadius,
3465
3872
  marginTop: "0.5rem",
3466
- padding: "10px",
3467
- ...isButtons && extraStyle ? extraStyle : {}
3873
+ padding: "10px"
3468
3874
  });
3469
3875
  const inputFieldStyle = () => ({
3470
3876
  width: "100%",
3471
3877
  border: "none",
3472
3878
  outline: "none",
3473
3879
  background: "transparent",
3474
- ...sharedInputTypography,
3475
- ...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
3880
+ ...sharedInputTypography
3476
3881
  });
3477
3882
  const stateOpts = getStateOptions(cc);
3478
3883
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
3479
- isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx6("div", { style: inputWrapStyle(bStyles.addressLine1Input), children: /* @__PURE__ */ jsx6(
3884
+ isAVSFieldVisible(avsConfig.address_line_1, cc) && /* @__PURE__ */ jsx7("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ jsx7(
3480
3885
  "input",
3481
3886
  {
3482
3887
  className: "flopay-shared-input",
3888
+ id: "flopay-billing-address-line1",
3889
+ name: "billing-address-line1",
3483
3890
  placeholder: "Street Address (e.g. 123 Main St)",
3484
- autoComplete: "address-line1",
3891
+ autoComplete: "billing address-line1",
3485
3892
  value: addressLine1,
3486
3893
  onChange: (e) => {
3487
3894
  addressLine1Ref.current = e.target.value;
@@ -3493,12 +3900,14 @@ function SplitCardFormInner({
3493
3900
  style: inputFieldStyle()
3494
3901
  }
3495
3902
  ) }),
3496
- isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx6("div", { style: inputWrapStyle(bStyles.addressLine2Input), children: /* @__PURE__ */ jsx6(
3903
+ isAVSFieldVisible(avsConfig.address_line_2, cc) && /* @__PURE__ */ jsx7("div", { style: inputWrapStyle(), children: /* @__PURE__ */ jsx7(
3497
3904
  "input",
3498
3905
  {
3499
3906
  className: "flopay-shared-input",
3907
+ id: "flopay-billing-address-line2",
3908
+ name: "billing-address-line2",
3500
3909
  placeholder: "Apt, Suite, Unit (optional)",
3501
- autoComplete: "address-line2",
3910
+ autoComplete: "billing address-line2",
3502
3911
  value: addressLine2,
3503
3912
  onChange: (e) => {
3504
3913
  addressLine2Ref.current = e.target.value;
@@ -3514,24 +3923,25 @@ function SplitCardFormInner({
3514
3923
  gap: "0",
3515
3924
  marginTop: "0.5rem"
3516
3925
  }, children: [
3517
- isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx6("div", { style: {
3926
+ isAVSFieldVisible(avsConfig.city, cc) && /* @__PURE__ */ jsx7("div", { style: {
3518
3927
  flex: 1,
3519
3928
  backgroundColor: cardInputBg,
3520
- borderTop: `1px solid ${resolvedBorder}`,
3521
- borderRight: `1px solid ${resolvedBorder}`,
3522
- borderBottom: `1px solid ${resolvedBorder}`,
3523
- borderLeft: `1px solid ${resolvedBorder}`,
3929
+ borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3930
+ borderRight: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3931
+ borderBottom: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3932
+ borderLeft: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3524
3933
  padding: "10px",
3525
- borderTopLeftRadius: "8px",
3526
- borderBottomLeftRadius: "8px",
3527
- ...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: "8px" },
3528
- ...isButtons && bStyles.cityInput ? bStyles.cityInput : {}
3529
- }, children: /* @__PURE__ */ jsx6(
3934
+ borderTopLeftRadius: resolvedBorderRadius,
3935
+ borderBottomLeftRadius: resolvedBorderRadius,
3936
+ ...isAVSFieldVisible(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
3937
+ }, children: /* @__PURE__ */ jsx7(
3530
3938
  "input",
3531
3939
  {
3532
3940
  className: "flopay-shared-input",
3941
+ id: "flopay-billing-city",
3942
+ name: "billing-city",
3533
3943
  placeholder: "City",
3534
- autoComplete: "address-level2",
3944
+ autoComplete: "billing address-level2",
3535
3945
  value: city,
3536
3946
  onChange: (e) => {
3537
3947
  cityRef.current = e.target.value;
@@ -3543,39 +3953,42 @@ function SplitCardFormInner({
3543
3953
  style: inputFieldStyle()
3544
3954
  }
3545
3955
  ) }),
3546
- isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx6("div", { style: {
3956
+ isAVSFieldVisible(avsConfig.state, cc) && /* @__PURE__ */ jsx7("div", { style: {
3547
3957
  flex: 1,
3548
3958
  backgroundColor: cardInputBg,
3549
- border: `1px solid ${resolvedBorder}`,
3959
+ border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
3550
3960
  padding: "10px",
3551
- borderTopRightRadius: "8px",
3552
- borderBottomRightRadius: "8px",
3553
- ...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: "8px" },
3554
- ...isButtons && bStyles.stateInput ? bStyles.stateInput : {}
3961
+ borderTopRightRadius: resolvedBorderRadius,
3962
+ borderBottomRightRadius: resolvedBorderRadius,
3963
+ ...isAVSFieldVisible(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
3555
3964
  }, children: stateOpts ? /* @__PURE__ */ jsxs4(
3556
3965
  "select",
3557
3966
  {
3967
+ id: "flopay-billing-state",
3968
+ name: "billing-state",
3558
3969
  value: stateValue,
3559
3970
  onChange: (e) => {
3560
3971
  stateRef.current = e.target.value;
3561
3972
  setStateValue(e.target.value);
3562
3973
  },
3563
3974
  disabled: isSubmitting,
3564
- autoComplete: "address-level1",
3975
+ autoComplete: "billing address-level1",
3565
3976
  required: true,
3566
3977
  "data-testid": "flopay-state",
3567
3978
  style: { ...inputFieldStyle(), cursor: "pointer" },
3568
3979
  children: [
3569
- /* @__PURE__ */ jsx6("option", { value: "", children: getStateLabel(cc) }),
3570
- stateOpts.map((s) => /* @__PURE__ */ jsx6("option", { value: s.code, children: s.name }, s.code))
3980
+ /* @__PURE__ */ jsx7("option", { value: "", children: getStateLabel(cc) }),
3981
+ stateOpts.map((s) => /* @__PURE__ */ jsx7("option", { value: s.code, children: s.name }, s.code))
3571
3982
  ]
3572
3983
  }
3573
- ) : /* @__PURE__ */ jsx6(
3984
+ ) : /* @__PURE__ */ jsx7(
3574
3985
  "input",
3575
3986
  {
3576
3987
  className: "flopay-shared-input",
3988
+ id: "flopay-billing-state",
3989
+ name: "billing-state",
3577
3990
  placeholder: getStateLabel(cc),
3578
- autoComplete: "address-level1",
3991
+ autoComplete: "billing address-level1",
3579
3992
  value: stateValue,
3580
3993
  onChange: (e) => {
3581
3994
  stateRef.current = e.target.value;
@@ -3594,7 +4007,7 @@ function SplitCardFormInner({
3594
4007
  gap: avsLayoutProp === "column" ? "0.5rem" : "0",
3595
4008
  marginTop: "0.5rem"
3596
4009
  }, children: [
3597
- isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx6("div", { style: {
4010
+ isAVSFieldVisible(avsConfig.country, cc) && /* @__PURE__ */ jsx7("div", { style: {
3598
4011
  flex: avsLayoutProp === "row" ? 1 : void 0,
3599
4012
  backgroundColor: cardInputBg,
3600
4013
  borderTop: `1px solid ${resolvedBorder}`,
@@ -3602,11 +4015,12 @@ function SplitCardFormInner({
3602
4015
  borderBottom: `1px solid ${resolvedBorder}`,
3603
4016
  borderLeft: `1px solid ${resolvedBorder}`,
3604
4017
  padding: "10px",
3605
- ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
3606
- ...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
3607
- }, children: /* @__PURE__ */ jsx6(
4018
+ ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
4019
+ }, children: /* @__PURE__ */ jsx7(
3608
4020
  "select",
3609
4021
  {
4022
+ id: "flopay-billing-country",
4023
+ name: "billing-country",
3610
4024
  value: selectedCountry,
3611
4025
  onChange: (e) => {
3612
4026
  selectedCountryRef.current = e.target.value;
@@ -3616,7 +4030,7 @@ function SplitCardFormInner({
3616
4030
  setStateValue("");
3617
4031
  },
3618
4032
  disabled: isSubmitting,
3619
- autoComplete: "country",
4033
+ autoComplete: "billing country",
3620
4034
  "data-testid": "flopay-country",
3621
4035
  style: { ...inputFieldStyle(), cursor: "pointer" },
3622
4036
  children: COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ jsxs4("option", { value: c.code, children: [
@@ -3626,19 +4040,20 @@ function SplitCardFormInner({
3626
4040
  ] }, c.code))
3627
4041
  }
3628
4042
  ) }),
3629
- isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx6("div", { style: {
4043
+ isAVSFieldVisible(avsConfig.postal_code, cc) && /* @__PURE__ */ jsx7("div", { style: {
3630
4044
  flex: avsLayoutProp === "row" ? 1 : void 0,
3631
4045
  backgroundColor: cardInputBg,
3632
- border: `1px solid ${resolvedBorder}`,
4046
+ border: `1px solid ${avsBorderColor(invalidAvsFields.zip)}`,
3633
4047
  padding: "10px",
3634
- ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: "8px", borderBottomRightRadius: "8px" } : { borderRadius: "8px" },
3635
- ...isButtons && bStyles.zipInput ? bStyles.zipInput : {}
3636
- }, children: /* @__PURE__ */ jsx6(
4048
+ ...avsLayoutProp === "row" && isAVSFieldVisible(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
4049
+ }, children: /* @__PURE__ */ jsx7(
3637
4050
  "input",
3638
4051
  {
3639
4052
  className: "flopay-shared-input",
4053
+ id: "flopay-billing-postal-code",
4054
+ name: "billing-postal-code",
3640
4055
  placeholder: getPostalCodeLabel(selectedCountry),
3641
- autoComplete: "postal-code",
4056
+ autoComplete: "billing postal-code",
3642
4057
  value: zipCode,
3643
4058
  onChange: (e) => {
3644
4059
  zipCodeRef.current = e.target.value;
@@ -3653,7 +4068,9 @@ function SplitCardFormInner({
3653
4068
  ) })
3654
4069
  ] })
3655
4070
  ] });
3656
- })(),
4071
+ })() }),
4072
+ vaultActive && cardPreFormSlot && /* @__PURE__ */ jsx7("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
4073
+ vaultActive && vaultCardFieldsNode,
3657
4074
  displayError && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
3658
4075
  margin: "0.75rem 0",
3659
4076
  padding: "0.625rem 0.875rem",
@@ -3668,15 +4085,21 @@ function SplitCardFormInner({
3668
4085
  gap: "0.5rem",
3669
4086
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3670
4087
  }, children: [
3671
- /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx6("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" }) }),
4088
+ /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("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" }) }),
3672
4089
  displayError
3673
4090
  ] }),
3674
- children ?? /* @__PURE__ */ jsx6(
4091
+ !vaultActive && (children ?? /* @__PURE__ */ jsx7(
3675
4092
  "button",
3676
4093
  {
3677
4094
  type: "submit",
3678
4095
  disabled: !formReady || isSubmitting,
3679
4096
  "data-testid": "flopay-submit",
4097
+ onMouseEnter: (e) => {
4098
+ if (formReady && !isSubmitting) e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4099
+ },
4100
+ onMouseLeave: (e) => {
4101
+ e.currentTarget.style.backgroundColor = bStyles.submitButton?.backgroundColor ?? resolvedPrimaryColor;
4102
+ },
3680
4103
  style: {
3681
4104
  width: "100%",
3682
4105
  padding: "0.875rem",
@@ -3689,11 +4112,12 @@ function SplitCardFormInner({
3689
4112
  fontWeight: 600,
3690
4113
  cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
3691
4114
  opacity: !formReady || isSubmitting ? 0.5 : 1,
4115
+ transition: "background-color 0.15s",
3692
4116
  ...bStyles.submitButton
3693
4117
  },
3694
4118
  children: isSubmitting ? "PROCESSING..." : submitLabel
3695
4119
  }
3696
- )
4120
+ ))
3697
4121
  ] });
3698
4122
  const gateDebugStyle = {
3699
4123
  margin: 0,
@@ -3709,9 +4133,9 @@ function SplitCardFormInner({
3709
4133
  const renderDirectPaypalGateDebug = (testId) => {
3710
4134
  if (!debug) return null;
3711
4135
  if (!showPayPal || !directPaypalConfigured) {
3712
- return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
4136
+ return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
3713
4137
  }
3714
- return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4138
+ return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3715
4139
  "FloPay/DirectPayPal-debug (parent gate)",
3716
4140
  ` showPayPal=${showPayPal}`,
3717
4141
  ` directPaypalConfigured=${directPaypalConfigured}`,
@@ -3724,9 +4148,9 @@ function SplitCardFormInner({
3724
4148
  const renderStripeGateDebug = (testId) => {
3725
4149
  if (!debug) return null;
3726
4150
  if (!showStripe || !stripeInstance) {
3727
- return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
4151
+ return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
3728
4152
  }
3729
- return /* @__PURE__ */ jsx6("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4153
+ return /* @__PURE__ */ jsx7("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3730
4154
  "FloPay/Stripe-debug (parent gate)",
3731
4155
  ` showStripe=${showStripe}`,
3732
4156
  ` currency=${currency}`,
@@ -3756,8 +4180,8 @@ function SplitCardFormInner({
3756
4180
  const buttonsAnim = viewState === "expanding" || viewState === "apm-expanding" ? `flopay-buttons-exit ${TRANSITION_MS}ms cubic-bezier(0.4, 0, 0.2, 1) both` : viewState === "collapsing" || viewState === "apm-collapsing" ? `flopay-buttons-enter ${TRANSITION_MS}ms cubic-bezier(0, 0, 0.2, 1) both` : void 0;
3757
4181
  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;
3758
4182
  return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
3759
- /* @__PURE__ */ jsx6(FloPayKeyframes, {}),
3760
- overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4183
+ /* @__PURE__ */ jsx7(FloPayKeyframes, {}),
4184
+ overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
3761
4185
  /* @__PURE__ */ jsxs4("div", { style: { display: "grid" }, children: [
3762
4186
  /* @__PURE__ */ jsxs4(
3763
4187
  "div",
@@ -3777,7 +4201,7 @@ function SplitCardFormInner({
3777
4201
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
3778
4202
  renderStripeGateDebug("flopay-stripe-gate-debug"),
3779
4203
  shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
3780
- paypalDirectRetry && /* @__PURE__ */ jsx6(
4204
+ paypalDirectRetry && /* @__PURE__ */ jsx7(
3781
4205
  "div",
3782
4206
  {
3783
4207
  "data-testid": "flopay-paypal-direct-retry-notice",
@@ -3793,7 +4217,7 @@ function SplitCardFormInner({
3793
4217
  children: "Please confirm your PayPal payment to complete checkout."
3794
4218
  }
3795
4219
  ),
3796
- /* @__PURE__ */ jsx6(
4220
+ /* @__PURE__ */ jsx7(
3797
4221
  DirectPayPalButton,
3798
4222
  {
3799
4223
  sessionId,
@@ -3819,7 +4243,7 @@ function SplitCardFormInner({
3819
4243
  paypalDirectRetry?.orderId ?? "fresh"
3820
4244
  )
3821
4245
  ] }),
3822
- shouldRenderStripePayPal && /* @__PURE__ */ jsx6(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx6(
4246
+ shouldRenderStripePayPal && /* @__PURE__ */ jsx7(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx7(
3823
4247
  PayPalButtonInner,
3824
4248
  {
3825
4249
  sessionId,
@@ -3833,10 +4257,10 @@ function SplitCardFormInner({
3833
4257
  onDecline,
3834
4258
  runBeforeButtonClick,
3835
4259
  onLoadStateChange: setPaypalLoadState,
3836
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4260
+ placeholderBorderRadius: buttonBorderRadius
3837
4261
  }
3838
4262
  ) }),
3839
- shouldRenderWallets ? /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
4263
+ shouldRenderWallets ? /* @__PURE__ */ jsx7(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx7(
3840
4264
  WalletButtonInner,
3841
4265
  {
3842
4266
  sessionId,
@@ -3850,10 +4274,10 @@ function SplitCardFormInner({
3850
4274
  onDecline,
3851
4275
  runBeforeButtonClick,
3852
4276
  onLoadStateChange: setWalletLoadState,
3853
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4277
+ placeholderBorderRadius: buttonBorderRadius
3854
4278
  }
3855
- ) }) : shouldShowWallets ? /* @__PURE__ */ jsx6("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
3856
- shouldRenderPaymentElement && /* @__PURE__ */ jsx6(
4279
+ ) }) : shouldShowWallets ? /* @__PURE__ */ jsx7("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
4280
+ shouldRenderPaymentElement && /* @__PURE__ */ jsx7(
3857
4281
  StripePaymentElementInner,
3858
4282
  {
3859
4283
  sessionId,
@@ -3881,11 +4305,11 @@ function SplitCardFormInner({
3881
4305
  backgroundColor: bStyles.cardButton?.backgroundColor,
3882
4306
  borderColor: bStyles.cardInputBorder,
3883
4307
  textColor: bStyles.cardButton?.color,
3884
- borderRadius: bStyles.cardButton?.borderRadius
4308
+ borderRadius: buttonBorderRadius
3885
4309
  }
3886
4310
  }
3887
4311
  ),
3888
- showStripe && /* @__PURE__ */ jsx6(
4312
+ showStripe && /* @__PURE__ */ jsx7(
3889
4313
  "button",
3890
4314
  {
3891
4315
  type: "button",
@@ -3913,7 +4337,8 @@ function SplitCardFormInner({
3913
4337
  themeBundle,
3914
4338
  resolvedPrimaryColor,
3915
4339
  resolvedBorderRadius,
3916
- submitButtonStyle: bStyles.submitButton
4340
+ submitButtonStyle: bStyles.submitButton,
4341
+ explicitPrimaryColor: appearanceVars?.colorPrimary
3917
4342
  }),
3918
4343
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
3919
4344
  fontWeight: 600,
@@ -3922,17 +4347,25 @@ function SplitCardFormInner({
3922
4347
  alignItems: "center",
3923
4348
  justifyContent: "center",
3924
4349
  gap: "0.625rem",
3925
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
4350
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
3926
4351
  position: "relative",
3927
4352
  opacity: isSubmitting ? 0.6 : 1
3928
4353
  },
4354
+ onMouseEnter: (e) => {
4355
+ if (!isSubmitting && (themeBundle || appearanceVars?.colorPrimary)) {
4356
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4357
+ }
4358
+ },
4359
+ onMouseLeave: (e) => {
4360
+ if (themeBundle || appearanceVars?.colorPrimary) e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
4361
+ },
3929
4362
  onMouseDown: (e) => {
3930
4363
  e.currentTarget.style.transform = "scale(0.985)";
3931
4364
  },
3932
4365
  onMouseUp: (e) => {
3933
4366
  e.currentTarget.style.transform = "scale(1)";
3934
4367
  },
3935
- children: /* @__PURE__ */ jsx6(CardButtonContentSlot, { content: cardButtonContent })
4368
+ children: /* @__PURE__ */ jsx7(CardButtonContentSlot, { content: cardButtonContent })
3936
4369
  }
3937
4370
  ),
3938
4371
  displayError && viewState === "buttons" && /* @__PURE__ */ jsxs4("div", { role: "alert", "data-testid": "flopay-error", style: {
@@ -3949,18 +4382,18 @@ function SplitCardFormInner({
3949
4382
  gap: "0.5rem",
3950
4383
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3951
4384
  }, children: [
3952
- /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx6("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" }) }),
4385
+ /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("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" }) }),
3953
4386
  displayError
3954
4387
  ] })
3955
4388
  ]
3956
4389
  }
3957
4390
  ),
3958
- showStripe && isCardView && /* @__PURE__ */ jsx6("div", { style: {
4391
+ showStripe && isCardView && /* @__PURE__ */ jsx7("div", { style: {
3959
4392
  gridArea: "1 / 1",
3960
4393
  ...cardAnim ? { animation: cardAnim } : {},
3961
4394
  ...viewState === "collapsing" ? { pointerEvents: "none" } : {}
3962
4395
  }, children: cardFormBlock }),
3963
- showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ jsx6("div", { style: {
4396
+ showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ jsx7("div", { style: {
3964
4397
  gridArea: "1 / 1",
3965
4398
  ...apmAnim ? { animation: apmAnim } : {},
3966
4399
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
@@ -3998,7 +4431,7 @@ function SplitCardFormInner({
3998
4431
  },
3999
4432
  "aria-label": "Back to payment methods",
4000
4433
  children: [
4001
- /* @__PURE__ */ jsx6("span", { style: {
4434
+ /* @__PURE__ */ jsx7("span", { style: {
4002
4435
  display: "inline-flex",
4003
4436
  alignItems: "center",
4004
4437
  justifyContent: "center",
@@ -4008,12 +4441,12 @@ function SplitCardFormInner({
4008
4441
  backgroundColor: "#f3f4f6",
4009
4442
  transition: "background-color 0.15s",
4010
4443
  ...bStyles.backButtonIcon
4011
- }, children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 18l-6-6 6-6" }) }) }),
4012
- /* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
4444
+ }, children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M15 18l-6-6 6-6" }) }) }),
4445
+ /* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
4013
4446
  ]
4014
4447
  }
4015
4448
  ),
4016
- /* @__PURE__ */ jsx6("div", { style: {
4449
+ /* @__PURE__ */ jsx7("div", { style: {
4017
4450
  flex: 1,
4018
4451
  textAlign: "center",
4019
4452
  fontWeight: 600,
@@ -4023,12 +4456,12 @@ function SplitCardFormInner({
4023
4456
  ...bStyles.title
4024
4457
  }, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
4025
4458
  ] }),
4026
- /* @__PURE__ */ jsx6(
4459
+ /* @__PURE__ */ jsx7(
4027
4460
  StripeElements,
4028
4461
  {
4029
4462
  stripe: stripeInstance,
4030
4463
  options: apmInlineOptions,
4031
- children: /* @__PURE__ */ jsx6(
4464
+ children: /* @__PURE__ */ jsx7(
4032
4465
  StripeMethodInlineForm,
4033
4466
  {
4034
4467
  method: expandedApmMethod,
@@ -4046,7 +4479,8 @@ function SplitCardFormInner({
4046
4479
  isProcessing: isSubmitting,
4047
4480
  submitButtonColor: resolvedPrimaryColor,
4048
4481
  submitButtonBorderRadius: resolvedBorderRadius,
4049
- submitButtonStyle: bStyles.submitButton
4482
+ submitButtonStyle: bStyles.submitButton,
4483
+ errorText: displayError
4050
4484
  }
4051
4485
  )
4052
4486
  },
@@ -4058,9 +4492,9 @@ function SplitCardFormInner({
4058
4492
  }
4059
4493
  if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
4060
4494
  return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4061
- /* @__PURE__ */ jsx6(FloPayKeyframes, {}),
4062
- overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4063
- /* @__PURE__ */ jsx6("div", { style: {
4495
+ /* @__PURE__ */ jsx7(FloPayKeyframes, {}),
4496
+ overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4497
+ /* @__PURE__ */ jsx7("div", { style: {
4064
4498
  ...apmAnim ? { animation: apmAnim } : {},
4065
4499
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
4066
4500
  }, children: /* @__PURE__ */ jsxs4("div", { style: {
@@ -4097,7 +4531,7 @@ function SplitCardFormInner({
4097
4531
  },
4098
4532
  "aria-label": "Back to payment methods",
4099
4533
  children: [
4100
- /* @__PURE__ */ jsx6("span", { style: {
4534
+ /* @__PURE__ */ jsx7("span", { style: {
4101
4535
  display: "inline-flex",
4102
4536
  alignItems: "center",
4103
4537
  justifyContent: "center",
@@ -4107,12 +4541,12 @@ function SplitCardFormInner({
4107
4541
  backgroundColor: "#f3f4f6",
4108
4542
  transition: "background-color 0.15s",
4109
4543
  ...bStyles.backButtonIcon
4110
- }, children: /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 18l-6-6 6-6" }) }) }),
4111
- /* @__PURE__ */ jsx6(BackButtonContentSlot, { content: cardBackButtonContent })
4544
+ }, children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M15 18l-6-6 6-6" }) }) }),
4545
+ /* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
4112
4546
  ]
4113
4547
  }
4114
4548
  ),
4115
- /* @__PURE__ */ jsx6("div", { style: {
4549
+ /* @__PURE__ */ jsx7("div", { style: {
4116
4550
  flex: 1,
4117
4551
  textAlign: "center",
4118
4552
  fontWeight: 600,
@@ -4122,12 +4556,12 @@ function SplitCardFormInner({
4122
4556
  ...bStyles.title
4123
4557
  }, children: `Pay with ${getStripeMethodDisplayName(expandedApmMethod)}` })
4124
4558
  ] }),
4125
- /* @__PURE__ */ jsx6(
4559
+ /* @__PURE__ */ jsx7(
4126
4560
  StripeElements,
4127
4561
  {
4128
4562
  stripe: stripeInstance,
4129
4563
  options: apmInlineOptions,
4130
- children: /* @__PURE__ */ jsx6(
4564
+ children: /* @__PURE__ */ jsx7(
4131
4565
  StripeMethodInlineForm,
4132
4566
  {
4133
4567
  method: expandedApmMethod,
@@ -4145,7 +4579,8 @@ function SplitCardFormInner({
4145
4579
  isProcessing: isSubmitting,
4146
4580
  submitButtonColor: resolvedPrimaryColor,
4147
4581
  submitButtonBorderRadius: resolvedBorderRadius,
4148
- submitButtonStyle: bStyles.submitButton
4582
+ submitButtonStyle: bStyles.submitButton,
4583
+ errorText: displayError
4149
4584
  }
4150
4585
  )
4151
4586
  },
@@ -4155,13 +4590,13 @@ function SplitCardFormInner({
4155
4590
  ] });
4156
4591
  }
4157
4592
  return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4158
- /* @__PURE__ */ jsx6(FloPayKeyframes, {}),
4159
- overlayStatus && /* @__PURE__ */ jsx6(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4593
+ /* @__PURE__ */ jsx7(FloPayKeyframes, {}),
4594
+ overlayStatus && /* @__PURE__ */ jsx7(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4160
4595
  /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4161
4596
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
4162
4597
  renderStripeGateDebug("flopay-stripe-gate-debug-default"),
4163
4598
  shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ jsxs4(Fragment2, { children: [
4164
- paypalDirectRetry && /* @__PURE__ */ jsx6(
4599
+ paypalDirectRetry && /* @__PURE__ */ jsx7(
4165
4600
  "div",
4166
4601
  {
4167
4602
  "data-testid": "flopay-paypal-direct-retry-notice-default",
@@ -4177,7 +4612,7 @@ function SplitCardFormInner({
4177
4612
  children: "Please confirm your PayPal payment to complete checkout."
4178
4613
  }
4179
4614
  ),
4180
- /* @__PURE__ */ jsx6(
4615
+ /* @__PURE__ */ jsx7(
4181
4616
  DirectPayPalButton,
4182
4617
  {
4183
4618
  sessionId,
@@ -4203,7 +4638,7 @@ function SplitCardFormInner({
4203
4638
  paypalDirectRetry?.orderId ?? "fresh"
4204
4639
  )
4205
4640
  ] }),
4206
- shouldRenderStripePayPal && /* @__PURE__ */ jsx6(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx6(
4641
+ shouldRenderStripePayPal && /* @__PURE__ */ jsx7(StripeElements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ jsx7(
4207
4642
  PayPalButtonInner,
4208
4643
  {
4209
4644
  sessionId,
@@ -4217,10 +4652,10 @@ function SplitCardFormInner({
4217
4652
  onDecline,
4218
4653
  runBeforeButtonClick,
4219
4654
  onLoadStateChange: setPaypalLoadState,
4220
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4655
+ placeholderBorderRadius: buttonBorderRadius
4221
4656
  }
4222
4657
  ) }),
4223
- shouldRenderWallets && /* @__PURE__ */ jsx6(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx6(
4658
+ shouldRenderWallets && /* @__PURE__ */ jsx7(StripeElements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ jsx7(
4224
4659
  WalletButtonInner,
4225
4660
  {
4226
4661
  sessionId,
@@ -4234,10 +4669,10 @@ function SplitCardFormInner({
4234
4669
  onDecline,
4235
4670
  runBeforeButtonClick,
4236
4671
  onLoadStateChange: setWalletLoadState,
4237
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4672
+ placeholderBorderRadius: buttonBorderRadius
4238
4673
  }
4239
4674
  ) }),
4240
- shouldRenderPaymentElement && /* @__PURE__ */ jsx6(
4675
+ shouldRenderPaymentElement && /* @__PURE__ */ jsx7(
4241
4676
  StripePaymentElementInner,
4242
4677
  {
4243
4678
  sessionId,
@@ -4265,7 +4700,7 @@ function SplitCardFormInner({
4265
4700
  backgroundColor: bStyles.cardButton?.backgroundColor,
4266
4701
  borderColor: bStyles.cardInputBorder,
4267
4702
  textColor: bStyles.cardButton?.color,
4268
- borderRadius: bStyles.cardButton?.borderRadius
4703
+ borderRadius: buttonBorderRadius
4269
4704
  }
4270
4705
  }
4271
4706
  )
@@ -4278,9 +4713,9 @@ function SplitCardFormInner({
4278
4713
  color: "#999",
4279
4714
  fontSize: "0.85rem"
4280
4715
  }, children: [
4281
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
4282
- /* @__PURE__ */ jsx6("span", { children: "or pay with card" }),
4283
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
4716
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
4717
+ /* @__PURE__ */ jsx7("span", { children: "or pay with card" }),
4718
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
4284
4719
  ] }),
4285
4720
  showStripe && cardFormBlock
4286
4721
  ] });
@@ -4288,8 +4723,28 @@ function SplitCardFormInner({
4288
4723
 
4289
4724
  // src/saved-payment-flow.ts
4290
4725
  import { loadFloPay, PaymentAPI as PaymentAPI3 } from "@flopay/js";
4291
- import { FloPayError as FloPayError4 } from "@flopay/shared";
4726
+ import { FloPayError as FloPayError4, isSetupIntentClientSecret as isSetupIntentClientSecret3 } from "@flopay/shared";
4292
4727
  var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
4728
+ async function retrieveResumeIntent(stripe, clientSecret, isSetupIntent) {
4729
+ if (isSetupIntent) {
4730
+ if (typeof stripe.retrieveSetupIntent !== "function") return null;
4731
+ const { setupIntent, error: error2 } = await stripe.retrieveSetupIntent(clientSecret);
4732
+ return { error: error2, intent: setupIntent ?? null };
4733
+ }
4734
+ if (typeof stripe.retrievePaymentIntent !== "function") return null;
4735
+ const { paymentIntent, error } = await stripe.retrievePaymentIntent(clientSecret);
4736
+ return { error, intent: paymentIntent ?? null };
4737
+ }
4738
+ async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
4739
+ if (isSetupIntent) {
4740
+ if (typeof stripe.confirmCardSetup !== "function") return null;
4741
+ const { setupIntent, error: error2 } = await stripe.confirmCardSetup(clientSecret, data);
4742
+ return { error: error2, intent: setupIntent ?? null };
4743
+ }
4744
+ if (typeof stripe.confirmCardPayment !== "function") return null;
4745
+ const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
4746
+ return { error, intent: paymentIntent ?? null };
4747
+ }
4293
4748
  function getRedirectResultFromCheckoutProcessError(error) {
4294
4749
  if (!error?.type || !error.threeDSecureToken) {
4295
4750
  return null;
@@ -4303,6 +4758,210 @@ function getRedirectResultFromCheckoutProcessError(error) {
4303
4758
  paymentMethodId: error.paymentMethodId
4304
4759
  };
4305
4760
  }
4761
+ function isTerminalAutoCheckoutThreeDsOutcome(outcome) {
4762
+ return outcome.status === "succeeded" || outcome.status === "declined";
4763
+ }
4764
+ async function runAutoCheckoutThreeDsChallenge(input) {
4765
+ if (typeof document === "undefined" || typeof window === "undefined") {
4766
+ throw new FloPayError4("3DS challenge requires a browser environment.", "api_error", {
4767
+ code: "three_ds_no_window"
4768
+ });
4769
+ }
4770
+ if (input.signal?.aborted) {
4771
+ throw new FloPayError4("Card authentication was cancelled.", "api_error", {
4772
+ code: "three_ds_aborted"
4773
+ });
4774
+ }
4775
+ const CHALLENGE_TIMEOUT_MS = 3e5;
4776
+ const CHALLENGE_POLL_INTERVAL_MS = 1e3;
4777
+ const COMPLETE_REQUEST_TIMEOUT_MS = 15e3;
4778
+ const completionEndpoint = `${input.billingApiUrl.replace(/\/$/, "")}/v1/checkouts/sessions/${encodeURIComponent(
4779
+ input.sessionId
4780
+ )}/3ds/complete`;
4781
+ const completeThreeDs = async () => {
4782
+ const controller = new AbortController();
4783
+ const onParentAbort = () => controller.abort();
4784
+ if (input.signal?.aborted) {
4785
+ controller.abort();
4786
+ } else {
4787
+ input.signal?.addEventListener("abort", onParentAbort);
4788
+ }
4789
+ const requestTimeout = window.setTimeout(() => controller.abort(), COMPLETE_REQUEST_TIMEOUT_MS);
4790
+ try {
4791
+ const response = await fetch(completionEndpoint, {
4792
+ method: "POST",
4793
+ headers: {
4794
+ "x-checkout-session-token": input.nonce,
4795
+ "content-type": "application/json"
4796
+ },
4797
+ body: "{}",
4798
+ signal: controller.signal
4799
+ });
4800
+ if (!response.ok) {
4801
+ return { status: "unknown" };
4802
+ }
4803
+ const json = await response.json().catch(() => null);
4804
+ return coerceThreeDsOutcome(json);
4805
+ } catch {
4806
+ return { status: "unknown" };
4807
+ } finally {
4808
+ window.clearTimeout(requestTimeout);
4809
+ input.signal?.removeEventListener("abort", onParentAbort);
4810
+ }
4811
+ };
4812
+ const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4813
+ const backdrop = document.createElement("div");
4814
+ backdrop.setAttribute("data-flopay-auto-3ds-overlay", "1");
4815
+ backdrop.setAttribute("role", "dialog");
4816
+ backdrop.setAttribute("aria-modal", "true");
4817
+ backdrop.setAttribute("aria-label", "Card authentication");
4818
+ backdrop.style.cssText = [
4819
+ "position:fixed",
4820
+ "inset:0",
4821
+ "z-index:2147483647",
4822
+ "background:rgba(15,23,42,0.6)",
4823
+ "display:flex",
4824
+ "align-items:center",
4825
+ "justify-content:center",
4826
+ "padding:16px"
4827
+ ].join(";");
4828
+ const frame = document.createElement("iframe");
4829
+ frame.setAttribute("title", "Card authentication");
4830
+ frame.setAttribute("allow", "payment");
4831
+ frame.tabIndex = 0;
4832
+ frame.style.cssText = [
4833
+ "width:min(100%,460px)",
4834
+ "height:min(100%,640px)",
4835
+ "border:0",
4836
+ "border-radius:12px",
4837
+ "background:#fff",
4838
+ "box-shadow:0 12px 30px rgba(0,0,0,0.35)"
4839
+ ].join(";");
4840
+ frame.src = input.nextActionRedirectUrl;
4841
+ backdrop.appendChild(frame);
4842
+ document.body.appendChild(backdrop);
4843
+ frame.focus();
4844
+ let expectedReturnOrigin = null;
4845
+ try {
4846
+ expectedReturnOrigin = new URL(input.billingApiUrl, window.location.href).origin;
4847
+ } catch {
4848
+ expectedReturnOrigin = null;
4849
+ }
4850
+ try {
4851
+ const polledOutcome = await new Promise((resolve, reject) => {
4852
+ let settled = false;
4853
+ let timer = 0;
4854
+ let pollTimer = 0;
4855
+ let loadPollTimer = 0;
4856
+ let pollInFlight = false;
4857
+ const cleanup = () => {
4858
+ window.clearTimeout(timer);
4859
+ window.clearInterval(pollTimer);
4860
+ window.clearTimeout(loadPollTimer);
4861
+ window.removeEventListener("message", listener);
4862
+ frame.removeEventListener("load", onFrameLoad);
4863
+ input.signal?.removeEventListener("abort", onAbort);
4864
+ };
4865
+ const maybeResolveFromBackend = async () => {
4866
+ if (settled || pollInFlight) return;
4867
+ pollInFlight = true;
4868
+ try {
4869
+ const outcome = await completeThreeDs();
4870
+ if (settled || !isTerminalAutoCheckoutThreeDsOutcome(outcome)) return;
4871
+ settled = true;
4872
+ cleanup();
4873
+ resolve(outcome);
4874
+ } finally {
4875
+ pollInFlight = false;
4876
+ }
4877
+ };
4878
+ const onFrameLoad = () => {
4879
+ window.clearTimeout(loadPollTimer);
4880
+ loadPollTimer = window.setTimeout(() => {
4881
+ void maybeResolveFromBackend();
4882
+ }, 250);
4883
+ };
4884
+ const onAbort = () => {
4885
+ if (settled) return;
4886
+ settled = true;
4887
+ cleanup();
4888
+ reject(
4889
+ new FloPayError4("Card authentication was cancelled.", "api_error", {
4890
+ code: "three_ds_aborted"
4891
+ })
4892
+ );
4893
+ };
4894
+ const listener = (event) => {
4895
+ if (event.source !== frame.contentWindow) return;
4896
+ if (expectedReturnOrigin && event.origin !== expectedReturnOrigin) return;
4897
+ const data = event.data;
4898
+ if (!data || typeof data !== "object") return;
4899
+ const record = data;
4900
+ if (record["source"] !== "flopay-vault-3ds-return") return;
4901
+ if (settled) return;
4902
+ settled = true;
4903
+ cleanup();
4904
+ resolve(null);
4905
+ };
4906
+ timer = window.setTimeout(() => {
4907
+ if (settled) return;
4908
+ settled = true;
4909
+ cleanup();
4910
+ reject(
4911
+ new FloPayError4("Card authentication timed out.", "api_error", {
4912
+ code: "three_ds_timeout"
4913
+ })
4914
+ );
4915
+ }, CHALLENGE_TIMEOUT_MS);
4916
+ pollTimer = window.setInterval(() => {
4917
+ void maybeResolveFromBackend();
4918
+ }, CHALLENGE_POLL_INTERVAL_MS);
4919
+ frame.addEventListener("load", onFrameLoad);
4920
+ window.addEventListener("message", listener);
4921
+ input.signal?.addEventListener("abort", onAbort);
4922
+ if (input.signal?.aborted) onAbort();
4923
+ });
4924
+ if (polledOutcome) {
4925
+ return polledOutcome;
4926
+ }
4927
+ return await completeThreeDs();
4928
+ } finally {
4929
+ backdrop.parentNode?.removeChild(backdrop);
4930
+ if (previousFocus?.isConnected) {
4931
+ previousFocus.focus();
4932
+ }
4933
+ }
4934
+ }
4935
+ function coerceThreeDsOutcome(json) {
4936
+ if (!json || typeof json !== "object") return { status: "unknown" };
4937
+ const status = typeof json["status"] === "string" ? json["status"] : "unknown";
4938
+ const providerIntentId = typeof json["providerIntentId"] === "string" ? json["providerIntentId"] : null;
4939
+ switch (status) {
4940
+ case "succeeded":
4941
+ return { status: "succeeded", providerIntentId };
4942
+ case "declined":
4943
+ return {
4944
+ status: "declined",
4945
+ providerIntentId,
4946
+ declineReason: typeof json["declineReason"] === "string" ? json["declineReason"] : null,
4947
+ gatewayDeclineReason: typeof json["gatewayDeclineReason"] === "string" ? json["gatewayDeclineReason"] : null
4948
+ };
4949
+ case "requires_action":
4950
+ return {
4951
+ status: "requires_action",
4952
+ providerIntentId,
4953
+ nextActionRedirectUrl: typeof json["nextActionRedirectUrl"] === "string" ? json["nextActionRedirectUrl"] : null
4954
+ };
4955
+ case "pending":
4956
+ return { status: "pending", providerIntentId };
4957
+ case "timeout":
4958
+ return { status: "timeout", providerIntentId };
4959
+ case "no_attempt":
4960
+ return { status: "no_attempt" };
4961
+ default:
4962
+ return { status: "unknown" };
4963
+ }
4964
+ }
4306
4965
  function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
4307
4966
  const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
4308
4967
  const rawMessage = error?.message ?? fallbackMessage;
@@ -4525,64 +5184,66 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
4525
5184
  { checkoutMethod: "card" }
4526
5185
  );
4527
5186
  }
5187
+ const isSetupIntent = isSetupIntentClientSecret3(redirectResult.threeDSecureToken);
4528
5188
  let paymentIntent = null;
4529
5189
  let savedPaymentMethodId = redirectResult.paymentMethodId;
4530
- if (typeof stripe.retrievePaymentIntent === "function") {
4531
- const { paymentIntent: existingPaymentIntent, error: retrieveError } = await stripe.retrievePaymentIntent(
4532
- redirectResult.threeDSecureToken
4533
- );
4534
- if (retrieveError) {
5190
+ const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
5191
+ if (retrieved) {
5192
+ if (retrieved.error) {
4535
5193
  throw Object.assign(
4536
5194
  new FloPayError4(
4537
- retrieveError.message ?? "Failed to retrieve 3DS payment status.",
5195
+ retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
4538
5196
  "api_error",
4539
- { code: retrieveError.code }
5197
+ { code: retrieved.error.code }
4540
5198
  ),
4541
5199
  { checkoutMethod: "card" }
4542
5200
  );
4543
5201
  }
4544
- if (!savedPaymentMethodId && existingPaymentIntent?.payment_method) {
4545
- if (typeof existingPaymentIntent.payment_method === "string") {
4546
- savedPaymentMethodId = existingPaymentIntent.payment_method;
4547
- } else if ("id" in existingPaymentIntent.payment_method) {
4548
- savedPaymentMethodId = existingPaymentIntent.payment_method.id;
5202
+ const existingIntent = retrieved.intent;
5203
+ if (!savedPaymentMethodId && existingIntent?.payment_method) {
5204
+ if (typeof existingIntent.payment_method === "string") {
5205
+ savedPaymentMethodId = existingIntent.payment_method;
5206
+ } else if ("id" in existingIntent.payment_method) {
5207
+ savedPaymentMethodId = existingIntent.payment_method.id ?? void 0;
4549
5208
  }
4550
5209
  }
4551
5210
  }
4552
- if (savedPaymentMethodId && typeof stripe.confirmCardPayment === "function") {
4553
- const { error: confirmError, paymentIntent: confirmedPaymentIntent } = await stripe.confirmCardPayment(
4554
- redirectResult.threeDSecureToken,
4555
- {
4556
- payment_method: savedPaymentMethodId,
4557
- return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
4558
- }
4559
- );
4560
- if (confirmError) {
5211
+ const confirmed = savedPaymentMethodId ? await confirmResumeIntent(
5212
+ stripe,
5213
+ redirectResult.threeDSecureToken,
5214
+ {
5215
+ payment_method: savedPaymentMethodId,
5216
+ return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
5217
+ },
5218
+ isSetupIntent
5219
+ ) : null;
5220
+ if (confirmed) {
5221
+ if (confirmed.error) {
4561
5222
  throw Object.assign(
4562
5223
  new FloPayError4(
4563
- confirmError.message ?? "3DS authentication failed.",
5224
+ confirmed.error.message ?? "3DS authentication failed.",
4564
5225
  "api_error",
4565
- { code: confirmError.code }
5226
+ { code: confirmed.error.code }
4566
5227
  ),
4567
5228
  { checkoutMethod: "card" }
4568
5229
  );
4569
5230
  }
4570
- paymentIntent = confirmedPaymentIntent ?? null;
5231
+ paymentIntent = confirmed.intent;
4571
5232
  } else {
4572
- const { error: nextActionError, paymentIntent: nextActionPaymentIntent } = await stripe.handleNextAction({
5233
+ const nextAction = await stripe.handleNextAction({
4573
5234
  clientSecret: redirectResult.threeDSecureToken
4574
5235
  });
4575
- if (nextActionError) {
5236
+ if (nextAction.error) {
4576
5237
  throw Object.assign(
4577
5238
  new FloPayError4(
4578
- nextActionError.message ?? "3DS authentication failed.",
5239
+ nextAction.error.message ?? "3DS authentication failed.",
4579
5240
  "api_error",
4580
- { code: nextActionError.code }
5241
+ { code: nextAction.error.code }
4581
5242
  ),
4582
5243
  { checkoutMethod: "card" }
4583
5244
  );
4584
5245
  }
4585
- paymentIntent = nextActionPaymentIntent ?? null;
5246
+ paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
4586
5247
  }
4587
5248
  if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
4588
5249
  const followUp = await processSavedPaymentForMode({
@@ -4742,7 +5403,7 @@ async function loadSavedPaymentProviders({
4742
5403
  }
4743
5404
 
4744
5405
  // src/flopay-checkout.tsx
4745
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
5406
+ import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
4746
5407
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
4747
5408
  var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
4748
5409
  var sessionInflightMap = /* @__PURE__ */ new Map();
@@ -4791,6 +5452,36 @@ function clearPayPalResumeState() {
4791
5452
  console.warn("[FloPayCheckout] Failed to clear PayPal resume state.", error);
4792
5453
  }
4793
5454
  }
5455
+ function readCachedInlineSession(cacheKey) {
5456
+ if (!canUseStorage()) return null;
5457
+ const raw = window.sessionStorage.getItem(cacheKey);
5458
+ if (!raw) return null;
5459
+ try {
5460
+ const parsed = JSON.parse(raw);
5461
+ if (parsed && typeof parsed.sid === "string" && parsed.sid) {
5462
+ return { sid: parsed.sid, nonce: typeof parsed.nonce === "string" ? parsed.nonce : void 0 };
5463
+ }
5464
+ return null;
5465
+ } catch {
5466
+ return { sid: raw };
5467
+ }
5468
+ }
5469
+ function persistCachedInlineSession(cacheKey, sid, nonce) {
5470
+ if (!canUseStorage()) return;
5471
+ try {
5472
+ window.sessionStorage.setItem(cacheKey, JSON.stringify(nonce ? { sid, nonce } : { sid }));
5473
+ } catch (error) {
5474
+ console.warn("[FloPayCheckout] Failed to persist checkout session cache.", error);
5475
+ }
5476
+ }
5477
+ function clearCachedInlineSession(cacheKey) {
5478
+ if (!canUseStorage()) return;
5479
+ try {
5480
+ window.sessionStorage.removeItem(cacheKey);
5481
+ } catch (error) {
5482
+ console.warn("[FloPayCheckout] Failed to clear checkout session cache.", error);
5483
+ }
5484
+ }
4794
5485
  function clearPayPalRedirectParams() {
4795
5486
  if (typeof window === "undefined") return;
4796
5487
  const url = new URL(window.location.href);
@@ -4849,6 +5540,8 @@ function FloPayCheckout({
4849
5540
  onButtonClick,
4850
5541
  onBeforeButtonClick,
4851
5542
  enableAVS,
5543
+ cardFieldOrder,
5544
+ cardPreFormSlot,
4852
5545
  avsLayout,
4853
5546
  submitLabel,
4854
5547
  className,
@@ -4866,9 +5559,9 @@ function FloPayCheckout({
4866
5559
  const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
4867
5560
  const [unified, setUnified] = useState4(null);
4868
5561
  const [flopay, setFloPay] = useState4(null);
4869
- const flopayRef = useRef4(null);
5562
+ const flopayRef = useRef5(null);
4870
5563
  const [paypalFlopay, setPaypalFloPay] = useState4(null);
4871
- const paypalFlopayRef = useRef4(null);
5564
+ const paypalFlopayRef = useRef5(null);
4872
5565
  const [session, setSession] = useState4(null);
4873
5566
  const [resolvedSessionId, setResolvedSessionId] = useState4(sessionIdProp ?? "");
4874
5567
  const activeSessionId = sessionIdProp ?? resolvedSessionId;
@@ -4883,18 +5576,18 @@ function FloPayCheckout({
4883
5576
  const [createSessionPatch, setCreateSessionPatch] = useState4(void 0);
4884
5577
  const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = useState4("");
4885
5578
  const [cardBootstrapPending, setCardBootstrapPending] = useState4(false);
4886
- const autoCheckoutAttempted = useRef4(false);
4887
- const paypalResumeAttempted = useRef4(false);
4888
- const savedPaymentKeysRef = useRef4(null);
4889
- const onCompleteRef = useRef4(onComplete);
5579
+ const autoCheckoutAttempted = useRef5(false);
5580
+ const paypalResumeAttempted = useRef5(false);
5581
+ const savedPaymentKeysRef = useRef5(null);
5582
+ const onCompleteRef = useRef5(onComplete);
4890
5583
  onCompleteRef.current = onComplete;
4891
- const onErrorRef = useRef4(onError);
5584
+ const onErrorRef = useRef5(onError);
4892
5585
  onErrorRef.current = onError;
4893
- const onDeclineRef = useRef4(onDecline);
5586
+ const onDeclineRef = useRef5(onDecline);
4894
5587
  onDeclineRef.current = onDecline;
4895
- const onSessionCompletedRef = useRef4(onSessionCompleted);
5588
+ const onSessionCompletedRef = useRef5(onSessionCompleted);
4896
5589
  onSessionCompletedRef.current = onSessionCompleted;
4897
- useEffect5(() => {
5590
+ useEffect6(() => {
4898
5591
  console.info("[FloPay] Checkout initialized", {
4899
5592
  sdk_version: SDK_VERSION,
4900
5593
  checkout_type: checkoutType,
@@ -4922,11 +5615,11 @@ function FloPayCheckout({
4922
5615
  } : void 0,
4923
5616
  [effectiveCreateSessionBase, effectiveCreateSessionMode]
4924
5617
  );
4925
- useEffect5(() => {
5618
+ useEffect6(() => {
4926
5619
  setCreateSessionPatch(void 0);
4927
5620
  setCreateSessionPatchBaseHash(baseCreateSessionHash);
4928
5621
  }, [baseCreateSessionHash]);
4929
- useEffect5(() => {
5622
+ useEffect6(() => {
4930
5623
  setModeError(initialErrorMessage);
4931
5624
  }, [initialErrorMessage]);
4932
5625
  const emitDecline = useCallback2(
@@ -5053,7 +5746,7 @@ function FloPayCheckout({
5053
5746
  resolvedBillingUrl
5054
5747
  ]
5055
5748
  );
5056
- useEffect5(() => {
5749
+ useEffect6(() => {
5057
5750
  if (typeof window === "undefined" || paypalResumeAttempted.current) {
5058
5751
  return;
5059
5752
  }
@@ -5170,7 +5863,7 @@ function FloPayCheckout({
5170
5863
  }
5171
5864
  })();
5172
5865
  }, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
5173
- const initializedHashRef = useRef4(null);
5866
+ const initializedHashRef = useRef5(null);
5174
5867
  function hashCreateParams(params) {
5175
5868
  const key = JSON.stringify({
5176
5869
  c: params?.clientId,
@@ -5207,12 +5900,12 @@ function FloPayCheckout({
5207
5900
  () => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
5208
5901
  [effectiveCreateSession]
5209
5902
  );
5210
- const createSessionParamsRef = useRef4(effectiveCreateSession);
5903
+ const createSessionParamsRef = useRef5(effectiveCreateSession);
5211
5904
  createSessionParamsRef.current = effectiveCreateSession;
5212
- useEffect5(() => {
5905
+ useEffect6(() => {
5213
5906
  setResolvedSessionId(sessionIdProp ?? "");
5214
5907
  }, [sessionIdProp]);
5215
- useEffect5(() => {
5908
+ useEffect6(() => {
5216
5909
  autoCheckoutAttempted.current = false;
5217
5910
  setModeError(initialErrorMessage);
5218
5911
  setModeOverlayError(null);
@@ -5220,22 +5913,23 @@ function FloPayCheckout({
5220
5913
  }, [createSessionHash, initialErrorMessage, sessionIdProp]);
5221
5914
  async function resolveInlineSession(params, cacheKey) {
5222
5915
  const api = new PaymentAPI4(resolvedBillingUrl);
5223
- let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
5916
+ const cached = readCachedInlineSession(cacheKey);
5917
+ let sid = cached?.sid ?? null;
5224
5918
  let realResult = null;
5225
5919
  if (sid) {
5226
5920
  try {
5227
- realResult = await api.getUnifiedCheckoutSession(sid);
5921
+ realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
5228
5922
  const status = realResult.data.session?.status;
5229
5923
  if (status === "complete") {
5230
5924
  if (wasSessionRecentlyCompleted(sid)) {
5231
5925
  return { sid, result: realResult };
5232
5926
  }
5233
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
5927
+ clearCachedInlineSession(cacheKey);
5234
5928
  sid = null;
5235
5929
  realResult = null;
5236
5930
  }
5237
5931
  } catch {
5238
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
5932
+ clearCachedInlineSession(cacheKey);
5239
5933
  sid = null;
5240
5934
  }
5241
5935
  }
@@ -5249,8 +5943,8 @@ function FloPayCheckout({
5249
5943
  };
5250
5944
  realResult = await api.createAndFetchSession(paramsWithAnalytics);
5251
5945
  sid = realResult.data.session?.id ?? "";
5252
- if (sid && typeof window !== "undefined") {
5253
- window.sessionStorage.setItem(cacheKey, sid);
5946
+ if (sid) {
5947
+ persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
5254
5948
  }
5255
5949
  }
5256
5950
  return { sid: sid ?? "", result: realResult };
@@ -5339,7 +6033,7 @@ function FloPayCheckout({
5339
6033
  resolvedSessionId,
5340
6034
  session
5341
6035
  ]);
5342
- useEffect5(() => {
6036
+ useEffect6(() => {
5343
6037
  let cancelled = false;
5344
6038
  setLoadError(null);
5345
6039
  if (createSessionHash) {
@@ -5561,7 +6255,7 @@ function FloPayCheckout({
5561
6255
  ]
5562
6256
  );
5563
6257
  const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
5564
- const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx7(
6258
+ const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ jsx8(
5565
6259
  ProcessingOverlay,
5566
6260
  {
5567
6261
  status: modeOverlayStatus,
@@ -5577,7 +6271,7 @@ function FloPayCheckout({
5577
6271
  }
5578
6272
  if (layout === "buttons") {
5579
6273
  const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5580
- const skeletonBar = (h) => /* @__PURE__ */ jsx7("div", { style: {
6274
+ const skeletonBar = (h) => /* @__PURE__ */ jsx8("div", { style: {
5581
6275
  height: h,
5582
6276
  borderRadius: bundleRadius,
5583
6277
  background: "#e5e7eb",
@@ -5588,14 +6282,14 @@ function FloPayCheckout({
5588
6282
  showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5589
6283
  showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5590
6284
  showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5591
- /* @__PURE__ */ jsx7("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6285
+ /* @__PURE__ */ jsx8("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
5592
6286
  ] }),
5593
6287
  modeOverlay
5594
6288
  ] });
5595
6289
  }
5596
6290
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
5597
6291
  /* @__PURE__ */ jsxs5("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
5598
- /* @__PURE__ */ jsx7("div", { style: {
6292
+ /* @__PURE__ */ jsx8("div", { style: {
5599
6293
  width: 24,
5600
6294
  height: 24,
5601
6295
  border: "2px solid #e5e7eb",
@@ -5603,16 +6297,16 @@ function FloPayCheckout({
5603
6297
  borderRadius: "50%",
5604
6298
  animation: "spin 0.6s linear infinite"
5605
6299
  } }),
5606
- /* @__PURE__ */ jsx7("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
6300
+ /* @__PURE__ */ jsx8("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
5607
6301
  ] }),
5608
6302
  modeOverlay
5609
6303
  ] });
5610
6304
  }
5611
6305
  if (loadError) {
5612
6306
  if (errorNode) {
5613
- return /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
6307
+ return /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
5614
6308
  }
5615
- return /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(
6309
+ return /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(
5616
6310
  "div",
5617
6311
  {
5618
6312
  role: "alert",
@@ -5629,7 +6323,7 @@ function FloPayCheckout({
5629
6323
  }
5630
6324
  if (shouldShowInterimButtons) {
5631
6325
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
5632
- /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(
6326
+ /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(
5633
6327
  InterimButtonsView,
5634
6328
  {
5635
6329
  onButtonClick,
@@ -5650,8 +6344,8 @@ function FloPayCheckout({
5650
6344
  }
5651
6345
  if (isPaypalOnlySession && session && directPaypalConfig) {
5652
6346
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
5653
- /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsxs5("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5654
- modeError && /* @__PURE__ */ jsx7(
6347
+ /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsxs5("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6348
+ modeError && /* @__PURE__ */ jsx8(
5655
6349
  "div",
5656
6350
  {
5657
6351
  role: "alert",
@@ -5668,7 +6362,7 @@ function FloPayCheckout({
5668
6362
  children: modeError
5669
6363
  }
5670
6364
  ),
5671
- /* @__PURE__ */ jsx7(
6365
+ /* @__PURE__ */ jsx8(
5672
6366
  DirectPayPalButton,
5673
6367
  {
5674
6368
  sessionId: activeSessionId,
@@ -5692,12 +6386,12 @@ function FloPayCheckout({
5692
6386
  ] });
5693
6387
  }
5694
6388
  if (!flopay || !providerOptions) {
5695
- return /* @__PURE__ */ jsx7(Fragment3, { children: modeOverlay });
6389
+ return /* @__PURE__ */ jsx8(Fragment3, { children: modeOverlay });
5696
6390
  }
5697
6391
  if (currentMode === "confirm") {
5698
6392
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
5699
- /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs5("div", { className, children: [
5700
- modeError && /* @__PURE__ */ jsx7(
6393
+ /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ jsxs5("div", { className, children: [
6394
+ modeError && /* @__PURE__ */ jsx8(
5701
6395
  "div",
5702
6396
  {
5703
6397
  style: {
@@ -5712,7 +6406,7 @@ function FloPayCheckout({
5712
6406
  renderConfirmButton ? renderConfirmButton({
5713
6407
  onConfirm: handleConfirmCheckout,
5714
6408
  isProcessing: confirmProcessing
5715
- }) : /* @__PURE__ */ jsx7(
6409
+ }) : /* @__PURE__ */ jsx8(
5716
6410
  "button",
5717
6411
  {
5718
6412
  type: "button",
@@ -5738,8 +6432,8 @@ function FloPayCheckout({
5738
6432
  ] });
5739
6433
  }
5740
6434
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
5741
- /* @__PURE__ */ jsx7(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx7(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
5742
- modeError && /* @__PURE__ */ jsx7(
6435
+ /* @__PURE__ */ jsx8(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ jsx8(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
6436
+ modeError && /* @__PURE__ */ jsx8(
5743
6437
  "div",
5744
6438
  {
5745
6439
  style: {
@@ -5754,7 +6448,7 @@ function FloPayCheckout({
5754
6448
  children: modeError
5755
6449
  }
5756
6450
  ),
5757
- /* @__PURE__ */ jsx7(
6451
+ /* @__PURE__ */ jsx8(
5758
6452
  SessionInjector,
5759
6453
  {
5760
6454
  sessionId: activeSessionId,
@@ -5764,7 +6458,7 @@ function FloPayCheckout({
5764
6458
  children
5765
6459
  }
5766
6460
  )
5767
- ] }) : /* @__PURE__ */ jsx7(
6461
+ ] }) : /* @__PURE__ */ jsx8(
5768
6462
  SplitCardForm,
5769
6463
  {
5770
6464
  sessionId: activeSessionId,
@@ -5784,6 +6478,7 @@ function FloPayCheckout({
5784
6478
  showPayPal,
5785
6479
  showStripe,
5786
6480
  enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
6481
+ enabledPaymentMethodCountries: unified?.data.stripe?.enabledPaymentMethodCountries,
5787
6482
  showApplePay,
5788
6483
  showGooglePay,
5789
6484
  layout,
@@ -5797,6 +6492,8 @@ function FloPayCheckout({
5797
6492
  onButtonClick,
5798
6493
  onBeforeButtonClick,
5799
6494
  enableAVS,
6495
+ ...cardFieldOrder ? { cardFieldOrder } : {},
6496
+ ...cardPreFormSlot ? { cardPreFormSlot } : {},
5800
6497
  avsLayout,
5801
6498
  country: session?.customer?.country,
5802
6499
  city: session?.customer?.city,
@@ -5824,8 +6521,8 @@ function SessionInjector({
5824
6521
  session,
5825
6522
  children
5826
6523
  }) {
5827
- return /* @__PURE__ */ jsx7(Fragment3, { children: React7.Children.map(children, (child) => {
5828
- if (!React7.isValidElement(child)) return child;
6524
+ return /* @__PURE__ */ jsx8(Fragment3, { children: React8.Children.map(children, (child) => {
6525
+ if (!React8.isValidElement(child)) return child;
5829
6526
  const existing = child.props;
5830
6527
  const injected = {};
5831
6528
  if (!existing.sessionId) injected.sessionId = sessionId;
@@ -5840,7 +6537,7 @@ function SessionInjector({
5840
6537
  injected.lastName = session.customer.lastName;
5841
6538
  }
5842
6539
  if (Object.keys(injected).length === 0) return child;
5843
- return React7.cloneElement(child, injected);
6540
+ return React8.cloneElement(child, injected);
5844
6541
  }) });
5845
6542
  }
5846
6543
  function InterimButtonsView({
@@ -5862,7 +6559,7 @@ function InterimButtonsView({
5862
6559
  }) {
5863
6560
  const [showCardForm, setShowCardForm] = useState4(false);
5864
6561
  const isCardOpenControlled = typeof cardOpen === "boolean";
5865
- useEffect5(() => {
6562
+ useEffect6(() => {
5866
6563
  if (isCardOpenControlled) {
5867
6564
  setShowCardForm(cardOpen);
5868
6565
  }
@@ -5883,7 +6580,7 @@ function InterimButtonsView({
5883
6580
  };
5884
6581
  }, [themeBundle, buttonsTheme, stylesOverride]);
5885
6582
  const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5886
- const skeleton = (h) => /* @__PURE__ */ jsx7("div", { style: {
6583
+ const skeleton = (h) => /* @__PURE__ */ jsx8("div", { style: {
5887
6584
  height: h,
5888
6585
  borderRadius: skeletonRadius,
5889
6586
  background: "#e5e7eb",
@@ -5930,7 +6627,7 @@ function InterimButtonsView({
5930
6627
  ...bStyles.backButton
5931
6628
  },
5932
6629
  children: [
5933
- /* @__PURE__ */ jsx7("span", { style: {
6630
+ /* @__PURE__ */ jsx8("span", { style: {
5934
6631
  display: "inline-flex",
5935
6632
  alignItems: "center",
5936
6633
  justifyContent: "center",
@@ -5939,12 +6636,12 @@ function InterimButtonsView({
5939
6636
  borderRadius: "50%",
5940
6637
  backgroundColor: "#f3f4f6",
5941
6638
  ...bStyles.backButtonIcon
5942
- }, children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M15 18l-6-6 6-6" }) }) }),
5943
- /* @__PURE__ */ jsx7(BackButtonContentSlot, { content: cardBackButtonContent })
6639
+ }, children: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "M15 18l-6-6 6-6" }) }) }),
6640
+ /* @__PURE__ */ jsx8(BackButtonContentSlot, { content: cardBackButtonContent })
5944
6641
  ]
5945
6642
  }
5946
6643
  ),
5947
- hideTitle ? /* @__PURE__ */ jsx7("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx7("div", { style: {
6644
+ hideTitle ? /* @__PURE__ */ jsx8("div", { style: { flex: 1 } }) : /* @__PURE__ */ jsx8("div", { style: {
5948
6645
  flex: 1,
5949
6646
  textAlign: "center",
5950
6647
  fontWeight: 600,
@@ -5952,11 +6649,11 @@ function InterimButtonsView({
5952
6649
  color: "#262833",
5953
6650
  paddingRight: 80,
5954
6651
  ...bStyles.title
5955
- }, children: /* @__PURE__ */ jsx7(TitleContentSlot, { content: cardTitleContent }) })
6652
+ }, children: /* @__PURE__ */ jsx8(TitleContentSlot, { content: cardTitleContent }) })
5956
6653
  ] }),
5957
- /* @__PURE__ */ jsx7("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6654
+ /* @__PURE__ */ jsx8("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx8("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
5958
6655
  /* @__PURE__ */ jsxs5("div", { style: { display: "flex" }, children: [
5959
- /* @__PURE__ */ jsx7("div", { style: {
6656
+ /* @__PURE__ */ jsx8("div", { style: {
5960
6657
  flex: 1,
5961
6658
  backgroundColor: inputBg,
5962
6659
  borderTop: "none",
@@ -5966,8 +6663,8 @@ function InterimButtonsView({
5966
6663
  borderBottomLeftRadius: 8,
5967
6664
  padding: 12,
5968
6665
  height: 45
5969
- }, children: /* @__PURE__ */ jsx7("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
5970
- /* @__PURE__ */ jsx7("div", { style: {
6666
+ }, children: /* @__PURE__ */ jsx8("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6667
+ /* @__PURE__ */ jsx8("div", { style: {
5971
6668
  flex: 1,
5972
6669
  backgroundColor: inputBg,
5973
6670
  borderTop: "none",
@@ -5977,10 +6674,10 @@ function InterimButtonsView({
5977
6674
  borderBottomRightRadius: 8,
5978
6675
  padding: 12,
5979
6676
  height: 45
5980
- }, children: /* @__PURE__ */ jsx7("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
6677
+ }, children: /* @__PURE__ */ jsx8("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
5981
6678
  ] }),
5982
- /* @__PURE__ */ jsx7("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx7("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
5983
- /* @__PURE__ */ jsx7("div", { style: {
6679
+ /* @__PURE__ */ jsx8("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ jsx8("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6680
+ /* @__PURE__ */ jsx8("div", { style: {
5984
6681
  height: 50,
5985
6682
  borderRadius: 8,
5986
6683
  marginTop: 16,
@@ -5989,7 +6686,7 @@ function InterimButtonsView({
5989
6686
  ...bStyles.submitButton,
5990
6687
  opacity: 0.5
5991
6688
  } }),
5992
- /* @__PURE__ */ jsx7("style", { children: `
6689
+ /* @__PURE__ */ jsx8("style", { children: `
5993
6690
  @keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
5994
6691
  @keyframes flopay-interim-expand {
5995
6692
  0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
@@ -6002,7 +6699,7 @@ function InterimButtonsView({
6002
6699
  return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6003
6700
  showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6004
6701
  showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6005
- showStripe && /* @__PURE__ */ jsx7(
6702
+ showStripe && /* @__PURE__ */ jsx8(
6006
6703
  "button",
6007
6704
  {
6008
6705
  type: "button",
@@ -6042,7 +6739,7 @@ function InterimButtonsView({
6042
6739
  onMouseUp: (e) => {
6043
6740
  e.currentTarget.style.transform = "scale(1)";
6044
6741
  },
6045
- children: /* @__PURE__ */ jsx7(CardButtonContentSlot, { content: cardButtonContent })
6742
+ children: /* @__PURE__ */ jsx8(CardButtonContentSlot, { content: cardButtonContent })
6046
6743
  }
6047
6744
  ),
6048
6745
  errorMessage && /* @__PURE__ */ jsxs5("div", { style: {
@@ -6059,22 +6756,22 @@ function InterimButtonsView({
6059
6756
  gap: "0.5rem",
6060
6757
  ...bStyles.errorBanner
6061
6758
  }, children: [
6062
- /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx7("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" }) }),
6759
+ /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx8("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" }) }),
6063
6760
  errorMessage
6064
6761
  ] }),
6065
- /* @__PURE__ */ jsx7("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6762
+ /* @__PURE__ */ jsx8("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6066
6763
  ] });
6067
6764
  }
6068
6765
 
6069
6766
  // src/checkout-form.tsx
6070
6767
  import { PaymentAPI as PaymentAPI5 } from "@flopay/js";
6071
6768
  import { FloPayError as FloPayError6 } from "@flopay/shared";
6072
- import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect6, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
6073
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
6769
+ import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect7, useImperativeHandle as useImperativeHandle2, useState as useState5 } from "react";
6770
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
6074
6771
  var WALLET_RESUME_KEY = "flopay_wallet_resume";
6075
6772
  var CheckoutForm = forwardRef2(
6076
6773
  function CheckoutForm2(props, ref) {
6077
- return /* @__PURE__ */ jsx8(CheckoutFormInner, { ...props, innerRef: ref });
6774
+ return /* @__PURE__ */ jsx9(CheckoutFormInner, { ...props, innerRef: ref });
6078
6775
  }
6079
6776
  );
6080
6777
  function CheckoutFormInner({
@@ -6273,7 +6970,7 @@ function CheckoutFormInner({
6273
6970
  }
6274
6971
  }
6275
6972
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
6276
- useEffect6(() => {
6973
+ useEffect7(() => {
6277
6974
  if (typeof window === "undefined") return;
6278
6975
  const stored = localStorage.getItem(WALLET_RESUME_KEY);
6279
6976
  if (!stored) return;
@@ -6384,7 +7081,7 @@ function CheckoutFormInner({
6384
7081
  );
6385
7082
  const isReady = flopay !== null && elements !== null;
6386
7083
  return /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
6387
- (is3DSActive || isSubmitting) && /* @__PURE__ */ jsx8("div", { "data-testid": "flopay-overlay", style: {
7084
+ (is3DSActive || isSubmitting) && /* @__PURE__ */ jsx9("div", { "data-testid": "flopay-overlay", style: {
6388
7085
  position: "absolute",
6389
7086
  inset: 0,
6390
7087
  background: "rgba(255,255,255,0.7)",
@@ -6393,12 +7090,12 @@ function CheckoutFormInner({
6393
7090
  justifyContent: "center",
6394
7091
  zIndex: 10
6395
7092
  }, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
6396
- !isReady && /* @__PURE__ */ jsx8("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
7093
+ !isReady && /* @__PURE__ */ jsx9("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
6397
7094
  isReady && /* @__PURE__ */ jsxs6(Fragment4, { children: [
6398
- /* @__PURE__ */ jsx8(PaymentElement, { options: { layout } }),
6399
- showAddress && /* @__PURE__ */ jsx8(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
6400
- displayError && /* @__PURE__ */ jsx8("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
6401
- children ?? /* @__PURE__ */ jsx8(
7095
+ /* @__PURE__ */ jsx9(PaymentElement, { options: { layout } }),
7096
+ showAddress && /* @__PURE__ */ jsx9(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
7097
+ displayError && /* @__PURE__ */ jsx9("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
7098
+ children ?? /* @__PURE__ */ jsx9(
6402
7099
  "button",
6403
7100
  {
6404
7101
  type: "submit",
@@ -6414,8 +7111,8 @@ function CheckoutFormInner({
6414
7111
  // src/paypal-button.tsx
6415
7112
  import { PaymentAPI as PaymentAPI6 } from "@flopay/js";
6416
7113
  import { FloPayError as FloPayError7 } from "@flopay/shared";
6417
- import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef5, useState as useState6 } from "react";
6418
- import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
7114
+ import { useCallback as useCallback4, useEffect as useEffect8, useRef as useRef6, useState as useState6 } from "react";
7115
+ import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
6419
7116
  function PayPalButton({
6420
7117
  sessionId,
6421
7118
  nonce,
@@ -6435,7 +7132,7 @@ function PayPalButton({
6435
7132
  const contextBillingUrl = useBillingApiUrl();
6436
7133
  const [ready, setReady] = useState6(false);
6437
7134
  const [submitting, setSubmitting] = useState6(false);
6438
- const paypalResumeAttempted = useRef5(false);
7135
+ const paypalResumeAttempted = useRef6(false);
6439
7136
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
6440
7137
  const processPaymentInternal = useCallback4(
6441
7138
  async (tokenizedBody) => {
@@ -6475,7 +7172,7 @@ function PayPalButton({
6475
7172
  },
6476
7173
  [onTokenizedBody, processPaymentInternal]
6477
7174
  );
6478
- useEffect7(() => {
7175
+ useEffect8(() => {
6479
7176
  if (!flopay || paypalResumeAttempted.current) return;
6480
7177
  const params = new URLSearchParams(window.location.search);
6481
7178
  const paymentIntentId = params.get("payment_intent");
@@ -6557,11 +7254,11 @@ function PayPalButton({
6557
7254
  }
6558
7255
  }, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
6559
7256
  if (!flopay || !elements) {
6560
- return /* @__PURE__ */ jsx9("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
7257
+ return /* @__PURE__ */ jsx10("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
6561
7258
  }
6562
7259
  return /* @__PURE__ */ jsxs7(Fragment5, { children: [
6563
- !ready && /* @__PURE__ */ jsx9("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
6564
- /* @__PURE__ */ jsx9("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx9(
7260
+ !ready && /* @__PURE__ */ jsx10("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
7261
+ /* @__PURE__ */ jsx10("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ jsx10(
6565
7262
  "button",
6566
7263
  {
6567
7264
  type: "button",
@@ -6583,7 +7280,7 @@ function PayPalButton({
6583
7280
  children: submitting ? "Processing..." : "PayPal"
6584
7281
  }
6585
7282
  ) }),
6586
- (submitting || isProcessing) && /* @__PURE__ */ jsx9("div", { style: {
7283
+ (submitting || isProcessing) && /* @__PURE__ */ jsx10("div", { style: {
6587
7284
  position: "fixed",
6588
7285
  inset: 0,
6589
7286
  background: "rgba(0,0,0,0.4)",
@@ -6591,7 +7288,7 @@ function PayPalButton({
6591
7288
  alignItems: "center",
6592
7289
  justifyContent: "center",
6593
7290
  zIndex: 1e3
6594
- }, children: /* @__PURE__ */ jsx9("div", { style: {
7291
+ }, children: /* @__PURE__ */ jsx10("div", { style: {
6595
7292
  background: "white",
6596
7293
  borderRadius: 8,
6597
7294
  padding: "1.5rem",
@@ -6603,10 +7300,10 @@ function PayPalButton({
6603
7300
  }
6604
7301
 
6605
7302
  // src/automatic-payment-button.tsx
6606
- import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo5, useRef as useRef6, useState as useState7 } from "react";
7303
+ import { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef7, useState as useState7 } from "react";
6607
7304
  import { PaymentAPI as PaymentAPI7 } from "@flopay/js";
6608
7305
  import { FloPayError as FloPayError8, resolveBillingApiUrl as resolveBillingApiUrl4, resolveButtonsLayoutTheme as resolveButtonsLayoutTheme3, resolveTheme as resolveTheme3 } from "@flopay/shared";
6609
- import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
7306
+ import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
6610
7307
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
6611
7308
  function sleep2(ms) {
6612
7309
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -6674,6 +7371,7 @@ function FloPayAutomaticPaymentButton({
6674
7371
  billingApiUrl,
6675
7372
  locale,
6676
7373
  theme,
7374
+ appearance,
6677
7375
  buttonsTheme,
6678
7376
  buttonsStyles: stylesOverride,
6679
7377
  onSuccess,
@@ -6721,30 +7419,32 @@ function FloPayAutomaticPaymentButton({
6721
7419
  const [overlayStatus, setOverlayStatus] = useState7(null);
6722
7420
  const [overlayError, setOverlayError] = useState7(null);
6723
7421
  const [fallbackSession, setFallbackSession] = useState7(null);
6724
- const isMountedRef = useRef6(true);
6725
- const fallbackSessionRef = useRef6(fallbackSession);
6726
- const onSuccessRef = useRef6(onSuccess);
6727
- const onErrorRef = useRef6(onError);
6728
- const onDeclineRef = useRef6(onDecline);
6729
- useEffect8(() => {
7422
+ const isMountedRef = useRef7(true);
7423
+ const threeDsAbortRef = useRef7(null);
7424
+ const fallbackSessionRef = useRef7(fallbackSession);
7425
+ const onSuccessRef = useRef7(onSuccess);
7426
+ const onErrorRef = useRef7(onError);
7427
+ const onDeclineRef = useRef7(onDecline);
7428
+ useEffect9(() => {
6730
7429
  fallbackSessionRef.current = fallbackSession;
6731
7430
  }, [fallbackSession]);
6732
- useEffect8(() => {
7431
+ useEffect9(() => {
6733
7432
  onSuccessRef.current = onSuccess;
6734
7433
  }, [onSuccess]);
6735
- useEffect8(() => {
7434
+ useEffect9(() => {
6736
7435
  onErrorRef.current = onError;
6737
7436
  }, [onError]);
6738
- useEffect8(() => {
7437
+ useEffect9(() => {
6739
7438
  onDeclineRef.current = onDecline;
6740
7439
  }, [onDecline]);
6741
- useEffect8(() => {
7440
+ useEffect9(() => {
6742
7441
  isMountedRef.current = true;
6743
7442
  return () => {
6744
7443
  isMountedRef.current = false;
7444
+ threeDsAbortRef.current?.abort();
6745
7445
  };
6746
7446
  }, []);
6747
- useEffect8(() => {
7447
+ useEffect9(() => {
6748
7448
  if (!fallbackSession || typeof window === "undefined") {
6749
7449
  return;
6750
7450
  }
@@ -6823,6 +7523,62 @@ function FloPayAutomaticPaymentButton({
6823
7523
  return;
6824
7524
  }
6825
7525
  if (apiResult.autoProcessingError) {
7526
+ if (apiResult.autoProcessingError.type === "3ds_required" && apiResult.autoProcessingError.nextActionRedirectUrl && resolvedSessionId && effectiveNonce) {
7527
+ const threeDsAbort = new AbortController();
7528
+ threeDsAbortRef.current = threeDsAbort;
7529
+ let outcome;
7530
+ try {
7531
+ outcome = await runAutoCheckoutThreeDsChallenge({
7532
+ billingApiUrl: resolvedBillingUrl,
7533
+ sessionId: resolvedSessionId,
7534
+ nonce: effectiveNonce,
7535
+ nextActionRedirectUrl: apiResult.autoProcessingError.nextActionRedirectUrl,
7536
+ signal: threeDsAbort.signal
7537
+ });
7538
+ } finally {
7539
+ if (threeDsAbortRef.current === threeDsAbort) {
7540
+ threeDsAbortRef.current = null;
7541
+ }
7542
+ }
7543
+ if (outcome.status === "declined") {
7544
+ throw checkoutProcessErrorToFloPayError(
7545
+ {
7546
+ type: outcome.declineReason ?? "decline",
7547
+ message: "Card was declined.",
7548
+ gatewayErrorCode: outcome.gatewayDeclineReason ?? void 0
7549
+ },
7550
+ "Card was declined.",
7551
+ {
7552
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7553
+ }
7554
+ );
7555
+ }
7556
+ const api = new PaymentAPI7(resolvedBillingUrl);
7557
+ const completed = await api.waitForCheckoutSessionCompletion(resolvedSessionId, {
7558
+ initialDelayMs: 0,
7559
+ nonce: effectiveNonce
7560
+ });
7561
+ const completedSession = completed.data.session;
7562
+ if (!completedSession || completedSession.status !== "complete") {
7563
+ throw checkoutProcessErrorToFloPayError(
7564
+ {
7565
+ type: "unknown",
7566
+ message: "Card authentication was not completed."
7567
+ },
7568
+ "Card authentication was not completed.",
7569
+ {
7570
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7571
+ }
7572
+ );
7573
+ }
7574
+ await showSuccess({
7575
+ result: { status: "succeeded" },
7576
+ session: completedSession,
7577
+ sessionId: completedSession.id || resolvedSessionId,
7578
+ autoCompleted: false
7579
+ });
7580
+ return;
7581
+ }
6826
7582
  throw checkoutProcessErrorToFloPayError(
6827
7583
  apiResult.autoProcessingError,
6828
7584
  "Automatic payment failed. Please try again.",
@@ -6990,9 +7746,26 @@ function FloPayAutomaticPaymentButton({
6990
7746
  cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
6991
7747
  };
6992
7748
  }, [themeBundle, buttonsTheme, stylesOverride]);
7749
+ const resolvedAppearance = useMemo5(() => {
7750
+ const bundleAppearance = themeBundle?.appearance;
7751
+ if (!appearance) return bundleAppearance;
7752
+ if (!bundleAppearance) return appearance;
7753
+ return {
7754
+ ...bundleAppearance,
7755
+ ...appearance,
7756
+ variables: {
7757
+ ...bundleAppearance.variables,
7758
+ ...appearance.variables
7759
+ }
7760
+ };
7761
+ }, [appearance, themeBundle]);
7762
+ const resolvedAppearanceVars = resolvedAppearance?.variables;
7763
+ const resolvedPrimaryColor = resolvedAppearanceVars?.colorPrimary ?? "#4A49FF";
7764
+ const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
7765
+ const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
6993
7766
  const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
6994
7767
  return /* @__PURE__ */ jsxs8(Fragment6, { children: [
6995
- /* @__PURE__ */ jsx10(
7768
+ /* @__PURE__ */ jsx11(
6996
7769
  "button",
6997
7770
  {
6998
7771
  ...buttonProps,
@@ -7008,14 +7781,17 @@ function FloPayAutomaticPaymentButton({
7008
7781
  // on top so the auto-pay button carries the *submit* button's
7009
7782
  // background and text colours — making it visually identical to
7010
7783
  // the "Confirm Payment" / "Pay with X" actions it stands in for.
7784
+ // `resolvedPrimaryColor` is the *merged* appearance value, so a
7785
+ // per-checkout `colorPrimary` override re-skins this button too.
7011
7786
  // Inline `style` consumer override stays at the end so explicit
7012
7787
  // per-button overrides still win.
7013
7788
  ...bStyles.cardButton,
7014
7789
  ...derivePrimaryTileStyle({
7015
7790
  themeBundle,
7016
- resolvedPrimaryColor: themeBundle?.appearance.variables?.colorPrimary ?? "#4A49FF",
7017
- resolvedBorderRadius: themeBundle?.appearance.variables?.borderRadius ?? "8px",
7018
- submitButtonStyle: bStyles.submitButton
7791
+ resolvedPrimaryColor,
7792
+ resolvedBorderRadius: resolvedButtonBorderRadius,
7793
+ submitButtonStyle: bStyles.submitButton,
7794
+ explicitPrimaryColor: resolvedAppearanceVars?.colorPrimary
7019
7795
  }),
7020
7796
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
7021
7797
  fontWeight: 600,
@@ -7024,11 +7800,23 @@ function FloPayAutomaticPaymentButton({
7024
7800
  alignItems: "center",
7025
7801
  justifyContent: "center",
7026
7802
  gap: "0.625rem",
7027
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7803
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7028
7804
  position: "relative",
7029
7805
  opacity: disabled || isProcessing ? 0.6 : 1,
7030
7806
  ...style
7031
7807
  },
7808
+ onMouseEnter: (e) => {
7809
+ buttonProps.onMouseEnter?.(e);
7810
+ if (!e.defaultPrevented && !disabled && !isProcessing && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7811
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
7812
+ }
7813
+ },
7814
+ onMouseLeave: (e) => {
7815
+ buttonProps.onMouseLeave?.(e);
7816
+ if (!e.defaultPrevented && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7817
+ e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
7818
+ }
7819
+ },
7032
7820
  onMouseDown: (e) => {
7033
7821
  buttonProps.onMouseDown?.(e);
7034
7822
  if (!e.defaultPrevented) {
@@ -7041,17 +7829,17 @@ function FloPayAutomaticPaymentButton({
7041
7829
  e.currentTarget.style.transform = "scale(1)";
7042
7830
  }
7043
7831
  },
7044
- children: /* @__PURE__ */ jsx10(CardButtonContentSlot, { content: children })
7832
+ children: /* @__PURE__ */ jsx11(CardButtonContentSlot, { content: children })
7045
7833
  }
7046
7834
  ),
7047
- overlayStatus && /* @__PURE__ */ jsx10(
7835
+ overlayStatus && /* @__PURE__ */ jsx11(
7048
7836
  ProcessingOverlay,
7049
7837
  {
7050
7838
  status: overlayStatus,
7051
7839
  errorMessage: overlayError
7052
7840
  }
7053
7841
  ),
7054
- fallbackSession && /* @__PURE__ */ jsx10(
7842
+ fallbackSession && /* @__PURE__ */ jsx11(
7055
7843
  "div",
7056
7844
  {
7057
7845
  "data-testid": "flopay-automatic-payment-fallback",
@@ -7072,7 +7860,7 @@ function FloPayAutomaticPaymentButton({
7072
7860
  padding: "1.5rem",
7073
7861
  zIndex: 1100
7074
7862
  },
7075
- children: /* @__PURE__ */ jsx10(
7863
+ children: /* @__PURE__ */ jsx11(
7076
7864
  "div",
7077
7865
  {
7078
7866
  style: {
@@ -7088,7 +7876,7 @@ function FloPayAutomaticPaymentButton({
7088
7876
  flexDirection: "column",
7089
7877
  gap: "1rem"
7090
7878
  },
7091
- children: /* @__PURE__ */ jsx10(
7879
+ children: /* @__PURE__ */ jsx11(
7092
7880
  FloPayCheckout,
7093
7881
  {
7094
7882
  sessionId: fallbackSession.sessionId,
@@ -7097,6 +7885,7 @@ function FloPayAutomaticPaymentButton({
7097
7885
  billingApiUrl: resolvedBillingUrl,
7098
7886
  locale,
7099
7887
  theme,
7888
+ ...resolvedAppearance ? { appearance: resolvedAppearance } : {},
7100
7889
  buttonsTheme,
7101
7890
  buttonsStyles: stylesOverride,
7102
7891
  initialErrorMessage: fallbackSession.errorMessage,
@@ -7126,6 +7915,7 @@ export {
7126
7915
  PayPalButton,
7127
7916
  PaymentElement,
7128
7917
  SplitCardForm,
7918
+ VaultCardFields,
7129
7919
  useCheckout,
7130
7920
  useElements,
7131
7921
  useFloPay,