AppmintForm is a powerful, lightweight, and flexible form builder library for React applications. It allows developers to create complex forms with minimal code while maintaining excellent performance and aesthetics.
- Introduction
- Installation
- Basic Usage
- Form Schema Structure
- Form Elements
- Layout Options
- Validation
- Theming
- API Reference
- Common Threads
- Examples
- Troubleshooting
- Contributing
AppmintForm simplifies form creation and management in React applications. It provides a highly customizable and easy-to-use solution that can handle complex form structures, dynamic rendering, and validation with minimal effort from developers, all while being lightweight and performance-oriented.
- JSON Schema Configuration: Define forms using a declarative JSON schema
- Rich Component Library: Support for 30+ input types and controls
- Conditional Rendering: Show/hide fields based on form data
- Built-in Validation: Comprehensive validation using Zod
- Customizable Layouts: Multiple layout options including tabs, accordions, and more
- Theming Support: Easily customize the appearance of your forms
- Performance Optimized: Only updates what has changed, ensuring efficient rendering
- Extensible: Add custom input components and layouts
To install AppmintForm, run one of the following commands in your project's root directory:
# Using npm
npm install @appmint/form
# Using yarn
yarn add @appmint/form
# Using pnpm
pnpm add @appmint/form- React 18 or higher
- Node.js 18 or higher
Here's a simple example of how to use AppmintForm in your React application:
import React from 'react';
import { AppmintForm } from '@appmint/form';
const MyForm = () => {
// Define your form schema
const schema = {
type: 'object',
title: 'User Information',
properties: {
firstName: {
type: 'string',
title: 'First Name',
description: 'Enter your first name',
inputRequired: true
},
lastName: {
type: 'string',
title: 'Last Name',
description: 'Enter your last name',
inputRequired: true
},
email: {
type: 'string',
title: 'Email',
description: 'Enter your email address',
format: 'email',
inputRequired: true
}
}
};
// Initial form data (optional)
const initialData = {
firstName: '',
lastName: '',
email: ''
};
// Handle form changes
const handleChange = (path, value, data, files, error) => {
console.log('Form data changed:', data);
};
return (
<AppmintForm
schema={schema}
initData={initialData}
onChange={handleChange}
id="user-form"
/>
);
};
export default MyForm;AppmintForm uses a JSON schema to define the structure and behavior of your forms. The schema follows a structure similar to JSON Schema but with additional properties specific to AppmintForm.
{
"type": "object",
"title": "Form Title",
"description": "Form description",
"properties": {
"fieldName": {
"type": "string",
"title": "Field Label",
"description": "Field description",
"inputRequired": true,
"x-control": "text"
}
},
"x-layout": {
// Layout configuration
}
}| Property | Type | Description |
|---|---|---|
type |
string | The data type of the form (usually "object") |
title |
string | The title of the form |
description |
string | The description of the form |
properties |
object | An object containing field definitions |
x-layout |
object | Layout configuration for the form |
pages |
array | For multi-page forms, an array of page objects |
theme |
object | Theme configuration for the form |
collapsible |
boolean | Whether the form can be collapsed |
Each field in the properties object can have the following properties:
| Property | Type | Description |
|---|---|---|
type |
string | The data type of the field (string, number, boolean, array, object, null) |
title |
string | The label for the field |
description |
string | The description or help text for the field |
inputRequired |
boolean | Whether the field is required |
default |
any | The default value for the field |
x-control |
string | The type of control to use for the field |
x-control-variant |
string | A variant of the control |
placeholder |
string | Placeholder text for input fields |
enum |
array | For selection fields, an array of possible values |
minimum |
number | For number fields, the minimum allowed value |
maximum |
number | For number fields, the maximum allowed value |
minLength |
number | For string fields, the minimum allowed length |
maxLength |
number | For string fields, the maximum allowed length |
pattern |
string | For string fields, a regex pattern for validation |
format |
string | For string fields, a predefined format (e.g., "email", "date") |
validations |
array | Custom validation rules |
prefix |
string | Text to display before the input |
suffix |
string | Text to display after the input |
disabled |
boolean | Whether the field is disabled |
readOnly |
boolean | Whether the field is read-only |
hidden |
boolean | Whether the field is hidden |
layoutGroup |
string | The layout group the field belongs to |
AppmintForm provides a wide range of form elements to handle different types of data and user interactions.
| Element | Description | Schema Configuration |
|---|---|---|
text |
Basic text input | { "type": "string" } |
textarea |
Multi-line text input | { "type": "string", "x-control-variant": "textarea" } |
email |
Email input with validation | { "type": "string", "format": "email", "x-control": "email" } |
richtext |
Rich text editor with formatting | { "type": "string", "x-control": "richtext" } |
markdown |
Markdown editor | { "type": "string", "x-control": "markdown" } |
code |
Code editor | { "type": "string", "x-control": "code" } |
| Element | Description | Schema Configuration |
|---|---|---|
number |
Basic number input | { "type": "number" } |
slider |
Slider for selecting a number | { "type": "number", "x-control-variant": "slider" } |
numberrange |
Range of numbers | { "type": "object", "x-control": "numberrange" } |
| Element | Description | Schema Configuration |
|---|---|---|
selectsingle |
Single selection dropdown | { "type": "string", "enum": ["Option 1", "Option 2"] } |
selectmany |
Multiple selection control | { "type": "array", "items": { "type": "string", "enum": ["Option A", "Option B"] }, "x-control": "selectmany" } |
rating |
Star rating input | { "type": "number", "x-control": "rating" } |
ranking |
Drag-and-drop ranking | { "type": "array", "x-control": "ranking" } |
| Element | Description | Schema Configuration |
|---|---|---|
date |
Date picker | { "type": "string", "format": "date", "x-control": "date" } |
daterange |
Date range picker | { "type": "object", "x-control": "daterange" } |
cron |
Cron expression editor | { "type": "string", "x-control": "cron" } |
| Element | Description | Schema Configuration |
|---|---|---|
color |
Color picker | { "type": "string", "x-control": "color" } |
file |
File upload | { "type": "string", "x-control": "file" } |
map |
Map location picker | { "type": "object", "x-control": "map" } |
phone |
Phone number input | { "type": "string", "x-control": "phone" } |
icon |
Icon picker | { "type": "string", "x-control": "icon" } |
uuid |
UUID generator | { "type": "string", "x-control": "uuid" } |
sociallinks |
Social media links | { "type": "object", "x-control": "sociallinks" } |
legalconsent |
Legal consent checkbox | { "type": "boolean", "x-control": "legalconsent" } |
| Element | Description | Schema Configuration |
|---|---|---|
paragraph |
Static text display | { "type": "null", "x-control": "paragraph", "x-content": "Text content" } |
label |
Label element | { "type": "null", "x-control": "label" } |
button |
Button element | { "type": "null", "x-control": "button" } |
preview |
Preview of other content | { "type": "null", "x-control": "preview" } |
shadow |
Shadow DOM element | { "type": "null", "x-control": "shadow" } |
| Element | Description | Schema Configuration |
|---|---|---|
dataview |
Data view component | { "type": "array", "x-control": "dataview" } |
lookup |
Data lookup combo | { "type": "string", "x-control": "lookup" } |
generated |
AI-generated content | { "type": "string", "x-control": "generated" } |
AppmintForm provides several layout options to organize your form fields.
By default, form fields are displayed in a vertical stack. You can customize this using the x-layout property in your schema.
{
"x-layout": {
"main": {
"type": "tab",
"id": "main",
"items": [
{ "id": "personal-info", "title": "Personal Information" },
{ "id": "contact-info", "title": "Contact Information" }
]
}
},
"properties": {
"firstName": {
"type": "string",
"title": "First Name",
"layoutGroup": "x-layout.main.items.0"
},
"email": {
"type": "string",
"title": "Email",
"layoutGroup": "x-layout.main.items.1"
}
}
}{
"x-layout": {
"main": {
"type": "accordion",
"id": "main",
"items": [
{ "id": "personal-info", "title": "Personal Information" },
{ "id": "contact-info", "title": "Contact Information" }
]
}
}
}{
"x-layout": {
"main": {
"type": "slider",
"id": "main",
"items": [
{ "id": "step1", "title": "Step 1" },
{ "id": "step2", "title": "Step 2" }
]
}
}
}For multi-page forms, use the pages property:
{
"type": "object",
"title": "Multi-Page Form",
"pages": [
{
"title": "Page 1",
"properties": {
"field1": {
"type": "string",
"title": "Field 1"
}
}
},
{
"title": "Page 2",
"properties": {
"field2": {
"type": "string",
"title": "Field 2"
}
}
}
],
"theme": {
"paging": "tab" // or "default" for next/back buttons
}
}AppmintForm provides built-in validation using Zod. You can define validation rules in your schema using standard JSON Schema validation properties or custom validation rules.
{
"type": "string",
"title": "Username",
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$",
"inputRequired": true
}{
"type": "string",
"title": "Password",
"validations": [
{
"validation": "regex",
"arg": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$",
"message": "Password must contain at least 8 characters, including uppercase, lowercase, and numbers"
}
]
}required: Field is requiredmin: Minimum value (for numbers) or length (for strings)max: Maximum value (for numbers) or length (for strings)regex: Regular expression patternemail: Valid email formaturl: Valid URL formatequals: Value equals the argumentnotEquals: Value does not equal the argumentcontains: Value contains the argumentnotContains: Value does not contain the argumentstartsWith: Value starts with the argumentendsWith: Value ends with the argument
AppmintForm supports theming to customize the appearance of your forms.
const theme = {
form: {
className: 'bg-gray-50 p-4 rounded-lg shadow-sm'
},
title: {
className: 'text-xl font-bold text-blue-600'
},
control: {
className: 'mb-4'
},
label: {
className: 'text-sm font-medium text-gray-700'
},
input: {
className: 'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500'
}
};
<AppmintForm schema={schema} theme={theme} />const theme = {
text: {
className: 'border-blue-300 focus:ring-blue-500'
},
number: {
className: 'border-green-300 focus:ring-green-500'
}
};<AppmintForm
initData={object} // Initial form data
rules={object} // Form rules for conditional logic
schema={object} // Form schema
theme={object} // Theme configuration
datatype={string} // Data type identifier
id={string} // Unique identifier for the form
onChange={function} // Callback function for form changes
/>| Prop | Type | Description |
|---|---|---|
initData |
object | Initial form data |
rules |
object | Form rules for conditional logic |
schema |
object | Form schema definition |
theme |
object | Theme configuration |
datatype |
string | Data type identifier |
id |
string | Unique identifier for the form |
onChange |
function | Callback function for form changes: (path, value, data, files, error) => void |
readOnly |
boolean | Whether the form is read-only |
collapsible |
boolean | Whether the form can be collapsed |
icon |
string | Icon for the form (when collapsible) |
<AppmintTable
title={string} // Table title
rules={object} // Table rules
schema={object} // Table schema
datatype={string} // Data type identifier
description={string} // Table description
id={string} // Unique identifier for the table
/>| Prop | Type | Description |
|---|---|---|
title |
string | Table title |
rules |
object | Table rules |
schema |
object | Table schema definition |
datatype |
string | Data type identifier |
description |
string | Table description |
id |
string | Unique identifier for the table |
data |
array | Table data |
columns |
array | Table columns |
filterPreset |
object | Preset filters |
filters |
object | Active filters |
accessMode |
string | Access mode |
inlineEdit |
boolean | Whether inline editing is enabled |
isDemo |
boolean | Whether the table is in demo mode |
onRowEvent |
function | Callback function for row events: (event, rowId, row) => void |
onTableEvent |
function | Callback function for table events: (event, option, selected) => void |
isLoading |
boolean | Whether the table is loading |
cellRenderers |
object | Custom cell renderers |
itemRenderer |
function | Custom item renderer |
options |
object | Table options |
AppmintForm uses several tools to ensure code quality and consistency:
The project uses ESLint for static code analysis with the following configuration:
{
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"@typescript-eslint/recommended"
],
"plugins": ["react", "@typescript-eslint"],
"rules": {
// Custom rules
}
}To run ESLint:
npm run lintThe project uses TypeScript for type checking with the following configuration:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}The project uses Vitest for unit testing:
npm testThe project uses Size Limit to control the size of the library:
npm run sizeCurrent size limits:
- CJS bundle: 10 KB
- ES module: 10 KB
To analyze the bundle size:
npm run analyzeYou can view the download statistics for AppmintForm on npm-stat.com.
AppmintForm is maintained by Jac Light and the AppmintForm team.
To view all contributors:
git shortlog -snimport React from 'react';
import { AppmintForm } from '@appmint/form';
const BasicForm = () => {
const schema = {
type: 'object',
title: 'Contact Form',
properties: {
name: {
type: 'string',
title: 'Name',
inputRequired: true
},
email: {
type: 'string',
title: 'Email',
format: 'email',
inputRequired: true
},
message: {
type: 'string',
title: 'Message',
'x-control-variant': 'textarea',
inputRequired: true
}
}
};
const handleChange = (path, value, data) => {
console.log('Form data:', data);
};
return (
<AppmintForm
schema={schema}
onChange={handleChange}
id="contact-form"
/>
);
};
export default BasicForm;import React from 'react';
import { AppmintForm } from '@appmint/form';
const MultiPageForm = () => {
const schema = {
type: 'object',
title: 'Registration Form',
pages: [
{
title: 'Personal Information',
properties: {
firstName: {
type: 'string',
title: 'First Name',
inputRequired: true
},
lastName: {
type: 'string',
title: 'Last Name',
inputRequired: true
}
}
},
{
title: 'Account Information',
properties: {
email: {
type: 'string',
title: 'Email',
format: 'email',
inputRequired: true
},
password: {
type: 'string',
title: 'Password',
'x-control-variant': 'password',
inputRequired: true
}
}
}
],
theme: {
paging: 'tab'
}
};
return (
<AppmintForm
schema={schema}
id="registration-form"
/>
);
};
export default MultiPageForm;import React from 'react';
import { AppmintForm } from '@appmint/form';
const ConditionalForm = () => {
const schema = {
type: 'object',
title: 'Subscription Form',
properties: {
plan: {
type: 'string',
title: 'Subscription Plan',
enum: ['free', 'basic', 'premium'],
default: 'free'
},
paymentMethod: {
type: 'string',
title: 'Payment Method',
enum: ['credit_card', 'paypal', 'bank_transfer'],
default: 'credit_card',
hidden: true
},
cardNumber: {
type: 'string',
title: 'Card Number',
hidden: true
}
}
};
const rules = [
{
when: 'plan',
is: value => value !== 'free',
then: {
paymentMethod: {
hidden: false
}
}
},
{
when: 'paymentMethod',
is: 'credit_card',
then: {
cardNumber: {
hidden: false
}
}
}
];
return (
<AppmintForm
schema={schema}
rules={rules}
id="subscription-form"
/>
);
};
export default ConditionalForm;- Check that you've provided a valid schema
- Ensure that the schema has a
typeproperty set toobject - Verify that the
propertiesobject contains at least one field
- Make sure you've set
inputRequired: truefor required fields - Check that your validation rules are correctly formatted
- Verify that you're using the correct validation types
- Ensure that your
x-layoutconfiguration is correct - Verify that your
layoutGroupreferences match the items in your layout - Check that you're using the correct layout type (tab, accordion, slider)
You can enable debug mode by setting the debug prop to true:
<AppmintForm
schema={schema}
debug={true}
/>This will log additional information to the console, including:
- Schema parsing
- Validation results
- Form state changes
- Layout rendering
We welcome contributions from the community! To contribute to AppmintForm:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Write your code, making sure to follow the existing code style and conventions.
- Add or update tests, if necessary.
- Update documentation if you're introducing new features or making changes to the API.
- Commit your changes and create a pull request.
# Clone the repository
git clone https://github.com/durubata/appmint-form.git
cd appmint-form
# Install dependencies
yarn install
# Start the development server
yarn dev
# Run tests
yarn test
# Build the library
yarn buildThe project uses ESLint and Prettier for code formatting. Make sure your code passes the linting checks:
yarn lintWrite tests for your changes using Vitest:
yarn testUpdate the documentation to reflect your changes. If you're adding new features, make sure to include examples of how to use them.
- Update the README.md or documentation with details of changes, if appropriate.
- Update the CHANGELOG.md with details of changes.
- The PR will be merged once it has been reviewed and approved by a maintainer.
AppmintForm is open-source software licensed under the MIT license.
Documentation created for AppmintForm v0.2.0