Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
ShreyPurohit authored Sep 4, 2024
0 parents commit b09db3d
Show file tree
Hide file tree
Showing 13 changed files with 562 additions and 0 deletions.
163 changes: 163 additions & 0 deletions npm-dynamic-form/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Dynamic Form Component

A highly customizable and easy-to-use dynamic form component built with React, TypeScript, and React Hook Form. This component allows you to generate a form dynamically based on an array of field configurations, making it suitable for various use cases.

## Installation
To install the package, run:
```bash
npm install dynamic-form-component
```

## Peer Dependencies
Ensure you have the following peer dependencies installed:
* `react`
* `react-dom`
* `react-hook-form`
* `react-icons`

You can install them with:
```bash
npm install react react-dom react-hook-form react-icons
```

## Usage
### Importing The Component
```bash
import DynamicForm, { IFormField } from 'dynamic-form-component';
```
### Example Usage
Below is an example of how to use the `DynamicForm` component in your react project:
```js
import DynamicForm, { IFormField } from 'dynamic-form-component';
import { RegisterOptions } from 'react-hook-form';
import { AiOutlineLock, AiOutlineMail, AiOutlineNumber, AiOutlineUser } from 'react-icons/ai';

const App = () => {
const formFields: IFormField[] = [
{
id: 'name',
errorId: 'nameErr',
label: 'Name',
type: 'text',
placeholder: 'Enter your name',
required: true,
validation: {
required: 'Name is required',
maxLength: {
value: 20,
message: 'Name must be less than 20 characters',
},
},
icon: <AiOutlineUser />
},
{
id: 'email',
errorId: 'emailErr',
label: 'Email',
type: 'email',
placeholder: 'Enter your email',
validation: {
required: 'Email is required',
pattern: {
value: /^\S+@\S+$/i,
message: 'Enter a valid email address',
},
},
icon: <AiOutlineMail />
},
{
id: 'age',
errorId: 'ageError',
label: 'Age',
type: 'number',
placeholder: 'Enter your age',
validation: {
min: {
value: 18,
message: 'You must be at least 18 years old',
},
},
icon: <AiOutlineNumber />
},
{
id: 'password',
errorId: 'passwordErr',
label: 'Password',
type: 'password',
placeholder: 'Enter your Password',
validation: {
required: 'Password is required',
},
icon: <AiOutlineLock />
},
{
id: 'hobbies',
errorId: 'subscriptionErr',
label: 'Hobbies',
type: 'checkbox',
options: [
{ value: 'reading', label: "Reading" },
{ value: 'sports', label: "Sports" },
{ value: 'music', label: "Music" },
{ value: 'travelling', label: "Travelling" },
],
validation: {},
},
{
id: 'gender',
errorId: 'genderErr',
label: 'Gender',
type: 'select',
options: [
{ value: 'male', label: 'Male' },
{ value: 'female', label: 'Female' },
{ value: 'other', label: 'Other' },
],
validation: {
required: 'Gender is required',
},
},
];

const handleFormSubmit = (data: Record<string, any>) => {
console.log('Form Data:', data);
};

return (
<div>
<h1>Dynamic Form Example</h1>
<DynamicForm fields={formFields} onSubmit={handleFormSubmit} />
</div>
)
}

export default App
```
### Field Configuration
* id: Unique identifier for the field.
* errorId: Identifier for displaying error messages.
* label: Label for the form field.
* type: Type of the field (text, number, email, password, checkbox, select).
* options: (Optional) Array of options for select and checkbox fields.
* placeholder: (Optional) Placeholder text for the input.
* required: (Optional) Boolean indicating if the field is required.
* validation: (Optional) Validation rules based on React Hook Form's RegisterOptions.
* icon: (Optional) Icon component to display alongside the input.
### Form Submission
The `onSubmit` function passed to `DynamicForm` will receive the form data as a `Record<string, any>`. You can handle form submission by implementing your own logic in this function.
Example Form Data
```bash
{
"name": "John Doe",
"email": "[email protected]",
"age": 25,
"password": "password123",
"hobbies": Array ["reading", "travelling"],
"gender": "male"
}
```
## Contributing
If you have any ideas, suggestions, or issues, feel free to open an issue or contribute with a pull request.
20 changes: 20 additions & 0 deletions npm-dynamic-form/dist/assets/interfaces.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { RegisterOptions, FieldValues } from "react-hook-form";
export interface IFormField {
id: string;
errorId: string;
label: string;
type: 'text' | 'number' | 'email' | 'password' | 'checkbox' | 'select';
options?: {
value: string;
label: string;
}[];
placeholder?: string;
required?: boolean;
validation?: RegisterOptions;
icon?: React.ReactNode;
value?: string;
}
export interface DynamicFormProps {
fields: IFormField[];
onSubmit: (data: FieldValues) => void;
}
2 changes: 2 additions & 0 deletions npm-dynamic-form/dist/assets/interfaces.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
4 changes: 4 additions & 0 deletions npm-dynamic-form/dist/components/DynamicForm.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { DynamicFormProps } from '../assets/interfaces';
import React from 'react';
declare const DynamicForm: React.FC<DynamicFormProps>;
export default DynamicForm;
36 changes: 36 additions & 0 deletions npm-dynamic-form/dist/components/DynamicForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const react_hook_form_1 = require("react-hook-form");
const ai_1 = require("react-icons/ai");
const react_2 = __importDefault(require("react"));
const DynamicForm = ({ fields, onSubmit }) => {
const [showPassword, setShowPassword] = (0, react_1.useState)(false);
const { register, handleSubmit, formState: { errors } } = (0, react_hook_form_1.useForm)({ mode: 'all' });
const renderField = (field) => {
var _a, _b;
const error = (_a = errors[field.id]) === null || _a === void 0 ? void 0 : _a.message;
const isPasswordField = field.type === 'password';
const inputType = isPasswordField && showPassword ? 'text' : field.type;
return (react_2.default.createElement("div", { id: 'input-wrapper' },
react_2.default.createElement("div", { id: 'input-container' }, field.type === 'checkbox' && field.options ? (react_2.default.createElement("div", { className: 'grid grid-cols-2 gap-4' }, field.options.map(option => (react_2.default.createElement("div", { key: option.value, className: 'flex gap-1 items-center justify-center' },
react_2.default.createElement("label", { htmlFor: `${field.id}-${option.value}`, className: 'ml-2 mt-1' },
option.label,
" :"),
react_2.default.createElement("input", Object.assign({ id: `${field.id}-${option.value}` }, register(field.id, Object.assign({}, field.validation)), { type: field.type, value: option.value, className: 'w-max' }))))))) : field.type === 'select' ? (react_2.default.createElement("select", Object.assign({}, register(field.id, Object.assign({}, field.validation)), { id: field.id }), (_b = field.options) === null || _b === void 0 ? void 0 : _b.map((option) => (react_2.default.createElement("option", { key: option.value, value: option.value }, option.label))))) : (react_2.default.createElement("div", { className: 'flex items-center p-1 border' },
field.icon && react_2.default.createElement("div", { className: 'ml-2' }, field.icon),
react_2.default.createElement("input", Object.assign({ id: field.id }, register(field.id, Object.assign({}, field.validation)), { type: inputType, placeholder: field.placeholder })),
isPasswordField && (react_2.default.createElement("div", { id: "prop-icon", className: "hover:cursor-pointer mr-3", onClick: () => setShowPassword(!showPassword) }, showPassword ? react_2.default.createElement(ai_1.AiOutlineEye, null) : react_2.default.createElement(ai_1.AiOutlineEyeInvisible, null)))))),
error && react_2.default.createElement("span", { id: field.errorId }, error)));
};
return (react_2.default.createElement("main", { className: 'md:w-3/4 m-auto md:h-0' },
react_2.default.createElement("form", { onSubmit: handleSubmit(onSubmit), className: "flex flex-col md:w-1/2 m-auto p-5 gap-5 md:mt-5 md:border border-black" },
fields.map((field) => (react_2.default.createElement("div", { key: field.id },
react_2.default.createElement("label", { htmlFor: field.id }, field.label),
renderField(field)))),
react_2.default.createElement("button", { type: 'submit', disabled: Object.keys(errors).length ? true : false, className: 'px-4 py-2 bg-slate-400 hover:bg-slate-600 hover:transition hover:text-white rounded-lg disabled:bg-gray-600 disabled:hover:bg-gray-600' }, "Submit"))));
};
exports.default = DynamicForm;
4 changes: 4 additions & 0 deletions npm-dynamic-form/dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import DynamicForm from './components/DynamicForm';
import { IFormField, DynamicFormProps } from './assets/interfaces';
export default DynamicForm;
export { IFormField, DynamicFormProps };
7 changes: 7 additions & 0 deletions npm-dynamic-form/dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const DynamicForm_1 = __importDefault(require("./components/DynamicForm"));
exports.default = DynamicForm_1.default;
147 changes: 147 additions & 0 deletions npm-dynamic-form/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b09db3d

Please sign in to comment.