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

formease-sb

v0.1.2

Published

A lightweight React form validation library with 20+ built-in validators, async support, and conditional logic

Readme

React Form Validator

A lightweight, zero-dependency React form validation library with hooks-based API. Built with performance and developer experience in mind.

🎯 Overview

React Form Validator provides a complete solution for form validation in React applications:

  • 20+ Built-in Validators - String, number, date, and logical validators
  • Async Support - Native async/await validation
  • Conditional Logic - Smart validation rules based on other fields
  • Flexible Configuration - Granular control over validation triggers
  • Developer Friendly - Simple API with comprehensive error handling
  • Production Ready - Battle-tested, optimized, and maintainable

✨ Features

  • 🎯 Simple API - Intuitive hooks-based design
  • 🚀 Lightweight - Zero dependencies (~4KB gzipped)
  • 🔧 Flexible - 20+ built-in validators + custom validation
  • Performant - Optimized re-renders with React hooks
  • 🔄 Async Support - Built-in async validation support
  • 📝 Type-safe - Full TypeScript support (coming soon)
  • 🎨 Composable - Mix and match validators easily
  • 🔍 Conditional - Smart conditional validation rules
  • 🎛️ Configurable - Granular control over validation triggers

📦 Installation

npm install formease-sb

🚀 Quick Start

import { useForm, validators } from "formease-sb";

