@flopay/react 1.3.4 → 1.4.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
@@ -69,6 +69,59 @@ var CheckoutContext = (0, import_react.createContext)({
69
69
  error: null
70
70
  });
71
71
 
72
+ // src/telemetry-bridge.ts
73
+ var FLOPAY_TELEMETRY_BRIDGE = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.bridge.v1");
74
+ var TELEMETRY_REPORTER_FACTORY = /* @__PURE__ */ Symbol.for("@flopay/js.telemetry.reporter-factory.v1");
75
+ function noopTelemetryBridge() {
76
+ return {
77
+ error: () => {
78
+ },
79
+ log: () => {
80
+ },
81
+ performance: () => {
82
+ },
83
+ terminal: () => {
84
+ },
85
+ now: () => globalThis.performance?.now() ?? 0,
86
+ elapsed: (startedAt) => Math.max(0, (globalThis.performance?.now() ?? startedAt) - startedAt),
87
+ setCheckoutContext: () => {
88
+ },
89
+ beginCheckout: () => globalThis.performance?.now() ?? 0,
90
+ disable: () => {
91
+ },
92
+ flush: async () => {
93
+ },
94
+ destroy: () => {
95
+ }
96
+ };
97
+ }
98
+ function normalizeTelemetryBridge(source) {
99
+ const fallback = noopTelemetryBridge();
100
+ const bind = (candidate, defaultValue) => candidate ? candidate.bind(source) : defaultValue;
101
+ const now = bind(source.now, fallback.now);
102
+ return {
103
+ error: bind(source.error, fallback.error),
104
+ log: bind(source.log, fallback.log),
105
+ performance: bind(source.performance, fallback.performance),
106
+ terminal: bind(source.terminal, fallback.terminal),
107
+ now,
108
+ elapsed: source.elapsed ? source.elapsed.bind(source) : (startedAt) => Math.max(0, now() - startedAt),
109
+ setCheckoutContext: bind(source.setCheckoutContext, fallback.setCheckoutContext),
110
+ beginCheckout: bind(source.beginCheckout, fallback.beginCheckout),
111
+ disable: bind(source.disable, fallback.disable),
112
+ flush: bind(source.flush, fallback.flush),
113
+ destroy: bind(source.destroy, fallback.destroy)
114
+ };
115
+ }
116
+ function createTelemetryBridge(options) {
117
+ const factory = globalThis[TELEMETRY_REPORTER_FACTORY];
118
+ return normalizeTelemetryBridge(factory?.(options) ?? {});
119
+ }
120
+ function getFloPayTelemetryBridge(floPay) {
121
+ if (!floPay) return void 0;
122
+ return floPay[FLOPAY_TELEMETRY_BRIDGE];
123
+ }
124
+
72
125
  // src/provider.tsx
73
126
  var import_jsx_runtime = require("react/jsx-runtime");
74
127
  function FloPayProvider({
@@ -84,6 +137,18 @@ function FloPayProvider({
84
137
  paypalFloPayProp instanceof Promise || !paypalFloPayProp ? null : paypalFloPayProp
85
138
  );
86
139
  const [elements, setElements] = (0, import_react2.useState)(null);
140
+ const mountedAt = (0, import_react2.useRef)(null);
141
+ const renderedElements = (0, import_react2.useRef)(null);
142
+ const interactiveElements = (0, import_react2.useRef)(null);
143
+ (0, import_react2.useEffect)(() => {
144
+ if (!flopay) return;
145
+ const telemetry = getFloPayTelemetryBridge(flopay);
146
+ mountedAt.current = telemetry?.beginCheckout() ?? telemetry?.now() ?? 0;
147
+ telemetry?.log({ name: "checkout.mount", stage: "checkout_mount" });
148
+ return () => {
149
+ telemetry?.log({ name: "checkout.unmount", stage: "unmount" });
150
+ };
151
+ }, [flopay]);
87
152
  (0, import_react2.useEffect)(() => {
88
153
  let cancelled = false;
89
154
  if (floPayProp instanceof Promise) {
@@ -144,16 +209,44 @@ function FloPayProvider({
144
209
  options?.paymentMethodCreation,
145
210
  options?.setupFutureUsage
146
211
  ]);
212
+ (0, import_react2.useEffect)(() => {
213
+ if (!flopay || !elements || renderedElements.current === elements) return;
214
+ renderedElements.current = elements;
215
+ const telemetry = getFloPayTelemetryBridge(flopay);
216
+ telemetry?.log({ name: "checkout.rendered", stage: "checkout_render" });
217
+ telemetry?.performance({
218
+ stage: "checkout_render",
219
+ durationMs: telemetry.elapsed(mountedAt.current ?? 0),
220
+ durationMode: "machine"
221
+ });
222
+ }, [elements, flopay]);
223
+ const reportInteractive = (0, import_react2.useCallback)(() => {
224
+ if (!flopay || !elements || interactiveElements.current === elements) return;
225
+ interactiveElements.current = elements;
226
+ const telemetry = getFloPayTelemetryBridge(flopay);
227
+ telemetry?.log({ name: "checkout.interactive", stage: "checkout_interactive" });
228
+ telemetry?.performance({
229
+ stage: "checkout_interactive",
230
+ durationMs: telemetry.elapsed(mountedAt.current ?? 0),
231
+ durationMode: "machine"
232
+ });
233
+ }, [elements, flopay]);
147
234
  const resolvedBillingApiUrl = (0, import_shared.resolveBillingApiUrl)(options?.billingApiUrl);
148
235
  const value = (0, import_react2.useMemo)(
149
- () => ({ flopay, paypalFlopay, elements, billingApiUrl: resolvedBillingApiUrl }),
150
- [flopay, paypalFlopay, elements, resolvedBillingApiUrl]
236
+ () => ({
237
+ flopay,
238
+ paypalFlopay,
239
+ elements,
240
+ billingApiUrl: resolvedBillingApiUrl,
241
+ reportInteractive
242
+ }),
243
+ [flopay, paypalFlopay, elements, resolvedBillingApiUrl, reportInteractive]
151
244
  );
152
245
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FloPayContext.Provider, { value, children });
153
246
  }
154
247
 
155
248
  // src/flopay-checkout.tsx
156
- var import_react10 = __toESM(require("react"), 1);
249
+ var import_react11 = __toESM(require("react"), 1);
157
250
  var import_js4 = require("@flopay/js");
158
251
  var import_shared8 = require("@flopay/shared");
159
252
 
@@ -241,7 +334,7 @@ function createElementComponent(elementType, displayName) {
241
334
  }) {
242
335
  const containerRef = (0, import_react4.useRef)(null);
243
336
  const elementRef = (0, import_react4.useRef)(null);
244
- const { elements } = (0, import_react4.useContext)(FloPayContext);
337
+ const { elements, reportInteractive } = (0, import_react4.useContext)(FloPayContext);
245
338
  (0, import_react4.useEffect)(() => {
246
339
  if (!elements || !containerRef.current) return;
247
340
  let mounted = true;
@@ -256,7 +349,10 @@ function createElementComponent(elementType, displayName) {
256
349
  element.mount(containerRef.current);
257
350
  elementRef.current = element;
258
351
  if (onChange) element.on("change", onChange);
259
- if (onReady) element.on("ready", onReady);
352
+ element.on("ready", () => {
353
+ reportInteractive?.();
354
+ onReady?.();
355
+ });
260
356
  if (onFocus) element.on("focus", onFocus);
261
357
  if (onBlur) element.on("blur", onBlur);
262
358
  if (onEscape) element.on("escape", onEscape);
@@ -271,7 +367,7 @@ function createElementComponent(elementType, displayName) {
271
367
  elementRef.current = null;
272
368
  }
273
369
  };
274
- }, [elements]);
370
+ }, [elements, reportInteractive]);
275
371
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: containerRef, className, id, style });
276
372
  }
277
373
  ElementComponent.displayName = displayName;
@@ -360,42 +456,100 @@ function VaultCardFields({
360
456
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: containerRef, "data-testid": "flopay-vault-card-fields", style: containerStyle });
361
457
  }
362
458
 
459
+ // src/error-banner.tsx
460
+ var import_react6 = require("react");
461
+ var import_jsx_runtime5 = require("react/jsx-runtime");
462
+ function ErrorBanner({
463
+ children,
464
+ margin,
465
+ icon = true,
466
+ styleOverride
467
+ }) {
468
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
469
+ "div",
470
+ {
471
+ role: "alert",
472
+ "data-testid": "flopay-error",
473
+ style: {
474
+ margin,
475
+ padding: "0.625rem 0.875rem",
476
+ background: "#FEF2F2",
477
+ border: "1px solid #FECACA",
478
+ borderRadius: "8px",
479
+ color: "#991B1B",
480
+ fontSize: "0.85rem",
481
+ fontWeight: 600,
482
+ ...icon ? { display: "flex", alignItems: "center", gap: "0.5rem" } : {},
483
+ ...styleOverride ?? {}
484
+ },
485
+ children: [
486
+ icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
487
+ "path",
488
+ {
489
+ d: "M12 9v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z",
490
+ stroke: "#DC2626",
491
+ strokeWidth: "2",
492
+ strokeLinecap: "round",
493
+ strokeLinejoin: "round"
494
+ }
495
+ ) }),
496
+ children
497
+ ]
498
+ }
499
+ );
500
+ }
501
+
502
+ // src/payment-logos.generated.ts
503
+ var import_meta = {};
504
+ var PAYMENT_METHOD_LOGO_URLS = {
505
+ "alipay": new URL("./payment-logos/alipay.svg", import_meta.url).href,
506
+ "bancontact": new URL("./payment-logos/bancontact.svg", import_meta.url).href,
507
+ "blik": new URL("./payment-logos/blik.svg", import_meta.url).href,
508
+ "eps": new URL("./payment-logos/eps.svg", import_meta.url).href,
509
+ "giropay": new URL("./payment-logos/giropay.svg", import_meta.url).href,
510
+ "ideal": new URL("./payment-logos/ideal.svg", import_meta.url).href,
511
+ "klarna": new URL("./payment-logos/klarna.svg", import_meta.url).href,
512
+ "p24": new URL("./payment-logos/p24.svg", import_meta.url).href,
513
+ "sepa_debit": new URL("./payment-logos/sepa_debit.svg", import_meta.url).href,
514
+ "wechat_pay": new URL("./payment-logos/wechat_pay.svg", import_meta.url).href
515
+ };
516
+
363
517
  // src/split-card-form.tsx
364
- var import_react9 = __toESM(require("react"), 1);
518
+ var import_react10 = __toESM(require("react"), 1);
365
519
 
366
520
  // src/hooks.ts
367
- var import_react6 = require("react");
521
+ var import_react7 = require("react");
368
522
  var import_shared2 = require("@flopay/shared");
369
523
  function useFloPay() {
370
- const ctx = (0, import_react6.useContext)(FloPayContext);
524
+ const ctx = (0, import_react7.useContext)(FloPayContext);
371
525
  return ctx.flopay;
372
526
  }
373
527
  function usePayPalFloPay() {
374
- const ctx = (0, import_react6.useContext)(FloPayContext);
528
+ const ctx = (0, import_react7.useContext)(FloPayContext);
375
529
  return ctx.paypalFlopay ?? null;
376
530
  }
377
531
  function useElements() {
378
- const ctx = (0, import_react6.useContext)(FloPayContext);
532
+ const ctx = (0, import_react7.useContext)(FloPayContext);
379
533
  return ctx.elements;
380
534
  }
381
535
  function useCheckout() {
382
- return (0, import_react6.useContext)(CheckoutContext);
536
+ return (0, import_react7.useContext)(CheckoutContext);
383
537
  }
384
538
  function useBillingApiUrl() {
385
- const ctx = (0, import_react6.useContext)(FloPayContext);
539
+ const ctx = (0, import_react7.useContext)(FloPayContext);
386
540
  return ctx.billingApiUrl || (0, import_shared2.resolveBillingApiUrl)();
387
541
  }
388
542
 
389
543
  // src/processing-overlay.tsx
390
- var import_react7 = require("react");
391
- var import_jsx_runtime5 = require("react/jsx-runtime");
544
+ var import_react8 = require("react");
545
+ var import_jsx_runtime6 = require("react/jsx-runtime");
392
546
  var PROCESSING_OVERLAY_SUCCESS_DELAY_MS = 1200;
393
547
  var PROCESSING_OVERLAY_ERROR_DELAY_MS = 1500;
394
548
  function ProcessingOverlay({
395
549
  status,
396
550
  errorMessage
397
551
  }) {
398
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
552
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
399
553
  "div",
400
554
  {
401
555
  "data-testid": "flopay-processing-overlay",
@@ -412,7 +566,7 @@ function ProcessingOverlay({
412
566
  zIndex: 1e3,
413
567
  backdropFilter: "blur(2px)"
414
568
  },
415
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
569
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
416
570
  "div",
417
571
  {
418
572
  style: {
@@ -428,8 +582,8 @@ function ProcessingOverlay({
428
582
  gap: 16
429
583
  },
430
584
  children: [
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)(
585
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { width: 48, height: 48, position: "relative" }, children: [
586
+ status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
433
587
  "svg",
434
588
  {
435
589
  width: "48",
@@ -439,14 +593,14 @@ function ProcessingOverlay({
439
593
  xmlns: "http://www.w3.org/2000/svg",
440
594
  style: { animation: "flopay-spin 0.8s linear infinite" },
441
595
  children: [
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" })
596
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "#e5e7eb", strokeWidth: "3" }),
597
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z", fill: "#4A49FF" })
444
598
  ]
445
599
  }
446
600
  ),
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)(
601
+ status === "success" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { animation: "flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
602
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#22c55e" }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
450
604
  "path",
451
605
  {
452
606
  d: "M7 12.5l3 3 7-7",
@@ -462,9 +616,9 @@ function ProcessingOverlay({
462
616
  }
463
617
  )
464
618
  ] }) }),
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)(
619
+ status === "error" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { animation: "flopay-shake 0.4s ease" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
620
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "11", fill: "#ef4444" }),
621
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
468
622
  "path",
469
623
  {
470
624
  d: "M8 8l8 8M16 8l-8 8",
@@ -480,7 +634,7 @@ function ProcessingOverlay({
480
634
  )
481
635
  ] }) })
482
636
  ] }),
483
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
637
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
484
638
  "span",
