npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

@constructor-io/constructorio-ui-checkout

v1.0.0

Published

Constructor.io Stripe Embedded Checkout UI library for web applications

Readme

Constructor.io UI Checkout

minzipped size NPM Version MIT licensed

Introduction

Headless primitives for building multi-step checkout on top of Stripe. The library owns the state machine, session lifecycle, storage, routing, and the default Stripe surface — your app composes the UI (cart, address, review, confirmation, custom steps).

Our Storybook Docs are the best place to explore behavior, adapters, and full integration recipes.

Installation

npm i @constructor-io/constructorio-ui-checkout

Three integration paths, one core

| Path | Best for | Entry | | ----------------- | --------------------------------- | -------------------------------------------- | | React | React apps with the full flow | <CioCheckoutProvider> + useCioCheckout() | | Vanilla JS (npm) | Non-React SPAs or custom UIs | createCheckoutFlow(config) | | Standalone bundle | Server-rendered sites, <script> | window.CioCheckout.resume(config) |

All three wrap the framework-agnostic createCheckoutFlow(config) core.

Quick start (React)

import {
  CioCheckoutProvider,
  CioCheckoutStep,
  CioStripePaymentStep,
  CioFulfillmentStep,
  PAYMENT_STEP,
  useCioCheckout,
} from '@constructor-io/constructorio-ui-checkout';
import '@constructor-io/constructorio-ui-checkout/styles.css';

function App() {
  return (
    <CioCheckoutProvider
      provider="stripe"
      steps={[
        { id: 'cart' },
        { id: 'address' },
        { id: PAYMENT_STEP },
        { id: 'fulfill' },
        { id: 'done' },
      ]}
      onCreateSession={async () => {
        const res = await fetch('/api/checkout-session', { method: 'POST' });
        return res.json(); // must return { clientSecret, publishableKey }
      }}
      onEvent={(event) => console.log(event)}
    >
      <StartButton />
      <CioCheckoutStep id="cart">
        <MyCart />
      </CioCheckoutStep>
      <CioCheckoutStep id="address">
        <MyAddressForm />
      </CioCheckoutStep>
      <CioCheckoutStep id={PAYMENT_STEP}>
        <CioStripePaymentStep uiMode="form" />
      </CioCheckoutStep>
      <CioCheckoutStep id="fulfill">
        <CioFulfillmentStep
          onFulfill={() => fetch('/api/verify').then((r) => r.json())}
        />
      </CioCheckoutStep>
      <CioCheckoutStep id="done">
        <MyConfirmation />
      </CioCheckoutStep>
    </CioCheckoutProvider>
  );
}

function StartButton() {
  const flow = useCioCheckout();
  if (flow.state.currentStepId !== null) return null;
  return <button onClick={() => flow.start()}>Checkout</button>;
}

You own the button, the layout, and every non-Stripe step. See the Integration Guide for routed multi-step, modal presentation, guards, guest vs. login, and mid-flow cart updates.

Standalone bundle

A framework-agnostic bundle for non-React SPAs, server-rendered sites, or <script>-tag integrations. The bundle exposes window.CioCheckout — a state-only namespace; you drive your own DOM.

<script src="/path/to/constructorio-ui-checkout.standalone.js"></script>
<script>
  const flow = CioCheckout.resume({
    steps: [{ id: 'cart' }, { id: 'payment' }, { id: 'done' }],
    onCreateSession: () =>
      fetch('/api/checkout-session', { method: 'POST' }).then((r) => r.json()),
    onEvent: (e) => console.log(e),
  });

  flow.start();
</script>

Consuming through a bundler? Import the same bundle via subpath — same CioCheckout surface:

import CioCheckout from '@constructor-io/constructorio-ui-checkout/constructorio-ui-checkout-standalone';

CioCheckout.resume(config) creates a checkout flow backed by a sessionStorage adapter (auto-hydrates on page load) and registers it as the active flow so any other CIO library on the page can reach it.

Standalone API

| Member | Description | | ----------------------------------------- | -------------------------------------------------------------------------- | | CioCheckout.VERSION | Library version string | | CioCheckout.createCheckoutFlow | Factory returning the framework-agnostic checkout flow | | CioCheckout.createSessionStorageAdapter | Default sessionStorage-backed CheckoutStorageAdapter | | CioCheckout.resume(config) | Creates + registers a flow with the sessionStorage adapter injected | | CioCheckout.reset() | Destroys the registered flow | | CioCheckout.cioCheckoutRegistry | Singleton registry — register(flow), getFlow(), hasFlow(), clear() |

