@flopay/react 1.9.5 → 1.9.6

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 CHANGED
@@ -184,6 +184,67 @@ form from the buyer's submit ("SAVING CARD...") and flips to "CARD SAVED"
184
184
  (held briefly before `onComplete`) or "CARD NOT SAVED" with the decline
185
185
  message (cleared automatically so the buyer can retry in place).
186
186
 
187
+ #### Card-setup theming
188
+
189
+ `theme` accepts the same `ThemeId` as `FloPayCheckout` (default
190
+ `'modern-light'`) or raw `VaultCardThemeColors`. A named preset styles the
191
+ whole card-setup experience coherently:
192
+
193
+ - **Surface** — the container around the hosted form wears the preset's
194
+ complete credit-card pane treatment (`cardFormContainer`: background or
195
+ gradient, border, radius, shadow, padding), so `modern-dark` never places
196
+ dark hosted fields on a light, unthemed box.
197
+ - **Hosted form** — the widget receives the preset's field colors and
198
+ typography plus the complete hosted submit snapshot
199
+ (`VaultCardThemeColors.submitButton`, billing API v1.9.6+): label color,
200
+ solid or gradient enabled/hover/disabled fills, typography, spacing, shadow,
201
+ radius, disabled opacity, and blur. The legacy flat keys are always sent
202
+ alongside it, so an older hosted asset keeps its solid approximation during a
203
+ rolling deployment, and an older SDK against a newer asset keeps its
204
+ historical flat-only behavior. `modern-dark`'s dark label stays at or above
205
+ 4.5:1 in the enabled, hover, and disabled states, disabled compositing
206
+ included.
207
+ - **Processing / success / error** — the overlay reuses the pane surface and
208
+ typography; processing wears the preset primary on its spinner, while success
209
+ and error keep semantic green/red accents chosen per color scheme so they
210
+ stay legible on every pane.
211
+
212
+ `'classic'` keeps the historical card-setup appearance exactly: no derived
213
+ surface, the neutral overlay, and no theme directive sent to a freshly mounted
214
+ hosted form. Raw `VaultCardThemeColors` objects — including partial ones — are
215
+ forwarded to the hosted form unchanged and add no surface or overlay treatment.
216
+
217
+ Changing `theme` at runtime updates the SDK-owned surface and overlay in place
218
+ and re-skins the mounted hosted form without remounting it, so entered card
219
+ details, focus, and caret are preserved. Switching back to `'classic'` sends
220
+ the hosted form's explicit reset (`theme: null`) so nothing from the previous
221
+ preset lingers.
222
+
223
+ ##### `containerStyle` precedence
224
+
225
+ `containerStyle` is merged over the preset surface with deterministic rules:
226
+
227
+ 1. Each `containerStyle` property wins over the preset value for the same
228
+ property.
229
+ 2. Declarations are applied preset-first, then `containerStyle` in your own key
230
+ order, so a longhand refines a preset shorthand of the same family the way
231
+ CSS cascades: `borderColor: 'red'` recolors the preset border and keeps its
232
+ width and style; `paddingTop: 0` adjusts one side.
233
+ 3. Background is the exception: any `background*` member in `containerStyle`
234
+ replaces the preset's background treatment entirely, so a color never shows
235
+ a glass preset's gradient through it.
236
+ 4. With `'classic'` or a raw theme there is no preset surface: `containerStyle`
237
+ applies alone, exactly as before.
238
+
239
+ ```tsx
240
+ <FloPayCardSetup
241
+ sessionId={sessionId}
242
+ nonce={nonce}
243
+ theme="glass-dark"
244
+ containerStyle={{ borderColor: '#60A5FA', padding: 16 }} // refines the glass-dark pane
245
+ />
246
+ ```
247
+
187
248
  Saved-card listing, setup-session creation, and deletion remain authenticated
188
249
  merchant REST calls. Replacement is composition: complete setup for the new
189
250
  card, then ask your server to delete the old card. `FloPayCardSetup` deliberately
@@ -371,7 +432,7 @@ legacy props will be removed in `2.0`.
371
432
 
372
433
  #### Theming
373
434
 
374
- `FloPayCheckout`, `FloPayAutomaticPaymentButton`, `SplitCardForm`, and `FloPayCardSetup` accept a single `theme` prop that maps to a coherent `{appearance, buttonsLayout}` bundle in `@flopay/shared`'s `THEMES` map. (`FloPayCardSetup` styles only the hosted vault widget — there are no surrounding Stripe Elements on that surface — and unlike the checkout components it defaults to `'modern-light'` rather than `'classic'`.) One value styles non-card Stripe Elements, the React-rendered wrapper and AVS inputs, the hosted vault widget, and — for `FloPayAutomaticPaymentButton` — the fallback modal that opens when a saved-payment charge can't complete silently.
435
+ `FloPayCheckout`, `FloPayAutomaticPaymentButton`, `SplitCardForm`, and `FloPayCardSetup` accept a single `theme` prop that maps to a coherent `{appearance, buttonsLayout}` bundle in `@flopay/shared`'s `THEMES` map. (`FloPayCardSetup` has no surrounding Stripe Elements: the preset styles its container surface, the hosted vault widget, and its outcome overlay — see [Card-setup theming](#card-setup-theming) — and unlike the checkout components it defaults to `'modern-light'` rather than `'classic'`.) One value styles non-card Stripe Elements, the React-rendered wrapper and AVS inputs, the hosted vault widget, and — for `FloPayAutomaticPaymentButton` — the fallback modal that opens when a saved-payment charge can't complete silently.
375
436
 
376
437
  | `theme` | Aesthetic |
377
438
  |---|---|
