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

@siphesihle_thomo/form-generator

v1.0.0

Published

A schema driven form generator for React

Readme

@form-generator/core

A schema-driven form generator for React applications that combines the power of Zod for validation, React Hook Form for form state management, and customizable field renderers.

Features

  • 🎯 Schema-driven: Define your form structure using Zod schemas
  • 🔧 Type-safe: Full TypeScript support with automatic type inference
  • 🎨 Customizable: Extensible field renderers for any UI component
  • Performance: Built on React Hook Form for optimal performance
  • 🎨 Styling: Built-in Tailwind CSS classes with custom styling support
  • 🔌 Flexible: Support for custom field types and renderers

Installation

npm install @form-generator/core
# or
yarn add @form-generator/core
# or
pnpm add @form-generator/core

Peer Dependencies

This package requires the following peer dependencies:

npm install react react-dom zod react-hook-form @hookform/resolvers

Quick Start

import React from 'react';
import { z } from 'zod';
import { FormGenerator } from '@form-generator/core';

// Define your form schema
const userSchema = z.object({
  name: z.string().min(2, 'Name must be at least 2 characters'),
  email: z.string().email('Invalid email address'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
});

// Define your field configurations
const fieldConfigs = [
  {
    name: 'name',
    label: 'Full Name',
    type: 'text',
    placeholder: 'Enter your full name',
    required: true,
  },
  {
    name: 'email',
    label: 'Email Address',
    type: 'email',
    placeholder: 'Enter your email',
    required: true,
  },
  {
    name: 'password',
    label: 'Password',
    type: 'password',
    placeholder: 'Enter your password',
    required: true,
  },
];

function App() {
  const handleSubmit = (data: z.infer<typeof userSchema>) => {
    console.log('Form data:', data);
    // Handle form submission
  };

  return (
    <div className="max-w-md mx-auto mt-8 p-6">
      <h1 className="text-2xl font-bold mb-6">User Registration</h1>
      <FormGenerator
        schema={userSchema}
        fieldConfigs={fieldConfigs}
        onSubmit={handleSubmit}
        submitText="Create Account"
      />
    </div>
  );
}

export default App;

API Reference

FormGenerator

The main component that renders the form based on your schema and field configurations.

Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | schema | z.ZodType<any, any> | ✅ | Zod schema for form validation | | fieldConfigs | FieldProps[] | ✅ | Array of field configurations | | onSubmit | (data: any) => void | ✅ | Callback function called on form submission | | className | string | ❌ | CSS classes for the form container | | submitText | string | ❌ | Text for the submit button (default: "Submit") | | submitVariant | "default" \| "destructive" \| "outline" | ❌ | Button styling variant | | submitClassName | string | ❌ | Custom CSS classes for submit button | | customRenderers | Partial<Record<FieldType, FieldRenderer>> | ❌ | Custom field renderers |

FieldProps

Configuration object for individual form fields.

interface FieldProps {
  name: string;                    // Field name (must match schema)
  label?: string;                  // Field label
  type?: FieldType;               // Field type
  placeholder?: string;            // Input placeholder
  options?: Option[];             // Options for select/radio fields
  required?: boolean;             // Whether field is required
  disabled?: boolean;             // Whether field is disabled
  styles?: {                      // Custom CSS classes
    container?: string;
    label?: string;
    input?: string;
    error?: string;
  };
  render?: FieldRenderer;         // Custom renderer function
}

Field Types

Currently supported field types:

  • text - Text input
  • email - Email input
  • password - Password input
  • number - Number input
  • checkbox - Checkbox input
  • radio - Radio button group
  • select - Select dropdown
  • textarea - Textarea

useForm Hook

A custom hook that provides form methods with Zod validation.

import { useForm } from '@form-generator/core';

const formMethods = useForm(schema);

Advanced Usage

Custom Field Renderers

You can create custom renderers for specific field types:

import React from 'react';
import { FormGenerator, FieldProps } from '@form-generator/core';

const customRenderers = {
  textarea: ({ name, label, placeholder, required }: FieldProps) => (
    <div className="mb-4">
      {label && (
        <label htmlFor={name} className="block mb-1 font-medium text-sm text-gray-700">
          {label}
        </label>
      )}
      <textarea
        id={name}
        name={name}
        placeholder={placeholder}
        required={required}
        className="w-full border rounded px-3 py-2 focus:outline-none focus:ring focus:ring-black min-h-[100px]"
      />
    </div>
  ),
  select: ({ name, label, options, required }: FieldProps) => (
    <div className="mb-4">
      {label && (
        <label htmlFor={name} className="block mb-1 font-medium text-sm text-gray-700">
          {label}
        </label>
      )}
      <select
        id={name}
        name={name}
        required={required}
        className="w-full border rounded px-3 py-2 focus:outline-none focus:ring focus:ring-black"
      >
        <option value="">Select an option</option>
        {options?.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
    </div>
  ),
};

function App() {
  return (
    <FormGenerator
      schema={schema}
      fieldConfigs={fieldConfigs}
      onSubmit={handleSubmit}
      customRenderers={customRenderers}
    />
  );
}

Custom Styling

You can customize the styling of individual fields:

const fieldConfigs = [
  {
    name: 'email',
    label: 'Email',
    type: 'email',
    styles: {
      container: 'mb-6',
      label: 'block mb-2 text-sm font-semibold text-gray-800',
      input: 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent',
      error: 'mt-1 text-sm text-red-600',
    },
  },
];

Complex Forms

For complex forms with nested objects or arrays:

const complexSchema = z.object({
  personalInfo: z.object({
    firstName: z.string().min(2),
    lastName: z.string().min(2),
    email: z.string().email(),
  }),
  preferences: z.object({
    newsletter: z.boolean(),
    notifications: z.boolean(),
  }),
});

const complexFieldConfigs = [
  {
    name: 'personalInfo.firstName',
    label: 'First Name',
    type: 'text',
  },
  {
    name: 'personalInfo.lastName',
    label: 'Last Name',
    type: 'text',
  },
  {
    name: 'personalInfo.email',
    label: 'Email',
    type: 'email',
  },
  {
    name: 'preferences.newsletter',
    label: 'Subscribe to newsletter',
    type: 'checkbox',
  },
  {
    name: 'preferences.notifications',
    label: 'Enable notifications',
    type: 'checkbox',
  },
];

Form Validation

The form automatically validates based on your Zod schema:

const validationSchema = z.object({
  username: z.string()
    .min(3, 'Username must be at least 3 characters')
    .max(20, 'Username must be less than 20 characters')
    .regex(/^[a-zA-Z0-9_]+$/, 'Username can only contain letters, numbers, and underscores'),
  email: z.string()
    .email('Please enter a valid email address'),
  password: z.string()
    .min(8, 'Password must be at least 8 characters')
    .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, 'Password must contain at least one uppercase letter, one lowercase letter, and one number'),
  confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
  message: "Passwords don't match",
  path: ["confirmPassword"],
});

Examples

Login Form

const loginSchema = z.object({
  email: z.string().email('Invalid email address'),
  password: z.string().min(1, 'Password is required'),
});

const loginFields = [
  {
    name: 'email',
    label: 'Email',
    type: 'email',
    placeholder: 'Enter your email',
  },
  {
    name: 'password',
    label: 'Password',
    type: 'password',
    placeholder: 'Enter your password',
  },
];

<FormGenerator
  schema={loginSchema}
  fieldConfigs={loginFields}
  onSubmit={handleLogin}
  submitText="Sign In"
  submitVariant="default"
/>

Registration Form with Custom Styling

const registrationFields = [
  {
    name: 'firstName',
    label: 'First Name',
    type: 'text',
    required: true,
    styles: {
      container: 'mb-4',
      label: 'block text-sm font-medium text-gray-700 mb-1',
      input: 'w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500',
    },
  },
  {
    name: 'lastName',
    label: 'Last Name',
    type: 'text',
    required: true,
  },
  {
    name: 'email',
    label: 'Email Address',
    type: 'email',
    required: true,
  },
  {
    name: 'role',
    label: 'Role',
    type: 'select',
    options: [
      { value: 'user', label: 'User' },
      { value: 'admin', label: 'Administrator' },
      { value: 'moderator', label: 'Moderator' },
    ],
  },
];

<FormGenerator
  schema={registrationSchema}
  fieldConfigs={registrationFields}
  onSubmit={handleRegistration}
  submitText="Create Account"
  submitVariant="default"
  className="max-w-lg mx-auto p-6 bg-white rounded-lg shadow-md"
/>

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

If you have any questions or need help, please open an issue on GitHub or contact the maintainers.