/**
* SDK-internal identifier for each rendered field. One-to-one with the Clover
* element types except `CARD` (composite — we don't use it).
*/
type FieldKey = 'cardNumber' | 'cardDate' | 'cardCvv' | 'cardPostalCode' | 'cardName' | 'cardEmail' | 'paymentRequestButton';
/**
* CSS properties Clover supports inside its iframe ``. Curated from
* production usage in the WP plugin + Clover SDK behavior. Properties not
* listed here are silently ignored by Clover; we don't pretend they work.
*/
interface CloverCssProperties {
color?: string;
fontFamily?: string;
fontSize?: string;
fontWeight?: string | number;
lineHeight?: string | number;
letterSpacing?: string;
textAlign?: 'left' | 'right' | 'center' | 'inherit' | 'initial';
textIndent?: string;
padding?: string;
margin?: string;
height?: string;
width?: string;
border?: string;
borderRadius?: string;
background?: string;
backgroundColor?: string;
}
/**
* Element-scoped selectors Clover honors. Each is the lower-kebab form of the
* Clover element type (`CARD_EMAIL_ADDRESS` → `card-email-address`). Using a
* shortened form (e.g. `card-email`) is silently ignored — Clover does not
* warn, the style just never applies. Discovery captured 2026-05-18.
*/
type CloverElementSelector = 'card-number' | 'card-date' | 'card-cvv' | 'card-postal-code' | 'card-name' | 'card-email-address' | 'card-phone-number' | 'card-street-address';
/**
* Placeholder pseudo-classes Clover honors. The vendor-prefixed forms are
* required by older Clover versions; modern `::placeholder` is also accepted.
* Production code in the WP plugin sets all four prefixed variants.
*/
type PlaceholderPseudo = '::placeholder' | '::-webkit-input-placeholder' | '::-moz-placeholder' | ':-ms-input-placeholder' | ':-moz-placeholder';
/**
* Every selector key Clover's `elements.create(type, styles)` accepts. The
* SDK exports this union so consumers get autocomplete and typo safety on
* a previously-untyped JSON payload.
*
* - `'input'` — applies to the input in every element
* - `''` — global placeholder rule
* - `'card- input'` — per-element input rule
* - `'card- input'` — per-element placeholder rule
*/
type CloverStyleSelector = 'input' | PlaceholderPseudo | CloverElementSelector | `${CloverElementSelector} input` | `${CloverElementSelector} input${PlaceholderPseudo}`;
/**
* Strongly-typed styles object for `clover.elements().create()`. Replaces
* `type CloverElementStyles = object`.
*
* Most consumers should NOT construct this directly — pass a higher-level
* `theme` on `PaymentFieldsConfig` and let `compileTheme()` emit the JSON.
*/
type CloverElementStyles = Partial>;
/**
* High-level theme config. The SDK compiles this into a `CloverElementStyles`
* JSON object internally — most apps never need to touch the raw selectors.
*/
interface CloverFieldTheme {
readonly fontFamily?: string;
readonly fontSize?: string;
readonly textColor?: string;
readonly placeholderColor?: string;
/**
* Height of the input inside each Clover iframe. Must match (or slightly
* exceed) the host wrapper's height so the entire wrapper is clickable.
* Defaults to `'46px'` to match `.wcp-pf__field` in the SDK stylesheet.
*/
readonly inputHeight?: string;
/** Extra style overrides merged on top of the theme-emitted defaults. */
readonly overrides?: CloverElementStyles;
}
type ThreeDsBrowserInfo = Record;
/**
* Lifecycle states the SDK transitions through. See the lifecycle preview at
* `design-previews/06-states.html` for what the customer sees in each state.
*/
type PaymentFieldsState = 'idle' | 'gpay_opening' | 'gpay_ready' | 'gpay_cancelled' | 'tokenizing' | 'submitting' | 'threeds_method' | 'threeds_challenge' | 'finalizing' | 'done' | 'error';
/**
* Per-field validation state. Two error fields — `error` is the raw signal
* from Clover, `displayedError` is what the UI should actually render. They
* diverge for the deferred-error UX rule: while the user is mid-typing, raw
* `error` may report "incomplete card", but we don't surface it until they
* blur once. After first blur, the two stay in sync. See README → Events &
* Validation, and the comment block at the top of `validation-machine.ts`.
*/
interface FieldValidationState {
/** Clover-reported: user has interacted with the field. */
readonly touched: boolean;
/** Clover-reported: raw error message, fires on every `change` event. */
readonly error?: string;
/** SDK-derived: user has blurred this field at least once. */
readonly hasBlurred: boolean;
/** SDK-derived: at least one `change` event has been observed for this field. */
readonly hadChangeEver: boolean;
/** SDK-derived: the error to render. Undefined until first blur (deferred-error rule). */
readonly displayedError?: string;
}
interface ValidationSnapshot {
/** Per-field touched + error state. Only fields actually mounted appear. */
readonly fields: {
readonly [K in FieldKey]?: FieldValidationState;
};
/** True when all required fields are valid (no errors, all touched). */
readonly canSubmit: boolean;
}
interface PaymentFieldsSnapshot {
readonly state: PaymentFieldsState;
readonly validation: ValidationSnapshot;
/** Set when state is 'error' or after a recoverable failure. */
readonly error?: PaymentFieldsError;
/** Set after successful tokenization (either path). */
readonly result?: TokenizationResult;
/** Set during the 3DS flow. */
readonly threeDs?: ThreeDsInterim;
}
interface PaymentFieldsError {
readonly code: PaymentFieldsErrorCode;
readonly message: string;
readonly cause?: unknown;
}
type PaymentFieldsErrorCode = 'clover_load_failed' | 'clover_3ds_load_failed' | 'not_mounted' | 'rate_limited' | 'tokenization_failed' | 'gpay_unavailable' | 'threeds_prerequisites_missing' | 'threeds_timeout' | 'threeds_finalize_failed' | 'unknown';
interface TokenizationResult {
/** 'card' = manual entry tokenized via `clover.createToken()`. 'google_pay' = captured from `PAYMENT_REQUEST_BUTTON` paymentMethod event. */
readonly source: 'card' | 'google_pay';
readonly token: string;
readonly card: {
readonly brand: string;
readonly last4: string;
readonly expMonth?: string;
readonly expYear?: string;
readonly first6?: string;
readonly addressZip?: string;
};
/** 3DS browser fingerprint, collected when 3DS is enabled. */
readonly browserInfo?: ThreeDsBrowserInfo;
}
interface ThreeDsInterim {
readonly state: 'method_required' | 'challenge_required';
readonly chargeId: string;
readonly fields: ThreeDsInterimFields;
}
interface ThreeDsInterimFields {
readonly acsUrl?: string;
readonly acsTransactionId?: string;
readonly methodUrl?: string;
readonly methodNotificationUrl?: string;
readonly threeDsServerTransactionId?: string;
/** Clover varies the field name between `threeds_protocol_version` and `message_version`. The SDK normalizes to this. */
readonly protocolVersion?: string;
}
type ThreeDsResult = {
readonly kind: 'success';
readonly redirect?: string;
readonly data?: unknown;
} | {
readonly kind: 'escalation';
readonly next: ThreeDsInterim;
} | {
readonly kind: 'failure';
readonly message: string;
};
interface PaymentFieldsConfig {
readonly pakmsKey: string;
readonly merchantId: string;
readonly locale: string;
readonly cartTotal: number;
readonly currency: string;
readonly country?: string;
readonly cloverSdkUrl: string;
readonly clover3DSSdkUrl?: string;
readonly features?: PaymentFieldsFeatures;
readonly endpoints?: PaymentFieldsEndpoints;
readonly theme?: CloverFieldTheme;
readonly onTokenized?: (result: TokenizationResult) => void;
readonly onThreeDsRequired?: (interim: ThreeDsInterim) => void;
readonly onError?: (error: PaymentFieldsError) => void;
}
interface PaymentFieldsFeatures {
readonly googlePay?: boolean;
readonly threeDSecure?: boolean;
/**
* Cardholder name + email field visibility.
* - `'auto'` (default) — visible when 3DSecure is enabled
* - `'always'` — visible always
* - `'hidden'` — never rendered
*/
readonly cardholderFields?: 'auto' | 'always' | 'hidden';
readonly savedCredentials?: SavedCredential | readonly SavedCredential[];
}
interface PaymentFieldsEndpoints {
/** Host's POST URL for 3DS finalization (e.g., WC's `/wp-json/.../3ds/finalize`). */
readonly threeDsFinalize?: string;
/** Returns headers (nonce, auth, etc.) for the finalize POST. Called per-request. */
readonly headers?: HeadersProvider;
}
type HeadersProvider = () => Record | Promise>;
interface SavedCredential {
readonly token: string;
readonly last4: string;
readonly brand: string;
}
interface MountTargets {
readonly cardNumber: string;
readonly cardDate: string;
readonly cardCvv: string;
readonly cardPostalCode: string;
readonly cardName?: string;
readonly cardEmail?: string;
readonly paymentRequestButton?: string;
}
type PaymentFieldsListener = (snapshot: PaymentFieldsSnapshot) => void;
type Unsubscribe = () => void;
declare class PaymentFieldsMachine {
/** The config the machine was constructed with. Read-only after construction. */
readonly config: PaymentFieldsConfig;
private readonly listeners;
private readonly rateLimiter;
private snapshot;
private mounted;
private destroyed;
private clover;
private threeDsUtil;
private registry;
private validation;
private capturedGpayToken;
constructor(config: PaymentFieldsConfig);
/** Subscribe to snapshot updates. The listener is called immediately with the current snapshot. */
subscribe(listener: PaymentFieldsListener): Unsubscribe;
getSnapshot(): PaymentFieldsSnapshot;
/**
* Load the Clover SDK(s), create the elements, mount them to the host's DOM
* targets, and wire validation + GPay event handlers. Idempotent — calling
* again is a no-op.
*/
mount(targets: MountTargets): Promise;
/**
* Return a tokenization result the host can POST to the API.
*
* Two paths:
* - **GPay**: if we're in `gpay_ready`, return the already-captured token immediately (no second prompt).
* - **Manual card**: call `clover.createToken()`, rate-limited.
*
* Throws on rate-limit, invalid card, missing token, or unmounted state.
*/
tokenize(): Promise;
/**
* Drive the 3DS flow given an interim payload from the host's API response.
* Handles method/challenge dispatch, the `executePatch` callback, the
* finalize POST, and escalation (method ↔ challenge) internally.
*
* @param options.extraBody Host-specific fields merged into the finalize POST body.
* E.g., WC passes `{ order_id, order_key, nonce }` so the WP REST endpoint
* can find and update the order. Keeps WC-specific concerns out of the SDK.
*/
runThreeDs(interim: ThreeDsInterim, options?: {
readonly extraBody?: Record;
}): Promise;
/**
* Restore the form to idle, discarding any captured GPay token. Used by the
* "Use card details instead" link on the GPay-ready state.
*/
resetToIdle(): void;
destroy(): void;
private shouldShowCardholderFields;
private buildPaymentRequestData;
private wireGpayEvents;
private update;
private emitError;
}
/**
* Optional setter for the host's headers provider — must be set BEFORE the
* element is connected (e.g., via `el.headersProvider = ...; document.body.appendChild(el)`).
*/
interface WcpPaymentFieldsElement extends HTMLElement {
headersProvider?: HeadersProvider;
tokenize: () => Promise;
runThreeDs: (interim: ThreeDsInterim, options?: {
readonly extraBody?: Record;
}) => Promise;
resetToIdle: () => void;
readonly machine: PaymentFieldsMachine | null;
}
declare class WcpPaymentFields extends HTMLElement implements WcpPaymentFieldsElement {
/** Tells the form machinery that this element participates in form submission. */
static readonly formAssociated = true;
private internals;
/** Light-DOM mount container for the React tree. NOT a shadowRoot. */
private container;
private root;
private _machine;
private unsubscribe;
private lastTokenizedFor;
private lastErrorCode;
private lastState;
/** Caller-provided headers function (for 3DS finalize POST). Property — not an attribute. */
headersProvider?: HeadersProvider;
constructor();
connectedCallback(): void;
disconnectedCallback(): void;
get machine(): PaymentFieldsMachine | null;
tokenize(): Promise;
runThreeDs(interim: ThreeDsInterim, options?: {
readonly extraBody?: Record;
}): Promise;
resetToIdle(): void;
formResetCallback(): void;
private subscribeMachineToEvents;
private onSnapshot;
private dispatchTyped;
private parseConfig;
}
export { type PaymentFieldsConfig, type PaymentFieldsError, type PaymentFieldsSnapshot, type PaymentFieldsState, type ThreeDsInterim, type ThreeDsResult, type TokenizationResult, WcpPaymentFields, type WcpPaymentFieldsElement };