@@ -931,8 +992,8 @@ function PaymentStatus() {
931
992
  | `nonce` | `string` | Required session-bound read/capture token. |
932
993
  | `billingApiUrl` | `string?` | Billing API base URL; defaults through normal FloPay environment resolution. |
933
994
  | `telemetry` | `boolean?` | Privacy-safe operational telemetry; set `false` to opt out. |
934
- | `theme` | `ThemeId \| VaultCardThemeColors?` | High-level theme id (same values as `FloPayCheckout`, resolved through the same bundle) or raw hosted-widget colors. Defaults to `'modern-light'`; `'classic'` keeps the historic FloPay look. |
935
- | `containerStyle` | `React.CSSProperties?` | Inline styles for the hosted-widget container. |
995
+ | `theme` | `ThemeId \| VaultCardThemeColors?` | High-level theme id (same values as `FloPayCheckout`, resolved through the same bundle) or raw hosted-widget colors. A preset styles the surrounding surface, the hosted form (complete submit snapshot included), and the outcome overlay coherently; see [Card-setup theming](#card-setup-theming). Defaults to `'modern-light'`; `'classic'` keeps the historic FloPay look and raw objects are forwarded unchanged. |
996
+ | `containerStyle` | `React.CSSProperties?` | Inline styles for the hosted-widget container, merged over a preset's surface with deterministic precedence: each property wins over the preset's, a longhand refines a preset shorthand, any `background*` member replaces the preset background, and `'classic'` / raw themes apply it alone. |
936
997
  | `loading` | `React.ReactNode?` | Content shown while the session and hosted widget load. |
937
998
  | `onReady` | `() => void` | Hosted widget is mounted and accepting input. |
938
999
  | `onComplete` | `(event: FloPayCardSetupCompleteEvent) => void` | Verified usable card. Includes `sessionId` and optional display-only `paymentMethod`; never amount, charge, or payment-success data. |
@@ -1,6 +1,6 @@
1
- "use strict";var U=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var se=(e,t)=>{for(var o in t)U(e,o,{get:t[o],enumerable:!0})},ie=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ne(t))!ae.call(e,r)&&r!==o&&U(e,r,{get:()=>t[r],enumerable:!(n=oe(t,r))||n.enumerable});return e};var le=e=>ie(U({},"__esModule",{value:!0}),e);var fe={};se(fe,{FloPayCardSetup:()=>re,FloPayCardSetupError:()=>M});module.exports=le(fe);var D=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");var ce={processing:"#374151",success:"#16a34a",error:"#dc2626"};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",{"aria-hidden":"true",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",{"aria-hidden":"true",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",{"aria-hidden":"true",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:ce[e]},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:`
1
+ "use strict";var q=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var Fe=(e,r)=>{for(var t in r)q(e,t,{get:r[t],enumerable:!0})},Ee=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Re(r))!ve.call(e,o)&&o!==t&&q(e,o,{get:()=>r[o],enumerable:!(n=xe(r,o))||n.enumerable});return e};var Pe=e=>Ee(q({},"__esModule",{value:!0}),e);var Ze={};Fe(Ze,{FloPayCardSetup:()=>Se,FloPayCardSetupError:()=>N});module.exports=Pe(Ze);var $=require("@flopay/js/card-setup"),b=require("@flopay/shared"),u=require("react");function te(e,r){if(!e)return r;let t=r??{},n=Object.keys(t),o=n.some(i=>i.startsWith("background")),a={};for(let[i,l]of Object.entries(e))i in t||o&&i.startsWith("background")||(a[i]=l);for(let i of n)a[i]=t[i];return a}var Te=new Set(["animationIterationCount","aspectRatio","borderImageOutset","borderImageSlice","borderImageWidth","boxFlex","boxFlexGroup","boxOrdinalGroup","columnCount","columns","flex","flexGrow","flexPositive","flexShrink","flexNegative","flexOrder","gridArea","gridRow","gridRowEnd","gridRowSpan","gridRowStart","gridColumn","gridColumnEnd","gridColumnSpan","gridColumnStart","fontWeight","lineClamp","lineHeight","opacity","order","orphans","scale","tabSize","widows","zIndex","zoom","fillOpacity","floodOpacity","stopOpacity","strokeDasharray","strokeDashoffset","strokeMiterlimit","strokeOpacity","strokeWidth"]);function Ve(e){let r=e.replace(/^(Webkit|Moz|ms)(?=[A-Z])/,"");return Te.has(r.charAt(0).toLowerCase()+r.slice(1))}function Ae(e,r){return typeof r=="number"&&r!==0&&!Ve(e)?`${r}px`:String(r).trim()}function ne(e,r){if(e.style.cssText="",!!r){for(let[t,n]of Object.entries(r))if(!(n==null||n==="")){if(t.startsWith("--")){e.style.setProperty(t,String(n));continue}e.style[t]=Ae(t,n)}}}var oe={light:{success:"#166534",error:"#991B1B"},dark:{success:"#4ADE80",error:"#FCA5A5"}};function ae(e){let r=e.appearance.variables??{},t=e.buttonsLayout.cardFormContainer??{},n=e.appearance.theme==="night",o=n?oe.dark:oe.light,a=r.colorText??(n?"#F1F5F9":"#262833"),i=e.appearance.rules?.[".Label"];return{panel:{...t.background===void 0?{}:{background:t.background},...t.backgroundColor===void 0?{}:{backgroundColor:t.backgroundColor},...t.border===void 0?{}:{border:t.border},...t.borderRadius===void 0?{}:{borderRadius:t.borderRadius},...t.boxShadow===void 0?{}:{boxShadow:t.boxShadow},color:a,...r.fontFamily?{fontFamily:r.fontFamily}:{}},spinnerTrackColor:e.buttonsLayout.cardInputBorder??(n?"#374151":"#e5e7eb"),spinnerAccentColor:r.colorPrimary??"#4A49FF",labelColors:{processing:a,success:o.success,error:o.error},noteColor:i?.color??a}}function F(e){if(!e)return;let r=t=>{console.error("[FloPay] Merchant callback failed; checkout continued.",t)};try{Promise.resolve(e()).catch(r)}catch(t){r(t)}}var f=require("react/jsx-runtime");var Le={panel:{background:"white"},spinnerTrackColor:"#e5e7eb",spinnerAccentColor:"#4A49FF",labelColors:{processing:"#374151",success:"#16a34a",error:"#dc2626"},noteColor:"#6b7280"};function ie({status:e,errorMessage:r,authorized:t=!1,processingLabel:n="PROCESSING...",successLabel:o,errorLabel:a="PAYMENT FAILED",successNote:i="You will be automatically redirected, do not close or navigate away from this window.",theme:l=Le}){let s={fontSize:13,color:l.noteColor,fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0};return(0,f.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,f.jsxs)("div",{"data-testid":"flopay-processing-overlay-panel",style:{borderRadius:12,boxShadow:"0 8px 32px rgba(0,0,0,0.18)",...l.panel,padding:"2rem 2.5rem",textAlign:"center",minWidth:240,display:"flex",flexDirection:"column",alignItems:"center",gap:16},children:[(0,f.jsxs)("div",{style:{width:48,height:48,position:"relative"},children:[e==="processing"&&(0,f.jsxs)("svg",{"aria-hidden":"true",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,f.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:l.spinnerTrackColor,strokeWidth:"3"}),(0,f.jsx)("path",{d:"M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z",fill:l.spinnerAccentColor})]}),e==="success"&&(0,f.jsx)("div",{style:{animation:"flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)"},children:(0,f.jsxs)("svg",{"aria-hidden":"true",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,f.jsx)("circle",{cx:"12",cy:"12",r:"11",fill:"#22c55e"}),(0,f.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,f.jsx)("div",{style:{animation:"flopay-shake 0.4s ease"},children:(0,f.jsxs)("svg",{"aria-hidden":"true",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,f.jsx)("circle",{cx:"12",cy:"12",r:"11",fill:"#ef4444"}),(0,f.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,f.jsxs)("span",{style:{fontSize:14,fontWeight:600,letterSpacing:"0.05em",color:l.labelColors[e]},children:[e==="processing"&&n,e==="success"&&(o??(t?"PAYMENT AUTHORISED":"PAYMENT SUCCESSFUL")),e==="error"&&a]}),e==="success"&&i!==null&&(0,f.jsx)("p",{style:s,children:i}),e==="error"&&r&&(0,f.jsx)("p",{style:s,children:r}),(0,f.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
- `})]})})}var S=require("react"),K=require("react/jsx-runtime");function J({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||A||(A=!0,x.current?.())},L=e.on("ready",()=>{_()}),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)}),I={html:t,...o?{messageToken:o}:{},...n?{expectedOrigin:n}:{},...d.current?{theme:d.current}:{}};return e.mount(F,I).then(()=>{_()}).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,K.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=Number.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 Q({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"),M=class extends c.FloPayError{constructor(t,o,n){super(t,o,n),this.name="FloPayCardSetupError",this.retryable=n.retryable}};function ee(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 M(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 re({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),[_,L]=(0,a.useState)(null),[O,h]=(0,a.useState)(null),[I,p]=(0,a.useState)(null),P=(0,a.useRef)(!1),B=(0,a.useRef)(!1),te=(0,a.useMemo)(()=>{if(typeof r=="object")return r;let s=(0,c.resolveTheme)(r);if(s)return Q({appearance:s.appearance,buttonsStyles:s.buttonsLayout,layout:"default"})},[r]),H=(0,a.useRef)(y),N=(0,a.useRef)(k),G=(0,a.useRef)(g),q=(0,a.useRef)(C),X=(0,a.useRef)(x),$=(0,a.useRef)(w),T=(0,a.useRef)(!1),W=(0,a.useRef)(!1),Y=(0,a.useRef)(0);return H.current=y,N.current=k,G.current=g,q.current=C,X.current=x,$.current=w,(0,a.useEffect)(()=>{let s=Y.current+1;return Y.current=s,()=>{queueMicrotask(()=>{Y.current===s&&(T.current||W.current||(W.current=!0,R(()=>{X.current?.({status:"cancelled",sessionId:e})})))})}},[e]),(0,a.useEffect)(()=>{let s=!0,b=new D.PaymentAPI((0,c.resolveBillingApiUrl)(o),{telemetry:n});return F(null),A(null),L(null),T.current=!1,W.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 V=await b.getUnifiedCheckoutSession(e,t);if(!s)return;let E=V.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 D.PciVaultCardCapture({sessionId:e,operation:"card_setup",telemetry:n}))}catch(V){if(!s)return;let E=ee(V);T.current=!0,L(E),R(()=>N.current?.(E))}})(),()=>{s=!1,b.destroy()}},[o,t,e,n]),(0,a.useEffect)(()=>{if(!d)return;let s=!1;B.current=!1,P.current=!1;let b=d.on("submitting",()=>{P.current=!0,p(null),h("processing")}),V=d.on("complete",l=>{T.current=!0,P.current=!1,h("success"),(async()=>(await new Promise(z=>setTimeout(z,1200)),!B.current&&(B.current=!0,R(()=>{G.current?.({status:"succeeded",sessionId:e,...l.paymentMethod?{paymentMethod:l.paymentMethod}:{}})}),s||h(null))))()}),E=d.on("decline",l=>{T.current=!0,P.current=!1,p(l.message??null),h("error"),R(()=>{q.current?.({status:"declined",sessionId:e,...l.declineReason?{reason:l.declineReason}:{},...l.message?{message:l.message}:{}})}),(async()=>(await new Promise(z=>setTimeout(z,1500)),s||h(null)))()});return()=>{s=!0,b(),V(),E()}},[d,e]),_?(0,f.jsx)("div",{role:"alert",children:_.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:I,processingLabel:"SAVING CARD...",successLabel:"CARD SAVED",errorLabel:"CARD NOT SAVED",successNote:null}),(0,f.jsx)(J,{capture:d,html:v.html,messageToken:v.messageToken,expectedOrigin:v.expectedOrigin,theme:te,containerStyle:m,onReady:()=>{R(()=>H.current?.())},onValidation:s=>{R(()=>$.current?.(s))},onError:s=>{if(!s)return;P.current&&(P.current=!1,p(s),h("error"),setTimeout(()=>h(null),1500));let b=ee(new Error(s),{code:"card_setup_widget_failed",retryable:!0});R(()=>N.current?.(b))}})]})}0&&(module.exports={FloPayCardSetup,FloPayCardSetupError});
6
+ `})]})})}var k=require("react");var z=require("react"),se=typeof window>"u"?z.useEffect:z.useLayoutEffect;var le=require("react/jsx-runtime");function ue({capture:e,html:r,messageToken:t,expectedOrigin:n,theme:o,containerStyle:a,onReady:i,onError:l,onValidation:s}){let c=(0,k.useRef)(null),d=(0,k.useRef)(i),m=(0,k.useRef)(l),C=(0,k.useRef)(s);d.current=i,m.current=l,C.current=s;let g=(0,k.useRef)(o);g.current=o;let T=(0,k.useRef)(null);return(0,k.useEffect)(()=>{let S=c.current;if(!S)return;let V=!0,A=!1,L=()=>{!V||A||(A=!0,d.current?.())},D=e.on("ready",()=>{L()}),x=e.on("error",y=>{m.current?.(y.message??"There was a problem loading the secure card form.")}),G=e.on("validation",y=>{C.current?.(y.message??null)}),B={html:r,...t?{messageToken:t}:{},...n?{expectedOrigin:n}:{},...g.current?{theme:g.current}:{}};return T.current=g.current??null,e.mount(S,B).then(()=>{L()}).catch(y=>{V&&m.current?.(y instanceof Error?y.message:"Failed to load the secure card form.")}),()=>{V=!1,D(),x(),G(),e.unmount()}},[e,r,t,n]),se(()=>{let S=c.current;S&&ne(S,a)},[a]),(0,k.useEffect)(()=>{o!==void 0&&(o===null&&T.current===null||(T.current=o,e.applyTheme?.(o)))},[e,o]),(0,le.jsx)("div",{ref:c,"data-testid":"flopay-vault-card-fields"})}var de=/^#([0-9a-f]{6})$/i,Be=/^#([0-9a-f]{3})$/i,fe=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i,pe=/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+|1\.0+)\s*\)$/i,Oe=/^linear-gradient\(\s*(-?\d+(?:\.\d+)?)deg\s*,\s*(.+)\)$/i,Ie=/^(-?\d+(?:\.\d+)?)(?:px)?$/,Me=/^(-?\d+(?:\.\d+)?)em$/,_e=/^blur\(\s*(\d+(?:\.\d+)?)(?:px)?\s*\)$/i,Ne=/^[a-z][a-z0-9 -]{0,31}$/i,De=new Set(["none","uppercase","lowercase","capitalize"]);function me(e){if(typeof e!="string")return null;let r=e.trim(),t=de.exec(r);if(t){let d=Number.parseInt(t[1],16);return{r:d>>16&255,g:d>>8&255,b:d&255,a:null}}let n=Be.exec(r);if(n){let[d,m,C]=n[1].split("").map(g=>Number.parseInt(g+g,16));return{r:d,g:m,b:C,a:null}}let o=fe.exec(r),a=o?null:pe.exec(r),i=o??a;if(!i)return null;let l=Number(i[1]),s=Number(i[2]),c=Number(i[3]);return l>255||s>255||c>255?null:{r:l,g:s,b:c,a:a?Number(a[4]):null}}function ge({r:e,g:r,b:t,a:n}){return n===null?`#${(1<<24|e<<16|r<<8|t).toString(16).slice(1)}`:`rgba(${e},${r},${t},${n})`}function M(e){if(typeof e!="string")return;let r=e.trim();if(de.test(r)||fe.test(r))return r;let t=pe.exec(r);if(t&&/^\d/.test(t[4]))return r;let n=me(r);return n?ge(n):void 0}function W(e,r=.12){let t=me(e);if(!t)return e;let n=Math.max(0,Math.min(1,1-r));return ge({r:Math.round(t.r*n),g:Math.round(t.g*n),b:Math.round(t.b*n),a:t.a})}function _(e,r){let t=[],n=0,o="";for(let a of e){if(a==="("&&(n+=1),a===")"&&(n-=1),a===r&&n===0){o.trim()&&t.push(o.trim()),o="";continue}o+=a}return o.trim()&&t.push(o.trim()),t}function P(e,r,t){if(typeof e!="number"&&typeof e!="string")return;let n=Ie.exec(String(e).trim());if(!n)return;let o=Number(n[1]);return Number.isFinite(o)&&o>=r&&o<=t?o:void 0}function ze(e,r,t){if(typeof e!="string")return;let n=Me.exec(e.trim());if(!n)return;let o=Number(n[1]);return Number.isFinite(o)&&o>=r&&o<=t?o:void 0}function We(e){let r=_(e,",");if(r.length<2||r.length>5)return;let t=[];for(let[n,o]of r.entries()){let a=_(o," "),i=M(a[0]);if(!i)return;let l=n/(r.length-1)*100,s=a[1]===void 0?l:Number(/^(\d+(?:\.\d+)?)%$/.exec(a[1])?.[1]),c=t[t.length-1]?.position??-1;if(!Number.isFinite(s)||s<0||s>100||s<c)return;t.push({color:i,position:s})}return{type:"linearGradient",angle:0,stops:t}}function $e(e){if(typeof e!="string")return;let r=e.trim(),t=M(r);if(t)return{type:"solid",color:t};let n=Oe.exec(r);if(!n)return;let o=Number(n[1]);if(!Number.isFinite(o)||o<0||o>360)return;let a=We(n[2]);return a&&a.type==="linearGradient"?{...a,angle:o}:void 0}function Ge(e){return e.type==="solid"?{type:"solid",color:W(e.color)}:{...e,stops:e.stops.map(r=>({...r,color:W(r.color)}))}}function He(e){let r=!1,t,n=[];for(let s of _(e," ")){if(s.toLowerCase()==="inset"){r=!0;continue}let c=M(s);if(c){t=c;continue}let d=P(s,-128,128);if(d===void 0)return;n.push(d)}if(!t||n.length<2||n.length>4)return;let[o,a,i=0,l=0]=n;if(!(Math.abs(o)>64||Math.abs(a)>64||i>128||Math.abs(l)>32))return{color:t,inset:r,offsetX:o,offsetY:a,blur:i,spread:l}}function Ye(e){if(typeof e!="string")return;let r=e.trim();if(r.toLowerCase()==="none")return[];let t=_(r,",").map(He);if(!(t.length===0||t.length>4))return t.every(n=>n!==void 0)?t:void 0}function ce(e){if(typeof e!="string")return;let r=_(e,",").map(t=>t.replace(/^['"]|['"]$/g,"").trim()).filter(t=>Ne.test(t)).slice(0,4);return r.length>0?r:void 0}function Ue(e){let r=typeof e=="string"?e.trim().split(/\s+/):[e],t=P(r[0],0,64),n=P(r[1]??r[0],0,64);if(!(t===void 0||n===void 0))return{paddingBlock:t,paddingInline:n}}function Xe(e){if(e==="bold")return 700;if(e==="normal")return 400;let r=Number(e);return Number.isInteger(r)&&r>=100&&r<=900?r:void 0}function ye({appearance:e,buttonsStyles:r,fontFamily:t}){let n=r.submitButton;if(!n)return;let o=e?.variables,a=$e(n.background??n.backgroundColor),i=M(o?.colorPrimaryHover),l=i?{type:"solid",color:i}:a&&Ge(a),s={fontFamilies:ce(n.fontFamily)??ce(t),fontSize:P(n.fontSize??r.submitButtonFontSize,10,32)??16,fontWeight:Xe(n.fontWeight)??600,letterSpacing:ze(n.letterSpacing,-.1,.5)??.01,lineHeight:P(n.lineHeight,.8,2)??1,textTransform:De.has(String(n.textTransform))?n.textTransform:"uppercase"},c=Ue(n.padding),d=Ye(n.boxShadow),m=P(n.borderRadius,0,9999),C=typeof n.backdropFilter=="string"?P(_e.exec(n.backdropFilter.trim())?.[1],0,40):void 0;return{foregroundColor:M(n.color)??"#FFFFFF",...a?{background:a,disabledBackground:a}:{},...l?{hoverBackground:l}:{},typography:s,...c?{spacing:c}:{},...d?{shadow:d}:{},...m===void 0?{}:{borderRadius:m},disabledOpacity:e?.theme==="night"?.8:.6,...C===void 0?{}:{backdropBlur:C}}}function je(e,r=.12){let t=e.trim(),n=/^[0-9a-fA-F]{6}$/.test(t)?`#${t}`:t;return/^#[0-9a-fA-F]{6}$/.test(n)?W(n,r):e}function qe(e){if(typeof e=="number"||typeof e=="string")return e}function he({appearance:e,buttonsStyles:r,layout:t="default"}){let n=e?.variables,o=m=>typeof m=="string"&&m?m:void 0,a=r.submitButton,i=o(n?.colorPrimary)??o(a?.backgroundColor)??"#4A49FF",l=t==="buttons",s=r.nameInput,c=o(s?.fontFamily)??o(n?.fontFamily)??"Poppins, sans-serif",d=ye({appearance:e,buttonsStyles:r,fontFamily:c});return{primaryColor:i,primaryHoverColor:o(n?.colorPrimaryHover)??je(i,.12),inputBackgroundColor:o(r.cardInputBackground)??o(n?.colorBackground)??"#ffffff",textColor:o(r.cardInputColor)??o(s?.color)??o(n?.colorText)??"#262833",borderColor:o(r.cardInputBorder)??(l?"#e5e7eb":"#A4A4FF"),placeholderColor:o(r.cardInputPlaceholderColor)??"#9ca3af",errorColor:o(n?.colorDanger)??"#dc2626",successColor:"#16a34a",fontFamily:c,fontSize:o(r.cardInputFontSize)??o(n?.fontSizeBase)??"16px",fontWeight:String(qe(s?.fontWeight)??400),borderRadius:o(n?.borderRadius)??"8px",...d?{submitButton:d}:{}}}var w=require("react/jsx-runtime"),N=class extends b.FloPayError{constructor(r,t,n){super(r,t,n),this.name="FloPayCardSetupError",this.retryable=n.retryable}};function Ce(e,r={}){let t=e instanceof b.FloPayError?e:void 0,n=t?.statusCode,o=r.retryable??(t?.type==="network_error"||t?.type==="rate_limit_error"||typeof n=="number"&&n>=500||t?.code==="vault_capture_timeout"||!t);return new N(t?.message??(e instanceof Error?e.message:"Failed to load the secure card form."),t?.type??"api_error",{code:r.code??t?.code??"card_setup_load_failed",retryable:o,...t?.param?{param:t.param}:{},...n===void 0?{}:{statusCode:n}})}function Se({sessionId:e,nonce:r,billingApiUrl:t,telemetry:n,theme:o="modern-light",containerStyle:a,loading:i=null,onReady:l,onComplete:s,onDecline:c,onCancel:d,onValidation:m,onError:C}){let[g,T]=(0,u.useState)(null),[S,V]=(0,u.useState)(null),[A,L]=(0,u.useState)(null),[D,x]=(0,u.useState)(null),[G,B]=(0,u.useState)(null),y=(0,u.useRef)(!1),H=(0,u.useRef)(!1),R=(0,u.useMemo)(()=>typeof o=="object"?void 0:(0,b.resolveTheme)(o),[o]),ke=(0,u.useMemo)(()=>typeof o=="object"?o:R?he({appearance:R.appearance,buttonsStyles:R.buttonsLayout,layout:"default"}):null,[R,o]),we=(0,u.useMemo)(()=>te(R?.buttonsLayout.cardFormContainer,a),[R,a]),K=(0,u.useMemo)(()=>R?ae(R):void 0,[R]),Z=(0,u.useRef)(l),Y=(0,u.useRef)(C),J=(0,u.useRef)(s),Q=(0,u.useRef)(c),ee=(0,u.useRef)(d),re=(0,u.useRef)(m),O=(0,u.useRef)(!1),U=(0,u.useRef)(!1),X=(0,u.useRef)(0);return Z.current=l,Y.current=C,J.current=s,Q.current=c,ee.current=d,re.current=m,(0,u.useEffect)(()=>{let p=X.current+1;return X.current=p,()=>{queueMicrotask(()=>{X.current===p&&(O.current||U.current||(U.current=!0,F(()=>{ee.current?.({status:"cancelled",sessionId:e})})))})}},[e]),(0,u.useEffect)(()=>{let p=!0,E=new $.PaymentAPI((0,b.resolveBillingApiUrl)(t),{telemetry:n});return T(null),V(null),L(null),O.current=!1,U.current=!1,(async()=>{try{if(!e.trim())throw new b.FloPayError("FloPayCardSetup requires a sessionId.","validation_error",{code:"MissingCheckoutSessionId",param:"sessionId"});if(!r.trim())throw new b.FloPayError("FloPayCardSetup requires a session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let I=await E.getUnifiedCheckoutSession(e,r);if(!p)return;let v=I.data.session;if(!v||!(0,b.isCardSetupCheckoutSession)(v))throw new b.FloPayError("FloPayCardSetup only accepts a zero-amount, productless setup session.","validation_error",{code:"InvalidCardSetupSession",param:"sessionId"});let h=v.vault;if(h?.html?.trim()||(h=await E.getVaultCapture(e,r)),!h.html?.trim())throw new b.FloPayError("FloPay: this setup session has no vault card capability. Upgrade the billing backend integration.","api_error",{code:"UnsupportedBackendVaultCapability"});if(!p)return;V(h),T(new $.PciVaultCardCapture({sessionId:e,operation:"card_setup",telemetry:n}))}catch(I){if(!p)return;let v=Ce(I);O.current=!0,L(v),F(()=>Y.current?.(v))}})(),()=>{p=!1,E.destroy()}},[t,r,e,n]),(0,u.useEffect)(()=>{if(!g)return;let p=!1;H.current=!1,y.current=!1;let E=g.on("submitting",()=>{y.current=!0,B(null),x("processing")}),I=g.on("complete",h=>{O.current=!0,y.current=!1,x("success"),(async()=>(await new Promise(j=>setTimeout(j,1200)),!H.current&&(H.current=!0,F(()=>{J.current?.({status:"succeeded",sessionId:e,...h.paymentMethod?{paymentMethod:h.paymentMethod}:{}})}),p||x(null))))()}),v=g.on("decline",h=>{O.current=!0,y.current=!1,B(h.message??null),x("error"),F(()=>{Q.current?.({status:"declined",sessionId:e,...h.declineReason?{reason:h.declineReason}:{},...h.message?{message:h.message}:{}})}),(async()=>(await new Promise(j=>setTimeout(j,1500)),p||x(null)))()});return()=>{p=!0,E(),I(),v()}},[g,e]),A?(0,w.jsx)("div",{role:"alert",children:A.message}):!g||!S?.html?(0,w.jsx)(w.Fragment,{children:i}):(0,w.jsxs)(w.Fragment,{children:[D&&(0,w.jsx)(ie,{status:D,errorMessage:G,processingLabel:"SAVING CARD...",successLabel:"CARD SAVED",errorLabel:"CARD NOT SAVED",successNote:null,...K?{theme:K}:{}}),(0,w.jsx)(ue,{capture:g,html:S.html,messageToken:S.messageToken,expectedOrigin:S.expectedOrigin,theme:ke,containerStyle:we,onReady:()=>{F(()=>Z.current?.())},onValidation:p=>{F(()=>re.current?.(p))},onError:p=>{if(!p)return;y.current&&(y.current=!1,B(p),x("error"),setTimeout(()=>x(null),1500));let E=Ce(new Error(p),{code:"card_setup_widget_failed",retryable:!0});F(()=>Y.current?.(E))}})]})}0&&(module.exports={FloPayCardSetup,FloPayCardSetupError});
@@ -48,7 +48,15 @@ interface FloPayCardSetupProps {
48
48
  * `'modern-light'`; pass `'classic'` for the historic FloPay look.
49
49
  */
50
50
  theme?: ThemeId | VaultCardThemeColors;
51
- /** Inline styles for the hosted-widget container. */
51
+ /**
52
+ * Inline styles for the hosted-widget container. A named preset first gives
53
+ * that container the same complete surface as the checkout's credit-card
54
+ * pane (background, border, radius, shadow, padding); each `containerStyle`
55
+ * property then wins over the preset's for the same property, a longhand
56
+ * refines a preset shorthand (`borderColor` recolors the preset border), and
57
+ * any `background*` member replaces the preset background entirely.
58
+ * `'classic'` and raw colors add no surface, so `containerStyle` applies alone.
59
+ */
52
60
  containerStyle?: React.CSSProperties;
53
61
  /** Optional content shown while the session and hosted widget are loading. */
54
62
  loading?: React.ReactNode;
@@ -48,7 +48,15 @@ interface FloPayCardSetupProps {
48
48
  * `'modern-light'`; pass `'classic'` for the historic FloPay look.
49
49
  */
50
50
  theme?: ThemeId | VaultCardThemeColors;
51
- /** Inline styles for the hosted-widget container. */
51
+ /**
52
+ * Inline styles for the hosted-widget container. A named preset first gives
53
+ * that container the same complete surface as the checkout's credit-card
54
+ * pane (background, border, radius, shadow, padding); each `containerStyle`
55
+ * property then wins over the preset's for the same property, a longhand
56
+ * refines a preset shorthand (`borderColor` recolors the preset border), and
57
+ * any `background*` member replaces the preset background entirely.
58
+ * `'classic'` and raw colors add no surface, so `containerStyle` applies alone.
59
+ */
52
60
  containerStyle?: React.CSSProperties;
53
61
  /** Optional content shown while the session and hosted widget are loading. */
54
62
  loading?: React.ReactNode;
@@ -1 +1 @@
1
- import{g as e,h as t}from"./chunk-KMQWWDWZ.mjs";export{t as FloPayCardSetup,e as FloPayCardSetupError};
1
+ import{h as e,i as t}from"./chunk-LI3VGXRI.mjs";export{t as FloPayCardSetup,e as FloPayCardSetupError};
@@ -0,0 +1,6 @@
1
+ import{useEffect as ie,useRef as T}from"react";function ne(e,r){if(!e)return r;let t=r??{},n=Object.keys(t),o=n.some(i=>i.startsWith("background")),a={};for(let[i,u]of Object.entries(e))i in t||o&&i.startsWith("background")||(a[i]=u);for(let i of n)a[i]=t[i];return a}var Re=new Set(["animationIterationCount","aspectRatio","borderImageOutset","borderImageSlice","borderImageWidth","boxFlex","boxFlexGroup","boxOrdinalGroup","columnCount","columns","flex","flexGrow","flexPositive","flexShrink","flexNegative","flexOrder","gridArea","gridRow","gridRowEnd","gridRowSpan","gridRowStart","gridColumn","gridColumnEnd","gridColumnSpan","gridColumnStart","fontWeight","lineClamp","lineHeight","opacity","order","orphans","scale","tabSize","widows","zIndex","zoom","fillOpacity","floodOpacity","stopOpacity","strokeDasharray","strokeDashoffset","strokeMiterlimit","strokeOpacity","strokeWidth"]);function ve(e){let r=e.replace(/^(Webkit|Moz|ms)(?=[A-Z])/,"");return Re.has(r.charAt(0).toLowerCase()+r.slice(1))}function Fe(e,r){return typeof r=="number"&&r!==0&&!ve(e)?`${r}px`:String(r).trim()}function oe(e,r){if(e.style.cssText="",!!r){for(let[t,n]of Object.entries(r))if(!(n==null||n==="")){if(t.startsWith("--")){e.style.setProperty(t,String(n));continue}e.style[t]=Fe(t,n)}}}import{useEffect as Ee,useLayoutEffect as Te}from"react";var ae=typeof window>"u"?Ee:Te;import{jsx as Pe}from"react/jsx-runtime";function se({capture:e,html:r,messageToken:t,expectedOrigin:n,theme:o,containerStyle:a,onReady:i,onError:u,onValidation:s}){let l=T(null),c=T(i),f=T(u),b=T(s);c.current=i,f.current=u,b.current=s;let p=T(o);p.current=o;let F=T(null);return ie(()=>{let C=l.current;if(!C)return;let E=!0,A=!1,L=()=>{!E||A||(A=!0,c.current?.())},D=e.on("ready",()=>{L()}),S=e.on("error",m=>{f.current?.(m.message??"There was a problem loading the secure card form.")}),G=e.on("validation",m=>{b.current?.(m.message??null)}),B={html:r,...t?{messageToken:t}:{},...n?{expectedOrigin:n}:{},...p.current?{theme:p.current}:{}};return F.current=p.current??null,e.mount(C,B).then(()=>{L()}).catch(m=>{E&&f.current?.(m instanceof Error?m.message:"Failed to load the secure card form.")}),()=>{E=!1,D(),S(),G(),e.unmount()}},[e,r,t,n]),ae(()=>{let C=l.current;C&&oe(C,a)},[a]),ie(()=>{o!==void 0&&(o===null&&F.current===null||(F.current=o,e.applyTheme?.(o)))},[e,o]),Pe("div",{ref:l,"data-testid":"flopay-vault-card-fields"})}import{PaymentAPI as qe,PciVaultCardCapture as Ke}from"@flopay/js/card-setup";import{FloPayError as V,isCardSetupCheckoutSession as Ze,resolveBillingApiUrl as Je,resolveTheme as Qe}from"@flopay/shared";import{useEffect as q,useMemo as W,useRef as h,useState as N}from"react";var ue={light:{success:"#166534",error:"#991B1B"},dark:{success:"#4ADE80",error:"#FCA5A5"}};function le(e){let r=e.appearance.variables??{},t=e.buttonsLayout.cardFormContainer??{},n=e.appearance.theme==="night",o=n?ue.dark:ue.light,a=r.colorText??(n?"#F1F5F9":"#262833"),i=e.appearance.rules?.[".Label"];return{panel:{...t.background===void 0?{}:{background:t.background},...t.backgroundColor===void 0?{}:{backgroundColor:t.backgroundColor},...t.border===void 0?{}:{border:t.border},...t.borderRadius===void 0?{}:{borderRadius:t.borderRadius},...t.boxShadow===void 0?{}:{boxShadow:t.boxShadow},color:a,...r.fontFamily?{fontFamily:r.fontFamily}:{}},spinnerTrackColor:e.buttonsLayout.cardInputBorder??(n?"#374151":"#e5e7eb"),spinnerAccentColor:r.colorPrimary??"#4A49FF",labelColors:{processing:a,success:o.success,error:o.error},noteColor:i?.color??a}}function x(e){if(!e)return;let r=t=>{console.error("[FloPay] Merchant callback failed; checkout continued.",t)};try{Promise.resolve(e()).catch(r)}catch(t){r(t)}}import{jsx as y,jsxs as P}from"react/jsx-runtime";var Ve={panel:{background:"white"},spinnerTrackColor:"#e5e7eb",spinnerAccentColor:"#4A49FF",labelColors:{processing:"#374151",success:"#16a34a",error:"#dc2626"},noteColor:"#6b7280"};function ce({status:e,errorMessage:r,authorized:t=!1,processingLabel:n="PROCESSING...",successLabel:o,errorLabel:a="PAYMENT FAILED",successNote:i="You will be automatically redirected, do not close or navigate away from this window.",theme:u=Ve}){let s={fontSize:13,color:u.noteColor,fontWeight:400,maxWidth:260,lineHeight:1.4,margin:0};return y("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:P("div",{"data-testid":"flopay-processing-overlay-panel",style:{borderRadius:12,boxShadow:"0 8px 32px rgba(0,0,0,0.18)",...u.panel,padding:"2rem 2.5rem",textAlign:"center",minWidth:240,display:"flex",flexDirection:"column",alignItems:"center",gap:16},children:[P("div",{style:{width:48,height:48,position:"relative"},children:[e==="processing"&&P("svg",{"aria-hidden":"true",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:[y("circle",{cx:"12",cy:"12",r:"10",stroke:u.spinnerTrackColor,strokeWidth:"3"}),y("path",{d:"M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z",fill:u.spinnerAccentColor})]}),e==="success"&&y("div",{style:{animation:"flopay-pop 0.4s cubic-bezier(0.34,1.56,0.64,1)"},children:P("svg",{"aria-hidden":"true",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[y("circle",{cx:"12",cy:"12",r:"11",fill:"#22c55e"}),y("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"&&y("div",{style:{animation:"flopay-shake 0.4s ease"},children:P("svg",{"aria-hidden":"true",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[y("circle",{cx:"12",cy:"12",r:"11",fill:"#ef4444"}),y("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"}})]})})]}),P("span",{style:{fontSize:14,fontWeight:600,letterSpacing:"0.05em",color:u.labelColors[e]},children:[e==="processing"&&n,e==="success"&&(o??(t?"PAYMENT AUTHORISED":"PAYMENT SUCCESSFUL")),e==="error"&&a]}),e==="success"&&i!==null&&y("p",{style:s,children:i}),e==="error"&&r&&y("p",{style:s,children:r}),y("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
+ `})]})})}var fe=/^#([0-9a-f]{6})$/i,Ae=/^#([0-9a-f]{3})$/i,pe=/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i,me=/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+|1\.0+)\s*\)$/i,Le=/^linear-gradient\(\s*(-?\d+(?:\.\d+)?)deg\s*,\s*(.+)\)$/i,Be=/^(-?\d+(?:\.\d+)?)(?:px)?$/,Oe=/^(-?\d+(?:\.\d+)?)em$/,Ie=/^blur\(\s*(\d+(?:\.\d+)?)(?:px)?\s*\)$/i,Me=/^[a-z][a-z0-9 -]{0,31}$/i,_e=new Set(["none","uppercase","lowercase","capitalize"]);function ge(e){if(typeof e!="string")return null;let r=e.trim(),t=fe.exec(r);if(t){let c=Number.parseInt(t[1],16);return{r:c>>16&255,g:c>>8&255,b:c&255,a:null}}let n=Ae.exec(r);if(n){let[c,f,b]=n[1].split("").map(p=>Number.parseInt(p+p,16));return{r:c,g:f,b,a:null}}let o=pe.exec(r),a=o?null:me.exec(r),i=o??a;if(!i)return null;let u=Number(i[1]),s=Number(i[2]),l=Number(i[3]);return u>255||s>255||l>255?null:{r:u,g:s,b:l,a:a?Number(a[4]):null}}function ye({r:e,g:r,b:t,a:n}){return n===null?`#${(1<<24|e<<16|r<<8|t).toString(16).slice(1)}`:`rgba(${e},${r},${t},${n})`}function M(e){if(typeof e!="string")return;let r=e.trim();if(fe.test(r)||pe.test(r))return r;let t=me.exec(r);if(t&&/^\d/.test(t[4]))return r;let n=ge(r);return n?ye(n):void 0}function z(e,r=.12){let t=ge(e);if(!t)return e;let n=Math.max(0,Math.min(1,1-r));return ye({r:Math.round(t.r*n),g:Math.round(t.g*n),b:Math.round(t.b*n),a:t.a})}function _(e,r){let t=[],n=0,o="";for(let a of e){if(a==="("&&(n+=1),a===")"&&(n-=1),a===r&&n===0){o.trim()&&t.push(o.trim()),o="";continue}o+=a}return o.trim()&&t.push(o.trim()),t}function v(e,r,t){if(typeof e!="number"&&typeof e!="string")return;let n=Be.exec(String(e).trim());if(!n)return;let o=Number(n[1]);return Number.isFinite(o)&&o>=r&&o<=t?o:void 0}function Ne(e,r,t){if(typeof e!="string")return;let n=Oe.exec(e.trim());if(!n)return;let o=Number(n[1]);return Number.isFinite(o)&&o>=r&&o<=t?o:void 0}function De(e){let r=_(e,",");if(r.length<2||r.length>5)return;let t=[];for(let[n,o]of r.entries()){let a=_(o," "),i=M(a[0]);if(!i)return;let u=n/(r.length-1)*100,s=a[1]===void 0?u:Number(/^(\d+(?:\.\d+)?)%$/.exec(a[1])?.[1]),l=t[t.length-1]?.position??-1;if(!Number.isFinite(s)||s<0||s>100||s<l)return;t.push({color:i,position:s})}return{type:"linearGradient",angle:0,stops:t}}function ze(e){if(typeof e!="string")return;let r=e.trim(),t=M(r);if(t)return{type:"solid",color:t};let n=Le.exec(r);if(!n)return;let o=Number(n[1]);if(!Number.isFinite(o)||o<0||o>360)return;let a=De(n[2]);return a&&a.type==="linearGradient"?{...a,angle:o}:void 0}function We(e){return e.type==="solid"?{type:"solid",color:z(e.color)}:{...e,stops:e.stops.map(r=>({...r,color:z(r.color)}))}}function $e(e){let r=!1,t,n=[];for(let s of _(e," ")){if(s.toLowerCase()==="inset"){r=!0;continue}let l=M(s);if(l){t=l;continue}let c=v(s,-128,128);if(c===void 0)return;n.push(c)}if(!t||n.length<2||n.length>4)return;let[o,a,i=0,u=0]=n;if(!(Math.abs(o)>64||Math.abs(a)>64||i>128||Math.abs(u)>32))return{color:t,inset:r,offsetX:o,offsetY:a,blur:i,spread:u}}function Ge(e){if(typeof e!="string")return;let r=e.trim();if(r.toLowerCase()==="none")return[];let t=_(r,",").map($e);if(!(t.length===0||t.length>4))return t.every(n=>n!==void 0)?t:void 0}function de(e){if(typeof e!="string")return;let r=_(e,",").map(t=>t.replace(/^['"]|['"]$/g,"").trim()).filter(t=>Me.test(t)).slice(0,4);return r.length>0?r:void 0}function He(e){let r=typeof e=="string"?e.trim().split(/\s+/):[e],t=v(r[0],0,64),n=v(r[1]??r[0],0,64);if(!(t===void 0||n===void 0))return{paddingBlock:t,paddingInline:n}}function Ye(e){if(e==="bold")return 700;if(e==="normal")return 400;let r=Number(e);return Number.isInteger(r)&&r>=100&&r<=900?r:void 0}function he({appearance:e,buttonsStyles:r,fontFamily:t}){let n=r.submitButton;if(!n)return;let o=e?.variables,a=ze(n.background??n.backgroundColor),i=M(o?.colorPrimaryHover),u=i?{type:"solid",color:i}:a&&We(a),s={fontFamilies:de(n.fontFamily)??de(t),fontSize:v(n.fontSize??r.submitButtonFontSize,10,32)??16,fontWeight:Ye(n.fontWeight)??600,letterSpacing:Ne(n.letterSpacing,-.1,.5)??.01,lineHeight:v(n.lineHeight,.8,2)??1,textTransform:_e.has(String(n.textTransform))?n.textTransform:"uppercase"},l=He(n.padding),c=Ge(n.boxShadow),f=v(n.borderRadius,0,9999),b=typeof n.backdropFilter=="string"?v(Ie.exec(n.backdropFilter.trim())?.[1],0,40):void 0;return{foregroundColor:M(n.color)??"#FFFFFF",...a?{background:a,disabledBackground:a}:{},...u?{hoverBackground:u}:{},typography:s,...l?{spacing:l}:{},...c?{shadow:c}:{},...f===void 0?{}:{borderRadius:f},disabledOpacity:e?.theme==="night"?.8:.6,...b===void 0?{}:{backdropBlur:b}}}function Ue(e,r=.12){let t=e.trim(),n=/^[0-9a-fA-F]{6}$/.test(t)?`#${t}`:t;return/^#[0-9a-fA-F]{6}$/.test(n)?z(n,r):e}function Xe(e){if(typeof e=="number"||typeof e=="string")return e}function be({appearance:e,buttonsStyles:r,layout:t="default"}){let n=e?.variables,o=f=>typeof f=="string"&&f?f:void 0,a=r.submitButton,i=o(n?.colorPrimary)??o(a?.backgroundColor)??"#4A49FF",u=t==="buttons",s=r.nameInput,l=o(s?.fontFamily)??o(n?.fontFamily)??"Poppins, sans-serif",c=he({appearance:e,buttonsStyles:r,fontFamily:l});return{primaryColor:i,primaryHoverColor:o(n?.colorPrimaryHover)??Ue(i,.12),inputBackgroundColor:o(r.cardInputBackground)??o(n?.colorBackground)??"#ffffff",textColor:o(r.cardInputColor)??o(s?.color)??o(n?.colorText)??"#262833",borderColor:o(r.cardInputBorder)??(u?"#e5e7eb":"#A4A4FF"),placeholderColor:o(r.cardInputPlaceholderColor)??"#9ca3af",errorColor:o(n?.colorDanger)??"#dc2626",successColor:"#16a34a",fontFamily:l,fontSize:o(r.cardInputFontSize)??o(n?.fontSizeBase)??"16px",fontWeight:String(Xe(s?.fontWeight)??400),borderRadius:o(n?.borderRadius)??"8px",...c?{submitButton:c}:{}}}import{Fragment as ke,jsx as $,jsxs as er}from"react/jsx-runtime";var K=class extends V{constructor(r,t,n){super(r,t,n),this.name="FloPayCardSetupError",this.retryable=n.retryable}};function Se(e,r={}){let t=e instanceof V?e:void 0,n=t?.statusCode,o=r.retryable??(t?.type==="network_error"||t?.type==="rate_limit_error"||typeof n=="number"&&n>=500||t?.code==="vault_capture_timeout"||!t);return new K(t?.message??(e instanceof Error?e.message:"Failed to load the secure card form."),t?.type??"api_error",{code:r.code??t?.code??"card_setup_load_failed",retryable:o,...t?.param?{param:t.param}:{},...n===void 0?{}:{statusCode:n}})}function vr({sessionId:e,nonce:r,billingApiUrl:t,telemetry:n,theme:o="modern-light",containerStyle:a,loading:i=null,onReady:u,onComplete:s,onDecline:l,onCancel:c,onValidation:f,onError:b}){let[p,F]=N(null),[C,E]=N(null),[A,L]=N(null),[D,S]=N(null),[G,B]=N(null),m=h(!1),H=h(!1),k=W(()=>typeof o=="object"?void 0:Qe(o),[o]),we=W(()=>typeof o=="object"?o:k?be({appearance:k.appearance,buttonsStyles:k.buttonsLayout,layout:"default"}):null,[k,o]),xe=W(()=>ne(k?.buttonsLayout.cardFormContainer,a),[k,a]),Z=W(()=>k?le(k):void 0,[k]),J=h(u),Y=h(b),Q=h(s),ee=h(l),re=h(c),te=h(f),O=h(!1),U=h(!1),X=h(0);return J.current=u,Y.current=b,Q.current=s,ee.current=l,re.current=c,te.current=f,q(()=>{let d=X.current+1;return X.current=d,()=>{queueMicrotask(()=>{X.current===d&&(O.current||U.current||(U.current=!0,x(()=>{re.current?.({status:"cancelled",sessionId:e})})))})}},[e]),q(()=>{let d=!0,R=new qe(Je(t),{telemetry:n});return F(null),E(null),L(null),O.current=!1,U.current=!1,(async()=>{try{if(!e.trim())throw new V("FloPayCardSetup requires a sessionId.","validation_error",{code:"MissingCheckoutSessionId",param:"sessionId"});if(!r.trim())throw new V("FloPayCardSetup requires a session nonce.","validation_error",{code:"MissingCheckoutSessionToken",param:"nonce"});let I=await R.getUnifiedCheckoutSession(e,r);if(!d)return;let w=I.data.session;if(!w||!Ze(w))throw new V("FloPayCardSetup only accepts a zero-amount, productless setup session.","validation_error",{code:"InvalidCardSetupSession",param:"sessionId"});let g=w.vault;if(g?.html?.trim()||(g=await R.getVaultCapture(e,r)),!g.html?.trim())throw new V("FloPay: this setup session has no vault card capability. Upgrade the billing backend integration.","api_error",{code:"UnsupportedBackendVaultCapability"});if(!d)return;E(g),F(new Ke({sessionId:e,operation:"card_setup",telemetry:n}))}catch(I){if(!d)return;let w=Se(I);O.current=!0,L(w),x(()=>Y.current?.(w))}})(),()=>{d=!1,R.destroy()}},[t,r,e,n]),q(()=>{if(!p)return;let d=!1;H.current=!1,m.current=!1;let R=p.on("submitting",()=>{m.current=!0,B(null),S("processing")}),I=p.on("complete",g=>{O.current=!0,m.current=!1,S("success"),(async()=>(await new Promise(j=>setTimeout(j,1200)),!H.current&&(H.current=!0,x(()=>{Q.current?.({status:"succeeded",sessionId:e,...g.paymentMethod?{paymentMethod:g.paymentMethod}:{}})}),d||S(null))))()}),w=p.on("decline",g=>{O.current=!0,m.current=!1,B(g.message??null),S("error"),x(()=>{ee.current?.({status:"declined",sessionId:e,...g.declineReason?{reason:g.declineReason}:{},...g.message?{message:g.message}:{}})}),(async()=>(await new Promise(j=>setTimeout(j,1500)),d||S(null)))()});return()=>{d=!0,R(),I(),w()}},[p,e]),A?$("div",{role:"alert",children:A.message}):!p||!C?.html?$(ke,{children:i}):er(ke,{children:[D&&$(ce,{status:D,errorMessage:G,processingLabel:"SAVING CARD...",successLabel:"CARD SAVED",errorLabel:"CARD NOT SAVED",successNote:null,...Z?{theme:Z}:{}}),$(se,{capture:p,html:C.html,messageToken:C.messageToken,expectedOrigin:C.expectedOrigin,theme:we,containerStyle:xe,onReady:()=>{x(()=>J.current?.())},onValidation:d=>{x(()=>te.current?.(d))},onError:d=>{if(!d)return;m.current&&(m.current=!1,B(d),S("error"),setTimeout(()=>S(null),1500));let R=Se(new Error(d),{code:"card_setup_widget_failed",retryable:!0});x(()=>Y.current?.(R))}})]})}export{x as a,ce as b,ae as c,se as d,Ue as e,Xe as f,be as g,K as h,vr as i};