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

@henrylabs/js

v1.0.7

Published

The Henry client SDK lets you embed checkout and card collection elements directly into your website.

Downloads

462

Readme

@henrylabs/js

The Henry client SDK lets you embed checkout and card collection elements directly into your website.

npm version

Installation

Use npm to install the Henry.js module:

npm install @henrylabs/js

Or load it directly from the CDN by adding a script tag to your page:

<script src="https://cdn.jsdelivr.net/npm/@henrylabs/js"></script>

When loaded via CDN, the SDK is available as window.Henry.

Usage

Import the SDK as an ES module:

import Henry from "@henrylabs/js";

Checkout Element

The Checkout Element renders an embedded checkout widget for one or more product links. To use it, you'll need a Widget ID from the Henry Developer Dashboard.

const el = Henry.createCheckoutElement("#checkout-container", {
  widgetId: "widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  items: [
    {
      link: "https://www.nike.com/t/some-product/ABC-123",
      quantity: 2,
      variant: {
        size: 10,
        color: "white",
      },
    },
  ],
});

Add a container element in your HTML:

<div id="checkout-container"></div>

Options

widgetId string - Required. Your Widget ID from the Henry dashboard.

items CartItem[] - Required. One or more products to include in the checkout. Each item requires a link (product URL) and optionally accepts quantity, variant (e.g. { size, color }), and metadata.

settings CheckoutOptions - Optional settings for the checkout, including custom fees, purchase options, and event triggers.

tags Record<string, string> - Optional key-value tags to associate with the checkout. Tags can be used for order management and segmentation in the dashboard.

prefill.address object - Optional address to pre-populate the checkout form. All fields are optional.

| Field | Type | Description | | ------------- | -------- | ---------------------------------------------------- | | firstName | string | Buyer's first name | | lastName | string | Buyer's last name | | email | string | Buyer's email address | | line1 | string | Street address line 1 | | line2 | string | Street address line 2 (apt, suite, etc.) | | city | string | City | | province | string | State / province code (e.g. "NY") | | postalCode | string | ZIP / postal code | | countryCode | string | ISO 3166-1 alpha-2 country code (e.g. "US") | | phone | string | Phone number in E.164 format (e.g. "+15555555555") |

Henry.createCheckoutElement("#checkout-container", {
  widgetId: "widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  items: [{ link: "https://example.com/products/item", quantity: 1 }],
  prefill: {
    address: {
      firstName: "Jane",
      lastName: "Smith",
      email: "[email protected]",
      line1: "123 Main St",
      city: "New York",
      province: "NY",
      postalCode: "10001",
      countryCode: "US",
      phone: "+12125550100",
    },
  },
});

display.size "full" | "comfortable" | "compact" | "bubble" | "direct" - Controls the widget's display size.

display.theme "light" | "dark" | "system" - Sets the color theme.

Full Example

const el = Henry.createCheckoutElement("#checkout-id-1", {
  widgetId: "widget_UtjTglNV1jg1TvlooBgRH6XdFdPURIYTbLM",
  items: [
    {
      link: "https://www.nike.com/t/al8-womens-shoes-r93WJ3g5/FJ3794-109990",
      // Set quantity for this item (default is 1)
      quantity: 2,
      // Set variant options info for this item
      selectedOptions: ["regular", "white", "size 10"],
      // Set the recommended shipping option for this item
      selectedShipping: {
        value: "express",
      },
    },
    {
      link: "https://usa.lastresortab.com/products/vm001-black?variant=46245656821911",
      selectedShipping: {
        value: "express",
      },
      // Set whatever custom metadata you want
      metadata: {
        creatorSource: "@HenryHenderson",
      },
    },
  ],
  // Set custom tags to associate with this cart
  tags: {
    user: "hen-123",
    region: "us-ny",
  },
  settings: {
    // Set custom fees for this checkout
    commissionFeeFixed: {
      value: 1.99,
      currency: "USD",
    },
    commissionFeePercent: 0.05,
    // Prevent buyers from removing items at checkout
    options: {
      allowPartialPurchase: false,
    },
    // Trigger a pre-defined webhook when the order is complete (configure in the dashboard)
    events: [
      {
        type: "order.purchase.complete",
        data: [
          {
            type: "send_webhook",
            webhookUUID: "123e4567-e89b-12d3-a456-426614174000",
          },
        ],
      },
    ],
  },
  display: {
    size: "comfortable",
    theme: "system",
  },
});

Events

Use .on() to listen for checkout events:

el.on("checkout-complete", ({ status, order }) => {
  console.log("Checkout finished with status:", status);
});

el.on("checkout-closed", ({ source }) => {
  console.log("Checkout closed by:", source); // "user" | "system"
});

Use .off() to remove a listener:

el.off("checkout-complete", handler);

Card Element

The Card Element renders a secure card input iframe for collecting payment card details. Card data is collected entirely within the iframe - sensitive information is never exposed to your page.

const cardEl = Henry.createCardElement("#card-container");

You can optionally pass styles to customize the card input fields:

const cardEl = Henry.createCardElement("#card-container", {
  styles: {
    cardNumber: {
      base: {
        color: "#333",
        fontSize: "16px",
      },
      "::placeholder": {
        color: "#aaa",
      },
    },
  },
});

Methods

validate() - Returns a Promise<boolean> indicating whether the current card input is valid.

const isValid = await cardEl.validate();

submit() - Tokenizes the card and returns a Promise<{ cardToken: string }>. Use the returned token to process the payment server-side.

const { cardToken } = await cardEl.submit();

CVC Element

The CVC Element renders a secure CVC/CVV input iframe for updating the verification code on an existing card token. Like the Card Element, the sensitive value never touches your page.

const cvcEl = Henry.createCvcElement("#cvc-container", {
  cardToken: "card_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
});

The cardToken is the token you received from a previous cardEl.submit() call.

You can optionally pass styles to customize the input field:

const cvcEl = Henry.createCvcElement("#cvc-container", {
  cardToken: "card_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  styles: {
    cardVerification: {
      base: {
        color: "#333",
        fontSize: "16px",
      },
      "::placeholder": {
        color: "#aaa",
      },
    },
  },
});

Methods

validate() - Returns a Promise<boolean> indicating whether the current CVC input is valid.

const isValid = await cvcEl.validate();

submit() - Patches the existing card token with the new CVC. Returns a Promise<void> that resolves on success.

await cvcEl.submit();

destroy() - Removes the iframe and cleans up event listeners.

cvcEl.destroy();

TypeScript support

This package includes TypeScript declarations. Key types exported from @henrylabs/js:

import type { CartItem, CheckoutOptions } from "@henrylabs/js";

React

When using Henry.js in React, use a ref guard to prevent the element from being created more than once in Strict Mode:

import { useEffect, useRef } from "react";
import Henry from "@henrylabs/js";

function Checkout() {
  const initialized = useRef(false);

  useEffect(() => {
    if (initialized.current) return;
    initialized.current = true;

    const el = Henry.createCheckoutElement("#checkout-container", {
      widgetId: "widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
      items: [{ link: "https://example.com/products/item", quantity: 1 }],
      display: { size: "compact", theme: "dark" },
    });

    el.on("checkout-complete", ({ status, order }) => {
      console.log("Done:", status, order);
    });
  }, []);

  return <div id="checkout-container" />;
}