@ashimkoirala/dynamicform-lib
v1.1.0
Published
DynamicForm renders forms from a JSON or Zod schema, supports validation, conditional fields, and is optimized for fast iteration and content-driven apps.
Downloads
16
Readme
📦 @ashimkoirala/dynamicform-lib
A flexible React + TypeScript component library to render dynamic forms from a JSON or Zod schema. It supports validation, conditional logic, preview mode, multi-step wizards, and full accessibility. Perfect for content-driven apps and admin panels.
🚀 Installation
Install via npm or yarn:
npm install @ashimkoirala/dynamicform-lib
# or
yarn add @ashimkoirala/dynamicform-lib
✨ Usage Example
A simple example using a form schema and Zod validation:
import { DynamicForm } from "@ashimkoirala/dynamicform-lib";
import { z } from "zod";
const formSchema = [
{ type: "text", label: "Name", key: "name", required: true },
{ type: "email", label: "Email", key: "email" },
{ type: "select", label: "Gender", key: "gender", options: ["Male", "Female"] },
{ type: "textarea", label: "Message", key: "message" }
];
const validationSchema = z.object({
name: z.string().min(2, "Name is required"),
email: z.string().email("Invalid email").optional(),
gender: z.enum(["Male", "Female"]),
message: z.string().min(5, "Too short").optional()
});
export default function ContactForm() {
const handleFormSubmit = (data) => {
console.log("Form data:", data);
};
return (
<DynamicForm
schema={formSchema}
zodSchema={validationSchema}
onSubmit={handleFormSubmit}
/>
);
}
🎨 Props
| Prop | Type | Description |
|--------------------------|----------------------------|---------------------------------|
| schema | FieldSchema[] | JSON schema to define fields |
| zodSchema | ZodSchema<T> (optional) | Schema for validation |
| onSubmit | (data: T) => void | Callback on submit |
| preview | boolean (optional) | Show JSON preview of form data |
| step, stepCount | number | For multi-step forms |
| components | FieldComponentMap | Override specific field renderers|
| fieldClassName | string | Wrapper for each field |
| labelClassName | string | Style for <label> |
| inputClassName | string | Style for input, select, textarea|
| errorClassName | string | Error message class |
| checkboxWrapperClassName | string | Wrapper around checkbox/switch |
| checkboxLabelClassName | string | Label style for checkbox/switch |
| submitButtonClassName | string | Submit button styling |
| submitButtonText | string | Submit button text |
🧩 Field Schema Structure
Each field in the schema should follow this structure:
type FieldType = "text" | "textarea" | "email" | "select" | "switch" | "checkbox" | "file" | "number";
interface FieldSchema {
type: FieldType;
label: string;
key: string;
required?: boolean;
options?: string[];
conditional?: { key: string; value: any };
}
🎨 Style Customization via Props
Customize your form UI using className props:
<DynamicForm
schema={formSchema}
zodSchema={validationSchema}
onSubmit={handleFormSubmit}
fieldClassName="mb-6"
labelClassName="block mb-2 text-sm font-semibold text-gray-700"
inputClassName="w-full border border-gray-300 rounded-md px-3 py-2"
errorClassName="mt-1 text-sm text-red-600"
checkboxWrapperClassName="flex items-center mb-6"
checkboxLabelClassName="ml-2 text-gray-700 font-medium"
submitButtonClassName="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-3 rounded-md"
submitButtonText="Send Message"
/>
🧠 Conditional Fields
Fields can appear based on other field values:
const formSchema = [
{ type: "text", label: "Name", key: "name" },
{
type: "text",
label: "Referral Code",
key: "referral",
conditional: { key: "name", value: "admin" }
}
];
If name === "admin", the "Referral Code" field appears.
🧭 Multi-Step Support
<DynamicForm
schema={stepSchemas[currentStep]}
step={currentStep}
stepCount={stepSchemas.length}
onSubmit={handleStepSubmit}
/>Use step and stepCount to handle wizard-style forms.
👓 Preview Mode
<DynamicForm
preview={true}
schema={formSchema}
zodSchema={validationSchema}
onSubmit={() => {}}
/>This renders a read-only JSON output of current values.
🧪 Custom Field Components
You can override default inputs with your own custom components via the components prop.
📜 License
MIT
👨💻 Author
Made with 💙 by Ashim Koirala
