@flopay/react 1.5.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,304 +1,215 @@
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, 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;
12
- /**
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.
16
- */
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;
39
- };
40
- children: React.ReactNode;
8
+ interface FloPayAutomaticPaymentSuccessEvent {
9
+ result: PaymentResult;
10
+ session: CheckoutSession | null;
11
+ sessionId: string | null;
12
+ autoCompleted: boolean;
41
13
  }
42
- /**
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
- * ```
59
- */
60
- declare function FloPayProvider({ flopay: floPayProp, paypalFlopay: paypalFloPayProp, options, children, }: FloPayProviderProps): React.ReactElement;
61
-
62
- /** Props for the all-in-one `FloPayCheckout` wrapper. */
63
- interface FloPayCheckoutProps {
64
- /** The checkout session ID (UUID from billing API). Required unless `createSession` is provided. */
14
+ interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
65
15
  sessionId?: string;
66
16
  /**
67
- * Session-bound checkout token (the `nonce` returned when the session was
68
- * created). Sent as the `x-checkout-session-token` header when fetching a
69
- * session by `sessionId`. Required by post-#640 backends, which no longer
70
- * let the UUID alone authorize a session read; harmless on older backends.
71
- * Only consulted in the `sessionId` flow inline `createSession` sessions
72
- * carry their own freshly-minted nonce server-side.
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.
73
23
  */
74
24
  nonce?: string;
75
- /**
76
- * Create a checkout session inline — no separate API route needed.
77
- * The component POSTs to the billing API, gets the full session back, and renders the form.
78
- * Alternative to `sessionId` (provide one or the other).
79
- */
80
25
  createSession?: InlineSessionDraft;
81
- /** Billing API base URL. Defaults to the shared `BILLING_API_URL` constant. */
82
- billingApiUrl?: string;
83
- /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
84
- telemetry?: boolean;
85
- /** Visual appearance for payment elements. */
86
- appearance?: FloPayAppearance;
87
- /** Locale for payment elements (default: 'auto'). */
88
- locale?: string;
89
- /** Custom loading UI. Defaults to a simple centered spinner. */
90
- loading?: React.ReactNode;
91
- /** Custom error UI. Receives the error. Defaults to showing the error message. */
92
- error?: (error: FloPayError) => React.ReactNode;
93
- /** Called when the full payment flow completes successfully. */
94
- onComplete?: (result: PaymentResult) => void;
95
- /** Called when a payment error occurs. */
96
- onError?: (error: FloPayError) => void;
97
- /** Called when a payment is declined or the authentication step fails. */
98
- onDecline?: (decline: DeclineEvent) => void;
99
- /** Called when the AVS country dropdown changes. */
100
- onCountryChange?: (country: string) => void;
101
- /** Called when the AVS ZIP/postcode input changes. */
102
- onZipChange?: (zip: string) => void;
103
- /**
104
- * Show the PayPal payment surface (default: `true`). Renderer is chosen
105
- * from `gateways.paypal` on the session — DirectPayPalButton when present,
106
- * Stripe-rendered PayPal otherwise.
107
- */
108
- showPayPal?: boolean;
109
26
  /**
110
- * Show Stripe-rendered wallets/APMs alongside the vault-hosted card surface
111
- * (default: `true`). When `false`, only
112
- * `DirectPayPalButton` can render. Both `showStripe=false` and
113
- * `showPayPal=false` (with no PayPal gateway configured) triggers a
114
- * bootstrap-time validation error.
115
- */
116
- showStripe?: boolean;
117
- /**
118
- * Override the wallet/APM list the session advertises via
119
- * `gateways.stripe.enabledPaymentMethods`. Omit (the default) and the
120
- * backend's per-session list is used, which is what a normal integration
121
- * wants.
122
- *
123
- * Pass an explicit list to narrow it, or `[]` to render the hosted card form
124
- * on its own — the empty array means "no methods enabled", not "fall back to
125
- * the backend list". This is the supported way to get a card-only checkout:
126
- * `showStripe={false}` also gates the vault, so it takes the card form down
127
- * with the wallets.
128
- *
129
- * Narrowing only. Naming a method the backend hasn't enabled for the session
130
- * will not turn it on.
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.
131
32
  */
132
- enabledPaymentMethods?: string[];
33
+ paymentMethodId?: string;
133
34
  /**
134
- * @deprecated Apple Pay availability is now driven by
135
- * `gateways.stripe.enabledPaymentMethods` on the per-session response from
136
- * the billing API. Setting this prop emits a one-time deprecation warning
137
- * and is otherwise ignored once the backend ships the list.
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.
138
38
  */
139
- showApplePay?: boolean;
39
+ checkoutMethod?: CheckoutButtonMethod;
40
+ clientId?: string;
140
41
  /**
141
- * @deprecated See {@link FloPayCheckoutProps.showApplePay}.
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.
142
45
  */
143
- showGooglePay?: boolean;
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;
144
57
  /**
145
- * Enables on-screen diagnostic panels (PayPal gate decision, DirectPayPalButton
146
- * lifecycle). Intended for debugging in-app browsers (Facebook, Instagram, etc.)
147
- * where remote console access is impractical. Off by default.
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.
148
63
  */
149
- debug?: boolean;
150
- /** Layout mode: 'default' (all visible) or 'buttons' (PayPal/wallets + expandable card form). */
151
- layout?: 'default' | 'buttons';
64
+ theme?: ThemeId;
152
65
  /**
153
- * High-level theme bundle that styles non-card Stripe Elements, the FloPay
154
- * wrapper / AVS inputs, and the hosted vault widget. One of: `'classic'`
155
- * (historic FloPay look, no bundle applied), `'modern-light'`, `'modern-dark'`,
156
- * `'bold-light'`, `'bold-dark'`, `'glass-light'`, `'glass-dark'`. Explicit
157
- * `appearance` / `buttonsStyles` props still override their respective
158
- * halves when supplied.
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.
159
71
  */
160
- theme?: _flopay_shared.ThemeId;
72
+ appearance?: FloPayAppearance;
161
73
  /**
162
74
  * @deprecated Use `theme` instead. Legacy buttons-layout preset
163
75
  * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
164
76
  * back-compat.
165
77
  */
166
- buttonsTheme?: _flopay_shared.ButtonsLayoutTheme;
167
- /** Style overrides merged on top of the resolved theme bundle / buttonsTheme preset. */
168
- buttonsStyles?: _flopay_shared.ButtonsLayoutStyles;
169
- /** Custom React content rendered inside the card button when `layout="buttons"`. */
170
- cardButtonContent?: React.ReactNode;
171
- /** Custom React content rendered for the buttons-layout card back button label. */
172
- cardBackButtonContent?: React.ReactNode;
173
- /** Custom React content rendered for the card-form title. */
174
- cardTitleContent?: React.ReactNode;
175
- /**
176
- * @deprecated No longer rendered the default-layout security footer was
177
- * removed alongside the theme-bundle refactor. Retained as an optional
178
- * prop so existing integrations type-check without changes.
179
- */
180
- showSecurityFooter?: boolean;
181
- /**
182
- * Called when a payment method button is clicked.
183
- * `method`: `'card'` | `'paypal'` | `'apple_pay'` | `'google_pay'`
184
- */
185
- onButtonClick?: (method: CheckoutButtonMethod) => void;
186
- /**
187
- * Called before a payment button continues in `layout="buttons"`.
188
- * Runs for card, PayPal, Apple Pay, and Google Pay.
189
- * In `layout="buttons"` with `createSession`, the returned patch is merged
190
- * into the inline session params before the selected flow continues.
191
- */
192
- onBeforeButtonClick?: (event: BeforeButtonClickEvent) => void | false | Promise<void | false | InlineSessionPatch> | InlineSessionPatch;
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;
193
126
  /**
194
- * Enable AVS (Address Verification).
195
- * - `true` show country + postal code (backward compatible default)
196
- * - `AVSFieldConfig` granular per-field control, optionally scoped to country codes
197
- * - `false` / omitted — AVS disabled
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.
198
130
  */
199
- enableAVS?: boolean | _flopay_shared.AVSFieldConfig;
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;
200
144
  /**
201
- * Per-merchant order of the hosted vault card rows a permutation of
202
- * `['name','number','expiry']` (`'expiry'` = the expiry+CVV row; submit stays
203
- * last). Sets both the visual and tab order. Omit for the default
204
- * (`name`, `number`, `expiry`). Vault card path only.
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.
205
151
  */
206
- cardFieldOrder?: _flopay_shared.VaultCardFieldKey[];
152
+ providerObjectType?: PayPalProviderObjectType;
207
153
  /**
208
- * Content rendered directly above the hosted vault card widget (below the
209
- * "or pay with card" divider). Used by the demo playground to surface a
210
- * test-cards helper; harmless to omit in a normal integration.
154
+ * If provided, called with the tokenized body once PayPal capture
155
+ * completes. When omitted, the component processes payment internally.
211
156
  */
212
- cardPreFormSlot?: React.ReactNode;
213
- /** Layout for AVS fields: 'row' (side-by-side, default) or 'column' (stacked). */
214
- avsLayout?: 'row' | 'column';
215
- /** Additional CSS class for the wrapper. */
216
- className?: string;
217
- /** Seed an initial checkout error message for the rendered payment form. */
218
- initialErrorMessage?: string | null;
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;
219
176
  /**
220
- * Override the default `SplitCardForm`. When provided, children are rendered
221
- * inside the initialized `FloPayProvider` with session props auto-injected.
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.
222
181
  */
223
- children?: React.ReactNode;
182
+ runBeforeButtonClick?: DirectPayPalRunBeforeButtonClick;
183
+ /** Backing session — used for self-contained accountData population. */
184
+ session?: CheckoutSession | null;
224
185
  /**
225
- * Override the session's checkoutMode.
226
- * - `'full'` show payment form (default)
227
- * - `'confirm'` show confirm button, uses saved payment method
228
- * - `'auto'` — auto-submit with saved PM, falls back to `'full'` on failure
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).
229
199
  */
230
- checkoutMode?: CheckoutMode;
231
- /** Label for the confirm button in `confirm` mode. Default: `'Confirm Purchase'`. */
232
- confirmLabel?: string;
233
- /** Custom confirm button renderer for `confirm` mode. */
234
- renderConfirmButton?: (props: {
235
- onConfirm: () => void;
236
- isProcessing: boolean;
237
- }) => React.ReactNode;
238
- /** Called when the session has already been completed. Receives the successUrl. */
239
- onSessionCompleted?: (successUrl: string) => void;
200
+ existingOrderId?: string;
201
+ /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
202
+ telemetry?: boolean;
240
203
  /**
241
- * @deprecated No longer used. The Stripe publishable key is sourced exclusively
242
- * from the checkout session's `gateways.stripe.publishableKey`. Accepted only
243
- * for backward compatibility with older consumer code the value is ignored.
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.
244
208
  */
245
- fallbackPublishableKey?: string;
246
- }
247
- /**
248
- * All-in-one checkout component. Fetches the session, initializes the
249
- * payment provider, and renders the appropriate UI based on checkout mode.
250
- *
251
- * **Modes:**
252
- * - `full` (default) — renders hosted-vault card capture, wallets, APMs, and PayPal
253
- * - `confirm` — renders a "Confirm Purchase" button, uses saved payment method
254
- * - `auto` — auto-submits with saved PM, falls back to `full` on failure
255
- *
256
- * ```tsx
257
- * <FloPayCheckout
258
- * sessionId="sess_abc123"
259
- * onComplete={(result) => router.push('/success')}
260
- * onError={(err) => console.error(err)}
261
- * />
262
- * ```
263
- */
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;
265
-
266
- /**
267
- * Returns the current `FloPay` instance, or `null` if the provider
268
- * is still loading (i.e. the `loadFloPay()` promise has not resolved yet).
269
- *
270
- * Must be called within a `<FloPayProvider>`.
271
- */
272
- declare function useFloPay(): FloPay | null;
273
- /**
274
- * Returns the Stripe `FloPay` instance dedicated to the Stripe-rendered
275
- * PayPal fallback, or `null` if PayPal is disabled for this session. Direct
276
- * PayPal (`gateways.paypal`) does not use this instance.
277
- *
278
- * Must be called within a `<FloPayProvider>`.
279
- */
280
- declare function usePayPalFloPay(): FloPay | null;
281
- /**
282
- * Returns the current `FloPayElements` instance, or `null` if the
283
- * provider is still loading.
284
- *
285
- * Must be called within a `<FloPayProvider>`.
286
- */
287
- declare function useElements(): FloPayElements | null;
288
- /** Checkout state exposed by `useCheckout()`. */
289
- interface CheckoutState {
290
- session: CheckoutSession | null;
291
- loading: boolean;
292
- error: FloPayError | null;
293
- /** True while a detached session shell is not yet safe to charge. */
294
- claimPending?: boolean;
209
+ debug?: boolean;
295
210
  }
