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

z-quick-forms

v1.0.31

Published

A powerful, configurable React form engine that generates dynamic forms from JSON configuration. Built with TypeScript, supports conditional rendering, validation, and complex form structures.

Downloads

44

Readme

Z-Quick-Forms

A powerful, configurable React form engine that generates dynamic forms from JSON configuration. Built with TypeScript, supports conditional rendering, validation, and complex form structures.

🚀 Features

  • Dynamic Form Generation: Create forms from JSON configuration
  • Multiple Input Types: Support for text, select, radio, checkbox, signature, and more
  • Conditional Rendering: Show/hide fields based on other field values
  • Validation System: Built-in and custom validation with error handling
  • Nested Forms: Unlimited nesting depth with parent-child relationships
  • TypeScript Support: Full TypeScript definitions included
  • Chakra UI Integration: Beautiful, accessible components out of the box
  • Tailwind CSS Support: Custom styling with className props
  • Form State Management: Built-in state tracking and form validation

📦 Installation

npm install z-quick-forms

Peer Dependencies

This package only requires React as a peer dependency:

npm install react

Note: While this package works with any styling solution, it's optimized for use with Tailwind CSS. If you want to use Tailwind classes in your form configurations, you'll need to install and configure Tailwind CSS separately.

🎯 Quick Start

import { FormEngine } from 'z-quick-forms';

function MyForm() {
  const formConfig = [
    {
      question: 'What is your name?',
      name: 'name',
      type: 'text',
      placeholder: 'Enter your name',
    },
    {
      question: 'When is your birthday?',
      name: 'birthday',
      type: 'date',
    },
  ];

  return (
    <FormEngine
      config={formConfig}
      Submit={({ getData, isFormValid }) => (
        <button
          onClick={() => {
            const { isValid, data } = getData();
            if (isValid) {
              console.log('Form data:', data);
            }
          }}
          disabled={!isFormValid()}
        >
          Submit
        </button>
      )}
    />
  );
}

📋 Configuration

The FormEngine component accepts the following props:

FormEngine Props

| Prop | Type | Required | Description | | -------------- | ------------------------- | -------- | ---------------------------------- | | config | FormConfigProp[] | ✅ | Array of form field configurations | | Submit | React.FC<SubmitProps> | ❌ | Custom submit component | | constants | ConstantsType | ❌ | Global styling constants | | stateTracker | (data: unknown) => void | ❌ | Callback for form state changes |

FormConfigProp Properties

Each form field configuration supports the following properties:

Basic Properties

| Property | Type | Description | | -------------- | ------------------ | --------------------------------------------- | | question | string | The question/label for the field | | name | string | Unique identifier for the field | | type | string | HTML input type (text, email, password, etc.) | | placeholder | string | Placeholder text for input fields | | defaultValue | string \| number | Default value for the field | | className | string | CSS classes for styling | | disabled | boolean | Whether the field is disabled |

Advanced Properties

| Property | Type | Description | | ---------------------- | --------------------- | ---------------------------------------- | | complexType | ComplexType | Special input type (see below) | | options | OptionsType[] | Options for select/radio/checkbox fields | | validationConditions | CheckType[] | Validation rules | | displayConditions | CheckType[] | Conditional rendering rules | | customValidator | CustomValidatorType | Custom validation function | | customElement | CustomElementType | Custom React component |

🎨 Input Types

Basic Input Types

// Text input
{
  question: "What is your name?",
  name: "name",
  type: "text",
  placeholder: "Enter your name"
}

// Email input
{
  question: "What is your email?",
  name: "email",
  type: "email",
  placeholder: "Enter your email"
}

// Password input
{
  question: "Enter your password",
  name: "password",
  type: "password"
}

// Number input
{
  question: "How old are you?",
  name: "age",
  type: "number"
}

// Date input
{
  question: "When is your birthday?",
  name: "birthday",
  type: "date"
}

// Textarea
{
  question: "Tell us about yourself",
  name: "bio",
  type: "textarea",
  placeholder: "Write something..."
}

Complex Input Types

Select Dropdown

{
  question: "Choose your country",
  name: "country",
  complexType: "SELECT",
  options: ["USA", "Canada", "UK", "Australia"],
  placeholder: "Select a country"
}

Multi-Select

{
  question: "Select your interests",
  name: "interests",
  complexType: "MULTI-SELECT",
  options: ["Sports", "Music", "Reading", "Travel"],
  placeholder: "Choose multiple options"
}

Radio Group

{
  question: "What is your gender?",
  name: "gender",
  complexType: "RADIO_GROUP",
  options: ["Male", "Female", "Other"],
  direction: "row" // or "column"
}

Checkbox

{
  question: "Do you agree to the terms?",
  name: "agree",
  complexType: "CHECKBOX",
  label: "I agree to the terms and conditions"
}

