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

@hnpsaga/makeform

v0.1.2

Published

Lightweight schema-driven form library for React with strong TypeScript type inference.

Readme

MakeForm

Schema-driven TypeScript forms for React.

Build forms with strong type inference, validation, state management, dynamic rendering, and extensible UI customization — all from a single schema.

Most form libraries force you to choose between strong typing, dynamic form generation, and flexible UI customization. MakeForm provides all three. Define your form once and get:

  • Strong TypeScript inference
  • Built-in validation
  • Form state management
  • Dynamic form rendering
  • React integration
  • Renderer overrides
  • Custom field support
  • Styling overrides
  • Framework-agnostic core engine

Live Demo

Try MakeForm in action:

https://makeform-demo.vercel.app/


Features

Strong Type Inference

const schema = {
  name: textField(),
  age: numberField(),
  subscribed: checkboxField(),
};

type FormValues = InferValues<typeof schema>;

/*
{
  name: string;
  age: number;
  subscribed: boolean;
}
*/

Schema-Driven Forms

Define your form structure in one place.

const schema = {
  name: textField({
    label: 'Full Name',
    validators: [required('Name is required')],
  }),

  email: emailField({
    label: 'Email Address',
    validators: [required('Email is required'), email()],
  }),

  age: numberField({
    label: 'Age',
    validators: [min(18, 'Must be 18 or older')],
  }),
};

Dynamic Form Rendering

Render complete forms directly from a schema.

<FormRenderer form={form} schema={schema} />

Extensible UI

Replace any built-in field renderer.

<FormRenderer
  form={form}
  schema={schema}
  renderers={{
    text: CustomTextRenderer,
  }}
/>

Or create entirely new field experiences.

<FormRenderer
  form={form}
  schema={schema}
  renderers={{
    custom: {
      richText: RichTextRenderer,
    },
  }}
/>

Styling Overrides

Keep the default theme or integrate with your own design system.

<FormRenderer
  form={form}
  schema={schema}
  classNames={{
    input: 'my-input',
    field: 'my-field',
    error: 'my-error',
  }}
/>

Installation

npm install @hnpsaga/makeform

Peer dependency:

npm install react

Supports:

  • React 18
  • React 19

Quick Start

import { useForm, FormRenderer, textField, emailField, required, email } from '@hnpsaga/makeform';

const schema = {
  name: textField({
    label: 'Name',
    validators: [required()],
  }),

  email: emailField({
    label: 'Email',
    validators: [required(), email()],
  }),
};

export default function App() {
  const form = useForm(schema);

  const submit = form.handleSubmit((values) => {
    console.log(values);
  });

  return (
    <>
      <FormRenderer form={form} schema={schema} />

      <button onClick={submit}>Submit</button>
    </>
  );
}

Core Concepts

1. Schema Definition

Schemas define field types, labels, default values, validation rules, and rendering metadata.

const schema = {
  firstName: textField({
    label: 'First Name',
    validators: [required('First name is required')],
  }),

  age: numberField({
    label: 'Age',
    validators: [min(18, 'Minimum age is 18')],
  }),
};

2. Type Inference

Generate form value types automatically — no manual interfaces required.

type FormValues = InferValues<typeof schema>;

3. Validation

Attach validators directly to fields.

const schema = {
  password: passwordField({
    validators: [required(), min(8)],
  }),
};

Each validator accepts an optional custom error message.

required('Password is required');
min(8, 'Password must be at least 8 characters');
max(50, 'Password must be at most 50 characters');
pattern(/^[a-zA-Z]+$/, 'Letters only');
email('Invalid email address');
phone('Invalid phone number');

When no message is provided, a default message is used.

required()  // → "Field is required"
min(3)      // → "Minimum length is 3"
max(10)     // → "Maximum length is 10"

Validate manually:

const result = form.validate();

if (!result.valid) {
  console.log(result.errors);
}

Built-in validators:

required(message?);
min(limit, message?);
max(limit, message?);
pattern(regex, message?);
email(message?);
phone(message?);
custom(fn);

4. Form Submission

MakeForm includes a submission helper.

const submit = form.handleSubmit((values) => {
  console.log(values);
});

submit();

handleSubmit():

  1. Marks all fields as touched
  2. Runs validation
  3. Prevents invalid submission
  4. Returns strongly typed values

API Overview

Form State Engine

The core engine is framework agnostic.

import { createForm } from '@hnpsaga/makeform';

const form = createForm(schema);

Available APIs:

form.getValues();
form.getValue('name');

form.setValue('name', 'John');

form.validate();

form.reset();

