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

@usgb/forms

v1.0.1

Published

Shared USGB lead-form package for PWA and WordPress

Readme

@usgb/forms

Shared lead and newsletter forms for the PWA (React) and WordPress (Web Component) hosts.

You pick a predefined formId. The package owns fields, validation, consent copy, tracking keys, and layout. You own the submit endpoint, legal-document URLs, heading/subheading/CTA copy, and thank-you behavior.

What you get

| Artifact | Path / export | Who uses it | | ------------- | --------------------------------------------------------------- | ----------------------------------- | | React package | @usgb/formsdist/index.js | PWA / any React host | | Stylesheet | @usgb/forms/usgb-forms.css | Required for React hosts | | Web Component | dist/usgb-forms.js (also versioned usgb-forms.<version>.js) | WordPress and other non-React hosts | | Catalog | @usgb/forms/manifestforms-manifest.json | CMS pickers, docs, tooling |

The Web Component script injects the same CSS once on load. React hosts must import the stylesheet themselves.

Mental model

| You pass | Package already decided | | -------------------------------- | ------------------------------------------------------------------------------------- | | formId | Fields, required/optional rules, consent bundle, tracking set, layout family (kind) | | adapter.submit | Where the payload goes (never an attribute or hardcoded URL) | | legalUrls / *-url | Hrefs for package-owned consent copy | | heading, subheading, ctaLabel | Marketing copy around the form | | successMessage or successUrl | Thank-you UX after accept |

Hosts must not invent field lists, consent wording, or tracking keys. New forms are new catalog entries in this package, not host-built schemas.

Use listFormDefinitions() (or the manifest) when a CMS needs a picker of available formIds. Deeper catalog rules: src/definitions/context.md.

Available forms

| formId | Kind | Fields | Consent | Variants | | -------------------- | ------------ | --------------------------------------------------------- | ------------------------------ | ------------------------------------------------------- | | main-investors-kit | lead | First name, last name, email (required); phone (optional) | TCPA checkbox (lead-tcpa v1) | dense, large, sidebar, plus optional two-column | | newsletter | newsletter | Email only | None | None — omit variants / variant |

Appearances for both: on-light | on-dark. Appearance only recolors the form for readability on a light or dark host background — it never sets a background, padding, or radius. The host container owns those.

kind is the layout family (lead grid vs inline newsletter row). The root exposes data-kind for CSS. Several catalog forms can share one kind (e.g. another lead kit that reuses the lead layout).

Install

Registry package name, scope, and CDN base URL are TBD — examples below use the working package name @usgb/forms and a placeholder CDN host. Replace them when publishing is finalized.

npm (React / PWA)

yarn add @usgb/forms
# or
npm install @usgb/forms

Then import the component and stylesheet:

import { UsgbForm } from '@usgb/forms'
import '@usgb/forms/usgb-forms.css'

Peer dependency: react and react-dom ^18 or ^19.

CDN (Web Component / WordPress)

Load the built IIFE (styles inject themselves):

<script src="https://cdn.example.com/usgb-forms/usgb-forms.1.0.0.js"></script>

Exact CDN hostname, path, and versioning scheme are TBD. Prefer a versioned filename (usgb-forms.<version>.js) so hosts can pin releases.

Until the package is published, you can still develop against a local checkout (yarn add file:../usgb-forms or yarn link).

React (PWA)

import { UsgbForm, createStubAdapter, PWA_LEGAL_URLS } from '@usgb/forms'
import '@usgb/forms/usgb-forms.css'
;<UsgbForm
    formId="main-investors-kit"
    appearance="on-dark"
    variants={['large', 'two-column']}
    heading="Get My Free Guide"
    subheading="Enter your details to receive the Main Investors Kit."
    ctaLabel="GET MY FREE GUIDE"
    source="cms-home"
    campaign="spring-kit"
    legalUrls={PWA_LEGAL_URLS}
    successMessage="Thanks — we will send your kit shortly."
    adapter={yourHostAdapter}
    onAccepted={(payload) => {
        /* analytics bridge */
    }}
    onFailed={(payload, message) => {
        /* error bridge */
    }}
/>

Newsletter (no consent, no variants):