Multiple Checkboxes

{
  question: "Select your favorite colors",
  name: "colors",
  complexType: "MULTIPLE_CHECKBOX",
  options: ["Red", "Blue", "Green", "Yellow"],
  noneOption: true // Adds "None" option
}

Signature

{
  question: "Please sign here",
  name: "signature",
  complexType: "SIGNATURE"
}

Input Group

{
  question: "Enter your phone number",
  name: "phone",
  complexType: "INPUT_GROUP",
  group: {
    type: "phone",
    countryCode: "+1",
    placeholder: "Enter phone number"
  }
}

Select with Value Options

For select fields that need additional input values:

{
  question: "Choose your subscription",
  name: "subscription",
  complexType: "SELECT_WITH_VALUE",
  options: [
    {
      label: "Basic Plan",
      optionalValue: true,
      valuePlaceholder: "Enter custom amount",
      valueType: "number"
    },
    {
      label: "Premium Plan",
      optionalValue: false
    }
  ]
}

🔄 Conditional Rendering

Simple Parent-Child Relationship

const config = [
  {
    question: 'Do you have a car?',
    name: 'hasCar',
    complexType: 'RADIO_GROUP',
    options: ['Yes', 'No'],
  },
  {
    question: 'What is your car model?',
    name: 'carModel',
    type: 'text',
    displayConditions: [
      {
        attr: 'hasCar',
        eq: 'Yes',
      },
    ],
  },
];

Complex Conditional Logic

{
  question: "Enter your age",
  name: "age",
  type: "number"
},
{
  question: "Parent consent required",
  name: "parentConsent",
  complexType: "CHECKBOX",
  displayConditions: [
    {
      attr: "age",
      lt: 18
    }
  ]
}

Multiple Conditions

{
  question: "Special discount code",
  name: "discountCode",
  type: "text",
  displayConditions: [
    {
      attr: "age",
      ge: 18
    },
    {
      attr: "hasCar",
      eq: "Yes"
    }
  ]
}

✅ Validation

Built-in Validation

{
  question: "Enter your email",
  name: "email",
  type: "email",
  defaultValidation: { enabled: true },
  errorMessage: "Please enter a valid email address"
}

Custom Validation

{
  question: "Enter your username",
  name: "username",
  type: "text",
  customValidator: (value, values, setError) => {
    if (value === "admin") {
      setError("Username 'admin' is reserved");
      return true; // indicates error
    }
    if (value && value.length < 3) {
      setError("Username must be at least 3 characters");
      return true;
    }
    return false; // no error
  }
}

Validation Conditions

{
  question: "Confirm password",
  name: "confirmPassword",
  type: "password",
  validationConditions: [
    {
      attr: "password",
      eq: "confirmPassword",
      errorMessage: "Passwords must match"
    }
  ]
}

Complex Validation Rules

{
  question: "Enter your age",
  name: "age",
  type: "number",
  validationConditions: [
    {
      gt: 0,
      errorMessage: "Age must be positive"
    },
    {
      lt: 120,
      errorMessage: "Age must be less than 120"
    }
  ]
}

🎨 Styling

Using Tailwind CSS

{
  question: "What is your name?",
  name: "name",
  type: "text",
  className: "w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500"
}

Global Styling Constants

<FormEngine
  config={config}
  constants={{
    question: {
      className: 'text-lg font-semibold text-gray-800 mb-2',
      style: { color: '#374151' },
    },
  }}
  Submit={SubmitComponent}
/>

Custom Error Styling

{
  question: "Enter your email",
  name: "email",
  type: "email",
  errorClassName: "text-red-500 text-sm mt-1"
}

🔧 Advanced Features

Custom Elements

{
  question: "Upload your file",
  name: "file",
  customElement: ({ name, onChange, disabled }) => (
    <input
      type="file"
      onChange={(e) => onChange(e.target.files?.[0]?.name || "")}
      disabled={disabled}
      className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
    />
  )
}

Form State Tracking

<FormEngine
  config={config}
  stateTracker={(data) => {
    console.log('Form state changed:', data);
    // Save to localStorage, send to server, etc.
  }}
  Submit={SubmitComponent}
/>

Submit Component

const SubmitComponent = ({ getData, isFormValid, data }) => {
  const handleSubmit = () => {
    const { isValid, data: cleanData } = getData();
    if (isValid) {
      console.log('Submitting:', cleanData);
      // Send data to server
    } else {
      console.log('Form has errors');
    }
  };

  return (
    <button
      onClick={handleSubmit}
      disabled={!isFormValid()}
      className="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
    >
      Submit Form
    </button>
  );
};

📝 Complete Example

import React from 'react';
import { FormEngine } from 'z-quick-forms';

