1.3.6 ā¢ Published 22 hours ago
@bright-lab/tw-form v1.3.6
ā
Installation
@bright-lab/tw-form
@bright-lab/tw-form is available as an npm package
// with npm
npm install @bright-lab/tw-form
// with yarn
yarn add @bright-lab/tw-form
What is so powerful about the TW-Form ?
This Form is so smart that it will handle everything for you, as well as you can style your own inputs, custom components, error validation and responsiveness!
Getting started with @bright-lab/tw-form
Here is an example of a basic app using @bright-lab/tw-form:
in App.tsx, Import the required css file.
import '@bright-lab/tw-form/css';
in Form.tsx for example, we will import useState, DynamicForm and start adding the required fields.
import React, { useState } from 'react';
import { DynamicForm, DynamicFields } from '@bright-lab/tw-form';
const fields: DynamicFields = [
{
label: 'Email',
type: 'email',
name: 'email',
required: true,
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Password',
type: 'password',
name: 'password',
required: true,
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Nationality',
type: 'select',
name: 'nationality',
data: [
{
title: 'Lebanon',
value: 'Lebanon',
},
{
title: 'Spain',
value: 'Spain',
},
],
grid: {
xs: 12,
},
},
{
label: 'seperator',
type: 'seperator',
name: 'seperator',
},
{
label: 'Gender',
type: 'radioGroup',
name: 'gender',
content: 'between',
data: [
{
label: 'Male',
value: 'male',
},
{
label: 'Female',
value: 'female',
},
],
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Software',
type: 'checkboxGroup',
name: 'software',
content: 'between',
data: [
{
label: 'Adobe',
value: 'Adobe',
},
{
label: 'VSCode',
value: 'VSCode',
},
],
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Married?',
type: 'checkbox',
name: 'married',
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Kids',
type: 'number',
name: 'kids',
min: 0,
required: true,
grid: {
xs: 12,
md: 6,
},
},
{
label: 'Hobbies',
type: 'chips',
name: 'hobbies',
grid: {
xs: 12,
md: 6,
},
},
];
Now Let's validate the form.
const validation = {
email: (value: string) => {
if (value?.trim()?.length === 0) {
return 'Email is required';
}
if (!/\S+@\S+\.\S+/.test(value)) {
return 'Email is invalid';
}
return '';
},
password: (value: string) => {
if (value?.length < 8) {
return 'Password is shorter than the minimum length (8)';
}
return '';
},
};
Finally, Let's add the default values and return the Dynamic Form.
type values = {
name: string,
email: string,
password: string,
married: boolean,
gender: string,
nationality: string,
kids: number,
hobbies: string[],
};
const [values, setValues] = useState({
name: '',
email: '',
password: '',
married: false,
gender: 'male',
nationality: 'Lebanon',
kids: 0,
hobbies: ['basketball', 'football'],
});
const [isError, setIsError] = useState(false);
return (
<div>
<h1>Dynamic Form</h1>
<div className="max-w-[800px] mx-auto bg-slate-50 p-5">
<DynamicForm
fields={fields}
defaultValues={values}
handleChange={(val: values) => console.log(val)} // returns new values on change
validation={validation}
isError={(error) => setIsError(error)} //returns boolean
/>
<button disabled={isError}>Submit</button>
</div>
</div>
);
Here's an example on how to add Custom Fields.
{
label: 'file',
type: 'custom',
name: 'image',
Component: (customValue: File, customOnChange: () => void, errors: Record<string, string>, expectedErrors: Record<string, string>) => {
return <File value={customValue} onChange={customOnChange} errors={errors} expectedErrors={expectedErrors} />;
},
grid: {
xs: 12,
md: 6,
},
},
const [values, setValues] = useState({
name: '',
email: '',
drink: ''
});
File Component would look like this for example:
interface Props {
onChange: (value: string) => void;
value: string;
errors: Record<string, string>;
expectedErrors: Record<string, string>;
handleBlur: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
const Drink: React.FC<Props> = ({
onChange,
value,
errors,
expectedErrors,
}) => {
return (
<>
<input
type="text"
name="drink"
value={value}
onChange={(e) => {
onChange(e.target.value);
}}
onBlur={handleBlur} // error validation on blur
/>
{errors?.drink && 'error in drinks'}
</>
);
};
export default File;
Show errors when submitting the form.
Import useRef and DynamicRef Type
import { useRef } from 'react';
import { DynamicForm, DynamicRef } from '@bright-lab/tw-form';
Add the reference to the DynamicForm component, a submit button, and let's handle the functionality.
const dynamicFormRef = useRef<DynamicRef>();
const handleSubmit = () => {
if (isError) {
return dynamicFormRef.current?.onSubmit();
}
console.log('no errors')
};
return (
<>
<DynamicForm
ref={dynamicFormRef}
fields={fields}
defaultValues={values}
handleChange={handleChange}
validation={validation}
isError={(error) => setIsError(error)}
gap={{ rowGap: '3px', columnGap: '3px' }}
/>
<button
onClick={handleSubmit}
>
Submit
</button>
</>
);
CSS Styling
:root {
--tw-label-text-color: #000;
--tw-label-text-size: 1rem;
--tw-input-bg-color: #fefefe;
--tw-input-text-color: #4b5563;
--tw-input-text-size: 1rem;
--tw-input-border-color: #d1d5db;
--tw-input-border-focus-color: #475569;
--tw-input-border-radius: 0.5rem;
--tw-input-padding: 0.5rem 0.7rem;
--tw-input-error-border-color: #ef4444;
--tw-input-error-text-color: #ef4444;
--tw-input-radio-checked-color: dodgerblue;
--tw-input-checkbox-checked-color: dodgerblue;
--tw-input-select-arrow-color: #999;
--tw-chips-add-btn-color: dodgerblue;
--tw-chips-dlt-btn-color: #475569;
--tw-chips-selected-bg-color: #e2e8f0;
}
Additional Props
Property | Type | Initial State | Example |
---|---|---|---|
isError | Callback function returns boolean | null | (error) => setIsError(error) |
gap | object | null | rowGap: '10px', columnGap: '10px' |
useCheckboxAsBoolean | boolean | true | false |
darkMode | boolean | false | true |
Keys in fields
Key | Type | Example | Required | For |
---|---|---|---|---|
label | String or JSX Element | Name | No | All |
type | String | text | Yes | All |
name | String | username | Yes | All |
placeholder | String | write here.. | No | All |
required | Boolean | true | No | All |
disabled | Boolean | false | No | All |
grid | Object | {xs: 12, md: 6, lg: 3, xl: 2} | No | All |
groupGrid | Object | {xs: 12, md: 6, lg: 3, xl: 2} | No | RadioGroup, checkboxGroup |
minLength | Number | 5 | No | Text/Email/Password/Textarea |
maxLength | Number | 20 | No | Text/Email/Password/Textarea |
min | Number | 1 | No | Number |
max | Number | 100 | No | Number |
rows | Number | 5 | No | Textarea |
cols | Number | 5 | No | Textarea |
generatePassword | Boolean | true | No | Password |
data | Array of Objects | [{label: 'Cream', value:'cream'}] | Yes | Select, RadioGroup, checkboxGroup |
content | String | between, around, center, end | No | RadioGroup, checkboxGroup |
groupCols | boolean | true | No | RadioGroup, checkboxGroup |
style | Object | {marginBottom: '5px'} | No | All |
Changelog
The changelog is regularly updated to reflect what's changed in each new release.
1.3.6
22 hours ago
1.3.5
8 days ago
1.3.4
11 days ago
1.3.3
11 days ago
1.3.2
12 days ago
1.3.1
12 days ago
1.3.0
13 days ago
1.2.0
1 year ago
1.1.1
1 year ago
1.1.0
1 year ago
1.1.9
1 year ago
1.1.8
1 year ago
1.0.9
1 year ago
1.1.7
1 year ago
1.0.8
1 year ago
1.1.6
1 year ago
1.0.7
1 year ago
1.1.5
1 year ago
1.1.4
1 year ago
1.1.3
1 year ago
1.1.2
1 year ago
1.0.6
1 year ago
1.0.5
1 year ago
1.0.4
1 year ago
1.0.3
1 year ago
1.0.2
1 year ago
1.0.1
1 year ago
1.0.0
1 year ago