react-smart-fields 1.0.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 ADDED
@@ -0,0 +1,23 @@
1
+ # 🧩 react-dynamic-fields
2
+
3
+ > A flexible, customizable, and developer-friendly component to generate dynamic form fields in React. Supports all HTML inputs, validation, and styling out of the box.
4
+
5
+ ---
6
+
7
+ ## 🚀 Features
8
+
9
+ ✅ Supports all HTML field types (text, number, select, radio, checkbox, etc.)
10
+ ✅ Real-time error validation (required & custom)
11
+ ✅ Style customization with `style` or `className`
12
+ ✅ Minimal setup – just pass a `fields` config
13
+ ✅ React 18+ support
14
+ ✅ TypeScript ready
15
+
16
+ ---
17
+
18
+ ## 📦 Installation
19
+
20
+ ```bash
21
+ npm install react-dynamic-fields
22
+ # or
23
+ yarn add react-dynamic-fields
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ type FieldType = "text" | "number" | "email" | "password" | "date" | "checkbox" | "radio" | "select";
3
+ export interface FieldOption {
4
+ label: string;
5
+ value: string | number | boolean;
6
+ }
7
+ export interface FieldConfig {
8
+ name: string;
9
+ label?: string;
10
+ type: FieldType;
11
+ required?: boolean;
12
+ defaultValue?: any;
13
+ customValidation?: (value: any) => string | null;
14
+ options?: FieldOption[];
15
+ style?: React.CSSProperties;
16
+ className?: string;
17
+ }
18
+ interface DynamicFieldsProps {
19
+ fields: FieldConfig[];
20
+ onChange?: (formData: {
21
+ [key: string]: any;
22
+ }, errors: {
23
+ [key: string]: string | null;
24
+ }) => void;
25
+ }
26
+ export declare const DynamicFields: React.FC<DynamicFieldsProps>;
27
+ export {};
@@ -0,0 +1,44 @@
1
+ import React, { useState } from "react";
2
+ export const DynamicFields = ({ fields, onChange, }) => {
3
+ const [formData, setFormData] = useState(() => {
4
+ const initial = {};
5
+ fields.forEach((f) => {
6
+ initial[f.name] =
7
+ f.type === "checkbox"
8
+ ? f.defaultValue ?? false
9
+ : f.defaultValue ?? "";
10
+ });
11
+ return initial;
12
+ });
13
+ const [errors, setErrors] = useState({});
14
+ const validateField = (field, value) => {
15
+ if (field.required && (value === "" || value === null || value === undefined || value === false)) {
16
+ return "This field is required";
17
+ }
18
+ if (field.customValidation)
19
+ return field.customValidation(value);
20
+ return null;
21
+ };
22
+ const handleChange = (name, value, field) => {
23
+ const newFormData = { ...formData, [name]: value };
24
+ const error = validateField(field, value);
25
+ const newErrors = { ...errors, [name]: error };
26
+ setFormData(newFormData);
27
+ setErrors(newErrors);
28
+ if (onChange)
29
+ onChange(newFormData, newErrors);
30
+ };
31
+ return (React.createElement(React.Fragment, null, fields.map((field) => (React.createElement("div", { key: field.name, style: { marginBottom: "1rem" } },
32
+ field.label && (React.createElement("label", { htmlFor: field.name, style: { display: "block" } }, field.label)),
33
+ field.type === "select" && (React.createElement("select", { name: field.name, className: field.className, style: field.style, value: formData[field.name], onChange: (e) => handleChange(field.name, e.target.value, field) },
34
+ React.createElement("option", { value: "" }, "Select an option"),
35
+ field.options?.map((opt) => (React.createElement("option", { key: String(opt.value), value: String(opt.value) }, opt.label))))),
36
+ field.type === "radio" &&
37
+ field.options?.map((opt) => (React.createElement("label", { key: String(opt.value), style: { marginRight: "1rem" } },
38
+ React.createElement("input", { type: "radio", name: field.name, value: String(opt.value), checked: formData[field.name] === opt.value, onChange: () => handleChange(field.name, opt.value, field) }),
39
+ " ",
40
+ opt.label))),
41
+ field.type === "checkbox" && (React.createElement("input", { type: "checkbox", name: field.name, checked: formData[field.name], className: field.className, style: field.style, onChange: (e) => handleChange(field.name, e.target.checked, field) })),
42
+ !["select", "radio", "checkbox"].includes(field.type) && (React.createElement("input", { type: field.type, name: field.name, value: formData[field.name], className: field.className, style: field.style, onChange: (e) => handleChange(field.name, e.target.value, field) })),
43
+ errors[field.name] && (React.createElement("p", { style: { color: "red", marginTop: "0.25rem" } }, errors[field.name])))))));
44
+ };
@@ -0,0 +1,2 @@
1
+ export { DynamicFields } from "./components/DynamicField";
2
+ export type { FieldConfig, FieldOption } from "./components/DynamicField";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { DynamicFields } from "./components/DynamicField";
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "react-smart-fields",
3
+ "version": "1.0.0",
4
+ "description": "> A flexible, customizable, and developer-friendly component to generate dynamic form fields in React. Supports all HTML inputs, validation, and styling out of the box.",
5
+ "license": "MIT",
6
+ "author": "Pratik Panchal",
7
+ "type": "commonjs",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "scripts": {
11
+ "build": "tsc"
12
+ },
13
+ "dependencies": {
14
+ "csstype": "^3.1.3",
15
+ "js-tokens": "^4.0.0",
16
+ "loose-envify": "^1.4.0",
17
+ "react": "^18.3.1"
18
+ },
19
+ "devDependencies": {
20
+ "typescript": "^5.0.0",
21
+ "@types/react": "^18.0.0"
22
+ },
23
+ "peerDependencies": {
24
+ "react": "^18.0.0"
25
+ }
26
+ }
@@ -0,0 +1,163 @@
1
+ import React, { useState } from "react";
2
+
3
+ type FieldType =
4
+ | "text"
5
+ | "number"
6
+ | "email"
7
+ | "password"
8
+ | "date"
9
+ | "checkbox"
10
+ | "radio"
11
+ | "select";
12
+
13
+ export interface FieldOption {
14
+ label: string;
15
+ value: string | number | boolean;
16
+ }
17
+
18
+ export interface FieldConfig {
19
+ name: string;
20
+ label?: string;
21
+ type: FieldType;
22
+ required?: boolean;
23
+ defaultValue?: any;
24
+ customValidation?: (value: any) => string | null;
25
+ options?: FieldOption[]; // for select & radio
26
+ style?: React.CSSProperties;
27
+ className?: string;
28
+ }
29
+
30
+ interface DynamicFieldsProps {
31
+ fields: FieldConfig[];
32
+ onChange?: (
33
+ formData: { [key: string]: any },
34
+ errors: { [key: string]: string | null }
35
+ ) => void;
36
+ }
37
+
38
+ export const DynamicFields: React.FC<DynamicFieldsProps> = ({
39
+ fields,
40
+ onChange,
41
+ }) => {
42
+ const [formData, setFormData] = useState<{ [key: string]: any }>(() => {
43
+ const initial: any = {};
44
+ fields.forEach((f) => {
45
+ initial[f.name] =
46
+ f.type === "checkbox"
47
+ ? f.defaultValue ?? false
48
+ : f.defaultValue ?? "";
49
+ });
50
+ return initial;
51
+ });
52
+
53
+ const [errors, setErrors] = useState<{ [key: string]: string | null }>({});
54
+
55
+ const validateField = (field: FieldConfig, value: any) => {
56
+ if (field.required && (value === "" || value === null || value === undefined || value === false)) {
57
+ return "This field is required";
58
+ }
59
+ if (field.customValidation) return field.customValidation(value);
60
+ return null;
61
+ };
62
+
63
+ const handleChange = (
64
+ name: string,
65
+ value: any,
66
+ field: FieldConfig
67
+ ) => {
68
+ const newFormData = { ...formData, [name]: value };
69
+ const error = validateField(field, value);
70
+ const newErrors = { ...errors, [name]: error };
71
+
72
+ setFormData(newFormData);
73
+ setErrors(newErrors);
74
+
75
+ if (onChange) onChange(newFormData, newErrors);
76
+ };
77
+
78
+ return (
79
+ <>
80
+ {fields.map((field) => (
81
+ <div key={field.name} style={{ marginBottom: "1rem" }}>
82
+ {field.label && (
83
+ <label htmlFor={field.name} style={{ display: "block" }}>
84
+ {field.label}
85
+ </label>
86
+ )}
87
+
88
+ {/* Select Dropdown */}
89
+ {field.type === "select" && (
90
+ <select
91
+ name={field.name}
92
+ className={field.className}
93
+ style={field.style}
94
+ value={formData[field.name]}
95
+ onChange={(e) =>
96
+ handleChange(field.name, e.target.value, field)
97
+ }
98
+ >
99
+ <option value="">Select an option</option>
100
+ {field.options?.map((opt) => (
101
+ <option key={String(opt.value)} value={String(opt.value)}>
102
+ {opt.label}
103
+ </option>
104
+ ))}
105
+ </select>
106
+ )}
107
+
108
+ {/* Radio Buttons */}
109
+ {field.type === "radio" &&
110
+ field.options?.map((opt) => (
111
+ <label key={String(opt.value)} style={{ marginRight: "1rem" }}>
112
+ <input
113
+ type="radio"
114
+ name={field.name}
115
+ value={String(opt.value)}
116
+ checked={formData[field.name] === opt.value}
117
+ onChange={() =>
118
+ handleChange(field.name, opt.value, field)
119
+ }
120
+ />{" "}
121
+ {opt.label}
122
+ </label>
123
+ ))}
124
+
125
+ {/* Checkbox */}
126
+ {field.type === "checkbox" && (
127
+ <input
128
+ type="checkbox"
129
+ name={field.name}
130
+ checked={formData[field.name]}
131
+ className={field.className}
132
+ style={field.style}
133
+ onChange={(e) =>
134
+ handleChange(field.name, e.target.checked, field)
135
+ }
136
+ />
137
+ )}
138
+
139
+ {/* Other Inputs (text, email, number, etc.) */}
140
+ {!["select", "radio", "checkbox"].includes(field.type) && (
141
+ <input
142
+ type={field.type}
143
+ name={field.name}
144
+ value={formData[field.name]}
145
+ className={field.className}
146
+ style={field.style}
147
+ onChange={(e) =>
148
+ handleChange(field.name, e.target.value, field)
149
+ }
150
+ />
151
+ )}
152
+
153
+ {/* Error Display */}
154
+ {errors[field.name] && (
155
+ <p style={{ color: "red", marginTop: "0.25rem" }}>
156
+ {errors[field.name]}
157
+ </p>
158
+ )}
159
+ </div>
160
+ ))}
161
+ </>
162
+ );
163
+ };
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { DynamicFields } from "./components/DynamicField";
2
+ export type { FieldConfig, FieldOption } from "./components/DynamicField";
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "jsx": "react",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "moduleResolution": "Node"
11
+ },
12
+ "include": ["src"]
13
+ }