react-smart-fields 1.1.5 โ†’ 2.1.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,191 +1,279 @@
1
- # ๐Ÿงน DynamicFields React Component
1
+ # React Smart Fields
2
2
 
3
3
  ![npm](https://img.shields.io/npm/v/react-smart-fields)
4
4
  ![downloads](https://img.shields.io/npm/dw/react-smart-fields)
5
5
  ![license](https://img.shields.io/npm/l/react-smart-fields)
6
- ![issues](https://img.shields.io/github/issues/Pratikpanchal25/react-smart-fields)
7
6
 
7
+ `react-smart-fields` is a powerful dynamic form renderer for React with:
8
8
 
9
- A flexible, fully-styled dynamic form generator built with **React** and **Tailwind CSS**, supporting custom input types, validation, and class overrides. Ideal for building forms quickly with full control over design and behavior.
9
+ - configurable field schemas
10
+ - built-in + custom validation
11
+ - conditional visibility/disable/required rules
12
+ - async options for selects
13
+ - nested field names (`user.addresses[0].city`)
14
+ - theme presets + headless mode + full render slots
10
15
 
11
- ---
16
+ ## Installation
12
17
 
13
- ## โœจ Features
14
-
15
- * ๐Ÿ“ฆ Supports `text`, `number`, `checkbox`, `radio`, and `select` fields
16
- * ๐Ÿ’… Fully customizable via Tailwind-compatible className props
17
- * ๐Ÿง  Built-in required field validation
18
- * ๐Ÿงฑ Extensible for advanced usage
19
- * ๐ŸŒƒ Full **dark mode** support
20
- * ๐Ÿ”„ Real-time `onChange` callback with live `formData` and `errors`
21
-
22
- ---
23
-
24
- ## ๐Ÿ“ฆ Installation
25
-
26
- Copy the `DynamicFields.tsx` file into your React project.
27
-
28
- Make sure you have Tailwind CSS and React configured in your app.
18
+ ```bash
19
+ npm install react-smart-fields
20
+ ```
29
21
 
30
- ---
22
+ or
31
23
 
32
- ## ๐Ÿš€ Usage
24
+ ```bash
25
+ yarn add react-smart-fields
26
+ ```
33
27
 
34
- ### Basic Example
28
+ ## Quick Start
35
29
 
36
30
  ```tsx
37
- import React from "react";
38
- import DynamicFields from "./DynamicFields";
31
+ import { DynamicFields, FieldConfig } from "react-smart-fields";
39
32
 
40
- const fields = [
41
- {
42
- name: "username",
43
- label: "Username",
44
- type: "text",
45
- required: true,
46
- },
33
+ const fields: FieldConfig[] = [
34
+ { name: "name", label: "Name", type: "text", required: true },
47
35
  {
48
36
  name: "email",
49
37
  label: "Email",
50
- type: "text",
51
- required: true,
52
- },
53
- {
54
- name: "gender",
55
- label: "Gender",
56
- type: "radio",
38
+ type: "email",
57
39
  required: true,
58
- options: [
59
- { label: "Male", value: "male" },
60
- { label: "Female", value: "female" },
61
- ],
40
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
41
+ patternMessage: "Please enter a valid email",
62
42
  },
63
43
  {
64
44
  name: "country",
65
45
  label: "Country",
66
46
  type: "select",
47
+ placeholder: "Select country",
67
48
  options: [
68
- { label: "USA", value: "us" },
69
49
  { label: "India", value: "in" },
50
+ { label: "United States", value: "us" },
70
51
  ],
71
52
  },
72
53
  {
73
- name: "subscribe",
74
- label: "Subscribe",
54
+ name: "newsletter",
55
+ label: "Subscribe to newsletter",
75
56
  type: "checkbox",
76
- }
57
+ defaultValue: true,
58
+ },
77
59
  ];
78
60
 
79
- function App() {
80
- const handleChange = (data) => {
81
- console.log("Form Data:", data);
82
- };
83
-
61
+ export default function App() {
84
62
  return (
85
63
  <DynamicFields
86
64
  fields={fields}
87
- title="Sign Up"
88
- description="Please fill all fields"
89
- onChange={handleChange}
65
+ title="Profile"
66
+ description="Update your profile details"
67
+ theme="default"
68
+ size="md"
69
+ onChange={(values, meta) => {
70
+ console.log(values, meta?.errors);
71
+ }}
90
72
  />
91
73
  );
92
74
  }
93
75
  ```
94
76
 
95
- ---
96
-
97
- ## โš™๏ธ Props
77
+ ## Major Capabilities
78
+
79
+ - **Validation engine**: `required`, `min/max`, `minLength/maxLength`, `pattern`, and `validate`
80
+ - **Conditional behavior**: `showWhen`, `disableWhen`, `requiredWhen`
81
+ - **Nested paths**: dot/bracket field names are supported
82
+ - **Async select options**: `loadOptions` with `loadOptionsOn: "mount" | "change"`
83
+ - **Theme presets**: `default`, `minimal`, `filled`, `underline`
84
+ - **Headless mode**: set `headless` to fully control UI
85
+ - **Render slots**: `renderField`, `renderControl`, `renderLabel`, `renderDescription`, `renderError`
86
+ - **State styling hooks**: `stateClassNames` for `invalid`, `disabled`, `readonly`, `dirty`, `touched`
87
+
88
+ ## Component Props
89
+
90
+ | Prop | Type | Required | Description |
91
+ | --- | --- | --- | --- |
92
+ | `fields` | `FieldConfig[]` | โœ… | Field schema array |
93
+ | `onChange` | `(values, meta?) => void` | โœ… | Fires on every value/meta update |
94
+ | `value` | `Record<string, any>` | โŒ | Controlled mode values |
95
+ | `defaultValues` | `Record<string, any>` | โŒ | Initial values (uncontrolled mode) |
96
+ | `resolver` | `(values) => errors \| Promise<errors>` | โŒ | External validation resolver |
97
+ | `validateMode` | `"change" \| "blur"` | โŒ | Validation trigger mode |
98
+ | `showErrorWhen` | `"always" \| "touched" \| "dirty"` | โŒ | Error visibility strategy |
99
+ | `headless` | `boolean` | โŒ | Disables built-in styling |
100
+ | `theme` | `"default" \| "minimal" \| "filled" \| "underline"` | โŒ | Built-in visual preset |
101
+ | `size` | `"sm" \| "md" \| "lg"` | โŒ | Input/label sizing |
102
+ | `ui` | `UiClassMap` | โŒ | Global slot class overrides |
103
+ | `stateClassNames` | `StateClassNames` | โŒ | State class hooks |
104
+ | `renderField` | `(ctx) => ReactNode` | โŒ | Full custom field renderer |
105
+ | `renderControl` | `(ctx) => ReactNode` | โŒ | Custom control renderer |
106
+ | `renderLabel` | `(ctx) => ReactNode` | โŒ | Custom label renderer |
107
+ | `renderDescription` | `(ctx) => ReactNode` | โŒ | Custom helper text renderer |
108
+ | `renderError` | `(ctx) => ReactNode` | โŒ | Custom error renderer |
109
+ | `title` | `string` | โŒ | Form heading |
110
+ | `description` | `string` | โŒ | Form subtitle |
111
+
112
+ Legacy class props are still supported for backward compatibility:
113
+ `className`, `inputClassName`, `labelClassName`, `mainFieldClassName`, `fieldClassName`, `errorClassName`, `selectClassName`, `optionClassName`, `checkboxClassName`, `radioClassName`.
114
+
115
+ ## FieldConfig API
98
116
 
99
- | Prop | Type | Required | Description |
100
- | -------------------- | ------------------------------------- | -------- | --------------------------------- |
101
- | `fields` | `FieldConfig[]` | โœ… Yes | List of field definitions |
102
- | `onChange` | `(data: Record<string, any>) => void` | โœ… Yes | Callback on value change |
103
- | `title` | `string` | โŒ No | Optional form title |
104
- | `description` | `string` | โŒ No | Optional description |
105
- | `className` | `string` | โŒ No | Wrapper div styling |
106
- | `mainFieldClassName` | `string` | โŒ No | Class for the fields wrapper |
107
- | `inputClassName` | `string` | โŒ No | Applies to `text`/`number` inputs |
108
- | `labelClassName` | `string` | โŒ No | Applies to all labels |
109
- | `fieldClassName` | `string` | โŒ No | Applied to each field wrapper div |
110
- | `errorClassName` | `string` | โŒ No | Error message styling |
111
- | `selectClassName` | `string` | โŒ No | `select` field styling |
112
- | `checkboxClassName` | `string` | โŒ No | Checkbox input styling |
113
- | `radioClassName` | `string` | โŒ No | Radio input styling |
114
- | `optionClassName` | `string` | โŒ No | Dropdown option styling |
115
-
116
- ---
117
-
118
- ## ๐Ÿ”ง `FieldConfig` (field definition)
117
+ ```ts
118
+ type FieldConfig = {
119
+ name: string;
120
+ label?: string;
121
+ type:
122
+ | "text"
123
+ | "number"
124
+ | "select"
125
+ | "radio"
126
+ | "checkbox"
127
+ | "textarea"
128
+ | "email"
129
+ | "password"
130
+ | "tel"
131
+ | "url"
132
+ | "date";
133
+
134
+ // values/options
135
+ defaultValue?: any;
136
+ placeholder?: string;
137
+ options?: { label: string; value: string | number | boolean | null | undefined; disabled?: boolean }[];
138
+ loadOptions?: (ctx: { values: Record<string, any>; field: FieldConfig }) => Promise<FieldOption[]>;
139
+ loadOptionsOn?: "mount" | "change";
140
+
141
+ // behavior
142
+ disabled?: boolean;
143
+ readOnly?: boolean;
144
+ showWhen?: (values: Record<string, any>) => boolean;
145
+ disableWhen?: (values: Record<string, any>) => boolean;
146
+ required?: boolean;
147
+ requiredWhen?: (values: Record<string, any>) => boolean;
148
+ requiredMessage?: string;
149
+
150
+ // validation
151
+ min?: number;
152
+ max?: number;
153
+ minLength?: number;
154
+ maxLength?: number;
155
+ pattern?: RegExp;
156
+ patternMessage?: string;
157
+ validate?: (value: any, values: Record<string, any>) => string | undefined | null;
158
+
159
+ // value transforms
160
+ transformIn?: (storedValue: any, values: Record<string, any>) => any;
161
+ transformOut?: (rawValue: any, values: Record<string, any>) => any;
162
+
163
+ // styling/rendering
164
+ className?: string;
165
+ inputClassName?: string;
166
+ labelClassName?: string;
167
+ errorClassName?: string;
168
+ ui?: UiClassMap;
169
+ renderControl?: (ctx: RenderControlContext) => ReactNode;
170
+ };
171
+ ```
119
172
 
120
- Each field object can contain:
173
+ ## Customization Examples
121
174
 
122
- | Property | Type | Required | Notes |
123
- | ------------- | --------------------------------------------------------- | --------------------------------- | -------------------------------------- |
124
- | `name` | `string` | โœ… Yes | Unique key |
125
- | `label` | `string` | โŒ No | Display label |
126
- | `type` | `"text"`, `"number"`, `"select"`, `"radio"`, `"checkbox"` | โœ… Yes | Field type |
127
- | `required` | `boolean` | โŒ No | Show red asterisk and basic validation |
128
- | `placeholder` | `string` | โŒ No | Placeholder (for inputs/selects) |
129
- | `description` | `string` | โŒ No | Optional helper text |
130
- | `options` | `{ label: string; value: any; }[]` | Required for `select` and `radio` | Dropdown/Radio values |
175
+ ### 1) Conditional + Nested Fields
131
176
 
132
- ---
177
+ ```tsx
178
+ const fields: FieldConfig[] = [
179
+ { name: "accountType", label: "Account Type", type: "select", options: [
180
+ { label: "Individual", value: "individual" },
181
+ { label: "Business", value: "business" },
182
+ ]},
183
+ {
184
+ name: "company.name",
185
+ label: "Company Name",
186
+ type: "text",
187
+ showWhen: (values) => values.accountType === "business",
188
+ requiredWhen: (values) => values.accountType === "business",
189
+ },
190
+ {
191
+ name: "addresses[0].city",
192
+ label: "Primary City",
193
+ type: "text",
194
+ required: true,
195
+ },
196
+ ];
197
+ ```
133
198
 
134
- ## ๐ŸŽจ Class Mapping
199
+ ### 2) Async Select Options
135
200
 
136
- Here's how classes are applied to each section:
201
+ ```tsx
202
+ {
203
+ name: "state",
204
+ label: "State",
205
+ type: "select",
206
+ loadOptionsOn: "change",
207
+ loadOptions: async ({ values }) => {
208
+ if (!values.country) return [];
209
+ const response = await fetch(`/api/states?country=${values.country}`);
210
+ const data = await response.json();
211
+ return data.map((item: any) => ({ label: item.name, value: item.code }));
212
+ },
213
+ }
214
+ ```
137
215
 
138
- | Section | Class Prop | Default Tailwind Example |
139
- | ------------------- | ------------------- | ---------------------------------- |
140
- | Wrapper div | `className` | `bg-white dark:bg-gray-900` |
141
- | Label text | `labelClassName` | `text-gray-800 dark:text-gray-200` |
142
- | Input fields | `inputClassName` | `bg-white dark:bg-gray-800` |
143
- | Select dropdown | `selectClassName` | `rounded-lg` |
144
- | Radio buttons | `radioClassName` | `rounded-full` |
145
- | Checkbox | `checkboxClassName` | `rounded` |
146
- | Field container div | `fieldClassName` | `w-full` |
147
- | Dropdown options | `optionClassName` | `hover:bg-gray-100` |
148
- | Error messages | `errorClassName` | `text-red-500` |
216
+ ### 3) Headless + Slots
149
217
 
150
- You can override all styles with your own Tailwind classes!
218
+ ```tsx
219
+ <DynamicFields
220
+ fields={fields}
221
+ headless
222
+ renderField={({ field, labelNode, controlNode, errorNode, helpNode }) => (
223
+ <div key={field.name} className="mb-6">
224
+ {labelNode}
225
+ <div className="mt-2">{controlNode}</div>
226
+ <div className="mt-1">{helpNode}</div>
227
+ <div className="mt-1">{errorNode}</div>
228
+ </div>
229
+ )}
230
+ onChange={(values) => console.log(values)}
231
+ />
232
+ ```
151
233
 
152
- ---
234
+ ### 4) Resolver Validation
153
235
 
154
- ## ๐Ÿงช Advanced Usage: Custom Styling Per Field
236
+ ```tsx
237
+ <DynamicFields
238
+ fields={fields}
239
+ resolver={(values) => {
240
+ const errors: Record<string, string> = {};
241
+ if (values.password !== values.confirmPassword) {
242
+ errors.confirmPassword = "Passwords do not match";
243
+ }
244
+ return errors;
245
+ }}
246
+ onChange={(values, meta) => {
247
+ console.log(meta?.errors);
248
+ }}
249
+ />
250
+ ```
155
251
 
156
- You can add `inputClassName`, `labelClassName`, or `className` inside each field:
252
+ ## Type Exports
157
253
 
158
254
  ```ts
159
- {
160
- name: "email",
161
- label: "Email",
162
- type: "text",
163
- inputClassName: "border-purple-500",
164
- labelClassName: "text-purple-700 font-semibold",
165
- className: "mb-6",
166
- }
255
+ import type {
256
+ FieldConfig,
257
+ FieldOption,
258
+ FieldType,
259
+ DynamicFieldsProps,
260
+ UiClassMap,
261
+ StateClassNames,
262
+ ChangeMeta,
263
+ RenderControlContext,
264
+ RenderFieldContext,
265
+ } from "react-smart-fields";
167
266
  ```
168
267
 
169
- ---
268
+ ## Author
170
269
 
171
- ## ๐Ÿง‘โ€๐Ÿ’ป Author
172
-
173
- **Name:** Pratik Panchal
270
+ **Name:** Pratik Panchal
174
271
  **GitHub:** [@Pratikpanchal25](https://github.com/Pratikpanchal25)
175
272
 
176
- ---
177
-
178
-
179
- ## ๐Ÿ“„ License
273
+ ## License
180
274
 
181
275
  MIT โ€” Free to use, modify and distribute.
182
276
 
183
- ---
184
-
185
- ## ๐Ÿ›  Contributing
186
-
187
- Pull requests are welcome! If you find bugs, feel free to [open an issue](https://github.com/ShubhamNakum/DynamicFields/issues).
188
-
189
- ---
277
+ ## Contributing
190
278
 
191
- <!-- Keywords: react form builder, tailwind forms, dynamic form, smart form, react tailwind input -->
279
+ Pull requests are welcome! If you find bugs, feel free to open an issue.