config-driven-form 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,46 +1,224 @@
1
- # Config-Driven Form
1
+ # Config-Driven Form 🚀
2
2
 
3
- A highly scalable, config-driven React form library that dynamically generates beautiful, fully validated forms directly from JSON Schema.
3
+ [![npm version](https://badge.fury.io/js/config-driven-form.svg)](https://badge.fury.io/js/config-driven-form)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
- ## Features
6
+ A highly scalable, production-ready React form library that dynamically generates beautiful, fully validated forms directly from standard **JSON Schema**.
6
7
 
7
- - **Performant**: Built on top of `react-hook-form` and `ajv` to minimize re-renders and handle complex schemas efficiently.
8
- - **Extensible**: Easily add custom field types (like rich-text editors, maps, or file uploaders) using our custom `FieldRenderer` engine.
9
- - **Rich Text Support**: Built-in integration with `Tiptap` for rich text editing.
10
- - **Beautiful by Default**: Features a modern, glassmorphic design system out of the box using pure CSS.
8
+ Stop writing thousands of lines of boilerplate form code. Define your data structure in JSON, and let `config-driven-form` handle the UI, complex nested state, and validation instantly.
11
9
 
12
- ## Installation
10
+ ---
11
+
12
+ ## ✨ Features
13
+
14
+ - ⚡️ **Extreme Performance:** Built on `react-hook-form` to prevent unnecessary re-renders. Handles massive forms with ease.
15
+ - 🛡️ **Bulletproof Validation:** Uses `ajv` (the fastest JSON Schema validator) to enforce strict validation rules.
16
+ - 🎨 **Beautiful by Default:** Includes a stunning, modern glassmorphic design system out of the box.
17
+ - 🏗️ **Multi-Column Layouts:** Easily build complex 2, 3, or 4-column grid layouts using the `uiSchema`.
18
+ - 🧩 **Rich Field Types:** Natively supports Text, Numbers, Passwords, Dropdowns, Radios, Checkboxes, File Uploads, and a Tiptap Rich Text Editor!
19
+
20
+ ---
21
+
22
+ ## 📦 Installation
13
23
 
14
24
  ```bash
15
25
  npm install config-driven-form
16
26
  ```
17
27
 
18
- ## Quick Start
28
+ _(Note: `react-hook-form` and `ajv` are included internally, so you don't need to install them separately!)_
29
+
30
+ ---
31
+
32
+ ## 🚀 Quick Start (Basic Example)
33
+
34
+ The easiest way to generate a form is to pass a standard JSON Schema to the `<SchemaForm />` component.
19
35
 
20
36
  ```tsx
21
37
  import React from 'react';
22
38
  import { SchemaForm, JSONSchema } from 'config-driven-form';
23
- import 'config-driven-form/dist/index.css';
39
+ import 'config-driven-form/dist/index.css'; // Import the default CSS theme
24
40
 
25
- const mySchema: JSONSchema = {
41
+ const basicSchema: JSONSchema = {
26
42
  type: 'object',
27
43
  title: 'Contact Us',
44
+ description: 'We would love to hear from you.',
28
45
  properties: {
29
- email: { type: 'string', format: 'email', title: 'Email Address' },
30
- message: { type: 'string', format: 'rich-text', title: 'Your Message' },
46
+ fullName: {
47
+ type: 'string',
48
+ title: 'Full Name',
49
+ },
50
+ email: {
51
+ type: 'string',
52
+ format: 'email',
53
+ title: 'Email Address',
54
+ },
31
55
  },
32
- required: ['email'],
56
+ required: ['fullName', 'email'],
33
57
  };
34
58
 
35
59
  export default function App() {
36
60
  return (
37
61
  <div style={{ padding: '2rem' }}>
38
- <SchemaForm schema={mySchema} onSubmit={(data) => console.log(data)} />
62
+ <SchemaForm schema={basicSchema} onSubmit={(data) => console.log('Submitted Data:', data)} />
63
+ </div>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 🛠️ Advanced Usage (Layouts, Theming & UI Schema)
71
+
72
+ For complex enterprise applications, you often need to decouple your **data structure** from your **UI design**. You can achieve this by passing a `uiSchema` to control layouts and widgets, alongside the `theme` and `columns` props.
73
+
74
+ ### Example: A 2-Column Employee Profile Form
75
+
76
+ ```tsx
77
+ import React from 'react';
78
+ import { SchemaForm, JSONSchema, UISchema } from 'config-driven-form';
79
+ import 'config-driven-form/dist/index.css';
80
+
81
+ const complexSchema: JSONSchema = {
82
+ type: 'object',
83
+ title: 'Employee Profile',
84
+ properties: {
85
+ avatar: {
86
+ type: 'string',
87
+ title: 'Profile Picture',
88
+ format: 'data-url', // Automatically renders a File Uploader!
89
+ },
90
+ firstName: { type: 'string', title: 'First Name' },
91
+ lastName: { type: 'string', title: 'Last Name' },
92
+ department: {
93
+ type: 'string',
94
+ title: 'Department',
95
+ enum: ['Engineering', 'Design', 'Marketing', 'Sales'], // Renders a Dropdown by default
96
+ },
97
+ roleLevel: {
98
+ type: 'string',
99
+ title: 'Role Level',
100
+ enum: ['Junior', 'Mid', 'Senior', 'Lead'],
101
+ },
102
+ remoteWorking: {
103
+ type: 'boolean', // Renders a Checkbox
104
+ title: 'I want to work remotely',
105
+ },
106
+ biography: {
107
+ type: 'string',
108
+ title: 'Biography',
109
+ format: 'rich-text', // Renders a full WYSIWYG Tiptap Editor!
110
+ },
111
+ },
112
+ required: ['firstName', 'lastName'],
113
+ };
114
+
115
+ // 🎨 Control the layout independently of the data!
116
+ const myUiSchema: Record<string, UISchema> = {
117
+ avatar: { 'ui:columnSpan': 2 }, // Make the file uploader span across both columns
118
+ roleLevel: { 'ui:widget': 'radio' }, // Force the dropdown to render as Radio buttons instead
119
+ biography: { 'ui:columnSpan': 2 },
120
+ };
121
+
122
+ export default function AdvancedForm() {
123
+ return (
124
+ <div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
125
+ <SchemaForm
126
+ schema={complexSchema}
127
+ uiSchema={myUiSchema}
128
+ columns={2} // Sets the master grid to 2 columns
129
+ theme={{
130
+ primary: '#10b981', // Customize the primary brand color (Emerald Green)
131
+ background: '#f0fdf4', // Customize the form background
132
+ }}
133
+ onSubmit={(data) => console.log('Profile Saved:', data)}
134
+ />
39
135
  </div>
40
136
  );
41
137
  }
42
138
  ```
43
139
 
44
- ## Contributing
140
+ ---
141
+
142
+ ## 🎨 Deep Customization with Tailwind CSS (New!)
143
+
144
+ If you want to use **Tailwind CSS** (or any other class-based framework) to completely reskin the form, `config-driven-form` exposes a deeply nested `classNames` API.
145
+
146
+ This is a zero-dependency, standard headless UI approach. You can pass global classes via the `classNames` prop on `<SchemaForm>`, and even override specific individual fields using `ui:classNames` in your `uiSchema`!
147
+
148
+ ```tsx
149
+ import React from 'react';
150
+ import { SchemaForm, JSONSchema } from 'config-driven-form';
151
+ // Note: You can skip importing the default CSS if you want pure Tailwind styling
152
+
153
+ const schema: JSONSchema = {
154
+ type: 'object',
155
+ properties: {
156
+ email: { type: 'string', format: 'email', title: 'Email Address' },
157
+ },
158
+ };
159
+
160
+ export default function TailwindForm() {
161
+ return (
162
+ <SchemaForm
163
+ schema={schema}
164
+ classNames={{
165
+ container: 'max-w-xl mx-auto p-6 bg-white rounded-xl shadow-md',
166
+ label: 'block text-sm font-medium text-gray-700 mb-1',
167
+ input:
168
+ 'w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500',
169
+ submitButton: 'w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition',
170
+ }}
171
+ // You can override specific fields!
172
+ uiSchema={{
173
+ email: {
174
+ 'ui:classNames': {
175
+ input: 'border-red-500 bg-red-50', // e.g. force error state styling statically
176
+ },
177
+ },
178
+ }}
179
+ onSubmit={(data) => console.log(data)}
180
+ />
181
+ );
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 📚 Supported Field Types
188
+
189
+ The library automatically inspects the `type`, `format`, and `enum` properties of your JSON Schema to render the correct UI component:
190
+
191
+ | JSON Schema Definition | Rendered React Component |
192
+ | :-------------------------------------- | :--------------------------------------------- |
193
+ | `type: "string"` | Text Input (`<input type="text">`) |
194
+ | `type: "number"` / `"integer"` | Number Input (`<input type="number">`) |
195
+ | `type: "string", format: "email"` | Email Input (Validated by AJV) |
196
+ | `type: "string", format: "password"` | Password Input (`<input type="password">`) |
197
+ | `type: "string", format: "rich-text"` | Tiptap WYSIWYG Rich Text Editor |
198
+ | `type: "string", format: "data-url"` | File Upload Dropzone (Auto-converts to Base64) |
199
+ | `type: "boolean"` | Single Checkbox |
200
+ | `enum: ["A", "B"]` | Dropdown Select (`<select>`) |
201
+ | `enum: [...]` + `ui:widget: "radio"` | Radio Button Group |
202
+ | `type: "array", items: { enum: [...] }` | Checkbox Group (Multiple Selections) |
203
+
204
+ ---
205
+
206
+ ## ⚙️ API Reference
207
+
208
+ ### `<SchemaForm />` Props
209
+
210
+ | Prop | Type | Required | Description |
211
+ | :-------------- | :------------------------- | :------: | :-------------------------------------------------------------------------------------- |
212
+ | `schema` | `JSONSchema` | Yes | The standard JSON Schema defining your data. |
213
+ | `onSubmit` | `(data: any) => void` | Yes | Callback function triggered when the form is valid and submitted. |
214
+ | `uiSchema` | `Record<string, UISchema>` | No | Controls UI-specific rendering (widgets, column spans, field-level classNames). |
215
+ | `columns` | `1 \| 2 \| 3 \| 4` | No | Defines the global CSS Grid columns for the form layout. Default: `1`. |
216
+ | `theme` | `Object` | No | An object to override CSS variables (`primary`, `background`, `text`, `error`, etc.). |
217
+ | `classNames` | `FormClassNames` | No | An object mapping internal elements to custom CSS classes (e.g., Tailwind CSS support). |
218
+ | `defaultValues` | `Object` | No | Initial data to populate the form fields before rendering. |
219
+
220
+ ---
221
+
222
+ ## 🤝 Contributing
45
223
 
46
224
  We welcome contributions! If you want to fix a bug, add a new field type, or improve the documentation, please read our [Developer's Guide (CONTRIBUTING.md)](./CONTRIBUTING.md) to get started with your local development environment.
package/dist/index.d.mts CHANGED
@@ -18,9 +18,30 @@ interface JSONSchema {
18
18
  items?: JSONSchema | JSONSchema[];
19
19
  default?: any;
20
20
  }
21
+ interface FormClassNames {
22
+ container?: string;
23
+ title?: string;
24
+ description?: string;
25
+ form?: string;
26
+ fieldGroup?: string;
27
+ label?: string;
28
+ input?: string;
29
+ inputError?: string;
30
+ errorText?: string;
31
+ submitButton?: string;
32
+ radioGroup?: string;
33
+ radioLabel?: string;
34
+ radioInput?: string;
35
+ checkboxGroup?: string;
36
+ checkboxLabel?: string;
37
+ checkboxInput?: string;
38
+ fileWrapper?: string;
39
+ fileText?: string;
40
+ }
21
41
  interface UISchema {
22
42
  'ui:widget'?: 'radio' | 'checkboxes' | 'textarea' | 'color' | string;
23
43
  'ui:columnSpan'?: number;
44
+ 'ui:classNames'?: FormClassNames;
24
45
  [key: string]: any;
25
46
  }
26
47
 
@@ -38,6 +59,7 @@ interface SchemaFormProps {
38
59
  surface?: string;
39
60
  border?: string;
40
61
  };
62
+ classNames?: FormClassNames;
41
63
  }
42
64
  declare const SchemaForm: React.FC<SchemaFormProps>;
43
65
 
@@ -49,4 +71,4 @@ interface FieldRendererProps {
49
71
  }
50
72
  declare const FieldRenderer: React.FC<FieldRendererProps>;
51
73
 
52
- export { type FieldFormat, FieldRenderer, type FieldType, type JSONSchema, SchemaForm, type UISchema };
74
+ export { type FieldFormat, FieldRenderer, type FieldType, type FormClassNames, type JSONSchema, SchemaForm, type UISchema };
package/dist/index.d.ts CHANGED
@@ -18,9 +18,30 @@ interface JSONSchema {
18
18
  items?: JSONSchema | JSONSchema[];
19
19
  default?: any;
20
20
  }
21
+ interface FormClassNames {
22
+ container?: string;
23
+ title?: string;
24
+ description?: string;
25
+ form?: string;
26
+ fieldGroup?: string;
27
+ label?: string;
28
+ input?: string;
29
+ inputError?: string;
30
+ errorText?: string;
31
+ submitButton?: string;
32
+ radioGroup?: string;
33
+ radioLabel?: string;
34
+ radioInput?: string;
35
+ checkboxGroup?: string;
36
+ checkboxLabel?: string;
37
+ checkboxInput?: string;
38
+ fileWrapper?: string;
39
+ fileText?: string;
40
+ }
21
41
  interface UISchema {
22
42
  'ui:widget'?: 'radio' | 'checkboxes' | 'textarea' | 'color' | string;
23
43
  'ui:columnSpan'?: number;
44
+ 'ui:classNames'?: FormClassNames;
24
45
  [key: string]: any;
25
46
  }
26
47
 
@@ -38,6 +59,7 @@ interface SchemaFormProps {
38
59
  surface?: string;
39
60
  border?: string;
40
61
  };
62
+ classNames?: FormClassNames;
41
63
  }
42
64
  declare const SchemaForm: React.FC<SchemaFormProps>;
43
65
 
@@ -49,4 +71,4 @@ interface FieldRendererProps {
49
71
  }
50
72
  declare const FieldRenderer: React.FC<FieldRendererProps>;
51
73
 
52
- export { type FieldFormat, FieldRenderer, type FieldType, type JSONSchema, SchemaForm, type UISchema };
74
+ export { type FieldFormat, FieldRenderer, type FieldType, type FormClassNames, type JSONSchema, SchemaForm, type UISchema };