@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/dist/index.d.cts CHANGED
@@ -1,63 +1,257 @@
1
- import React from 'react';
2
- import { FloPay, FloPayElements } from '@flopay/js';
3
1
  import * as _flopay_shared from '@flopay/shared';
4
- import { FloPayAppearance, InlineSessionDraft, FloPayError, PaymentResult, DeclineEvent, CheckoutButtonMethod, BeforeButtonClickEvent, InlineSessionPatch, CheckoutMode, CheckoutSession, ElementOptions, ElementChangeEvent, TokenizedBody, AVSFieldConfig, GatewayEnvironment, PayPalProviderObjectType, CardCaptureAdapter, VaultCardThemeColors, CheckoutProduct, CheckoutItem, CheckoutSubscription, ThemeId, ButtonsLayoutTheme, ButtonsLayoutStyles } from '@flopay/shared';
5
- export { BeforeButtonClickEvent, CheckoutButtonMethod, DeclineEvent, InlineSessionDraft, InlineSessionPatch, SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
2
+ import { InlineSessionDraft, CheckoutButtonMethod, CheckoutProduct, CheckoutItem, CheckoutSubscription, ThemeId, FloPayAppearance, ButtonsLayoutTheme, ButtonsLayoutStyles, PaymentResult, CheckoutSession, FloPayError, DeclineEvent, GatewayEnvironment, PayPalProviderObjectType, TokenizedBody, InlineSessionPatch, ElementOptions, ElementChangeEvent, FloInstrumentEvent, BeforeButtonClickEvent, CheckoutMode, AVSFieldConfig, CardCaptureAdapter, VaultCardThemeColors } from '@flopay/shared';
3
+ export { BeforeButtonClickEvent, CheckoutButtonMethod, DeclineEvent, FloInstrumentEvent, InlineSessionDraft, InlineSessionPatch, SentryEventLike, SentryStackFrameLike, dropThirdPartyOnlyError } from '@flopay/shared';
4
+ import React from 'react';
6
5
  export { FloPayCardSetup, FloPayCardSetupCancelEvent, FloPayCardSetupCompleteEvent, FloPayCardSetupDeclineEvent, FloPayCardSetupError, FloPayCardSetupProps } from './card-setup-entry.cjs';
6
+ import { FloPayElements, FloPay } from '@flopay/js';
7
7
 
8
- /** Props for the `FloPayProvider` component. */
9
- interface FloPayProviderProps {
10
- /** A `FloPay` instance or a promise that resolves to one (from `loadFloPay()`). */
11
- flopay: Promise<FloPay> | FloPay;
8
+ interface FloPayAutomaticPaymentSuccessEvent {
9
+ result: PaymentResult;
10
+ session: CheckoutSession | null;
11
+ sessionId: string | null;
12
+ autoCompleted: boolean;
13
+ }
14
+ interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
15
+ sessionId?: string;
12
16
  /**
13
- * Optional Stripe `FloPay` instance used to drive the Stripe-rendered PayPal
14
- * fallback. When omitted or `null`, the Stripe-rendered PayPal button is
15
- * not rendered. Direct PayPal (`gateways.paypal`) does not use this prop.
17
+ * Session-bound checkout token for a consumer-supplied {@link sessionId}
18
+ * (the `nonce` returned when that session was created). Post-#640 backends
19
+ * require it as `x-checkout-session-token` to read the session and to
20
+ * `/process` it; without it the existing-session path 401s with
21
+ * "Missing checkout session token.". Ignored on the create-session path,
22
+ * where the SDK mints and threads the nonce itself.
16
23
  */
17
- paypalFlopay?: Promise<FloPay> | FloPay | null;
18
- /** Optional configuration applied when creating the elements group. */
19
- options?: {
20
- locale?: string;
21
- appearance?: FloPayAppearance;
22
- /**
23
- * Client secret for an existing non-card PaymentIntent or SetupIntent.
24
- * The SDK verifies the provider intent against the `PaymentElement`'s
25
- * explicit `paymentMethodTypes` allowlist before mounting and rejects card
26
- * or undeclared methods. Card checkout uses the hosted vault.
27
- */
28
- clientSecret?: string;
29
- /** Total amount in cents for deferred non-card Elements without a client secret. */
30
- amount?: number;
31
- /** ISO 4217 currency code for deferred non-card Elements without a client secret. */
32
- currency?: string;
33
- /** How non-card payment methods are created: `'manual'` or `'auto'` (needed for PayPal). */
34
- paymentMethodCreation?: 'manual' | 'auto';
35
- /** Requests reusable payment credentials for future payments. */
36
- setupFutureUsage?: 'off_session' | 'on_session';
37
- /** Billing API base URL. Set once here so child components don't need to repeat it. */
38
- billingApiUrl?: string;
24
+ nonce?: string;
25
+ createSession?: InlineSessionDraft;
26
+ /**
27
+ * @deprecated Ignored. The backend now picks the customer's most recent
28
+ * vaulted payment method via `getLatestByUserId` and rebinds the session's
29
+ * gateway to match it (see `apps/api`'s `createSingle` auto-checkout
30
+ * branch). Passing this prop has no effect it is retained only to avoid
31
+ * breaking existing integrations.
32
+ */
33
+ paymentMethodId?: string;
34
+ /**
35
+ * @deprecated Ignored. The backend orchestrates gateway routing — clients
36
+ * no longer choose between card and PayPal at the SDK boundary. Passing
37
+ * this prop has no effect.
38
+ */
39
+ checkoutMethod?: CheckoutButtonMethod;
40
+ clientId?: string;
41
+ /**
42
+ * Unified products array (TeamFloPay/backend#760). When supplied,
43
+ * `items`/`subscriptions` are ignored. The SDK folds the legacy fields
44
+ * into this shape internally.
45
+ */
46
+ products?: CheckoutProduct[];
47
+ items?: CheckoutItem[];
48
+ subscriptions?: CheckoutSubscription[];
49
+ account?: InlineSessionDraft['account'];
50
+ successUrl?: string;
51
+ cancelUrl?: string;
52
+ couponCodes?: string[];
53
+ tagsData?: InlineSessionDraft['tagsData'];
54
+ utmMetadata?: InlineSessionDraft['utmMetadata'];
55
+ billingApiUrl?: string;
56
+ locale?: string;
57
+ /**
58
+ * High-level theme bundle that styles the button (and the fallback
59
+ * `FloPayCheckout` modal that opens when the saved-payment charge needs
60
+ * user interaction). One of: `'classic'`, `'modern-light'`, `'modern-dark'`,
61
+ * `'bold-light'`, `'bold-dark'`, `'glass-light'`, `'glass-dark'`. Explicit
62
+ * `buttonsStyles` still wins for fine-grained overrides.
63
+ */
64
+ theme?: ThemeId;
65
+ /**
66
+ * Per-checkout appearance overrides layered on top of the chosen `theme`
67
+ * (same shape as {@link FloPayCheckout}'s `appearance`). Its `colorPrimary` /
68
+ * `colorPrimaryHover` / `borderRadius` re-skin the button — and the fallback
69
+ * `FloPayCheckout` modal — so the auto-pay button matches the rest of the
70
+ * themed checkout. Without this the button only saw the bundle's defaults.
71
+ */
72
+ appearance?: FloPayAppearance;
73
+ /**
74
+ * @deprecated Use `theme` instead. Legacy buttons-layout preset
75
+ * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
76
+ * back-compat.
77
+ */
78
+ buttonsTheme?: ButtonsLayoutTheme;
79
+ buttonsStyles?: ButtonsLayoutStyles;
80
+ onSuccess?: (event: FloPayAutomaticPaymentSuccessEvent) => void;
81
+ onError?: (error: FloPayError) => void;
82
+ onDecline?: (decline: DeclineEvent) => void;
83
+ children?: React.ReactNode;
84
+ }
85
+ declare function FloPayAutomaticPaymentButton({ sessionId, nonce, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, appearance, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps): React.JSX.Element;
86
+
87
+ /**
88
+ * Overrides that `SplitCardForm`'s tokenized-body dispatcher uses to apply a
89
+ * `runBeforeButtonClick` patch to the in-flight processPayment call. Kept in
90
+ * sync structurally with `TokenizedBodyOverrides` in `split-card-form.tsx`.
91
+ */
92
+ interface DirectPayPalTokenizedOverrides {
93
+ accountPatch?: InlineSessionPatch['account'];
94
+ sessionId?: string;
95
+ nonce?: string;
96
+ }
97
+ /**
98
+ * Internal handler signature aligned with `SplitCardForm`'s tokenized-body
99
+ * dispatcher. Direct PayPal completes via the backend's process endpoint and
100
+ * never produces a Stripe PaymentIntent, so we still forward a synthetic
101
+ * `TokenizedBody` describing the captured order, optionally with the
102
+ * session/account patch captured at click-time.
103
+ */
104
+ type DirectPayPalTokenizedHandler = (body: TokenizedBody, overrides?: DirectPayPalTokenizedOverrides) => void;
105
+ /** Click-time `runBeforeButtonClick` result, structurally compatible with `SplitCardForm`. */
106
+ interface DirectPayPalBeforeButtonClickResult {
107
+ proceed: boolean;
108
+ accountPatch?: InlineSessionPatch['account'];
109
+ sessionId?: string;
110
+ nonce?: string;
111
+ }
112
+ /**
113
+ * Click-time gate. Mirrors `RunBeforeButtonClick` in `SplitCardForm`: lets the
114
+ * consumer patch the session/account before PayPal creates the order, and lets
115
+ * them abort the click entirely by returning `proceed: false`.
116
+ */
117
+ type DirectPayPalRunBeforeButtonClick = (method: CheckoutButtonMethod) => Promise<DirectPayPalBeforeButtonClickResult>;
118
+ type DirectPayPalInitializationState = 'loading' | 'retrying' | 'ready' | 'exhausted';
119
+ type DirectPayPalTechnicalFailureHandler = (method: 'paypal', err: unknown, options?: {
120
+ code?: string;
121
+ popupBlocked?: boolean;
122
+ }) => void;
123
+ interface DirectPayPalButtonProps {
124
+ /** Checkout session ID. */
125
+ sessionId: string;
126
+ /**
127
+ * Session-bound checkout token returned by session creation. Forwarded as
128
+ * `x-checkout-session-token` on every continuation request — required by
129
+ * post-#640 backends. `FloPayCheckout` plumbs this prop automatically.
130
+ */
131
+ nonce?: string;
132
+ /** Billing API base URL. */
133
+ billingApiUrl: string;
134
+ /** Buyer email. */
135
+ email?: string;
136
+ /** PayPal client identifier (`gateways.paypal.publishableKey`). */
137
+ clientId: string;
138
+ /** Gateway environment, drives the sandbox/live SDK script. */
139
+ environment?: GatewayEnvironment;
140
+ /** ISO 4217 currency code. */
141
+ currency: string;
142
+ /** Whether the session is a subscription (drives intent + flow selection). */
143
+ isSubscription: boolean;
144
+ /**
145
+ * Provider object the backend advertised for this PayPal continuation.
146
+ * When omitted, legacy sessions continue to derive the flow from
147
+ * `isSubscription`. An advertised `'order'`/`'setup_token'` opts intent and
148
+ * process requests into the Flo-owned `paypal_vaulted` payment-method
149
+ * channel; an advertised `'subscription'` or an omission keeps the released
150
+ * `paypal` requests byte-identical.
151
+ */
152
+ providerObjectType?: PayPalProviderObjectType;
153
+ /**
154
+ * If provided, called with the tokenized body once PayPal capture
155
+ * completes. When omitted, the component processes payment internally.
156
+ */
157
+ onTokenizedBody?: DirectPayPalTokenizedHandler;
158
+ /** Called when the full self-contained payment flow succeeds. */
159
+ onComplete?: (result: PaymentResult) => void;
160
+ /** Called when an error occurs. */
161
+ onErrorChange?: (error: string | null) => void;
162
+ /** Decline emitter (mirrors SplitCardForm semantics). */
163
+ onDecline?: (decline: DeclineEvent) => void;
164
+ /** Called for post-click technical failures before PayPal authorization completes. */
165
+ onTechnicalFailure?: DirectPayPalTechnicalFailureHandler;
166
+ /** External processing state. */
167
+ isProcessing?: boolean;
168
+ /** Notify the parent of the loading state for placeholder swapping. */
169
+ onLoadStateChange?: (ready: boolean) => void;
170
+ /** Notify a PayPal-only wrapper about pre-render recovery state. */
171
+ onInitializationStateChange?: (state: DirectPayPalInitializationState) => void;
172
+ /** Disable the automatic retry for a buyer-initiated single manual attempt. */
173
+ allowAutomaticRetry?: boolean;
174
+ /** Tracks button-click for analytics. */
175
+ onButtonClick?: (method: CheckoutButtonMethod) => void;
176
+ /**
177
+ * Click-time gate (runs before PayPal creates the order). When provided, the
178
+ * returned patch is applied to the in-flight create-intent and tokenized
179
+ * dispatch so callers using `onBeforeButtonClick` see the same session/email
180
+ * the Stripe-rendered PayPal flow does.
181
+ */
182
+ runBeforeButtonClick?: DirectPayPalRunBeforeButtonClick;
183
+ /** Backing session — used for self-contained accountData population. */
184
+ session?: CheckoutSession | null;
185
+ /**
186
+ * Pre-existing PayPal Order id (or Subscription id when `isSubscription` is
187
+ * true) to bind the button to. When set, the button skips its usual
188
+ * session-scoped create-intent round-trip on click and feeds this
189
+ * id straight into PayPal's create-order / create-subscription callback.
190
+ *
191
+ * Used by `SplitCardForm`'s `paypal_direct_required` retry path: backend
192
+ * creates a fresh PayPal order after a stalled process attempt and returns
193
+ * its id; the SDK re-renders this button bound to that id so the buyer can
194
+ * confirm with one more click without the backend re-creating the order on
195
+ * each retry.
196
+ *
197
+ * Changing this value remounts the PayPal SDK so the new createOrder
198
+ * binding takes effect (PayPal's render() options aren't live-updatable).
199
+ */
200
+ existingOrderId?: string;
201
+ /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
202
+ telemetry?: boolean;
203
+ /**
204
+ * When true, renders an on-screen lifecycle tracer panel above the button
205
+ * (mount, loadScript, eligibility, render, errors). Intended for debugging
206
+ * in-app browsers (Facebook IAB, etc.) where remote console access is
207
+ * impractical. Off by default — leave disabled in production.
208
+ */
209
+ debug?: boolean;
210
+ }
211
+ /** Public direct-PayPal surface: telemetry accepts only the boolean opt-out. */
212
+ declare function DirectPayPalButton(props: DirectPayPalButtonProps): React.ReactElement | null;
213
+
214
+ /** Common props shared by all element components. */
215
+ interface ElementComponentProps {
216
+ /** Additional CSS class for the wrapper div. */
217
+ className?: string;
218
+ /** Element id attribute for the wrapper div. */
219
+ id?: string;
220
+ /** Inline styles for the wrapper div. */
221
+ style?: React.CSSProperties;
222
+ /** Options forwarded to the underlying element. */
223
+ options?: Partial<ElementOptions>;
224
+ /** Fired when the element's value changes. */
225
+ onChange?: (event: ElementChangeEvent) => void;
226
+ /** Fired when the element is fully rendered and ready. */
227
+ onReady?: () => void;
228
+ /** Fired when the element gains focus. */
229
+ onFocus?: () => void;
230
+ /** Fired when the element loses focus. */
231
+ onBlur?: () => void;
232
+ /** Fired when the Escape key is pressed inside the element. */
233
+ onEscape?: () => void;
234
+ }
235
+ /** Props for the standalone non-card Payment Element. */
236
+ interface PaymentElementProps extends Omit<ElementComponentProps, 'options'> {
237
+ /**
238
+ * Element options with an explicit wallet/APM allowlist. `card` is removed
239
+ * at runtime; an empty result is rejected before the provider is called.
240
+ */
241
+ options: Omit<Partial<ElementOptions>, 'paymentMethodTypes'> & {
242
+ paymentMethodTypes: readonly string[];
39
243
  };
40
- children: React.ReactNode;
41
244
  }
42
245
  /**
43
- * Provides FloPay SDK context to the component tree.
44
- *
45
- * Wrap provider-context elements with this provider:
46
- *
47
- * ```tsx
48
- * <FloPayProvider flopay={loadFloPay('pk_test_...')}>
49
- * <PaymentElement options={{ paymentMethodTypes: ['cashapp', 'ideal'] }} />
50
- * </FloPayProvider>
51
- * ```
52
- *
53
- * `FloPayCheckout` is a standalone integration that owns its provider and
54
- * session-specific Elements setup:
55
- *
56
- * ```tsx
57
- * <FloPayCheckout sessionId="sess_..." />
58
- * ```
246
+ * Renders a provider Payment Element restricted to the declared non-card
247
+ * wallet/APM methods. Card collection is available only through the hosted
248
+ * vault checkout surfaces.
249
+ */
250
+ declare const PaymentElement: React.FC<PaymentElementProps>;
251
+ /**
252
+ * Renders an address input element.
59
253
  */
60
- declare function FloPayProvider({ flopay: floPayProp, paypalFlopay: paypalFloPayProp, options, children, }: FloPayProviderProps): React.ReactElement;
254
+ declare const AddressElement: React.FC<ElementComponentProps>;
61
255
 
62
256
  /** Props for the all-in-one `FloPayCheckout` wrapper. */
63
257
  interface FloPayCheckoutProps {
@@ -94,6 +288,8 @@ interface FloPayCheckoutProps {
94
288
  onComplete?: (result: PaymentResult) => void;
95
289
  /** Called when a payment error occurs. */
96
290
  onError?: (error: FloPayError) => void;
291
+ /** Receives the versioned, privacy-safe checkout instrument feed. */
292
+ onInstrument?: (event: FloInstrumentEvent) => void;
97
293
  /** Called when a payment is declined or the authentication step fails. */
98
294
  onDecline?: (decline: DeclineEvent) => void;
99
295
  /** Called when the AVS country dropdown changes. */
@@ -189,7 +385,7 @@ interface FloPayCheckoutProps {
189
385
  * In `layout="buttons"` with `createSession`, the returned patch is merged
190
386
  * into the inline session params before the selected flow continues.
191
387
  */
192
- onBeforeButtonClick?: (event: BeforeButtonClickEvent) => void | false | Promise<void | false | InlineSessionPatch> | InlineSessionPatch;
388
+ onBeforeButtonClick?: (event: BeforeButtonClickEvent) => undefined | false | Promise<undefined | false | InlineSessionPatch> | InlineSessionPatch;
193
389
  /**
194
390
  * Enable AVS (Address Verification).
195
391
  * - `true` — show country + postal code (backward compatible default)
@@ -261,7 +457,7 @@ interface FloPayCheckoutProps {
261
457
  * />
262
458
  * ```
263
459
  */
264
- declare function FloPayCheckout({ sessionId: sessionIdProp, nonce: nonceProp, createSession: createSessionParams, billingApiUrl, telemetry, appearance: appearanceOverride, locale, loading: loadingNode, error: errorNode, onComplete, onError, onDecline, onCountryChange, onZipChange, showPayPal, showStripe, enabledPaymentMethods: enabledPaymentMethodsProp, showApplePay, showGooglePay, debug, layout, theme, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, showSecurityFooter: _showSecurityFooter, onButtonClick, onBeforeButtonClick, enableAVS, cardFieldOrder, cardPreFormSlot, avsLayout, className, initialErrorMessage, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
460
+ declare function FloPayCheckout({ sessionId: sessionIdProp, nonce: nonceProp, createSession: createSessionParams, billingApiUrl, telemetry, appearance: appearanceOverride, locale, loading: loadingNode, error: errorNode, onComplete, onError, onInstrument, onDecline, onCountryChange, onZipChange, showPayPal, showStripe, enabledPaymentMethods: enabledPaymentMethodsProp, showApplePay, showGooglePay, debug, layout, theme, buttonsTheme, buttonsStyles, cardButtonContent, cardBackButtonContent, cardTitleContent, showSecurityFooter: _showSecurityFooter, onButtonClick, onBeforeButtonClick, enableAVS, cardFieldOrder, cardPreFormSlot, avsLayout, className, initialErrorMessage, children, checkoutMode: checkoutModeProp, confirmLabel, renderConfirmButton, onSessionCompleted, }: FloPayCheckoutProps): React.ReactElement;
265
461
 
266
462
  /**
267
463
  * Returns the current `FloPay` instance, or `null` if the provider
@@ -300,47 +496,121 @@ interface CheckoutState {
300
496
  */
301
497
  declare function useCheckout(): CheckoutState;
302
498
 
303
- /** Common props shared by all element components. */
304
- interface ElementComponentProps {
305
- /** Additional CSS class for the wrapper div. */
306
- className?: string;
307
- /** Element id attribute for the wrapper div. */
308
- id?: string;
309
- /** Inline styles for the wrapper div. */
310
- style?: React.CSSProperties;
311
- /** Options forwarded to the underlying element. */
312
- options?: Partial<ElementOptions>;
313
- /** Fired when the element's value changes. */
314
- onChange?: (event: ElementChangeEvent) => void;
315
- /** Fired when the element is fully rendered and ready. */
316
- onReady?: () => void;
317
- /** Fired when the element gains focus. */
318
- onFocus?: () => void;
319
- /** Fired when the element loses focus. */
320
- onBlur?: () => void;
321
- /** Fired when the Escape key is pressed inside the element. */
322
- onEscape?: () => void;
323
- }
324
- /** Props for the standalone non-card Payment Element. */
325
- interface PaymentElementProps extends Omit<ElementComponentProps, 'options'> {
499
+ /**
500
+ * Props for the `PayPalButton` component.
501
+ *
502
+ * Must be rendered inside its own `FloPayProvider` with `paymentMethodCreation: undefined`
503
+ * (not 'manual') because this PayPal flow needs automatic payment-method creation.
504
+ */
505
+ interface PayPalButtonProps {
506
+ /** The checkout session ID (UUID from billing API). */
507
+ sessionId: string;
326
508
  /**
327
- * Element options with an explicit wallet/APM allowlist. `card` is removed
328
- * at runtime; an empty result is rejected before the provider is called.
509
+ * Session-bound checkout token returned by session creation. Forwarded as
510
+ * `x-checkout-session-token` on continuation requests required by
511
+ * post-#640 backends.
329
512
  */
330
- options: Omit<Partial<ElementOptions>, 'paymentMethodTypes'> & {
331
- paymentMethodTypes: readonly string[];
332
- };
513
+ nonce?: string;
514
+ /** Billing API base URL. Optional — defaults to the value from FloPayProvider or the shared constant. */
515
+ billingApiUrl?: string;
516
+ /** User's email. */
517
+ email?: string;
518
+ /** User ID for processing payments. */
519
+ userId?: string;
520
+ /** First name for billing. */
521
+ firstName?: string;
522
+ /** Last name for billing. */
523
+ lastName?: string;
524
+ /** Checkout version for tracking. */
525
+ chv?: string;
526
+ /**
527
+ * Called with tokenized data after PayPal authorization.
528
+ * If omitted, the component calls processPayment internally.
529
+ */
530
+ onTokenizedBody?: (body: TokenizedBody) => void;
531
+ /** Called on successful payment (self-contained mode). */
532
+ onComplete?: () => void;
533
+ /** Called when an error occurs. */
534
+ onErrorChange?: (error: string | null) => void;
535
+ /** External processing state. */
536
+ isProcessing?: boolean;
333
537
  }
334
538
  /**
335
- * Renders a provider Payment Element restricted to the declared non-card
336
- * wallet/APM methods. Card collection is available only through the hosted
337
- * vault checkout surfaces.
539
+ * PayPal button that handles the full PayPal payment flow.
540
+ *
541
+ * **Important**: PayPal requires its own `FloPayProvider` with automatic
542
+ * payment-method creation. Keep it separate from manually created wallet/APM
543
+ * Elements groups.
544
+ *
545
+ * ```tsx
546
+ * {/* Main checkout provider *\/}
547
+ * <FloPayProvider flopay={flopay} options={{ amount, currency }}>
548
+ * <SplitCardForm ... />
549
+ * </FloPayProvider>
550
+ *
551
+ * {/* PayPal provider (no paymentMethodCreation) *\/}
552
+ * <FloPayProvider flopay={flopay} options={{ amount, currency, paymentMethodCreation: 'auto' }}>
553
+ * <PayPalButton ... />
554
+ * </FloPayProvider>
555
+ * ```
338
556
  */
339
- declare const PaymentElement: React.FC<PaymentElementProps>;
557
+ declare function PayPalButton({ sessionId, nonce, billingApiUrl, email, userId, firstName, lastName, chv, onTokenizedBody, onComplete, onErrorChange, isProcessing, }: PayPalButtonProps): React.ReactElement;
558
+
559
+ /** Props for the `FloPayProvider` component. */
560
+ interface FloPayProviderProps {
561
+ /** A `FloPay` instance or a promise that resolves to one (from `loadFloPay()`). */
562
+ flopay: Promise<FloPay> | FloPay;
563
+ /**
564
+ * Optional Stripe `FloPay` instance used to drive the Stripe-rendered PayPal
565
+ * fallback. When omitted or `null`, the Stripe-rendered PayPal button is
566
+ * not rendered. Direct PayPal (`gateways.paypal`) does not use this prop.
567
+ */
568
+ paypalFlopay?: Promise<FloPay> | FloPay | null;
569
+ /** Optional configuration applied when creating the elements group. */
570
+ options?: {
571
+ locale?: string;
572
+ appearance?: FloPayAppearance;
573
+ /**
574
+ * Client secret for an existing non-card PaymentIntent or SetupIntent.
575
+ * The SDK verifies the provider intent against the `PaymentElement`'s
576
+ * explicit `paymentMethodTypes` allowlist before mounting and rejects card
577
+ * or undeclared methods. Card checkout uses the hosted vault.
578
+ */
579
+ clientSecret?: string;
580
+ /** Total amount in cents for deferred non-card Elements without a client secret. */
581
+ amount?: number;
582
+ /** ISO 4217 currency code for deferred non-card Elements without a client secret. */
583
+ currency?: string;
584
+ /** How non-card payment methods are created: `'manual'` or `'auto'` (needed for PayPal). */
585
+ paymentMethodCreation?: 'manual' | 'auto';
586
+ /** Requests reusable payment credentials for future payments. */
587
+ setupFutureUsage?: 'off_session' | 'on_session';
588
+ /** Billing API base URL. Set once here so child components don't need to repeat it. */
589
+ billingApiUrl?: string;
590
+ };
591
+ /** Receives the versioned, privacy-safe checkout instrument feed. */
592
+ onInstrument?: (event: FloInstrumentEvent) => void;
593
+ children: React.ReactNode;
594
+ }
340
595
  /**
341
- * Renders an address input element.
596
+ * Provides FloPay SDK context to the component tree.
597
+ *
598
+ * Wrap provider-context elements with this provider:
599
+ *
600
+ * ```tsx
601
+ * <FloPayProvider flopay={loadFloPay('pk_test_...')}>
602
+ * <PaymentElement options={{ paymentMethodTypes: ['cashapp', 'ideal'] }} />
603
+ * </FloPayProvider>
604
+ * ```
605
+ *
606
+ * `FloPayCheckout` is a standalone integration that owns its provider and
607
+ * session-specific Elements setup:
608
+ *
609
+ * ```tsx
610
+ * <FloPayCheckout sessionId="sess_..." />
611
+ * ```
342
612
  */
343
- declare const AddressElement: React.FC<ElementComponentProps>;
613
+ declare function FloPayProvider({ flopay: floPayProp, paypalFlopay: paypalFloPayProp, options, onInstrument, children, }: FloPayProviderProps): React.ReactElement;
344
614
 
345
615
  type MaybePromise<T> = T | Promise<T>;
346
616
 
@@ -487,425 +757,159 @@ interface SplitCardFormProps {
487
757
  */
488
758
  onButtonClick?: (method: CheckoutButtonMethod) => void;
489
759
  /**
490
- * Called before a payment button continues in `layout="buttons"`.
491
- * Runs for card, PayPal, Apple Pay, and Google Pay.
492
- */
493
- onBeforeButtonClick?: (event: BeforeButtonClickEvent) => MaybePromise<void | false | InlineSessionPatch>;
494
- /**
495
- * Enable AVS (Address Verification).
496
- * - `true` — show country + postal code (backward compatible default)
497
- * - `AVSFieldConfig` — granular per-field control, optionally scoped to country codes
498
- * - `false` / omitted — AVS disabled
499
- */
500
- enableAVS?: boolean | AVSFieldConfig;
501
- /**
502
- * Per-merchant order of the hosted vault card rows — a permutation of
503
- * `['name','number','expiry']` (`'expiry'` is the combined expiry+CVV row;
504
- * the submit button stays last). Drives both the visual order and the tab
505
- * order inside the widget. Omit for the default (`name`, `number`, `expiry`).
506
- * Only applies on the vault card path.
507
- */
508
- cardFieldOrder?: _flopay_shared.VaultCardFieldKey[];
509
- /** Content rendered above the hosted vault card widget (below the wallet divider). */
510
- cardPreFormSlot?: React.ReactNode;
511
- /** Layout for AVS fields: 'row' (side-by-side, default) or 'column' (stacked). */
512
- avsLayout?: 'row' | 'column';
513
- /** Pre-filled country code (ISO 3166-1 alpha-2) for AVS. */
514
- country?: string;
515
- /** Pre-filled ZIP/postal code for AVS. */
516
- zip?: string;
517
- /** Pre-filled street address (line 1) for AVS. Typically from a partner GeoIP / profile lookup. */
518
- addressLine1?: string;
519
- /** Pre-filled apt/suite/unit (line 2) for AVS. */
520
- addressLine2?: string;
521
- /** Pre-filled city for AVS. Typically from a partner GeoIP / profile lookup. */
522
- city?: string;
523
- /** Pre-filled state/province for AVS. Typically from a partner GeoIP / profile lookup. */
524
- state?: string;
525
- /** Callback when AVS country changes. */
526
- onCountryChange?: (country: string) => void;
527
- /** Callback when AVS ZIP/postal code changes. */
528
- onZipChange?: (zip: string) => void;
529
- /** Whether AVS was enabled (sent to backend for analytics). */
530
- avsCheck?: boolean;
531
- /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */
532
- checkoutType?: string;
533
- /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */
534
- checkoutLayout?: string;
535
- /** Total amount in cents (smallest currency unit). Used for wallet/PayPal Elements config. */
536
- totalAmount?: number;
537
- /** Currency code (used for PayPal Elements config). */
538
- currency?: string;
539
- /** Render the card form expanded on first paint when `layout="buttons"`. */
540
- initialCardOpen?: boolean;
541
- /**
542
- * Direct PayPal gateway configuration. When provided, PayPal renders via
543
- * the official PayPal JS SDK (in-app browser compliant) instead of via
544
- * Stripe's ExpressCheckoutElement. Selection is mutually exclusive:
545
- * setting this disables the Stripe-rendered PayPal path automatically.
546
- */
547
- directPaypal?: {
548
- clientId: string;
549
- environment?: GatewayEnvironment;
550
- providerObjectType?: PayPalProviderObjectType;
551
- };
552
- /** Whether the active session represents a subscription (drives direct PayPal intent). */
553
- isSubscription?: boolean;
554
- /** Backing session — forwarded to direct-PayPal so it can populate accountData. */
555
- session?: CheckoutSession | null;
556
- /**
557
- * True while a **detached** session's background claim is still in flight
558
- * (TeamFloPay/backend#1099).
559
- *
560
- * The hosted card widget is already mounted and the buyer can fill it in, but
561
- * the session has no cart attached yet, so nothing may be submitted: the
562
- * billing API rejects process / intent calls on an unclaimed session with
563
- * `409 checkout_session_data_attachment_required`, and holds an unclaimed
564
- * vault charge with a retryable `503`. While true, the card submit is gated
565
- * and the non-card surfaces stay hidden; all of them enable together the
566
- * moment the claim lands. `FloPayCheckout` plumbs this prop automatically.
567
- */
568
- dataAttachmentPending?: boolean;
569
- /**
570
- * Enables on-screen diagnostic panels for the PayPal/wallet gating decision
571
- * and the `DirectPayPalButton` lifecycle. Intended for debugging in-app
572
- * browsers where remote console access is impractical. Off by default.
573
- */
574
- debug?: boolean;
575
- }
576
- /**
577
- * Checkout surface combining hosted vault card capture with wallets, APMs,
578
- * and PayPal. Card entry is hosted-vault-only.
579
- *
580
- * Stripe-hosted PayPal uses its own Elements instance; direct PayPal uses the
581
- * official PayPal SDK when the session advertises that gateway.
582
- */
583
- declare function SplitCardForm(props: SplitCardFormProps): React.JSX.Element;
584
-
585
- /** Props for {@link VaultCardFields}. */
586
- interface VaultCardFieldsProps {
587
- /**
588
- * The card-capture adapter (typically `useFloPay().cardCapture()`). Owns
589
- * injecting + bootstrapping the hosted vault widget. Changing this instance
590
- * (or {@link VaultCardFieldsProps.html}) remounts the widget.
591
- */
592
- capture: CardCaptureAdapter;
593
- /**
594
- * Server-rendered hosted vault widget HTML (the session's
595
- * {@link CheckoutSession.vault} block `html`, or one fetched from
596
- * `POST /vault/capture`). The widget owns the card fields, submit button,
597
- * tokenization, charge, and 3DS; this component only injects it.
598
- */
599
- html: string;
600
- /**
601
- * Per-session integrity token (the vault block's `messageToken`). Forwarded
602
- * to the adapter so it can reject forged terminal `postMessage` outcomes that
603
- * omit/mismatch it. Omitted when the backend does not (yet) mint one.
604
- */
605
- messageToken?: string;
606
- /**
607
- * Exact origin expected for the widget's terminal `postMessage` outcomes
608
- * (the vault block's `expectedOrigin`). Forwarded to the adapter's origin
609
- * gate; omitted to skip it.
610
- */
611
- expectedOrigin?: string;
612
- /**
613
- * Merchant theme colors pushed into the hosted widget so the card form
614
- * matches the surrounding checkout. Applied live on change (no remount).
615
- */
616
- theme?: VaultCardThemeColors;
617
- /** Inline styles for the container the widget mounts into. */
618
- containerStyle?: React.CSSProperties;
619
- /** Fired once the widget is injected and bootstrapping. */
620
- onReady?: () => void;
621
- /**
622
- * Fired with a load/runtime error message from the widget, or `null` when it
623
- * clears. Wired to the card form's shared error banner. Terminal payment
624
- * outcomes (`complete` / `decline`) are observed by the parent form directly
625
- * off the same adapter and are not surfaced here.
626
- */
627
- onError?: (message: string | null) => void;
628
- /**
629
- * Fired with the widget's inline field-validation message (live, debounced by
630
- * the widget to changes), or `null` when validation clears. Surfaced in the
631
- * card form's error banner and the merchant `onError`.
632
- */
633
- onValidation?: (message: string | null) => void;
634
- }
635
- /**
636
- * Renders the backend-served vault PCI card widget
637
- * (TeamFloPay/backend#823, Model A). The hosted widget
638
- * is a self-contained form: PAN / CVC, the submit button, the charge, and 3DS
639
- * all live inside it. This component only injects the widget HTML through the
640
- * {@link CardCaptureAdapter} and bridges its `ready` / `error` lifecycle events
641
- * back to the surrounding card form.
642
- */
643
- declare function VaultCardFields({ capture, html, messageToken, expectedOrigin, theme, containerStyle, onReady, onError, onValidation, }: VaultCardFieldsProps): React.ReactElement;
644
-
645
- /**
646
- * Props for the `PayPalButton` component.
647
- *
648
- * Must be rendered inside its own `FloPayProvider` with `paymentMethodCreation: undefined`
649
- * (not 'manual') because this PayPal flow needs automatic payment-method creation.
650
- */
651
- interface PayPalButtonProps {
652
- /** The checkout session ID (UUID from billing API). */
653
- sessionId: string;
654
- /**
655
- * Session-bound checkout token returned by session creation. Forwarded as
656
- * `x-checkout-session-token` on continuation requests — required by
657
- * post-#640 backends.
658
- */
659
- nonce?: string;
660
- /** Billing API base URL. Optional — defaults to the value from FloPayProvider or the shared constant. */
661
- billingApiUrl?: string;
662
- /** User's email. */
663
- email?: string;
664
- /** User ID for processing payments. */
665
- userId?: string;
666
- /** First name for billing. */
667
- firstName?: string;
668
- /** Last name for billing. */
669
- lastName?: string;
670
- /** Checkout version for tracking. */
671
- chv?: string;
672
- /**
673
- * Called with tokenized data after PayPal authorization.
674
- * If omitted, the component calls processPayment internally.
675
- */
676
- onTokenizedBody?: (body: TokenizedBody) => void;
677
- /** Called on successful payment (self-contained mode). */
678
- onComplete?: () => void;
679
- /** Called when an error occurs. */
680
- onErrorChange?: (error: string | null) => void;
681
- /** External processing state. */
682
- isProcessing?: boolean;
683
- }
684
- /**
685
- * PayPal button that handles the full PayPal payment flow.
686
- *
687
- * **Important**: PayPal requires its own `FloPayProvider` with automatic
688
- * payment-method creation. Keep it separate from manually created wallet/APM
689
- * Elements groups.
690
- *
691
- * ```tsx
692
- * {/* Main checkout provider *\/}
693
- * <FloPayProvider flopay={flopay} options={{ amount, currency }}>
694
- * <SplitCardForm ... />
695
- * </FloPayProvider>
696
- *
697
- * {/* PayPal provider (no paymentMethodCreation) *\/}
698
- * <FloPayProvider flopay={flopay} options={{ amount, currency, paymentMethodCreation: 'auto' }}>
699
- * <PayPalButton ... />
700
- * </FloPayProvider>
701
- * ```
702
- */
703
- declare function PayPalButton({ sessionId, nonce, billingApiUrl, email, userId, firstName, lastName, chv, onTokenizedBody, onComplete, onErrorChange, isProcessing, }: PayPalButtonProps): React.ReactElement;
704
-
705
- /**
706
- * Overrides that `SplitCardForm`'s tokenized-body dispatcher uses to apply a
707
- * `runBeforeButtonClick` patch to the in-flight processPayment call. Kept in
708
- * sync structurally with `TokenizedBodyOverrides` in `split-card-form.tsx`.
709
- */
710
- interface DirectPayPalTokenizedOverrides {
711
- accountPatch?: InlineSessionPatch['account'];
712
- sessionId?: string;
713
- nonce?: string;
714
- }
715
- /**
716
- * Internal handler signature aligned with `SplitCardForm`'s tokenized-body
717
- * dispatcher. Direct PayPal completes via the backend's process endpoint and
718
- * never produces a Stripe PaymentIntent, so we still forward a synthetic
719
- * `TokenizedBody` describing the captured order, optionally with the
720
- * session/account patch captured at click-time.
721
- */
722
- type DirectPayPalTokenizedHandler = (body: TokenizedBody, overrides?: DirectPayPalTokenizedOverrides) => void;
723
- /** Click-time `runBeforeButtonClick` result, structurally compatible with `SplitCardForm`. */
724
- interface DirectPayPalBeforeButtonClickResult {
725
- proceed: boolean;
726
- accountPatch?: InlineSessionPatch['account'];
727
- sessionId?: string;
728
- nonce?: string;
729
- }
730
- /**
731
- * Click-time gate. Mirrors `RunBeforeButtonClick` in `SplitCardForm`: lets the
732
- * consumer patch the session/account before PayPal creates the order, and lets
733
- * them abort the click entirely by returning `proceed: false`.
734
- */
735
- type DirectPayPalRunBeforeButtonClick = (method: CheckoutButtonMethod) => Promise<DirectPayPalBeforeButtonClickResult>;
736
- type DirectPayPalInitializationState = 'loading' | 'retrying' | 'ready' | 'exhausted';
737
- type DirectPayPalTechnicalFailureHandler = (method: 'paypal', err: unknown, options?: {
738
- code?: string;
739
- popupBlocked?: boolean;
740
- }) => void;
741
- interface DirectPayPalButtonProps {
742
- /** Checkout session ID. */
743
- sessionId: string;
744
- /**
745
- * Session-bound checkout token returned by session creation. Forwarded as
746
- * `x-checkout-session-token` on every continuation request — required by
747
- * post-#640 backends. `FloPayCheckout` plumbs this prop automatically.
760
+ * Called before a payment button continues in `layout="buttons"`.
761
+ * Runs for card, PayPal, Apple Pay, and Google Pay.
748
762
  */
749
- nonce?: string;
750
- /** Billing API base URL. */
751
- billingApiUrl: string;
752
- /** Buyer email. */
753
- email?: string;
754
- /** PayPal client identifier (`gateways.paypal.publishableKey`). */
755
- clientId: string;
756
- /** Gateway environment, drives the sandbox/live SDK script. */
757
- environment?: GatewayEnvironment;
758
- /** ISO 4217 currency code. */
759
- currency: string;
760
- /** Whether the session is a subscription (drives intent + flow selection). */
761
- isSubscription: boolean;
763
+ onBeforeButtonClick?: (event: BeforeButtonClickEvent) => MaybePromise<undefined | false | InlineSessionPatch>;
762
764
  /**
763
- * Provider object the backend advertised for this PayPal continuation.
764
- * When omitted, legacy sessions continue to derive the flow from
765
- * `isSubscription`. An advertised `'order'`/`'setup_token'` opts intent and
766
- * process requests into the Flo-owned `paypal_vaulted` payment-method
767
- * channel; an advertised `'subscription'` or an omission keeps the released
768
- * `paypal` requests byte-identical.
765
+ * Enable AVS (Address Verification).
766
+ * - `true` show country + postal code (backward compatible default)
767
+ * - `AVSFieldConfig` granular per-field control, optionally scoped to country codes
768
+ * - `false` / omitted AVS disabled
769
769
  */
770
- providerObjectType?: PayPalProviderObjectType;
770
+ enableAVS?: boolean | AVSFieldConfig;
771
771
  /**
772
- * If provided, called with the tokenized body once PayPal capture
773
- * completes. When omitted, the component processes payment internally.
772
+ * Per-merchant order of the hosted vault card rows — a permutation of
773
+ * `['name','number','expiry']` (`'expiry'` is the combined expiry+CVV row;
774
+ * the submit button stays last). Drives both the visual order and the tab
775
+ * order inside the widget. Omit for the default (`name`, `number`, `expiry`).
776
+ * Only applies on the vault card path.
774
777
  */
775
- onTokenizedBody?: DirectPayPalTokenizedHandler;
776
- /** Called when the full self-contained payment flow succeeds. */
777
- onComplete?: (result: PaymentResult) => void;
778
- /** Called when an error occurs. */
779
- onErrorChange?: (error: string | null) => void;
780
- /** Decline emitter (mirrors SplitCardForm semantics). */
781
- onDecline?: (decline: DeclineEvent) => void;
782
- /** Called for post-click technical failures before PayPal authorization completes. */
783
- onTechnicalFailure?: DirectPayPalTechnicalFailureHandler;
784
- /** External processing state. */
785
- isProcessing?: boolean;
786
- /** Notify the parent of the loading state for placeholder swapping. */
787
- onLoadStateChange?: (ready: boolean) => void;
788
- /** Notify a PayPal-only wrapper about pre-render recovery state. */
789
- onInitializationStateChange?: (state: DirectPayPalInitializationState) => void;
790
- /** Disable the automatic retry for a buyer-initiated single manual attempt. */
791
- allowAutomaticRetry?: boolean;
792
- /** Tracks button-click for analytics. */
793
- onButtonClick?: (method: CheckoutButtonMethod) => void;
778
+ cardFieldOrder?: _flopay_shared.VaultCardFieldKey[];
779
+ /** Content rendered above the hosted vault card widget (below the wallet divider). */
780
+ cardPreFormSlot?: React.ReactNode;
781
+ /** Layout for AVS fields: 'row' (side-by-side, default) or 'column' (stacked). */
782
+ avsLayout?: 'row' | 'column';
783
+ /** Pre-filled country code (ISO 3166-1 alpha-2) for AVS. */
784
+ country?: string;
785
+ /** Pre-filled ZIP/postal code for AVS. */
786
+ zip?: string;
787
+ /** Pre-filled street address (line 1) for AVS. Typically from a partner GeoIP / profile lookup. */
788
+ addressLine1?: string;
789
+ /** Pre-filled apt/suite/unit (line 2) for AVS. */
790
+ addressLine2?: string;
791
+ /** Pre-filled city for AVS. Typically from a partner GeoIP / profile lookup. */
792
+ city?: string;
793
+ /** Pre-filled state/province for AVS. Typically from a partner GeoIP / profile lookup. */
794
+ state?: string;
795
+ /** Callback when AVS country changes. */
796
+ onCountryChange?: (country: string) => void;
797
+ /** Callback when AVS ZIP/postal code changes. */
798
+ onZipChange?: (zip: string) => void;
799
+ /** Whether AVS was enabled (sent to backend for analytics). */
800
+ avsCheck?: boolean;
801
+ /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */
802
+ checkoutType?: string;
803
+ /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */
804
+ checkoutLayout?: string;
805
+ /** Total amount in cents (smallest currency unit). Used for wallet/PayPal Elements config. */
806
+ totalAmount?: number;
807
+ /** Currency code (used for PayPal Elements config). */
808
+ currency?: string;
809
+ /** Render the card form expanded on first paint when `layout="buttons"`. */
810
+ initialCardOpen?: boolean;
794
811
  /**
795
- * Click-time gate (runs before PayPal creates the order). When provided, the
796
- * returned patch is applied to the in-flight create-intent and tokenized
797
- * dispatch so callers using `onBeforeButtonClick` see the same session/email
798
- * the Stripe-rendered PayPal flow does.
812
+ * Direct PayPal gateway configuration. When provided, PayPal renders via
813
+ * the official PayPal JS SDK (in-app browser compliant) instead of via
814
+ * Stripe's ExpressCheckoutElement. Selection is mutually exclusive:
815
+ * setting this disables the Stripe-rendered PayPal path automatically.
799
816
  */
800
- runBeforeButtonClick?: DirectPayPalRunBeforeButtonClick;
801
- /** Backing session — used for self-contained accountData population. */
817
+ directPaypal?: {
818
+ clientId: string;
819
+ environment?: GatewayEnvironment;
820
+ providerObjectType?: PayPalProviderObjectType;
821
+ };
822
+ /** Whether the active session represents a subscription (drives direct PayPal intent). */
823
+ isSubscription?: boolean;
824
+ /** Backing session — forwarded to direct-PayPal so it can populate accountData. */
802
825
  session?: CheckoutSession | null;
803
826
  /**
804
- * Pre-existing PayPal Order id (or Subscription id when `isSubscription` is
805
- * true) to bind the button to. When set, the button skips its usual
806
- * session-scoped create-intent round-trip on click and feeds this
807
- * id straight into PayPal's create-order / create-subscription callback.
808
- *
809
- * Used by `SplitCardForm`'s `paypal_direct_required` retry path: backend
810
- * creates a fresh PayPal order after a stalled process attempt and returns
811
- * its id; the SDK re-renders this button bound to that id so the buyer can
812
- * confirm with one more click without the backend re-creating the order on
813
- * each retry.
827
+ * True while a **detached** session's background claim is still in flight
828
+ * (TeamFloPay/backend#1099).
814
829
  *
815
- * Changing this value remounts the PayPal SDK so the new createOrder
816
- * binding takes effect (PayPal's render() options aren't live-updatable).
830
+ * The hosted card widget is already mounted and the buyer can fill it in, but
831
+ * the session has no cart attached yet, so nothing may be submitted: the
832
+ * billing API rejects process / intent calls on an unclaimed session with
833
+ * `409 checkout_session_data_attachment_required`, and holds an unclaimed
834
+ * vault charge with a retryable `503`. While true, the card submit is gated
835
+ * and the non-card surfaces stay hidden; all of them enable together the
836
+ * moment the claim lands. `FloPayCheckout` plumbs this prop automatically.
817
837
  */
818
- existingOrderId?: string;
819
- /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
820
- telemetry?: boolean;
838
+ dataAttachmentPending?: boolean;
821
839
  /**
822
- * When true, renders an on-screen lifecycle tracer panel above the button
823
- * (mount, loadScript, eligibility, render, errors). Intended for debugging
824
- * in-app browsers (Facebook IAB, etc.) where remote console access is
825
- * impractical. Off by default — leave disabled in production.
840
+ * Enables on-screen diagnostic panels for the PayPal/wallet gating decision
841
+ * and the `DirectPayPalButton` lifecycle. Intended for debugging in-app
842
+ * browsers where remote console access is impractical. Off by default.
826
843
  */
827
844
  debug?: boolean;
828
845
  }
829
- /** Public direct-PayPal surface: telemetry accepts only the boolean opt-out. */
830
- declare function DirectPayPalButton(props: DirectPayPalButtonProps): React.ReactElement | null;
846
+ /**
847
+ * Checkout surface combining hosted vault card capture with wallets, APMs,
848
+ * and PayPal. Card entry is hosted-vault-only.
849
+ *
850
+ * Stripe-hosted PayPal uses its own Elements instance; direct PayPal uses the
851
+ * official PayPal SDK when the session advertises that gateway.
852
+ */
853
+ declare function SplitCardForm(props: SplitCardFormProps): React.JSX.Element;
831
854
 
832
- interface FloPayAutomaticPaymentSuccessEvent {
833
- result: PaymentResult;
834
- session: CheckoutSession | null;
835
- sessionId: string | null;
836
- autoCompleted: boolean;
837
- }
838
- interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
839
- sessionId?: string;
855
+ /** Props for {@link VaultCardFields}. */
856
+ interface VaultCardFieldsProps {
840
857
  /**
841
- * Session-bound checkout token for a consumer-supplied {@link sessionId}
842
- * (the `nonce` returned when that session was created). Post-#640 backends
843
- * require it as `x-checkout-session-token` to read the session and to
844
- * `/process` it; without it the existing-session path 401s with
845
- * "Missing checkout session token.". Ignored on the create-session path,
846
- * where the SDK mints and threads the nonce itself.
858
+ * The card-capture adapter (typically `useFloPay().cardCapture()`). Owns
859
+ * injecting + bootstrapping the hosted vault widget. Changing this instance
860
+ * (or {@link VaultCardFieldsProps.html}) remounts the widget.
847
861
  */
848
- nonce?: string;
849
- createSession?: InlineSessionDraft;
862
+ capture: CardCaptureAdapter;
850
863
  /**
851
- * @deprecated Ignored. The backend now picks the customer's most recent
852
- * vaulted payment method via `getLatestByUserId` and rebinds the session's
853
- * gateway to match it (see `apps/api`'s `createSingle` auto-checkout
854
- * branch). Passing this prop has no effect it is retained only to avoid
855
- * breaking existing integrations.
864
+ * Server-rendered hosted vault widget HTML (the session's
865
+ * {@link CheckoutSession.vault} block `html`, or one fetched from
866
+ * `POST /vault/capture`). The widget owns the card fields, submit button,
867
+ * tokenization, charge, and 3DS; this component only injects it.
856
868
  */
857
- paymentMethodId?: string;
869
+ html: string;
858
870
  /**
859
- * @deprecated Ignored. The backend orchestrates gateway routing — clients
860
- * no longer choose between card and PayPal at the SDK boundary. Passing
861
- * this prop has no effect.
871
+ * Per-session integrity token (the vault block's `messageToken`). Forwarded
872
+ * to the adapter so it can reject forged terminal `postMessage` outcomes that
873
+ * omit/mismatch it. Omitted when the backend does not (yet) mint one.
862
874
  */
863
- checkoutMethod?: CheckoutButtonMethod;
864
- clientId?: string;
875
+ messageToken?: string;
865
876
  /**
866
- * Unified products array (TeamFloPay/backend#760). When supplied,
867
- * `items`/`subscriptions` are ignored. The SDK folds the legacy fields
868
- * into this shape internally.
877
+ * Exact origin expected for the widget's terminal `postMessage` outcomes
878
+ * (the vault block's `expectedOrigin`). Forwarded to the adapter's origin
879
+ * gate; omitted to skip it.
869
880
  */
870
- products?: CheckoutProduct[];
871
- items?: CheckoutItem[];
872
- subscriptions?: CheckoutSubscription[];
873
- account?: InlineSessionDraft['account'];
874
- successUrl?: string;
875
- cancelUrl?: string;
876
- couponCodes?: string[];
877
- tagsData?: InlineSessionDraft['tagsData'];
878
- utmMetadata?: InlineSessionDraft['utmMetadata'];
879
- billingApiUrl?: string;
880
- locale?: string;
881
+ expectedOrigin?: string;
881
882
  /**
882
- * High-level theme bundle that styles the button (and the fallback
883
- * `FloPayCheckout` modal that opens when the saved-payment charge needs
884
- * user interaction). One of: `'classic'`, `'modern-light'`, `'modern-dark'`,
885
- * `'bold-light'`, `'bold-dark'`, `'glass-light'`, `'glass-dark'`. Explicit
886
- * `buttonsStyles` still wins for fine-grained overrides.
883
+ * Merchant theme colors pushed into the hosted widget so the card form
884
+ * matches the surrounding checkout. Applied live on change (no remount).
887
885
  */
888
- theme?: ThemeId;
886
+ theme?: VaultCardThemeColors;
887
+ /** Inline styles for the container the widget mounts into. */
888
+ containerStyle?: React.CSSProperties;
889
+ /** Fired once the widget is injected and bootstrapping. */
890
+ onReady?: () => void;
889
891
  /**
890
- * Per-checkout appearance overrides layered on top of the chosen `theme`
891
- * (same shape as {@link FloPayCheckout}'s `appearance`). Its `colorPrimary` /
892
- * `colorPrimaryHover` / `borderRadius` re-skin the button and the fallback
893
- * `FloPayCheckout` modal — so the auto-pay button matches the rest of the
894
- * themed checkout. Without this the button only saw the bundle's defaults.
892
+ * Fired with a load/runtime error message from the widget, or `null` when it
893
+ * clears. Wired to the card form's shared error banner. Terminal payment
894
+ * outcomes (`complete` / `decline`) are observed by the parent form directly
895
+ * off the same adapter and are not surfaced here.
895
896
  */
896
- appearance?: FloPayAppearance;
897
+ onError?: (message: string | null) => void;
897
898
  /**
898
- * @deprecated Use `theme` instead. Legacy buttons-layout preset
899
- * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
900
- * back-compat.
899
+ * Fired with the widget's inline field-validation message (live, debounced by
900
+ * the widget to changes), or `null` when validation clears. Surfaced in the
901
+ * card form's error banner and the merchant `onError`.
901
902
  */
902
- buttonsTheme?: ButtonsLayoutTheme;
903
- buttonsStyles?: ButtonsLayoutStyles;
904
- onSuccess?: (event: FloPayAutomaticPaymentSuccessEvent) => void;
905
- onError?: (error: FloPayError) => void;
906
- onDecline?: (decline: DeclineEvent) => void;
907
- children?: React.ReactNode;
903
+ onValidation?: (message: string | null) => void;
908
904
  }
909
- declare function FloPayAutomaticPaymentButton({ sessionId, nonce, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, appearance, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps): React.JSX.Element;
905
+ /**
906
+ * Renders the backend-served vault PCI card widget
907
+ * (TeamFloPay/backend#823, Model A). The hosted widget
908
+ * is a self-contained form: PAN / CVC, the submit button, the charge, and 3DS
909
+ * all live inside it. This component only injects the widget HTML through the
910
+ * {@link CardCaptureAdapter} and bridges its `ready` / `error` lifecycle events
911
+ * back to the surrounding card form.
912
+ */
913
+ declare function VaultCardFields({ capture, html, messageToken, expectedOrigin, theme, containerStyle, onReady, onError, onValidation, }: VaultCardFieldsProps): React.ReactElement;
910
914
 
911
915
  export { AddressElement, type CheckoutState, DirectPayPalButton, type DirectPayPalButtonProps, type DirectPayPalInitializationState, type ElementComponentProps, FloPayAutomaticPaymentButton, type FloPayAutomaticPaymentButtonProps, type FloPayAutomaticPaymentSuccessEvent, FloPayCheckout, type FloPayCheckoutProps, FloPayProvider, type FloPayProviderProps, PayPalButton, type PayPalButtonProps, PaymentElement, type PaymentElementProps, SplitCardForm, type SplitCardFormProps, VaultCardFields, type VaultCardFieldsProps, useCheckout, useElements, useFloPay, usePayPalFloPay };