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

react-render-form-input-cli

v1.2.1

Published

A powerful CLI tool that generates reusable React form components with automatic shadcn/ui integration. Quickly scaffold form inputs with TypeScript support, validation, and modern UI components.

Readme

React Render Form Input CLI

A powerful CLI tool that generates reusable React form components with automatic shadcn/ui integration. Quickly scaffold form inputs with TypeScript support, validation, and modern UI components.

Features

Automatic shadcn/ui Integration - Detects and installs required shadcn/ui components 🎯 TypeScript Support - Fully typed form components and configurations 🔧 Multiple Input Types - Support for text, textarea, select, multi-select, currency, and searchable dropdowns 📦 Zero Configuration - Works out of the box with sensible defaults 🎨 Customizable - Easy to modify and extend generated components 🚀 Modern Stack - Built with React Hook Form, Zod validation, and Tailwind CSS

Quick Start

1. Create a Next.js Project (Recommended)

npx create-next-app@latest my-form-app --typescript --tailwind --eslint --app
cd my-form-app

2. Initialize shadcn/ui

npx shadcn@latest init

3. Run the CLI

npx react-render-form-input-cli@latest add-form

Installation

For global installation:

npm install -g react-render-form-input-cli

Or use directly with npx (recommended):

npx react-render-form-input-cli@latest add-form

Prerequisites

Your project should have:

  • Next.js 13+ (recommended) or React 18+
  • TypeScript
  • Tailwind CSS
  • shadcn/ui initialized
  • A package manager (npm, yarn, or pnpm)

Note: Next.js is the recommended framework due to better shadcn/ui compatibility and active maintenance. Create React App is deprecated and may cause compatibility issues.

Usage

Basic Usage

Navigate to your Next.js project directory and run:

react-render-form add-form

This command will:

  1. 🔍 Check if shadcn/ui is initialized in your project
  2. 🚀 Initialize shadcn/ui if not present (with default settings)
  3. 📦 Install required shadcn/ui components (input, textarea, form, label)
  4. 📁 Create form components in src/components/form/ (or components/form/ if no src folder)
  5. 📝 Install additional dependencies (react-hook-form, react-select)

Force Overwrite

To overwrite existing form components:

react-render-form add-form --force

Generated Components

The CLI generates the following files:

components/
├── form/
│   ├── RenderFormInput.tsx    # Main form input renderer
│   └── formInputWrapper.tsx   # Form field wrapper with validation
└── types/
    └── form.ts                # TypeScript definitions

Usage Examples

🚀 The Power of Config-Driven Forms

The generated FormInputWrapper component revolutionizes form development by handling all form logic through configuration. No more repetitive onChange handlers, manual error display, or state management - just provide the config and everything works automatically!

Complete Form Example

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Form } from "@/components/ui/form";
import { FormInputWrapper } from "@/components/form/FormInputWrapper";
import { Button } from "@/components/ui/button";

// Define your schema
const formSchema = z.object({
  contact: z.object({
    email: z.string().email("Invalid email address"),
    name: z.string().min(2, "Name must be at least 2 characters"),
  }),
  preferences: z.object({
    country: z.string().min(1, "Please select a country"),
    skills: z.array(z.object({ label: z.string(), value: z.string() })),
    bio: z.string().optional(),
  }),
  salary: z.string().min(1, "Salary is required"),
});

type FormData = z.infer<typeof formSchema>;

function ContactForm() {
  const form = useForm<FormData>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      contact: { email: "", name: "" },
      preferences: { country: "", skills: [], bio: "" },
      salary: "",
    },
  });

  const onSubmission = (data: FormData) => {
    console.log("Form submitted:", data);
  };

  const reviewOnly = false; // Toggle for read-only mode

  return (
    <Form {...form}>
      <form onSubmit={(event) => void form.handleSubmit(onSubmission)(event)} className="space-y-6">
        {/* Email Input - Just config, no onChange needed! */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "input",
            label: "Contact Email",
            name: "contact.email",
            inputType: "email",
            placeHolder: "Email address",
            disabled: reviewOnly,
          }}
        />

        {/* Name Input */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "input",
            label: "Full Name",
            name: "contact.name",
            placeHolder: "Your full name",
            disabled: reviewOnly,
          }}
        />

        {/* Country Select */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "select",
            label: "Country",
            name: "preferences.country",
            placeHolder: "Select your country",
            options: [
              { label: "United States", value: "us" },
              { label: "Canada", value: "ca" },
              { label: "United Kingdom", value: "uk" },
            ],
            disabled: reviewOnly,
          }}
        />

        {/* Multi-Select Skills */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "multiSelect",
            label: "Skills",
            name: "preferences.skills",
            placeHolder: "Select your skills",
            options: [
              { label: "React", value: "react" },
              { label: "TypeScript", value: "typescript" },
              { label: "Node.js", value: "nodejs" },
              { label: "Python", value: "python" },
            ],
            disabled: reviewOnly,
          }}
        />

        {/* Textarea Bio */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "textArea",
            label: "Bio",
            name: "preferences.bio",
            placeHolder: "Tell us about yourself",
            disabled: reviewOnly,
          }}
        />

        {/* Currency Input */}
        <FormInputWrapper
          form={form}
          fieldConfig={{
            fieldVariant: "currencyInput",
            label: "Expected Salary",
            name: "salary",
            placeHolder: "Enter expected salary",
            disabled: reviewOnly,
          }}
        />

        <Button type="submit" disabled={reviewOnly}>
          Submit Form
        </Button>
      </form>
    </Form>
  );
}

