npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flopay/react

v1.3.0

Published

React bindings for the FloPay SDK. Provides a context provider, drop-in checkout form components, individual element components, and hooks.

Readme

@flopay/react

React bindings for the FloPay SDK. Provides a context provider, drop-in checkout form components, individual element components, and hooks.

Installation

pnpm add @flopay/react @flopay/js @flopay/shared react react-dom

Peer dependencies: react >= 18.0.0, react-dom >= 18.0.0.

Environment Setup

Configure which billing API the SDK uses. Choose one:

# Option A: Environment variable (recommended)
# .env.production
NEXT_PUBLIC_FLOPAY_ENV=production

# .env.development
NEXT_PUBLIC_FLOPAY_ENV=staging
// Option B: Call at app startup
import { configureFlopay } from '@flopay/shared';
configureFlopay({ environment: 'production' });

If neither is set, the SDK defaults to staging.

Quick Start

Recommended: FloPayCheckout

The simplest integration — one component, one prop:

import { FloPayCheckout } from '@flopay/react';

function CheckoutPage() {
  return (
    <FloPayCheckout
      sessionId="sess_abc123"
      onComplete={(result) => {
        window.location.href = '/success';
      }}
      onError={(err) => console.error(err)}
    />
  );
}

FloPayCheckout automatically fetches the session, initializes the correct payment provider, and renders a SplitCardForm with card fields, Apple Pay, Google Pay, and PayPal. Customer data (email, userId, name) is injected from the session.

Checkout Modes

FloPayCheckout supports three checkout modes matching the billing API's checkoutMode field:

  • full (default) — Shows the full payment form with card fields + wallet buttons.
  • confirm — Hides the payment form and shows a "Confirm Purchase" button. Uses a saved payment method on the backend.
  • auto — Auto-submits with a saved payment method after the session loads. Falls back to full mode on failure.
// Confirm mode — one-click purchase with saved card
<FloPayCheckout
  sessionId="sess_abc123"
  checkoutMode="confirm"
  confirmLabel="Complete Purchase"
  onComplete={(result) => router.push('/success')}
/>

// Auto mode — instant checkout, falls back to full form
<FloPayCheckout
  sessionId="sess_abc123"
  checkoutMode="auto"
  onComplete={(result) => router.push('/success')}
  onSessionCompleted={(successUrl) => router.push(successUrl)}
/>

The mode can also be set on the session itself via the billing API's checkoutMode field. The checkoutMode prop overrides the session value.

Expired Sessions

When FloPayCheckout or FloPayAutomaticPaymentButton loads a checkout session whose status is expired, the component calls onError with a FloPayError so your app can route the customer into a recovery flow.

The error has:

  • message: 'Checkout session has expired.'
  • type: 'api_error'
  • code: 'checkout_session_expired'

Use this code to create or request a fresh checkout session, then send the customer back through checkout:

<FloPayCheckout
  sessionId={sessionId}
  onComplete={() => router.push('/success')}
  onError={(error) => {
    if (error.code === 'checkout_session_expired') {
      router.push('/checkout/expired');
      return;
    }

    console.error(error);
  }}
/>

Automatic Payment Buttons

Use FloPayAutomaticPaymentButton when you want a single reusable button that:

  • creates an auto checkout session inline or reuses an existing sessionId
  • lets the backend resolve and charge the customer's most recently vaulted payment method (across providers)
  • shows the shared processing / success / failure modal
  • emits the same success and decline events without rendering a full checkout form

The button accepts either:

  • sessionId
  • or the same session-creation props you would normally post to the backend: clientId, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata

It accepts the same theme prop as FloPayCheckout and SplitCardForm (see Theming below) — the value is forwarded to the fallback FloPayCheckout modal so the entire flow stays visually consistent. When the saved-payment charge can't complete silently, the button opens the standard FloPayCheckout inline with the same theme already applied.

