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

@page-speed/forms

v0.8.2

Published

Ultra-high-performance React form library with field-level reactivity and tree-shakable architecture

Readme

@page-speed/forms

Type-safe, high-performance React form state and input components. Utilized by the OpenSite Semantic UI website platform

Page Speed React Forms

npm version npm downloads License TypeScript Tree-Shakeable

Highlights

  • FormEngine — declarative form component with built-in API integration
  • Field-level reactivity via @legendapp/state/react
  • Built-in input library (text, select, date, time, upload, rich text)
  • Tree-shakable subpath exports (/core, /inputs, /validation, /upload, /integration)
  • Validation rules and utilities (sync + async)
  • Valibot adapter in a separate entrypoint (/validation/valibot)
  • Tailwind token-based default UI aligned with ShadCN interaction patterns

Installation

pnpm add @page-speed/forms
# or
npm install @page-speed/forms

Peer dependencies:

  • react >= 16.8.0
  • react-dom >= 16.8.0

Quick Start with FormEngine

FormEngine is the recommended entry point for most use cases. It provides a declarative API for rendering forms with built-in API integration, validation, file uploads, and styling.

import * as React from "react";
import {
  FormEngine,
  type FormFieldConfig,
} from "@page-speed/forms/integration";

const fields: FormFieldConfig[] = [
  {
    name: "full_name",
    type: "text",
    label: "Full Name",
    required: true,
    placeholder: "Your name",
    columnSpan: 12,
  },
  {
    name: "email",
    type: "email",
    label: "Email",
    required: true,
    placeholder: "[email protected]",
    columnSpan: 6,
  },
  {
    name: "phone",
    type: "tel",
    label: "Phone",
    columnSpan: 6,
  },
  {
    name: "content",
    type: "textarea",
    label: "Message",
    required: true,
    columnSpan: 12,
  },
];

export function ContactForm() {
  return (
    <FormEngine
      api={{
        endpoint: "/api/contact",
        method: "post",
        submissionConfig: { behavior: "showConfirmation" },
      }}
      fields={fields}
      successMessage="Thanks for reaching out!"
      formLayoutSettings={{
        submitButtonSetup: {
          submitLabel: "Send Message",
        },
      }}
    />
  );
}

FormEngine Props

| Prop | Type | Description | |------|------|-------------| | api | PageSpeedFormConfig | API endpoint and submission configuration | | fields | FormFieldConfig[] | Array of field definitions | | formLayoutSettings | FormEngineLayoutSettings | Layout, style, and submit button settings | | successMessage | ReactNode | Message shown after successful submission | | onSubmit | (values) => void \| Promise<void> | Custom submit handler | | onSuccess | (data) => void | Called after successful submission | | onError | (error) => void | Called when submission fails | | resetOnSuccess | boolean | Reset form after success (default: true) |

Field Configuration

Each field in the fields array supports:

interface FormFieldConfig {
  name: string;
  type: "text" | "email" | "tel" | "textarea" | "select" | "multiselect" | 
        "date" | "daterange" | "time" | "file" | "checkbox" | "radio";
  label?: string;
  placeholder?: string;
  required?: boolean;
  columnSpan?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
  className?: string;
  options?: { label: string; value: string }[]; // For select/multiselect/radio
  // File-specific props
  accept?: string;
  maxFiles?: number;
  maxFileSize?: number;
}

Layout Options

Standard Layout (default)

Multi-column grid with a submit button below the fields:

<FormEngine
  fields={fields}
  formLayoutSettings={{
    formLayout: "standard",
    submitButtonSetup: {
      submitLabel: "Submit",
      submitVariant: "default", // | "destructive" | "outline" | "secondary" | "ghost" | "link"
    },
    styleRules: {
      formContainer: "max-w-2xl mx-auto",
      fieldsContainer: "gap-6",
      formClassName: "space-y-4",
    },
  }}
/>

Button-Group Layout

Inline input with submit button (e.g., newsletter signup):

<FormEngine
  fields={[{ name: "email", type: "email", label: "Email", required: true }]}
  formLayoutSettings={{
    formLayout: "button-group",
    buttonGroupSetup: {
      size: "lg", // | "xs" | "sm" | "default"
      submitLabel: "Subscribe",
      submitVariant: "default",
    },
  }}
/>

Using formEngineSetup Wrapper

For block/component libraries that provide default configurations:

import {
  FormEngine,
  type FormEngineSetup,
  type FormFieldConfig,
  type FormEngineStyleRules,
} from "@page-speed/forms/integration";

const defaultFields: FormFieldConfig[] = [
  { name: "email", type: "email", label: "Email", required: true },
];

