@flopay/react 1.2.8 → 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.cjs CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  PayPalButton: () => PayPalButton,
44
44
  PaymentElement: () => PaymentElement,
45
45
  SplitCardForm: () => SplitCardForm,
46
+ VaultCardFields: () => VaultCardFields,
46
47
  useCheckout: () => useCheckout,
47
48
  useElements: () => useElements,
48
49
  useFloPay: () => useFloPay,
@@ -152,7 +153,7 @@ function FloPayProvider({
152
153
  }
153
154
 
154
155
  // src/flopay-checkout.tsx
155
- var import_react9 = __toESM(require("react"), 1);
156
+ var import_react10 = __toESM(require("react"), 1);
156
157
  var import_js4 = require("@flopay/js");
157
158
  var import_shared8 = require("@flopay/shared");
158
159
 
@@ -287,41 +288,114 @@ var AddressElement = createElementComponent("address", "AddressElement");
287
288
  var import_react_stripe_js = require("@stripe/react-stripe-js");
288
289
  var import_shared5 = require("@flopay/shared");
289
290
  var import_js2 = require("@flopay/js");
290
- var import_react8 = __toESM(require("react"), 1);
291
291
 
292
- // src/hooks.ts
292
+ // src/vault-card-fields.tsx
293
293
  var import_react5 = require("react");
294
+ var import_jsx_runtime4 = require("react/jsx-runtime");
295
+ function VaultCardFields({
296
+ capture,
297
+ html,
298
+ messageToken,
299
+ expectedOrigin,
300
+ theme,
301
+ containerStyle,
302
+ onReady,
303
+ onError,
304
+ onValidation
305
+ }) {
306
+ const containerRef = (0, import_react5.useRef)(null);
307
+ const onReadyRef = (0, import_react5.useRef)(onReady);
308
+ const onErrorRef = (0, import_react5.useRef)(onError);
309
+ const onValidationRef = (0, import_react5.useRef)(onValidation);
310
+ onReadyRef.current = onReady;
311
+ onErrorRef.current = onError;
312
+ onValidationRef.current = onValidation;
313
+ const themeRef = (0, import_react5.useRef)(theme);
314
+ themeRef.current = theme;
315
+ (0, import_react5.useEffect)(() => {
316
+ const el = containerRef.current;
317
+ if (!el) return;
318
+ let active = true;
319
+ let readyEmitted = false;
320
+ const emitReadyOnce = () => {
321
+ if (!active || readyEmitted) return;
322
+ readyEmitted = true;
323
+ onReadyRef.current?.();
324
+ };
325
+ const offReady = capture.on("ready", () => {
326
+ emitReadyOnce();
327
+ });
328
+ const offError = capture.on("error", (event) => {
329
+ onErrorRef.current?.(event.message ?? "There was a problem loading the secure card form.");
330
+ });
331
+ const offValidation = capture.on("validation", (event) => {
332
+ onValidationRef.current?.(event.message ?? null);
333
+ });
334
+ const mountOptions = {
335
+ html,
336
+ ...messageToken ? { messageToken } : {},
337
+ ...expectedOrigin ? { expectedOrigin } : {},
338
+ ...themeRef.current ? { theme: themeRef.current } : {}
339
+ };
340
+ capture.mount(el, mountOptions).then(() => {
341
+ emitReadyOnce();
342
+ }).catch((err) => {
343
+ if (active) {
344
+ onErrorRef.current?.(
345
+ err instanceof Error ? err.message : "Failed to load the secure card form."
346
+ );
347
+ }
348
+ });
349
+ return () => {
350
+ active = false;
351
+ offReady();
352
+ offError();
353
+ offValidation();
354
+ capture.unmount();
355
+ };
356
+ }, [capture, html, messageToken, expectedOrigin]);
357
+ (0, import_react5.useEffect)(() => {
358
+ if (theme) capture.applyTheme?.(theme);
359
+ }, [capture, theme]);
360
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
361
+ }
362
+
363
+ // src/split-card-form.tsx
364
+ var import_react9 = __toESM(require("react"), 1);
365
+
366
+ // src/hooks.ts
367
+ var import_react6 = require("react");
294
368
  var import_shared2 = require("@flopay/shared");
295
369
  function useFloPay() {
296
- const ctx = (0, import_react5.useContext)(FloPayContext);
370
+ const ctx = (0, import_react6.useContext)(FloPayContext);
297
371
  return ctx.flopay;
298
372
  }
299
373
  function usePayPalFloPay() {
300
- const ctx = (0, import_react5.useContext)(FloPayContext);
374
+ const ctx = (0, import_react6.useContext)(FloPayContext);
301
375
  return ctx.paypalFlopay ?? null;
302
376
  }
303
377
  function useElements() {
304
- const ctx = (0, import_react5.useContext)(FloPayContext);
378
+ const ctx = (0, import_react6.useContext)(FloPayContext);
305
379
  return ctx.elements;
306
380
  }
307
381
  function useCheckout() {
308
- return (0, import_react5.useContext)(CheckoutContext);
382
+ return (0, import_react6.useContext)(CheckoutContext);
309
383
  }
310
384
  function useBillingApiUrl() {
311
- const ctx = (0, import_react5.useContext)(FloPayContext);
385
+ const ctx = (0, import_react6.useContext)(FloPayContext);
312
386
  return ctx.billingApiUrl || (0, import_shared2.resolveBillingApiUrl)();
313
387
  }
314
388
 
315
389
  // src/processing-overlay.tsx
316
- var import_react6 = require("react");
317
- var import_jsx_runtime4 = require("react/jsx-runtime");
390
+ var import_react7 = require("react");
391
+ var import_jsx_runtime5 = require("react/jsx-runtime");
318
392
  var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
319
393
  var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
320
394
  function ProcessingOverlay({
321
395
  status,
322
396
  errorMessage
323
397
  }) {
324
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
398
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
325
399
  "div",
326
400
  {
327
401
  "data-testid": "flopay-processing-overlay",
@@ -338,7 +412,7 @@ function ProcessingOverlay({
338
412
  zIndex: 1e3,
339
413
  backdropFilter: "blur(2px)"
340
414
  },
341
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
415
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
342
416
  "div",
343
417
  {
344
418
  style: {
@@ -354,8 +428,8 @@ function ProcessingOverlay({
354
428
  gap: 16
355
429
  },
356
430
  children: [
357
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
358
- status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
431
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
432
+ status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
359
433
  "svg",
360
434
  {
361
435
  width: "48",
@@ -365,14 +439,14 @@ function ProcessingOverlay({
365
439
  xmlns: "http://www.w3.org/2000/svg",
366
440
  style: { animation: "flopay-spin 0.8s linear infinite" },
367
441
  children: [
368
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
369
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
442
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
443
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
370
444
  ]
371
445
  }
372
446
  ),
373
- status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
374
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
375
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
447
+ status === "success" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
449
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
376
450
  "path",
377
451
  {
378
452
  d: "M7 12.5l3 3 7-7",
@@ -388,9 +462,9 @@ function ProcessingOverlay({
388
462
  }
389
463
  )
390
464
  ] }) }),
391
- status === "error" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
392
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
393
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
465
+ status === "error" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
394
468
  "path",
395
469
  {
396
470
  d: "M8 8l8 8M16 8l-8 8",
@@ -406,7 +480,7 @@ function ProcessingOverlay({
406
480
  )
407
481
  ] }) })
408
482
  ] }),
409
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
483
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
410
484
  "span",