function LoginForm() {
  const { errors, touched, handleSubmit, getFieldProps } = useForm(
    { email: "", password: "" },
    {
      email: [
        validators.required("Email is required"),
        validators.email("Please enter a valid email"),
      ],
      password: [
        validators.required("Password is required"),
        validators.minLength(8, "Password must be at least 8 characters"),
      ],
    }
  );

  const onSubmit = async (values) => {
    console.log("Form values:", values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <input type="email" {...getFieldProps("email")} />
        {errors.email && touched.email && <span>{errors.email}</span>}
      </div>

      <div>
        <input type="password" {...getFieldProps("password")} />
        {errors.password && touched.password && <span>{errors.password}</span>}
      </div>

      <button type="submit">Submit</button>
    </form>
  );
}

📚 API Reference

useForm(initialValues, validationSchema, options?)

Main hook for form management and validation.

Parameters

initialValues (Object)

  • Initial values for form fields
  • Example: { email: '', password: '', age: 18 }

validationSchema (Object)

  • Validation rules for each field
  • Each field can have single validator or array of validators
  • Example:
    {
      email: validators.email(),
      password: [
        validators.required(),
        validators.minLength(8)
      ]
    }

options (Object) - Optional configuration

  • validateOnChange (boolean) - Validate on input change (default: true)
  • validateOnBlur (boolean) - Validate on blur event (default: true)
  • validateOnSubmit (boolean) - Validate on form submit (default: true)
  • initialErrors (Object) - Initial error state (default: {})
  • initialTouched (Object) - Initial touched state (default: {})

Returns

State:

  • values (Object) - Current form values
  • errors (Object) - Current validation errors
  • touched (Object) - Touched state for each field
  • isSubmitting (boolean) - Form submission state

Handlers:

  • handleChange (Function) - Input change handler
  • handleBlur (Function) - Input blur handler
  • handleSubmit (Function) - Form submit handler

Methods:

  • setValue(name, value) - Manually set field value
  • setError(name, error) - Manually set field error
  • clearField(name) - Clear field and its state
  • reset() - Reset form to initial state
  • clearErrors() - Clear all errors
  • validate() - Validate all fields
  • validateField(name, value) - Validate single field
  • validateFields(fields) - Validate specific fields
  • hasError(name) - Check if field has error
  • getFieldProps(name) - Get props for field integration

🎯 Built-in Validators

String Validators

validators.required(message?)

Validates that field is not empty.

required: validators.required("This field is required");
required: validators.required(); // Default message

validators.email(message?)

Validates email format using RFC standard regex.

email: validators.email("Please enter a valid email");

validators.minLength(length, message?)

Validates minimum string length.

password: validators.minLength(8, "Must be at least 8 characters");
password: validators.minLength(8); // Default message

validators.maxLength(length, message?)

Validates maximum string length.

username: validators.maxLength(20, "Username too long");

validators.pattern(regex, message?)

Validates using custom regular expression.

phone: validators.pattern(/^\d{10}$/, "Invalid phone number");

validators.strongPassword(message?)

Validates strong password with uppercase, lowercase, number, and special character.

password: validators.strongPassword("Weak password!");

validators.alpha(message?)

Validates only alphabetic characters.

firstName: validators.alpha("Only letters allowed");

validators.alphaNumeric(message?)

Validates alphanumeric characters.

username: validators.alphaNumeric("Only letters and numbers");

validators.url(message?)

Validates URL format.

website: validators.url("Invalid URL");

Number Validators

validators.number(message?)

Validates numeric value.

age: validators.number("Must be a number");

validators.minValueAllowed(min, message?)

Validates minimum numeric value.

age: validators.minValueAllowed(18, "Must be at least 18");

validators.maxValueAllowed(max, message?)

Validates maximum numeric value.

age: validators.maxValueAllowed(120, "Invalid age");

Date Validators

validators.date(message?)

Validates date format.

birthday: validators.date("Invalid date");

validators.futureDate(message?)

Validates that date is in the future.

appointmentDate: validators.futureDate("Must be future date");

Logical / Conditional Validators

validators.match(fieldName, message?)

Validates field matches another field (e.g., password confirmation).

confirmPassword: validators.match("password", "Passwords must match");

validators.requiredIf(fieldName, expectedValue, message?)

Conditional required validation.

licenseNumber: validators.requiredIf("hasLicense", true, "License required");

validators.differentFrom(fieldName, message?)

Validates field is different from another field.

newPassword: validators.differentFrom("oldPassword", "Must be different");

Miscellaneous Validators

validators.boolean(message?)

Validates boolean value.

terms: validators.boolean("Must accept terms");

validators.custom(validatorFn, message?)

Custom validation function. Return truthy for valid, falsy for invalid.

custom: validators.custom((value, allValues) => {
  return value.includes("@");
}, "Must contain @");

💡 Usage Examples

Basic Form

const { errors, touched, handleSubmit, getFieldProps } = useForm(
  { username: "", email: "" },
  {
    username: [
      validators.required("Username is required"),
      validators.minLength(3),
    ],
    email: [validators.required(), validators.email("Invalid email format")],
  }
);

return (
  <form onSubmit={handleSubmit(onSubmit)}>
    <input {...getFieldProps("username")} />
    {errors.username && touched.username && <span>{errors.username}</span>}

    <input {...getFieldProps("email")} />
    {errors.email && touched.email && <span>{errors.email}</span>}

    <button type="submit">Submit</button>
  </form>
);

Password Confirmation

const validationSchema = {
  password: [
    validators.required(),
    validators.minLength(8),
    validators.strongPassword(),
  ],
  confirmPassword: [
    validators.required(),
    validators.match("password", "Passwords do not match"),
  ],
};

Conditional Validation

const validationSchema = {
  hasLicense: validators.boolean(),
  licenseNumber: validators.requiredIf("hasLicense", true),
  licenseState: validators.requiredIf("hasLicense", true),
};

Custom Async Validation

const validationSchema = {
  username: [
    validators.required(),
    validators.minLength(3),
    validators.custom(async (value) => {
      const exists = await checkUsernameExists(value);
      return !exists;
    }, "Username already taken"),
  ],
};

Manual Control

const { setValue, setError, validateField, reset } = useForm(...);

// Programmatically set value
setValue('username', 'new_username');

// Manually set error
setError('username', 'Username taken');

// Validate specific field
const error = await validateField('email', '[email protected]');

// Reset entire form
reset();

Partial Validation

const { validateFields, values } = useForm(...);

// Validate only specific fields
await validateFields(['email', 'password']);

// Validates all fields by default
const isValid = await validateFields();

Check Field State

const { hasError, values, errors, touched } = useForm(...);

// Check if field has error
if (hasError('email')) {
  console.log('Email field has validation error');
}

// Direct access
if (errors.email && touched.email) {
  console.log('Email error:', errors.email);
}

⚙️ Configuration Options

Validation Triggers

Control when validation occurs:

const form = useForm(initialValues, validationSchema, {
  validateOnChange: true, // Validate on input change
  validateOnBlur: true, // Validate on blur
  validateOnSubmit: true, // Validate on submit
});

Initial State

Set initial form state:

const form = useForm({ email: "[email protected]" }, validationSchema, {
  initialErrors: { email: "Please verify email" },
  initialTouched: { email: true },
});

🛠️ Development

# Install dependencies
npm install

# Run development server with demo
npm run dev

# Build library
npm run build:lib

# Preview production build
npm run preview

# Run linter
npm run lint

📝 License

MIT


📦 Publishing This Library

Want to publish your own version of this library? See HOW_TO_PUBLISH.md for detailed instructions.

Quick steps:

  1. Choose a unique package name (or use scoped package)
  2. Login to npm: npm login
  3. Build: npm run build:lib
  4. Publish: npm publish or npm publish --access public

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


📄 Full Example

See the src/App.jsx file for a complete working example with all validators and features.