Web components

@biaspay/elements registers light-DOM custom elements for an embedded Bias checkout. Use it with plain HTML or any framework that supports custom elements.

Install

npm install @biaspay/elements

Importing the package in a browser registers every bias-* element. Svelte is bundled as an implementation detail and is not a peer dependency.

<script type="module">
    import "@biaspay/elements";

    const provider = document.querySelector("bias-provider");
    provider.addEventListener("biascomplete", () => location.assign("/complete"));
</script>

<bias-provider client-secret="cs_...">
    <bias-contact-element></bias-contact-element>
    <bias-payment-element payment-method-layout="tabs"></bias-payment-element>
    <bias-submit-button label="Pay now"></bias-submit-button>
</bias-provider>

The entry point is safe to import without a DOM. Registration is skipped until the package runs in a browser. defineBiasElements() is also exported for explicit registration and is safe to call more than once for the same Elements version.

Provider configuration

<bias-provider> owns the session, field state, and payment lifecycle for its descendants.

PropertyAttributeTypeRequired
clientSecretclient-secretstringYes
initialCheckoutSessionCheckoutSessionNo
appearanceAppearanceNo
onComplete() => voidNo

Use properties for objects and functions. Assign them before inserting a provider when they must be present on its first connection:

import "@biaspay/elements";

const provider = document.createElement("bias-provider");
provider.clientSecret = clientSecret;
provider.initialCheckoutSession = checkoutSession;
provider.appearance = {
    labelStyle: "floating",
    variables: { colorPrimary: "#4f46e5" },
};
provider.onComplete = () => location.assign("/complete");

provider.append(document.createElement("bias-payment-element"), document.createElement("bias-submit-button"));
document.querySelector("#checkout").append(provider);

initialCheckoutSession is a one-time hydration seed. Its client_secret must match clientSecret. Elements shows a matching seed after activation and refreshes it from the API; later seed changes for the same secret are ignored.

Changing clientSecret starts a new session and resets session-owned state.

Child elements

ElementPropertiesDefaults
<bias-payment-element>paymentMethodLayout?: "tabs" | "radio", appearance?: Appearance"tabs"
<bias-card-element>appearance?: Appearance
<bias-us-bank-account-element>appearance?: Appearance
<bias-contact-element>appearance?: Appearance
<bias-address-element>scope?: "billing" | "shipping", collectPhone?: boolean, appearance?: Appearance"billing", false
<bias-submit-button>disabled?: boolean, label?: stringfalse, session label

The string and boolean properties also have kebab-case attributes: payment-method-layout, scope, collect-phone, disabled, and label. Assign appearance as a property.

Use exactly one payment element under each provider. See components and appearance for composition and theming rules.

State and methods

The provider exposes read-only checkout state:

PropertyType
sessionStateSessionState
paymentMethod"card" | "us_bank_account" | undefined
status"idle" | "submitting" | "succeeded" | "failed"
canSubmitboolean
submissionErrorBiasElementsError | null

Actions are methods:

provider.setPaymentMethod("card");
provider.submit();
provider.refreshSession();

const email = provider.getField("email", {
    validate: (value) => ({
        isValid: value.includes("@"),
        error: value.includes("@") ? null : "Enter a valid email.",
    }),
});
email.setValue("shopper@example.com");

submit() validates the current form and creates the payment when validation passes. Calls made while a submission is already running or after it succeeds are ignored. setPaymentMethod() ignores a method that the checkout session does not enable. refreshSession() retries a session refresh when a usable session has been retained.

Events

Provider events bubble, so they can be handled on the provider or an ancestor.

EventdetailWhen it fires
biasreadyvoidThe provider controller is attached; the session may still be loading.
biaschangeBiasElementsStateAny public checkout state changes.
biascompleteBiasElementsStateSubmission changes to succeeded.
biaserrorBiasElementsErrorA new session, configuration, frame, or payment error occurs.
provider.addEventListener("biaschange", ({ detail }) => {
    customButton.disabled = !detail.canSubmit;
});

provider.addEventListener("biaserror", ({ detail: error }) => {
    console.error(error.code, error.message, error.retryable);
});

Rendering and multiple checkouts

Elements render into the page’s light DOM. Every bias-* host uses display: contents, and the provider stays hidden while it has no usable session. A provider registry associates each child with its nearest provider, so multiple checkout trees on one page keep independent state.

TypeScript exports

The package exports element interfaces, typed event aliases, provider configuration and field binding types, plus the shared checkout types:

import type {
    Appearance,
    BiasChangeEvent,
    BiasElementsError,
    BiasElementsState,
    BiasFieldBinding,
    BiasFieldName,
    BiasProviderConfiguration,
    PaymentMethod,
    SessionState,
    ThemeVariables,
} from "@biaspay/elements";

The package also augments HTMLElementTagNameMap and HTMLElementEventMap for the registered tags and events.