Removed in this version: the legacy paymentMethodId and checkoutMethod props are now @deprecated and silently ignored. The backend's auto-checkout (createSingle) looks up the customer's latest vaulted payment method via getLatestByUserId and rebinds the session's gateway to match, so the SDK no longer hand-picks a PM or a provider. Existing integrations that still pass these props continue to work — they have no effect.

import { FloPayAutomaticPaymentButton } from '@flopay/react';

function UpsellButton() {
  return (
    <FloPayAutomaticPaymentButton
      clientId="your-client-id"
      account={{ userId: 'user_1', email: '[email protected]' }}
      items={[
        {
          providerItemId: 'upsell_1',
          providerItemName: 'AI Supercharger Pack',
          totalAmount: 249,
          overrideAmount: 80,
          currency: 'EUR',
          quantity: 1,
        },
      ]}
      successUrl={`${window.location.origin}/success`}
      cancelUrl={`${window.location.origin}/success`}
      theme="bold-dark"
      onClick={() => {
        window.dataLayer?.push({ event: 'automatic_payment_button_click' });
      }}
      onSuccess={() => {
        console.log('automatic payment succeeded');
      }}
      onError={(error) => {
        console.error(error.message);
      }}
      onDecline={(decline) => {
        console.log('automatic payment declined', decline);
      }}
    >
      Purchase Item
    </FloPayAutomaticPaymentButton>
  );
}

children render inside the button, so you can treat them as slot content. If omitted, the default buttons-layout card content is used.

Wallet Buttons & alternative payment methods

The payment-method list is now gateway-driven: the billing API ships gateways.stripe.enabledPaymentMethods per session, derived from the Stripe Payment Method Configurations enabled on the merchant account. The SDK partitions that list into two regions inside SplitCardForm:

  • ExpressCheckoutElementapple_pay, google_pay, paypal, link, amazon_pay, klarna (everything supported as a native big button).
  • PaymentElement (accordion) — every other enabled method, e.g. cashapp, affirm, ideal, bancontact, sepa_debit.

Enabling Cash App Pay (or any future Stripe method) in the Stripe dashboard is the entire integration change — no SDK redeploy or consumer code update is required. Wallets only render on supported devices regardless of dashboard state (Apple Pay on Safari/macOS/iOS, Google Pay on Chrome).

Toggle the whole Stripe region or the PayPal region independently with the two gateway-level props:

<FloPayCheckout
  sessionId="sess_abc123"
  showStripe={true}  // default: true — card + ECE + PaymentElement
  showPayPal={true}  // default: true — DirectPayPal when gateway present,
                     //                  Stripe-rendered PayPal otherwise
  onComplete={handleSuccess}
/>

Setting both to false (with no PayPal gateway configured) is treated as a bootstrap-time validation error — onError fires with a FloPayError({ type: 'validation_error' }) so the misconfiguration surfaces during integration instead of silently rendering an empty form.

Deprecated props

showApplePay, showGooglePay, and directPaypal are still accepted but emit a one-time console.warn when supplied alongside the new enabledPaymentMethods payload. They are no-ops once the backend ships the field — Apple Pay / Google Pay are dashboard-controlled at Stripe, and direct PayPal is auto-resolved from gateways.paypal on the session response. The legacy props will be removed in 2.0.

Theming

FloPayCheckout, FloPayAutomaticPaymentButton, and SplitCardForm accept a single theme prop that maps to a coherent {appearance, buttonsLayout} bundle in @flopay/shared's THEMES map. One value styles the Stripe-side appearance, the React-rendered wrapper, the submit button, the inputs, and — for FloPayAutomaticPaymentButton — the fallback modal that opens when a saved-payment charge can't complete silently.