411
485
  {
412
486
  style: {
@@ -422,7 +496,7 @@ function ProcessingOverlay({
422
496
  ]
423
497
  }
424
498
  ),
425
- status === "success" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
499
+ status === "success" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
426
500
  "p",
427
501
  {
428
502
  style: {
@@ -436,7 +510,7 @@ function ProcessingOverlay({
436
510
  children: "You will be automatically redirected, do not close or navigate away from this window."
437
511
  }
438
512
  ),
439
- status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
513
+ status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
440
514
  "p",
441
515
  {
442
516
  style: {
@@ -450,7 +524,7 @@ function ProcessingOverlay({
450
524
  children: errorMessage
451
525
  }
452
526
  ),
453
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
527
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
454
528
  @keyframes flopay-spin { to { transform: rotate(360deg); } }
455
529
  @keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
456
530
  @keyframes flopay-draw { to { stroke-dashoffset: 0; } }
@@ -724,11 +798,11 @@ function isInAppBrowser(userAgent) {
724
798
  }
725
799
 
726
800
  // src/direct-paypal-button.tsx
727
- var import_react7 = require("react");
801
+ var import_react8 = require("react");
728
802
  var import_paypal_js = require("@paypal/paypal-js");
729
803
  var import_js = require("@flopay/js");
730
804
  var import_shared4 = require("@flopay/shared");
731
- var import_jsx_runtime5 = require("react/jsx-runtime");
805
+ var import_jsx_runtime6 = require("react/jsx-runtime");
732
806
  var DEFAULT_BUTTON_HEIGHT = 45;
733
807
  function DirectPayPalButton({
734
808
  sessionId,
@@ -751,62 +825,62 @@ function DirectPayPalButton({
751
825
  existingOrderId,
752
826
  debug = false
753
827
  }) {
754
- const containerRef = (0, import_react7.useRef)(null);
755
- const [ready, setReady] = (0, import_react7.useState)(false);
756
- const [failed, setFailed] = (0, import_react7.useState)(false);
757
- const [submitting, setSubmitting] = (0, import_react7.useState)(false);
758
- const baseUrl = (0, import_react7.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
759
- const [debugLines, setDebugLines] = (0, import_react7.useState)([]);
828
+ const containerRef = (0, import_react8.useRef)(null);
829
+ const [ready, setReady] = (0, import_react8.useState)(false);
830
+ const [failed, setFailed] = (0, import_react8.useState)(false);
831
+ const [submitting, setSubmitting] = (0, import_react8.useState)(false);
832
+ const baseUrl = (0, import_react8.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
833
+ const [debugLines, setDebugLines] = (0, import_react8.useState)([]);
760
834
  const appendDebug = (line) => {
761
835
  if (!debug) return;
762
836
  setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
763
837
  };
764
- const onTokenizedBodyRef = (0, import_react7.useRef)(onTokenizedBody);
765
- const onCompleteRef = (0, import_react7.useRef)(onComplete);
766
- const onErrorChangeRef = (0, import_react7.useRef)(onErrorChange);
767
- const onDeclineRef = (0, import_react7.useRef)(onDecline);
768
- const onButtonClickRef = (0, import_react7.useRef)(onButtonClick);
769
- const onLoadStateChangeRef = (0, import_react7.useRef)(onLoadStateChange);
770
- const runBeforeButtonClickRef = (0, import_react7.useRef)(runBeforeButtonClick);
771
- const sessionRef = (0, import_react7.useRef)(session);
772
- const emailRef = (0, import_react7.useRef)(email);
773
- const nonceRef = (0, import_react7.useRef)(nonce);
774
- const beforeClickRef = (0, import_react7.useRef)(null);
775
- (0, import_react7.useEffect)(() => {
838
+ const onTokenizedBodyRef = (0, import_react8.useRef)(onTokenizedBody);
839
+ const onCompleteRef = (0, import_react8.useRef)(onComplete);
840
+ const onErrorChangeRef = (0, import_react8.useRef)(onErrorChange);
841
+ const onDeclineRef = (0, import_react8.useRef)(onDecline);
842
+ const onButtonClickRef = (0, import_react8.useRef)(onButtonClick);
843
+ const onLoadStateChangeRef = (0, import_react8.useRef)(onLoadStateChange);
844
+ const runBeforeButtonClickRef = (0, import_react8.useRef)(runBeforeButtonClick);
845
+ const sessionRef = (0, import_react8.useRef)(session);
846
+ const emailRef = (0, import_react8.useRef)(email);
847
+ const nonceRef = (0, import_react8.useRef)(nonce);
848
+ const beforeClickRef = (0, import_react8.useRef)(null);
849
+ (0, import_react8.useEffect)(() => {
776
850
  onTokenizedBodyRef.current = onTokenizedBody;
777
851
  }, [onTokenizedBody]);
778
- (0, import_react7.useEffect)(() => {
852
+ (0, import_react8.useEffect)(() => {
779
853
  onCompleteRef.current = onComplete;
780
854
  }, [onComplete]);
781
- (0, import_react7.useEffect)(() => {
855
+ (0, import_react8.useEffect)(() => {
782
856
  onErrorChangeRef.current = onErrorChange;
783
857
  }, [onErrorChange]);
784
- (0, import_react7.useEffect)(() => {
858
+ (0, import_react8.useEffect)(() => {
785
859
  onDeclineRef.current = onDecline;
786
860
  }, [onDecline]);
787
- (0, import_react7.useEffect)(() => {
861
+ (0, import_react8.useEffect)(() => {
788
862
  onButtonClickRef.current = onButtonClick;
789
863
  }, [onButtonClick]);
790
- (0, import_react7.useEffect)(() => {
864
+ (0, import_react8.useEffect)(() => {
791
865
  onLoadStateChangeRef.current = onLoadStateChange;
792
866
  }, [onLoadStateChange]);
793
- (0, import_react7.useEffect)(() => {
867
+ (0, import_react8.useEffect)(() => {
794
868
  runBeforeButtonClickRef.current = runBeforeButtonClick;
795
869
  }, [runBeforeButtonClick]);
796
- (0, import_react7.useEffect)(() => {
870
+ (0, import_react8.useEffect)(() => {
797
871
  sessionRef.current = session;
798
872
  }, [session]);
799
- (0, import_react7.useEffect)(() => {
873
+ (0, import_react8.useEffect)(() => {
800
874
  emailRef.current = email;
801
875
  }, [email]);
802
- (0, import_react7.useEffect)(() => {
876
+ (0, import_react8.useEffect)(() => {
803
877
  nonceRef.current = nonce;
804
878
  }, [nonce]);
805
- (0, import_react7.useEffect)(() => {
879
+ (0, import_react8.useEffect)(() => {
806
880
  onLoadStateChangeRef.current?.(ready && !failed);
807
881
  }, [ready, failed]);
808
882
  const normalizedEnv = (0, import_shared4.normalizeGatewayEnvironment)(environment);
809
- (0, import_react7.useEffect)(() => {
883
+ (0, import_react8.useEffect)(() => {
810
884
  const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
811
885
  const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
812
886
  appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
@@ -1218,7 +1292,7 @@ function DirectPayPalButton({
1218
1292
  }
1219
1293
  };
1220
1294
  }, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId]);
1221
- const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1295
+ const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1222
1296
  "pre",
1223
1297
  {
1224
1298
  "data-testid": "flopay-direct-paypal-debug",
@@ -1243,17 +1317,17 @@ ${debugLines.join("\n")}`
1243
1317
  }
1244
1318
  ) : null;
1245
1319
  if (failed) {
1246
- return debug ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: debugPanel }) : null;
1320
+ return debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: debugPanel }) : null;
1247
1321
  }
1248
1322
  return (
1249
1323
  // Single wrapper so the parent flex container sees exactly one flex item
1250
1324
  // (otherwise the fragment's placeholder + container become two siblings
1251
1325
  // and any spacing-sensitive layout has to reason about both). The wrapper
1252
1326
  // intentionally has no margin/padding so the parent owns all spacing.
1253
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1327
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1254
1328
  debugPanel,
1255
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1256
- !ready && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1329
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1330
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1257
1331
  "div",
1258
1332
  {
1259
1333
  "data-testid": "flopay-direct-paypal-placeholder",
@@ -1267,7 +1341,7 @@ ${debugLines.join("\n")}`
1267
1341
  }
1268
1342
  }
1269
1343
  ),
1270
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1344
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1271
1345
  "div",
1272
1346
  {
1273
1347
  ref: containerRef,
@@ -1287,10 +1361,28 @@ ${debugLines.join("\n")}`
1287
1361
 
1288
1362
  // src/split-card-form.tsx
1289
1363
  var import_shared6 = require("@flopay/shared");
1290
- var import_jsx_runtime6 = require("react/jsx-runtime");
1364
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1291
1365
  var STRIPE_RESUME_KEY = "flopay_stripe_resume";
1292
1366
  var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
1293
1367
  var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
1368
+ function toVaultMount(block) {
1369
+ if (!block?.html) return null;
1370
+ return {
1371
+ html: block.html,
1372
+ ...block.messageToken ? { messageToken: block.messageToken } : {},
1373
+ ...block.expectedOrigin ? { expectedOrigin: block.expectedOrigin } : {}
1374
+ };
1375
+ }
1376
+ function darkenHex(hex, amount = 0.12) {
1377
+ const match = /^#?([0-9a-fA-F]{6})$/.exec(hex.trim());
1378
+ if (!match) return hex;
1379
+ const value = parseInt(match[1], 16);
1380
+ const scale = Math.max(0, Math.min(1, 1 - amount));
1381
+ const r = Math.round((value >> 16 & 255) * scale);
1382
+ const g = Math.round((value >> 8 & 255) * scale);
1383
+ const b = Math.round((value & 255) * scale);
1384
+ return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}`;
1385
+ }
1294
1386
  var FLOPAY_KEYFRAMES = `
1295
1387
  .paypal-buttons { margin: 0 !important; vertical-align: top !important; }
1296
1388
  @keyframes flopay-spin { to { transform: rotate(360deg); } }
@@ -1315,18 +1407,20 @@ var FLOPAY_KEYFRAMES = `
1315
1407
  `;
1316
1408
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT = 44;
1317
1409
  function derivePrimaryTileStyle(opts) {
1318
- if (!opts.themeBundle) {
1410
+ if (!opts.themeBundle && !opts.explicitPrimaryColor) {
1319
1411
  return {
1320
1412
  backgroundColor: "white",
1321
1413
  color: "#262833",
1322
1414
  border: "1px solid #d1d5db",
1323
- borderRadius: "8px",
1415
+ borderRadius: opts.resolvedBorderRadius,
1324
1416
  boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
1325
1417
  };
1326
1418
  }
1327
- const submit = opts.submitButtonStyle ?? {};
1419
+ const submit = opts.themeBundle ? opts.submitButtonStyle ?? {} : {};
1328
1420
  return {
1329
- backgroundColor: submit.backgroundColor ?? opts.resolvedPrimaryColor,
1421
+ // `colorPrimary` wins so a per-checkout override re-skins the card / auto-pay
1422
+ // buttons in lock-step with the submit CTA (which also keys off it).
1423
+ backgroundColor: opts.resolvedPrimaryColor,
1330
1424
  color: submit.color ?? "white",
1331
1425
  border: submit.border ?? "none",
1332
1426
  borderRadius: submit.borderRadius ?? opts.resolvedBorderRadius,
@@ -1360,7 +1454,7 @@ function normalizeBeforeButtonClickError(method, err) {
1360
1454
  );
1361
1455
  }
1362
1456
  function FloPayKeyframes() {
1363
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: FLOPAY_KEYFRAMES });
1457
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: FLOPAY_KEYFRAMES });
1364
1458
  }
1365
1459
  function toCssSize(value) {
1366
1460
  if (typeof value === "number") return `${value}px`;
@@ -1382,8 +1476,8 @@ function ExpressCheckoutReadySwap({
1382
1476
  children
1383
1477
  }) {
1384
1478
  if (state === "unavailable" || state === "load_error") return null;
1385
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
1386
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1479
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1387
1481
  "div",
1388
1482
  {
1389
1483
  "data-testid": placeholderTestId,
@@ -1402,7 +1496,7 @@ function ExpressCheckoutReadySwap({
1402
1496
  }
1403
1497
  }
1404
1498
  ),
1405
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1499
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1406
1500
  "div",
1407
1501
  {
1408
1502
  style: {
@@ -1420,9 +1514,9 @@ function ExpressCheckoutReadySwap({
1420
1514
  function isExpressCheckoutRowVisible(state) {
1421
1515
  return state !== "unavailable" && state !== "load_error";
1422
1516
  }
1423
- var SplitCardForm = (0, import_react8.forwardRef)(
1517
+ var SplitCardForm = (0, import_react9.forwardRef)(
1424
1518
  function SplitCardForm2(props, ref) {
1425
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
1519
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
1426
1520
  }
1427
1521
  );
1428
1522
  function PayPalButtonInner({
@@ -1441,15 +1535,15 @@ function PayPalButtonInner({
1441
1535
  }) {
1442
1536
  const stripe = (0, import_react_stripe_js.useStripe)();
1443
1537
  const elements = (0, import_react_stripe_js.useElements)();
1444
- const [loadState, setLoadState] = (0, import_react8.useState)("loading");
1445
- (0, import_react8.useEffect)(() => {
1538
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
1539
+ (0, import_react9.useEffect)(() => {
1446
1540
  onLoadStateChange?.(loadState);
1447
1541
  }, [loadState, onLoadStateChange]);
1448
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
1449
- const paypalResumeAttempted = (0, import_react8.useRef)(false);
1450
- const beforeClickRef = (0, import_react8.useRef)(null);
1542
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1543
+ const paypalResumeAttempted = (0, import_react9.useRef)(false);
1544
+ const beforeClickRef = (0, import_react9.useRef)(null);
1451
1545
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1452
- (0, import_react8.useEffect)(() => {
1546
+ (0, import_react9.useEffect)(() => {
1453
1547
  if (!stripe || paypalResumeAttempted.current) return;
1454
1548
  const params = new URLSearchParams(window.location.search);
1455
1549
  const paymentIntentId = params.get("payment_intent");
@@ -1515,7 +1609,7 @@ function PayPalButtonInner({
1515
1609
  }
1516
1610
  })();
1517
1611
  }, [stripe, onTokenizedBody, onErrorChange, onDecline]);
1518
- const handlePayPalClick = (0, import_react8.useCallback)(async (event) => {
1612
+ const handlePayPalClick = (0, import_react9.useCallback)(async (event) => {
1519
1613
  if (isProcessing || submitting) {
1520
1614
  event.reject();
1521
1615
  return;
@@ -1534,7 +1628,7 @@ function PayPalButtonInner({
1534
1628
  onButtonClick?.("paypal");
1535
1629
  event.resolve();
1536
1630
  }, [isProcessing, onButtonClick, runBeforeButtonClick, submitting]);
1537
- const handlePayPalConfirm = (0, import_react8.useCallback)(async (event) => {
1631
+ const handlePayPalConfirm = (0, import_react9.useCallback)(async (event) => {
1538
1632
  if (!stripe || !elements) return;
1539
1633
  let prepared = beforeClickRef.current;
1540
1634
  beforeClickRef.current = null;
@@ -1654,14 +1748,14 @@ function PayPalButtonInner({
1654
1748
  setSubmitting(false);
1655
1749
  }
1656
1750
  }, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
1657
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1658
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1751
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1752
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1659
1753
  ExpressCheckoutReadySwap,
1660
1754
  {
1661
1755
  state: loadState,
1662
1756
  placeholderTestId: "flopay-paypal-placeholder",
1663
1757
  borderRadius: placeholderBorderRadius,
1664
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1758
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1665
1759
  import_react_stripe_js.ExpressCheckoutElement,
1666
1760
  {
1667
1761
  onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
@@ -1688,7 +1782,7 @@ function PayPalButtonInner({
1688
1782
  )
1689
1783
  }
1690
1784
  ),
1691
- submitting && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: "processing" })
1785
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
1692
1786
  ] });
1693
1787
  }
1694
1788
  function WalletButtonInner({
@@ -1707,15 +1801,15 @@ function WalletButtonInner({
1707
1801
  }) {
1708
1802
  const stripe = (0, import_react_stripe_js.useStripe)();
1709
1803
  const elements = (0, import_react_stripe_js.useElements)();
1710
- const [loadState, setLoadState] = (0, import_react8.useState)("loading");
1711
- (0, import_react8.useEffect)(() => {
1804
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
1805
+ (0, import_react9.useEffect)(() => {
1712
1806
  onLoadStateChange?.(loadState);
1713
1807
  }, [loadState, onLoadStateChange]);
1714
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
1808
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1715
1809
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1716
- const lastWalletMethodRef = (0, import_react8.useRef)("card");
1717
- const beforeClickRef = (0, import_react8.useRef)(null);
1718
- const handleWalletConfirm = (0, import_react8.useCallback)(
1810
+ const lastWalletMethodRef = (0, import_react9.useRef)("card");
1811
+ const beforeClickRef = (0, import_react9.useRef)(null);
1812
+ const handleWalletConfirm = (0, import_react9.useCallback)(
1719
1813
  async (event) => {
1720
1814
  if (!stripe || !elements) return;
1721
1815
  const walletType = event.expressPaymentType;
@@ -1805,7 +1899,7 @@ function WalletButtonInner({
1805
1899
  },
1806
1900
  [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
1807
1901
  );
1808
- const expressMethodMap = (0, import_react8.useMemo)(() => {
1902
+ const expressMethodMap = (0, import_react9.useMemo)(() => {
1809
1903
  const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
1810
1904
  const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
1811
1905
  const enabledKeys = new Set(expressMethods.map(import_shared5.stripeExpressMethodToOptionKey));
@@ -1819,18 +1913,18 @@ function WalletButtonInner({
1819
1913
  }
1820
1914
  return out;
1821
1915
  }, [expressMethods]);
1822
- const availableMethodKeys = (0, import_react8.useMemo)(
1916
+ const availableMethodKeys = (0, import_react9.useMemo)(
1823
1917
  () => expressMethods.map(import_shared5.stripeExpressMethodToOptionKey),
1824
1918
  [expressMethods]
1825
1919
  );
1826
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1827
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1920
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1921
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1828
1922
  ExpressCheckoutReadySwap,
1829
1923
  {
1830
1924
  state: loadState,
1831
1925
  placeholderTestId: "flopay-wallet-placeholder",
1832
1926
  borderRadius: placeholderBorderRadius,
1833
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1927
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1834
1928
  import_react_stripe_js.ExpressCheckoutElement,
1835
1929
  {
1836
1930
  onReady: (event) => {
@@ -1869,7 +1963,7 @@ function WalletButtonInner({
1869
1963
  )
1870
1964
  }
1871
1965
  ),
1872
- submitting && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: "processing" })
1966
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
1873
1967
  ] });
1874
1968
  }
1875
1969
  function StripeMethodButton({
@@ -1890,7 +1984,7 @@ function StripeMethodButton({
1890
1984
  const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
1891
1985
  const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
1892
1986
  const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
1893
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1987
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1894
1988
  "button",
1895
1989
  {
1896
1990
  type: "button",
@@ -1937,9 +2031,9 @@ function StripeMethodButton({
1937
2031
  // Pulse-skeleton parity with the wallet ECE: no spinner, just the
1938
2032
  // status text on top of the pulsing background. Keeps the loading
1939
2033
  // affordance shape-equivalent across both kinds of tile.
1940
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
1941
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1942
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2034
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
2035
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2036
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1943
2037
  "span",
1944
2038
  {
1945
2039
  style: {
@@ -1952,7 +2046,7 @@ function StripeMethodButton({
1952
2046
  gap: (0, import_shared5.hasVendoredStripeMethodLogo)(method) ? 8 : 0
1953
2047
  },
1954
2048
  children: [
1955
- brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2049
+ brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1956
2050
  "span",
1957
2051
  {
1958
2052
  "aria-hidden": "true",
@@ -1971,11 +2065,11 @@ function StripeMethodButton({
1971
2065
  dangerouslySetInnerHTML: { __html: brand.logoSvg }
1972
2066
  }
1973
2067
  ),
1974
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
2068
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
1975
2069
  ]
1976
2070
  }
1977
2071
  ),
1978
- hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2072
+ hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1979
2073
  "svg",
1980
2074
  {
1981
2075
  width: "14",
@@ -1995,7 +2089,7 @@ function StripeMethodButton({
1995
2089
  opacity: 0.7
1996
2090
  },
1997
2091
  "aria-hidden": "true",
1998
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 18l6-6-6-6" })
2092
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 18l6-6-6-6" })
1999
2093
  }
2000
2094
  )
2001
2095
  ] })
@@ -2018,16 +2112,17 @@ function StripeMethodInlineForm({
2018
2112
  isProcessing,
2019
2113
  submitButtonColor,
2020
2114
  submitButtonBorderRadius,
2021
- submitButtonStyle
2115
+ submitButtonStyle,
2116
+ errorText
2022
2117
  }) {
2023
2118
  const stripe = (0, import_react_stripe_js.useStripe)();
2024
2119
  const elements = (0, import_react_stripe_js.useElements)();
2025
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
2026
- const submittingRef = (0, import_react8.useRef)(false);
2027
- const [isMethodComplete, setIsMethodComplete] = (0, import_react8.useState)(false);
2028
- const [loadState, setLoadState] = (0, import_react8.useState)("loading");
2120
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
2121
+ const submittingRef = (0, import_react9.useRef)(false);
2122
+ const [isMethodComplete, setIsMethodComplete] = (0, import_react9.useState)(false);
2123
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
2029
2124
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2030
- const handlePay = (0, import_react8.useCallback)(async () => {
2125
+ const handlePay = (0, import_react9.useCallback)(async () => {
2031
2126
  if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
2032
2127
  submittingRef.current = true;
2033
2128
  setSubmitting(true);
@@ -2167,8 +2262,8 @@ function StripeMethodInlineForm({
2167
2262
  onDecline
2168
2263
  ]);
2169
2264
  void onCancel;
2170
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
2171
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2265
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
2266
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2172
2267
  import_react_stripe_js.PaymentElement,
2173
2268
  {
2174
2269
  onReady: () => setLoadState("ready"),
@@ -2188,7 +2283,7 @@ function StripeMethodInlineForm({
2188
2283
  }
2189
2284
  }
2190
2285
  ),
2191
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2286
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2192
2287
  "button",
2193
2288
  {
2194
2289
  type: "button",
@@ -2214,7 +2309,23 @@ function StripeMethodInlineForm({
2214
2309
  },
2215
2310
  children: submitting ? "Processing\u2026" : `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(method)}`
2216
2311
  }
2217
- )
2312
+ ),
2313
+ errorText && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
2314
+ margin: "0.75rem 0 0",
2315
+ padding: "0.625rem 0.875rem",
2316
+ background: "#FEF2F2",
2317
+ border: "1px solid #FECACA",
2318
+ borderRadius: "8px",
2319
+ color: "#991B1B",
2320
+ fontSize: "0.85rem",
2321
+ fontWeight: 600,
2322
+ display: "flex",
2323
+ alignItems: "center",
2324
+ gap: "0.5rem"
2325
+ }, children: [
2326
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2327
+ errorText
2328
+ ] })
2218
2329
  ] });
2219
2330
  }
2220
2331
  function StripePaymentElementInner({
@@ -2242,17 +2353,17 @@ function StripePaymentElementInner({
2242
2353
  expandedApmMethod
2243
2354
  }) {
2244
2355
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2245
- const [expandedMethod, setExpandedMethod] = (0, import_react8.useState)(null);
2246
- const [submittingMethod, setSubmittingMethod] = (0, import_react8.useState)(null);
2247
- const submittingRef = (0, import_react8.useRef)(false);
2248
- (0, import_react8.useEffect)(() => {
2356
+ const [expandedMethod, setExpandedMethod] = (0, import_react9.useState)(null);
2357
+ const [submittingMethod, setSubmittingMethod] = (0, import_react9.useState)(null);
2358
+ const submittingRef = (0, import_react9.useRef)(false);
2359
+ (0, import_react9.useEffect)(() => {
2249
2360
  if (paymentElementMethods.length > 0 && stripeInstance) {
2250
2361
  onLoadStateChange?.("ready");
2251
2362
  } else if (!stripeInstance) {
2252
2363
  onLoadStateChange?.("loading");
2253
2364
  }
2254
2365
  }, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
2255
- const handleAutoConfirm = (0, import_react8.useCallback)(async (method) => {
2366
+ const handleAutoConfirm = (0, import_react9.useCallback)(async (method) => {
2256
2367
  if (!stripeInstance) return;
2257
2368
  if (submittingRef.current || isProcessing) return;
2258
2369
  submittingRef.current = true;
@@ -2391,9 +2502,9 @@ function StripePaymentElementInner({
2391
2502
  onErrorChange,
2392
2503
  onDecline
2393
2504
  ]);
2394
- const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react8.useState)(null);
2505
+ const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react9.useState)(null);
2395
2506
  const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
2396
- const handleMethodClick = (0, import_react8.useCallback)((method) => {
2507
+ const handleMethodClick = (0, import_react9.useCallback)((method) => {
2397
2508
  if (submittingRef.current || isProcessing) return;
2398
2509
  if (activeExpandedMethod && activeExpandedMethod !== method) return;
2399
2510
  if ((0, import_shared5.needsStripeMethodExplicitConfirm)(method)) {
@@ -2406,14 +2517,14 @@ function StripePaymentElementInner({
2406
2517
  void handleAutoConfirm(method);
2407
2518
  }
2408
2519
  }, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
2409
- const localInlineElementsOptions = (0, import_react8.useMemo)(() => {
2520
+ const localInlineElementsOptions = (0, import_react9.useMemo)(() => {
2410
2521
  if (!localExpandedMethod) return null;
2411
2522
  return {
2412
2523
  ...paymentElementBaseOptions,
2413
2524
  paymentMethodTypes: [localExpandedMethod]
2414
2525
  };
2415
2526
  }, [localExpandedMethod, paymentElementBaseOptions]);
2416
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2527
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2417
2528
  "div",
2418
2529
  {
2419
2530
  "data-testid": "flopay-stripe-payment-element-region",
@@ -2422,8 +2533,8 @@ function StripePaymentElementInner({
2422
2533
  const isExpanded = expandedApmMethod === method;
2423
2534
  const isSubmittingThis = submittingMethod === method;
2424
2535
  const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
2425
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react8.default.Fragment, { children: [
2426
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2536
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.default.Fragment, { children: [
2537
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2427
2538
  StripeMethodButton,
2428
2539
  {
2429
2540
  method,
@@ -2440,12 +2551,12 @@ function StripePaymentElementInner({
2440
2551
  fontFamily: buttonAppearance?.fontFamily
2441
2552
  }
2442
2553
  ),
2443
- !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2554
+ !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2444
2555
  import_react_stripe_js.Elements,
2445
2556
  {
2446
2557
  stripe: stripeInstance,
2447
2558
  options: localInlineElementsOptions,
2448
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2559
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2449
2560
  StripeMethodInlineForm,
2450
2561
  {
2451
2562
  method,
@@ -2498,6 +2609,7 @@ function SplitCardFormInner({
2498
2609
  showPayPal = true,
2499
2610
  showStripe = true,
2500
2611
  enabledPaymentMethods,
2612
+ enabledPaymentMethodCountries,
2501
2613
  showApplePay = true,
2502
2614
  showGooglePay = true,
2503
2615
  layout = "default",
@@ -2512,6 +2624,8 @@ function SplitCardFormInner({
2512
2624
  onButtonClick,
2513
2625
  onBeforeButtonClick,
2514
2626
  enableAVS: enableAVSProp,
2627
+ cardFieldOrder,
2628
+ cardPreFormSlot,
2515
2629
  avsLayout: avsLayoutProp = "row",
2516
2630
  country: countryProp,
2517
2631
  zip: zipProp,
@@ -2536,68 +2650,95 @@ function SplitCardFormInner({
2536
2650
  const flopay = useFloPay();
2537
2651
  const paypalFlopay = usePayPalFloPay();
2538
2652
  const elements = useElements();
2539
- const checkout = (0, import_react8.useContext)(CheckoutContext);
2653
+ const checkout = (0, import_react9.useContext)(CheckoutContext);
2540
2654
  const contextBillingUrl = useBillingApiUrl();
2541
- const [processing, setProcessing] = (0, import_react8.useState)(false);
2542
- const [error, setError] = (0, import_react8.useState)(null);
2543
- const [is3DSActive, setIs3DSActive] = (0, import_react8.useState)(false);
2544
- const [selectedCountry, setSelectedCountry] = (0, import_react8.useState)(countryProp ?? "US");
2545
- const [zipCode, setZipCode] = (0, import_react8.useState)(zipProp ?? "");
2546
- const [addressLine1, setAddressLine1] = (0, import_react8.useState)(addressLine1Prop ?? "");
2547
- const [addressLine2, setAddressLine2] = (0, import_react8.useState)(addressLine2Prop ?? "");
2548
- const [city, setCity] = (0, import_react8.useState)(cityProp ?? "");
2549
- const [stateValue, setStateValue] = (0, import_react8.useState)(stateProp ?? "");
2550
- const [accountPatch, setAccountPatch] = (0, import_react8.useState)({});
2551
- const zipCodeRef = (0, import_react8.useRef)(zipProp ?? "");
2552
- const selectedCountryRef = (0, import_react8.useRef)(countryProp ?? "US");
2553
- const addressLine1Ref = (0, import_react8.useRef)(addressLine1Prop ?? "");
2554
- const addressLine2Ref = (0, import_react8.useRef)(addressLine2Prop ?? "");
2555
- const cityRef = (0, import_react8.useRef)(cityProp ?? "");
2556
- const stateRef = (0, import_react8.useRef)(stateProp ?? "");
2557
- const avsConfig = (0, import_react8.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
2655
+ const [processing, setProcessing] = (0, import_react9.useState)(false);
2656
+ const [error, setError] = (0, import_react9.useState)(null);
2657
+ const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
2658
+ const [selectedCountry, setSelectedCountry] = (0, import_react9.useState)(countryProp ?? "US");
2659
+ const [zipCode, setZipCode] = (0, import_react9.useState)(zipProp ?? "");
2660
+ const [addressLine1, setAddressLine1] = (0, import_react9.useState)(addressLine1Prop ?? "");
2661
+ const [addressLine2, setAddressLine2] = (0, import_react9.useState)(addressLine2Prop ?? "");
2662
+ const [city, setCity] = (0, import_react9.useState)(cityProp ?? "");
2663
+ const [stateValue, setStateValue] = (0, import_react9.useState)(stateProp ?? "");
2664
+ const [accountPatch, setAccountPatch] = (0, import_react9.useState)({});
2665
+ const zipCodeRef = (0, import_react9.useRef)(zipProp ?? "");
2666
+ const selectedCountryRef = (0, import_react9.useRef)(countryProp ?? "US");
2667
+ const addressLine1Ref = (0, import_react9.useRef)(addressLine1Prop ?? "");
2668
+ const addressLine2Ref = (0, import_react9.useRef)(addressLine2Prop ?? "");
2669
+ const cityRef = (0, import_react9.useRef)(cityProp ?? "");
2670
+ const stateRef = (0, import_react9.useRef)(stateProp ?? "");
2671
+ const avsConfig = (0, import_react9.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
2558
2672
  const enableAVS = avsConfig !== null;
2559
- const [viewState, setViewState] = (0, import_react8.useState)(initialCardOpen ? "card" : "buttons");
2560
- const [expandedApmMethod, setExpandedApmMethod] = (0, import_react8.useState)(null);
2673
+ const vaultBlockReady = Boolean(session?.vault?.html);
2674
+ const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
2675
+ const vaultActive = Boolean(
2676
+ showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
2677
+ );
2678
+ const cardCapture = (0, import_react9.useMemo)(() => {
2679
+ if (!flopay || !vaultActive || !sessionId) return null;
2680
+ return flopay.cardCapture({ sessionId });
2681
+ }, [flopay, vaultActive, sessionId]);
2682
+ const { avsInvalid, invalidAvsFields } = (0, import_react9.useMemo)(() => {
2683
+ const none = { line1: false, city: false, state: false, zip: false };
2684
+ if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
2685
+ const cc = selectedCountry;
2686
+ const isEmpty = (field, value) => (0, import_shared5.isAVSFieldVisible)(field, cc) && !value.trim();
2687
+ const invalidAvsFields2 = {
2688
+ line1: isEmpty(avsConfig.address_line_1, addressLine1),
2689
+ city: isEmpty(avsConfig.city, city),
2690
+ state: isEmpty(avsConfig.state, stateValue),
2691
+ zip: isEmpty(avsConfig.postal_code, zipCode)
2692
+ };
2693
+ const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
2694
+ return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
2695
+ }, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, zipCode]);
2696
+ const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react9.useState)(false);
2697
+ const [vaultMount, setVaultMount] = (0, import_react9.useState)(
2698
+ () => toVaultMount(session?.vault)
2699
+ );
2700
+ const [viewState, setViewState] = (0, import_react9.useState)(initialCardOpen ? "card" : "buttons");
2701
+ const [expandedApmMethod, setExpandedApmMethod] = (0, import_react9.useState)(null);
2561
2702
  const showCardForm = viewState === "expanding" || viewState === "card";
2562
2703
  const TRANSITION_MS = 280;
2563
- const expandToCard = (0, import_react8.useCallback)(() => {
2704
+ const expandToCard = (0, import_react9.useCallback)(() => {
2564
2705
  setViewState("expanding");
2565
2706
  setTimeout(() => setViewState("card"), TRANSITION_MS);
2566
2707
  }, []);
2567
- const collapseToButtons = (0, import_react8.useCallback)(() => {
2708
+ const collapseToButtons = (0, import_react9.useCallback)(() => {
2568
2709
  setViewState("collapsing");
2569
2710
  setTimeout(() => setViewState("buttons"), TRANSITION_MS);
2570
2711
  }, []);
2571
- const expandToApm = (0, import_react8.useCallback)((method) => {
2712
+ const expandToApm = (0, import_react9.useCallback)((method) => {
2572
2713
  setExpandedApmMethod(method);
2573
2714
  setViewState("apm-expanding");
2574
2715
  setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
2575
2716
  }, []);
2576
- const collapseFromApm = (0, import_react8.useCallback)(() => {
2717
+ const collapseFromApm = (0, import_react9.useCallback)(() => {
2577
2718
  setViewState("apm-collapsing");
2578
2719
  setTimeout(() => {
2579
2720
  setViewState("buttons");
2580
2721
  setExpandedApmMethod(null);
2581
2722
  }, TRANSITION_MS);
2582
2723
  }, []);
2583
- (0, import_react8.useEffect)(() => {
2724
+ (0, import_react9.useEffect)(() => {
2584
2725
  if (layout === "buttons" && initialCardOpen) {
2585
2726
  setViewState("card");
2586
2727
  }
2587
2728
  }, [layout, initialCardOpen]);
2588
- const [fullName, setFullName] = (0, import_react8.useState)("");
2589
- const [formReady, setFormReady] = (0, import_react8.useState)(false);
2590
- const [overlayStatus, setOverlayStatus] = (0, import_react8.useState)(null);
2591
- const processingRef = (0, import_react8.useRef)(false);
2592
- const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react8.useState)(null);
2593
- const paypalDirectRetryRef = (0, import_react8.useRef)(paypalDirectRetry);
2594
- (0, import_react8.useEffect)(() => {
2729
+ const [fullName, setFullName] = (0, import_react9.useState)("");
2730
+ const [formReady, setFormReady] = (0, import_react9.useState)(false);
2731
+ const [overlayStatus, setOverlayStatus] = (0, import_react9.useState)(null);
2732
+ const processingRef = (0, import_react9.useRef)(false);
2733
+ const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react9.useState)(null);
2734
+ const paypalDirectRetryRef = (0, import_react9.useRef)(paypalDirectRetry);
2735
+ (0, import_react9.useEffect)(() => {
2595
2736
  paypalDirectRetryRef.current = paypalDirectRetry;
2596
2737
  }, [paypalDirectRetry]);
2597
2738
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
2598
2739
  const displayError = externalError ?? error;
2599
- const themeBundle = (0, import_react8.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
2600
- const bStyles = (0, import_react8.useMemo)(() => {
2740
+ const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
2741
+ const bStyles = (0, import_react9.useMemo)(() => {
2601
2742
  const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
2602
2743
  if (!buttonsStylesOverride) return base;
2603
2744
  return {
@@ -2612,11 +2753,36 @@ function SplitCardFormInner({
2612
2753
  };
2613
2754
  }, [themeBundle, buttonsTheme, buttonsStylesOverride]);
2614
2755
  const appearance = appearanceOverride ?? themeBundle?.appearance;
2756
+ const vaultThemeColors = (0, import_react9.useMemo)(() => {
2757
+ const vars = appearance?.variables;
2758
+ const asString = (value) => typeof value === "string" && value ? value : void 0;
2759
+ const submitButtonStyle = bStyles.submitButton;
2760
+ const primary = asString(vars?.colorPrimary) ?? asString(submitButtonStyle?.backgroundColor) ?? "#4A49FF";
2761
+ const isButtonsLayout = layout === "buttons";
2762
+ const nameInput = bStyles.nameInput;
2763
+ return {
2764
+ primaryColor: primary,
2765
+ primaryHoverColor: asString(vars?.colorPrimaryHover) ?? darkenHex(primary, 0.12),
2766
+ inputBackgroundColor: asString(bStyles.cardInputBackground) ?? asString(vars?.colorBackground) ?? "#ffffff",
2767
+ textColor: asString(bStyles.cardInputColor) ?? asString(nameInput?.color) ?? asString(vars?.colorText) ?? "#262833",
2768
+ borderColor: asString(bStyles.cardInputBorder) ?? (isButtonsLayout ? "#e5e7eb" : "#A4A4FF"),
2769
+ placeholderColor: asString(bStyles.cardInputPlaceholderColor) ?? "#9ca3af",
2770
+ errorColor: asString(vars?.colorDanger) ?? "#dc2626",
2771
+ successColor: "#16a34a",
2772
+ fontFamily: asString(nameInput?.fontFamily) ?? asString(vars?.fontFamily) ?? "Poppins, sans-serif",
2773
+ fontSize: asString(bStyles.cardInputFontSize) ?? asString(vars?.fontSizeBase) ?? "16px",
2774
+ // `resolvedInputFontWeight` equivalent — sent as a string (the widget's
2775
+ // theme applier only honors string values) so vault inputs/placeholders
2776
+ // match the AVS fields' weight per theme (default 400).
2777
+ fontWeight: String(toCssWeight(nameInput?.fontWeight) ?? 400),
2778
+ borderRadius: asString(vars?.borderRadius) ?? "8px"
2779
+ };
2780
+ }, [appearance, bStyles, layout]);
2615
2781
  const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
2616
2782
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
2617
2783
  const isSelfContained = !onTokenizedBody;
2618
2784
  const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
2619
- const resolvedAccount = (0, import_react8.useMemo)(() => mergeAccountPatch({
2785
+ const resolvedAccount = (0, import_react9.useMemo)(() => mergeAccountPatch({
2620
2786
  userId,
2621
2787
  email,
2622
2788
  firstName,
@@ -2624,17 +2790,17 @@ function SplitCardFormInner({
2624
2790
  country: countryProp,
2625
2791
  zip: zipProp
2626
2792
  }, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
2627
- const stripeInstance = (0, import_react8.useMemo)(() => {
2793
+ const stripeInstance = (0, import_react9.useMemo)(() => {
2628
2794
  if (!flopay) return null;
2629
2795
  return flopay.getRawProvider();
2630
2796
  }, [flopay]);
2631
- const paypalStripeInstance = (0, import_react8.useMemo)(() => {
2797
+ const paypalStripeInstance = (0, import_react9.useMemo)(() => {
2632
2798
  if (!paypalFlopay) return null;
2633
2799
  return paypalFlopay.getRawProvider();
2634
2800
  }, [paypalFlopay]);
2635
2801
  const amountInCents = totalAmount || 100;
2636
2802
  const stripeAppearanceProp = appearance ? { appearance } : null;
2637
- const paymentElementAppearance = (0, import_react8.useMemo)(() => {
2803
+ const paymentElementAppearance = (0, import_react9.useMemo)(() => {
2638
2804
  const base = appearance ?? {};
2639
2805
  const baseRules = base.rules ?? {};
2640
2806
  return {
@@ -2654,7 +2820,7 @@ function SplitCardFormInner({
2654
2820
  }
2655
2821
  };
2656
2822
  }, [appearance]);
2657
- const walletOptions = (0, import_react8.useMemo)(() => {
2823
+ const walletOptions = (0, import_react9.useMemo)(() => {
2658
2824
  const modeOptions = resolveWalletElementsMode(totalAmount);
2659
2825
  return {
2660
2826
  ...modeOptions,
@@ -2665,7 +2831,7 @@ function SplitCardFormInner({
2665
2831
  ...stripeAppearanceProp
2666
2832
  };
2667
2833
  }, [totalAmount, currency, stripeAppearanceProp]);
2668
- const paypalOptions = (0, import_react8.useMemo)(() => ({
2834
+ const paypalOptions = (0, import_react9.useMemo)(() => ({
2669
2835
  mode: "payment",
2670
2836
  amount: amountInCents,
2671
2837
  currency: currency.toLowerCase(),
@@ -2673,35 +2839,183 @@ function SplitCardFormInner({
2673
2839
  setupFutureUsage: "off_session",
2674
2840
  ...stripeAppearanceProp
2675
2841
  }), [amountInCents, currency, stripeAppearanceProp]);
2676
- const updateError = (0, import_react8.useCallback)(
2842
+ const updateError = (0, import_react9.useCallback)(
2677
2843
  (err) => {
2678
2844
  setError(err);
2679
2845
  onErrorChange?.(err);
2680
2846
  },
2681
2847
  [onErrorChange]
2682
2848
  );
2683
- const emitDecline = (0, import_react8.useCallback)(
2849
+ (0, import_react9.useEffect)(() => {
2850
+ if (!vaultActive || !cardCapture) return;
2851
+ cardCapture.setSubmitGate?.(avsInvalid);
2852
+ }, [vaultActive, cardCapture, avsInvalid]);
2853
+ (0, import_react9.useEffect)(() => {
2854
+ if (!vaultActive || !cardCapture) return;
2855
+ cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
2856
+ }, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
2857
+ (0, import_react9.useEffect)(() => {
2858
+ if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
2859
+ updateError(null);
2860
+ }
2861
+ }, [viewState, updateError]);
2862
+ const emitDecline = (0, import_react9.useCallback)(
2684
2863
  (method, input, overrides) => {
2685
2864
  onDecline?.(buildDeclineEvent(method, input, overrides));
2686
2865
  },
2687
2866
  [onDecline]
2688
2867
  );
2868
+ (0, import_react9.useEffect)(() => {
2869
+ if (!vaultActive || !sessionId) {
2870
+ setVaultMount(null);
2871
+ return;
2872
+ }
2873
+ const embedded = toVaultMount(session?.vault);
2874
+ if (embedded) {
2875
+ setVaultMount(embedded);
2876
+ return;
2877
+ }
2878
+ setVaultMount(null);
2879
+ let active = true;
2880
+ new import_js2.PaymentAPI(baseUrl).getVaultCapture(sessionId, nonce).then((block) => {
2881
+ if (!active) return;
2882
+ const mount = toVaultMount(block);
2883
+ if (mount) {
2884
+ setVaultMount(mount);
2885
+ } else {
2886
+ updateError("Failed to load the secure card form.");
2887
+ }
2888
+ }).catch((err) => {
2889
+ if (active) {
2890
+ updateError(err instanceof Error ? err.message : "Failed to load the secure card form.");
2891
+ }
2892
+ });
2893
+ return () => {
2894
+ active = false;
2895
+ };
2896
+ }, [
2897
+ vaultActive,
2898
+ sessionId,
2899
+ session?.vault?.html,
2900
+ session?.vault?.messageToken,
2901
+ session?.vault?.expectedOrigin,
2902
+ baseUrl,
2903
+ nonce,
2904
+ updateError
2905
+ ]);
2906
+ (0, import_react9.useEffect)(() => {
2907
+ if (!vaultActive || !cardCapture) return;
2908
+ let cancelled = false;
2909
+ const offSubmitting = cardCapture.on("submitting", () => {
2910
+ setHasAttemptedSubmit(true);
2911
+ setOverlayStatus("processing");
2912
+ if (!sessionId || !nonce) return;
2913
+ const cc = selectedCountryRef.current || resolvedAccount.country || "US";
2914
+ const stateVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) : false;
2915
+ const line1Visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) : false;
2916
+ const zipVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) : false;
2917
+ const cityVisible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) : false;
2918
+ const line2Visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) : false;
2919
+ const derivedState = line1Visible && !stateVisible && zipVisible ? (0, import_shared5.getStateFromPostalCode)(cc, zipCodeRef.current ?? "") : null;
2920
+ const stateValue2 = stateVisible ? stateRef.current : derivedState;
2921
+ void new import_js2.PaymentAPI(baseUrl).patchAccountSnapshot(sessionId, nonce, {
2922
+ accountData: {
2923
+ userId: resolvedAccount.userId ?? "",
2924
+ email: resolvedAccount.email ?? "",
2925
+ firstName: resolvedAccount.firstName ?? fullName.trim().split(/\s+/)[0] ?? "",
2926
+ lastName: resolvedAccount.lastName ?? fullName.trim().split(/\s+/).slice(1).join(" ") ?? "",
2927
+ ...zipVisible && zipCodeRef.current ? { zip: zipCodeRef.current } : {},
2928
+ ...cityVisible && cityRef.current ? { city: cityRef.current } : {},
2929
+ ...stateValue2 ? { state: stateValue2 } : {},
2930
+ ...line1Visible && addressLine1Ref.current ? { addressLine1: addressLine1Ref.current } : {},
2931
+ ...line2Visible && addressLine2Ref.current ? { addressLine2: addressLine2Ref.current } : {},
2932
+ country: cc
2933
+ },
2934
+ ...avsCheckProp !== void 0 ? { avsCheck: avsCheckProp } : {},
2935
+ ...avsConfig ? {
2936
+ avsConfig: {
2937
+ country: (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc),
2938
+ postal_code: zipVisible,
2939
+ address_line_1: line1Visible,
2940
+ address_line_2: line2Visible,
2941
+ city: cityVisible,
2942
+ state: stateVisible
2943
+ }
2944
+ } : {}
2945
+ }).catch(() => {
2946
+ });
2947
+ });
2948
+ const offComplete = cardCapture.on("complete", async (event) => {
2949
+ markSessionRecentlyCompleted(event.sessionId ?? sessionId);
2950
+ setOverlayStatus("success");
2951
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
2952
+ if (cancelled) return;
2953
+ onComplete?.({
2954
+ status: "succeeded",
2955
+ paymentIntentId: event.intentId,
2956
+ checkoutMethod: "card"
2957
+ });
2958
+ });
2959
+ const offDecline = cardCapture.on("decline", async (event) => {
2960
+ const message = event.message ?? "Your payment was declined. Please try another card or contact your bank.";
2961
+ updateError(message);
2962
+ setOverlayStatus("error");
2963
+ emitDecline("card", message, event.declineReason ? { declineCode: event.declineReason } : void 0);
2964
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
2965
+ if (cancelled) return;
2966
+ setOverlayStatus(null);
2967
+ });
2968
+ const offError = cardCapture.on("error", async (event) => {
2969
+ const message = event.message ?? "There was a problem processing your payment. Please try again.";
2970
+ updateError(message);
2971
+ setOverlayStatus("error");
2972
+ onError?.(new import_shared6.FloPayError(message, "api_error"));
2973
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
2974
+ if (cancelled) return;
2975
+ setOverlayStatus(null);
2976
+ });
2977
+ return () => {
2978
+ cancelled = true;
2979
+ offSubmitting();
2980
+ offComplete();
2981
+ offDecline();
2982
+ offError();
2983
+ };
2984
+ }, [
2985
+ vaultActive,
2986
+ cardCapture,
2987
+ sessionId,
2988
+ nonce,
2989
+ baseUrl,
2990
+ avsConfig,
2991
+ avsCheckProp,
2992
+ resolvedAccount.userId,
2993
+ resolvedAccount.email,
2994
+ resolvedAccount.firstName,
2995
+ resolvedAccount.lastName,
2996
+ resolvedAccount.country,
2997
+ fullName,
2998
+ onComplete,
2999
+ onError,
3000
+ updateError,
3001
+ emitDecline
3002
+ ]);
2689
3003
  const directPaypalConfigured = !!directPaypal?.clientId;
2690
3004
  const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
2691
3005
  const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
2692
3006
  const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
2693
- const { expressMethods, paymentElementMethods } = (0, import_react8.useMemo)(
3007
+ const { expressMethods, paymentElementMethods } = (0, import_react9.useMemo)(
2694
3008
  () => (0, import_shared5.partitionStripeMethods)(enabledPaymentMethods, {
2695
3009
  excludePaypal: directPaypalConfigured
2696
3010
  }),
2697
3011
  [enabledPaymentMethods, directPaypalConfigured]
2698
3012
  );
2699
3013
  const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
2700
- const expressMethodsForWalletRow = (0, import_react8.useMemo)(
3014
+ const expressMethodsForWalletRow = (0, import_react9.useMemo)(
2701
3015
  () => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
2702
3016
  [expressMethods, paypalRenderedSeparately]
2703
3017
  );
2704
- const legacyExpressMethods = (0, import_react8.useMemo)(() => {
3018
+ const legacyExpressMethods = (0, import_react9.useMemo)(() => {
2705
3019
  const out = [];
2706
3020
  if (showApplePay) out.push("apple_pay");
2707
3021
  if (showGooglePay) out.push("google_pay");
@@ -2709,30 +3023,31 @@ function SplitCardFormInner({
2709
3023
  }, [showApplePay, showGooglePay]);
2710
3024
  const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
2711
3025
  const showWallets = showStripe && walletExpressMethods.length > 0;
2712
- const paymentElementMethodsForCurrency = (0, import_react8.useMemo)(
2713
- () => (0, import_shared5.filterStripeMethodsByAmount)(
2714
- (0, import_shared5.filterStripeMethodsByCountry)(
2715
- (0, import_shared5.filterStripeMethodsByCurrency)(paymentElementMethods, currency),
2716
- countryProp
2717
- ),
2718
- currency,
2719
- amountInCents
2720
- ),
2721
- [paymentElementMethods, currency, countryProp, amountInCents]
2722
- );
2723
- const paymentElementBaseOptions = (0, import_react8.useMemo)(() => ({
3026
+ const apmCountry = enableAVS ? selectedCountry : countryProp;
3027
+ const paymentElementMethodsForCurrency = (0, import_react9.useMemo)(() => {
3028
+ const target = apmCountry?.trim().toUpperCase();
3029
+ if (!target) return paymentElementMethods;
3030
+ if (!enabledPaymentMethodCountries) {
3031
+ return (0, import_shared5.filterStripeMethodsByCountry)(paymentElementMethods, apmCountry);
3032
+ }
3033
+ return paymentElementMethods.filter((method) => {
3034
+ const allowed = enabledPaymentMethodCountries[method];
3035
+ return !allowed || allowed.length === 0 || allowed.includes(target);
3036
+ });
3037
+ }, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
3038
+ const paymentElementBaseOptions = (0, import_react9.useMemo)(() => ({
2724
3039
  mode: "payment",
2725
3040
  amount: amountInCents,
2726
3041
  currency: currency.toLowerCase(),
2727
3042
  paymentMethodCreation: "manual",
2728
3043
  appearance: paymentElementAppearance
2729
3044
  }), [amountInCents, currency, paymentElementAppearance]);
2730
- const [paypalLoadState, setPaypalLoadState] = (0, import_react8.useState)("loading");
2731
- const [walletLoadState, setWalletLoadState] = (0, import_react8.useState)("loading");
2732
- const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react8.useState)("loading");
2733
- const [directPaypalReady, setDirectPaypalReady] = (0, import_react8.useState)(false);
2734
- const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react8.useState)();
2735
- (0, import_react8.useEffect)(() => {
3045
+ const [paypalLoadState, setPaypalLoadState] = (0, import_react9.useState)("loading");
3046
+ const [walletLoadState, setWalletLoadState] = (0, import_react9.useState)("loading");
3047
+ const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react9.useState)("loading");
3048
+ const [directPaypalReady, setDirectPaypalReady] = (0, import_react9.useState)(false);
3049
+ const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react9.useState)();
3050
+ (0, import_react9.useEffect)(() => {
2736
3051
  setInAppBrowserDetected(isInAppBrowser());
2737
3052
  }, []);
2738
3053
  const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
@@ -2744,8 +3059,8 @@ function SplitCardFormInner({
2744
3059
  const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
2745
3060
  const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
2746
3061
  const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
2747
- const validationFiredRef = (0, import_react8.useRef)(false);
2748
- (0, import_react8.useEffect)(() => {
3062
+ const validationFiredRef = (0, import_react9.useRef)(false);
3063
+ (0, import_react9.useEffect)(() => {
2749
3064
  if (validationFiredRef.current) return;
2750
3065
  if (!showStripe && !showPayPal) {
2751
3066
  validationFiredRef.current = true;
@@ -2765,8 +3080,8 @@ function SplitCardFormInner({
2765
3080
  updateError(err.message);
2766
3081
  }
2767
3082
  }, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
2768
- const deprecationLoggedRef = (0, import_react8.useRef)(false);
2769
- (0, import_react8.useEffect)(() => {
3083
+ const deprecationLoggedRef = (0, import_react9.useRef)(false);
3084
+ (0, import_react9.useEffect)(() => {
2770
3085
  if (deprecationLoggedRef.current) return;
2771
3086
  if (!hasEnabledMethods) return;
2772
3087
  const stale = [];
@@ -2778,14 +3093,14 @@ function SplitCardFormInner({
2778
3093
  `[FloPay] ${stale.join(" / ")} ${stale.length === 1 ? "is" : "are"} deprecated: the Apple Pay / Google Pay surface is now driven by \`gateways.stripe.enabledPaymentMethods\` on the session response. Remove the legacy prop(s) to silence this warning.`
2779
3094
  );
2780
3095
  }, [hasEnabledMethods, showApplePay, showGooglePay]);
2781
- const handleNameChange = (0, import_react8.useCallback)((value) => {
3096
+ const handleNameChange = (0, import_react9.useCallback)((value) => {
2782
3097
  setFullName(value);
2783
3098
  onFullNameChange?.(value);
2784
3099
  const parts = value.trim().split(/\s+/);
2785
3100
  onFirstNameChange?.(parts[0] ?? "");
2786
3101
  onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
2787
3102
  }, [onFullNameChange, onFirstNameChange, onLastNameChange]);
2788
- const applyInlineSessionPatch = (0, import_react8.useCallback)(
3103
+ const applyInlineSessionPatch = (0, import_react9.useCallback)(
2789
3104
  (patch, method) => {
2790
3105
  if (!checkout.applyInlineSessionPatch) {
2791
3106
  return Promise.resolve({ error: null, sessionId, nonce });
@@ -2807,7 +3122,7 @@ function SplitCardFormInner({
2807
3122
  },
2808
3123
  [checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
2809
3124
  );
2810
- const runBeforeButtonClick = (0, import_react8.useCallback)(async (method) => {
3125
+ const runBeforeButtonClick = (0, import_react9.useCallback)(async (method) => {
2811
3126
  if (!onBeforeButtonClick) return { proceed: true };
2812
3127
  try {
2813
3128
  const result = await onBeforeButtonClick({
@@ -2844,7 +3159,7 @@ function SplitCardFormInner({
2844
3159
  return { proceed: false };
2845
3160
  }
2846
3161
  }, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
2847
- const processPaymentInternal = (0, import_react8.useCallback)(
3162
+ const processPaymentInternal = (0, import_react9.useCallback)(
2848
3163
  async (tokenizedBody, overrides) => {
2849
3164
  if (processingRef.current) return;
2850
3165
  processingRef.current = true;
@@ -3055,7 +3370,7 @@ function SplitCardFormInner({
3055
3370
  },
3056
3371
  [baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
3057
3372
  );
3058
- const dispatchTokenizedBody = (0, import_react8.useCallback)(
3373
+ const dispatchTokenizedBody = (0, import_react9.useCallback)(
3059
3374
  (tokenizedBody, overrides) => {
3060
3375
  if (onTokenizedBody) {
3061
3376
  onTokenizedBody(tokenizedBody);
@@ -3065,7 +3380,7 @@ function SplitCardFormInner({
3065
3380
  },
3066
3381
  [onTokenizedBody, processPaymentInternal]
3067
3382
  );
3068
- (0, import_react8.useImperativeHandle)(innerRef, () => ({
3383
+ (0, import_react9.useImperativeHandle)(innerRef, () => ({
3069
3384
  async handleNextAction(secret) {
3070
3385
  if (!flopay) return;
3071
3386
  setIs3DSActive(true);
@@ -3092,8 +3407,8 @@ function SplitCardFormInner({
3092
3407
  }
3093
3408
  }
3094
3409
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
3095
- const stripeResumeAttemptedRef = (0, import_react8.useRef)(false);
3096
- (0, import_react8.useEffect)(() => {
3410
+ const stripeResumeAttemptedRef = (0, import_react9.useRef)(false);
3411
+ (0, import_react9.useEffect)(() => {
3097
3412
  if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
3098
3413
  const params = new URLSearchParams(window.location.search);
3099
3414
  const paymentIntentId = params.get("payment_intent");
@@ -3171,10 +3486,11 @@ function SplitCardFormInner({
3171
3486
  }, persistedOverrides);
3172
3487
  })();
3173
3488
  }, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
3174
- const handleSubmit = (0, import_react8.useCallback)(
3489
+ const handleSubmit = (0, import_react9.useCallback)(
3175
3490
  async (e) => {
3176
3491
  e.preventDefault();
3177
3492
  if (!flopay || !elements || isSubmitting || processingRef.current) return;
3493
+ if (vaultActive) return;
3178
3494
  if (layout !== "buttons") {
3179
3495
  onButtonClick?.("card");
3180
3496
  }
@@ -3202,11 +3518,13 @@ function SplitCardFormInner({
3202
3518
  return;
3203
3519
  }
3204
3520
  }
3205
- const submitResult = await flopay.submitElements();
3206
- if (submitResult.error) {
3207
- updateError(submitResult.error.message);
3208
- onError?.(submitResult.error);
3209
- return;
3521
+ if (!vaultActive) {
3522
+ const submitResult = await flopay.submitElements();
3523
+ if (submitResult.error) {
3524
+ updateError(submitResult.error.message);
3525
+ onError?.(submitResult.error);
3526
+ return;
3527
+ }
3210
3528
  }
3211
3529
  const billingAddress = {};
3212
3530
  const cc = selectedCountryRef.current;
@@ -3231,75 +3549,77 @@ function SplitCardFormInner({
3231
3549
  ...fullName.trim() ? { name: fullName.trim() } : {},
3232
3550
  ...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
3233
3551
  };
3234
- const pmResult = await flopay.createPaymentMethod(billingDetails);
3235
- if (pmResult.error || !pmResult.paymentMethodId) {
3236
- updateError(pmResult.error?.message ?? "Failed to create payment method.");
3237
- return;
3238
- }
3239
3552
  if (!sessionId || !resolvedAccount.email) {
3240
3553
  throw new import_shared6.FloPayError("Missing sessionId or email", "validation_error");
3241
3554
  }
3242
- const intentHeaders = { "Content-Type": "application/json" };
3243
- if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
3244
- const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
3245
- method: "POST",
3246
- headers: intentHeaders,
3247
- body: JSON.stringify({
3248
- sessionId,
3249
- email: resolvedAccount.email,
3250
- paymentMethodType: pmResult.paymentMethodId,
3251
- isPaypal: false
3252
- })
3253
- });
3254
- if (!intentResponse.ok) {
3255
- const intentError = await buildFloPayApiErrorFromResponse(
3256
- intentResponse,
3257
- "Failed to create payment intent"
3555
+ {
3556
+ const pmResult = await flopay.createPaymentMethod(billingDetails);
3557
+ if (pmResult.error || !pmResult.paymentMethodId) {
3558
+ updateError(pmResult.error?.message ?? "Failed to create payment method.");
3559
+ return;
3560
+ }
3561
+ const intentHeaders = { "Content-Type": "application/json" };
3562
+ if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
3563
+ const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
3564
+ method: "POST",
3565
+ headers: intentHeaders,
3566
+ body: JSON.stringify({
3567
+ sessionId,
3568
+ email: resolvedAccount.email,
3569
+ paymentMethodType: pmResult.paymentMethodId,
3570
+ isPaypal: false
3571
+ })
3572
+ });
3573
+ if (!intentResponse.ok) {
3574
+ const intentError = await buildFloPayApiErrorFromResponse(
3575
+ intentResponse,
3576
+ "Failed to create payment intent"
3577
+ );
3578
+ setOverlayStatus("error");
3579
+ updateError(intentError.message);
3580
+ onError?.(intentError);
3581
+ emitDecline("card", intentError);
3582
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3583
+ return;
3584
+ }
3585
+ const intentJson = await intentResponse.json();
3586
+ const intentClientSecret = intentJson.data?.id;
3587
+ if (!intentClientSecret) throw new import_shared6.FloPayError("No client_secret in payment intent response", "api_error");
3588
+ const confirmResult = await flopay.confirmCardPayment({
3589
+ clientSecret: intentClientSecret,
3590
+ paymentMethodId: pmResult.paymentMethodId
3591
+ });
3592
+ if (confirmResult.error) {
3593
+ setOverlayStatus("error");
3594
+ updateError(confirmResult.error.message);
3595
+ onError?.(confirmResult.error);
3596
+ emitDecline("card", confirmResult.error);
3597
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3598
+ return;
3599
+ }
3600
+ const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3601
+ const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3602
+ rawProvider,
3603
+ intentClientSecret
3258
3604
  );
3259
- setOverlayStatus("error");
3260
- updateError(intentError.message);
3261
- onError?.(intentError);
3262
- emitDecline("card", intentError);
3263
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3264
- return;
3265
- }
3266
- const intentJson = await intentResponse.json();
3267
- const intentClientSecret = intentJson.data?.id;
3268
- if (!intentClientSecret) throw new import_shared6.FloPayError("No client_secret in payment intent response", "api_error");
3269
- const confirmResult = await flopay.confirmCardPayment({
3270
- clientSecret: intentClientSecret,
3271
- paymentMethodId: pmResult.paymentMethodId
3272
- });
3273
- if (confirmResult.error) {
3274
- setOverlayStatus("error");
3275
- updateError(confirmResult.error.message);
3276
- onError?.(confirmResult.error);
3277
- emitDecline("card", confirmResult.error);
3278
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3279
- return;
3280
- }
3281
- const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3282
- const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3283
- rawProvider,
3284
- intentClientSecret
3285
- );
3286
- const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3287
- const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
3288
- if (!paymentIntentId) {
3289
- const error2 = new import_shared6.FloPayError("No payment intent returned after confirmation.", "api_error");
3290
- setOverlayStatus("error");
3291
- updateError(error2.message);
3292
- onError?.(error2);
3293
- await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3294
- return;
3605
+ const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3606
+ const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
3607
+ if (!paymentIntentId) {
3608
+ const error2 = new import_shared6.FloPayError("No payment intent returned after confirmation.", "api_error");
3609
+ setOverlayStatus("error");
3610
+ updateError(error2.message);
3611
+ onError?.(error2);
3612
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3613
+ return;
3614
+ }
3615
+ handedOff = isSelfContained;
3616
+ dispatchTokenizedBody({
3617
+ id: paymentMethodId,
3618
+ type: "card",
3619
+ threeDSecureActionResultTokenId: paymentIntentId,
3620
+ originalPaymentMethodId: pmResult.paymentMethodId
3621
+ });
3295
3622
  }
3296
- handedOff = isSelfContained;
3297
- dispatchTokenizedBody({
3298
- id: paymentMethodId,
3299
- type: "card",
3300
- threeDSecureActionResultTokenId: paymentIntentId,
3301
- originalPaymentMethodId: pmResult.paymentMethodId
3302
- });
3303
3623
  } catch (err) {
3304
3624
  setOverlayStatus("error");
3305
3625
  updateError(err instanceof Error ? err.message : "An unexpected error occurred");
@@ -3311,11 +3631,11 @@ function SplitCardFormInner({
3311
3631
  }
3312
3632
  }
3313
3633
  },
3314
- [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3634
+ [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, vaultActive, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3315
3635
  );
3316
- const isReady = flopay !== null && elements !== null;
3636
+ const isReady = flopay !== null && (vaultActive || elements !== null);
3317
3637
  if (!isReady) {
3318
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3638
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3319
3639
  }
3320
3640
  const isButtons = layout === "buttons";
3321
3641
  const appearanceVars = appearance?.variables;
@@ -3323,6 +3643,8 @@ function SplitCardFormInner({
3323
3643
  const appearanceColorBg = appearanceVars?.colorBackground;
3324
3644
  const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
3325
3645
  const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
3646
+ const resolvedDangerColor = appearanceVars?.colorDanger ?? "#dc2626";
3647
+ const avsBorderColor = (fieldInvalid) => hasAttemptedSubmit && fieldInvalid ? resolvedDangerColor : resolvedBorder;
3326
3648
  const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
3327
3649
  const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
3328
3650
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
@@ -3334,7 +3656,9 @@ function SplitCardFormInner({
3334
3656
  const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
3335
3657
  const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
3336
3658
  const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
3659
+ const buttonBorderRadius = appearanceVars?.borderRadius ?? bStyles.cardButton?.borderRadius ?? resolvedBorderRadius;
3337
3660
  const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
3661
+ const resolvedPrimaryHoverColor = appearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
3338
3662
  const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
3339
3663
  const sharedInputTypography = {
3340
3664
  fontSize: resolvedInputFontSize,
@@ -3368,14 +3692,73 @@ function SplitCardFormInner({
3368
3692
  const containerOverrides = bStyles.cardFormContainer ?? {};
3369
3693
  const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
3370
3694
  const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
3371
- const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3695
+ const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3696
+ VaultCardFields,
3697
+ {
3698
+ capture: cardCapture,
3699
+ html: vaultMount.html,
3700
+ messageToken: vaultMount.messageToken,
3701
+ expectedOrigin: vaultMount.expectedOrigin,
3702
+ theme: vaultThemeColors,
3703
+ onReady: () => {
3704
+ setFormReady(true);
3705
+ if (!avsConfig || typeof document === "undefined") return;
3706
+ const focusFirstAvs = () => {
3707
+ const block = document.querySelector('[data-testid="flopay-avs-fields"]');
3708
+ const first = block?.querySelector(
3709
+ "input:not([disabled]), select:not([disabled])"
3710
+ );
3711
+ first?.focus();
3712
+ };
3713
+ focusFirstAvs();
3714
+ let tries = 0;
3715
+ const timer = window.setInterval(() => {
3716
+ tries += 1;
3717
+ const active = document.activeElement;
3718
+ const onIframe = !!active && active.tagName === "IFRAME" && active.id === "flopay_vault_form_iframe";
3719
+ if (onIframe) {
3720
+ focusFirstAvs();
3721
+ window.clearInterval(timer);
3722
+ } else if (tries >= 50) {
3723
+ window.clearInterval(timer);
3724
+ }
3725
+ }, 100);
3726
+ },
3727
+ onError: (message) => updateError(message),
3728
+ onValidation: (message) => {
3729
+ updateError(message);
3730
+ if (message) setOverlayStatus(null);
3731
+ }
3732
+ }
3733
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3734
+ "div",
3735
+ {
3736
+ "data-testid": "flopay-vault-loading",
3737
+ style: {
3738
+ minHeight: 120,
3739
+ display: "flex",
3740
+ alignItems: "center",
3741
+ justifyContent: "center",
3742
+ color: "#6b7280",
3743
+ fontSize: 14
3744
+ },
3745
+ children: "Loading secure card form\u2026"
3746
+ }
3747
+ );
3748
+ const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3372
3749
  backgroundColor: cardBg,
3373
3750
  borderRadius: containerRadius,
3374
3751
  ...containerOverrides,
3375
3752
  padding: containerPadding,
3376
- ...sharedInputPlaceholderVars
3753
+ ...sharedInputPlaceholderVars,
3754
+ // Flex column (BOTH layouts, so default and buttons>card never diverge) so
3755
+ // AVS can be ordered above the vault widget — its submit lives inside the
3756
+ // iframe, so AVS can't sit between fields and button; it goes above the
3757
+ // card form instead of after the button.
3758
+ display: "flex",
3759
+ flexDirection: "column"
3377
3760
  }, children: [
3378
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
3761
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
3379
3762
  .flopay-shared-input::placeholder {
3380
3763
  color: var(--flopay-input-placeholder-color);
3381
3764
  opacity: 1;
@@ -3384,12 +3767,14 @@ function SplitCardFormInner({
3384
3767
  font-weight: var(--flopay-input-font-weight);
3385
3768
  }
3386
3769
  ` }),
3387
- isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3770
+ isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3388
3771
  display: "flex",
3389
3772
  alignItems: "center",
3390
- padding: "0.75rem 0 0.625rem"
3773
+ padding: "0.75rem 0 0.625rem",
3774
+ // Keep the header on top when AVS is ordered above the card on vault.
3775
+ order: vaultActive ? -2 : 0
3391
3776
  }, children: [
3392
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3777
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3393
3778
  "button",
3394
3779
  {
3395
3780
  type: "button",
@@ -3411,7 +3796,7 @@ function SplitCardFormInner({
3411
3796
  },
3412
3797
  "aria-label": "Back to payment methods",
3413
3798
  children: [
3414
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
3799
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
3415
3800
  display: "inline-flex",
3416
3801
  alignItems: "center",
3417
3802
  justifyContent: "center",
@@ -3421,12 +3806,12 @@ function SplitCardFormInner({
3421
3806
  backgroundColor: "#f3f4f6",
3422
3807
  transition: "background-color 0.15s",
3423
3808
  ...bStyles.backButtonIcon
3424
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
3425
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
3809
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
3810
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
3426
3811
  ]
3427
3812
  }
3428
3813
  ),
3429
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3814
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3430
3815
  flex: 1,
3431
3816
  textAlign: "center",
3432
3817
  fontWeight: 600,
@@ -3434,58 +3819,65 @@ function SplitCardFormInner({
3434
3819
  color: "#262833",
3435
3820
  paddingRight: 80,
3436
3821
  ...bStyles.title
3437
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) })
3822
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
3438
3823
  ] }),
3439
- !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3824
+ !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3440
3825
  textAlign: "center",
3441
3826
  fontWeight: 600,
3442
3827
  fontSize: "1.1rem",
3443
3828
  padding: "0.5rem 0",
3444
3829
  color: resolvedTitleColor,
3830
+ // Keep the title at the very top on the vault path. The card-form slot
3831
+ // (-2) and AVS block (-1) are ordered below it but above the card form.
3832
+ order: vaultActive ? -3 : 0,
3445
3833
  ...bStyles.title
3446
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
3447
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3448
- backgroundColor: cardInputBg,
3449
- border: `1px solid ${resolvedBorder}`,
3450
- borderTopLeftRadius: "8px",
3451
- borderTopRightRadius: "8px",
3452
- padding: "10px"
3453
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
3454
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex" }, children: [
3455
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3456
- flex: 1,
3457
- backgroundColor: cardInputBg,
3458
- // Longhand only — mixing `border` shorthand with per-side
3459
- // overrides triggers React's "shorthand vs longhand" warning
3460
- // because render order isn't deterministic.
3461
- borderTop: "none",
3462
- borderRight: "none",
3463
- borderBottom: `1px solid ${resolvedBorder}`,
3464
- borderLeft: `1px solid ${resolvedBorder}`,
3465
- borderBottomLeftRadius: "8px",
3466
- padding: "10px"
3467
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
3468
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3469
- flex: 1,
3834
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
3835
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3836
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3470
3837
  backgroundColor: cardInputBg,
3471
- borderTop: "none",
3472
- borderRight: `1px solid ${resolvedBorder}`,
3473
- borderBottom: `1px solid ${resolvedBorder}`,
3474
- borderLeft: `1px solid ${resolvedBorder}`,
3475
- borderBottomRightRadius: "8px",
3838
+ border: `1px solid ${resolvedBorder}`,
3839
+ borderTopLeftRadius: resolvedBorderRadius,
3840
+ borderTopRightRadius: resolvedBorderRadius,
3476
3841
  padding: "10px"
3477
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardCvcElement, { options: stripeElementStyle }) })
3842
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
3843
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex" }, children: [
3844
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3845
+ flex: 1,
3846
+ backgroundColor: cardInputBg,
3847
+ // Longhand only — mixing `border` shorthand with per-side
3848
+ // overrides triggers React's "shorthand vs longhand" warning
3849
+ // because render order isn't deterministic.
3850
+ borderTop: "none",
3851
+ borderRight: "none",
3852
+ borderBottom: `1px solid ${resolvedBorder}`,
3853
+ borderLeft: `1px solid ${resolvedBorder}`,
3854
+ borderBottomLeftRadius: resolvedBorderRadius,
3855
+ padding: "10px"
3856
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
3857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3858
+ flex: 1,
3859
+ backgroundColor: cardInputBg,
3860
+ borderTop: "none",
3861
+ borderRight: `1px solid ${resolvedBorder}`,
3862
+ borderBottom: `1px solid ${resolvedBorder}`,
3863
+ borderLeft: `1px solid ${resolvedBorder}`,
3864
+ borderBottomRightRadius: resolvedBorderRadius,
3865
+ padding: "10px"
3866
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardCvcElement, { options: stripeElementStyle }) })
3867
+ ] })
3478
3868
  ] }),
3479
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3869
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3480
3870
  backgroundColor: cardInputBg,
3481
3871
  border: `1px solid ${resolvedBorder}`,
3482
- borderRadius: "8px",
3872
+ borderRadius: resolvedBorderRadius,
3483
3873
  marginTop: "0.5rem",
3484
3874
  padding: "10px"
3485
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3875
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3486
3876
  "input",
3487
3877
  {
3488
3878
  className: "flopay-shared-input",
3879
+ id: "flopay-cc-name",
3880
+ name: "cc-name",
3489
3881
  placeholder: "Full Name on Card",
3490
3882
  autoComplete: "cc-name",
3491
3883
  value: fullName,
@@ -3502,32 +3894,32 @@ function SplitCardFormInner({
3502
3894
  }
3503
3895
  }
3504
3896
  ) }),
3505
- avsConfig && (() => {
3897
+ avsConfig && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
3506
3898
  const cc = selectedCountry;
3507
- const inputWrapStyle = (extraStyle) => ({
3899
+ const inputWrapStyle = (invalid = false) => ({
3508
3900
  backgroundColor: cardInputBg,
3509
- border: `1px solid ${resolvedBorder}`,
3510
- borderRadius: "8px",
3901
+ border: `1px solid ${avsBorderColor(invalid)}`,
3902
+ borderRadius: resolvedBorderRadius,
3511
3903
  marginTop: "0.5rem",
3512
- padding: "10px",
3513
- ...isButtons && extraStyle ? extraStyle : {}
3904
+ padding: "10px"
3514
3905
  });
3515
3906
  const inputFieldStyle = () => ({
3516
3907
  width: "100%",
3517
3908
  border: "none",
3518
3909
  outline: "none",
3519
3910
  background: "transparent",
3520
- ...sharedInputTypography,
3521
- ...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
3911
+ ...sharedInputTypography
3522
3912
  });
3523
3913
  const stateOpts = (0, import_shared5.getStateOptions)(cc);
3524
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3525
- (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: inputWrapStyle(bStyles.addressLine1Input), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3914
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3915
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3526
3916
  "input",
3527
3917
  {
3528
3918
  className: "flopay-shared-input",
3919
+ id: "flopay-billing-address-line1",
3920
+ name: "billing-address-line1",
3529
3921
  placeholder: "Street Address (e.g. 123 Main St)",
3530
- autoComplete: "address-line1",
3922
+ autoComplete: "billing address-line1",
3531
3923
  value: addressLine1,
3532
3924
  onChange: (e) => {
3533
3925
  addressLine1Ref.current = e.target.value;
@@ -3539,12 +3931,14 @@ function SplitCardFormInner({
3539
3931
  style: inputFieldStyle()
3540
3932
  }
3541
3933
  ) }),
3542
- (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: inputWrapStyle(bStyles.addressLine2Input), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3934
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: inputWrapStyle(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3543
3935
  "input",
3544
3936
  {
3545
3937
  className: "flopay-shared-input",
3938
+ id: "flopay-billing-address-line2",
3939
+ name: "billing-address-line2",
3546
3940
  placeholder: "Apt, Suite, Unit (optional)",
3547
- autoComplete: "address-line2",
3941
+ autoComplete: "billing address-line2",
3548
3942
  value: addressLine2,
3549
3943
  onChange: (e) => {
3550
3944
  addressLine2Ref.current = e.target.value;
@@ -3555,29 +3949,30 @@ function SplitCardFormInner({
3555
3949
  style: inputFieldStyle()
3556
3950
  }
3557
3951
  ) }),
3558
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3952
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3559
3953
  display: "flex",
3560
3954
  gap: "0",
3561
3955
  marginTop: "0.5rem"
3562
3956
  }, children: [
3563
- (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3957
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3564
3958
  flex: 1,
3565
3959
  backgroundColor: cardInputBg,
3566
- borderTop: `1px solid ${resolvedBorder}`,
3567
- borderRight: `1px solid ${resolvedBorder}`,
3568
- borderBottom: `1px solid ${resolvedBorder}`,
3569
- borderLeft: `1px solid ${resolvedBorder}`,
3960
+ borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3961
+ borderRight: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3962
+ borderBottom: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3963
+ borderLeft: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3570
3964
  padding: "10px",
3571
- borderTopLeftRadius: "8px",
3572
- borderBottomLeftRadius: "8px",
3573
- ...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: "8px" },
3574
- ...isButtons && bStyles.cityInput ? bStyles.cityInput : {}
3575
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3965
+ borderTopLeftRadius: resolvedBorderRadius,
3966
+ borderBottomLeftRadius: resolvedBorderRadius,
3967
+ ...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
3968
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3576
3969
  "input",
3577
3970
  {
3578
3971
  className: "flopay-shared-input",
3972
+ id: "flopay-billing-city",
3973
+ name: "billing-city",
3579
3974
  placeholder: "City",
3580
- autoComplete: "address-level2",
3975
+ autoComplete: "billing address-level2",
3581
3976
  value: city,
3582
3977
  onChange: (e) => {
3583
3978
  cityRef.current = e.target.value;
@@ -3589,39 +3984,42 @@ function SplitCardFormInner({
3589
3984
  style: inputFieldStyle()
3590
3985
  }
3591
3986
  ) }),
3592
- (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3987
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3593
3988
  flex: 1,
3594
3989
  backgroundColor: cardInputBg,
3595
- border: `1px solid ${resolvedBorder}`,
3990
+ border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
3596
3991
  padding: "10px",
3597
- borderTopRightRadius: "8px",
3598
- borderBottomRightRadius: "8px",
3599
- ...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: "8px" },
3600
- ...isButtons && bStyles.stateInput ? bStyles.stateInput : {}
3601
- }, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3992
+ borderTopRightRadius: resolvedBorderRadius,
3993
+ borderBottomRightRadius: resolvedBorderRadius,
3994
+ ...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
3995
+ }, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3602
3996
  "select",
3603
3997
  {
3998
+ id: "flopay-billing-state",
3999
+ name: "billing-state",
3604
4000
  value: stateValue,
3605
4001
  onChange: (e) => {
3606
4002
  stateRef.current = e.target.value;
3607
4003
  setStateValue(e.target.value);
3608
4004
  },
3609
4005
  disabled: isSubmitting,
3610
- autoComplete: "address-level1",
4006
+ autoComplete: "billing address-level1",
3611
4007
  required: true,
3612
4008
  "data-testid": "flopay-state",
3613
4009
  style: { ...inputFieldStyle(), cursor: "pointer" },
3614
4010
  children: [
3615
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
3616
- stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: s.code, children: s.name }, s.code))
4011
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
4012
+ stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: s.code, children: s.name }, s.code))
3617
4013
  ]
3618
4014
  }
3619
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4015
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3620
4016
  "input",
3621
4017
  {
3622
4018
  className: "flopay-shared-input",
4019
+ id: "flopay-billing-state",
4020
+ name: "billing-state",
3623
4021
  placeholder: (0, import_shared5.getStateLabel)(cc),
3624
- autoComplete: "address-level1",
4022
+ autoComplete: "billing address-level1",
3625
4023
  value: stateValue,
3626
4024
  onChange: (e) => {
3627
4025
  stateRef.current = e.target.value;
@@ -3634,13 +4032,13 @@ function SplitCardFormInner({
3634
4032
  }
3635
4033
  ) })
3636
4034
  ] }),
3637
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4035
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3638
4036
  display: "flex",
3639
4037
  flexDirection: avsLayoutProp === "column" ? "column" : "row",
3640
4038
  gap: avsLayoutProp === "column" ? "0.5rem" : "0",
3641
4039
  marginTop: "0.5rem"
3642
4040
  }, children: [
3643
- (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4041
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3644
4042
  flex: avsLayoutProp === "row" ? 1 : void 0,
3645
4043
  backgroundColor: cardInputBg,
3646
4044
  borderTop: `1px solid ${resolvedBorder}`,
@@ -3648,11 +4046,12 @@ function SplitCardFormInner({
3648
4046
  borderBottom: `1px solid ${resolvedBorder}`,
3649
4047
  borderLeft: `1px solid ${resolvedBorder}`,
3650
4048
  padding: "10px",
3651
- ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: "8px", borderBottomLeftRadius: "8px", borderRight: "none" } : { borderRadius: "8px" },
3652
- ...isButtons && bStyles.countrySelect ? bStyles.countrySelect : {}
3653
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4049
+ ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
4050
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3654
4051
  "select",
3655
4052
  {
4053
+ id: "flopay-billing-country",
4054
+ name: "billing-country",
3656
4055
  value: selectedCountry,
3657
4056
  onChange: (e) => {
3658
4057
  selectedCountryRef.current = e.target.value;
@@ -3662,29 +4061,30 @@ function SplitCardFormInner({
3662
4061
  setStateValue("");
3663
4062
  },
3664
4063
  disabled: isSubmitting,
3665
- autoComplete: "country",
4064
+ autoComplete: "billing country",
3666
4065
  "data-testid": "flopay-country",
3667
4066
  style: { ...inputFieldStyle(), cursor: "pointer" },
3668
- children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: c.code, children: [
4067
+ children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("option", { value: c.code, children: [
3669
4068
  c.flag,
3670
4069
  " ",
3671
4070
  c.name
3672
4071
  ] }, c.code))
3673
4072
  }
3674
4073
  ) }),
3675
- (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4074
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3676
4075
  flex: avsLayoutProp === "row" ? 1 : void 0,
3677
4076
  backgroundColor: cardInputBg,
3678
- border: `1px solid ${resolvedBorder}`,
4077
+ border: `1px solid ${avsBorderColor(invalidAvsFields.zip)}`,
3679
4078
  padding: "10px",
3680
- ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: "8px", borderBottomRightRadius: "8px" } : { borderRadius: "8px" },
3681
- ...isButtons && bStyles.zipInput ? bStyles.zipInput : {}
3682
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4079
+ ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
4080
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3683
4081
  "input",
3684
4082
  {
3685
4083
  className: "flopay-shared-input",
4084
+ id: "flopay-billing-postal-code",
4085
+ name: "billing-postal-code",
3686
4086
  placeholder: (0, import_shared5.getPostalCodeLabel)(selectedCountry),
3687
- autoComplete: "postal-code",
4087
+ autoComplete: "billing postal-code",
3688
4088
  value: zipCode,
3689
4089
  onChange: (e) => {
3690
4090
  zipCodeRef.current = e.target.value;
@@ -3699,8 +4099,10 @@ function SplitCardFormInner({
3699
4099
  ) })
3700
4100
  ] })
3701
4101
  ] });
3702
- })(),
3703
- displayError && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
4102
+ })() }),
4103
+ vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
4104
+ vaultActive && vaultCardFieldsNode,
4105
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
3704
4106
  margin: "0.75rem 0",
3705
4107
  padding: "0.625rem 0.875rem",
3706
4108
  background: "#FEF2F2",
@@ -3714,15 +4116,21 @@ function SplitCardFormInner({
3714
4116
  gap: "0.5rem",
3715
4117
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3716
4118
  }, children: [
3717
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
4119
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
3718
4120
  displayError
3719
4121
  ] }),
3720
- children ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4122
+ !vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3721
4123
  "button",
3722
4124
  {
3723
4125
  type: "submit",
3724
4126
  disabled: !formReady || isSubmitting,
3725
4127
  "data-testid": "flopay-submit",
4128
+ onMouseEnter: (e) => {
4129
+ if (formReady && !isSubmitting) e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4130
+ },
4131
+ onMouseLeave: (e) => {
4132
+ e.currentTarget.style.backgroundColor = bStyles.submitButton?.backgroundColor ?? resolvedPrimaryColor;
4133
+ },
3726
4134
  style: {
3727
4135
  width: "100%",
3728
4136
  padding: "0.875rem",
@@ -3735,11 +4143,12 @@ function SplitCardFormInner({
3735
4143
  fontWeight: 600,
3736
4144
  cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
3737
4145
  opacity: !formReady || isSubmitting ? 0.5 : 1,
4146
+ transition: "background-color 0.15s",
3738
4147
  ...bStyles.submitButton
3739
4148
  },
3740
4149
  children: isSubmitting ? "PROCESSING..." : submitLabel
3741
4150
  }
3742
- )
4151
+ ))
3743
4152
  ] });
3744
4153
  const gateDebugStyle = {
3745
4154
  margin: 0,
@@ -3755,9 +4164,9 @@ function SplitCardFormInner({
3755
4164
  const renderDirectPaypalGateDebug = (testId) => {
3756
4165
  if (!debug) return null;
3757
4166
  if (!showPayPal || !directPaypalConfigured) {
3758
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
4167
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
3759
4168
  }
3760
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4169
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3761
4170
  "FloPay/DirectPayPal-debug (parent gate)",
3762
4171
  ` showPayPal=${showPayPal}`,
3763
4172
  ` directPaypalConfigured=${directPaypalConfigured}`,
@@ -3770,9 +4179,9 @@ function SplitCardFormInner({
3770
4179
  const renderStripeGateDebug = (testId) => {
3771
4180
  if (!debug) return null;
3772
4181
  if (!showStripe || !stripeInstance) {
3773
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
4182
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
3774
4183
  }
3775
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4184
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3776
4185
  "FloPay/Stripe-debug (parent gate)",
3777
4186
  ` showStripe=${showStripe}`,
3778
4187
  ` currency=${currency}`,
@@ -3801,11 +4210,11 @@ function SplitCardFormInner({
3801
4210
  const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
3802
4211
  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;
3803
4212
  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;
3804
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
3805
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayKeyframes, {}),
3806
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
3807
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "grid" }, children: [
3808
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4213
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4214
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4215
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4216
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid" }, children: [
4217
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3809
4218
  "div",
3810
4219
  {
3811
4220
  "data-testid": "flopay-buttons-panel",
@@ -3822,8 +4231,8 @@ function SplitCardFormInner({
3822
4231
  children: [
3823
4232
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
3824
4233
  renderStripeGateDebug("flopay-stripe-gate-debug"),
3825
- shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3826
- paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4234
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4235
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3827
4236
  "div",
3828
4237
  {
3829
4238
  "data-testid": "flopay-paypal-direct-retry-notice",
@@ -3839,7 +4248,7 @@ function SplitCardFormInner({
3839
4248
  children: "Please confirm your PayPal payment to complete checkout."
3840
4249
  }
3841
4250
  ),
3842
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4251
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3843
4252
  DirectPayPalButton,
3844
4253
  {
3845
4254
  sessionId,
@@ -3865,7 +4274,7 @@ function SplitCardFormInner({
3865
4274
  paypalDirectRetry?.orderId ?? "fresh"
3866
4275
  )
3867
4276
  ] }),
3868
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4277
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3869
4278
  PayPalButtonInner,
3870
4279
  {
3871
4280
  sessionId,
@@ -3879,10 +4288,10 @@ function SplitCardFormInner({
3879
4288
  onDecline,
3880
4289
  runBeforeButtonClick,
3881
4290
  onLoadStateChange: setPaypalLoadState,
3882
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4291
+ placeholderBorderRadius: buttonBorderRadius
3883
4292
  }
3884
4293
  ) }),
3885
- shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4294
+ shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3886
4295
  WalletButtonInner,
3887
4296
  {
3888
4297
  sessionId,
@@ -3896,10 +4305,10 @@ function SplitCardFormInner({
3896
4305
  onDecline,
3897
4306
  runBeforeButtonClick,
3898
4307
  onLoadStateChange: setWalletLoadState,
3899
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4308
+ placeholderBorderRadius: buttonBorderRadius
3900
4309
  }
3901
- ) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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,
3902
- shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4310
+ ) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
4311
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3903
4312
  StripePaymentElementInner,
3904
4313
  {
3905
4314
  sessionId,
@@ -3927,11 +4336,11 @@ function SplitCardFormInner({
3927
4336
  backgroundColor: bStyles.cardButton?.backgroundColor,
3928
4337
  borderColor: bStyles.cardInputBorder,
3929
4338
  textColor: bStyles.cardButton?.color,
3930
- borderRadius: bStyles.cardButton?.borderRadius
4339
+ borderRadius: buttonBorderRadius
3931
4340
  }
3932
4341
  }
3933
4342
  ),
3934
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4343
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3935
4344
  "button",
3936
4345
  {
3937
4346
  type: "button",
@@ -3959,7 +4368,8 @@ function SplitCardFormInner({
3959
4368
  themeBundle,
3960
4369
  resolvedPrimaryColor,
3961
4370
  resolvedBorderRadius,
3962
- submitButtonStyle: bStyles.submitButton
4371
+ submitButtonStyle: bStyles.submitButton,
4372
+ explicitPrimaryColor: appearanceVars?.colorPrimary
3963
4373
  }),
3964
4374
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
3965
4375
  fontWeight: 600,
@@ -3968,20 +4378,28 @@ function SplitCardFormInner({
3968
4378
  alignItems: "center",
3969
4379
  justifyContent: "center",
3970
4380
  gap: "0.625rem",
3971
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
4381
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
3972
4382
  position: "relative",
3973
4383
  opacity: isSubmitting ? 0.6 : 1
3974
4384
  },
4385
+ onMouseEnter: (e) => {
4386
+ if (!isSubmitting && (themeBundle || appearanceVars?.colorPrimary)) {
4387
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4388
+ }
4389
+ },
4390
+ onMouseLeave: (e) => {
4391
+ if (themeBundle || appearanceVars?.colorPrimary) e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
4392
+ },
3975
4393
  onMouseDown: (e) => {
3976
4394
  e.currentTarget.style.transform = "scale(0.985)";
3977
4395
  },
3978
4396
  onMouseUp: (e) => {
3979
4397
  e.currentTarget.style.transform = "scale(1)";
3980
4398
  },
3981
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
4399
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
3982
4400
  }
3983
4401
  ),
3984
- displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
4402
+ displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
3985
4403
  margin: "0.25rem 0",
3986
4404
  padding: "0.625rem 0.875rem",
3987
4405
  background: "#FEF2F2",
@@ -3995,33 +4413,33 @@ function SplitCardFormInner({
3995
4413
  gap: "0.5rem",
3996
4414
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3997
4415
  }, children: [
3998
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
4416
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
3999
4417
  displayError
4000
4418
  ] })
4001
4419
  ]
4002
4420
  }
4003
4421
  ),
4004
- showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4422
+ showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4005
4423
  gridArea: "1 / 1",
4006
4424
  ...cardAnim ? { animation: cardAnim } : {},
4007
4425
  ...viewState === "collapsing" ? { pointerEvents: "none" } : {}
4008
4426
  }, children: cardFormBlock }),
4009
- showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4427
+ showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4010
4428
  gridArea: "1 / 1",
4011
4429
  ...apmAnim ? { animation: apmAnim } : {},
4012
4430
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
4013
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4431
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4014
4432
  backgroundColor: cardBg,
4015
4433
  borderRadius: containerRadius,
4016
4434
  ...containerOverrides,
4017
4435
  padding: containerPadding
4018
4436
  }, children: [
4019
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4437
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4020
4438
  display: "flex",
4021
4439
  alignItems: "center",
4022
4440
  padding: "0.75rem 0 0.625rem"
4023
4441
  }, children: [
4024
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4442
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4025
4443
  "button",
4026
4444
  {
4027
4445
  type: "button",
@@ -4044,7 +4462,7 @@ function SplitCardFormInner({
4044
4462
  },
4045
4463
  "aria-label": "Back to payment methods",
4046
4464
  children: [
4047
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
4465
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
4048
4466
  display: "inline-flex",
4049
4467
  alignItems: "center",
4050
4468
  justifyContent: "center",
@@ -4054,12 +4472,12 @@ function SplitCardFormInner({
4054
4472
  backgroundColor: "#f3f4f6",
4055
4473
  transition: "background-color 0.15s",
4056
4474
  ...bStyles.backButtonIcon
4057
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
4058
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4475
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
4476
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4059
4477
  ]
4060
4478
  }
4061
4479
  ),
4062
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4480
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4063
4481
  flex: 1,
4064
4482
  textAlign: "center",
4065
4483
  fontWeight: 600,
@@ -4069,12 +4487,12 @@ function SplitCardFormInner({
4069
4487
  ...bStyles.title
4070
4488
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
4071
4489
  ] }),
4072
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4490
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4073
4491
  import_react_stripe_js.Elements,
4074
4492
  {
4075
4493
  stripe: stripeInstance,
4076
4494
  options: apmInlineOptions,
4077
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4495
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4078
4496
  StripeMethodInlineForm,
4079
4497
  {
4080
4498
  method: expandedApmMethod,
@@ -4092,7 +4510,8 @@ function SplitCardFormInner({
4092
4510
  isProcessing: isSubmitting,
4093
4511
  submitButtonColor: resolvedPrimaryColor,
4094
4512
  submitButtonBorderRadius: resolvedBorderRadius,
4095
- submitButtonStyle: bStyles.submitButton
4513
+ submitButtonStyle: bStyles.submitButton,
4514
+ errorText: displayError
4096
4515
  }
4097
4516
  )
4098
4517
  },
@@ -4103,24 +4522,24 @@ function SplitCardFormInner({
4103
4522
  ] });
4104
4523
  }
4105
4524
  if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
4106
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4107
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayKeyframes, {}),
4108
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4109
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4525
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4526
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4527
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4528
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4110
4529
  ...apmAnim ? { animation: apmAnim } : {},
4111
4530
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
4112
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4531
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4113
4532
  backgroundColor: cardBg,
4114
4533
  borderRadius: containerRadius,
4115
4534
  ...containerOverrides,
4116
4535
  padding: containerPadding
4117
4536
  }, children: [
4118
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4537
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4119
4538
  display: "flex",
4120
4539
  alignItems: "center",
4121
4540
  padding: "0.75rem 0 0.625rem"
4122
4541
  }, children: [
4123
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4542
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4124
4543
  "button",
4125
4544
  {
4126
4545
  type: "button",
@@ -4143,7 +4562,7 @@ function SplitCardFormInner({
4143
4562
  },
4144
4563
  "aria-label": "Back to payment methods",
4145
4564
  children: [
4146
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
4565
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
4147
4566
  display: "inline-flex",
4148
4567
  alignItems: "center",
4149
4568
  justifyContent: "center",
@@ -4153,12 +4572,12 @@ function SplitCardFormInner({
4153
4572
  backgroundColor: "#f3f4f6",
4154
4573
  transition: "background-color 0.15s",
4155
4574
  ...bStyles.backButtonIcon
4156
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
4157
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4575
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
4576
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4158
4577
  ]
4159
4578
  }
4160
4579
  ),
4161
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4580
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4162
4581
  flex: 1,
4163
4582
  textAlign: "center",
4164
4583
  fontWeight: 600,
@@ -4168,12 +4587,12 @@ function SplitCardFormInner({
4168
4587
  ...bStyles.title
4169
4588
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
4170
4589
  ] }),
4171
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4590
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4172
4591
  import_react_stripe_js.Elements,
4173
4592
  {
4174
4593
  stripe: stripeInstance,
4175
4594
  options: apmInlineOptions,
4176
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4595
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4177
4596
  StripeMethodInlineForm,
4178
4597
  {
4179
4598
  method: expandedApmMethod,
@@ -4191,7 +4610,8 @@ function SplitCardFormInner({
4191
4610
  isProcessing: isSubmitting,
4192
4611
  submitButtonColor: resolvedPrimaryColor,
4193
4612
  submitButtonBorderRadius: resolvedBorderRadius,
4194
- submitButtonStyle: bStyles.submitButton
4613
+ submitButtonStyle: bStyles.submitButton,
4614
+ errorText: displayError
4195
4615
  }
4196
4616
  )
4197
4617
  },
@@ -4200,14 +4620,14 @@ function SplitCardFormInner({
4200
4620
  ] }) })
4201
4621
  ] });
4202
4622
  }
4203
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4204
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloPayKeyframes, {}),
4205
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4206
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4623
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4624
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4625
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4626
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4207
4627
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
4208
4628
  renderStripeGateDebug("flopay-stripe-gate-debug-default"),
4209
- shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
4210
- paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4629
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4630
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4211
4631
  "div",
4212
4632
  {
4213
4633
  "data-testid": "flopay-paypal-direct-retry-notice-default",
@@ -4223,7 +4643,7 @@ function SplitCardFormInner({
4223
4643
  children: "Please confirm your PayPal payment to complete checkout."
4224
4644
  }
4225
4645
  ),
4226
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4646
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4227
4647
  DirectPayPalButton,
4228
4648
  {
4229
4649
  sessionId,
@@ -4249,7 +4669,7 @@ function SplitCardFormInner({
4249
4669
  paypalDirectRetry?.orderId ?? "fresh"
4250
4670
  )
4251
4671
  ] }),
4252
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4672
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4253
4673
  PayPalButtonInner,
4254
4674
  {
4255
4675
  sessionId,
@@ -4263,10 +4683,10 @@ function SplitCardFormInner({
4263
4683
  onDecline,
4264
4684
  runBeforeButtonClick,
4265
4685
  onLoadStateChange: setPaypalLoadState,
4266
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4686
+ placeholderBorderRadius: buttonBorderRadius
4267
4687
  }
4268
4688
  ) }),
4269
- shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4689
+ shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4270
4690
  WalletButtonInner,
4271
4691
  {
4272
4692
  sessionId,
@@ -4280,10 +4700,10 @@ function SplitCardFormInner({
4280
4700
  onDecline,
4281
4701
  runBeforeButtonClick,
4282
4702
  onLoadStateChange: setWalletLoadState,
4283
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4703
+ placeholderBorderRadius: buttonBorderRadius
4284
4704
  }
4285
4705
  ) }),
4286
- shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4706
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4287
4707
  StripePaymentElementInner,
4288
4708
  {
4289
4709
  sessionId,
@@ -4311,12 +4731,12 @@ function SplitCardFormInner({
4311
4731
  backgroundColor: bStyles.cardButton?.backgroundColor,
4312
4732
  borderColor: bStyles.cardInputBorder,
4313
4733
  textColor: bStyles.cardButton?.color,
4314
- borderRadius: bStyles.cardButton?.borderRadius
4734
+ borderRadius: buttonBorderRadius
4315
4735
  }
4316
4736
  }
4317
4737
  )
4318
4738
  ] }),
4319
- showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4739
+ showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4320
4740
  display: "flex",
4321
4741
  alignItems: "center",
4322
4742
  gap: "0.75rem",
@@ -4324,9 +4744,9 @@ function SplitCardFormInner({
4324
4744
  color: "#999",
4325
4745
  fontSize: "0.85rem"
4326
4746
  }, children: [
4327
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
4328
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "or pay with card" }),
4329
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
4747
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
4748
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "or pay with card" }),
4749
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
4330
4750
  ] }),
4331
4751
  showStripe && cardFormBlock
4332
4752
  ] });
@@ -4369,6 +4789,210 @@ function getRedirectResultFromCheckoutProcessError(error) {
4369
4789
  paymentMethodId: error.paymentMethodId
4370
4790
  };
4371
4791
  }
4792
+ function isTerminalAutoCheckoutThreeDsOutcome(outcome) {
4793
+ return outcome.status === "succeeded" || outcome.status === "declined";
4794
+ }
4795
+ async function runAutoCheckoutThreeDsChallenge(input) {
4796
+ if (typeof document === "undefined" || typeof window === "undefined") {
4797
+ throw new import_shared7.FloPayError("3DS challenge requires a browser environment.", "api_error", {
4798
+ code: "three_ds_no_window"
4799
+ });
4800
+ }
4801
+ if (input.signal?.aborted) {
4802
+ throw new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
4803
+ code: "three_ds_aborted"
4804
+ });
4805
+ }
4806
+ const CHALLENGE_TIMEOUT_MS = 3e5;
4807
+ const CHALLENGE_POLL_INTERVAL_MS = 1e3;
4808
+ const COMPLETE_REQUEST_TIMEOUT_MS = 15e3;
4809
+ const completionEndpoint = `${input.billingApiUrl.replace(/\/$/, "")}/v1/checkouts/sessions/${encodeURIComponent(
4810
+ input.sessionId
4811
+ )}/3ds/complete`;
4812
+ const completeThreeDs = async () => {
4813
+ const controller = new AbortController();
4814
+ const onParentAbort = () => controller.abort();
4815
+ if (input.signal?.aborted) {
4816
+ controller.abort();
4817
+ } else {
4818
+ input.signal?.addEventListener("abort", onParentAbort);
4819
+ }
4820
+ const requestTimeout = window.setTimeout(() => controller.abort(), COMPLETE_REQUEST_TIMEOUT_MS);
4821
+ try {
4822
+ const response = await fetch(completionEndpoint, {
4823
+ method: "POST",
4824
+ headers: {
4825
+ "x-checkout-session-token": input.nonce,
4826
+ "content-type": "application/json"
4827
+ },
4828
+ body: "{}",
4829
+ signal: controller.signal
4830
+ });
4831
+ if (!response.ok) {
4832
+ return { status: "unknown" };
4833
+ }
4834
+ const json = await response.json().catch(() => null);
4835
+ return coerceThreeDsOutcome(json);
4836
+ } catch {
4837
+ return { status: "unknown" };
4838
+ } finally {
4839
+ window.clearTimeout(requestTimeout);
4840
+ input.signal?.removeEventListener("abort", onParentAbort);
4841
+ }
4842
+ };
4843
+ const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4844
+ const backdrop = document.createElement("div");
4845
+ backdrop.setAttribute("data-flopay-auto-3ds-overlay", "1");
4846
+ backdrop.setAttribute("role", "dialog");
4847
+ backdrop.setAttribute("aria-modal", "true");
4848
+ backdrop.setAttribute("aria-label", "Card authentication");
4849
+ backdrop.style.cssText = [
4850
+ "position:fixed",
4851
+ "inset:0",
4852
+ "z-index:2147483647",
4853
+ "background:rgba(15,23,42,0.6)",
4854
+ "display:flex",
4855
+ "align-items:center",
4856
+ "justify-content:center",
4857
+ "padding:16px"
4858
+ ].join(";");
4859
+ const frame = document.createElement("iframe");
4860
+ frame.setAttribute("title", "Card authentication");
4861
+ frame.setAttribute("allow", "payment");
4862
+ frame.tabIndex = 0;
4863
+ frame.style.cssText = [
4864
+ "width:min(100%,460px)",
4865
+ "height:min(100%,640px)",
4866
+ "border:0",
4867
+ "border-radius:12px",
4868
+ "background:#fff",
4869
+ "box-shadow:0 12px 30px rgba(0,0,0,0.35)"
4870
+ ].join(";");
4871
+ frame.src = input.nextActionRedirectUrl;
4872
+ backdrop.appendChild(frame);
4873
+ document.body.appendChild(backdrop);
4874
+ frame.focus();
4875
+ let expectedReturnOrigin = null;
4876
+ try {
4877
+ expectedReturnOrigin = new URL(input.billingApiUrl, window.location.href).origin;
4878
+ } catch {
4879
+ expectedReturnOrigin = null;
4880
+ }
4881
+ try {
4882
+ const polledOutcome = await new Promise((resolve, reject) => {
4883
+ let settled = false;
4884
+ let timer = 0;
4885
+ let pollTimer = 0;
4886
+ let loadPollTimer = 0;
4887
+ let pollInFlight = false;
4888
+ const cleanup = () => {
4889
+ window.clearTimeout(timer);
4890
+ window.clearInterval(pollTimer);
4891
+ window.clearTimeout(loadPollTimer);
4892
+ window.removeEventListener("message", listener);
4893
+ frame.removeEventListener("load", onFrameLoad);
4894
+ input.signal?.removeEventListener("abort", onAbort);
4895
+ };
4896
+ const maybeResolveFromBackend = async () => {
4897
+ if (settled || pollInFlight) return;
4898
+ pollInFlight = true;
4899
+ try {
4900
+ const outcome = await completeThreeDs();
4901
+ if (settled || !isTerminalAutoCheckoutThreeDsOutcome(outcome)) return;
4902
+ settled = true;
4903
+ cleanup();
4904
+ resolve(outcome);
4905
+ } finally {
4906
+ pollInFlight = false;
4907
+ }
4908
+ };
4909
+ const onFrameLoad = () => {
4910
+ window.clearTimeout(loadPollTimer);
4911
+ loadPollTimer = window.setTimeout(() => {
4912
+ void maybeResolveFromBackend();
4913
+ }, 250);
4914
+ };
4915
+ const onAbort = () => {
4916
+ if (settled) return;
4917
+ settled = true;
4918
+ cleanup();
4919
+ reject(
4920
+ new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
4921
+ code: "three_ds_aborted"
4922
+ })
4923
+ );
4924
+ };
4925
+ const listener = (event) => {
4926
+ if (event.source !== frame.contentWindow) return;
4927
+ if (expectedReturnOrigin && event.origin !== expectedReturnOrigin) return;
4928
+ const data = event.data;
4929
+ if (!data || typeof data !== "object") return;
4930
+ const record = data;
4931
+ if (record["source"] !== "flopay-vault-3ds-return") return;
4932
+ if (settled) return;
4933
+ settled = true;
4934
+ cleanup();
4935
+ resolve(null);
4936
+ };
4937
+ timer = window.setTimeout(() => {
4938
+ if (settled) return;
4939
+ settled = true;
4940
+ cleanup();
4941
+ reject(
4942
+ new import_shared7.FloPayError("Card authentication timed out.", "api_error", {
4943
+ code: "three_ds_timeout"
4944
+ })
4945
+ );
4946
+ }, CHALLENGE_TIMEOUT_MS);
4947
+ pollTimer = window.setInterval(() => {
4948
+ void maybeResolveFromBackend();
4949
+ }, CHALLENGE_POLL_INTERVAL_MS);
4950
+ frame.addEventListener("load", onFrameLoad);
4951
+ window.addEventListener("message", listener);
4952
+ input.signal?.addEventListener("abort", onAbort);
4953
+ if (input.signal?.aborted) onAbort();
4954
+ });
4955
+ if (polledOutcome) {
4956
+ return polledOutcome;
4957
+ }
4958
+ return await completeThreeDs();
4959
+ } finally {
4960
+ backdrop.parentNode?.removeChild(backdrop);
4961
+ if (previousFocus?.isConnected) {
4962
+ previousFocus.focus();
4963
+ }
4964
+ }
4965
+ }
4966
+ function coerceThreeDsOutcome(json) {
4967
+ if (!json || typeof json !== "object") return { status: "unknown" };
4968
+ const status = typeof json["status"] === "string" ? json["status"] : "unknown";
4969
+ const providerIntentId = typeof json["providerIntentId"] === "string" ? json["providerIntentId"] : null;
4970
+ switch (status) {
4971
+ case "succeeded":
4972
+ return { status: "succeeded", providerIntentId };
4973
+ case "declined":
4974
+ return {
4975
+ status: "declined",
4976
+ providerIntentId,
4977
+ declineReason: typeof json["declineReason"] === "string" ? json["declineReason"] : null,
4978
+ gatewayDeclineReason: typeof json["gatewayDeclineReason"] === "string" ? json["gatewayDeclineReason"] : null
4979
+ };
4980
+ case "requires_action":
4981
+ return {
4982
+ status: "requires_action",
4983
+ providerIntentId,
4984
+ nextActionRedirectUrl: typeof json["nextActionRedirectUrl"] === "string" ? json["nextActionRedirectUrl"] : null
4985
+ };
4986
+ case "pending":
4987
+ return { status: "pending", providerIntentId };
4988
+ case "timeout":
4989
+ return { status: "timeout", providerIntentId };
4990
+ case "no_attempt":
4991
+ return { status: "no_attempt" };
4992
+ default:
4993
+ return { status: "unknown" };
4994
+ }
4995
+ }
4372
4996
  function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
4373
4997
  const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
4374
4998
  const rawMessage = error?.message ?? fallbackMessage;
@@ -4810,7 +5434,7 @@ async function loadSavedPaymentProviders({
4810
5434
  }
4811
5435
 
4812
5436
  // src/flopay-checkout.tsx
4813
- var import_jsx_runtime7 = require("react/jsx-runtime");
5437
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4814
5438
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
4815
5439
  var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
4816
5440
  var sessionInflightMap = /* @__PURE__ */ new Map();
@@ -4859,6 +5483,36 @@ function clearPayPalResumeState() {
4859
5483
  console.warn("[FloPayCheckout] Failed to clear PayPal resume state.", error);
4860
5484
  }
4861
5485
  }
5486
+ function readCachedInlineSession(cacheKey) {
5487
+ if (!canUseStorage()) return null;
5488
+ const raw = window.sessionStorage.getItem(cacheKey);
5489
+ if (!raw) return null;
5490
+ try {
5491
+ const parsed = JSON.parse(raw);
5492
+ if (parsed && typeof parsed.sid === "string" && parsed.sid) {
5493
+ return { sid: parsed.sid, nonce: typeof parsed.nonce === "string" ? parsed.nonce : void 0 };
5494
+ }
5495
+ return null;
5496
+ } catch {
5497
+ return { sid: raw };
5498
+ }
5499
+ }
5500
+ function persistCachedInlineSession(cacheKey, sid, nonce) {
5501
+ if (!canUseStorage()) return;
5502
+ try {
5503
+ window.sessionStorage.setItem(cacheKey, JSON.stringify(nonce ? { sid, nonce } : { sid }));
5504
+ } catch (error) {
5505
+ console.warn("[FloPayCheckout] Failed to persist checkout session cache.", error);
5506
+ }
5507
+ }
5508
+ function clearCachedInlineSession(cacheKey) {
5509
+ if (!canUseStorage()) return;
5510
+ try {
5511
+ window.sessionStorage.removeItem(cacheKey);
5512
+ } catch (error) {
5513
+ console.warn("[FloPayCheckout] Failed to clear checkout session cache.", error);
5514
+ }
5515
+ }
4862
5516
  function clearPayPalRedirectParams() {
4863
5517
  if (typeof window === "undefined") return;
4864
5518
  const url = new URL(window.location.href);
@@ -4917,6 +5571,8 @@ function FloPayCheckout({
4917
5571
  onButtonClick,
4918
5572
  onBeforeButtonClick,
4919
5573
  enableAVS,
5574
+ cardFieldOrder,
5575
+ cardPreFormSlot,
4920
5576
  avsLayout,
4921
5577
  submitLabel,
4922
5578
  className,
@@ -4928,41 +5584,41 @@ function FloPayCheckout({
4928
5584
  onSessionCompleted
4929
5585
  }) {
4930
5586
  const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
4931
- const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
5587
+ const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
4932
5588
  const appearance = appearanceOverride ?? themeBundle?.appearance;
4933
5589
  const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
4934
5590
  const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
4935
- const [unified, setUnified] = (0, import_react9.useState)(null);
4936
- const [flopay, setFloPay] = (0, import_react9.useState)(null);
4937
- const flopayRef = (0, import_react9.useRef)(null);
4938
- const [paypalFlopay, setPaypalFloPay] = (0, import_react9.useState)(null);
4939
- const paypalFlopayRef = (0, import_react9.useRef)(null);
4940
- const [session, setSession] = (0, import_react9.useState)(null);
4941
- const [resolvedSessionId, setResolvedSessionId] = (0, import_react9.useState)(sessionIdProp ?? "");
5591
+ const [unified, setUnified] = (0, import_react10.useState)(null);
5592
+ const [flopay, setFloPay] = (0, import_react10.useState)(null);
5593
+ const flopayRef = (0, import_react10.useRef)(null);
5594
+ const [paypalFlopay, setPaypalFloPay] = (0, import_react10.useState)(null);
5595
+ const paypalFlopayRef = (0, import_react10.useRef)(null);
5596
+ const [session, setSession] = (0, import_react10.useState)(null);
5597
+ const [resolvedSessionId, setResolvedSessionId] = (0, import_react10.useState)(sessionIdProp ?? "");
4942
5598
  const activeSessionId = sessionIdProp ?? resolvedSessionId;
4943
5599
  const initSessionDependency = createSessionParams ? "" : activeSessionId;
4944
- const [isLoading, setIsLoading] = (0, import_react9.useState)(true);
4945
- const [loadError, setLoadError] = (0, import_react9.useState)(null);
4946
- const [currentMode, setCurrentMode] = (0, import_react9.useState)("full");
4947
- const [confirmProcessing, setConfirmProcessing] = (0, import_react9.useState)(false);
4948
- const [modeError, setModeError] = (0, import_react9.useState)(initialErrorMessage);
4949
- const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react9.useState)(null);
4950
- const [modeOverlayError, setModeOverlayError] = (0, import_react9.useState)(null);
4951
- const [createSessionPatch, setCreateSessionPatch] = (0, import_react9.useState)(void 0);
4952
- const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react9.useState)("");
4953
- const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react9.useState)(false);
4954
- const autoCheckoutAttempted = (0, import_react9.useRef)(false);
4955
- const paypalResumeAttempted = (0, import_react9.useRef)(false);
4956
- const savedPaymentKeysRef = (0, import_react9.useRef)(null);
4957
- const onCompleteRef = (0, import_react9.useRef)(onComplete);
5600
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
5601
+ const [loadError, setLoadError] = (0, import_react10.useState)(null);
5602
+ const [currentMode, setCurrentMode] = (0, import_react10.useState)("full");
5603
+ const [confirmProcessing, setConfirmProcessing] = (0, import_react10.useState)(false);
5604
+ const [modeError, setModeError] = (0, import_react10.useState)(initialErrorMessage);
5605
+ const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react10.useState)(null);
5606
+ const [modeOverlayError, setModeOverlayError] = (0, import_react10.useState)(null);
5607
+ const [createSessionPatch, setCreateSessionPatch] = (0, import_react10.useState)(void 0);
5608
+ const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react10.useState)("");
5609
+ const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react10.useState)(false);
5610
+ const autoCheckoutAttempted = (0, import_react10.useRef)(false);
5611
+ const paypalResumeAttempted = (0, import_react10.useRef)(false);
5612
+ const savedPaymentKeysRef = (0, import_react10.useRef)(null);
5613
+ const onCompleteRef = (0, import_react10.useRef)(onComplete);
4958
5614
  onCompleteRef.current = onComplete;
4959
- const onErrorRef = (0, import_react9.useRef)(onError);
5615
+ const onErrorRef = (0, import_react10.useRef)(onError);
4960
5616
  onErrorRef.current = onError;
4961
- const onDeclineRef = (0, import_react9.useRef)(onDecline);
5617
+ const onDeclineRef = (0, import_react10.useRef)(onDecline);
4962
5618
  onDeclineRef.current = onDecline;
4963
- const onSessionCompletedRef = (0, import_react9.useRef)(onSessionCompleted);
5619
+ const onSessionCompletedRef = (0, import_react10.useRef)(onSessionCompleted);
4964
5620
  onSessionCompletedRef.current = onSessionCompleted;
4965
- (0, import_react9.useEffect)(() => {
5621
+ (0, import_react10.useEffect)(() => {
4966
5622
  console.info("[FloPay] Checkout initialized", {
4967
5623
  sdk_version: import_shared8.SDK_VERSION,
4968
5624
  checkout_type: checkoutType,
@@ -4970,40 +5626,40 @@ function FloPayCheckout({
4970
5626
  billing_api_url: resolvedBillingUrl
4971
5627
  });
4972
5628
  }, [checkoutLayout, checkoutType, resolvedBillingUrl]);
4973
- const baseCreateSessionHash = (0, import_react9.useMemo)(
5629
+ const baseCreateSessionHash = (0, import_react10.useMemo)(
4974
5630
  () => createSessionParams ? hashCreateParams(createSessionParams) : "",
4975
5631
  [createSessionParams]
4976
5632
  );
4977
- const activeCreateSessionPatch = (0, import_react9.useMemo)(
5633
+ const activeCreateSessionPatch = (0, import_react10.useMemo)(
4978
5634
  () => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
4979
5635
  [createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
4980
5636
  );
4981
- const effectiveCreateSessionBase = (0, import_react9.useMemo)(
5637
+ const effectiveCreateSessionBase = (0, import_react10.useMemo)(
4982
5638
  () => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
4983
5639
  [createSessionParams, activeCreateSessionPatch]
4984
5640
  );
4985
5641
  const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
4986
- const effectiveCreateSession = (0, import_react9.useMemo)(
5642
+ const effectiveCreateSession = (0, import_react10.useMemo)(
4987
5643
  () => effectiveCreateSessionBase ? {
4988
5644
  ...effectiveCreateSessionBase,
4989
5645
  checkoutMode: effectiveCreateSessionMode
4990
5646
  } : void 0,
4991
5647
  [effectiveCreateSessionBase, effectiveCreateSessionMode]
4992
5648
  );
4993
- (0, import_react9.useEffect)(() => {
5649
+ (0, import_react10.useEffect)(() => {
4994
5650
  setCreateSessionPatch(void 0);
4995
5651
  setCreateSessionPatchBaseHash(baseCreateSessionHash);
4996
5652
  }, [baseCreateSessionHash]);
4997
- (0, import_react9.useEffect)(() => {
5653
+ (0, import_react10.useEffect)(() => {
4998
5654
  setModeError(initialErrorMessage);
4999
5655
  }, [initialErrorMessage]);
5000
- const emitDecline = (0, import_react9.useCallback)(
5656
+ const emitDecline = (0, import_react10.useCallback)(
5001
5657
  (method, input, overrides) => {
5002
5658
  onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
5003
5659
  },
5004
5660
  []
5005
5661
  );
5006
- const runSavedPaymentFlow = (0, import_react9.useCallback)(
5662
+ const runSavedPaymentFlow = (0, import_react10.useCallback)(
5007
5663
  async (sess, options) => {
5008
5664
  setModeError(null);
5009
5665
  setModeOverlayError(null);
@@ -5121,7 +5777,7 @@ function FloPayCheckout({
5121
5777
  resolvedBillingUrl
5122
5778
  ]
5123
5779
  );
5124
- (0, import_react9.useEffect)(() => {
5780
+ (0, import_react10.useEffect)(() => {
5125
5781
  if (typeof window === "undefined" || paypalResumeAttempted.current) {
5126
5782
  return;
5127
5783
  }
@@ -5238,7 +5894,7 @@ function FloPayCheckout({
5238
5894
  }
5239
5895
  })();
5240
5896
  }, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
5241
- const initializedHashRef = (0, import_react9.useRef)(null);
5897
+ const initializedHashRef = (0, import_react10.useRef)(null);
5242
5898
  function hashCreateParams(params) {
5243
5899
  const key = JSON.stringify({
5244
5900
  c: params?.clientId,
@@ -5271,16 +5927,16 @@ function FloPayCheckout({
5271
5927
  }
5272
5928
  return `flopay_session_${Math.abs(h).toString(36)}`;
5273
5929
  }
5274
- const createSessionHash = (0, import_react9.useMemo)(
5930
+ const createSessionHash = (0, import_react10.useMemo)(
5275
5931
  () => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
5276
5932
  [effectiveCreateSession]
5277
5933
  );
5278
- const createSessionParamsRef = (0, import_react9.useRef)(effectiveCreateSession);
5934
+ const createSessionParamsRef = (0, import_react10.useRef)(effectiveCreateSession);
5279
5935
  createSessionParamsRef.current = effectiveCreateSession;
5280
- (0, import_react9.useEffect)(() => {
5936
+ (0, import_react10.useEffect)(() => {
5281
5937
  setResolvedSessionId(sessionIdProp ?? "");
5282
5938
  }, [sessionIdProp]);
5283
- (0, import_react9.useEffect)(() => {
5939
+ (0, import_react10.useEffect)(() => {
5284
5940
  autoCheckoutAttempted.current = false;
5285
5941
  setModeError(initialErrorMessage);
5286
5942
  setModeOverlayError(null);
@@ -5288,22 +5944,23 @@ function FloPayCheckout({
5288
5944
  }, [createSessionHash, initialErrorMessage, sessionIdProp]);
5289
5945
  async function resolveInlineSession(params, cacheKey) {
5290
5946
  const api = new import_js4.PaymentAPI(resolvedBillingUrl);
5291
- let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
5947
+ const cached = readCachedInlineSession(cacheKey);
5948
+ let sid = cached?.sid ?? null;
5292
5949
  let realResult = null;
5293
5950
  if (sid) {
5294
5951
  try {
5295
- realResult = await api.getUnifiedCheckoutSession(sid);
5952
+ realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
5296
5953
  const status = realResult.data.session?.status;
5297
5954
  if (status === "complete") {
5298
5955
  if (wasSessionRecentlyCompleted(sid)) {
5299
5956
  return { sid, result: realResult };
5300
5957
  }
5301
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
5958
+ clearCachedInlineSession(cacheKey);
5302
5959
  sid = null;
5303
5960
  realResult = null;
5304
5961
  }
5305
5962
  } catch {
5306
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
5963
+ clearCachedInlineSession(cacheKey);
5307
5964
  sid = null;
5308
5965
  }
5309
5966
  }
@@ -5317,13 +5974,13 @@ function FloPayCheckout({
5317
5974
  };
5318
5975
  realResult = await api.createAndFetchSession(paramsWithAnalytics);
5319
5976
  sid = realResult.data.session?.id ?? "";
5320
- if (sid && typeof window !== "undefined") {
5321
- window.sessionStorage.setItem(cacheKey, sid);
5977
+ if (sid) {
5978
+ persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
5322
5979
  }
5323
5980
  }
5324
5981
  return { sid: sid ?? "", result: realResult };
5325
5982
  }
5326
- const bootstrapInlineSession = (0, import_react9.useCallback)(
5983
+ const bootstrapInlineSession = (0, import_react10.useCallback)(
5327
5984
  async (patch) => {
5328
5985
  const baseParams = createSessionParamsRef.current;
5329
5986
  if (!baseParams) {
@@ -5384,7 +6041,7 @@ function FloPayCheckout({
5384
6041
  },
5385
6042
  [locale, resolvedBillingUrl]
5386
6043
  );
5387
- const handleInlineSessionPatch = (0, import_react9.useCallback)(async (patch) => {
6044
+ const handleInlineSessionPatch = (0, import_react10.useCallback)(async (patch) => {
5388
6045
  if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
5389
6046
  return {
5390
6047
  sessionId: resolvedSessionId,
@@ -5407,7 +6064,7 @@ function FloPayCheckout({
5407
6064
  resolvedSessionId,
5408
6065
  session
5409
6066
  ]);
5410
- (0, import_react9.useEffect)(() => {
6067
+ (0, import_react10.useEffect)(() => {
5411
6068
  let cancelled = false;
5412
6069
  setLoadError(null);
5413
6070
  if (createSessionHash) {
@@ -5573,7 +6230,7 @@ function FloPayCheckout({
5573
6230
  nonceProp,
5574
6231
  runSavedPaymentFlow
5575
6232
  ]);
5576
- const handleConfirmCheckout = (0, import_react9.useCallback)(async () => {
6233
+ const handleConfirmCheckout = (0, import_react10.useCallback)(async () => {
5577
6234
  if (confirmProcessing || !session) return;
5578
6235
  setConfirmProcessing(true);
5579
6236
  setModeError(null);
@@ -5588,7 +6245,7 @@ function FloPayCheckout({
5588
6245
  }, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
5589
6246
  const directPaypalConfig = resolveDirectPaypalConfig(unified);
5590
6247
  const isPaypalOnlySession = isPayPalOnlyUnified(unified);
5591
- const providerOptions = (0, import_react9.useMemo)(() => {
6248
+ const providerOptions = (0, import_react10.useMemo)(() => {
5592
6249
  if (!unified || !session || !unified.data.stripe?.publishableKey) return void 0;
5593
6250
  const opts = {
5594
6251
  appearance,
@@ -5607,7 +6264,7 @@ function FloPayCheckout({
5607
6264
  const shouldHandleInlineSessionPatch = Boolean(
5608
6265
  createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
5609
6266
  );
5610
- const checkoutValue = (0, import_react9.useMemo)(
6267
+ const checkoutValue = (0, import_react10.useMemo)(
5611
6268
  () => ({
5612
6269
  session,
5613
6270
  loading: isLoading,
@@ -5629,7 +6286,7 @@ function FloPayCheckout({
5629
6286
  ]
5630
6287
  );
5631
6288
  const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
5632
- const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6289
+ const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5633
6290
  ProcessingOverlay,
5634
6291
  {
5635
6292
  status: modeOverlayStatus,
@@ -5638,32 +6295,32 @@ function FloPayCheckout({
5638
6295
  ) : null;
5639
6296
  if (isLoading) {
5640
6297
  if (loadingNode) {
5641
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6298
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
5642
6299
  loadingNode,
5643
6300
  modeOverlay
5644
6301
  ] });
5645
6302
  }
5646
6303
  if (layout === "buttons") {
5647
6304
  const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5648
- const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6305
+ const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5649
6306
  height: h,
5650
6307
  borderRadius: bundleRadius,
5651
6308
  background: "#e5e7eb",
5652
6309
  animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
5653
6310
  } });
5654
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5655
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6311
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6312
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5656
6313
  showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5657
6314
  showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5658
6315
  showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5659
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6316
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
5660
6317
  ] }),
5661
6318
  modeOverlay
5662
6319
  ] });
5663
6320
  }
5664
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5665
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
5666
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6321
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6322
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
6323
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5667
6324
  width: 24,
5668
6325
  height: 24,
5669
6326
  border: "2px solid #e5e7eb",
@@ -5671,16 +6328,16 @@ function FloPayCheckout({
5671
6328
  borderRadius: "50%",
5672
6329
  animation: "spin 0.6s linear infinite"
5673
6330
  } }),
5674
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
6331
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
5675
6332
  ] }),
5676
6333
  modeOverlay
5677
6334
  ] });
5678
6335
  }
5679
6336
  if (loadError) {
5680
6337
  if (errorNode) {
5681
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
6338
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
5682
6339
  }
5683
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6340
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5684
6341
  "div",
5685
6342
  {
5686
6343
  role: "alert",
@@ -5696,8 +6353,8 @@ function FloPayCheckout({
5696
6353
  ) });
5697
6354
  }
5698
6355
  if (shouldShowInterimButtons) {
5699
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5700
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6356
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6357
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5701
6358
  InterimButtonsView,
5702
6359
  {
5703
6360
  onButtonClick,
@@ -5717,9 +6374,9 @@ function FloPayCheckout({
5717
6374
  ] });
5718
6375
  }
5719
6376
  if (isPaypalOnlySession && session && directPaypalConfig) {
5720
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5721
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5722
- modeError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6377
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6378
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6379
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5723
6380
  "div",
5724
6381
  {
5725
6382
  role: "alert",
@@ -5736,7 +6393,7 @@ function FloPayCheckout({
5736
6393
  children: modeError
5737
6394
  }
5738
6395
  ),
5739
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6396
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5740
6397
  DirectPayPalButton,
5741
6398
  {
5742
6399
  sessionId: activeSessionId,
@@ -5760,12 +6417,12 @@ function FloPayCheckout({
5760
6417
  ] });
5761
6418
  }
5762
6419
  if (!flopay || !providerOptions) {
5763
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: modeOverlay });
6420
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: modeOverlay });
5764
6421
  }
5765
6422
  if (currentMode === "confirm") {
5766
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5767
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className, children: [
5768
- modeError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6423
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6424
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className, children: [
6425
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5769
6426
  "div",
5770
6427
  {
5771
6428
  style: {
@@ -5780,7 +6437,7 @@ function FloPayCheckout({
5780
6437
  renderConfirmButton ? renderConfirmButton({
5781
6438
  onConfirm: handleConfirmCheckout,
5782
6439
  isProcessing: confirmProcessing
5783
- }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6440
+ }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5784
6441
  "button",
5785
6442
  {
5786
6443
  type: "button",
@@ -5805,9 +6462,9 @@ function FloPayCheckout({
5805
6462
  modeOverlay
5806
6463
  ] });
5807
6464
  }
5808
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5809
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5810
- modeError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6465
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6466
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6467
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5811
6468
  "div",
5812
6469
  {
5813
6470
  style: {
@@ -5822,7 +6479,7 @@ function FloPayCheckout({
5822
6479
  children: modeError
5823
6480
  }
5824
6481
  ),
5825
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6482
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5826
6483
  SessionInjector,
5827
6484
  {
5828
6485
  sessionId: activeSessionId,
@@ -5832,7 +6489,7 @@ function FloPayCheckout({
5832
6489
  children
5833
6490
  }
5834
6491
  )
5835
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6492
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5836
6493
  SplitCardForm,
5837
6494
  {
5838
6495
  sessionId: activeSessionId,
@@ -5852,6 +6509,7 @@ function FloPayCheckout({
5852
6509
  showPayPal,
5853
6510
  showStripe,
5854
6511
  enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
6512
+ enabledPaymentMethodCountries: unified?.data.stripe?.enabledPaymentMethodCountries,
5855
6513
  showApplePay,
5856
6514
  showGooglePay,
5857
6515
  layout,
@@ -5865,6 +6523,8 @@ function FloPayCheckout({
5865
6523
  onButtonClick,
5866
6524
  onBeforeButtonClick,
5867
6525
  enableAVS,
6526
+ ...cardFieldOrder ? { cardFieldOrder } : {},
6527
+ ...cardPreFormSlot ? { cardPreFormSlot } : {},
5868
6528
  avsLayout,
5869
6529
  country: session?.customer?.country,
5870
6530
  city: session?.customer?.city,
@@ -5892,8 +6552,8 @@ function SessionInjector({
5892
6552
  session,
5893
6553
  children
5894
6554
  }) {
5895
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: import_react9.default.Children.map(children, (child) => {
5896
- if (!import_react9.default.isValidElement(child)) return child;
6555
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: import_react10.default.Children.map(children, (child) => {
6556
+ if (!import_react10.default.isValidElement(child)) return child;
5897
6557
  const existing = child.props;
5898
6558
  const injected = {};
5899
6559
  if (!existing.sessionId) injected.sessionId = sessionId;
@@ -5908,7 +6568,7 @@ function SessionInjector({
5908
6568
  injected.lastName = session.customer.lastName;
5909
6569
  }
5910
6570
  if (Object.keys(injected).length === 0) return child;
5911
- return import_react9.default.cloneElement(child, injected);
6571
+ return import_react10.default.cloneElement(child, injected);
5912
6572
  }) });
5913
6573
  }
5914
6574
  function InterimButtonsView({
@@ -5928,15 +6588,15 @@ function InterimButtonsView({
5928
6588
  cardBackButtonContent,
5929
6589
  cardTitleContent
5930
6590
  }) {
5931
- const [showCardForm, setShowCardForm] = (0, import_react9.useState)(false);
6591
+ const [showCardForm, setShowCardForm] = (0, import_react10.useState)(false);
5932
6592
  const isCardOpenControlled = typeof cardOpen === "boolean";
5933
- (0, import_react9.useEffect)(() => {
6593
+ (0, import_react10.useEffect)(() => {
5934
6594
  if (isCardOpenControlled) {
5935
6595
  setShowCardForm(cardOpen);
5936
6596
  }
5937
6597
  }, [cardOpen, isCardOpenControlled]);
5938
- const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
5939
- const bStyles = (0, import_react9.useMemo)(() => {
6598
+ const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
6599
+ const bStyles = (0, import_react10.useMemo)(() => {
5940
6600
  const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
5941
6601
  if (!stylesOverride) return base;
5942
6602
  return {
@@ -5951,7 +6611,7 @@ function InterimButtonsView({
5951
6611
  };
5952
6612
  }, [themeBundle, buttonsTheme, stylesOverride]);
5953
6613
  const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5954
- const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6614
+ const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5955
6615
  height: h,
5956
6616
  borderRadius: skeletonRadius,
5957
6617
  background: "#e5e7eb",
@@ -5963,15 +6623,15 @@ function InterimButtonsView({
5963
6623
  const inputBg = bStyles.cardInputBackground ?? "white";
5964
6624
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
5965
6625
  const hideTitle = isEmptySlotContent(cardTitleContent);
5966
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
6626
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5967
6627
  backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
5968
6628
  borderRadius: "8px",
5969
6629
  animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
5970
6630
  overflow: "hidden",
5971
6631
  ...bStyles.cardFormContainer
5972
6632
  }, children: [
5973
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
5974
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
6633
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
6634
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5975
6635
  "button",
5976
6636
  {
5977
6637
  type: "button",
@@ -5998,7 +6658,7 @@ function InterimButtonsView({
5998
6658
  ...bStyles.backButton
5999
6659
  },
6000
6660
  children: [
6001
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
6661
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
6002
6662
  display: "inline-flex",
6003
6663
  alignItems: "center",
6004
6664
  justifyContent: "center",
@@ -6007,12 +6667,12 @@ function InterimButtonsView({
6007
6667
  borderRadius: "50%",
6008
6668
  backgroundColor: "#f3f4f6",
6009
6669
  ...bStyles.backButtonIcon
6010
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
6011
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
6670
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
6671
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
6012
6672
  ]
6013
6673
  }
6014
6674
  ),
6015
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6675
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6016
6676
  flex: 1,
6017
6677
  textAlign: "center",
6018
6678
  fontWeight: 600,
@@ -6020,11 +6680,11 @@ function InterimButtonsView({
6020
6680
  color: "#262833",
6021
6681
  paddingRight: 80,
6022
6682
  ...bStyles.title
6023
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
6683
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
6024
6684
  ] }),
6025
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6026
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex" }, children: [
6027
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6685
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6686
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
6687
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6028
6688
  flex: 1,
6029
6689
  backgroundColor: inputBg,
6030
6690
  borderTop: "none",
@@ -6034,8 +6694,8 @@ function InterimButtonsView({
6034
6694
  borderBottomLeftRadius: 8,
6035
6695
  padding: 12,
6036
6696
  height: 45
6037
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6038
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6697
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6698
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6039
6699
  flex: 1,
6040
6700
  backgroundColor: inputBg,
6041
6701
  borderTop: "none",
@@ -6045,10 +6705,10 @@ function InterimButtonsView({
6045
6705
  borderBottomRightRadius: 8,
6046
6706
  padding: 12,
6047
6707
  height: 45
6048
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
6708
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
6049
6709
  ] }),
6050
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6051
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6710
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
6711
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6052
6712
  height: 50,
6053
6713
  borderRadius: 8,
6054
6714
  marginTop: 16,
@@ -6057,7 +6717,7 @@ function InterimButtonsView({
6057
6717
  ...bStyles.submitButton,
6058
6718
  opacity: 0.5
6059
6719
  } }),
6060
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
6720
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
6061
6721
  @keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
6062
6722
  @keyframes flopay-interim-expand {
6063
6723
  0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
@@ -6067,10 +6727,10 @@ function InterimButtonsView({
6067
6727
  ` })
6068
6728
  ] });
6069
6729
  }
6070
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6730
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6071
6731
  showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6072
6732
  showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6073
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6733
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6074
6734
  "button",
6075
6735
  {
6076
6736
  type: "button",
@@ -6110,10 +6770,10 @@ function InterimButtonsView({
6110
6770
  onMouseUp: (e) => {
6111
6771
  e.currentTarget.style.transform = "scale(1)";
6112
6772
  },
6113
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
6773
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
6114
6774
  }
6115
6775
  ),
6116
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
6776
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
6117
6777
  margin: "0.25rem 0",
6118
6778
  padding: "0.625rem 0.875rem",
6119
6779
  background: "#FEF2F2",
@@ -6127,22 +6787,22 @@ function InterimButtonsView({
6127
6787
  gap: "0.5rem",
6128
6788
  ...bStyles.errorBanner
6129
6789
  }, children: [
6130
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
6790
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", stroke: "#DC2626", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
6131
6791
  errorMessage
6132
6792
  ] }),
6133
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6793
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6134
6794
  ] });
6135
6795
  }
6136
6796
 
6137
6797
  // src/checkout-form.tsx
6138
6798
  var import_js5 = require("@flopay/js");
6139
6799
  var import_shared9 = require("@flopay/shared");
6140
- var import_react10 = require("react");
6141
- var import_jsx_runtime8 = require("react/jsx-runtime");
6800
+ var import_react11 = require("react");
6801
+ var import_jsx_runtime9 = require("react/jsx-runtime");
6142
6802
  var WALLET_RESUME_KEY = "flopay_wallet_resume";
6143
- var CheckoutForm = (0, import_react10.forwardRef)(
6803
+ var CheckoutForm = (0, import_react11.forwardRef)(
6144
6804
  function CheckoutForm2(props, ref) {
6145
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
6805
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
6146
6806
  }
6147
6807
  );
6148
6808
  function CheckoutFormInner({
@@ -6172,27 +6832,27 @@ function CheckoutFormInner({
6172
6832
  const paypalFlopay = usePayPalFloPay();
6173
6833
  const elements = useElements();
6174
6834
  const contextBillingUrl = useBillingApiUrl();
6175
- const [processing, setProcessing] = (0, import_react10.useState)(false);
6176
- const [error, setError] = (0, import_react10.useState)(null);
6177
- const [is3DSActive, setIs3DSActive] = (0, import_react10.useState)(false);
6835
+ const [processing, setProcessing] = (0, import_react11.useState)(false);
6836
+ const [error, setError] = (0, import_react11.useState)(null);
6837
+ const [is3DSActive, setIs3DSActive] = (0, import_react11.useState)(false);
6178
6838
  const displayError = externalError ?? error;
6179
6839
  const isSubmitting = externalProcessing ?? processing;
6180
6840
  const isSelfContained = !onTokenizedBody;
6181
6841
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
6182
- const updateError = (0, import_react10.useCallback)(
6842
+ const updateError = (0, import_react11.useCallback)(
6183
6843
  (err) => {
6184
6844
  setError(err);
6185
6845
  onErrorChange?.(err);
6186
6846
  },
6187
6847
  [onErrorChange]
6188
6848
  );
6189
- const emitDecline = (0, import_react10.useCallback)(
6849
+ const emitDecline = (0, import_react11.useCallback)(
6190
6850
  (input, overrides) => {
6191
6851
  onDecline?.(buildDeclineEvent("card", input, overrides));
6192
6852
  },
6193
6853
  [onDecline]
6194
6854
  );
6195
- const processPaymentInternal = (0, import_react10.useCallback)(
6855
+ const processPaymentInternal = (0, import_react11.useCallback)(
6196
6856
  async (tokenizedBody, completionPaymentMethodId) => {
6197
6857
  setProcessing(true);
6198
6858
  updateError(null);
@@ -6304,7 +6964,7 @@ function CheckoutFormInner({
6304
6964
  },
6305
6965
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
6306
6966
  );
6307
- const dispatchTokenizedBody = (0, import_react10.useCallback)(
6967
+ const dispatchTokenizedBody = (0, import_react11.useCallback)(
6308
6968
  (tokenizedBody) => {
6309
6969
  if (onTokenizedBody) {
6310
6970
  onTokenizedBody(tokenizedBody);
@@ -6314,7 +6974,7 @@ function CheckoutFormInner({
6314
6974
  },
6315
6975
  [onTokenizedBody, processPaymentInternal]
6316
6976
  );
6317
- (0, import_react10.useImperativeHandle)(innerRef, () => ({
6977
+ (0, import_react11.useImperativeHandle)(innerRef, () => ({
6318
6978
  async handleNextAction(secret) {
6319
6979
  if (!flopay) return;
6320
6980
  setIs3DSActive(true);
@@ -6341,7 +7001,7 @@ function CheckoutFormInner({
6341
7001
  }
6342
7002
  }
6343
7003
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
6344
- (0, import_react10.useEffect)(() => {
7004
+ (0, import_react11.useEffect)(() => {
6345
7005
  if (typeof window === "undefined") return;
6346
7006
  const stored = localStorage.getItem(WALLET_RESUME_KEY);
6347
7007
  if (!stored) return;
@@ -6359,7 +7019,7 @@ function CheckoutFormInner({
6359
7019
  localStorage.removeItem(WALLET_RESUME_KEY);
6360
7020
  }
6361
7021
  }, [sessionId, dispatchTokenizedBody]);
6362
- const handleSubmit = (0, import_react10.useCallback)(
7022
+ const handleSubmit = (0, import_react11.useCallback)(
6363
7023
  async (e) => {
6364
7024
  e.preventDefault();
6365
7025
  if (!flopay || !elements || isSubmitting) return;
@@ -6451,8 +7111,8 @@ function CheckoutFormInner({
6451
7111
  [flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
6452
7112
  );
6453
7113
  const isReady = flopay !== null && elements !== null;
6454
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
6455
- (is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { "data-testid": "flopay-overlay", style: {
7114
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
7115
+ (is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-overlay", style: {
6456
7116
  position: "absolute",
6457
7117
  inset: 0,
6458
7118
  background: "rgba(255,255,255,0.7)",
@@ -6461,12 +7121,12 @@ function CheckoutFormInner({
6461
7121
  justifyContent: "center",
6462
7122
  zIndex: 10
6463
7123
  }, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
6464
- !isReady && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
6465
- isReady && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6466
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PaymentElement, { options: { layout } }),
6467
- showAddress && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
6468
- displayError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
6469
- children ?? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7124
+ !isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
7125
+ isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7126
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PaymentElement, { options: { layout } }),
7127
+ showAddress && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
7128
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
7129
+ children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
6470
7130
  "button",
6471
7131
  {
6472
7132
  type: "submit",
@@ -6482,8 +7142,8 @@ function CheckoutFormInner({
6482
7142
  // src/paypal-button.tsx
6483
7143
  var import_js6 = require("@flopay/js");
6484
7144
  var import_shared10 = require("@flopay/shared");
6485
- var import_react11 = require("react");
6486
- var import_jsx_runtime9 = require("react/jsx-runtime");
7145
+ var import_react12 = require("react");
7146
+ var import_jsx_runtime10 = require("react/jsx-runtime");
6487
7147
  function PayPalButton({
6488
7148
  sessionId,
6489
7149
  nonce,
@@ -6501,11 +7161,11 @@ function PayPalButton({
6501
7161
  const flopay = useFloPay();
6502
7162
  const elements = useElements();
6503
7163
  const contextBillingUrl = useBillingApiUrl();
6504
- const [ready, setReady] = (0, import_react11.useState)(false);
6505
- const [submitting, setSubmitting] = (0, import_react11.useState)(false);
6506
- const paypalResumeAttempted = (0, import_react11.useRef)(false);
7164
+ const [ready, setReady] = (0, import_react12.useState)(false);
7165
+ const [submitting, setSubmitting] = (0, import_react12.useState)(false);
7166
+ const paypalResumeAttempted = (0, import_react12.useRef)(false);
6507
7167
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
6508
- const processPaymentInternal = (0, import_react11.useCallback)(
7168
+ const processPaymentInternal = (0, import_react12.useCallback)(
6509
7169
  async (tokenizedBody) => {
6510
7170
  try {
6511
7171
  const api = new import_js6.PaymentAPI(baseUrl);
@@ -6533,7 +7193,7 @@ function PayPalButton({
6533
7193
  },
6534
7194
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
6535
7195
  );
6536
- const dispatchTokenizedBody = (0, import_react11.useCallback)(
7196
+ const dispatchTokenizedBody = (0, import_react12.useCallback)(
6537
7197
  (body) => {
6538
7198
  if (onTokenizedBody) {
6539
7199
  onTokenizedBody(body);
@@ -6543,7 +7203,7 @@ function PayPalButton({
6543
7203
  },
6544
7204
  [onTokenizedBody, processPaymentInternal]
6545
7205
  );
6546
- (0, import_react11.useEffect)(() => {
7206
+ (0, import_react12.useEffect)(() => {
6547
7207
  if (!flopay || paypalResumeAttempted.current) return;
6548
7208
  const params = new URLSearchParams(window.location.search);
6549
7209
  const paymentIntentId = params.get("payment_intent");
@@ -6591,7 +7251,7 @@ function PayPalButton({
6591
7251
  }
6592
7252
  })();
6593
7253
  }, [flopay, dispatchTokenizedBody, onErrorChange]);
6594
- const handlePayPalConfirm = (0, import_react11.useCallback)(async () => {
7254
+ const handlePayPalConfirm = (0, import_react12.useCallback)(async () => {
6595
7255
  if (!flopay || !elements) return;
6596
7256
  try {
6597
7257
  setSubmitting(true);
@@ -6625,11 +7285,11 @@ function PayPalButton({
6625
7285
  }
6626
7286
  }, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
6627
7287
  if (!flopay || !elements) {
6628
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
7288
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
6629
7289
  }
6630
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
6631
- !ready && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
6632
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7290
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
7291
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
7292
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6633
7293
  "button",
6634
7294
  {
6635
7295
  type: "button",
@@ -6651,7 +7311,7 @@ function PayPalButton({
6651
7311
  children: submitting ? "Processing..." : "PayPal"
6652
7312
  }
6653
7313
  ) }),
6654
- (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7314
+ (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
6655
7315
  position: "fixed",
6656
7316
  inset: 0,
6657
7317
  background: "rgba(0,0,0,0.4)",
@@ -6659,7 +7319,7 @@ function PayPalButton({
6659
7319
  alignItems: "center",
6660
7320
  justifyContent: "center",
6661
7321
  zIndex: 1e3
6662
- }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7322
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
6663
7323
  background: "white",
6664
7324
  borderRadius: 8,
6665
7325
  padding: "1.5rem",
@@ -6671,10 +7331,10 @@ function PayPalButton({
6671
7331
  }
6672
7332
 
6673
7333
  // src/automatic-payment-button.tsx
6674
- var import_react12 = require("react");
7334
+ var import_react13 = require("react");
6675
7335
  var import_js7 = require("@flopay/js");
6676
7336
  var import_shared11 = require("@flopay/shared");
6677
- var import_jsx_runtime10 = require("react/jsx-runtime");
7337
+ var import_jsx_runtime11 = require("react/jsx-runtime");
6678
7338
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
6679
7339
  function sleep2(ms) {
6680
7340
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -6742,6 +7402,7 @@ function FloPayAutomaticPaymentButton({
6742
7402
  billingApiUrl,
6743
7403
  locale,
6744
7404
  theme,
7405
+ appearance,
6745
7406
  buttonsTheme,
6746
7407
  buttonsStyles: stylesOverride,
6747
7408
  onSuccess,
@@ -6753,11 +7414,11 @@ function FloPayAutomaticPaymentButton({
6753
7414
  style,
6754
7415
  ...buttonProps
6755
7416
  }) {
6756
- const resolvedBillingUrl = (0, import_react12.useMemo)(
7417
+ const resolvedBillingUrl = (0, import_react13.useMemo)(
6757
7418
  () => (0, import_shared11.resolveBillingApiUrl)(billingApiUrl),
6758
7419
  [billingApiUrl]
6759
7420
  );
6760
- const createSessionDraft = (0, import_react12.useMemo)(
7421
+ const createSessionDraft = (0, import_react13.useMemo)(
6761
7422
  () => resolveCreateSessionDraft({
6762
7423
  createSession,
6763
7424
  clientId,
@@ -6785,34 +7446,36 @@ function FloPayAutomaticPaymentButton({
6785
7446
  utmMetadata
6786
7447
  ]
6787
7448
  );
6788
- const [isProcessing, setIsProcessing] = (0, import_react12.useState)(false);
6789
- const [overlayStatus, setOverlayStatus] = (0, import_react12.useState)(null);
6790
- const [overlayError, setOverlayError] = (0, import_react12.useState)(null);
6791
- const [fallbackSession, setFallbackSession] = (0, import_react12.useState)(null);
6792
- const isMountedRef = (0, import_react12.useRef)(true);
6793
- const fallbackSessionRef = (0, import_react12.useRef)(fallbackSession);
6794
- const onSuccessRef = (0, import_react12.useRef)(onSuccess);
6795
- const onErrorRef = (0, import_react12.useRef)(onError);
6796
- const onDeclineRef = (0, import_react12.useRef)(onDecline);
6797
- (0, import_react12.useEffect)(() => {
7449
+ const [isProcessing, setIsProcessing] = (0, import_react13.useState)(false);
7450
+ const [overlayStatus, setOverlayStatus] = (0, import_react13.useState)(null);
7451
+ const [overlayError, setOverlayError] = (0, import_react13.useState)(null);
7452
+ const [fallbackSession, setFallbackSession] = (0, import_react13.useState)(null);
7453
+ const isMountedRef = (0, import_react13.useRef)(true);
7454
+ const threeDsAbortRef = (0, import_react13.useRef)(null);
7455
+ const fallbackSessionRef = (0, import_react13.useRef)(fallbackSession);
7456
+ const onSuccessRef = (0, import_react13.useRef)(onSuccess);
7457
+ const onErrorRef = (0, import_react13.useRef)(onError);
7458
+ const onDeclineRef = (0, import_react13.useRef)(onDecline);
7459
+ (0, import_react13.useEffect)(() => {
6798
7460
  fallbackSessionRef.current = fallbackSession;
6799
7461
  }, [fallbackSession]);
6800
- (0, import_react12.useEffect)(() => {
7462
+ (0, import_react13.useEffect)(() => {
6801
7463
  onSuccessRef.current = onSuccess;
6802
7464
  }, [onSuccess]);
6803
- (0, import_react12.useEffect)(() => {
7465
+ (0, import_react13.useEffect)(() => {
6804
7466
  onErrorRef.current = onError;
6805
7467
  }, [onError]);
6806
- (0, import_react12.useEffect)(() => {
7468
+ (0, import_react13.useEffect)(() => {
6807
7469
  onDeclineRef.current = onDecline;
6808
7470
  }, [onDecline]);
6809
- (0, import_react12.useEffect)(() => {
7471
+ (0, import_react13.useEffect)(() => {
6810
7472
  isMountedRef.current = true;
6811
7473
  return () => {
6812
7474
  isMountedRef.current = false;
7475
+ threeDsAbortRef.current?.abort();
6813
7476
  };
6814
7477
  }, []);
6815
- (0, import_react12.useEffect)(() => {
7478
+ (0, import_react13.useEffect)(() => {
6816
7479
  if (!fallbackSession || typeof window === "undefined") {
6817
7480
  return;
6818
7481
  }
@@ -6826,13 +7489,13 @@ function FloPayAutomaticPaymentButton({
6826
7489
  window.removeEventListener("keydown", handleKeyDown);
6827
7490
  };
6828
7491
  }, [fallbackSession]);
6829
- const emitDecline = (0, import_react12.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
7492
+ const emitDecline = (0, import_react13.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
6830
7493
  onDeclineRef.current?.(buildDeclineEvent(method, error, {
6831
7494
  code: error.code,
6832
7495
  declineCode: error.declineCode
6833
7496
  }));
6834
7497
  }, []);
6835
- const showSuccess = (0, import_react12.useCallback)(async (event) => {
7498
+ const showSuccess = (0, import_react13.useCallback)(async (event) => {
6836
7499
  if (!isMountedRef.current) return;
6837
7500
  setOverlayError(null);
6838
7501
  setOverlayStatus("success");
@@ -6840,7 +7503,7 @@ function FloPayAutomaticPaymentButton({
6840
7503
  if (!isMountedRef.current) return;
6841
7504
  onSuccessRef.current?.(event);
6842
7505
  }, []);
6843
- const showError = (0, import_react12.useCallback)(async (error, options) => {
7506
+ const showError = (0, import_react13.useCallback)(async (error, options) => {
6844
7507
  if (!isMountedRef.current) return;
6845
7508
  onErrorRef.current?.(error);
6846
7509
  if (options?.emitDecline) {
@@ -6850,7 +7513,7 @@ function FloPayAutomaticPaymentButton({
6850
7513
  setOverlayStatus("error");
6851
7514
  await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
6852
7515
  }, [emitDecline]);
6853
- const processResolvedSession = (0, import_react12.useCallback)(async (apiResult, resolvedSessionId, options) => {
7516
+ const processResolvedSession = (0, import_react13.useCallback)(async (apiResult, resolvedSessionId, options) => {
6854
7517
  const session = apiResult.data.session ?? null;
6855
7518
  if (!session) {
6856
7519
  throw new import_shared11.FloPayError("No session data returned", "api_error");
@@ -6891,6 +7554,62 @@ function FloPayAutomaticPaymentButton({
6891
7554
  return;
6892
7555
  }
6893
7556
  if (apiResult.autoProcessingError) {
7557
+ if (apiResult.autoProcessingError.type === "3ds_required" && apiResult.autoProcessingError.nextActionRedirectUrl && resolvedSessionId && effectiveNonce) {
7558
+ const threeDsAbort = new AbortController();
7559
+ threeDsAbortRef.current = threeDsAbort;
7560
+ let outcome;
7561
+ try {
7562
+ outcome = await runAutoCheckoutThreeDsChallenge({
7563
+ billingApiUrl: resolvedBillingUrl,
7564
+ sessionId: resolvedSessionId,
7565
+ nonce: effectiveNonce,
7566
+ nextActionRedirectUrl: apiResult.autoProcessingError.nextActionRedirectUrl,
7567
+ signal: threeDsAbort.signal
7568
+ });
7569
+ } finally {
7570
+ if (threeDsAbortRef.current === threeDsAbort) {
7571
+ threeDsAbortRef.current = null;
7572
+ }
7573
+ }
7574
+ if (outcome.status === "declined") {
7575
+ throw checkoutProcessErrorToFloPayError(
7576
+ {
7577
+ type: outcome.declineReason ?? "decline",
7578
+ message: "Card was declined.",
7579
+ gatewayErrorCode: outcome.gatewayDeclineReason ?? void 0
7580
+ },
7581
+ "Card was declined.",
7582
+ {
7583
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7584
+ }
7585
+ );
7586
+ }
7587
+ const api = new import_js7.PaymentAPI(resolvedBillingUrl);
7588
+ const completed = await api.waitForCheckoutSessionCompletion(resolvedSessionId, {
7589
+ initialDelayMs: 0,
7590
+ nonce: effectiveNonce
7591
+ });
7592
+ const completedSession = completed.data.session;
7593
+ if (!completedSession || completedSession.status !== "complete") {
7594
+ throw checkoutProcessErrorToFloPayError(
7595
+ {
7596
+ type: "unknown",
7597
+ message: "Card authentication was not completed."
7598
+ },
7599
+ "Card authentication was not completed.",
7600
+ {
7601
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7602
+ }
7603
+ );
7604
+ }
7605
+ await showSuccess({
7606
+ result: { status: "succeeded" },
7607
+ session: completedSession,
7608
+ sessionId: completedSession.id || resolvedSessionId,
7609
+ autoCompleted: false
7610
+ });
7611
+ return;
7612
+ }
6894
7613
  throw checkoutProcessErrorToFloPayError(
6895
7614
  apiResult.autoProcessingError,
6896
7615
  "Automatic payment failed. Please try again.",
@@ -6950,7 +7669,7 @@ function FloPayAutomaticPaymentButton({
6950
7669
  showError,
6951
7670
  showSuccess
6952
7671
  ]);
6953
- const handleButtonClick = (0, import_react12.useCallback)(async (event) => {
7672
+ const handleButtonClick = (0, import_react13.useCallback)(async (event) => {
6954
7673
  buttonProps.onClick?.(event);
6955
7674
  if (event.defaultPrevented || disabled || isProcessing) {
6956
7675
  return;
@@ -7032,7 +7751,7 @@ function FloPayAutomaticPaymentButton({
7032
7751
  showError,
7033
7752
  showSuccess
7034
7753
  ]);
7035
- const handleFallbackComplete = (0, import_react12.useCallback)((result) => {
7754
+ const handleFallbackComplete = (0, import_react13.useCallback)((result) => {
7036
7755
  const activeFallback = fallbackSessionRef.current;
7037
7756
  setFallbackSession(null);
7038
7757
  onSuccessRef.current?.({
@@ -7042,14 +7761,14 @@ function FloPayAutomaticPaymentButton({
7042
7761
  autoCompleted: false
7043
7762
  });
7044
7763
  }, []);
7045
- const handleFallbackError = (0, import_react12.useCallback)((error) => {
7764
+ const handleFallbackError = (0, import_react13.useCallback)((error) => {
7046
7765
  onErrorRef.current?.(error);
7047
7766
  }, []);
7048
- const handleFallbackDecline = (0, import_react12.useCallback)((decline) => {
7767
+ const handleFallbackDecline = (0, import_react13.useCallback)((decline) => {
7049
7768
  onDeclineRef.current?.(decline);
7050
7769
  }, []);
7051
- const themeBundle = (0, import_react12.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
7052
- const bStyles = (0, import_react12.useMemo)(() => {
7770
+ const themeBundle = (0, import_react13.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
7771
+ const bStyles = (0, import_react13.useMemo)(() => {
7053
7772
  const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
7054
7773
  if (!stylesOverride) return base;
7055
7774
  return {
@@ -7058,9 +7777,26 @@ function FloPayAutomaticPaymentButton({
7058
7777
  cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
7059
7778
  };
7060
7779
  }, [themeBundle, buttonsTheme, stylesOverride]);
7780
+ const resolvedAppearance = (0, import_react13.useMemo)(() => {
7781
+ const bundleAppearance = themeBundle?.appearance;
7782
+ if (!appearance) return bundleAppearance;
7783
+ if (!bundleAppearance) return appearance;
7784
+ return {
7785
+ ...bundleAppearance,
7786
+ ...appearance,
7787
+ variables: {
7788
+ ...bundleAppearance.variables,
7789
+ ...appearance.variables
7790
+ }
7791
+ };
7792
+ }, [appearance, themeBundle]);
7793
+ const resolvedAppearanceVars = resolvedAppearance?.variables;
7794
+ const resolvedPrimaryColor = resolvedAppearanceVars?.colorPrimary ?? "#4A49FF";
7795
+ const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
7796
+ const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
7061
7797
  const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
7062
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
7063
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7798
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
7799
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7064
7800
  "button",
7065
7801
  {
7066
7802
  ...buttonProps,
@@ -7076,14 +7812,17 @@ function FloPayAutomaticPaymentButton({
7076
7812
  // on top so the auto-pay button carries the *submit* button's
7077
7813
  // background and text colours — making it visually identical to
7078
7814
  // the "Confirm Payment" / "Pay with X" actions it stands in for.
7815
+ // `resolvedPrimaryColor` is the *merged* appearance value, so a
7816
+ // per-checkout `colorPrimary` override re-skins this button too.
7079
7817
  // Inline `style` consumer override stays at the end so explicit
7080
7818
  // per-button overrides still win.
7081
7819
  ...bStyles.cardButton,
7082
7820
  ...derivePrimaryTileStyle({
7083
7821
  themeBundle,
7084
- resolvedPrimaryColor: themeBundle?.appearance.variables?.colorPrimary ?? "#4A49FF",
7085
- resolvedBorderRadius: themeBundle?.appearance.variables?.borderRadius ?? "8px",
7086
- submitButtonStyle: bStyles.submitButton
7822
+ resolvedPrimaryColor,
7823
+ resolvedBorderRadius: resolvedButtonBorderRadius,
7824
+ submitButtonStyle: bStyles.submitButton,
7825
+ explicitPrimaryColor: resolvedAppearanceVars?.colorPrimary
7087
7826
  }),
7088
7827
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
7089
7828
  fontWeight: 600,
@@ -7092,11 +7831,23 @@ function FloPayAutomaticPaymentButton({
7092
7831
  alignItems: "center",
7093
7832
  justifyContent: "center",
7094
7833
  gap: "0.625rem",
7095
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7834
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7096
7835
  position: "relative",
7097
7836
  opacity: disabled || isProcessing ? 0.6 : 1,
7098
7837
  ...style
7099
7838
  },
7839
+ onMouseEnter: (e) => {
7840
+ buttonProps.onMouseEnter?.(e);
7841
+ if (!e.defaultPrevented && !disabled && !isProcessing && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7842
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
7843
+ }
7844
+ },
7845
+ onMouseLeave: (e) => {
7846
+ buttonProps.onMouseLeave?.(e);
7847
+ if (!e.defaultPrevented && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7848
+ e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
7849
+ }
7850
+ },
7100
7851
  onMouseDown: (e) => {
7101
7852
  buttonProps.onMouseDown?.(e);
7102
7853
  if (!e.defaultPrevented) {
@@ -7109,17 +7860,17 @@ function FloPayAutomaticPaymentButton({
7109
7860
  e.currentTarget.style.transform = "scale(1)";
7110
7861
  }
7111
7862
  },
7112
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CardButtonContentSlot, { content: children })
7863
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CardButtonContentSlot, { content: children })
7113
7864
  }
7114
7865
  ),
7115
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7866
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7116
7867
  ProcessingOverlay,
7117
7868
  {
7118
7869
  status: overlayStatus,
7119
7870
  errorMessage: overlayError
7120
7871
  }
7121
7872
  ),
7122
- fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7873
+ fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7123
7874
  "div",
7124
7875
  {
7125
7876
  "data-testid": "flopay-automatic-payment-fallback",
@@ -7140,7 +7891,7 @@ function FloPayAutomaticPaymentButton({
7140
7891
  padding: "1.5rem",
7141
7892
  zIndex: 1100
7142
7893
  },
7143
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7894
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7144
7895
  "div",
7145
7896
  {
7146
7897
  style: {
@@ -7156,7 +7907,7 @@ function FloPayAutomaticPaymentButton({
7156
7907
  flexDirection: "column",
7157
7908
  gap: "1rem"
7158
7909
  },
7159
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7910
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7160
7911
  FloPayCheckout,
7161
7912
  {
7162
7913
  sessionId: fallbackSession.sessionId,
@@ -7165,6 +7916,7 @@ function FloPayAutomaticPaymentButton({
7165
7916
  billingApiUrl: resolvedBillingUrl,
7166
7917
  locale,
7167
7918
  theme,
7919
+ ...resolvedAppearance ? { appearance: resolvedAppearance } : {},
7168
7920
  buttonsTheme,
7169
7921
  buttonsStyles: stylesOverride,
7170
7922
  initialErrorMessage: fallbackSession.errorMessage,
@@ -7195,6 +7947,7 @@ function FloPayAutomaticPaymentButton({
7195
7947
  PayPalButton,
7196
7948
  PaymentElement,
7197
7949
  SplitCardForm,
7950
+ VaultCardFields,
7198
7951
  useCheckout,
7199
7952
  useElements,
7200
7953
  useFloPay,