@flopay/shared 1.4.1 → 1.4.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/errors.ts","../src/telemetry.ts","../src/config.ts","../src/payment-logos.generated.ts","../src/constants.ts","../src/postal-code-lookup.ts","../src/postal-code-validation.ts","../src/checkout-payload.ts","../src/display.ts","../src/validation.ts","../src/idempotency.ts"],"sourcesContent":["// Types\nexport type {\n FloPayThemeVariables,\n FloPayAppearance,\n Customer,\n RecurringInterval,\n PriceData,\n LineItem,\n CheckoutMode,\n CheckoutSession,\n CheckoutSessionProduct,\n CheckoutProduct,\n CheckoutProductType,\n PaymentResult,\n ConfirmPaymentParams,\n CreatePaymentMethodResult,\n ConfirmCardPaymentParams,\n CardThreeDsLifecycle,\n ConfirmCardPaymentResult,\n ElementType,\n ElementChangeEvent,\n ElementOptions,\n MountedElement,\n FloPayConfig,\n PaymentProviderAdapter,\n BillingProvider,\n GatewayEnvironment,\n NormalizedGatewayEnvironment,\n CheckoutGateway,\n CheckoutGateways,\n TokenizedBody,\n CheckoutProcessError,\n CheckoutProcessingPending,\n CheckoutModeKind,\n NormalizedCheckoutSession,\n CheckoutItem,\n CheckoutSubscription,\n CheckoutAccount,\n TagsData,\n CreateSessionParams,\n CheckoutSessionResult,\n ProcessPaymentParams,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n CurrencyInfo,\n CountryOption,\n ButtonsLayoutStyles,\n ButtonsLayoutTheme,\n CardCaptureProviderId,\n VaultCaptureBlock,\n CardCaptureMountOptions,\n VaultCardThemeColors,\n VaultCardFieldKey,\n CardCaptureEventType,\n CardCaptureOutcomeEvent,\n VaultCaptureResultMessage,\n CardCaptureAdapter,\n AVSFieldConfig,\n InlineSessionParams,\n InlineSessionDraft,\n InlineSessionPatch,\n BeforeButtonClickEvent,\n CheckoutButtonMethod,\n DeclineEvent,\n BillingDetails,\n ThemeBundle,\n ThemeBundleId,\n ThemeId,\n} from './types.js';\nexport { normalizeGatewayEnvironment } from './types.js';\n\n// Errors\nexport {\n FloPayError,\n validationError,\n apiError,\n authenticationError,\n rateLimitError,\n networkError,\n} from './errors.js';\nexport type { FloPayErrorType } from './errors.js';\n\n// Privacy-safe SDK telemetry contract\nexport {\n TELEMETRY_SCHEMA_VERSION,\n TELEMETRY_SDK_PACKAGES,\n TELEMETRY_MAX_BATCH_BYTES,\n TELEMETRY_MAX_BATCH_EVENTS,\n TELEMETRY_ERROR_CODES,\n TELEMETRY_LOG_NAMES,\n buildTelemetryErrorEvent,\n buildTelemetryLogEvent,\n buildTelemetryPerformanceEvent,\n buildTelemetryTerminalEvent,\n serializeTelemetryBatch,\n} from './telemetry.js';\nexport type {\n BuildTelemetryErrorEventInput,\n BuildTelemetryLogEventInput,\n BuildTelemetryPerformanceEventInput,\n BuildTelemetryTerminalEventInput,\n SerializeTelemetryBatchOptions,\n TelemetryBatchEnvelope,\n TelemetryCheckoutMode,\n TelemetryDurationMode,\n TelemetryErrorCode,\n TelemetryErrorEvent,\n TelemetryEvent,\n TelemetryEventClass,\n TelemetryExpectedOutcome,\n TelemetryExpectedOutcomeEvent,\n TelemetryLayout,\n TelemetryLogEvent,\n TelemetryLogName,\n TelemetryPaymentMethodCategory,\n TelemetryPerformanceEvent,\n TelemetryProvider,\n TelemetryProviderInput,\n TelemetryRequestCategory,\n TelemetrySdkPackage,\n TelemetryStage,\n TelemetryStatusClass,\n} from './telemetry.js';\n\n// Configuration\nexport { configureFlopay, getConfiguredBillingApiUrl, getFloPayEnvironment } from './config.js';\nexport type { FloPayEnvironment } from './config.js';\n\n// Constants\nexport {\n SDK_VERSION,\n FLO_SDK_VERSION_HEADER,\n DEFAULT_API_BASE_URL,\n DEFAULT_API_VERSION,\n BILLING_API_URL,\n BILLING_API_URL_STAGING,\n BILLING_API_URL_PRODUCTION,\n resolveBillingApiUrl,\n DEFAULT_APPEARANCE,\n FLAT_APPEARANCE,\n NIGHT_APPEARANCE,\n MODERN_LIGHT_APPEARANCE,\n MODERN_DARK_APPEARANCE,\n BOLD_LIGHT_APPEARANCE,\n BOLD_DARK_APPEARANCE,\n GLASS_LIGHT_APPEARANCE,\n GLASS_DARK_APPEARANCE,\n ELEMENT_TYPES,\n SUPPORTED_CARD_BRANDS,\n CURRENCY_MAP,\n DEFAULT_CURRENCY,\n BUTTONS_LAYOUT_DEFAULT,\n BUTTONS_LAYOUT_MINIMAL,\n BUTTONS_LAYOUT_ROUNDED,\n BUTTONS_LAYOUT_DARK,\n BUTTONS_LAYOUT_MODERN_LIGHT,\n BUTTONS_LAYOUT_MODERN_DARK,\n BUTTONS_LAYOUT_BOLD_LIGHT,\n BUTTONS_LAYOUT_BOLD_DARK,\n BUTTONS_LAYOUT_GLASS_LIGHT,\n BUTTONS_LAYOUT_GLASS_DARK,\n THEMES,\n resolveTheme,\n resolveButtonsLayoutTheme,\n getPostalCodeLabel,\n COUNTRY_OPTIONS,\n getCountryByCode,\n resolveAVSConfig,\n isAVSFieldVisible,\n isAVSEnabled,\n US_STATES,\n CA_PROVINCES,\n getStateOptions,\n getStateLabel,\n type StateOption,\n STRIPE_EXPRESS_METHODS,\n STRIPE_METHOD_CURRENCIES,\n STRIPE_METHOD_COUNTRIES,\n STRIPE_METHOD_AMOUNT_LIMITS,\n STRIPE_METHOD_MATRIX,\n type StripeMethodEntry,\n type StripeMethodThemeVariant,\n filterStripeMethodsByCurrency,\n filterStripeMethodsByCountry,\n filterStripeMethodsByAmount,\n getStripeMethodDisplayName,\n hasVendoredStripeMethodLogo,\n needsStripeMethodExplicitConfirm,\n resolveStripeMethodBrandVariant,\n partitionStripeMethods,\n stripeExpressMethodToOptionKey,\n} from './constants.js';\n\n// Postal code lookups\nexport { getStateFromPostalCode } from './postal-code-lookup.js';\n\n// Postal code format validation (country-aware, mirrors backend #887)\nexport {\n isPostalCodeSupported,\n isValidPostalCode,\n getPostalCodeExample,\n} from './postal-code-validation.js';\n\n// Display helpers\nexport { buildCheckoutDisplayData } from './display.js';\nexport type {\n DisplayLineItem,\n CheckoutDisplayData,\n BuildCheckoutDisplayDataOptions,\n} from './display.js';\n\n// Checkout payload helpers\nexport {\n resolveSessionCurrency,\n foldIntoProducts,\n buildProductPayload,\n buildItemPayload,\n buildSubscriptionPayload,\n} from './checkout-payload.js';\n\n// Validation helpers\nexport {\n getCurrencyByCountry,\n isValidPublishableKey,\n isValidSecretKey,\n isSetupIntentClientSecret,\n} from './validation.js';\n\n// Idempotency (stable checkout-create key — TeamFloPay/backend#972)\nexport {\n IDEMPOTENCY_KEY_HEADER,\n MAX_IDEMPOTENCY_KEY_LENGTH,\n IDEMPOTENCY_IN_PROGRESS_CODE,\n generateIdempotencyKey,\n resolveIdempotencyKey,\n} from './idempotency.js';\n","// ---------------------------------------------------------------------------\n// Appearance / Theming\n// ---------------------------------------------------------------------------\n\n/** Theme variables that map to CSS custom properties on FloPay elements. */\nexport interface FloPayThemeVariables {\n colorPrimary?: string;\n /** Hover background for all \"flo\" buttons (submit / card / wallet CTAs). */\n colorPrimaryHover?: string;\n colorBackground?: string;\n colorText?: string;\n colorDanger?: string;\n borderRadius?: string;\n fontFamily?: string;\n fontSizeBase?: string;\n spacingUnit?: string;\n}\n\n/** Controls the visual appearance of all FloPay elements. */\nexport interface FloPayAppearance {\n theme?: 'default' | 'flat' | 'night' | 'none';\n variables?: FloPayThemeVariables;\n /** CSS-like rules keyed by selector (e.g. `\".Input\"`, `\".Label\"`). */\n rules?: Record<string, Record<string, string>>;\n}\n\n/** Style overrides for the `buttons` layout mode. */\nexport interface ButtonsLayoutStyles {\n /** Style for the \"Credit / Debit Card\" button. */\n cardButton?: Record<string, string | number>;\n /** Font size for the \"Credit / Debit Card\" button label. */\n cardButtonFontSize?: string;\n /** Style for the card form container when expanded. */\n cardFormContainer?: Record<string, string | number>;\n /** Border color for card input fields. */\n cardInputBorder?: string;\n /** Text color inside the card input fields (number, expiry, CVC). */\n cardInputColor?: string;\n /** Placeholder text color for the card input fields. */\n cardInputPlaceholderColor?: string;\n /** Font size for the card input fields. */\n cardInputFontSize?: string;\n /** Background color for card input fields. */\n cardInputBackground?: string;\n /**\n * Opt-in escape hatch for vault-only style hooks that the appearance →\n * hosted-field mapper cannot express. Merged last (last-write-wins) into the\n * style config handed to the vault PCI card form, so these win over the\n * auto-translated `cardInput*` knobs and `appearance.variables`. Keys are\n * passed through verbatim — use vault-supported style property names.\n * No effect on the legacy Stripe-Elements card path.\n */\n vaultCardForm?: Record<string, string | number>;\n /** Style for the full-name text input. */\n nameInput?: Record<string, string | number>;\n /** Style for the \"Go back\" button text/container. */\n backButton?: Record<string, string | number>;\n /** Font size for the \"Go back\" button label. */\n backButtonFontSize?: string;\n /** Style for the back button circle icon. */\n backButtonIcon?: Record<string, string | number>;\n /** Style for the submit/confirm button. */\n submitButton?: Record<string, string | number>;\n /** Font size for the submit button label. */\n submitButtonFontSize?: string;\n /** Style for the \"Secure card checkout\" title. */\n title?: Record<string, string | number>;\n /** Font size for the \"Secure card checkout\" title. */\n titleFontSize?: string;\n /** Style for the error banner. */\n errorBanner?: Record<string, string | number>;\n /** Style for the country select dropdown container (AVS). */\n countrySelect?: Record<string, string | number>;\n /** Style for the ZIP/postcode input container (AVS). */\n zipInput?: Record<string, string | number>;\n /** Style for the street address input (AVS address_line_1). */\n addressLine1Input?: Record<string, string | number>;\n /** Style for the apt/suite input (AVS address_line_2). */\n addressLine2Input?: Record<string, string | number>;\n /** Style for the city input (AVS). */\n cityInput?: Record<string, string | number>;\n /** Style for the state/province input or dropdown (AVS). */\n stateInput?: Record<string, string | number>;\n}\n\n/** Predefined theme for the `buttons` layout. */\nexport type ButtonsLayoutTheme =\n | 'default'\n | 'minimal'\n | 'rounded'\n | 'dark'\n | 'modern-light'\n | 'modern-dark'\n | 'bold-light'\n | 'bold-dark'\n | 'glass-light'\n | 'glass-dark';\n\n/**\n * Identifier for a coherent {appearance, buttonsLayout} theme bundle exported\n * by `@flopay/shared`. Subset of `ButtonsLayoutTheme` covering the bundles\n * that ship matching `*_APPEARANCE` + `BUTTONS_LAYOUT_*` halves.\n */\nexport type ThemeBundleId =\n | 'modern-light'\n | 'modern-dark'\n | 'bold-light'\n | 'bold-dark'\n | 'glass-light'\n | 'glass-dark';\n\n/**\n * Theme identifier accepted by FloPay React components (`FloPayCheckout`,\n * `FloPayAutomaticPaymentButton`, `SplitCardForm`) on the `theme` prop.\n *\n * - `'classic'` — historic FloPay look (no bundle applied); kept as the\n * no-theme baseline so consumers can declare it explicitly.\n * - Bundle ids (`'modern-light'`, `'glass-dark'`, …) pull both halves\n * (`appearance` + `buttonsLayout`) from {@link THEMES} so a single prop\n * styles every part of the checkout consistently.\n */\nexport type ThemeId = 'classic' | ThemeBundleId;\n\n/** A coherent theme: appearance for Stripe Elements + wrapper styles for the FloPay buttons/card form. */\nexport interface ThemeBundle {\n appearance: FloPayAppearance;\n buttonsLayout: ButtonsLayoutStyles;\n}\n\n// ---------------------------------------------------------------------------\n// AVS Field Configuration\n// ---------------------------------------------------------------------------\n\n/**\n * Per-field AVS configuration.\n * - `true` = show for all countries\n * - `string[]` = show only for listed country codes (ISO 3166-1 alpha-2)\n * - `false` or omitted = hidden\n */\nexport interface AVSFieldConfig {\n /** Street address (line 1). */\n address_line_1?: boolean | string[];\n /** Apt, suite, unit, etc. (line 2). */\n address_line_2?: boolean | string[];\n /** City / Town. */\n city?: boolean | string[];\n /** State / Province / Region. Renders as dropdown for US and CA. */\n state?: boolean | string[];\n /** ZIP / Postal code. */\n postal_code?: boolean | string[];\n /** Country dropdown. */\n country?: boolean | string[];\n}\n\n// ---------------------------------------------------------------------------\n// Checkout Session (mirrors checkout project's CheckoutSession)\n// ---------------------------------------------------------------------------\n\n/** A customer attached to a checkout session. */\nexport interface Customer {\n id: string;\n email: string;\n firstName?: string;\n lastName?: string;\n gender?: string;\n city?: string;\n state?: string;\n country?: string;\n zip?: string;\n /** Street address (line 1). */\n line1?: string;\n /** Apt, suite, unit (line 2). */\n line2?: string;\n}\n\n/** Recurring interval configuration for subscription line items. */\nexport interface RecurringInterval {\n interval: 'month' | 'year';\n intervalCount?: number;\n}\n\n/** Inline product data when no pre-created price is referenced. */\nexport interface PriceData {\n currency: string;\n unitAmount: number;\n productData: { name: string; description?: string };\n recurring?: RecurringInterval;\n}\n\n/** A single line item within a checkout session. */\nexport interface LineItem {\n /** Reference to a pre-created price object on the provider. */\n price?: string;\n /** Inline price data (used when no `price` reference exists). */\n priceData?: PriceData;\n quantity: number;\n}\n\n/** Checkout mode controlling the payment UI behavior. */\nexport type CheckoutMode = 'full' | 'auto' | 'confirm';\n\n/**\n * Discriminator describing whether a checkout product is a one-time item or a\n * recurring subscription. Mirrors the backend's `ProductTypeEnum`.\n */\nexport type CheckoutProductType = 'item' | 'subscription';\n\n/** Unified checkout product from a session response. */\nexport interface CheckoutSessionProduct {\n uuid: string;\n checkoutSessionId: string;\n /**\n * Whether this product is a one-time item or a recurring subscription.\n * Optional to mirror {@link CheckoutProduct.type}; when omitted, consumers\n * treat the product as an `'item'` for display ordering.\n */\n type?: CheckoutProductType;\n /** Preferred catalog code for the product. */\n code?: string;\n /**\n * Display-only name. Resolved from the catalog server-side; the SDK\n * populates this from the client-side display cache when missing.\n */\n name?: string | null;\n /** Display-only description from the catalog. */\n description?: string | null;\n quantity: number;\n /** Display-only. Populated from cache when the server omits it. */\n totalAmount?: number;\n /** Display-only. Populated from cache when the server omits it. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CheckoutSession}. */\n currency?: string;\n metadata?: Record<string, unknown> | null;\n}\n\n/**\n * Environment for an upstream gateway. Accepts both the gateway-native values\n * (`'sandbox'` | `'live'`) and FloPay's internal aliases (`'stage'` |\n * `'production'`) so the same string can flow from the billing API straight\n * to gateway SDKs without translation at every call site. Use\n * {@link normalizeGatewayEnvironment} to collapse to the canonical pair\n * before handing the value to a gateway SDK.\n */\nexport type GatewayEnvironment = 'sandbox' | 'live' | 'stage' | 'production';\n\n/** Canonical gateway-native form returned by {@link normalizeGatewayEnvironment}. */\nexport type NormalizedGatewayEnvironment = 'sandbox' | 'live';\n\n/**\n * Map FloPay's environment aliases to the gateway-native `'sandbox'`/`'live'`\n * pair. `'stage'` → `'sandbox'`, `'production'` → `'live'`. Returns `undefined`\n * for `undefined` input and logs a console warning for unrecognized strings\n * (so misconfiguration surfaces immediately instead of hanging later — most\n * gateway SDKs silently fall back to live endpoints on an unknown env, which\n * then fails opaquely against sandbox credentials).\n */\nexport function normalizeGatewayEnvironment(\n env: GatewayEnvironment | string | undefined | null,\n): NormalizedGatewayEnvironment | undefined {\n if (env == null) return undefined;\n switch (env) {\n case 'sandbox':\n case 'stage':\n return 'sandbox';\n case 'live':\n case 'production':\n return 'live';\n default:\n // eslint-disable-next-line no-console\n console.warn(\n `[FloPay] Unrecognized gateway environment \"${env}\". Expected one of: sandbox, live, stage, production. Falling back to undefined.`,\n );\n return undefined;\n }\n}\n\n/** Per-gateway configuration returned by the billing API. */\nexport interface CheckoutGateway {\n /** Public client identifier (e.g. Stripe publishable key, PayPal client id). */\n publishableKey?: string | null;\n /** Sandbox or live mode for the gateway credentials. */\n environment?: GatewayEnvironment;\n /**\n * Optional Stripe PaymentIntent client secret exposed by the billing API\n * when additional authentication is required for a saved payment method.\n * Stripe-specific.\n */\n stripeClientSecret?: string | null;\n /**\n * Optional publishable key for a dedicated Stripe sub-account that renders\n * PayPal via Stripe Elements. Stripe-specific. Distinct from\n * `gateways.paypal.publishableKey`, which is a PayPal client id used by the\n * direct PayPal SDK.\n */\n paypalPublishableKey?: string | null;\n /**\n * Per-session list of payment method type identifiers that the gateway has\n * enabled for this consumer (e.g. `['apple_pay', 'google_pay', 'cashapp',\n * 'klarna']`). Populated by the billing API after looking up the gateway's\n * Payment Method Configurations. The SDK partitions this list against\n * {@link STRIPE_EXPRESS_METHODS} to decide which methods render in the\n * `ExpressCheckoutElement` row (Apple Pay / Google Pay / PayPal / Link /\n * Amazon Pay / Klarna) vs the `PaymentElement` accordion (Cash App Pay /\n * Affirm / iDEAL / Bancontact / …). `card` is always filtered out — the\n * card path stays on the split-fields elements. Absent on legacy backends.\n */\n enabledPaymentMethods?: string[];\n /**\n * Per-method buyer-country gate (uppercase ISO 3166-1 alpha-2), keyed by the\n * same method strings as {@link enabledPaymentMethods}. A method absent here\n * has no country restriction. The SDK filters the rendered tile row by the\n * buyer's *live* country (which can change via AVS after the session is\n * created) against this map — so per-method country eligibility lives in one\n * place (the backend) rather than a hardcoded SDK table. Absent on legacy\n * backends (the SDK then falls back to its built-in table).\n */\n enabledPaymentMethodCountries?: Record<string, string[]>;\n}\n\n/**\n * Map of gateways attached to a session, keyed by gateway code. A session can\n * advertise multiple gateways concurrently — e.g. `gateways.stripe` for card\n * + wallets and `gateways.paypal` for direct PayPal rendering.\n */\nexport interface CheckoutGateways {\n stripe?: CheckoutGateway;\n paypal?: CheckoutGateway;\n [key: string]: CheckoutGateway | undefined;\n}\n\n/** Represents a FloPay checkout session. */\nexport interface CheckoutSession {\n // ── Core fields ──\n id: string;\n clientSecret: string;\n mode: 'payment' | 'subscription' | 'setup';\n status: 'open' | 'complete' | 'expired';\n amount: number;\n currency: string;\n lineItems?: LineItem[];\n customer?: Customer;\n metadata?: Record<string, string>;\n // ── Session data from billing API ──\n checkoutMode?: CheckoutMode;\n /**\n * Embedded hosted vault capture credentials (TeamFloPay/backend#823),\n * populated on the `POST /v1/checkouts/sessions` response when the SDK\n * declared `X-Flo-SDK-Version >= 1.3.0` and the backend advertises a\n * `pcivault` gateway. The SDK injects {@link VaultCaptureBlock.html} as the\n * card-capture widget. Absent on legacy backends or when the SDK must fetch\n * the block via `POST /v1/checkouts/sessions/{id}/vault/capture` instead.\n */\n vault?: VaultCaptureBlock;\n /**\n * Generic, provider-agnostic payment method identifier for a card already on\n * file for the customer (TeamFloPay/backend#823). For the initial\n * Stripe-behind-vault rollout this is the Stripe `pm_…` id, but the SDK\n * treats it as an opaque card-method token. Present for returning customers\n * so the SDK can skip the vault widget; `null`/absent otherwise.\n */\n providerPaymentMethodId?: string | null;\n /** Unified products array as returned by post-#760 backends. */\n products?: CheckoutSessionProduct[];\n successUrl?: string;\n cancelUrl?: string;\n coupons?: string[];\n /**\n * Pre-discount total in cart-currency major units (e.g. 24.95). Populated by\n * billing API ≥ v1.1.2; `undefined` on older backends — readers must fall\n * back to summing per-line `totalAmount`.\n */\n subtotalAmount?: number;\n /**\n * Total reduction from applied coupons in cart-currency major units.\n * Populated by billing API ≥ v1.1.2; `undefined` on older backends.\n */\n discountAmount?: number;\n /**\n * Final charge amount in cart-currency major units (subtotal − discount,\n * clamped ≥ 0). Populated by billing API ≥ v1.1.2; `undefined` on older\n * backends — readers must fall back to summing per-line `overrideAmount`.\n */\n totalAmount?: number;\n createdAt?: string;\n /**\n * Per-gateway configuration. A session can advertise multiple concurrent\n * gateways — read `gateways.stripe` for card/wallets, `gateways.paypal` for\n * direct PayPal, and so on.\n */\n gateways?: CheckoutGateways;\n accountData?: {\n userId: string;\n email: string;\n firstName: string;\n lastName: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData?: TagsData;\n}\n\n// ---------------------------------------------------------------------------\n// Payment Results\n// ---------------------------------------------------------------------------\n\n/** The result of a payment confirmation attempt. */\nexport interface PaymentResult {\n status: 'succeeded' | 'processing' | 'requires_action' | 'failed';\n paymentIntentId?: string;\n paymentMethodId?: string;\n checkoutMethod?: CheckoutButtonMethod;\n error?: import('./errors.js').FloPayError;\n}\n\n/** Parameters for confirming a payment. */\nexport interface ConfirmPaymentParams {\n clientSecret: string;\n /** Optional redirect URL after 3-D Secure or wallet authentication. */\n returnUrl?: string;\n /**\n * Optional billing details appended to `payment_method_data` on the confirm call.\n * Ensures `billing_details.email` (and name/address) lands on the PaymentMethod\n * Stripe mints from Elements during 3DS confirmation — otherwise the new PM\n * inherits none of the info we attached at `createPaymentMethod` time.\n */\n billingDetails?: BillingDetails;\n}\n\n/** Billing details passed to Stripe for AVS (Address Verification). */\nexport interface BillingDetails {\n email?: string;\n name?: string;\n address?: {\n country?: string;\n postal_code?: string;\n city?: string;\n line1?: string;\n line2?: string;\n state?: string;\n };\n}\n\n/** Result from creating a payment method (tokenizing card fields). */\nexport interface CreatePaymentMethodResult {\n paymentMethodId: string | null;\n error?: import('./errors.js').FloPayError;\n}\n\n/** Parameters for confirming a card payment with a known client secret. */\nexport interface ConfirmCardPaymentParams {\n clientSecret: string;\n paymentMethodId: string;\n}\n\n/** Provider-observed 3DS lifecycle for one opaque, attempt-scoped confirmation. */\nexport interface CardThreeDsLifecycle {\n /** Opaque in-memory identifier; never derived from payment identifiers. */\n attemptId: string;\n status: 'handoff' | 'returned' | 'failed';\n}\n\n/** Result from confirming a card payment. */\nexport interface ConfirmCardPaymentResult {\n status: 'succeeded' | 'processing' | 'requires_action' | 'requires_capture' | 'failed';\n paymentIntentId?: string;\n paymentMethodId?: string;\n error?: import('./errors.js').FloPayError;\n /** @internal Provider-observed lifecycle used for privacy-safe telemetry. */\n threeDs?: CardThreeDsLifecycle;\n}\n\n// ---------------------------------------------------------------------------\n// Elements\n// ---------------------------------------------------------------------------\n\n/** The type of payment element to render. */\nexport type ElementType =\n | 'payment'\n | 'card'\n | 'cardNumber'\n | 'cardExpiry'\n | 'cardCvc'\n | 'address';\n\n/** Emitted when an element's internal state changes. */\nexport interface ElementChangeEvent {\n elementType: ElementType;\n complete: boolean;\n empty: boolean;\n error?: { message: string; type: string };\n /** Only populated for non-sensitive fields (e.g. address). */\n value?: Record<string, unknown>;\n}\n\n/** Configuration options when creating an element. */\nexport interface ElementOptions {\n appearance?: FloPayAppearance;\n /** Client secret for the PaymentIntent or SetupIntent. When present, Stripe uses it directly. */\n clientSecret?: string;\n /**\n * Total amount in the smallest currency unit (e.g. cents).\n * Used when no `clientSecret` is available — Stripe Elements needs\n * `mode` + `amount` + `currency` to render without a server-side intent.\n */\n amount?: number;\n /** ISO 4217 currency code (lowercase). Used with `amount` when no `clientSecret`. */\n currency?: string;\n /** How payment methods are created. 'manual' = tokenize only, 'auto' = Stripe handles it. */\n paymentMethodCreation?: 'manual' | 'auto';\n /**\n * Requests reusable payment credentials for future payments when Stripe\n * creates or validates a deferred PaymentIntent for this Elements group.\n */\n setupFutureUsage?: 'off_session' | 'on_session';\n layout?: 'tabs' | 'accordion' | 'auto';\n defaultValues?: Record<string, unknown>;\n readOnly?: boolean;\n /** Address element mode: 'billing' or 'shipping'. */\n mode?: 'billing' | 'shipping';\n /**\n * Style object for individual card elements (cardNumber, cardExpiry, cardCvc).\n * Passed directly to the underlying provider element.\n *\n * @example\n * ```ts\n * style: {\n * base: { color: '#f9fafb', fontSize: '16px', '::placeholder': { color: '#6b7280' } },\n * invalid: { color: '#ef4444' },\n * }\n * ```\n */\n style?: Record<string, Record<string, unknown>>;\n}\n\n// ---------------------------------------------------------------------------\n// Mounted Element (runtime instance)\n// ---------------------------------------------------------------------------\n\n/**\n * A payment element that has been created and can be mounted into the DOM.\n *\n * TODO: In a future phase, each MountedElement will render inside an iframe\n * for PCI DSS SAQ-A compliance. For now, it wraps the underlying provider\n * element directly.\n */\nexport interface MountedElement {\n mount(container: HTMLElement): void;\n unmount(): void;\n update(options: Partial<ElementOptions>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler: (...args: unknown[]) => void): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Provider Configuration\n// ---------------------------------------------------------------------------\n\n/** Top-level configuration for initializing FloPay. */\nexport interface FloPayConfig {\n publishableKey: string;\n /** Billing API base URL (e.g. https://api.stage.flopay.com). */\n billingApiUrl?: string;\n /**\n * Flo-owned privacy-safe operational telemetry. Enabled by default; set to\n * `false` to opt out. This intentionally accepts no endpoint, tags, user\n * context, messages, or custom metadata.\n */\n telemetry?: boolean;\n locale?: string;\n appearance?: FloPayAppearance;\n apiVersion?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider Adapter Interface\n// ---------------------------------------------------------------------------\n\n/**\n * Abstraction layer for payment providers.\n *\n * Currently only Stripe is implemented (`StripeAdapter`). The interface\n * ensures that adding new providers (Chargebee, Recurly, etc.) will not\n * require changes in consumer code.\n */\nexport interface PaymentProviderAdapter {\n readonly name: string;\n initialize(config: FloPayConfig): Promise<void>;\n createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement>;\n /** Retrieve an existing element by type, or `null` if not yet created. */\n getElement(type: ElementType): MountedElement | null;\n /** Submit elements for validation (Stripe `elements.submit()`). */\n submitElements(): Promise<{ error?: import('./errors.js').FloPayError }>;\n /** Create a payment method from the current elements (tokenize card). */\n createPaymentMethod(billingDetails?: BillingDetails): Promise<CreatePaymentMethodResult>;\n /** Confirm a card payment with a known client secret and payment method. */\n confirmCardPayment(params: ConfirmCardPaymentParams): Promise<ConfirmCardPaymentResult>;\n confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;\n /**\n * Create a PayPal payment: create PM → create intent → confirm with redirect.\n * Returns the confirmed PaymentIntent ID if completed inline, or redirects to PayPal.\n *\n * `nonce` is the session-bound checkout token from session creation. Post-#640\n * backends reject `POST /v1/checkouts/payments/intents` with 401 when the\n * `x-checkout-session-token` header is missing — pass `nonce` to forward it.\n */\n confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n nonce?: string;\n }): Promise<ConfirmCardPaymentResult>;\n /**\n * Resume a PayPal payment after redirect return.\n * Checks URL params for payment_intent + redirect_status.\n */\n resumePayPalPayment(): Promise<ConfirmCardPaymentResult | null>;\n /**\n * Get the raw underlying provider instance (e.g. Stripe object).\n * Used internally for creating secondary Elements groups (e.g. PayPal).\n */\n getRawProvider(): unknown;\n /**\n * Create a secondary Elements group for PayPal.\n * PayPal can't share Elements with card fields that use paymentMethodCreation: 'manual'.\n */\n createPayPalElements(options: ElementOptions): unknown;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Card Capture Adapter (vault-hosted PCI card widget)\n// ---------------------------------------------------------------------------\n\n/**\n * Identifier for a card-capture backend that owns the hosted PCI card form.\n * The SDK models card collection as a generic card method so additional\n * vault/card providers can be added behind the same {@link CardCaptureAdapter}\n * without changing the React card form. `'pcivault'` is the first (and\n * currently only) implementation.\n */\nexport type CardCaptureProviderId = 'pcivault';\n\n/**\n * Server-rendered hosted vault capture credentials (TeamFloPay/backend#823).\n *\n * Returned either embedded on the `POST /v1/checkouts/sessions` response (when\n * the SDK declared `X-Flo-SDK-Version >= 1.3.0`) or from the explicit\n * `POST /v1/checkouts/sessions/{id}/vault/capture` endpoint. `html` is a\n * self-contained, Flo-bundled hosted-form widget (PCIVault card fields, its own\n * submit button, status overlay, and — owned entirely by the backend — card\n * tokenization, PaymentIntent creation/confirmation, 3DS, and decline display).\n * The SDK injects `html` and steps back; PAN / CVC never enter the SDK runtime.\n *\n * `url` is the raw PCIVault submit endpoint the bundle POSTs to; it is surfaced\n * for diagnostics and is not used directly by the Model-A (inject-the-widget)\n * integration. The PCIVault submit *secret* is intentionally **not** part of\n * this type — it is server-only and must never cross onto the public session\n * surface (logs / telemetry / client inspection).\n */\nexport interface VaultCaptureBlock {\n /** Self-contained hosted-form widget HTML the SDK injects into the card slot. */\n html?: string;\n /** PCIVault submit URL the hosted form POSTs the captured card to. */\n url?: string;\n /**\n * One-time integrity token minted by the backend and baked into the widget\n * bootstrap. When present the SDK threads it into\n * {@link CardCaptureMountOptions.messageToken} and rejects any terminal\n * `postMessage` outcome whose {@link VaultCaptureResultMessage.messageToken}\n * does not match — the primary defence against same-window forged outcomes\n * (TeamFloPay/backend#823).\n */\n messageToken?: string;\n /**\n * Exact origin the hosted widget posts its terminal outcomes from, when it\n * runs in a cross-origin frame. When present the SDK rejects messages from\n * any other origin.\n */\n expectedOrigin?: string;\n}\n\n/**\n * Lifecycle / outcome events emitted by a {@link CardCaptureAdapter}.\n *\n * Under the Model-A (backend-orchestrated) vault flow the hosted widget owns\n * the entire payment — capture, charge, and 3DS — so the SDK observes only:\n * - `ready` — the widget mounted and is accepting input.\n * - `complete`— the backend reported a successful (terminal) charge.\n * - `decline` — the backend reported a declined / failed charge.\n * - `error` — the widget failed to load, or an unexpected runtime error.\n *\n * `complete` / `decline` arrive via a `postMessage` from the hosted widget (see\n * {@link VaultCaptureResultMessage}); the backend is responsible for emitting\n * them. When it does not, the widget falls back to its own success redirect.\n */\nexport type CardCaptureEventType =\n | 'ready'\n | 'submitting'\n | 'complete'\n | 'decline'\n | 'error'\n | 'validation'\n /**\n * The buyer clicked the widget's submit button but the host had gated it\n * (see {@link CardCaptureAdapter.setSubmitGate}) — the widget blocked its own\n * charge so the host can surface its merchant-DOM validation (e.g. AVS) the\n * same way the widget surfaces inline card validation.\n */\n | 'blocked'\n /**\n * The provider needs the buyer to complete an additional verification step\n * (e.g. Stripe 3DS-2 challenge) before the payment can settle. The widget\n * surfaces the provider-hosted challenge URL on the outcome event; the host\n * should:\n * 1. Hide its \"processing\" backdrop so the buyer can interact with the\n * challenge (the widget renders the iframe at the parent page level\n * so it isn't trapped inside the vault iframe).\n * 2. Render the challenge — the SDK's default vault adapter creates a\n * full-page overlay iframe pointing at `nextActionRedirectUrl`.\n * The next `complete` / `decline` / `error` fires after the buyer finishes\n * (or abandons) the challenge.\n */\n | 'action_required';\n\n/** Payload for a {@link CardCaptureAdapter} outcome event. */\nexport interface CardCaptureOutcomeEvent {\n /** Owning checkout session id, for correlation. */\n sessionId?: string;\n /** Provider intent / transaction id on a terminal outcome, when available. */\n intentId?: string;\n /** Mapped decline reason on `decline` (backend `PaymentDeclineReason` enum). */\n declineReason?: string;\n /** Human-readable message for `decline` / `error`. */\n message?: string;\n /**\n * Provider-hosted next-action URL the buyer must complete on\n * `action_required` (e.g. Stripe 3DS-2 challenge page). Absent on every\n * other event type.\n */\n nextActionRedirectUrl?: string;\n}\n\n/**\n * `window.postMessage` payload the hosted vault widget sends its embedding SDK\n * to report a terminal payment outcome.\n *\n * The widget HTML is injected **same-window** (see `PciVaultCardCapture`), so\n * `event.origin` for a genuine outcome is the merchant page's own origin and\n * the bare `source` string alone is forgeable by any other script on the page.\n * Authenticity therefore rests on, in order of strength:\n * 1. `messageToken` — an unguessable per-session token the backend bakes into\n * the widget bootstrap and echoes here; the SDK rejects terminal outcomes\n * that omit/mismatch it ({@link CardCaptureMountOptions.messageToken}).\n * 2. `sessionId` — money-affecting outcomes (`complete` / `decline`) must be\n * bound to the mounted session; the SDK rejects ones that are not.\n * 3. `expectedOrigin` — an optional strict origin gate for widgets that post\n * from a cross-origin frame ({@link CardCaptureMountOptions.expectedOrigin}).\n */\nexport interface VaultCaptureResultMessage {\n source: 'flopay-vault';\n type: 'ready' | 'submitting' | 'complete' | 'decline' | 'error' | 'action_required';\n /**\n * Owning checkout session id. Always present for terminal outcomes\n * (`complete` / `decline`) — the SDK rejects money-affecting outcomes that\n * are not bound to the mounted session. May be absent on a pre-bootstrap\n * `ready` / load-`error` the widget emits before the session is wired.\n */\n sessionId?: string;\n /**\n * Integrity token echoed from the widget bootstrap; must equal the value the\n * SDK was mounted with ({@link CardCaptureMountOptions.messageToken}). When\n * the SDK was given a token it rejects messages that omit or mismatch it.\n */\n messageToken?: string;\n intentId?: string;\n declineReason?: string;\n message?: string;\n /**\n * Provider-hosted next-action URL the buyer must complete on\n * `type === 'action_required'` (e.g. Stripe 3DS-2 challenge page). The host\n * SDK renders the challenge at the parent page level so the buyer isn't\n * blocked by the SDK's processing backdrop.\n */\n nextActionRedirectUrl?: string;\n}\n\n/** Options for mounting the hosted vault widget into a container element. */\nexport interface CardCaptureMountOptions {\n /**\n * Server-rendered hosted-form widget HTML (the vault capture block's `html`).\n * The adapter injects this and lets the bundled `<script>` bootstrap the\n * PCIVault form; the SDK does not own its fields or styling.\n */\n html: string;\n /**\n * Per-session integrity token (the vault block's `messageToken`). When\n * supplied, the adapter rejects any `postMessage` outcome whose\n * {@link VaultCaptureResultMessage.messageToken} does not match — closing the\n * same-window forgery vector. Omit when the backend does not (yet) mint one.\n */\n messageToken?: string;\n /**\n * Exact origin expected for terminal `postMessage` outcomes (the vault\n * block's `expectedOrigin`). When supplied, the adapter rejects messages from\n * any other origin. Omit to skip the origin gate (default).\n */\n expectedOrigin?: string;\n /**\n * Merchant theme colors to apply to the hosted form. The SDK owns theming;\n * the adapter pushes these into the (cross-origin) widget so the card form\n * matches the surrounding checkout. Only provided keys are applied — the\n * backend ships neutral defaults for the rest. Re-pushable at runtime via\n * {@link CardCaptureAdapter.applyTheme} for live theme switches.\n */\n theme?: VaultCardThemeColors;\n}\n\n/**\n * Merchant style values the SDK pushes into the hosted vault card form so it\n * matches the SDK-rendered (Stripe) card fields. The form's own surface stays\n * transparent — these only drive the inputs, submit button, and overlay.\n */\nexport interface VaultCardThemeColors {\n /** Submit button background. */\n primaryColor?: string;\n /** Submit button hover background. */\n primaryHoverColor?: string;\n /** Card input fill (the surrounding form surface stays transparent). */\n inputBackgroundColor?: string;\n /** Input + selected-value text color. */\n textColor?: string;\n /** Input border color. */\n borderColor?: string;\n /** Input placeholder color. */\n placeholderColor?: string;\n /** Error/invalid border + overlay color. */\n errorColor?: string;\n /** Success overlay color. */\n successColor?: string;\n /** Input font family. */\n fontFamily?: string;\n /** Input font size (e.g. `16px`). */\n fontSize?: string;\n /**\n * Input + placeholder font weight (e.g. `400`). Sent as a string so the\n * hosted widget's string-only theme applier picks it up. Mirrors the SDK's\n * `resolvedInputFontWeight` so the vault inputs match the AVS fields.\n */\n fontWeight?: string;\n /** Outer corner radius for the grouped card inputs (e.g. `8px`). */\n borderRadius?: string;\n}\n\n/**\n * Abstraction for a hosted, PCI-scoped card capture widget. The React card\n * form depends only on this interface — never on Stripe element types — so the\n * card path stays decoupled from any specific card provider.\n *\n * Under the Model-A vault flow (TeamFloPay/backend#823) the widget is rendered\n * server-side and the backend orchestrates the whole charge (tokenize → create\n * + confirm PaymentIntent → 3DS → fulfilment). The SDK's only job is to inject\n * the widget HTML and relay its terminal `postMessage` outcome to the host\n * checkout. No Stripe.js is involved on the card path.\n */\nexport interface CardCaptureAdapter {\n /** The card-capture backend backing this adapter. */\n readonly provider: CardCaptureProviderId;\n /** Inject the hosted widget HTML into `container` and bootstrap it. */\n mount(container: HTMLElement, options: CardCaptureMountOptions): Promise<void>;\n /** Subscribe to a lifecycle / outcome event. Returns an unsubscribe fn. */\n on(\n event: CardCaptureEventType,\n handler: (event: CardCaptureOutcomeEvent) => void,\n ): () => void;\n /**\n * Push merchant theme colors into the mounted widget (live). Lets the host\n * re-skin the card form on a runtime theme switch without a remount. No-op\n * before the widget is ready or if unsupported.\n */\n applyTheme?(theme: VaultCardThemeColors): void;\n /**\n * Gate the widget's submit button from the host. When `blocked` is `true`,\n * the widget cancels its own submit on the next click and emits a `'blocked'`\n * event instead of `'submitting'` — letting the host validate merchant-DOM\n * fields (e.g. AVS) and surface errors uniformly before any charge. The\n * latest gate is re-applied when the widget (re)becomes ready. No-op if\n * unsupported.\n */\n setSubmitGate?(blocked: boolean): void;\n /**\n * Push the card-field display/tab order into the widget (live), plus whether\n * the widget should move the cursor to its first field on load. `order` is a\n * permutation of the rows ({@link VaultCardFieldKey}); `null` restores the\n * default. `autoFocus` is `false` when the host renders AVS fields above the\n * widget (it focuses the first AVS field itself). Re-applied on `ready`.\n */\n setCardFieldOrder?(order: VaultCardFieldKey[] | null, autoFocus: boolean): void;\n /** Tear down the widget and release resources. */\n unmount(): void;\n}\n\n/**\n * The reorderable rows of the hosted vault card form. `'expiry'` is the combined\n * expiry + CVV row. The submit button always stays last.\n */\nexport type VaultCardFieldKey = 'name' | 'number' | 'expiry';\n\n// ---------------------------------------------------------------------------\n// Billing Provider (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Supported upstream gateway codes. */\nexport type BillingProvider = 'stripe' | 'paypal';\n\n// ---------------------------------------------------------------------------\n// Tokenized Body (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Token payload produced by client-side tokenization. */\nexport interface TokenizedBody {\n id?: string;\n type?: string;\n threeDSecureActionResultTokenId?: string;\n originalPaymentMethodId?: string;\n /**\n * @deprecated Use {@link TokenizedBody.gateway} + {@link TokenizedBody.paymentMethodType}.\n * Still populated by the SDK for PayPal payments so backends that gate on\n * `isPaypal === 'true'` keep working through the deprecation window.\n */\n isPaypal?: boolean;\n /**\n * Upstream gateway that produced the token. `'stripe'` covers every Stripe\n * payment method (card / wallets / Cash App Pay / Klarna / …); `'paypal'`\n * is set when DirectPayPalButton produced the token via the PayPal JS SDK.\n * Backend should route `/process` by `(gateway, paymentMethodType)` instead\n * of branching on `isPaypal` once consumers have adopted the new fields.\n */\n gateway?: BillingProvider | (string & {});\n /**\n * Concrete payment method type. For Stripe gateways this mirrors the Stripe\n * PaymentMethod.type value (`'card'`, `'apple_pay'`, `'google_pay'`,\n * `'cashapp'`, `'klarna'`, …). For PayPal it is the literal `'paypal'`.\n */\n paymentMethodType?: string;\n}\n\n/** Structured checkout-processing error returned by the billing API. */\nexport interface CheckoutProcessError {\n type: string;\n message?: string;\n transactionId?: string;\n threeDSecureToken?: string;\n paymentMethodId?: string;\n checkoutMethod?: CheckoutButtonMethod;\n advice?: string;\n gatewayErrorCode?: string;\n fields?: Array<{ field: string; message: string }>;\n /**\n * Provider-hosted next-action URL on `type === '3ds_required'` (e.g.\n * Stripe's hosted 3DS challenge page). Present on auto-checkout upsell\n * errors when the saved PM requires a fresh 3DS challenge — the SDK's\n * AutomaticPaymentButton mounts this URL in a full-page overlay iframe\n * so the buyer can authenticate without being demoted to a fresh\n * card-entry flow.\n */\n nextActionRedirectUrl?: string;\n}\n\n/** Recoverable checkout-processing state returned when fulfillment is still in progress. */\nexport interface CheckoutProcessingPending {\n type: 'checkout_processing';\n sessionId: string;\n retryAfterMs: number;\n statusUrl?: string;\n sessionUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Normalized Checkout Session (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Checkout mode: tokenize client-side or redirect to hosted page. */\nexport type CheckoutModeKind = 'tokenize' | 'redirect';\n\n/**\n * Provider-agnostic normalized checkout session. Backend may attach multiple\n * gateways per session — read each from `data.<gatewayCode>`.\n */\nexport interface NormalizedCheckoutSession {\n /** Gateway codes advertised by the backend for this session, for diagnostics. */\n providers: BillingProvider[];\n mode: CheckoutModeKind;\n autoProcessingError?: CheckoutProcessError;\n autoProcessingAttempted?: boolean;\n autoProcessingPending?: CheckoutProcessingPending;\n data: {\n hostedUrl?: string;\n clientToken?: string;\n session?: CheckoutSession;\n stripe?: {\n clientSecret?: string;\n publishableKey?: string;\n /**\n * Optional dedicated Stripe sub-account publishable key for rendering\n * PayPal via Stripe Elements. When present and distinct, the saved-PM\n * resume flow loads a separate FloPay instance for the PayPal PI.\n */\n paypalPublishableKey?: string;\n environment?: GatewayEnvironment;\n /**\n * Mirrors {@link CheckoutGateway.enabledPaymentMethods}. Drives dynamic\n * `ExpressCheckoutElement` / `PaymentElement` rendering inside\n * `SplitCardForm` instead of the historic hardcoded Apple/Google/PayPal\n * set. Absent on backends that have not yet adopted the field.\n */\n enabledPaymentMethods?: string[];\n /** Mirrors {@link CheckoutGateway.enabledPaymentMethodCountries}. */\n enabledPaymentMethodCountries?: Record<string, string[]>;\n };\n /**\n * Direct PayPal gateway configuration. Present only when the backend has\n * configured a dedicated PayPal gateway for the consumer; absent means the\n * Stripe-rendered PayPal fallback should be used (if Stripe is configured).\n */\n paypal?: {\n publishableKey?: string;\n environment?: GatewayEnvironment;\n };\n };\n raw?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Server-side SDK types (mirrors clicktech-core-ui/createCheckoutSession)\n// ---------------------------------------------------------------------------\n\n/** A one-time purchase item for checkout session creation. */\nexport interface CheckoutItem {\n /**\n * Catalog code for the item — the preferred identifier. When omitted, the\n * deprecated `providerItemId` is used as a fallback.\n */\n code?: string;\n /**\n * @deprecated Use {@link CheckoutItem.code}. Still accepted as a fallback\n * when `code` is not provided.\n */\n providerItemId?: string;\n /**\n * Display-only name for the item. Takes priority over the deprecated\n * `providerItemName`. Backend resolves names from the catalog; pass this\n * to seed the client-side display cache for the post-redirect fetch.\n */\n itemName?: string | null;\n /** @deprecated Use {@link CheckoutItem.itemName}. Still accepted as a fallback when `itemName` is not provided. */\n providerItemName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog; pass this to seed the client-side display cache so the UI can render the regular price after redirect. */\n totalAmount?: number;\n /** Display-only. Backend ignores this entirely; pass this to seed the client-side display cache so the UI can render the discounted price after redirect. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CreateSessionParams}/{@link InlineSessionParams}. */\n currency?: string;\n /** Arbitrary key/value metadata forwarded to the backend. */\n metadata?: Record<string, unknown> | null;\n}\n\n/**\n * Unified product input for checkout session creation. Mirrors the backend's\n * `CreateCheckoutProductBodyDto` introduced in #760 — the SDK accepts this\n * shape on `CreateSessionParams.products`. Callers using the legacy\n * {@link CheckoutItem} / {@link CheckoutSubscription} shapes do not need to\n * migrate; the SDK folds them into this shape internally.\n */\nexport interface CheckoutProduct {\n /**\n * @deprecated Optional and no longer needed — the backend resolves item vs\n * subscription from the catalog `code`. Pass it only to refine the\n * client-side optimistic display rendered before the session response loads\n * (subscriptions are listed first). Safe to omit.\n */\n type?: CheckoutProductType;\n /** Catalog code — preferred identifier. */\n code?: string;\n /** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */\n providerItemId?: string;\n /** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */\n providerPlanId?: string;\n /** Display-only name for the product. */\n name?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n itemName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n providerItemName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n subscriptionName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n providerPlanName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog. */\n totalAmount?: number;\n /** Display-only discount override. Backend ignores this entirely. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency`. */\n currency?: string;\n metadata?: Record<string, unknown> | null;\n}\n\n/** A recurring subscription plan for checkout session creation. */\nexport interface CheckoutSubscription {\n /**\n * Catalog code for the plan — the preferred identifier. When omitted, the\n * deprecated `providerPlanId` is used as a fallback.\n */\n code?: string;\n /**\n * @deprecated Use {@link CheckoutSubscription.code}. Still accepted as a\n * fallback when `code` is not provided.\n */\n providerPlanId?: string;\n /**\n * Display-only name for the subscription plan. Takes priority over the\n * deprecated `providerPlanName`. Backend resolves names from the catalog;\n * pass this to seed the client-side display cache for the post-redirect fetch.\n */\n subscriptionName?: string | null;\n /** @deprecated Use {@link CheckoutSubscription.subscriptionName}. Still accepted as a fallback when `subscriptionName` is not provided. */\n providerPlanName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog; pass this to seed the client-side display cache so the UI can render the regular price after redirect. */\n totalAmount?: number;\n /** Display-only. Backend ignores this entirely; pass this to seed the client-side display cache so the UI can render the discounted price after redirect. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CreateSessionParams}/{@link InlineSessionParams}. */\n currency?: string;\n /** Arbitrary key/value metadata forwarded to the backend. */\n metadata?: Record<string, unknown> | null;\n}\n\n/** Buyer's account information for session creation. */\nexport interface CheckoutAccount {\n userId: string;\n firstName?: string;\n lastName?: string;\n email: string;\n country?: string | null;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n zip?: string | null;\n /** Street address (line 1). */\n addressLine1?: string | null;\n /** Apt, suite, unit (line 2). */\n addressLine2?: string | null;\n}\n\n/** Analytics / pixel tags forwarded to the checkout page. */\nexport interface TagsData {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n}\n\n/**\n * Parameters for creating a checkout session via the billing API.\n * Mirrors the `CreateCheckoutSessionOptions` from clicktech-core-ui.\n */\nexport interface CreateSessionParams {\n /** Base URL of the billing API, e.g. https://billing.clicktech.com */\n billingApiUrl: string;\n /** Base URL of the checkout frontend, e.g. https://checkout.clicktech.com */\n checkoutBaseUrl: string;\n /** Flo-owned privacy-safe telemetry is enabled by default; set false to opt out. */\n telemetry?: boolean;\n /** The client ID for the checkout session. */\n clientId: string;\n /**\n * Session-level ISO 4217 currency code. **Required** by post-#760\n * backends (`@IsNotEmpty`). The SDK resolves it from this field first,\n * then `items[0].currency`, then `subscriptions[0].currency`, then\n * `products[0].currency`. When none resolve, the SDK throws\n * `FloPayError('validation_error')` before issuing the HTTP request.\n */\n currency?: string;\n /**\n * Unified products array. When supplied, it is sent verbatim and\n * {@link CreateSessionParams.items} / {@link CreateSessionParams.subscriptions}\n * are ignored. Otherwise the SDK folds the legacy fields into this shape\n * before POSTing to the backend.\n */\n products?: CheckoutProduct[];\n /** One-time purchase items. Folded into `products[]` before send. */\n items?: CheckoutItem[];\n /** Recurring subscription plans. Folded into `products[]` before send. */\n subscriptions?: CheckoutSubscription[];\n /** Buyer's account information. */\n account: CheckoutAccount;\n /** URL to redirect to after successful payment. */\n successUrl: string;\n /** URL to redirect to if the user cancels. */\n cancelUrl: string;\n /**\n * Checkout mode sent to the billing API.\n * - 'confirm' – show a payment confirmation page (default)\n * - 'auto' – skip confirmation when a payment method is already on file\n * - 'full' – full checkout flow\n */\n checkoutMode?: 'confirm' | 'auto' | 'full';\n /** Coupon codes to apply. */\n couponCodes?: string[];\n /** Pixel / analytics tags forwarded to the checkout page. */\n tagsData?: TagsData;\n /** Extra query params appended to the checkout redirect URL. */\n redirectParams?: Record<string, string>;\n /** Whether to set the checkout_data cookie. Defaults to true. */\n setCookie?: boolean;\n /** Request timeout in milliseconds. Defaults to 12000. */\n timeoutMs?: number;\n /** UTM and funnel tracking metadata. */\n utmMetadata?: Record<string, string | null | undefined>[];\n /**\n * Optional idempotency key identifying exactly **one** logical checkout\n * creation (TeamFloPay/backend#972). When supplied it is sent unchanged as\n * the `Idempotency-Key` header and reused across the SDK's transport retries,\n * so a timeout or lost response cannot mint a second session. Supply this to\n * keep the key stable across React remounts, multiple SDK instances, or\n * server retries you control; it **must not** be reused for a new purchase.\n * When omitted, the SDK generates a fresh, cryptographically random key per\n * call. Must be non-empty and at most 255 characters.\n */\n idempotencyKey?: string;\n}\n\n/**\n * Parameters for inline session creation via `FloPayCheckout.createSession`.\n * Subset of `CreateSessionParams` — no redirect fields needed since the\n * component handles the checkout flow inline.\n */\nexport interface InlineSessionParams {\n /** The client ID for the checkout session. */\n clientId: string;\n /**\n * Session-level ISO 4217 currency code. **Required** by post-#760\n * backends (`@IsNotEmpty`). The SDK resolves it from this field first,\n * then `items[0].currency`, then `subscriptions[0].currency`, then\n * `products[0].currency`. When none resolve, the SDK throws\n * `FloPayError('validation_error')` before issuing the HTTP request.\n */\n currency?: string;\n /**\n * Unified products array. When supplied, it is sent verbatim and\n * {@link InlineSessionParams.items} / {@link InlineSessionParams.subscriptions}\n * are ignored. Otherwise the SDK folds the legacy fields into this shape\n * before POSTing to the backend.\n */\n products?: CheckoutProduct[];\n /** One-time purchase items. Folded into `products[]` before send. */\n items?: CheckoutItem[];\n /** Recurring subscription plans. Folded into `products[]` before send. */\n subscriptions?: CheckoutSubscription[];\n /** Buyer's account information. */\n account: CheckoutAccount;\n /** URL to redirect to after successful payment. */\n successUrl: string;\n /** URL to redirect to if the user cancels. */\n cancelUrl: string;\n /** Checkout mode: 'full' (default), 'auto', or 'confirm'. */\n checkoutMode?: 'full' | 'auto' | 'confirm';\n /** Optional saved/tokenized payment method for inline auto or confirm checkout. */\n tokenizedData?: TokenizedBody;\n /** Coupon codes to apply. */\n couponCodes?: string[];\n /** Pixel / analytics tags. */\n tagsData?: TagsData;\n /** UTM and funnel tracking metadata. */\n utmMetadata?: Record<string, string | null | undefined>[];\n /**\n * Optional idempotency key identifying exactly **one** logical checkout\n * creation (TeamFloPay/backend#972). When supplied it is sent unchanged as\n * the `Idempotency-Key` header and reused across the SDK's transport retries.\n * Supply this to keep the key stable across React remounts, multiple SDK\n * instances, or server retries you control; it **must not** be reused for a\n * new purchase. When omitted, the SDK generates a fresh, cryptographically\n * random key per create. Must be non-empty and at most 255 characters.\n */\n idempotencyKey?: string;\n // ── Checkout analytics metadata (set by SDK automatically) ──\n /** Whether AVS is enabled for this checkout. */\n avsCheck?: boolean;\n /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */\n checkoutType?: string;\n /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */\n checkoutLayout?: string;\n /** AVS field configuration for analytics. */\n avsConfig?: AVSFieldConfig;\n}\n\n/** Payment methods exposed by the React buttons layout callbacks. */\nexport type CheckoutButtonMethod = 'card' | 'paypal' | 'apple_pay' | 'google_pay';\n\n/**\n * Draft inline-session params used by `FloPayCheckout` before a real\n * checkout session has been created. Buttons-layout checkout can seed\n * placeholder account data up front; `onBeforeButtonClick` can still\n * update it before the selected payment button continues.\n */\nexport interface InlineSessionDraft extends Omit<InlineSessionParams, 'account'> {\n account: Omit<CheckoutAccount, 'email'> & { email?: string };\n}\n\n/**\n * Partial inline-session fields that can be returned from\n * `onBeforeButtonClick` and merged into the draft session params.\n */\nexport interface InlineSessionPatch {\n account?: Partial<CheckoutAccount>;\n couponCodes?: string[];\n tagsData?: TagsData;\n utmMetadata?: Record<string, string | null | undefined>[];\n}\n\n/** Context passed to the `onBeforeButtonClick` callback for buttons-layout payment methods. */\nexport interface BeforeButtonClickEvent {\n method: CheckoutButtonMethod;\n sessionId?: string;\n createSession?: InlineSessionDraft;\n}\n\n/** Structured decline event emitted by the React checkout components. */\nexport interface DeclineEvent {\n method: CheckoutButtonMethod;\n message: string;\n code?: string;\n declineCode?: string;\n}\n\n/** Result from creating a checkout session. */\nexport type CheckoutSessionResult =\n | {\n status: 201;\n redirectUrl: string;\n /**\n * Session-bound checkout token returned by the billing API alongside the\n * session UUID. Must be echoed back on every continuation request via the\n * `x-checkout-session-token` header — backend `TeamFloPay/backend#640`\n * matches this value against `checkout_session.nonce` to authorize the\n * call. Surfaced here so the redirect-style flow's caller can forward it\n * (e.g. into a hosted checkout page that hits continuation routes).\n */\n nonce: string;\n }\n | { status: 204 }\n | { status: number };\n\n/**\n * Data submitted when processing a payment (tokenized card/wallet data).\n * Mirrors checkout project's ProcessCheckoutBodyDto.\n */\nexport interface ProcessPaymentParams {\n sessionId: string;\n /**\n * Session-bound checkout token returned from session creation. Forwarded as\n * the `x-checkout-session-token` header on every call to\n * `POST /v1/checkouts/sessions/:id/process`. Required by post-#640 backends —\n * `PaymentAPI.processPayment` throws `MissingCheckoutSessionToken` when this\n * is missing or empty so the 401 fails fast on the client instead of after\n * the network round trip. Typed as optional so callers do not need to coerce\n * `undefined` to `''` to satisfy the type — pass the value through verbatim\n * and let `processPayment` surface the missing-token error.\n */\n nonce?: string;\n tokenizedData?: TokenizedBody;\n accountData: {\n userId: string;\n email: string;\n firstName: string;\n lastName: string;\n zip?: string;\n country?: string;\n city?: string;\n state?: string;\n addressLine1?: string;\n addressLine2?: string;\n };\n chv?: string;\n /** Current page URL for redirect-capable auth flows such as 3DS and PayPal. */\n returnUrl?: string;\n // ── Checkout analytics metadata ──\n /** Whether AVS (Address Verification) was enabled for this checkout. */\n avsCheck?: boolean;\n /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */\n checkoutType?: string;\n /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */\n checkoutLayout?: string;\n /** AVS field configuration for analytics — which fields were shown. */\n avsConfig?: AVSFieldConfig;\n}\n\n/** Parameters for creating a customer. */\nexport interface CreateCustomerParams {\n email: string;\n name?: string;\n metadata?: Record<string, string>;\n}\n\n/** Parameters for updating a customer. */\nexport interface UpdateCustomerParams {\n email?: string;\n name?: string;\n metadata?: Record<string, string>;\n}\n\n/** A webhook event from FloPay. */\nexport interface WebhookEvent {\n id: string;\n type: string;\n data: Record<string, unknown>;\n created: number;\n}\n\n// ---------------------------------------------------------------------------\n// Currency (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Currency information mapped to a country. */\nexport interface CurrencyInfo {\n currency: string;\n symbol: string;\n country: string;\n countryCode: string;\n /** 0 = no tax, 1 = tax (VAT) applies. */\n tax: number;\n}\n\n/** A country option for UI select elements. */\nexport interface CountryOption {\n code: string;\n name: string;\n flag: string;\n}\n","/** Discriminated error types returned by the FloPay SDK. */\nexport type FloPayErrorType =\n | 'validation_error'\n | 'api_error'\n | 'authentication_error'\n | 'rate_limit_error'\n | 'network_error';\n\n/**\n * Custom error class for all FloPay SDK errors.\n *\n * Extends the native `Error` and adds structured fields that mirror\n * Stripe-style error responses for familiarity.\n */\nexport class FloPayError extends Error {\n readonly type: FloPayErrorType;\n readonly code?: string;\n readonly declineCode?: string;\n readonly param?: string;\n readonly statusCode?: number;\n\n constructor(\n message: string,\n type: FloPayErrorType,\n options?: { code?: string; declineCode?: string; param?: string; statusCode?: number },\n ) {\n super(message);\n this.name = 'FloPayError';\n this.type = type;\n this.code = options?.code;\n this.declineCode = options?.declineCode;\n this.param = options?.param;\n this.statusCode = options?.statusCode;\n\n // Restore prototype chain (required when extending built-ins)\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error Factories\n// ---------------------------------------------------------------------------\n\n/** Create a validation error (e.g. missing required field). */\nexport function validationError(\n message: string,\n param?: string,\n): FloPayError {\n return new FloPayError(message, 'validation_error', { param });\n}\n\n/** Create an API error (e.g. upstream provider returned an error). */\nexport function apiError(\n message: string,\n code?: string,\n statusCode?: number,\n): FloPayError {\n return new FloPayError(message, 'api_error', { code, statusCode });\n}\n\n/** Create an authentication error (e.g. invalid publishable key). */\nexport function authenticationError(message: string): FloPayError {\n return new FloPayError(message, 'authentication_error');\n}\n\n/** Create a rate limit error. */\nexport function rateLimitError(message: string): FloPayError {\n return new FloPayError(message, 'rate_limit_error');\n}\n\n/** Create a network error (e.g. fetch failed). */\nexport function networkError(message: string): FloPayError {\n return new FloPayError(message, 'network_error');\n}\n","/** Wire schema version shared with the Flo telemetry ingestion service. */\nexport const TELEMETRY_SCHEMA_VERSION = 1 as const;\nexport const TELEMETRY_SDK_PACKAGES = [\n '@flopay/shared',\n '@flopay/js',\n '@flopay/react',\n] as const;\nexport type TelemetrySdkPackage = (typeof TELEMETRY_SDK_PACKAGES)[number];\nexport const TELEMETRY_MAX_BATCH_BYTES = 32 * 1024;\nexport const TELEMETRY_MAX_BATCH_EVENTS = 20;\n\nexport type TelemetryEventClass =\n | 'technical_error'\n | 'lifecycle'\n | 'expected_outcome'\n | 'performance';\n\nconst TELEMETRY_PROVIDERS = ['stripe', 'paypal'] as const;\nexport type TelemetryProvider = (typeof TELEMETRY_PROVIDERS)[number];\nexport type TelemetryProviderInput =\n | TelemetryProvider\n | 'flo'\n | 'pcivault'\n | 'other'\n | 'unknown';\n\nconst TELEMETRY_PAYMENT_METHOD_CATEGORIES = [\n 'card',\n 'wallet',\n 'paypal',\n 'apm',\n 'saved',\n 'unknown',\n] as const;\nexport type TelemetryPaymentMethodCategory =\n (typeof TELEMETRY_PAYMENT_METHOD_CATEGORIES)[number];\n\nconst TELEMETRY_STAGES = [\n 'callback',\n 'sdk_initialize',\n 'checkout_mount',\n 'session_create',\n 'session_read',\n 'session_first_byte',\n 'session_complete',\n 'checkout_data_ready',\n 'checkout_render',\n 'checkout_interactive',\n 'provider_load',\n 'provider_ready',\n 'overlay_open',\n 'overlay_return',\n 'redirect',\n 'redirect_resume',\n 'vault_request',\n 'vault_mount',\n 'vault_ready',\n 'vault_submit',\n 'tokenization',\n 'three_ds_handoff',\n 'three_ds_return',\n 'processing',\n 'recovery',\n 'completion',\n 'unmount',\n 'total_journey',\n] as const;\nexport type TelemetryStage = (typeof TELEMETRY_STAGES)[number];\n\nexport const TELEMETRY_ERROR_CODES = [\n 'CALLBACK_FAILED',\n 'CHECKOUT_SESSION_CREATE_FAILED',\n 'CONFIGURATION_INVALID',\n 'INTERNAL_SDK_ERROR',\n 'NETWORK_REQUEST_FAILED',\n 'PAYMENT_PROCESSING_FAILED',\n 'POPUP_BLOCKED',\n 'PROVIDER_LOAD_FAILED',\n 'PROVIDER_RUNTIME_FAILED',\n 'RECOVERY_FAILED',\n 'REDIRECT_RESUME_FAILED',\n 'REQUEST_TIMEOUT',\n 'SDK_INITIALIZATION_FAILED',\n 'THREE_DS_FAILED',\n 'TOKENIZATION_FAILED',\n 'VAULT_LOAD_FAILED',\n 'VAULT_SUBMIT_FAILED',\n] as const;\nexport type TelemetryErrorCode = (typeof TELEMETRY_ERROR_CODES)[number];\n\n/** Closed catalog of SDK-authored lifecycle and operational log names. */\nexport const TELEMETRY_LOG_NAMES = [\n 'sdk.initialize.started',\n 'sdk.initialize.ready',\n 'sdk.cache.hit',\n 'sdk.cache.miss',\n 'checkout.mount',\n 'session.create.started',\n 'session.read.started',\n 'session.request.first_byte',\n 'session.request.completed',\n 'checkout.data.ready',\n 'checkout.rendered',\n 'checkout.interactive',\n 'checkout.recovery.started',\n 'checkout.recovery.completed',\n 'checkout.unmount',\n 'provider.load.started',\n 'provider.eligibility.checked',\n 'provider.availability.checked',\n 'provider.ready',\n 'provider.popup.opened',\n 'provider.overlay.opened',\n 'provider.overlay.returned',\n 'provider.redirect.started',\n 'provider.redirect.resumed',\n 'vault.capture.requested',\n 'vault.widget.mounted',\n 'vault.widget.ready',\n 'vault.submission.started',\n 'vault.action.required',\n 'vault.three_ds.handoff',\n 'vault.three_ds.returned',\n 'vault.terminal',\n 'payment.method.selected',\n 'payment.intent.started',\n 'payment.intent.completed',\n 'payment.tokenization.started',\n 'payment.tokenization.completed',\n 'payment.processing.started',\n 'payment.processing.completed',\n 'payment.three_ds.handoff',\n 'payment.three_ds.returned',\n 'operation.retry',\n 'operation.deduplicated',\n 'operation.fallback',\n 'operation.cache.hit',\n 'operation.cache.miss',\n 'operation.recovery.started',\n 'operation.recovery.completed',\n 'operation.state_transition',\n] as const;\nexport type TelemetryLogName = (typeof TELEMETRY_LOG_NAMES)[number];\n\nconst TELEMETRY_REQUEST_CATEGORIES = [\n 'session_create',\n 'session_read',\n 'intent_create',\n 'process_payment',\n 'vault_capture',\n 'account_snapshot',\n 'provider_sdk',\n 'other',\n] as const;\nexport type TelemetryRequestCategory = (typeof TELEMETRY_REQUEST_CATEGORIES)[number];\n\nconst TELEMETRY_STATUS_CLASSES = [\n '2xx',\n '3xx',\n '4xx',\n '5xx',\n 'network_error',\n 'timeout',\n 'unknown',\n] as const;\nexport type TelemetryStatusClass = (typeof TELEMETRY_STATUS_CLASSES)[number];\n\nconst TELEMETRY_CHECKOUT_MODES = ['full', 'auto', 'confirm', 'unknown'] as const;\nexport type TelemetryCheckoutMode = (typeof TELEMETRY_CHECKOUT_MODES)[number];\n\nconst TELEMETRY_LAYOUTS = ['embedded', 'buttons', 'automatic', 'unknown'] as const;\nexport type TelemetryLayout = (typeof TELEMETRY_LAYOUTS)[number];\n\nconst TELEMETRY_DURATION_MODES = ['machine', 'buyer', 'total'] as const;\nexport type TelemetryDurationMode = (typeof TELEMETRY_DURATION_MODES)[number];\n\nconst TELEMETRY_EXPECTED_OUTCOMES = [\n 'action_required',\n 'customer_abandoned',\n 'payment_cancelled',\n 'payment_declined',\n 'payment_succeeded',\n 'validation_rejected',\n] as const;\nexport type TelemetryExpectedOutcome = (typeof TELEMETRY_EXPECTED_OUTCOMES)[number];\n\ninterface TelemetryCommonFields {\n eventId: string;\n stage: TelemetryStage;\n sequence: number;\n provider?: TelemetryProvider;\n attempt?: number;\n statusClass?: TelemetryStatusClass;\n requestCategory?: TelemetryRequestCategory;\n paymentMethodCategory?: TelemetryPaymentMethodCategory;\n checkoutMode?: TelemetryCheckoutMode;\n layout?: TelemetryLayout;\n}\n\ninterface BuildTelemetryCommonInput {\n eventId: string;\n stage: TelemetryStage;\n sequence: number;\n provider?: TelemetryProviderInput;\n attempt?: number;\n statusClass?: TelemetryStatusClass;\n requestCategory?: TelemetryRequestCategory;\n paymentMethodCategory?: TelemetryPaymentMethodCategory;\n checkoutMode?: TelemetryCheckoutMode;\n layout?: TelemetryLayout;\n}\n\nexport interface TelemetryErrorEvent extends TelemetryCommonFields {\n class: 'technical_error';\n code: TelemetryErrorCode;\n}\n\nexport interface BuildTelemetryErrorEventInput extends BuildTelemetryCommonInput {\n errorCode: TelemetryErrorCode;\n}\n\nexport interface TelemetryLogEvent extends TelemetryCommonFields {\n class: 'lifecycle';\n name: TelemetryLogName;\n}\n\nexport interface BuildTelemetryLogEventInput extends BuildTelemetryCommonInput {\n name: TelemetryLogName;\n}\n\nexport interface TelemetryExpectedOutcomeEvent extends TelemetryCommonFields {\n class: 'expected_outcome';\n outcome: TelemetryExpectedOutcome;\n}\n\nexport interface BuildTelemetryTerminalEventInput\n extends Omit<BuildTelemetryCommonInput, 'stage'> {\n outcome: TelemetryExpectedOutcome;\n stage?: TelemetryStage;\n}\n\nexport interface TelemetryPerformanceEvent extends TelemetryCommonFields {\n class: 'performance';\n durationMs: number;\n durationMode: TelemetryDurationMode;\n}\n\nexport interface BuildTelemetryPerformanceEventInput extends BuildTelemetryCommonInput {\n durationMs: number;\n durationMode: TelemetryDurationMode;\n}\n\nexport type TelemetryEvent =\n | TelemetryErrorEvent\n | TelemetryLogEvent\n | TelemetryExpectedOutcomeEvent\n | TelemetryPerformanceEvent;\n\nexport interface SerializeTelemetryBatchOptions {\n correlationId: string;\n sdkPackage: TelemetrySdkPackage;\n sdkVersion: string;\n batchId?: string;\n}\n\nexport interface TelemetryBatchEnvelope {\n schemaVersion: typeof TELEMETRY_SCHEMA_VERSION;\n batchId: string;\n correlationId: string;\n sdk: {\n package: TelemetrySdkPackage;\n version: string;\n };\n events: TelemetryEvent[];\n}\n\nconst UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst SDK_VERSION = /^\\d{1,4}\\.\\d{1,4}\\.\\d{1,4}(?:-[0-9A-Za-z.-]{1,32})?$/;\nconst ERROR_CODES = new Set<string>(TELEMETRY_ERROR_CODES);\nconst STAGES = new Set<string>(TELEMETRY_STAGES);\nconst PROVIDERS = new Set<string>(TELEMETRY_PROVIDERS);\nconst PAYMENT_METHODS = new Set<string>(TELEMETRY_PAYMENT_METHOD_CATEGORIES);\nconst LOG_NAMES = new Set<string>(TELEMETRY_LOG_NAMES);\nconst CHECKOUT_MODES = new Set<string>(TELEMETRY_CHECKOUT_MODES);\nconst LAYOUTS = new Set<string>(TELEMETRY_LAYOUTS);\nconst REQUEST_CATEGORIES = new Set<string>(TELEMETRY_REQUEST_CATEGORIES);\nconst STATUS_CLASSES = new Set<string>(TELEMETRY_STATUS_CLASSES);\nconst DURATION_MODES = new Set<string>(TELEMETRY_DURATION_MODES);\nconst EXPECTED_OUTCOMES = new Set<string>(TELEMETRY_EXPECTED_OUTCOMES);\nconst SDK_PACKAGES = new Set<string>(TELEMETRY_SDK_PACKAGES);\n\nfunction enumOr<T extends string>(value: unknown, allowed: Set<string>, fallback: T): T {\n return typeof value === 'string' && allowed.has(value) ? (value as T) : fallback;\n}\n\nfunction createUuidV4(): string {\n try {\n const id = globalThis.crypto.randomUUID();\n if (UUID_V4.test(id)) return id;\n } catch {\n // Fall through to a non-persistent compatibility UUID.\n }\n const bytes = new Uint8Array(16);\n try {\n globalThis.crypto.getRandomValues(bytes);\n } catch {\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction safeUuid(value: string | undefined): string {\n return typeof value === 'string' && UUID_V4.test(value) ? value : createUuidV4();\n}\n\nfunction safeAttempt(value: number | undefined): number | undefined {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 100\n ? value\n : undefined;\n}\n\nfunction safeSequence(value: number): number {\n return Number.isSafeInteger(value) && value >= 0 ? Math.min(value, 1_000_000) : 0;\n}\n\nfunction safeDuration(value: number): number {\n if (!Number.isFinite(value) || value < 0) return 0;\n return Math.min(Math.round(value), 120_000);\n}\n\nfunction addCommonFields<T extends TelemetryCommonFields>(\n event: T,\n input: BuildTelemetryCommonInput,\n): T {\n const attempt = safeAttempt(input.attempt);\n if (input.provider && PROVIDERS.has(input.provider)) event.provider = input.provider as TelemetryProvider;\n if (attempt !== undefined) event.attempt = attempt;\n if (input.statusClass) event.statusClass = enumOr(input.statusClass, STATUS_CLASSES, 'unknown');\n if (input.requestCategory) {\n event.requestCategory = enumOr(input.requestCategory, REQUEST_CATEGORIES, 'other');\n }\n if (input.paymentMethodCategory) {\n event.paymentMethodCategory = enumOr(\n input.paymentMethodCategory,\n PAYMENT_METHODS,\n 'unknown',\n );\n }\n if (input.checkoutMode) {\n event.checkoutMode = enumOr(input.checkoutMode, CHECKOUT_MODES, 'unknown');\n }\n if (input.layout) event.layout = enumOr(input.layout, LAYOUTS, 'unknown');\n return event;\n}\n\n/** Build a closed SDK technical-error event. */\nexport function buildTelemetryErrorEvent(\n input: BuildTelemetryErrorEventInput,\n): TelemetryErrorEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'technical_error',\n code: enumOr(input.errorCode, ERROR_CODES, 'INTERNAL_SDK_ERROR'),\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n },\n input,\n );\n}\n\n/** Build a typed SDK lifecycle event; arbitrary text is never accepted. */\nexport function buildTelemetryLogEvent(input: BuildTelemetryLogEventInput): TelemetryLogEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'lifecycle',\n name: enumOr(input.name, LOG_NAMES, 'operation.retry'),\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n },\n input,\n );\n}\n\n/** Build a non-error expected checkout outcome. */\nexport function buildTelemetryTerminalEvent(\n input: BuildTelemetryTerminalEventInput,\n): TelemetryExpectedOutcomeEvent {\n const commonInput: BuildTelemetryCommonInput = {\n ...input,\n stage: input.stage ?? 'completion',\n };\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'expected_outcome',\n outcome: enumOr(input.outcome, EXPECTED_OUTCOMES, 'customer_abandoned'),\n stage: enumOr(input.stage, STAGES, 'completion'),\n sequence: safeSequence(input.sequence),\n },\n commonInput,\n );\n}\n\n/** Build a monotonic SDK-owned duration measurement. */\nexport function buildTelemetryPerformanceEvent(\n input: BuildTelemetryPerformanceEventInput,\n): TelemetryPerformanceEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'performance',\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n durationMs: safeDuration(input.durationMs),\n durationMode: enumOr(input.durationMode, DURATION_MODES, 'machine'),\n },\n input,\n );\n}\n\n/** Serialize one closed backend-owned v1 telemetry envelope. */\nexport function serializeTelemetryBatch(\n events: readonly TelemetryEvent[],\n options: SerializeTelemetryBatchOptions,\n): string {\n const sanitizedEvents = events.slice(0, TELEMETRY_MAX_BATCH_EVENTS).flatMap((event): TelemetryEvent[] => {\n if (event.class === 'technical_error') {\n return [buildTelemetryErrorEvent({ ...event, errorCode: event.code })];\n }\n if (event.class === 'lifecycle') return [buildTelemetryLogEvent(event)];\n if (event.class === 'expected_outcome') return [buildTelemetryTerminalEvent(event)];\n if (event.class === 'performance') return [buildTelemetryPerformanceEvent(event)];\n return [];\n });\n const envelope: TelemetryBatchEnvelope = {\n schemaVersion: TELEMETRY_SCHEMA_VERSION,\n batchId: safeUuid(options.batchId),\n correlationId: safeUuid(options.correlationId),\n sdk: {\n package: enumOr(options.sdkPackage, SDK_PACKAGES, '@flopay/shared'),\n version: SDK_VERSION.test(options.sdkVersion) ? options.sdkVersion : '0.0.0',\n },\n events: sanitizedEvents,\n };\n return JSON.stringify(envelope);\n}\n","/** FloPay environment — determines which billing API URL is used. */\nexport type FloPayEnvironment = 'staging' | 'production' | 'local';\n\nconst ENV_URL_MAP: Record<FloPayEnvironment, string> = {\n local: 'https://flo.ngrok.pro',\n staging: 'https://api.stage.flopay.com',\n production: 'https://api.flopay.com',\n};\n\nlet globalEnvironment: FloPayEnvironment = 'staging';\n\n/**\n * Configure the FloPay SDK globally. Call once at app startup.\n *\n * The environment determines which billing API URL is used for all\n * FloPay operations (session creation, payment processing, etc.).\n *\n * @example\n * ```ts\n * import { configureFlopay } from '@flopay/shared';\n *\n * // In production\n * configureFlopay({ environment: 'production' });\n *\n * // In staging/development\n * configureFlopay({ environment: 'staging' });\n * ```\n *\n * Alternatively, set the `NEXT_PUBLIC_FLOPAY_ENV` environment variable\n * to `'staging'` or `'production'` — the SDK reads it automatically.\n */\nexport function configureFlopay(config: { environment: FloPayEnvironment }): void {\n globalEnvironment = config.environment;\n}\n\n/** Get the billing API URL for the currently configured environment. */\nexport function getConfiguredBillingApiUrl(): string {\n return ENV_URL_MAP[globalEnvironment];\n}\n\n/** Get the current configured environment. */\nexport function getFloPayEnvironment(): FloPayEnvironment {\n return globalEnvironment;\n}\n","// AUTO-GENERATED — do not edit by hand.\n// Source: https://github.com/datatrans/payment-logos @ 6538b978b60523224332031bf4ac267730268abb (assets/apm/*.svg)\n// Regenerate: pnpm --filter @flopay/shared fetch:logos\n//\n// The Stripe wire identifiers that have a vendored brand logo. The logo SVGs\n// themselves live in @flopay/react as sibling `.svg` assets (loaded via <img>),\n// not as inline strings here — a card-only checkout ships none of their bytes.\n// This list only records *which* methods have one, so `hasVendoredStripeMethodLogo`\n// can size the tile logo/label gap without importing any SVG markup.\nexport const VENDORED_LOGO_METHODS: readonly string[] = [\n 'alipay',\n 'bancontact',\n 'blik',\n 'eps',\n 'giropay',\n 'ideal',\n 'klarna',\n 'p24',\n 'sepa_debit',\n 'wechat_pay',\n];\n","import type {\n AVSFieldConfig,\n ButtonsLayoutStyles,\n ButtonsLayoutTheme,\n CountryOption,\n CurrencyInfo,\n FloPayAppearance,\n ThemeBundle,\n ThemeBundleId,\n ThemeId,\n} from './types.js';\n\nimport type { FloPayEnvironment } from './config.js';\nimport { getConfiguredBillingApiUrl } from './config.js';\n// Vendored brand logos (datatrans/payment-logos), generated by\n// `pnpm --filter @flopay/shared fetch:logos`. Methods present here render\n// their real logo on the tile button; methods absent fall back to the\n// generated placeholder mark below.\nimport { VENDORED_LOGO_METHODS } from './payment-logos.generated.js';\n\n// ---------------------------------------------------------------------------\n// SDK Version & API\n// ---------------------------------------------------------------------------\n\n/** Current SDK version. */\nexport const SDK_VERSION = '1.4.1';\n\n/**\n * HTTP header the SDK sends on `POST /v1/checkouts/sessions` so the backend\n * can decide whether to embed the vault capture block (the hosted PCI card\n * widget) in the create-session response. Backends at TeamFloPay/backend#823\n * only serve the embedded `vault` block to SDKs that declare `>= 1.3.0` here;\n * older SDKs are unaffected and keep the legacy Stripe card path.\n *\n * @see SDK_VERSION — the value sent in this header.\n */\nexport const FLO_SDK_VERSION_HEADER = 'x-flo-sdk-version';\n\n/** Billing API URL for staging environment. */\nexport const BILLING_API_URL_STAGING = 'https://api.stage.flopay.com';\n\n/** Billing API URL for production environment. */\nexport const BILLING_API_URL_PRODUCTION = 'https://api.flopay.com';\n\n/** Default FloPay API base URL (used by @flopay/node). Alias for staging. */\nexport const DEFAULT_API_BASE_URL = BILLING_API_URL_STAGING;\n\n/** Default billing API base URL. Alias for staging — prefer `resolveBillingApiUrl()`. */\nexport const BILLING_API_URL = BILLING_API_URL_STAGING;\n\n/**\n * Resolve the billing API URL from available configuration.\n *\n * Priority:\n * 1. Explicit `billingApiUrl` (prop/param override)\n * 2. `NEXT_PUBLIC_FLOPAY_ENV` environment variable (`'staging'` | `'production'`)\n * 3. `configureFlopay()` global environment setting\n * 4. Fallback: staging URL\n *\n * @example\n * ```ts\n * import { resolveBillingApiUrl } from '@flopay/shared';\n *\n * // Reads from env var or configureFlopay() — no args needed\n * const url = resolveBillingApiUrl();\n *\n * // Explicit override takes priority\n * const url = resolveBillingApiUrl('https://custom.example.com');\n * ```\n */\nexport function resolveBillingApiUrl(billingApiUrl?: string): string {\n if (billingApiUrl) return billingApiUrl;\n\n // Environment variable (works in Next.js and bundlers that inline process.env)\n if (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_FLOPAY_ENV) {\n const env = process.env.NEXT_PUBLIC_FLOPAY_ENV as FloPayEnvironment;\n if (env === 'production') return BILLING_API_URL_PRODUCTION;\n return BILLING_API_URL_STAGING;\n }\n\n // Global config from configureFlopay()\n return getConfiguredBillingApiUrl();\n}\n\n/** Default API version header value. */\nexport const DEFAULT_API_VERSION = '2024-01-01';\n\n// ---------------------------------------------------------------------------\n// Default Themes\n// ---------------------------------------------------------------------------\n\n/** The default appearance applied when no custom appearance is provided. */\nexport const DEFAULT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#4A49FF',\n colorBackground: '#FFFFFF',\n colorText: '#262833',\n colorDanger: '#DF1B41',\n borderRadius: '8px',\n fontFamily: 'Poppins, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '4px',\n },\n};\n\n/** Flat theme — minimal borders and shadows. */\nexport const FLAT_APPEARANCE: FloPayAppearance = {\n theme: 'flat',\n variables: {\n ...DEFAULT_APPEARANCE.variables,\n borderRadius: '4px',\n },\n};\n\n/** Night theme — dark background. */\nexport const NIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#7B7BFF',\n colorBackground: '#1A1A2E',\n colorText: '#E0E0E0',\n colorDanger: '#FF6B6B',\n borderRadius: '8px',\n fontFamily: 'Poppins, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '4px',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme Bundles — appearance halves\n//\n// Each bundle pairs a `*_APPEARANCE` (Stripe-side) with a matching\n// `BUTTONS_LAYOUT_*` (FloPay-side wrapper) defined further below. The\n// `THEMES` map at the bottom of this file ties them together so consumers can\n// pick a bundle by id.\n// ---------------------------------------------------------------------------\n\n/** Modern light — clean & airy: Inter, soft shadows, generous spacing, 12px radius. */\nexport const MODERN_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#0F172A',\n colorDanger: '#EF4444',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n padding: '14px 16px',\n border: '1.5px solid #E5E7EB',\n boxShadow: '0 1px 2px rgba(15,23,42,0.04)',\n },\n '.Input:focus': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 4px rgba(23,133,224,0.12)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#475569',\n marginBottom: '6px',\n },\n '.Tab': {\n padding: '12px 16px',\n borderRadius: '12px',\n border: '1.5px solid #E5E7EB',\n },\n '.Tab:hover': {\n borderColor: '#CBD5E1',\n },\n '.Tab--selected': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 1px #1785E0',\n },\n },\n};\n\n/** Modern dark — clean & airy on a deep-blue surface, 12px radius. */\nexport const MODERN_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0B1220',\n colorText: '#F1F5F9',\n colorDanger: '#F87171',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: '#111827',\n padding: '14px 16px',\n border: '1.5px solid #1F2937',\n color: '#F1F5F9',\n boxShadow: 'none',\n },\n '.Input:focus': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 4px rgba(96,165,250,0.18)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#94A3B8',\n marginBottom: '6px',\n },\n '.Tab': {\n padding: '12px 16px',\n borderRadius: '12px',\n border: '1.5px solid #1F2937',\n backgroundColor: '#111827',\n color: '#F1F5F9',\n },\n '.Tab:hover': {\n borderColor: '#374151',\n },\n '.Tab--selected': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 1px #60A5FA',\n },\n },\n};\n\n/** Bold light — vibrant: saturated primary, gradient submit, heavier weights. */\nexport const BOLD_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#0C2B4D',\n colorDanger: '#DC2626',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n padding: '14px 16px',\n border: '2px solid #E5E7EB',\n },\n '.Input:focus': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 3px rgba(23,133,224,0.2)',\n },\n '.Label': {\n fontWeight: '600',\n color: '#0C2B4D',\n },\n '.Tab': {\n padding: '14px 18px',\n border: '2px solid #E5E7EB',\n fontWeight: '600',\n },\n '.Tab--selected': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 1px #1785E0',\n },\n },\n};\n\n/** Bold dark — saturated deep-blue surface, gradient submit. */\nexport const BOLD_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0C2B4D',\n colorText: '#FFFFFF',\n colorDanger: '#F87171',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: '#1E3A8A',\n padding: '14px 16px',\n border: '2px solid #1E40AF',\n color: '#FFFFFF',\n },\n '.Input:focus': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 3px rgba(96,165,250,0.25)',\n },\n '.Label': {\n fontWeight: '600',\n color: '#DBEAFE',\n },\n '.Tab': {\n padding: '14px 18px',\n border: '2px solid #1E40AF',\n backgroundColor: '#1E3A8A',\n color: '#FFFFFF',\n fontWeight: '600',\n },\n '.Tab--selected': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 1px #60A5FA',\n },\n },\n};\n\n/** Glass light — translucent surfaces with backdrop blur over a pastel blue gradient. */\nexport const GLASS_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#1E293B',\n colorDanger: '#EF4444',\n borderRadius: '16px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: 'rgba(255,255,255,0.6)',\n backdropFilter: 'blur(10px)',\n padding: '14px 16px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.5), 0 1px 3px rgba(23,133,224,0.08)',\n },\n '.Input:focus': {\n borderColor: 'rgba(23,133,224,0.5)',\n boxShadow: '0 0 0 3px rgba(23,133,224,0.15)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#475569',\n },\n '.Tab': {\n padding: '12px 16px',\n backgroundColor: 'rgba(255,255,255,0.5)',\n border: '1px solid rgba(255,255,255,0.6)',\n borderRadius: '14px',\n },\n '.Tab--selected': {\n borderColor: 'rgba(23,133,224,0.6)',\n boxShadow: '0 0 0 1px rgba(23,133,224,0.6)',\n },\n },\n};\n\n/** Glass dark — translucent surfaces with backdrop blur over a deep-blue gradient. */\nexport const GLASS_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0F172A',\n colorText: '#F1F5F9',\n colorDanger: '#F87171',\n borderRadius: '16px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(10px)',\n padding: '14px 16px',\n border: '1px solid rgba(255,255,255,0.08)',\n color: '#F1F5F9',\n },\n '.Input:focus': {\n borderColor: 'rgba(96,165,250,0.5)',\n boxShadow: '0 0 0 3px rgba(96,165,250,0.2)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#94A3B8',\n },\n '.Tab': {\n padding: '12px 16px',\n backgroundColor: 'rgba(15,23,42,0.6)',\n border: '1px solid rgba(255,255,255,0.08)',\n borderRadius: '14px',\n color: '#F1F5F9',\n },\n '.Tab--selected': {\n borderColor: 'rgba(96,165,250,0.6)',\n boxShadow: '0 0 0 1px rgba(96,165,250,0.6)',\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Buttons Layout Theme Presets\n// ---------------------------------------------------------------------------\n\n/** Default buttons layout — white card button, neutral borders. */\nexport const BUTTONS_LAYOUT_DEFAULT: ButtonsLayoutStyles = {};\n\n/** Minimal buttons layout — borderless, subtle hover. */\nexport const BUTTONS_LAYOUT_MINIMAL: ButtonsLayoutStyles = {\n cardButton: {\n border: 'none',\n backgroundColor: '#f9fafb',\n boxShadow: 'none',\n },\n cardFormContainer: {\n backgroundColor: '#f9fafb',\n border: 'none',\n },\n cardInputBorder: '#e5e7eb',\n backButtonIcon: {\n backgroundColor: '#e5e7eb',\n },\n submitButton: {\n borderRadius: '6px',\n },\n};\n\n/** Rounded buttons layout — large border radius, soft shadows. */\nexport const BUTTONS_LAYOUT_ROUNDED: ButtonsLayoutStyles = {\n cardButton: {\n borderRadius: '9999px',\n border: '1px solid #e5e7eb',\n boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n },\n cardFormContainer: {\n borderRadius: '16px',\n border: '1px solid #e5e7eb',\n boxShadow: '0 2px 8px rgba(0,0,0,0.06)',\n },\n cardInputBorder: '#d1d5db',\n submitButton: {\n borderRadius: '9999px',\n },\n backButtonIcon: {\n backgroundColor: '#f3f4f6',\n },\n};\n\n/** Dark buttons layout — dark backgrounds, light text. */\nexport const BUTTONS_LAYOUT_DARK: ButtonsLayoutStyles = {\n cardButton: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n border: '1px solid #374151',\n boxShadow: 'none',\n },\n cardFormContainer: {\n backgroundColor: '#111827',\n border: '1px solid #374151',\n },\n cardInputBorder: '#4b5563',\n cardInputColor: '#f9fafb',\n cardInputPlaceholderColor: '#6b7280',\n cardInputBackground: '#1f2937',\n nameInput: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n backButton: {\n color: '#9ca3af',\n },\n backButtonIcon: {\n backgroundColor: '#374151',\n },\n submitButton: {\n backgroundColor: '#6366f1',\n },\n title: {\n color: '#f9fafb',\n },\n countrySelect: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n zipInput: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme Bundles — buttons-layout halves\n//\n// Each block pairs with the matching `*_APPEARANCE` above to produce a\n// coherent look across both the Stripe-rendered nested inputs and the FloPay\n// wrapper (container, title, submit button, back button).\n// ---------------------------------------------------------------------------\n\n/** Modern light — soft surface, 14px radius, FloPay-blue submit with subtle shadow. */\nexport const BUTTONS_LAYOUT_MODERN_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#FAFAFA',\n borderRadius: '20px',\n border: '1px solid #E5E7EB',\n boxShadow: '0 8px 24px rgba(15,23,42,0.04)',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#FFFFFF',\n borderRadius: '14px',\n border: '1.5px solid #E5E7EB',\n boxShadow: '0 1px 2px rgba(15,23,42,0.04)',\n padding: '14px 18px',\n },\n cardInputBorder: '#E5E7EB',\n nameInput: {\n backgroundColor: '#FFFFFF',\n border: '1.5px solid #E5E7EB',\n borderRadius: '14px',\n padding: '14px 16px',\n },\n submitButton: {\n backgroundColor: '#1785E0',\n borderRadius: '14px',\n padding: '16px 24px',\n boxShadow: '0 4px 14px rgba(23,133,224,0.25)',\n fontWeight: '600',\n },\n title: {\n color: '#0F172A',\n fontWeight: '600',\n },\n titleFontSize: '20px',\n backButton: { color: '#64748B' },\n backButtonIcon: { backgroundColor: '#F1F5F9' },\n};\n\n/** Modern dark — deep surface, 14px radius, sky-blue submit. */\nexport const BUTTONS_LAYOUT_MODERN_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#111827',\n borderRadius: '20px',\n border: '1px solid #1F2937',\n boxShadow: '0 8px 24px rgba(0,0,0,0.2)',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#0B1220',\n borderRadius: '14px',\n border: '1.5px solid #1F2937',\n color: '#F1F5F9',\n padding: '14px 18px',\n },\n cardInputBorder: '#1F2937',\n cardInputBackground: '#111827',\n cardInputColor: '#F1F5F9',\n cardInputPlaceholderColor: '#64748B',\n nameInput: {\n backgroundColor: '#111827',\n border: '1.5px solid #1F2937',\n borderRadius: '14px',\n padding: '14px 16px',\n color: '#F1F5F9',\n },\n submitButton: {\n backgroundColor: '#60A5FA',\n borderRadius: '14px',\n padding: '16px 24px',\n boxShadow: '0 4px 14px rgba(96,165,250,0.3)',\n fontWeight: '600',\n color: '#0B1220',\n },\n title: {\n color: '#F1F5F9',\n fontWeight: '600',\n },\n titleFontSize: '20px',\n backButton: { color: '#94A3B8' },\n backButtonIcon: { backgroundColor: '#1F2937' },\n countrySelect: { backgroundColor: '#111827', color: '#F1F5F9' },\n zipInput: { backgroundColor: '#111827', color: '#F1F5F9' },\n};\n\n/** Bold light — blue-tint backdrop, primary-bordered card, gradient pill submit. */\nexport const BUTTONS_LAYOUT_BOLD_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#EFF6FF',\n borderRadius: '20px',\n border: '2px solid #1785E0',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#FFFFFF',\n borderRadius: '12px',\n border: '2px solid #1785E0',\n color: '#1785E0',\n fontWeight: '700',\n padding: '14px 18px',\n },\n cardInputBorder: '#E5E7EB',\n nameInput: {\n backgroundColor: '#FFFFFF',\n border: '2px solid #E5E7EB',\n borderRadius: '12px',\n padding: '14px 16px',\n fontWeight: '500',\n },\n submitButton: {\n background: 'linear-gradient(135deg, #1785E0 0%, #0EA5E9 100%)',\n borderRadius: '9999px',\n padding: '16px 24px',\n boxShadow: '0 10px 25px rgba(23,133,224,0.35)',\n fontWeight: '700',\n color: '#FFFFFF',\n border: 'none',\n },\n submitButtonFontSize: '17px',\n title: {\n color: '#0C2B4D',\n fontWeight: '800',\n letterSpacing: '-0.02em',\n },\n titleFontSize: '22px',\n backButton: { color: '#1785E0', fontWeight: '600' },\n backButtonIcon: { backgroundColor: '#DBEAFE' },\n};\n\n/** Bold dark — saturated deep-blue surface, accented borders, gradient pill submit. */\nexport const BUTTONS_LAYOUT_BOLD_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#1E3A8A',\n borderRadius: '20px',\n border: '2px solid #60A5FA',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#0C2B4D',\n borderRadius: '12px',\n border: '2px solid #60A5FA',\n color: '#60A5FA',\n fontWeight: '700',\n padding: '14px 18px',\n },\n cardInputBorder: '#1E40AF',\n cardInputBackground: '#1E3A8A',\n cardInputColor: '#FFFFFF',\n cardInputPlaceholderColor: '#60A5FA',\n nameInput: {\n backgroundColor: '#1E3A8A',\n border: '2px solid #1E40AF',\n borderRadius: '12px',\n padding: '14px 16px',\n fontWeight: '500',\n color: '#FFFFFF',\n },\n submitButton: {\n background: 'linear-gradient(135deg, #60A5FA 0%, #38BDF8 100%)',\n borderRadius: '9999px',\n padding: '16px 24px',\n boxShadow: '0 10px 25px rgba(96,165,250,0.35)',\n fontWeight: '700',\n color: '#FFFFFF',\n border: 'none',\n },\n submitButtonFontSize: '17px',\n title: {\n color: '#FFFFFF',\n fontWeight: '800',\n letterSpacing: '-0.02em',\n },\n titleFontSize: '22px',\n backButton: { color: '#DBEAFE', fontWeight: '600' },\n backButtonIcon: { backgroundColor: '#1E40AF' },\n countrySelect: { backgroundColor: '#1E3A8A', color: '#FFFFFF' },\n zipInput: { backgroundColor: '#1E3A8A', color: '#FFFFFF' },\n};\n\n/** Glass light — translucent surfaces with backdrop blur over a pastel blue gradient. */\nexport const BUTTONS_LAYOUT_GLASS_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n background: 'linear-gradient(135deg, #DBEAFE 0%, #BFDBFE 100%)',\n borderRadius: '24px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.6), 0 12px 40px rgba(23,133,224,0.15)',\n padding: '28px',\n },\n cardButton: {\n backgroundColor: 'rgba(255,255,255,0.7)',\n backdropFilter: 'blur(20px)',\n borderRadius: '16px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.5), 0 4px 16px rgba(23,133,224,0.1)',\n padding: '14px 18px',\n },\n cardInputBorder: 'rgba(255,255,255,0.6)',\n nameInput: {\n backgroundColor: 'rgba(255,255,255,0.6)',\n backdropFilter: 'blur(10px)',\n border: '1px solid rgba(255,255,255,0.6)',\n borderRadius: '14px',\n padding: '14px 16px',\n },\n submitButton: {\n backgroundColor: 'rgba(23,133,224,0.95)',\n backdropFilter: 'blur(10px)',\n borderRadius: '16px',\n padding: '16px 24px',\n boxShadow: '0 10px 30px rgba(23,133,224,0.3), inset 0 1px 0 rgba(255,255,255,0.2)',\n fontWeight: '600',\n color: '#FFFFFF',\n },\n title: {\n color: '#1E293B',\n fontWeight: '600',\n letterSpacing: '-0.01em',\n },\n titleFontSize: '20px',\n backButton: { color: '#1785E0', fontWeight: '500' },\n backButtonIcon: { backgroundColor: 'rgba(255,255,255,0.7)' },\n};\n\n/** Glass dark — translucent surfaces with backdrop blur over a deep-blue gradient. */\nexport const BUTTONS_LAYOUT_GLASS_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n background: 'linear-gradient(135deg, #0C2B4D 0%, #0F172A 100%)',\n borderRadius: '24px',\n border: '1px solid rgba(255,255,255,0.08)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.06), 0 20px 50px rgba(0,0,0,0.4)',\n padding: '28px',\n },\n cardButton: {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(20px)',\n borderRadius: '16px',\n border: '1px solid rgba(255,255,255,0.08)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.05), 0 4px 16px rgba(0,0,0,0.3)',\n padding: '14px 18px',\n color: '#F1F5F9',\n },\n cardInputBorder: 'rgba(255,255,255,0.08)',\n cardInputBackground: 'rgba(15,23,42,0.6)',\n cardInputColor: '#F1F5F9',\n cardInputPlaceholderColor: '#64748B',\n nameInput: {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(10px)',\n border: '1px solid rgba(255,255,255,0.08)',\n borderRadius: '14px',\n padding: '14px 16px',\n color: '#F1F5F9',\n },\n submitButton: {\n backgroundColor: 'rgba(96,165,250,0.9)',\n backdropFilter: 'blur(10px)',\n borderRadius: '16px',\n padding: '16px 24px',\n boxShadow: '0 10px 30px rgba(96,165,250,0.35), inset 0 1px 0 rgba(255,255,255,0.15)',\n fontWeight: '600',\n color: '#0F172A',\n },\n title: {\n color: '#F1F5F9',\n fontWeight: '600',\n letterSpacing: '-0.01em',\n },\n titleFontSize: '20px',\n backButton: { color: '#60A5FA', fontWeight: '500' },\n backButtonIcon: { backgroundColor: 'rgba(255,255,255,0.08)' },\n countrySelect: { backgroundColor: 'rgba(15,23,42,0.6)', color: '#F1F5F9' },\n zipInput: { backgroundColor: 'rgba(15,23,42,0.6)', color: '#F1F5F9' },\n};\n\n/** Resolve a buttons layout theme name to its style preset. */\nexport function resolveButtonsLayoutTheme(theme?: ButtonsLayoutTheme): ButtonsLayoutStyles {\n switch (theme) {\n case 'minimal': return BUTTONS_LAYOUT_MINIMAL;\n case 'rounded': return BUTTONS_LAYOUT_ROUNDED;\n case 'dark': return BUTTONS_LAYOUT_DARK;\n case 'modern-light': return BUTTONS_LAYOUT_MODERN_LIGHT;\n case 'modern-dark': return BUTTONS_LAYOUT_MODERN_DARK;\n case 'bold-light': return BUTTONS_LAYOUT_BOLD_LIGHT;\n case 'bold-dark': return BUTTONS_LAYOUT_BOLD_DARK;\n case 'glass-light': return BUTTONS_LAYOUT_GLASS_LIGHT;\n case 'glass-dark': return BUTTONS_LAYOUT_GLASS_DARK;\n default: return BUTTONS_LAYOUT_DEFAULT;\n }\n}\n\n/**\n * First-class theme bundles. Each entry pairs a `FloPayAppearance` (for Stripe\n * Elements) with a `ButtonsLayoutStyles` (for the FloPay wrapper) so the look\n * is coherent across both halves. Consumers can pick by id without having to\n * import the two halves separately.\n *\n * @example\n * ```tsx\n * import { THEMES } from '@flopay/shared';\n *\n * const { appearance, buttonsLayout } = THEMES['glass-dark'];\n * <FloPayCheckout appearance={appearance} buttonsLayoutStyles={buttonsLayout} />\n * ```\n */\nexport const THEMES: Record<ThemeBundleId, ThemeBundle> = {\n 'modern-light': { appearance: MODERN_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_MODERN_LIGHT },\n 'modern-dark': { appearance: MODERN_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_MODERN_DARK },\n 'bold-light': { appearance: BOLD_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_BOLD_LIGHT },\n 'bold-dark': { appearance: BOLD_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_BOLD_DARK },\n 'glass-light': { appearance: GLASS_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_GLASS_LIGHT },\n 'glass-dark': { appearance: GLASS_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_GLASS_DARK },\n};\n\n/**\n * Resolve a {@link ThemeId} to its {@link ThemeBundle}, or `undefined` for\n * `'classic'` / a missing id (the historic FloPay look with no bundle applied).\n *\n * Used by FloPay React components when consumers pass the high-level `theme`\n * prop instead of supplying `appearance` + `buttonsStyles` manually. Explicit\n * `appearance` / `buttonsStyles` props still override the resolved bundle.\n */\nexport function resolveTheme(id?: ThemeId | null): ThemeBundle | undefined {\n if (!id || id === 'classic') return undefined;\n return THEMES[id];\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Payment Method partitioning\n// ---------------------------------------------------------------------------\n\n/**\n * Map Stripe wire identifiers (`apple_pay`, `google_pay`, `amazon_pay`) to the\n * camelCase keys that `ExpressCheckoutElement`'s `paymentMethods` options\n * map expects. Everything not in this map is already camelCase compatible.\n */\nexport function stripeExpressMethodToOptionKey(method: string): string {\n switch (method) {\n case 'apple_pay': return 'applePay';\n case 'google_pay': return 'googlePay';\n case 'amazon_pay': return 'amazonPay';\n default: return method;\n }\n}\n\n/**\n * Per-method metadata for every Stripe payment-method type the SDK\n * recognises. One source of truth instead of half a dozen disjoint maps —\n * `STRIPE_METHOD_CURRENCIES`, `STRIPE_METHOD_AMOUNT_LIMITS`, the React\n * package's display-name table, and the inline-form heuristic all derive\n * from entries here.\n *\n * Source: Stripe payment-method support matrices at\n * <https://docs.stripe.com/payments/payment-methods/integration-options>.\n * Update entries when Stripe ships a new currency / amount limit / method\n * — the SDK falls back to safe defaults for any wire identifier not listed.\n */\nexport interface StripeMethodEntry {\n /**\n * Human-readable label, used by consumers for \"Pay with X\" buttons and\n * other UI surfaces that need the brand name.\n */\n displayName: string;\n /**\n * Lowercase ISO-4217 currency codes Stripe accepts for this method. The\n * sentinel `'*'` means \"currency-agnostic\" — only the universal big-button\n * wallets (Apple Pay / Google Pay) use this today.\n */\n currencies: readonly string[];\n /**\n * Uppercase ISO 3166-1 alpha-2 codes for the buyer countries Stripe makes\n * this method available to (matched against the session customer's\n * country). Many local APMs are country-gated independently of currency —\n * Bancontact is Belgium-only, EPS Austria-only, iDEAL Netherlands-only,\n * SEPA Debit the whole SEPA zone — so a EUR cart still must not offer\n * Bancontact to a Dutch buyer.\n *\n * **Omit** for methods with no meaningful country restriction (the global\n * wallets, Alipay, Klarna, …) — a missing list means \"no country gate\", so\n * the method passes {@link filterStripeMethodsByCountry} for every buyer.\n */\n countries?: readonly string[];\n /**\n * Per-currency amount min/max in the smallest currency unit (cents for USD,\n * pence for GBP, etc.). Omit when there is no notable limit. Stripe's\n * `/v1/elements/sessions` rejects the whole accordion when an entry is in\n * `paymentMethodTypes` and the deferred-intent amount falls outside its\n * advertised range, so filtering here matches Stripe's reality.\n */\n amounts?: Record<string, { min?: number; max?: number }>;\n /**\n * True when this method renders inside Stripe's `ExpressCheckoutElement`\n * (apple_pay, google_pay, paypal, link, amazon_pay, klarna). Everything\n * else lives in the `PaymentElement` accordion.\n */\n express?: boolean;\n /**\n * When `false`, the SDK auto-submits the moment the buyer clicks the\n * method card — the buyer is taken straight to Stripe's authorization UI\n * (popup / redirect) without an intermediate confirm step. Only set this\n * for *pure* redirect-only methods that have no inline data collection\n * (Cash App, Affirm).\n *\n * **Default `true`**: render an explicit \"Pay with X\" button at the\n * bottom of the accordion. Safer-by-default — any new/unknown APM, or\n * any method whose Stripe UI changes to add inline inputs, will surface\n * a deliberate confirm action instead of silently auto-submitting on a\n * stray keystroke. Bancontact / Giropay are theoretically redirect-only\n * but ship with a Name input by default, so they stay on the default\n * (button) path.\n */\n needsExplicitConfirm?: boolean;\n /**\n * Per-mode brand styling for the method tile button. The SDK looks up\n * `theme.dark` when the active FloPay theme is one of the `*-dark`\n * bundles, otherwise `theme.light` (also used for `classic`, since\n * brand assets are designed primarily against light surfaces).\n *\n * Entries are optional — methods without a `theme` fall back to the\n * neutral tile styling derived from the theme's `buttonsStyles.cardButton`\n * + `derivePrimaryTileStyle`. Consumers can override per-tile via\n * `buttonAppearance` on the inner component.\n */\n theme?: {\n light?: StripeMethodThemeVariant;\n dark?: StripeMethodThemeVariant;\n };\n}\n\n/**\n * Per-mode visual treatment for a Stripe method tile button. Applies brand\n * colors and (optionally) an inline mark so each APM tile reads\n * unmistakably as itself.\n *\n * `logoSvg` is an inline SVG string rendered at ~22px tall inside the\n * button before the label. The SDK ships a small generic placeholder mark\n * per method (a colored disc + initial) authored as original geometry —\n * **not** a reproduction of any official trademarked logo. Consumers who\n * have rights to a brand's artwork can replace these per-entry by\n * overriding the matrix in their own deployment.\n */\nexport interface StripeMethodThemeVariant {\n backgroundColor?: string;\n borderColor?: string;\n textColor?: string;\n /**\n * Inline SVG markup, e.g. `'<svg viewBox=\"0 0 24 24\">…</svg>'`. Trusted\n * by the renderer (mounted via `dangerouslySetInnerHTML`) — only edit\n * via this matrix or a controlled override; never wire user input here.\n */\n logoSvg?: string;\n}\n\n/**\n * Helper for building the SDK's default placeholder marks: a filled disc\n * with a single-character glyph centered in a contrasting color. Original\n * geometry — not a reproduction of any official brand artwork.\n */\nfunction buildPlaceholderMark(glyph: string, discColor: string, glyphColor: string): string {\n // Hand-rolled SVG so the matrix entries below stay declarative and tiny.\n // `font-family` falls through to the host page's sans-serif to keep the\n // SDK's bundle free of font assets.\n return (\n '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-hidden=\"true\">' +\n `<circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"${discColor}\"/>` +\n `<text x=\"11\" y=\"15.5\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" ` +\n `font-family=\"-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif\" ` +\n `fill=\"${glyphColor}\">${glyph}</text>` +\n '</svg>'\n );\n}\n\n/**\n * Bank-building glyph for the Bank Transfer (`customer_balance`) tile — a\n * pediment + columns + base on a coloured disc. Hand-rolled SVG so the matrix\n * stays declarative and the bundle carries no image assets.\n */\nfunction buildBankMark(discColor: string, glyphColor: string): string {\n return (\n '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-hidden=\"true\">' +\n `<circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"${discColor}\"/>` +\n `<g fill=\"${glyphColor}\">` +\n '<path d=\"M11 4 L17.5 8 L4.5 8 Z\"/>' +\n '<rect x=\"5\" y=\"8.4\" width=\"12\" height=\"1.2\" rx=\"0.3\"/>' +\n '<rect x=\"5.9\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"8.55\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"11.95\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"14.6\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"4.6\" y=\"15.4\" width=\"12.8\" height=\"1.5\" rx=\"0.3\"/>' +\n '</g>' +\n '</svg>'\n );\n}\n\n/**\n * Buyer countries covered by the SEPA Direct Debit scheme (ISO 3166-1\n * alpha-2). Used as `sepa_debit.countries` so the method is offered to the\n * whole SEPA zone — the EU/EEA plus the handful of non-EEA participants\n * (CH, GB, MC, SM, AD, VA) — rather than a single country.\n */\nconst SEPA_COUNTRIES: readonly string[] = [\n 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR',\n 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO',\n 'SE', 'SI', 'SK',\n 'IS', 'LI', 'NO', // EEA non-EU\n 'CH', 'GB', 'MC', 'SM', 'AD', 'VA', // non-EEA SEPA participants\n];\n\n/**\n * Buyer countries Bank Transfer (`customer_balance`) is offered to: the whole\n * of Europe (the SEPA zone, which includes the UK) plus Japan, Mexico and the\n * US. Settled in EUR or USD only.\n */\nconst BANK_TRANSFER_COUNTRIES: readonly string[] = [...SEPA_COUNTRIES, 'JP', 'MX', 'US'];\n\nexport const STRIPE_METHOD_MATRIX: Record<string, StripeMethodEntry> = {\n // ─── Express wallets ────────────────────────────────────────────────────\n apple_pay: {\n displayName: 'Apple Pay',\n currencies: ['*'],\n express: true,\n needsExplicitConfirm: false,\n },\n google_pay: {\n displayName: 'Google Pay',\n currencies: ['*'],\n express: true,\n needsExplicitConfirm: false,\n },\n paypal: {\n displayName: 'PayPal',\n currencies: ['eur', 'gbp', 'usd', 'cad', 'aud', 'nzd', 'chf', 'jpy', 'pln', 'sek', 'nok', 'dkk', 'czk', 'huf'],\n express: true,\n needsExplicitConfirm: false,\n },\n link: {\n displayName: 'Link',\n currencies: ['usd', 'eur'],\n express: true,\n needsExplicitConfirm: false,\n },\n amazon_pay: {\n displayName: 'Amazon Pay',\n currencies: ['usd', 'eur', 'gbp'],\n express: true,\n needsExplicitConfirm: false,\n },\n\n // ─── Klarna: PaymentElement tile, explicit confirm ─────────────────────\n // Klarna renders as a PaymentElement tile (NOT express) so it always appears\n // when the backend includes it in `enabledPaymentMethods`. Stripe's\n // ExpressCheckoutElement only paints a Klarna button in eligible *real*\n // browsers (never headless), which made it effectively invisible and looked\n // like an SDK-level disable — as a tile it's purely backend-driven. Klarna\n // may redirect during confirm, but it still surfaces a deliberate \"Pay with\n // Klarna\" step: it omits `needsExplicitConfirm: false`, so the default\n // `needsStripeMethodExplicitConfirm(...) === true` applies — unlike the\n // auto-confirm APMs below.\n klarna: {\n displayName: 'Klarna',\n currencies: ['usd', 'eur', 'gbp', 'aud', 'nzd', 'cad', 'chf', 'sek', 'nok', 'dkk', 'pln', 'czk', 'ron'],\n amounts: { usd: { min: 100 }, eur: { min: 100 }, gbp: { min: 100 } },\n // Default (explicit \"Pay with Klarna\" button) — Klarna's PaymentElement can\n // collect inline data and isn't a pure redirect-only method, so surface a\n // deliberate confirm rather than auto-submitting on tile click.\n theme: {\n light: {\n backgroundColor: '#FFB3C7',\n textColor: '#0A0B09',\n borderColor: '#FFB3C7',\n logoSvg: buildPlaceholderMark('K', '#0A0B09', '#FFB3C7'),\n },\n dark: {\n backgroundColor: '#FFB3C7',\n textColor: '#0A0B09',\n borderColor: '#FFB3C7',\n logoSvg: buildPlaceholderMark('K', '#0A0B09', '#FFB3C7'),\n },\n },\n },\n // ─── PaymentElement APMs: auto-confirm (redirect-only, no Pay button) ───\n // Affirm and Cash App Pay are pure redirect/handoff methods with no inline\n // inputs, so they auto-submit on tile click (`needsExplicitConfirm: false`).\n //\n // Affirm currently rejects on non-USD currencies via\n // /v1/elements/sessions, hence the narrow currency list. Below $35.00 USD\n // it returns `amount_too_small` and blanks out the whole accordion, hence\n // the explicit min — see `filterStripeMethodsByAmount` for the gate.\n affirm: {\n displayName: 'Affirm',\n currencies: ['usd'],\n countries: ['US', 'CA'],\n amounts: { usd: { min: 3500, max: 3_000_000 } },\n needsExplicitConfirm: false,\n theme: {\n light: {\n backgroundColor: '#060F33',\n textColor: '#FFFFFF',\n borderColor: '#060F33',\n logoSvg: buildPlaceholderMark('a', '#FFFFFF', '#060F33'),\n },\n dark: {\n backgroundColor: '#0FA0EA',\n textColor: '#060F33',\n borderColor: '#0FA0EA',\n logoSvg: buildPlaceholderMark('a', '#060F33', '#FFFFFF'),\n },\n },\n },\n cashapp: {\n displayName: 'Cash App Pay',\n currencies: ['usd'],\n countries: ['US'],\n // Cash App Pay cannot process a $0 (or sub-$0.50) charge — Stripe rejects\n // `amount_too_small`. Range per Stripe: USD 0.50 – 999,999.99. Keeps a\n // free-trial ($0 today) cart from surfacing a Cash App button.\n amounts: { usd: { min: 50, max: 99_999_999 } },\n needsExplicitConfirm: false,\n theme: {\n light: {\n backgroundColor: '#00D54B',\n textColor: '#0A1F0E',\n borderColor: '#00D54B',\n logoSvg: buildPlaceholderMark('$', '#0A1F0E', '#00D54B'),\n },\n dark: {\n backgroundColor: '#00D54B',\n textColor: '#0A1F0E',\n borderColor: '#00D54B',\n logoSvg: buildPlaceholderMark('$', '#0A1F0E', '#00D54B'),\n },\n },\n },\n\n // ─── PaymentElement APMs: default (explicit Pay button) ─────────────────\n // These methods either render an inline form (IBAN, bank picker, …) or\n // ship with a Name input by default. Either way the buyer expects to\n // review and confirm with a deliberate click, so we surface a Pay button\n // and never auto-submit on a `change` event.\n afterpay_clearpay: {\n displayName: 'Afterpay',\n currencies: ['usd', 'aud', 'cad', 'gbp', 'nzd'],\n countries: ['US', 'CA', 'GB', 'AU', 'NZ'],\n amounts: {\n usd: { min: 100, max: 200_000 },\n cad: { min: 100, max: 200_000 },\n gbp: { min: 100, max: 120_000 },\n aud: { min: 100, max: 200_000 },\n nzd: { min: 100, max: 200_000 },\n },\n // Afterpay's brand mint (#B2FCE4) with black wordmark/icon — the signature\n // palette from afterpay.com's brand system.\n theme: {\n light: {\n backgroundColor: '#B2FCE4',\n textColor: '#0A0B09',\n borderColor: '#B2FCE4',\n logoSvg: buildPlaceholderMark('A', '#0A0B09', '#B2FCE4'),\n },\n dark: {\n backgroundColor: '#B2FCE4',\n textColor: '#0A0B09',\n borderColor: '#B2FCE4',\n logoSvg: buildPlaceholderMark('A', '#0A0B09', '#B2FCE4'),\n },\n },\n },\n alipay: {\n displayName: 'Alipay',\n // Presentment currencies only — Alipay is offered to USD / CNY carts.\n currencies: ['usd', 'cny'],\n theme: {\n light: {\n backgroundColor: '#1677FF',\n textColor: '#FFFFFF',\n borderColor: '#1677FF',\n logoSvg: buildPlaceholderMark('A', '#FFFFFF', '#1677FF'),\n },\n dark: {\n backgroundColor: '#1677FF',\n textColor: '#FFFFFF',\n borderColor: '#1677FF',\n logoSvg: buildPlaceholderMark('A', '#FFFFFF', '#1677FF'),\n },\n },\n },\n au_becs_debit: { displayName: 'BECS Direct Debit', currencies: ['aud'], countries: ['AU'] },\n bacs_debit: { displayName: 'Bacs Debit', currencies: ['gbp'], countries: ['GB'] },\n bancontact: {\n displayName: 'Bancontact',\n currencies: ['eur'],\n countries: ['BE'],\n theme: {\n light: {\n backgroundColor: '#FFDD55',\n textColor: '#1E3791',\n borderColor: '#FFDD55',\n logoSvg: buildPlaceholderMark('B', '#1E3791', '#FFDD55'),\n },\n dark: {\n backgroundColor: '#1E3791',\n textColor: '#FFDD55',\n borderColor: '#1E3791',\n logoSvg: buildPlaceholderMark('B', '#FFDD55', '#1E3791'),\n },\n },\n },\n bizum: {\n displayName: 'Bizum',\n currencies: ['eur'],\n countries: ['ES'],\n theme: {\n light: {\n backgroundColor: '#00BFB3',\n textColor: '#FFFFFF',\n borderColor: '#00BFB3',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#00BFB3'),\n },\n dark: {\n backgroundColor: '#00BFB3',\n textColor: '#FFFFFF',\n borderColor: '#00BFB3',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#00BFB3'),\n },\n },\n },\n blik: {\n displayName: 'BLIK',\n currencies: ['pln'],\n countries: ['PL'],\n theme: {\n light: {\n backgroundColor: '#000000',\n textColor: '#FFFFFF',\n borderColor: '#000000',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#000000'),\n },\n dark: {\n backgroundColor: '#FFFFFF',\n textColor: '#000000',\n borderColor: '#FFFFFF',\n logoSvg: buildPlaceholderMark('B', '#000000', '#FFFFFF'),\n },\n },\n },\n boleto: { displayName: 'Boleto', currencies: ['brl'], countries: ['BR'] },\n customer_balance: {\n displayName: 'Bank Transfer',\n currencies: ['eur', 'usd'],\n countries: BANK_TRANSFER_COUNTRIES,\n theme: {\n light: {\n backgroundColor: '#1F2937',\n textColor: '#FFFFFF',\n borderColor: '#1F2937',\n logoSvg: buildBankMark('#1F2937', '#FFFFFF'),\n },\n dark: {\n backgroundColor: '#374151',\n textColor: '#FFFFFF',\n borderColor: '#374151',\n logoSvg: buildBankMark('#374151', '#FFFFFF'),\n },\n },\n },\n eps: {\n displayName: 'EPS',\n currencies: ['eur'],\n countries: ['AT'],\n theme: {\n light: {\n backgroundColor: '#C8102E',\n textColor: '#FFFFFF',\n borderColor: '#C8102E',\n logoSvg: buildPlaceholderMark('E', '#FFFFFF', '#C8102E'),\n },\n dark: {\n backgroundColor: '#C8102E',\n textColor: '#FFFFFF',\n borderColor: '#C8102E',\n logoSvg: buildPlaceholderMark('E', '#FFFFFF', '#C8102E'),\n },\n },\n },\n giropay: {\n displayName: 'Giropay',\n currencies: ['eur'],\n countries: ['DE'],\n theme: {\n light: {\n backgroundColor: '#0F4197',\n textColor: '#FFFFFF',\n borderColor: '#0F4197',\n logoSvg: buildPlaceholderMark('G', '#FFFFFF', '#0F4197'),\n },\n dark: {\n backgroundColor: '#0F4197',\n textColor: '#FFFFFF',\n borderColor: '#0F4197',\n logoSvg: buildPlaceholderMark('G', '#FFFFFF', '#0F4197'),\n },\n },\n },\n ideal: {\n displayName: 'iDEAL',\n currencies: ['eur'],\n countries: ['NL'],\n theme: {\n light: {\n backgroundColor: '#CC0066',\n textColor: '#FFFFFF',\n borderColor: '#CC0066',\n logoSvg: buildPlaceholderMark('i', '#FFFFFF', '#CC0066'),\n },\n dark: {\n backgroundColor: '#CC0066',\n textColor: '#FFFFFF',\n borderColor: '#CC0066',\n logoSvg: buildPlaceholderMark('i', '#FFFFFF', '#CC0066'),\n },\n },\n },\n konbini: { displayName: 'Konbini', currencies: ['jpy'], countries: ['JP'] },\n kr_card: {\n displayName: 'Korean Card',\n currencies: ['krw'],\n countries: ['KR'],\n theme: {\n light: {\n backgroundColor: '#0B3D91',\n textColor: '#FFFFFF',\n borderColor: '#0B3D91',\n logoSvg: buildPlaceholderMark('K', '#FFFFFF', '#0B3D91'),\n },\n dark: {\n backgroundColor: '#0B3D91',\n textColor: '#FFFFFF',\n borderColor: '#0B3D91',\n logoSvg: buildPlaceholderMark('K', '#FFFFFF', '#0B3D91'),\n },\n },\n },\n multibanco: { displayName: 'Multibanco', currencies: ['eur'], countries: ['PT'] },\n oxxo: { displayName: 'OXXO', currencies: ['mxn'], countries: ['MX'] },\n p24: {\n displayName: 'Przelewy24',\n currencies: ['eur', 'pln'],\n countries: ['PL'],\n theme: {\n light: {\n backgroundColor: '#D90F1B',\n textColor: '#FFFFFF',\n borderColor: '#D90F1B',\n logoSvg: buildPlaceholderMark('P', '#FFFFFF', '#D90F1B'),\n },\n dark: {\n backgroundColor: '#D90F1B',\n textColor: '#FFFFFF',\n borderColor: '#D90F1B',\n logoSvg: buildPlaceholderMark('P', '#FFFFFF', '#D90F1B'),\n },\n },\n },\n paynow: { displayName: 'PayNow', currencies: ['sgd'], countries: ['SG'] },\n pix: { displayName: 'Pix', currencies: ['brl'], countries: ['BR'] },\n promptpay: { displayName: 'PromptPay', currencies: ['thb'], countries: ['TH'] },\n sepa_debit: {\n displayName: 'SEPA Debit',\n currencies: ['eur'],\n countries: SEPA_COUNTRIES,\n theme: {\n // SEPA itself isn't a brand with a saturated palette — use a neutral\n // bank-blue that reads as \"European bank transfer\" without leaning\n // on a specific institution.\n light: {\n backgroundColor: '#10298E',\n textColor: '#FFFFFF',\n borderColor: '#10298E',\n logoSvg: buildPlaceholderMark('€', '#FFFFFF', '#10298E'),\n },\n dark: {\n backgroundColor: '#3056D3',\n textColor: '#FFFFFF',\n borderColor: '#3056D3',\n logoSvg: buildPlaceholderMark('€', '#FFFFFF', '#3056D3'),\n },\n },\n },\n sofort: {\n displayName: 'Sofort',\n currencies: ['eur'],\n countries: ['AT', 'BE', 'DE', 'ES', 'IT', 'NL'],\n theme: {\n light: {\n backgroundColor: '#EF809F',\n textColor: '#FFFFFF',\n borderColor: '#EF809F',\n logoSvg: buildPlaceholderMark('S', '#FFFFFF', '#EF809F'),\n },\n dark: {\n backgroundColor: '#EF809F',\n textColor: '#FFFFFF',\n borderColor: '#EF809F',\n logoSvg: buildPlaceholderMark('S', '#FFFFFF', '#EF809F'),\n },\n },\n },\n upi: {\n displayName: 'UPI',\n currencies: ['inr'],\n countries: ['IN'],\n theme: {\n light: {\n backgroundColor: '#FF7909',\n textColor: '#FFFFFF',\n borderColor: '#FF7909',\n logoSvg: buildPlaceholderMark('U', '#FFFFFF', '#FF7909'),\n },\n dark: {\n backgroundColor: '#FF7909',\n textColor: '#FFFFFF',\n borderColor: '#FF7909',\n logoSvg: buildPlaceholderMark('U', '#FFFFFF', '#FF7909'),\n },\n },\n },\n us_bank_account: { displayName: 'US Bank Account', currencies: ['usd'], countries: ['US'] },\n wechat_pay: {\n displayName: 'WeChat Pay',\n // Presentment currencies only — WeChat Pay is offered to USD / CNY carts.\n currencies: ['usd', 'cny'],\n theme: {\n light: {\n backgroundColor: '#07C160',\n textColor: '#FFFFFF',\n borderColor: '#07C160',\n logoSvg: buildPlaceholderMark('W', '#FFFFFF', '#07C160'),\n },\n dark: {\n backgroundColor: '#07C160',\n textColor: '#FFFFFF',\n borderColor: '#07C160',\n logoSvg: buildPlaceholderMark('W', '#FFFFFF', '#07C160'),\n },\n },\n },\n zip: { displayName: 'Zip', currencies: ['aud'], countries: ['AU', 'NZ'] },\n};\n\n/**\n * Whether a method's `logoSvg` is a vendored real brand logo (from\n * `fetch:logos`) rather than the SDK's generated placeholder mark. Tile\n * buttons use this to size the gap between logo and label: the real logos\n * are self-contained cards that read as a separate mark (8px gap), whereas\n * the generated placeholder monogram reads as part of the label (0px gap).\n */\nexport function hasVendoredStripeMethodLogo(type: string | null | undefined): boolean {\n if (!type) return false;\n return VENDORED_LOGO_METHODS.includes(type);\n}\n\n/**\n * Stripe payment method types that render as native big buttons in the\n * `ExpressCheckoutElement`. Everything else falls into the `PaymentElement`\n * accordion. Derived from {@link STRIPE_METHOD_MATRIX} entries flagged\n * `express: true` — insertion order in the matrix dictates the wallet-row\n * ordering (apple_pay → google_pay → paypal → link → amazon_pay → klarna).\n */\nexport const STRIPE_EXPRESS_METHODS: readonly string[] = Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.express)\n .map(([key]) => key);\n\nconst STRIPE_EXPRESS_METHODS_SET: ReadonlySet<string> = new Set(STRIPE_EXPRESS_METHODS);\n\n/**\n * Stripe payment-method → supported-currencies map. Derived from\n * {@link STRIPE_METHOD_MATRIX} — kept as a separate export for callers that\n * just want the currency list without the rest of the entry.\n *\n * Stripe rejects the entire `PaymentElement` mount with an `IntegrationError`\n * when `paymentMethodTypes` contains a method that doesn't support the session\n * currency (e.g. `bancontact` on a USD session). The SDK drops those methods\n * before forwarding them to Stripe so a single mis-matched method doesn't\n * blank out the whole accordion.\n *\n * Unknown methods (anything not in the matrix) pass through unchanged so a\n * brand-new Stripe APM keeps working until the matrix is refreshed.\n */\nexport const STRIPE_METHOD_CURRENCIES: Record<string, readonly string[]> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX).map(([key, entry]) => [key, entry.currencies]),\n);\n\n/**\n * Stripe payment-method → supported-buyer-countries map (uppercase ISO\n * 3166-1 alpha-2). Derived from {@link STRIPE_METHOD_MATRIX}; only methods\n * that declared a `countries` list appear here. Methods absent from this map\n * have no country gate and are offered to every buyer (subject to the\n * currency / amount filters).\n *\n * Local APMs like Bancontact (BE), EPS (AT) and iDEAL (NL) are available\n * only to buyers in their home country even on a EUR cart, so the SDK drops\n * them when the session customer's country doesn't match — mirroring what\n * Stripe's `PaymentElement` would do from the buyer's locale anyway.\n */\nexport const STRIPE_METHOD_COUNTRIES: Record<string, readonly string[]> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.countries)\n .map(([key, entry]) => [key, entry.countries as readonly string[]]),\n);\n\n/**\n * Display-name lookup. Falls back to a title-cased version of the wire id\n * (e.g. `au_becs_debit` → `Au Becs Debit`) for methods not in the matrix so\n * a brand-new APM still produces a legible label until the matrix catches up.\n */\nexport function getStripeMethodDisplayName(type: string | null | undefined): string {\n if (!type) return 'this method';\n const entry = STRIPE_METHOD_MATRIX[type];\n if (entry) return entry.displayName;\n return type\n .split('_')\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\n/**\n * Whether the SDK should render an explicit \"Pay with X\" button for this\n * method rather than auto-submitting on click. Defaults to `true` (safer for\n * unknown methods) — only methods explicitly flagged `needsExplicitConfirm:\n * false` in the matrix (Cash App, Affirm) auto-submit.\n */\nexport function needsStripeMethodExplicitConfirm(type: string | null | undefined): boolean {\n if (!type) return true;\n const entry = STRIPE_METHOD_MATRIX[type];\n if (!entry) return true;\n return entry.needsExplicitConfirm !== false;\n}\n\n/**\n * Resolve the per-mode brand styling for a method tile button, given the\n * active FloPay theme id. Returns `null` when the method has no `theme`\n * entry in the matrix — callers fall back to the neutral tile styling\n * derived from `buttonsStyles.cardButton`.\n *\n * Theme-id → variant rule:\n * - `*-dark` themes get `theme.dark` (then `theme.light` as fallback).\n * - Everything else (`classic`, `*-light`, undefined) gets `theme.light`.\n */\nexport function resolveStripeMethodBrandVariant(\n type: string | null | undefined,\n themeId: ThemeId | null | undefined,\n): StripeMethodThemeVariant | null {\n if (!type) return null;\n const entry = STRIPE_METHOD_MATRIX[type];\n if (!entry?.theme) return null;\n const isDark = typeof themeId === 'string' && themeId.endsWith('-dark');\n // Returns theme colours + the placeholder mark only. The vendored real brand\n // logo (when `hasVendoredStripeMethodLogo`) is an <img> asset owned by\n // @flopay/react, so the SVG markup never enters this package's JS.\n return (isDark ? entry.theme.dark : entry.theme.light) ?? entry.theme.light ?? null;\n}\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those that\n * support the supplied ISO-4217 currency code. Unknown methods (anything not\n * in {@link STRIPE_METHOD_CURRENCIES}) pass through unchanged so a brand-new\n * Stripe APM keeps working until the SDK ships an updated map.\n *\n * The currency comparison is case-insensitive (`USD` and `usd` both match).\n * An empty / missing currency disables filtering entirely (returns the input\n * list as-is) — callers that don't know the currency are still better off\n * letting Stripe fail loudly than dropping everything to silence.\n */\nexport function filterStripeMethodsByCurrency(\n methods: readonly string[] | undefined,\n currency: string | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!currency) return [...methods];\n const target = currency.trim().toLowerCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const supported = STRIPE_METHOD_CURRENCIES[method];\n if (!supported) return true; // unknown method → pass through\n return supported.includes('*') || supported.includes(target);\n });\n}\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those available\n * to the supplied buyer country (ISO 3166-1 alpha-2). Methods with no country\n * gate in {@link STRIPE_METHOD_COUNTRIES} — the global wallets, Alipay,\n * Klarna, unknown methods — pass through unchanged.\n *\n * The country comparison is case-insensitive (`be` and `BE` both match). An\n * empty / missing country disables filtering entirely (returns the input list\n * as-is) — when the session doesn't know the buyer's country we'd rather let\n * Stripe make the final call than drop every country-gated method.\n */\nexport function filterStripeMethodsByCountry(\n methods: readonly string[] | undefined,\n country: string | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!country) return [...methods];\n const target = country.trim().toUpperCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const supported = STRIPE_METHOD_COUNTRIES[method];\n if (!supported) return true; // no country gate → pass through\n return supported.includes('*') || supported.includes(target);\n });\n}\n\n/**\n * Per-method amount limits (in the smallest currency unit, e.g. cents for USD)\n * keyed by Stripe wire identifier and then currency code. Derived from\n * {@link STRIPE_METHOD_MATRIX} — kept as a separate export for callers that\n * just want the amount limits without the rest of the entry.\n *\n * Stripe's `/v1/elements/sessions` endpoint hard-400's when\n * `paymentMethodTypes` contains a method whose per-currency minimum or\n * maximum is violated by the deferred-intent amount — and a single rejected\n * method blanks out the entire `PaymentElement` accordion (\"Frame not\n * initialized\" / empty `<div class=\"\">` shell). Filtering here matches\n * Stripe's reality so an incompatible amount silently drops the offending\n * method instead of poisoning the whole mount.\n */\nexport const STRIPE_METHOD_AMOUNT_LIMITS: Record<\n string,\n Record<string, { min?: number; max?: number }>\n> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.amounts)\n .map(([key, entry]) => [key, entry.amounts as Record<string, { min?: number; max?: number }>]),\n);\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those whose\n * per-currency amount range accepts {@link amountInMinorUnits}. Unknown methods\n * (anything not in {@link STRIPE_METHOD_AMOUNT_LIMITS}) pass through unchanged\n * so a brand-new Stripe APM keeps working without an SDK update.\n *\n * Currency comparison is case-insensitive. Missing currency / amount disables\n * filtering — callers that don't know the cart yet should pass through the\n * full list rather than silently dropping everything.\n */\nexport function filterStripeMethodsByAmount(\n methods: readonly string[] | undefined,\n currency: string | undefined,\n amountInMinorUnits: number | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!currency || typeof amountInMinorUnits !== 'number' || !Number.isFinite(amountInMinorUnits)) {\n return [...methods];\n }\n const target = currency.trim().toLowerCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const perCurrency = STRIPE_METHOD_AMOUNT_LIMITS[method];\n if (!perCurrency) return true;\n const limits = perCurrency[target];\n if (!limits) return true;\n if (typeof limits.min === 'number' && amountInMinorUnits < limits.min) return false;\n if (typeof limits.max === 'number' && amountInMinorUnits > limits.max) return false;\n return true;\n });\n}\n\n/**\n * Partition the backend's `enabledPaymentMethods` list into the two SDK\n * regions inside `SplitCardForm`:\n *\n * - `expressMethods` — intersected with {@link STRIPE_EXPRESS_METHODS} so\n * only `ExpressCheckoutElement`-supported methods land in the big-button\n * row.\n * - `paymentElementMethods` — every remaining method (Cash App Pay, Affirm,\n * iDEAL, Bancontact, SEPA debit, …) for the `PaymentElement` accordion.\n *\n * `card` is dropped from both lists — the card path stays on the split\n * fields. When `options.excludePaypal` is `true`, the SDK is rendering\n * `DirectPayPalButton` separately and PayPal is also pulled out of the\n * express list to avoid double-rendering.\n */\nexport function partitionStripeMethods(\n enabledPaymentMethods: readonly string[] | undefined,\n options?: { excludePaypal?: boolean },\n): { expressMethods: string[]; paymentElementMethods: string[] } {\n if (!enabledPaymentMethods?.length) {\n return { expressMethods: [], paymentElementMethods: [] };\n }\n const expressMethods: string[] = [];\n const paymentElementMethods: string[] = [];\n const seenExpress = new Set<string>();\n const seenElement = new Set<string>();\n\n for (const raw of enabledPaymentMethods) {\n if (typeof raw !== 'string') continue;\n const method = raw.trim();\n if (!method || method === 'card') continue;\n if (options?.excludePaypal && method === 'paypal') continue;\n\n if (STRIPE_EXPRESS_METHODS_SET.has(method)) {\n if (seenExpress.has(method)) continue;\n seenExpress.add(method);\n expressMethods.push(method);\n } else {\n if (seenElement.has(method)) continue;\n seenElement.add(method);\n paymentElementMethods.push(method);\n }\n }\n return { expressMethods, paymentElementMethods };\n}\n\n// ---------------------------------------------------------------------------\n// Supported Element Types\n// ---------------------------------------------------------------------------\n\n/** All supported element type identifiers. */\nexport const ELEMENT_TYPES = [\n 'payment',\n 'card',\n 'cardNumber',\n 'cardExpiry',\n 'cardCvc',\n 'address',\n] as const;\n\n// ---------------------------------------------------------------------------\n// Supported Card Brands\n// ---------------------------------------------------------------------------\n\nexport const SUPPORTED_CARD_BRANDS = [\n 'visa',\n 'mastercard',\n 'mastercard_debit',\n 'amex',\n 'discover',\n] as const;\n\n// ---------------------------------------------------------------------------\n// Currency Mapping (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Country code to currency information mapping. */\nexport const CURRENCY_MAP: Record<string, CurrencyInfo> = {\n // EUR (VAT applies)\n AT: { currency: 'EUR', symbol: '\\u20AC', country: 'Austria', countryCode: 'AT', tax: 1 },\n BE: { currency: 'EUR', symbol: '\\u20AC', country: 'Belgium', countryCode: 'BE', tax: 1 },\n CY: { currency: 'EUR', symbol: '\\u20AC', country: 'Cyprus', countryCode: 'CY', tax: 1 },\n DE: { currency: 'EUR', symbol: '\\u20AC', country: 'Germany', countryCode: 'DE', tax: 1 },\n EE: { currency: 'EUR', symbol: '\\u20AC', country: 'Estonia', countryCode: 'EE', tax: 1 },\n ES: { currency: 'EUR', symbol: '\\u20AC', country: 'Spain', countryCode: 'ES', tax: 1 },\n FI: { currency: 'EUR', symbol: '\\u20AC', country: 'Finland', countryCode: 'FI', tax: 1 },\n FR: { currency: 'EUR', symbol: '\\u20AC', country: 'France', countryCode: 'FR', tax: 1 },\n GR: { currency: 'EUR', symbol: '\\u20AC', country: 'Greece', countryCode: 'GR', tax: 1 },\n HR: { currency: 'EUR', symbol: '\\u20AC', country: 'Croatia', countryCode: 'HR', tax: 1 },\n IE: { currency: 'EUR', symbol: '\\u20AC', country: 'Ireland', countryCode: 'IE', tax: 1 },\n IT: { currency: 'EUR', symbol: '\\u20AC', country: 'Italy', countryCode: 'IT', tax: 1 },\n LT: { currency: 'EUR', symbol: '\\u20AC', country: 'Lithuania', countryCode: 'LT', tax: 1 },\n LU: { currency: 'EUR', symbol: '\\u20AC', country: 'Luxembourg', countryCode: 'LU', tax: 1 },\n LV: { currency: 'EUR', symbol: '\\u20AC', country: 'Latvia', countryCode: 'LV', tax: 1 },\n MT: { currency: 'EUR', symbol: '\\u20AC', country: 'Malta', countryCode: 'MT', tax: 1 },\n NL: { currency: 'EUR', symbol: '\\u20AC', country: 'Netherlands', countryCode: 'NL', tax: 1 },\n PT: { currency: 'EUR', symbol: '\\u20AC', country: 'Portugal', countryCode: 'PT', tax: 1 },\n SI: { currency: 'EUR', symbol: '\\u20AC', country: 'Slovenia', countryCode: 'SI', tax: 1 },\n SK: { currency: 'EUR', symbol: '\\u20AC', country: 'Slovakia', countryCode: 'SK', tax: 1 },\n BG: { currency: 'EUR', symbol: '\\u20AC', country: 'Bulgaria', countryCode: 'BG', tax: 1 },\n RO: { currency: 'EUR', symbol: '\\u20AC', country: 'Romania', countryCode: 'RO', tax: 1 },\n CZ: { currency: 'EUR', symbol: '\\u20AC', country: 'Czech Republic', countryCode: 'CZ', tax: 1 },\n SE: { currency: 'EUR', symbol: '\\u20AC', country: 'Sweden', countryCode: 'SE', tax: 1 },\n DK: { currency: 'EUR', symbol: '\\u20AC', country: 'Denmark', countryCode: 'DK', tax: 1 },\n PL: { currency: 'EUR', symbol: '\\u20AC', country: 'Poland', countryCode: 'PL', tax: 1 },\n HU: { currency: 'EUR', symbol: '\\u20AC', country: 'Hungary', countryCode: 'HU', tax: 1 },\n // GBP (VAT applies)\n GB: { currency: 'GBP', symbol: '\\u00A3', country: 'United Kingdom', countryCode: 'GB', tax: 1 },\n // USD (no VAT)\n US: { currency: 'USD', symbol: '$', country: 'United States', countryCode: 'US', tax: 0 },\n // CAD (no VAT)\n CA: { currency: 'CAD', symbol: 'CA$', country: 'Canada', countryCode: 'CA', tax: 0 },\n // NZD (no VAT)\n NZ: { currency: 'NZD', symbol: 'NZ$', country: 'New Zealand', countryCode: 'NZ', tax: 0 },\n // AUD (no VAT)\n AU: { currency: 'AUD', symbol: 'AU$', country: 'Australia', countryCode: 'AU', tax: 0 },\n};\n\n/** Default currency info when country is unknown. */\nexport const DEFAULT_CURRENCY: CurrencyInfo = {\n currency: 'USD',\n symbol: '$',\n country: 'United States',\n countryCode: 'US',\n tax: 0,\n};\n\n// ---------------------------------------------------------------------------\n// Postal Code Labels\n// ---------------------------------------------------------------------------\n\n/** Returns the correct postal code label for a country code (ISO 3166-1 alpha-2). */\nexport function getPostalCodeLabel(countryCode: string): string {\n switch (countryCode.toUpperCase()) {\n case 'US': return 'ZIP Code';\n case 'GB': return 'Postcode';\n case 'CA': return 'Postal Code';\n case 'AU':\n case 'NZ': return 'Postcode';\n case 'IE': return 'Eircode';\n default: return 'Postal Code';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Country List (ISO 3166-1 alpha-2)\n// ---------------------------------------------------------------------------\n\nconst regionNames = new Intl.DisplayNames(['en'], { type: 'region' });\n\nfunction codeToFlag(code: string): string {\n return [...code.toUpperCase()]\n .map((c) => String.fromCodePoint(0x1f1e6 - 65 + c.charCodeAt(0)))\n .join('');\n}\n\n/** Priority countries shown first in dropdowns. */\nconst PRIORITY_CODES = ['US', 'GB', 'CA', 'AU', 'NZ', 'IE', 'DE', 'FR'];\n\nconst ALL_CODES = [\n 'AD', 'AE', 'AF', 'AG', 'AL', 'AM', 'AO', 'AR', 'AT', 'AU',\n 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ',\n 'BN', 'BO', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CD',\n 'CF', 'CG', 'CH', 'CI', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU',\n 'CV', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC',\n 'EE', 'EG', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FM', 'FR', 'GA',\n 'GB', 'GD', 'GE', 'GH', 'GM', 'GN', 'GQ', 'GR', 'GT', 'GW',\n 'GY', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IQ',\n 'IR', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI',\n 'KM', 'KN', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK',\n 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME',\n 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MR', 'MT', 'MU', 'MV',\n 'MW', 'MX', 'MY', 'MZ', 'NA', 'NE', 'NG', 'NI', 'NL', 'NO',\n 'NP', 'NR', 'NZ', 'OM', 'PA', 'PE', 'PG', 'PH', 'PK', 'PL',\n 'PT', 'PW', 'PY', 'QA', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB',\n 'SC', 'SD', 'SE', 'SG', 'SI', 'SK', 'SL', 'SM', 'SN', 'SO',\n 'SR', 'SS', 'ST', 'SV', 'SY', 'SZ', 'TD', 'TG', 'TH', 'TJ',\n 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA',\n 'UG', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VN', 'VU', 'WS',\n 'XK', 'YE', 'ZA', 'ZM', 'ZW',\n] as const;\n\nfunction buildCountryOption(code: string): CountryOption {\n return { code, name: regionNames.of(code) ?? code, flag: codeToFlag(code) };\n}\n\nconst prioritySet = new Set(PRIORITY_CODES);\nconst rest = ALL_CODES.filter((c) => !prioritySet.has(c));\n\n/** All countries for dropdown select, priority countries first. */\nexport const COUNTRY_OPTIONS: CountryOption[] = [\n ...PRIORITY_CODES.map(buildCountryOption),\n ...rest.map(buildCountryOption),\n];\n\n/** Look up a country option by ISO 3166-1 alpha-2 code. */\nexport function getCountryByCode(code: string): CountryOption | undefined {\n return COUNTRY_OPTIONS.find((c) => c.code === code);\n}\n\n// ---------------------------------------------------------------------------\n// AVS Configuration Helpers\n// ---------------------------------------------------------------------------\n\n/** Default AVS config when `enableAVS: true` (backward compatible — country + postal code). */\nconst DEFAULT_AVS_CONFIG: AVSFieldConfig = {\n country: true,\n postal_code: true,\n};\n\n/**\n * Normalize `enableAVS` to a resolved config object.\n * - `false` / `undefined` → `null` (AVS disabled)\n * - `true` → default config (country + postal_code)\n * - `AVSFieldConfig` → returned as-is\n */\nexport function resolveAVSConfig(enableAVS?: boolean | AVSFieldConfig): AVSFieldConfig | null {\n if (!enableAVS) return null;\n if (enableAVS === true) return DEFAULT_AVS_CONFIG;\n return enableAVS;\n}\n\n/**\n * Check if an AVS field should be visible for the given country.\n * - `undefined` / `false` → hidden\n * - `true` → visible for all countries\n * - `string[]` (non-empty) → visible only for listed country codes\n * - `[]` (empty) → visible for no countries; use `true` to show everywhere.\n * A UI that wants \"clear the country list = show everywhere\" must normalize\n * the cleared list to `true` before persisting — preserves the historical\n * `[]` = \"off\" semantics so existing configs don't start rendering AVS\n * globally.\n */\nexport function isAVSFieldVisible(\n field: boolean | string[] | undefined,\n country: string,\n): boolean {\n if (field === undefined || field === false) return false;\n if (field === true) return true;\n const normalizedCountry = country.trim().toUpperCase();\n return field.some((code) => code.trim().toUpperCase() === normalizedCountry);\n}\n\n/** Returns true if any AVS field is meaningfully configured (at least one field is truthy). */\nexport function isAVSEnabled(enableAVS?: boolean | AVSFieldConfig): boolean {\n const config = resolveAVSConfig(enableAVS);\n if (!config) return false;\n // `true` or a non-empty array means the field is configured to render;\n // only `false`/`undefined`/`[]` is \"off\".\n return Object.values(config).some(\n (v) => v === true || (Array.isArray(v) && v.length > 0),\n );\n}\n\n// ---------------------------------------------------------------------------\n// US States & CA Provinces\n// ---------------------------------------------------------------------------\n\nexport interface StateOption {\n code: string;\n name: string;\n}\n\nexport const US_STATES: StateOption[] = [\n { code: 'AL', name: 'Alabama' },\n { code: 'AK', name: 'Alaska' },\n { code: 'AZ', name: 'Arizona' },\n { code: 'AR', name: 'Arkansas' },\n { code: 'CA', name: 'California' },\n { code: 'CO', name: 'Colorado' },\n { code: 'CT', name: 'Connecticut' },\n { code: 'DE', name: 'Delaware' },\n { code: 'DC', name: 'District of Columbia' },\n { code: 'FL', name: 'Florida' },\n { code: 'GA', name: 'Georgia' },\n { code: 'HI', name: 'Hawaii' },\n { code: 'ID', name: 'Idaho' },\n { code: 'IL', name: 'Illinois' },\n { code: 'IN', name: 'Indiana' },\n { code: 'IA', name: 'Iowa' },\n { code: 'KS', name: 'Kansas' },\n { code: 'KY', name: 'Kentucky' },\n { code: 'LA', name: 'Louisiana' },\n { code: 'ME', name: 'Maine' },\n { code: 'MD', name: 'Maryland' },\n { code: 'MA', name: 'Massachusetts' },\n { code: 'MI', name: 'Michigan' },\n { code: 'MN', name: 'Minnesota' },\n { code: 'MS', name: 'Mississippi' },\n { code: 'MO', name: 'Missouri' },\n { code: 'MT', name: 'Montana' },\n { code: 'NE', name: 'Nebraska' },\n { code: 'NV', name: 'Nevada' },\n { code: 'NH', name: 'New Hampshire' },\n { code: 'NJ', name: 'New Jersey' },\n { code: 'NM', name: 'New Mexico' },\n { code: 'NY', name: 'New York' },\n { code: 'NC', name: 'North Carolina' },\n { code: 'ND', name: 'North Dakota' },\n { code: 'OH', name: 'Ohio' },\n { code: 'OK', name: 'Oklahoma' },\n { code: 'OR', name: 'Oregon' },\n { code: 'PA', name: 'Pennsylvania' },\n { code: 'RI', name: 'Rhode Island' },\n { code: 'SC', name: 'South Carolina' },\n { code: 'SD', name: 'South Dakota' },\n { code: 'TN', name: 'Tennessee' },\n { code: 'TX', name: 'Texas' },\n { code: 'UT', name: 'Utah' },\n { code: 'VT', name: 'Vermont' },\n { code: 'VA', name: 'Virginia' },\n { code: 'WA', name: 'Washington' },\n { code: 'WV', name: 'West Virginia' },\n { code: 'WI', name: 'Wisconsin' },\n { code: 'WY', name: 'Wyoming' },\n];\n\nexport const CA_PROVINCES: StateOption[] = [\n { code: 'AB', name: 'Alberta' },\n { code: 'BC', name: 'British Columbia' },\n { code: 'MB', name: 'Manitoba' },\n { code: 'NB', name: 'New Brunswick' },\n { code: 'NL', name: 'Newfoundland and Labrador' },\n { code: 'NS', name: 'Nova Scotia' },\n { code: 'NT', name: 'Northwest Territories' },\n { code: 'NU', name: 'Nunavut' },\n { code: 'ON', name: 'Ontario' },\n { code: 'PE', name: 'Prince Edward Island' },\n { code: 'QC', name: 'Quebec' },\n { code: 'SK', name: 'Saskatchewan' },\n { code: 'YT', name: 'Yukon' },\n];\n\n/**\n * Get state/province options for a country.\n * Returns a list for US and CA, or `null` for countries where a free-text input is appropriate.\n */\nexport function getStateOptions(country: string): StateOption[] | null {\n switch (country.toUpperCase()) {\n case 'US': return US_STATES;\n case 'CA': return CA_PROVINCES;\n default: return null;\n }\n}\n\n/** Returns the appropriate label for the state/province field based on country. */\nexport function getStateLabel(countryCode: string): string {\n switch (countryCode.toUpperCase()) {\n case 'US': return 'State';\n case 'CA': return 'Province';\n case 'GB': return 'County';\n case 'AU': return 'State / Territory';\n default: return 'State / Province / Region';\n }\n}\n","/**\n * Postal-code → state derivation for AVS.\n *\n * Used when the form configuration shows `address_line_1` but hides the\n * `state` input — we still want to populate `billing_details.address.state`\n * so Stripe Radar gets a richer address signal. Currently supports US and CA;\n * other countries return `null` (caller should fall back to omitting state).\n */\n\n/**\n * US 3-digit ZIP-prefix ranges → state code (USPS Sectional Center Facility).\n * Sourced from the public USPS SCF table. Each entry is `[startPrefix, endPrefix, stateCode]`,\n * inclusive on both ends. Coverage is contiguous within a state; gaps in the table\n * (e.g. unused 3-digit prefixes) are intentional and resolve to `null`.\n */\nconst US_ZIP_PREFIX_RANGES: ReadonlyArray<readonly [number, number, string]> = [\n [5, 5, 'NY'],\n [10, 27, 'MA'],\n [28, 29, 'RI'],\n [30, 38, 'NH'],\n [39, 49, 'ME'],\n [50, 59, 'VT'],\n [60, 69, 'CT'],\n [70, 89, 'NJ'],\n [100, 149, 'NY'],\n [150, 196, 'PA'],\n [197, 199, 'DE'],\n [200, 205, 'DC'],\n [206, 219, 'MD'],\n [220, 246, 'VA'],\n [247, 268, 'WV'],\n [270, 289, 'NC'],\n [290, 299, 'SC'],\n [300, 319, 'GA'],\n [320, 349, 'FL'],\n [350, 369, 'AL'],\n [370, 385, 'TN'],\n [386, 397, 'MS'],\n [398, 399, 'GA'],\n [400, 427, 'KY'],\n [430, 459, 'OH'],\n [460, 479, 'IN'],\n [480, 499, 'MI'],\n [500, 528, 'IA'],\n [530, 549, 'WI'],\n [550, 567, 'MN'],\n [570, 577, 'SD'],\n [580, 588, 'ND'],\n [590, 599, 'MT'],\n [600, 629, 'IL'],\n [630, 658, 'MO'],\n [660, 679, 'KS'],\n [680, 693, 'NE'],\n [700, 714, 'LA'],\n [716, 729, 'AR'],\n [730, 749, 'OK'],\n [750, 799, 'TX'],\n [800, 816, 'CO'],\n [820, 831, 'WY'],\n [832, 838, 'ID'],\n [840, 847, 'UT'],\n [850, 865, 'AZ'],\n [870, 884, 'NM'],\n [889, 898, 'NV'],\n [900, 961, 'CA'],\n [967, 968, 'HI'],\n [970, 979, 'OR'],\n [980, 994, 'WA'],\n [995, 999, 'AK'],\n];\n\n/**\n * CA postal-code first letter → province code (Forward Sortation Area).\n * The first letter of every Canadian postal code identifies the province\n * uniquely, except `X` which is shared by Northwest Territories and Nunavut\n * — we resolve it to `NT` because the volume strongly favours NT.\n */\nconst CA_FSA_FIRST_LETTER_TO_PROVINCE: Readonly<Record<string, string>> = {\n A: 'NL',\n B: 'NS',\n C: 'PE',\n E: 'NB',\n G: 'QC',\n H: 'QC',\n J: 'QC',\n K: 'ON',\n L: 'ON',\n M: 'ON',\n N: 'ON',\n P: 'ON',\n R: 'MB',\n S: 'SK',\n T: 'AB',\n V: 'BC',\n X: 'NT',\n Y: 'YT',\n};\n\nfunction deriveUsState(zip: string): string | null {\n const digits = zip.replace(/\\D/g, '');\n if (digits.length < 5) return null;\n const prefix = Number.parseInt(digits.slice(0, 3), 10);\n if (!Number.isFinite(prefix)) return null;\n\n for (const [start, end, code] of US_ZIP_PREFIX_RANGES) {\n if (prefix >= start && prefix <= end) return code;\n }\n return null;\n}\n\nfunction deriveCaProvince(postalCode: string): string | null {\n const compact = postalCode.replace(/\\s+/g, '').toUpperCase();\n if (!/^[A-Z]\\d[A-Z]\\d[A-Z]\\d$/.test(compact)) return null;\n const firstLetter = compact[0] ?? '';\n return CA_FSA_FIRST_LETTER_TO_PROVINCE[firstLetter] ?? null;\n}\n\n/**\n * Resolve a state / province code from a postal code for the given country.\n *\n * - US: 5-digit ZIP → 2-letter USPS state code (uses 3-digit prefix table).\n * - CA: A1A 1A1 → 2-letter ISO 3166-2:CA province code (first-letter mapping).\n * - All other countries: `null`.\n *\n * Returns `null` when the postal code is malformed or falls in an unmapped\n * range. Callers should treat `null` as \"skip — don't derive\".\n */\nexport function getStateFromPostalCode(\n country: string,\n postalCode: string,\n): string | null {\n if (!country || !postalCode) return null;\n const normalizedCountry = country.trim().toUpperCase();\n const normalizedZip = postalCode.trim();\n if (!normalizedZip) return null;\n\n switch (normalizedCountry) {\n case 'US':\n return deriveUsState(normalizedZip);\n case 'CA':\n return deriveCaProvince(normalizedZip);\n default:\n return null;\n }\n}\n","/**\n * Client-side postcode format validation for AVS.\n *\n * A faithful mirror of the backend's authoritative, country-aware postcode\n * check — `is-valid-postal-code.validator.ts` (TeamFloPay/backend#895, pinned\n * `validator@13.15.35`). The SDK reuses the *same* `validator` package's\n * `isPostalCode(str, locale)`, the *same* country→ISO-2 normalization\n * (`COUNTRY_ALIASES` + the 2-letter passthrough), and the *same* fail-open\n * conditions, so the SDK's submit gate never opens on a postcode the deployed\n * `PATCH /v1/checkouts/sessions/{id}/account` validator will reject with a 400\n * (the client/server rule drift behind sdk#124). The set of locales `validator`\n * recognises is the single source of truth:\n *\n * - Supported locale → the postcode is required *and* format-validated; an\n * empty or malformed value blocks submit.\n * - Unsupported / no-postcode locale → validation is skipped (fail open); the\n * field is visible but optional and never blocks.\n *\n * We import the `validator/lib/isPostalCode.js` submodule (not the `validator`\n * barrel) so a consumer's bundler only pulls this one check into the browser\n * bundle instead of the whole `validator` library. The explicit `.js` extension\n * is required: `validator` ships no `exports` map, so Node's native ESM loader\n * only resolves the fully-specified file path.\n */\nimport * as isPostalCodeModule from 'validator/lib/isPostalCode.js';\n\ntype IsPostalCodeFn = (str: string, locale: string) => boolean;\n\n/**\n * The CJS submodule's runtime shape is `{ default: fn, locales: string[] }`.\n * `@types/validator` only declares `default`, and ESM↔CJS interop leaves the\n * namespace's `default` as either the whole `module.exports` object (Node\n * native ESM) or the function itself (esbuild/CJS output). `locales` is a plain\n * named export and is the array in both. Read through a cast and unwrap\n * `default` so the two build outputs behave identically.\n */\nconst mod = isPostalCodeModule as unknown as {\n default: IsPostalCodeFn | { default: IsPostalCodeFn };\n locales: string[];\n};\n\nconst isPostalCode: IsPostalCodeFn =\n typeof mod.default === 'function' ? mod.default : mod.default?.default;\n\n// Fail fast, and loudly, if a third bundler/runtime interop shape slips past the\n// two we anticipate above. Without this, `isPostalCode` would silently be\n// `undefined` at module load and every supported-country check would throw a\n// cryptic `TypeError: isPostalCode is not a function` at submit time instead.\nif (typeof isPostalCode !== 'function') {\n throw new Error(\n \"validator/lib/isPostalCode.js interop failed: unexpected module shape. This likely means the bundler's CJS/ESM interop changed.\",\n );\n}\n\n/** `validator`'s supported ISO 3166-1 alpha-2 postcode locales, normalised to uppercase. */\nconst SUPPORTED_LOCALES: ReadonlySet<string> = new Set(\n mod.locales.map((code) => code.toUpperCase()),\n);\n\n/**\n * Country → ISO 3166-1 alpha-2 aliases, replicated **verbatim** from the backend\n * validator's `COUNTRY_ALIASES` (backend#895) so client and server normalize\n * identically. The SDK's own `COUNTRY_OPTIONS` are already ISO-2, so in practice\n * only the passthrough branch fires here; the full-name / 3-letter aliases exist\n * purely for parity when a caller (or a future field) hands us a non-ISO-2 value.\n *\n * Note the deliberate 2-letter short-circuit in {@link normalizeCountryToIso2}:\n * a 2-letter input is passed straight through *before* this map is consulted, so\n * the 2-letter keys below (`GB`, `US`, `UK`, `CH`, `DE`) are unreachable — they\n * are kept only to mirror the backend map 1:1. This means `UK` normalizes to\n * `UK` (an unsupported `validator` locale → fail open), exactly as the backend\n * does; only the full name `UNITED KINGDOM` / `GREATBRITAIN` maps to `GB`.\n */\nconst COUNTRY_ALIASES: Readonly<Record<string, string>> = {\n AUSTRALIA: 'AU',\n BRAZIL: 'BR',\n CANADA: 'CA',\n CH: 'CH',\n DENMARK: 'DK',\n DE: 'DE',\n DEUTSCHLAND: 'DE',\n FRANCE: 'FR',\n GB: 'GB',\n GERMANY: 'DE',\n GREATBRITAIN: 'GB',\n GREAT_BRITAIN: 'GB',\n INDIA: 'IN',\n IRELAND: 'IE',\n ITALY: 'IT',\n JAPAN: 'JP',\n MEXICO: 'MX',\n NETHERLANDS: 'NL',\n NEWZEALAND: 'NZ',\n NORWAY: 'NO',\n POLAND: 'PL',\n PORTUGAL: 'PT',\n SINGAPORE: 'SG',\n SOUTHAFRICA: 'ZA',\n SPAIN: 'ES',\n SWEDEN: 'SE',\n SWITZERLAND: 'CH',\n UK: 'GB',\n UNITEDKINGDOM: 'GB',\n UNITEDSTATES: 'US',\n US: 'US',\n USA: 'US',\n 'UNITED STATES': 'US',\n 'UNITED KINGDOM': 'GB',\n 'GREAT BRITAIN': 'GB',\n ENGLAND: 'GB',\n};\n\n/**\n * Normalize a country string to an ISO 3166-1 alpha-2 locale, or `null` when it\n * can't be resolved. Mirrors the backend's `normalizeCountryToIso2`:\n * 1. trim + uppercase; blank → `null` (fail open upstream);\n * 2. any 2-letter input is passed straight through (NOT alias-mapped);\n * 3. otherwise look it up in {@link COUNTRY_ALIASES}; unknown → `null`.\n */\nfunction normalizeCountryToIso2(country: string): string | null {\n // Nullish-safe: JS callers (and untyped consumers) may pass null/undefined;\n // treat those as an unresolvable country and fail open rather than throwing.\n const upper = (country ?? '').trim().toUpperCase();\n if (!upper) return null;\n if (upper.length === 2) return upper;\n return COUNTRY_ALIASES[upper] ?? null;\n}\n\n/**\n * ISO 3166-1 alpha-2 → example postcode map, surfaced in the field hint / inline\n * error so the buyer sees the expected shape. Replicated **verbatim** from the\n * backend validator's `POSTAL_CODE_EXAMPLES` (backend#895) so the SDK's own\n * client-side hint shows the *same* example the backend embeds in its 400\n * message (\"Expected format: e.g. {example}\") — the two can never contradict.\n * Every example is verified against `validator`'s own pattern (see the package\n * tests). A supported country absent from this map still validates — the hint,\n * like the backend message, simply omits the example.\n *\n * Exported (module-level, not via the package barrel) so the drift-guard test\n * can derive its country list from this single source of truth instead of\n * hardcoding a subset that silently falls out of sync as entries are added.\n */\nexport const POSTAL_CODE_EXAMPLES: Readonly<Record<string, string>> = {\n AU: '2000',\n BR: '01000-000',\n CA: 'A1A 1A1',\n CH: '8001',\n DE: '10115',\n DK: '1050',\n ES: '28001',\n FR: '75008',\n GB: 'SW1A 1AA',\n IE: 'D02 X285',\n IN: '110001',\n IT: '00118',\n JP: '100-0001',\n MX: '06500',\n NL: '1012 JS',\n NO: '0150',\n NZ: '6011',\n PL: '00-001',\n PT: '1100-148',\n SE: '111 22',\n SG: '018989',\n US: '12345 or 12345-6789',\n ZA: '8001',\n};\n\n/**\n * True when `validator` has an authoritative postcode pattern for the country\n * (normalized to ISO 3166-1 alpha-2 via {@link normalizeCountryToIso2}).\n * Supported countries validate the postcode format; unsupported / no-postcode /\n * unresolvable countries fail open. Note the 2-letter passthrough means `UK`\n * (an unsupported `validator` locale) returns `false` here — matching the\n * backend; use the full name `United Kingdom` for `GB` semantics.\n */\nexport function isPostalCodeSupported(country: string): boolean {\n const iso2 = normalizeCountryToIso2(country);\n return iso2 !== null && SUPPORTED_LOCALES.has(iso2);\n}\n\n/**\n * Validate a postcode against the country's expected format. A faithful mirror\n * of the backend's `isPostalCodeValidForCountry`, so the SDK never blocks a\n * value the server would accept, nor opens the submit gate on one it would\n * reject. Fail-open (returns `true`) in exactly the backend's three cases:\n *\n * - `postalCode` is blank / whitespace-only;\n * - the country can't be normalized to an ISO-2 locale;\n * - the ISO-2 locale isn't one `validator` recognises.\n *\n * Otherwise returns `validator`'s `isPostalCode(zip.trim(), locale)`. Callers\n * that distinguish \"required\" (empty) from \"malformed\" (bad format) must check\n * emptiness themselves — an empty value fails open here, as it does server-side.\n */\nexport function isValidPostalCode(country: string, postalCode: string): boolean {\n // Nullish-safe: a null/undefined postcode fails open (same as blank).\n const trimmed = (postalCode ?? '').trim();\n if (!trimmed) return true;\n const iso2 = normalizeCountryToIso2(country);\n if (iso2 === null || !SUPPORTED_LOCALES.has(iso2)) return true;\n try {\n return isPostalCode(trimmed, iso2);\n } catch {\n return true;\n }\n}\n\n/**\n * The example postcode the backend would embed in its 400 message for the\n * country (e.g. US `12345 or 12345-6789`, GB `SW1A 1AA`, CA `A1A 1A1`), or\n * `undefined` when there is none (unresolvable country, or a supported country\n * absent from {@link POSTAL_CODE_EXAMPLES}).\n */\nexport function getPostalCodeExample(country: string): string | undefined {\n const iso2 = normalizeCountryToIso2(country);\n return iso2 ? POSTAL_CODE_EXAMPLES[iso2] : undefined;\n}\n","import type {\n CheckoutItem,\n CheckoutProduct,\n CheckoutSubscription,\n} from './types.js';\n\n/**\n * Return the trimmed string when it has at least one non-whitespace character,\n * otherwise undefined. Used so that empty and whitespace-only inputs flow\n * through the same fallback chain as `undefined`.\n */\nfunction nonBlank(value: string | null | undefined): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\n/**\n * Resolve the session-level currency, honoring the documented fallback:\n * `session.currency ?? items[*].currency ?? subscriptions[*].currency ?? products[*].currency`.\n *\n * Returns the first non-blank currency found, or `null` when nothing is set.\n * Empty and whitespace-only strings are treated as unset so they do not\n * bypass the fallback chain.\n *\n * Post-#760 backends reject session-create requests without a session-level\n * currency (`@IsNotEmpty`); callers should throw a validation error when\n * this returns `null` rather than silently defaulting.\n */\nexport function resolveSessionCurrency(\n sessionCurrency: string | undefined,\n items?: ReadonlyArray<{ currency?: string }> | undefined,\n subscriptions?: ReadonlyArray<{ currency?: string }> | undefined,\n products?: ReadonlyArray<{ currency?: string }> | undefined,\n): string | null {\n const session = nonBlank(sessionCurrency);\n if (session) return session;\n for (const item of items ?? []) {\n const c = nonBlank(item.currency);\n if (c) return c;\n }\n for (const sub of subscriptions ?? []) {\n const c = nonBlank(sub.currency);\n if (c) return c;\n }\n for (const product of products ?? []) {\n const c = nonBlank(product.currency);\n if (c) return c;\n }\n return null;\n}\n\n/**\n * Fold legacy `items` + `subscriptions` arrays into the unified `products[]`\n * shape introduced by backend #760. Items become `type: 'item'`,\n * subscriptions become `type: 'subscription'`. The relative order is\n * subscriptions-first then items, matching the order the previous payload\n * builders emitted on the wire.\n */\nexport function foldIntoProducts(\n items: readonly CheckoutItem[] | undefined,\n subscriptions: readonly CheckoutSubscription[] | undefined,\n): CheckoutProduct[] {\n const products: CheckoutProduct[] = [];\n\n for (const sub of subscriptions ?? []) {\n products.push({\n type: 'subscription',\n code: nonBlank(sub.code) ?? nonBlank(sub.providerPlanId),\n providerPlanId: sub.providerPlanId,\n name: nonBlank(sub.subscriptionName) ?? nonBlank(sub.providerPlanName) ?? null,\n subscriptionName: sub.subscriptionName ?? null,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount,\n currency: sub.currency,\n metadata: sub.metadata,\n });\n }\n\n for (const item of items ?? []) {\n products.push({\n type: 'item',\n code: nonBlank(item.code) ?? nonBlank(item.providerItemId),\n providerItemId: item.providerItemId,\n name: nonBlank(item.itemName) ?? nonBlank(item.providerItemName) ?? null,\n itemName: item.itemName ?? null,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount,\n currency: item.currency,\n metadata: item.metadata,\n });\n }\n\n return products;\n}\n\n/**\n * Build the request payload for a single product in the unified shape\n * introduced by backend #760. Emits `type`, `code`, `name`, `quantity`,\n * `totalAmount`, `overrideAmount`, `currency`, and optional `metadata`.\n */\nexport function buildProductPayload(\n product: CheckoutProduct,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code =\n nonBlank(product.code)\n ?? nonBlank(product.providerItemId)\n ?? nonBlank(product.providerPlanId);\n if (!code) {\n throw new Error(\n 'CheckoutProduct requires `code` (or the deprecated `providerItemId` / `providerPlanId`).',\n );\n }\n\n const name =\n nonBlank(product.name)\n ?? nonBlank(product.itemName)\n ?? nonBlank(product.providerItemName)\n ?? nonBlank(product.subscriptionName)\n ?? nonBlank(product.providerPlanName)\n ?? null;\n\n const payload: Record<string, unknown> = {\n type: product.type,\n code,\n name,\n quantity: product.quantity ?? 1,\n totalAmount: product.totalAmount,\n overrideAmount: product.overrideAmount ?? null,\n currency: nonBlank(product.currency) ?? sessionCurrency,\n };\n\n if (product.metadata) {\n payload['metadata'] = product.metadata;\n }\n\n return payload;\n}\n\n/**\n * Build the request payload for a single item.\n *\n * @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.\n * Retained until the next major so external callers building the legacy\n * `items[]` payload manually keep working.\n */\nexport function buildItemPayload(\n item: CheckoutItem,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code = nonBlank(item.code) ?? nonBlank(item.providerItemId);\n if (!code) {\n throw new Error('CheckoutItem requires either `code` or the deprecated `providerItemId`.');\n }\n const itemName = nonBlank(item.itemName) ?? nonBlank(item.providerItemName) ?? null;\n\n const payload: Record<string, unknown> = {\n code,\n providerItemId: nonBlank(item.providerItemId) ?? code,\n itemName,\n providerItemName: nonBlank(item.providerItemName) ?? itemName,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: nonBlank(item.currency) ?? sessionCurrency,\n };\n\n if (item.metadata) {\n payload['metadata'] = item.metadata;\n }\n\n return payload;\n}\n\n/**\n * Build the request payload for a single subscription.\n *\n * @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.\n * Retained until the next major so external callers building the legacy\n * `subscriptions[]` payload manually keep working.\n */\nexport function buildSubscriptionPayload(\n subscription: CheckoutSubscription,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code = nonBlank(subscription.code) ?? nonBlank(subscription.providerPlanId);\n if (!code) {\n throw new Error(\n 'CheckoutSubscription requires either `code` or the deprecated `providerPlanId`.',\n );\n }\n const subscriptionName =\n nonBlank(subscription.subscriptionName) ?? nonBlank(subscription.providerPlanName) ?? null;\n\n const payload: Record<string, unknown> = {\n code,\n providerPlanId: nonBlank(subscription.providerPlanId) ?? code,\n subscriptionName,\n providerPlanName: nonBlank(subscription.providerPlanName) ?? subscriptionName,\n quantity: subscription.quantity ?? 1,\n totalAmount: subscription.totalAmount,\n overrideAmount: subscription.overrideAmount ?? null,\n currency: nonBlank(subscription.currency) ?? sessionCurrency,\n };\n\n if (subscription.metadata) {\n payload['metadata'] = subscription.metadata;\n }\n\n return payload;\n}\n","import { resolveSessionCurrency } from './checkout-payload.js';\nimport type { CheckoutSession } from './types.js';\n\n/** A single line item formatted for display in the checkout UI. */\nexport interface DisplayLineItem {\n name: string;\n quantity: number;\n /** Price per unit in the session's currency (major units, e.g. 24.95). */\n price: number;\n /** Original price per unit before any discount (major units). */\n originalPrice: number;\n}\n\n/** Computed display data for rendering an order summary. */\nexport interface CheckoutDisplayData {\n /** Individual items/subscriptions with names, prices, and quantities. */\n items: DisplayLineItem[];\n /** ISO 4217 currency code (uppercase). */\n currency: string;\n /** Total amount due after discounts (major units, e.g. 24.95). */\n total: number;\n /** Sum of original prices before discounts (major units). */\n originalTotal: number;\n /** Total savings (originalTotal - total), clamped to >= 0. */\n totalSave: number;\n /** Discount percentage (0–100). */\n discountPercent: number;\n /**\n * Coupon discount reported by the backend (cart-currency major units),\n * when available. Populated from `session.discountAmount` (billing\n * API ≥ v1.1.2); `undefined` on older backends. Use this to render an\n * explicit \"coupon\" line without recomputing per-item math.\n */\n couponDiscount?: number;\n}\n\n/** Options for {@link buildCheckoutDisplayData}. */\nexport interface BuildCheckoutDisplayDataOptions {\n /**\n * When `true`, items are hidden from the order summary if the session also\n * contains subscriptions (matches the legacy checkout/CheckoutModal\n * behavior). Defaults to `false` — items are always shown.\n */\n hideBundledItems?: boolean;\n}\n\n/**\n * Builds display data from a `CheckoutSession` for rendering an order summary.\n *\n * - Subscriptions are always shown\n * - Items are shown by default; pass `{ hideBundledItems: true }` to suppress\n * them when the session also contains subscriptions (legacy behavior)\n * - `overrideAmount` (when not null/undefined) is the discounted price\n * - Plan name \"4-WEEK PLAN\" with price <= 1 is renamed to \"7-DAY TRIAL: FULL ACCESS\"\n * - Discount percentage and savings are computed from the difference\n *\n * All amounts are in **major currency units** (dollars, not cents).\n *\n * @example\n * ```ts\n * import { buildCheckoutDisplayData } from '@flopay/shared';\n *\n * const display = buildCheckoutDisplayData(session);\n * // display.items → [{ name: 'Starter', price: 24.95, originalPrice: 24.95, quantity: 1 }]\n * // display.total → 24.95\n * // display.currency → 'EUR'\n * ```\n */\nexport function buildCheckoutDisplayData(\n session: CheckoutSession,\n options: BuildCheckoutDisplayDataOptions = {},\n): CheckoutDisplayData {\n const itemsList: DisplayLineItem[] = [];\n\n const products = session.products ?? [];\n const subscriptions = products.filter((p) => p.type === 'subscription');\n // `type` is optional; anything not explicitly a subscription renders as an item.\n const items = products.filter((p) => p.type !== 'subscription');\n\n const resolvedCurrency = resolveSessionCurrency(session.currency, undefined, undefined, products);\n const currency = (resolvedCurrency ?? 'USD').toUpperCase();\n\n // Subscriptions first so the legacy \"subscriptions then items\" ordering is\n // preserved for callers rendering the display list.\n for (const sub of subscriptions) {\n const originalPrice = sub.totalAmount ?? 0;\n const discountedPrice = sub.overrideAmount ?? originalPrice;\n\n // Match checkout/CheckoutModal: rename \"4-WEEK PLAN\" to \"7-DAY TRIAL: FULL ACCESS\"\n // when the discounted price is $1 or less\n let name = sub.name || sub.code || 'Subscription';\n if (name === '4-WEEK PLAN' && discountedPrice <= 1) {\n name = '7-DAY TRIAL: FULL ACCESS';\n }\n\n itemsList.push({\n name,\n quantity: sub.quantity,\n price: discountedPrice,\n originalPrice,\n });\n }\n\n const hideItems =\n options.hideBundledItems === true\n && subscriptions.length > 0\n && items.length > 0;\n\n if (!hideItems) {\n for (const item of items) {\n const originalPrice = item.totalAmount ?? 0;\n const discountedPrice = item.overrideAmount ?? originalPrice;\n\n itemsList.push({\n name: item.name || item.code || 'Item',\n quantity: item.quantity,\n price: discountedPrice,\n originalPrice,\n });\n }\n }\n\n if (itemsList.length === 0) {\n itemsList.push({\n name: 'Purchase',\n quantity: 1,\n price: session.amount / 100,\n originalPrice: session.amount / 100,\n });\n }\n\n const lineOriginalTotal = itemsList.reduce((sum, i) => sum + i.originalPrice * i.quantity, 0);\n const lineTotal = itemsList.reduce((sum, i) => sum + i.price * i.quantity, 0);\n\n // Billing API ≥ v1.1.2 returns the coupon-adjusted totals on the session.\n // When present, they are the source of truth for wallet sheets and order\n // summaries (per-line `overrideAmount` carries item-level discounts but is\n // blind to coupons). Older backends omit these fields — fall back to the\n // per-line computation.\n const hasBackendTotals =\n typeof session.totalAmount === 'number'\n && Number.isFinite(session.totalAmount);\n const hasBackendSubtotal =\n typeof session.subtotalAmount === 'number'\n && Number.isFinite(session.subtotalAmount);\n const hasBackendDiscount =\n typeof session.discountAmount === 'number'\n && Number.isFinite(session.discountAmount);\n\n const total = hasBackendTotals ? (session.totalAmount as number) : lineTotal;\n const originalTotal = hasBackendSubtotal\n ? (session.subtotalAmount as number)\n : lineOriginalTotal;\n const totalSave = Math.max(0, originalTotal - total);\n const discountPercent = originalTotal > 0\n ? Math.round((totalSave / originalTotal) * 100)\n : 0;\n\n return {\n items: itemsList,\n currency,\n total,\n originalTotal,\n totalSave,\n discountPercent,\n ...(hasBackendDiscount ? { couponDiscount: session.discountAmount as number } : {}),\n };\n}\n","import type { CurrencyInfo } from './types.js';\nimport { CURRENCY_MAP, DEFAULT_CURRENCY } from './constants.js';\n\n/**\n * Look up currency information by ISO 3166-1 alpha-2 country code.\n * Falls back to USD when the country is not in the map.\n */\nexport function getCurrencyByCountry(countryCode: string): CurrencyInfo {\n return CURRENCY_MAP[countryCode.toUpperCase()] ?? DEFAULT_CURRENCY;\n}\n\n/** Returns `true` if the string looks like a Stripe publishable key. */\nexport function isValidPublishableKey(key: string): boolean {\n return /^pk_(test|live)_[A-Za-z0-9]+$/.test(key);\n}\n\n/** Returns `true` if the string looks like a Stripe secret key. */\nexport function isValidSecretKey(key: string): boolean {\n return /^sk_(test|live)_[A-Za-z0-9]+$/.test(key);\n}\n\n/**\n * Returns `true` when the client secret belongs to a SetupIntent (`seti_…`).\n * Trial-only / $0 checkouts confirm and retrieve a SetupIntent instead of a\n * PaymentIntent, so callers must route those to `confirmCardSetup` /\n * `retrieveSetupIntent` rather than the PaymentIntent equivalents.\n */\nexport function isSetupIntentClientSecret(clientSecret: string | null | undefined): boolean {\n return typeof clientSecret === 'string' && clientSecret.startsWith('seti_');\n}\n","import { FloPayError } from './errors.js';\n\n/**\n * HTTP header the SDK sends to make checkout-session creation idempotent\n * (TeamFloPay/backend#972, paired SDK issue TeamFloPay/sdk#133).\n *\n * The backend treats the header as **optional**: when it is absent the legacy,\n * non-idempotent creation path runs unchanged. When present, every transport\n * retry of the same logical create reuses the same key so a timeout or lost\n * response cannot mint a second checkout session.\n */\nexport const IDEMPOTENCY_KEY_HEADER = 'Idempotency-Key';\n\n/**\n * Maximum length of an idempotency key accepted by the billing API\n * (TeamFloPay/backend#972). Mirrors the widely-used 255-character ceiling;\n * automatically generated keys stay well under it.\n */\nexport const MAX_IDEMPOTENCY_KEY_LENGTH = 255;\n\n/**\n * Backend `code` (TeamFloPay/backend#972) returned when a checkout-create\n * replay arrives while the first request carrying the same key is still being\n * processed. It is a **retryable** in-progress response: the caller should\n * retry with the *same* key after a short backoff, never with a new key. This\n * is distinct from a payload-conflict (`409`), which is non-retryable.\n *\n * Mirrors a backend-defined code the same way the coupon error codes\n * (`CouponLimitExceeded`, `CouponCurrencyUnsupported`) mirror billing v1.1.2.\n */\nexport const IDEMPOTENCY_IN_PROGRESS_CODE = 'IdempotencyKeyInProgress';\n\ninterface RandomSource {\n randomUUID?: () => string;\n getRandomValues?: <T extends ArrayBufferView | null>(array: T) => T;\n}\n\nfunction getSecureRandomSource(): RandomSource | undefined {\n const source = (globalThis as { crypto?: RandomSource }).crypto;\n if (!source) return undefined;\n if (typeof source.randomUUID === 'function' || typeof source.getRandomValues === 'function') {\n return source;\n }\n return undefined;\n}\n\n/**\n * Generate a cryptographically random, high-entropy idempotency key.\n *\n * Prefers `crypto.randomUUID()` and falls back to 16 random bytes from\n * `crypto.getRandomValues`. Returns `undefined` when no cryptographically\n * secure RNG is available so the caller falls back to the legacy unkeyed path\n * rather than emitting a weak or predictable key.\n *\n * The key is never derived from request data, customer identity, or time, so\n * two independent operations never collide by construction.\n */\nexport function generateIdempotencyKey(): string | undefined {\n const source = getSecureRandomSource();\n if (!source) return undefined;\n\n if (typeof source.randomUUID === 'function') {\n return source.randomUUID();\n }\n\n const bytes = new Uint8Array(16);\n source.getRandomValues!(bytes);\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Resolve the idempotency key for one logical checkout-create operation.\n *\n * - A merchant-supplied key is validated (non-empty, within\n * {@link MAX_IDEMPOTENCY_KEY_LENGTH}) and returned **unchanged** so it can be\n * preserved across React remounts, multiple SDK instances, or server retries\n * the merchant controls.\n * - Otherwise a fresh cryptographically random key is generated. When no secure\n * RNG is available this returns `undefined` and the caller omits the header,\n * preserving the legacy path.\n *\n * @throws FloPayError('validation_error') when a supplied key is empty,\n * whitespace-only, or exceeds the length limit. The offending value is never\n * included in the error message.\n */\nexport function resolveIdempotencyKey(supplied?: string): string | undefined {\n if (supplied === undefined) {\n return generateIdempotencyKey();\n }\n\n if (typeof supplied !== 'string' || supplied.trim() === '') {\n throw new FloPayError(\n 'idempotencyKey must be a non-empty string identifying exactly one checkout creation.',\n 'validation_error',\n { code: 'InvalidIdempotencyKey', param: 'idempotencyKey' },\n );\n }\n\n if (supplied.length > MAX_IDEMPOTENCY_KEY_LENGTH) {\n throw new FloPayError(\n `idempotencyKey must be at most ${MAX_IDEMPOTENCY_KEY_LENGTH} characters.`,\n 'validation_error',\n { code: 'InvalidIdempotencyKey', param: 'idempotencyKey' },\n );\n }\n\n return supplied;\n}\n"],"mappings":"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AI,IAAI,IAAI;AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KA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","names":["SDK_VERSION","SDK_VERSION"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/errors.ts","../src/telemetry.ts","../src/config.ts","../src/payment-logos.generated.ts","../src/constants.ts","../src/postal-code-lookup.ts","../src/postal-code-validation.ts","../src/checkout-payload.ts","../src/display.ts","../src/validation.ts","../src/idempotency.ts","../src/uuid.ts"],"sourcesContent":["// Types\nexport type {\n FloPayThemeVariables,\n FloPayAppearance,\n Customer,\n RecurringInterval,\n PriceData,\n LineItem,\n CheckoutMode,\n CheckoutSession,\n CheckoutSessionProduct,\n CheckoutProduct,\n CheckoutProductType,\n PaymentResult,\n ConfirmPaymentParams,\n PayPalPaymentResult,\n NonCardPaymentMethodCategory,\n StripeSessionIntentRequest,\n PayPalSessionIntentRequest,\n CreateSessionIntentRequest,\n StripeSessionIntent,\n PayPalSessionIntent,\n SessionIntent,\n SessionIntentDeclineRequest,\n ElementType,\n ElementChangeEvent,\n ElementOptions,\n MountedElement,\n FloPayConfig,\n PaymentProviderAdapter,\n BillingProvider,\n GatewayEnvironment,\n NormalizedGatewayEnvironment,\n CheckoutGateway,\n CheckoutGateways,\n TokenizedBody,\n CheckoutProcessError,\n CheckoutProcessingPending,\n CheckoutModeKind,\n NormalizedCheckoutSession,\n CheckoutItem,\n CheckoutSubscription,\n CheckoutAccount,\n TagsData,\n CreateSessionParams,\n CheckoutSessionResult,\n ProcessPaymentParams,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n CurrencyInfo,\n CountryOption,\n ButtonsLayoutStyles,\n ButtonsLayoutTheme,\n CardCaptureProviderId,\n VaultCaptureBlock,\n CardCaptureMountOptions,\n VaultCardThemeColors,\n VaultCardFieldKey,\n CardCaptureEventType,\n CardCaptureOutcomeEvent,\n VaultCaptureResultMessage,\n CardCaptureAdapter,\n AVSFieldConfig,\n InlineSessionParams,\n InlineSessionDraft,\n InlineSessionPatch,\n BeforeButtonClickEvent,\n CheckoutButtonMethod,\n DeclineEvent,\n BillingDetails,\n ThemeBundle,\n ThemeBundleId,\n ThemeId,\n} from './types.js';\nexport { normalizeGatewayEnvironment } from './types.js';\n\n// Errors\nexport {\n FloPayError,\n validationError,\n apiError,\n authenticationError,\n rateLimitError,\n networkError,\n} from './errors.js';\nexport type { FloPayErrorType } from './errors.js';\n\n// Privacy-safe SDK telemetry contract\nexport {\n TELEMETRY_SCHEMA_VERSION,\n TELEMETRY_SDK_PACKAGES,\n TELEMETRY_MAX_BATCH_BYTES,\n TELEMETRY_MAX_BATCH_EVENTS,\n TELEMETRY_ERROR_CODES,\n TELEMETRY_LOG_NAMES,\n buildTelemetryErrorEvent,\n buildTelemetryLogEvent,\n buildTelemetryPerformanceEvent,\n buildTelemetryTerminalEvent,\n serializeTelemetryBatch,\n} from './telemetry.js';\nexport type {\n BuildTelemetryErrorEventInput,\n BuildTelemetryLogEventInput,\n BuildTelemetryPerformanceEventInput,\n BuildTelemetryTerminalEventInput,\n SerializeTelemetryBatchOptions,\n TelemetryBatchEnvelope,\n TelemetryCheckoutMode,\n TelemetryDurationMode,\n TelemetryErrorCode,\n TelemetryErrorEvent,\n TelemetryEvent,\n TelemetryEventClass,\n TelemetryExpectedOutcome,\n TelemetryExpectedOutcomeEvent,\n TelemetryLayout,\n TelemetryLogEvent,\n TelemetryLogName,\n TelemetryPaymentMethodCategory,\n TelemetryPerformanceEvent,\n TelemetryProvider,\n TelemetryProviderInput,\n TelemetryRequestCategory,\n TelemetrySdkPackage,\n TelemetryStage,\n TelemetryStatusClass,\n} from './telemetry.js';\n\n// Configuration\nexport { configureFlopay, getConfiguredBillingApiUrl, getFloPayEnvironment } from './config.js';\nexport type { FloPayEnvironment } from './config.js';\n\n// Constants\nexport {\n SDK_VERSION,\n FLO_SDK_VERSION_HEADER,\n DEFAULT_API_BASE_URL,\n DEFAULT_API_VERSION,\n BILLING_API_URL,\n BILLING_API_URL_STAGING,\n BILLING_API_URL_PRODUCTION,\n resolveBillingApiUrl,\n DEFAULT_APPEARANCE,\n FLAT_APPEARANCE,\n NIGHT_APPEARANCE,\n MODERN_LIGHT_APPEARANCE,\n MODERN_DARK_APPEARANCE,\n BOLD_LIGHT_APPEARANCE,\n BOLD_DARK_APPEARANCE,\n GLASS_LIGHT_APPEARANCE,\n GLASS_DARK_APPEARANCE,\n ELEMENT_TYPES,\n SUPPORTED_CARD_BRANDS,\n CURRENCY_MAP,\n DEFAULT_CURRENCY,\n BUTTONS_LAYOUT_DEFAULT,\n BUTTONS_LAYOUT_MINIMAL,\n BUTTONS_LAYOUT_ROUNDED,\n BUTTONS_LAYOUT_DARK,\n BUTTONS_LAYOUT_MODERN_LIGHT,\n BUTTONS_LAYOUT_MODERN_DARK,\n BUTTONS_LAYOUT_BOLD_LIGHT,\n BUTTONS_LAYOUT_BOLD_DARK,\n BUTTONS_LAYOUT_GLASS_LIGHT,\n BUTTONS_LAYOUT_GLASS_DARK,\n THEMES,\n resolveTheme,\n resolveButtonsLayoutTheme,\n getPostalCodeLabel,\n COUNTRY_OPTIONS,\n getCountryByCode,\n resolveAVSConfig,\n isAVSFieldVisible,\n isAVSEnabled,\n US_STATES,\n CA_PROVINCES,\n getStateOptions,\n getStateLabel,\n type StateOption,\n STRIPE_EXPRESS_METHODS,\n STRIPE_METHOD_CURRENCIES,\n STRIPE_METHOD_COUNTRIES,\n STRIPE_METHOD_AMOUNT_LIMITS,\n STRIPE_METHOD_MATRIX,\n type StripeMethodEntry,\n type StripeMethodThemeVariant,\n filterStripeMethodsByCurrency,\n filterStripeMethodsByCountry,\n filterStripeMethodsByAmount,\n getStripeMethodDisplayName,\n hasVendoredStripeMethodLogo,\n needsStripeMethodExplicitConfirm,\n resolveStripeMethodBrandVariant,\n partitionStripeMethods,\n stripeExpressMethodToOptionKey,\n} from './constants.js';\n\n// Postal code lookups\nexport { getStateFromPostalCode } from './postal-code-lookup.js';\n\n// Postal code format validation (country-aware, mirrors backend #887)\nexport {\n isPostalCodeSupported,\n isValidPostalCode,\n getPostalCodeExample,\n} from './postal-code-validation.js';\n\n// Display helpers\nexport { buildCheckoutDisplayData } from './display.js';\nexport type {\n DisplayLineItem,\n CheckoutDisplayData,\n BuildCheckoutDisplayDataOptions,\n} from './display.js';\n\n// Checkout payload helpers\nexport {\n resolveSessionCurrency,\n foldIntoProducts,\n buildProductPayload,\n buildItemPayload,\n buildSubscriptionPayload,\n} from './checkout-payload.js';\n\n// Validation helpers\nexport {\n getCurrencyByCountry,\n isValidPublishableKey,\n isValidSecretKey,\n isSetupIntentClientSecret,\n} from './validation.js';\n\n// Idempotency (stable checkout-create key — TeamFloPay/backend#972)\nexport {\n IDEMPOTENCY_KEY_HEADER,\n MAX_IDEMPOTENCY_KEY_LENGTH,\n IDEMPOTENCY_IN_PROGRESS_CODE,\n generateIdempotencyKey,\n resolveIdempotencyKey,\n} from './idempotency.js';\n\n// UUID helpers (v4 generation for backend `@IsUUID()` fields)\nexport { UUID_V4, isUuidV4, randomUuidV4 } from './uuid.js';\n","// ---------------------------------------------------------------------------\n// Appearance / Theming\n// ---------------------------------------------------------------------------\n\n/** Theme variables that map to CSS custom properties on FloPay elements. */\nexport interface FloPayThemeVariables {\n colorPrimary?: string;\n /** Hover background for all \"flo\" buttons (submit / card / wallet CTAs). */\n colorPrimaryHover?: string;\n colorBackground?: string;\n colorText?: string;\n colorDanger?: string;\n borderRadius?: string;\n fontFamily?: string;\n fontSizeBase?: string;\n spacingUnit?: string;\n}\n\n/** Controls the visual appearance of all FloPay elements. */\nexport interface FloPayAppearance {\n theme?: 'default' | 'flat' | 'night' | 'none';\n variables?: FloPayThemeVariables;\n /** CSS-like rules keyed by selector (e.g. `\".Input\"`, `\".Label\"`). */\n rules?: Record<string, Record<string, string>>;\n}\n\n/** Style overrides for the `buttons` layout mode. */\nexport interface ButtonsLayoutStyles {\n /** Style for the \"Credit / Debit Card\" button. */\n cardButton?: Record<string, string | number>;\n /** Font size for the \"Credit / Debit Card\" button label. */\n cardButtonFontSize?: string;\n /** Style for the card form container when expanded. */\n cardFormContainer?: Record<string, string | number>;\n /** Border color for card input fields. */\n cardInputBorder?: string;\n /** Text color inside the card input fields (number, expiry, CVC). */\n cardInputColor?: string;\n /** Placeholder text color for the card input fields. */\n cardInputPlaceholderColor?: string;\n /** Font size for the card input fields. */\n cardInputFontSize?: string;\n /** Background color for card input fields. */\n cardInputBackground?: string;\n /**\n * Opt-in escape hatch for vault-only style hooks that the appearance →\n * hosted-field mapper cannot express. Merged last (last-write-wins) into the\n * style config handed to the vault PCI card form, so these win over the\n * auto-translated `cardInput*` knobs and `appearance.variables`. Keys are\n * passed through verbatim — use vault-supported style property names.\n * Applied only to the hosted vault card form.\n */\n vaultCardForm?: Record<string, string | number>;\n /** Style for the full-name text input. */\n nameInput?: Record<string, string | number>;\n /** Style for the \"Go back\" button text/container. */\n backButton?: Record<string, string | number>;\n /** Font size for the \"Go back\" button label. */\n backButtonFontSize?: string;\n /** Style for the back button circle icon. */\n backButtonIcon?: Record<string, string | number>;\n /** Style for the submit/confirm button. */\n submitButton?: Record<string, string | number>;\n /** Font size for the submit button label. */\n submitButtonFontSize?: string;\n /** Style for the \"Secure card checkout\" title. */\n title?: Record<string, string | number>;\n /** Font size for the \"Secure card checkout\" title. */\n titleFontSize?: string;\n /** Style for the error banner. */\n errorBanner?: Record<string, string | number>;\n /** Style for the country select dropdown container (AVS). */\n countrySelect?: Record<string, string | number>;\n /** Style for the ZIP/postcode input container (AVS). */\n zipInput?: Record<string, string | number>;\n /** Style for the street address input (AVS address_line_1). */\n addressLine1Input?: Record<string, string | number>;\n /** Style for the apt/suite input (AVS address_line_2). */\n addressLine2Input?: Record<string, string | number>;\n /** Style for the city input (AVS). */\n cityInput?: Record<string, string | number>;\n /** Style for the state/province input or dropdown (AVS). */\n stateInput?: Record<string, string | number>;\n}\n\n/** Predefined theme for the `buttons` layout. */\nexport type ButtonsLayoutTheme =\n | 'default'\n | 'minimal'\n | 'rounded'\n | 'dark'\n | 'modern-light'\n | 'modern-dark'\n | 'bold-light'\n | 'bold-dark'\n | 'glass-light'\n | 'glass-dark';\n\n/**\n * Identifier for a coherent {appearance, buttonsLayout} theme bundle exported\n * by `@flopay/shared`. Subset of `ButtonsLayoutTheme` covering the bundles\n * that ship matching `*_APPEARANCE` + `BUTTONS_LAYOUT_*` halves.\n */\nexport type ThemeBundleId =\n | 'modern-light'\n | 'modern-dark'\n | 'bold-light'\n | 'bold-dark'\n | 'glass-light'\n | 'glass-dark';\n\n/**\n * Theme identifier accepted by FloPay React components (`FloPayCheckout`,\n * `FloPayAutomaticPaymentButton`, `SplitCardForm`) on the `theme` prop.\n *\n * - `'classic'` — historic FloPay look (no bundle applied); kept as the\n * no-theme baseline so consumers can declare it explicitly.\n * - Bundle ids (`'modern-light'`, `'glass-dark'`, …) pull both halves\n * (`appearance` + `buttonsLayout`) from {@link THEMES} so a single prop\n * styles every part of the checkout consistently.\n */\nexport type ThemeId = 'classic' | ThemeBundleId;\n\n/** A coherent theme: appearance for Stripe Elements + wrapper styles for the FloPay buttons/card form. */\nexport interface ThemeBundle {\n appearance: FloPayAppearance;\n buttonsLayout: ButtonsLayoutStyles;\n}\n\n// ---------------------------------------------------------------------------\n// AVS Field Configuration\n// ---------------------------------------------------------------------------\n\n/**\n * Per-field AVS configuration.\n * - `true` = show for all countries\n * - `string[]` = show only for listed country codes (ISO 3166-1 alpha-2)\n * - `false` or omitted = hidden\n */\nexport interface AVSFieldConfig {\n /** Street address (line 1). */\n address_line_1?: boolean | string[];\n /** Apt, suite, unit, etc. (line 2). */\n address_line_2?: boolean | string[];\n /** City / Town. */\n city?: boolean | string[];\n /** State / Province / Region. Renders as dropdown for US and CA. */\n state?: boolean | string[];\n /** ZIP / Postal code. */\n postal_code?: boolean | string[];\n /** Country dropdown. */\n country?: boolean | string[];\n}\n\n// ---------------------------------------------------------------------------\n// Checkout Session (mirrors checkout project's CheckoutSession)\n// ---------------------------------------------------------------------------\n\n/** A customer attached to a checkout session. */\nexport interface Customer {\n id: string;\n email: string;\n firstName?: string;\n lastName?: string;\n gender?: string;\n city?: string;\n state?: string;\n country?: string;\n zip?: string;\n /** Street address (line 1). */\n line1?: string;\n /** Apt, suite, unit (line 2). */\n line2?: string;\n}\n\n/** Recurring interval configuration for subscription line items. */\nexport interface RecurringInterval {\n interval: 'month' | 'year';\n intervalCount?: number;\n}\n\n/** Inline product data when no pre-created price is referenced. */\nexport interface PriceData {\n currency: string;\n unitAmount: number;\n productData: { name: string; description?: string };\n recurring?: RecurringInterval;\n}\n\n/** A single line item within a checkout session. */\nexport interface LineItem {\n /** Reference to a pre-created price object on the provider. */\n price?: string;\n /** Inline price data (used when no `price` reference exists). */\n priceData?: PriceData;\n quantity: number;\n}\n\n/** Checkout mode controlling the payment UI behavior. */\nexport type CheckoutMode = 'full' | 'auto' | 'confirm';\n\n/**\n * Discriminator describing whether a checkout product is a one-time item or a\n * recurring subscription. Mirrors the backend's `ProductTypeEnum`.\n */\nexport type CheckoutProductType = 'item' | 'subscription';\n\n/** Unified checkout product from a session response. */\nexport interface CheckoutSessionProduct {\n uuid: string;\n checkoutSessionId: string;\n /**\n * Whether this product is a one-time item or a recurring subscription.\n * Optional to mirror {@link CheckoutProduct.type}; when omitted, consumers\n * treat the product as an `'item'` for display ordering.\n */\n type?: CheckoutProductType;\n /** Preferred catalog code for the product. */\n code?: string;\n /**\n * Display-only name. Resolved from the catalog server-side; the SDK\n * populates this from the client-side display cache when missing.\n */\n name?: string | null;\n /** Display-only description from the catalog. */\n description?: string | null;\n quantity: number;\n /** Display-only. Populated from cache when the server omits it. */\n totalAmount?: number;\n /** Display-only. Populated from cache when the server omits it. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CheckoutSession}. */\n currency?: string;\n metadata?: Record<string, unknown> | null;\n}\n\n/**\n * Environment for an upstream gateway. Accepts both the gateway-native values\n * (`'sandbox'` | `'live'`) and FloPay's internal aliases (`'stage'` |\n * `'production'`) so the same string can flow from the billing API straight\n * to gateway SDKs without translation at every call site. Use\n * {@link normalizeGatewayEnvironment} to collapse to the canonical pair\n * before handing the value to a gateway SDK.\n */\nexport type GatewayEnvironment = 'sandbox' | 'live' | 'stage' | 'production';\n\n/** Canonical gateway-native form returned by {@link normalizeGatewayEnvironment}. */\nexport type NormalizedGatewayEnvironment = 'sandbox' | 'live';\n\n/**\n * Map FloPay's environment aliases to the gateway-native `'sandbox'`/`'live'`\n * pair. `'stage'` → `'sandbox'`, `'production'` → `'live'`. Returns `undefined`\n * for `undefined` input and logs a console warning for unrecognized strings\n * (so misconfiguration surfaces immediately instead of hanging later — most\n * gateway SDKs silently fall back to live endpoints on an unknown env, which\n * then fails opaquely against sandbox credentials).\n */\nexport function normalizeGatewayEnvironment(\n env: GatewayEnvironment | string | undefined | null,\n): NormalizedGatewayEnvironment | undefined {\n if (env == null) return undefined;\n switch (env) {\n case 'sandbox':\n case 'stage':\n return 'sandbox';\n case 'live':\n case 'production':\n return 'live';\n default:\n // eslint-disable-next-line no-console\n console.warn(\n `[FloPay] Unrecognized gateway environment \"${env}\". Expected one of: sandbox, live, stage, production. Falling back to undefined.`,\n );\n return undefined;\n }\n}\n\n/** Per-gateway configuration returned by the billing API. */\nexport interface CheckoutGateway {\n /** Public client identifier (e.g. Stripe publishable key, PayPal client id). */\n publishableKey?: string | null;\n /** Sandbox or live mode for the gateway credentials. */\n environment?: GatewayEnvironment;\n /**\n * Optional Stripe PaymentIntent client secret exposed by the billing API\n * when additional authentication is required for a saved payment method.\n * Stripe-specific.\n */\n stripeClientSecret?: string | null;\n /**\n * Optional publishable key for a dedicated Stripe sub-account that renders\n * PayPal via Stripe Elements. Stripe-specific. Distinct from\n * `gateways.paypal.publishableKey`, which is a PayPal client id used by the\n * direct PayPal SDK.\n */\n paypalPublishableKey?: string | null;\n /**\n * Per-session list of payment method type identifiers that the gateway has\n * enabled for this consumer (e.g. `['apple_pay', 'google_pay', 'cashapp',\n * 'klarna']`). Populated by the billing API after looking up the gateway's\n * Payment Method Configurations. The SDK partitions this list against\n * {@link STRIPE_EXPRESS_METHODS} to decide which methods render in the\n * `ExpressCheckoutElement` row (Apple Pay / Google Pay / PayPal / Link /\n * Amazon Pay / Klarna) vs the `PaymentElement` accordion (Cash App Pay /\n * Affirm / iDEAL / Bancontact / …). `card` is always filtered out because\n * the hosted vault owns the card path. Absent on legacy backends.\n */\n enabledPaymentMethods?: string[];\n /**\n * Per-method buyer-country gate (uppercase ISO 3166-1 alpha-2), keyed by the\n * same method strings as {@link enabledPaymentMethods}. A method absent here\n * has no country restriction. The SDK filters the rendered tile row by the\n * buyer's *live* country (which can change via AVS after the session is\n * created) against this map — so per-method country eligibility lives in one\n * place (the backend) rather than a hardcoded SDK table. Absent on legacy\n * backends (the SDK then falls back to its built-in table).\n */\n enabledPaymentMethodCountries?: Record<string, string[]>;\n}\n\n/**\n * Map of gateways attached to a session, keyed by gateway code. A session can\n * advertise multiple gateways concurrently — e.g. `gateways.stripe` for card\n * + wallets and `gateways.paypal` for direct PayPal rendering.\n */\nexport interface CheckoutGateways {\n stripe?: CheckoutGateway;\n paypal?: CheckoutGateway;\n [key: string]: CheckoutGateway | undefined;\n}\n\n/** Represents a FloPay checkout session. */\nexport interface CheckoutSession {\n // ── Core fields ──\n id: string;\n clientSecret: string;\n mode: 'payment' | 'subscription' | 'setup';\n status: 'open' | 'complete' | 'expired';\n amount: number;\n currency: string;\n lineItems?: LineItem[];\n customer?: Customer;\n metadata?: Record<string, string>;\n // ── Session data from billing API ──\n checkoutMode?: CheckoutMode;\n /**\n * Embedded hosted vault capture credentials (TeamFloPay/backend#823).\n * Card-capable session create/read responses include this block without\n * SDK-version dispatch. The SDK injects {@link VaultCaptureBlock.html} as\n * the card-capture widget; the explicit recovery path remains\n * `POST /v1/checkouts/sessions/{id}/vault/capture`.\n */\n vault?: VaultCaptureBlock;\n /**\n * Generic, provider-agnostic payment method identifier for a card already on\n * file for the customer (TeamFloPay/backend#823). For the initial\n * Stripe-behind-vault rollout this is the Stripe `pm_…` id, but the SDK\n * treats it as an opaque card-method token. Present for returning customers\n * so the SDK can skip the vault widget; `null`/absent otherwise.\n */\n providerPaymentMethodId?: string | null;\n /** Unified products array as returned by post-#760 backends. */\n products?: CheckoutSessionProduct[];\n successUrl?: string;\n cancelUrl?: string;\n coupons?: string[];\n /**\n * Pre-discount total in cart-currency major units (e.g. 24.95). Populated by\n * billing API ≥ v1.1.2; `undefined` on older backends — readers must fall\n * back to summing per-line `totalAmount`.\n */\n subtotalAmount?: number;\n /**\n * Total reduction from applied coupons in cart-currency major units.\n * Populated by billing API ≥ v1.1.2; `undefined` on older backends.\n */\n discountAmount?: number;\n /**\n * Final charge amount in cart-currency major units (subtotal − discount,\n * clamped ≥ 0). Populated by billing API ≥ v1.1.2; `undefined` on older\n * backends — readers must fall back to summing per-line `overrideAmount`.\n */\n totalAmount?: number;\n createdAt?: string;\n /**\n * Per-gateway configuration. A session can advertise multiple concurrent\n * gateways — read `gateways.stripe` for card/wallets, `gateways.paypal` for\n * direct PayPal, and so on.\n */\n gateways?: CheckoutGateways;\n accountData?: {\n userId: string;\n email: string;\n firstName: string;\n lastName: string;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n country?: string | null;\n zip?: string | null;\n };\n tagsData?: TagsData;\n}\n\n// ---------------------------------------------------------------------------\n// Payment Results\n// ---------------------------------------------------------------------------\n\n/** The result of a payment confirmation attempt. */\nexport interface PaymentResult {\n status: 'succeeded' | 'processing' | 'requires_action' | 'failed';\n paymentIntentId?: string;\n paymentMethodId?: string;\n checkoutMethod?: CheckoutButtonMethod;\n error?: import('./errors.js').FloPayError;\n}\n\n/** Parameters for confirming a wallet/APM payment from a mounted PaymentElement. */\nexport interface ConfirmPaymentParams {\n clientSecret: string;\n /** Explicit non-card category for the selected payment method. */\n paymentMethodCategory: NonCardPaymentMethodCategory;\n /** Provider method type (for example `cashapp` or `ideal`); `card` is rejected. */\n paymentMethodType: string;\n /** Optional redirect URL after 3-D Secure or wallet authentication. */\n returnUrl?: string;\n /**\n * Optional billing details appended to `payment_method_data` on the confirm call.\n * Ensures `billing_details.email` (and name/address) lands on the PaymentMethod\n * Stripe mints from Elements during 3DS confirmation.\n */\n billingDetails?: BillingDetails;\n}\n\n/** Billing details passed to Stripe for AVS (Address Verification). */\nexport interface BillingDetails {\n email?: string;\n name?: string;\n address?: {\n country?: string;\n postal_code?: string;\n city?: string;\n line1?: string;\n line2?: string;\n state?: string;\n };\n}\n\n/** Result from the Stripe-hosted PayPal confirmation or redirect-resume flow. */\nexport interface PayPalPaymentResult {\n status: 'succeeded' | 'processing' | 'requires_action' | 'requires_capture' | 'failed';\n paymentIntentId?: string;\n paymentMethodId?: string;\n error?: import('./errors.js').FloPayError;\n}\n\n// ---------------------------------------------------------------------------\n// Session-scoped non-card intent contract\n// ---------------------------------------------------------------------------\n\n/** Non-card method families accepted by the public session intent endpoint. */\nexport type NonCardPaymentMethodCategory = 'wallet' | 'apm';\n\n/**\n * Stable identity of one buyer authorization attempt (a v4 UUID).\n *\n * The backend folds this into the provider idempotency key, so reusing the same\n * value makes a transport retry reuse the *same* provider intent, while a fresh\n * value deliberately starts a new authorization. Optional on the SDK request:\n * `PaymentAPI.createSessionIntent` generates one when omitted and only advanced\n * callers that drive their own retries need to pass a stable value.\n */\nexport interface SessionIntentAuthorizationAttempt {\n authorizationAttemptId?: string;\n}\n\n/** Stripe wallet/APM request. Direct card is deliberately not representable. */\nexport interface StripeSessionIntentRequest\n extends SessionIntentAuthorizationAttempt {\n provider: 'stripe';\n paymentMethodCategory: NonCardPaymentMethodCategory;\n paymentMethodType: string;\n paymentMethodId: string | null;\n intentKind: 'payment' | 'setup';\n}\n\n/** Direct PayPal order/subscription request. */\nexport interface PayPalSessionIntentRequest\n extends SessionIntentAuthorizationAttempt {\n provider: 'paypal';\n paymentMethodCategory: 'wallet';\n paymentMethodType: 'paypal';\n paymentMethodId: null;\n intentKind: 'order' | 'subscription';\n}\n\nexport type CreateSessionIntentRequest =\n | StripeSessionIntentRequest\n | PayPalSessionIntentRequest;\n\nexport interface StripeSessionIntent extends StripeSessionIntentRequest {\n clientSecret: string;\n providerObjectId: string;\n}\n\nexport interface PayPalSessionIntent extends PayPalSessionIntentRequest {\n clientSecret: null;\n providerObjectId: string;\n}\n\nexport type SessionIntent = StripeSessionIntent | PayPalSessionIntent;\n\nexport type SessionIntentDeclineRequest =\n | {\n provider: 'stripe';\n paymentMethodCategory: NonCardPaymentMethodCategory;\n paymentMethodType: string;\n /** Provider classification code only; messages and identifiers are rejected. */\n providerDeclineReason: string;\n }\n | {\n provider: 'paypal';\n paymentMethodCategory: 'wallet';\n paymentMethodType: 'paypal';\n /** Provider classification code only; messages and identifiers are rejected. */\n providerDeclineReason: string;\n };\n\n// ---------------------------------------------------------------------------\n// Elements\n// ---------------------------------------------------------------------------\n\n/** The type of payment element to render. */\nexport type ElementType =\n | 'payment'\n | 'address';\n\n/** Emitted when an element's internal state changes. */\nexport interface ElementChangeEvent {\n elementType: ElementType;\n complete: boolean;\n empty: boolean;\n error?: { message: string; type: string };\n /** Only populated for non-sensitive fields (e.g. address). */\n value?: Record<string, unknown>;\n}\n\n/** Configuration options when creating an element. */\nexport interface ElementOptions {\n appearance?: FloPayAppearance;\n /**\n * Explicit non-card provider method types rendered by a payment element.\n * The SDK removes `card`; card collection belongs to the hosted vault.\n */\n paymentMethodTypes?: readonly string[];\n /**\n * Client secret for an existing non-card PaymentIntent or SetupIntent.\n * The explicit `paymentMethodTypes` allowlist remains required; the SDK uses\n * it to validate the provider intent before mounting. Card checkout uses the\n * hosted vault.\n */\n clientSecret?: string;\n /**\n * Total amount in the smallest currency unit (e.g. cents).\n * Used when no `clientSecret` is available — Stripe Elements needs\n * `mode` + `amount` + `currency` to render without a server-side intent.\n */\n amount?: number;\n /** ISO 4217 currency code (lowercase). Used with `amount` when no `clientSecret`. */\n currency?: string;\n /** How payment methods are created. 'manual' = tokenize only, 'auto' = Stripe handles it. */\n paymentMethodCreation?: 'manual' | 'auto';\n /**\n * Requests reusable payment credentials for future payments when Stripe\n * creates or validates a deferred PaymentIntent for this Elements group.\n */\n setupFutureUsage?: 'off_session' | 'on_session';\n layout?: 'tabs' | 'accordion' | 'auto';\n defaultValues?: Record<string, unknown>;\n readOnly?: boolean;\n /** Address element mode: 'billing' or 'shipping'. */\n mode?: 'billing' | 'shipping';\n}\n\n// ---------------------------------------------------------------------------\n// Mounted Element (runtime instance)\n// ---------------------------------------------------------------------------\n\n/**\n * A payment element that has been created and can be mounted into the DOM.\n *\n * TODO: In a future phase, each MountedElement will render inside an iframe\n * for PCI DSS SAQ-A compliance. For now, it wraps the underlying provider\n * element directly.\n */\nexport interface MountedElement {\n mount(container: HTMLElement): void;\n unmount(): void;\n update(options: Partial<ElementOptions>): void;\n on(event: string, handler: (...args: unknown[]) => void): void;\n off(event: string, handler: (...args: unknown[]) => void): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Provider Configuration\n// ---------------------------------------------------------------------------\n\n/** Top-level configuration for initializing FloPay. */\nexport interface FloPayConfig {\n publishableKey: string;\n /** Billing API base URL (e.g. https://api.stage.flopay.com). */\n billingApiUrl?: string;\n /**\n * Flo-owned privacy-safe operational telemetry. Enabled by default; set to\n * `false` to opt out. This intentionally accepts no endpoint, tags, user\n * context, messages, or custom metadata.\n */\n telemetry?: boolean;\n locale?: string;\n appearance?: FloPayAppearance;\n apiVersion?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider Adapter Interface\n// ---------------------------------------------------------------------------\n\n/**\n * Abstraction layer for payment providers.\n *\n * Currently only Stripe is implemented (`StripeAdapter`). The interface\n * ensures that adding new providers (Chargebee, Recurly, etc.) will not\n * require changes in consumer code.\n */\nexport interface PaymentProviderAdapter {\n readonly name: string;\n initialize(config: FloPayConfig): Promise<void>;\n createElement(\n type: ElementType,\n options: ElementOptions,\n ): Promise<MountedElement>;\n /** Retrieve an existing element by type, or `null` if not yet created. */\n getElement(type: ElementType): MountedElement | null;\n /** Submit elements for validation (Stripe `elements.submit()`). */\n submitElements(): Promise<{ error?: import('./errors.js').FloPayError }>;\n /** Confirm a non-card wallet/APM payment from mounted elements. */\n confirmPayment(params: ConfirmPaymentParams): Promise<PaymentResult>;\n /**\n * Create a PayPal payment: create PM → create intent → confirm with redirect.\n * Returns the confirmed PaymentIntent ID if completed inline, or redirects to PayPal.\n *\n * `nonce` is the session-bound checkout token forwarded to the\n * session-scoped non-card intent contract.\n */\n confirmPayPalPayment(params: {\n billingApiUrl: string;\n sessionId: string;\n email: string;\n returnUrl: string;\n nonce?: string;\n }): Promise<PayPalPaymentResult>;\n /**\n * Resume a PayPal payment after redirect return.\n * Checks URL params for payment_intent + redirect_status.\n */\n resumePayPalPayment(): Promise<PayPalPaymentResult | null>;\n /**\n * Get the raw underlying provider instance (e.g. Stripe object).\n * Used internally for creating secondary Elements groups (e.g. PayPal).\n */\n getRawProvider(): unknown;\n /** Create a secondary Elements group for PayPal's automatic payment-method flow. */\n createPayPalElements(options: ElementOptions): unknown;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Card Capture Adapter (vault-hosted PCI card widget)\n// ---------------------------------------------------------------------------\n\n/**\n * Identifier for a card-capture backend that owns the hosted PCI card form.\n * The SDK models card collection as a generic card method so additional\n * vault/card providers can be added behind the same {@link CardCaptureAdapter}\n * without changing the React card form. `'pcivault'` is the first (and\n * currently only) implementation.\n */\nexport type CardCaptureProviderId = 'pcivault';\n\n/**\n * Server-rendered hosted vault capture credentials (TeamFloPay/backend#823).\n *\n * Returned either embedded on every card-capable session create/read response\n * or from the explicit\n * `POST /v1/checkouts/sessions/{id}/vault/capture` endpoint. `html` is a\n * self-contained, Flo-bundled hosted-form widget (PCIVault card fields, its own\n * submit button, status overlay, and — owned entirely by the backend — card\n * tokenization, PaymentIntent creation/confirmation, 3DS, and decline display).\n * The SDK injects `html` and steps back; PAN / CVC never enter the SDK runtime.\n *\n * `url` is the raw PCIVault submit endpoint the bundle POSTs to; it is surfaced\n * for diagnostics and is not used directly by the Model-A (inject-the-widget)\n * integration. The PCIVault submit *secret* is intentionally **not** part of\n * this type — it is server-only and must never cross onto the public session\n * surface (logs / telemetry / client inspection).\n */\nexport interface VaultCaptureBlock {\n /** Self-contained hosted-form widget HTML the SDK injects into the card slot. */\n html?: string;\n /** PCIVault submit URL the hosted form POSTs the captured card to. */\n url?: string;\n /**\n * One-time integrity token minted by the backend and baked into the widget\n * bootstrap. When present the SDK threads it into\n * {@link CardCaptureMountOptions.messageToken} and rejects any terminal\n * `postMessage` outcome whose {@link VaultCaptureResultMessage.messageToken}\n * does not match — the primary defence against same-window forged outcomes\n * (TeamFloPay/backend#823).\n */\n messageToken?: string;\n /**\n * Exact origin the hosted widget posts its terminal outcomes from, when it\n * runs in a cross-origin frame. When present the SDK rejects messages from\n * any other origin.\n */\n expectedOrigin?: string;\n}\n\n/**\n * Lifecycle / outcome events emitted by a {@link CardCaptureAdapter}.\n *\n * Under the Model-A (backend-orchestrated) vault flow the hosted widget owns\n * the entire payment — capture, charge, and 3DS — so the SDK observes only:\n * - `ready` — the widget mounted and is accepting input.\n * - `complete`— the backend reported a successful (terminal) charge.\n * - `decline` — the backend reported a declined / failed charge.\n * - `error` — the widget failed to load, or an unexpected runtime error.\n *\n * `complete` / `decline` arrive via a `postMessage` from the hosted widget (see\n * {@link VaultCaptureResultMessage}); the backend is responsible for emitting\n * them. When it does not, the widget falls back to its own success redirect.\n */\nexport type CardCaptureEventType =\n | 'ready'\n | 'submitting'\n | 'complete'\n | 'decline'\n | 'error'\n | 'validation'\n /**\n * The buyer clicked the widget's submit button but the host had gated it\n * (see {@link CardCaptureAdapter.setSubmitGate}) — the widget blocked its own\n * charge so the host can surface its merchant-DOM validation (e.g. AVS) the\n * same way the widget surfaces inline card validation.\n */\n | 'blocked'\n /**\n * The provider needs the buyer to complete an additional verification step\n * (e.g. Stripe 3DS-2 challenge) before the payment can settle. The widget\n * surfaces the provider-hosted challenge URL on the outcome event; the host\n * should:\n * 1. Hide its \"processing\" backdrop so the buyer can interact with the\n * challenge (the widget renders the iframe at the parent page level\n * so it isn't trapped inside the vault iframe).\n * 2. Render the challenge — the SDK's default vault adapter creates a\n * full-page overlay iframe pointing at `nextActionRedirectUrl`.\n * The next `complete` / `decline` / `error` fires after the buyer finishes\n * (or abandons) the challenge.\n */\n | 'action_required';\n\n/** Payload for a {@link CardCaptureAdapter} outcome event. */\nexport interface CardCaptureOutcomeEvent {\n /** Owning checkout session id, for correlation. */\n sessionId?: string;\n /** Provider intent / transaction id on a terminal outcome, when available. */\n intentId?: string;\n /** Mapped decline reason on `decline` (backend `PaymentDeclineReason` enum). */\n declineReason?: string;\n /** Human-readable message for `decline` / `error`. */\n message?: string;\n /**\n * Provider-hosted next-action URL the buyer must complete on\n * `action_required` (e.g. Stripe 3DS-2 challenge page). Absent on every\n * other event type.\n */\n nextActionRedirectUrl?: string;\n}\n\n/**\n * `window.postMessage` payload the hosted vault widget sends its embedding SDK\n * to report a terminal payment outcome.\n *\n * The widget HTML is injected **same-window** (see `PciVaultCardCapture`), so\n * `event.origin` for a genuine outcome is the merchant page's own origin and\n * the bare `source` string alone is forgeable by any other script on the page.\n * Authenticity therefore rests on, in order of strength:\n * 1. `messageToken` — an unguessable per-session token the backend bakes into\n * the widget bootstrap and echoes here; the SDK rejects terminal outcomes\n * that omit/mismatch it ({@link CardCaptureMountOptions.messageToken}).\n * 2. `sessionId` — money-affecting outcomes (`complete` / `decline`) must be\n * bound to the mounted session; the SDK rejects ones that are not.\n * 3. `expectedOrigin` — an optional strict origin gate for widgets that post\n * from a cross-origin frame ({@link CardCaptureMountOptions.expectedOrigin}).\n */\nexport interface VaultCaptureResultMessage {\n source: 'flopay-vault';\n type: 'ready' | 'submitting' | 'complete' | 'decline' | 'error' | 'action_required';\n /**\n * Owning checkout session id. Always present for terminal outcomes\n * (`complete` / `decline`) — the SDK rejects money-affecting outcomes that\n * are not bound to the mounted session. May be absent on a pre-bootstrap\n * `ready` / load-`error` the widget emits before the session is wired.\n */\n sessionId?: string;\n /**\n * Integrity token echoed from the widget bootstrap; must equal the value the\n * SDK was mounted with ({@link CardCaptureMountOptions.messageToken}). When\n * the SDK was given a token it rejects messages that omit or mismatch it.\n */\n messageToken?: string;\n intentId?: string;\n declineReason?: string;\n message?: string;\n /**\n * Provider-hosted next-action URL the buyer must complete on\n * `type === 'action_required'` (e.g. Stripe 3DS-2 challenge page). The host\n * SDK renders the challenge at the parent page level so the buyer isn't\n * blocked by the SDK's processing backdrop.\n */\n nextActionRedirectUrl?: string;\n}\n\n/** Options for mounting the hosted vault widget into a container element. */\nexport interface CardCaptureMountOptions {\n /**\n * Server-rendered hosted-form widget HTML (the vault capture block's `html`).\n * The adapter injects this and lets the bundled `<script>` bootstrap the\n * PCIVault form; the SDK does not own its fields or styling.\n */\n html: string;\n /**\n * Per-session integrity token (the vault block's `messageToken`). When\n * supplied, the adapter rejects any `postMessage` outcome whose\n * {@link VaultCaptureResultMessage.messageToken} does not match — closing the\n * same-window forgery vector. Omit when the backend does not (yet) mint one.\n */\n messageToken?: string;\n /**\n * Exact origin expected for terminal `postMessage` outcomes (the vault\n * block's `expectedOrigin`). When supplied, the adapter rejects messages from\n * any other origin. Omit to skip the origin gate (default).\n */\n expectedOrigin?: string;\n /**\n * Merchant theme colors to apply to the hosted form. The SDK owns theming;\n * the adapter pushes these into the (cross-origin) widget so the card form\n * matches the surrounding checkout. Only provided keys are applied — the\n * backend ships neutral defaults for the rest. Re-pushable at runtime via\n * {@link CardCaptureAdapter.applyTheme} for live theme switches.\n */\n theme?: VaultCardThemeColors;\n}\n\n/**\n * Merchant style values the SDK pushes into the hosted vault card form so it\n * matches the surrounding checkout fields. The form's own surface stays\n * transparent — these only drive the inputs, submit button, and overlay.\n */\nexport interface VaultCardThemeColors {\n /** Submit button background. */\n primaryColor?: string;\n /** Submit button hover background. */\n primaryHoverColor?: string;\n /** Card input fill (the surrounding form surface stays transparent). */\n inputBackgroundColor?: string;\n /** Input + selected-value text color. */\n textColor?: string;\n /** Input border color. */\n borderColor?: string;\n /** Input placeholder color. */\n placeholderColor?: string;\n /** Error/invalid border + overlay color. */\n errorColor?: string;\n /** Success overlay color. */\n successColor?: string;\n /** Input font family. */\n fontFamily?: string;\n /** Input font size (e.g. `16px`). */\n fontSize?: string;\n /**\n * Input + placeholder font weight (e.g. `400`). Sent as a string so the\n * hosted widget's string-only theme applier picks it up. Mirrors the SDK's\n * `resolvedInputFontWeight` so the vault inputs match the AVS fields.\n */\n fontWeight?: string;\n /** Outer corner radius for the grouped card inputs (e.g. `8px`). */\n borderRadius?: string;\n}\n\n/**\n * Abstraction for a hosted, PCI-scoped card capture widget. The React card\n * form depends only on this interface — never on Stripe element types — so the\n * card path stays decoupled from any specific card provider.\n *\n * Under the Model-A vault flow (TeamFloPay/backend#823) the widget is rendered\n * server-side and the backend orchestrates the whole charge (tokenize → create\n * + confirm PaymentIntent → 3DS → fulfilment). The SDK's only job is to inject\n * the widget HTML and relay its terminal `postMessage` outcome to the host\n * checkout. No Stripe.js is involved on the card path.\n */\nexport interface CardCaptureAdapter {\n /** The card-capture backend backing this adapter. */\n readonly provider: CardCaptureProviderId;\n /** Inject the hosted widget HTML into `container` and bootstrap it. */\n mount(container: HTMLElement, options: CardCaptureMountOptions): Promise<void>;\n /** Subscribe to a lifecycle / outcome event. Returns an unsubscribe fn. */\n on(\n event: CardCaptureEventType,\n handler: (event: CardCaptureOutcomeEvent) => void,\n ): () => void;\n /**\n * Push merchant theme colors into the mounted widget (live). Lets the host\n * re-skin the card form on a runtime theme switch without a remount. No-op\n * before the widget is ready or if unsupported.\n */\n applyTheme?(theme: VaultCardThemeColors): void;\n /**\n * Gate the widget's submit button from the host. When `blocked` is `true`,\n * the widget cancels its own submit on the next click and emits a `'blocked'`\n * event instead of `'submitting'` — letting the host validate merchant-DOM\n * fields (e.g. AVS) and surface errors uniformly before any charge. The\n * latest gate is re-applied when the widget (re)becomes ready. No-op if\n * unsupported.\n */\n setSubmitGate?(blocked: boolean): void;\n /**\n * Push the card-field display/tab order into the widget (live), plus whether\n * the widget should move the cursor to its first field on load. `order` is a\n * permutation of the rows ({@link VaultCardFieldKey}); `null` restores the\n * default. `autoFocus` is `false` when the host renders AVS fields above the\n * widget (it focuses the first AVS field itself). Re-applied on `ready`.\n */\n setCardFieldOrder?(order: VaultCardFieldKey[] | null, autoFocus: boolean): void;\n /** Tear down the widget and release resources. */\n unmount(): void;\n}\n\n/**\n * The reorderable rows of the hosted vault card form. `'expiry'` is the combined\n * expiry + CVV row. The submit button always stays last.\n */\nexport type VaultCardFieldKey = 'name' | 'number' | 'expiry';\n\n// ---------------------------------------------------------------------------\n// Billing Provider (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Supported upstream gateway codes. */\nexport type BillingProvider = 'stripe' | 'paypal';\n\n// ---------------------------------------------------------------------------\n// Tokenized Body (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Token payload produced by client-side tokenization. */\nexport interface TokenizedBody {\n id?: string;\n type?: string;\n threeDSecureActionResultTokenId?: string;\n originalPaymentMethodId?: string;\n /**\n * @deprecated Use {@link TokenizedBody.gateway} + {@link TokenizedBody.paymentMethodType}.\n * Still populated by the SDK for PayPal payments so backends that gate on\n * `isPaypal === 'true'` keep working through the deprecation window.\n */\n isPaypal?: boolean;\n /**\n * Upstream gateway that produced the token. `'stripe'` covers every Stripe\n * payment method (card / wallets / Cash App Pay / Klarna / …); `'paypal'`\n * is set when DirectPayPalButton produced the token via the PayPal JS SDK.\n * Backend should route `/process` by `(gateway, paymentMethodType)` instead\n * of branching on `isPaypal` once consumers have adopted the new fields.\n */\n gateway?: BillingProvider | (string & {});\n /**\n * Concrete payment method type. For Stripe gateways this mirrors the Stripe\n * PaymentMethod.type value (`'card'`, `'apple_pay'`, `'google_pay'`,\n * `'cashapp'`, `'klarna'`, …). For PayPal it is the literal `'paypal'`.\n */\n paymentMethodType?: string;\n}\n\n/** Structured checkout-processing error returned by the billing API. */\nexport interface CheckoutProcessError {\n type: string;\n message?: string;\n transactionId?: string;\n threeDSecureToken?: string;\n paymentMethodId?: string;\n checkoutMethod?: CheckoutButtonMethod;\n advice?: string;\n gatewayErrorCode?: string;\n fields?: Array<{ field: string; message: string }>;\n /**\n * Provider-hosted next-action URL on `type === '3ds_required'` (e.g.\n * Stripe's hosted 3DS challenge page). Present on auto-checkout upsell\n * errors when the saved PM requires a fresh 3DS challenge — the SDK's\n * AutomaticPaymentButton mounts this URL in a full-page overlay iframe\n * so the buyer can authenticate without being demoted to a fresh\n * card-entry flow.\n */\n nextActionRedirectUrl?: string;\n}\n\n/** Recoverable checkout-processing state returned when fulfillment is still in progress. */\nexport interface CheckoutProcessingPending {\n type: 'checkout_processing';\n sessionId: string;\n retryAfterMs: number;\n statusUrl?: string;\n sessionUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Normalized Checkout Session (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Checkout mode: tokenize client-side or redirect to hosted page. */\nexport type CheckoutModeKind = 'tokenize' | 'redirect';\n\n/**\n * Provider-agnostic normalized checkout session. Backend may attach multiple\n * gateways per session — read each from `data.<gatewayCode>`.\n */\nexport interface NormalizedCheckoutSession {\n /** Gateway codes advertised by the backend for this session, for diagnostics. */\n providers: BillingProvider[];\n mode: CheckoutModeKind;\n autoProcessingError?: CheckoutProcessError;\n autoProcessingAttempted?: boolean;\n autoProcessingPending?: CheckoutProcessingPending;\n data: {\n hostedUrl?: string;\n clientToken?: string;\n session?: CheckoutSession;\n stripe?: {\n clientSecret?: string;\n publishableKey?: string;\n /**\n * Optional dedicated Stripe sub-account publishable key for rendering\n * PayPal via Stripe Elements. When present and distinct, the saved-PM\n * resume flow loads a separate FloPay instance for the PayPal PI.\n */\n paypalPublishableKey?: string;\n environment?: GatewayEnvironment;\n /**\n * Mirrors {@link CheckoutGateway.enabledPaymentMethods}. Drives dynamic\n * `ExpressCheckoutElement` / `PaymentElement` rendering inside\n * `SplitCardForm` instead of the historic hardcoded Apple/Google/PayPal\n * set. Absent on backends that have not yet adopted the field.\n */\n enabledPaymentMethods?: string[];\n /** Mirrors {@link CheckoutGateway.enabledPaymentMethodCountries}. */\n enabledPaymentMethodCountries?: Record<string, string[]>;\n };\n /**\n * Direct PayPal gateway configuration. Present only when the backend has\n * configured a dedicated PayPal gateway for the consumer; absent means the\n * Stripe-rendered PayPal fallback should be used (if Stripe is configured).\n */\n paypal?: {\n publishableKey?: string;\n environment?: GatewayEnvironment;\n };\n };\n raw?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Server-side SDK types (mirrors clicktech-core-ui/createCheckoutSession)\n// ---------------------------------------------------------------------------\n\n/** A one-time purchase item for checkout session creation. */\nexport interface CheckoutItem {\n /**\n * Catalog code for the item — the preferred identifier. When omitted, the\n * deprecated `providerItemId` is used as a fallback.\n */\n code?: string;\n /**\n * @deprecated Use {@link CheckoutItem.code}. Still accepted as a fallback\n * when `code` is not provided.\n */\n providerItemId?: string;\n /**\n * Display-only name for the item. Takes priority over the deprecated\n * `providerItemName`. Backend resolves names from the catalog; pass this\n * to seed the client-side display cache for the post-redirect fetch.\n */\n itemName?: string | null;\n /** @deprecated Use {@link CheckoutItem.itemName}. Still accepted as a fallback when `itemName` is not provided. */\n providerItemName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog; pass this to seed the client-side display cache so the UI can render the regular price after redirect. */\n totalAmount?: number;\n /** Display-only. Backend ignores this entirely; pass this to seed the client-side display cache so the UI can render the discounted price after redirect. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CreateSessionParams}/{@link InlineSessionParams}. */\n currency?: string;\n /** Arbitrary key/value metadata forwarded to the backend. */\n metadata?: Record<string, unknown> | null;\n}\n\n/**\n * Unified product input for checkout session creation. Mirrors the backend's\n * `CreateCheckoutProductBodyDto` introduced in #760 — the SDK accepts this\n * shape on `CreateSessionParams.products`. Callers using the legacy\n * {@link CheckoutItem} / {@link CheckoutSubscription} shapes do not need to\n * migrate; the SDK folds them into this shape internally.\n */\nexport interface CheckoutProduct {\n /**\n * @deprecated Optional and no longer needed — the backend resolves item vs\n * subscription from the catalog `code`. Pass it only to refine the\n * client-side optimistic display rendered before the session response loads\n * (subscriptions are listed first). Safe to omit.\n */\n type?: CheckoutProductType;\n /** Catalog code — preferred identifier. */\n code?: string;\n /** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */\n providerItemId?: string;\n /** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */\n providerPlanId?: string;\n /** Display-only name for the product. */\n name?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n itemName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n providerItemName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n subscriptionName?: string | null;\n /** @deprecated Use {@link CheckoutProduct.name}. */\n providerPlanName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog. */\n totalAmount?: number;\n /** Display-only discount override. Backend ignores this entirely. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency`. */\n currency?: string;\n metadata?: Record<string, unknown> | null;\n}\n\n/** A recurring subscription plan for checkout session creation. */\nexport interface CheckoutSubscription {\n /**\n * Catalog code for the plan — the preferred identifier. When omitted, the\n * deprecated `providerPlanId` is used as a fallback.\n */\n code?: string;\n /**\n * @deprecated Use {@link CheckoutSubscription.code}. Still accepted as a\n * fallback when `code` is not provided.\n */\n providerPlanId?: string;\n /**\n * Display-only name for the subscription plan. Takes priority over the\n * deprecated `providerPlanName`. Backend resolves names from the catalog;\n * pass this to seed the client-side display cache for the post-redirect fetch.\n */\n subscriptionName?: string | null;\n /** @deprecated Use {@link CheckoutSubscription.subscriptionName}. Still accepted as a fallback when `subscriptionName` is not provided. */\n providerPlanName?: string | null;\n /** Defaults to 1. */\n quantity?: number;\n /** Display-only. Backend resolves prices from the catalog; pass this to seed the client-side display cache so the UI can render the regular price after redirect. */\n totalAmount?: number;\n /** Display-only. Backend ignores this entirely; pass this to seed the client-side display cache so the UI can render the discounted price after redirect. */\n overrideAmount?: number | null;\n /** @deprecated Prefer the session-level `currency` on {@link CreateSessionParams}/{@link InlineSessionParams}. */\n currency?: string;\n /** Arbitrary key/value metadata forwarded to the backend. */\n metadata?: Record<string, unknown> | null;\n}\n\n/** Buyer's account information for session creation. */\nexport interface CheckoutAccount {\n userId: string;\n firstName?: string;\n lastName?: string;\n email: string;\n country?: string | null;\n gender?: string | null;\n city?: string | null;\n state?: string | null;\n zip?: string | null;\n /** Street address (line 1). */\n addressLine1?: string | null;\n /** Apt, suite, unit (line 2). */\n addressLine2?: string | null;\n}\n\n/** Analytics / pixel tags forwarded to the checkout page. */\nexport interface TagsData {\n googleContainerId?: string | null;\n sessionId?: string | null;\n testEventCode?: string | null;\n}\n\n/**\n * Parameters for creating a checkout session via the billing API.\n * Mirrors the `CreateCheckoutSessionOptions` from clicktech-core-ui.\n */\nexport interface CreateSessionParams {\n /** Base URL of the billing API, e.g. https://billing.clicktech.com */\n billingApiUrl: string;\n /** Base URL of the checkout frontend, e.g. https://checkout.clicktech.com */\n checkoutBaseUrl: string;\n /** Flo-owned privacy-safe telemetry is enabled by default; set false to opt out. */\n telemetry?: boolean;\n /** The client ID for the checkout session. */\n clientId: string;\n /**\n * Session-level ISO 4217 currency code. **Required** by post-#760\n * backends (`@IsNotEmpty`). The SDK resolves it from this field first,\n * then `items[0].currency`, then `subscriptions[0].currency`, then\n * `products[0].currency`. When none resolve, the SDK throws\n * `FloPayError('validation_error')` before issuing the HTTP request.\n */\n currency?: string;\n /**\n * Unified products array. When supplied, it is sent verbatim and\n * {@link CreateSessionParams.items} / {@link CreateSessionParams.subscriptions}\n * are ignored. Otherwise the SDK folds the legacy fields into this shape\n * before POSTing to the backend.\n */\n products?: CheckoutProduct[];\n /** One-time purchase items. Folded into `products[]` before send. */\n items?: CheckoutItem[];\n /** Recurring subscription plans. Folded into `products[]` before send. */\n subscriptions?: CheckoutSubscription[];\n /** Buyer's account information. */\n account: CheckoutAccount;\n /** URL to redirect to after successful payment. */\n successUrl: string;\n /** URL to redirect to if the user cancels. */\n cancelUrl: string;\n /**\n * Checkout mode sent to the billing API.\n * - 'confirm' – show a payment confirmation page (default)\n * - 'auto' – skip confirmation when a payment method is already on file\n * - 'full' – full checkout flow\n */\n checkoutMode?: 'confirm' | 'auto' | 'full';\n /** Coupon codes to apply. */\n couponCodes?: string[];\n /** Pixel / analytics tags forwarded to the checkout page. */\n tagsData?: TagsData;\n /** Extra query params appended to the checkout redirect URL. */\n redirectParams?: Record<string, string>;\n /** Whether to set the checkout_data cookie. Defaults to true. */\n setCookie?: boolean;\n /** Request timeout in milliseconds. Defaults to 12000. */\n timeoutMs?: number;\n /** UTM and funnel tracking metadata. */\n utmMetadata?: Record<string, string | null | undefined>[];\n /**\n * Optional idempotency key identifying exactly **one** logical checkout\n * creation (TeamFloPay/backend#972). When supplied it is sent unchanged as\n * the `Idempotency-Key` header and reused across the SDK's transport retries,\n * so a timeout or lost response cannot mint a second session. Supply this to\n * keep the key stable across React remounts, multiple SDK instances, or\n * server retries you control; it **must not** be reused for a new purchase.\n * When omitted, the SDK generates a fresh, cryptographically random key per\n * call. Must be non-empty and at most 255 characters.\n */\n idempotencyKey?: string;\n}\n\n/**\n * Parameters for inline session creation via `FloPayCheckout.createSession`.\n * Subset of `CreateSessionParams` — no redirect fields needed since the\n * component handles the checkout flow inline.\n */\nexport interface InlineSessionParams {\n /** The client ID for the checkout session. */\n clientId: string;\n /**\n * Session-level ISO 4217 currency code. **Required** by post-#760\n * backends (`@IsNotEmpty`). The SDK resolves it from this field first,\n * then `items[0].currency`, then `subscriptions[0].currency`, then\n * `products[0].currency`. When none resolve, the SDK throws\n * `FloPayError('validation_error')` before issuing the HTTP request.\n */\n currency?: string;\n /**\n * Unified products array. When supplied, it is sent verbatim and\n * {@link InlineSessionParams.items} / {@link InlineSessionParams.subscriptions}\n * are ignored. Otherwise the SDK folds the legacy fields into this shape\n * before POSTing to the backend.\n */\n products?: CheckoutProduct[];\n /** One-time purchase items. Folded into `products[]` before send. */\n items?: CheckoutItem[];\n /** Recurring subscription plans. Folded into `products[]` before send. */\n subscriptions?: CheckoutSubscription[];\n /** Buyer's account information. */\n account: CheckoutAccount;\n /** URL to redirect to after successful payment. */\n successUrl: string;\n /** URL to redirect to if the user cancels. */\n cancelUrl: string;\n /** Checkout mode: 'full' (default), 'auto', or 'confirm'. */\n checkoutMode?: 'full' | 'auto' | 'confirm';\n /** Optional saved/tokenized payment method for inline auto or confirm checkout. */\n tokenizedData?: TokenizedBody;\n /** Coupon codes to apply. */\n couponCodes?: string[];\n /** Pixel / analytics tags. */\n tagsData?: TagsData;\n /** UTM and funnel tracking metadata. */\n utmMetadata?: Record<string, string | null | undefined>[];\n /**\n * Optional idempotency key identifying exactly **one** logical checkout\n * creation (TeamFloPay/backend#972). When supplied it is sent unchanged as\n * the `Idempotency-Key` header and reused across the SDK's transport retries.\n * Supply this to keep the key stable across React remounts, multiple SDK\n * instances, or server retries you control; it **must not** be reused for a\n * new purchase. When omitted, the SDK generates a fresh, cryptographically\n * random key per create. Must be non-empty and at most 255 characters.\n */\n idempotencyKey?: string;\n // ── Checkout analytics metadata (set by SDK automatically) ──\n /** Whether AVS is enabled for this checkout. */\n avsCheck?: boolean;\n /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */\n checkoutType?: string;\n /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */\n checkoutLayout?: string;\n /** AVS field configuration for analytics. */\n avsConfig?: AVSFieldConfig;\n}\n\n/** Payment methods exposed by the React buttons layout callbacks. */\nexport type CheckoutButtonMethod = 'card' | 'paypal' | 'apple_pay' | 'google_pay';\n\n/**\n * Draft inline-session params used by `FloPayCheckout` before a real\n * checkout session has been created. Buttons-layout checkout can seed\n * placeholder account data up front; `onBeforeButtonClick` can still\n * update it before the selected payment button continues.\n */\nexport interface InlineSessionDraft extends Omit<InlineSessionParams, 'account'> {\n account: Omit<CheckoutAccount, 'email'> & { email?: string };\n}\n\n/**\n * Partial inline-session fields that can be returned from\n * `onBeforeButtonClick` and merged into the draft session params.\n */\nexport interface InlineSessionPatch {\n account?: Partial<CheckoutAccount>;\n couponCodes?: string[];\n tagsData?: TagsData;\n utmMetadata?: Record<string, string | null | undefined>[];\n}\n\n/** Context passed to the `onBeforeButtonClick` callback for buttons-layout payment methods. */\nexport interface BeforeButtonClickEvent {\n method: CheckoutButtonMethod;\n sessionId?: string;\n createSession?: InlineSessionDraft;\n}\n\n/** Structured decline event emitted by the React checkout components. */\nexport interface DeclineEvent {\n method: CheckoutButtonMethod;\n message: string;\n code?: string;\n declineCode?: string;\n}\n\n/** Result from creating a checkout session. */\nexport type CheckoutSessionResult =\n | {\n status: 201;\n redirectUrl: string;\n /**\n * Session-bound checkout token returned by the billing API alongside the\n * session UUID. Must be echoed back on every continuation request via the\n * `x-checkout-session-token` header — backend `TeamFloPay/backend#640`\n * matches this value against `checkout_session.nonce` to authorize the\n * call. Surfaced here so the redirect-style flow's caller can forward it\n * (e.g. into a hosted checkout page that hits continuation routes).\n */\n nonce: string;\n }\n | { status: 204 }\n | { status: number };\n\n/**\n * Data submitted when processing a payment (tokenized card/wallet data).\n * Mirrors checkout project's ProcessCheckoutBodyDto.\n */\nexport interface ProcessPaymentParams {\n sessionId: string;\n /**\n * Session-bound checkout token returned from session creation. Forwarded as\n * the `x-checkout-session-token` header on every call to\n * `POST /v1/checkouts/sessions/:id/process`. Required by post-#640 backends —\n * `PaymentAPI.processPayment` throws `MissingCheckoutSessionToken` when this\n * is missing or empty so the 401 fails fast on the client instead of after\n * the network round trip. Typed as optional so callers do not need to coerce\n * `undefined` to `''` to satisfy the type — pass the value through verbatim\n * and let `processPayment` surface the missing-token error.\n */\n nonce?: string;\n tokenizedData?: TokenizedBody;\n accountData: {\n userId: string;\n email: string;\n firstName: string;\n lastName: string;\n zip?: string;\n country?: string;\n city?: string;\n state?: string;\n addressLine1?: string;\n addressLine2?: string;\n };\n chv?: string;\n /** Current page URL for redirect-capable auth flows such as 3DS and PayPal. */\n returnUrl?: string;\n // ── Checkout analytics metadata ──\n /** Whether AVS (Address Verification) was enabled for this checkout. */\n avsCheck?: boolean;\n /** Checkout type: 'standard_checkout' or 'embedded_checkout'. */\n checkoutType?: string;\n /** Checkout layout: 'default_layout', 'buttons_layout', or 'custom_layout'. */\n checkoutLayout?: string;\n /** AVS field configuration for analytics — which fields were shown. */\n avsConfig?: AVSFieldConfig;\n}\n\n/** Parameters for creating a customer. */\nexport interface CreateCustomerParams {\n email: string;\n name?: string;\n metadata?: Record<string, string>;\n}\n\n/** Parameters for updating a customer. */\nexport interface UpdateCustomerParams {\n email?: string;\n name?: string;\n metadata?: Record<string, string>;\n}\n\n/** A webhook event from FloPay. */\nexport interface WebhookEvent {\n id: string;\n type: string;\n data: Record<string, unknown>;\n created: number;\n}\n\n// ---------------------------------------------------------------------------\n// Currency (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Currency information mapped to a country. */\nexport interface CurrencyInfo {\n currency: string;\n symbol: string;\n country: string;\n countryCode: string;\n /** 0 = no tax, 1 = tax (VAT) applies. */\n tax: number;\n}\n\n/** A country option for UI select elements. */\nexport interface CountryOption {\n code: string;\n name: string;\n flag: string;\n}\n","/** Discriminated error types returned by the FloPay SDK. */\nexport type FloPayErrorType =\n | 'validation_error'\n | 'api_error'\n | 'authentication_error'\n | 'rate_limit_error'\n | 'network_error';\n\n/**\n * Custom error class for all FloPay SDK errors.\n *\n * Extends the native `Error` and adds structured fields that mirror\n * Stripe-style error responses for familiarity.\n */\nexport class FloPayError extends Error {\n readonly type: FloPayErrorType;\n readonly code?: string;\n readonly declineCode?: string;\n readonly param?: string;\n readonly statusCode?: number;\n\n constructor(\n message: string,\n type: FloPayErrorType,\n options?: { code?: string; declineCode?: string; param?: string; statusCode?: number },\n ) {\n super(message);\n this.name = 'FloPayError';\n this.type = type;\n this.code = options?.code;\n this.declineCode = options?.declineCode;\n this.param = options?.param;\n this.statusCode = options?.statusCode;\n\n // Restore prototype chain (required when extending built-ins)\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error Factories\n// ---------------------------------------------------------------------------\n\n/** Create a validation error (e.g. missing required field). */\nexport function validationError(\n message: string,\n param?: string,\n): FloPayError {\n return new FloPayError(message, 'validation_error', { param });\n}\n\n/** Create an API error (e.g. upstream provider returned an error). */\nexport function apiError(\n message: string,\n code?: string,\n statusCode?: number,\n): FloPayError {\n return new FloPayError(message, 'api_error', { code, statusCode });\n}\n\n/** Create an authentication error (e.g. invalid publishable key). */\nexport function authenticationError(message: string): FloPayError {\n return new FloPayError(message, 'authentication_error');\n}\n\n/** Create a rate limit error. */\nexport function rateLimitError(message: string): FloPayError {\n return new FloPayError(message, 'rate_limit_error');\n}\n\n/** Create a network error (e.g. fetch failed). */\nexport function networkError(message: string): FloPayError {\n return new FloPayError(message, 'network_error');\n}\n","/** Wire schema version shared with the Flo telemetry ingestion service. */\nexport const TELEMETRY_SCHEMA_VERSION = 1 as const;\nexport const TELEMETRY_SDK_PACKAGES = [\n '@flopay/shared',\n '@flopay/js',\n '@flopay/react',\n] as const;\nexport type TelemetrySdkPackage = (typeof TELEMETRY_SDK_PACKAGES)[number];\nexport const TELEMETRY_MAX_BATCH_BYTES = 32 * 1024;\nexport const TELEMETRY_MAX_BATCH_EVENTS = 20;\n\nexport type TelemetryEventClass =\n | 'technical_error'\n | 'lifecycle'\n | 'expected_outcome'\n | 'performance';\n\nconst TELEMETRY_PROVIDERS = ['stripe', 'paypal'] as const;\nexport type TelemetryProvider = (typeof TELEMETRY_PROVIDERS)[number];\nexport type TelemetryProviderInput =\n | TelemetryProvider\n | 'flo'\n | 'pcivault'\n | 'other'\n | 'unknown';\n\nconst TELEMETRY_PAYMENT_METHOD_CATEGORIES = [\n 'card',\n 'wallet',\n 'paypal',\n 'apm',\n 'saved',\n 'unknown',\n] as const;\nexport type TelemetryPaymentMethodCategory =\n (typeof TELEMETRY_PAYMENT_METHOD_CATEGORIES)[number];\n\nconst TELEMETRY_STAGES = [\n 'callback',\n 'sdk_initialize',\n 'checkout_mount',\n 'session_create',\n 'session_read',\n 'session_first_byte',\n 'session_complete',\n 'checkout_data_ready',\n 'checkout_render',\n 'checkout_interactive',\n 'provider_load',\n 'provider_ready',\n 'overlay_open',\n 'overlay_return',\n 'redirect',\n 'redirect_resume',\n 'vault_request',\n 'vault_mount',\n 'vault_ready',\n 'vault_submit',\n 'tokenization',\n 'three_ds_handoff',\n 'three_ds_return',\n 'processing',\n 'recovery',\n 'completion',\n 'unmount',\n 'total_journey',\n] as const;\nexport type TelemetryStage = (typeof TELEMETRY_STAGES)[number];\n\nexport const TELEMETRY_ERROR_CODES = [\n 'CALLBACK_FAILED',\n 'CHECKOUT_SESSION_CREATE_FAILED',\n 'CONFIGURATION_INVALID',\n 'INTERNAL_SDK_ERROR',\n 'NETWORK_REQUEST_FAILED',\n 'PAYMENT_PROCESSING_FAILED',\n 'POPUP_BLOCKED',\n 'PROVIDER_LOAD_FAILED',\n 'PROVIDER_RUNTIME_FAILED',\n 'RECOVERY_FAILED',\n 'REDIRECT_RESUME_FAILED',\n 'REQUEST_TIMEOUT',\n 'SDK_INITIALIZATION_FAILED',\n 'THREE_DS_FAILED',\n 'TOKENIZATION_FAILED',\n 'VAULT_LOAD_FAILED',\n 'VAULT_SUBMIT_FAILED',\n] as const;\nexport type TelemetryErrorCode = (typeof TELEMETRY_ERROR_CODES)[number];\n\n/** Closed catalog of SDK-authored lifecycle and operational log names. */\nexport const TELEMETRY_LOG_NAMES = [\n 'sdk.initialize.started',\n 'sdk.initialize.ready',\n 'sdk.cache.hit',\n 'sdk.cache.miss',\n 'checkout.mount',\n 'session.create.started',\n 'session.read.started',\n 'session.request.first_byte',\n 'session.request.completed',\n 'checkout.data.ready',\n 'checkout.rendered',\n 'checkout.interactive',\n 'checkout.recovery.started',\n 'checkout.recovery.completed',\n 'checkout.unmount',\n 'provider.load.started',\n 'provider.eligibility.checked',\n 'provider.availability.checked',\n 'provider.ready',\n 'provider.popup.opened',\n 'provider.overlay.opened',\n 'provider.overlay.returned',\n 'provider.redirect.started',\n 'provider.redirect.resumed',\n 'vault.capture.requested',\n 'vault.widget.mounted',\n 'vault.widget.ready',\n 'vault.submission.started',\n 'vault.action.required',\n 'vault.three_ds.handoff',\n 'vault.three_ds.returned',\n 'vault.terminal',\n 'payment.method.selected',\n 'payment.intent.started',\n 'payment.intent.completed',\n 'payment.tokenization.started',\n 'payment.tokenization.completed',\n 'payment.processing.started',\n 'payment.processing.completed',\n 'payment.three_ds.handoff',\n 'payment.three_ds.returned',\n 'operation.retry',\n 'operation.deduplicated',\n 'operation.fallback',\n 'operation.cache.hit',\n 'operation.cache.miss',\n 'operation.recovery.started',\n 'operation.recovery.completed',\n 'operation.state_transition',\n] as const;\nexport type TelemetryLogName = (typeof TELEMETRY_LOG_NAMES)[number];\n\nconst TELEMETRY_REQUEST_CATEGORIES = [\n 'session_create',\n 'session_read',\n 'intent_create',\n 'process_payment',\n 'vault_capture',\n 'account_snapshot',\n 'provider_sdk',\n 'other',\n] as const;\nexport type TelemetryRequestCategory = (typeof TELEMETRY_REQUEST_CATEGORIES)[number];\n\nconst TELEMETRY_STATUS_CLASSES = [\n '2xx',\n '3xx',\n '4xx',\n '5xx',\n 'network_error',\n 'timeout',\n 'unknown',\n] as const;\nexport type TelemetryStatusClass = (typeof TELEMETRY_STATUS_CLASSES)[number];\n\nconst TELEMETRY_CHECKOUT_MODES = ['full', 'auto', 'confirm', 'unknown'] as const;\nexport type TelemetryCheckoutMode = (typeof TELEMETRY_CHECKOUT_MODES)[number];\n\nconst TELEMETRY_LAYOUTS = ['embedded', 'buttons', 'automatic', 'unknown'] as const;\nexport type TelemetryLayout = (typeof TELEMETRY_LAYOUTS)[number];\n\nconst TELEMETRY_DURATION_MODES = ['machine', 'buyer', 'total'] as const;\nexport type TelemetryDurationMode = (typeof TELEMETRY_DURATION_MODES)[number];\n\nconst TELEMETRY_EXPECTED_OUTCOMES = [\n 'action_required',\n 'customer_abandoned',\n 'payment_cancelled',\n 'payment_declined',\n 'payment_succeeded',\n 'validation_rejected',\n] as const;\nexport type TelemetryExpectedOutcome = (typeof TELEMETRY_EXPECTED_OUTCOMES)[number];\n\ninterface TelemetryCommonFields {\n eventId: string;\n stage: TelemetryStage;\n sequence: number;\n provider?: TelemetryProvider;\n attempt?: number;\n statusClass?: TelemetryStatusClass;\n requestCategory?: TelemetryRequestCategory;\n paymentMethodCategory?: TelemetryPaymentMethodCategory;\n checkoutMode?: TelemetryCheckoutMode;\n layout?: TelemetryLayout;\n}\n\ninterface BuildTelemetryCommonInput {\n eventId: string;\n stage: TelemetryStage;\n sequence: number;\n provider?: TelemetryProviderInput;\n attempt?: number;\n statusClass?: TelemetryStatusClass;\n requestCategory?: TelemetryRequestCategory;\n paymentMethodCategory?: TelemetryPaymentMethodCategory;\n checkoutMode?: TelemetryCheckoutMode;\n layout?: TelemetryLayout;\n}\n\nexport interface TelemetryErrorEvent extends TelemetryCommonFields {\n class: 'technical_error';\n code: TelemetryErrorCode;\n}\n\nexport interface BuildTelemetryErrorEventInput extends BuildTelemetryCommonInput {\n errorCode: TelemetryErrorCode;\n}\n\nexport interface TelemetryLogEvent extends TelemetryCommonFields {\n class: 'lifecycle';\n name: TelemetryLogName;\n}\n\nexport interface BuildTelemetryLogEventInput extends BuildTelemetryCommonInput {\n name: TelemetryLogName;\n}\n\nexport interface TelemetryExpectedOutcomeEvent extends TelemetryCommonFields {\n class: 'expected_outcome';\n outcome: TelemetryExpectedOutcome;\n}\n\nexport interface BuildTelemetryTerminalEventInput\n extends Omit<BuildTelemetryCommonInput, 'stage'> {\n outcome: TelemetryExpectedOutcome;\n stage?: TelemetryStage;\n}\n\nexport interface TelemetryPerformanceEvent extends TelemetryCommonFields {\n class: 'performance';\n durationMs: number;\n durationMode: TelemetryDurationMode;\n}\n\nexport interface BuildTelemetryPerformanceEventInput extends BuildTelemetryCommonInput {\n durationMs: number;\n durationMode: TelemetryDurationMode;\n}\n\nexport type TelemetryEvent =\n | TelemetryErrorEvent\n | TelemetryLogEvent\n | TelemetryExpectedOutcomeEvent\n | TelemetryPerformanceEvent;\n\nexport interface SerializeTelemetryBatchOptions {\n correlationId: string;\n sdkPackage: TelemetrySdkPackage;\n sdkVersion: string;\n batchId?: string;\n}\n\nexport interface TelemetryBatchEnvelope {\n schemaVersion: typeof TELEMETRY_SCHEMA_VERSION;\n batchId: string;\n correlationId: string;\n sdk: {\n package: TelemetrySdkPackage;\n version: string;\n };\n events: TelemetryEvent[];\n}\n\nconst UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst SDK_VERSION = /^\\d{1,4}\\.\\d{1,4}\\.\\d{1,4}(?:-[0-9A-Za-z.-]{1,32})?$/;\nconst ERROR_CODES = new Set<string>(TELEMETRY_ERROR_CODES);\nconst STAGES = new Set<string>(TELEMETRY_STAGES);\nconst PROVIDERS = new Set<string>(TELEMETRY_PROVIDERS);\nconst PAYMENT_METHODS = new Set<string>(TELEMETRY_PAYMENT_METHOD_CATEGORIES);\nconst LOG_NAMES = new Set<string>(TELEMETRY_LOG_NAMES);\nconst CHECKOUT_MODES = new Set<string>(TELEMETRY_CHECKOUT_MODES);\nconst LAYOUTS = new Set<string>(TELEMETRY_LAYOUTS);\nconst REQUEST_CATEGORIES = new Set<string>(TELEMETRY_REQUEST_CATEGORIES);\nconst STATUS_CLASSES = new Set<string>(TELEMETRY_STATUS_CLASSES);\nconst DURATION_MODES = new Set<string>(TELEMETRY_DURATION_MODES);\nconst EXPECTED_OUTCOMES = new Set<string>(TELEMETRY_EXPECTED_OUTCOMES);\nconst SDK_PACKAGES = new Set<string>(TELEMETRY_SDK_PACKAGES);\n\nfunction enumOr<T extends string>(value: unknown, allowed: Set<string>, fallback: T): T {\n return typeof value === 'string' && allowed.has(value) ? (value as T) : fallback;\n}\n\nfunction createUuidV4(): string {\n try {\n const id = globalThis.crypto.randomUUID();\n if (UUID_V4.test(id)) return id;\n } catch {\n // Fall through to a non-persistent compatibility UUID.\n }\n const bytes = new Uint8Array(16);\n try {\n globalThis.crypto.getRandomValues(bytes);\n } catch {\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction safeUuid(value: string | undefined): string {\n return typeof value === 'string' && UUID_V4.test(value) ? value : createUuidV4();\n}\n\nfunction safeAttempt(value: number | undefined): number | undefined {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 100\n ? value\n : undefined;\n}\n\nfunction safeSequence(value: number): number {\n return Number.isSafeInteger(value) && value >= 0 ? Math.min(value, 1_000_000) : 0;\n}\n\nfunction safeDuration(value: number): number {\n if (!Number.isFinite(value) || value < 0) return 0;\n return Math.min(Math.round(value), 120_000);\n}\n\nfunction addCommonFields<T extends TelemetryCommonFields>(\n event: T,\n input: BuildTelemetryCommonInput,\n): T {\n const attempt = safeAttempt(input.attempt);\n if (input.provider && PROVIDERS.has(input.provider)) event.provider = input.provider as TelemetryProvider;\n if (attempt !== undefined) event.attempt = attempt;\n if (input.statusClass) event.statusClass = enumOr(input.statusClass, STATUS_CLASSES, 'unknown');\n if (input.requestCategory) {\n event.requestCategory = enumOr(input.requestCategory, REQUEST_CATEGORIES, 'other');\n }\n if (input.paymentMethodCategory) {\n event.paymentMethodCategory = enumOr(\n input.paymentMethodCategory,\n PAYMENT_METHODS,\n 'unknown',\n );\n }\n if (input.checkoutMode) {\n event.checkoutMode = enumOr(input.checkoutMode, CHECKOUT_MODES, 'unknown');\n }\n if (input.layout) event.layout = enumOr(input.layout, LAYOUTS, 'unknown');\n return event;\n}\n\n/** Build a closed SDK technical-error event. */\nexport function buildTelemetryErrorEvent(\n input: BuildTelemetryErrorEventInput,\n): TelemetryErrorEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'technical_error',\n code: enumOr(input.errorCode, ERROR_CODES, 'INTERNAL_SDK_ERROR'),\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n },\n input,\n );\n}\n\n/** Build a typed SDK lifecycle event; arbitrary text is never accepted. */\nexport function buildTelemetryLogEvent(input: BuildTelemetryLogEventInput): TelemetryLogEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'lifecycle',\n name: enumOr(input.name, LOG_NAMES, 'operation.retry'),\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n },\n input,\n );\n}\n\n/** Build a non-error expected checkout outcome. */\nexport function buildTelemetryTerminalEvent(\n input: BuildTelemetryTerminalEventInput,\n): TelemetryExpectedOutcomeEvent {\n const commonInput: BuildTelemetryCommonInput = {\n ...input,\n stage: input.stage ?? 'completion',\n };\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'expected_outcome',\n outcome: enumOr(input.outcome, EXPECTED_OUTCOMES, 'customer_abandoned'),\n stage: enumOr(input.stage, STAGES, 'completion'),\n sequence: safeSequence(input.sequence),\n },\n commonInput,\n );\n}\n\n/** Build a monotonic SDK-owned duration measurement. */\nexport function buildTelemetryPerformanceEvent(\n input: BuildTelemetryPerformanceEventInput,\n): TelemetryPerformanceEvent {\n return addCommonFields(\n {\n eventId: safeUuid(input.eventId),\n class: 'performance',\n stage: enumOr(input.stage, STAGES, 'sdk_initialize'),\n sequence: safeSequence(input.sequence),\n durationMs: safeDuration(input.durationMs),\n durationMode: enumOr(input.durationMode, DURATION_MODES, 'machine'),\n },\n input,\n );\n}\n\n/** Serialize one closed backend-owned v1 telemetry envelope. */\nexport function serializeTelemetryBatch(\n events: readonly TelemetryEvent[],\n options: SerializeTelemetryBatchOptions,\n): string {\n const sanitizedEvents = events.slice(0, TELEMETRY_MAX_BATCH_EVENTS).flatMap((event): TelemetryEvent[] => {\n if (event.class === 'technical_error') {\n return [buildTelemetryErrorEvent({ ...event, errorCode: event.code })];\n }\n if (event.class === 'lifecycle') return [buildTelemetryLogEvent(event)];\n if (event.class === 'expected_outcome') return [buildTelemetryTerminalEvent(event)];\n if (event.class === 'performance') return [buildTelemetryPerformanceEvent(event)];\n return [];\n });\n const envelope: TelemetryBatchEnvelope = {\n schemaVersion: TELEMETRY_SCHEMA_VERSION,\n batchId: safeUuid(options.batchId),\n correlationId: safeUuid(options.correlationId),\n sdk: {\n package: enumOr(options.sdkPackage, SDK_PACKAGES, '@flopay/shared'),\n version: SDK_VERSION.test(options.sdkVersion) ? options.sdkVersion : '0.0.0',\n },\n events: sanitizedEvents,\n };\n return JSON.stringify(envelope);\n}\n","/** FloPay environment — determines which billing API URL is used. */\nexport type FloPayEnvironment = 'staging' | 'production' | 'local';\n\nconst ENV_URL_MAP: Record<FloPayEnvironment, string> = {\n local: 'https://flo.ngrok.pro',\n staging: 'https://api.stage.flopay.com',\n production: 'https://api.flopay.com',\n};\n\nlet globalEnvironment: FloPayEnvironment = 'staging';\n\n/**\n * Configure the FloPay SDK globally. Call once at app startup.\n *\n * The environment determines which billing API URL is used for all\n * FloPay operations (session creation, payment processing, etc.).\n *\n * @example\n * ```ts\n * import { configureFlopay } from '@flopay/shared';\n *\n * // In production\n * configureFlopay({ environment: 'production' });\n *\n * // In staging/development\n * configureFlopay({ environment: 'staging' });\n * ```\n *\n * Alternatively, set the `NEXT_PUBLIC_FLOPAY_ENV` environment variable\n * to `'staging'` or `'production'` — the SDK reads it automatically.\n */\nexport function configureFlopay(config: { environment: FloPayEnvironment }): void {\n globalEnvironment = config.environment;\n}\n\n/** Get the billing API URL for the currently configured environment. */\nexport function getConfiguredBillingApiUrl(): string {\n return ENV_URL_MAP[globalEnvironment];\n}\n\n/** Get the current configured environment. */\nexport function getFloPayEnvironment(): FloPayEnvironment {\n return globalEnvironment;\n}\n","// AUTO-GENERATED — do not edit by hand.\n// Source: https://github.com/datatrans/payment-logos @ 6538b978b60523224332031bf4ac267730268abb (assets/apm/*.svg)\n// Regenerate: pnpm --filter @flopay/shared fetch:logos\n//\n// The Stripe wire identifiers that have a vendored brand logo. The logo SVGs\n// themselves live in @flopay/react as sibling `.svg` assets (loaded via <img>),\n// not as inline strings here — a card-only checkout ships none of their bytes.\n// This list only records *which* methods have one, so `hasVendoredStripeMethodLogo`\n// can size the tile logo/label gap without importing any SVG markup.\nexport const VENDORED_LOGO_METHODS: readonly string[] = [\n 'alipay',\n 'bancontact',\n 'blik',\n 'eps',\n 'giropay',\n 'ideal',\n 'klarna',\n 'p24',\n 'sepa_debit',\n 'wechat_pay',\n];\n","import type {\n AVSFieldConfig,\n ButtonsLayoutStyles,\n ButtonsLayoutTheme,\n CountryOption,\n CurrencyInfo,\n FloPayAppearance,\n ThemeBundle,\n ThemeBundleId,\n ThemeId,\n} from './types.js';\n\nimport type { FloPayEnvironment } from './config.js';\nimport { getConfiguredBillingApiUrl } from './config.js';\n// Vendored brand logos (datatrans/payment-logos), generated by\n// `pnpm --filter @flopay/shared fetch:logos`. Methods present here render\n// their real logo on the tile button; methods absent fall back to the\n// generated placeholder mark below.\nimport { VENDORED_LOGO_METHODS } from './payment-logos.generated.js';\n\n// ---------------------------------------------------------------------------\n// SDK Version & API\n// ---------------------------------------------------------------------------\n\n/** Current SDK version. */\nexport const SDK_VERSION = '1.4.1';\n\n/**\n * HTTP header the SDK sends on `POST /v1/checkouts/sessions` so the backend\n * provides compatibility visibility on session create/read requests. Vault\n * capability is part of the session contract and must not be gated by this\n * value.\n *\n * @see SDK_VERSION — the value sent in this header.\n */\nexport const FLO_SDK_VERSION_HEADER = 'x-flo-sdk-version';\n\n/** Billing API URL for staging environment. */\nexport const BILLING_API_URL_STAGING = 'https://api.stage.flopay.com';\n\n/** Billing API URL for production environment. */\nexport const BILLING_API_URL_PRODUCTION = 'https://api.flopay.com';\n\n/** Default FloPay API base URL (used by @flopay/node). Alias for staging. */\nexport const DEFAULT_API_BASE_URL = BILLING_API_URL_STAGING;\n\n/** Default billing API base URL. Alias for staging — prefer `resolveBillingApiUrl()`. */\nexport const BILLING_API_URL = BILLING_API_URL_STAGING;\n\n/**\n * Resolve the billing API URL from available configuration.\n *\n * Priority:\n * 1. Explicit `billingApiUrl` (prop/param override)\n * 2. `NEXT_PUBLIC_FLOPAY_ENV` environment variable (`'staging'` | `'production'`)\n * 3. `configureFlopay()` global environment setting\n * 4. Fallback: staging URL\n *\n * @example\n * ```ts\n * import { resolveBillingApiUrl } from '@flopay/shared';\n *\n * // Reads from env var or configureFlopay() — no args needed\n * const url = resolveBillingApiUrl();\n *\n * // Explicit override takes priority\n * const url = resolveBillingApiUrl('https://custom.example.com');\n * ```\n */\nexport function resolveBillingApiUrl(billingApiUrl?: string): string {\n if (billingApiUrl) return billingApiUrl;\n\n // Environment variable (works in Next.js and bundlers that inline process.env)\n if (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_FLOPAY_ENV) {\n const env = process.env.NEXT_PUBLIC_FLOPAY_ENV as FloPayEnvironment;\n if (env === 'production') return BILLING_API_URL_PRODUCTION;\n return BILLING_API_URL_STAGING;\n }\n\n // Global config from configureFlopay()\n return getConfiguredBillingApiUrl();\n}\n\n/** Default API version header value. */\nexport const DEFAULT_API_VERSION = '2024-01-01';\n\n// ---------------------------------------------------------------------------\n// Default Themes\n// ---------------------------------------------------------------------------\n\n/** The default appearance applied when no custom appearance is provided. */\nexport const DEFAULT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#4A49FF',\n colorBackground: '#FFFFFF',\n colorText: '#262833',\n colorDanger: '#DF1B41',\n borderRadius: '8px',\n fontFamily: 'Poppins, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '4px',\n },\n};\n\n/** Flat theme — minimal borders and shadows. */\nexport const FLAT_APPEARANCE: FloPayAppearance = {\n theme: 'flat',\n variables: {\n ...DEFAULT_APPEARANCE.variables,\n borderRadius: '4px',\n },\n};\n\n/** Night theme — dark background. */\nexport const NIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#7B7BFF',\n colorBackground: '#1A1A2E',\n colorText: '#E0E0E0',\n colorDanger: '#FF6B6B',\n borderRadius: '8px',\n fontFamily: 'Poppins, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '4px',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme Bundles — appearance halves\n//\n// Each bundle pairs a `*_APPEARANCE` (Stripe-side) with a matching\n// `BUTTONS_LAYOUT_*` (FloPay-side wrapper) defined further below. The\n// `THEMES` map at the bottom of this file ties them together so consumers can\n// pick a bundle by id.\n// ---------------------------------------------------------------------------\n\n/** Modern light — clean & airy: Inter, soft shadows, generous spacing, 12px radius. */\nexport const MODERN_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#0F172A',\n colorDanger: '#EF4444',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n padding: '14px 16px',\n border: '1.5px solid #E5E7EB',\n boxShadow: '0 1px 2px rgba(15,23,42,0.04)',\n },\n '.Input:focus': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 4px rgba(23,133,224,0.12)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#475569',\n marginBottom: '6px',\n },\n '.Tab': {\n padding: '12px 16px',\n borderRadius: '12px',\n border: '1.5px solid #E5E7EB',\n },\n '.Tab:hover': {\n borderColor: '#CBD5E1',\n },\n '.Tab--selected': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 1px #1785E0',\n },\n },\n};\n\n/** Modern dark — clean & airy on a deep-blue surface, 12px radius. */\nexport const MODERN_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0B1220',\n colorText: '#F1F5F9',\n colorDanger: '#F87171',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: '#111827',\n padding: '14px 16px',\n border: '1.5px solid #1F2937',\n color: '#F1F5F9',\n boxShadow: 'none',\n },\n '.Input:focus': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 4px rgba(96,165,250,0.18)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#94A3B8',\n marginBottom: '6px',\n },\n '.Tab': {\n padding: '12px 16px',\n borderRadius: '12px',\n border: '1.5px solid #1F2937',\n backgroundColor: '#111827',\n color: '#F1F5F9',\n },\n '.Tab:hover': {\n borderColor: '#374151',\n },\n '.Tab--selected': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 1px #60A5FA',\n },\n },\n};\n\n/** Bold light — vibrant: saturated primary, gradient submit, heavier weights. */\nexport const BOLD_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#0C2B4D',\n colorDanger: '#DC2626',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n padding: '14px 16px',\n border: '2px solid #E5E7EB',\n },\n '.Input:focus': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 3px rgba(23,133,224,0.2)',\n },\n '.Label': {\n fontWeight: '600',\n color: '#0C2B4D',\n },\n '.Tab': {\n padding: '14px 18px',\n border: '2px solid #E5E7EB',\n fontWeight: '600',\n },\n '.Tab--selected': {\n borderColor: '#1785E0',\n boxShadow: '0 0 0 1px #1785E0',\n },\n },\n};\n\n/** Bold dark — saturated deep-blue surface, gradient submit. */\nexport const BOLD_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0C2B4D',\n colorText: '#FFFFFF',\n colorDanger: '#F87171',\n borderRadius: '12px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '16px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: '#1E3A8A',\n padding: '14px 16px',\n border: '2px solid #1E40AF',\n color: '#FFFFFF',\n },\n '.Input:focus': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 3px rgba(96,165,250,0.25)',\n },\n '.Label': {\n fontWeight: '600',\n color: '#DBEAFE',\n },\n '.Tab': {\n padding: '14px 18px',\n border: '2px solid #1E40AF',\n backgroundColor: '#1E3A8A',\n color: '#FFFFFF',\n fontWeight: '600',\n },\n '.Tab--selected': {\n borderColor: '#60A5FA',\n boxShadow: '0 0 0 1px #60A5FA',\n },\n },\n};\n\n/** Glass light — translucent surfaces with backdrop blur over a pastel blue gradient. */\nexport const GLASS_LIGHT_APPEARANCE: FloPayAppearance = {\n theme: 'default',\n variables: {\n colorPrimary: '#1785E0',\n colorBackground: '#FFFFFF',\n colorText: '#1E293B',\n colorDanger: '#EF4444',\n borderRadius: '16px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: 'rgba(255,255,255,0.6)',\n backdropFilter: 'blur(10px)',\n padding: '14px 16px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.5), 0 1px 3px rgba(23,133,224,0.08)',\n },\n '.Input:focus': {\n borderColor: 'rgba(23,133,224,0.5)',\n boxShadow: '0 0 0 3px rgba(23,133,224,0.15)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#475569',\n },\n '.Tab': {\n padding: '12px 16px',\n backgroundColor: 'rgba(255,255,255,0.5)',\n border: '1px solid rgba(255,255,255,0.6)',\n borderRadius: '14px',\n },\n '.Tab--selected': {\n borderColor: 'rgba(23,133,224,0.6)',\n boxShadow: '0 0 0 1px rgba(23,133,224,0.6)',\n },\n },\n};\n\n/** Glass dark — translucent surfaces with backdrop blur over a deep-blue gradient. */\nexport const GLASS_DARK_APPEARANCE: FloPayAppearance = {\n theme: 'night',\n variables: {\n colorPrimary: '#60A5FA',\n colorBackground: '#0F172A',\n colorText: '#F1F5F9',\n colorDanger: '#F87171',\n borderRadius: '16px',\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSizeBase: '15px',\n spacingUnit: '5px',\n },\n rules: {\n '.Input': {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(10px)',\n padding: '14px 16px',\n border: '1px solid rgba(255,255,255,0.08)',\n color: '#F1F5F9',\n },\n '.Input:focus': {\n borderColor: 'rgba(96,165,250,0.5)',\n boxShadow: '0 0 0 3px rgba(96,165,250,0.2)',\n },\n '.Label': {\n fontWeight: '500',\n color: '#94A3B8',\n },\n '.Tab': {\n padding: '12px 16px',\n backgroundColor: 'rgba(15,23,42,0.6)',\n border: '1px solid rgba(255,255,255,0.08)',\n borderRadius: '14px',\n color: '#F1F5F9',\n },\n '.Tab--selected': {\n borderColor: 'rgba(96,165,250,0.6)',\n boxShadow: '0 0 0 1px rgba(96,165,250,0.6)',\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Buttons Layout Theme Presets\n// ---------------------------------------------------------------------------\n\n/** Default buttons layout — white card button, neutral borders. */\nexport const BUTTONS_LAYOUT_DEFAULT: ButtonsLayoutStyles = {};\n\n/** Minimal buttons layout — borderless, subtle hover. */\nexport const BUTTONS_LAYOUT_MINIMAL: ButtonsLayoutStyles = {\n cardButton: {\n border: 'none',\n backgroundColor: '#f9fafb',\n boxShadow: 'none',\n },\n cardFormContainer: {\n backgroundColor: '#f9fafb',\n border: 'none',\n },\n cardInputBorder: '#e5e7eb',\n backButtonIcon: {\n backgroundColor: '#e5e7eb',\n },\n submitButton: {\n borderRadius: '6px',\n },\n};\n\n/** Rounded buttons layout — large border radius, soft shadows. */\nexport const BUTTONS_LAYOUT_ROUNDED: ButtonsLayoutStyles = {\n cardButton: {\n borderRadius: '9999px',\n border: '1px solid #e5e7eb',\n boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n },\n cardFormContainer: {\n borderRadius: '16px',\n border: '1px solid #e5e7eb',\n boxShadow: '0 2px 8px rgba(0,0,0,0.06)',\n },\n cardInputBorder: '#d1d5db',\n submitButton: {\n borderRadius: '9999px',\n },\n backButtonIcon: {\n backgroundColor: '#f3f4f6',\n },\n};\n\n/** Dark buttons layout — dark backgrounds, light text. */\nexport const BUTTONS_LAYOUT_DARK: ButtonsLayoutStyles = {\n cardButton: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n border: '1px solid #374151',\n boxShadow: 'none',\n },\n cardFormContainer: {\n backgroundColor: '#111827',\n border: '1px solid #374151',\n },\n cardInputBorder: '#4b5563',\n cardInputColor: '#f9fafb',\n cardInputPlaceholderColor: '#6b7280',\n cardInputBackground: '#1f2937',\n nameInput: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n backButton: {\n color: '#9ca3af',\n },\n backButtonIcon: {\n backgroundColor: '#374151',\n },\n submitButton: {\n backgroundColor: '#6366f1',\n },\n title: {\n color: '#f9fafb',\n },\n countrySelect: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n zipInput: {\n backgroundColor: '#1f2937',\n color: '#f9fafb',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Theme Bundles — buttons-layout halves\n//\n// Each block pairs with the matching `*_APPEARANCE` above to produce a\n// coherent look across both the Stripe-rendered nested inputs and the FloPay\n// wrapper (container, title, submit button, back button).\n// ---------------------------------------------------------------------------\n\n/** Modern light — soft surface, 14px radius, FloPay-blue submit with subtle shadow. */\nexport const BUTTONS_LAYOUT_MODERN_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#FAFAFA',\n borderRadius: '20px',\n border: '1px solid #E5E7EB',\n boxShadow: '0 8px 24px rgba(15,23,42,0.04)',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#FFFFFF',\n borderRadius: '14px',\n border: '1.5px solid #E5E7EB',\n boxShadow: '0 1px 2px rgba(15,23,42,0.04)',\n padding: '14px 18px',\n },\n cardInputBorder: '#E5E7EB',\n nameInput: {\n backgroundColor: '#FFFFFF',\n border: '1.5px solid #E5E7EB',\n borderRadius: '14px',\n padding: '14px 16px',\n },\n submitButton: {\n backgroundColor: '#1785E0',\n borderRadius: '14px',\n padding: '16px 24px',\n boxShadow: '0 4px 14px rgba(23,133,224,0.25)',\n fontWeight: '600',\n },\n title: {\n color: '#0F172A',\n fontWeight: '600',\n },\n titleFontSize: '20px',\n backButton: { color: '#64748B' },\n backButtonIcon: { backgroundColor: '#F1F5F9' },\n};\n\n/** Modern dark — deep surface, 14px radius, sky-blue submit. */\nexport const BUTTONS_LAYOUT_MODERN_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#111827',\n borderRadius: '20px',\n border: '1px solid #1F2937',\n boxShadow: '0 8px 24px rgba(0,0,0,0.2)',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#0B1220',\n borderRadius: '14px',\n border: '1.5px solid #1F2937',\n color: '#F1F5F9',\n padding: '14px 18px',\n },\n cardInputBorder: '#1F2937',\n cardInputBackground: '#111827',\n cardInputColor: '#F1F5F9',\n cardInputPlaceholderColor: '#64748B',\n nameInput: {\n backgroundColor: '#111827',\n border: '1.5px solid #1F2937',\n borderRadius: '14px',\n padding: '14px 16px',\n color: '#F1F5F9',\n },\n submitButton: {\n backgroundColor: '#60A5FA',\n borderRadius: '14px',\n padding: '16px 24px',\n boxShadow: '0 4px 14px rgba(96,165,250,0.3)',\n fontWeight: '600',\n color: '#0B1220',\n },\n title: {\n color: '#F1F5F9',\n fontWeight: '600',\n },\n titleFontSize: '20px',\n backButton: { color: '#94A3B8' },\n backButtonIcon: { backgroundColor: '#1F2937' },\n countrySelect: { backgroundColor: '#111827', color: '#F1F5F9' },\n zipInput: { backgroundColor: '#111827', color: '#F1F5F9' },\n};\n\n/** Bold light — blue-tint backdrop, primary-bordered card, gradient pill submit. */\nexport const BUTTONS_LAYOUT_BOLD_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#EFF6FF',\n borderRadius: '20px',\n border: '2px solid #1785E0',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#FFFFFF',\n borderRadius: '12px',\n border: '2px solid #1785E0',\n color: '#1785E0',\n fontWeight: '700',\n padding: '14px 18px',\n },\n cardInputBorder: '#E5E7EB',\n nameInput: {\n backgroundColor: '#FFFFFF',\n border: '2px solid #E5E7EB',\n borderRadius: '12px',\n padding: '14px 16px',\n fontWeight: '500',\n },\n submitButton: {\n background: 'linear-gradient(135deg, #1785E0 0%, #0EA5E9 100%)',\n borderRadius: '9999px',\n padding: '16px 24px',\n boxShadow: '0 10px 25px rgba(23,133,224,0.35)',\n fontWeight: '700',\n color: '#FFFFFF',\n border: 'none',\n },\n submitButtonFontSize: '17px',\n title: {\n color: '#0C2B4D',\n fontWeight: '800',\n letterSpacing: '-0.02em',\n },\n titleFontSize: '22px',\n backButton: { color: '#1785E0', fontWeight: '600' },\n backButtonIcon: { backgroundColor: '#DBEAFE' },\n};\n\n/** Bold dark — saturated deep-blue surface, accented borders, gradient pill submit. */\nexport const BUTTONS_LAYOUT_BOLD_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n backgroundColor: '#1E3A8A',\n borderRadius: '20px',\n border: '2px solid #60A5FA',\n padding: '24px',\n },\n cardButton: {\n backgroundColor: '#0C2B4D',\n borderRadius: '12px',\n border: '2px solid #60A5FA',\n color: '#60A5FA',\n fontWeight: '700',\n padding: '14px 18px',\n },\n cardInputBorder: '#1E40AF',\n cardInputBackground: '#1E3A8A',\n cardInputColor: '#FFFFFF',\n cardInputPlaceholderColor: '#60A5FA',\n nameInput: {\n backgroundColor: '#1E3A8A',\n border: '2px solid #1E40AF',\n borderRadius: '12px',\n padding: '14px 16px',\n fontWeight: '500',\n color: '#FFFFFF',\n },\n submitButton: {\n background: 'linear-gradient(135deg, #60A5FA 0%, #38BDF8 100%)',\n borderRadius: '9999px',\n padding: '16px 24px',\n boxShadow: '0 10px 25px rgba(96,165,250,0.35)',\n fontWeight: '700',\n color: '#FFFFFF',\n border: 'none',\n },\n submitButtonFontSize: '17px',\n title: {\n color: '#FFFFFF',\n fontWeight: '800',\n letterSpacing: '-0.02em',\n },\n titleFontSize: '22px',\n backButton: { color: '#DBEAFE', fontWeight: '600' },\n backButtonIcon: { backgroundColor: '#1E40AF' },\n countrySelect: { backgroundColor: '#1E3A8A', color: '#FFFFFF' },\n zipInput: { backgroundColor: '#1E3A8A', color: '#FFFFFF' },\n};\n\n/** Glass light — translucent surfaces with backdrop blur over a pastel blue gradient. */\nexport const BUTTONS_LAYOUT_GLASS_LIGHT: ButtonsLayoutStyles = {\n cardFormContainer: {\n background: 'linear-gradient(135deg, #DBEAFE 0%, #BFDBFE 100%)',\n borderRadius: '24px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.6), 0 12px 40px rgba(23,133,224,0.15)',\n padding: '28px',\n },\n cardButton: {\n backgroundColor: 'rgba(255,255,255,0.7)',\n backdropFilter: 'blur(20px)',\n borderRadius: '16px',\n border: '1px solid rgba(255,255,255,0.6)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.5), 0 4px 16px rgba(23,133,224,0.1)',\n padding: '14px 18px',\n },\n cardInputBorder: 'rgba(255,255,255,0.6)',\n nameInput: {\n backgroundColor: 'rgba(255,255,255,0.6)',\n backdropFilter: 'blur(10px)',\n border: '1px solid rgba(255,255,255,0.6)',\n borderRadius: '14px',\n padding: '14px 16px',\n },\n submitButton: {\n backgroundColor: 'rgba(23,133,224,0.95)',\n backdropFilter: 'blur(10px)',\n borderRadius: '16px',\n padding: '16px 24px',\n boxShadow: '0 10px 30px rgba(23,133,224,0.3), inset 0 1px 0 rgba(255,255,255,0.2)',\n fontWeight: '600',\n color: '#FFFFFF',\n },\n title: {\n color: '#1E293B',\n fontWeight: '600',\n letterSpacing: '-0.01em',\n },\n titleFontSize: '20px',\n backButton: { color: '#1785E0', fontWeight: '500' },\n backButtonIcon: { backgroundColor: 'rgba(255,255,255,0.7)' },\n};\n\n/** Glass dark — translucent surfaces with backdrop blur over a deep-blue gradient. */\nexport const BUTTONS_LAYOUT_GLASS_DARK: ButtonsLayoutStyles = {\n cardFormContainer: {\n background: 'linear-gradient(135deg, #0C2B4D 0%, #0F172A 100%)',\n borderRadius: '24px',\n border: '1px solid rgba(255,255,255,0.08)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.06), 0 20px 50px rgba(0,0,0,0.4)',\n padding: '28px',\n },\n cardButton: {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(20px)',\n borderRadius: '16px',\n border: '1px solid rgba(255,255,255,0.08)',\n boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.05), 0 4px 16px rgba(0,0,0,0.3)',\n padding: '14px 18px',\n color: '#F1F5F9',\n },\n cardInputBorder: 'rgba(255,255,255,0.08)',\n cardInputBackground: 'rgba(15,23,42,0.6)',\n cardInputColor: '#F1F5F9',\n cardInputPlaceholderColor: '#64748B',\n nameInput: {\n backgroundColor: 'rgba(15,23,42,0.6)',\n backdropFilter: 'blur(10px)',\n border: '1px solid rgba(255,255,255,0.08)',\n borderRadius: '14px',\n padding: '14px 16px',\n color: '#F1F5F9',\n },\n submitButton: {\n backgroundColor: 'rgba(96,165,250,0.9)',\n backdropFilter: 'blur(10px)',\n borderRadius: '16px',\n padding: '16px 24px',\n boxShadow: '0 10px 30px rgba(96,165,250,0.35), inset 0 1px 0 rgba(255,255,255,0.15)',\n fontWeight: '600',\n color: '#0F172A',\n },\n title: {\n color: '#F1F5F9',\n fontWeight: '600',\n letterSpacing: '-0.01em',\n },\n titleFontSize: '20px',\n backButton: { color: '#60A5FA', fontWeight: '500' },\n backButtonIcon: { backgroundColor: 'rgba(255,255,255,0.08)' },\n countrySelect: { backgroundColor: 'rgba(15,23,42,0.6)', color: '#F1F5F9' },\n zipInput: { backgroundColor: 'rgba(15,23,42,0.6)', color: '#F1F5F9' },\n};\n\n/** Resolve a buttons layout theme name to its style preset. */\nexport function resolveButtonsLayoutTheme(theme?: ButtonsLayoutTheme): ButtonsLayoutStyles {\n switch (theme) {\n case 'minimal': return BUTTONS_LAYOUT_MINIMAL;\n case 'rounded': return BUTTONS_LAYOUT_ROUNDED;\n case 'dark': return BUTTONS_LAYOUT_DARK;\n case 'modern-light': return BUTTONS_LAYOUT_MODERN_LIGHT;\n case 'modern-dark': return BUTTONS_LAYOUT_MODERN_DARK;\n case 'bold-light': return BUTTONS_LAYOUT_BOLD_LIGHT;\n case 'bold-dark': return BUTTONS_LAYOUT_BOLD_DARK;\n case 'glass-light': return BUTTONS_LAYOUT_GLASS_LIGHT;\n case 'glass-dark': return BUTTONS_LAYOUT_GLASS_DARK;\n default: return BUTTONS_LAYOUT_DEFAULT;\n }\n}\n\n/**\n * First-class theme bundles. Each entry pairs a `FloPayAppearance` (for Stripe\n * Elements) with a `ButtonsLayoutStyles` (for the FloPay wrapper) so the look\n * is coherent across both halves. Consumers can pick by id without having to\n * import the two halves separately.\n *\n * @example\n * ```tsx\n * import { THEMES } from '@flopay/shared';\n *\n * const { appearance, buttonsLayout } = THEMES['glass-dark'];\n * <FloPayCheckout appearance={appearance} buttonsLayoutStyles={buttonsLayout} />\n * ```\n */\nexport const THEMES: Record<ThemeBundleId, ThemeBundle> = {\n 'modern-light': { appearance: MODERN_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_MODERN_LIGHT },\n 'modern-dark': { appearance: MODERN_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_MODERN_DARK },\n 'bold-light': { appearance: BOLD_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_BOLD_LIGHT },\n 'bold-dark': { appearance: BOLD_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_BOLD_DARK },\n 'glass-light': { appearance: GLASS_LIGHT_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_GLASS_LIGHT },\n 'glass-dark': { appearance: GLASS_DARK_APPEARANCE, buttonsLayout: BUTTONS_LAYOUT_GLASS_DARK },\n};\n\n/**\n * Resolve a {@link ThemeId} to its {@link ThemeBundle}, or `undefined` for\n * `'classic'` / a missing id (the historic FloPay look with no bundle applied).\n *\n * Used by FloPay React components when consumers pass the high-level `theme`\n * prop instead of supplying `appearance` + `buttonsStyles` manually. Explicit\n * `appearance` / `buttonsStyles` props still override the resolved bundle.\n */\nexport function resolveTheme(id?: ThemeId | null): ThemeBundle | undefined {\n if (!id || id === 'classic') return undefined;\n return THEMES[id];\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Payment Method partitioning\n// ---------------------------------------------------------------------------\n\n/**\n * Map Stripe wire identifiers (`apple_pay`, `google_pay`, `amazon_pay`) to the\n * camelCase keys that `ExpressCheckoutElement`'s `paymentMethods` options\n * map expects. Everything not in this map is already camelCase compatible.\n */\nexport function stripeExpressMethodToOptionKey(method: string): string {\n switch (method) {\n case 'apple_pay': return 'applePay';\n case 'google_pay': return 'googlePay';\n case 'amazon_pay': return 'amazonPay';\n default: return method;\n }\n}\n\n/**\n * Per-method metadata for every Stripe payment-method type the SDK\n * recognises. One source of truth instead of half a dozen disjoint maps —\n * `STRIPE_METHOD_CURRENCIES`, `STRIPE_METHOD_AMOUNT_LIMITS`, the React\n * package's display-name table, and the inline-form heuristic all derive\n * from entries here.\n *\n * Source: Stripe payment-method support matrices at\n * <https://docs.stripe.com/payments/payment-methods/integration-options>.\n * Update entries when Stripe ships a new currency / amount limit / method\n * — the SDK falls back to safe defaults for any wire identifier not listed.\n */\nexport interface StripeMethodEntry {\n /**\n * Human-readable label, used by consumers for \"Pay with X\" buttons and\n * other UI surfaces that need the brand name.\n */\n displayName: string;\n /**\n * Lowercase ISO-4217 currency codes Stripe accepts for this method. The\n * sentinel `'*'` means \"currency-agnostic\" — only the universal big-button\n * wallets (Apple Pay / Google Pay) use this today.\n */\n currencies: readonly string[];\n /**\n * Uppercase ISO 3166-1 alpha-2 codes for the buyer countries Stripe makes\n * this method available to (matched against the session customer's\n * country). Many local APMs are country-gated independently of currency —\n * Bancontact is Belgium-only, EPS Austria-only, iDEAL Netherlands-only,\n * SEPA Debit the whole SEPA zone — so a EUR cart still must not offer\n * Bancontact to a Dutch buyer.\n *\n * **Omit** for methods with no meaningful country restriction (the global\n * wallets, Alipay, Klarna, …) — a missing list means \"no country gate\", so\n * the method passes {@link filterStripeMethodsByCountry} for every buyer.\n */\n countries?: readonly string[];\n /**\n * Per-currency amount min/max in the smallest currency unit (cents for USD,\n * pence for GBP, etc.). Omit when there is no notable limit. Stripe's\n * `/v1/elements/sessions` rejects the whole accordion when an entry is in\n * `paymentMethodTypes` and the deferred-intent amount falls outside its\n * advertised range, so filtering here matches Stripe's reality.\n */\n amounts?: Record<string, { min?: number; max?: number }>;\n /**\n * True when this method renders inside Stripe's `ExpressCheckoutElement`\n * (apple_pay, google_pay, paypal, link, amazon_pay, klarna). Everything\n * else lives in the `PaymentElement` accordion.\n */\n express?: boolean;\n /**\n * When `false`, the SDK auto-submits the moment the buyer clicks the\n * method card — the buyer is taken straight to Stripe's authorization UI\n * (popup / redirect) without an intermediate confirm step. Only set this\n * for *pure* redirect-only methods that have no inline data collection\n * (Cash App, Affirm).\n *\n * **Default `true`**: render an explicit \"Pay with X\" button at the\n * bottom of the accordion. Safer-by-default — any new/unknown APM, or\n * any method whose Stripe UI changes to add inline inputs, will surface\n * a deliberate confirm action instead of silently auto-submitting on a\n * stray keystroke. Bancontact / Giropay are theoretically redirect-only\n * but ship with a Name input by default, so they stay on the default\n * (button) path.\n */\n needsExplicitConfirm?: boolean;\n /**\n * Per-mode brand styling for the method tile button. The SDK looks up\n * `theme.dark` when the active FloPay theme is one of the `*-dark`\n * bundles, otherwise `theme.light` (also used for `classic`, since\n * brand assets are designed primarily against light surfaces).\n *\n * Entries are optional — methods without a `theme` fall back to the\n * neutral tile styling derived from the theme's `buttonsStyles.cardButton`\n * + `derivePrimaryTileStyle`. Consumers can override per-tile via\n * `buttonAppearance` on the inner component.\n */\n theme?: {\n light?: StripeMethodThemeVariant;\n dark?: StripeMethodThemeVariant;\n };\n}\n\n/**\n * Per-mode visual treatment for a Stripe method tile button. Applies brand\n * colors and (optionally) an inline mark so each APM tile reads\n * unmistakably as itself.\n *\n * `logoSvg` is an inline SVG string rendered at ~22px tall inside the\n * button before the label. The SDK ships a small generic placeholder mark\n * per method (a colored disc + initial) authored as original geometry —\n * **not** a reproduction of any official trademarked logo. Consumers who\n * have rights to a brand's artwork can replace these per-entry by\n * overriding the matrix in their own deployment.\n */\nexport interface StripeMethodThemeVariant {\n backgroundColor?: string;\n borderColor?: string;\n textColor?: string;\n /**\n * Inline SVG markup, e.g. `'<svg viewBox=\"0 0 24 24\">…</svg>'`. Trusted\n * by the renderer (mounted via `dangerouslySetInnerHTML`) — only edit\n * via this matrix or a controlled override; never wire user input here.\n */\n logoSvg?: string;\n}\n\n/**\n * Helper for building the SDK's default placeholder marks: a filled disc\n * with a single-character glyph centered in a contrasting color. Original\n * geometry — not a reproduction of any official brand artwork.\n */\nfunction buildPlaceholderMark(glyph: string, discColor: string, glyphColor: string): string {\n // Hand-rolled SVG so the matrix entries below stay declarative and tiny.\n // `font-family` falls through to the host page's sans-serif to keep the\n // SDK's bundle free of font assets.\n return (\n '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-hidden=\"true\">' +\n `<circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"${discColor}\"/>` +\n `<text x=\"11\" y=\"15.5\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" ` +\n `font-family=\"-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif\" ` +\n `fill=\"${glyphColor}\">${glyph}</text>` +\n '</svg>'\n );\n}\n\n/**\n * Bank-building glyph for the Bank Transfer (`customer_balance`) tile — a\n * pediment + columns + base on a coloured disc. Hand-rolled SVG so the matrix\n * stays declarative and the bundle carries no image assets.\n */\nfunction buildBankMark(discColor: string, glyphColor: string): string {\n return (\n '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-hidden=\"true\">' +\n `<circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"${discColor}\"/>` +\n `<g fill=\"${glyphColor}\">` +\n '<path d=\"M11 4 L17.5 8 L4.5 8 Z\"/>' +\n '<rect x=\"5\" y=\"8.4\" width=\"12\" height=\"1.2\" rx=\"0.3\"/>' +\n '<rect x=\"5.9\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"8.55\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"11.95\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"14.6\" y=\"10\" width=\"1.5\" height=\"5\"/>' +\n '<rect x=\"4.6\" y=\"15.4\" width=\"12.8\" height=\"1.5\" rx=\"0.3\"/>' +\n '</g>' +\n '</svg>'\n );\n}\n\n/**\n * Buyer countries covered by the SEPA Direct Debit scheme (ISO 3166-1\n * alpha-2). Used as `sepa_debit.countries` so the method is offered to the\n * whole SEPA zone — the EU/EEA plus the handful of non-EEA participants\n * (CH, GB, MC, SM, AD, VA) — rather than a single country.\n */\nconst SEPA_COUNTRIES: readonly string[] = [\n 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR',\n 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO',\n 'SE', 'SI', 'SK',\n 'IS', 'LI', 'NO', // EEA non-EU\n 'CH', 'GB', 'MC', 'SM', 'AD', 'VA', // non-EEA SEPA participants\n];\n\n/**\n * Buyer countries Bank Transfer (`customer_balance`) is offered to: the whole\n * of Europe (the SEPA zone, which includes the UK) plus Japan, Mexico and the\n * US. Settled in EUR or USD only.\n */\nconst BANK_TRANSFER_COUNTRIES: readonly string[] = [...SEPA_COUNTRIES, 'JP', 'MX', 'US'];\n\nexport const STRIPE_METHOD_MATRIX: Record<string, StripeMethodEntry> = {\n // ─── Express wallets ────────────────────────────────────────────────────\n apple_pay: {\n displayName: 'Apple Pay',\n currencies: ['*'],\n express: true,\n needsExplicitConfirm: false,\n },\n google_pay: {\n displayName: 'Google Pay',\n currencies: ['*'],\n express: true,\n needsExplicitConfirm: false,\n },\n paypal: {\n displayName: 'PayPal',\n currencies: ['eur', 'gbp', 'usd', 'cad', 'aud', 'nzd', 'chf', 'jpy', 'pln', 'sek', 'nok', 'dkk', 'czk', 'huf'],\n express: true,\n needsExplicitConfirm: false,\n },\n link: {\n displayName: 'Link',\n currencies: ['usd', 'eur'],\n express: true,\n needsExplicitConfirm: false,\n },\n amazon_pay: {\n displayName: 'Amazon Pay',\n currencies: ['usd', 'eur', 'gbp'],\n express: true,\n needsExplicitConfirm: false,\n },\n\n // ─── Klarna: PaymentElement tile, explicit confirm ─────────────────────\n // Klarna renders as a PaymentElement tile (NOT express) so it always appears\n // when the backend includes it in `enabledPaymentMethods`. Stripe's\n // ExpressCheckoutElement only paints a Klarna button in eligible *real*\n // browsers (never headless), which made it effectively invisible and looked\n // like an SDK-level disable — as a tile it's purely backend-driven. Klarna\n // may redirect during confirm, but it still surfaces a deliberate \"Pay with\n // Klarna\" step: it omits `needsExplicitConfirm: false`, so the default\n // `needsStripeMethodExplicitConfirm(...) === true` applies — unlike the\n // auto-confirm APMs below.\n klarna: {\n displayName: 'Klarna',\n currencies: ['usd', 'eur', 'gbp', 'aud', 'nzd', 'cad', 'chf', 'sek', 'nok', 'dkk', 'pln', 'czk', 'ron'],\n amounts: { usd: { min: 100 }, eur: { min: 100 }, gbp: { min: 100 } },\n // Default (explicit \"Pay with Klarna\" button) — Klarna's PaymentElement can\n // collect inline data and isn't a pure redirect-only method, so surface a\n // deliberate confirm rather than auto-submitting on tile click.\n theme: {\n light: {\n backgroundColor: '#FFB3C7',\n textColor: '#0A0B09',\n borderColor: '#FFB3C7',\n logoSvg: buildPlaceholderMark('K', '#0A0B09', '#FFB3C7'),\n },\n dark: {\n backgroundColor: '#FFB3C7',\n textColor: '#0A0B09',\n borderColor: '#FFB3C7',\n logoSvg: buildPlaceholderMark('K', '#0A0B09', '#FFB3C7'),\n },\n },\n },\n // ─── PaymentElement APMs: auto-confirm (redirect-only, no Pay button) ───\n // Affirm and Cash App Pay are pure redirect/handoff methods with no inline\n // inputs, so they auto-submit on tile click (`needsExplicitConfirm: false`).\n //\n // Affirm currently rejects on non-USD currencies via\n // /v1/elements/sessions, hence the narrow currency list. Below $35.00 USD\n // it returns `amount_too_small` and blanks out the whole accordion, hence\n // the explicit min — see `filterStripeMethodsByAmount` for the gate.\n affirm: {\n displayName: 'Affirm',\n currencies: ['usd'],\n countries: ['US', 'CA'],\n amounts: { usd: { min: 3500, max: 3_000_000 } },\n needsExplicitConfirm: false,\n theme: {\n light: {\n backgroundColor: '#060F33',\n textColor: '#FFFFFF',\n borderColor: '#060F33',\n logoSvg: buildPlaceholderMark('a', '#FFFFFF', '#060F33'),\n },\n dark: {\n backgroundColor: '#0FA0EA',\n textColor: '#060F33',\n borderColor: '#0FA0EA',\n logoSvg: buildPlaceholderMark('a', '#060F33', '#FFFFFF'),\n },\n },\n },\n cashapp: {\n displayName: 'Cash App Pay',\n currencies: ['usd'],\n countries: ['US'],\n // Cash App Pay cannot process a $0 (or sub-$0.50) charge — Stripe rejects\n // `amount_too_small`. Range per Stripe: USD 0.50 – 999,999.99. Keeps a\n // free-trial ($0 today) cart from surfacing a Cash App button.\n amounts: { usd: { min: 50, max: 99_999_999 } },\n needsExplicitConfirm: false,\n theme: {\n light: {\n backgroundColor: '#00D54B',\n textColor: '#0A1F0E',\n borderColor: '#00D54B',\n logoSvg: buildPlaceholderMark('$', '#0A1F0E', '#00D54B'),\n },\n dark: {\n backgroundColor: '#00D54B',\n textColor: '#0A1F0E',\n borderColor: '#00D54B',\n logoSvg: buildPlaceholderMark('$', '#0A1F0E', '#00D54B'),\n },\n },\n },\n\n // ─── PaymentElement APMs: default (explicit Pay button) ─────────────────\n // These methods either render an inline form (IBAN, bank picker, …) or\n // ship with a Name input by default. Either way the buyer expects to\n // review and confirm with a deliberate click, so we surface a Pay button\n // and never auto-submit on a `change` event.\n afterpay_clearpay: {\n displayName: 'Afterpay',\n currencies: ['usd', 'aud', 'cad', 'gbp', 'nzd'],\n countries: ['US', 'CA', 'GB', 'AU', 'NZ'],\n amounts: {\n usd: { min: 100, max: 200_000 },\n cad: { min: 100, max: 200_000 },\n gbp: { min: 100, max: 120_000 },\n aud: { min: 100, max: 200_000 },\n nzd: { min: 100, max: 200_000 },\n },\n // Afterpay's brand mint (#B2FCE4) with black wordmark/icon — the signature\n // palette from afterpay.com's brand system.\n theme: {\n light: {\n backgroundColor: '#B2FCE4',\n textColor: '#0A0B09',\n borderColor: '#B2FCE4',\n logoSvg: buildPlaceholderMark('A', '#0A0B09', '#B2FCE4'),\n },\n dark: {\n backgroundColor: '#B2FCE4',\n textColor: '#0A0B09',\n borderColor: '#B2FCE4',\n logoSvg: buildPlaceholderMark('A', '#0A0B09', '#B2FCE4'),\n },\n },\n },\n alipay: {\n displayName: 'Alipay',\n // Presentment currencies only — Alipay is offered to USD / CNY carts.\n currencies: ['usd', 'cny'],\n theme: {\n light: {\n backgroundColor: '#1677FF',\n textColor: '#FFFFFF',\n borderColor: '#1677FF',\n logoSvg: buildPlaceholderMark('A', '#FFFFFF', '#1677FF'),\n },\n dark: {\n backgroundColor: '#1677FF',\n textColor: '#FFFFFF',\n borderColor: '#1677FF',\n logoSvg: buildPlaceholderMark('A', '#FFFFFF', '#1677FF'),\n },\n },\n },\n au_becs_debit: { displayName: 'BECS Direct Debit', currencies: ['aud'], countries: ['AU'] },\n bacs_debit: { displayName: 'Bacs Debit', currencies: ['gbp'], countries: ['GB'] },\n bancontact: {\n displayName: 'Bancontact',\n currencies: ['eur'],\n countries: ['BE'],\n theme: {\n light: {\n backgroundColor: '#FFDD55',\n textColor: '#1E3791',\n borderColor: '#FFDD55',\n logoSvg: buildPlaceholderMark('B', '#1E3791', '#FFDD55'),\n },\n dark: {\n backgroundColor: '#1E3791',\n textColor: '#FFDD55',\n borderColor: '#1E3791',\n logoSvg: buildPlaceholderMark('B', '#FFDD55', '#1E3791'),\n },\n },\n },\n bizum: {\n displayName: 'Bizum',\n currencies: ['eur'],\n countries: ['ES'],\n theme: {\n light: {\n backgroundColor: '#00BFB3',\n textColor: '#FFFFFF',\n borderColor: '#00BFB3',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#00BFB3'),\n },\n dark: {\n backgroundColor: '#00BFB3',\n textColor: '#FFFFFF',\n borderColor: '#00BFB3',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#00BFB3'),\n },\n },\n },\n blik: {\n displayName: 'BLIK',\n currencies: ['pln'],\n countries: ['PL'],\n theme: {\n light: {\n backgroundColor: '#000000',\n textColor: '#FFFFFF',\n borderColor: '#000000',\n logoSvg: buildPlaceholderMark('B', '#FFFFFF', '#000000'),\n },\n dark: {\n backgroundColor: '#FFFFFF',\n textColor: '#000000',\n borderColor: '#FFFFFF',\n logoSvg: buildPlaceholderMark('B', '#000000', '#FFFFFF'),\n },\n },\n },\n boleto: { displayName: 'Boleto', currencies: ['brl'], countries: ['BR'] },\n customer_balance: {\n displayName: 'Bank Transfer',\n currencies: ['eur', 'usd'],\n countries: BANK_TRANSFER_COUNTRIES,\n theme: {\n light: {\n backgroundColor: '#1F2937',\n textColor: '#FFFFFF',\n borderColor: '#1F2937',\n logoSvg: buildBankMark('#1F2937', '#FFFFFF'),\n },\n dark: {\n backgroundColor: '#374151',\n textColor: '#FFFFFF',\n borderColor: '#374151',\n logoSvg: buildBankMark('#374151', '#FFFFFF'),\n },\n },\n },\n eps: {\n displayName: 'EPS',\n currencies: ['eur'],\n countries: ['AT'],\n theme: {\n light: {\n backgroundColor: '#C8102E',\n textColor: '#FFFFFF',\n borderColor: '#C8102E',\n logoSvg: buildPlaceholderMark('E', '#FFFFFF', '#C8102E'),\n },\n dark: {\n backgroundColor: '#C8102E',\n textColor: '#FFFFFF',\n borderColor: '#C8102E',\n logoSvg: buildPlaceholderMark('E', '#FFFFFF', '#C8102E'),\n },\n },\n },\n giropay: {\n displayName: 'Giropay',\n currencies: ['eur'],\n countries: ['DE'],\n theme: {\n light: {\n backgroundColor: '#0F4197',\n textColor: '#FFFFFF',\n borderColor: '#0F4197',\n logoSvg: buildPlaceholderMark('G', '#FFFFFF', '#0F4197'),\n },\n dark: {\n backgroundColor: '#0F4197',\n textColor: '#FFFFFF',\n borderColor: '#0F4197',\n logoSvg: buildPlaceholderMark('G', '#FFFFFF', '#0F4197'),\n },\n },\n },\n ideal: {\n displayName: 'iDEAL',\n currencies: ['eur'],\n countries: ['NL'],\n theme: {\n light: {\n backgroundColor: '#CC0066',\n textColor: '#FFFFFF',\n borderColor: '#CC0066',\n logoSvg: buildPlaceholderMark('i', '#FFFFFF', '#CC0066'),\n },\n dark: {\n backgroundColor: '#CC0066',\n textColor: '#FFFFFF',\n borderColor: '#CC0066',\n logoSvg: buildPlaceholderMark('i', '#FFFFFF', '#CC0066'),\n },\n },\n },\n konbini: { displayName: 'Konbini', currencies: ['jpy'], countries: ['JP'] },\n kr_card: {\n displayName: 'Korean Card',\n currencies: ['krw'],\n countries: ['KR'],\n theme: {\n light: {\n backgroundColor: '#0B3D91',\n textColor: '#FFFFFF',\n borderColor: '#0B3D91',\n logoSvg: buildPlaceholderMark('K', '#FFFFFF', '#0B3D91'),\n },\n dark: {\n backgroundColor: '#0B3D91',\n textColor: '#FFFFFF',\n borderColor: '#0B3D91',\n logoSvg: buildPlaceholderMark('K', '#FFFFFF', '#0B3D91'),\n },\n },\n },\n multibanco: { displayName: 'Multibanco', currencies: ['eur'], countries: ['PT'] },\n oxxo: { displayName: 'OXXO', currencies: ['mxn'], countries: ['MX'] },\n p24: {\n displayName: 'Przelewy24',\n currencies: ['eur', 'pln'],\n countries: ['PL'],\n theme: {\n light: {\n backgroundColor: '#D90F1B',\n textColor: '#FFFFFF',\n borderColor: '#D90F1B',\n logoSvg: buildPlaceholderMark('P', '#FFFFFF', '#D90F1B'),\n },\n dark: {\n backgroundColor: '#D90F1B',\n textColor: '#FFFFFF',\n borderColor: '#D90F1B',\n logoSvg: buildPlaceholderMark('P', '#FFFFFF', '#D90F1B'),\n },\n },\n },\n paynow: { displayName: 'PayNow', currencies: ['sgd'], countries: ['SG'] },\n pix: { displayName: 'Pix', currencies: ['brl'], countries: ['BR'] },\n promptpay: { displayName: 'PromptPay', currencies: ['thb'], countries: ['TH'] },\n sepa_debit: {\n displayName: 'SEPA Debit',\n currencies: ['eur'],\n countries: SEPA_COUNTRIES,\n theme: {\n // SEPA itself isn't a brand with a saturated palette — use a neutral\n // bank-blue that reads as \"European bank transfer\" without leaning\n // on a specific institution.\n light: {\n backgroundColor: '#10298E',\n textColor: '#FFFFFF',\n borderColor: '#10298E',\n logoSvg: buildPlaceholderMark('€', '#FFFFFF', '#10298E'),\n },\n dark: {\n backgroundColor: '#3056D3',\n textColor: '#FFFFFF',\n borderColor: '#3056D3',\n logoSvg: buildPlaceholderMark('€', '#FFFFFF', '#3056D3'),\n },\n },\n },\n sofort: {\n displayName: 'Sofort',\n currencies: ['eur'],\n countries: ['AT', 'BE', 'DE', 'ES', 'IT', 'NL'],\n theme: {\n light: {\n backgroundColor: '#EF809F',\n textColor: '#FFFFFF',\n borderColor: '#EF809F',\n logoSvg: buildPlaceholderMark('S', '#FFFFFF', '#EF809F'),\n },\n dark: {\n backgroundColor: '#EF809F',\n textColor: '#FFFFFF',\n borderColor: '#EF809F',\n logoSvg: buildPlaceholderMark('S', '#FFFFFF', '#EF809F'),\n },\n },\n },\n upi: {\n displayName: 'UPI',\n currencies: ['inr'],\n countries: ['IN'],\n theme: {\n light: {\n backgroundColor: '#FF7909',\n textColor: '#FFFFFF',\n borderColor: '#FF7909',\n logoSvg: buildPlaceholderMark('U', '#FFFFFF', '#FF7909'),\n },\n dark: {\n backgroundColor: '#FF7909',\n textColor: '#FFFFFF',\n borderColor: '#FF7909',\n logoSvg: buildPlaceholderMark('U', '#FFFFFF', '#FF7909'),\n },\n },\n },\n us_bank_account: { displayName: 'US Bank Account', currencies: ['usd'], countries: ['US'] },\n wechat_pay: {\n displayName: 'WeChat Pay',\n // Presentment currencies only — WeChat Pay is offered to USD / CNY carts.\n currencies: ['usd', 'cny'],\n theme: {\n light: {\n backgroundColor: '#07C160',\n textColor: '#FFFFFF',\n borderColor: '#07C160',\n logoSvg: buildPlaceholderMark('W', '#FFFFFF', '#07C160'),\n },\n dark: {\n backgroundColor: '#07C160',\n textColor: '#FFFFFF',\n borderColor: '#07C160',\n logoSvg: buildPlaceholderMark('W', '#FFFFFF', '#07C160'),\n },\n },\n },\n zip: { displayName: 'Zip', currencies: ['aud'], countries: ['AU', 'NZ'] },\n};\n\n/**\n * Whether a method's `logoSvg` is a vendored real brand logo (from\n * `fetch:logos`) rather than the SDK's generated placeholder mark. Tile\n * buttons use this to size the gap between logo and label: the real logos\n * are self-contained cards that read as a separate mark (8px gap), whereas\n * the generated placeholder monogram reads as part of the label (0px gap).\n */\nexport function hasVendoredStripeMethodLogo(type: string | null | undefined): boolean {\n if (!type) return false;\n return VENDORED_LOGO_METHODS.includes(type);\n}\n\n/**\n * Stripe payment method types that render as native big buttons in the\n * `ExpressCheckoutElement`. Everything else falls into the `PaymentElement`\n * accordion. Derived from {@link STRIPE_METHOD_MATRIX} entries flagged\n * `express: true` — insertion order in the matrix dictates the wallet-row\n * ordering (apple_pay → google_pay → paypal → link → amazon_pay → klarna).\n */\nexport const STRIPE_EXPRESS_METHODS: readonly string[] = Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.express)\n .map(([key]) => key);\n\nconst STRIPE_EXPRESS_METHODS_SET: ReadonlySet<string> = new Set(STRIPE_EXPRESS_METHODS);\n\n/**\n * Stripe payment-method → supported-currencies map. Derived from\n * {@link STRIPE_METHOD_MATRIX} — kept as a separate export for callers that\n * just want the currency list without the rest of the entry.\n *\n * Stripe rejects the entire `PaymentElement` mount with an `IntegrationError`\n * when `paymentMethodTypes` contains a method that doesn't support the session\n * currency (e.g. `bancontact` on a USD session). The SDK drops those methods\n * before forwarding them to Stripe so a single mis-matched method doesn't\n * blank out the whole accordion.\n *\n * Unknown methods (anything not in the matrix) pass through unchanged so a\n * brand-new Stripe APM keeps working until the matrix is refreshed.\n */\nexport const STRIPE_METHOD_CURRENCIES: Record<string, readonly string[]> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX).map(([key, entry]) => [key, entry.currencies]),\n);\n\n/**\n * Stripe payment-method → supported-buyer-countries map (uppercase ISO\n * 3166-1 alpha-2). Derived from {@link STRIPE_METHOD_MATRIX}; only methods\n * that declared a `countries` list appear here. Methods absent from this map\n * have no country gate and are offered to every buyer (subject to the\n * currency / amount filters).\n *\n * Local APMs like Bancontact (BE), EPS (AT) and iDEAL (NL) are available\n * only to buyers in their home country even on a EUR cart, so the SDK drops\n * them when the session customer's country doesn't match — mirroring what\n * Stripe's `PaymentElement` would do from the buyer's locale anyway.\n */\nexport const STRIPE_METHOD_COUNTRIES: Record<string, readonly string[]> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.countries)\n .map(([key, entry]) => [key, entry.countries as readonly string[]]),\n);\n\n/**\n * Display-name lookup. Falls back to a title-cased version of the wire id\n * (e.g. `au_becs_debit` → `Au Becs Debit`) for methods not in the matrix so\n * a brand-new APM still produces a legible label until the matrix catches up.\n */\nexport function getStripeMethodDisplayName(type: string | null | undefined): string {\n if (!type) return 'this method';\n const entry = STRIPE_METHOD_MATRIX[type];\n if (entry) return entry.displayName;\n return type\n .split('_')\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\n/**\n * Whether the SDK should render an explicit \"Pay with X\" button for this\n * method rather than auto-submitting on click. Defaults to `true` (safer for\n * unknown methods) — only methods explicitly flagged `needsExplicitConfirm:\n * false` in the matrix (Cash App, Affirm) auto-submit.\n */\nexport function needsStripeMethodExplicitConfirm(type: string | null | undefined): boolean {\n if (!type) return true;\n const entry = STRIPE_METHOD_MATRIX[type];\n if (!entry) return true;\n return entry.needsExplicitConfirm !== false;\n}\n\n/**\n * Resolve the per-mode brand styling for a method tile button, given the\n * active FloPay theme id. Returns `null` when the method has no `theme`\n * entry in the matrix — callers fall back to the neutral tile styling\n * derived from `buttonsStyles.cardButton`.\n *\n * Theme-id → variant rule:\n * - `*-dark` themes get `theme.dark` (then `theme.light` as fallback).\n * - Everything else (`classic`, `*-light`, undefined) gets `theme.light`.\n */\nexport function resolveStripeMethodBrandVariant(\n type: string | null | undefined,\n themeId: ThemeId | null | undefined,\n): StripeMethodThemeVariant | null {\n if (!type) return null;\n const entry = STRIPE_METHOD_MATRIX[type];\n if (!entry?.theme) return null;\n const isDark = typeof themeId === 'string' && themeId.endsWith('-dark');\n // Returns theme colours + the placeholder mark only. The vendored real brand\n // logo (when `hasVendoredStripeMethodLogo`) is an <img> asset owned by\n // @flopay/react, so the SVG markup never enters this package's JS.\n return (isDark ? entry.theme.dark : entry.theme.light) ?? entry.theme.light ?? null;\n}\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those that\n * support the supplied ISO-4217 currency code. Unknown methods (anything not\n * in {@link STRIPE_METHOD_CURRENCIES}) pass through unchanged so a brand-new\n * Stripe APM keeps working until the SDK ships an updated map.\n *\n * The currency comparison is case-insensitive (`USD` and `usd` both match).\n * An empty / missing currency disables filtering entirely (returns the input\n * list as-is) — callers that don't know the currency are still better off\n * letting Stripe fail loudly than dropping everything to silence.\n */\nexport function filterStripeMethodsByCurrency(\n methods: readonly string[] | undefined,\n currency: string | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!currency) return [...methods];\n const target = currency.trim().toLowerCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const supported = STRIPE_METHOD_CURRENCIES[method];\n if (!supported) return true; // unknown method → pass through\n return supported.includes('*') || supported.includes(target);\n });\n}\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those available\n * to the supplied buyer country (ISO 3166-1 alpha-2). Methods with no country\n * gate in {@link STRIPE_METHOD_COUNTRIES} — the global wallets, Alipay,\n * Klarna, unknown methods — pass through unchanged.\n *\n * The country comparison is case-insensitive (`be` and `BE` both match). An\n * empty / missing country disables filtering entirely (returns the input list\n * as-is) — when the session doesn't know the buyer's country we'd rather let\n * Stripe make the final call than drop every country-gated method.\n */\nexport function filterStripeMethodsByCountry(\n methods: readonly string[] | undefined,\n country: string | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!country) return [...methods];\n const target = country.trim().toUpperCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const supported = STRIPE_METHOD_COUNTRIES[method];\n if (!supported) return true; // no country gate → pass through\n return supported.includes('*') || supported.includes(target);\n });\n}\n\n/**\n * Per-method amount limits (in the smallest currency unit, e.g. cents for USD)\n * keyed by Stripe wire identifier and then currency code. Derived from\n * {@link STRIPE_METHOD_MATRIX} — kept as a separate export for callers that\n * just want the amount limits without the rest of the entry.\n *\n * Stripe's `/v1/elements/sessions` endpoint hard-400's when\n * `paymentMethodTypes` contains a method whose per-currency minimum or\n * maximum is violated by the deferred-intent amount — and a single rejected\n * method blanks out the entire `PaymentElement` accordion (\"Frame not\n * initialized\" / empty `<div class=\"\">` shell). Filtering here matches\n * Stripe's reality so an incompatible amount silently drops the offending\n * method instead of poisoning the whole mount.\n */\nexport const STRIPE_METHOD_AMOUNT_LIMITS: Record<\n string,\n Record<string, { min?: number; max?: number }>\n> = Object.fromEntries(\n Object.entries(STRIPE_METHOD_MATRIX)\n .filter(([, entry]) => entry.amounts)\n .map(([key, entry]) => [key, entry.amounts as Record<string, { min?: number; max?: number }>]),\n);\n\n/**\n * Filter a Stripe payment-method wire-identifier list down to those whose\n * per-currency amount range accepts {@link amountInMinorUnits}. Unknown methods\n * (anything not in {@link STRIPE_METHOD_AMOUNT_LIMITS}) pass through unchanged\n * so a brand-new Stripe APM keeps working without an SDK update.\n *\n * Currency comparison is case-insensitive. Missing currency / amount disables\n * filtering — callers that don't know the cart yet should pass through the\n * full list rather than silently dropping everything.\n */\nexport function filterStripeMethodsByAmount(\n methods: readonly string[] | undefined,\n currency: string | undefined,\n amountInMinorUnits: number | undefined,\n): string[] {\n if (!methods?.length) return [];\n if (!currency || typeof amountInMinorUnits !== 'number' || !Number.isFinite(amountInMinorUnits)) {\n return [...methods];\n }\n const target = currency.trim().toLowerCase();\n if (!target) return [...methods];\n return methods.filter((method) => {\n const perCurrency = STRIPE_METHOD_AMOUNT_LIMITS[method];\n if (!perCurrency) return true;\n const limits = perCurrency[target];\n if (!limits) return true;\n if (typeof limits.min === 'number' && amountInMinorUnits < limits.min) return false;\n if (typeof limits.max === 'number' && amountInMinorUnits > limits.max) return false;\n return true;\n });\n}\n\n/**\n * Partition the backend's `enabledPaymentMethods` list into the two SDK\n * regions inside `SplitCardForm`:\n *\n * - `expressMethods` — intersected with {@link STRIPE_EXPRESS_METHODS} so\n * only `ExpressCheckoutElement`-supported methods land in the big-button\n * row.\n * - `paymentElementMethods` — every remaining method (Cash App Pay, Affirm,\n * iDEAL, Bancontact, SEPA debit, …) for the `PaymentElement` accordion.\n *\n * `card` is dropped from both lists — the card path stays on the split\n * fields. When `options.excludePaypal` is `true`, the SDK is rendering\n * `DirectPayPalButton` separately and PayPal is also pulled out of the\n * express list to avoid double-rendering.\n */\nexport function partitionStripeMethods(\n enabledPaymentMethods: readonly string[] | undefined,\n options?: { excludePaypal?: boolean },\n): { expressMethods: string[]; paymentElementMethods: string[] } {\n if (!enabledPaymentMethods?.length) {\n return { expressMethods: [], paymentElementMethods: [] };\n }\n const expressMethods: string[] = [];\n const paymentElementMethods: string[] = [];\n const seenExpress = new Set<string>();\n const seenElement = new Set<string>();\n\n for (const raw of enabledPaymentMethods) {\n if (typeof raw !== 'string') continue;\n const method = raw.trim();\n if (!method || method === 'card') continue;\n if (options?.excludePaypal && method === 'paypal') continue;\n\n if (STRIPE_EXPRESS_METHODS_SET.has(method)) {\n if (seenExpress.has(method)) continue;\n seenExpress.add(method);\n expressMethods.push(method);\n } else {\n if (seenElement.has(method)) continue;\n seenElement.add(method);\n paymentElementMethods.push(method);\n }\n }\n return { expressMethods, paymentElementMethods };\n}\n\n// ---------------------------------------------------------------------------\n// Supported Element Types\n// ---------------------------------------------------------------------------\n\n/** All supported element type identifiers. */\nexport const ELEMENT_TYPES = [\n 'payment',\n 'address',\n] as const;\n\n// ---------------------------------------------------------------------------\n// Supported Card Brands\n// ---------------------------------------------------------------------------\n\nexport const SUPPORTED_CARD_BRANDS = [\n 'visa',\n 'mastercard',\n 'mastercard_debit',\n 'amex',\n 'discover',\n] as const;\n\n// ---------------------------------------------------------------------------\n// Currency Mapping (from checkout project)\n// ---------------------------------------------------------------------------\n\n/** Country code to currency information mapping. */\nexport const CURRENCY_MAP: Record<string, CurrencyInfo> = {\n // EUR (VAT applies)\n AT: { currency: 'EUR', symbol: '\\u20AC', country: 'Austria', countryCode: 'AT', tax: 1 },\n BE: { currency: 'EUR', symbol: '\\u20AC', country: 'Belgium', countryCode: 'BE', tax: 1 },\n CY: { currency: 'EUR', symbol: '\\u20AC', country: 'Cyprus', countryCode: 'CY', tax: 1 },\n DE: { currency: 'EUR', symbol: '\\u20AC', country: 'Germany', countryCode: 'DE', tax: 1 },\n EE: { currency: 'EUR', symbol: '\\u20AC', country: 'Estonia', countryCode: 'EE', tax: 1 },\n ES: { currency: 'EUR', symbol: '\\u20AC', country: 'Spain', countryCode: 'ES', tax: 1 },\n FI: { currency: 'EUR', symbol: '\\u20AC', country: 'Finland', countryCode: 'FI', tax: 1 },\n FR: { currency: 'EUR', symbol: '\\u20AC', country: 'France', countryCode: 'FR', tax: 1 },\n GR: { currency: 'EUR', symbol: '\\u20AC', country: 'Greece', countryCode: 'GR', tax: 1 },\n HR: { currency: 'EUR', symbol: '\\u20AC', country: 'Croatia', countryCode: 'HR', tax: 1 },\n IE: { currency: 'EUR', symbol: '\\u20AC', country: 'Ireland', countryCode: 'IE', tax: 1 },\n IT: { currency: 'EUR', symbol: '\\u20AC', country: 'Italy', countryCode: 'IT', tax: 1 },\n LT: { currency: 'EUR', symbol: '\\u20AC', country: 'Lithuania', countryCode: 'LT', tax: 1 },\n LU: { currency: 'EUR', symbol: '\\u20AC', country: 'Luxembourg', countryCode: 'LU', tax: 1 },\n LV: { currency: 'EUR', symbol: '\\u20AC', country: 'Latvia', countryCode: 'LV', tax: 1 },\n MT: { currency: 'EUR', symbol: '\\u20AC', country: 'Malta', countryCode: 'MT', tax: 1 },\n NL: { currency: 'EUR', symbol: '\\u20AC', country: 'Netherlands', countryCode: 'NL', tax: 1 },\n PT: { currency: 'EUR', symbol: '\\u20AC', country: 'Portugal', countryCode: 'PT', tax: 1 },\n SI: { currency: 'EUR', symbol: '\\u20AC', country: 'Slovenia', countryCode: 'SI', tax: 1 },\n SK: { currency: 'EUR', symbol: '\\u20AC', country: 'Slovakia', countryCode: 'SK', tax: 1 },\n BG: { currency: 'EUR', symbol: '\\u20AC', country: 'Bulgaria', countryCode: 'BG', tax: 1 },\n RO: { currency: 'EUR', symbol: '\\u20AC', country: 'Romania', countryCode: 'RO', tax: 1 },\n CZ: { currency: 'EUR', symbol: '\\u20AC', country: 'Czech Republic', countryCode: 'CZ', tax: 1 },\n SE: { currency: 'EUR', symbol: '\\u20AC', country: 'Sweden', countryCode: 'SE', tax: 1 },\n DK: { currency: 'EUR', symbol: '\\u20AC', country: 'Denmark', countryCode: 'DK', tax: 1 },\n PL: { currency: 'EUR', symbol: '\\u20AC', country: 'Poland', countryCode: 'PL', tax: 1 },\n HU: { currency: 'EUR', symbol: '\\u20AC', country: 'Hungary', countryCode: 'HU', tax: 1 },\n // GBP (VAT applies)\n GB: { currency: 'GBP', symbol: '\\u00A3', country: 'United Kingdom', countryCode: 'GB', tax: 1 },\n // USD (no VAT)\n US: { currency: 'USD', symbol: '$', country: 'United States', countryCode: 'US', tax: 0 },\n // CAD (no VAT)\n CA: { currency: 'CAD', symbol: 'CA$', country: 'Canada', countryCode: 'CA', tax: 0 },\n // NZD (no VAT)\n NZ: { currency: 'NZD', symbol: 'NZ$', country: 'New Zealand', countryCode: 'NZ', tax: 0 },\n // AUD (no VAT)\n AU: { currency: 'AUD', symbol: 'AU$', country: 'Australia', countryCode: 'AU', tax: 0 },\n};\n\n/** Default currency info when country is unknown. */\nexport const DEFAULT_CURRENCY: CurrencyInfo = {\n currency: 'USD',\n symbol: '$',\n country: 'United States',\n countryCode: 'US',\n tax: 0,\n};\n\n// ---------------------------------------------------------------------------\n// Postal Code Labels\n// ---------------------------------------------------------------------------\n\n/** Returns the correct postal code label for a country code (ISO 3166-1 alpha-2). */\nexport function getPostalCodeLabel(countryCode: string): string {\n switch (countryCode.toUpperCase()) {\n case 'US': return 'ZIP Code';\n case 'GB': return 'Postcode';\n case 'CA': return 'Postal Code';\n case 'AU':\n case 'NZ': return 'Postcode';\n case 'IE': return 'Eircode';\n default: return 'Postal Code';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Country List (ISO 3166-1 alpha-2)\n// ---------------------------------------------------------------------------\n\nconst regionNames = new Intl.DisplayNames(['en'], { type: 'region' });\n\nfunction codeToFlag(code: string): string {\n return [...code.toUpperCase()]\n .map((c) => String.fromCodePoint(0x1f1e6 - 65 + c.charCodeAt(0)))\n .join('');\n}\n\n/** Priority countries shown first in dropdowns. */\nconst PRIORITY_CODES = ['US', 'GB', 'CA', 'AU', 'NZ', 'IE', 'DE', 'FR'];\n\nconst ALL_CODES = [\n 'AD', 'AE', 'AF', 'AG', 'AL', 'AM', 'AO', 'AR', 'AT', 'AU',\n 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ',\n 'BN', 'BO', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CD',\n 'CF', 'CG', 'CH', 'CI', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU',\n 'CV', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC',\n 'EE', 'EG', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FM', 'FR', 'GA',\n 'GB', 'GD', 'GE', 'GH', 'GM', 'GN', 'GQ', 'GR', 'GT', 'GW',\n 'GY', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IQ',\n 'IR', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI',\n 'KM', 'KN', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK',\n 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME',\n 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MR', 'MT', 'MU', 'MV',\n 'MW', 'MX', 'MY', 'MZ', 'NA', 'NE', 'NG', 'NI', 'NL', 'NO',\n 'NP', 'NR', 'NZ', 'OM', 'PA', 'PE', 'PG', 'PH', 'PK', 'PL',\n 'PT', 'PW', 'PY', 'QA', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB',\n 'SC', 'SD', 'SE', 'SG', 'SI', 'SK', 'SL', 'SM', 'SN', 'SO',\n 'SR', 'SS', 'ST', 'SV', 'SY', 'SZ', 'TD', 'TG', 'TH', 'TJ',\n 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA',\n 'UG', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VN', 'VU', 'WS',\n 'XK', 'YE', 'ZA', 'ZM', 'ZW',\n] as const;\n\nfunction buildCountryOption(code: string): CountryOption {\n return { code, name: regionNames.of(code) ?? code, flag: codeToFlag(code) };\n}\n\nconst prioritySet = new Set(PRIORITY_CODES);\nconst rest = ALL_CODES.filter((c) => !prioritySet.has(c));\n\n/** All countries for dropdown select, priority countries first. */\nexport const COUNTRY_OPTIONS: CountryOption[] = [\n ...PRIORITY_CODES.map(buildCountryOption),\n ...rest.map(buildCountryOption),\n];\n\n/** Look up a country option by ISO 3166-1 alpha-2 code. */\nexport function getCountryByCode(code: string): CountryOption | undefined {\n return COUNTRY_OPTIONS.find((c) => c.code === code);\n}\n\n// ---------------------------------------------------------------------------\n// AVS Configuration Helpers\n// ---------------------------------------------------------------------------\n\n/** Default AVS config when `enableAVS: true` (backward compatible — country + postal code). */\nconst DEFAULT_AVS_CONFIG: AVSFieldConfig = {\n country: true,\n postal_code: true,\n};\n\n/**\n * Normalize `enableAVS` to a resolved config object.\n * - `false` / `undefined` → `null` (AVS disabled)\n * - `true` → default config (country + postal_code)\n * - `AVSFieldConfig` → returned as-is\n */\nexport function resolveAVSConfig(enableAVS?: boolean | AVSFieldConfig): AVSFieldConfig | null {\n if (!enableAVS) return null;\n if (enableAVS === true) return DEFAULT_AVS_CONFIG;\n return enableAVS;\n}\n\n/**\n * Check if an AVS field should be visible for the given country.\n * - `undefined` / `false` → hidden\n * - `true` → visible for all countries\n * - `string[]` (non-empty) → visible only for listed country codes\n * - `[]` (empty) → visible for no countries; use `true` to show everywhere.\n * A UI that wants \"clear the country list = show everywhere\" must normalize\n * the cleared list to `true` before persisting — preserves the historical\n * `[]` = \"off\" semantics so existing configs don't start rendering AVS\n * globally.\n */\nexport function isAVSFieldVisible(\n field: boolean | string[] | undefined,\n country: string,\n): boolean {\n if (field === undefined || field === false) return false;\n if (field === true) return true;\n const normalizedCountry = country.trim().toUpperCase();\n return field.some((code) => code.trim().toUpperCase() === normalizedCountry);\n}\n\n/** Returns true if any AVS field is meaningfully configured (at least one field is truthy). */\nexport function isAVSEnabled(enableAVS?: boolean | AVSFieldConfig): boolean {\n const config = resolveAVSConfig(enableAVS);\n if (!config) return false;\n // `true` or a non-empty array means the field is configured to render;\n // only `false`/`undefined`/`[]` is \"off\".\n return Object.values(config).some(\n (v) => v === true || (Array.isArray(v) && v.length > 0),\n );\n}\n\n// ---------------------------------------------------------------------------\n// US States & CA Provinces\n// ---------------------------------------------------------------------------\n\nexport interface StateOption {\n code: string;\n name: string;\n}\n\nexport const US_STATES: StateOption[] = [\n { code: 'AL', name: 'Alabama' },\n { code: 'AK', name: 'Alaska' },\n { code: 'AZ', name: 'Arizona' },\n { code: 'AR', name: 'Arkansas' },\n { code: 'CA', name: 'California' },\n { code: 'CO', name: 'Colorado' },\n { code: 'CT', name: 'Connecticut' },\n { code: 'DE', name: 'Delaware' },\n { code: 'DC', name: 'District of Columbia' },\n { code: 'FL', name: 'Florida' },\n { code: 'GA', name: 'Georgia' },\n { code: 'HI', name: 'Hawaii' },\n { code: 'ID', name: 'Idaho' },\n { code: 'IL', name: 'Illinois' },\n { code: 'IN', name: 'Indiana' },\n { code: 'IA', name: 'Iowa' },\n { code: 'KS', name: 'Kansas' },\n { code: 'KY', name: 'Kentucky' },\n { code: 'LA', name: 'Louisiana' },\n { code: 'ME', name: 'Maine' },\n { code: 'MD', name: 'Maryland' },\n { code: 'MA', name: 'Massachusetts' },\n { code: 'MI', name: 'Michigan' },\n { code: 'MN', name: 'Minnesota' },\n { code: 'MS', name: 'Mississippi' },\n { code: 'MO', name: 'Missouri' },\n { code: 'MT', name: 'Montana' },\n { code: 'NE', name: 'Nebraska' },\n { code: 'NV', name: 'Nevada' },\n { code: 'NH', name: 'New Hampshire' },\n { code: 'NJ', name: 'New Jersey' },\n { code: 'NM', name: 'New Mexico' },\n { code: 'NY', name: 'New York' },\n { code: 'NC', name: 'North Carolina' },\n { code: 'ND', name: 'North Dakota' },\n { code: 'OH', name: 'Ohio' },\n { code: 'OK', name: 'Oklahoma' },\n { code: 'OR', name: 'Oregon' },\n { code: 'PA', name: 'Pennsylvania' },\n { code: 'RI', name: 'Rhode Island' },\n { code: 'SC', name: 'South Carolina' },\n { code: 'SD', name: 'South Dakota' },\n { code: 'TN', name: 'Tennessee' },\n { code: 'TX', name: 'Texas' },\n { code: 'UT', name: 'Utah' },\n { code: 'VT', name: 'Vermont' },\n { code: 'VA', name: 'Virginia' },\n { code: 'WA', name: 'Washington' },\n { code: 'WV', name: 'West Virginia' },\n { code: 'WI', name: 'Wisconsin' },\n { code: 'WY', name: 'Wyoming' },\n];\n\nexport const CA_PROVINCES: StateOption[] = [\n { code: 'AB', name: 'Alberta' },\n { code: 'BC', name: 'British Columbia' },\n { code: 'MB', name: 'Manitoba' },\n { code: 'NB', name: 'New Brunswick' },\n { code: 'NL', name: 'Newfoundland and Labrador' },\n { code: 'NS', name: 'Nova Scotia' },\n { code: 'NT', name: 'Northwest Territories' },\n { code: 'NU', name: 'Nunavut' },\n { code: 'ON', name: 'Ontario' },\n { code: 'PE', name: 'Prince Edward Island' },\n { code: 'QC', name: 'Quebec' },\n { code: 'SK', name: 'Saskatchewan' },\n { code: 'YT', name: 'Yukon' },\n];\n\n/**\n * Get state/province options for a country.\n * Returns a list for US and CA, or `null` for countries where a free-text input is appropriate.\n */\nexport function getStateOptions(country: string): StateOption[] | null {\n switch (country.toUpperCase()) {\n case 'US': return US_STATES;\n case 'CA': return CA_PROVINCES;\n default: return null;\n }\n}\n\n/** Returns the appropriate label for the state/province field based on country. */\nexport function getStateLabel(countryCode: string): string {\n switch (countryCode.toUpperCase()) {\n case 'US': return 'State';\n case 'CA': return 'Province';\n case 'GB': return 'County';\n case 'AU': return 'State / Territory';\n default: return 'State / Province / Region';\n }\n}\n","/**\n * Postal-code → state derivation for AVS.\n *\n * Used when the form configuration shows `address_line_1` but hides the\n * `state` input — we still want to populate `billing_details.address.state`\n * so Stripe Radar gets a richer address signal. Currently supports US and CA;\n * other countries return `null` (caller should fall back to omitting state).\n */\n\n/**\n * US 3-digit ZIP-prefix ranges → state code (USPS Sectional Center Facility).\n * Sourced from the public USPS SCF table. Each entry is `[startPrefix, endPrefix, stateCode]`,\n * inclusive on both ends. Coverage is contiguous within a state; gaps in the table\n * (e.g. unused 3-digit prefixes) are intentional and resolve to `null`.\n */\nconst US_ZIP_PREFIX_RANGES: ReadonlyArray<readonly [number, number, string]> = [\n [5, 5, 'NY'],\n [10, 27, 'MA'],\n [28, 29, 'RI'],\n [30, 38, 'NH'],\n [39, 49, 'ME'],\n [50, 59, 'VT'],\n [60, 69, 'CT'],\n [70, 89, 'NJ'],\n [100, 149, 'NY'],\n [150, 196, 'PA'],\n [197, 199, 'DE'],\n [200, 205, 'DC'],\n [206, 219, 'MD'],\n [220, 246, 'VA'],\n [247, 268, 'WV'],\n [270, 289, 'NC'],\n [290, 299, 'SC'],\n [300, 319, 'GA'],\n [320, 349, 'FL'],\n [350, 369, 'AL'],\n [370, 385, 'TN'],\n [386, 397, 'MS'],\n [398, 399, 'GA'],\n [400, 427, 'KY'],\n [430, 459, 'OH'],\n [460, 479, 'IN'],\n [480, 499, 'MI'],\n [500, 528, 'IA'],\n [530, 549, 'WI'],\n [550, 567, 'MN'],\n [570, 577, 'SD'],\n [580, 588, 'ND'],\n [590, 599, 'MT'],\n [600, 629, 'IL'],\n [630, 658, 'MO'],\n [660, 679, 'KS'],\n [680, 693, 'NE'],\n [700, 714, 'LA'],\n [716, 729, 'AR'],\n [730, 749, 'OK'],\n [750, 799, 'TX'],\n [800, 816, 'CO'],\n [820, 831, 'WY'],\n [832, 838, 'ID'],\n [840, 847, 'UT'],\n [850, 865, 'AZ'],\n [870, 884, 'NM'],\n [889, 898, 'NV'],\n [900, 961, 'CA'],\n [967, 968, 'HI'],\n [970, 979, 'OR'],\n [980, 994, 'WA'],\n [995, 999, 'AK'],\n];\n\n/**\n * CA postal-code first letter → province code (Forward Sortation Area).\n * The first letter of every Canadian postal code identifies the province\n * uniquely, except `X` which is shared by Northwest Territories and Nunavut\n * — we resolve it to `NT` because the volume strongly favours NT.\n */\nconst CA_FSA_FIRST_LETTER_TO_PROVINCE: Readonly<Record<string, string>> = {\n A: 'NL',\n B: 'NS',\n C: 'PE',\n E: 'NB',\n G: 'QC',\n H: 'QC',\n J: 'QC',\n K: 'ON',\n L: 'ON',\n M: 'ON',\n N: 'ON',\n P: 'ON',\n R: 'MB',\n S: 'SK',\n T: 'AB',\n V: 'BC',\n X: 'NT',\n Y: 'YT',\n};\n\nfunction deriveUsState(zip: string): string | null {\n const digits = zip.replace(/\\D/g, '');\n if (digits.length < 5) return null;\n const prefix = Number.parseInt(digits.slice(0, 3), 10);\n if (!Number.isFinite(prefix)) return null;\n\n for (const [start, end, code] of US_ZIP_PREFIX_RANGES) {\n if (prefix >= start && prefix <= end) return code;\n }\n return null;\n}\n\nfunction deriveCaProvince(postalCode: string): string | null {\n const compact = postalCode.replace(/\\s+/g, '').toUpperCase();\n if (!/^[A-Z]\\d[A-Z]\\d[A-Z]\\d$/.test(compact)) return null;\n const firstLetter = compact[0] ?? '';\n return CA_FSA_FIRST_LETTER_TO_PROVINCE[firstLetter] ?? null;\n}\n\n/**\n * Resolve a state / province code from a postal code for the given country.\n *\n * - US: 5-digit ZIP → 2-letter USPS state code (uses 3-digit prefix table).\n * - CA: A1A 1A1 → 2-letter ISO 3166-2:CA province code (first-letter mapping).\n * - All other countries: `null`.\n *\n * Returns `null` when the postal code is malformed or falls in an unmapped\n * range. Callers should treat `null` as \"skip — don't derive\".\n */\nexport function getStateFromPostalCode(\n country: string,\n postalCode: string,\n): string | null {\n if (!country || !postalCode) return null;\n const normalizedCountry = country.trim().toUpperCase();\n const normalizedZip = postalCode.trim();\n if (!normalizedZip) return null;\n\n switch (normalizedCountry) {\n case 'US':\n return deriveUsState(normalizedZip);\n case 'CA':\n return deriveCaProvince(normalizedZip);\n default:\n return null;\n }\n}\n","/**\n * Client-side postcode format validation for AVS.\n *\n * A faithful mirror of the backend's authoritative, country-aware postcode\n * check — `is-valid-postal-code.validator.ts` (TeamFloPay/backend#895, pinned\n * `validator@13.15.35`). The SDK reuses the *same* `validator` package's\n * `isPostalCode(str, locale)`, the *same* country→ISO-2 normalization\n * (`COUNTRY_ALIASES` + the 2-letter passthrough), and the *same* fail-open\n * conditions, so the SDK's submit gate never opens on a postcode the deployed\n * `PATCH /v1/checkouts/sessions/{id}/account` validator will reject with a 400\n * (the client/server rule drift behind sdk#124). The set of locales `validator`\n * recognises is the single source of truth:\n *\n * - Supported locale → the postcode is required *and* format-validated; an\n * empty or malformed value blocks submit.\n * - Unsupported / no-postcode locale → validation is skipped (fail open); the\n * field is visible but optional and never blocks.\n *\n * We import the `validator/lib/isPostalCode.js` submodule (not the `validator`\n * barrel) so a consumer's bundler only pulls this one check into the browser\n * bundle instead of the whole `validator` library. The explicit `.js` extension\n * is required: `validator` ships no `exports` map, so Node's native ESM loader\n * only resolves the fully-specified file path.\n */\nimport * as isPostalCodeModule from 'validator/lib/isPostalCode.js';\n\ntype IsPostalCodeFn = (str: string, locale: string) => boolean;\n\n/**\n * The CJS submodule's runtime shape is `{ default: fn, locales: string[] }`.\n * `@types/validator` only declares `default`, and ESM↔CJS interop leaves the\n * namespace's `default` as either the whole `module.exports` object (Node\n * native ESM) or the function itself (esbuild/CJS output). `locales` is a plain\n * named export and is the array in both. Read through a cast and unwrap\n * `default` so the two build outputs behave identically.\n */\nconst mod = isPostalCodeModule as unknown as {\n default: IsPostalCodeFn | { default: IsPostalCodeFn };\n locales: string[];\n};\n\nconst isPostalCode: IsPostalCodeFn =\n typeof mod.default === 'function' ? mod.default : mod.default?.default;\n\n// Fail fast, and loudly, if a third bundler/runtime interop shape slips past the\n// two we anticipate above. Without this, `isPostalCode` would silently be\n// `undefined` at module load and every supported-country check would throw a\n// cryptic `TypeError: isPostalCode is not a function` at submit time instead.\nif (typeof isPostalCode !== 'function') {\n throw new Error(\n \"validator/lib/isPostalCode.js interop failed: unexpected module shape. This likely means the bundler's CJS/ESM interop changed.\",\n );\n}\n\n/** `validator`'s supported ISO 3166-1 alpha-2 postcode locales, normalised to uppercase. */\nconst SUPPORTED_LOCALES: ReadonlySet<string> = new Set(\n mod.locales.map((code) => code.toUpperCase()),\n);\n\n/**\n * Country → ISO 3166-1 alpha-2 aliases, replicated **verbatim** from the backend\n * validator's `COUNTRY_ALIASES` (backend#895) so client and server normalize\n * identically. The SDK's own `COUNTRY_OPTIONS` are already ISO-2, so in practice\n * only the passthrough branch fires here; the full-name / 3-letter aliases exist\n * purely for parity when a caller (or a future field) hands us a non-ISO-2 value.\n *\n * Note the deliberate 2-letter short-circuit in {@link normalizeCountryToIso2}:\n * a 2-letter input is passed straight through *before* this map is consulted, so\n * the 2-letter keys below (`GB`, `US`, `UK`, `CH`, `DE`) are unreachable — they\n * are kept only to mirror the backend map 1:1. This means `UK` normalizes to\n * `UK` (an unsupported `validator` locale → fail open), exactly as the backend\n * does; only the full name `UNITED KINGDOM` / `GREATBRITAIN` maps to `GB`.\n */\nconst COUNTRY_ALIASES: Readonly<Record<string, string>> = {\n AUSTRALIA: 'AU',\n BRAZIL: 'BR',\n CANADA: 'CA',\n CH: 'CH',\n DENMARK: 'DK',\n DE: 'DE',\n DEUTSCHLAND: 'DE',\n FRANCE: 'FR',\n GB: 'GB',\n GERMANY: 'DE',\n GREATBRITAIN: 'GB',\n GREAT_BRITAIN: 'GB',\n INDIA: 'IN',\n IRELAND: 'IE',\n ITALY: 'IT',\n JAPAN: 'JP',\n MEXICO: 'MX',\n NETHERLANDS: 'NL',\n NEWZEALAND: 'NZ',\n NORWAY: 'NO',\n POLAND: 'PL',\n PORTUGAL: 'PT',\n SINGAPORE: 'SG',\n SOUTHAFRICA: 'ZA',\n SPAIN: 'ES',\n SWEDEN: 'SE',\n SWITZERLAND: 'CH',\n UK: 'GB',\n UNITEDKINGDOM: 'GB',\n UNITEDSTATES: 'US',\n US: 'US',\n USA: 'US',\n 'UNITED STATES': 'US',\n 'UNITED KINGDOM': 'GB',\n 'GREAT BRITAIN': 'GB',\n ENGLAND: 'GB',\n};\n\n/**\n * Normalize a country string to an ISO 3166-1 alpha-2 locale, or `null` when it\n * can't be resolved. Mirrors the backend's `normalizeCountryToIso2`:\n * 1. trim + uppercase; blank → `null` (fail open upstream);\n * 2. any 2-letter input is passed straight through (NOT alias-mapped);\n * 3. otherwise look it up in {@link COUNTRY_ALIASES}; unknown → `null`.\n */\nfunction normalizeCountryToIso2(country: string): string | null {\n // Nullish-safe: JS callers (and untyped consumers) may pass null/undefined;\n // treat those as an unresolvable country and fail open rather than throwing.\n const upper = (country ?? '').trim().toUpperCase();\n if (!upper) return null;\n if (upper.length === 2) return upper;\n return COUNTRY_ALIASES[upper] ?? null;\n}\n\n/**\n * ISO 3166-1 alpha-2 → example postcode map, surfaced in the field hint / inline\n * error so the buyer sees the expected shape. Replicated **verbatim** from the\n * backend validator's `POSTAL_CODE_EXAMPLES` (backend#895) so the SDK's own\n * client-side hint shows the *same* example the backend embeds in its 400\n * message (\"Expected format: e.g. {example}\") — the two can never contradict.\n * Every example is verified against `validator`'s own pattern (see the package\n * tests). A supported country absent from this map still validates — the hint,\n * like the backend message, simply omits the example.\n *\n * Exported (module-level, not via the package barrel) so the drift-guard test\n * can derive its country list from this single source of truth instead of\n * hardcoding a subset that silently falls out of sync as entries are added.\n */\nexport const POSTAL_CODE_EXAMPLES: Readonly<Record<string, string>> = {\n AU: '2000',\n BR: '01000-000',\n CA: 'A1A 1A1',\n CH: '8001',\n DE: '10115',\n DK: '1050',\n ES: '28001',\n FR: '75008',\n GB: 'SW1A 1AA',\n IE: 'D02 X285',\n IN: '110001',\n IT: '00118',\n JP: '100-0001',\n MX: '06500',\n NL: '1012 JS',\n NO: '0150',\n NZ: '6011',\n PL: '00-001',\n PT: '1100-148',\n SE: '111 22',\n SG: '018989',\n US: '12345 or 12345-6789',\n ZA: '8001',\n};\n\n/**\n * True when `validator` has an authoritative postcode pattern for the country\n * (normalized to ISO 3166-1 alpha-2 via {@link normalizeCountryToIso2}).\n * Supported countries validate the postcode format; unsupported / no-postcode /\n * unresolvable countries fail open. Note the 2-letter passthrough means `UK`\n * (an unsupported `validator` locale) returns `false` here — matching the\n * backend; use the full name `United Kingdom` for `GB` semantics.\n */\nexport function isPostalCodeSupported(country: string): boolean {\n const iso2 = normalizeCountryToIso2(country);\n return iso2 !== null && SUPPORTED_LOCALES.has(iso2);\n}\n\n/**\n * Validate a postcode against the country's expected format. A faithful mirror\n * of the backend's `isPostalCodeValidForCountry`, so the SDK never blocks a\n * value the server would accept, nor opens the submit gate on one it would\n * reject. Fail-open (returns `true`) in exactly the backend's three cases:\n *\n * - `postalCode` is blank / whitespace-only;\n * - the country can't be normalized to an ISO-2 locale;\n * - the ISO-2 locale isn't one `validator` recognises.\n *\n * Otherwise returns `validator`'s `isPostalCode(zip.trim(), locale)`. Callers\n * that distinguish \"required\" (empty) from \"malformed\" (bad format) must check\n * emptiness themselves — an empty value fails open here, as it does server-side.\n */\nexport function isValidPostalCode(country: string, postalCode: string): boolean {\n // Nullish-safe: a null/undefined postcode fails open (same as blank).\n const trimmed = (postalCode ?? '').trim();\n if (!trimmed) return true;\n const iso2 = normalizeCountryToIso2(country);\n if (iso2 === null || !SUPPORTED_LOCALES.has(iso2)) return true;\n try {\n return isPostalCode(trimmed, iso2);\n } catch {\n return true;\n }\n}\n\n/**\n * The example postcode the backend would embed in its 400 message for the\n * country (e.g. US `12345 or 12345-6789`, GB `SW1A 1AA`, CA `A1A 1A1`), or\n * `undefined` when there is none (unresolvable country, or a supported country\n * absent from {@link POSTAL_CODE_EXAMPLES}).\n */\nexport function getPostalCodeExample(country: string): string | undefined {\n const iso2 = normalizeCountryToIso2(country);\n return iso2 ? POSTAL_CODE_EXAMPLES[iso2] : undefined;\n}\n","import type {\n CheckoutItem,\n CheckoutProduct,\n CheckoutSubscription,\n} from './types.js';\n\n/**\n * Return the trimmed string when it has at least one non-whitespace character,\n * otherwise undefined. Used so that empty and whitespace-only inputs flow\n * through the same fallback chain as `undefined`.\n */\nfunction nonBlank(value: string | null | undefined): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\n/**\n * Resolve the session-level currency, honoring the documented fallback:\n * `session.currency ?? items[*].currency ?? subscriptions[*].currency ?? products[*].currency`.\n *\n * Returns the first non-blank currency found, or `null` when nothing is set.\n * Empty and whitespace-only strings are treated as unset so they do not\n * bypass the fallback chain.\n *\n * Post-#760 backends reject session-create requests without a session-level\n * currency (`@IsNotEmpty`); callers should throw a validation error when\n * this returns `null` rather than silently defaulting.\n */\nexport function resolveSessionCurrency(\n sessionCurrency: string | undefined,\n items?: ReadonlyArray<{ currency?: string }> | undefined,\n subscriptions?: ReadonlyArray<{ currency?: string }> | undefined,\n products?: ReadonlyArray<{ currency?: string }> | undefined,\n): string | null {\n const session = nonBlank(sessionCurrency);\n if (session) return session;\n for (const item of items ?? []) {\n const c = nonBlank(item.currency);\n if (c) return c;\n }\n for (const sub of subscriptions ?? []) {\n const c = nonBlank(sub.currency);\n if (c) return c;\n }\n for (const product of products ?? []) {\n const c = nonBlank(product.currency);\n if (c) return c;\n }\n return null;\n}\n\n/**\n * Fold legacy `items` + `subscriptions` arrays into the unified `products[]`\n * shape introduced by backend #760. Items become `type: 'item'`,\n * subscriptions become `type: 'subscription'`. The relative order is\n * subscriptions-first then items, matching the order the previous payload\n * builders emitted on the wire.\n */\nexport function foldIntoProducts(\n items: readonly CheckoutItem[] | undefined,\n subscriptions: readonly CheckoutSubscription[] | undefined,\n): CheckoutProduct[] {\n const products: CheckoutProduct[] = [];\n\n for (const sub of subscriptions ?? []) {\n products.push({\n type: 'subscription',\n code: nonBlank(sub.code) ?? nonBlank(sub.providerPlanId),\n providerPlanId: sub.providerPlanId,\n name: nonBlank(sub.subscriptionName) ?? nonBlank(sub.providerPlanName) ?? null,\n subscriptionName: sub.subscriptionName ?? null,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount,\n currency: sub.currency,\n metadata: sub.metadata,\n });\n }\n\n for (const item of items ?? []) {\n products.push({\n type: 'item',\n code: nonBlank(item.code) ?? nonBlank(item.providerItemId),\n providerItemId: item.providerItemId,\n name: nonBlank(item.itemName) ?? nonBlank(item.providerItemName) ?? null,\n itemName: item.itemName ?? null,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount,\n currency: item.currency,\n metadata: item.metadata,\n });\n }\n\n return products;\n}\n\n/**\n * Build the request payload for a single product in the unified shape\n * introduced by backend #760. Emits `type`, `code`, `name`, `quantity`,\n * `totalAmount`, `overrideAmount`, `currency`, and optional `metadata`.\n */\nexport function buildProductPayload(\n product: CheckoutProduct,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code =\n nonBlank(product.code)\n ?? nonBlank(product.providerItemId)\n ?? nonBlank(product.providerPlanId);\n if (!code) {\n throw new Error(\n 'CheckoutProduct requires `code` (or the deprecated `providerItemId` / `providerPlanId`).',\n );\n }\n\n const name =\n nonBlank(product.name)\n ?? nonBlank(product.itemName)\n ?? nonBlank(product.providerItemName)\n ?? nonBlank(product.subscriptionName)\n ?? nonBlank(product.providerPlanName)\n ?? null;\n\n const payload: Record<string, unknown> = {\n type: product.type,\n code,\n name,\n quantity: product.quantity ?? 1,\n totalAmount: product.totalAmount,\n overrideAmount: product.overrideAmount ?? null,\n currency: nonBlank(product.currency) ?? sessionCurrency,\n };\n\n if (product.metadata) {\n payload['metadata'] = product.metadata;\n }\n\n return payload;\n}\n\n/**\n * Build the request payload for a single item.\n *\n * @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.\n * Retained until the next major so external callers building the legacy\n * `items[]` payload manually keep working.\n */\nexport function buildItemPayload(\n item: CheckoutItem,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code = nonBlank(item.code) ?? nonBlank(item.providerItemId);\n if (!code) {\n throw new Error('CheckoutItem requires either `code` or the deprecated `providerItemId`.');\n }\n const itemName = nonBlank(item.itemName) ?? nonBlank(item.providerItemName) ?? null;\n\n const payload: Record<string, unknown> = {\n code,\n providerItemId: nonBlank(item.providerItemId) ?? code,\n itemName,\n providerItemName: nonBlank(item.providerItemName) ?? itemName,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: nonBlank(item.currency) ?? sessionCurrency,\n };\n\n if (item.metadata) {\n payload['metadata'] = item.metadata;\n }\n\n return payload;\n}\n\n/**\n * Build the request payload for a single subscription.\n *\n * @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.\n * Retained until the next major so external callers building the legacy\n * `subscriptions[]` payload manually keep working.\n */\nexport function buildSubscriptionPayload(\n subscription: CheckoutSubscription,\n sessionCurrency: string,\n): Record<string, unknown> {\n const code = nonBlank(subscription.code) ?? nonBlank(subscription.providerPlanId);\n if (!code) {\n throw new Error(\n 'CheckoutSubscription requires either `code` or the deprecated `providerPlanId`.',\n );\n }\n const subscriptionName =\n nonBlank(subscription.subscriptionName) ?? nonBlank(subscription.providerPlanName) ?? null;\n\n const payload: Record<string, unknown> = {\n code,\n providerPlanId: nonBlank(subscription.providerPlanId) ?? code,\n subscriptionName,\n providerPlanName: nonBlank(subscription.providerPlanName) ?? subscriptionName,\n quantity: subscription.quantity ?? 1,\n totalAmount: subscription.totalAmount,\n overrideAmount: subscription.overrideAmount ?? null,\n currency: nonBlank(subscription.currency) ?? sessionCurrency,\n };\n\n if (subscription.metadata) {\n payload['metadata'] = subscription.metadata;\n }\n\n return payload;\n}\n","import { resolveSessionCurrency } from './checkout-payload.js';\nimport type { CheckoutSession } from './types.js';\n\n/** A single line item formatted for display in the checkout UI. */\nexport interface DisplayLineItem {\n name: string;\n quantity: number;\n /** Price per unit in the session's currency (major units, e.g. 24.95). */\n price: number;\n /** Original price per unit before any discount (major units). */\n originalPrice: number;\n}\n\n/** Computed display data for rendering an order summary. */\nexport interface CheckoutDisplayData {\n /** Individual items/subscriptions with names, prices, and quantities. */\n items: DisplayLineItem[];\n /** ISO 4217 currency code (uppercase). */\n currency: string;\n /** Total amount due after discounts (major units, e.g. 24.95). */\n total: number;\n /** Sum of original prices before discounts (major units). */\n originalTotal: number;\n /** Total savings (originalTotal - total), clamped to >= 0. */\n totalSave: number;\n /** Discount percentage (0–100). */\n discountPercent: number;\n /**\n * Coupon discount reported by the backend (cart-currency major units),\n * when available. Populated from `session.discountAmount` (billing\n * API ≥ v1.1.2); `undefined` on older backends. Use this to render an\n * explicit \"coupon\" line without recomputing per-item math.\n */\n couponDiscount?: number;\n}\n\n/** Options for {@link buildCheckoutDisplayData}. */\nexport interface BuildCheckoutDisplayDataOptions {\n /**\n * When `true`, items are hidden from the order summary if the session also\n * contains subscriptions (matches the legacy checkout/CheckoutModal\n * behavior). Defaults to `false` — items are always shown.\n */\n hideBundledItems?: boolean;\n}\n\n/**\n * Builds display data from a `CheckoutSession` for rendering an order summary.\n *\n * - Subscriptions are always shown\n * - Items are shown by default; pass `{ hideBundledItems: true }` to suppress\n * them when the session also contains subscriptions (legacy behavior)\n * - `overrideAmount` (when not null/undefined) is the discounted price\n * - Plan name \"4-WEEK PLAN\" with price <= 1 is renamed to \"7-DAY TRIAL: FULL ACCESS\"\n * - Discount percentage and savings are computed from the difference\n *\n * All amounts are in **major currency units** (dollars, not cents).\n *\n * @example\n * ```ts\n * import { buildCheckoutDisplayData } from '@flopay/shared';\n *\n * const display = buildCheckoutDisplayData(session);\n * // display.items → [{ name: 'Starter', price: 24.95, originalPrice: 24.95, quantity: 1 }]\n * // display.total → 24.95\n * // display.currency → 'EUR'\n * ```\n */\nexport function buildCheckoutDisplayData(\n session: CheckoutSession,\n options: BuildCheckoutDisplayDataOptions = {},\n): CheckoutDisplayData {\n const itemsList: DisplayLineItem[] = [];\n\n const products = session.products ?? [];\n const subscriptions = products.filter((p) => p.type === 'subscription');\n // `type` is optional; anything not explicitly a subscription renders as an item.\n const items = products.filter((p) => p.type !== 'subscription');\n\n const resolvedCurrency = resolveSessionCurrency(session.currency, undefined, undefined, products);\n const currency = (resolvedCurrency ?? 'USD').toUpperCase();\n\n // Subscriptions first so the legacy \"subscriptions then items\" ordering is\n // preserved for callers rendering the display list.\n for (const sub of subscriptions) {\n const originalPrice = sub.totalAmount ?? 0;\n const discountedPrice = sub.overrideAmount ?? originalPrice;\n\n // Match checkout/CheckoutModal: rename \"4-WEEK PLAN\" to \"7-DAY TRIAL: FULL ACCESS\"\n // when the discounted price is $1 or less\n let name = sub.name || sub.code || 'Subscription';\n if (name === '4-WEEK PLAN' && discountedPrice <= 1) {\n name = '7-DAY TRIAL: FULL ACCESS';\n }\n\n itemsList.push({\n name,\n quantity: sub.quantity,\n price: discountedPrice,\n originalPrice,\n });\n }\n\n const hideItems =\n options.hideBundledItems === true\n && subscriptions.length > 0\n && items.length > 0;\n\n if (!hideItems) {\n for (const item of items) {\n const originalPrice = item.totalAmount ?? 0;\n const discountedPrice = item.overrideAmount ?? originalPrice;\n\n itemsList.push({\n name: item.name || item.code || 'Item',\n quantity: item.quantity,\n price: discountedPrice,\n originalPrice,\n });\n }\n }\n\n if (itemsList.length === 0) {\n itemsList.push({\n name: 'Purchase',\n quantity: 1,\n price: session.amount / 100,\n originalPrice: session.amount / 100,\n });\n }\n\n const lineOriginalTotal = itemsList.reduce((sum, i) => sum + i.originalPrice * i.quantity, 0);\n const lineTotal = itemsList.reduce((sum, i) => sum + i.price * i.quantity, 0);\n\n // Billing API ≥ v1.1.2 returns the coupon-adjusted totals on the session.\n // When present, they are the source of truth for wallet sheets and order\n // summaries (per-line `overrideAmount` carries item-level discounts but is\n // blind to coupons). Older backends omit these fields — fall back to the\n // per-line computation.\n const hasBackendTotals =\n typeof session.totalAmount === 'number'\n && Number.isFinite(session.totalAmount);\n const hasBackendSubtotal =\n typeof session.subtotalAmount === 'number'\n && Number.isFinite(session.subtotalAmount);\n const hasBackendDiscount =\n typeof session.discountAmount === 'number'\n && Number.isFinite(session.discountAmount);\n\n const total = hasBackendTotals ? (session.totalAmount as number) : lineTotal;\n const originalTotal = hasBackendSubtotal\n ? (session.subtotalAmount as number)\n : lineOriginalTotal;\n const totalSave = Math.max(0, originalTotal - total);\n const discountPercent = originalTotal > 0\n ? Math.round((totalSave / originalTotal) * 100)\n : 0;\n\n return {\n items: itemsList,\n currency,\n total,\n originalTotal,\n totalSave,\n discountPercent,\n ...(hasBackendDiscount ? { couponDiscount: session.discountAmount as number } : {}),\n };\n}\n","import type { CurrencyInfo } from './types.js';\nimport { CURRENCY_MAP, DEFAULT_CURRENCY } from './constants.js';\n\n/**\n * Look up currency information by ISO 3166-1 alpha-2 country code.\n * Falls back to USD when the country is not in the map.\n */\nexport function getCurrencyByCountry(countryCode: string): CurrencyInfo {\n return CURRENCY_MAP[countryCode.toUpperCase()] ?? DEFAULT_CURRENCY;\n}\n\n/** Returns `true` if the string looks like a Stripe publishable key. */\nexport function isValidPublishableKey(key: string): boolean {\n return /^pk_(test|live)_[A-Za-z0-9]+$/.test(key);\n}\n\n/** Returns `true` if the string looks like a Stripe secret key. */\nexport function isValidSecretKey(key: string): boolean {\n return /^sk_(test|live)_[A-Za-z0-9]+$/.test(key);\n}\n\n/**\n * Returns `true` when the client secret belongs to a SetupIntent (`seti_…`).\n * Trial-only / $0 checkouts confirm and retrieve a SetupIntent instead of a\n * PaymentIntent, so callers must route those to `confirmCardSetup` /\n * `retrieveSetupIntent` rather than the PaymentIntent equivalents.\n */\nexport function isSetupIntentClientSecret(clientSecret: string | null | undefined): boolean {\n return typeof clientSecret === 'string' && clientSecret.startsWith('seti_');\n}\n","import { FloPayError } from './errors.js';\n\n/**\n * HTTP header the SDK sends to make checkout-session creation idempotent\n * (TeamFloPay/backend#972, paired SDK issue TeamFloPay/sdk#133).\n *\n * The backend treats the header as **optional**: when it is absent the legacy,\n * non-idempotent creation path runs unchanged. When present, every transport\n * retry of the same logical create reuses the same key so a timeout or lost\n * response cannot mint a second checkout session.\n */\nexport const IDEMPOTENCY_KEY_HEADER = 'Idempotency-Key';\n\n/**\n * Maximum length of an idempotency key accepted by the billing API\n * (TeamFloPay/backend#972). Mirrors the widely-used 255-character ceiling;\n * automatically generated keys stay well under it.\n */\nexport const MAX_IDEMPOTENCY_KEY_LENGTH = 255;\n\n/**\n * Backend `code` (TeamFloPay/backend#972) returned when a checkout-create\n * replay arrives while the first request carrying the same key is still being\n * processed. It is a **retryable** in-progress response: the caller should\n * retry with the *same* key after a short backoff, never with a new key. This\n * is distinct from a payload-conflict (`409`), which is non-retryable.\n *\n * Mirrors a backend-defined code the same way the coupon error codes\n * (`CouponLimitExceeded`, `CouponCurrencyUnsupported`) mirror billing v1.1.2.\n */\nexport const IDEMPOTENCY_IN_PROGRESS_CODE = 'IdempotencyKeyInProgress';\n\ninterface RandomSource {\n randomUUID?: () => string;\n getRandomValues?: <T extends ArrayBufferView | null>(array: T) => T;\n}\n\nfunction getSecureRandomSource(): RandomSource | undefined {\n const source = (globalThis as { crypto?: RandomSource }).crypto;\n if (!source) return undefined;\n if (typeof source.randomUUID === 'function' || typeof source.getRandomValues === 'function') {\n return source;\n }\n return undefined;\n}\n\n/**\n * Generate a cryptographically random, high-entropy idempotency key.\n *\n * Prefers `crypto.randomUUID()` and falls back to 16 random bytes from\n * `crypto.getRandomValues`. Returns `undefined` when no cryptographically\n * secure RNG is available so the caller falls back to the legacy unkeyed path\n * rather than emitting a weak or predictable key.\n *\n * The key is never derived from request data, customer identity, or time, so\n * two independent operations never collide by construction.\n */\nexport function generateIdempotencyKey(): string | undefined {\n const source = getSecureRandomSource();\n if (!source) return undefined;\n\n if (typeof source.randomUUID === 'function') {\n return source.randomUUID();\n }\n\n const bytes = new Uint8Array(16);\n source.getRandomValues!(bytes);\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Resolve the idempotency key for one logical checkout-create operation.\n *\n * - A merchant-supplied key is validated (non-empty, within\n * {@link MAX_IDEMPOTENCY_KEY_LENGTH}) and returned **unchanged** so it can be\n * preserved across React remounts, multiple SDK instances, or server retries\n * the merchant controls.\n * - Otherwise a fresh cryptographically random key is generated. When no secure\n * RNG is available this returns `undefined` and the caller omits the header,\n * preserving the legacy path.\n *\n * @throws FloPayError('validation_error') when a supplied key is empty,\n * whitespace-only, or exceeds the length limit. The offending value is never\n * included in the error message.\n */\nexport function resolveIdempotencyKey(supplied?: string): string | undefined {\n if (supplied === undefined) {\n return generateIdempotencyKey();\n }\n\n if (typeof supplied !== 'string' || supplied.trim() === '') {\n throw new FloPayError(\n 'idempotencyKey must be a non-empty string identifying exactly one checkout creation.',\n 'validation_error',\n { code: 'InvalidIdempotencyKey', param: 'idempotencyKey' },\n );\n }\n\n if (supplied.length > MAX_IDEMPOTENCY_KEY_LENGTH) {\n throw new FloPayError(\n `idempotencyKey must be at most ${MAX_IDEMPOTENCY_KEY_LENGTH} characters.`,\n 'validation_error',\n { code: 'InvalidIdempotencyKey', param: 'idempotencyKey' },\n );\n }\n\n return supplied;\n}\n","/**\n * RFC 4122 v4 UUID shape (case-insensitive). Mirrors the backend's `@IsUUID()`\n * acceptance for the fields the SDK fills, e.g. the session-intent\n * `authorizationAttemptId`.\n */\nexport const UUID_V4 =\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** True when `value` is a v4 UUID string. */\nexport function isUuidV4(value: unknown): value is string {\n return typeof value === 'string' && UUID_V4.test(value);\n}\n\n/**\n * Generate a cryptographically-random v4 UUID.\n *\n * Prefers `crypto.randomUUID()`, falls back to `crypto.getRandomValues`, and\n * only as a last resort to `Math.random`, so the SDK still produces a\n * well-formed UUID in environments without a secure RNG. Unlike\n * {@link generateIdempotencyKey} this never returns `undefined` or a non-UUID\n * string, because callers send it to backend fields validated as `@IsUUID()`\n * (a weak or missing value there is a hard `400`, not a silent downgrade).\n */\nexport function randomUuidV4(): string {\n try {\n const id = globalThis.crypto.randomUUID();\n if (UUID_V4.test(id)) return id;\n } catch {\n // Fall through to the getRandomValues / Math.random compatibility path.\n }\n const bytes = new Uint8Array(16);\n try {\n globalThis.crypto.getRandomValues(bytes);\n } catch {\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n"],"mappings":"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AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,IAAI,IAAI,IAAI;AAAA,EACb,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;AAAA,EACf,CAAC,KAAK,KAAK,IAAI;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","names":["SDK_VERSION","UUID_V4","SDK_VERSION","UUID_V4"]}