form.markAllTouched();

form.handleSubmit(callback);

form.subscribe(listener);

React Integration

useForm

Creates and manages a form instance bound to React's rendering cycle.

const form = useForm(schema);

useField

Subscribe to a single field. Only re-renders when that field changes.

const name = useField(form, 'name');

Returns:

{
  value,
  errors,
  touched,
  dirty,
  setValue,
}

Dynamic Form Rendering

FormRenderer

Automatically renders a complete form.

<FormRenderer form={form} schema={schema} />

Supported field types:

| Field | | ---------------- | | textField | | textareaField | | emailField | | phoneField | | passwordField | | numberField | | dateField | | checkboxField | | radioField | | selectField | | multiSelectField | | customField |

Renderer Overrides

Replace built-in field renderers with your own components.

<FormRenderer
  form={form}
  schema={schema}
  renderers={{
    text: CustomTextRenderer,
    email: CustomEmailRenderer,
  }}
/>

Useful for:

  • Design systems
  • Component libraries
  • Internal UI standards

Custom Renderers

Integrate third-party components such as rich text editors, date pickers, phone pickers, file uploads, typeahead inputs, and location pickers.

Schema:

const schema = {
  bio: customField<string>({
    component: 'richText',
  }),
};

Renderer:

<FormRenderer
  form={form}
  schema={schema}
  renderers={{
    custom: {
      richText: RichTextRenderer,
    },
  }}
/>

Custom renderers automatically participate in validation, state updates, dirty tracking, touched tracking, reset, and submission.

Field Renderer Overrides

Complete field-level overrides that replace the entire field presentation — label, error, layout, and input.

import type { FieldRendererProps, FieldRenderers, TextField } from '@hnpsaga/makeform';

function MuiTextRenderer({ id, field, fieldState }: FieldRendererProps<string, TextField>) {
  return (
    <TextField
      id={id}
      label={field.label}
      value={fieldState.value}
      onChange={(e) => fieldState.setValue(e.target.value)}
      error={fieldState.touched && fieldState.errors.length > 0}
      helperText={fieldState.touched ? fieldState.errors[0] : undefined}
      fullWidth
    />
  );
}

<FormRenderer
  form={form}
  schema={schema}
  fieldRenderers={{
    text: MuiTextRenderer,
  }}
/>;

Resolution Priority

fieldRenderers.text
        ↓
renderers.text
        ↓
builtInRenderers.text

When to Use

| Extension Point | Controls | Use Case | | ---------------- | ------------------- | ------------------------- | | fieldRenderers | Label, error, input | Design system integration | | renderers | Input only | Custom input controls | | Built-in | Everything | Default MakeForm UI |

Default Theme

MakeForm ships with a clean default theme.

import '@hnpsaga/makeform/dist/styles/default.css';

Includes responsive layout, labels, inputs, selects, textareas, checkboxes, radio groups, and error states.

Styling Overrides

Customize styling without replacing renderers.

<FormRenderer
  form={form}
  schema={schema}
  classNames={{
    form: 'my-form',
    grid: 'my-grid',
    field: 'my-field',
    label: 'my-label',
    input: 'my-input',
    error: 'my-error',
  }}
/>

Default styles remain active. Custom classes are appended.

Architecture

MakeForm consists of five layers:

Schema System
      ↓
Type Inference
      ↓
Validation Engine
      ↓
Form State Engine
      ↓
React Rendering Layer

The form engine itself is framework agnostic. React integration is intentionally thin.


Status

Current Release: v0.1.2

This project is actively maintained and available on npm.


Development

A demo application is available in apps/demo/ demonstrating schema definition, validation, form state, submission, and dynamic rendering.

Running the Demo

# Build the library first
npm run build

# Navigate to the demo app
cd apps/demo

# Install dependencies
npm install

# Start the dev server
npm run dev

Demo Pages

  • Home — Introduction and navigation
  • Registration — Registration form with text, email, password, and checkbox fields
  • Profile — Profile form with text, textarea, phone, date, and select fields
  • Validation — Validation showcase with required, min, max, pattern, and custom validators
  • Features — Overview of MakeForm features
  • Styling — Styling showcase with default theme, custom classNames, and utility-style customization
  • Renderers — Demonstrates renderers (input replacement) and fieldRenderers (complete field replacement)
  • Advanced — Specialized input controls (rich text editor, rating, tag selector) via renderers
  • Material UI — Material UI integration via fieldRenderers

Contributing

Issues and pull requests are welcome.

Before submitting changes:

npm run lint
npm run typecheck
npm run test
npm run build

License

MIT