Registry pattern

For multi-library setups where another CIO library (e.g. pia) needs to reach the active checkout flow, register once and let others call getFlow():

import {
  createCheckoutFlow,
  cioCheckoutRegistry,
} from '@constructor-io/constructorio-ui-checkout';

const flow = createCheckoutFlow({ provider: 'stripe', steps, onCreateSession, ... });
cioCheckoutRegistry.register(flow);

// Elsewhere:
const active = cioCheckoutRegistry.getFlow();
active?.syncCart(newItems);

Persistence & resume

Persistence is opt-in. Pass a storage adapter + storageKey to CioCheckoutProvider (or createCheckoutFlow) and the library serializes CheckoutFlowState on every change and hydrates on next mount:

import { createSessionStorageAdapter } from '@constructor-io/constructorio-ui-checkout';

<CioCheckoutProvider
  storage={createSessionStorageAdapter()}
  storageKey={`checkout-${userId}`}
  ...
/>

Supply your own adapter (Redis, DynamoDB, your API) for B2B pause/resume, cross-device recovery, or emailed abandoned-cart links. See Persistence & Resume for the full recipe.

Local Development

Note: Local development requires Node.js >= 20. The consuming library supports Node.js >= 18, but the Storybook 9 toolchain requires Node.js >= 20.

Development scripts

npm ci                  # install dependencies for local dev
npm run dev             # start a local Storybook dev server
npm run lint            # run linter
npm run lint:fix        # run linter with auto-fix
npm run check-types     # run TypeScript type checking
npm run test            # run tests
npm run test:coverage   # run tests with coverage report
npm run check-license   # check dependency licenses
npm run build           # build the library
npm run build-storybook # build Storybook for deployment

Server-side setup

Your backend creates the Stripe Checkout Session and returns { clientSecret, publishableKey } to the library. The server ui_mode must match the client uiMode you pass to <CioStripePaymentStep>: 'form' (beta) or 'elements' (GA).

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/api/checkout-session', async (req, res) => {
  const session = await stripe.checkout.sessions.create({
    ui_mode: 'form', // use 'elements' for the elements uiMode
    mode: 'payment',
    line_items: [
      {
        price_data: {
          currency: 'usd',
          product_data: { name: 'Product Name' },
          unit_amount: 4999,
        },
        quantity: 1,
      },
    ],
    return_url:
      'https://example.com/order-confirm?session_id={CHECKOUT_SESSION_ID}',
  });

  res.json({
    clientSecret: session.client_secret,
    publishableKey: process.env.STRIPE_PUBLISHABLE_KEY,
  });
});

Note: Requires stripe SDK v18+. ui_mode: 'form' is in beta and requires Stripe to enable it on the account.

Requirements

  • Node.js >= 18
  • React >= 16.12.0
  • React DOM >= 16.12.0
  • @stripe/stripe-js >= 9.3.1
  • @stripe/react-stripe-js >= 6.6.0
  • @constructor-io/constructorio-ui-components >= 1.4.0

Supporting Docs

Publishing New Versions

Dispatch the Publish workflow in GitHub Actions. You're required to provide two arguments:

  • Version Strategy: major, minor, or patch.
  • Title: A title for the release.

This workflow will automatically:

  1. Bump the library version using the provided strategy.
  2. Create a new git tag.
  3. Create a new GitHub release.
  4. Compile the library.
  5. Publish the new version to NPM.
  6. Deploy the Storybook docs to GitHub Pages.

Note: Please don't manually increase the package.json version or create new git tags.

The library version is tracked by releases and git tags. This intentionally avoids pushing version bumps to the main branch, sidestepping branch-protection rule exceptions.

Contributing

  1. Fork the repo and create a new branch.
  2. Run npm ci to install dependencies.
  3. Make your changes.
  4. Run npm run lint and npm test to verify.
  5. Submit a PR for review.

Please avoid committing anything sensitive — API keys, Stripe secret keys, customer data, or internal URLs. The default .gitignore excludes .env* files; keep it that way.

License

MIT - Constructor.io