function RegistrationForm() {
  const config = [
    {
      question: 'What is your full name?',
      name: 'fullName',
      type: 'text',
      placeholder: 'Enter your full name',
      defaultValidation: { enabled: true },
    },
    {
      question: 'What is your email address?',
      name: 'email',
      type: 'email',
      placeholder: 'Enter your email',
      validationConditions: [
        {
          contains: '@',
          errorMessage: 'Please enter a valid email address',
        },
      ],
    },
    {
      question: 'How old are you?',
      name: 'age',
      type: 'number',
      validationConditions: [
        {
          gt: 0,
          errorMessage: 'Age must be positive',
        },
        {
          lt: 120,
          errorMessage: 'Age must be less than 120',
        },
      ],
    },
    {
      question: "Do you have a driver's license?",
      name: 'hasLicense',
      complexType: 'RADIO_GROUP',
      options: ['Yes', 'No'],
    },
    {
      question: 'What type of vehicle do you drive?',
      name: 'vehicleType',
      complexType: 'SELECT',
      options: ['Car', 'Motorcycle', 'Truck', 'Other'],
      displayConditions: [
        {
          attr: 'hasLicense',
          eq: 'Yes',
        },
      ],
    },
    {
      question: 'Select your interests',
      name: 'interests',
      complexType: 'MULTIPLE_CHECKBOX',
      options: ['Sports', 'Music', 'Reading', 'Travel', 'Cooking'],
      noneOption: true,
    },
    {
      question: 'Tell us about yourself',
      name: 'bio',
      type: 'textarea',
      placeholder: 'Write a short bio...',
    },
    {
      question: 'Please sign to confirm',
      name: 'signature',
      complexType: 'SIGNATURE',
      displayConditions: [
        {
          attr: 'age',
          ge: 18,
        },
      ],
    },
  ];

  const SubmitButton = ({ getData, isFormValid }) => (
    <button
      onClick={() => {
        const { isValid, data } = getData();
        if (isValid) {
          console.log('Registration data:', data);
          // Submit to server
        }
      }}
      disabled={!isFormValid()}
      className="w-full px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
    >
      Register
    </button>
  );

  return (
    <div className="max-w-2xl mx-auto p-6">
      <h1 className="text-3xl font-bold mb-6">Registration Form</h1>
      <FormEngine
        config={config}
        Submit={SubmitButton}
        constants={{
          question: {
            className: 'text-lg font-medium text-gray-900 mb-2',
          },
        }}
        stateTracker={(data) => {
          // Optional: Track form state changes
          console.log('Form updated:', data);
        }}
      />
    </div>
  );
}

export default RegistrationForm;

🔍 Validation Conditions Reference

Simple Conditions

| Property | Description | Example | | ---------- | --------------------- | ----------------------------------------- | | eq | Equal to | { attr: "age", eq: 18 } | | ne | Not equal to | { attr: "status", ne: "inactive" } | | gt | Greater than | { attr: "score", gt: 80 } | | lt | Less than | { attr: "age", lt: 65 } | | ge | Greater than or equal | { attr: "quantity", ge: 1 } | | le | Less than or equal | { attr: "price", le: 100 } | | contains | Contains substring | { attr: "email", contains: "@" } | | isIn | Value is in array | { attr: "country", isIn: ["US", "CA"] } | | len | Length check | { attr: "password", len: 8 } |

Complex Conditions

{
  if: { attr: "userType", eq: "premium" },
  then: [
    { attr: "age", ge: 18 },
    { attr: "email", contains: "@" }
  ],
  errorMessage: "Premium users must be 18+ with valid email"
}

🚨 Error Handling

The form engine provides comprehensive error handling:

  • Validation Errors: Displayed below each field
  • Form Validation: Prevents submission when errors exist
  • Custom Error Messages: Configurable error text
  • Error Styling: Customizable error appearance

📦 Bundle Size

The package is optimized for size:

  • Minified: ~10KB
  • Gzipped: ~3KB

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🆘 Support

For issues and questions:

  • Create an issue on GitHub
  • Check the examples in the /example directory
  • Review the TypeScript definitions for detailed type information

🔄 Migration Guide

From v1.0 to v2.0

  • parent property is deprecated, use displayConditions instead
  • displayCondition function is deprecated, use displayConditions array
  • additionalInputs is deprecated, use displayConditions for nested fields
  • customValidator is deprecated, use validationConditions for better performance

Deprecated Properties

// ❌ Old way (deprecated)
{
  question: "Child field",
  name: "child",
  parent: "parentField"
}

// ✅ New way
{
  question: "Child field",
  name: "child",
  displayConditions: [
    { attr: "parentField", eq: true }
  ]
}

Built with ❤️ using React, TypeScript, and Chakra UI