485
639
  {
486
640
  style: {
@@ -496,7 +650,7 @@ function ProcessingOverlay({
496
650
  ]
497
651
  }
498
652
  ),
499
- status === "success" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
653
+ status === "success" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
500
654
  "p",
501
655
  {
502
656
  style: {
@@ -510,7 +664,7 @@ function ProcessingOverlay({
510
664
  children: "You will be automatically redirected, do not close or navigate away from this window."
511
665
  }
512
666
  ),
513
- status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
667
+ status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
514
668
  "p",
515
669
  {
516
670
  style: {
@@ -524,7 +678,7 @@ function ProcessingOverlay({
524
678
  children: errorMessage
525
679
  }
526
680
  ),
527
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
681
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
528
682
  @keyframes flopay-spin { to { transform: rotate(360deg); } }
529
683
  @keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
530
684
  @keyframes flopay-draw { to { stroke-dashoffset: 0; } }
@@ -686,6 +840,14 @@ async function buildFloPayApiErrorFromResponse(response, fallbackMessage) {
686
840
  const payload = await response.json().catch(() => null);
687
841
  return buildFloPayApiError(payload, fallbackMessage);
688
842
  }
843
+ function intentRequestHeaders(nonce) {
844
+ const headers = { "Content-Type": "application/json" };
845
+ if (nonce) headers["x-checkout-session-token"] = nonce;
846
+ return headers;
847
+ }
848
+ function isSuccessfulPaymentIntentStatus(status) {
849
+ return status === "succeeded" || status === "requires_capture" || status === "processing";
850
+ }
689
851
  function mapPayPalIntentStatusToPaymentResult(status) {
690
852
  if (status === "succeeded") {
691
853
  return "succeeded";
@@ -798,11 +960,24 @@ function isInAppBrowser(userAgent) {
798
960
  }
799
961
 
800
962
  // src/direct-paypal-button.tsx
801
- var import_react8 = require("react");
963
+ var import_react9 = require("react");
802
964
  var import_paypal_js = require("@paypal/paypal-js");
803
965
  var import_js = require("@flopay/js");
804
966
  var import_shared4 = require("@flopay/shared");
805
967
 
968
+ // src/merchant-callback.ts
969
+ function invokeMerchantCallback(callback) {
970
+ if (!callback) return;
971
+ const reportFailure = (error) => {
972
+ console.error("[FloPay] Merchant callback failed; checkout continued.", error);
973
+ };
974
+ try {
975
+ void Promise.resolve(callback()).catch(reportFailure);
976
+ } catch (error) {
977
+ reportFailure(error);
978
+ }
979
+ }
980
+
806
981
  // src/external-method-recovery.ts
807
982
  var EXTERNAL_METHOD_CALLBACK_GRACE_MS = 600;
808
983
  function getProviderErrorMessage(err) {
@@ -840,7 +1015,7 @@ function isPopupBlockedError(err) {
840
1015
  }
841
1016
 
842
1017
  // src/direct-paypal-button.tsx
843
- var import_jsx_runtime6 = require("react/jsx-runtime");
1018
+ var import_jsx_runtime7 = require("react/jsx-runtime");
844
1019
  var DEFAULT_BUTTON_HEIGHT = 45;
845
1020
  var DIRECT_PAYPAL_RECOVERY_MESSAGE = "We couldn't open PayPal. Try again or choose another payment method.";
846
1021
  var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
@@ -859,7 +1034,7 @@ var DIRECT_PAYPAL_RECOVERY_ACTION_STYLE = {
859
1034
  function buildDirectPayPalRecoveryMessage(popupBlocked) {
860
1035
  return popupBlocked ? `${DIRECT_PAYPAL_RECOVERY_MESSAGE} Allow pop-ups for this site, then try again.` : DIRECT_PAYPAL_RECOVERY_MESSAGE;
861
1036
  }
862
- function DirectPayPalButton({
1037
+ function DirectPayPalButtonImplementation({
863
1038
  sessionId,
864
1039
  nonce,
865
1040
  billingApiUrl,
@@ -879,101 +1054,149 @@ function DirectPayPalButton({
879
1054
  runBeforeButtonClick,
880
1055
  session,
881
1056
  existingOrderId,
1057
+ telemetry,
1058
+ telemetryContext,
882
1059
  debug = false
883
1060
  }) {
884
- const containerRef = (0, import_react8.useRef)(null);
885
- const focusTargetRef = (0, import_react8.useRef)(null);
886
- const pendingProviderFocusRef = (0, import_react8.useRef)(false);
887
- const [ready, setReady] = (0, import_react8.useState)(false);
888
- const [renderGeneration, setRenderGeneration] = (0, import_react8.useState)(0);
889
- const activeRenderGenerationRef = (0, import_react8.useRef)(0);
890
- const [showRetryFocusTarget, setShowRetryFocusTarget] = (0, import_react8.useState)(false);
891
- const [failed, setFailed] = (0, import_react8.useState)(false);
892
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
893
- const baseUrl = (0, import_react8.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
894
- const [debugLines, setDebugLines] = (0, import_react8.useState)([]);
1061
+ const flopay = useFloPay();
1062
+ const standaloneTelemetry = (0, import_react9.useMemo)(() => {
1063
+ if (flopay) return null;
1064
+ const reporter = createTelemetryBridge({
1065
+ billingApiUrl,
1066
+ sdkPackage: "@flopay/react",
1067
+ sdkVersion: import_shared4.SDK_VERSION,
1068
+ enabled: telemetry !== false
1069
+ });
1070
+ reporter.setCheckoutContext(telemetryContext ?? {});
1071
+ reporter.beginCheckout(telemetryContext ?? {});
1072
+ return reporter;
1073
+ }, [
1074
+ billingApiUrl,
1075
+ flopay,
1076
+ telemetry,
1077
+ telemetryContext?.checkoutMode,
1078
+ telemetryContext?.layout
1079
+ ]);
1080
+ const floPayTelemetry = (0, import_react9.useMemo)(() => getFloPayTelemetryBridge(flopay), [flopay]);
1081
+ (0, import_react9.useEffect)(() => () => {
1082
+ if (!standaloneTelemetry) return;
1083
+ void standaloneTelemetry.flush().catch(() => {
1084
+ }).finally(() => standaloneTelemetry.destroy());
1085
+ }, [standaloneTelemetry]);
1086
+ const telemetrySource = (0, import_react9.useMemo)(() => ({
1087
+ error: (input) => {
1088
+ if (floPayTelemetry) floPayTelemetry.error(input);
1089
+ else standaloneTelemetry?.error(input);
1090
+ },
1091
+ log: (input) => {
1092
+ if (floPayTelemetry) floPayTelemetry.log(input);
1093
+ else standaloneTelemetry?.log(input);
1094
+ },
1095
+ performance: (input) => {
1096
+ if (floPayTelemetry) floPayTelemetry.performance(input);
1097
+ else standaloneTelemetry?.performance(input);
1098
+ },
1099
+ terminal: (input) => {
1100
+ if (floPayTelemetry) floPayTelemetry.terminal(input);
1101
+ else standaloneTelemetry?.terminal(input);
1102
+ },
1103
+ startTiming: () => floPayTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
1104
+ elapsed: (startedAt) => floPayTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
1105
+ }), [floPayTelemetry, standaloneTelemetry]);
1106
+ const containerRef = (0, import_react9.useRef)(null);
1107
+ const providerStartedAt = (0, import_react9.useRef)(0);
1108
+ const focusTargetRef = (0, import_react9.useRef)(null);
1109
+ const pendingProviderFocusRef = (0, import_react9.useRef)(false);
1110
+ const [ready, setReady] = (0, import_react9.useState)(false);
1111
+ const [renderGeneration, setRenderGeneration] = (0, import_react9.useState)(0);
1112
+ const activeRenderGenerationRef = (0, import_react9.useRef)(0);
1113
+ const [showRetryFocusTarget, setShowRetryFocusTarget] = (0, import_react9.useState)(false);
1114
+ const [failed, setFailed] = (0, import_react9.useState)(false);
1115
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1116
+ const baseUrl = (0, import_react9.useMemo)(() => billingApiUrl.replace(/\/+$/, ""), [billingApiUrl]);
1117
+ const [debugLines, setDebugLines] = (0, import_react9.useState)([]);
895
1118
  const appendDebug = (line) => {
896
1119
  if (!debug) return;
897
1120
  setDebugLines((prev) => [...prev, `${(/* @__PURE__ */ new Date()).toISOString().slice(11, 23)} ${line}`]);
898
1121
  };
899
- const onTokenizedBodyRef = (0, import_react8.useRef)(onTokenizedBody);
900
- const onCompleteRef = (0, import_react8.useRef)(onComplete);
901
- const onErrorChangeRef = (0, import_react8.useRef)(onErrorChange);
902
- const onDeclineRef = (0, import_react8.useRef)(onDecline);
903
- const onTechnicalFailureRef = (0, import_react8.useRef)(onTechnicalFailure);
904
- const onButtonClickRef = (0, import_react8.useRef)(onButtonClick);
905
- const onLoadStateChangeRef = (0, import_react8.useRef)(onLoadStateChange);
906
- const runBeforeButtonClickRef = (0, import_react8.useRef)(runBeforeButtonClick);
907
- const sessionRef = (0, import_react8.useRef)(session);
908
- const emailRef = (0, import_react8.useRef)(email);
909
- const nonceRef = (0, import_react8.useRef)(nonce);
910
- const beforeClickRef = (0, import_react8.useRef)(null);
911
- const attemptGenerationRef = (0, import_react8.useRef)(0);
912
- const attemptRef = (0, import_react8.useRef)(null);
913
- const invalidatedAttemptGenerationRef = (0, import_react8.useRef)(null);
914
- const attemptContextBySurfaceRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
915
- const approvalContextByTokenRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
916
- (0, import_react8.useEffect)(() => {
1122
+ const onTokenizedBodyRef = (0, import_react9.useRef)(onTokenizedBody);
1123
+ const onCompleteRef = (0, import_react9.useRef)(onComplete);
1124
+ const onErrorChangeRef = (0, import_react9.useRef)(onErrorChange);
1125
+ const onDeclineRef = (0, import_react9.useRef)(onDecline);
1126
+ const onTechnicalFailureRef = (0, import_react9.useRef)(onTechnicalFailure);
1127
+ const onButtonClickRef = (0, import_react9.useRef)(onButtonClick);
1128
+ const onLoadStateChangeRef = (0, import_react9.useRef)(onLoadStateChange);
1129
+ const runBeforeButtonClickRef = (0, import_react9.useRef)(runBeforeButtonClick);
1130
+ const sessionRef = (0, import_react9.useRef)(session);
1131
+ const emailRef = (0, import_react9.useRef)(email);
1132
+ const nonceRef = (0, import_react9.useRef)(nonce);
1133
+ const beforeClickRef = (0, import_react9.useRef)(null);
1134
+ const attemptGenerationRef = (0, import_react9.useRef)(0);
1135
+ const attemptRef = (0, import_react9.useRef)(null);
1136
+ const invalidatedAttemptGenerationRef = (0, import_react9.useRef)(null);
1137
+ const attemptContextBySurfaceRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
1138
+ const approvalContextByTokenRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
1139
+ (0, import_react9.useEffect)(() => {
917
1140
  onTokenizedBodyRef.current = onTokenizedBody;
918
1141
  }, [onTokenizedBody]);
919
- (0, import_react8.useEffect)(() => {
1142
+ (0, import_react9.useEffect)(() => {
920
1143
  onCompleteRef.current = onComplete;
921
1144
  }, [onComplete]);
922
- (0, import_react8.useEffect)(() => {
1145
+ (0, import_react9.useEffect)(() => {
923
1146
  onErrorChangeRef.current = onErrorChange;
924
1147
  }, [onErrorChange]);
925
- (0, import_react8.useEffect)(() => {
1148
+ (0, import_react9.useEffect)(() => {
926
1149
  onDeclineRef.current = onDecline;
927
1150
  }, [onDecline]);
928
- (0, import_react8.useEffect)(() => {
1151
+ (0, import_react9.useEffect)(() => {
929
1152
  onTechnicalFailureRef.current = onTechnicalFailure;
930
1153
  }, [onTechnicalFailure]);
931
- (0, import_react8.useEffect)(() => {
1154
+ (0, import_react9.useEffect)(() => {
932
1155
  onButtonClickRef.current = onButtonClick;
933
1156
  }, [onButtonClick]);
934
- (0, import_react8.useEffect)(() => {
1157
+ (0, import_react9.useEffect)(() => {
935
1158
  onLoadStateChangeRef.current = onLoadStateChange;
936
1159
  }, [onLoadStateChange]);
937
- (0, import_react8.useEffect)(() => {
1160
+ (0, import_react9.useEffect)(() => {
938
1161
  runBeforeButtonClickRef.current = runBeforeButtonClick;
939
1162
  }, [runBeforeButtonClick]);
940
- (0, import_react8.useEffect)(() => {
1163
+ (0, import_react9.useEffect)(() => {
941
1164
  sessionRef.current = session;
942
1165
  }, [session]);
943
- (0, import_react8.useEffect)(() => {
1166
+ (0, import_react9.useEffect)(() => {
944
1167
  emailRef.current = email;
945
1168
  }, [email]);
946
- (0, import_react8.useEffect)(() => {
1169
+ (0, import_react9.useEffect)(() => {
947
1170
  nonceRef.current = nonce;
948
1171
  }, [nonce]);
949
- (0, import_react8.useEffect)(() => {
1172
+ (0, import_react9.useEffect)(() => {
950
1173
  activeRenderGenerationRef.current = renderGeneration;
951
1174
  }, [renderGeneration]);
952
- (0, import_react8.useEffect)(() => {
1175
+ (0, import_react9.useEffect)(() => {
953
1176
  if (showRetryFocusTarget) focusTargetRef.current?.focus();
954
1177
  }, [showRetryFocusTarget, renderGeneration]);
955
- const focusRetryTarget = (0, import_react8.useCallback)(() => {
1178
+ const focusRetryTarget = (0, import_react9.useCallback)(() => {
956
1179
  window.setTimeout(() => {
957
1180
  focusTargetRef.current?.focus();
958
1181
  }, 0);
959
1182
  }, []);
960
- const remountPayPalButtons = (0, import_react8.useCallback)(() => {
1183
+ const remountPayPalButtons = (0, import_react9.useCallback)(() => {
961
1184
  setReady(false);
962
1185
  setRenderGeneration((current) => current + 1);
963
1186
  }, []);
964
- const focusPayPalSurface = (0, import_react8.useCallback)(() => {
1187
+ const focusPayPalSurface = (0, import_react9.useCallback)(() => {
965
1188
  setShowRetryFocusTarget(false);
966
1189
  const target = containerRef.current?.querySelector(
967
1190
  'iframe, button, [tabindex]:not([tabindex="-1"])'
968
1191
  );
969
1192
  (target ?? containerRef.current)?.focus?.();
970
1193
  }, []);
971
- (0, import_react8.useEffect)(() => {
1194
+ (0, import_react9.useEffect)(() => {
972
1195
  if (!ready || !pendingProviderFocusRef.current) return;
973
1196
  pendingProviderFocusRef.current = false;
974
1197
  focusPayPalSurface();
975
1198
  }, [focusPayPalSurface, ready, renderGeneration]);
976
- const notifyTechnicalFailure = (0, import_react8.useCallback)((err, options) => {
1199
+ const notifyTechnicalFailure = (0, import_react9.useCallback)((err, options) => {
977
1200
  const handler = onTechnicalFailureRef.current;
978
1201
  if (handler) {
979
1202
  handler("paypal", err, options);
@@ -1051,7 +1274,7 @@ function DirectPayPalButton({
1051
1274
  }
1052
1275
  return token;
1053
1276
  };
1054
- (0, import_react8.useEffect)(() => {
1277
+ (0, import_react9.useEffect)(() => {
1055
1278
  const handleVisibilityChange = () => {
1056
1279
  if (document.visibilityState === "visible") {
1057
1280
  scheduleMissingCallbackRecovery();
@@ -1069,11 +1292,11 @@ function DirectPayPalButton({
1069
1292
  clearAttemptTimer();
1070
1293
  };
1071
1294
  }, []);
1072
- (0, import_react8.useEffect)(() => {
1073
- onLoadStateChangeRef.current?.(ready && !failed);
1295
+ (0, import_react9.useEffect)(() => {
1296
+ invokeMerchantCallback(() => onLoadStateChangeRef.current?.(ready && !failed));
1074
1297
  }, [ready, failed]);
1075
1298
  const normalizedEnv = (0, import_shared4.normalizeGatewayEnvironment)(environment);
1076
- (0, import_react8.useEffect)(() => {
1299
+ (0, import_react9.useEffect)(() => {
1077
1300
  const maskedClient = clientId ? `${clientId.slice(0, 6)}\u2026(len ${clientId.length})` : "(empty)";
1078
1301
  const ua = typeof navigator !== "undefined" ? navigator.userAgent : "(no navigator)";
1079
1302
  appendDebug(`mount clientId=${maskedClient} env=${environment ?? "(unset)"}\u2192${normalizedEnv ?? "live"} ccy=${currency} sub=${isSubscription}`);
@@ -1081,6 +1304,13 @@ function DirectPayPalButton({
1081
1304
  if (!clientId) {
1082
1305
  appendDebug("FAIL: clientId empty \u2014 gateway misconfigured");
1083
1306
  setFailed(true);
1307
+ telemetrySource.error({
1308
+ errorCode: "CONFIGURATION_INVALID",
1309
+ stage: "provider_load",
1310
+ provider: "paypal",
1311
+ paymentMethodCategory: "paypal",
1312
+ requestCategory: "provider_sdk"
1313
+ });
1084
1314
  console.error("[FloPay] DirectPayPal: clientId empty \u2014 gateway misconfigured");
1085
1315
  return;
1086
1316
  }
@@ -1088,8 +1318,33 @@ function DirectPayPalButton({
1088
1318
  appendDebug("FAIL: containerRef not attached");
1089
1319
  return;
1090
1320
  }
1321
+ providerStartedAt.current = telemetrySource.startTiming();
1322
+ telemetrySource.log({
1323
+ name: "provider.load.started",
1324
+ stage: "provider_load",
1325
+ provider: "paypal",
1326
+ paymentMethodCategory: "paypal"
1327
+ });
1091
1328
  let cancelled = false;
1092
1329
  let activeButtons = null;
1330
+ let overlayStartedAt = null;
1331
+ const finishOverlay = () => {
1332
+ if (overlayStartedAt === null) return;
1333
+ telemetrySource.log({
1334
+ name: "provider.overlay.returned",
1335
+ stage: "overlay_return",
1336
+ provider: "paypal",
1337
+ paymentMethodCategory: "paypal"
1338
+ });
1339
+ telemetrySource.performance({
1340
+ stage: "overlay_return",
1341
+ durationMs: telemetrySource.elapsed(overlayStartedAt),
1342
+ durationMode: "buyer",
1343
+ provider: "paypal",
1344
+ paymentMethodCategory: "paypal"
1345
+ });
1346
+ overlayStartedAt = null;
1347
+ };
1093
1348
  let rendered = false;
1094
1349
  const container = containerRef.current;
1095
1350
  let containerObserver = null;
@@ -1193,7 +1448,7 @@ function DirectPayPalButton({
1193
1448
  if (cancelled) return;
1194
1449
  if (isZoidLifecycleMessage(message)) return;
1195
1450
  const friendly = applyFriendlyMessageOverride(message) ?? message;
1196
- onErrorChangeRef.current?.(friendly);
1451
+ invokeMerchantCallback(() => onErrorChangeRef.current?.(friendly));
1197
1452
  };
1198
1453
  const markRenderFailed = (message) => {
1199
1454
  if (cancelled) return;
@@ -1202,24 +1457,55 @@ function DirectPayPalButton({
1202
1457
  return;
1203
1458
  }
1204
1459
  setFailed(true);
1460
+ if (!message.includes("paypal_ineligible")) {
1461
+ telemetrySource.error({
1462
+ errorCode: "PROVIDER_LOAD_FAILED",
1463
+ stage: "provider_load",
1464
+ provider: "paypal",
1465
+ paymentMethodCategory: "paypal",
1466
+ requestCategory: "provider_sdk"
1467
+ });
1468
+ }
1205
1469
  console.error("[FloPay] DirectPayPal load/render failure:", message);
1206
1470
  };
1207
1471
  setFailed(false);
1208
1472
  const dispatchTokenizedBody = async (body, prepared = beforeClickRef.current) => {
1209
1473
  const effectiveSessionId = prepared?.sessionId ?? sessionId;
1210
1474
  if (onTokenizedBodyRef.current) {
1211
- onTokenizedBodyRef.current(body, {
1475
+ await onTokenizedBodyRef.current(body, {
1212
1476
  sessionId: effectiveSessionId,
1213
1477
  accountPatch: prepared?.accountPatch,
1214
1478
  nonce: prepared?.nonce
1215
1479
  });
1216
1480
  return;
1217
1481
  }
1482
+ const processingStartedAt = telemetrySource.startTiming();
1483
+ telemetrySource.log({
1484
+ name: "payment.processing.started",
1485
+ stage: "processing",
1486
+ provider: "paypal",
1487
+ paymentMethodCategory: "paypal"
1488
+ });
1489
+ const finishProcessing = () => {
1490
+ telemetrySource.log({
1491
+ name: "payment.processing.completed",
1492
+ stage: "processing",
1493
+ provider: "paypal",
1494
+ paymentMethodCategory: "paypal"
1495
+ });
1496
+ telemetrySource.performance({
1497
+ stage: "processing",
1498
+ durationMs: telemetrySource.elapsed(processingStartedAt),
1499
+ durationMode: "machine",
1500
+ provider: "paypal",
1501
+ paymentMethodCategory: "paypal"
1502
+ });
1503
+ };
1218
1504
  try {
1219
1505
  const currentSession = sessionRef.current;
1220
1506
  const currentEmail = prepared?.accountPatch?.email ?? emailRef.current;
1221
1507
  const effectiveUserId = prepared?.accountPatch?.userId ?? currentSession?.customer?.id ?? currentSession?.accountData?.userId ?? "";
1222
- const api = new import_js.PaymentAPI(baseUrl);
1508
+ const api = new import_js.PaymentAPI(baseUrl, { telemetry: false });
1223
1509
  const response = await api.processPayment(
1224
1510
  effectiveUserId,
1225
1511
  {
@@ -1237,31 +1523,71 @@ function DirectPayPalButton({
1237
1523
  }
1238
1524
  );
1239
1525
  if (response.ok) {
1240
- onCompleteRef.current?.({ status: "succeeded", checkoutMethod: "paypal" });
1526
+ finishProcessing();
1527
+ telemetrySource.terminal({
1528
+ outcome: "payment_succeeded",
1529
+ provider: "paypal",
1530
+ paymentMethodCategory: "paypal"
1531
+ });
1532
+ } else {
1533
+ const json = await response.json().catch(() => null);
1534
+ const rawMessage = json?.["message"] ?? "PayPal payment failed.";
1535
+ const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
1536
+ finishProcessing();
1537
+ if (typeof json?.["declineCode"] === "string") {
1538
+ telemetrySource.terminal({
1539
+ outcome: "payment_declined",
1540
+ provider: "paypal",
1541
+ paymentMethodCategory: "paypal"
1542
+ });
1543
+ } else {
1544
+ telemetrySource.error({
1545
+ errorCode: "PAYMENT_PROCESSING_FAILED",
1546
+ stage: "processing",
1547
+ provider: "paypal",
1548
+ paymentMethodCategory: "paypal",
1549
+ requestCategory: "process_payment",
1550
+ statusClass: response.status >= 500 ? "5xx" : response.status >= 400 ? "4xx" : response.status >= 300 ? "3xx" : "unknown"
1551
+ });
1552
+ }
1553
+ forwardError(message);
1554
+ invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
1555
+ code: json?.["code"],
1556
+ declineCode: json?.["declineCode"]
1557
+ })));
1241
1558
  return;
1242
1559
  }
1243
- const json = await response.json().catch(() => null);
1244
- const rawMessage = json?.["message"] ?? "PayPal payment failed.";
1245
- const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
1246
- forwardError(message);
1247
- onDeclineRef.current?.(buildDeclineEvent("paypal", message, {
1248
- code: json?.["code"],
1249
- declineCode: json?.["declineCode"]
1250
- }));
1251
1560
  } catch (err) {
1561
+ finishProcessing();
1562
+ telemetrySource.error({
1563
+ errorCode: "NETWORK_REQUEST_FAILED",
1564
+ stage: "processing",
1565
+ provider: "paypal",
1566
+ paymentMethodCategory: "paypal",
1567
+ requestCategory: "process_payment",
1568
+ statusClass: "network_error"
1569
+ });
1252
1570
  const rawMessage = err instanceof Error ? err.message : "PayPal payment failed.";
1253
1571
  const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
1254
1572
  forwardError(message);
1255
- onDeclineRef.current?.(buildDeclineEvent("paypal", message));
1573
+ invokeMerchantCallback(() => onDeclineRef.current?.(buildDeclineEvent("paypal", message)));
1574
+ return;
1256
1575
  }
1576
+ invokeMerchantCallback(() => onCompleteRef.current?.({ status: "succeeded", checkoutMethod: "paypal" }));
1257
1577
  };
1258
1578
  const createPaypalIntent = async (fallbackMessage) => {
1259
1579
  const prepared = beforeClickRef.current;
1260
1580
  const effectiveSessionId = prepared?.sessionId ?? sessionId;
1261
1581
  const effectiveEmail = prepared?.accountPatch?.email ?? emailRef.current;
1262
- const intentHeaders = { "Content-Type": "application/json" };
1263
1582
  const currentNonce = prepared?.nonce ?? nonceRef.current;
1264
- if (currentNonce) intentHeaders["x-checkout-session-token"] = currentNonce;
1583
+ const intentHeaders = intentRequestHeaders(currentNonce);
1584
+ telemetrySource.log({
1585
+ name: "payment.intent.started",
1586
+ stage: "processing",
1587
+ provider: "paypal",
1588
+ paymentMethodCategory: "paypal",
1589
+ requestCategory: "intent_create"
1590
+ });
1265
1591
  const response = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
1266
1592
  method: "POST",
1267
1593
  headers: intentHeaders,
@@ -1280,6 +1606,14 @@ function DirectPayPalButton({
1280
1606
  if (!id) {
1281
1607
  throw new Error(fallbackMessage);
1282
1608
  }
1609
+ telemetrySource.log({
1610
+ name: "payment.intent.completed",
1611
+ stage: "processing",
1612
+ provider: "paypal",
1613
+ paymentMethodCategory: "paypal",
1614
+ requestCategory: "intent_create",
1615
+ statusClass: "2xx"
1616
+ });
1283
1617
  return id;
1284
1618
  };
1285
1619
  const effectRenderGeneration = renderGeneration;
@@ -1314,6 +1648,12 @@ function DirectPayPalButton({
1314
1648
  if (!cancelled && !paypal?.Buttons) appendDebug("FAIL: namespace missing Buttons factory");
1315
1649
  return;
1316
1650
  }
1651
+ telemetrySource.log({
1652
+ name: "provider.availability.checked",
1653
+ stage: "provider_ready",
1654
+ provider: "paypal",
1655
+ paymentMethodCategory: "paypal"
1656
+ });
1317
1657
  const handleApprove = async (data) => {
1318
1658
  if (cancelled || activeRenderGenerationRef.current !== effectRenderGeneration) return;
1319
1659
  const token = data.subscriptionID ?? data.orderID ?? "";
@@ -1322,9 +1662,10 @@ function DirectPayPalButton({
1322
1662
  if (!finishAttempt(context.generation)) return;
1323
1663
  approvalContextByTokenRef.current.delete(token);
1324
1664
  attemptContextBySurfaceRef.current.delete(context.surfaceKey);
1665
+ finishOverlay();
1325
1666
  try {
1326
1667
  setSubmitting(true);
1327
- onErrorChangeRef.current?.(null);
1668
+ invokeMerchantCallback(() => onErrorChangeRef.current?.(null));
1328
1669
  if (!token) {
1329
1670
  throw new import_shared4.FloPayError(
1330
1671
  "PayPal did not return an approval token.",
@@ -1374,7 +1715,7 @@ function DirectPayPalButton({
1374
1715
  return;
1375
1716
  }
1376
1717
  }
1377
- onButtonClickRef.current?.("paypal");
1718
+ invokeMerchantCallback(() => onButtonClickRef.current?.("paypal"));
1378
1719
  const generation = startAttempt();
1379
1720
  const context = {
1380
1721
  generation,
@@ -1384,6 +1725,25 @@ function DirectPayPalButton({
1384
1725
  beforeClickRef.current = context;
1385
1726
  attemptContextBySurfaceRef.current.set(effectRenderGeneration, context);
1386
1727
  await actions.resolve();
1728
+ telemetrySource.log({
1729
+ name: "payment.method.selected",
1730
+ stage: "processing",
1731
+ provider: "paypal",
1732
+ paymentMethodCategory: "paypal"
1733
+ });
1734
+ telemetrySource.log({
1735
+ name: "provider.popup.opened",
1736
+ stage: "overlay_open",
1737
+ provider: "paypal",
1738
+ paymentMethodCategory: "paypal"
1739
+ });
1740
+ telemetrySource.log({
1741
+ name: "provider.overlay.opened",
1742
+ stage: "overlay_open",
1743
+ provider: "paypal",
1744
+ paymentMethodCategory: "paypal"
1745
+ });
1746
+ overlayStartedAt = telemetrySource.startTiming();
1387
1747
  },
1388
1748
  // When the SDK is already holding an order/subscription id from a
1389
1749
  // prior backend round-trip (the `paypal_direct_required` retry
@@ -1396,6 +1756,12 @@ function DirectPayPalButton({
1396
1756
  const context = attemptContextBySurfaceRef.current.get(effectRenderGeneration) ?? beforeClickRef.current;
1397
1757
  if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
1398
1758
  beforeClickRef.current = null;
1759
+ finishOverlay();
1760
+ telemetrySource.terminal({
1761
+ outcome: "payment_cancelled",
1762
+ provider: "paypal",
1763
+ paymentMethodCategory: "paypal"
1764
+ });
1399
1765
  pendingProviderFocusRef.current = true;
1400
1766
  invalidateAttempt({ generation: context?.generation, remount: true, focus: false });
1401
1767
  },
@@ -1411,6 +1777,15 @@ function DirectPayPalButton({
1411
1777
  finishAttempt(context?.generation);
1412
1778
  return;
1413
1779
  }
1780
+ finishOverlay();
1781
+ const lower = message.toLowerCase();
1782
+ telemetrySource.error({
1783
+ errorCode: lower.includes("popup") && lower.includes("block") ? "POPUP_BLOCKED" : "PROVIDER_RUNTIME_FAILED",
1784
+ stage: "provider_ready",
1785
+ provider: "paypal",
1786
+ paymentMethodCategory: "paypal",
1787
+ requestCategory: "provider_sdk"
1788
+ });
1414
1789
  if (context) attemptContextBySurfaceRef.current.delete(context.surfaceKey);
1415
1790
  beforeClickRef.current = null;
1416
1791
  invalidateAttempt({ generation: context?.generation, remount: true, showRetry: true, focus: true });
@@ -1422,6 +1797,12 @@ function DirectPayPalButton({
1422
1797
  });
1423
1798
  const eligible = buttons.isEligible();
1424
1799
  appendDebug(`isEligible=${eligible}`);
1800
+ telemetrySource.log({
1801
+ name: "provider.eligibility.checked",
1802
+ stage: "provider_ready",
1803
+ provider: "paypal",
1804
+ paymentMethodCategory: "paypal"
1805
+ });
1425
1806
  if (!eligible) {
1426
1807
  setReady(false);
1427
1808
  markRenderFailed(
@@ -1493,6 +1874,19 @@ function DirectPayPalButton({
1493
1874
  activeButtons = typedButtons;
1494
1875
  rendered = true;
1495
1876
  setReady(true);
1877
+ telemetrySource.log({
1878
+ name: "provider.ready",
1879
+ stage: "provider_ready",
1880
+ provider: "paypal",
1881
+ paymentMethodCategory: "paypal"
1882
+ });
1883
+ telemetrySource.performance({
1884
+ stage: "provider_ready",
1885
+ durationMs: telemetrySource.elapsed(providerStartedAt.current),
1886
+ durationMode: "machine",
1887
+ provider: "paypal",
1888
+ paymentMethodCategory: "paypal"
1889
+ });
1496
1890
  }).catch((err) => {
1497
1891
  const message = err instanceof Error ? err.message : "PayPal failed to render.";
1498
1892
  appendDebug(`render:rejected msg=${message.slice(0, 120)}`);
@@ -1514,8 +1908,8 @@ function DirectPayPalButton({
1514
1908
  });
1515
1909
  }
1516
1910
  };
1517
- }, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration]);
1518
- const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1911
+ }, [baseUrl, clientId, currency, environment, isSubscription, sessionId, existingOrderId, renderGeneration, telemetrySource]);
1912
+ const debugPanel = debug ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1519
1913
  "pre",
1520
1914
  {
1521
1915
  "data-testid": "flopay-direct-paypal-debug",
@@ -1540,17 +1934,17 @@ ${debugLines.join("\n")}`
1540
1934
  }
1541
1935
  ) : null;
1542
1936
  if (failed) {
1543
- return debug ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: debugPanel }) : null;
1937
+ return debug ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: debugPanel }) : null;
1544
1938
  }
1545
1939
  return (
1546
1940
  // Single wrapper so the parent flex container sees exactly one flex item
1547
1941
  // (otherwise the fragment's placeholder + container become two siblings
1548
1942
  // and any spacing-sensitive layout has to reason about both). The wrapper
1549
1943
  // intentionally has no margin/padding so the parent owns all spacing.
1550
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1944
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1551
1945
  debugPanel,
1552
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1553
- !ready && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1946
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: DEFAULT_BUTTON_HEIGHT }, children: [
1947
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1554
1948
  "div",
1555
1949
  {
1556
1950
  "data-testid": "flopay-direct-paypal-placeholder",
@@ -1564,7 +1958,7 @@ ${debugLines.join("\n")}`
1564
1958
  }
1565
1959
  }
1566
1960
  ),
1567
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1961
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1568
1962
  "div",
1569
1963
  {
1570
1964
  ref: containerRef,
@@ -1581,7 +1975,7 @@ ${debugLines.join("\n")}`
1581
1975
  renderGeneration
1582
1976
  )
1583
1977
  ] }),
1584
- showRetryFocusTarget && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1978
+ showRetryFocusTarget && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1585
1979
  "button",
1586
1980
  {
1587
1981
  ref: focusTargetRef,
@@ -1595,10 +1989,16 @@ ${debugLines.join("\n")}`
1595
1989
  ] })
1596
1990
  );
1597
1991
  }
1992
+ function DirectPayPalButton(props) {
1993
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DirectPayPalButtonImplementation, { ...props });
1994
+ }
1995
+ function InstrumentedDirectPayPalButton(props) {
1996
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DirectPayPalButtonImplementation, { ...props });
1997
+ }
1598
1998
 
1599
1999
  // src/split-card-form.tsx
1600
2000
  var import_shared6 = require("@flopay/shared");
1601
- var import_jsx_runtime7 = require("react/jsx-runtime");
2001
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1602
2002
  var STRIPE_RESUME_KEY = "flopay_stripe_resume";
1603
2003
  var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
1604
2004
  var PAYPAL_RESUME_KEY = "flopay_paypal_resume";
@@ -1713,17 +2113,17 @@ function buildExternalMethodRecoveryMessage(method, popupBlocked) {
1713
2113
  return popupBlocked ? `${base} Allow pop-ups for this site, then try again.` : base;
1714
2114
  }
1715
2115
  function useExternalAttemptReconciliation(onMissingTerminal) {
1716
- const generationRef = (0, import_react9.useRef)(0);
1717
- const invalidatedGenerationRef = (0, import_react9.useRef)(null);
1718
- const attemptRef = (0, import_react9.useRef)(null);
1719
- const clearAttemptTimer = (0, import_react9.useCallback)((targetAttempt = attemptRef.current) => {
2116
+ const generationRef = (0, import_react10.useRef)(0);
2117
+ const invalidatedGenerationRef = (0, import_react10.useRef)(null);
2118
+ const attemptRef = (0, import_react10.useRef)(null);
2119
+ const clearAttemptTimer = (0, import_react10.useCallback)((targetAttempt = attemptRef.current) => {
1720
2120
  const attempt = targetAttempt;
1721
2121
  if (attempt?.timer) {
1722
2122
  clearTimeout(attempt.timer);
1723
2123
  attempt.timer = null;
1724
2124
  }
1725
2125
  }, []);
1726
- const armAttemptTimer = (0, import_react9.useCallback)((attempt, delayMs) => {
2126
+ const armAttemptTimer = (0, import_react10.useCallback)((attempt, delayMs) => {
1727
2127
  if (typeof document !== "undefined" && document.visibilityState !== "visible") return;
1728
2128
  clearAttemptTimer(attempt);
1729
2129
  attempt.timer = setTimeout(() => {
@@ -1738,11 +2138,11 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
1738
2138
  );
1739
2139
  }, delayMs);
1740
2140
  }, [clearAttemptTimer, onMissingTerminal]);
1741
- const armRecoveryTimer = (0, import_react9.useCallback)((attempt) => {
2141
+ const armRecoveryTimer = (0, import_react10.useCallback)((attempt) => {
1742
2142
  if (!attempt.yieldedControl) return;
1743
2143
  armAttemptTimer(attempt, EXTERNAL_METHOD_CALLBACK_GRACE_MS);
1744
2144
  }, [armAttemptTimer]);
1745
- const startAttempt = (0, import_react9.useCallback)((method) => {
2145
+ const startAttempt = (0, import_react10.useCallback)((method) => {
1746
2146
  clearAttemptTimer();
1747
2147
  const generation = generationRef.current + 1;
1748
2148
  generationRef.current = generation;
@@ -1751,7 +2151,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
1751
2151
  attemptRef.current = attempt;
1752
2152
  return generation;
1753
2153
  }, [clearAttemptTimer]);
1754
- const finishAttempt = (0, import_react9.useCallback)((generation) => {
2154
+ const finishAttempt = (0, import_react10.useCallback)((generation) => {
1755
2155
  const attempt = attemptRef.current;
1756
2156
  if (typeof generation === "number" && attempt?.generation !== generation) return false;
1757
2157
  clearAttemptTimer(attempt);
@@ -1761,7 +2161,7 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
1761
2161
  }
1762
2162
  return true;
1763
2163
  }, [clearAttemptTimer]);
1764
- const invalidateAttempt = (0, import_react9.useCallback)((generation) => {
2164
+ const invalidateAttempt = (0, import_react10.useCallback)((generation) => {
1765
2165
  const attempt = attemptRef.current;
1766
2166
  const targetGeneration = generation ?? attempt?.generation ?? generationRef.current;
1767
2167
  if (!generation || attempt?.generation === generation) {
@@ -1770,26 +2170,26 @@ function useExternalAttemptReconciliation(onMissingTerminal) {
1770
2170
  }
1771
2171
  invalidatedGenerationRef.current = targetGeneration;
1772
2172
  }, [clearAttemptTimer]);
1773
- const isAttemptInvalidated = (0, import_react9.useCallback)(
2173
+ const isAttemptInvalidated = (0, import_react10.useCallback)(
1774
2174
  (generation) => invalidatedGenerationRef.current === (generation ?? generationRef.current),
1775
2175
  []
1776
2176
  );
1777
- const isAttemptCurrent = (0, import_react9.useCallback)(
2177
+ const isAttemptCurrent = (0, import_react10.useCallback)(
1778
2178
  (generation) => attemptRef.current?.generation === generation && invalidatedGenerationRef.current !== generation,
1779
2179
  []
1780
2180
  );
1781
- const scheduleRecoveryIfReturned = (0, import_react9.useCallback)(() => {
2181
+ const scheduleRecoveryIfReturned = (0, import_react10.useCallback)(() => {
1782
2182
  const attempt = attemptRef.current;
1783
2183
  if (!attempt) return;
1784
2184
  armRecoveryTimer(attempt);
1785
2185
  }, [armRecoveryTimer]);
1786
- const markAttemptYieldedControl = (0, import_react9.useCallback)(() => {
2186
+ const markAttemptYieldedControl = (0, import_react10.useCallback)(() => {
1787
2187
  const attempt = attemptRef.current;
1788
2188
  if (!attempt) return;
1789
2189
  attempt.yieldedControl = true;
1790
2190
  clearAttemptTimer(attempt);
1791
2191
  }, [clearAttemptTimer]);
1792
- (0, import_react9.useEffect)(() => {
2192
+ (0, import_react10.useEffect)(() => {
1793
2193
  const handleVisibilityChange = () => {
1794
2194
  if (document.visibilityState === "visible") {
1795
2195
  scheduleRecoveryIfReturned();
@@ -1831,7 +2231,7 @@ function normalizeBeforeButtonClickError(method, err) {
1831
2231
  );
1832
2232
  }
1833
2233
  function FloPayKeyframes() {
1834
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: FLOPAY_KEYFRAMES });
2234
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: FLOPAY_KEYFRAMES });
1835
2235
  }
1836
2236
  function toCssSize(value) {
1837
2237
  if (typeof value === "number") return `${value}px`;
@@ -1853,8 +2253,8 @@ function ExpressCheckoutReadySwap({
1853
2253
  children
1854
2254
  }) {
1855
2255
  if (state === "unavailable" || state === "load_error") return null;
1856
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
1857
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2256
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { position: "relative", minHeight: 44 }, children: [
2257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1858
2258
  "div",
1859
2259
  {
1860
2260
  "data-testid": placeholderTestId,
@@ -1873,7 +2273,7 @@ function ExpressCheckoutReadySwap({
1873
2273
  }
1874
2274
  }
1875
2275
  ),
1876
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2276
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1877
2277
  "div",
1878
2278
  {
1879
2279
  style: {
@@ -1891,9 +2291,9 @@ function ExpressCheckoutReadySwap({
1891
2291
  function isExpressCheckoutRowVisible(state) {
1892
2292
  return state !== "unavailable" && state !== "load_error";
1893
2293
  }
1894
- var SplitCardForm = (0, import_react9.forwardRef)(
2294
+ var SplitCardForm = (0, import_react10.forwardRef)(
1895
2295
  function SplitCardForm2(props, ref) {
1896
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
2296
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SplitCardFormInner, { ...props, innerRef: ref });
1897
2297
  }
1898
2298
  );
1899
2299
  function PayPalButtonInner({
@@ -1911,20 +2311,21 @@ function PayPalButtonInner({
1911
2311
  onLoadStateChange,
1912
2312
  placeholderBorderRadius
1913
2313
  }) {
2314
+ const flopay = useFloPay();
1914
2315
  const stripe = (0, import_react_stripe_js.useStripe)();
1915
2316
  const elements = (0, import_react_stripe_js.useElements)();
1916
- const [loadState, setLoadState] = (0, import_react9.useState)("loading");
1917
- (0, import_react9.useEffect)(() => {
2317
+ const [loadState, setLoadState] = (0, import_react10.useState)("loading");
2318
+ (0, import_react10.useEffect)(() => {
1918
2319
  onLoadStateChange?.(loadState);
1919
2320
  }, [loadState, onLoadStateChange]);
1920
- const [submitting, setSubmitting] = (0, import_react9.useState)(false);
1921
- const paypalResumeAttempted = (0, import_react9.useRef)(false);
1922
- const focusTargetRef = (0, import_react9.useRef)(null);
1923
- const recoveryActionRef = (0, import_react9.useRef)(null);
1924
- const [surfaceKey, setSurfaceKey] = (0, import_react9.useState)(0);
1925
- const [showRecoveryAction, setShowRecoveryAction] = (0, import_react9.useState)(false);
1926
- const pendingProviderFocusRef = (0, import_react9.useRef)(false);
1927
- const attemptContextBySurfaceRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
2321
+ const [submitting, setSubmitting] = (0, import_react10.useState)(false);
2322
+ const paypalResumeAttempted = (0, import_react10.useRef)(false);
2323
+ const focusTargetRef = (0, import_react10.useRef)(null);
2324
+ const recoveryActionRef = (0, import_react10.useRef)(null);
2325
+ const [surfaceKey, setSurfaceKey] = (0, import_react10.useState)(0);
2326
+ const [showRecoveryAction, setShowRecoveryAction] = (0, import_react10.useState)(false);
2327
+ const pendingProviderFocusRef = (0, import_react10.useRef)(false);
2328
+ const attemptContextBySurfaceRef = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
1928
2329
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
1929
2330
  const {
1930
2331
  startAttempt,
@@ -1940,35 +2341,35 @@ function PayPalButtonInner({
1940
2341
  setShowRecoveryAction(true);
1941
2342
  setSurfaceKey((key) => key + 1);
1942
2343
  });
1943
- (0, import_react9.useEffect)(() => {
2344
+ (0, import_react10.useEffect)(() => {
1944
2345
  if (showRecoveryAction) recoveryActionRef.current?.focus();
1945
2346
  }, [showRecoveryAction, surfaceKey]);
1946
- const resetSurface = (0, import_react9.useCallback)(() => {
2347
+ const resetSurface = (0, import_react10.useCallback)(() => {
1947
2348
  setSurfaceKey((key) => key + 1);
1948
2349
  }, []);
1949
- const recoverTechnicalFailure = (0, import_react9.useCallback)((err, code, generation) => {
2350
+ const recoverTechnicalFailure = (0, import_react10.useCallback)((err, code, generation) => {
1950
2351
  invalidateAttempt(generation);
1951
2352
  onTechnicalFailure?.("paypal", err, { code, popupBlocked: isPopupBlockedError(err) });
1952
2353
  setShowRecoveryAction(true);
1953
2354
  resetSurface();
1954
2355
  }, [invalidateAttempt, onTechnicalFailure, resetSurface]);
1955
- const focusProviderSurface = (0, import_react9.useCallback)(() => {
2356
+ const focusProviderSurface = (0, import_react10.useCallback)(() => {
1956
2357
  window.setTimeout(() => {
1957
2358
  const target = focusTargetRef.current?.querySelector("iframe");
1958
2359
  (target ?? focusTargetRef.current)?.focus();
1959
2360
  }, 0);
1960
2361
  }, []);
1961
- (0, import_react9.useEffect)(() => {
2362
+ (0, import_react10.useEffect)(() => {
1962
2363
  if (!pendingProviderFocusRef.current) return;
1963
2364
  pendingProviderFocusRef.current = false;
1964
2365
  focusProviderSurface();
1965
2366
  }, [focusProviderSurface, surfaceKey]);
1966
- const handleRecoveryActionClick = (0, import_react9.useCallback)(() => {
2367
+ const handleRecoveryActionClick = (0, import_react10.useCallback)(() => {
1967
2368
  setShowRecoveryAction(false);
1968
2369
  onErrorChange?.(null);
1969
2370
  focusProviderSurface();
1970
2371
  }, [focusProviderSurface, onErrorChange]);
1971
- (0, import_react9.useEffect)(() => {
2372
+ (0, import_react10.useEffect)(() => {
1972
2373
  if (!stripe || paypalResumeAttempted.current) return;
1973
2374
  const params = new URLSearchParams(window.location.search);
1974
2375
  const paymentIntentId = params.get("payment_intent");
@@ -2034,7 +2435,7 @@ function PayPalButtonInner({
2034
2435
  }
2035
2436
  })();
2036
2437
  }, [stripe, onTokenizedBody, onErrorChange, onDecline]);
2037
- const handlePayPalClick = (0, import_react9.useCallback)(async (event) => {
2438
+ const handlePayPalClick = (0, import_react10.useCallback)(async (event) => {
2038
2439
  if (isProcessing || submitting) {
2039
2440
  event.reject();
2040
2441
  return;
@@ -2056,7 +2457,7 @@ function PayPalButtonInner({
2056
2457
  onButtonClick?.("paypal");
2057
2458
  event.resolve();
2058
2459
  }, [attemptContextBySurfaceRef, isProcessing, onButtonClick, runBeforeButtonClick, startAttempt, submitting, surfaceKey]);
2059
- const handlePayPalConfirm = (0, import_react9.useCallback)(async (event) => {
2460
+ const handlePayPalConfirm = (0, import_react10.useCallback)(async (event) => {
2060
2461
  if (!stripe || !elements) return;
2061
2462
  const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
2062
2463
  if (attemptContext && !isAttemptCurrent(attemptContext.generation)) {
@@ -2096,8 +2497,7 @@ function PayPalButtonInner({
2096
2497
  event.paymentFailed({ reason: "fail" });
2097
2498
  return;
2098
2499
  }
2099
- const intentHeaders = { "Content-Type": "application/json" };
2100
- if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
2500
+ const intentHeaders = intentRequestHeaders(effectiveNonce);
2101
2501
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
2102
2502
  method: "POST",
2103
2503
  headers: intentHeaders,
@@ -2188,14 +2588,14 @@ function PayPalButtonInner({
2188
2588
  setSubmitting(false);
2189
2589
  }
2190
2590
  }, [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick, recoverTechnicalFailure, finishAttempt, isAttemptCurrent, isAttemptInvalidated, surfaceKey]);
2191
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2192
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2591
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2592
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2193
2593
  ExpressCheckoutReadySwap,
2194
2594
  {
2195
2595
  state: loadState,
2196
2596
  placeholderTestId: "flopay-paypal-placeholder",
2197
2597
  borderRadius: placeholderBorderRadius,
2198
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2598
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2199
2599
  "div",
2200
2600
  {
2201
2601
  ref: focusTargetRef,
@@ -2204,7 +2604,7 @@ function PayPalButtonInner({
2204
2604
  "aria-label": "PayPal payment method",
2205
2605
  style: { borderRadius: 8, outlineOffset: 4 },
2206
2606
  children: [
2207
- showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2607
+ showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2208
2608
  "button",
2209
2609
  {
2210
2610
  ref: recoveryActionRef,
@@ -2215,7 +2615,7 @@ function PayPalButtonInner({
2215
2615
  children: "Try PayPal again"
2216
2616
  }
2217
2617
  ),
2218
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2618
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2219
2619
  import_react_stripe_js.ExpressCheckoutElement,
2220
2620
  {
2221
2621
  onReady: (event) => setLoadState(resolveExpressCheckoutLoadState(event, ["paypal"])),
@@ -2225,6 +2625,11 @@ function PayPalButtonInner({
2225
2625
  onCancel: () => {
2226
2626
  const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
2227
2627
  attemptContextBySurfaceRef.current.delete(surfaceKey);
2628
+ getFloPayTelemetryBridge(flopay)?.terminal({
2629
+ outcome: "payment_cancelled",
2630
+ provider: "paypal",
2631
+ paymentMethodCategory: "paypal"
2632
+ });
2228
2633
  invalidateAttempt(attemptContext?.generation);
2229
2634
  setShowRecoveryAction(false);
2230
2635
  pendingProviderFocusRef.current = true;
@@ -2250,7 +2655,7 @@ function PayPalButtonInner({
2250
2655
  )
2251
2656
  }
2252
2657
  ),
2253
- submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
2658
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: "processing" })
2254
2659
  ] });
2255
2660
  }
2256
2661
  function WalletButtonInner({
@@ -2268,23 +2673,24 @@ function WalletButtonInner({
2268
2673
  onLoadStateChange,
2269
2674
  placeholderBorderRadius
2270
2675
  }) {
2676
+ const flopay = useFloPay();
2271
2677
  const stripe = (0, import_react_stripe_js.useStripe)();
2272
2678
  const elements = (0, import_react_stripe_js.useElements)();
2273
- const [loadState, setLoadState] = (0, import_react9.useState)("loading");
2274
- (0, import_react9.useEffect)(() => {
2679
+ const [loadState, setLoadState] = (0, import_react10.useState)("loading");
2680
+ (0, import_react10.useEffect)(() => {
2275
2681
  onLoadStateChange?.(loadState);
2276
2682
  }, [loadState, onLoadStateChange]);
2277
- const [submitting, setSubmitting] = (0, import_react9.useState)(false);
2683
+ const [submitting, setSubmitting] = (0, import_react10.useState)(false);
2278
2684
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2279
- const focusTargetRef = (0, import_react9.useRef)(null);
2280
- const recoveryActionRef = (0, import_react9.useRef)(null);
2281
- const [surfaceKey, setSurfaceKey] = (0, import_react9.useState)(0);
2282
- const [showRecoveryAction, setShowRecoveryAction] = (0, import_react9.useState)(false);
2283
- const [recoveryActionMethod, setRecoveryActionMethod] = (0, import_react9.useState)("google_pay");
2284
- const pendingProviderFocusRef = (0, import_react9.useRef)(false);
2285
- const lastWalletProviderMethodRef = (0, import_react9.useRef)("google_pay");
2286
- const lastWalletMethodRef = (0, import_react9.useRef)("google_pay");
2287
- const attemptContextBySurfaceRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
2685
+ const focusTargetRef = (0, import_react10.useRef)(null);
2686
+ const recoveryActionRef = (0, import_react10.useRef)(null);
2687
+ const [surfaceKey, setSurfaceKey] = (0, import_react10.useState)(0);
2688
+ const [showRecoveryAction, setShowRecoveryAction] = (0, import_react10.useState)(false);
2689
+ const [recoveryActionMethod, setRecoveryActionMethod] = (0, import_react10.useState)("google_pay");
2690
+ const pendingProviderFocusRef = (0, import_react10.useRef)(false);
2691
+ const lastWalletProviderMethodRef = (0, import_react10.useRef)("google_pay");
2692
+ const lastWalletMethodRef = (0, import_react10.useRef)("google_pay");
2693
+ const attemptContextBySurfaceRef = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2288
2694
  const {
2289
2695
  startAttempt,
2290
2696
  finishAttempt,
@@ -2300,36 +2706,36 @@ function WalletButtonInner({
2300
2706
  setShowRecoveryAction(true);
2301
2707
  setSurfaceKey((key) => key + 1);
2302
2708
  });
2303
- (0, import_react9.useEffect)(() => {
2709
+ (0, import_react10.useEffect)(() => {
2304
2710
  if (showRecoveryAction) recoveryActionRef.current?.focus();
2305
2711
  }, [showRecoveryAction, surfaceKey]);
2306
- const resetSurface = (0, import_react9.useCallback)(() => {
2712
+ const resetSurface = (0, import_react10.useCallback)(() => {
2307
2713
  setSurfaceKey((key) => key + 1);
2308
2714
  }, []);
2309
- const recoverTechnicalFailure = (0, import_react9.useCallback)((method, err, code, generation) => {
2715
+ const recoverTechnicalFailure = (0, import_react10.useCallback)((method, err, code, generation) => {
2310
2716
  invalidateAttempt(generation);
2311
2717
  onTechnicalFailure?.(method, err, { code, popupBlocked: isPopupBlockedError(err) });
2312
2718
  setRecoveryActionMethod(method);
2313
2719
  setShowRecoveryAction(true);
2314
2720
  resetSurface();
2315
2721
  }, [invalidateAttempt, onTechnicalFailure, resetSurface]);
2316
- const focusProviderSurface = (0, import_react9.useCallback)(() => {
2722
+ const focusProviderSurface = (0, import_react10.useCallback)(() => {
2317
2723
  window.setTimeout(() => {
2318
2724
  const target = focusTargetRef.current?.querySelector("iframe");
2319
2725
  (target ?? focusTargetRef.current)?.focus();
2320
2726
  }, 0);
2321
2727
  }, []);
2322
- (0, import_react9.useEffect)(() => {
2728
+ (0, import_react10.useEffect)(() => {
2323
2729
  if (!pendingProviderFocusRef.current) return;
2324
2730
  pendingProviderFocusRef.current = false;
2325
2731
  focusProviderSurface();
2326
2732
  }, [focusProviderSurface, surfaceKey]);
2327
- const handleRecoveryActionClick = (0, import_react9.useCallback)(() => {
2733
+ const handleRecoveryActionClick = (0, import_react10.useCallback)(() => {
2328
2734
  setShowRecoveryAction(false);
2329
2735
  onErrorChange?.(null);
2330
2736
  focusProviderSurface();
2331
2737
  }, [focusProviderSurface, onErrorChange]);
2332
- const handleWalletConfirm = (0, import_react9.useCallback)(
2738
+ const handleWalletConfirm = (0, import_react10.useCallback)(
2333
2739
  async (event) => {
2334
2740
  if (!stripe || !elements) return;
2335
2741
  const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
@@ -2376,8 +2782,7 @@ function WalletButtonInner({
2376
2782
  if (!effectiveSessionId || !effectiveEmail) {
2377
2783
  throw new Error("Missing sessionId or email for wallet payment");
2378
2784
  }
2379
- const intentHeaders = { "Content-Type": "application/json" };
2380
- if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
2785
+ const intentHeaders = intentRequestHeaders(effectiveNonce);
2381
2786
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
2382
2787
  method: "POST",
2383
2788
  headers: intentHeaders,
@@ -2432,7 +2837,7 @@ function WalletButtonInner({
2432
2837
  },
2433
2838
  [stripe, elements, sessionId, nonce, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick, recoverTechnicalFailure, finishAttempt, isAttemptCurrent, isAttemptInvalidated, surfaceKey]
2434
2839
  );
2435
- const expressMethodMap = (0, import_react9.useMemo)(() => {
2840
+ const expressMethodMap = (0, import_react10.useMemo)(() => {
2436
2841
  const allKeys = ["applePay", "googlePay", "paypal", "link", "amazonPay", "klarna"];
2437
2842
  const alwaysCapable = /* @__PURE__ */ new Set(["applePay", "googlePay"]);
2438
2843
  const enabledKeys = new Set(expressMethods.map(import_shared5.stripeExpressMethodToOptionKey));
@@ -2446,18 +2851,18 @@ function WalletButtonInner({
2446
2851
  }
2447
2852
  return out;
2448
2853
  }, [expressMethods]);
2449
- const availableMethodKeys = (0, import_react9.useMemo)(
2854
+ const availableMethodKeys = (0, import_react10.useMemo)(
2450
2855
  () => expressMethods.map(import_shared5.stripeExpressMethodToOptionKey),
2451
2856
  [expressMethods]
2452
2857
  );
2453
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2454
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2858
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2859
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2455
2860
  ExpressCheckoutReadySwap,
2456
2861
  {
2457
2862
  state: loadState,
2458
2863
  placeholderTestId: "flopay-wallet-placeholder",
2459
2864
  borderRadius: placeholderBorderRadius,
2460
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2865
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2461
2866
  "div",
2462
2867
  {
2463
2868
  ref: focusTargetRef,
@@ -2466,7 +2871,7 @@ function WalletButtonInner({
2466
2871
  "aria-label": "Wallet payment methods",
2467
2872
  style: { borderRadius: 8, outlineOffset: 4 },
2468
2873
  children: [
2469
- showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2874
+ showRecoveryAction && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2470
2875
  "button",
2471
2876
  {
2472
2877
  ref: recoveryActionRef,
@@ -2481,7 +2886,7 @@ function WalletButtonInner({
2481
2886
  ]
2482
2887
  }
2483
2888
  ),
2484
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2889
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2485
2890
  import_react_stripe_js.ExpressCheckoutElement,
2486
2891
  {
2487
2892
  onReady: (event) => {
@@ -2489,6 +2894,13 @@ function WalletButtonInner({
2489
2894
  },
2490
2895
  onLoadError: (_event) => {
2491
2896
  setLoadState("load_error");
2897
+ getFloPayTelemetryBridge(flopay)?.error({
2898
+ errorCode: "PROVIDER_LOAD_FAILED",
2899
+ stage: "provider_load",
2900
+ provider: "stripe",
2901
+ paymentMethodCategory: "wallet",
2902
+ requestCategory: "provider_sdk"
2903
+ });
2492
2904
  },
2493
2905
  onClick: async (event) => {
2494
2906
  lastWalletProviderMethodRef.current = event.expressPaymentType;
@@ -2515,6 +2927,11 @@ function WalletButtonInner({
2515
2927
  onCancel: () => {
2516
2928
  const attemptContext = attemptContextBySurfaceRef.current.get(surfaceKey);
2517
2929
  attemptContextBySurfaceRef.current.delete(surfaceKey);
2930
+ getFloPayTelemetryBridge(flopay)?.terminal({
2931
+ outcome: "payment_cancelled",
2932
+ provider: "stripe",
2933
+ paymentMethodCategory: "wallet"
2934
+ });
2518
2935
  invalidateAttempt(attemptContext?.generation);
2519
2936
  setShowRecoveryAction(false);
2520
2937
  pendingProviderFocusRef.current = true;
@@ -2533,7 +2950,7 @@ function WalletButtonInner({
2533
2950
  )
2534
2951
  }
2535
2952
  ),
2536
- submitting && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: "processing" })
2953
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: "processing" })
2537
2954
  ] });
2538
2955
  }
2539
2956
  function StripeMethodButton({
@@ -2551,10 +2968,11 @@ function StripeMethodButton({
2551
2968
  fontFamily
2552
2969
  }) {
2553
2970
  const brand = (0, import_shared5.resolveStripeMethodBrandVariant)(method, themeId);
2971
+ const vendoredLogoUrl = PAYMENT_METHOD_LOGO_URLS[method];
2554
2972
  const resolvedBackground = brand?.backgroundColor ?? backgroundColor ?? "#ffffff";
2555
2973
  const resolvedBorder = brand?.borderColor ?? borderColor ?? "#d1d5db";
2556
2974
  const resolvedTextColor = brand?.textColor ?? textColor ?? "#262833";
2557
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2975
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2558
2976
  "button",
2559
2977
  {
2560
2978
  type: "button",
@@ -2601,9 +3019,9 @@ function StripeMethodButton({
2601
3019
  // Pulse-skeleton parity with the wallet ECE: no spinner, just the
2602
3020
  // status text on top of the pulsing background. Keeps the loading
2603
3021
  // affordance shape-equivalent across both kinds of tile.
2604
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
2605
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2606
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3022
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { margin: "0 auto" }, children: `Connecting to ${(0, import_shared5.getStripeMethodDisplayName)(method)}\u2026` })
3023
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
3024
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2607
3025
  "span",
2608
3026
  {
2609
3027
  style: {
@@ -2616,15 +3034,36 @@ function StripeMethodButton({
2616
3034
  gap: (0, import_shared5.hasVendoredStripeMethodLogo)(method) ? 8 : 0
2617
3035
  },
2618
3036
  children: [
2619
- brand?.logoSvg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3037
+ vendoredLogoUrl ? (
3038
+ // Vendored brand logo — an <img> asset (not inline SVG) so its
3039
+ // bytes ship as a sibling file, out of the JS bundle. 3:2 box
3040
+ // matching the datatrans logos' 120×80 viewBox; each ships its own
3041
+ // white rounded-rect background so it stays legible on any tile.
3042
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3043
+ "img",
3044
+ {
3045
+ src: vendoredLogoUrl,
3046
+ alt: "",
3047
+ "aria-hidden": "true",
3048
+ loading: "lazy",
3049
+ decoding: "async",
3050
+ width: 30,
3051
+ height: 20,
3052
+ style: {
3053
+ width: 30,
3054
+ height: 20,
3055
+ flexShrink: 0,
3056
+ borderRadius: 3,
3057
+ objectFit: "contain",
3058
+ display: "inline-flex"
3059
+ }
3060
+ }
3061
+ )
3062
+ ) : brand?.logoSvg ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2620
3063
  "span",
2621
3064
  {
2622
3065
  "aria-hidden": "true",
2623
3066
  style: {
2624
- // 3:2 box matching the vendored datatrans logos' 120×80
2625
- // viewBox. Each logo ships with its own white rounded-rect
2626
- // background baked in, so the mark stays legible on any
2627
- // brand-coloured tile without an extra chip wrapper here.
2628
3067
  width: 30,
2629
3068
  height: 20,
2630
3069
  flexShrink: 0,
@@ -2634,12 +3073,12 @@ function StripeMethodButton({
2634
3073
  },
2635
3074
  dangerouslySetInnerHTML: { __html: brand.logoSvg }
2636
3075
  }
2637
- ),
2638
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
3076
+ ) : null,
3077
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: (0, import_shared5.getStripeMethodDisplayName)(method) })
2639
3078
  ]
2640
3079
  }
2641
3080
  ),
2642
- hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3081
+ hasNextStep && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2643
3082
  "svg",
2644
3083
  {
2645
3084
  width: "14",
@@ -2659,7 +3098,7 @@ function StripeMethodButton({
2659
3098
  opacity: 0.7
2660
3099
  },
2661
3100
  "aria-hidden": "true",
2662
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 18l6-6-6-6" })
3101
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9 18l6-6-6-6" })
2663
3102
  }
2664
3103
  )
2665
3104
  ] })
@@ -2685,14 +3124,15 @@ function StripeMethodInlineForm({
2685
3124
  submitButtonStyle,
2686
3125
  errorText
2687
3126
  }) {
3127
+ const flopay = useFloPay();
2688
3128
  const stripe = (0, import_react_stripe_js.useStripe)();
2689
3129
  const elements = (0, import_react_stripe_js.useElements)();
2690
- const [submitting, setSubmitting] = (0, import_react9.useState)(false);
2691
- const submittingRef = (0, import_react9.useRef)(false);
2692
- const [isMethodComplete, setIsMethodComplete] = (0, import_react9.useState)(false);
2693
- const [loadState, setLoadState] = (0, import_react9.useState)("loading");
3130
+ const [submitting, setSubmitting] = (0, import_react10.useState)(false);
3131
+ const submittingRef = (0, import_react10.useRef)(false);
3132
+ const [isMethodComplete, setIsMethodComplete] = (0, import_react10.useState)(false);
3133
+ const [loadState, setLoadState] = (0, import_react10.useState)("loading");
2694
3134
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2695
- const handlePay = (0, import_react9.useCallback)(async () => {
3135
+ const handlePay = (0, import_react10.useCallback)(async () => {
2696
3136
  if (!stripe || !elements || isProcessing || submittingRef.current || !isMethodComplete) return;
2697
3137
  submittingRef.current = true;
2698
3138
  setSubmitting(true);
@@ -2722,8 +3162,7 @@ function StripeMethodInlineForm({
2722
3162
  if (!effectiveSessionId || !effectiveEmail) {
2723
3163
  throw new Error("Missing sessionId or email for payment.");
2724
3164
  }
2725
- const intentHeaders = { "Content-Type": "application/json" };
2726
- if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
3165
+ const intentHeaders = intentRequestHeaders(effectiveNonce);
2727
3166
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
2728
3167
  method: "POST",
2729
3168
  headers: intentHeaders,
@@ -2777,9 +3216,8 @@ function StripeMethodInlineForm({
2777
3216
  onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
2778
3217
  return;
2779
3218
  }
2780
- const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
2781
3219
  const piStatus = paymentIntent?.status;
2782
- if (!piStatus || !SUCCESSFUL_PI_STATUSES.has(piStatus)) {
3220
+ if (!isSuccessfulPaymentIntentStatus(piStatus)) {
2783
3221
  if (typeof window !== "undefined") {
2784
3222
  try {
2785
3223
  localStorage.removeItem(STRIPE_RESUME_KEY);
@@ -2832,12 +3270,21 @@ function StripeMethodInlineForm({
2832
3270
  onDecline
2833
3271
  ]);
2834
3272
  void onCancel;
2835
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
2836
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3273
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-testid": `flopay-stripe-method-form-${method}`, style: { display: "flex", flexDirection: "column" }, children: [
3274
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2837
3275
  import_react_stripe_js.PaymentElement,
2838
3276
  {
2839
3277
  onReady: () => setLoadState("ready"),
2840
- onLoadError: () => setLoadState("load_error"),
3278
+ onLoadError: () => {
3279
+ setLoadState("load_error");
3280
+ getFloPayTelemetryBridge(flopay)?.error({
3281
+ errorCode: "PROVIDER_LOAD_FAILED",
3282
+ stage: "provider_load",
3283
+ provider: "stripe",
3284
+ paymentMethodCategory: "apm",
3285
+ requestCategory: "provider_sdk"
3286
+ });
3287
+ },
2841
3288
  onChange: (event) => {
2842
3289
  const evRecord = event;
2843
3290
  setIsMethodComplete(!!evRecord.complete);
@@ -2853,7 +3300,7 @@ function StripeMethodInlineForm({
2853
3300
  }
2854
3301
  }
2855
3302
  ),
2856
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3303
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2857
3304
  "button",
2858
3305
  {
2859
3306
  type: "button",
@@ -2880,22 +3327,7 @@ function StripeMethodInlineForm({
2880
3327
  children: submitting ? "Processing\u2026" : `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(method)}`
2881
3328
  }
2882
3329
  ),
2883
- errorText && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
2884
- margin: "0.75rem 0 0",
2885
- padding: "0.625rem 0.875rem",
2886
- background: "#FEF2F2",
2887
- border: "1px solid #FECACA",
2888
- borderRadius: "8px",
2889
- color: "#991B1B",
2890
- fontSize: "0.85rem",
2891
- fontWeight: 600,
2892
- display: "flex",
2893
- alignItems: "center",
2894
- gap: "0.5rem"
2895
- }, children: [
2896
- /* @__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" }) }),
2897
- errorText
2898
- ] })
3330
+ errorText && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.75rem 0 0", children: errorText })
2899
3331
  ] });
2900
3332
  }
2901
3333
  function StripePaymentElementInner({
@@ -2923,17 +3355,17 @@ function StripePaymentElementInner({
2923
3355
  expandedApmMethod
2924
3356
  }) {
2925
3357
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
2926
- const [expandedMethod, setExpandedMethod] = (0, import_react9.useState)(null);
2927
- const [submittingMethod, setSubmittingMethod] = (0, import_react9.useState)(null);
2928
- const submittingRef = (0, import_react9.useRef)(false);
2929
- (0, import_react9.useEffect)(() => {
3358
+ const [expandedMethod, setExpandedMethod] = (0, import_react10.useState)(null);
3359
+ const [submittingMethod, setSubmittingMethod] = (0, import_react10.useState)(null);
3360
+ const submittingRef = (0, import_react10.useRef)(false);
3361
+ (0, import_react10.useEffect)(() => {
2930
3362
  if (paymentElementMethods.length > 0 && stripeInstance) {
2931
3363
  onLoadStateChange?.("ready");
2932
3364
  } else if (!stripeInstance) {
2933
3365
  onLoadStateChange?.("loading");
2934
3366
  }
2935
3367
  }, [paymentElementMethods.length, stripeInstance, onLoadStateChange]);
2936
- const handleAutoConfirm = (0, import_react9.useCallback)(async (method) => {
3368
+ const handleAutoConfirm = (0, import_react10.useCallback)(async (method) => {
2937
3369
  if (!stripeInstance) return;
2938
3370
  if (submittingRef.current || isProcessing) return;
2939
3371
  submittingRef.current = true;
@@ -2953,8 +3385,7 @@ function StripePaymentElementInner({
2953
3385
  if (!effectiveSessionId || !effectiveEmail) {
2954
3386
  throw new Error("Missing sessionId or email for payment.");
2955
3387
  }
2956
- const intentHeaders = { "Content-Type": "application/json" };
2957
- if (effectiveNonce) intentHeaders["x-checkout-session-token"] = effectiveNonce;
3388
+ const intentHeaders = intentRequestHeaders(effectiveNonce);
2958
3389
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
2959
3390
  method: "POST",
2960
3391
  headers: intentHeaders,
@@ -3020,9 +3451,8 @@ function StripePaymentElementInner({
3020
3451
  onDecline?.(buildDeclineEvent("card", message, { code: confirmError.code }));
3021
3452
  return;
3022
3453
  }
3023
- const SUCCESSFUL_PI_STATUSES = /* @__PURE__ */ new Set(["succeeded", "requires_capture", "processing"]);
3024
3454
  const piStatus = paymentIntent?.status;
3025
- if (!piStatus || !SUCCESSFUL_PI_STATUSES.has(piStatus)) {
3455
+ if (!isSuccessfulPaymentIntentStatus(piStatus)) {
3026
3456
  if (typeof window !== "undefined") {
3027
3457
  try {
3028
3458
  localStorage.removeItem(STRIPE_RESUME_KEY);
@@ -3072,9 +3502,9 @@ function StripePaymentElementInner({
3072
3502
  onErrorChange,
3073
3503
  onDecline
3074
3504
  ]);
3075
- const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react9.useState)(null);
3505
+ const [localExpandedMethod, setLocalExpandedMethod] = (0, import_react10.useState)(null);
3076
3506
  const activeExpandedMethod = onExpandApm ? expandedApmMethod ?? null : localExpandedMethod;
3077
- const handleMethodClick = (0, import_react9.useCallback)((method) => {
3507
+ const handleMethodClick = (0, import_react10.useCallback)((method) => {
3078
3508
  if (submittingRef.current || isProcessing) return;
3079
3509
  if (activeExpandedMethod && activeExpandedMethod !== method) return;
3080
3510
  if ((0, import_shared5.needsStripeMethodExplicitConfirm)(method)) {
@@ -3087,14 +3517,14 @@ function StripePaymentElementInner({
3087
3517
  void handleAutoConfirm(method);
3088
3518
  }
3089
3519
  }, [activeExpandedMethod, isProcessing, handleAutoConfirm, onExpandApm]);
3090
- const localInlineElementsOptions = (0, import_react9.useMemo)(() => {
3520
+ const localInlineElementsOptions = (0, import_react10.useMemo)(() => {
3091
3521
  if (!localExpandedMethod) return null;
3092
3522
  return {
3093
3523
  ...paymentElementBaseOptions,
3094
3524
  paymentMethodTypes: [localExpandedMethod]
3095
3525
  };
3096
3526
  }, [localExpandedMethod, paymentElementBaseOptions]);
3097
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3527
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3098
3528
  "div",
3099
3529
  {
3100
3530
  "data-testid": "flopay-stripe-payment-element-region",
@@ -3103,8 +3533,8 @@ function StripePaymentElementInner({
3103
3533
  const isExpanded = expandedApmMethod === method;
3104
3534
  const isSubmittingThis = submittingMethod === method;
3105
3535
  const otherInProgress = submittingMethod !== null && submittingMethod !== method || expandedApmMethod !== null && expandedApmMethod !== void 0 && expandedApmMethod !== method;
3106
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.default.Fragment, { children: [
3107
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3536
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react10.default.Fragment, { children: [
3537
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3108
3538
  StripeMethodButton,
3109
3539
  {
3110
3540
  method,
@@ -3121,12 +3551,12 @@ function StripePaymentElementInner({
3121
3551
  fontFamily: buttonAppearance?.fontFamily
3122
3552
  }
3123
3553
  ),
3124
- !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3554
+ !onExpandApm && localExpandedMethod === method && localInlineElementsOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3125
3555
  import_react_stripe_js.Elements,
3126
3556
  {
3127
3557
  stripe: stripeInstance,
3128
3558
  options: localInlineElementsOptions,
3129
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3559
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3130
3560
  StripeMethodInlineForm,
3131
3561
  {
3132
3562
  method,
@@ -3220,41 +3650,41 @@ function SplitCardFormInner({
3220
3650
  const flopay = useFloPay();
3221
3651
  const paypalFlopay = usePayPalFloPay();
3222
3652
  const elements = useElements();
3223
- const checkout = (0, import_react9.useContext)(CheckoutContext);
3653
+ const checkout = (0, import_react10.useContext)(CheckoutContext);
3224
3654
  const contextBillingUrl = useBillingApiUrl();
3225
- const [processing, setProcessing] = (0, import_react9.useState)(false);
3226
- const [error, setError] = (0, import_react9.useState)(null);
3227
- const [is3DSActive, setIs3DSActive] = (0, import_react9.useState)(false);
3228
- const [selectedCountry, setSelectedCountry] = (0, import_react9.useState)(countryProp ?? "US");
3229
- const [zipCode, setZipCode] = (0, import_react9.useState)(zipProp ?? "");
3230
- const [addressLine1, setAddressLine1] = (0, import_react9.useState)(addressLine1Prop ?? "");
3231
- const [addressLine2, setAddressLine2] = (0, import_react9.useState)(addressLine2Prop ?? "");
3232
- const [city, setCity] = (0, import_react9.useState)(cityProp ?? "");
3233
- const [stateValue, setStateValue] = (0, import_react9.useState)(stateProp ?? "");
3234
- const [accountPatch, setAccountPatch] = (0, import_react9.useState)({});
3235
- const zipCodeRef = (0, import_react9.useRef)(zipProp ?? "");
3236
- const selectedCountryRef = (0, import_react9.useRef)(countryProp ?? "US");
3237
- const addressLine1Ref = (0, import_react9.useRef)(addressLine1Prop ?? "");
3238
- const addressLine2Ref = (0, import_react9.useRef)(addressLine2Prop ?? "");
3239
- const cityRef = (0, import_react9.useRef)(cityProp ?? "");
3240
- const stateRef = (0, import_react9.useRef)(stateProp ?? "");
3241
- const avsConfig = (0, import_react9.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
3655
+ const [processing, setProcessing] = (0, import_react10.useState)(false);
3656
+ const [error, setError] = (0, import_react10.useState)(null);
3657
+ const [is3DSActive, setIs3DSActive] = (0, import_react10.useState)(false);
3658
+ const [selectedCountry, setSelectedCountry] = (0, import_react10.useState)(countryProp ?? "US");
3659
+ const [zipCode, setZipCode] = (0, import_react10.useState)(zipProp ?? "");
3660
+ const [addressLine1, setAddressLine1] = (0, import_react10.useState)(addressLine1Prop ?? "");
3661
+ const [addressLine2, setAddressLine2] = (0, import_react10.useState)(addressLine2Prop ?? "");
3662
+ const [city, setCity] = (0, import_react10.useState)(cityProp ?? "");
3663
+ const [stateValue, setStateValue] = (0, import_react10.useState)(stateProp ?? "");
3664
+ const [accountPatch, setAccountPatch] = (0, import_react10.useState)({});
3665
+ const zipCodeRef = (0, import_react10.useRef)(zipProp ?? "");
3666
+ const selectedCountryRef = (0, import_react10.useRef)(countryProp ?? "US");
3667
+ const addressLine1Ref = (0, import_react10.useRef)(addressLine1Prop ?? "");
3668
+ const addressLine2Ref = (0, import_react10.useRef)(addressLine2Prop ?? "");
3669
+ const cityRef = (0, import_react10.useRef)(cityProp ?? "");
3670
+ const stateRef = (0, import_react10.useRef)(stateProp ?? "");
3671
+ const avsConfig = (0, import_react10.useMemo)(() => (0, import_shared5.resolveAVSConfig)(enableAVSProp), [enableAVSProp]);
3242
3672
  const enableAVS = avsConfig !== null;
3243
3673
  const vaultBlockReady = Boolean(session?.vault?.html);
3244
3674
  const vaultGatewayAdvertised = Boolean(session?.gateways?.pcivault);
3245
3675
  const vaultActive = Boolean(
3246
3676
  showStripe && (vaultBlockReady || vaultGatewayAdvertised) && flopay && sessionId
3247
3677
  );
3248
- const cardCapture = (0, import_react9.useMemo)(() => {
3678
+ const cardCapture = (0, import_react10.useMemo)(() => {
3249
3679
  if (!flopay || !vaultActive || !sessionId) return null;
3250
3680
  return flopay.cardCapture({ sessionId });
3251
3681
  }, [flopay, vaultActive, sessionId]);
3252
- const postalCodeState = (0, import_react9.useMemo)(() => {
3682
+ const postalCodeState = (0, import_react10.useMemo)(() => {
3253
3683
  const cc = selectedCountry;
3254
3684
  const visible = avsConfig ? (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) : false;
3255
3685
  return computePostalCodeState(cc, zipCode, visible);
3256
3686
  }, [avsConfig, selectedCountry, zipCode]);
3257
- const { avsInvalid, invalidAvsFields } = (0, import_react9.useMemo)(() => {
3687
+ const { avsInvalid, invalidAvsFields } = (0, import_react10.useMemo)(() => {
3258
3688
  const none = { line1: false, city: false, state: false, zip: false };
3259
3689
  if (!vaultActive || !avsConfig) return { avsInvalid: false, invalidAvsFields: none };
3260
3690
  const cc = selectedCountry;
@@ -3270,53 +3700,53 @@ function SplitCardFormInner({
3270
3700
  const avsInvalid2 = invalidAvsFields2.line1 || invalidAvsFields2.city || invalidAvsFields2.state || invalidAvsFields2.zip;
3271
3701
  return { avsInvalid: avsInvalid2, invalidAvsFields: invalidAvsFields2 };
3272
3702
  }, [vaultActive, avsConfig, selectedCountry, addressLine1, city, stateValue, postalCodeState]);
3273
- const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react9.useState)(false);
3274
- const [zipTouched, setZipTouched] = (0, import_react9.useState)(false);
3275
- const [vaultMount, setVaultMount] = (0, import_react9.useState)(
3703
+ const [hasAttemptedSubmit, setHasAttemptedSubmit] = (0, import_react10.useState)(false);
3704
+ const [zipTouched, setZipTouched] = (0, import_react10.useState)(false);
3705
+ const [vaultMount, setVaultMount] = (0, import_react10.useState)(
3276
3706
  () => toVaultMount(session?.vault)
3277
3707
  );
3278
- const [viewState, setViewState] = (0, import_react9.useState)(initialCardOpen ? "card" : "buttons");
3279
- const [expandedApmMethod, setExpandedApmMethod] = (0, import_react9.useState)(null);
3708
+ const [viewState, setViewState] = (0, import_react10.useState)(initialCardOpen ? "card" : "buttons");
3709
+ const [expandedApmMethod, setExpandedApmMethod] = (0, import_react10.useState)(null);
3280
3710
  const showCardForm = viewState === "expanding" || viewState === "card";
3281
3711
  const TRANSITION_MS = 280;
3282
- const expandToCard = (0, import_react9.useCallback)(() => {
3712
+ const expandToCard = (0, import_react10.useCallback)(() => {
3283
3713
  setViewState("expanding");
3284
3714
  setTimeout(() => setViewState("card"), TRANSITION_MS);
3285
3715
  }, []);
3286
- const collapseToButtons = (0, import_react9.useCallback)(() => {
3716
+ const collapseToButtons = (0, import_react10.useCallback)(() => {
3287
3717
  setViewState("collapsing");
3288
3718
  setTimeout(() => setViewState("buttons"), TRANSITION_MS);
3289
3719
  }, []);
3290
- const expandToApm = (0, import_react9.useCallback)((method) => {
3720
+ const expandToApm = (0, import_react10.useCallback)((method) => {
3291
3721
  setExpandedApmMethod(method);
3292
3722
  setViewState("apm-expanding");
3293
3723
  setTimeout(() => setViewState("apm-form"), TRANSITION_MS);
3294
3724
  }, []);
3295
- const collapseFromApm = (0, import_react9.useCallback)(() => {
3725
+ const collapseFromApm = (0, import_react10.useCallback)(() => {
3296
3726
  setViewState("apm-collapsing");
3297
3727
  setTimeout(() => {
3298
3728
  setViewState("buttons");
3299
3729
  setExpandedApmMethod(null);
3300
3730
  }, TRANSITION_MS);
3301
3731
  }, []);
3302
- (0, import_react9.useEffect)(() => {
3732
+ (0, import_react10.useEffect)(() => {
3303
3733
  if (layout === "buttons" && initialCardOpen) {
3304
3734
  setViewState("card");
3305
3735
  }
3306
3736
  }, [layout, initialCardOpen]);
3307
- const [fullName, setFullName] = (0, import_react9.useState)("");
3308
- const [formReady, setFormReady] = (0, import_react9.useState)(false);
3309
- const [overlayStatus, setOverlayStatus] = (0, import_react9.useState)(null);
3310
- const processingRef = (0, import_react9.useRef)(false);
3311
- const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react9.useState)(null);
3312
- const paypalDirectRetryRef = (0, import_react9.useRef)(paypalDirectRetry);
3313
- (0, import_react9.useEffect)(() => {
3737
+ const [fullName, setFullName] = (0, import_react10.useState)("");
3738
+ const [formReady, setFormReady] = (0, import_react10.useState)(false);
3739
+ const [overlayStatus, setOverlayStatus] = (0, import_react10.useState)(null);
3740
+ const processingRef = (0, import_react10.useRef)(false);
3741
+ const [paypalDirectRetry, setPaypalDirectRetry] = (0, import_react10.useState)(null);
3742
+ const paypalDirectRetryRef = (0, import_react10.useRef)(paypalDirectRetry);
3743
+ (0, import_react10.useEffect)(() => {
3314
3744
  paypalDirectRetryRef.current = paypalDirectRetry;
3315
3745
  }, [paypalDirectRetry]);
3316
3746
  const resolvedBillingApiUrl = billingApiUrl || contextBillingUrl;
3317
3747
  const displayError = externalError ?? error;
3318
- const themeBundle = (0, import_react9.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
3319
- const bStyles = (0, import_react9.useMemo)(() => {
3748
+ const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared6.resolveTheme)(theme), [theme]);
3749
+ const bStyles = (0, import_react10.useMemo)(() => {
3320
3750
  const base = themeBundle?.buttonsLayout ?? (0, import_shared5.resolveButtonsLayoutTheme)(buttonsTheme);
3321
3751
  if (!buttonsStylesOverride) return base;
3322
3752
  return {
@@ -3331,7 +3761,7 @@ function SplitCardFormInner({
3331
3761
  };
3332
3762
  }, [themeBundle, buttonsTheme, buttonsStylesOverride]);
3333
3763
  const appearance = appearanceOverride ?? themeBundle?.appearance;
3334
- const vaultThemeColors = (0, import_react9.useMemo)(() => {
3764
+ const vaultThemeColors = (0, import_react10.useMemo)(() => {
3335
3765
  const vars = appearance?.variables;
3336
3766
  const asString = (value) => typeof value === "string" && value ? value : void 0;
3337
3767
  const submitButtonStyle = bStyles.submitButton;
@@ -3360,7 +3790,7 @@ function SplitCardFormInner({
3360
3790
  const isSubmitting = (externalProcessing ?? processing) || isInlineSessionPatchProcessing;
3361
3791
  const isSelfContained = !onTokenizedBody;
3362
3792
  const baseUrl = resolvedBillingApiUrl.replace(/\/+$/, "");
3363
- const resolvedAccount = (0, import_react9.useMemo)(() => mergeAccountPatch({
3793
+ const resolvedAccount = (0, import_react10.useMemo)(() => mergeAccountPatch({
3364
3794
  userId,
3365
3795
  email,
3366
3796
  firstName,
@@ -3368,17 +3798,17 @@ function SplitCardFormInner({
3368
3798
  country: countryProp,
3369
3799
  zip: zipProp
3370
3800
  }, accountPatch), [userId, email, firstName, lastName, countryProp, zipProp, accountPatch]);
3371
- const stripeInstance = (0, import_react9.useMemo)(() => {
3801
+ const stripeInstance = (0, import_react10.useMemo)(() => {
3372
3802
  if (!flopay) return null;
3373
3803
  return flopay.getRawProvider();
3374
3804
  }, [flopay]);
3375
- const paypalStripeInstance = (0, import_react9.useMemo)(() => {
3805
+ const paypalStripeInstance = (0, import_react10.useMemo)(() => {
3376
3806
  if (!paypalFlopay) return null;
3377
3807
  return paypalFlopay.getRawProvider();
3378
3808
  }, [paypalFlopay]);
3379
3809
  const amountInCents = totalAmount || 100;
3380
3810
  const stripeAppearanceProp = appearance ? { appearance } : null;
3381
- const paymentElementAppearance = (0, import_react9.useMemo)(() => {
3811
+ const paymentElementAppearance = (0, import_react10.useMemo)(() => {
3382
3812
  const base = appearance ?? {};
3383
3813
  const baseRules = base.rules ?? {};
3384
3814
  return {
@@ -3398,7 +3828,7 @@ function SplitCardFormInner({
3398
3828
  }
3399
3829
  };
3400
3830
  }, [appearance]);
3401
- const walletOptions = (0, import_react9.useMemo)(() => {
3831
+ const walletOptions = (0, import_react10.useMemo)(() => {
3402
3832
  const modeOptions = resolveWalletElementsMode(totalAmount);
3403
3833
  return {
3404
3834
  ...modeOptions,
@@ -3409,7 +3839,7 @@ function SplitCardFormInner({
3409
3839
  ...stripeAppearanceProp
3410
3840
  };
3411
3841
  }, [totalAmount, currency, stripeAppearanceProp]);
3412
- const paypalOptions = (0, import_react9.useMemo)(() => ({
3842
+ const paypalOptions = (0, import_react10.useMemo)(() => ({
3413
3843
  mode: "payment",
3414
3844
  amount: amountInCents,
3415
3845
  currency: currency.toLowerCase(),
@@ -3417,29 +3847,29 @@ function SplitCardFormInner({
3417
3847
  setupFutureUsage: "off_session",
3418
3848
  ...stripeAppearanceProp
3419
3849
  }), [amountInCents, currency, stripeAppearanceProp]);
3420
- const updateError = (0, import_react9.useCallback)(
3850
+ const updateError = (0, import_react10.useCallback)(
3421
3851
  (err) => {
3422
3852
  setError(err);
3423
3853
  onErrorChange?.(err);
3424
3854
  },
3425
3855
  [onErrorChange]
3426
3856
  );
3427
- (0, import_react9.useEffect)(() => {
3857
+ (0, import_react10.useEffect)(() => {
3428
3858
  if (!vaultActive || !cardCapture) return;
3429
3859
  cardCapture.setCardFieldOrder?.(cardFieldOrder ?? null, avsConfig == null);
3430
3860
  }, [vaultActive, cardCapture, cardFieldOrder, avsConfig]);
3431
- (0, import_react9.useEffect)(() => {
3861
+ (0, import_react10.useEffect)(() => {
3432
3862
  if (viewState === "expanding" || viewState === "collapsing" || viewState === "apm-expanding" || viewState === "apm-collapsing") {
3433
3863
  updateError(null);
3434
3864
  }
3435
3865
  }, [viewState, updateError]);
3436
- const emitDecline = (0, import_react9.useCallback)(
3866
+ const emitDecline = (0, import_react10.useCallback)(
3437
3867
  (method, input, overrides) => {
3438
3868
  onDecline?.(buildDeclineEvent(method, input, overrides));
3439
3869
  },
3440
3870
  [onDecline]
3441
3871
  );
3442
- const recoverExternalMethodTechnicalFailure = (0, import_react9.useCallback)(
3872
+ const recoverExternalMethodTechnicalFailure = (0, import_react10.useCallback)(
3443
3873
  (method, err, options) => {
3444
3874
  const popupBlocked = options?.popupBlocked ?? isPopupBlockedError(err);
3445
3875
  const message = buildExternalMethodRecoveryMessage(method, popupBlocked);
@@ -3463,7 +3893,7 @@ function SplitCardFormInner({
3463
3893
  },
3464
3894
  [layout, onError, updateError]
3465
3895
  );
3466
- (0, import_react9.useEffect)(() => {
3896
+ (0, import_react10.useEffect)(() => {
3467
3897
  if (!vaultActive || !sessionId) {
3468
3898
  setVaultMount(null);
3469
3899
  return;
@@ -3501,7 +3931,7 @@ function SplitCardFormInner({
3501
3931
  nonce,
3502
3932
  updateError
3503
3933
  ]);
3504
- const vaultOutcomeRef = (0, import_react9.useRef)({
3934
+ const vaultOutcomeRef = (0, import_react10.useRef)({
3505
3935
  onComplete,
3506
3936
  onError,
3507
3937
  updateError,
@@ -3527,8 +3957,8 @@ function SplitCardFormInner({
3527
3957
  nonce,
3528
3958
  baseUrl
3529
3959
  };
3530
- const vaultCompletedRef = (0, import_react9.useRef)(false);
3531
- const buildVaultAccountSnapshot = (0, import_react9.useCallback)(() => {
3960
+ const vaultCompletedRef = (0, import_react10.useRef)(false);
3961
+ const buildVaultAccountSnapshot = (0, import_react10.useCallback)(() => {
3532
3962
  const { resolvedAccount: resolvedAccount2, avsConfig: avsConfig2, fullName: fullName2, avsCheckProp: avsCheckProp2 } = vaultOutcomeRef.current;
3533
3963
  const cc = selectedCountryRef.current || resolvedAccount2.country || "US";
3534
3964
  const stateVisible = avsConfig2 ? (0, import_shared5.isAVSFieldVisible)(avsConfig2.state, cc) : false;
@@ -3564,11 +3994,11 @@ function SplitCardFormInner({
3564
3994
  } : {}
3565
3995
  };
3566
3996
  }, []);
3567
- (0, import_react9.useEffect)(() => {
3997
+ (0, import_react10.useEffect)(() => {
3568
3998
  if (!vaultActive || !cardCapture) return;
3569
3999
  cardCapture.setSubmitGate?.(avsInvalid);
3570
4000
  }, [vaultActive, cardCapture, avsInvalid]);
3571
- (0, import_react9.useEffect)(() => {
4001
+ (0, import_react10.useEffect)(() => {
3572
4002
  if (!vaultActive || !cardCapture) return;
3573
4003
  vaultCompletedRef.current = false;
3574
4004
  let cancelled = false;
@@ -3629,18 +4059,18 @@ function SplitCardFormInner({
3629
4059
  const hasEnabledMethodsPayload = Array.isArray(enabledPaymentMethods);
3630
4060
  const hasEnabledMethods = hasEnabledMethodsPayload && enabledPaymentMethods.length > 0;
3631
4061
  const paypalEnabled = hasEnabledMethodsPayload && enabledPaymentMethods.includes("paypal");
3632
- const { expressMethods, paymentElementMethods } = (0, import_react9.useMemo)(
4062
+ const { expressMethods, paymentElementMethods } = (0, import_react10.useMemo)(
3633
4063
  () => (0, import_shared5.partitionStripeMethods)(enabledPaymentMethods, {
3634
4064
  excludePaypal: directPaypalConfigured
3635
4065
  }),
3636
4066
  [enabledPaymentMethods, directPaypalConfigured]
3637
4067
  );
3638
4068
  const paypalRenderedSeparately = directPaypalConfigured || !!paypalFlopay;
3639
- const expressMethodsForWalletRow = (0, import_react9.useMemo)(
4069
+ const expressMethodsForWalletRow = (0, import_react10.useMemo)(
3640
4070
  () => paypalRenderedSeparately ? expressMethods.filter((m) => m !== "paypal") : expressMethods,
3641
4071
  [expressMethods, paypalRenderedSeparately]
3642
4072
  );
3643
- const legacyExpressMethods = (0, import_react9.useMemo)(() => {
4073
+ const legacyExpressMethods = (0, import_react10.useMemo)(() => {
3644
4074
  const out = [];
3645
4075
  if (showApplePay) out.push("apple_pay");
3646
4076
  if (showGooglePay) out.push("google_pay");
@@ -3649,7 +4079,7 @@ function SplitCardFormInner({
3649
4079
  const walletExpressMethods = hasEnabledMethodsPayload ? expressMethodsForWalletRow : legacyExpressMethods;
3650
4080
  const showWallets = showStripe && walletExpressMethods.length > 0;
3651
4081
  const apmCountry = enableAVS ? selectedCountry : countryProp;
3652
- const paymentElementMethodsForCurrency = (0, import_react9.useMemo)(() => {
4082
+ const paymentElementMethodsForCurrency = (0, import_react10.useMemo)(() => {
3653
4083
  const target = apmCountry?.trim().toUpperCase();
3654
4084
  if (!target) return paymentElementMethods;
3655
4085
  if (!enabledPaymentMethodCountries) {
@@ -3660,19 +4090,19 @@ function SplitCardFormInner({
3660
4090
  return !allowed || allowed.length === 0 || allowed.includes(target);
3661
4091
  });
3662
4092
  }, [paymentElementMethods, apmCountry, enabledPaymentMethodCountries]);
3663
- const paymentElementBaseOptions = (0, import_react9.useMemo)(() => ({
4093
+ const paymentElementBaseOptions = (0, import_react10.useMemo)(() => ({
3664
4094
  mode: "payment",
3665
4095
  amount: amountInCents,
3666
4096
  currency: currency.toLowerCase(),
3667
4097
  paymentMethodCreation: "manual",
3668
4098
  appearance: paymentElementAppearance
3669
4099
  }), [amountInCents, currency, paymentElementAppearance]);
3670
- const [paypalLoadState, setPaypalLoadState] = (0, import_react9.useState)("loading");
3671
- const [walletLoadState, setWalletLoadState] = (0, import_react9.useState)("loading");
3672
- const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react9.useState)("loading");
3673
- const [directPaypalReady, setDirectPaypalReady] = (0, import_react9.useState)(false);
3674
- const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react9.useState)();
3675
- (0, import_react9.useEffect)(() => {
4100
+ const [paypalLoadState, setPaypalLoadState] = (0, import_react10.useState)("loading");
4101
+ const [walletLoadState, setWalletLoadState] = (0, import_react10.useState)("loading");
4102
+ const [paymentElementLoadState, setPaymentElementLoadState] = (0, import_react10.useState)("loading");
4103
+ const [directPaypalReady, setDirectPaypalReady] = (0, import_react10.useState)(false);
4104
+ const [inAppBrowserDetected, setInAppBrowserDetected] = (0, import_react10.useState)();
4105
+ (0, import_react10.useEffect)(() => {
3676
4106
  setInAppBrowserDetected(isInAppBrowser());
3677
4107
  }, []);
3678
4108
  const shouldShowPayPal = showPayPal && (directPaypalConfigured || (hasEnabledMethodsPayload ? paypalEnabled : inAppBrowserDetected === false));
@@ -3684,8 +4114,8 @@ function SplitCardFormInner({
3684
4114
  const shouldDisplayPayPalRow = shouldRenderDirectPayPal ? directPaypalReady : shouldRenderStripePayPal && isExpressCheckoutRowVisible(paypalLoadState);
3685
4115
  const shouldDisplayWalletRow = shouldRenderWallets && isExpressCheckoutRowVisible(walletLoadState);
3686
4116
  const shouldDisplayPaymentElementRow = shouldRenderPaymentElement && paymentElementLoadState !== "load_error";
3687
- const validationFiredRef = (0, import_react9.useRef)(false);
3688
- (0, import_react9.useEffect)(() => {
4117
+ const validationFiredRef = (0, import_react10.useRef)(false);
4118
+ (0, import_react10.useEffect)(() => {
3689
4119
  if (validationFiredRef.current) return;
3690
4120
  if (!showStripe && !showPayPal) {
3691
4121
  validationFiredRef.current = true;
@@ -3705,8 +4135,8 @@ function SplitCardFormInner({
3705
4135
  updateError(err.message);
3706
4136
  }
3707
4137
  }, [showStripe, showPayPal, directPaypalConfigured, paypalStripeInstance, onError, updateError]);
3708
- const deprecationLoggedRef = (0, import_react9.useRef)(false);
3709
- (0, import_react9.useEffect)(() => {
4138
+ const deprecationLoggedRef = (0, import_react10.useRef)(false);
4139
+ (0, import_react10.useEffect)(() => {
3710
4140
  if (deprecationLoggedRef.current) return;
3711
4141
  if (!hasEnabledMethods) return;
3712
4142
  const stale = [];
@@ -3718,14 +4148,14 @@ function SplitCardFormInner({
3718
4148
  `[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.`
3719
4149
  );
3720
4150
  }, [hasEnabledMethods, showApplePay, showGooglePay]);
3721
- const handleNameChange = (0, import_react9.useCallback)((value) => {
4151
+ const handleNameChange = (0, import_react10.useCallback)((value) => {
3722
4152
  setFullName(value);
3723
4153
  onFullNameChange?.(value);
3724
4154
  const parts = value.trim().split(/\s+/);
3725
4155
  onFirstNameChange?.(parts[0] ?? "");
3726
4156
  onLastNameChange?.(parts.length > 1 ? parts.slice(1).join(" ") : "");
3727
4157
  }, [onFullNameChange, onFirstNameChange, onLastNameChange]);
3728
- const applyInlineSessionPatch = (0, import_react9.useCallback)(
4158
+ const applyInlineSessionPatch = (0, import_react10.useCallback)(
3729
4159
  (patch, method) => {
3730
4160
  if (!checkout.applyInlineSessionPatch) {
3731
4161
  return Promise.resolve({ error: null, sessionId, nonce });
@@ -3747,7 +4177,7 @@ function SplitCardFormInner({
3747
4177
  },
3748
4178
  [checkout.applyInlineSessionPatch, nonce, onError, sessionId, updateError]
3749
4179
  );
3750
- const runBeforeButtonClick = (0, import_react9.useCallback)(async (method) => {
4180
+ const runBeforeButtonClick = (0, import_react10.useCallback)(async (method) => {
3751
4181
  if (!onBeforeButtonClick) return { proceed: true };
3752
4182
  try {
3753
4183
  const result = await onBeforeButtonClick({
@@ -3784,7 +4214,7 @@ function SplitCardFormInner({
3784
4214
  return { proceed: false };
3785
4215
  }
3786
4216
  }, [applyInlineSessionPatch, checkout.inlineSessionDraft, onBeforeButtonClick, onError, sessionId, updateError]);
3787
- const processPaymentInternal = (0, import_react9.useCallback)(
4217
+ const processPaymentInternal = (0, import_react10.useCallback)(
3788
4218
  async (tokenizedBody, overrides) => {
3789
4219
  if (processingRef.current) return;
3790
4220
  processingRef.current = true;
@@ -3995,7 +4425,7 @@ function SplitCardFormInner({
3995
4425
  },
3996
4426
  [baseUrl, sessionId, nonce, resolvedAccount, fullName, chv, flopay, paypalFlopay, onComplete, onError, updateError, emitDecline]
3997
4427
  );
3998
- const dispatchTokenizedBody = (0, import_react9.useCallback)(
4428
+ const dispatchTokenizedBody = (0, import_react10.useCallback)(
3999
4429
  (tokenizedBody, overrides) => {
4000
4430
  if (onTokenizedBody) {
4001
4431
  onTokenizedBody(tokenizedBody);
@@ -4005,7 +4435,7 @@ function SplitCardFormInner({
4005
4435
  },
4006
4436
  [onTokenizedBody, processPaymentInternal]
4007
4437
  );
4008
- (0, import_react9.useImperativeHandle)(innerRef, () => ({
4438
+ (0, import_react10.useImperativeHandle)(innerRef, () => ({
4009
4439
  async handleNextAction(secret) {
4010
4440
  if (!flopay) return;
4011
4441
  setIs3DSActive(true);
@@ -4032,8 +4462,8 @@ function SplitCardFormInner({
4032
4462
  }
4033
4463
  }
4034
4464
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
4035
- const stripeResumeAttemptedRef = (0, import_react9.useRef)(false);
4036
- (0, import_react9.useEffect)(() => {
4465
+ const stripeResumeAttemptedRef = (0, import_react10.useRef)(false);
4466
+ (0, import_react10.useEffect)(() => {
4037
4467
  if (typeof window === "undefined" || stripeResumeAttemptedRef.current) return;
4038
4468
  const params = new URLSearchParams(window.location.search);
4039
4469
  const paymentIntentId = params.get("payment_intent");
@@ -4094,7 +4524,7 @@ function SplitCardFormInner({
4094
4524
  return;
4095
4525
  }
4096
4526
  const piStatus = paymentIntent?.status;
4097
- const successful = piStatus === "succeeded" || piStatus === "requires_capture" || piStatus === "processing";
4527
+ const successful = isSuccessfulPaymentIntentStatus(piStatus);
4098
4528
  if (!paymentIntent || !successful) {
4099
4529
  const message = piStatus === "canceled" ? "Payment was canceled." : "Payment was not completed. Please try again.";
4100
4530
  updateError(message);
@@ -4111,7 +4541,7 @@ function SplitCardFormInner({
4111
4541
  }, persistedOverrides);
4112
4542
  })();
4113
4543
  }, [sessionId, dispatchTokenizedBody, flopay, updateError, emitDecline]);
4114
- const handleSubmit = (0, import_react9.useCallback)(
4544
+ const handleSubmit = (0, import_react10.useCallback)(
4115
4545
  async (e) => {
4116
4546
  e.preventDefault();
4117
4547
  if (!flopay || !elements || isSubmitting || processingRef.current) return;
@@ -4194,8 +4624,7 @@ function SplitCardFormInner({
4194
4624
  updateError(pmResult.error?.message ?? "Failed to create payment method.");
4195
4625
  return;
4196
4626
  }
4197
- const intentHeaders = { "Content-Type": "application/json" };
4198
- if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
4627
+ const intentHeaders = intentRequestHeaders(nonce);
4199
4628
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
4200
4629
  method: "POST",
4201
4630
  headers: intentHeaders,
@@ -4271,7 +4700,7 @@ function SplitCardFormInner({
4271
4700
  );
4272
4701
  const isReady = flopay !== null && (vaultActive || elements !== null);
4273
4702
  if (!isReady) {
4274
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
4703
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." });
4275
4704
  }
4276
4705
  const isButtons = layout === "buttons";
4277
4706
  const appearanceVars = appearance?.variables;
@@ -4330,7 +4759,7 @@ function SplitCardFormInner({
4330
4759
  const containerOverrides = bStyles.cardFormContainer ?? {};
4331
4760
  const containerPadding = containerOverrides.padding ?? (isButtons ? "0" : "1rem");
4332
4761
  const containerRadius = containerOverrides.borderRadius ?? resolvedBorderRadius;
4333
- const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4762
+ const vaultCardFieldsNode = cardCapture && vaultMount ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4334
4763
  VaultCardFields,
4335
4764
  {
4336
4765
  capture: cardCapture,
@@ -4368,7 +4797,7 @@ function SplitCardFormInner({
4368
4797
  if (message) setOverlayStatus(null);
4369
4798
  }
4370
4799
  }
4371
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4800
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4372
4801
  "div",
4373
4802
  {
4374
4803
  "data-testid": "flopay-vault-loading",
@@ -4383,7 +4812,7 @@ function SplitCardFormInner({
4383
4812
  children: "Loading secure card form\u2026"
4384
4813
  }
4385
4814
  );
4386
- const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4815
+ const cardFormBlock = /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
4387
4816
  backgroundColor: cardBg,
4388
4817
  borderRadius: containerRadius,
4389
4818
  ...containerOverrides,
@@ -4396,7 +4825,7 @@ function SplitCardFormInner({
4396
4825
  display: "flex",
4397
4826
  flexDirection: "column"
4398
4827
  }, children: [
4399
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
4828
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
4400
4829
  .flopay-shared-input::placeholder {
4401
4830
  color: var(--flopay-input-placeholder-color);
4402
4831
  opacity: 1;
@@ -4405,14 +4834,14 @@ function SplitCardFormInner({
4405
4834
  font-weight: var(--flopay-input-font-weight);
4406
4835
  }
4407
4836
  ` }),
4408
- isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
4837
+ isButtons && showCardForm && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
4409
4838
  display: "flex",
4410
4839
  alignItems: "center",
4411
4840
  padding: "0.75rem 0 0.625rem",
4412
4841
  // Keep the header on top when AVS is ordered above the card on vault.
4413
4842
  order: vaultActive ? -2 : 0
4414
4843
  }, children: [
4415
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4844
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4416
4845
  "button",
4417
4846
  {
4418
4847
  type: "button",
@@ -4434,7 +4863,7 @@ function SplitCardFormInner({
4434
4863
  },
4435
4864
  "aria-label": "Back to payment methods",
4436
4865
  children: [
4437
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
4866
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
4438
4867
  display: "inline-flex",
4439
4868
  alignItems: "center",
4440
4869
  justifyContent: "center",
@@ -4444,12 +4873,12 @@ function SplitCardFormInner({
4444
4873
  backgroundColor: "#f3f4f6",
4445
4874
  transition: "background-color 0.15s",
4446
4875
  ...bStyles.backButtonIcon
4447
- }, 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" }) }) }),
4448
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4876
+ }, 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" }) }) }),
4877
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
4449
4878
  ]
4450
4879
  }
4451
4880
  ),
4452
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4881
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4453
4882
  flex: 1,
4454
4883
  textAlign: "center",
4455
4884
  fontWeight: 600,
@@ -4457,9 +4886,9 @@ function SplitCardFormInner({
4457
4886
  color: "#262833",
4458
4887
  paddingRight: 80,
4459
4888
  ...bStyles.title
4460
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) })
4889
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
4461
4890
  ] }),
4462
- !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4891
+ !isButtons && !hideTitle && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4463
4892
  textAlign: "center",
4464
4893
  fontWeight: 600,
4465
4894
  fontSize: "1.1rem",
@@ -4469,17 +4898,17 @@ function SplitCardFormInner({
4469
4898
  // (-2) and AVS block (-1) are ordered below it but above the card form.
4470
4899
  order: vaultActive ? -3 : 0,
4471
4900
  ...bStyles.title
4472
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
4473
- !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4474
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4901
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) }),
4902
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
4903
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4475
4904
  backgroundColor: cardInputBg,
4476
4905
  border: `1px solid ${resolvedBorder}`,
4477
4906
  borderTopLeftRadius: resolvedBorderRadius,
4478
4907
  borderTopRightRadius: resolvedBorderRadius,
4479
4908
  padding: "10px"
4480
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
4481
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex" }, children: [
4482
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4909
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardNumberElement, { onReady: () => setFormReady(true), options: stripeElementStyle }) }),
4910
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
4911
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4483
4912
  flex: 1,
4484
4913
  backgroundColor: cardInputBg,
4485
4914
  // Longhand only — mixing `border` shorthand with per-side
@@ -4491,8 +4920,8 @@ function SplitCardFormInner({
4491
4920
  borderLeft: `1px solid ${resolvedBorder}`,
4492
4921
  borderBottomLeftRadius: resolvedBorderRadius,
4493
4922
  padding: "10px"
4494
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
4495
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4923
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardExpiryElement, { options: stripeElementStyle }) }),
4924
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4496
4925
  flex: 1,
4497
4926
  backgroundColor: cardInputBg,
4498
4927
  borderTop: "none",
@@ -4501,16 +4930,16 @@ function SplitCardFormInner({
4501
4930
  borderLeft: `1px solid ${resolvedBorder}`,
4502
4931
  borderBottomRightRadius: resolvedBorderRadius,
4503
4932
  padding: "10px"
4504
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardCvcElement, { options: stripeElementStyle }) })
4933
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardCvcElement, { options: stripeElementStyle }) })
4505
4934
  ] })
4506
4935
  ] }),
4507
- !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
4936
+ !vaultActive && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4508
4937
  backgroundColor: cardInputBg,
4509
4938
  border: `1px solid ${resolvedBorder}`,
4510
4939
  borderRadius: resolvedBorderRadius,
4511
4940
  marginTop: "0.5rem",
4512
4941
  padding: "10px"
4513
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4942
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4514
4943
  "input",
4515
4944
  {
4516
4945
  className: "flopay-shared-input",
@@ -4532,7 +4961,7 @@ function SplitCardFormInner({
4532
4961
  }
4533
4962
  }
4534
4963
  ) }),
4535
- avsConfig && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
4964
+ avsConfig && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { order: vaultActive ? -1 : 0 }, "data-testid": "flopay-avs-fields", children: (() => {
4536
4965
  const cc = selectedCountry;
4537
4966
  const inputWrapStyle = (invalid = false) => ({
4538
4967
  backgroundColor: cardInputBg,
@@ -4549,8 +4978,8 @@ function SplitCardFormInner({
4549
4978
  ...sharedInputTypography
4550
4979
  });
4551
4980
  const stateOpts = (0, import_shared5.getStateOptions)(cc);
4552
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4553
- (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)(
4981
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
4982
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_1, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: inputWrapStyle(invalidAvsFields.line1), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4554
4983
  "input",
4555
4984
  {
4556
4985
  className: "flopay-shared-input",
@@ -4569,7 +4998,7 @@ function SplitCardFormInner({
4569
4998
  style: inputFieldStyle()
4570
4999
  }
4571
5000
  ) }),
4572
- (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)(
5001
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.address_line_2, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: inputWrapStyle(), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4573
5002
  "input",
4574
5003
  {
4575
5004
  className: "flopay-shared-input",
@@ -4587,12 +5016,12 @@ function SplitCardFormInner({
4587
5016
  style: inputFieldStyle()
4588
5017
  }
4589
5018
  ) }),
4590
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5019
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc)) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
4591
5020
  display: "flex",
4592
5021
  gap: "0",
4593
5022
  marginTop: "0.5rem"
4594
5023
  }, children: [
4595
- (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5024
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4596
5025
  flex: 1,
4597
5026
  backgroundColor: cardInputBg,
4598
5027
  borderTop: `1px solid ${avsBorderColor(invalidAvsFields.city)}`,
@@ -4603,7 +5032,7 @@ function SplitCardFormInner({
4603
5032
  borderTopLeftRadius: resolvedBorderRadius,
4604
5033
  borderBottomLeftRadius: resolvedBorderRadius,
4605
5034
  ...(0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) ? { borderRight: "none", borderTopRightRadius: 0, borderBottomRightRadius: 0 } : { borderRadius: resolvedBorderRadius }
4606
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5035
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4607
5036
  "input",
4608
5037
  {
4609
5038
  className: "flopay-shared-input",
@@ -4622,7 +5051,7 @@ function SplitCardFormInner({
4622
5051
  style: inputFieldStyle()
4623
5052
  }
4624
5053
  ) }),
4625
- (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5054
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.state, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4626
5055
  flex: 1,
4627
5056
  backgroundColor: cardInputBg,
4628
5057
  border: `1px solid ${avsBorderColor(invalidAvsFields.state)}`,
@@ -4630,7 +5059,7 @@ function SplitCardFormInner({
4630
5059
  borderTopRightRadius: resolvedBorderRadius,
4631
5060
  borderBottomRightRadius: resolvedBorderRadius,
4632
5061
  ...(0, import_shared5.isAVSFieldVisible)(avsConfig.city, cc) ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0 } : { borderRadius: resolvedBorderRadius }
4633
- }, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5062
+ }, children: stateOpts ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4634
5063
  "select",
4635
5064
  {
4636
5065
  id: "flopay-billing-state",
@@ -4646,11 +5075,11 @@ function SplitCardFormInner({
4646
5075
  "data-testid": "flopay-state",
4647
5076
  style: { ...inputFieldStyle(), cursor: "pointer" },
4648
5077
  children: [
4649
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
4650
- stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: s.code, children: s.name }, s.code))
5078
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: (0, import_shared5.getStateLabel)(cc) }),
5079
+ stateOpts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: s.code, children: s.name }, s.code))
4651
5080
  ]
4652
5081
  }
4653
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5082
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4654
5083
  "input",
4655
5084
  {
4656
5085
  className: "flopay-shared-input",
@@ -4670,13 +5099,13 @@ function SplitCardFormInner({
4670
5099
  }
4671
5100
  ) })
4672
5101
  ] }),
4673
- ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5102
+ ((0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) || (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc)) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
4674
5103
  display: "flex",
4675
5104
  flexDirection: avsLayoutProp === "column" ? "column" : "row",
4676
5105
  gap: avsLayoutProp === "column" ? "0.5rem" : "0",
4677
5106
  marginTop: "0.5rem"
4678
5107
  }, children: [
4679
- (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5108
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4680
5109
  flex: avsLayoutProp === "row" ? 1 : void 0,
4681
5110
  backgroundColor: cardInputBg,
4682
5111
  borderTop: `1px solid ${resolvedBorder}`,
@@ -4685,7 +5114,7 @@ function SplitCardFormInner({
4685
5114
  borderLeft: `1px solid ${resolvedBorder}`,
4686
5115
  padding: "10px",
4687
5116
  ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) ? { borderRadius: "0", borderTopLeftRadius: resolvedBorderRadius, borderBottomLeftRadius: resolvedBorderRadius, borderRight: "none" } : { borderRadius: resolvedBorderRadius }
4688
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5117
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4689
5118
  "select",
4690
5119
  {
4691
5120
  id: "flopay-billing-country",
@@ -4702,20 +5131,20 @@ function SplitCardFormInner({
4702
5131
  autoComplete: "billing country",
4703
5132
  "data-testid": "flopay-country",
4704
5133
  style: { ...inputFieldStyle(), cursor: "pointer" },
4705
- children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("option", { value: c.code, children: [
5134
+ children: import_shared5.COUNTRY_OPTIONS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("option", { value: c.code, children: [
4706
5135
  c.flag,
4707
5136
  " ",
4708
5137
  c.name
4709
5138
  ] }, c.code))
4710
5139
  }
4711
5140
  ) }),
4712
- (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5141
+ (0, import_shared5.isAVSFieldVisible)(avsConfig.postal_code, cc) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
4713
5142
  flex: avsLayoutProp === "row" ? 1 : void 0,
4714
5143
  backgroundColor: cardInputBg,
4715
5144
  border: `1px solid ${zipBorderColor}`,
4716
5145
  padding: "10px",
4717
5146
  ...avsLayoutProp === "row" && (0, import_shared5.isAVSFieldVisible)(avsConfig.country, cc) ? { borderRadius: "0", borderTopRightRadius: resolvedBorderRadius, borderBottomRightRadius: resolvedBorderRadius } : { borderRadius: resolvedBorderRadius }
4718
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5147
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4719
5148
  "input",
4720
5149
  {
4721
5150
  className: "flopay-shared-input",
@@ -4739,7 +5168,7 @@ function SplitCardFormInner({
4739
5168
  }
4740
5169
  ) })
4741
5170
  ] }),
4742
- showPostcodeError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5171
+ showPostcodeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4743
5172
  "div",
4744
5173
  {
4745
5174
  id: "flopay-billing-postal-code-error",
@@ -4756,26 +5185,10 @@ function SplitCardFormInner({
4756
5185
  )
4757
5186
  ] });
4758
5187
  })() }),
4759
- vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
5188
+ vaultActive && cardPreFormSlot && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { order: -2, width: "100%" }, children: cardPreFormSlot }),
4760
5189
  vaultActive && vaultCardFieldsNode,
4761
- displayError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
4762
- margin: "0.75rem 0",
4763
- padding: "0.625rem 0.875rem",
4764
- background: "#FEF2F2",
4765
- border: "1px solid #FECACA",
4766
- borderRadius: "8px",
4767
- color: "#991B1B",
4768
- fontSize: "0.85rem",
4769
- fontWeight: 600,
4770
- display: "flex",
4771
- alignItems: "center",
4772
- gap: "0.5rem",
4773
- ...bStyles.errorBanner ? bStyles.errorBanner : {}
4774
- }, children: [
4775
- /* @__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" }) }),
4776
- displayError
4777
- ] }),
4778
- !vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5190
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.75rem 0", styleOverride: bStyles.errorBanner, children: displayError }),
5191
+ !vaultActive && (children ?? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4779
5192
  "button",
4780
5193
  {
4781
5194
  type: "submit",
@@ -4820,9 +5233,9 @@ function SplitCardFormInner({
4820
5233
  const renderDirectPaypalGateDebug = (testId) => {
4821
5234
  if (!debug) return null;
4822
5235
  if (!showPayPal || !directPaypalConfigured) {
4823
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
5236
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/DirectPayPal-debug - not enabled" });
4824
5237
  }
4825
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
5238
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4826
5239
  "FloPay/DirectPayPal-debug (parent gate)",
4827
5240
  ` showPayPal=${showPayPal}`,
4828
5241
  ` directPaypalConfigured=${directPaypalConfigured}`,
@@ -4835,9 +5248,9 @@ function SplitCardFormInner({
4835
5248
  const renderStripeGateDebug = (testId) => {
4836
5249
  if (!debug) return null;
4837
5250
  if (!showStripe || !stripeInstance) {
4838
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
5251
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: "FloPay/Stripe-debug - not enabled" });
4839
5252
  }
4840
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
5253
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { "data-testid": testId, style: gateDebugStyle, children: [
4841
5254
  "FloPay/Stripe-debug (parent gate)",
4842
5255
  ` showStripe=${showStripe}`,
4843
5256
  ` currency=${currency}`,
@@ -4866,11 +5279,11 @@ function SplitCardFormInner({
4866
5279
  const cardButtonSizing = cardButtonContent === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
4867
5280
  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;
4868
5281
  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;
4869
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
4870
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
4871
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
4872
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "grid" }, children: [
4873
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5282
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5283
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
5284
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
5285
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "grid" }, children: [
5286
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4874
5287
  "div",
4875
5288
  {
4876
5289
  "data-testid": "flopay-buttons-panel",
@@ -4887,8 +5300,8 @@ function SplitCardFormInner({
4887
5300
  children: [
4888
5301
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug"),
4889
5302
  renderStripeGateDebug("flopay-stripe-gate-debug"),
4890
- shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4891
- paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5303
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
5304
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4892
5305
  "div",
4893
5306
  {
4894
5307
  "data-testid": "flopay-paypal-direct-retry-notice",
@@ -4904,7 +5317,7 @@ function SplitCardFormInner({
4904
5317
  children: "Please confirm your PayPal payment to complete checkout."
4905
5318
  }
4906
5319
  ),
4907
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5320
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4908
5321
  DirectPayPalButton,
4909
5322
  {
4910
5323
  sessionId,
@@ -4931,7 +5344,7 @@ function SplitCardFormInner({
4931
5344
  paypalDirectRetry?.orderId ?? "fresh"
4932
5345
  )
4933
5346
  ] }),
4934
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5347
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4935
5348
  PayPalButtonInner,
4936
5349
  {
4937
5350
  sessionId,
@@ -4949,7 +5362,7 @@ function SplitCardFormInner({
4949
5362
  placeholderBorderRadius: buttonBorderRadius
4950
5363
  }
4951
5364
  ) }),
4952
- shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5365
+ shouldRenderWallets ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4953
5366
  WalletButtonInner,
4954
5367
  {
4955
5368
  sessionId,
@@ -4966,8 +5379,8 @@ function SplitCardFormInner({
4966
5379
  onLoadStateChange: setWalletLoadState,
4967
5380
  placeholderBorderRadius: buttonBorderRadius
4968
5381
  }
4969
- ) }) : 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,
4970
- shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5382
+ ) }) : shouldShowWallets ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT, borderRadius: buttonBorderRadius, background: "#e5e7eb", animation: "flopay-pulse 1.5s ease-in-out infinite" } }) : null,
5383
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4971
5384
  StripePaymentElementInner,
4972
5385
  {
4973
5386
  sessionId,
@@ -4999,7 +5412,7 @@ function SplitCardFormInner({
4999
5412
  }
5000
5413
  }
5001
5414
  ),
5002
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5415
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5003
5416
  "button",
5004
5417
  {
5005
5418
  type: "button",
@@ -5055,50 +5468,34 @@ function SplitCardFormInner({
5055
5468
  onMouseUp: (e) => {
5056
5469
  e.currentTarget.style.transform = "scale(1)";
5057
5470
  },
5058
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CardButtonContentSlot, { content: cardButtonContent })
5471
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
5059
5472
  }
5060
5473
  ),
5061
- displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", "data-testid": "flopay-error", style: {
5062
- margin: "0.25rem 0",
5063
- padding: "0.625rem 0.875rem",
5064
- background: "#FEF2F2",
5065
- border: "1px solid #FECACA",
5066
- borderRadius: "8px",
5067
- color: "#991B1B",
5068
- fontSize: "0.85rem",
5069
- fontWeight: 600,
5070
- display: "flex",
5071
- alignItems: "center",
5072
- gap: "0.5rem",
5073
- ...bStyles.errorBanner ? bStyles.errorBanner : {}
5074
- }, children: [
5075
- /* @__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" }) }),
5076
- displayError
5077
- ] })
5474
+ displayError && viewState === "buttons" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBanner, { margin: "0.25rem 0", styleOverride: bStyles.errorBanner, children: displayError })
5078
5475
  ]
5079
5476
  }
5080
5477
  ),
5081
- showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5478
+ showStripe && isCardView && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5082
5479
  gridArea: "1 / 1",
5083
5480
  ...cardAnim ? { animation: cardAnim } : {},
5084
5481
  ...viewState === "collapsing" ? { pointerEvents: "none" } : {}
5085
5482
  }, children: cardFormBlock }),
5086
- showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5483
+ showStripe && isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5087
5484
  gridArea: "1 / 1",
5088
5485
  ...apmAnim ? { animation: apmAnim } : {},
5089
5486
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
5090
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5487
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5091
5488
  backgroundColor: cardBg,
5092
5489
  borderRadius: containerRadius,
5093
5490
  ...containerOverrides,
5094
5491
  padding: containerPadding
5095
5492
  }, children: [
5096
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5493
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5097
5494
  display: "flex",
5098
5495
  alignItems: "center",
5099
5496
  padding: "0.75rem 0 0.625rem"
5100
5497
  }, children: [
5101
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5498
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5102
5499
  "button",
5103
5500
  {
5104
5501
  type: "button",
@@ -5121,7 +5518,7 @@ function SplitCardFormInner({
5121
5518
  },
5122
5519
  "aria-label": "Back to payment methods",
5123
5520
  children: [
5124
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
5521
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
5125
5522
  display: "inline-flex",
5126
5523
  alignItems: "center",
5127
5524
  justifyContent: "center",
@@ -5131,12 +5528,12 @@ function SplitCardFormInner({
5131
5528
  backgroundColor: "#f3f4f6",
5132
5529
  transition: "background-color 0.15s",
5133
5530
  ...bStyles.backButtonIcon
5134
- }, 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" }) }) }),
5135
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
5531
+ }, 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" }) }) }),
5532
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
5136
5533
  ]
5137
5534
  }
5138
5535
  ),
5139
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5536
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5140
5537
  flex: 1,
5141
5538
  textAlign: "center",
5142
5539
  fontWeight: 600,
@@ -5146,12 +5543,12 @@ function SplitCardFormInner({
5146
5543
  ...bStyles.title
5147
5544
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
5148
5545
  ] }),
5149
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5546
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5150
5547
  import_react_stripe_js.Elements,
5151
5548
  {
5152
5549
  stripe: stripeInstance,
5153
5550
  options: apmInlineOptions,
5154
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5551
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5155
5552
  StripeMethodInlineForm,
5156
5553
  {
5157
5554
  method: expandedApmMethod,
@@ -5181,24 +5578,24 @@ function SplitCardFormInner({
5181
5578
  ] });
5182
5579
  }
5183
5580
  if (isApmView && expandedApmMethod && apmInlineOptions && stripeInstance && showStripe) {
5184
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5185
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
5186
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
5187
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5581
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5582
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
5583
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
5584
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5188
5585
  ...apmAnim ? { animation: apmAnim } : {},
5189
5586
  ...viewState === "apm-collapsing" ? { pointerEvents: "none" } : {}
5190
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5587
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5191
5588
  backgroundColor: cardBg,
5192
5589
  borderRadius: containerRadius,
5193
5590
  ...containerOverrides,
5194
5591
  padding: containerPadding
5195
5592
  }, children: [
5196
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5593
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5197
5594
  display: "flex",
5198
5595
  alignItems: "center",
5199
5596
  padding: "0.75rem 0 0.625rem"
5200
5597
  }, children: [
5201
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
5598
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5202
5599
  "button",
5203
5600
  {
5204
5601
  type: "button",
@@ -5221,7 +5618,7 @@ function SplitCardFormInner({
5221
5618
  },
5222
5619
  "aria-label": "Back to payment methods",
5223
5620
  children: [
5224
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: {
5621
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
5225
5622
  display: "inline-flex",
5226
5623
  alignItems: "center",
5227
5624
  justifyContent: "center",
@@ -5231,12 +5628,12 @@ function SplitCardFormInner({
5231
5628
  backgroundColor: "#f3f4f6",
5232
5629
  transition: "background-color 0.15s",
5233
5630
  ...bStyles.backButtonIcon
5234
- }, 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" }) }) }),
5235
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
5631
+ }, 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" }) }) }),
5632
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
5236
5633
  ]
5237
5634
  }
5238
5635
  ),
5239
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
5636
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
5240
5637
  flex: 1,
5241
5638
  textAlign: "center",
5242
5639
  fontWeight: 600,
@@ -5246,12 +5643,12 @@ function SplitCardFormInner({
5246
5643
  ...bStyles.title
5247
5644
  }, children: `Pay with ${(0, import_shared5.getStripeMethodDisplayName)(expandedApmMethod)}` })
5248
5645
  ] }),
5249
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5646
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5250
5647
  import_react_stripe_js.Elements,
5251
5648
  {
5252
5649
  stripe: stripeInstance,
5253
5650
  options: apmInlineOptions,
5254
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5651
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5255
5652
  StripeMethodInlineForm,
5256
5653
  {
5257
5654
  method: expandedApmMethod,
@@ -5279,14 +5676,14 @@ function SplitCardFormInner({
5279
5676
  ] }) })
5280
5677
  ] });
5281
5678
  }
5282
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5283
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloPayKeyframes, {}),
5284
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
5285
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5679
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
5680
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FloPayKeyframes, {}),
5681
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProcessingOverlay, { status: overlayStatus, errorMessage: displayError }),
5682
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
5286
5683
  renderDirectPaypalGateDebug("flopay-direct-paypal-gate-debug-default"),
5287
5684
  renderStripeGateDebug("flopay-stripe-gate-debug-default"),
5288
- shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
5289
- paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5685
+ shouldRenderDirectPayPal && directPaypal && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
5686
+ paypalDirectRetry && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5290
5687
  "div",
5291
5688
  {
5292
5689
  "data-testid": "flopay-paypal-direct-retry-notice-default",
@@ -5302,7 +5699,7 @@ function SplitCardFormInner({
5302
5699
  children: "Please confirm your PayPal payment to complete checkout."
5303
5700
  }
5304
5701
  ),
5305
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5702
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5306
5703
  DirectPayPalButton,
5307
5704
  {
5308
5705
  sessionId,
@@ -5329,7 +5726,7 @@ function SplitCardFormInner({
5329
5726
  paypalDirectRetry?.orderId ?? "fresh"
5330
5727
  )
5331
5728
  ] }),
5332
- shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5729
+ shouldRenderStripePayPal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: paypalStripeInstance, options: paypalOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5333
5730
  PayPalButtonInner,
5334
5731
  {
5335
5732
  sessionId,
@@ -5347,7 +5744,7 @@ function SplitCardFormInner({
5347
5744
  placeholderBorderRadius: buttonBorderRadius
5348
5745
  }
5349
5746
  ) }),
5350
- shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5747
+ shouldRenderWallets && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_stripe_js.Elements, { stripe: stripeInstance, options: walletOptions, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5351
5748
  WalletButtonInner,
5352
5749
  {
5353
5750
  sessionId,
@@ -5365,7 +5762,7 @@ function SplitCardFormInner({
5365
5762
  placeholderBorderRadius: buttonBorderRadius
5366
5763
  }
5367
5764
  ) }),
5368
- shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5765
+ shouldRenderPaymentElement && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5369
5766
  StripePaymentElementInner,
5370
5767
  {
5371
5768
  sessionId,
@@ -5398,7 +5795,7 @@ function SplitCardFormInner({
5398
5795
  }
5399
5796
  )
5400
5797
  ] }),
5401
- showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: {
5798
+ showStripe && (shouldDisplayWalletRow || shouldDisplayPayPalRow || shouldDisplayPaymentElementRow) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
5402
5799
  display: "flex",
5403
5800
  alignItems: "center",
5404
5801
  gap: "0.75rem",
@@ -5406,9 +5803,9 @@ function SplitCardFormInner({
5406
5803
  color: "#999",
5407
5804
  fontSize: "0.85rem"
5408
5805
  }, children: [
5409
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
5410
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "or pay with card" }),
5411
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
5806
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } }),
5807
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "or pay with card" }),
5808
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1, height: 1, backgroundColor: "#ddd" } })
5412
5809
  ] }),
5413
5810
  showStripe && cardFormBlock
5414
5811
  ] });
@@ -5438,6 +5835,9 @@ async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
5438
5835
  const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
5439
5836
  return { error, intent: paymentIntent ?? null };
5440
5837
  }
5838
+ function withCheckoutMethod(error, checkoutMethod) {
5839
+ return Object.assign(error, { checkoutMethod });
5840
+ }
5441
5841
  function getRedirectResultFromCheckoutProcessError(error) {
5442
5842
  if (!error?.type || !error.threeDSecureToken) {
5443
5843
  return null;
@@ -5659,7 +6059,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
5659
6059
  const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
5660
6060
  const rawMessage = error?.message ?? fallbackMessage;
5661
6061
  const message = applyFriendlyMessageOverride(rawMessage) ?? rawMessage;
5662
- return Object.assign(
6062
+ return withCheckoutMethod(
5663
6063
  new import_shared7.FloPayError(
5664
6064
  message,
5665
6065
  "api_error",
@@ -5667,7 +6067,7 @@ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment fai
5667
6067
  code: error?.gatewayErrorCode
5668
6068
  }
5669
6069
  ),
5670
- { checkoutMethod }
6070
+ checkoutMethod
5671
6071
  );
5672
6072
  }
5673
6073
  function resolveSavedPaymentReturnUrl(session) {
@@ -5753,7 +6153,7 @@ async function recover3DSRedirectResult({
5753
6153
  return null;
5754
6154
  }
5755
6155
  try {
5756
- const api = new import_js3.PaymentAPI(billingApiUrl);
6156
+ const api = new import_js3.PaymentAPI(billingApiUrl, { telemetry: false });
5757
6157
  const unified = await api.getUnifiedCheckoutSession(sessionId, nonce);
5758
6158
  const refreshedToken = unified.data.stripe?.clientSecret;
5759
6159
  if (isStripePaymentIntentClientSecret(refreshedToken)) {
@@ -5772,7 +6172,8 @@ async function processSavedPaymentForMode({
5772
6172
  session,
5773
6173
  nonce,
5774
6174
  tokenizedData,
5775
- returnUrl
6175
+ returnUrl,
6176
+ telemetry
5776
6177
  }) {
5777
6178
  const baseUrl = billingApiUrl.replace(/\/+$/, "");
5778
6179
  const resolvedSessionId = sessionId ?? session.id;
@@ -5783,7 +6184,10 @@ async function processSavedPaymentForMode({
5783
6184
  const lastName = session.customer?.lastName ?? session.accountData?.lastName ?? "";
5784
6185
  const country = session.customer?.country ?? session.accountData?.country ?? void 0;
5785
6186
  const zip = session.customer?.zip ?? session.accountData?.zip ?? void 0;
5786
- const api = new import_js3.PaymentAPI(baseUrl);
6187
+ const api = new import_js3.PaymentAPI(
6188
+ baseUrl,
6189
+ telemetry === false ? { telemetry: false } : void 0
6190
+ );
5787
6191
  const response = await retryOnceOnFetchFailure(() => api.processPayment(customerId, {
5788
6192
  sessionId: resolvedSessionId,
5789
6193
  nonce: resolvedNonce,
@@ -5835,13 +6239,13 @@ async function processSavedPaymentForMode({
5835
6239
  if (recoveredRedirect) {
5836
6240
  return recoveredRedirect;
5837
6241
  }
5838
- throw Object.assign(
6242
+ throw withCheckoutMethod(
5839
6243
  new import_shared7.FloPayError(
5840
6244
  "Your card requires authentication. Please enter your payment details below.",
5841
6245
  "api_error",
5842
6246
  { code: "authentication_required" }
5843
6247
  ),
5844
- { checkoutMethod: "card" }
6248
+ "card"
5845
6249
  );
5846
6250
  }
5847
6251
  throw new import_shared7.FloPayError(
@@ -5860,7 +6264,8 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5860
6264
  billingApiUrl,
5861
6265
  sessionId,
5862
6266
  session,
5863
- returnUrl
6267
+ returnUrl,
6268
+ telemetry
5864
6269
  }) {
5865
6270
  const stripe = flopay?.getRawProvider();
5866
6271
  if (!stripe) {
@@ -5868,13 +6273,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5868
6273
  }
5869
6274
  if (redirectResult.type === "3ds_required") {
5870
6275
  if (!attempt3DS || !redirectResult.threeDSecureToken) {
5871
- throw Object.assign(
6276
+ throw withCheckoutMethod(
5872
6277
  new import_shared7.FloPayError(
5873
6278
  "Your card requires authentication. Please enter your payment details below.",
5874
6279
  "api_error",
5875
6280
  { code: "authentication_required" }
5876
6281
  ),
5877
- { checkoutMethod: "card" }
6282
+ "card"
5878
6283
  );
5879
6284
  }
5880
6285
  const isSetupIntent = (0, import_shared7.isSetupIntentClientSecret)(redirectResult.threeDSecureToken);
@@ -5883,13 +6288,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5883
6288
  const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
5884
6289
  if (retrieved) {
5885
6290
  if (retrieved.error) {
5886
- throw Object.assign(
6291
+ throw withCheckoutMethod(
5887
6292
  new import_shared7.FloPayError(
5888
6293
  retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
5889
6294
  "api_error",
5890
6295
  { code: retrieved.error.code }
5891
6296
  ),
5892
- { checkoutMethod: "card" }
6297
+ "card"
5893
6298
  );
5894
6299
  }
5895
6300
  const existingIntent = retrieved.intent;
@@ -5912,13 +6317,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5912
6317
  ) : null;
5913
6318
  if (confirmed) {
5914
6319
  if (confirmed.error) {
5915
- throw Object.assign(
6320
+ throw withCheckoutMethod(
5916
6321
  new import_shared7.FloPayError(
5917
6322
  confirmed.error.message ?? "3DS authentication failed.",
5918
6323
  "api_error",
5919
6324
  { code: confirmed.error.code }
5920
6325
  ),
5921
- { checkoutMethod: "card" }
6326
+ "card"
5922
6327
  );
5923
6328
  }
5924
6329
  paymentIntent = confirmed.intent;
@@ -5927,13 +6332,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5927
6332
  clientSecret: redirectResult.threeDSecureToken
5928
6333
  });
5929
6334
  if (nextAction.error) {
5930
- throw Object.assign(
6335
+ throw withCheckoutMethod(
5931
6336
  new import_shared7.FloPayError(
5932
6337
  nextAction.error.message ?? "3DS authentication failed.",
5933
6338
  "api_error",
5934
6339
  { code: nextAction.error.code }
5935
6340
  ),
5936
- { checkoutMethod: "card" }
6341
+ "card"
5937
6342
  );
5938
6343
  }
5939
6344
  paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
@@ -5943,6 +6348,7 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5943
6348
  billingApiUrl,
5944
6349
  sessionId,
5945
6350
  session,
6351
+ telemetry,
5946
6352
  tokenizedData: {
5947
6353
  id: paymentIntent.id,
5948
6354
  type: "card",
@@ -5964,20 +6370,21 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5964
6370
  billingApiUrl,
5965
6371
  sessionId,
5966
6372
  session,
5967
- returnUrl
6373
+ returnUrl,
6374
+ telemetry
5968
6375
  });
5969
6376
  }
5970
- throw Object.assign(
6377
+ throw withCheckoutMethod(
5971
6378
  new import_shared7.FloPayError("3DS authentication did not complete successfully.", "api_error"),
5972
- { checkoutMethod: "card" }
6379
+ "card"
5973
6380
  );
5974
6381
  }
5975
6382
  if (redirectResult.type === "paypal_redirect_required") {
5976
6383
  const paypalStripe = (paypalFlopay ?? flopay)?.getRawProvider();
5977
6384
  if (!paypalStripe) {
5978
- throw Object.assign(
6385
+ throw withCheckoutMethod(
5979
6386
  new import_shared7.FloPayError("PayPal is not available.", "api_error"),
5980
- { checkoutMethod: "paypal" }
6387
+ "paypal"
5981
6388
  );
5982
6389
  }
5983
6390
  if (redirectResult.paymentMethodId) {
@@ -5985,13 +6392,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
5985
6392
  clientSecret: redirectResult.threeDSecureToken
5986
6393
  });
5987
6394
  if (error2) {
5988
- throw Object.assign(
6395
+ throw withCheckoutMethod(
5989
6396
  new import_shared7.FloPayError(
5990
6397
  error2.message ?? "PayPal authorization failed.",
5991
6398
  "api_error",
5992
6399
  { code: error2.code }
5993
6400
  ),
5994
- { checkoutMethod: "paypal" }
6401
+ "paypal"
5995
6402
  );
5996
6403
  }
5997
6404
  return {
@@ -6008,13 +6415,13 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
6008
6415
  redirect: "if_required"
6009
6416
  });
6010
6417
  if (error) {
6011
- throw Object.assign(
6418
+ throw withCheckoutMethod(
6012
6419
  new import_shared7.FloPayError(
6013
6420
  error.message ?? "PayPal authorization failed.",
6014
6421
  "api_error",
6015
6422
  { code: error.code }
6016
6423
  ),
6017
- { checkoutMethod: "paypal" }
6424
+ "paypal"
6018
6425
  );
6019
6426
  }
6020
6427
  return {
@@ -6070,7 +6477,8 @@ async function loadSavedPaymentProviders({
6070
6477
  publishableKey,
6071
6478
  paypalPublishableKey,
6072
6479
  billingApiUrl,
6073
- locale
6480
+ locale,
6481
+ telemetry
6074
6482
  }) {
6075
6483
  if (!publishableKey) {
6076
6484
  return { flopay: null, paypalFlopay: null };
@@ -6079,11 +6487,13 @@ async function loadSavedPaymentProviders({
6079
6487
  const [instance, paypalInstanceOrError] = await Promise.all([
6080
6488
  (0, import_js3.loadFloPay)(publishableKey, {
6081
6489
  billingApiUrl,
6082
- locale
6490
+ locale,
6491
+ telemetry
6083
6492
  }),
6084
6493
  needsSeparatePaypal ? (0, import_js3.loadFloPay)(paypalPublishableKey, {
6085
6494
  billingApiUrl,
6086
- locale
6495
+ locale,
6496
+ telemetry
6087
6497
  }).catch((err) => {
6088
6498
  console.warn("[FloPay] Failed to load PayPal Stripe instance:", err);
6089
6499
  return null;
@@ -6096,13 +6506,40 @@ async function loadSavedPaymentProviders({
6096
6506
  }
6097
6507
 
6098
6508
  // src/flopay-checkout.tsx
6099
- var import_jsx_runtime8 = require("react/jsx-runtime");
6509
+ var import_jsx_runtime9 = require("react/jsx-runtime");
6100
6510
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
6101
6511
  var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
6102
6512
  var sessionInflightMap = /* @__PURE__ */ new Map();
6103
6513
  function sleep(ms) {
6104
6514
  return new Promise((resolve) => setTimeout(resolve, ms));
6105
6515
  }
6516
+ function createStandaloneTelemetryReporter(billingApiUrl, enabled, context) {
6517
+ const reporter = createTelemetryBridge({
6518
+ billingApiUrl,
6519
+ sdkPackage: "@flopay/react",
6520
+ sdkVersion: import_shared8.SDK_VERSION,
6521
+ enabled: enabled !== false
6522
+ });
6523
+ reporter.beginCheckout(context);
6524
+ return reporter;
6525
+ }
6526
+ function finishStandaloneTelemetry(reporter) {
6527
+ void reporter.flush().catch(() => {
6528
+ }).finally(() => reporter.destroy());
6529
+ }
6530
+ function reportStandaloneTelemetryError(billingApiUrl, enabled, context, errorCode, stage) {
6531
+ const reporter = createStandaloneTelemetryReporter(billingApiUrl, enabled, context);
6532
+ reporter.error({
6533
+ errorCode,
6534
+ stage,
6535
+ paymentMethodCategory: "unknown",
6536
+ ...stage === "session_read" ? { requestCategory: "session_read" } : {}
6537
+ });
6538
+ finishStandaloneTelemetry(reporter);
6539
+ }
6540
+ function isExpectedExistingSessionError(error) {
6541
+ return error.type === "validation_error" || error.code === "checkout_session_not_found" || error.code === "checkout_session_expired" || error.code === "checkout_session_completed" || error.code === "session_auto_completed";
6542
+ }
6106
6543
  function resolveDirectPaypalConfig(unified) {
6107
6544
  const clientId = unified?.data.paypal?.publishableKey;
6108
6545
  if (!clientId) return void 0;
@@ -6207,6 +6644,7 @@ function FloPayCheckout({
6207
6644
  nonce: nonceProp,
6208
6645
  createSession: createSessionParams,
6209
6646
  billingApiUrl,
6647
+ telemetry,
6210
6648
  appearance: appearanceOverride,
6211
6649
  locale,
6212
6650
  loading: loadingNode,
@@ -6246,41 +6684,51 @@ function FloPayCheckout({
6246
6684
  onSessionCompleted
6247
6685
  }) {
6248
6686
  const resolvedBillingUrl = (0, import_shared8.resolveBillingApiUrl)(billingApiUrl);
6249
- const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
6687
+ const themeBundle = (0, import_react11.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
6250
6688
  const appearance = appearanceOverride ?? themeBundle?.appearance;
6251
6689
  const checkoutType = createSessionParams ? "embedded_checkout" : "standard_checkout";
6252
6690
  const checkoutLayout = children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout";
6253
- const [unified, setUnified] = (0, import_react10.useState)(null);
6254
- const [flopay, setFloPay] = (0, import_react10.useState)(null);
6255
- const flopayRef = (0, import_react10.useRef)(null);
6256
- const [paypalFlopay, setPaypalFloPay] = (0, import_react10.useState)(null);
6257
- const paypalFlopayRef = (0, import_react10.useRef)(null);
6258
- const [session, setSession] = (0, import_react10.useState)(null);
6259
- const [resolvedSessionId, setResolvedSessionId] = (0, import_react10.useState)(sessionIdProp ?? "");
6691
+ const [unified, setUnified] = (0, import_react11.useState)(null);
6692
+ const [flopay, setFloPay] = (0, import_react11.useState)(null);
6693
+ const flopayRef = (0, import_react11.useRef)(null);
6694
+ const [paypalFlopay, setPaypalFloPay] = (0, import_react11.useState)(null);
6695
+ const paypalFlopayRef = (0, import_react11.useRef)(null);
6696
+ const [session, setSession] = (0, import_react11.useState)(null);
6697
+ const [resolvedSessionId, setResolvedSessionId] = (0, import_react11.useState)(sessionIdProp ?? "");
6260
6698
  const activeSessionId = sessionIdProp ?? resolvedSessionId;
6261
6699
  const initSessionDependency = createSessionParams ? "" : activeSessionId;
6262
- const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
6263
- const [loadError, setLoadError] = (0, import_react10.useState)(null);
6264
- const [currentMode, setCurrentMode] = (0, import_react10.useState)("full");
6265
- const [confirmProcessing, setConfirmProcessing] = (0, import_react10.useState)(false);
6266
- const [modeError, setModeError] = (0, import_react10.useState)(initialErrorMessage);
6267
- const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react10.useState)(null);
6268
- const [modeOverlayError, setModeOverlayError] = (0, import_react10.useState)(null);
6269
- const [createSessionPatch, setCreateSessionPatch] = (0, import_react10.useState)(void 0);
6270
- const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react10.useState)("");
6271
- const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react10.useState)(false);
6272
- const autoCheckoutAttempted = (0, import_react10.useRef)(false);
6273
- const paypalResumeAttempted = (0, import_react10.useRef)(false);
6274
- const savedPaymentKeysRef = (0, import_react10.useRef)(null);
6275
- const onCompleteRef = (0, import_react10.useRef)(onComplete);
6700
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
6701
+ const [loadError, setLoadError] = (0, import_react11.useState)(null);
6702
+ const [currentMode, setCurrentMode] = (0, import_react11.useState)("full");
6703
+ const [confirmProcessing, setConfirmProcessing] = (0, import_react11.useState)(false);
6704
+ const [modeError, setModeError] = (0, import_react11.useState)(initialErrorMessage);
6705
+ const [modeOverlayStatus, setModeOverlayStatus] = (0, import_react11.useState)(null);
6706
+ const [modeOverlayError, setModeOverlayError] = (0, import_react11.useState)(null);
6707
+ const [createSessionPatch, setCreateSessionPatch] = (0, import_react11.useState)(void 0);
6708
+ const [createSessionPatchBaseHash, setCreateSessionPatchBaseHash] = (0, import_react11.useState)("");
6709
+ const [cardBootstrapPending, setCardBootstrapPending] = (0, import_react11.useState)(false);
6710
+ const autoCheckoutAttempted = (0, import_react11.useRef)(false);
6711
+ const paypalResumeAttempted = (0, import_react11.useRef)(false);
6712
+ const savedPaymentKeysRef = (0, import_react11.useRef)(null);
6713
+ const telemetryCheckoutContext = (0, import_react11.useMemo)(() => ({
6714
+ checkoutMode: checkoutModeProp ?? currentMode,
6715
+ layout: children ? "unknown" : layout === "buttons" ? "buttons" : "embedded"
6716
+ }), [checkoutModeProp, children, currentMode, layout]);
6717
+ const onCompleteRef = (0, import_react11.useRef)(onComplete);
6276
6718
  onCompleteRef.current = onComplete;
6277
- const onErrorRef = (0, import_react10.useRef)(onError);
6719
+ const onErrorRef = (0, import_react11.useRef)(onError);
6278
6720
  onErrorRef.current = onError;
6279
- const onDeclineRef = (0, import_react10.useRef)(onDecline);
6721
+ const onDeclineRef = (0, import_react11.useRef)(onDecline);
6280
6722
  onDeclineRef.current = onDecline;
6281
- const onSessionCompletedRef = (0, import_react10.useRef)(onSessionCompleted);
6723
+ (0, import_react11.useEffect)(() => {
6724
+ getFloPayTelemetryBridge(flopay)?.setCheckoutContext(telemetryCheckoutContext);
6725
+ if (paypalFlopay && paypalFlopay !== flopay) {
6726
+ getFloPayTelemetryBridge(paypalFlopay)?.setCheckoutContext(telemetryCheckoutContext);
6727
+ }
6728
+ }, [flopay, paypalFlopay, telemetryCheckoutContext]);
6729
+ const onSessionCompletedRef = (0, import_react11.useRef)(onSessionCompleted);
6282
6730
  onSessionCompletedRef.current = onSessionCompleted;
6283
- (0, import_react10.useEffect)(() => {
6731
+ (0, import_react11.useEffect)(() => {
6284
6732
  console.info("[FloPay] Checkout initialized", {
6285
6733
  sdk_version: import_shared8.SDK_VERSION,
6286
6734
  checkout_type: checkoutType,
@@ -6288,49 +6736,139 @@ function FloPayCheckout({
6288
6736
  billing_api_url: resolvedBillingUrl
6289
6737
  });
6290
6738
  }, [checkoutLayout, checkoutType, resolvedBillingUrl]);
6291
- const baseCreateSessionHash = (0, import_react10.useMemo)(
6739
+ const baseCreateSessionHash = (0, import_react11.useMemo)(
6292
6740
  () => createSessionParams ? hashCreateParams(createSessionParams) : "",
6293
6741
  [createSessionParams]
6294
6742
  );
6295
- const activeCreateSessionPatch = (0, import_react10.useMemo)(
6743
+ const activeCreateSessionPatch = (0, import_react11.useMemo)(
6296
6744
  () => createSessionPatchBaseHash === baseCreateSessionHash ? createSessionPatch : void 0,
6297
6745
  [createSessionPatch, createSessionPatchBaseHash, baseCreateSessionHash]
6298
6746
  );
6299
- const effectiveCreateSessionBase = (0, import_react10.useMemo)(
6747
+ const effectiveCreateSessionBase = (0, import_react11.useMemo)(
6300
6748
  () => createSessionParams ? mergeInlineSessionPatch(createSessionParams, activeCreateSessionPatch) : void 0,
6301
6749
  [createSessionParams, activeCreateSessionPatch]
6302
6750
  );
6303
6751
  const effectiveCreateSessionMode = checkoutModeProp ?? effectiveCreateSessionBase?.checkoutMode ?? "full";
6304
- const effectiveCreateSession = (0, import_react10.useMemo)(
6752
+ const effectiveCreateSession = (0, import_react11.useMemo)(
6305
6753
  () => effectiveCreateSessionBase ? {
6306
6754
  ...effectiveCreateSessionBase,
6307
6755
  checkoutMode: effectiveCreateSessionMode
6308
6756
  } : void 0,
6309
6757
  [effectiveCreateSessionBase, effectiveCreateSessionMode]
6310
6758
  );
6311
- (0, import_react10.useEffect)(() => {
6759
+ (0, import_react11.useEffect)(() => {
6312
6760
  setCreateSessionPatch(void 0);
6313
6761
  setCreateSessionPatchBaseHash(baseCreateSessionHash);
6314
6762
  }, [baseCreateSessionHash]);
6315
- (0, import_react10.useEffect)(() => {
6763
+ (0, import_react11.useEffect)(() => {
6316
6764
  setModeError(initialErrorMessage);
6317
6765
  }, [initialErrorMessage]);
6318
- const emitDecline = (0, import_react10.useCallback)(
6766
+ const emitDecline = (0, import_react11.useCallback)(
6319
6767
  (method, input, overrides) => {
6320
- onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
6768
+ invokeMerchantCallback(() => {
6769
+ onDeclineRef.current?.(buildDeclineEvent(method, input, overrides));
6770
+ });
6321
6771
  },
6322
- []
6772
+ [invokeMerchantCallback]
6323
6773
  );
6324
- const runSavedPaymentFlow = (0, import_react10.useCallback)(
6774
+ const runSavedPaymentFlow = (0, import_react11.useCallback)(
6325
6775
  async (sess, options) => {
6326
6776
  setModeError(null);
6327
6777
  setModeOverlayError(null);
6328
6778
  setModeOverlayStatus("processing");
6329
6779
  const activeSessionId2 = options?.sessionId ?? sess.id;
6780
+ const activeFloPay = flopayRef.current ?? paypalFlopayRef.current;
6781
+ const activeTelemetry = getFloPayTelemetryBridge(activeFloPay);
6782
+ const standaloneTelemetry = activeFloPay ? null : createStandaloneTelemetryReporter(
6783
+ resolvedBillingUrl,
6784
+ telemetry,
6785
+ telemetryCheckoutContext
6786
+ );
6787
+ const telemetrySource = {
6788
+ log: (input) => {
6789
+ if (activeTelemetry) activeTelemetry.log(input);
6790
+ else standaloneTelemetry?.log(input);
6791
+ },
6792
+ error: (input) => {
6793
+ if (activeTelemetry) activeTelemetry.error(input);
6794
+ else standaloneTelemetry?.error(input);
6795
+ },
6796
+ terminal: (input) => {
6797
+ if (activeTelemetry) activeTelemetry.terminal(input);
6798
+ else standaloneTelemetry?.terminal(input);
6799
+ },
6800
+ performance: (input) => {
6801
+ if (activeTelemetry) activeTelemetry.performance(input);
6802
+ else standaloneTelemetry?.performance(input);
6803
+ },
6804
+ now: () => activeTelemetry?.now() ?? standaloneTelemetry?.now() ?? 0,
6805
+ elapsed: (startedAt) => activeTelemetry?.elapsed(startedAt) ?? Math.max(0, (standaloneTelemetry?.now() ?? startedAt) - startedAt)
6806
+ };
6807
+ const processingStartedAt = telemetrySource.now();
6808
+ let recoveryFlow = Boolean(
6809
+ options?.initialAutoProcessingError || options?.initialAutoProcessingPending
6810
+ );
6811
+ let recoveryStarted = false;
6812
+ let recoveryStartedAt;
6813
+ const startRecovery = () => {
6814
+ if (recoveryStarted) return;
6815
+ recoveryStarted = true;
6816
+ recoveryFlow = true;
6817
+ recoveryStartedAt = telemetrySource.now();
6818
+ telemetrySource.log({
6819
+ name: "checkout.recovery.started",
6820
+ stage: "recovery",
6821
+ paymentMethodCategory: "saved"
6822
+ });
6823
+ telemetrySource.log({
6824
+ name: "operation.recovery.started",
6825
+ stage: "recovery",
6826
+ paymentMethodCategory: "saved"
6827
+ });
6828
+ };
6829
+ let processingFinished = false;
6830
+ const finishProcessing = () => {
6831
+ if (processingFinished) return;
6832
+ processingFinished = true;
6833
+ telemetrySource.log({
6834
+ name: "payment.processing.completed",
6835
+ stage: "processing",
6836
+ paymentMethodCategory: "saved"
6837
+ });
6838
+ telemetrySource.performance({
6839
+ stage: "processing",
6840
+ durationMs: telemetrySource.elapsed(processingStartedAt),
6841
+ durationMode: "machine",
6842
+ paymentMethodCategory: "saved"
6843
+ });
6844
+ if (recoveryStartedAt !== void 0) {
6845
+ telemetrySource.performance({
6846
+ stage: "recovery",
6847
+ durationMs: telemetrySource.elapsed(recoveryStartedAt),
6848
+ durationMode: "machine",
6849
+ paymentMethodCategory: "saved"
6850
+ });
6851
+ }
6852
+ };
6853
+ telemetrySource.log({
6854
+ name: "payment.method.selected",
6855
+ stage: "processing",
6856
+ paymentMethodCategory: "saved"
6857
+ });
6858
+ telemetrySource.log({
6859
+ name: "payment.processing.started",
6860
+ stage: "processing",
6861
+ paymentMethodCategory: "saved"
6862
+ });
6863
+ if (recoveryFlow) {
6864
+ startRecovery();
6865
+ }
6866
+ let completionCallback;
6330
6867
  try {
6331
6868
  const redirectResult = getRedirectResultFromCheckoutProcessError(options?.initialAutoProcessingError);
6332
6869
  let paymentResult;
6333
6870
  if (redirectResult) {
6871
+ startRecovery();
6334
6872
  if (redirectResult.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
6335
6873
  persistPayPalResumeState({
6336
6874
  sessionId: activeSessionId2,
@@ -6344,13 +6882,14 @@ function FloPayCheckout({
6344
6882
  attempt3DS: options?.attempt3DS,
6345
6883
  billingApiUrl: resolvedBillingUrl,
6346
6884
  sessionId: activeSessionId2,
6347
- session: sess
6885
+ session: sess,
6886
+ telemetry: false
6348
6887
  });
6349
6888
  if (redirectResult.type === "paypal_redirect_required") {
6350
6889
  clearPayPalResumeState();
6351
6890
  }
6352
6891
  } else if (options?.initialAutoProcessingPending) {
6353
- const api = new import_js4.PaymentAPI(resolvedBillingUrl);
6892
+ const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
6354
6893
  const completed = await api.waitForCheckoutSessionCompletion(options.initialAutoProcessingPending.sessionId, {
6355
6894
  initialDelayMs: options.initialAutoProcessingPending.retryAfterMs
6356
6895
  });
@@ -6378,11 +6917,13 @@ function FloPayCheckout({
6378
6917
  const result = await processSavedPaymentForMode({
6379
6918
  billingApiUrl: resolvedBillingUrl,
6380
6919
  sessionId: activeSessionId2,
6381
- session: sess
6920
+ session: sess,
6921
+ telemetry: false
6382
6922
  });
6383
6923
  if (result.type === "success") {
6384
6924
  paymentResult = result.result;
6385
6925
  } else {
6926
+ startRecovery();
6386
6927
  if (result.type === "paypal_redirect_required" && savedPaymentKeysRef.current?.publishableKey) {
6387
6928
  persistPayPalResumeState({
6388
6929
  sessionId: activeSessionId2,
@@ -6396,7 +6937,8 @@ function FloPayCheckout({
6396
6937
  attempt3DS: options?.attempt3DS,
6397
6938
  billingApiUrl: resolvedBillingUrl,
6398
6939
  sessionId: activeSessionId2,
6399
- session: sess
6940
+ session: sess,
6941
+ telemetry: false
6400
6942
  });
6401
6943
  if (result.type === "paypal_redirect_required") {
6402
6944
  clearPayPalResumeState();
@@ -6404,20 +6946,57 @@ function FloPayCheckout({
6404
6946
  }
6405
6947
  }
6406
6948
  if (activeSessionId2) markSessionRecentlyCompleted(activeSessionId2);
6949
+ finishProcessing();
6950
+ if (recoveryFlow) {
6951
+ telemetrySource.log({
6952
+ name: "checkout.recovery.completed",
6953
+ stage: "recovery",
6954
+ paymentMethodCategory: "saved"
6955
+ });
6956
+ telemetrySource.log({
6957
+ name: "operation.recovery.completed",
6958
+ stage: "recovery",
6959
+ paymentMethodCategory: "saved"
6960
+ });
6961
+ }
6962
+ telemetrySource.terminal({
6963
+ outcome: "payment_succeeded",
6964
+ paymentMethodCategory: "saved"
6965
+ });
6407
6966
  setModeOverlayStatus("success");
6408
6967
  await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
6409
- onCompleteRef.current?.(paymentResult);
6410
- return true;
6968
+ completionCallback = () => onCompleteRef.current?.(paymentResult);
6411
6969
  } catch (err) {
6412
6970
  const floPayErr = normalizeSavedPaymentError(err);
6413
6971
  const method = floPayErr.checkoutMethod ?? DEFAULT_SAVED_PAYMENT_DECLINE_METHOD;
6414
6972
  setModeError(floPayErr.message);
6415
6973
  setModeOverlayError(floPayErr.message);
6416
6974
  if (options?.fallbackToFull) {
6975
+ telemetrySource.log({
6976
+ name: "operation.fallback",
6977
+ stage: "recovery",
6978
+ paymentMethodCategory: "saved"
6979
+ });
6417
6980
  setCurrentMode("full");
6418
6981
  replaceCheckoutModeQueryParam("full");
6419
6982
  }
6420
- onErrorRef.current?.(floPayErr);
6983
+ finishProcessing();
6984
+ const expectedDecline = Boolean(
6985
+ floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
6986
+ );
6987
+ if (expectedDecline) {
6988
+ telemetrySource.terminal({
6989
+ outcome: "payment_declined",
6990
+ paymentMethodCategory: "saved"
6991
+ });
6992
+ } else {
6993
+ telemetrySource.error({
6994
+ errorCode: recoveryFlow ? "RECOVERY_FAILED" : "PAYMENT_PROCESSING_FAILED",
6995
+ stage: recoveryFlow ? "recovery" : "processing",
6996
+ paymentMethodCategory: "saved"
6997
+ });
6998
+ }
6999
+ invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
6421
7000
  emitDecline(method, floPayErr, {
6422
7001
  code: floPayErr.code,
6423
7002
  declineCode: floPayErr.declineCode
@@ -6427,19 +7006,38 @@ function FloPayCheckout({
6427
7006
  sleep(PROCESSING_OVERLAY_ERROR_DELAY_MS),
6428
7007
  options?.ensureProvidersReady ? options.ensureProvidersReady() : Promise.resolve()
6429
7008
  ]);
7009
+ if (recoveryFlow) {
7010
+ telemetrySource.log({
7011
+ name: "checkout.recovery.completed",
7012
+ stage: "recovery",
7013
+ paymentMethodCategory: "saved"
7014
+ });
7015
+ telemetrySource.log({
7016
+ name: "operation.recovery.completed",
7017
+ stage: "recovery",
7018
+ paymentMethodCategory: "saved"
7019
+ });
7020
+ }
6430
7021
  return false;
6431
7022
  } finally {
7023
+ finishProcessing();
7024
+ if (standaloneTelemetry) finishStandaloneTelemetry(standaloneTelemetry);
6432
7025
  setModeOverlayStatus(null);
6433
7026
  setModeOverlayError(null);
6434
7027
  }
7028
+ invokeMerchantCallback(completionCallback);
7029
+ return true;
6435
7030
  },
6436
7031
  [
6437
7032
  emitDecline,
7033
+ invokeMerchantCallback,
6438
7034
  normalizeSavedPaymentError,
6439
- resolvedBillingUrl
7035
+ resolvedBillingUrl,
7036
+ telemetry,
7037
+ telemetryCheckoutContext
6440
7038
  ]
6441
7039
  );
6442
- (0, import_react10.useEffect)(() => {
7040
+ (0, import_react11.useEffect)(() => {
6443
7041
  if (typeof window === "undefined" || paypalResumeAttempted.current) {
6444
7042
  return;
6445
7043
  }
@@ -6454,6 +7052,8 @@ function FloPayCheckout({
6454
7052
  }
6455
7053
  paypalResumeAttempted.current = true;
6456
7054
  void (async () => {
7055
+ let resumeTelemetry;
7056
+ let redirectResumeStartedAt = 0;
6457
7057
  setModeError(null);
6458
7058
  setModeOverlayError(null);
6459
7059
  setModeOverlayStatus("processing");
@@ -6461,7 +7061,11 @@ function FloPayCheckout({
6461
7061
  try {
6462
7062
  if (params.get("redirect_status") === "failed") {
6463
7063
  throw Object.assign(
6464
- new import_shared8.FloPayError("PayPal payment was declined. Please try again.", "api_error"),
7064
+ new import_shared8.FloPayError(
7065
+ "PayPal payment was declined. Please try again.",
7066
+ "api_error",
7067
+ { declineCode: "paypal_redirect_failed" }
7068
+ ),
6465
7069
  { checkoutMethod: "paypal" }
6466
7070
  );
6467
7071
  }
@@ -6472,7 +7076,22 @@ function FloPayCheckout({
6472
7076
  publishableKey: resumeState.publishableKey,
6473
7077
  paypalPublishableKey: resumeState.paypalPublishableKey,
6474
7078
  billingApiUrl: resolvedBillingUrl,
6475
- locale
7079
+ locale,
7080
+ telemetry
7081
+ });
7082
+ resumeTelemetry = getFloPayTelemetryBridge(resumePaypalFlopay ?? resumeFlopay);
7083
+ redirectResumeStartedAt = resumeTelemetry?.now() ?? 0;
7084
+ resumeTelemetry?.log({
7085
+ name: "provider.redirect.resumed",
7086
+ stage: "redirect_resume",
7087
+ provider: "paypal",
7088
+ paymentMethodCategory: "paypal"
7089
+ });
7090
+ resumeTelemetry?.log({
7091
+ name: "operation.recovery.started",
7092
+ stage: "recovery",
7093
+ provider: "paypal",
7094
+ paymentMethodCategory: "paypal"
6476
7095
  });
6477
7096
  const paypalStripe = (resumePaypalFlopay ?? resumeFlopay)?.getRawProvider();
6478
7097
  if (!paypalStripe) {
@@ -6502,7 +7121,7 @@ function FloPayCheckout({
6502
7121
  const paymentMethodId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
6503
7122
  let finalResultStatus = resultStatus;
6504
7123
  if (resumeState.sessionId) {
6505
- const resumeApi = new import_js4.PaymentAPI(resolvedBillingUrl);
7124
+ const resumeApi = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
6506
7125
  const resumeSessionResult = await resumeApi.getUnifiedCheckoutSession(resumeState.sessionId);
6507
7126
  const resumeSession = resumeSessionResult.data.session;
6508
7127
  if (resumeSession && resumeSession.status !== "complete") {
@@ -6510,6 +7129,7 @@ function FloPayCheckout({
6510
7129
  billingApiUrl: resolvedBillingUrl,
6511
7130
  sessionId: resumeState.sessionId,
6512
7131
  session: resumeSession,
7132
+ telemetry: false,
6513
7133
  tokenizedData: {
6514
7134
  id: paymentMethodId ?? paymentIntent.id,
6515
7135
  type: "card",
@@ -6527,20 +7147,84 @@ function FloPayCheckout({
6527
7147
  }
6528
7148
  }
6529
7149
  if (resumeState.sessionId) markSessionRecentlyCompleted(resumeState.sessionId);
7150
+ resumeTelemetry?.log({
7151
+ name: "operation.recovery.completed",
7152
+ stage: "recovery",
7153
+ provider: "paypal",
7154
+ paymentMethodCategory: "paypal"
7155
+ });
7156
+ resumeTelemetry?.performance({
7157
+ stage: "redirect_resume",
7158
+ durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
7159
+ durationMode: "machine",
7160
+ provider: "paypal",
7161
+ paymentMethodCategory: "paypal"
7162
+ });
7163
+ resumeTelemetry?.terminal({
7164
+ outcome: "payment_succeeded",
7165
+ provider: "paypal",
7166
+ paymentMethodCategory: "paypal"
7167
+ });
6530
7168
  setModeOverlayStatus("success");
6531
7169
  await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
6532
- onCompleteRef.current?.({
7170
+ invokeMerchantCallback(() => onCompleteRef.current?.({
6533
7171
  status: finalResultStatus,
6534
7172
  paymentIntentId: paymentIntent.id,
6535
7173
  paymentMethodId,
6536
7174
  checkoutMethod: "paypal"
6537
- });
7175
+ }));
6538
7176
  } catch (err) {
6539
7177
  const floPayErr = normalizeSavedPaymentError(err);
6540
7178
  const method = floPayErr.checkoutMethod ?? "paypal";
7179
+ const expectedDecline = Boolean(
7180
+ floPayErr.declineCode || floPayErr.code?.toLowerCase().includes("declin")
7181
+ );
7182
+ if (resumeTelemetry) {
7183
+ resumeTelemetry.performance({
7184
+ stage: "redirect_resume",
7185
+ durationMs: resumeTelemetry.elapsed(redirectResumeStartedAt),
7186
+ durationMode: "machine",
7187
+ provider: "paypal",
7188
+ paymentMethodCategory: "paypal"
7189
+ });
7190
+ if (expectedDecline) {
7191
+ resumeTelemetry.terminal({
7192
+ outcome: "payment_declined",
7193
+ provider: "paypal",
7194
+ paymentMethodCategory: "paypal"
7195
+ });
7196
+ } else {
7197
+ resumeTelemetry.error({
7198
+ errorCode: "REDIRECT_RESUME_FAILED",
7199
+ stage: "redirect_resume",
7200
+ provider: "paypal",
7201
+ paymentMethodCategory: "paypal"
7202
+ });
7203
+ }
7204
+ } else if (expectedDecline) {
7205
+ const reporter = createStandaloneTelemetryReporter(
7206
+ resolvedBillingUrl,
7207
+ telemetry,
7208
+ telemetryCheckoutContext
7209
+ );
7210
+ reporter.terminal({
7211
+ outcome: "payment_declined",
7212
+ provider: "paypal",
7213
+ paymentMethodCategory: "paypal"
7214
+ });
7215
+ finishStandaloneTelemetry(reporter);
7216
+ } else {
7217
+ reportStandaloneTelemetryError(
7218
+ resolvedBillingUrl,
7219
+ telemetry,
7220
+ telemetryCheckoutContext,
7221
+ "REDIRECT_RESUME_FAILED",
7222
+ "redirect_resume"
7223
+ );
7224
+ }
6541
7225
  setModeError(floPayErr.message);
6542
7226
  setModeOverlayError(floPayErr.message);
6543
- onErrorRef.current?.(floPayErr);
7227
+ invokeMerchantCallback(() => onErrorRef.current?.(floPayErr));
6544
7228
  emitDecline(method, floPayErr, {
6545
7229
  code: floPayErr.code,
6546
7230
  declineCode: floPayErr.declineCode
@@ -6555,8 +7239,8 @@ function FloPayCheckout({
6555
7239
  setConfirmProcessing(false);
6556
7240
  }
6557
7241
  })();
6558
- }, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
6559
- const initializedHashRef = (0, import_react10.useRef)(null);
7242
+ }, [emitDecline, invokeMerchantCallback, locale, normalizeSavedPaymentError, resolvedBillingUrl, telemetry]);
7243
+ const initializedHashRef = (0, import_react11.useRef)(null);
6560
7244
  function hashCreateParams(params) {
6561
7245
  const key = JSON.stringify({
6562
7246
  c: params?.clientId,
@@ -6589,60 +7273,123 @@ function FloPayCheckout({
6589
7273
  }
6590
7274
  return `flopay_session_${Math.abs(h).toString(36)}`;
6591
7275
  }
6592
- const createSessionHash = (0, import_react10.useMemo)(
7276
+ const createSessionHash = (0, import_react11.useMemo)(
6593
7277
  () => effectiveCreateSession ? hashCreateParams(effectiveCreateSession) : "",
6594
7278
  [effectiveCreateSession]
6595
7279
  );
6596
- const createSessionParamsRef = (0, import_react10.useRef)(effectiveCreateSession);
7280
+ const createSessionParamsRef = (0, import_react11.useRef)(effectiveCreateSession);
6597
7281
  createSessionParamsRef.current = effectiveCreateSession;
6598
- (0, import_react10.useEffect)(() => {
7282
+ (0, import_react11.useEffect)(() => {
6599
7283
  setResolvedSessionId(sessionIdProp ?? "");
6600
7284
  }, [sessionIdProp]);
6601
- (0, import_react10.useEffect)(() => {
7285
+ (0, import_react11.useEffect)(() => {
6602
7286
  autoCheckoutAttempted.current = false;
6603
7287
  setModeError(initialErrorMessage);
6604
7288
  setModeOverlayError(null);
6605
7289
  setModeOverlayStatus(null);
6606
7290
  }, [createSessionHash, initialErrorMessage, sessionIdProp]);
6607
7291
  async function resolveInlineSession(params, cacheKey) {
6608
- const api = new import_js4.PaymentAPI(resolvedBillingUrl);
6609
- const cached = readCachedInlineSession(cacheKey);
6610
- let sid = cached?.sid ?? null;
6611
- let realResult = null;
6612
- if (sid) {
6613
- try {
6614
- realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
6615
- const status = realResult.data.session?.status;
6616
- if (status === "complete") {
6617
- if (wasSessionRecentlyCompleted(sid)) {
6618
- return { sid, result: realResult };
7292
+ const reporter = createStandaloneTelemetryReporter(
7293
+ resolvedBillingUrl,
7294
+ telemetry,
7295
+ telemetryCheckoutContext
7296
+ );
7297
+ const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
7298
+ try {
7299
+ const cached = readCachedInlineSession(cacheKey);
7300
+ reporter.log({
7301
+ name: cached ? "operation.cache.hit" : "operation.cache.miss",
7302
+ stage: "session_create",
7303
+ requestCategory: "session_create"
7304
+ });
7305
+ let sid = cached?.sid ?? null;
7306
+ let realResult = null;
7307
+ if (sid) {
7308
+ try {
7309
+ realResult = await api.getUnifiedCheckoutSession(sid, cached?.nonce);
7310
+ const status = realResult.data.session?.status;
7311
+ if (status === "complete") {
7312
+ if (wasSessionRecentlyCompleted(sid)) {
7313
+ return { sid, result: realResult };
7314
+ }
7315
+ clearCachedInlineSession(cacheKey);
7316
+ sid = null;
7317
+ realResult = null;
6619
7318
  }
7319
+ } catch {
7320
+ reporter.log({
7321
+ name: "operation.fallback",
7322
+ stage: "session_read",
7323
+ requestCategory: "session_read"
7324
+ });
6620
7325
  clearCachedInlineSession(cacheKey);
6621
7326
  sid = null;
6622
- realResult = null;
6623
7327
  }
6624
- } catch {
6625
- clearCachedInlineSession(cacheKey);
6626
- sid = null;
6627
7328
  }
6628
- }
6629
- if (!sid) {
6630
- const paramsWithAnalytics = {
6631
- ...params,
6632
- avsCheck: !!enableAVS,
6633
- avsConfig: typeof enableAVS === "object" ? enableAVS : void 0,
6634
- checkoutType: "embedded_checkout",
6635
- checkoutLayout: children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout"
6636
- };
6637
- realResult = await api.createAndFetchSession(paramsWithAnalytics);
6638
- sid = realResult.data.session?.id ?? "";
6639
- if (sid) {
6640
- persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
7329
+ if (!sid) {
7330
+ const sessionCreateStartedAt = reporter.now();
7331
+ reporter.log({
7332
+ name: "session.create.started",
7333
+ stage: "session_create",
7334
+ requestCategory: "session_create"
7335
+ });
7336
+ const paramsWithAnalytics = {
7337
+ ...params,
7338
+ avsCheck: !!enableAVS,
7339
+ avsConfig: typeof enableAVS === "object" ? enableAVS : void 0,
7340
+ checkoutType: "embedded_checkout",
7341
+ checkoutLayout: children ? "custom_layout" : layout === "buttons" ? "buttons_layout" : "default_layout"
7342
+ };
7343
+ try {
7344
+ realResult = await api.createAndFetchSession(paramsWithAnalytics);
7345
+ reporter.log({
7346
+ name: "session.request.completed",
7347
+ stage: "session_complete",
7348
+ requestCategory: "session_create",
7349
+ statusClass: "2xx"
7350
+ });
7351
+ reporter.performance({
7352
+ stage: "session_create",
7353
+ durationMs: reporter.now() - sessionCreateStartedAt,
7354
+ durationMode: "machine",
7355
+ requestCategory: "session_create",
7356
+ statusClass: "2xx"
7357
+ });
7358
+ } catch (error) {
7359
+ reporter.performance({
7360
+ stage: "session_create",
7361
+ durationMs: reporter.now() - sessionCreateStartedAt,
7362
+ durationMode: "machine",
7363
+ requestCategory: "session_create",
7364
+ statusClass: "network_error"
7365
+ });
7366
+ if (error instanceof import_shared8.FloPayError && error.type === "validation_error") {
7367
+ reporter.terminal({
7368
+ outcome: "validation_rejected",
7369
+ stage: "session_create",
7370
+ paymentMethodCategory: "unknown"
7371
+ });
7372
+ } else {
7373
+ reporter.error({
7374
+ errorCode: "CHECKOUT_SESSION_CREATE_FAILED",
7375
+ stage: "session_create",
7376
+ paymentMethodCategory: "unknown",
7377
+ requestCategory: "session_create"
7378
+ });
7379
+ }
7380
+ throw error;
7381
+ }
7382
+ sid = realResult.data.session?.id ?? "";
7383
+ if (sid) {
7384
+ persistCachedInlineSession(cacheKey, sid, realResult.data.session?.clientSecret);
7385
+ }
6641
7386
  }
7387
+ return { sid: sid ?? "", result: realResult };
7388
+ } finally {
7389
+ finishStandaloneTelemetry(reporter);
6642
7390
  }
6643
- return { sid: sid ?? "", result: realResult };
6644
7391
  }
6645
- const bootstrapInlineSession = (0, import_react10.useCallback)(
7392
+ const bootstrapInlineSession = (0, import_react11.useCallback)(
6646
7393
  async (patch) => {
6647
7394
  const baseParams = createSessionParamsRef.current;
6648
7395
  if (!baseParams) {
@@ -6686,7 +7433,8 @@ function FloPayCheckout({
6686
7433
  publishableKey,
6687
7434
  paypalPublishableKey,
6688
7435
  billingApiUrl: resolvedBillingUrl,
6689
- locale
7436
+ locale,
7437
+ telemetry
6690
7438
  });
6691
7439
  flopayRef.current = instance;
6692
7440
  setFloPay(instance);
@@ -6701,9 +7449,9 @@ function FloPayCheckout({
6701
7449
  }
6702
7450
  return resolved;
6703
7451
  },
6704
- [locale, resolvedBillingUrl]
7452
+ [locale, resolvedBillingUrl, telemetry, telemetryCheckoutContext]
6705
7453
  );
6706
- const handleInlineSessionPatch = (0, import_react10.useCallback)(async (patch) => {
7454
+ const handleInlineSessionPatch = (0, import_react11.useCallback)(async (patch) => {
6707
7455
  if (!hasInlineSessionPatchData(patch) || cardBootstrapPending) {
6708
7456
  return {
6709
7457
  sessionId: resolvedSessionId,
@@ -6726,7 +7474,7 @@ function FloPayCheckout({
6726
7474
  resolvedSessionId,
6727
7475
  session
6728
7476
  ]);
6729
- (0, import_react10.useEffect)(() => {
7477
+ (0, import_react11.useEffect)(() => {
6730
7478
  let cancelled = false;
6731
7479
  setLoadError(null);
6732
7480
  if (createSessionHash) {
@@ -6780,7 +7528,9 @@ function FloPayCheckout({
6780
7528
  setModeOverlayStatus("success");
6781
7529
  await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
6782
7530
  if (!cancelled) {
6783
- onCompleteRef.current?.({ status: "succeeded" });
7531
+ invokeMerchantCallback(() => {
7532
+ onCompleteRef.current?.({ status: "succeeded" });
7533
+ });
6784
7534
  setModeOverlayStatus(null);
6785
7535
  setModeOverlayError(null);
6786
7536
  }
@@ -6800,8 +7550,9 @@ function FloPayCheckout({
6800
7550
  }
6801
7551
  setIsLoading(true);
6802
7552
  async function init() {
7553
+ let sessionReadCompleted = false;
6803
7554
  try {
6804
- const api = new import_js4.PaymentAPI(resolvedBillingUrl);
7555
+ const api = new import_js4.PaymentAPI(resolvedBillingUrl, { telemetry: false });
6805
7556
  const result = await api.getUnifiedCheckoutSession(activeSessionId, nonceProp);
6806
7557
  if (cancelled) return;
6807
7558
  setUnified(result);
@@ -6812,7 +7563,9 @@ function FloPayCheckout({
6812
7563
  }
6813
7564
  if (sess.status === "complete") {
6814
7565
  setIsLoading(false);
6815
- onSessionCompletedRef.current?.(sess.successUrl ?? "");
7566
+ invokeMerchantCallback(() => {
7567
+ onSessionCompletedRef.current?.(sess.successUrl ?? "");
7568
+ });
6816
7569
  return;
6817
7570
  }
6818
7571
  if (sess.status === "expired") {
@@ -6820,6 +7573,7 @@ function FloPayCheckout({
6820
7573
  code: "checkout_session_expired"
6821
7574
  });
6822
7575
  }
7576
+ sessionReadCompleted = true;
6823
7577
  const effectiveMode = checkoutModeProp ?? sess.checkoutMode ?? "full";
6824
7578
  setCurrentMode(effectiveMode);
6825
7579
  const hasPayPalRedirectParams = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("payment_intent");
@@ -6851,6 +7605,23 @@ function FloPayCheckout({
6851
7605
  if (!cancelled) setIsLoading(false);
6852
7606
  } catch (err) {
6853
7607
  if (cancelled) return;
7608
+ if (!(err instanceof import_shared8.FloPayError)) {
7609
+ reportStandaloneTelemetryError(
7610
+ resolvedBillingUrl,
7611
+ telemetry,
7612
+ telemetryCheckoutContext,
7613
+ "INTERNAL_SDK_ERROR",
7614
+ "checkout_mount"
7615
+ );
7616
+ } else if (!sessionReadCompleted && !isExpectedExistingSessionError(err)) {
7617
+ reportStandaloneTelemetryError(
7618
+ resolvedBillingUrl,
7619
+ telemetry,
7620
+ telemetryCheckoutContext,
7621
+ "NETWORK_REQUEST_FAILED",
7622
+ "session_read"
7623
+ );
7624
+ }
6854
7625
  const floPayErr = err instanceof import_shared8.FloPayError ? err : new import_shared8.FloPayError(err instanceof Error ? err.message : "Failed to initialize checkout", "api_error");
6855
7626
  setLoadError(floPayErr);
6856
7627
  setIsLoading(false);
@@ -6872,7 +7643,8 @@ function FloPayCheckout({
6872
7643
  publishableKey,
6873
7644
  paypalPublishableKey,
6874
7645
  billingApiUrl: resolvedBillingUrl,
6875
- locale
7646
+ locale,
7647
+ telemetry
6876
7648
  });
6877
7649
  flopayRef.current = instance;
6878
7650
  setFloPay(instance);
@@ -6889,10 +7661,11 @@ function FloPayCheckout({
6889
7661
  createSessionHash,
6890
7662
  effectiveCreateSessionMode,
6891
7663
  initSessionDependency,
7664
+ invokeMerchantCallback,
6892
7665
  nonceProp,
6893
7666
  runSavedPaymentFlow
6894
7667
  ]);
6895
- const handleConfirmCheckout = (0, import_react10.useCallback)(async () => {
7668
+ const handleConfirmCheckout = (0, import_react11.useCallback)(async () => {
6896
7669
  if (confirmProcessing || !session) return;
6897
7670
  setConfirmProcessing(true);
6898
7671
  setModeError(null);
@@ -6907,7 +7680,7 @@ function FloPayCheckout({
6907
7680
  }, [activeSessionId, confirmProcessing, runSavedPaymentFlow, session]);
6908
7681
  const directPaypalConfig = resolveDirectPaypalConfig(unified);
6909
7682
  const isPaypalOnlySession = isPayPalOnlyUnified(unified);
6910
- const providerOptions = (0, import_react10.useMemo)(() => {
7683
+ const providerOptions = (0, import_react11.useMemo)(() => {
6911
7684
  if (!unified || !session || !unified.data.stripe?.publishableKey) return void 0;
6912
7685
  const opts = {
6913
7686
  appearance,
@@ -6926,7 +7699,7 @@ function FloPayCheckout({
6926
7699
  const shouldHandleInlineSessionPatch = Boolean(
6927
7700
  createSessionParams && !children && layout === "buttons" && onBeforeButtonClick && effectiveCreateSessionMode === "full"
6928
7701
  );
6929
- const checkoutValue = (0, import_react10.useMemo)(
7702
+ const checkoutValue = (0, import_react11.useMemo)(
6930
7703
  () => ({
6931
7704
  session,
6932
7705
  loading: isLoading,
@@ -6948,7 +7721,7 @@ function FloPayCheckout({
6948
7721
  ]
6949
7722
  );
6950
7723
  const shouldShowInterimButtons = Boolean(createSessionParams) && layout === "buttons" && !isPaypalOnlySession && (!flopay || !providerOptions);
6951
- const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7724
+ const modeOverlay = modeOverlayStatus ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
6952
7725
  ProcessingOverlay,
6953
7726
  {
6954
7727
  status: modeOverlayStatus,
@@ -6957,32 +7730,32 @@ function FloPayCheckout({
6957
7730
  ) : null;
6958
7731
  if (isLoading) {
6959
7732
  if (loadingNode) {
6960
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
7733
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
6961
7734
  loadingNode,
6962
7735
  modeOverlay
6963
7736
  ] });
6964
7737
  }
6965
7738
  if (layout === "buttons") {
6966
7739
  const bundleRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
6967
- const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
7740
+ const skeletonBar = (h) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
6968
7741
  height: h,
6969
7742
  borderRadius: bundleRadius,
6970
7743
  background: "#e5e7eb",
6971
7744
  animation: "flopay-loading-pulse 1.5s ease-in-out infinite"
6972
7745
  } });
6973
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6974
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
7746
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7747
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
6975
7748
  showPayPal && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6976
7749
  showStripe && (showApplePay || showGooglePay) && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6977
7750
  showStripe && skeletonBar(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
6978
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
7751
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes flopay-loading-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
6979
7752
  ] }),
6980
7753
  modeOverlay
6981
7754
  ] });
6982
7755
  }
6983
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6984
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
6985
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
7756
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7757
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: [
7758
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
6986
7759
  width: 24,
6987
7760
  height: 24,
6988
7761
  border: "2px solid #e5e7eb",
@@ -6990,16 +7763,16 @@ function FloPayCheckout({
6990
7763
  borderRadius: "50%",
6991
7764
  animation: "spin 0.6s linear infinite"
6992
7765
  } }),
6993
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
7766
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
6994
7767
  ] }),
6995
7768
  modeOverlay
6996
7769
  ] });
6997
7770
  }
6998
7771
  if (loadError) {
6999
7772
  if (errorNode) {
7000
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
7773
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: errorNode(loadError) });
7001
7774
  }
7002
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7775
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7003
7776
  "div",
7004
7777
  {
7005
7778
  role: "alert",
@@ -7015,8 +7788,8 @@ function FloPayCheckout({
7015
7788
  ) });
7016
7789
  }
7017
7790
  if (shouldShowInterimButtons) {
7018
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
7019
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7791
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7792
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7020
7793
  InterimButtonsView,
7021
7794
  {
7022
7795
  onButtonClick,
@@ -7036,27 +7809,11 @@ function FloPayCheckout({
7036
7809
  ] });
7037
7810
  }
7038
7811
  if (isPaypalOnlySession && session && directPaypalConfig) {
7039
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
7040
- /* @__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: [
7041
- modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7042
- "div",
7043
- {
7044
- role: "alert",
7045
- "data-testid": "flopay-error",
7046
- style: {
7047
- padding: "0.625rem 0.875rem",
7048
- background: "#FEF2F2",
7049
- border: "1px solid #FECACA",
7050
- borderRadius: "8px",
7051
- color: "#991B1B",
7052
- fontSize: "0.85rem",
7053
- fontWeight: 600
7054
- },
7055
- children: modeError
7056
- }
7057
- ),
7058
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7059
- DirectPayPalButton,
7812
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7813
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
7814
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorBanner, { icon: false, children: modeError }),
7815
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7816
+ InstrumentedDirectPayPalButton,
7060
7817
  {
7061
7818
  sessionId: activeSessionId,
7062
7819
  nonce: session.clientSecret || void 0,
@@ -7071,6 +7828,8 @@ function FloPayCheckout({
7071
7828
  onDecline,
7072
7829
  onButtonClick,
7073
7830
  session,
7831
+ telemetry,
7832
+ telemetryContext: telemetryCheckoutContext,
7074
7833
  debug
7075
7834
  }
7076
7835
  )
@@ -7079,12 +7838,12 @@ function FloPayCheckout({
7079
7838
  ] });
7080
7839
  }
7081
7840
  if (!flopay || !providerOptions) {
7082
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: modeOverlay });
7841
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: modeOverlay });
7083
7842
  }
7084
7843
  if (currentMode === "confirm") {
7085
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
7086
- /* @__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: [
7087
- modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7844
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7845
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, children: [
7846
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7088
7847
  "div",
7089
7848
  {
7090
7849
  style: {
@@ -7099,7 +7858,7 @@ function FloPayCheckout({
7099
7858
  renderConfirmButton ? renderConfirmButton({
7100
7859
  onConfirm: handleConfirmCheckout,
7101
7860
  isProcessing: confirmProcessing
7102
- }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7861
+ }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7103
7862
  "button",
7104
7863
  {
7105
7864
  type: "button",
@@ -7124,9 +7883,9 @@ function FloPayCheckout({
7124
7883
  modeOverlay
7125
7884
  ] });
7126
7885
  }
7127
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
7128
- /* @__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: [
7129
- modeError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7886
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7887
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutContext.Provider, { value: checkoutValue, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FloPayProvider, { flopay, paypalFlopay, options: providerOptions, children: children ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7888
+ modeError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7130
7889
  "div",
7131
7890
  {
7132
7891
  style: {
@@ -7141,7 +7900,7 @@ function FloPayCheckout({
7141
7900
  children: modeError
7142
7901
  }
7143
7902
  ),
7144
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7903
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7145
7904
  SessionInjector,
7146
7905
  {
7147
7906
  sessionId: activeSessionId,
@@ -7151,7 +7910,7 @@ function FloPayCheckout({
7151
7910
  children
7152
7911
  }
7153
7912
  )
7154
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7913
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7155
7914
  SplitCardForm,
7156
7915
  {
7157
7916
  sessionId: activeSessionId,
@@ -7214,8 +7973,8 @@ function SessionInjector({
7214
7973
  session,
7215
7974
  children
7216
7975
  }) {
7217
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: import_react10.default.Children.map(children, (child) => {
7218
- if (!import_react10.default.isValidElement(child)) return child;
7976
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: import_react11.default.Children.map(children, (child) => {
7977
+ if (!import_react11.default.isValidElement(child)) return child;
7219
7978
  const existing = child.props;
7220
7979
  const injected = {};
7221
7980
  if (!existing.sessionId) injected.sessionId = sessionId;
@@ -7230,15 +7989,11 @@ function SessionInjector({
7230
7989
  injected.lastName = session.customer.lastName;
7231
7990
  }
7232
7991
  if (Object.keys(injected).length === 0) return child;
7233
- return import_react10.default.cloneElement(child, injected);
7992
+ return import_react11.default.cloneElement(child, injected);
7234
7993
  }) });
7235
7994
  }
7236
7995
  function InterimButtonsView({
7237
7996
  onButtonClick,
7238
- onCardButtonClick,
7239
- cardLoading = false,
7240
- cardOpen,
7241
- errorMessage,
7242
7997
  showPayPal,
7243
7998
  showStripe = true,
7244
7999
  showApplePay,
@@ -7250,15 +8005,9 @@ function InterimButtonsView({
7250
8005
  cardBackButtonContent,
7251
8006
  cardTitleContent
7252
8007
  }) {
7253
- const [showCardForm, setShowCardForm] = (0, import_react10.useState)(false);
7254
- const isCardOpenControlled = typeof cardOpen === "boolean";
7255
- (0, import_react10.useEffect)(() => {
7256
- if (isCardOpenControlled) {
7257
- setShowCardForm(cardOpen);
7258
- }
7259
- }, [cardOpen, isCardOpenControlled]);
7260
- const themeBundle = (0, import_react10.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
7261
- const bStyles = (0, import_react10.useMemo)(() => {
8008
+ const [showCardForm, setShowCardForm] = (0, import_react11.useState)(false);
8009
+ const themeBundle = (0, import_react11.useMemo)(() => (0, import_shared8.resolveTheme)(theme), [theme]);
8010
+ const bStyles = (0, import_react11.useMemo)(() => {
7262
8011
  const base = themeBundle?.buttonsLayout ?? (0, import_shared8.resolveButtonsLayoutTheme)(buttonsTheme);
7263
8012
  if (!stylesOverride) return base;
7264
8013
  return {
@@ -7273,7 +8022,7 @@ function InterimButtonsView({
7273
8022
  };
7274
8023
  }, [themeBundle, buttonsTheme, stylesOverride]);
7275
8024
  const skeletonRadius = themeBundle?.buttonsLayout?.cardButton?.borderRadius ?? themeBundle?.appearance.variables?.borderRadius ?? 8;
7276
- const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
8025
+ const skeleton = (h) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7277
8026
  height: h,
7278
8027
  borderRadius: skeletonRadius,
7279
8028
  background: "#e5e7eb",
@@ -7285,25 +8034,20 @@ function InterimButtonsView({
7285
8034
  const inputBg = bStyles.cardInputBackground ?? "white";
7286
8035
  const hideBackButtonLabel = isEmptySlotContent(cardBackButtonContent);
7287
8036
  const hideTitle = isEmptySlotContent(cardTitleContent);
7288
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
8037
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: {
7289
8038
  backgroundColor: bStyles.cardFormContainer?.backgroundColor ?? "white",
7290
8039
  borderRadius: "8px",
7291
8040
  animation: "flopay-interim-expand 0.35s cubic-bezier(0.4, 0, 0.2, 1) both",
7292
8041
  overflow: "hidden",
7293
8042
  ...bStyles.cardFormContainer
7294
8043
  }, children: [
7295
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
7296
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
8044
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "0.75rem 0 0.625rem" }, children: [
8045
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
7297
8046
  "button",
7298
8047
  {
7299
8048
  type: "button",
7300
- onClick: () => {
7301
- if (!isCardOpenControlled) {
7302
- setShowCardForm(false);
7303
- }
7304
- },
8049
+ onClick: () => setShowCardForm(false),
7305
8050
  "aria-label": "Back to payment methods",
7306
- disabled: isCardOpenControlled || cardLoading,
7307
8051
  style: {
7308
8052
  display: "inline-flex",
7309
8053
  alignItems: "center",
@@ -7315,12 +8059,12 @@ function InterimButtonsView({
7315
8059
  fontWeight: 500,
7316
8060
  padding: 0,
7317
8061
  flexShrink: 0,
7318
- opacity: isCardOpenControlled || cardLoading ? 0.6 : 1,
7319
- cursor: isCardOpenControlled || cardLoading ? "not-allowed" : "pointer",
8062
+ opacity: 1,
8063
+ cursor: "pointer",
7320
8064
  ...bStyles.backButton
7321
8065
  },
7322
8066
  children: [
7323
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
8067
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: {
7324
8068
  display: "inline-flex",
7325
8069
  alignItems: "center",
7326
8070
  justifyContent: "center",
@@ -7329,12 +8073,12 @@ function InterimButtonsView({
7329
8073
  borderRadius: "50%",
7330
8074
  backgroundColor: "#f3f4f6",
7331
8075
  ...bStyles.backButtonIcon
7332
- }, 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" }) }) }),
7333
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
8076
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime9.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_runtime9.jsx)("path", { d: "M15 18l-6-6 6-6" }) }) }),
8077
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BackButtonContentSlot, { content: cardBackButtonContent })
7334
8078
  ]
7335
8079
  }
7336
8080
  ),
7337
- hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
8081
+ hideTitle ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: 1 } }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7338
8082
  flex: 1,
7339
8083
  textAlign: "center",
7340
8084
  fontWeight: 600,
@@ -7342,11 +8086,11 @@ function InterimButtonsView({
7342
8086
  color: "#262833",
7343
8087
  paddingRight: 80,
7344
8088
  ...bStyles.title
7345
- }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TitleContentSlot, { content: cardTitleContent }) })
8089
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TitleContentSlot, { content: cardTitleContent }) })
7346
8090
  ] }),
7347
- /* @__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" } }) }),
7348
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex" }, children: [
7349
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
8091
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderTopLeftRadius: 8, borderTopRightRadius: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "60%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
8092
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex" }, children: [
8093
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7350
8094
  flex: 1,
7351
8095
  backgroundColor: inputBg,
7352
8096
  borderTop: "none",
@@ -7356,8 +8100,8 @@ function InterimButtonsView({
7356
8100
  borderBottomLeftRadius: 8,
7357
8101
  padding: 12,
7358
8102
  height: 45
7359
- }, 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" } }) }),
7360
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
8103
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "50%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
8104
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7361
8105
  flex: 1,
7362
8106
  backgroundColor: inputBg,
7363
8107
  borderTop: "none",
@@ -7367,10 +8111,10 @@ function InterimButtonsView({
7367
8111
  borderBottomRightRadius: 8,
7368
8112
  padding: 12,
7369
8113
  height: 45
7370
- }, 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" } }) })
8114
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "40%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) })
7371
8115
  ] }),
7372
- /* @__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" } }) }),
7373
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
8116
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { backgroundColor: inputBg, border: `1px solid ${inputBorder}`, borderRadius: 8, marginTop: 8, padding: 12, height: 45 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "45%", height: 14, borderRadius: 4, background: "#e5e7eb", animation: "flopay-interim-pulse 1.5s ease-in-out infinite" } }) }),
8117
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
7374
8118
  height: 50,
7375
8119
  borderRadius: 8,
7376
8120
  marginTop: 16,
@@ -7379,7 +8123,7 @@ function InterimButtonsView({
7379
8123
  ...bStyles.submitButton,
7380
8124
  opacity: 0.5
7381
8125
  } }),
7382
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
8126
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
7383
8127
  @keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
7384
8128
  @keyframes flopay-interim-expand {
7385
8129
  0% { opacity: 0; max-height: 0; transform: translateY(-12px); }
@@ -7389,23 +8133,17 @@ function InterimButtonsView({
7389
8133
  ` })
7390
8134
  ] });
7391
8135
  }
7392
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
8136
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
7393
8137
  showPayPal && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
7394
8138
  showStripe && (showApplePay || showGooglePay) && skeleton(DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2),
7395
- showStripe && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
8139
+ showStripe && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
7396
8140
  "button",
7397
8141
  {
7398
8142
  type: "button",
7399
- onClick: async () => {
7400
- if (cardLoading) return;
7401
- if (onCardButtonClick) {
7402
- await onCardButtonClick();
7403
- return;
7404
- }
8143
+ onClick: () => {
7405
8144
  onButtonClick?.("card");
7406
8145
  setShowCardForm(true);
7407
8146
  },
7408
- disabled: cardLoading,
7409
8147
  style: {
7410
8148
  width: "100%",
7411
8149
  ...cardButtonSizing,
@@ -7415,7 +8153,7 @@ function InterimButtonsView({
7415
8153
  borderRadius: "8px",
7416
8154
  fontSize: bStyles.cardButtonFontSize ?? "0.95rem",
7417
8155
  fontWeight: 600,
7418
- cursor: cardLoading ? "not-allowed" : "pointer",
8156
+ cursor: "pointer",
7419
8157
  display: "flex",
7420
8158
  alignItems: "center",
7421
8159
  justifyContent: "center",
@@ -7423,7 +8161,7 @@ function InterimButtonsView({
7423
8161
  boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
7424
8162
  transition: "transform 0.1s",
7425
8163
  position: "relative",
7426
- opacity: cardLoading ? 0.6 : 1,
8164
+ opacity: 1,
7427
8165
  ...bStyles.cardButton
7428
8166
  },
7429
8167
  onMouseDown: (e) => {
@@ -7432,39 +8170,22 @@ function InterimButtonsView({
7432
8170
  onMouseUp: (e) => {
7433
8171
  e.currentTarget.style.transform = "scale(1)";
7434
8172
  },
7435
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CardButtonContentSlot, { content: cardButtonContent })
8173
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CardButtonContentSlot, { content: cardButtonContent })
7436
8174
  }
7437
8175
  ),
7438
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
7439
- margin: "0.25rem 0",
7440
- padding: "0.625rem 0.875rem",
7441
- background: "#FEF2F2",
7442
- border: "1px solid #FECACA",
7443
- borderRadius: "8px",
7444
- color: "#991B1B",
7445
- fontSize: "0.85rem",
7446
- fontWeight: 600,
7447
- display: "flex",
7448
- alignItems: "center",
7449
- gap: "0.5rem",
7450
- ...bStyles.errorBanner
7451
- }, children: [
7452
- /* @__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" }) }),
7453
- errorMessage
7454
- ] }),
7455
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
8176
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `@keyframes flopay-interim-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }` })
7456
8177
  ] });
7457
8178
  }
7458
8179
 
7459
8180
  // src/checkout-form.tsx
7460
8181
  var import_js5 = require("@flopay/js");
7461
8182
  var import_shared9 = require("@flopay/shared");
7462
- var import_react11 = require("react");
7463
- var import_jsx_runtime9 = require("react/jsx-runtime");
8183
+ var import_react12 = require("react");
8184
+ var import_jsx_runtime10 = require("react/jsx-runtime");
7464
8185
  var WALLET_RESUME_KEY = "flopay_wallet_resume";
7465
- var CheckoutForm = (0, import_react11.forwardRef)(
8186
+ var CheckoutForm = (0, import_react12.forwardRef)(
7466
8187
  function CheckoutForm2(props, ref) {
7467
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
8188
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CheckoutFormInner, { ...props, innerRef: ref });
7468
8189
  }
7469
8190
  );
7470
8191
  function CheckoutFormInner({
@@ -7494,27 +8215,27 @@ function CheckoutFormInner({
7494
8215
  const paypalFlopay = usePayPalFloPay();
7495
8216
  const elements = useElements();
7496
8217
  const contextBillingUrl = useBillingApiUrl();
7497
- const [processing, setProcessing] = (0, import_react11.useState)(false);
7498
- const [error, setError] = (0, import_react11.useState)(null);
7499
- const [is3DSActive, setIs3DSActive] = (0, import_react11.useState)(false);
8218
+ const [processing, setProcessing] = (0, import_react12.useState)(false);
8219
+ const [error, setError] = (0, import_react12.useState)(null);
8220
+ const [is3DSActive, setIs3DSActive] = (0, import_react12.useState)(false);
7500
8221
  const displayError = externalError ?? error;
7501
8222
  const isSubmitting = externalProcessing ?? processing;
7502
8223
  const isSelfContained = !onTokenizedBody;
7503
8224
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
7504
- const updateError = (0, import_react11.useCallback)(
8225
+ const updateError = (0, import_react12.useCallback)(
7505
8226
  (err) => {
7506
8227
  setError(err);
7507
8228
  onErrorChange?.(err);
7508
8229
  },
7509
8230
  [onErrorChange]
7510
8231
  );
7511
- const emitDecline = (0, import_react11.useCallback)(
8232
+ const emitDecline = (0, import_react12.useCallback)(
7512
8233
  (input, overrides) => {
7513
8234
  onDecline?.(buildDeclineEvent("card", input, overrides));
7514
8235
  },
7515
8236
  [onDecline]
7516
8237
  );
7517
- const processPaymentInternal = (0, import_react11.useCallback)(
8238
+ const processPaymentInternal = (0, import_react12.useCallback)(
7518
8239
  async (tokenizedBody, completionPaymentMethodId) => {
7519
8240
  setProcessing(true);
7520
8241
  updateError(null);
@@ -7626,7 +8347,7 @@ function CheckoutFormInner({
7626
8347
  },
7627
8348
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, flopay, paypalFlopay, onComplete, onError, onDecline, updateError, emitDecline]
7628
8349
  );
7629
- const dispatchTokenizedBody = (0, import_react11.useCallback)(
8350
+ const dispatchTokenizedBody = (0, import_react12.useCallback)(
7630
8351
  (tokenizedBody) => {
7631
8352
  if (onTokenizedBody) {
7632
8353
  onTokenizedBody(tokenizedBody);
@@ -7636,7 +8357,7 @@ function CheckoutFormInner({
7636
8357
  },
7637
8358
  [onTokenizedBody, processPaymentInternal]
7638
8359
  );
7639
- (0, import_react11.useImperativeHandle)(innerRef, () => ({
8360
+ (0, import_react12.useImperativeHandle)(innerRef, () => ({
7640
8361
  async handleNextAction(secret) {
7641
8362
  if (!flopay) return;
7642
8363
  setIs3DSActive(true);
@@ -7663,7 +8384,7 @@ function CheckoutFormInner({
7663
8384
  }
7664
8385
  }
7665
8386
  }), [flopay, dispatchTokenizedBody, onError, updateError, emitDecline]);
7666
- (0, import_react11.useEffect)(() => {
8387
+ (0, import_react12.useEffect)(() => {
7667
8388
  if (typeof window === "undefined") return;
7668
8389
  const stored = localStorage.getItem(WALLET_RESUME_KEY);
7669
8390
  if (!stored) return;
@@ -7681,7 +8402,7 @@ function CheckoutFormInner({
7681
8402
  localStorage.removeItem(WALLET_RESUME_KEY);
7682
8403
  }
7683
8404
  }, [sessionId, dispatchTokenizedBody]);
7684
- const handleSubmit = (0, import_react11.useCallback)(
8405
+ const handleSubmit = (0, import_react12.useCallback)(
7685
8406
  async (e) => {
7686
8407
  e.preventDefault();
7687
8408
  if (!flopay || !elements || isSubmitting) return;
@@ -7707,8 +8428,7 @@ function CheckoutFormInner({
7707
8428
  if (!sessionId || !email) {
7708
8429
  throw new import_shared9.FloPayError("Missing sessionId or email", "validation_error");
7709
8430
  }
7710
- const intentHeaders = { "Content-Type": "application/json" };
7711
- if (nonce) intentHeaders["x-checkout-session-token"] = nonce;
8431
+ const intentHeaders = intentRequestHeaders(nonce);
7712
8432
  const intentResponse = await fetch(`${baseUrl}/v1/checkouts/payments/intents`, {
7713
8433
  method: "POST",
7714
8434
  headers: intentHeaders,
@@ -7773,8 +8493,8 @@ function CheckoutFormInner({
7773
8493
  [flopay, elements, isSubmitting, sessionId, nonce, email, firstName, lastName, baseUrl, isSelfContained, dispatchTokenizedBody, onError, updateError, emitDecline]
7774
8494
  );
7775
8495
  const isReady = flopay !== null && elements !== null;
7776
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
7777
- (is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-overlay", style: {
8496
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handleSubmit, className, style: { position: "relative" }, children: [
8497
+ (is3DSActive || isSubmitting) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "flopay-overlay", style: {
7778
8498
  position: "absolute",
7779
8499
  inset: 0,
7780
8500
  background: "rgba(255,255,255,0.7)",
@@ -7783,12 +8503,12 @@ function CheckoutFormInner({
7783
8503
  justifyContent: "center",
7784
8504
  zIndex: 10
7785
8505
  }, children: is3DSActive ? "Verifying payment..." : "Processing..." }),
7786
- !isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
7787
- isReady && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
7788
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PaymentElement, { options: { layout } }),
7789
- showAddress && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
7790
- displayError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
7791
- children ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
8506
+ !isReady && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": "flopay-loading", "aria-busy": "true", children: "Loading payment form..." }),
8507
+ isReady && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
8508
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PaymentElement, { options: { layout } }),
8509
+ showAddress && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(AddressElement, { options: { mode: showAddress === true ? "billing" : showAddress } }),
8510
+ displayError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", "data-testid": "flopay-error", style: { color: "red", margin: "0.75rem 0" }, children: displayError }),
8511
+ children ?? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7792
8512
  "button",
7793
8513
  {
7794
8514
  type: "submit",
@@ -7804,8 +8524,8 @@ function CheckoutFormInner({
7804
8524
  // src/paypal-button.tsx
7805
8525
  var import_js6 = require("@flopay/js");
7806
8526
  var import_shared10 = require("@flopay/shared");
7807
- var import_react12 = require("react");
7808
- var import_jsx_runtime10 = require("react/jsx-runtime");
8527
+ var import_react13 = require("react");
8528
+ var import_jsx_runtime11 = require("react/jsx-runtime");
7809
8529
  function PayPalButton({
7810
8530
  sessionId,
7811
8531
  nonce,
@@ -7823,11 +8543,11 @@ function PayPalButton({
7823
8543
  const flopay = useFloPay();
7824
8544
  const elements = useElements();
7825
8545
  const contextBillingUrl = useBillingApiUrl();
7826
- const [ready, setReady] = (0, import_react12.useState)(false);
7827
- const [submitting, setSubmitting] = (0, import_react12.useState)(false);
7828
- const paypalResumeAttempted = (0, import_react12.useRef)(false);
8546
+ const [ready, setReady] = (0, import_react13.useState)(false);
8547
+ const [submitting, setSubmitting] = (0, import_react13.useState)(false);
8548
+ const paypalResumeAttempted = (0, import_react13.useRef)(false);
7829
8549
  const baseUrl = (billingApiUrl || contextBillingUrl).replace(/\/+$/, "");
7830
- const processPaymentInternal = (0, import_react12.useCallback)(
8550
+ const processPaymentInternal = (0, import_react13.useCallback)(
7831
8551
  async (tokenizedBody) => {
7832
8552
  try {
7833
8553
  const api = new import_js6.PaymentAPI(baseUrl);
@@ -7855,7 +8575,7 @@ function PayPalButton({
7855
8575
  },
7856
8576
  [baseUrl, sessionId, nonce, userId, email, firstName, lastName, chv, onComplete, onErrorChange]
7857
8577
  );
7858
- const dispatchTokenizedBody = (0, import_react12.useCallback)(
8578
+ const dispatchTokenizedBody = (0, import_react13.useCallback)(
7859
8579
  (body) => {
7860
8580
  if (onTokenizedBody) {
7861
8581
  onTokenizedBody(body);
@@ -7865,7 +8585,7 @@ function PayPalButton({
7865
8585
  },
7866
8586
  [onTokenizedBody, processPaymentInternal]
7867
8587
  );
7868
- (0, import_react12.useEffect)(() => {
8588
+ (0, import_react13.useEffect)(() => {
7869
8589
  if (!flopay || paypalResumeAttempted.current) return;
7870
8590
  const params = new URLSearchParams(window.location.search);
7871
8591
  const paymentIntentId = params.get("payment_intent");
@@ -7913,7 +8633,7 @@ function PayPalButton({
7913
8633
  }
7914
8634
  })();
7915
8635
  }, [flopay, dispatchTokenizedBody, onErrorChange]);
7916
- const handlePayPalConfirm = (0, import_react12.useCallback)(async () => {
8636
+ const handlePayPalConfirm = (0, import_react13.useCallback)(async () => {
7917
8637
  if (!flopay || !elements) return;
7918
8638
  try {
7919
8639
  setSubmitting(true);
@@ -7947,11 +8667,11 @@ function PayPalButton({
7947
8667
  }
7948
8668
  }, [flopay, elements, sessionId, nonce, email, baseUrl, dispatchTokenizedBody, onErrorChange]);
7949
8669
  if (!flopay || !elements) {
7950
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
8670
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6, animation: "pulse 1.5s infinite" } });
7951
8671
  }
7952
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
7953
- !ready && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
7954
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
8672
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
8673
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { height: 45, background: "#f0f0f0", borderRadius: 6 } }),
8674
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: ready ? {} : { display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7955
8675
  "button",
7956
8676
  {
7957
8677
  type: "button",
@@ -7973,7 +8693,7 @@ function PayPalButton({
7973
8693
  children: submitting ? "Processing..." : "PayPal"
7974
8694
  }
7975
8695
  ) }),
7976
- (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
8696
+ (submitting || isProcessing) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: {
7977
8697
  position: "fixed",
7978
8698
  inset: 0,
7979
8699
  background: "rgba(0,0,0,0.4)",
@@ -7981,7 +8701,7 @@ function PayPalButton({
7981
8701
  alignItems: "center",
7982
8702
  justifyContent: "center",
7983
8703
  zIndex: 1e3
7984
- }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: {
8704
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: {
7985
8705
  background: "white",
7986
8706
  borderRadius: 8,
7987
8707
  padding: "1.5rem",
@@ -7993,10 +8713,10 @@ function PayPalButton({
7993
8713
  }
7994
8714
 
7995
8715
  // src/automatic-payment-button.tsx
7996
- var import_react13 = require("react");
8716
+ var import_react14 = require("react");
7997
8717
  var import_js7 = require("@flopay/js");
7998
8718
  var import_shared11 = require("@flopay/shared");
7999
- var import_jsx_runtime11 = require("react/jsx-runtime");
8719
+ var import_jsx_runtime12 = require("react/jsx-runtime");
8000
8720
  var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3 = 44;
8001
8721
  function sleep2(ms) {
8002
8722
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -8076,11 +8796,11 @@ function FloPayAutomaticPaymentButton({
8076
8796
  style,
8077
8797
  ...buttonProps
8078
8798
  }) {
8079
- const resolvedBillingUrl = (0, import_react13.useMemo)(
8799
+ const resolvedBillingUrl = (0, import_react14.useMemo)(
8080
8800
  () => (0, import_shared11.resolveBillingApiUrl)(billingApiUrl),
8081
8801
  [billingApiUrl]
8082
8802
  );
8083
- const createSessionDraft = (0, import_react13.useMemo)(
8803
+ const createSessionDraft = (0, import_react14.useMemo)(
8084
8804
  () => resolveCreateSessionDraft({
8085
8805
  createSession,
8086
8806
  clientId,
@@ -8108,37 +8828,37 @@ function FloPayAutomaticPaymentButton({
8108
8828
  utmMetadata
8109
8829
  ]
8110
8830
  );
8111
- const [isProcessing, setIsProcessing] = (0, import_react13.useState)(false);
8112
- const [overlayStatus, setOverlayStatus] = (0, import_react13.useState)(null);
8113
- const [overlayError, setOverlayError] = (0, import_react13.useState)(null);
8114
- const [fallbackSession, setFallbackSession] = (0, import_react13.useState)(null);
8115
- const isMountedRef = (0, import_react13.useRef)(true);
8116
- const threeDsAbortRef = (0, import_react13.useRef)(null);
8117
- const fallbackSessionRef = (0, import_react13.useRef)(fallbackSession);
8118
- const onSuccessRef = (0, import_react13.useRef)(onSuccess);
8119
- const onErrorRef = (0, import_react13.useRef)(onError);
8120
- const onDeclineRef = (0, import_react13.useRef)(onDecline);
8121
- (0, import_react13.useEffect)(() => {
8831
+ const [isProcessing, setIsProcessing] = (0, import_react14.useState)(false);
8832
+ const [overlayStatus, setOverlayStatus] = (0, import_react14.useState)(null);
8833
+ const [overlayError, setOverlayError] = (0, import_react14.useState)(null);
8834
+ const [fallbackSession, setFallbackSession] = (0, import_react14.useState)(null);
8835
+ const isMountedRef = (0, import_react14.useRef)(true);
8836
+ const threeDsAbortRef = (0, import_react14.useRef)(null);
8837
+ const fallbackSessionRef = (0, import_react14.useRef)(fallbackSession);
8838
+ const onSuccessRef = (0, import_react14.useRef)(onSuccess);
8839
+ const onErrorRef = (0, import_react14.useRef)(onError);
8840
+ const onDeclineRef = (0, import_react14.useRef)(onDecline);
8841
+ (0, import_react14.useEffect)(() => {
8122
8842
  fallbackSessionRef.current = fallbackSession;
8123
8843
  }, [fallbackSession]);
8124
- (0, import_react13.useEffect)(() => {
8844
+ (0, import_react14.useEffect)(() => {
8125
8845
  onSuccessRef.current = onSuccess;
8126
8846
  }, [onSuccess]);
8127
- (0, import_react13.useEffect)(() => {
8847
+ (0, import_react14.useEffect)(() => {
8128
8848
  onErrorRef.current = onError;
8129
8849
  }, [onError]);
8130
- (0, import_react13.useEffect)(() => {
8850
+ (0, import_react14.useEffect)(() => {
8131
8851
  onDeclineRef.current = onDecline;
8132
8852
  }, [onDecline]);
8133
- (0, import_react13.useEffect)(() => {
8853
+ (0, import_react14.useEffect)(() => {
8134
8854
  isMountedRef.current = true;
8135
8855
  return () => {
8136
8856
  isMountedRef.current = false;
8137
8857
  threeDsAbortRef.current?.abort();
8138
8858
  };
8139
8859
  }, []);
8140
- (0, import_react13.useEffect)(() => {
8141
- if (!fallbackSession || typeof window === "undefined") {
8860
+ (0, import_react14.useEffect)(() => {
8861
+ if (typeof window === "undefined") {
8142
8862
  return;
8143
8863
  }
8144
8864
  const handleKeyDown = (event) => {
@@ -8150,14 +8870,14 @@ function FloPayAutomaticPaymentButton({
8150
8870
  return () => {
8151
8871
  window.removeEventListener("keydown", handleKeyDown);
8152
8872
  };
8153
- }, [fallbackSession]);
8154
- const emitDecline = (0, import_react13.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
8873
+ }, []);
8874
+ const emitDecline = (0, import_react14.useCallback)((error, method = DEFAULT_SAVED_PAYMENT_DECLINE_METHOD) => {
8155
8875
  onDeclineRef.current?.(buildDeclineEvent(method, error, {
8156
8876
  code: error.code,
8157
8877
  declineCode: error.declineCode
8158
8878
  }));
8159
8879
  }, []);
8160
- const showSuccess = (0, import_react13.useCallback)(async (event) => {
8880
+ const showSuccess = (0, import_react14.useCallback)(async (event) => {
8161
8881
  if (!isMountedRef.current) return;
8162
8882
  setOverlayError(null);
8163
8883
  setOverlayStatus("success");
@@ -8165,7 +8885,7 @@ function FloPayAutomaticPaymentButton({
8165
8885
  if (!isMountedRef.current) return;
8166
8886
  onSuccessRef.current?.(event);
8167
8887
  }, []);
8168
- const showError = (0, import_react13.useCallback)(async (error, options) => {
8888
+ const showError = (0, import_react14.useCallback)(async (error, options) => {
8169
8889
  if (!isMountedRef.current) return;
8170
8890
  onErrorRef.current?.(error);
8171
8891
  if (options?.emitDecline) {
@@ -8175,7 +8895,7 @@ function FloPayAutomaticPaymentButton({
8175
8895
  setOverlayStatus("error");
8176
8896
  await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
8177
8897
  }, [emitDecline]);
8178
- const processResolvedSession = (0, import_react13.useCallback)(async (apiResult, resolvedSessionId, options) => {
8898
+ const processResolvedSession = (0, import_react14.useCallback)(async (apiResult, resolvedSessionId, options) => {
8179
8899
  const session = apiResult.data.session ?? null;
8180
8900
  if (!session) {
8181
8901
  throw new import_shared11.FloPayError("No session data returned", "api_error");
@@ -8331,7 +9051,7 @@ function FloPayAutomaticPaymentButton({
8331
9051
  showError,
8332
9052
  showSuccess
8333
9053
  ]);
8334
- const handleButtonClick = (0, import_react13.useCallback)(async (event) => {
9054
+ const handleButtonClick = (0, import_react14.useCallback)(async (event) => {
8335
9055
  buttonProps.onClick?.(event);
8336
9056
  if (event.defaultPrevented || disabled || isProcessing) {
8337
9057
  return;
@@ -8413,7 +9133,7 @@ function FloPayAutomaticPaymentButton({
8413
9133
  showError,
8414
9134
  showSuccess
8415
9135
  ]);
8416
- const handleFallbackComplete = (0, import_react13.useCallback)((result) => {
9136
+ const handleFallbackComplete = (0, import_react14.useCallback)((result) => {
8417
9137
  const activeFallback = fallbackSessionRef.current;
8418
9138
  setFallbackSession(null);
8419
9139
  onSuccessRef.current?.({
@@ -8423,14 +9143,14 @@ function FloPayAutomaticPaymentButton({
8423
9143
  autoCompleted: false
8424
9144
  });
8425
9145
  }, []);
8426
- const handleFallbackError = (0, import_react13.useCallback)((error) => {
9146
+ const handleFallbackError = (0, import_react14.useCallback)((error) => {
8427
9147
  onErrorRef.current?.(error);
8428
9148
  }, []);
8429
- const handleFallbackDecline = (0, import_react13.useCallback)((decline) => {
9149
+ const handleFallbackDecline = (0, import_react14.useCallback)((decline) => {
8430
9150
  onDeclineRef.current?.(decline);
8431
9151
  }, []);
8432
- const themeBundle = (0, import_react13.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
8433
- const bStyles = (0, import_react13.useMemo)(() => {
9152
+ const themeBundle = (0, import_react14.useMemo)(() => (0, import_shared11.resolveTheme)(theme), [theme]);
9153
+ const bStyles = (0, import_react14.useMemo)(() => {
8434
9154
  const base = themeBundle?.buttonsLayout ?? (0, import_shared11.resolveButtonsLayoutTheme)(buttonsTheme);
8435
9155
  if (!stylesOverride) return base;
8436
9156
  return {
@@ -8439,7 +9159,7 @@ function FloPayAutomaticPaymentButton({
8439
9159
  cardButton: { ...base.cardButton, ...stylesOverride.cardButton }
8440
9160
  };
8441
9161
  }, [themeBundle, buttonsTheme, stylesOverride]);
8442
- const resolvedAppearance = (0, import_react13.useMemo)(() => {
9162
+ const resolvedAppearance = (0, import_react14.useMemo)(() => {
8443
9163
  const bundleAppearance = themeBundle?.appearance;
8444
9164
  if (!appearance) return bundleAppearance;
8445
9165
  if (!bundleAppearance) return appearance;
@@ -8457,8 +9177,8 @@ function FloPayAutomaticPaymentButton({
8457
9177
  const resolvedPrimaryHoverColor = resolvedAppearanceVars?.colorPrimaryHover ?? darkenHex(resolvedPrimaryColor, 0.12);
8458
9178
  const resolvedButtonBorderRadius = resolvedAppearanceVars?.borderRadius ?? "8px";
8459
9179
  const cardButtonSizing = children === void 0 ? { boxSizing: "border-box", height: DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT3, padding: "0 1rem" } : { padding: "0.9rem 1rem" };
8460
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
8461
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9180
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
9181
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8462
9182
  "button",
8463
9183
  {
8464
9184
  ...buttonProps,
@@ -8522,17 +9242,17 @@ function FloPayAutomaticPaymentButton({
8522
9242
  e.currentTarget.style.transform = "scale(1)";
8523
9243
  }
8524
9244
  },
8525
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CardButtonContentSlot, { content: children })
9245
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardButtonContentSlot, { content: children })
8526
9246
  }
8527
9247
  ),
8528
- overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9248
+ overlayStatus && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8529
9249
  ProcessingOverlay,
8530
9250
  {
8531
9251
  status: overlayStatus,
8532
9252
  errorMessage: overlayError
8533
9253
  }
8534
9254
  ),
8535
- fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9255
+ fallbackSession && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8536
9256
  "div",
8537
9257
  {
8538
9258
  "data-testid": "flopay-automatic-payment-fallback",
@@ -8553,7 +9273,7 @@ function FloPayAutomaticPaymentButton({
8553
9273
  padding: "1.5rem",
8554
9274
  zIndex: 1100
8555
9275
  },
8556
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9276
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8557
9277
  "div",
8558
9278
  {
8559
9279
  style: {
@@ -8569,7 +9289,7 @@ function FloPayAutomaticPaymentButton({
8569
9289
  flexDirection: "column",
8570
9290
  gap: "1rem"
8571
9291
  },
8572
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
9292
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8573
9293
  FloPayCheckout,
8574
9294
  {
8575
9295
  sessionId: fallbackSession.sessionId,