@flopay/react 1.2.8 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,
@@ -1353,6 +1447,18 @@ function getButtonMethodLabel(method) {
1353
1447
  return "Card";
1354
1448
  }
1355
1449
  }
1450
+ function malformedPostcodeMessage(country) {
1451
+ const example = (0, import_shared5.getPostalCodeExample)(country);
1452
+ return `Enter a valid ${(0, import_shared5.getPostalCodeLabel)(country)}${example ? ` (e.g. ${example})` : ""}`;
1453
+ }
1454
+ function computePostalCodeState(country, zip, visible) {
1455
+ const supported = (0, import_shared5.isPostalCodeSupported)(country);
1456
+ const trimmed = zip.trim();
1457
+ const required = visible && supported;
1458
+ const empty = required && !trimmed;
1459
+ const malformed = required && !!trimmed && !(0, import_shared5.isValidPostalCode)(country, trimmed);
1460
+ return { visible, supported, required, empty, malformed };
1461
+ }
1356
1462
  function normalizeBeforeButtonClickError(method, err) {
1357
1463
  return err instanceof import_shared6.FloPayError ? err : new import_shared6.FloPayError(
1358
1464
  err instanceof Error ? err.message : `${getButtonMethodLabel(method)} before-click hook failed.`,
@@ -1360,7 +1466,7 @@ function normalizeBeforeButtonClickError(method, err) {
1360
1466
  );
1361
1467
  }
1362
1468
  function FloPayKeyframes() {
1363
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: FLOPAY_KEYFRAMES });
1469
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: FLOPAY_KEYFRAMES });
1364
1470
  }