const defaultStyleRules: FormEngineStyleRules = {
  formClassName: "space-y-6",
};

// Consumer passes setup, component provides defaults
function ContactBlock({ formEngineSetup }: { formEngineSetup?: FormEngineSetup }) {
  return (
    <FormEngine
      formEngineSetup={formEngineSetup}
      defaultFields={defaultFields}
      defaultStyleRules={defaultStyleRules}
    />
  );
}

Package Entry Points

Main

  • @page-speed/forms

Exports:

  • useForm, useField, Form, Field, FormContext
  • Core form/types interfaces

Integration (Recommended)

  • @page-speed/forms/integration

Exports:

  • FormEngine, FormEngineSetup, FormEngineProps
  • FormFieldConfig, FormEngineStyleRules, FormEngineLayoutSettings
  • DynamicFormField, useContactForm, useFileUpload

Inputs

  • @page-speed/forms/inputs

Exports:

  • TextInput, TextArea, Checkbox, CheckboxGroup, Radio
  • Select, MultiSelect, DatePicker, DateRangePicker, TimePicker
  • FileInput

Validation

  • @page-speed/forms/validation
  • @page-speed/forms/validation/rules
  • @page-speed/forms/validation/utils
  • @page-speed/forms/validation/valibot

Upload

  • @page-speed/forms/upload

Input Notes

TimePicker

TimePicker uses a native input[type="time"] UX internally.

  • Accepts controlled values in HH:mm (24-hour) or h:mm AM/PM (12-hour)
  • Emits HH:mm when use24Hour is true
  • Emits h:mm AM/PM when use24Hour is false

DatePicker and DateRangePicker

  • Calendar popovers close on outside click
  • Compact month/day layout using tokenized Tailwind classes
  • DateRangePicker renders two months and highlights endpoints + in-range dates

Select and MultiSelect

  • Close on outside click
  • Search support
  • Option groups
  • Selected options inside the menu use accent highlight styles

Styling (Tailwind 4 + Semantic Tokens)

This library ships with Tailwind utility classes and semantic token class names.

Base conventions

  • Inputs/triggers are transparent shells with semantic borders/rings
  • Fields with values (text-like controls) use ring-2 ring-primary
  • Error states use destructive border/ring
  • Dropdown selected rows use muted backgrounds

FormEngine Style Rules

interface FormEngineStyleRules {
  formContainer?: string;       // Wrapper around <form>
  fieldsContainer?: string;     // Grid wrapper for fields
  fieldClassName?: string;      // Fallback className for fields
  formClassName?: string;       // Applied to <form> element
  successMessageClassName?: string;
  errorMessageClassName?: string;
}

Autofill normalization

Text-like controls apply autofill reset classes to avoid browser-injected background/text colors breaking your theme contrast.

See INPUT_AUTOFILL_RESET_CLASSES in src/utils.ts.

Token requirements

Ensure your app defines semantic tokens used in classes such as:

  • background, foreground, border, input, ring
  • primary, primary-foreground
  • muted, muted-foreground
  • destructive, destructive-foreground
  • popover, popover-foreground
  • card, card-foreground

For complete styling guidance, see docs/STYLES.md.

Advanced: Low-Level APIs

For custom form implementations, the lower-level useForm, Form, and Field APIs are available:

import { Form, Field, useForm } from "@page-speed/forms";
import { TextInput } from "@page-speed/forms/inputs";

function CustomForm() {
  const form = useForm({
    initialValues: { email: "" },
    validationSchema: {
      email: (value) => (!value ? "Required" : undefined),
    },
    onSubmit: async (values) => {
      console.log(values);
    },
  });

  return (
    <Form form={form}>
      <Field name="email" label="Email">
        {({ field, meta }) => (
          <TextInput
            {...field}
            error={Boolean(meta.touched && meta.error)}
          />
        )}
      </Field>
      <button type="submit">Submit</button>
    </Form>
  );
}

Validation Utilities

Use built-in rules:

  • required, email, url, phone
  • minLength, maxLength, min, max
  • pattern, matches, oneOf
  • creditCard, postalCode, alpha, alphanumeric, numeric, integer
  • compose

Use utilities from /validation/utils:

  • debounce, asyncValidator, crossFieldValidator, when
  • setErrorMessages, getErrorMessage, resetErrorMessages

File Uploads

FileInput and FormEngine support validation, drag/drop, preview, and crop workflows.

For full two-phase upload patterns and serializer usage, see:

Development

pnpm test:ci
pnpm build
pnpm type-check

License

MIT. See LICENSE.