🎯 Key Benefits

✨ Zero Boilerplate: No onChange, onBlur, or manual state updates needed 🔧 Automatic Validation: Errors display automatically based on your schema 🎨 Consistent UI: All inputs follow the same design patterns 📱 Type Safety: Full TypeScript support with intellisense 🚀 Rapid Development: Add new fields in seconds, not minutes

Field Configuration Examples

Basic Input with Validation

<FormInputWrapper
  form={form}
  fieldConfig={{
    fieldVariant: "input",
    label: "Username",
    name: "username",
    inputType: "text",
    placeHolder: "Enter username",
    inputMaxLength: 20,
    disabled: false,
  }}
/>

Searchable Dropdown

<FormInputWrapper
  form={form}
  fieldConfig={{
    fieldVariant: "singleSearchableSelect",
    label: "City",
    name: "city",
    placeHolder: "Search for a city",
    options: [
      { label: "New York", value: "ny" },
      { label: "Los Angeles", value: "la" },
      { label: "Chicago", value: "chicago" },
      { label: "Houston", value: "houston" },
    ],
  }}
/>

Dynamic Field States

const isReadOnly = user.role === 'viewer';
const isRequired = step === 'final';

<FormInputWrapper
  form={form}
  fieldConfig={{
    fieldVariant: "input",
    label: "Project Name",
    name: "projectName",
    placeHolder: isRequired ? "Project name (required)" : "Project name",
    disabled: isReadOnly,
  }}
/>

🔥 What Makes This Special?

Traditional Approach (lots of repetitive code):

// ❌ Old way - repetitive and error-prone
<input
  value={formData.email}
  onChange={(e) => setFormData({...formData, email: e.target.value})}
  onBlur={() => validateEmail(formData.email)}
  className="..."
/>
{errors.email && <span className="error">{errors.email}</span>}

Our Approach (clean and declarative):

// ✅ New way - clean, declarative, and powerful
<FormInputWrapper
  form={form}
  fieldConfig={{
    fieldVariant: "input",
    label: "Email",
    name: "email",
    inputType: "email",
    placeHolder: "Enter email",
  }}
/>
// That's it! Validation, errors, state management - all handled automatically!

Component Usage

Supported Field Types

Text Input

const textField: FormInputFields = {
  name: "username",
  label: "Username",
  fieldVariant: "input",
  inputType: "text",
  placeHolder: "Enter username",
  inputMaxLength: 50,
};

Textarea

const textareaField: FormInputFields = {
  name: "description",
  label: "Description",
  fieldVariant: "textArea",
  placeHolder: "Enter description",
};

Select Dropdown

const selectField: FormInputFields = {
  name: "country",
  label: "Country",
  fieldVariant: "select",
  options: [
    { label: "United States", value: "us" },
    { label: "Canada", value: "ca" },
    { label: "United Kingdom", value: "uk" },
  ],
};

Multi-Select

const multiSelectField: FormInputFields = {
  name: "skills",
  label: "Skills",
  fieldVariant: "multiSelect",
  options: [
    { label: "React", value: "react" },
    { label: "TypeScript", value: "typescript" },
    { label: "Node.js", value: "nodejs" },
  ],
};

Currency Input

const currencyField: FormInputFields = {
  name: "salary",
  label: "Expected Salary",
  fieldVariant: "currencyInput",
  placeHolder: "Enter amount",
};

Searchable Select

const searchableField: FormInputFields = {
  name: "city",
  label: "City",
  fieldVariant: "singleSearchableSelect",
  options: [
    { label: "New York", value: "ny" },
    { label: "Los Angeles", value: "la" },
    { label: "Chicago", value: "chicago" },
  ],
};

TypeScript Definitions

The generated form.ts includes comprehensive type definitions:

export interface IOptions {
  label: string;
  value: string;
}

export interface FormInputFields<TData extends FieldValues = FieldValues> {
  name: Path<TData>;
  label?: string;
  fieldVariant: "input" | "textArea" | "select" | "multiSelect" | "currencyInput" | "singleSearchableSelect";
  inputType?: "text" | "email" | "password" | "number";
  placeHolder?: string;
  options?: IOptions[];
  disabled?: boolean;
  inputMaxLength?: number;
  prefixIcon?: React.ReactNode;
}

Customization

The generated components use Tailwind CSS classes and can be easily customized:

  1. Styling: Modify the className props in the generated components
  2. Validation: Add Zod schemas or custom validation logic
  3. New Field Types: Extend the fieldVariant type and add cases to RenderFormInput.tsx

Dependencies

The CLI automatically installs these dependencies:

  • shadcn/ui components: input, textarea, form, label
  • react-hook-form: Form state management and validation
  • react-select: Enhanced select components

Troubleshooting

shadcn/ui Not Initializing

If automatic shadcn/ui initialization fails:

npx shadcn@latest init

Missing Components

If shadcn/ui components fail to install:

npx shadcn@latest add input textarea form label

Import Path Issues

Ensure your tsconfig.json has path mapping configured:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Contributing

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

License

MIT License - see LICENSE file for details.

Changelog

v1.1.2

  • ✨ Added automatic shadcn/ui integration
  • 🔧 Improved dependency management
  • 📦 Enhanced TypeScript support
  • 🎨 Updated component templates
  • 🚀 Recommended Next.js setup for better compatibility
  • ⚠️ Added deprecation notice for Create React App

Made with ❤️ for the React community