<UsgbForm
    formId="newsletter"
    appearance="on-light"
    heading="Subscribe"
    ctaLabel="SUBSCRIBE"
    adapter={yourHostAdapter}
/>

React props

| Prop | Required | Role | | ------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------- | | formId | yes | Catalog key (main-investors-kit, newsletter, …) | | adapter | yes | HostAdapter with host, getTrackingHints(), submit() | | appearance | no | on-light (default) or on-dark | | variants | no | Lead only. Default ['dense']. One of dense | large | sidebar, optionally add two-column | | heading / subheading | no | Title and supporting copy | | ctaLabel | no | Submit button label. Falls back to the catalog ctaLabel for that formId | | source / campaign | no | Placement / campaign context in the payload | | legalUrls | when consent requires them | Host CMS paths for legal links in consent copy | | successMessage | no | Inline thank-you when successUrl is omitted | | successUrl | no | Redirect after accept (analytics / onAccepted are invoked first; see Success behavior) | | analytics | no | (event) => void for view / validation / submit / success / failure | | className | no | Extra class on .usgb-form | | onAccepted / onFailed | no | Callbacks with the submission payload |

Web Component (WordPress)

Load one script. Styles are injected automatically.

<script src="https://cdn.example.com/usgb-forms/usgb-forms.1.0.0.js"></script>
<usgb-form
    ```
    form-id="main-investors-kit"
    appearance="on-dark"
    variant="large two-column"
    heading="Get My Free Guide"
    subheading="Enter your details to receive the Main Investors Kit."
    cta="GET MY FREE GUIDE"
    source="cms-home"
    client-agreement-url="/client-agreement/"
    privacy-policy-url="/privacy-policy/"
    success-message="Thanks — we will send your kit shortly."
></usgb-form>

Submit is not an attribute. Markup alone uses a stub adapter. Assign a real HostAdapter in script:

<script>
    const el = document.querySelector('usgb-form')
    el.adapter = {
        host: 'wordpress',
        getTrackingHints() {
            // Cookies, UTMs, click ids — keys must match the package tracking registry
            return {}
        },
        async submit(payload) {
            const res = await fetch('/your-form-submit', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload)
            })
            if (!res.ok) return { status: 'failed', message: res.statusText }
            return { status: 'accepted' }
        }
    }

    el.addEventListener('usgb-form:success', (e) => {
        /* e.detail is SubmissionPayload */
    })
    el.addEventListener('usgb-form:failure', (e) => {
        /* e.detail = { payload, message } */
    })
</script>

Attribute map

| Attribute | React prop | | ----------------------------------------------- | ------------------------------------------------------------- | | form-id | formId | | appearance | appearance | | variant | variants (space-separated) | | heading / subheading | heading / subheading | | cta | ctaLabel | | source / campaign | source / campaign | | success-message / success-url | successMessage / successUrl | | client-agreement-url, privacy-policy-url, … | legalUrls.* | | host | Used only for the stub adapter before you assign el.adapter |

Host adapter

interface HostAdapter {
    host: 'pwa' | 'wordpress'
    getTrackingHints(): Partial<Record<TrackingKey, string | undefined>>
    submit(payload: SubmissionPayload): Promise<SubmitResult>
}
  • submit must return { status: 'accepted' } or { status: 'failed', message?: string }.
  • The package never embeds Workato, Magento, or WordPress endpoints.
  • createStubAdapter('pwa' | 'wordpress') accepts every payload (playground / markup-only WC).
  • Tracking keys and destination names live in forms-manifest.json. Hosts may supply values for registered keys; they must not invent new ones.

Payload shape (summary)

Successful submits send a nested envelope: formId, definitionVersion, submissionContractVersion, idempotencyKey, data (field values), optional consent, and context (host, source, campaign, page, tracking). Exact field and tracking sets come from the form’s catalog entry.

Consent and legal URLs

Consent bundles are versioned and package-owned (checkboxes and/or clickwrap notices). Hosts only supply document hrefs.

  • main-investors-kit uses lead-tcpa v1 and requires clientAgreement and privacyPolicy.
  • PWA Magento defaults: PWA_LEGAL_URLS/content/client-agreement, /content/privacy-policy.
  • WordPress must pass every URL required by the selected consent. A consent form with a missing required URL does not render.
  • Checkbox values land in consent.values (and mirrored in data). Notices have no boolean field; the payload still records consent definition id/version.
  • Distinct legal wording requires a new consent id/version in this package — not freeform copy from the host.

LEAD_CLICKWRAP_V1 (“By clicking the button…”) is in the catalog and needs five legal URLs (privacyPolicy, userAgreement, marketLossPolicy, electronicDisclaimer, termsOfSale). It is not attached to a formId until that recipe is chosen.

Success behavior

  1. Adapter returns accepted.
  2. analytics({ type: 'success' }) and onAccepted / usgb-form:success run synchronously. The package does not await them.
  3. If successUrl / success-url is set, the page calls window.location.assign immediately after those callbacks return.
  4. Otherwise the form shows successMessage / success-message, or a package default thank-you line.

Redirect vs analytics

Invocation order is fixed (hooks first, then navigate). Delivery is not. location.assign starts unload in the same turn, so a typical GTM / gtag / dataLayer.push / image pixel started in analytics or onAccepted can be cancelled before the beacon leaves — especially on Safari and slow networks. Same for async work inside a usgb-form:success listener: the CustomEvent is dispatched synchronously, but anything it schedules after return can die with the document.

This package does not wait on a returned Promise, add a flush timeout, or call sendBeacon on the host’s behalf. A hung analytics callback must not trap the user on the submit screen.

What is reliable today:

  • Inline thank-you (successMessage only) — no navigation, so tags usually complete.
  • Same-document hash redirects (#thank-you) — no unload.
  • Host analytics that uses navigator.sendBeacon or fetch(..., { keepalive: true }).
  • Conversion measured on the thank-you page itself, not on this success event.

submit_attempt is safer than success because it fires before adapter.submit and has the round-trip to flush. Prefer the thank-you page (or a beacon) when successUrl is a full navigation.

Styling

Light DOM with stable usgb- class names (not CSS-in-JS). Isolation comes from the prefix and from styling .usgb-field-control / .usgb-btn instead of bare input / button. Host theme rules can still win; load host CSS after this package’s stylesheet and override under .usgb-form.

| Host | How styles load | | ------------- | ---------------------------------------------- | | React | import '@usgb/forms/usgb-forms.css' | | Web Component | Injected as <style id="usgb-forms-css"> once |

Prefer custom properties on .usgb-form for color, type, and spacing:

.usgb-form {
    --usgb-button-background: #123456;
    --usgb-field-border: #cccccc;
}

.usgb-form[data-appearance='on-dark'] {
    --usgb-button-background: #f4e08e;
}

Use class selectors when a token does not exist (.usgb-form .usgb-btn { border-radius: 0; }).

Stable hooks: .usgb-form (data-appearance, data-variant, data-kind), .usgb-form-heading, .usgb-form-subheading, .usgb-form-grid, .usgb-form-inline, .usgb-field-control, .usgb-field-error, .usgb-consent-*, .usgb-btn, .usgb-form-status-*.

Semantic tokens (--usgb-field-*, --usgb-button-*, --usgb-newsletter-underline, …) are the first place to retheme. Palette vars (--usgb-blue-1, …) are a PWA snapshot. Error and checkbox glyphs are inline SVGs that use currentColor — override --usgb-alert-danger or --usgb-checkbox-mark to recolor them.

Appearance never paints a card. Put the form on a dark host surface and pass appearance="on-dark" (or on-light on a light surface):

<div style="background: #001f3d; padding: 2rem; border-radius: 0.75rem">
    <usgb-form form-id="main-investors-kit" appearance="on-dark" …></usgb-form>
</div>

Visual styles are a ported snapshot of the PWA form kit. When PWA form styles change, update this package and bump the version.

Develop (package maintainers)

yarn install
yarn dev      # Vite playground (tries :5174)
yarn build
yarn typecheck
yarn lint
yarn format

Prettier and ESLint match magento-frontend (4-space indent, single quotes, no semicolons, print width 80).

Git

Local repo only. Connect a GitHub remote later when ready to publish.