| theme | Aesthetic | |---|---| | 'classic' | Historic FloPay look (no bundle applied — #EDEDFF wrapper, indigo submit). | | 'modern-light' / 'modern-dark' | Clean & airy, Inter, soft shadows, FloPay-blue accents. | | 'bold-light' / 'bold-dark' | Saturated FloPay blue with gradient pill submit and heavy borders. | | 'glass-light' / 'glass-dark' | Translucent surfaces with backdrop blur over a blue gradient. |

<FloPayCheckout
  sessionId="sess_abc123"
  theme="bold-dark"
  onComplete={handleSuccess}
/>

<FloPayAutomaticPaymentButton
  sessionId="sess_abc123"
  theme="bold-dark" // applied to the button AND the fallback modal
  onSuccess={handleSuccess}
/>

appearance (Stripe-side overrides) and buttonsStyles (per-field wrapper overrides) still work — both win over the resolved bundle for the fields they touch, so you can layer customizations on top of a theme:

<FloPayCheckout
  theme="modern-light"
  buttonsStyles={{ submitButton: { backgroundColor: '#FF0099' } }} // wins
/>

Buttons Layout

Switch from the default form layout to stacked payment buttons with an expandable card form:

<FloPayCheckout
  sessionId="sess_abc123"
  layout="buttons"
  theme="bold-dark"
  onButtonClick={(method) => console.log('clicked:', method)}
  onComplete={handleSuccess}
/>

Deprecated: the legacy buttonsTheme prop ('default' / 'minimal' / 'rounded' / 'dark') still works but new code should use theme so the same value drives both the buttons-layout wrapper and the auto-payment fallback. See ButtonsLayoutStyles reference for the underlying override fields.

Button Hooks

Use onButtonClick to track button interactions, onDecline to track declines/cancellations, and onBeforeButtonClick to enrich any buttons-layout payment method before it continues:

<FloPayCheckout
  layout="buttons"
  createSession={{
    clientId: 'your-client-id',
    currency: 'EUR',
    items: [{ providerItemId: 'product-1', providerItemName: 'Widget', totalAmount: 29.99 }],
    account: { userId: 'user_1', email: '[email protected]' },
    successUrl: '/success',
    cancelUrl: '/cancel',
  }}
  onBeforeButtonClick={async ({ method, createSession }) => {
    if (method !== 'card') {
      return {
        tagsData: { sessionId: `checkout_${method}_clicked` },
      };
    }

    const email = await openEmailCaptureModal({
      initialEmail: createSession?.account.email ?? '',
    });
    if (!email) return false;

    return {
      account: { email },
      tagsData: { sessionId: 'checkout_email_captured' },
    };
  }}
  onButtonClick={(method) => {
    window.dataLayer?.push({ event: 'checkout_button_click', payment_method: method });
  }}
  onDecline={(decline) => {
    window.dataLayer?.push({ event: 'checkout_decline', ...decline });
  }}
  onComplete={handleSuccess}
/>

onBeforeButtonClick runs for every payment button in layout="buttons". Branch on method if only some flows need extra work. For PayPal, Apple Pay, and Google Pay, keep the hook fast because it runs during the provider button handshake before the wallet sheet or PayPal window opens.

Inline Session Creation

Skip the backend API route — create the session directly in the component:

<FloPayCheckout
  layout="buttons"
  createSession={{
    clientId: 'your-client-id',
    currency: 'EUR',
    items: [{ providerItemId: 'product-1', providerItemName: 'Widget', totalAmount: 29.99 }],
    account: { userId: 'user_1', email: '[email protected]', firstName: 'Jane', lastName: 'Doe' },
    successUrl: '/success',
    cancelUrl: '/cancel',
  }}
  onComplete={(result) => window.location.href = '/success'}
/>

The component POSTs to the billing API, gets the full session back, and renders the form — zero backend code needed.

Session-level currency is now required. The backend (#760) enforces @IsNotEmpty on the field; the SDK pre-validates and throws FloPayError({ type: 'validation_error', code: 'CurrencyRequired' }) before issuing the request when neither the session nor any item/subscription/product carries a currency. Pass currency at the top of createSession (preferred), or rely on the legacy fallback to the first item/subscription/product currency.

When you use onBeforeButtonClick with createSession, any returned InlineSessionPatch is merged into the draft session params before the selected buttons-layout flow continues. That lets you add tracking data or update account fields just in time without pre-creating a separate backend session.

Advanced: Manual Provider Setup

For full control over initialization:

import { loadFloPay } from '@flopay/js';
import { FloPayProvider, CheckoutForm } from '@flopay/react';

const floPayPromise = loadFloPay('pk_test_...');

function CheckoutPage() {
  return (
    <FloPayProvider
      flopay={floPayPromise}
      options={{
        amount: 2999,
        currency: 'usd',
      }}
    >
      <CheckoutForm
        sessionId="session_uuid"
        nonce={sessionNonce}
        email="[email protected]"
        userId="user_1"
        onComplete={(result) => {
          if (result.status === 'succeeded') {
            window.location.href = '/success';
          }
        }}
        onError={(err) => console.error(err)}
      />
    </FloPayProvider>
  );
}

CheckoutForm handles the full payment lifecycle by default:

  1. Validate elements via submitElements()
  2. Tokenize card via createPaymentMethod() -> pm_xxx
  3. Create PaymentIntent via billing API
  4. Confirm card payment (handles 3D Secure)
  5. Submit tokenized body to POST /v1/checkouts/sessions/<id>/process
  6. If backend returns 3ds_required, re-confirm with new client secret
  7. Resume wallet payments after redirect (PayPal)

Pass nonce (the session-bound checkout token returned by session creation — CheckoutSessionResult.nonce, or session.clientSecret once the session is loaded). The SDK forwards it as x-checkout-session-token on every continuation call. Post-#640 backends (TeamFloPay/backend#640) 401 when the header is missing. FloPayCheckout already plumbs the prop automatically.

Override Mode (Custom Backend)

Pass onTokenizedBody to handle backend submission yourself:

<CheckoutForm
  sessionId="session_uuid"
  billingApiUrl="https://billing.example.com"
  email="[email protected]"
  onTokenizedBody={(body) => {
    // body = {
    //   id: 'pm_xxx',
    //   type: 'card',
    //   threeDSecureActionResultTokenId: 'pi_xxx',
    //   originalPaymentMethodId: 'pm_xxx',
    // }
    myCustomProcessPayment(body);
  }}
/>

Vault card path — onTokenizedBody does not fire. When the session uses the vault PCI card form, the backend-served widget owns the whole charge (tokenize → PaymentIntent → 3DS → result), so there is no client-side tokenization step to override. Use onComplete / onDecline / onError instead — the SDK relays the widget's terminal outcome to them. The legacy Stripe path's onTokenizedBody is unchanged.

SplitCardForm (Split Card Fields + PayPal)

SplitCardForm renders separate CardNumber, CardExpiry, and CardCVC fields with an integrated PayPal button. It matches the existing checkout/StripeCardForm layout.

import { FloPayProvider, SplitCardForm } from '@flopay/react';
import { loadFloPay } from '@flopay/js';

const floPayPromise = loadFloPay('pk_test_...');

function CheckoutPage() {
  return (
    <FloPayProvider
      flopay={floPayPromise}
      options={{
        amount: 2999,
        currency: 'usd',
      }}
    >
      <SplitCardForm
        sessionId="session_uuid"
        nonce={sessionNonce}
        billingApiUrl="https://billing.example.com"
        email="[email protected]"
        userId="user_1"
        totalAmount={29.99}    // dollars (for PayPal Elements config)
        currency="usd"
        showPayPal={true}      // default: true
        onComplete={(result) => {
          if (result.status === 'succeeded') {
            window.location.href = '/success';
          }
        }}
        onError={(err) => console.error(err)}
        onFirstNameChange={(name) => setFirstName(name)}
        onLastNameChange={(name) => setLastName(name)}
      />
    </FloPayProvider>
  );
}

The SplitCardForm layout:

  1. Wallet buttons — Apple Pay + Google Pay (via ExpressCheckoutElement in the main Elements instance)
  2. PayPal button (via ExpressCheckoutElement in a separate Elements instance)
  3. "or pay with card" divider
  4. Card Number input
  5. Card Expiry + CVC side by side
  6. Full Name input
  7. Submit button

Vault PCI card form

When the billing API returns a hosted vault card form on the session (session.vault), the card path renders a backend-served, self-contained hosted vault widget (VaultCardFields) instead of Stripe's embedded card elements (TeamFloPay/backend#823, Model A). The backend embeds this block for any SDK that advertises x-flo-sdk-version >= 1.3.0, so it is fully server-driven — there is no consumer prop to toggle it. The widget owns the card fields, its own submit button, card tokenization, the PaymentIntent (created and confirmed server-side), 3DS, and the result, so no Stripe.js runs on the card path and PAN / CVC never enter the SDK runtime. Wallets / PayPal / APMs render exactly as before.

Because the widget owns the form, on the vault path SplitCardForm hides its own card fields, cardholder-name input, AVS fields, and submit button. The flow is:

session includes a hosted vault card form (session.vault)
  → SDK injects the widget HTML (session.vault.html, or POST /vault/capture)
  → buyer pays inside the widget (tokenize → charge → 3DS, all backend-owned)
  → widget postMessages its outcome → SDK fires onComplete / onDecline / onError
  • The widget HTML comes from the embedded session.vault.html (SDKs ≥ 1.3.0 send X-Flo-SDK-Version, so the backend embeds it on create-session) or, if absent, from POST /v1/checkouts/sessions/{id}/vault/capture.
  • Returning customers with a card on file (session.providerPaymentMethodId) are charged by the backend's auto-checkout cascade.
  • 3DS is handled inside the widget — there is no client-side confirmCardPayment.

Failure modes: the widget renders its own status / decline UI; onDecline / onError receive the mapped reason + message so consumers can react.

Backend dependencies: the hosted widget must emit the flopay-vault postMessage outcome the SDK listens for (otherwise it falls back to its own success redirect), handle the 3DS step internally, and own AVS for the vault path (the SDK no longer collects it inline; account-level address set at session-create still flows to the backend). Because the widget is injected same-window, every terminal outcome must be bound to the session id, and — to fully defend against same-window forgery — the backend should mint a per-session messageToken on the vault block and echo it in each postMessage; the SDK threads it through and rejects outcomes that omit or mismatch it (TeamFloPay/backend#823).

PayPal Handling

The SDK supports two PayPal paths, selected per-session based on what the billing API advertises under gateways.*:

  • Direct PayPal (preferred where available — works inside Facebook, Instagram, and other in-app browsers): when the session exposes gateways.paypal.publishableKey, the SDK renders PayPal via the official PayPal JS SDK using <DirectPayPalButton>. The PayPal client ID and environment ('sandbox'/'live') come directly from the backend.
  • Stripe-rendered PayPal fallback (legacy): when only gateways.stripe is configured, PayPal renders through Stripe's ExpressCheckoutElement in its own Elements wrapper. This path can't render in Facebook/Instagram in-app browsers.

Renderer selection is mutually exclusive per session — direct PayPal takes priority over Stripe-rendered PayPal. Consumer props such as showPayPal continue to gate visibility on the client side.

PayPal-only sessions: When the backend advertises only gateways.paypal (no gateways.stripe), FloPayCheckout skips Stripe Elements entirely and renders <DirectPayPalButton> as the sole payment surface. Sessions that advertise no supported gateway at all throw a validation_error explaining the expected shape.

The SDK exposes the relevant pieces in three ways:

  • SplitCardForm / FloPayCheckout: pick the renderer automatically based on gateways.*. No additional configuration needed.

  • FloPayProvider (manual composition): accepts an optional paypalFlopay prop used to drive Stripe's PayPal redirect leg. Load a second FloPay instance yourself only if you need to render PayPal manually. usePayPalFloPay() exposes it to descendants.

  • DirectPayPalButton (standalone): can be rendered outside SplitCardForm when you only need the PayPal button. Pass clientId, currency, environment, and isSubscription.

  • PayPalButton (standalone): Must be rendered inside its own FloPayProvider:

{/* Card fields provider */}
<FloPayProvider flopay={flopay} options={{ amount, currency }}>
  <SplitCardForm ... />
</FloPayProvider>

{/* PayPal provider (separate instance) */}
<FloPayProvider flopay={flopay} options={{ amount, currency, paymentMethodCreation: 'auto' }}>
  <PayPalButton
    sessionId="session_uuid"
    billingApiUrl="https://billing.example.com"
    email="[email protected]"
    onComplete={() => router.push('/success')}
  />
</FloPayProvider>

Using Individual Elements

import { FloPayProvider, PaymentElement, CardElement, useFloPay } from '@flopay/react';

function CustomForm() {
  const flopay = useFloPay();

  const handleSubmit = async () => {
    if (!flopay) return;
    const { error } = await flopay.submitElements();
    if (error) return console.error(error);
    const { paymentMethodId } = await flopay.createPaymentMethod();
    // Use paymentMethodId...
  };

  return (
    <div>
      <PaymentElement options={{ layout: 'tabs' }} />
      <button onClick={handleSubmit}>Pay</button>
    </div>
  );
}

Using Hooks

import { useFloPay, useElements, useCheckout } from '@flopay/react';

function PaymentStatus() {
  const flopay = useFloPay();       // FloPay | null
  const elements = useElements();    // FloPayElements | null
  const checkout = useCheckout();    // { session, loading, error }

  if (!flopay) return <div>Loading SDK...</div>;
  // ...
}

API Reference

Components

| Component | Description | |-----------|-------------| | FloPayProvider | Context provider. Accepts flopay (instance or promise), options?, and children. Creates the elements group automatically. | | CheckoutForm | Drop-in form with unified PaymentElement. Self-contained by default, or override with onTokenizedBody. Supports ref for imperative handleNextAction(). | | SplitCardForm | Split card form (CardNumber + CardExpiry + CardCvc + Full Name). Integrates PayPal via separate Elements instance. Renders the vault PCI card form when the session includes a hosted vault card form (session.vault). Supports ref for imperative handleNextAction(). | | VaultCardFields | Hosted vault PCI card fields. Used internally by SplitCardForm on the vault path; consumes a CardCaptureAdapter from useFloPay().cardCapture(). | | PayPalButton | Standalone PayPal button. Requires its own FloPayProvider with paymentMethodCreation set to something other than 'manual'. | | PaymentElement | Unified payment element (cards, wallets, etc.) | | CardElement | Combined card input | | CardNumberElement | Card number field | | CardExpiryElement | Card expiry field | | CardCvcElement | Card CVC field | | AddressElement | Address input element |

Hooks

| Hook | Returns | Description | |------|---------|-------------| | useFloPay() | FloPay \| null | Current FloPay instance from context. null while loading. | | useElements() | FloPayElements \| null | Current elements group from context. null while loading. | | useCheckout() | CheckoutState | { session, loading, error } from CheckoutContext |

FloPayProviderProps

| Prop | Type | Description | |------|------|-------------| | flopay | Promise<FloPay> \| FloPay | SDK instance or promise from loadFloPay() | | options.locale | string? | Locale | | options.appearance | FloPayAppearance? | Theme appearance | | options.clientSecret | string? | PaymentIntent client secret (if intent already exists) | | options.amount | number? | Amount in cents (used when no clientSecret) | | options.currency | string? | ISO 4217 currency code (used when no clientSecret) | | options.paymentMethodCreation | 'manual' \| 'auto' | How payment methods are created |

CheckoutFormProps

| Prop | Type | Description | |------|------|-------------| | sessionId | string | Checkout session UUID | | billingApiUrl | string | Billing API base URL | | email | string? | User email | | userId | string? | User ID | | onComplete | (result: PaymentResult) => void | Success callback | | onError | (error: FloPayError) => void | Error callback | | onTokenizedBody | (body: TokenizedBody) => void | Override: handle backend submission yourself | | layout | 'tabs' \| 'accordion' \| 'auto' | PaymentElement layout (default: 'auto') | | submitLabel | string | Button text (default: 'Pay') | | showAddress | boolean \| 'billing' \| 'shipping' | Show address element (default: false) | | className | string? | CSS class for form wrapper | | children | ReactNode? | Custom submit button | | firstName | string? | Billing first name | | lastName | string? | Billing last name | | chv | string? | Checkout version for A/B tracking | | isProcessing | boolean? | External processing state | | error | string? | External error message | | onErrorChange | (error: string \| null) => void | Error state change callback |

SplitCardFormProps

Shares most props with CheckoutFormProps, plus:

| Prop | Type | Description | |------|------|-------------| | showStripe | boolean | Show the whole Stripe surface (card + ECE + PaymentElement). Default: true. Setting showStripe={false} together with showPayPal={false} (or no PayPal gateway) emits a FloPayError({ type: 'validation_error' }) via onError. | | showPayPal | boolean | Show PayPal. Renderer chosen by gateways.paypal presence (DirectPayPal JS SDK when present; Stripe-rendered PayPal otherwise). Default: true. | | enabledPaymentMethods | string[]? | Per-session list of Stripe method type identifiers (apple_pay, google_pay, cashapp, klarna, link, amazon_pay, sepa_debit, affirm, ideal, …). Normally threaded automatically from gateways.stripe.enabledPaymentMethods by FloPayCheckout. The SDK partitions it into the ExpressCheckoutElement big-button row (intersected with STRIPE_EXPRESS_METHODS) and the accordion PaymentElement region (everything else; card is always dropped because the split fields render the card path). | | showApplePay | boolean | Deprecated. Apple Pay availability is dashboard-controlled at Stripe and surfaces through enabledPaymentMethods. Emits a one-time console.warn when supplied alongside enabledPaymentMethods and is otherwise ignored. Removed in 2.0. | | showGooglePay | boolean | Deprecated. See showApplePay. | | directPaypal | { clientId: string; environment?: GatewayEnvironment }? | Deprecated input on FloPayCheckout — auto-resolved from gateways.paypal on the session response. Still accepted on SplitCardForm for advanced consumers wiring providers manually. | | totalAmount | number | Amount in cents for PayPal / wallet config | | currency | string | Currency code for PayPal / wallet config (default: 'usd') | | onFirstNameChange | (value: string) => void | First name change callback | | onLastNameChange | (value: string) => void | Last name change callback | | submitLabel | string | Button text (default: 'CONFIRM PAYMENT') |

ElementComponentProps (shared by all element components)

| Prop | Type | Description | |------|------|-------------| | className | string? | CSS class for wrapper div | | id | string? | HTML id for wrapper div | | style | CSSProperties? | Inline styles for wrapper div | | options | Partial<ElementOptions>? | Options for the underlying element | | onChange | (event: ElementChangeEvent) => void | Value change handler | | onReady | () => void | Element ready handler | | onFocus | () => void | Focus handler | | onBlur | () => void | Blur handler | | onEscape | () => void | Escape key handler |

Types

| Type | Description | |------|-------------| | FloPayProviderProps | Props for FloPayProvider | | CheckoutFormProps | Props for CheckoutForm | | CheckoutFormRef | Ref type: { handleNextAction(clientSecret) } | | SplitCardFormProps | Props for SplitCardForm | | SplitCardFormRef | Ref type: { handleNextAction(clientSecret) } | | PayPalButtonProps | Props for PayPalButton | | ElementComponentProps | Shared props for all element components | | CheckoutState | { session, loading, error } |