@flopay/react 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/card-setup-entry.cjs +2 -2
- package/dist/card-setup-entry.d.cts +1 -1
- package/dist/card-setup-entry.d.ts +1 -1
- package/dist/card-setup-entry.mjs +1 -1
- package/dist/chunk-VWT2TDA6.mjs +6 -0
- package/dist/index.cjs +10 -10
- package/dist/index.d.cts +480 -476
- package/dist/index.d.ts +480 -476
- package/dist/index.mjs +8 -8
- package/package.json +3 -3
- package/dist/chunk-P5QXEIBB.mjs +0 -6
package/README.md
CHANGED
|
@@ -55,6 +55,37 @@ function CheckoutPage() {
|
|
|
55
55
|
|
|
56
56
|
`FloPayCheckout` automatically fetches the session, initializes the correct payment providers, and renders a `SplitCardForm` with the hosted vault card widget plus the session's supported wallets, APMs, and PayPal. Customer data (email, userId, name) is injected from the session.
|
|
57
57
|
|
|
58
|
+
#### Merchant instrument feed
|
|
59
|
+
|
|
60
|
+
Use `onInstrument` on `FloPayCheckout` or `FloPayProvider` to forward a stable,
|
|
61
|
+
privacy-safe checkout funnel to your own analytics. The callback receives the
|
|
62
|
+
exported `FloInstrumentEvent` discriminated union; `schemaVersion` is always `1`,
|
|
63
|
+
and `gateway` is included as `stripe` or `paypal` only when the event is
|
|
64
|
+
attributable to that payment provider. Hosted-vault events may omit `gateway`.
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import type { FloInstrumentEvent } from '@flopay/react';
|
|
68
|
+
|
|
69
|
+
function forwardCheckoutInstrument(event: FloInstrumentEvent) {
|
|
70
|
+
window.analytics?.track(event.name, event);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
<FloPayCheckout sessionId={sessionId} onInstrument={forwardCheckoutInstrument} />;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Lifecycle names are `checkout_mount`, `sdk_loaded`, `form_rendered`,
|
|
77
|
+
`card_expanded`, `tokenize`, `process_attempt`, and `3ds_challenge`.
|
|
78
|
+
`checkout_mount`, `sdk_loaded`, `form_rendered`, and `card_expanded` arrive at
|
|
79
|
+
most once per logical checkout. `tokenize`, `process_attempt`, and
|
|
80
|
+
`3ds_challenge` may repeat for each attempt.
|
|
81
|
+
`checkout_error` adds one of four phases: `session_create`, `sdk_load`,
|
|
82
|
+
`process`, or `wallets`.
|
|
83
|
+
|
|
84
|
+
The callback is an allowlisted projection with no card data, tokens, provider
|
|
85
|
+
object IDs, secrets, or raw PII. A throwing `onInstrument` consumer never
|
|
86
|
+
breaks checkout. This merchant-owned feed is independent of the Flo-owned
|
|
87
|
+
backend telemetry setting, so `telemetry={false}` does not disable it.
|
|
88
|
+
|
|
58
89
|
#### Checkout Modes
|
|
59
90
|
|
|
60
91
|
`FloPayCheckout` supports three checkout modes matching the billing API's `checkoutMode` field:
|
|
@@ -853,6 +884,7 @@ function PaymentStatus() {
|
|
|
853
884
|
| `options.amount` | `number?` | Amount in cents for deferred non-card Elements without a `clientSecret` |
|
|
854
885
|
| `options.currency` | `string?` | ISO 4217 currency code for deferred non-card Elements without a `clientSecret` |
|
|
855
886
|
| `options.paymentMethodCreation` | `'manual' \| 'auto'` | How payment methods are created |
|
|
887
|
+
| `onInstrument` | `(event: FloInstrumentEvent) => void` | Versioned, privacy-safe checkout funnel and phased error feed for merchant analytics. |
|
|
856
888
|
|
|
857
889
|
### FloPayCardSetupProps
|
|
858
890
|
|
|
@@ -994,3 +1026,4 @@ endpoint when a buyer enters the card path.
|
|
|
994
1026
|
| `PayPalButtonProps` | Props for `PayPalButton` |
|
|
995
1027
|
| `ElementComponentProps` | Shared props for all element components |
|
|
996
1028
|
| `CheckoutState` | `{ session, loading, error, claimPending }` |
|
|
1029
|
+
| `FloInstrumentEvent` | Versioned merchant instrument union with seven lifecycle names, four `checkout_error` phases, and an optional gateway. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var H=Object.defineProperty;var
|
|
1
|
+
"use strict";var H=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var se=Object.prototype.hasOwnProperty;var ie=(e,t)=>{for(var o in t)H(e,o,{get:t[o],enumerable:!0})},le=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ae(t))!se.call(e,r)&&r!==o&&H(e,r,{get:()=>t[r],enumerable:!(n=ne(t,r))||n.enumerable});return e};var ce=e=>le(H({},"__esModule",{value:!0}),e);var fe={};ie(fe,{FloPayCardSetup:()=>te,FloPayCardSetupError:()=>D});module.exports=ce(fe);var I=require("@flopay/js/card-setup"),c=require("@flopay/shared"),a=require("react");function R(e){if(!e)return;let t=o=>{console.error("[FloPay] Merchant callback failed; checkout continued.",o)};try{Promise.resolve(e()).catch(t)}catch(o){t(o)}}var i=require("react/jsx-runtime");function J({status:e,errorMessage:t,authorized:o=!1,processingLabel:n="PROCESSING...",successLabel:r,errorLabel:m="PAYMENT FAILED",successNote:u="You will be automatically redirected, do not close or navigate away from this window."}){return(0,i.jsx)("div",{"data-testid":"flopay-processing-overlay","data-status":e,role:"dialog","aria-modal":"true",style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.35)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e3,backdropFilter:"blur(2px)"},children:(0,i.jsxs)("div",{style:{background:"white",borderRadius:12,padding:"2rem 2.5rem",textAlign:"center",boxShadow:"0 8px 32px rgba(0,0,0,0.18)",minWidth:240,display:"flex",flexDirection:"column",alignItems:"center",gap:16},children:[(0,i.jsxs)("div",{style:{width:48,height:48,position:"relative"},children:[e==="processing"&&(0,i.jsxs)("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",style:{animation:"flopay-spin 0.8s linear infinite"},children:[(0,i.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:"#e5e7eb",strokeWidth:"3"}),(0,i.jsx)("path",{d:"M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z",fill:"#4A49FF"})]}),e==="success"&&(0,i.jsx)("div",{style:{animation:"flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)"},children:(0,i.jsxs)("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,i.jsx)("circle",{cx:"12",cy:"12",r:"11",fill:"#22c55e"}),(0,i.jsx)("path",{d:"M7 12.5l3 3 7-7",stroke:"white",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",style:{strokeDasharray:20,strokeDashoffset:20,animation:"flopay-draw 0.4s 0.15s ease forwards"}})]})}),e==="error"&&(0,i.jsx)("div",{style:{animation:"flopay-shake 0.4s ease"},children:(0,i.jsxs)("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,i.jsx)("circle",{cx:"12",cy:"12",r:"11",fill:"#ef4444"}),(0,i.jsx)("path",{d:"M8 8l8 8M16 8l-8 8",stroke:"white",strokeWidth:"2.5",strokeLinecap:"round",style:{strokeDasharray:12,strokeDashoffset:12,animation:"flopay-draw 0.3s 0.1s ease forwards"}})]})})]}),(0,i.jsxs)("span",{style:{fontSize:14,fontWeight:600,letterSpacing:"0.05em",color:e==="success"?"#16a34a":e==="error"?"#dc2626":"#374151"},children:[e==="processing"&&n,e==="success"&&(r??(o?"PAYMENT AUTHORISED":"PAYMENT SUCCESSFUL")),e==="error"&&m]}),e==="success"&&u!==null&&(0,i.jsx)("p",{style:{fontSize:13,color:"#6b7280",fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0},children:u}),e==="error"&&t&&(0,i.jsx)("p",{style:{fontSize:13,color:"#6b7280",fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0},children:t}),(0,i.jsx)("style",{children:`
|
|
2
2
|
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
3
3
|
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
4
4
|
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
5
5
|
@keyframes flopay-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
|
|
6
|
-
`})]})})}function
|
|
6
|
+
`})]})})}var S=require("react"),Q=require("react/jsx-runtime");function K({capture:e,html:t,messageToken:o,expectedOrigin:n,theme:r,containerStyle:m,onReady:u,onError:y,onValidation:g}){let C=(0,S.useRef)(null),x=(0,S.useRef)(u),w=(0,S.useRef)(y),k=(0,S.useRef)(g);x.current=u,w.current=y,k.current=g;let d=(0,S.useRef)(r);return d.current=r,(0,S.useEffect)(()=>{let F=C.current;if(!F)return;let v=!0,A=!1,V=()=>{!v||A||(A=!0,x.current?.())},L=e.on("ready",()=>{V()}),O=e.on("error",p=>{w.current?.(p.message??"There was a problem loading the secure card form.")}),h=e.on("validation",p=>{k.current?.(p.message??null)}),B={html:t,...o?{messageToken:o}:{},...n?{expectedOrigin:n}:{},...d.current?{theme:d.current}:{}};return e.mount(F,B).then(()=>{V()}).catch(p=>{v&&w.current?.(p instanceof Error?p.message:"Failed to load the secure card form.")}),()=>{v=!1,L(),O(),h(),e.unmount()}},[e,t,o,n]),(0,S.useEffect)(()=>{r&&e.applyTheme?.(r)},[e,r]),(0,Q.jsx)("div",{ref:C,"data-testid":"flopay-vault-card-fields",style:m})}function ue(e,t=.12){let o=/^#?([0-9a-fA-F]{6})$/.exec(e.trim());if(!o)return e;let n=parseInt(o[1],16),r=Math.max(0,Math.min(1,1-t)),m=Math.round((n>>16&255)*r),u=Math.round((n>>8&255)*r),y=Math.round((n&255)*r);return`#${(1<<24|m<<16|u<<8|y).toString(16).slice(1)}`}function de(e){if(typeof e=="number"||typeof e=="string")return e}function Z({appearance:e,buttonsStyles:t,layout:o="default"}){let n=e?.variables,r=C=>typeof C=="string"&&C?C:void 0,m=t.submitButton,u=r(n?.colorPrimary)??r(m?.backgroundColor)??"#4A49FF",y=o==="buttons",g=t.nameInput;return{primaryColor:u,primaryHoverColor:r(n?.colorPrimaryHover)??ue(u,.12),inputBackgroundColor:r(t.cardInputBackground)??r(n?.colorBackground)??"#ffffff",textColor:r(t.cardInputColor)??r(g?.color)??r(n?.colorText)??"#262833",borderColor:r(t.cardInputBorder)??(y?"#e5e7eb":"#A4A4FF"),placeholderColor:r(t.cardInputPlaceholderColor)??"#9ca3af",errorColor:r(n?.colorDanger)??"#dc2626",successColor:"#16a34a",fontFamily:r(g?.fontFamily)??r(n?.fontFamily)??"Poppins, sans-serif",fontSize:r(t.cardInputFontSize)??r(n?.fontSizeBase)??"16px",fontWeight:String(de(g?.fontWeight)??400),borderRadius:r(n?.borderRadius)??"8px"}}var f=require("react/jsx-runtime"),D=class extends c.FloPayError{constructor(t,o,n){super(t,o,n),this.name="FloPayCardSetupError",this.retryable=n.retryable}};function re(e,t={}){let o=e instanceof c.FloPayError?e:void 0,n=o?.statusCode,r=t.retryable??(o?.type==="network_error"||o?.type==="rate_limit_error"||typeof n=="number"&&n>=500||o?.code==="vault_capture_timeout"||!o);return new D(o?.message??(e instanceof Error?e.message:"Failed to load the secure card form."),o?.type??"api_error",{code:t.code??o?.code??"card_setup_load_failed",retryable:r,...o?.param?{param:o.param}:{},...n!==void 0?{statusCode:n}:{}})}function te({sessionId:e,nonce:t,billingApiUrl:o,telemetry:n,theme:r="modern-light",containerStyle:m,loading:u=null,onReady:y,onComplete:g,onDecline:C,onCancel:x,onValidation:w,onError:k}){let[d,F]=(0,a.useState)(null),[v,A]=(0,a.useState)(null),[V,L]=(0,a.useState)(null),[O,h]=(0,a.useState)(null),[B,p]=(0,a.useState)(null),P=(0,a.useRef)(!1),N=(0,a.useRef)(!1),oe=(0,a.useMemo)(()=>{if(typeof r=="object")return r;let s=(0,c.resolveTheme)(r);if(s)return Z({appearance:s.appearance,buttonsStyles:s.buttonsLayout,layout:"default"})},[r]),G=(0,a.useRef)(y),W=(0,a.useRef)(k),q=(0,a.useRef)(g),X=(0,a.useRef)(C),$=(0,a.useRef)(x),j=(0,a.useRef)(w),_=(0,a.useRef)(!1),Y=(0,a.useRef)(!1),z=(0,a.useRef)(0);return G.current=y,W.current=k,q.current=g,X.current=C,$.current=x,j.current=w,(0,a.useEffect)(()=>{let s=z.current+1;return z.current=s,()=>{queueMicrotask(()=>{z.current===s&&(_.current||Y.current||(Y.current=!0,R(()=>{$.current?.({status:"cancelled",sessionId:e})})))})}},[e]),(0,a.useEffect)(()=>{let s=!0,b=new I.PaymentAPI((0,c.resolveBillingApiUrl)(o),{telemetry:n});return F(null),A(null),L(null),_.current=!1,Y.current=!1,(async()=>{try{if(!e.trim())throw new c.FloPayError("FloPayCardSetup requires a sessionId.","validation_error",{code:"MissingCheckoutSessionId",param:"sessionId"});if(!t.trim())throw new c.FloPayError("FloPayCardSetup requires a session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let M=await b.getUnifiedCheckoutSession(e,t);if(!s)return;let E=M.data.session;if(!E||!(0,c.isCardSetupCheckoutSession)(E))throw new c.FloPayError("FloPayCardSetup only accepts a zero-amount, productless setup session.","validation_error",{code:"InvalidCardSetupSession",param:"sessionId"});let l=E.vault;if(l?.html?.trim()||(l=await b.getVaultCapture(e,t)),!l.html?.trim())throw new c.FloPayError("FloPay: this setup session has no vault card capability. Upgrade the billing backend integration.","api_error",{code:"UnsupportedBackendVaultCapability"});if(!s)return;A(l),F(new I.PciVaultCardCapture({sessionId:e,operation:"card_setup",telemetry:n}))}catch(M){if(!s)return;let E=re(M);_.current=!0,L(E),R(()=>W.current?.(E))}})(),()=>{s=!1,b.destroy()}},[o,t,e,n]),(0,a.useEffect)(()=>{if(!d)return;let s=!1;N.current=!1,P.current=!1;let b=d.on("submitting",()=>{P.current=!0,p(null),h("processing")}),M=d.on("complete",l=>{_.current=!0,P.current=!1,h("success"),(async()=>(await new Promise(U=>setTimeout(U,1200)),!N.current&&(N.current=!0,R(()=>{q.current?.({status:"succeeded",sessionId:e,...l.paymentMethod?{paymentMethod:l.paymentMethod}:{}})}),s||h(null))))()}),E=d.on("decline",l=>{_.current=!0,P.current=!1,p(l.message??null),h("error"),R(()=>{X.current?.({status:"declined",sessionId:e,...l.declineReason?{reason:l.declineReason}:{},...l.message?{message:l.message}:{}})}),(async()=>(await new Promise(U=>setTimeout(U,1500)),s||h(null)))()});return()=>{s=!0,b(),M(),E()}},[d,e]),V?(0,f.jsx)("div",{role:"alert",children:V.message}):!d||!v?.html?(0,f.jsx)(f.Fragment,{children:u}):(0,f.jsxs)(f.Fragment,{children:[O&&(0,f.jsx)(J,{status:O,errorMessage:B,processingLabel:"SAVING CARD...",successLabel:"CARD SAVED",errorLabel:"CARD NOT SAVED",successNote:null}),(0,f.jsx)(K,{capture:d,html:v.html,messageToken:v.messageToken,expectedOrigin:v.expectedOrigin,theme:oe,containerStyle:m,onReady:()=>{R(()=>G.current?.())},onValidation:s=>{R(()=>j.current?.(s))},onError:s=>{if(!s)return;P.current&&(P.current=!1,p(s),h("error"),setTimeout(()=>h(null),1500));let b=re(new Error(s),{code:"card_setup_widget_failed",retryable:!0});R(()=>W.current?.(b))}})]})}0&&(module.exports={FloPayCardSetup,FloPayCardSetupError});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { ThemeId, VaultCardThemeColors, SavedCardDisplay, FloPayError, FloPayErrorType } from '@flopay/shared';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
4
|
/** Verified terminal result from a no-charge card setup. */
|
|
5
5
|
interface FloPayCardSetupCompleteEvent {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { ThemeId, VaultCardThemeColors, SavedCardDisplay, FloPayError, FloPayErrorType } from '@flopay/shared';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
4
|
/** Verified terminal result from a no-charge card setup. */
|
|
5
5
|
interface FloPayCardSetupCompleteEvent {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{g as e,h as t}from"./chunk-VWT2TDA6.mjs";export{t as FloPayCardSetup,e as FloPayCardSetupError};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{useEffect as Q,useRef as M}from"react";import{jsx as se}from"react/jsx-runtime";function Z({capture:e,html:n,messageToken:t,expectedOrigin:o,theme:r,containerStyle:f,onReady:i,onError:p,onValidation:m}){let y=M(null),k=M(i),R=M(p),x=M(m);k.current=i,R.current=p,x.current=m;let c=M(r);return c.current=r,Q(()=>{let P=y.current;if(!P)return;let h=!0,F=!1,A=()=>{!h||F||(F=!0,k.current?.())},L=e.on("ready",()=>{A()}),D=e.on("error",d=>{R.current?.(d.message??"There was a problem loading the secure card form.")}),g=e.on("validation",d=>{x.current?.(d.message??null)}),N={html:n,...t?{messageToken:t}:{},...o?{expectedOrigin:o}:{},...c.current?{theme:c.current}:{}};return e.mount(P,N).then(()=>{A()}).catch(d=>{h&&R.current?.(d instanceof Error?d.message:"Failed to load the secure card form.")}),()=>{h=!1,L(),D(),g(),e.unmount()}},[e,n,t,o]),Q(()=>{r&&e.applyTheme?.(r)},[e,r]),se("div",{ref:y,"data-testid":"flopay-vault-card-fields",style:f})}import{PaymentAPI as ue,PciVaultCardCapture as de}from"@flopay/js/card-setup";import{FloPayError as E,isCardSetupCheckoutSession as fe,resolveBillingApiUrl as pe,resolveTheme as me}from"@flopay/shared";import{useEffect as G,useMemo as ye,useRef as u,useState as T}from"react";function S(e){if(!e)return;let n=t=>{console.error("[FloPay] Merchant callback failed; checkout continued.",t)};try{Promise.resolve(e()).catch(n)}catch(t){n(t)}}import{jsx as l,jsxs as w}from"react/jsx-runtime";function ee({status:e,errorMessage:n,authorized:t=!1,processingLabel:o="PROCESSING...",successLabel:r,errorLabel:f="PAYMENT FAILED",successNote:i="You will be automatically redirected, do not close or navigate away from this window."}){return l("div",{"data-testid":"flopay-processing-overlay","data-status":e,role:"dialog","aria-modal":"true",style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.35)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e3,backdropFilter:"blur(2px)"},children:w("div",{style:{background:"white",borderRadius:12,padding:"2rem 2.5rem",textAlign:"center",boxShadow:"0 8px 32px rgba(0,0,0,0.18)",minWidth:240,display:"flex",flexDirection:"column",alignItems:"center",gap:16},children:[w("div",{style:{width:48,height:48,position:"relative"},children:[e==="processing"&&w("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",style:{animation:"flopay-spin 0.8s linear infinite"},children:[l("circle",{cx:"12",cy:"12",r:"10",stroke:"#e5e7eb",strokeWidth:"3"}),l("path",{d:"M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z",fill:"#4A49FF"})]}),e==="success"&&l("div",{style:{animation:"flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)"},children:w("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[l("circle",{cx:"12",cy:"12",r:"11",fill:"#22c55e"}),l("path",{d:"M7 12.5l3 3 7-7",stroke:"white",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",style:{strokeDasharray:20,strokeDashoffset:20,animation:"flopay-draw 0.4s 0.15s ease forwards"}})]})}),e==="error"&&l("div",{style:{animation:"flopay-shake 0.4s ease"},children:w("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[l("circle",{cx:"12",cy:"12",r:"11",fill:"#ef4444"}),l("path",{d:"M8 8l8 8M16 8l-8 8",stroke:"white",strokeWidth:"2.5",strokeLinecap:"round",style:{strokeDasharray:12,strokeDashoffset:12,animation:"flopay-draw 0.3s 0.1s ease forwards"}})]})})]}),w("span",{style:{fontSize:14,fontWeight:600,letterSpacing:"0.05em",color:e==="success"?"#16a34a":e==="error"?"#dc2626":"#374151"},children:[e==="processing"&&o,e==="success"&&(r??(t?"PAYMENT AUTHORISED":"PAYMENT SUCCESSFUL")),e==="error"&&f]}),e==="success"&&i!==null&&l("p",{style:{fontSize:13,color:"#6b7280",fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0},children:i}),e==="error"&&n&&l("p",{style:{fontSize:13,color:"#6b7280",fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0},children:n}),l("style",{children:`
|
|
2
|
+
@keyframes flopay-spin { to { transform: rotate(360deg); } }
|
|
3
|
+
@keyframes flopay-pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
|
|
4
|
+
@keyframes flopay-draw { to { stroke-dashoffset: 0; } }
|
|
5
|
+
@keyframes flopay-shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-4px); } 40%,80% { transform: translateX(4px); } }
|
|
6
|
+
`})]})})}function ie(e,n=.12){let t=/^#?([0-9a-fA-F]{6})$/.exec(e.trim());if(!t)return e;let o=parseInt(t[1],16),r=Math.max(0,Math.min(1,1-n)),f=Math.round((o>>16&255)*r),i=Math.round((o>>8&255)*r),p=Math.round((o&255)*r);return`#${(1<<24|f<<16|i<<8|p).toString(16).slice(1)}`}function le(e){if(typeof e=="number"||typeof e=="string")return e}function re({appearance:e,buttonsStyles:n,layout:t="default"}){let o=e?.variables,r=y=>typeof y=="string"&&y?y:void 0,f=n.submitButton,i=r(o?.colorPrimary)??r(f?.backgroundColor)??"#4A49FF",p=t==="buttons",m=n.nameInput;return{primaryColor:i,primaryHoverColor:r(o?.colorPrimaryHover)??ie(i,.12),inputBackgroundColor:r(n.cardInputBackground)??r(o?.colorBackground)??"#ffffff",textColor:r(n.cardInputColor)??r(m?.color)??r(o?.colorText)??"#262833",borderColor:r(n.cardInputBorder)??(p?"#e5e7eb":"#A4A4FF"),placeholderColor:r(n.cardInputPlaceholderColor)??"#9ca3af",errorColor:r(o?.colorDanger)??"#dc2626",successColor:"#16a34a",fontFamily:r(m?.fontFamily)??r(o?.fontFamily)??"Poppins, sans-serif",fontSize:r(n.cardInputFontSize)??r(o?.fontSizeBase)??"16px",fontWeight:String(le(m?.fontWeight)??400),borderRadius:r(o?.borderRadius)??"8px"}}import{Fragment as ne,jsx as B,jsxs as ge}from"react/jsx-runtime";var q=class extends E{constructor(n,t,o){super(n,t,o),this.name="FloPayCardSetupError",this.retryable=o.retryable}};function oe(e,n={}){let t=e instanceof E?e:void 0,o=t?.statusCode,r=n.retryable??(t?.type==="network_error"||t?.type==="rate_limit_error"||typeof o=="number"&&o>=500||t?.code==="vault_capture_timeout"||!t);return new q(t?.message??(e instanceof Error?e.message:"Failed to load the secure card form."),t?.type??"api_error",{code:n.code??t?.code??"card_setup_load_failed",retryable:r,...t?.param?{param:t.param}:{},...o!==void 0?{statusCode:o}:{}})}function De({sessionId:e,nonce:n,billingApiUrl:t,telemetry:o,theme:r="modern-light",containerStyle:f,loading:i=null,onReady:p,onComplete:m,onDecline:y,onCancel:k,onValidation:R,onError:x}){let[c,P]=T(null),[h,F]=T(null),[A,L]=T(null),[D,g]=T(null),[N,d]=T(null),b=u(!1),W=u(!1),ae=ye(()=>{if(typeof r=="object")return r;let a=me(r);if(a)return re({appearance:a.appearance,buttonsStyles:a.buttonsLayout,layout:"default"})},[r]),X=u(p),Y=u(x),$=u(m),j=u(y),J=u(k),K=u(R),V=u(!1),z=u(!1),U=u(0);return X.current=p,Y.current=x,$.current=m,j.current=y,J.current=k,K.current=R,G(()=>{let a=U.current+1;return U.current=a,()=>{queueMicrotask(()=>{U.current===a&&(V.current||z.current||(z.current=!0,S(()=>{J.current?.({status:"cancelled",sessionId:e})})))})}},[e]),G(()=>{let a=!0,v=new ue(pe(t),{telemetry:o});return P(null),F(null),L(null),V.current=!1,z.current=!1,(async()=>{try{if(!e.trim())throw new E("FloPayCardSetup requires a sessionId.","validation_error",{code:"MissingCheckoutSessionId",param:"sessionId"});if(!n.trim())throw new E("FloPayCardSetup requires a session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let _=await v.getUnifiedCheckoutSession(e,n);if(!a)return;let C=_.data.session;if(!C||!fe(C))throw new E("FloPayCardSetup only accepts a zero-amount, productless setup session.","validation_error",{code:"InvalidCardSetupSession",param:"sessionId"});let s=C.vault;if(s?.html?.trim()||(s=await v.getVaultCapture(e,n)),!s.html?.trim())throw new E("FloPay: this setup session has no vault card capability. Upgrade the billing backend integration.","api_error",{code:"UnsupportedBackendVaultCapability"});if(!a)return;F(s),P(new de({sessionId:e,operation:"card_setup",telemetry:o}))}catch(_){if(!a)return;let C=oe(_);V.current=!0,L(C),S(()=>Y.current?.(C))}})(),()=>{a=!1,v.destroy()}},[t,n,e,o]),G(()=>{if(!c)return;let a=!1;W.current=!1,b.current=!1;let v=c.on("submitting",()=>{b.current=!0,d(null),g("processing")}),_=c.on("complete",s=>{V.current=!0,b.current=!1,g("success"),(async()=>(await new Promise(H=>setTimeout(H,1200)),!W.current&&(W.current=!0,S(()=>{$.current?.({status:"succeeded",sessionId:e,...s.paymentMethod?{paymentMethod:s.paymentMethod}:{}})}),a||g(null))))()}),C=c.on("decline",s=>{V.current=!0,b.current=!1,d(s.message??null),g("error"),S(()=>{j.current?.({status:"declined",sessionId:e,...s.declineReason?{reason:s.declineReason}:{},...s.message?{message:s.message}:{}})}),(async()=>(await new Promise(H=>setTimeout(H,1500)),a||g(null)))()});return()=>{a=!0,v(),_(),C()}},[c,e]),A?B("div",{role:"alert",children:A.message}):!c||!h?.html?B(ne,{children:i}):ge(ne,{children:[D&&B(ee,{status:D,errorMessage:N,processingLabel:"SAVING CARD...",successLabel:"CARD SAVED",errorLabel:"CARD NOT SAVED",successNote:null}),B(Z,{capture:c,html:h.html,messageToken:h.messageToken,expectedOrigin:h.expectedOrigin,theme:ae,containerStyle:f,onReady:()=>{S(()=>X.current?.())},onValidation:a=>{S(()=>K.current?.(a))},onError:a=>{if(!a)return;b.current&&(b.current=!1,d(a),g("error"),setTimeout(()=>g(null),1500));let v=oe(new Error(a),{code:"card_setup_widget_failed",retryable:!0});S(()=>Y.current?.(v))}})]})}export{S as a,ee as b,Z as c,ie as d,le as e,re as f,q as g,De as h};
|