import type { ComponentOptionsMixin, DefineComponent, Ref, ShallowRef, VNode } from 'vue-demi'; import type { StripeCheckoutElementsSdk, StripeCheckoutFormSdk, StripeError } from '@stripe/stripe-js'; /** The Stripe element methods the factory relies on. */ export interface StripeElementLike { mount(domElement: HTMLElement | string): void; destroy(): void; on(eventType: string, handler: (...args: unknown[]) => void): unknown; off?(eventType: string, handler?: (...args: unknown[]) => void): unknown; update?(options: Record): unknown; focus?(): void; blur?(): void; clear?(): void; getValue?(...args: unknown[]): Promise; } export interface ElementDefinition { /** `elements.create()` type, e.g. 'card' or 'payment'. */ elementType: string; componentName: string; /** Stripe events re-emitted as Vue events (exact Stripe.js 10 union). Defaults to BASE_EVENTS. */ events?: readonly string[]; /** * Events subscribed on the Stripe element only when the app listens for them, because * subscribing changes Stripe's behaviour (Express Checkout waits for the handler to call * `resolve()` once a `click` handler is attached). */ listenerOnlyEvents?: readonly string[]; /** Options merged under `props.options` (e.g. IBAN supportedCountries). */ defaultOptions?: () => Record; /** Creator inside VueStripeCheckoutElementsProvider; omit when Checkout Sessions lack the element. */ checkout?: (sdk: StripeCheckoutElementsSdk, options: Record) => StripeElementLike; /** Creator inside VueStripeCheckoutFormProvider; omit when the Checkout Form SDK lacks the element. */ checkoutForm?: (sdk: StripeCheckoutFormSdk, options: Record) => StripeElementLike; /** * `false` when `elements.create()` cannot build the type (the Checkout Form, the Currency * Selector): Elements contexts are skipped, and one alone reports the element unavailable. */ elements?: boolean; /** * Set when `elements.create()` needs a group with a `clientSecret` or `mode`: Stripe.js * builds the element on a bare group, then fails asynchronously without `ready` or * `loaderror`. On a bare group the factory reports this message through `loaderror` / * `#error` instead. */ needsIntent?: string; /** * `true` to create the element a tick after mount, once the elements rendered after it * exist: Stripe.js throws when the Currency Selector is created before the Checkout Form. */ createLast?: boolean; /** Extra members for the component's public instance (e.g. getValue). */ expose?: (element: Ref) => Record; loadingText?: string; /** * Option keys `element.update()` refuses (Stripe.js warns or throws), kept out of updates: * the keys of the element's options type missing from its update type ({@link CreateOnly}). */ createOnly?: Record; /** What `ready` emits: the Stripe element (default) or Stripe's ready event (Express Checkout). */ readyPayload?: 'element' | 'event'; /** Root CSS class; `-error`, `-mount`, `-loader` are derived from it. */ className?: string; } /** The create-only keys of an element: in its create options, not in what its `update()` takes. */ export type CreateOnly = Record[0]>, true>; /** Members every element component exposes (template ref / `InstanceType`). */ export interface StripeElementExposed { /** The Stripe element instance (null until created). */ element: ShallowRef; loading: Ref; error: Ref; focus: () => void; blur: () => void; clear: () => void; } /** Event name -> payload tuple, used to type a component's listeners (`@change`, ...). */ export type ElementEvents = Record; /** Stripe's `{ elementType }` event: `focus`, `blur`, `escape` and `loaderstart`. */ export type ElementTypeEvent = [event: { elementType: T; }]; /** Payloads of the events most elements share; the element type comes from `TChange`. */ export type BaseElementEvents = { ready: [element: TElement]; change: [event: TChange]; focus: ElementTypeEvent; blur: ElementTypeEvent; escape: ElementTypeEvent; }; /** Payload of `loaderstart` / `loaderror` for an element type. */ export type LoadStartEvent = ElementTypeEvent; export type LoadErrorEvent = [event: { elementType: T; error: StripeError; }]; /** * Payload of the card elements' `networkschange`. Stripe.js 10's `.d.ts` declares only * `elementType`; Stripe sends `networks` (null while `loading`) as well. */ export type NetworksChangeEvent = [ event: { elementType: T; networks: string[] | null; loading: boolean; } ]; /** A slot that receives `TProps` (nothing when `void`). */ export type ScopedSlot = (...args: [TProps] extends [void] ? [] : [props: TProps]) => VNode[]; /** * The `#loading` and `#error` slots every element (and most other components) renders; * `#error` receives the error message. */ export interface StatusSlots { loading?: ScopedSlot; error?: ScopedSlot<{ error: string; }>; } /** * A component type with typed slots (#671). vue-tsc reads slot props from the `$slots` of * the instance that `new Component(props)` builds, and the `DefineComponent` parameters that * Vue 2.7 and Vue 3 share have no slots, so `$slots` would type every slot prop as `any`. * The extra construct signature comes first, so `new` picks it; `InstanceType` (template * refs) keeps reading the last one, the component's own. */ export type WithSlots object, TSlots> = (new (...args: unknown[]) => Omit, '$slots'> & { $slots: TSlots; }) & TComponent; /** * Public type of a factory-built element component. `TUnsupported` drops standard members * the Stripe element rejects (the Express Checkout Element throws on `clear()`). */ export type StripeElementComponent, TEvents extends ElementEvents = ElementEvents, TUnsupported extends keyof StripeElementExposed = never> = WithSlots, TUnsupported> & TExtra, Record, Record, Record, ComponentOptionsMixin, ComponentOptionsMixin, { [K in keyof TEvents]: (...args: TEvents[K]) => void; }>, StatusSlots>; /** * Public type of a hand-written component (providers, VueStripeCheckout, ...). It passes only * the first 8 `DefineComponent` parameters, which Vue 2.7 and Vue 3 share, so the emitted * `.d.ts` resolves on both; `defineComponent()`'s inferred type passes Vue 3's 16+. * `TProps` is the runtime props object (`typeof props`), so required props and defaults keep * their types; `TExposed` is what `expose()` publishes on the template ref; `TSlots` gives * each slot's props. */ export type VueStripeComponent, TEvents extends ElementEvents = ElementEvents, TSlots = StatusSlots> = WithSlots, Record, Record, ComponentOptionsMixin, ComponentOptionsMixin, { [K in keyof TEvents]: (...args: TEvents[K]) => void; }>, TSlots>;