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