1365
1471
  function toCssSize(value) {
1366
1472
  if (typeof value === "number") return `${value}px`;
@@ -1382,8 +1488,8 @@ function ExpressCheckoutReadySwap({
1382
1488
  children
1383
1489
  }) {
1384
1490
  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)(
1491
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
1492
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1387
1493
  "div",
1388
1494
  {
1389
1495
  "data-testid": placeholderTestId,
@@ -1402,7 +1508,7 @@ function ExpressCheckoutReadySwap({
1402
1508
  }
1403
1509
  }
1404
1510
  ),
1405
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1511
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1406
1512
  "div",
1407
1513
  {
1408
1514
  style: {
@@ -1420,9 +1526,9 @@ function ExpressCheckoutReadySwap({
1420
1526
  function isExpressCheckoutRowVisible(state) {
1421
1527
  return state !== "unavailable" && state !== "load_error";
1422
1528
  }
1423
- var SplitCardForm = (0, import_react8.forwardRef)(
1529
+ var SplitCardForm = (0, import_react9.forwardRef)(
1424
1530
  function SplitCardForm2(props, ref) {
1425
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
1531
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
1426
1532
  }
1427
1533
  );
1428
1534
  function PayPalButtonInner({
@@ -1441,15 +1547,15 @@ function PayPalButtonInner({
1441
1547
  }) {
1442
1548
  const stripe = (0, import_react_stripe_js.useStripe)();
1443
1549
  const elements = (0, import_react_stripe_js.useElements)();
1444
- const [loadState, setLoadState] = (0, import_react8.useState)("loading");
1445
- (0, import_react8.useEffect)(() => {
1550
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
1551
+ (0, import_react9.useEffect)(() => {
1446
1552
  onLoadStateChange?.(loadState);
1447
1553
  }, [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);
1554
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1555
+ const paypalResumeAttempted = (0, import_react9.useRef)(false);
1556
+ const beforeClickRef = (0, import_react9.useRef)(null);
1451
1557
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1452
- (0, import_react8.useEffect)(() => {
1558
+ (0, import_react9.useEffect)(() => {
1453
1559
  if (!stripe || paypalResumeAttempted.current) return;
1454
1560
  const params = new URLSearchParams(window.location.search);
1455
1561
  const paymentIntentId = params.get("payment_intent");
@@ -1515,7 +1621,7 @@ function PayPalButtonInner({
1515
1621
  }
1516
1622
  })();
1517
1623
  }, [stripe, onTokenizedBody, onErrorChange, onDecline]);
1518
- const handlePayPalClick = (0, import_react8.useCallback)(async (event) => {
1624
+ const handlePayPalClick = (0, import_react9.useCallback)(async (event) => {
1519
1625
  if (isProcessing || submitting) {
1520
1626
  event.reject();
1521
1627
  return;
@@ -1534,7 +1640,7 @@ function PayPalButtonInner({
1534
1640
  onButtonClick?.("paypal");
1535
1641
  event.resolve();
1536
1642
  }, [isProcessing, onButtonClick, runBeforeButtonClick, submitting]);
1537
- const handlePayPalConfirm = (0, import_react8.useCallback)(async (event) => {
1643
+ const handlePayPalConfirm = (0, import_react9.useCallback)(async (event) => {
1538
1644
  if (!stripe || !elements) return;
1539
1645
  let prepared = beforeClickRef.current;
1540
1646
  beforeClickRef.current = null;
@@ -1654,14 +1760,14 @@ function PayPalButtonInner({
1654
1760
  setSubmitting(false);
1655
1761
  }
1656
1762
  }, [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)(
1763
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1764
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1659
1765
  ExpressCheckoutReadySwap,
1660
1766
  {
1661
1767
  state: loadState,
1662
1768
  placeholderTestId: "flopay-paypal-placeholder",
1663
1769
  borderRadius: placeholderBorderRadius,
1664
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1770
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1665
1771
  import_react_stripe_js.ExpressCheckoutElement,
1666
1772
  {
1667
1773
  onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
@@ -1688,7 +1794,7 @@ function PayPalButtonInner({
1688
1794
  )
1689
1795
  }
1690
1796
  ),
1691
- submitting && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: "processing" })
1797
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
1692
1798
  ] });
1693
1799
  }
1694
1800
  function WalletButtonInner({
@@ -1707,15 +1813,15 @@ function WalletButtonInner({
1707
1813
  }) {
1708
1814
  const stripe = (0, import_react_stripe_js.useStripe)();
1709
1815
  const elements = (0, import_react_stripe_js.useElements)();
1710
- const [loadState, setLoadState] = (0, import_react8.useState)("loading");
1711
- (0, import_react8.useEffect)(() => {
1816
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
1817
+ (0, import_react9.useEffect)(() => {
1712
1818
  onLoadStateChange?.(loadState);
1713
1819
  }, [loadState, onLoadStateChange]);
1714
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
1820
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1715
1821
  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)(
1822
+ const lastWalletMethodRef = (0, import_react9.useRef)("card");
1823
+ const beforeClickRef = (0, import_react9.useRef)(null);
1824
+ const handleWalletConfirm = (0, import_react9.useCallback)(
1719
1825
  async (event) => {
1720
1826
  if (!stripe || !elements) return;
1721
1827
  const walletType = event.expressPaymentType;
@@ -1805,7 +1911,7 @@ function WalletButtonInner({
1805
1911
  },
1806
1912
  [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
1807
1913
  );
1808
- const expressMethodMap = (0, import_react8.useMemo)(() => {
1914
+ const expressMethodMap = (0, import_react9.useMemo)(() => {
1809
1915
  const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
1810
1916
  const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
1811
1917
  const enabledKeys = new Set(expressMethods.map(import_shared5.stripeExpressMethodToOptionKey));
@@ -1819,18 +1925,18 @@ function WalletButtonInner({
1819
1925
  }
1820
1926
  return out;
1821
1927
  }, [expressMethods]);
1822
- const availableMethodKeys = (0, import_react8.useMemo)(
1928
+ const availableMethodKeys = (0, import_react9.useMemo)(
1823
1929
  () => expressMethods.map(import_shared5.stripeExpressMethodToOptionKey),
1824
1930
  [expressMethods]
1825
1931
  );
1826
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1827
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1828
1934
  ExpressCheckoutReadySwap,
1829
1935
  {
1830
1936
  state: loadState,
1831
1937
  placeholderTestId: "flopay-wallet-placeholder",
1832
1938
  borderRadius: placeholderBorderRadius,
1833
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1939
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1834
1940
  import_react_stripe_js.ExpressCheckoutElement,
1835
1941
  {
1836
1942
  onReady: (event) => {
@@ -1869,7 +1975,7 @@ function WalletButtonInner({
1869
1975
  )
1870
1976
  }
1871
1977
  ),
1872
- submitting && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingOverlay, { status: "processing" })
1978
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
1873
1979
  ] });
1874
1980
  }
1875
1981
  function StripeMethodButton({
@@ -1890,7 +1996,7 @@ function StripeMethodButton({
1890
1996
  const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
1891
1997
  const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
1892
1998
  const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
1893
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1999
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1894
2000
  "button",
1895
2001
  {
1896
2002
  type: "button",
@@ -1937,9 +2043,9 @@ function StripeMethodButton({
1937
2043
  // Pulse-skeleton parity with the wallet ECE: no spinner, just the
1938
2044
  // status text on top of the pulsing background. Keeps the loading
1939
2045
  // 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)(
2046
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
2047
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2048
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1943
2049
  "span",
1944
2050
  {
1945
2051
  style: {
@@ -1952,7 +2058,7 @@ function StripeMethodButton({
1952
2058
  gap: (0, import_shared5.hasVendoredStripeMethodLogo)(method) ? 8 : 0
1953
2059
  },
1954
2060
  children: [
1955
- brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2061
+ brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1956
2062
  "span",
1957
2063
  {
1958
2064
  "aria-hidden": "true",
@@ -1971,11 +2077,11 @@ function StripeMethodButton({
1971
2077
  dangerouslySetInnerHTML: { __html: brand.logoSvg }
1972
2078
  }
1973
2079
  ),
1974
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
2080
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
1975
2081
  ]
1976
2082
  }
1977
2083
  ),
1978
- hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2084
+ hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1979
2085
  "svg",
1980
2086
  {
1981
2087
  width: "14",
@@ -1995,7 +2101,7 @@ function StripeMethodButton({
1995
2101
  opacity: 0.7
1996
2102
  },
1997
2103
  "aria-hidden": "true",
1998
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 18l6-6-6-6" })
2104
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 18l6-6-6-6" })
1999
2105
  }
2000
2106
  )
2001
2107
  ] })
@@ -2018,16 +2124,17 @@ function StripeMethodInlineForm({
2018
2124
  isProcessing,
2019
2125
  submitButtonColor,
2020
2126
  submitButtonBorderRadius,
2021
- submitButtonStyle
2127
+ submitButtonStyle,
2128
+ errorText
2022
2129
  }) {
2023
2130
  const stripe = (0, import_react_stripe_js.useStripe)();
2024
2131
  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");
2132
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
2133
+ const submittingRef = (0, import_react9.useRef)(false);
2134
+ const [isMethodComplete, setIsMethodComplete] = (0, import_react9.useState)(false);
2135
+ const [loadState, setLoadState] = (0, import_react9.useState)("loading");
2029
2136
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2030
- const handlePay = (0, import_react8.useCallback)(async () => {
2137
+ const handlePay = (0, import_react9.useCallback)(async () => {
2031
2138
  if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
2032
2139
  submittingRef.current = true;
2033
2140
  setSubmitting(true);
@@ -2167,8 +2274,8 @@ function StripeMethodInlineForm({
2167
2274
  onDecline
2168
2275
  ]);
2169
2276
  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)(
2277
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
2278
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2172
2279
  import_react_stripe_js.PaymentElement,
2173
2280
  {
2174
2281
  onReady: () => setLoadState("ready"),
@@ -2188,7 +2295,7 @@ function StripeMethodInlineForm({
2188
2295
  }
2189
2296
  }
2190
2297
  ),
2191
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2298
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2192
2299
  "button",
2193
2300
  {
2194
2301
  type: "button",
@@ -2214,7 +2321,23 @@ function StripeMethodInlineForm({
2214
2321
  },
2215
2322
  children: submitting ? "Processing\u2026" : `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(method)}`
2216
2323
  }
2217
- )
2324
+ ),
2325
+ errorText && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
2326
+ margin: "0.75rem 0 0",
2327
+ padding: "0.625rem 0.875rem",
2328
+ background: "#FEF2F2",
2329
+ border: "1px solid #FECACA",
2330
+ borderRadius: "8px",
2331
+ color: "#991B1B",
2332
+ fontSize: "0.85rem",
2333
+ fontWeight: 600,
2334
+ display: "flex",
2335
+ alignItems: "center",
2336
+ gap: "0.5rem"
2337
+ }, children: [
2338
+ /* @__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" }) }),
2339
+ errorText
2340
+ ] })
2218
2341
  ] });
2219
2342
  }
2220
2343
  function StripePaymentElementInner({
@@ -2242,17 +2365,17 @@ function StripePaymentElementInner({
2242
2365
  expandedApmMethod
2243
2366
  }) {
2244
2367
  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)(() => {
2368
+ const [expandedMethod, setExpandedMethod] = (0, import_react9.useState)(null);
2369
+ const [submittingMethod, setSubmittingMethod] = (0, import_react9.useState)(null);
2370
+ const submittingRef = (0, import_react9.useRef)(false);
2371
+ (0, import_react9.useEffect)(() => {
2249
2372
  if (paymentElementMethods.length > 0 && stripeInstance) {
2250
2373
  onLoadStateChange?.("ready");
2251
2374
  } else if (!stripeInstance) {
2252
2375
  onLoadStateChange?.("loading");
2253
2376
  }
2254
2377
  }, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
2255
- const handleAutoConfirm = (0, import_react8.useCallback)(async (method) => {
2378
+ const handleAutoConfirm = (0, import_react9.useCallback)(async (method) => {
2256
2379
  if (!stripeInstance) return;
2257
2380
  if (submittingRef.current || isProcessing) return;
2258
2381
  submittingRef.current = true;
@@ -2391,9 +2514,9 @@ function StripePaymentElementInner({
2391
2514
  onErrorChange,
2392
2515
  onDecline
2393
2516
  ]);
2394
- const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react8.useState)(null);
2517
+ const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react9.useState)(null);
2395
2518
  const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
2396
- const handleMethodClick = (0, import_react8.useCallback)((method) => {
2519
+ const handleMethodClick = (0, import_react9.useCallback)((method) => {
2397
2520
  if (submittingRef.current || isProcessing) return;
2398
2521
  if (activeExpandedMethod && activeExpandedMethod !== method) return;
2399
2522
  if ((0, import_shared5.needsStripeMethodExplicitConfirm)(method)) {
@@ -2406,14 +2529,14 @@ function StripePaymentElementInner({
2406
2529
  void handleAutoConfirm(method);
2407
2530
  }
2408
2531
  }, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
2409
- const localInlineElementsOptions = (0, import_react8.useMemo)(() => {
2532
+ const localInlineElementsOptions = (0, import_react9.useMemo)(() => {
2410
2533
  if (!localExpandedMethod) return null;
2411
2534
  return {
2412
2535
  ...paymentElementBaseOptions,
2413
2536
  paymentMethodTypes: [localExpandedMethod]
2414
2537
  };
2415
2538
  }, [localExpandedMethod, paymentElementBaseOptions]);
2416
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2539
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2417
2540
  "div",
2418
2541
  {
2419
2542
  "data-testid": "flopay-stripe-payment-element-region",
@@ -2422,8 +2545,8 @@ function StripePaymentElementInner({
2422
2545
  const isExpanded = expandedApmMethod === method;
2423
2546
  const isSubmittingThis = submittingMethod === method;
2424
2547
  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)(
2548
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.default.Fragment, { children: [
2549
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2427
2550
  StripeMethodButton,
2428
2551
  {
2429
2552
  method,
@@ -2440,12 +2563,12 @@ function StripePaymentElementInner({
2440
2563
  fontFamily: buttonAppearance?.fontFamily
2441
2564
  }
2442
2565
  ),
2443
- !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2566
+ !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2444
2567
  import_react_stripe_js.Elements,
2445
2568
  {
2446
2569
  stripe: stripeInstance,
2447
2570
  options: localInlineElementsOptions,
2448
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2571
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2449
2572
  StripeMethodInlineForm,
2450
2573
  {
2451
2574
  method,
@@ -2498,6 +2621,7 @@ function SplitCardFormInner({
2498
2621
  showPayPal = true,
2499
2622
  showStripe = true,
2500
2623
  enabledPaymentMethods,
2624
+ enabledPaymentMethodCountries,
2501
2625
  showApplePay = true,
2502
2626
  showGooglePay = true,
2503
2627
  layout = "default",
@@ -2512,6 +2636,8 @@ function SplitCardFormInner({
2512
2636
  onButtonClick,
2513
2637
  onBeforeButtonClick,
2514
2638
  enableAVS: enableAVSProp,
2639
+ cardFieldOrder,
2640
+ cardPreFormSlot,
2515
2641
  avsLayout: avsLayoutProp = "row",
2516
2642
  country: countryProp,
2517
2643
  zip: zipProp,
@@ -2536,68 +2662,103 @@ function SplitCardFormInner({
2536
2662
  const flopay = useFloPay();
2537
2663
  const paypalFlopay = usePayPalFloPay();
2538
2664
  const elements = useElements();
2539
- const checkout = (0, import_react8.useContext)(CheckoutContext);
2665
+ const checkout = (0, import_react9.useContext)(CheckoutContext);
2540
2666
  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]);
2667
+ const [processing, setProcessing] = (0, import_react9.useState)(false);
2668
+ const [error, setError] = (0, import_react9.useState)(null);
2669
+ const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
2670
+ const [selectedCountry, setSelectedCountry] = (0, import_react9.useState)(countryProp ?? "US");
2671
+ const [zipCode, setZipCode] = (0, import_react9.useState)(zipProp ?? "");
2672
+ const [addressLine1, setAddressLine1] = (0, import_react9.useState)(addressLine1Prop ?? "");
2673
+ const [addressLine2, setAddressLine2] = (0, import_react9.useState)(addressLine2Prop ?? "");
2674
+ const [city, setCity] = (0, import_react9.useState)(cityProp ?? "");
2675
+ const [stateValue, setStateValue] = (0, import_react9.useState)(stateProp ?? "");
2676
+ const [accountPatch, setAccountPatch] = (0, import_react9.useState)({});
2677
+ const zipCodeRef = (0, import_react9.useRef)(zipProp ?? "");
2678
+ const selectedCountryRef = (0, import_react9.useRef)(countryProp ?? "US");
2679
+ const addressLine1Ref = (0, import_react9.useRef)(addressLine1Prop ?? "");
2680
+ const addressLine2Ref = (0, import_react9.useRef)(addressLine2Prop ?? "");
2681
+ const cityRef = (0, import_react9.useRef)(cityProp ?? "");
2682
+ const stateRef = (0, import_react9.useRef)(stateProp ?? "");
2683
+ const avsConfig = (0, import_react9.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
2558
2684
  const enableAVS = avsConfig !== null;
2559
- const [viewState, setViewState] = (0, import_react8.useState)(initialCardOpen ? "card" : "buttons");
2560
- const [expandedApmMethod, setExpandedApmMethod] = (0, import_react8.useState)(null);
2685
+ const vaultBlockReady = Boolean(session?.vault?.html);
2686
+ const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
2687
+ const vaultActive = Boolean(
2688
+ showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
2689
+ );
2690
+ const cardCapture = (0, import_react9.useMemo)(() => {
2691
+ if (!flopay || !vaultActive || !sessionId) return null;
2692
+ return flopay.cardCapture({ sessionId });
2693
+ }, [flopay, vaultActive, sessionId]);
2694
+ const postalCodeState = (0, import_react9.useMemo)(() => {
2695
+ const cc = selectedCountry;
2696
+ const visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) : false;
2697
+ return computePostalCodeState(cc, zipCode, visible);
2698
+ }, [avsConfig, selectedCountry, zipCode]);
2699
+ const { avsInvalid, invalidAvsFields } = (0, import_react9.useMemo)(() => {
2700
+ const none = { line1: false, city: false, state: false, zip: false };
2701
+ if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
2702
+ const cc = selectedCountry;
2703
+ const isEmpty = (field, value) => (0, import_shared5.isAVSFieldVisible)(field, cc) && !value.trim();
2704
+ const invalidAvsFields2 = {
2705
+ line1: isEmpty(avsConfig.address_line_1, addressLine1),
2706
+ city: isEmpty(avsConfig.city, city),
2707
+ state: isEmpty(avsConfig.state, stateValue),
2708
+ // Empty (required) or malformed both block; unsupported/no-postcode
2709
+ // locales never block (`postalCodeState` fails open above).
2710
+ zip: postalCodeState.empty || postalCodeState.malformed
2711
+ };
2712
+ const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
2713
+ return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
2714
+ }, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, postalCodeState]);
2715
+ const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react9.useState)(false);
2716
+ const [zipTouched, setZipTouched] = (0, import_react9.useState)(false);
2717
+ const [vaultMount, setVaultMount] = (0, import_react9.useState)(
2718
+ () => toVaultMount(session?.vault)
2719
+ );
2720
+ const [viewState, setViewState] = (0, import_react9.useState)(initialCardOpen ? "card" : "buttons");
2721
+ const [expandedApmMethod, setExpandedApmMethod] = (0, import_react9.useState)(null);
2561
2722
  const showCardForm = viewState === "expanding" || viewState === "card";
2562
2723
  const TRANSITION_MS = 280;
2563
- const expandToCard = (0, import_react8.useCallback)(() => {
2724
+ const expandToCard = (0, import_react9.useCallback)(() => {
2564
2725
  setViewState("expanding");
2565
2726
  setTimeout(() => setViewState("card"), TRANSITION_MS);
2566
2727
  }, []);
2567
- const collapseToButtons = (0, import_react8.useCallback)(() => {
2728
+ const collapseToButtons = (0, import_react9.useCallback)(() => {
2568
2729
  setViewState("collapsing");
2569
2730
  setTimeout(() => setViewState("buttons"), TRANSITION_MS);
2570
2731
  }, []);
2571
- const expandToApm = (0, import_react8.useCallback)((method) => {
2732
+ const expandToApm = (0, import_react9.useCallback)((method) => {
2572
2733
  setExpandedApmMethod(method);
2573
2734
  setViewState("apm-expanding");
2574
2735
  setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
2575
2736
  }, []);
2576
- const collapseFromApm = (0, import_react8.useCallback)(() => {
2737
+ const collapseFromApm = (0, import_react9.useCallback)(() => {
2577
2738
  setViewState("apm-collapsing");
2578
2739
  setTimeout(() => {
2579
2740
  setViewState("buttons");
2580
2741
  setExpandedApmMethod(null);
2581
2742
  }, TRANSITION_MS);
2582
2743
  }, []);
2583
- (0, import_react8.useEffect)(() => {
2744
+ (0, import_react9.useEffect)(() => {
2584
2745
  if (layout === "buttons" && initialCardOpen) {
2585
2746
  setViewState("card");
2586
2747
  }
2587
2748
  }, [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)(() => {
2749
+ const [fullName, setFullName] = (0, import_react9.useState)("");
2750
+ const [formReady, setFormReady] = (0, import_react9.useState)(false);
2751
+ const [overlayStatus, setOverlayStatus] = (0, import_react9.useState)(null);
2752
+ const processingRef = (0, import_react9.useRef)(false);
2753
+ const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react9.useState)(null);
2754
+ const paypalDirectRetryRef = (0, import_react9.useRef)(paypalDirectRetry);
2755
+ (0, import_react9.useEffect)(() => {
2595
2756
  paypalDirectRetryRef.current = paypalDirectRetry;
2596
2757
  }, [paypalDirectRetry]);
2597
2758
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
2598
2759
  const displayError = externalError ?? error;
2599
- const themeBundle = (0, import_react8.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
2600
- const bStyles = (0, import_react8.useMemo)(() => {
2760
+ const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
2761
+ const bStyles = (0, import_react9.useMemo)(() => {
2601
2762
  const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
2602
2763
  if (!buttonsStylesOverride) return base;
2603
2764
  return {
@@ -2612,11 +2773,36 @@ function SplitCardFormInner({
2612
2773
  };
2613
2774
  }, [themeBundle, buttonsTheme, buttonsStylesOverride]);
2614
2775
  const appearance = appearanceOverride ?? themeBundle?.appearance;
2776
+ const vaultThemeColors = (0, import_react9.useMemo)(() => {
2777
+ const vars = appearance?.variables;
2778
+ const asString = (value) => typeof value === "string" && value ? value : void 0;
2779
+ const submitButtonStyle = bStyles.submitButton;
2780
+ const primary = asString(vars?.colorPrimary) ?? asString(submitButtonStyle?.backgroundColor) ?? "#4A49FF";
2781
+ const isButtonsLayout = layout === "buttons";
2782
+ const nameInput = bStyles.nameInput;
2783
+ return {
2784
+ primaryColor: primary,
2785
+ primaryHoverColor: asString(vars?.colorPrimaryHover) ?? darkenHex(primary, 0.12),
2786
+ inputBackgroundColor: asString(bStyles.cardInputBackground) ?? asString(vars?.colorBackground) ?? "#ffffff",
2787
+ textColor: asString(bStyles.cardInputColor) ?? asString(nameInput?.color) ?? asString(vars?.colorText) ?? "#262833",
2788
+ borderColor: asString(bStyles.cardInputBorder) ?? (isButtonsLayout ? "#e5e7eb" : "#A4A4FF"),
2789
+ placeholderColor: asString(bStyles.cardInputPlaceholderColor) ?? "#9ca3af",
2790
+ errorColor: asString(vars?.colorDanger) ?? "#dc2626",
2791
+ successColor: "#16a34a",
2792
+ fontFamily: asString(nameInput?.fontFamily) ?? asString(vars?.fontFamily) ?? "Poppins, sans-serif",
2793
+ fontSize: asString(bStyles.cardInputFontSize) ?? asString(vars?.fontSizeBase) ?? "16px",
2794
+ // `resolvedInputFontWeight` equivalent — sent as a string (the widget's
2795
+ // theme applier only honors string values) so vault inputs/placeholders
2796
+ // match the AVS fields' weight per theme (default 400).
2797
+ fontWeight: String(toCssWeight(nameInput?.fontWeight) ?? 400),
2798
+ borderRadius: asString(vars?.borderRadius) ?? "8px"
2799
+ };
2800
+ }, [appearance, bStyles, layout]);
2615
2801
  const isInlineSessionPatchProcessing = checkout.inlineSessionPatchProcessing ?? false;
2616
2802
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
2617
2803
  const isSelfContained = !onTokenizedBody;
2618
2804
  const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
2619
- const resolvedAccount = (0, import_react8.useMemo)(() => mergeAccountPatch({
2805
+ const resolvedAccount = (0, import_react9.useMemo)(() => mergeAccountPatch({
2620
2806
  userId,
2621
2807
  email,
2622
2808
  firstName,
@@ -2624,17 +2810,17 @@ function SplitCardFormInner({
2624
2810
  country: countryProp,
2625
2811
  zip: zipProp
2626
2812
  }, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
2627
- const stripeInstance = (0, import_react8.useMemo)(() => {
2813
+ const stripeInstance = (0, import_react9.useMemo)(() => {
2628
2814
  if (!flopay) return null;
2629
2815
  return flopay.getRawProvider();
2630
2816
  }, [flopay]);
2631
- const paypalStripeInstance = (0, import_react8.useMemo)(() => {
2817
+ const paypalStripeInstance = (0, import_react9.useMemo)(() => {
2632
2818
  if (!paypalFlopay) return null;
2633
2819
  return paypalFlopay.getRawProvider();
2634
2820
  }, [paypalFlopay]);
2635
2821
  const amountInCents = totalAmount || 100;
2636
2822
  const stripeAppearanceProp = appearance ? { appearance } : null;
2637
- const paymentElementAppearance = (0, import_react8.useMemo)(() => {
2823
+ const paymentElementAppearance = (0, import_react9.useMemo)(() => {
2638
2824
  const base = appearance ?? {};
2639
2825
  const baseRules = base.rules ?? {};
2640
2826
  return {
@@ -2654,7 +2840,7 @@ function SplitCardFormInner({
2654
2840
  }
2655
2841
  };
2656
2842
  }, [appearance]);
2657
- const walletOptions = (0, import_react8.useMemo)(() => {
2843
+ const walletOptions = (0, import_react9.useMemo)(() => {
2658
2844
  const modeOptions = resolveWalletElementsMode(totalAmount);
2659
2845
  return {
2660
2846
  ...modeOptions,
@@ -2665,7 +2851,7 @@ function SplitCardFormInner({
2665
2851
  ...stripeAppearanceProp
2666
2852
  };
2667
2853
  }, [totalAmount, currency, stripeAppearanceProp]);
2668
- const paypalOptions = (0, import_react8.useMemo)(() => ({
2854
+ const paypalOptions = (0, import_react9.useMemo)(() => ({
2669
2855
  mode: "payment",
2670
2856
  amount: amountInCents,
2671
2857
  currency: currency.toLowerCase(),
@@ -2673,35 +2859,197 @@ function SplitCardFormInner({
2673
2859
  setupFutureUsage: "off_session",
2674
2860
  ...stripeAppearanceProp
2675
2861
  }), [amountInCents, currency, stripeAppearanceProp]);
2676
- const updateError = (0, import_react8.useCallback)(
2862
+ const updateError = (0, import_react9.useCallback)(
2677
2863
  (err) => {
2678
2864
  setError(err);
2679
2865
  onErrorChange?.(err);
2680
2866
  },
2681
2867
  [onErrorChange]
2682
2868
  );
2683
- const emitDecline = (0, import_react8.useCallback)(
2869
+ (0, import_react9.useEffect)(() => {
2870
+ if (!vaultActive || !cardCapture) return;
2871
+ cardCapture.setSubmitGate?.(avsInvalid);
2872
+ }, [vaultActive, cardCapture, avsInvalid]);
2873
+ (0, import_react9.useEffect)(() => {
2874
+ if (!vaultActive || !cardCapture) return;
2875
+ cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
2876
+ }, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
2877
+ (0, import_react9.useEffect)(() => {
2878
+ if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
2879
+ updateError(null);
2880
+ }
2881
+ }, [viewState, updateError]);
2882
+ const emitDecline = (0, import_react9.useCallback)(
2684
2883
  (method, input, overrides) => {
2685
2884
  onDecline?.(buildDeclineEvent(method, input, overrides));
2686
2885
  },
2687
2886
  [onDecline]
2688
2887
  );
2888
+ (0, import_react9.useEffect)(() => {
2889
+ if (!vaultActive || !sessionId) {
2890
+ setVaultMount(null);
2891
+ return;
2892
+ }
2893
+ const embedded = toVaultMount(session?.vault);
2894
+ if (embedded) {
2895
+ setVaultMount(embedded);
2896
+ return;
2897
+ }
2898
+ setVaultMount(null);
2899
+ let active = true;
2900
+ new import_js2.PaymentAPI(baseUrl).getVaultCapture(sessionId, nonce).then((block) => {
2901
+ if (!active) return;
2902
+ const mount = toVaultMount(block);
2903
+ if (mount) {
2904
+ setVaultMount(mount);
2905
+ } else {
2906
+ updateError("Failed to load the secure card form.");
2907
+ }
2908
+ }).catch((err) => {
2909
+ if (active) {
2910
+ updateError(err instanceof Error ? err.message : "Failed to load the secure card form.");
2911
+ }
2912
+ });
2913
+ return () => {
2914
+ active = false;
2915
+ };
2916
+ }, [
2917
+ vaultActive,
2918
+ sessionId,
2919
+ session?.vault?.html,
2920
+ session?.vault?.messageToken,
2921
+ session?.vault?.expectedOrigin,
2922
+ baseUrl,
2923
+ nonce,
2924
+ updateError
2925
+ ]);
2926
+ const vaultOutcomeRef = (0, import_react9.useRef)({
2927
+ onComplete,
2928
+ onError,
2929
+ updateError,
2930
+ emitDecline,
2931
+ resolvedAccount,
2932
+ fullName,
2933
+ avsConfig,
2934
+ avsCheckProp,
2935
+ sessionId,
2936
+ nonce,
2937
+ baseUrl
2938
+ });
2939
+ vaultOutcomeRef.current = {
2940
+ onComplete,
2941
+ onError,
2942
+ updateError,
2943
+ emitDecline,
2944
+ resolvedAccount,
2945
+ fullName,
2946
+ avsConfig,
2947
+ avsCheckProp,
2948
+ sessionId,
2949
+ nonce,
2950
+ baseUrl
2951
+ };
2952
+ const vaultCompletedRef = (0, import_react9.useRef)(false);
2953
+ (0, import_react9.useEffect)(() => {
2954
+ if (!vaultActive || !cardCapture) return;
2955
+ vaultCompletedRef.current = false;
2956
+ let cancelled = false;
2957
+ const offSubmitting = cardCapture.on("submitting", () => {
2958
+ setHasAttemptedSubmit(true);
2959
+ setOverlayStatus("processing");
2960
+ const { resolvedAccount: resolvedAccount2, avsConfig: avsConfig2, fullName: fullName2, avsCheckProp: avsCheckProp2, baseUrl: baseUrl2, sessionId: sessionId2, nonce: nonce2 } = vaultOutcomeRef.current;
2961
+ if (!sessionId2 || !nonce2) return;
2962
+ const cc = selectedCountryRef.current || resolvedAccount2.country || "US";
2963
+ const stateVisible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.state, cc) : false;
2964
+ const line1Visible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.address_line_1, cc) : false;
2965
+ const zipVisible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.postal_code, cc) : false;
2966
+ const cityVisible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.city, cc) : false;
2967
+ const line2Visible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.address_line_2, cc) : false;
2968
+ const derivedState = line1Visible && !stateVisible && zipVisible ? (0, import_shared5.getStateFromPostalCode)(cc, zipCodeRef.current ?? "") : null;
2969
+ const stateValue2 = stateVisible ? stateRef.current : derivedState;
2970
+ void new import_js2.PaymentAPI(baseUrl2).patchAccountSnapshot(sessionId2, nonce2, {
2971
+ accountData: {
2972
+ userId: resolvedAccount2.userId ?? "",
2973
+ email: resolvedAccount2.email ?? "",
2974
+ firstName: resolvedAccount2.firstName ?? fullName2.trim().split(/\s+/)[0] ?? "",
2975
+ lastName: resolvedAccount2.lastName ?? fullName2.trim().split(/\s+/).slice(1).join(" ") ?? "",
2976
+ ...zipVisible && zipCodeRef.current ? { zip: zipCodeRef.current } : {},
2977
+ ...cityVisible && cityRef.current ? { city: cityRef.current } : {},
2978
+ ...stateValue2 ? { state: stateValue2 } : {},
2979
+ ...line1Visible && addressLine1Ref.current ? { addressLine1: addressLine1Ref.current } : {},
2980
+ ...line2Visible && addressLine2Ref.current ? { addressLine2: addressLine2Ref.current } : {},
2981
+ country: cc
2982
+ },
2983
+ ...avsCheckProp2 !== void 0 ? { avsCheck: avsCheckProp2 } : {},
2984
+ ...avsConfig2 ? {
2985
+ avsConfig: {
2986
+ country: (0, import_shared5.isAVSFieldVisible)(avsConfig2.country, cc),
2987
+ postal_code: zipVisible,
2988
+ address_line_1: line1Visible,
2989
+ address_line_2: line2Visible,
2990
+ city: cityVisible,
2991
+ state: stateVisible
2992
+ }
2993
+ } : {}
2994
+ }).catch(() => {
2995
+ });
2996
+ });
2997
+ const offComplete = cardCapture.on("complete", async (event) => {
2998
+ markSessionRecentlyCompleted(event.sessionId ?? vaultOutcomeRef.current.sessionId);
2999
+ setOverlayStatus("success");
3000
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
3001
+ if (vaultCompletedRef.current) return;
3002
+ vaultCompletedRef.current = true;
3003
+ vaultOutcomeRef.current.onComplete?.({
3004
+ status: "succeeded",
3005
+ paymentIntentId: event.intentId,
3006
+ checkoutMethod: "card"
3007
+ });
3008
+ });
3009
+ const offDecline = cardCapture.on("decline", async (event) => {
3010
+ const { updateError: updateError2, emitDecline: emitDecline2 } = vaultOutcomeRef.current;
3011
+ const message = event.message ?? "Your payment was declined. Please try another card or contact your bank.";
3012
+ updateError2(message);
3013
+ setOverlayStatus("error");
3014
+ emitDecline2("card", message, event.declineReason ? { declineCode: event.declineReason } : void 0);
3015
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3016
+ if (cancelled) return;
3017
+ setOverlayStatus(null);
3018
+ });
3019
+ const offError = cardCapture.on("error", async (event) => {
3020
+ const { updateError: updateError2, onError: onError2 } = vaultOutcomeRef.current;
3021
+ const message = event.message ?? "There was a problem processing your payment. Please try again.";
3022
+ updateError2(message);
3023
+ setOverlayStatus("error");
3024
+ onError2?.(new import_shared6.FloPayError(message, "api_error"));
3025
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3026
+ if (cancelled) return;
3027
+ setOverlayStatus(null);
3028
+ });
3029
+ return () => {
3030
+ cancelled = true;
3031
+ offSubmitting();
3032
+ offComplete();
3033
+ offDecline();
3034
+ offError();
3035
+ };
3036
+ }, [vaultActive, cardCapture]);
2689
3037
  const directPaypalConfigured = !!directPaypal?.clientId;
2690
3038
  const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
2691
3039
  const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
2692
3040
  const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
2693
- const { expressMethods, paymentElementMethods } = (0, import_react8.useMemo)(
3041
+ const { expressMethods, paymentElementMethods } = (0, import_react9.useMemo)(
2694
3042
  () => (0, import_shared5.partitionStripeMethods)(enabledPaymentMethods, {
2695
3043
  excludePaypal: directPaypalConfigured
2696
3044
  }),
2697
3045
  [enabledPaymentMethods, directPaypalConfigured]
2698
3046
  );
2699
3047
  const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
2700
- const expressMethodsForWalletRow = (0, import_react8.useMemo)(
3048
+ const expressMethodsForWalletRow = (0, import_react9.useMemo)(
2701
3049
  () => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
2702
3050
  [expressMethods, paypalRenderedSeparately]
2703
3051
  );
2704
- const legacyExpressMethods = (0, import_react8.useMemo)(() => {
3052
+ const legacyExpressMethods = (0, import_react9.useMemo)(() => {
2705
3053
  const out = [];
2706
3054
  if (showApplePay) out.push("apple_pay");
2707
3055
  if (showGooglePay) out.push("google_pay");
@@ -2709,30 +3057,31 @@ function SplitCardFormInner({
2709
3057
  }, [showApplePay, showGooglePay]);
2710
3058
  const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
2711
3059
  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)(() => ({
3060
+ const apmCountry = enableAVS ? selectedCountry : countryProp;
3061
+ const paymentElementMethodsForCurrency = (0, import_react9.useMemo)(() => {
3062
+ const target = apmCountry?.trim().toUpperCase();
3063
+ if (!target) return paymentElementMethods;
3064
+ if (!enabledPaymentMethodCountries) {
3065
+ return (0, import_shared5.filterStripeMethodsByCountry)(paymentElementMethods, apmCountry);
3066
+ }
3067
+ return paymentElementMethods.filter((method) => {
3068
+ const allowed = enabledPaymentMethodCountries[method];
3069
+ return !allowed || allowed.length === 0 || allowed.includes(target);
3070
+ });
3071
+ }, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
3072
+ const paymentElementBaseOptions = (0, import_react9.useMemo)(() => ({
2724
3073
  mode: "payment",
2725
3074
  amount: amountInCents,
2726
3075
  currency: currency.toLowerCase(),
2727
3076
  paymentMethodCreation: "manual",
2728
3077
  appearance: paymentElementAppearance
2729
3078
  }), [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)(() => {
3079
+ const [paypalLoadState, setPaypalLoadState] = (0, import_react9.useState)("loading");
3080
+ const [walletLoadState, setWalletLoadState] = (0, import_react9.useState)("loading");
3081
+ const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react9.useState)("loading");
3082
+ const [directPaypalReady, setDirectPaypalReady] = (0, import_react9.useState)(false);
3083
+ const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react9.useState)();
3084
+ (0, import_react9.useEffect)(() => {
2736
3085
  setInAppBrowserDetected(isInAppBrowser());
2737
3086
  }, []);
2738
3087
  const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
@@ -2744,8 +3093,8 @@ function SplitCardFormInner({
2744
3093
  const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
2745
3094
  const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
2746
3095
  const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
2747
- const validationFiredRef = (0, import_react8.useRef)(false);
2748
- (0, import_react8.useEffect)(() => {
3096
+ const validationFiredRef = (0, import_react9.useRef)(false);
3097
+ (0, import_react9.useEffect)(() => {
2749
3098
  if (validationFiredRef.current) return;
2750
3099
  if (!showStripe && !showPayPal) {
2751
3100
  validationFiredRef.current = true;
@@ -2765,8 +3114,8 @@ function SplitCardFormInner({
2765
3114
  updateError(err.message);
2766
3115
  }
2767
3116
  }, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
2768
- const deprecationLoggedRef = (0, import_react8.useRef)(false);
2769
- (0, import_react8.useEffect)(() => {
3117
+ const deprecationLoggedRef = (0, import_react9.useRef)(false);
3118
+ (0, import_react9.useEffect)(() => {
2770
3119
  if (deprecationLoggedRef.current) return;
2771
3120
  if (!hasEnabledMethods) return;
2772
3121
  const stale = [];
@@ -2778,14 +3127,14 @@ function SplitCardFormInner({
2778
3127
  `[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
3128
  );
2780
3129
  }, [hasEnabledMethods, showApplePay, showGooglePay]);
2781
- const handleNameChange = (0, import_react8.useCallback)((value) => {
3130
+ const handleNameChange = (0, import_react9.useCallback)((value) => {
2782
3131
  setFullName(value);
2783
3132
  onFullNameChange?.(value);
2784
3133
  const parts = value.trim().split(/\s+/);
2785
3134
  onFirstNameChange?.(parts[0] ?? "");
2786
3135
  onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
2787
3136
  }, [onFullNameChange, onFirstNameChange, onLastNameChange]);
2788
- const applyInlineSessionPatch = (0, import_react8.useCallback)(
3137
+ const applyInlineSessionPatch = (0, import_react9.useCallback)(
2789
3138
  (patch, method) => {
2790
3139
  if (!checkout.applyInlineSessionPatch) {
2791
3140
  return Promise.resolve({ error: null, sessionId, nonce });
@@ -2807,7 +3156,7 @@ function SplitCardFormInner({
2807
3156
  },
2808
3157
  [checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
2809
3158
  );
2810
- const runBeforeButtonClick = (0, import_react8.useCallback)(async (method) => {
3159
+ const runBeforeButtonClick = (0, import_react9.useCallback)(async (method) => {
2811
3160
  if (!onBeforeButtonClick) return { proceed: true };
2812
3161
  try {
2813
3162
  const result = await onBeforeButtonClick({
@@ -2844,7 +3193,7 @@ function SplitCardFormInner({
2844
3193
  return { proceed: false };
2845
3194
  }
2846
3195
  }, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
2847
- const processPaymentInternal = (0, import_react8.useCallback)(
3196
+ const processPaymentInternal = (0, import_react9.useCallback)(
2848
3197
  async (tokenizedBody, overrides) => {
2849
3198
  if (processingRef.current) return;
2850
3199
  processingRef.current = true;
@@ -3055,7 +3404,7 @@ function SplitCardFormInner({
3055
3404
  },
3056
3405
  [baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
3057
3406
  );
3058
- const dispatchTokenizedBody = (0, import_react8.useCallback)(
3407
+ const dispatchTokenizedBody = (0, import_react9.useCallback)(
3059
3408
  (tokenizedBody, overrides) => {
3060
3409
  if (onTokenizedBody) {
3061
3410
  onTokenizedBody(tokenizedBody);
@@ -3065,7 +3414,7 @@ function SplitCardFormInner({
3065
3414
  },
3066
3415
  [onTokenizedBody, processPaymentInternal]
3067
3416
  );
3068
- (0, import_react8.useImperativeHandle)(innerRef, () => ({
3417
+ (0, import_react9.useImperativeHandle)(innerRef, () => ({
3069
3418
  async handleNextAction(secret) {
3070
3419
  if (!flopay) return;
3071
3420
  setIs3DSActive(true);
@@ -3092,8 +3441,8 @@ function SplitCardFormInner({
3092
3441
  }
3093
3442
  }
3094
3443
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
3095
- const stripeResumeAttemptedRef = (0, import_react8.useRef)(false);
3096
- (0, import_react8.useEffect)(() => {
3444
+ const stripeResumeAttemptedRef = (0, import_react9.useRef)(false);
3445
+ (0, import_react9.useEffect)(() => {
3097
3446
  if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
3098
3447
  const params = new URLSearchParams(window.location.search);
3099
3448
  const paymentIntentId = params.get("payment_intent");
@@ -3171,10 +3520,11 @@ function SplitCardFormInner({
3171
3520
  }, persistedOverrides);
3172
3521
  })();
3173
3522
  }, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
3174
- const handleSubmit = (0, import_react8.useCallback)(
3523
+ const handleSubmit = (0, import_react9.useCallback)(
3175
3524
  async (e) => {
3176
3525
  e.preventDefault();
3177
3526
  if (!flopay || !elements || isSubmitting || processingRef.current) return;
3527
+ if (vaultActive) return;
3178
3528
  if (layout !== "buttons") {
3179
3529
  onButtonClick?.("card");
3180
3530
  }
@@ -3185,10 +3535,21 @@ function SplitCardFormInner({
3185
3535
  try {
3186
3536
  if (avsConfig) {
3187
3537
  const country = selectedCountryRef.current;
3188
- if ((0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, country) && !zipCodeRef.current.trim()) {
3538
+ const postal = computePostalCodeState(
3539
+ country,
3540
+ zipCodeRef.current,
3541
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, country)
3542
+ );
3543
+ if (postal.empty) {
3544
+ setZipTouched(true);
3189
3545
  updateError((0, import_shared5.getPostalCodeLabel)(country) + " is required");
3190
3546
  return;
3191
3547
  }
3548
+ if (postal.malformed) {
3549
+ setZipTouched(true);
3550
+ updateError(malformedPostcodeMessage(country));
3551
+ return;
3552
+ }
3192
3553
  if ((0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, country) && !addressLine1Ref.current.trim()) {
3193
3554
  updateError("Street address is required");
3194
3555
  return;
@@ -3202,11 +3563,13 @@ function SplitCardFormInner({
3202
3563
  return;
3203
3564
  }
3204
3565
  }
3205
- const submitResult = await flopay.submitElements();
3206
- if (submitResult.error) {
3207
- updateError(submitResult.error.message);
3208
- onError?.(submitResult.error);
3209
- return;
3566
+ if (!vaultActive) {
3567
+ const submitResult = await flopay.submitElements();
3568
+ if (submitResult.error) {
3569
+ updateError(submitResult.error.message);
3570
+ onError?.(submitResult.error);
3571
+ return;
3572
+ }
3210
3573
  }
3211
3574
  const billingAddress = {};
3212
3575
  const cc = selectedCountryRef.current;
@@ -3231,75 +3594,77 @@ function SplitCardFormInner({
3231
3594
  ...fullName.trim() ? { name: fullName.trim() } : {},
3232
3595
  ...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
3233
3596
  };
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
3597
  if (!sessionId || !resolvedAccount.email) {
3240
3598
  throw new import_shared6.FloPayError("Missing sessionId or email", "validation_error");
3241
3599
  }
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"
3600
+ {
3601
+ const pmResult = await flopay.createPaymentMethod(billingDetails);
3602
+ if (pmResult.error || !pmResult.paymentMethodId) {
3603
+ updateError(pmResult.error?.message ?? "Failed to create payment method.");
3604
+ return;
3605
+ }
3606
+ const intentHeaders = { "Content-Type": "application/json" };
3607
+ if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
3608
+ const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
3609
+ method: "POST",
3610
+ headers: intentHeaders,
3611
+ body: JSON.stringify({
3612
+ sessionId,
3613
+ email: resolvedAccount.email,
3614
+ paymentMethodType: pmResult.paymentMethodId,
3615
+ isPaypal: false
3616
+ })
3617
+ });
3618
+ if (!intentResponse.ok) {
3619
+ const intentError = await buildFloPayApiErrorFromResponse(
3620
+ intentResponse,
3621
+ "Failed to create payment intent"
3622
+ );
3623
+ setOverlayStatus("error");
3624
+ updateError(intentError.message);
3625
+ onError?.(intentError);
3626
+ emitDecline("card", intentError);
3627
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3628
+ return;
3629
+ }
3630
+ const intentJson = await intentResponse.json();
3631
+ const intentClientSecret = intentJson.data?.id;
3632
+ if (!intentClientSecret) throw new import_shared6.FloPayError("No client_secret in payment intent response", "api_error");
3633
+ const confirmResult = await flopay.confirmCardPayment({
3634
+ clientSecret: intentClientSecret,
3635
+ paymentMethodId: pmResult.paymentMethodId
3636
+ });
3637
+ if (confirmResult.error) {
3638
+ setOverlayStatus("error");
3639
+ updateError(confirmResult.error.message);
3640
+ onError?.(confirmResult.error);
3641
+ emitDecline("card", confirmResult.error);
3642
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3643
+ return;
3644
+ }
3645
+ const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
3646
+ const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
3647
+ rawProvider,
3648
+ intentClientSecret
3258
3649
  );
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;
3650
+ const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
3651
+ const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
3652
+ if (!paymentIntentId) {
3653
+ const error2 = new import_shared6.FloPayError("No payment intent returned after confirmation.", "api_error");
3654
+ setOverlayStatus("error");
3655
+ updateError(error2.message);
3656
+ onError?.(error2);
3657
+ await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
3658
+ return;
3659
+ }
3660
+ handedOff = isSelfContained;
3661
+ dispatchTokenizedBody({
3662
+ id: paymentMethodId,
3663
+ type: "card",
3664
+ threeDSecureActionResultTokenId: paymentIntentId,
3665
+ originalPaymentMethodId: pmResult.paymentMethodId
3666
+ });
3295
3667
  }
3296
- handedOff = isSelfContained;
3297
- dispatchTokenizedBody({
3298
- id: paymentMethodId,
3299
- type: "card",
3300
- threeDSecureActionResultTokenId: paymentIntentId,
3301
- originalPaymentMethodId: pmResult.paymentMethodId
3302
- });
3303
3668
  } catch (err) {
3304
3669
  setOverlayStatus("error");
3305
3670
  updateError(err instanceof Error ? err.message : "An unexpected error occurred");
@@ -3311,11 +3676,11 @@ function SplitCardFormInner({
3311
3676
  }
3312
3677
  }
3313
3678
  },
3314
- [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3679
+ [flopay, elements, isSubmitting, sessionId, nonce, resolvedAccount.email, baseUrl, isSelfContained, vaultActive, dispatchTokenizedBody, onButtonClick, onError, updateError, emitDecline, layout]
3315
3680
  );
3316
- const isReady = flopay !== null && elements !== null;
3681
+ const isReady = flopay !== null && (vaultActive || elements !== null);
3317
3682
  if (!isReady) {
3318
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3683
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
3319
3684
  }
3320
3685
  const isButtons = layout === "buttons";
3321
3686
  const appearanceVars = appearance?.variables;
@@ -3323,6 +3688,10 @@ function SplitCardFormInner({
3323
3688
  const appearanceColorBg = appearanceVars?.colorBackground;
3324
3689
  const themedWrapperBg = appearanceColorBg && !SDK_DEFAULT_WHITES.has(appearanceColorBg) ? appearanceColorBg : void 0;
3325
3690
  const resolvedBorder = bStyles.cardInputBorder ?? (isButtons ? "#e5e7eb" : "#A4A4FF");
3691
+ const resolvedDangerColor = appearanceVars?.colorDanger ?? "#dc2626";
3692
+ const avsBorderColor = (fieldInvalid) => hasAttemptedSubmit && fieldInvalid ? resolvedDangerColor : resolvedBorder;
3693
+ const showPostcodeError = (postalCodeState.malformed || postalCodeState.empty) && (zipTouched || hasAttemptedSubmit);
3694
+ const zipBorderColor = showPostcodeError ? resolvedDangerColor : avsBorderColor(invalidAvsFields.zip);
3326
3695
  const cardBg = bStyles.cardFormContainer?.backgroundColor ?? themedWrapperBg ?? (isButtons ? "white" : "#EDEDFF");
3327
3696
  const cardInputBg = bStyles.cardInputBackground ?? appearanceVars?.colorBackground ?? "white";
3328
3697
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
@@ -3334,7 +3703,9 @@ function SplitCardFormInner({
3334
3703
  const resolvedInputColor = bStyles.cardInputColor ?? (typeof nameInputOverrides?.color === "string" ? nameInputOverrides.color : void 0) ?? appearanceVars?.colorText ?? "#262833";
3335
3704
  const resolvedPlaceholderColor = bStyles.cardInputPlaceholderColor ?? "#9ca3af";
3336
3705
  const resolvedBorderRadius = appearanceVars?.borderRadius ?? "8px";
3706
+ const buttonBorderRadius = appearanceVars?.borderRadius ?? bStyles.cardButton?.borderRadius ?? resolvedBorderRadius;
3337
3707
  const resolvedPrimaryColor = appearanceVars?.colorPrimary ?? "#4A49FF";
3708
+ const resolvedPrimaryHoverColor = appearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
3338
3709
  const resolvedTitleColor = appearanceVars?.colorText ?? "#262833";
3339
3710
  const sharedInputTypography = {
3340
3711
  fontSize: resolvedInputFontSize,
@@ -3368,14 +3739,73 @@ function SplitCardFormInner({
3368
3739
  const containerOverrides = bStyles.cardFormContainer ?? {};
3369
3740
  const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
3370
3741
  const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
3371
- const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3742
+ const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3743
+ VaultCardFields,
3744
+ {
3745
+ capture: cardCapture,
3746
+ html: vaultMount.html,
3747
+ messageToken: vaultMount.messageToken,
3748
+ expectedOrigin: vaultMount.expectedOrigin,
3749
+ theme: vaultThemeColors,
3750
+ onReady: () => {
3751
+ setFormReady(true);
3752
+ if (!avsConfig || typeof document === "undefined") return;
3753
+ const focusFirstAvs = () => {
3754
+ const block = document.querySelector('[data-testid="flopay-avs-fields"]');
3755
+ const first = block?.querySelector(
3756
+ "input:not([disabled]), select:not([disabled])"
3757
+ );
3758
+ first?.focus();
3759
+ };
3760
+ focusFirstAvs();
3761
+ let tries = 0;
3762
+ const timer = window.setInterval(() => {
3763
+ tries += 1;
3764
+ const active = document.activeElement;
3765
+ const onIframe = !!active && active.tagName === "IFRAME" && active.id === "flopay_vault_form_iframe";
3766
+ if (onIframe) {
3767
+ focusFirstAvs();
3768
+ window.clearInterval(timer);
3769
+ } else if (tries >= 50) {
3770
+ window.clearInterval(timer);
3771
+ }
3772
+ }, 100);
3773
+ },
3774
+ onError: (message) => updateError(message),
3775
+ onValidation: (message) => {
3776
+ updateError(message);
3777
+ if (message) setOverlayStatus(null);
3778
+ }
3779
+ }
3780
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3781
+ "div",
3782
+ {
3783
+ "data-testid": "flopay-vault-loading",
3784
+ style: {
3785
+ minHeight: 120,
3786
+ display: "flex",
3787
+ alignItems: "center",
3788
+ justifyContent: "center",
3789
+ color: "#6b7280",
3790
+ fontSize: 14
3791
+ },
3792
+ children: "Loading secure card form\u2026"
3793
+ }
3794
+ );
3795
+ const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3372
3796
  backgroundColor: cardBg,
3373
3797
  borderRadius: containerRadius,
3374
3798
  ...containerOverrides,
3375
3799
  padding: containerPadding,
3376
- ...sharedInputPlaceholderVars
3800
+ ...sharedInputPlaceholderVars,
3801
+ // Flex column (BOTH layouts, so default and buttons>card never diverge) so
3802
+ // AVS can be ordered above the vault widget — its submit lives inside the
3803
+ // iframe, so AVS can't sit between fields and button; it goes above the
3804
+ // card form instead of after the button.
3805
+ display: "flex",
3806
+ flexDirection: "column"
3377
3807
  }, children: [
3378
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
3808
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
3379
3809
  .flopay-shared-input::placeholder {
3380
3810
  color: var(--flopay-input-placeholder-color);
3381
3811
  opacity: 1;
@@ -3384,12 +3814,14 @@ function SplitCardFormInner({
3384
3814
  font-weight: var(--flopay-input-font-weight);
3385
3815
  }
3386
3816
  ` }),
3387
- isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3817
+ isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3388
3818
  display: "flex",
3389
3819
  alignItems: "center",
3390
- padding: "0.75rem 0 0.625rem"
3820
+ padding: "0.75rem 0 0.625rem",
3821
+ // Keep the header on top when AVS is ordered above the card on vault.
3822
+ order: vaultActive ? -2 : 0
3391
3823
  }, children: [
3392
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3824
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3393
3825
  "button",
3394
3826
  {
3395
3827
  type: "button",
@@ -3411,7 +3843,7 @@ function SplitCardFormInner({
3411
3843
  },
3412
3844
  "aria-label": "Back to payment methods",
3413
3845
  children: [
3414
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
3846
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
3415
3847
  display: "inline-flex",
3416
3848
  alignItems: "center",
3417
3849
  justifyContent: "center",
@@ -3421,12 +3853,12 @@ function SplitCardFormInner({
3421
3853
  backgroundColor: "#f3f4f6",
3422
3854
  transition: "background-color 0.15s",
3423
3855
  ...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 })
3856
+ }, 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" }) }) }),
3857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
3426
3858
  ]
3427
3859
  }
3428
3860
  ),
3429
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3861
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3430
3862
  flex: 1,
3431
3863
  textAlign: "center",
3432
3864
  fontWeight: 600,
@@ -3434,58 +3866,65 @@ function SplitCardFormInner({
3434
3866
  color: "#262833",
3435
3867
  paddingRight: 80,
3436
3868
  ...bStyles.title
3437
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TitleContentSlot, { content: cardTitleContent }) })
3869
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
3438
3870
  ] }),
3439
- !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3871
+ !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3440
3872
  textAlign: "center",
3441
3873
  fontWeight: 600,
3442
3874
  fontSize: "1.1rem",
3443
3875
  padding: "0.5rem 0",
3444
3876
  color: resolvedTitleColor,
3877
+ // Keep the title at the very top on the vault path. The card-form slot
3878
+ // (-2) and AVS block (-1) are ordered below it but above the card form.
3879
+ order: vaultActive ? -3 : 0,
3445
3880
  ...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,
3881
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
3882
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3883
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3470
3884
  backgroundColor: cardInputBg,
3471
- borderTop: "none",
3472
- borderRight: `1px solid ${resolvedBorder}`,
3473
- borderBottom: `1px solid ${resolvedBorder}`,
3474
- borderLeft: `1px solid ${resolvedBorder}`,
3475
- borderBottomRightRadius: "8px",
3885
+ border: `1px solid ${resolvedBorder}`,
3886
+ borderTopLeftRadius: resolvedBorderRadius,
3887
+ borderTopRightRadius: resolvedBorderRadius,
3476
3888
  padding: "10px"
3477
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardCvcElement, { options: stripeElementStyle }) })
3889
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
3890
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex" }, children: [
3891
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3892
+ flex: 1,
3893
+ backgroundColor: cardInputBg,
3894
+ // Longhand only — mixing `border` shorthand with per-side
3895
+ // overrides triggers React's "shorthand vs longhand" warning
3896
+ // because render order isn't deterministic.
3897
+ borderTop: "none",
3898
+ borderRight: "none",
3899
+ borderBottom: `1px solid ${resolvedBorder}`,
3900
+ borderLeft: `1px solid ${resolvedBorder}`,
3901
+ borderBottomLeftRadius: resolvedBorderRadius,
3902
+ padding: "10px"
3903
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
3904
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3905
+ flex: 1,
3906
+ backgroundColor: cardInputBg,
3907
+ borderTop: "none",
3908
+ borderRight: `1px solid ${resolvedBorder}`,
3909
+ borderBottom: `1px solid ${resolvedBorder}`,
3910
+ borderLeft: `1px solid ${resolvedBorder}`,
3911
+ borderBottomRightRadius: resolvedBorderRadius,
3912
+ padding: "10px"
3913
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardCvcElement, { options: stripeElementStyle }) })
3914
+ ] })
3478
3915
  ] }),
3479
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
3916
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3480
3917
  backgroundColor: cardInputBg,
3481
3918
  border: `1px solid ${resolvedBorder}`,
3482
- borderRadius: "8px",
3919
+ borderRadius: resolvedBorderRadius,
3483
3920
  marginTop: "0.5rem",
3484
3921
  padding: "10px"
3485
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3922
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3486
3923
  "input",
3487
3924
  {
3488
3925
  className: "flopay-shared-input",
3926
+ id: "flopay-cc-name",
3927
+ name: "cc-name",
3489
3928
  placeholder: "Full Name on Card",
3490
3929
  autoComplete: "cc-name",
3491
3930
  value: fullName,
@@ -3502,32 +3941,32 @@ function SplitCardFormInner({
3502
3941
  }
3503
3942
  }
3504
3943
  ) }),
3505
- avsConfig && (() => {
3944
+ avsConfig && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
3506
3945
  const cc = selectedCountry;
3507
- const inputWrapStyle = (extraStyle) => ({
3946
+ const inputWrapStyle = (invalid = false) => ({
3508
3947
  backgroundColor: cardInputBg,
3509
- border: `1px solid ${resolvedBorder}`,
3510
- borderRadius: "8px",
3948
+ border: `1px solid ${avsBorderColor(invalid)}`,
3949
+ borderRadius: resolvedBorderRadius,
3511
3950
  marginTop: "0.5rem",
3512
- padding: "10px",
3513
- ...isButtons && extraStyle ? extraStyle : {}
3951
+ padding: "10px"
3514
3952
  });
3515
3953
  const inputFieldStyle = () => ({
3516
3954
  width: "100%",
3517
3955
  border: "none",
3518
3956
  outline: "none",
3519
3957
  background: "transparent",
3520
- ...sharedInputTypography,
3521
- ...isButtons && bStyles.nameInput ? bStyles.nameInput : {}
3958
+ ...sharedInputTypography
3522
3959
  });
3523
3960
  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)(
3961
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3962
+ (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
3963
  "input",
3527
3964
  {
3528
3965
  className: "flopay-shared-input",
3966
+ id: "flopay-billing-address-line1",
3967
+ name: "billing-address-line1",
3529
3968
  placeholder: "Street Address (e.g. 123 Main St)",
3530
- autoComplete: "address-line1",
3969
+ autoComplete: "billing address-line1",
3531
3970
  value: addressLine1,
3532
3971
  onChange: (e) => {
3533
3972
  addressLine1Ref.current = e.target.value;
@@ -3539,12 +3978,14 @@ function SplitCardFormInner({
3539
3978
  style: inputFieldStyle()
3540
3979
  }
3541
3980
  ) }),
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)(
3981
+ (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
3982
  "input",
3544
3983
  {
3545
3984
  className: "flopay-shared-input",
3985
+ id: "flopay-billing-address-line2",
3986
+ name: "billing-address-line2",
3546
3987
  placeholder: "Apt, Suite, Unit (optional)",
3547
- autoComplete: "address-line2",
3988
+ autoComplete: "billing address-line2",
3548
3989
  value: addressLine2,
3549
3990
  onChange: (e) => {
3550
3991
  addressLine2Ref.current = e.target.value;
@@ -3555,29 +3996,30 @@ function SplitCardFormInner({
3555
3996
  style: inputFieldStyle()
3556
3997
  }
3557
3998
  ) }),
3558
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
3999
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3559
4000
  display: "flex",
3560
4001
  gap: "0",
3561
4002
  marginTop: "0.5rem"
3562
4003
  }, children: [
3563
- (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4004
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3564
4005
  flex: 1,
3565
4006
  backgroundColor: cardInputBg,
3566
- borderTop: `1px solid ${resolvedBorder}`,
3567
- borderRight: `1px solid ${resolvedBorder}`,
3568
- borderBottom: `1px solid ${resolvedBorder}`,
3569
- borderLeft: `1px solid ${resolvedBorder}`,
4007
+ borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
4008
+ borderRight: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
4009
+ borderBottom: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
4010
+ borderLeft: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
3570
4011
  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)(
4012
+ borderTopLeftRadius: resolvedBorderRadius,
4013
+ borderBottomLeftRadius: resolvedBorderRadius,
4014
+ ...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
4015
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3576
4016
  "input",
3577
4017
  {
3578
4018
  className: "flopay-shared-input",
4019
+ id: "flopay-billing-city",
4020
+ name: "billing-city",
3579
4021
  placeholder: "City",
3580
- autoComplete: "address-level2",
4022
+ autoComplete: "billing address-level2",
3581
4023
  value: city,
3582
4024
  onChange: (e) => {
3583
4025
  cityRef.current = e.target.value;
@@ -3589,39 +4031,42 @@ function SplitCardFormInner({
3589
4031
  style: inputFieldStyle()
3590
4032
  }
3591
4033
  ) }),
3592
- (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4034
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3593
4035
  flex: 1,
3594
4036
  backgroundColor: cardInputBg,
3595
- border: `1px solid ${resolvedBorder}`,
4037
+ border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
3596
4038
  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)(
4039
+ borderTopRightRadius: resolvedBorderRadius,
4040
+ borderBottomRightRadius: resolvedBorderRadius,
4041
+ ...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
4042
+ }, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3602
4043
  "select",
3603
4044
  {
4045
+ id: "flopay-billing-state",
4046
+ name: "billing-state",
3604
4047
  value: stateValue,
3605
4048
  onChange: (e) => {
3606
4049
  stateRef.current = e.target.value;
3607
4050
  setStateValue(e.target.value);
3608
4051
  },
3609
4052
  disabled: isSubmitting,
3610
- autoComplete: "address-level1",
4053
+ autoComplete: "billing address-level1",
3611
4054
  required: true,
3612
4055
  "data-testid": "flopay-state",
3613
4056
  style: { ...inputFieldStyle(), cursor: "pointer" },
3614
4057
  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))
4058
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
4059
+ stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: s.code, children: s.name }, s.code))
3617
4060
  ]
3618
4061
  }
3619
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4062
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3620
4063
  "input",
3621
4064
  {
3622
4065
  className: "flopay-shared-input",
4066
+ id: "flopay-billing-state",
4067
+ name: "billing-state",
3623
4068
  placeholder: (0, import_shared5.getStateLabel)(cc),
3624
- autoComplete: "address-level1",
4069
+ autoComplete: "billing address-level1",
3625
4070
  value: stateValue,
3626
4071
  onChange: (e) => {
3627
4072
  stateRef.current = e.target.value;
@@ -3634,13 +4079,13 @@ function SplitCardFormInner({
3634
4079
  }
3635
4080
  ) })
3636
4081
  ] }),
3637
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4082
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
3638
4083
  display: "flex",
3639
4084
  flexDirection: avsLayoutProp === "column" ? "column" : "row",
3640
4085
  gap: avsLayoutProp === "column" ? "0.5rem" : "0",
3641
4086
  marginTop: "0.5rem"
3642
4087
  }, children: [
3643
- (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4088
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3644
4089
  flex: avsLayoutProp === "row" ? 1 : void 0,
3645
4090
  backgroundColor: cardInputBg,
3646
4091
  borderTop: `1px solid ${resolvedBorder}`,
@@ -3648,11 +4093,12 @@ function SplitCardFormInner({
3648
4093
  borderBottom: `1px solid ${resolvedBorder}`,
3649
4094
  borderLeft: `1px solid ${resolvedBorder}`,
3650
4095
  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)(
4096
+ ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
4097
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3654
4098
  "select",
3655
4099
  {
4100
+ id: "flopay-billing-country",
4101
+ name: "billing-country",
3656
4102
  value: selectedCountry,
3657
4103
  onChange: (e) => {
3658
4104
  selectedCountryRef.current = e.target.value;
@@ -3662,45 +4108,66 @@ function SplitCardFormInner({
3662
4108
  setStateValue("");
3663
4109
  },
3664
4110
  disabled: isSubmitting,
3665
- autoComplete: "country",
4111
+ autoComplete: "billing country",
3666
4112
  "data-testid": "flopay-country",
3667
4113
  style: { ...inputFieldStyle(), cursor: "pointer" },
3668
- children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: c.code, children: [
4114
+ children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("option", { value: c.code, children: [
3669
4115
  c.flag,
3670
4116
  " ",
3671
4117
  c.name
3672
4118
  ] }, c.code))
3673
4119
  }
3674
4120
  ) }),
3675
- (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4121
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
3676
4122
  flex: avsLayoutProp === "row" ? 1 : void 0,
3677
4123
  backgroundColor: cardInputBg,
3678
- border: `1px solid ${resolvedBorder}`,
4124
+ border: `1px solid ${zipBorderColor}`,
3679
4125
  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)(
4126
+ ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
4127
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3683
4128
  "input",
3684
4129
  {
3685
4130
  className: "flopay-shared-input",
4131
+ id: "flopay-billing-postal-code",
4132
+ name: "billing-postal-code",
3686
4133
  placeholder: (0, import_shared5.getPostalCodeLabel)(selectedCountry),
3687
- autoComplete: "postal-code",
4134
+ autoComplete: "billing postal-code",
3688
4135
  value: zipCode,
3689
4136
  onChange: (e) => {
3690
4137
  zipCodeRef.current = e.target.value;
3691
4138
  setZipCode(e.target.value);
3692
4139
  onZipChange?.(e.target.value);
3693
4140
  },
4141
+ onBlur: () => setZipTouched(true),
3694
4142
  disabled: isSubmitting,
3695
- required: true,
4143
+ required: postalCodeState.required,
4144
+ "aria-invalid": showPostcodeError || void 0,
4145
+ "aria-describedby": showPostcodeError ? "flopay-billing-postal-code-error" : void 0,
3696
4146
  "data-testid": "flopay-zip",
3697
4147
  style: inputFieldStyle()
3698
4148
  }
3699
4149
  ) })
3700
- ] })
4150
+ ] }),
4151
+ showPostcodeError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4152
+ "div",
4153
+ {
4154
+ id: "flopay-billing-postal-code-error",
4155
+ role: "alert",
4156
+ "data-testid": "flopay-zip-error",
4157
+ style: {
4158
+ marginTop: "0.375rem",
4159
+ color: resolvedDangerColor,
4160
+ ...sharedInputTypography,
4161
+ fontSize: "0.75rem"
4162
+ },
4163
+ children: postalCodeState.empty ? `${(0, import_shared5.getPostalCodeLabel)(cc)} is required` : malformedPostcodeMessage(cc)
4164
+ }
4165
+ )
3701
4166
  ] });
3702
- })(),
3703
- displayError && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
4167
+ })() }),
4168
+ vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
4169
+ vaultActive && vaultCardFieldsNode,
4170
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
3704
4171
  margin: "0.75rem 0",
3705
4172
  padding: "0.625rem 0.875rem",
3706
4173
  background: "#FEF2F2",
@@ -3714,15 +4181,21 @@ function SplitCardFormInner({
3714
4181
  gap: "0.5rem",
3715
4182
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3716
4183
  }, 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" }) }),
4184
+ /* @__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
4185
  displayError
3719
4186
  ] }),
3720
- children ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4187
+ !vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3721
4188
  "button",
3722
4189
  {
3723
4190
  type: "submit",
3724
4191
  disabled: !formReady || isSubmitting,
3725
4192
  "data-testid": "flopay-submit",
4193
+ onMouseEnter: (e) => {
4194
+ if (formReady && !isSubmitting) e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4195
+ },
4196
+ onMouseLeave: (e) => {
4197
+ e.currentTarget.style.backgroundColor = bStyles.submitButton?.backgroundColor ?? resolvedPrimaryColor;
4198
+ },
3726
4199
  style: {
3727
4200
  width: "100%",
3728
4201
  padding: "0.875rem",
@@ -3735,11 +4208,12 @@ function SplitCardFormInner({
3735
4208
  fontWeight: 600,
3736
4209
  cursor: !formReady || isSubmitting ? "not-allowed" : "pointer",
3737
4210
  opacity: !formReady || isSubmitting ? 0.5 : 1,
4211
+ transition: "background-color 0.15s",
3738
4212
  ...bStyles.submitButton
3739
4213
  },
3740
4214
  children: isSubmitting ? "PROCESSING..." : submitLabel
3741
4215
  }
3742
- )
4216
+ ))
3743
4217
  ] });
3744
4218
  const gateDebugStyle = {
3745
4219
  margin: 0,
@@ -3755,9 +4229,9 @@ function SplitCardFormInner({
3755
4229
  const renderDirectPaypalGateDebug = (testId) => {
3756
4230
  if (!debug) return null;
3757
4231
  if (!showPayPal || !directPaypalConfigured) {
3758
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
4232
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
3759
4233
  }
3760
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4234
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3761
4235
  "FloPay/DirectPayPal-debug (parent gate)",
3762
4236
  ` showPayPal=${showPayPal}`,
3763
4237
  ` directPaypalConfigured=${directPaypalConfigured}`,
@@ -3770,9 +4244,9 @@ function SplitCardFormInner({
3770
4244
  const renderStripeGateDebug = (testId) => {
3771
4245
  if (!debug) return null;
3772
4246
  if (!showStripe || !stripeInstance) {
3773
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
4247
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
3774
4248
  }
3775
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4249
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
3776
4250
  "FloPay/Stripe-debug (parent gate)",
3777
4251
  ` showStripe=${showStripe}`,
3778
4252
  ` currency=${currency}`,
@@ -3801,11 +4275,11 @@ function SplitCardFormInner({
3801
4275
  const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
3802
4276
  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
4277
  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)(
4278
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4279
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4280
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4281
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid" }, children: [
4282
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3809
4283
  "div",
3810
4284
  {
3811
4285
  "data-testid": "flopay-buttons-panel",
@@ -3822,8 +4296,8 @@ function SplitCardFormInner({
3822
4296
  children: [
3823
4297
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
3824
4298
  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)(
4299
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4300
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3827
4301
  "div",
3828
4302
  {
3829
4303
  "data-testid": "flopay-paypal-direct-retry-notice",
@@ -3839,7 +4313,7 @@ function SplitCardFormInner({
3839
4313
  children: "Please confirm your PayPal payment to complete checkout."
3840
4314
  }
3841
4315
  ),
3842
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4316
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3843
4317
  DirectPayPalButton,
3844
4318
  {
3845
4319
  sessionId,
@@ -3865,7 +4339,7 @@ function SplitCardFormInner({
3865
4339
  paypalDirectRetry?.orderId ?? "fresh"
3866
4340
  )
3867
4341
  ] }),
3868
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4342
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3869
4343
  PayPalButtonInner,
3870
4344
  {
3871
4345
  sessionId,
@@ -3879,10 +4353,10 @@ function SplitCardFormInner({
3879
4353
  onDecline,
3880
4354
  runBeforeButtonClick,
3881
4355
  onLoadStateChange: setPaypalLoadState,
3882
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4356
+ placeholderBorderRadius: buttonBorderRadius
3883
4357
  }
3884
4358
  ) }),
3885
- shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4359
+ shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3886
4360
  WalletButtonInner,
3887
4361
  {
3888
4362
  sessionId,
@@ -3896,10 +4370,10 @@ function SplitCardFormInner({
3896
4370
  onDecline,
3897
4371
  runBeforeButtonClick,
3898
4372
  onLoadStateChange: setWalletLoadState,
3899
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4373
+ placeholderBorderRadius: buttonBorderRadius
3900
4374
  }
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)(
4375
+ ) }) : 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,
4376
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3903
4377
  StripePaymentElementInner,
3904
4378
  {
3905
4379
  sessionId,
@@ -3927,11 +4401,11 @@ function SplitCardFormInner({
3927
4401
  backgroundColor: bStyles.cardButton?.backgroundColor,
3928
4402
  borderColor: bStyles.cardInputBorder,
3929
4403
  textColor: bStyles.cardButton?.color,
3930
- borderRadius: bStyles.cardButton?.borderRadius
4404
+ borderRadius: buttonBorderRadius
3931
4405
  }
3932
4406
  }
3933
4407
  ),
3934
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4408
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3935
4409
  "button",
3936
4410
  {
3937
4411
  type: "button",
@@ -3959,7 +4433,8 @@ function SplitCardFormInner({
3959
4433
  themeBundle,
3960
4434
  resolvedPrimaryColor,
3961
4435
  resolvedBorderRadius,
3962
- submitButtonStyle: bStyles.submitButton
4436
+ submitButtonStyle: bStyles.submitButton,
4437
+ explicitPrimaryColor: appearanceVars?.colorPrimary
3963
4438
  }),
3964
4439
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
3965
4440
  fontWeight: 600,
@@ -3968,20 +4443,28 @@ function SplitCardFormInner({
3968
4443
  alignItems: "center",
3969
4444
  justifyContent: "center",
3970
4445
  gap: "0.625rem",
3971
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
4446
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
3972
4447
  position: "relative",
3973
4448
  opacity: isSubmitting ? 0.6 : 1
3974
4449
  },
4450
+ onMouseEnter: (e) => {
4451
+ if (!isSubmitting && (themeBundle || appearanceVars?.colorPrimary)) {
4452
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
4453
+ }
4454
+ },
4455
+ onMouseLeave: (e) => {
4456
+ if (themeBundle || appearanceVars?.colorPrimary) e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
4457
+ },
3975
4458
  onMouseDown: (e) => {
3976
4459
  e.currentTarget.style.transform = "scale(0.985)";
3977
4460
  },
3978
4461
  onMouseUp: (e) => {
3979
4462
  e.currentTarget.style.transform = "scale(1)";
3980
4463
  },
3981
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CardButtonContentSlot, { content: cardButtonContent })
4464
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
3982
4465
  }
3983
4466
  ),
3984
- displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
4467
+ displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
3985
4468
  margin: "0.25rem 0",
3986
4469
  padding: "0.625rem 0.875rem",
3987
4470
  background: "#FEF2F2",
@@ -3995,33 +4478,33 @@ function SplitCardFormInner({
3995
4478
  gap: "0.5rem",
3996
4479
  ...bStyles.errorBanner ? bStyles.errorBanner : {}
3997
4480
  }, 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" }) }),
4481
+ /* @__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
4482
  displayError
4000
4483
  ] })
4001
4484
  ]
4002
4485
  }
4003
4486
  ),
4004
- showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4487
+ showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4005
4488
  gridArea: "1 / 1",
4006
4489
  ...cardAnim ? { animation: cardAnim } : {},
4007
4490
  ...viewState === "collapsing" ? { pointerEvents: "none" } : {}
4008
4491
  }, children: cardFormBlock }),
4009
- showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4492
+ showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4010
4493
  gridArea: "1 / 1",
4011
4494
  ...apmAnim ? { animation: apmAnim } : {},
4012
4495
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
4013
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4496
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4014
4497
  backgroundColor: cardBg,
4015
4498
  borderRadius: containerRadius,
4016
4499
  ...containerOverrides,
4017
4500
  padding: containerPadding
4018
4501
  }, children: [
4019
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4502
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4020
4503
  display: "flex",
4021
4504
  alignItems: "center",
4022
4505
  padding: "0.75rem 0 0.625rem"
4023
4506
  }, children: [
4024
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4507
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4025
4508
  "button",
4026
4509
  {
4027
4510
  type: "button",
@@ -4044,7 +4527,7 @@ function SplitCardFormInner({
4044
4527
  },
4045
4528
  "aria-label": "Back to payment methods",
4046
4529
  children: [
4047
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
4530
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
4048
4531
  display: "inline-flex",
4049
4532
  alignItems: "center",
4050
4533
  justifyContent: "center",
@@ -4054,12 +4537,12 @@ function SplitCardFormInner({
4054
4537
  backgroundColor: "#f3f4f6",
4055
4538
  transition: "background-color 0.15s",
4056
4539
  ...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 })
4540
+ }, 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" }) }) }),
4541
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4059
4542
  ]
4060
4543
  }
4061
4544
  ),
4062
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4545
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4063
4546
  flex: 1,
4064
4547
  textAlign: "center",
4065
4548
  fontWeight: 600,
@@ -4069,12 +4552,12 @@ function SplitCardFormInner({
4069
4552
  ...bStyles.title
4070
4553
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
4071
4554
  ] }),
4072
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4555
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4073
4556
  import_react_stripe_js.Elements,
4074
4557
  {
4075
4558
  stripe: stripeInstance,
4076
4559
  options: apmInlineOptions,
4077
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4560
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4078
4561
  StripeMethodInlineForm,
4079
4562
  {
4080
4563
  method: expandedApmMethod,
@@ -4092,7 +4575,8 @@ function SplitCardFormInner({
4092
4575
  isProcessing: isSubmitting,
4093
4576
  submitButtonColor: resolvedPrimaryColor,
4094
4577
  submitButtonBorderRadius: resolvedBorderRadius,
4095
- submitButtonStyle: bStyles.submitButton
4578
+ submitButtonStyle: bStyles.submitButton,
4579
+ errorText: displayError
4096
4580
  }
4097
4581
  )
4098
4582
  },
@@ -4103,24 +4587,24 @@ function SplitCardFormInner({
4103
4587
  ] });
4104
4588
  }
4105
4589
  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: {
4590
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4591
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4592
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4593
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4110
4594
  ...apmAnim ? { animation: apmAnim } : {},
4111
4595
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
4112
- }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4596
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4113
4597
  backgroundColor: cardBg,
4114
4598
  borderRadius: containerRadius,
4115
4599
  ...containerOverrides,
4116
4600
  padding: containerPadding
4117
4601
  }, children: [
4118
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4602
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4119
4603
  display: "flex",
4120
4604
  alignItems: "center",
4121
4605
  padding: "0.75rem 0 0.625rem"
4122
4606
  }, children: [
4123
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4607
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4124
4608
  "button",
4125
4609
  {
4126
4610
  type: "button",
@@ -4143,7 +4627,7 @@ function SplitCardFormInner({
4143
4627
  },
4144
4628
  "aria-label": "Back to payment methods",
4145
4629
  children: [
4146
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
4630
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
4147
4631
  display: "inline-flex",
4148
4632
  alignItems: "center",
4149
4633
  justifyContent: "center",
@@ -4153,12 +4637,12 @@ function SplitCardFormInner({
4153
4637
  backgroundColor: "#f3f4f6",
4154
4638
  transition: "background-color 0.15s",
4155
4639
  ...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 })
4640
+ }, 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" }) }) }),
4641
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4158
4642
  ]
4159
4643
  }
4160
4644
  ),
4161
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
4645
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4162
4646
  flex: 1,
4163
4647
  textAlign: "center",
4164
4648
  fontWeight: 600,
@@ -4168,12 +4652,12 @@ function SplitCardFormInner({
4168
4652
  ...bStyles.title
4169
4653
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
4170
4654
  ] }),
4171
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4655
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4172
4656
  import_react_stripe_js.Elements,
4173
4657
  {
4174
4658
  stripe: stripeInstance,
4175
4659
  options: apmInlineOptions,
4176
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4660
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4177
4661
  StripeMethodInlineForm,
4178
4662
  {
4179
4663
  method: expandedApmMethod,
@@ -4191,7 +4675,8 @@ function SplitCardFormInner({
4191
4675
  isProcessing: isSubmitting,
4192
4676
  submitButtonColor: resolvedPrimaryColor,
4193
4677
  submitButtonBorderRadius: resolvedBorderRadius,
4194
- submitButtonStyle: bStyles.submitButton
4678
+ submitButtonStyle: bStyles.submitButton,
4679
+ errorText: displayError
4195
4680
  }
4196
4681
  )
4197
4682
  },
@@ -4200,14 +4685,14 @@ function SplitCardFormInner({
4200
4685
  ] }) })
4201
4686
  ] });
4202
4687
  }
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: [
4688
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4689
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4690
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4691
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
4207
4692
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
4208
4693
  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)(
4694
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4695
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4211
4696
  "div",
4212
4697
  {
4213
4698
  "data-testid": "flopay-paypal-direct-retry-notice-default",
@@ -4223,7 +4708,7 @@ function SplitCardFormInner({
4223
4708
  children: "Please confirm your PayPal payment to complete checkout."
4224
4709
  }
4225
4710
  ),
4226
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4711
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4227
4712
  DirectPayPalButton,
4228
4713
  {
4229
4714
  sessionId,
@@ -4249,7 +4734,7 @@ function SplitCardFormInner({
4249
4734
  paypalDirectRetry?.orderId ?? "fresh"
4250
4735
  )
4251
4736
  ] }),
4252
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4737
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4253
4738
  PayPalButtonInner,
4254
4739
  {
4255
4740
  sessionId,
@@ -4263,10 +4748,10 @@ function SplitCardFormInner({
4263
4748
  onDecline,
4264
4749
  runBeforeButtonClick,
4265
4750
  onLoadStateChange: setPaypalLoadState,
4266
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4751
+ placeholderBorderRadius: buttonBorderRadius
4267
4752
  }
4268
4753
  ) }),
4269
- shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4754
+ shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4270
4755
  WalletButtonInner,
4271
4756
  {
4272
4757
  sessionId,
@@ -4280,10 +4765,10 @@ function SplitCardFormInner({
4280
4765
  onDecline,
4281
4766
  runBeforeButtonClick,
4282
4767
  onLoadStateChange: setWalletLoadState,
4283
- placeholderBorderRadius: bStyles.cardButton?.borderRadius ?? resolvedBorderRadius
4768
+ placeholderBorderRadius: buttonBorderRadius
4284
4769
  }
4285
4770
  ) }),
4286
- shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4771
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4287
4772
  StripePaymentElementInner,
4288
4773
  {
4289
4774
  sessionId,
@@ -4311,12 +4796,12 @@ function SplitCardFormInner({
4311
4796
  backgroundColor: bStyles.cardButton?.backgroundColor,
4312
4797
  borderColor: bStyles.cardInputBorder,
4313
4798
  textColor: bStyles.cardButton?.color,
4314
- borderRadius: bStyles.cardButton?.borderRadius
4799
+ borderRadius: buttonBorderRadius
4315
4800
  }
4316
4801
  }
4317
4802
  )
4318
4803
  ] }),
4319
- showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: {
4804
+ showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4320
4805
  display: "flex",
4321
4806
  alignItems: "center",
4322
4807
  gap: "0.75rem",
@@ -4324,9 +4809,9 @@ function SplitCardFormInner({
4324
4809
  color: "#999",
4325
4810
  fontSize: "0.85rem"
4326
4811
  }, 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" } })
4812
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
4813
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "or pay with card" }),
4814
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
4330
4815
  ] }),
4331
4816
  showStripe && cardFormBlock
4332
4817
  ] });
@@ -4369,6 +4854,210 @@ function getRedirectResultFromCheckoutProcessError(error) {
4369
4854
  paymentMethodId: error.paymentMethodId
4370
4855
  };
4371
4856
  }
4857
+ function isTerminalAutoCheckoutThreeDsOutcome(outcome) {
4858
+ return outcome.status === "succeeded" || outcome.status === "declined";
4859
+ }
4860
+ async function runAutoCheckoutThreeDsChallenge(input) {
4861
+ if (typeof document === "undefined" || typeof window === "undefined") {
4862
+ throw new import_shared7.FloPayError("3DS challenge requires a browser environment.", "api_error", {
4863
+ code: "three_ds_no_window"
4864
+ });
4865
+ }
4866
+ if (input.signal?.aborted) {
4867
+ throw new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
4868
+ code: "three_ds_aborted"
4869
+ });
4870
+ }
4871
+ const CHALLENGE_TIMEOUT_MS = 3e5;
4872
+ const CHALLENGE_POLL_INTERVAL_MS = 1e3;
4873
+ const COMPLETE_REQUEST_TIMEOUT_MS = 15e3;
4874
+ const completionEndpoint = `${input.billingApiUrl.replace(/\/$/, "")}/v1/checkouts/sessions/${encodeURIComponent(
4875
+ input.sessionId
4876
+ )}/3ds/complete`;
4877
+ const completeThreeDs = async () => {
4878
+ const controller = new AbortController();
4879
+ const onParentAbort = () => controller.abort();
4880
+ if (input.signal?.aborted) {
4881
+ controller.abort();
4882
+ } else {
4883
+ input.signal?.addEventListener("abort", onParentAbort);
4884
+ }
4885
+ const requestTimeout = window.setTimeout(() => controller.abort(), COMPLETE_REQUEST_TIMEOUT_MS);
4886
+ try {
4887
+ const response = await fetch(completionEndpoint, {
4888
+ method: "POST",
4889
+ headers: {
4890
+ "x-checkout-session-token": input.nonce,
4891
+ "content-type": "application/json"
4892
+ },
4893
+ body: "{}",
4894
+ signal: controller.signal
4895
+ });
4896
+ if (!response.ok) {
4897
+ return { status: "unknown" };
4898
+ }
4899
+ const json = await response.json().catch(() => null);
4900
+ return coerceThreeDsOutcome(json);
4901
+ } catch {
4902
+ return { status: "unknown" };
4903
+ } finally {
4904
+ window.clearTimeout(requestTimeout);
4905
+ input.signal?.removeEventListener("abort", onParentAbort);
4906
+ }
4907
+ };
4908
+ const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4909
+ const backdrop = document.createElement("div");
4910
+ backdrop.setAttribute("data-flopay-auto-3ds-overlay", "1");
4911
+ backdrop.setAttribute("role", "dialog");
4912
+ backdrop.setAttribute("aria-modal", "true");
4913
+ backdrop.setAttribute("aria-label", "Card authentication");
4914
+ backdrop.style.cssText = [
4915
+ "position:fixed",
4916
+ "inset:0",
4917
+ "z-index:2147483647",
4918
+ "background:rgba(15,23,42,0.6)",
4919
+ "display:flex",
4920
+ "align-items:center",
4921
+ "justify-content:center",
4922
+ "padding:16px"
4923
+ ].join(";");
4924
+ const frame = document.createElement("iframe");
4925
+ frame.setAttribute("title", "Card authentication");
4926
+ frame.setAttribute("allow", "payment");
4927
+ frame.tabIndex = 0;
4928
+ frame.style.cssText = [
4929
+ "width:min(100%,460px)",
4930
+ "height:min(100%,640px)",
4931
+ "border:0",
4932
+ "border-radius:12px",
4933
+ "background:#fff",
4934
+ "box-shadow:0 12px 30px rgba(0,0,0,0.35)"
4935
+ ].join(";");
4936
+ frame.src = input.nextActionRedirectUrl;
4937
+ backdrop.appendChild(frame);
4938
+ document.body.appendChild(backdrop);
4939
+ frame.focus();
4940
+ let expectedReturnOrigin = null;
4941
+ try {
4942
+ expectedReturnOrigin = new URL(input.billingApiUrl, window.location.href).origin;
4943
+ } catch {
4944
+ expectedReturnOrigin = null;
4945
+ }
4946
+ try {
4947
+ const polledOutcome = await new Promise((resolve, reject) => {
4948
+ let settled = false;
4949
+ let timer = 0;
4950
+ let pollTimer = 0;
4951
+ let loadPollTimer = 0;
4952
+ let pollInFlight = false;
4953
+ const cleanup = () => {
4954
+ window.clearTimeout(timer);
4955
+ window.clearInterval(pollTimer);
4956
+ window.clearTimeout(loadPollTimer);
4957
+ window.removeEventListener("message", listener);
4958
+ frame.removeEventListener("load", onFrameLoad);
4959
+ input.signal?.removeEventListener("abort", onAbort);
4960
+ };
4961
+ const maybeResolveFromBackend = async () => {
4962
+ if (settled || pollInFlight) return;
4963
+ pollInFlight = true;
4964
+ try {
4965
+ const outcome = await completeThreeDs();
4966
+ if (settled || !isTerminalAutoCheckoutThreeDsOutcome(outcome)) return;
4967
+ settled = true;
4968
+ cleanup();
4969
+ resolve(outcome);
4970
+ } finally {
4971
+ pollInFlight = false;
4972
+ }
4973
+ };
4974
+ const onFrameLoad = () => {
4975
+ window.clearTimeout(loadPollTimer);
4976
+ loadPollTimer = window.setTimeout(() => {
4977
+ void maybeResolveFromBackend();
4978
+ }, 250);
4979
+ };
4980
+ const onAbort = () => {
4981
+ if (settled) return;
4982
+ settled = true;
4983
+ cleanup();
4984
+ reject(
4985
+ new import_shared7.FloPayError("Card authentication was cancelled.", "api_error", {
4986
+ code: "three_ds_aborted"
4987
+ })
4988
+ );
4989
+ };
4990
+ const listener = (event) => {
4991
+ if (event.source !== frame.contentWindow) return;
4992
+ if (expectedReturnOrigin && event.origin !== expectedReturnOrigin) return;
4993
+ const data = event.data;
4994
+ if (!data || typeof data !== "object") return;
4995
+ const record = data;
4996
+ if (record["source"] !== "flopay-vault-3ds-return") return;
4997
+ if (settled) return;
4998
+ settled = true;
4999
+ cleanup();
5000
+ resolve(null);
5001
+ };
5002
+ timer = window.setTimeout(() => {
5003
+ if (settled) return;
5004
+ settled = true;
5005
+ cleanup();
5006
+ reject(
5007
+ new import_shared7.FloPayError("Card authentication timed out.", "api_error", {
5008
+ code: "three_ds_timeout"
5009
+ })
5010
+ );
5011
+ }, CHALLENGE_TIMEOUT_MS);
5012
+ pollTimer = window.setInterval(() => {
5013
+ void maybeResolveFromBackend();
5014
+ }, CHALLENGE_POLL_INTERVAL_MS);
5015
+ frame.addEventListener("load", onFrameLoad);
5016
+ window.addEventListener("message", listener);
5017
+ input.signal?.addEventListener("abort", onAbort);
5018
+ if (input.signal?.aborted) onAbort();
5019
+ });
5020
+ if (polledOutcome) {
5021
+ return polledOutcome;
5022
+ }
5023
+ return await completeThreeDs();
5024
+ } finally {
5025
+ backdrop.parentNode?.removeChild(backdrop);
5026
+ if (previousFocus?.isConnected) {
5027
+ previousFocus.focus();
5028
+ }
5029
+ }
5030
+ }
5031
+ function coerceThreeDsOutcome(json) {
5032
+ if (!json || typeof json !== "object") return { status: "unknown" };
5033
+ const status = typeof json["status"] === "string" ? json["status"] : "unknown";
5034
+ const providerIntentId = typeof json["providerIntentId"] === "string" ? json["providerIntentId"] : null;
5035
+ switch (status) {
5036
+ case "succeeded":
5037
+ return { status: "succeeded", providerIntentId };
5038
+ case "declined":
5039
+ return {
5040
+ status: "declined",
5041
+ providerIntentId,
5042
+ declineReason: typeof json["declineReason"] === "string" ? json["declineReason"] : null,
5043
+ gatewayDeclineReason: typeof json["gatewayDeclineReason"] === "string" ? json["gatewayDeclineReason"] : null
5044
+ };
5045
+ case "requires_action":
5046
+ return {
5047
+ status: "requires_action",
5048
+ providerIntentId,
5049
+ nextActionRedirectUrl: typeof json["nextActionRedirectUrl"] === "string" ? json["nextActionRedirectUrl"] : null
5050
+ };
5051
+ case "pending":
5052
+ return { status: "pending", providerIntentId };
5053
+ case "timeout":
5054
+ return { status: "timeout", providerIntentId };
5055
+ case "no_attempt":
5056
+ return { status: "no_attempt" };
5057
+ default:
5058
+ return { status: "unknown" };
5059
+ }
5060
+ }
4372
5061
  function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
4373
5062
  const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
4374
5063
  const rawMessage = error?.message ?? fallbackMessage;
@@ -4810,7 +5499,7 @@ async function loadSavedPaymentProviders({
4810
5499
  }
4811
5500
 
4812
5501
  // src/flopay-checkout.tsx
4813
- var import_jsx_runtime7 = require("react/jsx-runtime");
5502
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4814
5503
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
4815
5504
  var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
4816
5505
  var sessionInflightMap = /* @__PURE__ */ new Map();
@@ -4859,6 +5548,36 @@ function clearPayPalResumeState() {
4859
5548
  console.warn("[FloPayCheckout] Failed to clear PayPal resume state.", error);
4860
5549
  }
4861
5550
  }
5551
+ function readCachedInlineSession(cacheKey) {
5552
+ if (!canUseStorage()) return null;
5553
+ const raw = window.sessionStorage.getItem(cacheKey);
5554
+ if (!raw) return null;
5555
+ try {
5556
+ const parsed = JSON.parse(raw);
5557
+ if (parsed && typeof parsed.sid === "string" && parsed.sid) {
5558
+ return { sid: parsed.sid, nonce: typeof parsed.nonce === "string" ? parsed.nonce : void 0 };
5559
+ }
5560
+ return null;
5561
+ } catch {
5562
+ return { sid: raw };
5563
+ }
5564
+ }
5565
+ function persistCachedInlineSession(cacheKey, sid, nonce) {
5566
+ if (!canUseStorage()) return;
5567
+ try {
5568
+ window.sessionStorage.setItem(cacheKey, JSON.stringify(nonce ? { sid, nonce } : { sid }));
5569
+ } catch (error) {
5570
+ console.warn("[FloPayCheckout] Failed to persist checkout session cache.", error);
5571
+ }
5572
+ }
5573
+ function clearCachedInlineSession(cacheKey) {
5574
+ if (!canUseStorage()) return;
5575
+ try {
5576
+ window.sessionStorage.removeItem(cacheKey);
5577
+ } catch (error) {
5578
+ console.warn("[FloPayCheckout] Failed to clear checkout session cache.", error);
5579
+ }
5580
+ }
4862
5581
  function clearPayPalRedirectParams() {
4863
5582
  if (typeof window === "undefined") return;
4864
5583
  const url = new URL(window.location.href);
@@ -4917,6 +5636,8 @@ function FloPayCheckout({
4917
5636
  onButtonClick,
4918
5637
  onBeforeButtonClick,
4919
5638
  enableAVS,
5639
+ cardFieldOrder,
5640
+ cardPreFormSlot,
4920
5641
  avsLayout,
4921
5642
  submitLabel,
4922
5643
  className,
@@ -4928,41 +5649,41 @@ function FloPayCheckout({
4928
5649
  onSessionCompleted
4929
5650
  }) {
4930
5651
  const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
4931
- const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
5652
+ const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
4932
5653
  const appearance = appearanceOverride ?? themeBundle?.appearance;
4933
5654
  const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
4934
5655
  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 ?? "");
5656
+ const [unified, setUnified] = (0, import_react10.useState)(null);
5657
+ const [flopay, setFloPay] = (0, import_react10.useState)(null);
5658
+ const flopayRef = (0, import_react10.useRef)(null);
5659
+ const [paypalFlopay, setPaypalFloPay] = (0, import_react10.useState)(null);
5660
+ const paypalFlopayRef = (0, import_react10.useRef)(null);
5661
+ const [session, setSession] = (0, import_react10.useState)(null);
5662
+ const [resolvedSessionId, setResolvedSessionId] = (0, import_react10.useState)(sessionIdProp ?? "");
4942
5663
  const activeSessionId = sessionIdProp ?? resolvedSessionId;
4943
5664
  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);
5665
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
5666
+ const [loadError, setLoadError] = (0, import_react10.useState)(null);
5667
+ const [currentMode, setCurrentMode] = (0, import_react10.useState)("full");
5668
+ const [confirmProcessing, setConfirmProcessing] = (0, import_react10.useState)(false);
5669
+ const [modeError, setModeError] = (0, import_react10.useState)(initialErrorMessage);
5670
+ const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react10.useState)(null);
5671
+ const [modeOverlayError, setModeOverlayError] = (0, import_react10.useState)(null);
5672
+ const [createSessionPatch, setCreateSessionPatch] = (0, import_react10.useState)(void 0);
5673
+ const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react10.useState)("");
5674
+ const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react10.useState)(false);
5675
+ const autoCheckoutAttempted = (0, import_react10.useRef)(false);
5676
+ const paypalResumeAttempted = (0, import_react10.useRef)(false);
5677
+ const savedPaymentKeysRef = (0, import_react10.useRef)(null);
5678
+ const onCompleteRef = (0, import_react10.useRef)(onComplete);
4958
5679
  onCompleteRef.current = onComplete;
4959
- const onErrorRef = (0, import_react9.useRef)(onError);
5680
+ const onErrorRef = (0, import_react10.useRef)(onError);
4960
5681
  onErrorRef.current = onError;
4961
- const onDeclineRef = (0, import_react9.useRef)(onDecline);
5682
+ const onDeclineRef = (0, import_react10.useRef)(onDecline);
4962
5683
  onDeclineRef.current = onDecline;
4963
- const onSessionCompletedRef = (0, import_react9.useRef)(onSessionCompleted);
5684
+ const onSessionCompletedRef = (0, import_react10.useRef)(onSessionCompleted);
4964
5685
  onSessionCompletedRef.current = onSessionCompleted;
4965
- (0, import_react9.useEffect)(() => {
5686
+ (0, import_react10.useEffect)(() => {
4966
5687
  console.info("[FloPay] Checkout initialized", {
4967
5688
  sdk_version: import_shared8.SDK_VERSION,
4968
5689
  checkout_type: checkoutType,
@@ -4970,40 +5691,40 @@ function FloPayCheckout({
4970
5691
  billing_api_url: resolvedBillingUrl
4971
5692
  });
4972
5693
  }, [checkoutLayout, checkoutType, resolvedBillingUrl]);
4973
- const baseCreateSessionHash = (0, import_react9.useMemo)(
5694
+ const baseCreateSessionHash = (0, import_react10.useMemo)(
4974
5695
  () => createSessionParams ? hashCreateParams(createSessionParams) : "",
4975
5696
  [createSessionParams]
4976
5697
  );
4977
- const activeCreateSessionPatch = (0, import_react9.useMemo)(
5698
+ const activeCreateSessionPatch = (0, import_react10.useMemo)(
4978
5699
  () => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
4979
5700
  [createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
4980
5701
  );
4981
- const effectiveCreateSessionBase = (0, import_react9.useMemo)(
5702
+ const effectiveCreateSessionBase = (0, import_react10.useMemo)(
4982
5703
  () => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
4983
5704
  [createSessionParams, activeCreateSessionPatch]
4984
5705
  );
4985
5706
  const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
4986
- const effectiveCreateSession = (0, import_react9.useMemo)(
5707
+ const effectiveCreateSession = (0, import_react10.useMemo)(
4987
5708
  () => effectiveCreateSessionBase ? {
4988
5709
  ...effectiveCreateSessionBase,
4989
5710
  checkoutMode: effectiveCreateSessionMode
4990
5711
  } : void 0,
4991
5712
  [effectiveCreateSessionBase, effectiveCreateSessionMode]
4992
5713
  );
4993
- (0, import_react9.useEffect)(() => {
5714
+ (0, import_react10.useEffect)(() => {
4994
5715
  setCreateSessionPatch(void 0);
4995
5716
  setCreateSessionPatchBaseHash(baseCreateSessionHash);
4996
5717
  }, [baseCreateSessionHash]);
4997
- (0, import_react9.useEffect)(() => {
5718
+ (0, import_react10.useEffect)(() => {
4998
5719
  setModeError(initialErrorMessage);
4999
5720
  }, [initialErrorMessage]);
5000
- const emitDecline = (0, import_react9.useCallback)(
5721
+ const emitDecline = (0, import_react10.useCallback)(
5001
5722
  (method, input, overrides) => {
5002
5723
  onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
5003
5724
  },
5004
5725
  []
5005
5726
  );
5006
- const runSavedPaymentFlow = (0, import_react9.useCallback)(
5727
+ const runSavedPaymentFlow = (0, import_react10.useCallback)(
5007
5728
  async (sess, options) => {
5008
5729
  setModeError(null);
5009
5730
  setModeOverlayError(null);
@@ -5121,7 +5842,7 @@ function FloPayCheckout({
5121
5842
  resolvedBillingUrl
5122
5843
  ]
5123
5844
  );
5124
- (0, import_react9.useEffect)(() => {
5845
+ (0, import_react10.useEffect)(() => {
5125
5846
  if (typeof window === "undefined" || paypalResumeAttempted.current) {
5126
5847
  return;
5127
5848
  }
@@ -5238,7 +5959,7 @@ function FloPayCheckout({
5238
5959
  }
5239
5960
  })();
5240
5961
  }, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
5241
- const initializedHashRef = (0, import_react9.useRef)(null);
5962
+ const initializedHashRef = (0, import_react10.useRef)(null);
5242
5963
  function hashCreateParams(params) {
5243
5964
  const key = JSON.stringify({
5244
5965
  c: params?.clientId,
@@ -5271,16 +5992,16 @@ function FloPayCheckout({
5271
5992
  }
5272
5993
  return `flopay_session_${Math.abs(h).toString(36)}`;
5273
5994
  }
5274
- const createSessionHash = (0, import_react9.useMemo)(
5995
+ const createSessionHash = (0, import_react10.useMemo)(
5275
5996
  () => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
5276
5997
  [effectiveCreateSession]
5277
5998
  );
5278
- const createSessionParamsRef = (0, import_react9.useRef)(effectiveCreateSession);
5999
+ const createSessionParamsRef = (0, import_react10.useRef)(effectiveCreateSession);
5279
6000
  createSessionParamsRef.current = effectiveCreateSession;
5280
- (0, import_react9.useEffect)(() => {
6001
+ (0, import_react10.useEffect)(() => {
5281
6002
  setResolvedSessionId(sessionIdProp ?? "");
5282
6003
  }, [sessionIdProp]);
5283
- (0, import_react9.useEffect)(() => {
6004
+ (0, import_react10.useEffect)(() => {
5284
6005
  autoCheckoutAttempted.current = false;
5285
6006
  setModeError(initialErrorMessage);
5286
6007
  setModeOverlayError(null);
@@ -5288,22 +6009,23 @@ function FloPayCheckout({
5288
6009
  }, [createSessionHash, initialErrorMessage, sessionIdProp]);
5289
6010
  async function resolveInlineSession(params, cacheKey) {
5290
6011
  const api = new import_js4.PaymentAPI(resolvedBillingUrl);
5291
- let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
6012
+ const cached = readCachedInlineSession(cacheKey);
6013
+ let sid = cached?.sid ?? null;
5292
6014
  let realResult = null;
5293
6015
  if (sid) {
5294
6016
  try {
5295
- realResult = await api.getUnifiedCheckoutSession(sid);
6017
+ realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
5296
6018
  const status = realResult.data.session?.status;
5297
6019
  if (status === "complete") {
5298
6020
  if (wasSessionRecentlyCompleted(sid)) {
5299
6021
  return { sid, result: realResult };
5300
6022
  }
5301
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
6023
+ clearCachedInlineSession(cacheKey);
5302
6024
  sid = null;
5303
6025
  realResult = null;
5304
6026
  }
5305
6027
  } catch {
5306
- if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
6028
+ clearCachedInlineSession(cacheKey);
5307
6029
  sid = null;
5308
6030
  }
5309
6031
  }
@@ -5317,13 +6039,13 @@ function FloPayCheckout({
5317
6039
  };
5318
6040
  realResult = await api.createAndFetchSession(paramsWithAnalytics);
5319
6041
  sid = realResult.data.session?.id ?? "";
5320
- if (sid && typeof window !== "undefined") {
5321
- window.sessionStorage.setItem(cacheKey, sid);
6042
+ if (sid) {
6043
+ persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
5322
6044
  }
5323
6045
  }
5324
6046
  return { sid: sid ?? "", result: realResult };
5325
6047
  }
5326
- const bootstrapInlineSession = (0, import_react9.useCallback)(
6048
+ const bootstrapInlineSession = (0, import_react10.useCallback)(
5327
6049
  async (patch) => {
5328
6050
  const baseParams = createSessionParamsRef.current;
5329
6051
  if (!baseParams) {
@@ -5384,7 +6106,7 @@ function FloPayCheckout({
5384
6106
  },
5385
6107
  [locale, resolvedBillingUrl]
5386
6108
  );
5387
- const handleInlineSessionPatch = (0, import_react9.useCallback)(async (patch) => {
6109
+ const handleInlineSessionPatch = (0, import_react10.useCallback)(async (patch) => {
5388
6110
  if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
5389
6111
  return {
5390
6112
  sessionId: resolvedSessionId,
@@ -5407,7 +6129,7 @@ function FloPayCheckout({
5407
6129
  resolvedSessionId,
5408
6130
  session
5409
6131
  ]);
5410
- (0, import_react9.useEffect)(() => {
6132
+ (0, import_react10.useEffect)(() => {
5411
6133
  let cancelled = false;
5412
6134
  setLoadError(null);
5413
6135
  if (createSessionHash) {
@@ -5573,7 +6295,7 @@ function FloPayCheckout({
5573
6295
  nonceProp,
5574
6296
  runSavedPaymentFlow
5575
6297
  ]);
5576
- const handleConfirmCheckout = (0, import_react9.useCallback)(async () => {
6298
+ const handleConfirmCheckout = (0, import_react10.useCallback)(async () => {
5577
6299
  if (confirmProcessing || !session) return;
5578
6300
  setConfirmProcessing(true);
5579
6301
  setModeError(null);
@@ -5588,7 +6310,7 @@ function FloPayCheckout({
5588
6310
  }, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
5589
6311
  const directPaypalConfig = resolveDirectPaypalConfig(unified);
5590
6312
  const isPaypalOnlySession = isPayPalOnlyUnified(unified);
5591
- const providerOptions = (0, import_react9.useMemo)(() => {
6313
+ const providerOptions = (0, import_react10.useMemo)(() => {
5592
6314
  if (!unified || !session || !unified.data.stripe?.publishableKey) return void 0;
5593
6315
  const opts = {
5594
6316
  appearance,
@@ -5607,7 +6329,7 @@ function FloPayCheckout({
5607
6329
  const shouldHandleInlineSessionPatch = Boolean(
5608
6330
  createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
5609
6331
  );
5610
- const checkoutValue = (0, import_react9.useMemo)(
6332
+ const checkoutValue = (0, import_react10.useMemo)(
5611
6333
  () => ({
5612
6334
  session,
5613
6335
  loading: isLoading,
@@ -5629,7 +6351,7 @@ function FloPayCheckout({
5629
6351
  ]
5630
6352
  );
5631
6353
  const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
5632
- const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6354
+ const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5633
6355
  ProcessingOverlay,
5634
6356
  {
5635
6357
  status: modeOverlayStatus,
@@ -5638,32 +6360,32 @@ function FloPayCheckout({
5638
6360
  ) : null;
5639
6361
  if (isLoading) {
5640
6362
  if (loadingNode) {
5641
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6363
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
5642
6364
  loadingNode,
5643
6365
  modeOverlay
5644
6366
  ] });
5645
6367
  }
5646
6368
  if (layout === "buttons") {
5647
6369
  const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5648
- const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6370
+ const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5649
6371
  height: h,
5650
6372
  borderRadius: bundleRadius,
5651
6373
  background: "#e5e7eb",
5652
6374
  animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
5653
6375
  } });
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: [
6376
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6377
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5656
6378
  showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5657
6379
  showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
5658
6380
  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; } }` })
6381
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
5660
6382
  ] }),
5661
6383
  modeOverlay
5662
6384
  ] });
5663
6385
  }
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: {
6386
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6387
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
6388
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5667
6389
  width: 24,
5668
6390
  height: 24,
5669
6391
  border: "2px solid #e5e7eb",
@@ -5671,16 +6393,16 @@ function FloPayCheckout({
5671
6393
  borderRadius: "50%",
5672
6394
  animation: "spin 0.6s linear infinite"
5673
6395
  } }),
5674
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
6396
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
5675
6397
  ] }),
5676
6398
  modeOverlay
5677
6399
  ] });
5678
6400
  }
5679
6401
  if (loadError) {
5680
6402
  if (errorNode) {
5681
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
6403
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
5682
6404
  }
5683
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6405
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5684
6406
  "div",
5685
6407
  {
5686
6408
  role: "alert",
@@ -5696,8 +6418,8 @@ function FloPayCheckout({
5696
6418
  ) });
5697
6419
  }
5698
6420
  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)(
6421
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6422
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5701
6423
  InterimButtonsView,
5702
6424
  {
5703
6425
  onButtonClick,
@@ -5717,9 +6439,9 @@ function FloPayCheckout({
5717
6439
  ] });
5718
6440
  }
5719
6441
  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)(
6442
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6443
+ /* @__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: [
6444
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5723
6445
  "div",
5724
6446
  {
5725
6447
  role: "alert",
@@ -5736,7 +6458,7 @@ function FloPayCheckout({
5736
6458
  children: modeError
5737
6459
  }
5738
6460
  ),
5739
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6461
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5740
6462
  DirectPayPalButton,
5741
6463
  {
5742
6464
  sessionId: activeSessionId,
@@ -5760,12 +6482,12 @@ function FloPayCheckout({
5760
6482
  ] });
5761
6483
  }
5762
6484
  if (!flopay || !providerOptions) {
5763
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: modeOverlay });
6485
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: modeOverlay });
5764
6486
  }
5765
6487
  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)(
6488
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6489
+ /* @__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: [
6490
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5769
6491
  "div",
5770
6492
  {
5771
6493
  style: {
@@ -5780,7 +6502,7 @@ function FloPayCheckout({
5780
6502
  renderConfirmButton ? renderConfirmButton({
5781
6503
  onConfirm: handleConfirmCheckout,
5782
6504
  isProcessing: confirmProcessing
5783
- }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6505
+ }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5784
6506
  "button",
5785
6507
  {
5786
6508
  type: "button",
@@ -5805,9 +6527,9 @@ function FloPayCheckout({
5805
6527
  modeOverlay
5806
6528
  ] });
5807
6529
  }
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)(
6530
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6531
+ /* @__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: [
6532
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5811
6533
  "div",
5812
6534
  {
5813
6535
  style: {
@@ -5822,7 +6544,7 @@ function FloPayCheckout({
5822
6544
  children: modeError
5823
6545
  }
5824
6546
  ),
5825
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6547
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5826
6548
  SessionInjector,
5827
6549
  {
5828
6550
  sessionId: activeSessionId,
@@ -5832,7 +6554,7 @@ function FloPayCheckout({
5832
6554
  children
5833
6555
  }
5834
6556
  )
5835
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6557
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5836
6558
  SplitCardForm,
5837
6559
  {
5838
6560
  sessionId: activeSessionId,
@@ -5852,6 +6574,7 @@ function FloPayCheckout({
5852
6574
  showPayPal,
5853
6575
  showStripe,
5854
6576
  enabledPaymentMethods: unified?.data.stripe?.enabledPaymentMethods,
6577
+ enabledPaymentMethodCountries: unified?.data.stripe?.enabledPaymentMethodCountries,
5855
6578
  showApplePay,
5856
6579
  showGooglePay,
5857
6580
  layout,
@@ -5865,6 +6588,8 @@ function FloPayCheckout({
5865
6588
  onButtonClick,
5866
6589
  onBeforeButtonClick,
5867
6590
  enableAVS,
6591
+ ...cardFieldOrder ? { cardFieldOrder } : {},
6592
+ ...cardPreFormSlot ? { cardPreFormSlot } : {},
5868
6593
  avsLayout,
5869
6594
  country: session?.customer?.country,
5870
6595
  city: session?.customer?.city,
@@ -5892,8 +6617,8 @@ function SessionInjector({
5892
6617
  session,
5893
6618
  children
5894
6619
  }) {
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;
6620
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: import_react10.default.Children.map(children, (child) => {
6621
+ if (!import_react10.default.isValidElement(child)) return child;
5897
6622
  const existing = child.props;
5898
6623
  const injected = {};
5899
6624
  if (!existing.sessionId) injected.sessionId = sessionId;
@@ -5908,7 +6633,7 @@ function SessionInjector({
5908
6633
  injected.lastName = session.customer.lastName;
5909
6634
  }
5910
6635
  if (Object.keys(injected).length === 0) return child;
5911
- return import_react9.default.cloneElement(child, injected);
6636
+ return import_react10.default.cloneElement(child, injected);
5912
6637
  }) });
5913
6638
  }
5914
6639
  function InterimButtonsView({
@@ -5928,15 +6653,15 @@ function InterimButtonsView({
5928
6653
  cardBackButtonContent,
5929
6654
  cardTitleContent
5930
6655
  }) {
5931
- const [showCardForm, setShowCardForm] = (0, import_react9.useState)(false);
6656
+ const [showCardForm, setShowCardForm] = (0, import_react10.useState)(false);
5932
6657
  const isCardOpenControlled = typeof cardOpen === "boolean";
5933
- (0, import_react9.useEffect)(() => {
6658
+ (0, import_react10.useEffect)(() => {
5934
6659
  if (isCardOpenControlled) {
5935
6660
  setShowCardForm(cardOpen);
5936
6661
  }
5937
6662
  }, [cardOpen, isCardOpenControlled]);
5938
- const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
5939
- const bStyles = (0, import_react9.useMemo)(() => {
6663
+ const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
6664
+ const bStyles = (0, import_react10.useMemo)(() => {
5940
6665
  const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
5941
6666
  if (!stylesOverride) return base;
5942
6667
  return {
@@ -5951,7 +6676,7 @@ function InterimButtonsView({
5951
6676
  };
5952
6677
  }, [themeBundle, buttonsTheme, stylesOverride]);
5953
6678
  const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
5954
- const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6679
+ const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5955
6680
  height: h,
5956
6681
  borderRadius: skeletonRadius,
5957
6682
  background: "#e5e7eb",
@@ -5963,15 +6688,15 @@ function InterimButtonsView({
5963
6688
  const inputBg = bStyles.cardInputBackground ?? "white";
5964
6689
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
5965
6690
  const hideTitle = isEmptySlotContent(cardTitleContent);
5966
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
6691
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5967
6692
  backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
5968
6693
  borderRadius: "8px",
5969
6694
  animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
5970
6695
  overflow: "hidden",
5971
6696
  ...bStyles.cardFormContainer
5972
6697
  }, 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)(
6698
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
6699
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5975
6700
  "button",
5976
6701
  {
5977
6702
  type: "button",
@@ -5998,7 +6723,7 @@ function InterimButtonsView({
5998
6723
  ...bStyles.backButton
5999
6724
  },
6000
6725
  children: [
6001
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
6726
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
6002
6727
  display: "inline-flex",
6003
6728
  alignItems: "center",
6004
6729
  justifyContent: "center",
@@ -6007,12 +6732,12 @@ function InterimButtonsView({
6007
6732
  borderRadius: "50%",
6008
6733
  backgroundColor: "#f3f4f6",
6009
6734
  ...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 })
6735
+ }, 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" }) }) }),
6736
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
6012
6737
  ]
6013
6738
  }
6014
6739
  ),
6015
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
6740
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6016
6741
  flex: 1,
6017
6742
  textAlign: "center",
6018
6743
  fontWeight: 600,
@@ -6020,11 +6745,11 @@ function InterimButtonsView({
6020
6745
  color: "#262833",
6021
6746
  paddingRight: 80,
6022
6747
  ...bStyles.title
6023
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
6748
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
6024
6749
  ] }),
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: {
6750
+ /* @__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" } }) }),
6751
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
6752
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6028
6753
  flex: 1,
6029
6754
  backgroundColor: inputBg,
6030
6755
  borderTop: "none",
@@ -6034,8 +6759,8 @@ function InterimButtonsView({
6034
6759
  borderBottomLeftRadius: 8,
6035
6760
  padding: 12,
6036
6761
  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: {
6762
+ }, 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" } }) }),
6763
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6039
6764
  flex: 1,
6040
6765
  backgroundColor: inputBg,
6041
6766
  borderTop: "none",
@@ -6045,10 +6770,10 @@ function InterimButtonsView({
6045
6770
  borderBottomRightRadius: 8,
6046
6771
  padding: 12,
6047
6772
  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" } }) })
6773
+ }, 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
6774
  ] }),
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: {
6775
+ /* @__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" } }) }),
6776
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
6052
6777
  height: 50,
6053
6778
  borderRadius: 8,
6054
6779
  marginTop: 16,
@@ -6057,7 +6782,7 @@ function InterimButtonsView({
6057
6782
  ...bStyles.submitButton,
6058
6783
  opacity: 0.5
6059
6784
  } }),
6060
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
6785
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
6061
6786
  @keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
6062
6787
  @keyframes flopay-interim-expand {
6063
6788
  0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
@@ -6067,10 +6792,10 @@ function InterimButtonsView({
6067
6792
  ` })
6068
6793
  ] });
6069
6794
  }
6070
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6795
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6071
6796
  showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6072
6797
  showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6073
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6798
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6074
6799
  "button",
6075
6800
  {
6076
6801
  type: "button",
@@ -6110,10 +6835,10 @@ function InterimButtonsView({
6110
6835
  onMouseUp: (e) => {
6111
6836
  e.currentTarget.style.transform = "scale(1)";
6112
6837
  },
6113
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
6838
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
6114
6839
  }
6115
6840
  ),
6116
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
6841
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
6117
6842
  margin: "0.25rem 0",
6118
6843
  padding: "0.625rem 0.875rem",
6119
6844
  background: "#FEF2F2",
@@ -6127,22 +6852,22 @@ function InterimButtonsView({
6127
6852
  gap: "0.5rem",
6128
6853
  ...bStyles.errorBanner
6129
6854
  }, 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" }) }),
6855
+ /* @__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
6856
  errorMessage
6132
6857
  ] }),
6133
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6858
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6134
6859
  ] });
6135
6860
  }
6136
6861
 
6137
6862
  // src/checkout-form.tsx
6138
6863
  var import_js5 = require("@flopay/js");
6139
6864
  var import_shared9 = require("@flopay/shared");
6140
- var import_react10 = require("react");
6141
- var import_jsx_runtime8 = require("react/jsx-runtime");
6865
+ var import_react11 = require("react");
6866
+ var import_jsx_runtime9 = require("react/jsx-runtime");
6142
6867
  var WALLET_RESUME_KEY = "flopay_wallet_resume";
6143
- var CheckoutForm = (0, import_react10.forwardRef)(
6868
+ var CheckoutForm = (0, import_react11.forwardRef)(
6144
6869
  function CheckoutForm2(props, ref) {
6145
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
6870
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
6146
6871
  }
6147
6872
  );
6148
6873
  function CheckoutFormInner({
@@ -6172,27 +6897,27 @@ function CheckoutFormInner({
6172
6897
  const paypalFlopay = usePayPalFloPay();
6173
6898
  const elements = useElements();
6174
6899
  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);
6900
+ const [processing, setProcessing] = (0, import_react11.useState)(false);
6901
+ const [error, setError] = (0, import_react11.useState)(null);
6902
+ const [is3DSActive, setIs3DSActive] = (0, import_react11.useState)(false);
6178
6903
  const displayError = externalError ?? error;
6179
6904
  const isSubmitting = externalProcessing ?? processing;
6180
6905
  const isSelfContained = !onTokenizedBody;
6181
6906
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
6182
- const updateError = (0, import_react10.useCallback)(
6907
+ const updateError = (0, import_react11.useCallback)(
6183
6908
  (err) => {
6184
6909
  setError(err);
6185
6910
  onErrorChange?.(err);
6186
6911
  },
6187
6912
  [onErrorChange]
6188
6913
  );
6189
- const emitDecline = (0, import_react10.useCallback)(
6914
+ const emitDecline = (0, import_react11.useCallback)(
6190
6915
  (input, overrides) => {
6191
6916
  onDecline?.(buildDeclineEvent("card", input, overrides));
6192
6917
  },
6193
6918
  [onDecline]
6194
6919
  );
6195
- const processPaymentInternal = (0, import_react10.useCallback)(
6920
+ const processPaymentInternal = (0, import_react11.useCallback)(
6196
6921
  async (tokenizedBody, completionPaymentMethodId) => {
6197
6922
  setProcessing(true);
6198
6923
  updateError(null);
@@ -6304,7 +7029,7 @@ function CheckoutFormInner({
6304
7029
  },
6305
7030
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
6306
7031
  );
6307
- const dispatchTokenizedBody = (0, import_react10.useCallback)(
7032
+ const dispatchTokenizedBody = (0, import_react11.useCallback)(
6308
7033
  (tokenizedBody) => {
6309
7034
  if (onTokenizedBody) {
6310
7035
  onTokenizedBody(tokenizedBody);
@@ -6314,7 +7039,7 @@ function CheckoutFormInner({
6314
7039
  },
6315
7040
  [onTokenizedBody, processPaymentInternal]
6316
7041
  );
6317
- (0, import_react10.useImperativeHandle)(innerRef, () => ({
7042
+ (0, import_react11.useImperativeHandle)(innerRef, () => ({
6318
7043
  async handleNextAction(secret) {
6319
7044
  if (!flopay) return;
6320
7045
  setIs3DSActive(true);
@@ -6341,7 +7066,7 @@ function CheckoutFormInner({
6341
7066
  }
6342
7067
  }
6343
7068
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
6344
- (0, import_react10.useEffect)(() => {
7069
+ (0, import_react11.useEffect)(() => {
6345
7070
  if (typeof window === "undefined") return;
6346
7071
  const stored = localStorage.getItem(WALLET_RESUME_KEY);
6347
7072
  if (!stored) return;
@@ -6359,7 +7084,7 @@ function CheckoutFormInner({
6359
7084
  localStorage.removeItem(WALLET_RESUME_KEY);
6360
7085
  }
6361
7086
  }, [sessionId, dispatchTokenizedBody]);
6362
- const handleSubmit = (0, import_react10.useCallback)(
7087
+ const handleSubmit = (0, import_react11.useCallback)(
6363
7088
  async (e) => {
6364
7089
  e.preventDefault();
6365
7090
  if (!flopay || !elements || isSubmitting) return;
@@ -6451,8 +7176,8 @@ function CheckoutFormInner({
6451
7176
  [flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
6452
7177
  );
6453
7178
  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: {
7179
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
7180
+ (is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-overlay", style: {
6456
7181
  position: "absolute",
6457
7182
  inset: 0,
6458
7183
  background: "rgba(255,255,255,0.7)",
@@ -6461,12 +7186,12 @@ function CheckoutFormInner({
6461
7186
  justifyContent: "center",
6462
7187
  zIndex: 10
6463
7188
  }, 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)(
7189
+ !isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
7190
+ isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7191
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PaymentElement, { options: { layout } }),
7192
+ showAddress && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
7193
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
7194
+ children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
6470
7195
  "button",
6471
7196
  {
6472
7197
  type: "submit",
@@ -6482,8 +7207,8 @@ function CheckoutFormInner({
6482
7207
  // src/paypal-button.tsx
6483
7208
  var import_js6 = require("@flopay/js");
6484
7209
  var import_shared10 = require("@flopay/shared");
6485
- var import_react11 = require("react");
6486
- var import_jsx_runtime9 = require("react/jsx-runtime");
7210
+ var import_react12 = require("react");
7211
+ var import_jsx_runtime10 = require("react/jsx-runtime");
6487
7212
  function PayPalButton({
6488
7213
  sessionId,
6489
7214
  nonce,
@@ -6501,11 +7226,11 @@ function PayPalButton({
6501
7226
  const flopay = useFloPay();
6502
7227
  const elements = useElements();
6503
7228
  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);
7229
+ const [ready, setReady] = (0, import_react12.useState)(false);
7230
+ const [submitting, setSubmitting] = (0, import_react12.useState)(false);
7231
+ const paypalResumeAttempted = (0, import_react12.useRef)(false);
6507
7232
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
6508
- const processPaymentInternal = (0, import_react11.useCallback)(
7233
+ const processPaymentInternal = (0, import_react12.useCallback)(
6509
7234
  async (tokenizedBody) => {
6510
7235
  try {
6511
7236
  const api = new import_js6.PaymentAPI(baseUrl);
@@ -6533,7 +7258,7 @@ function PayPalButton({
6533
7258
  },
6534
7259
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
6535
7260
  );
6536
- const dispatchTokenizedBody = (0, import_react11.useCallback)(
7261
+ const dispatchTokenizedBody = (0, import_react12.useCallback)(
6537
7262
  (body) => {
6538
7263
  if (onTokenizedBody) {
6539
7264
  onTokenizedBody(body);
@@ -6543,7 +7268,7 @@ function PayPalButton({
6543
7268
  },
6544
7269
  [onTokenizedBody, processPaymentInternal]
6545
7270
  );
6546
- (0, import_react11.useEffect)(() => {
7271
+ (0, import_react12.useEffect)(() => {
6547
7272
  if (!flopay || paypalResumeAttempted.current) return;
6548
7273
  const params = new URLSearchParams(window.location.search);
6549
7274
  const paymentIntentId = params.get("payment_intent");
@@ -6591,7 +7316,7 @@ function PayPalButton({
6591
7316
  }
6592
7317
  })();
6593
7318
  }, [flopay, dispatchTokenizedBody, onErrorChange]);
6594
- const handlePayPalConfirm = (0, import_react11.useCallback)(async () => {
7319
+ const handlePayPalConfirm = (0, import_react12.useCallback)(async () => {
6595
7320
  if (!flopay || !elements) return;
6596
7321
  try {
6597
7322
  setSubmitting(true);
@@ -6625,11 +7350,11 @@ function PayPalButton({
6625
7350
  }
6626
7351
  }, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
6627
7352
  if (!flopay || !elements) {
6628
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
7353
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
6629
7354
  }
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)(
7355
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
7356
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
7357
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6633
7358
  "button",
6634
7359
  {
6635
7360
  type: "button",
@@ -6651,7 +7376,7 @@ function PayPalButton({
6651
7376
  children: submitting ? "Processing..." : "PayPal"
6652
7377
  }
6653
7378
  ) }),
6654
- (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7379
+ (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
6655
7380
  position: "fixed",
6656
7381
  inset: 0,
6657
7382
  background: "rgba(0,0,0,0.4)",
@@ -6659,7 +7384,7 @@ function PayPalButton({
6659
7384
  alignItems: "center",
6660
7385
  justifyContent: "center",
6661
7386
  zIndex: 1e3
6662
- }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7387
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
6663
7388
  background: "white",
6664
7389
  borderRadius: 8,
6665
7390
  padding: "1.5rem",
@@ -6671,10 +7396,10 @@ function PayPalButton({
6671
7396
  }
6672
7397
 
6673
7398
  // src/automatic-payment-button.tsx
6674
- var import_react12 = require("react");
7399
+ var import_react13 = require("react");
6675
7400
  var import_js7 = require("@flopay/js");
6676
7401
  var import_shared11 = require("@flopay/shared");
6677
- var import_jsx_runtime10 = require("react/jsx-runtime");
7402
+ var import_jsx_runtime11 = require("react/jsx-runtime");
6678
7403
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
6679
7404
  function sleep2(ms) {
6680
7405
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -6742,6 +7467,7 @@ function FloPayAutomaticPaymentButton({
6742
7467
  billingApiUrl,
6743
7468
  locale,
6744
7469
  theme,
7470
+ appearance,
6745
7471
  buttonsTheme,
6746
7472
  buttonsStyles: stylesOverride,
6747
7473
  onSuccess,
@@ -6753,11 +7479,11 @@ function FloPayAutomaticPaymentButton({
6753
7479
  style,
6754
7480
  ...buttonProps
6755
7481
  }) {
6756
- const resolvedBillingUrl = (0, import_react12.useMemo)(
7482
+ const resolvedBillingUrl = (0, import_react13.useMemo)(
6757
7483
  () => (0, import_shared11.resolveBillingApiUrl)(billingApiUrl),
6758
7484
  [billingApiUrl]
6759
7485
  );
6760
- const createSessionDraft = (0, import_react12.useMemo)(
7486
+ const createSessionDraft = (0, import_react13.useMemo)(
6761
7487
  () => resolveCreateSessionDraft({
6762
7488
  createSession,
6763
7489
  clientId,
@@ -6785,34 +7511,36 @@ function FloPayAutomaticPaymentButton({
6785
7511
  utmMetadata
6786
7512
  ]
6787
7513
  );
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)(() => {
7514
+ const [isProcessing, setIsProcessing] = (0, import_react13.useState)(false);
7515
+ const [overlayStatus, setOverlayStatus] = (0, import_react13.useState)(null);
7516
+ const [overlayError, setOverlayError] = (0, import_react13.useState)(null);
7517
+ const [fallbackSession, setFallbackSession] = (0, import_react13.useState)(null);
7518
+ const isMountedRef = (0, import_react13.useRef)(true);
7519
+ const threeDsAbortRef = (0, import_react13.useRef)(null);
7520
+ const fallbackSessionRef = (0, import_react13.useRef)(fallbackSession);
7521
+ const onSuccessRef = (0, import_react13.useRef)(onSuccess);
7522
+ const onErrorRef = (0, import_react13.useRef)(onError);
7523
+ const onDeclineRef = (0, import_react13.useRef)(onDecline);
7524
+ (0, import_react13.useEffect)(() => {
6798
7525
  fallbackSessionRef.current = fallbackSession;
6799
7526
  }, [fallbackSession]);
6800
- (0, import_react12.useEffect)(() => {
7527
+ (0, import_react13.useEffect)(() => {
6801
7528
  onSuccessRef.current = onSuccess;
6802
7529
  }, [onSuccess]);
6803
- (0, import_react12.useEffect)(() => {
7530
+ (0, import_react13.useEffect)(() => {
6804
7531
  onErrorRef.current = onError;
6805
7532
  }, [onError]);
6806
- (0, import_react12.useEffect)(() => {
7533
+ (0, import_react13.useEffect)(() => {
6807
7534
  onDeclineRef.current = onDecline;
6808
7535
  }, [onDecline]);
6809
- (0, import_react12.useEffect)(() => {
7536
+ (0, import_react13.useEffect)(() => {
6810
7537
  isMountedRef.current = true;
6811
7538
  return () => {
6812
7539
  isMountedRef.current = false;
7540
+ threeDsAbortRef.current?.abort();
6813
7541
  };
6814
7542
  }, []);
6815
- (0, import_react12.useEffect)(() => {
7543
+ (0, import_react13.useEffect)(() => {
6816
7544
  if (!fallbackSession || typeof window === "undefined") {
6817
7545
  return;
6818
7546
  }
@@ -6826,13 +7554,13 @@ function FloPayAutomaticPaymentButton({
6826
7554
  window.removeEventListener("keydown", handleKeyDown);
6827
7555
  };
6828
7556
  }, [fallbackSession]);
6829
- const emitDecline = (0, import_react12.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
7557
+ const emitDecline = (0, import_react13.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
6830
7558
  onDeclineRef.current?.(buildDeclineEvent(method, error, {
6831
7559
  code: error.code,
6832
7560
  declineCode: error.declineCode
6833
7561
  }));
6834
7562
  }, []);
6835
- const showSuccess = (0, import_react12.useCallback)(async (event) => {
7563
+ const showSuccess = (0, import_react13.useCallback)(async (event) => {
6836
7564
  if (!isMountedRef.current) return;
6837
7565
  setOverlayError(null);
6838
7566
  setOverlayStatus("success");
@@ -6840,7 +7568,7 @@ function FloPayAutomaticPaymentButton({
6840
7568
  if (!isMountedRef.current) return;
6841
7569
  onSuccessRef.current?.(event);
6842
7570
  }, []);
6843
- const showError = (0, import_react12.useCallback)(async (error, options) => {
7571
+ const showError = (0, import_react13.useCallback)(async (error, options) => {
6844
7572
  if (!isMountedRef.current) return;
6845
7573
  onErrorRef.current?.(error);
6846
7574
  if (options?.emitDecline) {
@@ -6850,7 +7578,7 @@ function FloPayAutomaticPaymentButton({
6850
7578
  setOverlayStatus("error");
6851
7579
  await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
6852
7580
  }, [emitDecline]);
6853
- const processResolvedSession = (0, import_react12.useCallback)(async (apiResult, resolvedSessionId, options) => {
7581
+ const processResolvedSession = (0, import_react13.useCallback)(async (apiResult, resolvedSessionId, options) => {
6854
7582
  const session = apiResult.data.session ?? null;
6855
7583
  if (!session) {
6856
7584
  throw new import_shared11.FloPayError("No session data returned", "api_error");
@@ -6891,6 +7619,62 @@ function FloPayAutomaticPaymentButton({
6891
7619
  return;
6892
7620
  }
6893
7621
  if (apiResult.autoProcessingError) {
7622
+ if (apiResult.autoProcessingError.type === "3ds_required" && apiResult.autoProcessingError.nextActionRedirectUrl && resolvedSessionId && effectiveNonce) {
7623
+ const threeDsAbort = new AbortController();
7624
+ threeDsAbortRef.current = threeDsAbort;
7625
+ let outcome;
7626
+ try {
7627
+ outcome = await runAutoCheckoutThreeDsChallenge({
7628
+ billingApiUrl: resolvedBillingUrl,
7629
+ sessionId: resolvedSessionId,
7630
+ nonce: effectiveNonce,
7631
+ nextActionRedirectUrl: apiResult.autoProcessingError.nextActionRedirectUrl,
7632
+ signal: threeDsAbort.signal
7633
+ });
7634
+ } finally {
7635
+ if (threeDsAbortRef.current === threeDsAbort) {
7636
+ threeDsAbortRef.current = null;
7637
+ }
7638
+ }
7639
+ if (outcome.status === "declined") {
7640
+ throw checkoutProcessErrorToFloPayError(
7641
+ {
7642
+ type: outcome.declineReason ?? "decline",
7643
+ message: "Card was declined.",
7644
+ gatewayErrorCode: outcome.gatewayDeclineReason ?? void 0
7645
+ },
7646
+ "Card was declined.",
7647
+ {
7648
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7649
+ }
7650
+ );
7651
+ }
7652
+ const api = new import_js7.PaymentAPI(resolvedBillingUrl);
7653
+ const completed = await api.waitForCheckoutSessionCompletion(resolvedSessionId, {
7654
+ initialDelayMs: 0,
7655
+ nonce: effectiveNonce
7656
+ });
7657
+ const completedSession = completed.data.session;
7658
+ if (!completedSession || completedSession.status !== "complete") {
7659
+ throw checkoutProcessErrorToFloPayError(
7660
+ {
7661
+ type: "unknown",
7662
+ message: "Card authentication was not completed."
7663
+ },
7664
+ "Card authentication was not completed.",
7665
+ {
7666
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
7667
+ }
7668
+ );
7669
+ }
7670
+ await showSuccess({
7671
+ result: { status: "succeeded" },
7672
+ session: completedSession,
7673
+ sessionId: completedSession.id || resolvedSessionId,
7674
+ autoCompleted: false
7675
+ });
7676
+ return;
7677
+ }
6894
7678
  throw checkoutProcessErrorToFloPayError(
6895
7679
  apiResult.autoProcessingError,
6896
7680
  "Automatic payment failed. Please try again.",
@@ -6950,7 +7734,7 @@ function FloPayAutomaticPaymentButton({
6950
7734
  showError,
6951
7735
  showSuccess
6952
7736
  ]);
6953
- const handleButtonClick = (0, import_react12.useCallback)(async (event) => {
7737
+ const handleButtonClick = (0, import_react13.useCallback)(async (event) => {
6954
7738
  buttonProps.onClick?.(event);
6955
7739
  if (event.defaultPrevented || disabled || isProcessing) {
6956
7740
  return;
@@ -7032,7 +7816,7 @@ function FloPayAutomaticPaymentButton({
7032
7816
  showError,
7033
7817
  showSuccess
7034
7818
  ]);
7035
- const handleFallbackComplete = (0, import_react12.useCallback)((result) => {
7819
+ const handleFallbackComplete = (0, import_react13.useCallback)((result) => {
7036
7820
  const activeFallback = fallbackSessionRef.current;
7037
7821
  setFallbackSession(null);
7038
7822
  onSuccessRef.current?.({
@@ -7042,14 +7826,14 @@ function FloPayAutomaticPaymentButton({
7042
7826
  autoCompleted: false
7043
7827
  });
7044
7828
  }, []);
7045
- const handleFallbackError = (0, import_react12.useCallback)((error) => {
7829
+ const handleFallbackError = (0, import_react13.useCallback)((error) => {
7046
7830
  onErrorRef.current?.(error);
7047
7831
  }, []);
7048
- const handleFallbackDecline = (0, import_react12.useCallback)((decline) => {
7832
+ const handleFallbackDecline = (0, import_react13.useCallback)((decline) => {
7049
7833
  onDeclineRef.current?.(decline);
7050
7834
  }, []);
7051
- const themeBundle = (0, import_react12.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
7052
- const bStyles = (0, import_react12.useMemo)(() => {
7835
+ const themeBundle = (0, import_react13.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
7836
+ const bStyles = (0, import_react13.useMemo)(() => {
7053
7837
  const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
7054
7838
  if (!stylesOverride) return base;
7055
7839
  return {
@@ -7058,9 +7842,26 @@ function FloPayAutomaticPaymentButton({
7058
7842
  cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
7059
7843
  };
7060
7844
  }, [themeBundle, buttonsTheme, stylesOverride]);
7845
+ const resolvedAppearance = (0, import_react13.useMemo)(() => {
7846
+ const bundleAppearance = themeBundle?.appearance;
7847
+ if (!appearance) return bundleAppearance;
7848
+ if (!bundleAppearance) return appearance;
7849
+ return {
7850
+ ...bundleAppearance,
7851
+ ...appearance,
7852
+ variables: {
7853
+ ...bundleAppearance.variables,
7854
+ ...appearance.variables
7855
+ }
7856
+ };
7857
+ }, [appearance, themeBundle]);
7858
+ const resolvedAppearanceVars = resolvedAppearance?.variables;
7859
+ const resolvedPrimaryColor = resolvedAppearanceVars?.colorPrimary ?? "#4A49FF";
7860
+ const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
7861
+ const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
7061
7862
  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)(
7863
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
7864
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7064
7865
  "button",
7065
7866
  {
7066
7867
  ...buttonProps,
@@ -7076,14 +7877,17 @@ function FloPayAutomaticPaymentButton({
7076
7877
  // on top so the auto-pay button carries the *submit* button's
7077
7878
  // background and text colours — making it visually identical to
7078
7879
  // the "Confirm Payment" / "Pay with X" actions it stands in for.
7880
+ // `resolvedPrimaryColor` is the *merged* appearance value, so a
7881
+ // per-checkout `colorPrimary` override re-skins this button too.
7079
7882
  // Inline `style` consumer override stays at the end so explicit
7080
7883
  // per-button overrides still win.
7081
7884
  ...bStyles.cardButton,
7082
7885
  ...derivePrimaryTileStyle({
7083
7886
  themeBundle,
7084
- resolvedPrimaryColor: themeBundle?.appearance.variables?.colorPrimary ?? "#4A49FF",
7085
- resolvedBorderRadius: themeBundle?.appearance.variables?.borderRadius ?? "8px",
7086
- submitButtonStyle: bStyles.submitButton
7887
+ resolvedPrimaryColor,
7888
+ resolvedBorderRadius: resolvedButtonBorderRadius,
7889
+ submitButtonStyle: bStyles.submitButton,
7890
+ explicitPrimaryColor: resolvedAppearanceVars?.colorPrimary
7087
7891
  }),
7088
7892
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
7089
7893
  fontWeight: 600,
@@ -7092,11 +7896,23 @@ function FloPayAutomaticPaymentButton({
7092
7896
  alignItems: "center",
7093
7897
  justifyContent: "center",
7094
7898
  gap: "0.625rem",
7095
- transition: "border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7899
+ transition: "background-color 0.15s, border-color 0.2s, box-shadow 0.2s, transform 0.1s",
7096
7900
  position: "relative",
7097
7901
  opacity: disabled || isProcessing ? 0.6 : 1,
7098
7902
  ...style
7099
7903
  },
7904
+ onMouseEnter: (e) => {
7905
+ buttonProps.onMouseEnter?.(e);
7906
+ if (!e.defaultPrevented && !disabled && !isProcessing && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7907
+ e.currentTarget.style.backgroundColor = resolvedPrimaryHoverColor;
7908
+ }
7909
+ },
7910
+ onMouseLeave: (e) => {
7911
+ buttonProps.onMouseLeave?.(e);
7912
+ if (!e.defaultPrevented && (themeBundle || resolvedAppearanceVars?.colorPrimary)) {
7913
+ e.currentTarget.style.backgroundColor = resolvedPrimaryColor;
7914
+ }
7915
+ },
7100
7916
  onMouseDown: (e) => {
7101
7917
  buttonProps.onMouseDown?.(e);
7102
7918
  if (!e.defaultPrevented) {
@@ -7109,17 +7925,17 @@ function FloPayAutomaticPaymentButton({
7109
7925
  e.currentTarget.style.transform = "scale(1)";
7110
7926
  }
7111
7927
  },
7112
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CardButtonContentSlot, { content: children })
7928
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CardButtonContentSlot, { content: children })
7113
7929
  }
7114
7930
  ),
7115
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7931
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7116
7932
  ProcessingOverlay,
7117
7933
  {
7118
7934
  status: overlayStatus,
7119
7935
  errorMessage: overlayError
7120
7936
  }
7121
7937
  ),
7122
- fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7938
+ fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7123
7939
  "div",
7124
7940
  {
7125
7941
  "data-testid": "flopay-automatic-payment-fallback",
@@ -7140,7 +7956,7 @@ function FloPayAutomaticPaymentButton({
7140
7956
  padding: "1.5rem",
7141
7957
  zIndex: 1100
7142
7958
  },
7143
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7959
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7144
7960
  "div",
7145
7961
  {
7146
7962
  style: {
@@ -7156,7 +7972,7 @@ function FloPayAutomaticPaymentButton({
7156
7972
  flexDirection: "column",
7157
7973
  gap: "1rem"
7158
7974
  },
7159
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7975
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7160
7976
  FloPayCheckout,
7161
7977
  {
7162
7978
  sessionId: fallbackSession.sessionId,
@@ -7165,6 +7981,7 @@ function FloPayAutomaticPaymentButton({
7165
7981
  billingApiUrl: resolvedBillingUrl,
7166
7982
  locale,
7167
7983
  theme,
7984
+ ...resolvedAppearance ? { appearance: resolvedAppearance } : {},
7168
7985
  buttonsTheme,
7169
7986
  buttonsStyles: stylesOverride,
7170
7987
  initialErrorMessage: fallbackSession.errorMessage,
@@ -7195,6 +8012,7 @@ function FloPayAutomaticPaymentButton({
7195
8012
  PayPalButton,
7196
8013
  PaymentElement,
7197
8014
  SplitCardForm,
8015
+ VaultCardFields,
7198
8016
  useCheckout,
7199
8017
  useElements,
7200
8018
  useFloPay,