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 🙏

© 2025 – Pkg Stats / Ryan Hefner

full-form-control

v0.1.6

Published

Headless form management for React & Next.js

Readme

full-form-control npm version Downloads License: MIT

full-form-control is a React hook library for managing complete form state and validation in one place. It provides an internal form store so you don’t need external state management. You can initialize it with default values and validation rules, then bind inputs as controlled components. The form values and errors are kept in React state and updated via onChange handlers – as the React docs note, with controlled components “the input’s value is always driven by the React state”. This package works with React 18+ out of the box and is written in TypeScript for type safety and developer-friendly errors.

Features

  • Comprehensive form state: Manages all form values (formValues) and validation errors (errors) internally, with no extra Redux/Zustand/etc. needed.
  • Validation-ready: Supports custom validation and popular schema libraries (e.g. Joi, Zod, Yup) for validating inputs.
  • Simple API: Returns useful properties/methods (formValues, errors, isValid, setFormValues, clearFormValues, unsubscribeFromStore) for easy form handling (see API table below).
  • TypeScript support: Written in TS; forms and schemas can be strongly typed.
  • React 18+ compatible: Safe to use with Concurrent Mode, Suspense, etc. (standard controlled components pattern).
  • Lightweight: Minimal dependencies; no external state or context setup needed.

Installation

Install via NPM (or Yarn):

npm install full-form-control

API

Using useFormStore() (imported from 'full-form-control') returns an object with the following properties and methods:

| Property / Method | Description | |--------------------------|-----------------------------------------------------------------------------------------| | formValues | Current form values (an object keyed by field name) | | errors | Current validation errors (object with same keys; each value is an object with a message) | | isValid | Boolean; true if there are no validation errors | | setFormValues | Function to update form values. Typically called as setFormValues(fieldName, value). | | clearFormValues | Function to reset/clear all form values back to initial (or empty) state. | | unsubscribeFromStore | Function to unsubscribe any internal listeners (call if needed on unmount). |

Example: In your component, call const form = useFormStore({ /* options */ }). Then access form.formValues, form.errors, etc. You might use const { formValues, setFormValues, errors, isValid } = form; to work with them directly.

You can try on this npm on Playcode: testForm for full-form-control

Quick Start

Use the useFormStore hook to manage your form. For example:

import { useFormStore } from "full-form-control";

function SignupForm() {
  const { formValues, setFormValues, errors, isValid } = useFormStore({
    initialValues: { username: "", email: "" },
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues(name, value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="username" value={formValues.username || ""} onChange={handleChange} />
      <input name="email" value={formValues.email || ""} onChange={handleChange} />
      {errors.username && <span>{errors.username.message}</span>}
      {errors.email && <span>{errors.email.message}</span>}
    </form>
  );
}

Examples: Validation Schemas

You can plug in validation schemas from libraries like Joi, Zod, or Yup. Each example below shows defining a schema; you would then pass it into useFormStore.

const Joi = require("joi");

const schema = Joi.object({
  username: Joi.string().alphanum().min(3).required(),
  password: Joi.string().min(6).required(),
  email: Joi.string().email({ tlds: { allow: false } }).required()
});
import { z } from "zod";

const schema = z.object({
  username: z.string().min(3, "Must be 3+ chars"),
  age: z.number().int().nonnegative().optional(),
  email: z.string().email()
});
import * as Yup from "yup";

const schema = Yup.object().shape({
  username: Yup.string().min(3, "Too short").required("Required"),
  email: Yup.string().email("Invalid email").required("Required")
});
const customValidator = (values) => {
  const errors = {};
  if (values.username && values.username.length < 3) {
    errors.username = { message: "Too short" };
  }
  if (values.email && !values.email.includes("@")) {
    errors.email = { message: "Invalid email" };
  }
  return errors;
};

Custom Validation Schema Structure

When writing your own validation logic or adapter, make sure the result is an “errors” object keyed by form fields. Each entry should be an object with a message string, e.g.: { email: { message: "Invalid email" } }. Keeping this structure ensures that errors for each field can be accessed and displayed easily.

Changelog & Links

See CHANGELOG.md for release notes and version history.
GitHub: VolcharaMastering/full-form-control

TODO

  • Add validation library support: valibot, superstruct, typia, ajv, vest.
  • Add built-in HTML validation support
  • Add JS (non-TS) support