296
- /**
297
- * Returns the current checkout session state.
298
- *
299
- * Must be called within the checkout context rendered by `<FloPayCheckout>`.
300
- */
301
- declare function useCheckout(): CheckoutState;
211
+ /** Public direct-PayPal surface: telemetry accepts only the boolean opt-out. */
212
+ declare function DirectPayPalButton(props: DirectPayPalButtonProps): React.ReactElement | null;
302
213
 
303
214
  /** Common props shared by all element components. */
304
215
  interface ElementComponentProps {
@@ -342,133 +253,115 @@ declare const PaymentElement: React.FC<PaymentElementProps>;
342
253
  */
343
254
  declare const AddressElement: React.FC<ElementComponentProps>;
344
255
 
345
- type MaybePromise<T> = T | Promise<T>;
346
-
347
- interface SplitCardFormProps {
348
- /** The checkout session ID (UUID from billing API). */
349
- sessionId: string;
256
+ /** Props for the all-in-one `FloPayCheckout` wrapper. */
257
+ interface FloPayCheckoutProps {
258
+ /** The checkout session ID (UUID from billing API). Required unless `createSession` is provided. */
259
+ sessionId?: string;
350
260
  /**
351
- * Session-bound checkout token returned by session creation
352
- * (`CheckoutSessionResult.nonce` or `session.clientSecret`). Forwarded as
353
- * `x-checkout-session-token` on every continuation request required by
354
- * post-#640 backends. `FloPayCheckout` plumbs this prop automatically.
261
+ * Session-bound checkout token (the `nonce` returned when the session was
262
+ * created). Sent as the `x-checkout-session-token` header when fetching a
263
+ * session by `sessionId`. Required by post-#640 backends, which no longer
264
+ * let the UUID alone authorize a session read; harmless on older backends.
265
+ * Only consulted in the `sessionId` flow — inline `createSession` sessions
266
+ * carry their own freshly-minted nonce server-side.
355
267
  */
356
268
  nonce?: string;
357
- /** Billing API base URL. Optional — defaults to the value from FloPayProvider or the shared constant. */
269
+ /**
270
+ * Create a checkout session inline — no separate API route needed.
271
+ * The component POSTs to the billing API, gets the full session back, and renders the form.
272
+ * Alternative to `sessionId` (provide one or the other).
273
+ */
274
+ createSession?: InlineSessionDraft;
275
+ /** Billing API base URL. Defaults to the shared `BILLING_API_URL` constant. */
358
276
  billingApiUrl?: string;
359
- /** User's email (required for creating payment intents). */
360
- email?: string;
361
- /** User ID (required for processing payments). */
362
- userId?: string;
277
+ /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
278
+ telemetry?: boolean;
279
+ /** Visual appearance for payment elements. */
280
+ appearance?: FloPayAppearance;
281
+ /** Locale for payment elements (default: 'auto'). */
282
+ locale?: string;
283
+ /** Custom loading UI. Defaults to a simple centered spinner. */
284
+ loading?: React.ReactNode;
285
+ /** Custom error UI. Receives the error. Defaults to showing the error message. */
286
+ error?: (error: FloPayError) => React.ReactNode;
363
287
  /** Called when the full payment flow completes successfully. */
364
288
  onComplete?: (result: PaymentResult) => void;
365
289
  /** Called when a payment error occurs. */
366
290
  onError?: (error: FloPayError) => void;
291
+ /** Receives the versioned, privacy-safe checkout instrument feed. */
292
+ onInstrument?: (event: FloInstrumentEvent) => void;
367
293
  /** Called when a payment is declined or the authentication step fails. */
368
- onDecline?: (decline: DeclineEvent) => void;
369
- /**
370
- * **Override**: If provided, delegates backend submission to the caller.
371
- * When omitted, processes internally (calls processPayment + handles 3DS).
372
- */
373
- onTokenizedBody?: (tokenizedBody: TokenizedBody) => void;
374
- /** First name for billing. */
375
- firstName?: string;
376
- /** Last name for billing. */
377
- lastName?: string;
378
- /** Checkout version for A/B tracking. */
379
- chv?: string;
380
- /** Additional CSS class for the form wrapper. */
381
- className?: string;
382
- /** External processing state. */
383
- isProcessing?: boolean;
384
- /** External error message. */
385
- error?: string | null;
386
- /** Called when internal error state changes. */
387
- onErrorChange?: (error: string | null) => void;
388
- /**
389
- * Show the PayPal payment surface above the hosted vault card surface. Defaults to `true`.
390
- * The renderer is chosen from `session.gateways.paypal`: when that gateway
391
- * is configured, `DirectPayPalButton` (PayPal JS SDK) takes over and Stripe
392
- * drops `paypal` from its express row to avoid double-rendering; otherwise
393
- * PayPal renders inside `ExpressCheckoutElement` (using either a dedicated
394
- * `gateways.stripe.paypalPublishableKey` sub-account or the main Stripe
395
- * account when the enabled-methods list includes `paypal`).
294
+ onDecline?: (decline: DeclineEvent) => void;
295
+ /** Called when the AVS country dropdown changes. */
296
+ onCountryChange?: (country: string) => void;
297
+ /** Called when the AVS ZIP/postcode input changes. */
298
+ onZipChange?: (zip: string) => void;
299
+ /**
300
+ * Show the PayPal payment surface (default: `true`). Renderer is chosen
301
+ * from `gateways.paypal` on the session — DirectPayPalButton when present,
302
+ * Stripe-rendered PayPal otherwise.
396
303
  */
397
304
  showPayPal?: boolean;
398
305
  /**
399
- * Show Stripe-rendered wallets and APMs (ExpressCheckoutElement +
400
- * PaymentElement). Defaults to `true`. When `false`, every Stripe surface
401
- * is hidden — only `DirectPayPalButton` can render. Setting both
402
- * `showStripe={false}` and `showPayPal={false}` (with no PayPal gateway
403
- * configured) throws a bootstrap-time validation error.
306
+ * Show Stripe-rendered wallets/APMs alongside the vault-hosted card surface
307
+ * (default: `true`). When `false`, only
308
+ * `DirectPayPalButton` can render. Both `showStripe=false` and
309
+ * `showPayPal=false` (with no PayPal gateway configured) triggers a
310
+ * bootstrap-time validation error.
404
311
  */
405
312
  showStripe?: boolean;
406
313
  /**
407
- * Per-session list of Stripe payment method type identifiers (as returned
408
- * by the billing API on `gateways.stripe.enabledPaymentMethods`). When
409
- * supplied, drives the contents of the `ExpressCheckoutElement` row and the
410
- * accordion `PaymentElement` instead of the historic hardcoded
411
- * Apple/Google/PayPal set. `card` is reserved for the hosted card path: it
412
- * advertises that `/vault/capture` recovery is available when the session
413
- * has no embedded vault block. When omitted, the SDK falls back to the
414
- * legacy `showApplePay`/`showGooglePay`/`showPayPal` toggles.
314
+ * Override the wallet/APM list the session advertises via
315
+ * `gateways.stripe.enabledPaymentMethods`. Omit (the default) and the
316
+ * backend's per-session list is used, which is what a normal integration
317
+ * wants.
318
+ *
319
+ * Pass an explicit list to narrow it, or `[]` to render the hosted card form
320
+ * on its own the empty array means "no methods enabled", not "fall back to
321
+ * the backend list". This is the supported way to get a card-only checkout:
322
+ * `showStripe={false}` also gates the vault, so it takes the card form down
323
+ * with the wallets.
324
+ *
325
+ * Narrowing only. Naming a method the backend hasn't enabled for the session
326
+ * will not turn it on.
415
327
  */
416
328
  enabledPaymentMethods?: string[];
417
329
  /**
418
- * Per-method buyer-country gate from `gateways.stripe.enabledPaymentMethodCountries`
419
- * (method allowed ISO-3166-1 alpha-2 countries; a method absent here has no
420
- * country gate). The SDK filters the rendered tile row by the buyer's *live*
421
- * country against this map, so per-method country eligibility comes from the
422
- * backend rather than a hardcoded SDK table. When omitted (legacy backend),
423
- * the SDK falls back to its built-in {@link STRIPE_METHOD_COUNTRIES} table.
424
- */
425
- enabledPaymentMethodCountries?: Record<string, string[]>;
426
- /**
427
- * @deprecated The Apple Pay / Google Pay surface is now driven by the
428
- * `gateways.stripe.enabledPaymentMethods` list returned per-session by the
429
- * billing API. Pass {@link SplitCardFormProps.enabledPaymentMethods} (or
430
- * upgrade the backend so `FloPayCheckout` threads it through automatically).
431
- * Setting this prop emits a one-time deprecation warning and is otherwise
432
- * ignored when `enabledPaymentMethods` is supplied.
330
+ * @deprecated Apple Pay availability is now driven by
331
+ * `gateways.stripe.enabledPaymentMethods` on the per-session response from
332
+ * the billing API. Setting this prop emits a one-time deprecation warning
333
+ * and is otherwise ignored once the backend ships the list.
433
334
  */
434
335
  showApplePay?: boolean;
435
336
  /**
436
- * @deprecated See {@link SplitCardFormProps.showApplePay}.
337
+ * @deprecated See {@link FloPayCheckoutProps.showApplePay}.
437
338
  */
438
339
  showGooglePay?: boolean;
439
340
  /**
440
- * Layout mode for the payment form.
441
- * - `'default'` all payment methods + card form shown together (current behavior)
442
- * - `'buttons'` PayPal, wallets, and a "Credit / Debit Card" button; clicking the card
443
- * button expands the card form with a back button to return to the button view
341
+ * Enables on-screen diagnostic panels (PayPal gate decision, DirectPayPalButton
342
+ * lifecycle). Intended for debugging in-app browsers (Facebook, Instagram, etc.)
343
+ * where remote console access is impractical. Off by default.
444
344
  */
345
+ debug?: boolean;
346
+ /** Layout mode: 'default' (all visible) or 'buttons' (PayPal/wallets + expandable card form). */
445
347
  layout?: 'default' | 'buttons';
446
348
  /**
447
349
  * High-level theme bundle that styles non-card Stripe Elements, the FloPay
448
- * wrapper / AVS inputs, and the hosted vault widget. One of:
449
- * `'classic'` (historic FloPay look, no bundle applied), `'modern-light'`,
450
- * `'modern-dark'`, `'bold-light'`, `'bold-dark'`, `'glass-light'`,
451
- * `'glass-dark'`. Explicit `appearance` / `buttonsStyles` props still
452
- * override their respective halves when provided.
350
+ * wrapper / AVS inputs, and the hosted vault widget. One of: `'classic'`
351
+ * (historic FloPay look, no bundle applied), `'modern-light'`, `'modern-dark'`,
352
+ * `'bold-light'`, `'bold-dark'`, `'glass-light'`, `'glass-dark'`. Explicit
353
+ * `appearance` / `buttonsStyles` props still override their respective
354
+ * halves when supplied.
453
355
  */
454
356
  theme?: _flopay_shared.ThemeId;
455
357
  /**
456
358
  * @deprecated Use `theme` instead. Legacy buttons-layout preset
457
359
  * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
458
- * back-compat — the new union accepts the bundle ids too but you should
459
- * migrate to the `theme` prop.
360
+ * back-compat.
460
361
  */
461
362
  buttonsTheme?: _flopay_shared.ButtonsLayoutTheme;
462
363
  /** Style overrides merged on top of the resolved theme bundle / buttonsTheme preset. */
463
364
  buttonsStyles?: _flopay_shared.ButtonsLayoutStyles;
464
- /**
465
- * Appearance from `FloPayProvider` / `FloPayCheckout`. Threaded through so
466
- * the React-rendered wrapper, AVS inputs, title, and hosted vault widget can
467
- * derive colors from `appearance.variables` when no explicit `buttonsStyles`
468
- * is supplied. Bundle consumers (`THEMES[id]`) get a coherent look without
469
- * having to forward both halves manually.
470
- */
471
- appearance?: _flopay_shared.FloPayAppearance;
472
365
  /** Custom React content rendered inside the card button when `layout="buttons"`. */
473
366
  cardButtonContent?: React.ReactNode;
474
367
  /** Custom React content rendered for the buttons-layout card back button label. */
@@ -489,157 +382,119 @@ interface SplitCardFormProps {
489
382
  /**
490
383
  * Called before a payment button continues in `layout="buttons"`.
491
384
  * Runs for card, PayPal, Apple Pay, and Google Pay.
385
+ * In `layout="buttons"` with `createSession`, the returned patch is merged
386
+ * into the inline session params before the selected flow continues.
492
387
  */
493
- onBeforeButtonClick?: (event: BeforeButtonClickEvent) => MaybePromise<void | false | InlineSessionPatch>;
388
+ onBeforeButtonClick?: (event: BeforeButtonClickEvent) => undefined | false | Promise<undefined | false | InlineSessionPatch> | InlineSessionPatch;
494
389
  /**
495
390
  * Enable AVS (Address Verification).
496
391
  * - `true` — show country + postal code (backward compatible default)
497
392
  * - `AVSFieldConfig` — granular per-field control, optionally scoped to country codes
498
393
  * - `false` / omitted — AVS disabled
499
394
  */
500
- enableAVS?: boolean | AVSFieldConfig;
395
+ enableAVS?: boolean | _flopay_shared.AVSFieldConfig;
501
396
  /**
502
397
  * 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.
398
+ * `['name','number','expiry']` (`'expiry'` = the expiry+CVV row; submit stays
399
+ * last). Sets both the visual and tab order. Omit for the default
400
+ * (`name`, `number`, `expiry`). Vault card path only.
507
401
  */
508
402
  cardFieldOrder?: _flopay_shared.VaultCardFieldKey[];
509
- /** Content rendered above the hosted vault card widget (below the wallet divider). */
403
+ /**
404
+ * Content rendered directly above the hosted vault card widget (below the
405
+ * "or pay with card" divider). Used by the demo playground to surface a
406
+ * test-cards helper; harmless to omit in a normal integration.
407
+ */
510
408
  cardPreFormSlot?: React.ReactNode;
511
409
  /** Layout for AVS fields: 'row' (side-by-side, default) or 'column' (stacked). */
512
410
  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;
411
+ /** Additional CSS class for the wrapper. */
412
+ className?: string;
413
+ /** Seed an initial checkout error message for the rendered payment form. */
414
+ initialErrorMessage?: string | null;
541
415
  /**
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.
416
+ * Override the default `SplitCardForm`. When provided, children are rendered
417
+ * inside the initialized `FloPayProvider` with session props auto-injected.
546
418
  */
547
- directPaypal?: {
548
- clientId: string;
549
- environment?: GatewayEnvironment;
550
- };
551
- /** Whether the active session represents a subscription (drives direct PayPal intent). */
552
- isSubscription?: boolean;
553
- /** Backing session — forwarded to direct-PayPal so it can populate accountData. */
554
- session?: CheckoutSession | null;
419
+ children?: React.ReactNode;
555
420
  /**
556
- * True while a **detached** session's background claim is still in flight
557
- * (TeamFloPay/backend#1099).
558
- *
559
- * The hosted card widget is already mounted and the buyer can fill it in, but
560
- * the session has no cart attached yet, so nothing may be submitted: the
561
- * billing API rejects process / intent calls on an unclaimed session with
562
- * `409 checkout_session_data_attachment_required`, and holds an unclaimed
563
- * vault charge with a retryable `503`. While true, the card submit is gated
564
- * and the non-card surfaces stay hidden; all of them enable together the
565
- * moment the claim lands. `FloPayCheckout` plumbs this prop automatically.
421
+ * Override the session's checkoutMode.
422
+ * - `'full'` — show payment form (default)
423
+ * - `'confirm'` — show confirm button, uses saved payment method
424
+ * - `'auto'` auto-submit with saved PM, falls back to `'full'` on failure
566
425
  */
567
- dataAttachmentPending?: boolean;
426
+ checkoutMode?: CheckoutMode;
427
+ /** Label for the confirm button in `confirm` mode. Default: `'Confirm Purchase'`. */
428
+ confirmLabel?: string;
429
+ /** Custom confirm button renderer for `confirm` mode. */
430
+ renderConfirmButton?: (props: {
431
+ onConfirm: () => void;
432
+ isProcessing: boolean;
433
+ }) => React.ReactNode;
434
+ /** Called when the session has already been completed. Receives the successUrl. */
435
+ onSessionCompleted?: (successUrl: string) => void;
568
436
  /**
569
- * Enables on-screen diagnostic panels for the PayPal/wallet gating decision
570
- * and the `DirectPayPalButton` lifecycle. Intended for debugging in-app
571
- * browsers where remote console access is impractical. Off by default.
437
+ * @deprecated No longer used. The Stripe publishable key is sourced exclusively
438
+ * from the checkout session's `gateways.stripe.publishableKey`. Accepted only
439
+ * for backward compatibility with older consumer code the value is ignored.
572
440
  */
573
- debug?: boolean;
441
+ fallbackPublishableKey?: string;
574
442
  }
575
443
  /**
576
- * Checkout surface combining hosted vault card capture with wallets, APMs,
577
- * and PayPal. Card entry is hosted-vault-only.
444
+ * All-in-one checkout component. Fetches the session, initializes the
445
+ * payment provider, and renders the appropriate UI based on checkout mode.
578
446
  *
579
- * Stripe-hosted PayPal uses its own Elements instance; direct PayPal uses the
580
- * official PayPal SDK when the session advertises that gateway.
447
+ * **Modes:**
448
+ * - `full` (default) renders hosted-vault card capture, wallets, APMs, and PayPal
449
+ * - `confirm` — renders a "Confirm Purchase" button, uses saved payment method
450
+ * - `auto` — auto-submits with saved PM, falls back to `full` on failure
451
+ *
452
+ * ```tsx
453
+ * <FloPayCheckout
454
+ * sessionId="sess_abc123"
455
+ * onComplete={(result) => router.push('/success')}
456
+ * onError={(err) => console.error(err)}
457
+ * />
458
+ * ```
581
459
  */
582
- declare function SplitCardForm(props: SplitCardFormProps): React.JSX.Element;
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;
583
461
 
584
- /** Props for {@link VaultCardFields}. */
585
- interface VaultCardFieldsProps {
586
- /**
587
- * The card-capture adapter (typically `useFloPay().cardCapture()`). Owns
588
- * injecting + bootstrapping the hosted vault widget. Changing this instance
589
- * (or {@link VaultCardFieldsProps.html}) remounts the widget.
590
- */
591
- capture: CardCaptureAdapter;
592
- /**
593
- * Server-rendered hosted vault widget HTML (the session's
594
- * {@link CheckoutSession.vault} block `html`, or one fetched from
595
- * `POST /vault/capture`). The widget owns the card fields, submit button,
596
- * tokenization, charge, and 3DS; this component only injects it.
597
- */
598
- html: string;
599
- /**
600
- * Per-session integrity token (the vault block's `messageToken`). Forwarded
601
- * to the adapter so it can reject forged terminal `postMessage` outcomes that
602
- * omit/mismatch it. Omitted when the backend does not (yet) mint one.
603
- */
604
- messageToken?: string;
605
- /**
606
- * Exact origin expected for the widget's terminal `postMessage` outcomes
607
- * (the vault block's `expectedOrigin`). Forwarded to the adapter's origin
608
- * gate; omitted to skip it.
609
- */
610
- expectedOrigin?: string;
611
- /**
612
- * Merchant theme colors pushed into the hosted widget so the card form
613
- * matches the surrounding checkout. Applied live on change (no remount).
614
- */
615
- theme?: VaultCardThemeColors;
616
- /** Inline styles for the container the widget mounts into. */
617
- containerStyle?: React.CSSProperties;
618
- /** Fired once the widget is injected and bootstrapping. */
619
- onReady?: () => void;
620
- /**
621
- * Fired with a load/runtime error message from the widget, or `null` when it
622
- * clears. Wired to the card form's shared error banner. Terminal payment
623
- * outcomes (`complete` / `decline`) are observed by the parent form directly
624
- * off the same adapter and are not surfaced here.
625
- */
626
- onError?: (message: string | null) => void;
627
- /**
628
- * Fired with the widget's inline field-validation message (live, debounced by
629
- * the widget to changes), or `null` when validation clears. Surfaced in the
630
- * card form's error banner and the merchant `onError`.
631
- */
632
- onValidation?: (message: string | null) => void;
462
+ /**
463
+ * Returns the current `FloPay` instance, or `null` if the provider
464
+ * is still loading (i.e. the `loadFloPay()` promise has not resolved yet).
465
+ *
466
+ * Must be called within a `<FloPayProvider>`.
467
+ */
468
+ declare function useFloPay(): FloPay | null;
469
+ /**
470
+ * Returns the Stripe `FloPay` instance dedicated to the Stripe-rendered
471
+ * PayPal fallback, or `null` if PayPal is disabled for this session. Direct
472
+ * PayPal (`gateways.paypal`) does not use this instance.
473
+ *
474
+ * Must be called within a `<FloPayProvider>`.
475
+ */
476
+ declare function usePayPalFloPay(): FloPay | null;
477
+ /**
478
+ * Returns the current `FloPayElements` instance, or `null` if the
479
+ * provider is still loading.
480
+ *
481
+ * Must be called within a `<FloPayProvider>`.
482
+ */
483
+ declare function useElements(): FloPayElements | null;
484
+ /** Checkout state exposed by `useCheckout()`. */
485
+ interface CheckoutState {
486
+ session: CheckoutSession | null;
487
+ loading: boolean;
488
+ error: FloPayError | null;
489
+ /** True while a detached session shell is not yet safe to charge. */
490
+ claimPending?: boolean;
633
491
  }
634
492
  /**
635
- * Renders the backend-served vault PCI card widget
636
- * (TeamFloPay/backend#823, Model A). The hosted widget
637
- * is a self-contained form: PAN / CVC, the submit button, the charge, and 3DS
638
- * all live inside it. This component only injects the widget HTML through the
639
- * {@link CardCaptureAdapter} and bridges its `ready` / `error` lifecycle events
640
- * back to the surrounding card form.
493
+ * Returns the current checkout session state.
494
+ *
495
+ * Must be called within the checkout context rendered by `<FloPayCheckout>`.
641
496
  */
642
- declare function VaultCardFields({ capture, html, messageToken, expectedOrigin, theme, containerStyle, onReady, onError, onValidation, }: VaultCardFieldsProps): React.ReactElement;
497
+ declare function useCheckout(): CheckoutState;
643
498
 
644
499
  /**
645
500
  * Props for the `PayPalButton` component.
@@ -701,201 +556,360 @@ interface PayPalButtonProps {
701
556
  */
702
557
  declare function PayPalButton({ sessionId, nonce, billingApiUrl, email, userId, firstName, lastName, chv, onTokenizedBody, onComplete, onErrorChange, isProcessing, }: PayPalButtonProps): React.ReactElement;
703
558
 
704
- /**
705
- * Overrides that `SplitCardForm`'s tokenized-body dispatcher uses to apply a
706
- * `runBeforeButtonClick` patch to the in-flight processPayment call. Kept in
707
- * sync structurally with `TokenizedBodyOverrides` in `split-card-form.tsx`.
708
- */
709
- interface DirectPayPalTokenizedOverrides {
710
- accountPatch?: InlineSessionPatch['account'];
711
- sessionId?: string;
712
- nonce?: string;
713
- }
714
- /**
715
- * Internal handler signature aligned with `SplitCardForm`'s tokenized-body
716
- * dispatcher. Direct PayPal completes via the backend's process endpoint and
717
- * never produces a Stripe PaymentIntent, so we still forward a synthetic
718
- * `TokenizedBody` describing the captured order, optionally with the
719
- * session/account patch captured at click-time.
720
- */
721
- type DirectPayPalTokenizedHandler = (body: TokenizedBody, overrides?: DirectPayPalTokenizedOverrides) => void;
722
- /** Click-time `runBeforeButtonClick` result, structurally compatible with `SplitCardForm`. */
723
- interface DirectPayPalBeforeButtonClickResult {
724
- proceed: boolean;
725
- accountPatch?: InlineSessionPatch['account'];
726
- sessionId?: string;
727
- nonce?: string;
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;
728
594
  }
729
595
  /**
730
- * Click-time gate. Mirrors `RunBeforeButtonClick` in `SplitCardForm`: lets the
731
- * consumer patch the session/account before PayPal creates the order, and lets
732
- * them abort the click entirely by returning `proceed: false`.
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
+ * ```
733
612
  */
734
- type DirectPayPalRunBeforeButtonClick = (method: CheckoutButtonMethod) => Promise<DirectPayPalBeforeButtonClickResult>;
735
- type DirectPayPalInitializationState = 'loading' | 'retrying' | 'ready' | 'exhausted';
736
- type DirectPayPalTechnicalFailureHandler = (method: 'paypal', err: unknown, options?: {
737
- code?: string;
738
- popupBlocked?: boolean;
739
- }) => void;
740
- interface DirectPayPalButtonProps {
741
- /** Checkout session ID. */
613
+ declare function FloPayProvider({ flopay: floPayProp, paypalFlopay: paypalFloPayProp, options, onInstrument, children, }: FloPayProviderProps): React.ReactElement;
614
+
615
+ type MaybePromise<T> = T | Promise<T>;
616
+
617
+ interface SplitCardFormProps {
618
+ /** The checkout session ID (UUID from billing API). */
742
619
  sessionId: string;
743
620
  /**
744
- * Session-bound checkout token returned by session creation. Forwarded as
621
+ * Session-bound checkout token returned by session creation
622
+ * (`CheckoutSessionResult.nonce` or `session.clientSecret`). Forwarded as
745
623
  * `x-checkout-session-token` on every continuation request — required by
746
624
  * post-#640 backends. `FloPayCheckout` plumbs this prop automatically.
747
625
  */
748
- nonce?: string;
749
- /** Billing API base URL. */
750
- billingApiUrl: string;
751
- /** Buyer email. */
752
- email?: string;
753
- /** PayPal client identifier (`gateways.paypal.publishableKey`). */
754
- clientId: string;
755
- /** Gateway environment, drives the sandbox/live SDK script. */
756
- environment?: GatewayEnvironment;
757
- /** ISO 4217 currency code. */
758
- currency: string;
759
- /** Whether the session is a subscription (drives intent + flow selection). */
760
- isSubscription: boolean;
626
+ nonce?: string;
627
+ /** Billing API base URL. Optional — defaults to the value from FloPayProvider or the shared constant. */
628
+ billingApiUrl?: string;
629
+ /** User's email (required for creating payment intents). */
630
+ email?: string;
631
+ /** User ID (required for processing payments). */
632
+ userId?: string;
633
+ /** Called when the full payment flow completes successfully. */
634
+ onComplete?: (result: PaymentResult) => void;
635
+ /** Called when a payment error occurs. */
636
+ onError?: (error: FloPayError) => void;
637
+ /** Called when a payment is declined or the authentication step fails. */
638
+ onDecline?: (decline: DeclineEvent) => void;
639
+ /**
640
+ * **Override**: If provided, delegates backend submission to the caller.
641
+ * When omitted, processes internally (calls processPayment + handles 3DS).
642
+ */
643
+ onTokenizedBody?: (tokenizedBody: TokenizedBody) => void;
644
+ /** First name for billing. */
645
+ firstName?: string;
646
+ /** Last name for billing. */
647
+ lastName?: string;
648
+ /** Checkout version for A/B tracking. */
649
+ chv?: string;
650
+ /** Additional CSS class for the form wrapper. */
651
+ className?: string;
652
+ /** External processing state. */
653
+ isProcessing?: boolean;
654
+ /** External error message. */
655
+ error?: string | null;
656
+ /** Called when internal error state changes. */
657
+ onErrorChange?: (error: string | null) => void;
658
+ /**
659
+ * Show the PayPal payment surface above the hosted vault card surface. Defaults to `true`.
660
+ * The renderer is chosen from `session.gateways.paypal`: when that gateway
661
+ * is configured, `DirectPayPalButton` (PayPal JS SDK) takes over and Stripe
662
+ * drops `paypal` from its express row to avoid double-rendering; otherwise
663
+ * PayPal renders inside `ExpressCheckoutElement` (using either a dedicated
664
+ * `gateways.stripe.paypalPublishableKey` sub-account or the main Stripe
665
+ * account when the enabled-methods list includes `paypal`).
666
+ */
667
+ showPayPal?: boolean;
668
+ /**
669
+ * Show Stripe-rendered wallets and APMs (ExpressCheckoutElement +
670
+ * PaymentElement). Defaults to `true`. When `false`, every Stripe surface
671
+ * is hidden — only `DirectPayPalButton` can render. Setting both
672
+ * `showStripe={false}` and `showPayPal={false}` (with no PayPal gateway
673
+ * configured) throws a bootstrap-time validation error.
674
+ */
675
+ showStripe?: boolean;
676
+ /**
677
+ * Per-session list of Stripe payment method type identifiers (as returned
678
+ * by the billing API on `gateways.stripe.enabledPaymentMethods`). When
679
+ * supplied, drives the contents of the `ExpressCheckoutElement` row and the
680
+ * accordion `PaymentElement` instead of the historic hardcoded
681
+ * Apple/Google/PayPal set. `card` is reserved for the hosted card path: it
682
+ * advertises that `/vault/capture` recovery is available when the session
683
+ * has no embedded vault block. When omitted, the SDK falls back to the
684
+ * legacy `showApplePay`/`showGooglePay`/`showPayPal` toggles.
685
+ */
686
+ enabledPaymentMethods?: string[];
687
+ /**
688
+ * Per-method buyer-country gate from `gateways.stripe.enabledPaymentMethodCountries`
689
+ * (method → allowed ISO-3166-1 alpha-2 countries; a method absent here has no
690
+ * country gate). The SDK filters the rendered tile row by the buyer's *live*
691
+ * country against this map, so per-method country eligibility comes from the
692
+ * backend rather than a hardcoded SDK table. When omitted (legacy backend),
693
+ * the SDK falls back to its built-in {@link STRIPE_METHOD_COUNTRIES} table.
694
+ */
695
+ enabledPaymentMethodCountries?: Record<string, string[]>;
696
+ /**
697
+ * @deprecated The Apple Pay / Google Pay surface is now driven by the
698
+ * `gateways.stripe.enabledPaymentMethods` list returned per-session by the
699
+ * billing API. Pass {@link SplitCardFormProps.enabledPaymentMethods} (or
700
+ * upgrade the backend so `FloPayCheckout` threads it through automatically).
701
+ * Setting this prop emits a one-time deprecation warning and is otherwise
702
+ * ignored when `enabledPaymentMethods` is supplied.
703
+ */
704
+ showApplePay?: boolean;
705
+ /**
706
+ * @deprecated See {@link SplitCardFormProps.showApplePay}.
707
+ */
708
+ showGooglePay?: boolean;
709
+ /**
710
+ * Layout mode for the payment form.
711
+ * - `'default'` — all payment methods + card form shown together (current behavior)
712
+ * - `'buttons'` — PayPal, wallets, and a "Credit / Debit Card" button; clicking the card
713
+ * button expands the card form with a back button to return to the button view
714
+ */
715
+ layout?: 'default' | 'buttons';
716
+ /**
717
+ * High-level theme bundle that styles non-card Stripe Elements, the FloPay
718
+ * wrapper / AVS inputs, and the hosted vault widget. One of:
719
+ * `'classic'` (historic FloPay look, no bundle applied), `'modern-light'`,
720
+ * `'modern-dark'`, `'bold-light'`, `'bold-dark'`, `'glass-light'`,
721
+ * `'glass-dark'`. Explicit `appearance` / `buttonsStyles` props still
722
+ * override their respective halves when provided.
723
+ */
724
+ theme?: _flopay_shared.ThemeId;
725
+ /**
726
+ * @deprecated Use `theme` instead. Legacy buttons-layout preset
727
+ * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
728
+ * back-compat — the new union accepts the bundle ids too but you should
729
+ * migrate to the `theme` prop.
730
+ */
731
+ buttonsTheme?: _flopay_shared.ButtonsLayoutTheme;
732
+ /** Style overrides merged on top of the resolved theme bundle / buttonsTheme preset. */
733
+ buttonsStyles?: _flopay_shared.ButtonsLayoutStyles;
734
+ /**
735
+ * Appearance from `FloPayProvider` / `FloPayCheckout`. Threaded through so
736
+ * the React-rendered wrapper, AVS inputs, title, and hosted vault widget can
737
+ * derive colors from `appearance.variables` when no explicit `buttonsStyles`
738
+ * is supplied. Bundle consumers (`THEMES[id]`) get a coherent look without
739
+ * having to forward both halves manually.
740
+ */
741
+ appearance?: _flopay_shared.FloPayAppearance;
742
+ /** Custom React content rendered inside the card button when `layout="buttons"`. */
743
+ cardButtonContent?: React.ReactNode;
744
+ /** Custom React content rendered for the buttons-layout card back button label. */
745
+ cardBackButtonContent?: React.ReactNode;
746
+ /** Custom React content rendered for the card-form title. */
747
+ cardTitleContent?: React.ReactNode;
748
+ /**
749
+ * @deprecated No longer rendered — the default-layout security footer was
750
+ * removed alongside the theme-bundle refactor. Retained as an optional
751
+ * prop so existing integrations type-check without changes.
752
+ */
753
+ showSecurityFooter?: boolean;
761
754
  /**
762
- * If provided, called with the tokenized body once PayPal capture
763
- * completes. When omitted, the component processes payment internally.
755
+ * Called when a payment method button is clicked.
756
+ * `method`: `'card'` | `'paypal'` | `'apple_pay'` | `'google_pay'`
764
757
  */
765
- onTokenizedBody?: DirectPayPalTokenizedHandler;
766
- /** Called when the full self-contained payment flow succeeds. */
767
- onComplete?: (result: PaymentResult) => void;
768
- /** Called when an error occurs. */
769
- onErrorChange?: (error: string | null) => void;
770
- /** Decline emitter (mirrors SplitCardForm semantics). */
771
- onDecline?: (decline: DeclineEvent) => void;
772
- /** Called for post-click technical failures before PayPal authorization completes. */
773
- onTechnicalFailure?: DirectPayPalTechnicalFailureHandler;
774
- /** External processing state. */
775
- isProcessing?: boolean;
776
- /** Notify the parent of the loading state for placeholder swapping. */
777
- onLoadStateChange?: (ready: boolean) => void;
778
- /** Notify a PayPal-only wrapper about pre-render recovery state. */
779
- onInitializationStateChange?: (state: DirectPayPalInitializationState) => void;
780
- /** Disable the automatic retry for a buyer-initiated single manual attempt. */
781
- allowAutomaticRetry?: boolean;
782
- /** Tracks button-click for analytics. */
783
758
  onButtonClick?: (method: CheckoutButtonMethod) => void;
784
759
  /**
785
- * Click-time gate (runs before PayPal creates the order). When provided, the
786
- * returned patch is applied to the in-flight create-intent and tokenized
787
- * dispatch so callers using `onBeforeButtonClick` see the same session/email
788
- * the Stripe-rendered PayPal flow does.
760
+ * Called before a payment button continues in `layout="buttons"`.
761
+ * Runs for card, PayPal, Apple Pay, and Google Pay.
789
762
  */
790
- runBeforeButtonClick?: DirectPayPalRunBeforeButtonClick;
791
- /** Backing session — used for self-contained accountData population. */
763
+ onBeforeButtonClick?: (event: BeforeButtonClickEvent) => MaybePromise<undefined | false | InlineSessionPatch>;
764
+ /**
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
+ */
770
+ enableAVS?: boolean | AVSFieldConfig;
771
+ /**
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.
777
+ */
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;
811
+ /**
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.
816
+ */
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. */
792
825
  session?: CheckoutSession | null;
793
826
  /**
794
- * Pre-existing PayPal Order id (or Subscription id when `isSubscription` is
795
- * true) to bind the button to. When set, the button skips its usual
796
- * session-scoped create-intent round-trip on click and feeds this
797
- * id straight into PayPal's create-order / create-subscription callback.
798
- *
799
- * Used by `SplitCardForm`'s `paypal_direct_required` retry path: backend
800
- * creates a fresh PayPal order after a stalled process attempt and returns
801
- * its id; the SDK re-renders this button bound to that id so the buyer can
802
- * confirm with one more click without the backend re-creating the order on
803
- * each retry.
827
+ * True while a **detached** session's background claim is still in flight
828
+ * (TeamFloPay/backend#1099).
804
829
  *
805
- * Changing this value remounts the PayPal SDK so the new createOrder
806
- * 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.
807
837
  */
808
- existingOrderId?: string;
809
- /** Flo-owned privacy-safe telemetry is enabled by default; set `false` to opt out. */
810
- telemetry?: boolean;
838
+ dataAttachmentPending?: boolean;
811
839
  /**
812
- * When true, renders an on-screen lifecycle tracer panel above the button
813
- * (mount, loadScript, eligibility, render, errors). Intended for debugging
814
- * in-app browsers (Facebook IAB, etc.) where remote console access is
815
- * 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.
816
843
  */
817
844
  debug?: boolean;
818
845
  }
819
- /** Public direct-PayPal surface: telemetry accepts only the boolean opt-out. */
820
- 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;
821
854
 
822
- interface FloPayAutomaticPaymentSuccessEvent {
823
- result: PaymentResult;
824
- session: CheckoutSession | null;
825
- sessionId: string | null;
826
- autoCompleted: boolean;
827
- }
828
- interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
829
- sessionId?: string;
855
+ /** Props for {@link VaultCardFields}. */
856
+ interface VaultCardFieldsProps {
830
857
  /**
831
- * Session-bound checkout token for a consumer-supplied {@link sessionId}
832
- * (the `nonce` returned when that session was created). Post-#640 backends
833
- * require it as `x-checkout-session-token` to read the session and to
834
- * `/process` it; without it the existing-session path 401s with
835
- * "Missing checkout session token.". Ignored on the create-session path,
836
- * 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.
837
861
  */
838
- nonce?: string;
839
- createSession?: InlineSessionDraft;
862
+ capture: CardCaptureAdapter;
840
863
  /**
841
- * @deprecated Ignored. The backend now picks the customer's most recent
842
- * vaulted payment method via `getLatestByUserId` and rebinds the session's
843
- * gateway to match it (see `apps/api`'s `createSingle` auto-checkout
844
- * branch). Passing this prop has no effect it is retained only to avoid
845
- * 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.
846
868
  */
847
- paymentMethodId?: string;
869
+ html: string;
848
870
  /**
849
- * @deprecated Ignored. The backend orchestrates gateway routing — clients
850
- * no longer choose between card and PayPal at the SDK boundary. Passing
851
- * 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.
852
874
  */
853
- checkoutMethod?: CheckoutButtonMethod;
854
- clientId?: string;
875
+ messageToken?: string;
855
876
  /**
856
- * Unified products array (TeamFloPay/backend#760). When supplied,
857
- * `items`/`subscriptions` are ignored. The SDK folds the legacy fields
858
- * 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.
859
880
  */
860
- products?: CheckoutProduct[];
861
- items?: CheckoutItem[];
862
- subscriptions?: CheckoutSubscription[];
863
- account?: InlineSessionDraft['account'];
864
- successUrl?: string;
865
- cancelUrl?: string;
866
- couponCodes?: string[];
867
- tagsData?: InlineSessionDraft['tagsData'];
868
- utmMetadata?: InlineSessionDraft['utmMetadata'];
869
- billingApiUrl?: string;
870
- locale?: string;
881
+ expectedOrigin?: string;
871
882
  /**
872
- * High-level theme bundle that styles the button (and the fallback
873
- * `FloPayCheckout` modal that opens when the saved-payment charge needs
874
- * user interaction). One of: `'classic'`, `'modern-light'`, `'modern-dark'`,
875
- * `'bold-light'`, `'bold-dark'`, `'glass-light'`, `'glass-dark'`. Explicit
876
- * `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).
877
885
  */
878
- 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;
879
891
  /**
880
- * Per-checkout appearance overrides layered on top of the chosen `theme`
881
- * (same shape as {@link FloPayCheckout}'s `appearance`). Its `colorPrimary` /
882
- * `colorPrimaryHover` / `borderRadius` re-skin the button and the fallback
883
- * `FloPayCheckout` modal — so the auto-pay button matches the rest of the
884
- * 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.
885
896
  */
886
- appearance?: FloPayAppearance;
897
+ onError?: (message: string | null) => void;
887
898
  /**
888
- * @deprecated Use `theme` instead. Legacy buttons-layout preset
889
- * (`'default' | 'minimal' | 'rounded' | 'dark'`). Still honored for
890
- * 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`.
891
902
  */
892
- buttonsTheme?: ButtonsLayoutTheme;
893
- buttonsStyles?: ButtonsLayoutStyles;
894
- onSuccess?: (event: FloPayAutomaticPaymentSuccessEvent) => void;
895
- onError?: (error: FloPayError) => void;
896
- onDecline?: (decline: DeclineEvent) => void;
897
- children?: React.ReactNode;
903
+ onValidation?: (message: string | null) => void;
898
904
  }
899
- 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;
900
914
 
901
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 };