@algodomain/smart-forms 0.1.0 → 0.1.1
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/LICENSE +22 -0
- package/README.md +930 -165
- package/dist/{SmartFormProvider-B-BTl4wO.d.cts → SmartFormProvider-DyJoDBjQ.d.cts} +2 -0
- package/dist/{SmartFormProvider-B-BTl4wO.d.ts → SmartFormProvider-DyJoDBjQ.d.ts} +2 -0
- package/dist/{chunk-6WAEAWTD.js → chunk-5A5WAAED.js} +3 -3
- package/dist/{chunk-6WAEAWTD.js.map → chunk-5A5WAAED.js.map} +1 -1
- package/dist/{chunk-IG4XDQMV.js → chunk-EE6VZXWC.js} +36 -9
- package/dist/chunk-EE6VZXWC.js.map +1 -0
- package/dist/{chunk-YV7RVYMD.cjs → chunk-LRMJP5OJ.cjs} +35 -8
- package/dist/chunk-LRMJP5OJ.cjs.map +1 -0
- package/dist/{chunk-Y6NGPMDH.cjs → chunk-Y3H6MI5D.cjs} +79 -79
- package/dist/{chunk-Y6NGPMDH.cjs.map → chunk-Y3H6MI5D.cjs.map} +1 -1
- package/dist/fields.cjs +108 -108
- package/dist/fields.d.cts +1 -1
- package/dist/fields.d.ts +1 -1
- package/dist/fields.js +4 -4
- package/dist/index.cjs +32 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/dist/opinionated.cjs +18 -18
- package/dist/opinionated.d.cts +1 -1
- package/dist/opinionated.d.ts +1 -1
- package/dist/opinionated.js +2 -2
- package/package.json +4 -2
- package/dist/chunk-IG4XDQMV.js.map +0 -1
- package/dist/chunk-YV7RVYMD.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,70 +1,119 @@
|
|
|
1
1
|
# @algodomain/smart-forms
|
|
2
2
|
|
|
3
|
-
A powerful, flexible React form framework with smart fields, multi-tab support, built-in validation, and seamless API integration.
|
|
3
|
+
> A powerful, flexible React form framework with smart fields, multi-tab support, built-in validation, and seamless API integration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@algodomain/smart-forms)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Built with TypeScript, Tailwind CSS, Zod validation, and shadcn/ui components.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
- 📑 **Multi-Tab Forms**: Create complex forms with tabbed navigation and progress tracking
|
|
11
|
-
- ✅ **Built-in Validation**: Powered by Zod for type-safe validation
|
|
12
|
-
- 🔄 **API Integration**: Automatic form submission with authentication support
|
|
13
|
-
- 💾 **Auto-Save**: LocalStorage support for draft saving
|
|
14
|
-
- 🎨 **Customizable**: Full theme control via CSS variables
|
|
15
|
-
- 🌙 **Dark Mode**: Built-in support for light and dark themes
|
|
16
|
-
- ♿ **Accessible**: Built on Radix UI primitives
|
|
17
|
-
- 📦 **Tree-Shakeable**: Import only what you need
|
|
10
|
+
---
|
|
18
11
|
|
|
19
|
-
##
|
|
12
|
+
## 📋 Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#-features)
|
|
15
|
+
- [Installation](#-installation)
|
|
16
|
+
- [Quick Start](#-quick-start)
|
|
17
|
+
- [Form Components](#-form-components)
|
|
18
|
+
- [Field Components](#-field-components)
|
|
19
|
+
- [Opinionated Fields](#-opinionated-fields)
|
|
20
|
+
- [Configuration Reference](#-configuration-reference)
|
|
21
|
+
- [Advanced Features](#-advanced-features)
|
|
22
|
+
- [Theming](#-theming--customization)
|
|
23
|
+
- [Hooks & Context](#-hooks--context)
|
|
24
|
+
- [Examples](#-examples)
|
|
25
|
+
- [Troubleshooting](#-troubleshooting)
|
|
26
|
+
- [Contributing](#-contributing)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ✨ Features
|
|
31
|
+
|
|
32
|
+
- 🎯 **Smart Fields** - Pre-built, validated form fields with consistent UX
|
|
33
|
+
- 📑 **Multi-Tab Forms** - Create complex forms with tabbed navigation and progress tracking
|
|
34
|
+
- ✅ **Built-in Validation** - Powered by Zod for type-safe validation
|
|
35
|
+
- 🔄 **API Integration** - Automatic form submission with authentication support
|
|
36
|
+
- 🔗 **Query Params** - Include URL query parameters in form submissions
|
|
37
|
+
- 💾 **Auto-Save** - LocalStorage support for draft saving
|
|
38
|
+
- 🎨 **Customizable** - Full theme control via CSS variables
|
|
39
|
+
- 🌙 **Dark Mode** - Built-in support for light and dark themes
|
|
40
|
+
- ♿ **Accessible** - Built on Radix UI primitives
|
|
41
|
+
- 📦 **Tree-Shakeable** - Import only what you need
|
|
42
|
+
- 🔒 **Type-Safe** - Full TypeScript support
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 📦 Installation
|
|
47
|
+
|
|
48
|
+
### 1. Install the Package
|
|
20
49
|
|
|
21
50
|
```bash
|
|
22
51
|
npm install @algodomain/smart-forms
|
|
23
52
|
# or
|
|
24
|
-
pnpm add @algodomain/smart-forms
|
|
25
|
-
# or
|
|
26
53
|
yarn add @algodomain/smart-forms
|
|
54
|
+
# or
|
|
55
|
+
pnpm add @algodomain/smart-forms
|
|
27
56
|
```
|
|
28
57
|
|
|
29
|
-
### Peer Dependencies
|
|
30
|
-
|
|
31
|
-
Make sure you have these installed:
|
|
58
|
+
### 2. Install Peer Dependencies
|
|
32
59
|
|
|
33
60
|
```bash
|
|
34
61
|
npm install react react-dom tailwindcss zod react-toastify date-fns lucide-react
|
|
35
62
|
```
|
|
36
63
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
### 1. Import the CSS
|
|
64
|
+
### 3. Import Styles
|
|
40
65
|
|
|
41
|
-
Add
|
|
66
|
+
Add to your main entry file (`main.tsx` or `index.tsx`):
|
|
42
67
|
|
|
43
68
|
```tsx
|
|
44
69
|
import '@algodomain/smart-forms/style.css'
|
|
45
|
-
import '
|
|
70
|
+
import 'react-toastify/dist/ReactToastify.css'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Configure Tailwind CSS (v4)
|
|
74
|
+
|
|
75
|
+
Add `@source` directives to scan the package for Tailwind classes:
|
|
76
|
+
|
|
77
|
+
```css
|
|
78
|
+
/* src/index.css */
|
|
79
|
+
@import "tailwindcss";
|
|
80
|
+
|
|
81
|
+
@source "../node_modules/@algodomain/smart-forms/dist/index.js";
|
|
82
|
+
@source "../node_modules/@algodomain/smart-forms/dist/index.cjs";
|
|
83
|
+
|
|
84
|
+
@import "@algodomain/smart-forms/style.css";
|
|
46
85
|
```
|
|
47
86
|
|
|
48
|
-
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🚀 Quick Start
|
|
90
|
+
|
|
91
|
+
### Basic Form Example
|
|
49
92
|
|
|
50
93
|
```tsx
|
|
51
94
|
import { SmartForm } from '@algodomain/smart-forms'
|
|
52
|
-
import { SmartInput } from '@algodomain/smart-forms/fields'
|
|
53
|
-
import { FieldEmail
|
|
95
|
+
import { SmartInput, SmartSelect } from '@algodomain/smart-forms/fields'
|
|
96
|
+
import { FieldEmail } from '@algodomain/smart-forms/opinionated'
|
|
97
|
+
import { z } from 'zod'
|
|
54
98
|
|
|
55
99
|
function RegistrationForm() {
|
|
56
100
|
return (
|
|
57
101
|
<SmartForm
|
|
58
|
-
api="
|
|
102
|
+
api="https://api.example.com/register"
|
|
59
103
|
method="POST"
|
|
60
104
|
submitButtonText="Sign Up"
|
|
61
|
-
onSuccess={(data) => console.log('
|
|
105
|
+
onSuccess={(data) => console.log('Success!', data)}
|
|
62
106
|
onError={(error) => console.error('Error:', error)}
|
|
63
|
-
authentication={{ enable: true }}
|
|
64
107
|
>
|
|
65
|
-
<SmartInput
|
|
108
|
+
<SmartInput
|
|
109
|
+
field="name"
|
|
110
|
+
label="Full Name"
|
|
111
|
+
validation={z.string().min(3, 'Name must be at least 3 characters')}
|
|
112
|
+
required
|
|
113
|
+
/>
|
|
114
|
+
|
|
66
115
|
<FieldEmail field="email" required />
|
|
67
|
-
|
|
116
|
+
|
|
68
117
|
<SmartSelect
|
|
69
118
|
field="role"
|
|
70
119
|
label="Role"
|
|
@@ -72,27 +121,27 @@ function RegistrationForm() {
|
|
|
72
121
|
{ value: 'user', label: 'User' },
|
|
73
122
|
{ value: 'admin', label: 'Admin' }
|
|
74
123
|
]}
|
|
124
|
+
required
|
|
75
125
|
/>
|
|
76
126
|
</SmartForm>
|
|
77
127
|
)
|
|
78
128
|
}
|
|
79
129
|
```
|
|
80
130
|
|
|
81
|
-
###
|
|
131
|
+
### Multi-Tab Form Example
|
|
82
132
|
|
|
83
133
|
```tsx
|
|
84
134
|
import { MultiTabSmartForm, Tab } from '@algodomain/smart-forms'
|
|
85
|
-
import { SmartInput,
|
|
135
|
+
import { SmartInput, SmartTags } from '@algodomain/smart-forms/fields'
|
|
86
136
|
import { z } from 'zod'
|
|
87
137
|
|
|
88
|
-
function
|
|
138
|
+
function JobPostingForm() {
|
|
89
139
|
return (
|
|
90
140
|
<MultiTabSmartForm
|
|
91
141
|
api="/api/jobs"
|
|
92
142
|
method="POST"
|
|
93
143
|
showProgressBar={true}
|
|
94
144
|
showTabNumbers={true}
|
|
95
|
-
authentication={{ enable: true }}
|
|
96
145
|
onSuccess={(data) => console.log('Job created:', data)}
|
|
97
146
|
>
|
|
98
147
|
<Tab title="Basic Info">
|
|
@@ -102,15 +151,6 @@ function CreateJobForm() {
|
|
|
102
151
|
validation={z.string().min(3)}
|
|
103
152
|
required
|
|
104
153
|
/>
|
|
105
|
-
<SmartRadioGroup
|
|
106
|
-
field="jobType"
|
|
107
|
-
label="Job Type"
|
|
108
|
-
options={[
|
|
109
|
-
{ value: 'FULL_TIME', label: 'Full Time' },
|
|
110
|
-
{ value: 'PART_TIME', label: 'Part Time' }
|
|
111
|
-
]}
|
|
112
|
-
required
|
|
113
|
-
/>
|
|
114
154
|
</Tab>
|
|
115
155
|
|
|
116
156
|
<Tab title="Requirements">
|
|
@@ -120,194 +160,919 @@ function CreateJobForm() {
|
|
|
120
160
|
validation={z.array(z.string()).min(1)}
|
|
121
161
|
required
|
|
122
162
|
/>
|
|
123
|
-
<SmartInput
|
|
124
|
-
field="experience"
|
|
125
|
-
label="Years of Experience"
|
|
126
|
-
type="number"
|
|
127
|
-
/>
|
|
128
163
|
</Tab>
|
|
129
164
|
</MultiTabSmartForm>
|
|
130
165
|
)
|
|
131
166
|
}
|
|
132
167
|
```
|
|
133
168
|
|
|
134
|
-
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 📝 Form Components
|
|
135
172
|
|
|
136
|
-
###
|
|
173
|
+
### SmartForm
|
|
137
174
|
|
|
138
|
-
|
|
139
|
-
- **MultiTabSmartForm**: Multi-step tabbed form with progress tracking
|
|
140
|
-
- **BaseSmartForm**: Low-level form component for custom layouts
|
|
175
|
+
Single-page form with automatic submission handling.
|
|
141
176
|
|
|
142
|
-
|
|
177
|
+
**Usage:**
|
|
143
178
|
|
|
144
|
-
|
|
179
|
+
```tsx
|
|
180
|
+
<SmartForm
|
|
181
|
+
api="/api/endpoint"
|
|
182
|
+
method="POST"
|
|
183
|
+
onSuccess={(data) => console.log(data)}
|
|
184
|
+
onError={(error) => console.error(error)}
|
|
185
|
+
>
|
|
186
|
+
{/* Your fields here */}
|
|
187
|
+
</SmartForm>
|
|
188
|
+
```
|
|
145
189
|
|
|
146
|
-
|
|
147
|
-
- `SmartSelect` - Dropdown select
|
|
148
|
-
- `SmartCheckbox` - Checkbox with label
|
|
149
|
-
- `SmartRadioGroup` - Radio button group
|
|
150
|
-
- `SmartCombobox` - Searchable select
|
|
151
|
-
- `SmartDatePicker` - Date picker with calendar
|
|
152
|
-
- `SmartFileUpload` - File upload with preview
|
|
153
|
-
- `SmartSlider` - Single value slider
|
|
154
|
-
- `SmartDualRangeSlider` - Min/max range slider
|
|
155
|
-
- `SmartTags` - Tag input field
|
|
156
|
-
- `SmartAutoSuggestTags` - Tags with autocomplete
|
|
157
|
-
- `SmartBasicRichTextbox` - Basic rich text editor
|
|
190
|
+
### MultiTabSmartForm
|
|
158
191
|
|
|
159
|
-
|
|
192
|
+
Multi-step form with tabs and progress tracking.
|
|
160
193
|
|
|
161
|
-
|
|
194
|
+
**Usage:**
|
|
162
195
|
|
|
163
|
-
|
|
196
|
+
```tsx
|
|
197
|
+
<MultiTabSmartForm
|
|
198
|
+
api="/api/submit"
|
|
199
|
+
showProgressBar={true}
|
|
200
|
+
showTabNumbers={true}
|
|
201
|
+
>
|
|
202
|
+
<Tab title="Step 1">
|
|
203
|
+
{/* Fields */}
|
|
204
|
+
</Tab>
|
|
205
|
+
<Tab title="Step 2">
|
|
206
|
+
{/* Fields */}
|
|
207
|
+
</Tab>
|
|
208
|
+
</MultiTabSmartForm>
|
|
209
|
+
```
|
|
164
210
|
|
|
165
|
-
|
|
166
|
-
- `FieldPassword` / `FieldConfirmPassword` - Password fields
|
|
167
|
-
- `FieldPhone` - Phone number field
|
|
168
|
-
- `FieldFirstName` / `FieldLastName` / `FieldFullName` - Name fields
|
|
169
|
-
- `FieldAge` - Age field with validation
|
|
170
|
-
- `FieldStreetAddress` / `FieldCity` / `FieldZipCode` / `FieldState` - Address fields
|
|
171
|
-
- `FieldMessage` / `FieldComments` - Message/comment fields
|
|
211
|
+
### BaseSmartForm
|
|
172
212
|
|
|
173
|
-
|
|
213
|
+
Low-level form component for custom layouts.
|
|
174
214
|
|
|
175
|
-
|
|
215
|
+
**Usage:**
|
|
176
216
|
|
|
177
217
|
```tsx
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
218
|
+
<BaseSmartForm api="/api/submit">
|
|
219
|
+
<div className="custom-layout">
|
|
220
|
+
<SmartInput field="name" label="Name" />
|
|
221
|
+
<CustomSubmitButton />
|
|
222
|
+
</div>
|
|
223
|
+
</BaseSmartForm>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 🎯 Field Components
|
|
229
|
+
|
|
230
|
+
All field components are imported from `@algodomain/smart-forms/fields`:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
import {
|
|
234
|
+
SmartInput,
|
|
235
|
+
SmartSelect,
|
|
236
|
+
SmartCheckbox,
|
|
237
|
+
SmartRadioGroup,
|
|
238
|
+
SmartDatePicker,
|
|
239
|
+
SmartTags,
|
|
240
|
+
SmartSlider,
|
|
241
|
+
SmartDualRangeSlider,
|
|
242
|
+
SmartCombobox,
|
|
243
|
+
SmartBasicRichTextbox,
|
|
244
|
+
SmartFileUpload,
|
|
245
|
+
SmartAutoSuggestTags
|
|
246
|
+
} from '@algodomain/smart-forms/fields'
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### SmartInput
|
|
250
|
+
|
|
251
|
+
Text input with support for multiple types.
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
<SmartInput
|
|
255
|
+
field="username"
|
|
256
|
+
label="Username"
|
|
257
|
+
type="text"
|
|
258
|
+
placeholder="Enter username"
|
|
259
|
+
validation={z.string().min(3).max(20)}
|
|
260
|
+
required
|
|
189
261
|
/>
|
|
190
262
|
```
|
|
191
263
|
|
|
192
|
-
|
|
264
|
+
**Supported types:** `text`, `email`, `password`, `tel`, `number`, `textarea`
|
|
193
265
|
|
|
194
|
-
|
|
266
|
+
### SmartSelect
|
|
195
267
|
|
|
196
|
-
|
|
197
|
-
- `label`: Display label
|
|
198
|
-
- `required`: Make field required
|
|
199
|
-
- `validation`: Zod schema for validation
|
|
200
|
-
- `defaultValue`: Initial value
|
|
201
|
-
- `placeholder`: Placeholder text
|
|
202
|
-
- `className`: Custom CSS class
|
|
203
|
-
- `info`: Info tooltip text
|
|
204
|
-
- `subLabel`: Additional label text
|
|
268
|
+
Dropdown select field.
|
|
205
269
|
|
|
206
|
-
|
|
270
|
+
```tsx
|
|
271
|
+
<SmartSelect
|
|
272
|
+
field="country"
|
|
273
|
+
label="Country"
|
|
274
|
+
options={[
|
|
275
|
+
{ value: 'us', label: 'United States' },
|
|
276
|
+
{ value: 'ca', label: 'Canada' }
|
|
277
|
+
]}
|
|
278
|
+
required
|
|
279
|
+
/>
|
|
280
|
+
```
|
|
207
281
|
|
|
208
|
-
###
|
|
282
|
+
### SmartCheckbox
|
|
209
283
|
|
|
210
|
-
|
|
284
|
+
Checkbox with label.
|
|
211
285
|
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
286
|
+
```tsx
|
|
287
|
+
<SmartCheckbox
|
|
288
|
+
field="terms"
|
|
289
|
+
label="I agree to terms"
|
|
290
|
+
validation={z.boolean().refine(val => val === true)}
|
|
291
|
+
required
|
|
292
|
+
/>
|
|
293
|
+
```
|
|
219
294
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
295
|
+
### SmartRadioGroup
|
|
296
|
+
|
|
297
|
+
Radio button group.
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
<SmartRadioGroup
|
|
301
|
+
field="gender"
|
|
302
|
+
label="Gender"
|
|
303
|
+
options={[
|
|
304
|
+
{ value: 'male', label: 'Male' },
|
|
305
|
+
{ value: 'female', label: 'Female' }
|
|
306
|
+
]}
|
|
307
|
+
alignment="horizontal"
|
|
308
|
+
required
|
|
309
|
+
/>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### SmartDatePicker
|
|
313
|
+
|
|
314
|
+
Date picker with calendar UI.
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
<SmartDatePicker
|
|
318
|
+
field="birthDate"
|
|
319
|
+
label="Date of Birth"
|
|
320
|
+
validation={z.date()}
|
|
321
|
+
required
|
|
322
|
+
/>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### SmartTags
|
|
326
|
+
|
|
327
|
+
Tag input for multiple values.
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
<SmartTags
|
|
331
|
+
field="skills"
|
|
332
|
+
label="Skills"
|
|
333
|
+
placeholder="Type and press Enter"
|
|
334
|
+
validation={z.array(z.string()).min(1)}
|
|
335
|
+
maxTags={10}
|
|
336
|
+
required
|
|
337
|
+
/>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### SmartSlider
|
|
341
|
+
|
|
342
|
+
Single value slider.
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
<SmartSlider
|
|
346
|
+
field="experience"
|
|
347
|
+
label="Years of Experience"
|
|
348
|
+
min={0}
|
|
349
|
+
max={40}
|
|
350
|
+
step={1}
|
|
351
|
+
showValue={true}
|
|
352
|
+
/>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### SmartDualRangeSlider
|
|
356
|
+
|
|
357
|
+
Min/max range slider.
|
|
358
|
+
|
|
359
|
+
```tsx
|
|
360
|
+
<SmartDualRangeSlider
|
|
361
|
+
minField="minSalary"
|
|
362
|
+
maxField="maxSalary"
|
|
363
|
+
label="Salary Range"
|
|
364
|
+
min={0}
|
|
365
|
+
max={200000}
|
|
366
|
+
step={5000}
|
|
367
|
+
/>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### SmartCombobox
|
|
371
|
+
|
|
372
|
+
Searchable combo box.
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
<SmartCombobox
|
|
376
|
+
field="technology"
|
|
377
|
+
label="Technology"
|
|
378
|
+
options={[
|
|
379
|
+
{ value: 'react', label: 'React' },
|
|
380
|
+
{ value: 'vue', label: 'Vue' }
|
|
381
|
+
]}
|
|
382
|
+
allowCustom={true}
|
|
383
|
+
/>
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### SmartBasicRichTextbox
|
|
387
|
+
|
|
388
|
+
Basic rich text editor.
|
|
389
|
+
|
|
390
|
+
```tsx
|
|
391
|
+
<SmartBasicRichTextbox
|
|
392
|
+
field="description"
|
|
393
|
+
label="Description"
|
|
394
|
+
minHeight="150px"
|
|
395
|
+
validation={z.string().min(50)}
|
|
396
|
+
required
|
|
397
|
+
/>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### SmartFileUpload
|
|
401
|
+
|
|
402
|
+
File upload field.
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
<SmartFileUpload
|
|
406
|
+
field="resume"
|
|
407
|
+
label="Upload Resume"
|
|
408
|
+
accept=".pdf,.doc,.docx"
|
|
409
|
+
maxSize={5 * 1024 * 1024}
|
|
410
|
+
required
|
|
411
|
+
/>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 🎨 Opinionated Fields
|
|
417
|
+
|
|
418
|
+
Pre-configured fields with built-in validation. Import from `@algodomain/smart-forms/opinionated`:
|
|
419
|
+
|
|
420
|
+
```tsx
|
|
421
|
+
import {
|
|
422
|
+
FieldEmail,
|
|
423
|
+
FieldPassword,
|
|
424
|
+
FieldConfirmPassword,
|
|
425
|
+
FieldPhone,
|
|
426
|
+
FieldFirstName,
|
|
427
|
+
FieldLastName,
|
|
428
|
+
FieldFullName,
|
|
429
|
+
FieldAge,
|
|
430
|
+
FieldStreetAddress,
|
|
431
|
+
FieldCity,
|
|
432
|
+
FieldState,
|
|
433
|
+
FieldZipCode,
|
|
434
|
+
FieldMessage,
|
|
435
|
+
FieldComments
|
|
436
|
+
} from '@algodomain/smart-forms/opinionated'
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Usage:**
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
<FieldEmail field="email" required />
|
|
443
|
+
<FieldPassword field="password" required />
|
|
444
|
+
<FieldPhone field="phone" />
|
|
445
|
+
<FieldFullName field="fullName" required />
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## ⚙️ Configuration Reference
|
|
451
|
+
|
|
452
|
+
### Form Component Props
|
|
453
|
+
|
|
454
|
+
All form components (`SmartForm`, `MultiTabSmartForm`, `BaseSmartForm`) support these props:
|
|
455
|
+
|
|
456
|
+
| Prop | Type | Default | Description |
|
|
457
|
+
|------|------|---------|-------------|
|
|
458
|
+
| `api` | `string` | - | API endpoint for form submission |
|
|
459
|
+
| `method` | `'POST' \| 'PUT' \| 'PATCH'` | `'POST'` | HTTP method |
|
|
460
|
+
| `submitButtonText` | `string` | `'Submit'` | Submit button text |
|
|
461
|
+
| `submitButtonIcon` | `ReactNode` | - | Icon for submit button |
|
|
462
|
+
| `allowSaveDraft` | `boolean` | `false` | Enable draft saving |
|
|
463
|
+
| `saveDraftApi` | `string` | - | API endpoint for saving drafts |
|
|
464
|
+
| `enableLocalStorage` | `boolean` | `false` | Save drafts to localStorage |
|
|
465
|
+
| `storageKey` | `string` | `'smart-form-data'` | Key for localStorage |
|
|
466
|
+
| `logFormData` | `boolean` | `false` | Log form data to console |
|
|
467
|
+
| `onSuccess` | `(data: unknown) => void` | - | Success callback |
|
|
468
|
+
| `onError` | `(error: unknown) => void` | - | Error callback |
|
|
469
|
+
| `transformData` | `(data: any) => any` | - | Transform data before submission |
|
|
470
|
+
| `className` | `string` | `'max-w-2xl mx-auto p-6 bg-white'` | Container CSS class |
|
|
471
|
+
| `title` | `string` | - | Form title |
|
|
472
|
+
| `subTitle` | `string` | - | Form subtitle |
|
|
473
|
+
| `logo` | `ReactNode` | - | Logo to display |
|
|
474
|
+
| `footer` | `ReactNode` | - | Footer content |
|
|
475
|
+
| `initialData` | `Record<string, unknown>` | `{}` | Initial form values |
|
|
476
|
+
| `showReset` | `boolean` | `false` | Show reset button |
|
|
477
|
+
| `showProgressBar` | `boolean` | `true` | Display progress bar (MultiTab only) |
|
|
478
|
+
| `showTabNumbers` | `boolean` | `true` | Show tab numbers (MultiTab only) |
|
|
479
|
+
| `authentication` | `AuthenticationConfig` | - | Authentication configuration |
|
|
480
|
+
| `includeQueryParams` | `boolean` | `false` | Include URL query parameters |
|
|
481
|
+
| `queryParamsToInclude` | `string[]` | - | Filter specific query params |
|
|
482
|
+
| `children` | `ReactNode` | - | Form content |
|
|
483
|
+
|
|
484
|
+
### Authentication Configuration
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
interface AuthenticationConfig {
|
|
488
|
+
enable: boolean // Enable authentication
|
|
489
|
+
refreshTokenEndpoint?: string // Token refresh endpoint
|
|
490
|
+
accessTokenKey?: string // localStorage key (default: 'accessToken')
|
|
491
|
+
refreshTokenKey?: string // localStorage key (default: 'refreshToken')
|
|
224
492
|
}
|
|
225
493
|
```
|
|
226
494
|
|
|
227
|
-
|
|
495
|
+
**Usage:**
|
|
228
496
|
|
|
229
|
-
|
|
497
|
+
```tsx
|
|
498
|
+
<SmartForm
|
|
499
|
+
authentication={{
|
|
500
|
+
enable: true,
|
|
501
|
+
refreshTokenEndpoint: "/api/auth/refresh",
|
|
502
|
+
accessTokenKey: "accessToken",
|
|
503
|
+
refreshTokenKey: "refreshToken"
|
|
504
|
+
}}
|
|
505
|
+
>
|
|
506
|
+
{/* Fields */}
|
|
507
|
+
</SmartForm>
|
|
508
|
+
```
|
|
230
509
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
510
|
+
### Common Field Props
|
|
511
|
+
|
|
512
|
+
All field components support these props:
|
|
513
|
+
|
|
514
|
+
| Prop | Type | Default | Description |
|
|
515
|
+
|------|------|---------|-------------|
|
|
516
|
+
| `field` | `string` | - | **Required.** Field identifier |
|
|
517
|
+
| `label` | `string` | - | Field label |
|
|
518
|
+
| `required` | `boolean` | `false` | Mark as required |
|
|
519
|
+
| `validation` | `ZodSchema` | - | Zod validation schema |
|
|
520
|
+
| `defaultValue` | `any` | - | Initial value |
|
|
521
|
+
| `placeholder` | `string` | - | Placeholder text |
|
|
522
|
+
| `className` | `string` | - | Custom CSS class |
|
|
523
|
+
| `info` | `string` | - | Info tooltip text |
|
|
524
|
+
| `subLabel` | `string` | - | Additional helper text |
|
|
525
|
+
|
|
526
|
+
### Field-Specific Props
|
|
527
|
+
|
|
528
|
+
#### SmartInput
|
|
529
|
+
|
|
530
|
+
| Prop | Type | Default | Allowed Values |
|
|
531
|
+
|------|------|---------|----------------|
|
|
532
|
+
| `type` | `string` | `'text'` | `text`, `email`, `password`, `tel`, `number`, `textarea` |
|
|
533
|
+
|
|
534
|
+
#### SmartSelect / SmartCombobox
|
|
535
|
+
|
|
536
|
+
| Prop | Type | Default | Description |
|
|
537
|
+
|------|------|---------|-------------|
|
|
538
|
+
| `options` | `Array<{value: string, label: string}>` | `[]` | Select options |
|
|
539
|
+
| `allowCustom` | `boolean` | `false` | Allow custom values (Combobox only) |
|
|
540
|
+
|
|
541
|
+
#### SmartRadioGroup
|
|
542
|
+
|
|
543
|
+
| Prop | Type | Default | Allowed Values |
|
|
544
|
+
|------|------|---------|----------------|
|
|
545
|
+
| `options` | `Array<{value: string, label: string}>` | `[]` | Radio options |
|
|
546
|
+
| `alignment` | `string` | `'vertical'` | `horizontal`, `vertical` |
|
|
547
|
+
|
|
548
|
+
#### SmartTags
|
|
549
|
+
|
|
550
|
+
| Prop | Type | Default | Description |
|
|
551
|
+
|------|------|---------|-------------|
|
|
552
|
+
| `maxTags` | `number` | - | Maximum number of tags |
|
|
553
|
+
| `maxLength` | `number` | - | Max length per tag |
|
|
554
|
+
| `minLength` | `number` | - | Min length per tag |
|
|
555
|
+
| `allowDuplicates` | `boolean` | `true` | Allow duplicate tags |
|
|
556
|
+
|
|
557
|
+
#### SmartSlider
|
|
558
|
+
|
|
559
|
+
| Prop | Type | Default | Description |
|
|
560
|
+
|------|------|---------|-------------|
|
|
561
|
+
| `min` | `number` | `0` | Minimum value |
|
|
562
|
+
| `max` | `number` | `100` | Maximum value |
|
|
563
|
+
| `step` | `number` | `1` | Step increment |
|
|
564
|
+
| `showValue` | `boolean` | `true` | Display current value |
|
|
565
|
+
| `valueFormatter` | `(value: number) => string` | - | Format displayed value |
|
|
566
|
+
|
|
567
|
+
#### SmartDualRangeSlider
|
|
568
|
+
|
|
569
|
+
| Prop | Type | Default | Description |
|
|
570
|
+
|------|------|---------|-------------|
|
|
571
|
+
| `minField` | `string` | - | **Required.** Field name for min value |
|
|
572
|
+
| `maxField` | `string` | - | **Required.** Field name for max value |
|
|
573
|
+
| `min` | `number` | `0` | Minimum value |
|
|
574
|
+
| `max` | `number` | `100` | Maximum value |
|
|
575
|
+
| `step` | `number` | `1` | Step increment |
|
|
576
|
+
| `showValues` | `boolean` | `true` | Display values |
|
|
577
|
+
| `valueFormatter` | `(value: number) => string` | - | Format displayed value |
|
|
578
|
+
|
|
579
|
+
#### SmartBasicRichTextbox
|
|
580
|
+
|
|
581
|
+
| Prop | Type | Default | Description |
|
|
582
|
+
|------|------|---------|-------------|
|
|
583
|
+
| `minHeight` | `string` | `'150px'` | Minimum height |
|
|
584
|
+
| `maxHeight` | `string` | `'400px'` | Maximum height |
|
|
585
|
+
|
|
586
|
+
#### SmartFileUpload
|
|
587
|
+
|
|
588
|
+
| Prop | Type | Default | Description |
|
|
589
|
+
|------|------|---------|-------------|
|
|
590
|
+
| `accept` | `string` | - | Accepted file types |
|
|
591
|
+
| `maxSize` | `number` | - | Max file size in bytes |
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## 🚀 Advanced Features
|
|
596
|
+
|
|
597
|
+
### Query Parameters
|
|
598
|
+
|
|
599
|
+
Automatically include URL query parameters in form submissions.
|
|
600
|
+
|
|
601
|
+
**Include ALL query parameters:**
|
|
602
|
+
|
|
603
|
+
```tsx
|
|
604
|
+
<SmartForm
|
|
605
|
+
api="/api/submit"
|
|
606
|
+
includeQueryParams={true}
|
|
607
|
+
>
|
|
608
|
+
<SmartInput field="name" label="Name" />
|
|
609
|
+
</SmartForm>
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
**Include SPECIFIC query parameters:**
|
|
613
|
+
|
|
614
|
+
```tsx
|
|
615
|
+
<SmartForm
|
|
616
|
+
api="/api/submit"
|
|
617
|
+
includeQueryParams={true}
|
|
618
|
+
queryParamsToInclude={['userId', 'companyId']}
|
|
619
|
+
>
|
|
620
|
+
<SmartInput field="name" label="Name" />
|
|
621
|
+
</SmartForm>
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
**Example:**
|
|
625
|
+
- URL: `/form?userId=123&companyId=456`
|
|
626
|
+
- Form data: `{ name: "John" }`
|
|
627
|
+
- Submitted: `{ userId: "123", companyId: "456", name: "John" }`
|
|
628
|
+
|
|
629
|
+
**Behavior:**
|
|
630
|
+
- Form field values always override query params if names conflict
|
|
631
|
+
- Works with both form submission and draft saving
|
|
632
|
+
- If `queryParamsToInclude` is omitted, all query params are included
|
|
633
|
+
|
|
634
|
+
### Draft Saving
|
|
635
|
+
|
|
636
|
+
**Local Storage:**
|
|
637
|
+
|
|
638
|
+
```tsx
|
|
639
|
+
<SmartForm
|
|
640
|
+
enableLocalStorage={true}
|
|
641
|
+
storageKey="my-form-draft"
|
|
642
|
+
allowSaveDraft={true}
|
|
643
|
+
>
|
|
644
|
+
{/* Fields */}
|
|
645
|
+
</SmartForm>
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
**API-based Draft:**
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
<SmartForm
|
|
652
|
+
allowSaveDraft={true}
|
|
653
|
+
saveDraftApi="/api/drafts"
|
|
654
|
+
>
|
|
655
|
+
{/* Fields */}
|
|
656
|
+
</SmartForm>
|
|
234
657
|
```
|
|
235
658
|
|
|
236
|
-
|
|
659
|
+
### Data Transformation
|
|
660
|
+
|
|
661
|
+
Transform form data before submission:
|
|
662
|
+
|
|
663
|
+
```tsx
|
|
664
|
+
<SmartForm
|
|
665
|
+
transformData={(data) => ({
|
|
666
|
+
...data,
|
|
667
|
+
skills: data.skills?.join(','),
|
|
668
|
+
timestamp: new Date().toISOString()
|
|
669
|
+
})}
|
|
670
|
+
>
|
|
671
|
+
{/* Fields */}
|
|
672
|
+
</SmartForm>
|
|
673
|
+
```
|
|
237
674
|
|
|
238
|
-
|
|
675
|
+
### Initial Values
|
|
239
676
|
|
|
240
|
-
|
|
677
|
+
Pre-populate form fields:
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
<SmartForm
|
|
681
|
+
initialData={{
|
|
682
|
+
name: 'John Doe',
|
|
683
|
+
email: 'john@example.com',
|
|
684
|
+
country: 'us'
|
|
685
|
+
}}
|
|
686
|
+
>
|
|
687
|
+
{/* Fields */}
|
|
688
|
+
</SmartForm>
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### Authentication
|
|
692
|
+
|
|
693
|
+
Enable automatic Bearer token authentication:
|
|
241
694
|
|
|
242
695
|
```tsx
|
|
243
696
|
<SmartForm
|
|
244
697
|
authentication={{
|
|
245
698
|
enable: true,
|
|
246
|
-
refreshTokenEndpoint: "/api/auth/refresh"
|
|
247
|
-
accessTokenKey: "accessToken", // Default
|
|
248
|
-
refreshTokenKey: "refreshToken" // Default
|
|
699
|
+
refreshTokenEndpoint: "/api/auth/refresh"
|
|
249
700
|
}}
|
|
250
|
-
|
|
701
|
+
>
|
|
702
|
+
{/* Fields */}
|
|
703
|
+
</SmartForm>
|
|
251
704
|
```
|
|
252
705
|
|
|
253
706
|
The library will:
|
|
254
|
-
1. Get
|
|
707
|
+
1. Get access token from localStorage
|
|
255
708
|
2. Include it as `Authorization: Bearer <token>`
|
|
256
|
-
3. Automatically refresh if
|
|
257
|
-
4. Retry the request with
|
|
709
|
+
3. Automatically refresh if token expires
|
|
710
|
+
4. Retry the request with new token
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## 🎨 Theming & Customization
|
|
715
|
+
|
|
716
|
+
### CSS Variables
|
|
717
|
+
|
|
718
|
+
Override the default theme by defining CSS variables:
|
|
719
|
+
|
|
720
|
+
```css
|
|
721
|
+
:root {
|
|
722
|
+
--radius: 0.5rem;
|
|
723
|
+
--background: white;
|
|
724
|
+
--foreground: black;
|
|
725
|
+
--primary: #3b82f6;
|
|
726
|
+
--primary-foreground: white;
|
|
727
|
+
--border: #e5e7eb;
|
|
728
|
+
--input: #e5e7eb;
|
|
729
|
+
--ring: #3b82f6;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.dark {
|
|
733
|
+
--background: #1f2937;
|
|
734
|
+
--foreground: white;
|
|
735
|
+
--primary: #60a5fa;
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### Tailwind Classes
|
|
740
|
+
|
|
741
|
+
Customize using Tailwind utility classes:
|
|
742
|
+
|
|
743
|
+
```tsx
|
|
744
|
+
<SmartForm className="max-w-4xl mx-auto p-8 bg-gray-50 rounded-xl shadow-lg">
|
|
745
|
+
<SmartInput
|
|
746
|
+
field="name"
|
|
747
|
+
label="Name"
|
|
748
|
+
className="border-blue-500 focus:ring-blue-500"
|
|
749
|
+
/>
|
|
750
|
+
</SmartForm>
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### Custom Submit Button
|
|
258
754
|
|
|
259
|
-
|
|
755
|
+
Use `BaseSmartForm` with custom buttons:
|
|
260
756
|
|
|
261
|
-
|
|
757
|
+
```tsx
|
|
758
|
+
import { BaseSmartForm, useSmartForm } from '@algodomain/smart-forms'
|
|
759
|
+
|
|
760
|
+
function CustomForm() {
|
|
761
|
+
return (
|
|
762
|
+
<BaseSmartForm api="/api/submit">
|
|
763
|
+
<SmartInput field="name" label="Name" />
|
|
764
|
+
<CustomSubmitButton />
|
|
765
|
+
</BaseSmartForm>
|
|
766
|
+
)
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function CustomSubmitButton() {
|
|
770
|
+
const { submitForm, isLoading } = useSmartForm()
|
|
771
|
+
|
|
772
|
+
return (
|
|
773
|
+
<button onClick={submitForm} disabled={isLoading}>
|
|
774
|
+
{isLoading ? 'Submitting...' : 'Submit'}
|
|
775
|
+
</button>
|
|
776
|
+
)
|
|
777
|
+
}
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
## 🪝 Hooks & Context
|
|
783
|
+
|
|
784
|
+
### useSmartForm
|
|
785
|
+
|
|
786
|
+
Access form context and methods.
|
|
262
787
|
|
|
263
788
|
```tsx
|
|
789
|
+
import { useSmartForm } from '@algodomain/smart-forms'
|
|
790
|
+
|
|
791
|
+
function MyComponent() {
|
|
792
|
+
const {
|
|
793
|
+
formData, // Current form values
|
|
794
|
+
errors, // Validation errors
|
|
795
|
+
isLoading, // Submission loading state
|
|
796
|
+
isDraftSaving, // Draft saving state
|
|
797
|
+
submitForm, // Submit function
|
|
798
|
+
saveDraft, // Save draft function
|
|
799
|
+
resetForm, // Reset to initial values
|
|
800
|
+
updateField, // Update specific field
|
|
801
|
+
config // Form configuration
|
|
802
|
+
} = useSmartForm()
|
|
803
|
+
|
|
804
|
+
return <button onClick={submitForm}>Submit</button>
|
|
805
|
+
}
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
### useFormField
|
|
809
|
+
|
|
810
|
+
Access individual field state (used internally by field components).
|
|
811
|
+
|
|
812
|
+
```tsx
|
|
813
|
+
import { useFormField } from '@algodomain/smart-forms'
|
|
814
|
+
|
|
815
|
+
function CustomField({ field }) {
|
|
816
|
+
const { value, error, onChange } = useFormField(field)
|
|
817
|
+
|
|
818
|
+
return (
|
|
819
|
+
<input
|
|
820
|
+
value={value || ''}
|
|
821
|
+
onChange={(e) => onChange(e.target.value)}
|
|
822
|
+
/>
|
|
823
|
+
)
|
|
824
|
+
}
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
---
|
|
828
|
+
|
|
829
|
+
## 💡 Examples
|
|
830
|
+
|
|
831
|
+
### Complete Registration Form
|
|
832
|
+
|
|
833
|
+
```tsx
|
|
834
|
+
import { SmartForm } from '@algodomain/smart-forms'
|
|
835
|
+
import { SmartInput, SmartSelect, SmartCheckbox, SmartDatePicker } from '@algodomain/smart-forms/fields'
|
|
836
|
+
import { FieldEmail, FieldPassword } from '@algodomain/smart-forms/opinionated'
|
|
264
837
|
import { z } from 'zod'
|
|
838
|
+
import { toast } from 'react-toastify'
|
|
265
839
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
840
|
+
export function RegistrationForm() {
|
|
841
|
+
return (
|
|
842
|
+
<SmartForm
|
|
843
|
+
api="https://api.example.com/register"
|
|
844
|
+
method="POST"
|
|
845
|
+
submitButtonText="Register"
|
|
846
|
+
onSuccess={(data) => {
|
|
847
|
+
toast.success('Account created successfully!')
|
|
848
|
+
}}
|
|
849
|
+
onError={(error) => {
|
|
850
|
+
toast.error('Registration failed.')
|
|
851
|
+
}}
|
|
852
|
+
>
|
|
853
|
+
<SmartInput
|
|
854
|
+
field="fullName"
|
|
855
|
+
label="Full Name"
|
|
856
|
+
validation={z.string().min(3)}
|
|
857
|
+
required
|
|
858
|
+
/>
|
|
859
|
+
|
|
860
|
+
<FieldEmail field="email" required />
|
|
861
|
+
<FieldPassword field="password" required />
|
|
862
|
+
|
|
863
|
+
<SmartSelect
|
|
864
|
+
field="country"
|
|
865
|
+
label="Country"
|
|
866
|
+
options={[
|
|
867
|
+
{ value: 'us', label: 'United States' },
|
|
868
|
+
{ value: 'ca', label: 'Canada' },
|
|
869
|
+
{ value: 'uk', label: 'United Kingdom' }
|
|
870
|
+
]}
|
|
871
|
+
required
|
|
872
|
+
/>
|
|
873
|
+
|
|
874
|
+
<SmartDatePicker
|
|
875
|
+
field="birthDate"
|
|
876
|
+
label="Date of Birth"
|
|
877
|
+
validation={z.date().max(new Date())}
|
|
878
|
+
required
|
|
879
|
+
/>
|
|
880
|
+
|
|
881
|
+
<SmartCheckbox
|
|
882
|
+
field="terms"
|
|
883
|
+
label="I agree to the Terms and Conditions"
|
|
884
|
+
validation={z.boolean().refine(val => val === true)}
|
|
885
|
+
required
|
|
886
|
+
/>
|
|
887
|
+
</SmartForm>
|
|
888
|
+
)
|
|
889
|
+
}
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### Multi-Tab Job Application
|
|
893
|
+
|
|
894
|
+
```tsx
|
|
895
|
+
import { MultiTabSmartForm, Tab } from '@algodomain/smart-forms'
|
|
896
|
+
import { SmartInput, SmartTags, SmartDualRangeSlider } from '@algodomain/smart-forms/fields'
|
|
897
|
+
import { FieldEmail, FieldPhone } from '@algodomain/smart-forms/opinionated'
|
|
898
|
+
import { z } from 'zod'
|
|
899
|
+
|
|
900
|
+
export function JobApplicationForm() {
|
|
901
|
+
return (
|
|
902
|
+
<MultiTabSmartForm
|
|
903
|
+
api="/api/applications"
|
|
904
|
+
method="POST"
|
|
905
|
+
showProgressBar={true}
|
|
906
|
+
showTabNumbers={true}
|
|
907
|
+
allowSaveDraft={true}
|
|
908
|
+
enableLocalStorage={true}
|
|
909
|
+
storageKey="job-application"
|
|
910
|
+
>
|
|
911
|
+
<Tab title="Personal Info">
|
|
912
|
+
<SmartInput
|
|
913
|
+
field="fullName"
|
|
914
|
+
label="Full Name"
|
|
915
|
+
validation={z.string().min(3)}
|
|
916
|
+
required
|
|
917
|
+
/>
|
|
918
|
+
<FieldEmail field="email" required />
|
|
919
|
+
<FieldPhone field="phone" required />
|
|
920
|
+
</Tab>
|
|
921
|
+
|
|
922
|
+
<Tab title="Experience">
|
|
923
|
+
<SmartDualRangeSlider
|
|
924
|
+
minField="minExperience"
|
|
925
|
+
maxField="maxExperience"
|
|
926
|
+
label="Years of Experience"
|
|
927
|
+
min={0}
|
|
928
|
+
max={40}
|
|
929
|
+
step={1}
|
|
930
|
+
/>
|
|
931
|
+
<SmartTags
|
|
932
|
+
field="skills"
|
|
933
|
+
label="Skills"
|
|
934
|
+
validation={z.array(z.string()).min(3)}
|
|
935
|
+
required
|
|
936
|
+
/>
|
|
937
|
+
</Tab>
|
|
938
|
+
</MultiTabSmartForm>
|
|
939
|
+
)
|
|
940
|
+
}
|
|
941
|
+
```
|
|
942
|
+
|
|
943
|
+
### Form with Query Parameters
|
|
944
|
+
|
|
945
|
+
```tsx
|
|
946
|
+
// URL: /create-job?userId=123&companyId=456
|
|
947
|
+
|
|
948
|
+
<SmartForm
|
|
949
|
+
api="/api/jobs"
|
|
950
|
+
includeQueryParams={true}
|
|
951
|
+
queryParamsToInclude={['userId', 'companyId']}
|
|
952
|
+
>
|
|
953
|
+
<SmartInput field="jobTitle" label="Job Title" required />
|
|
954
|
+
<SmartInput field="location" label="Location" required />
|
|
955
|
+
</SmartForm>
|
|
956
|
+
|
|
957
|
+
// Submitted data will include:
|
|
958
|
+
// { userId: "123", companyId: "456", jobTitle: "...", location: "..." }
|
|
276
959
|
```
|
|
277
960
|
|
|
278
|
-
|
|
961
|
+
---
|
|
962
|
+
|
|
963
|
+
## 🐛 Troubleshooting
|
|
964
|
+
|
|
965
|
+
### Error: "useSmartForm must be used within a SmartFormProvider"
|
|
966
|
+
|
|
967
|
+
**Cause:** Field components used outside a form wrapper.
|
|
968
|
+
|
|
969
|
+
**Solution:** Wrap fields in a form component:
|
|
970
|
+
|
|
971
|
+
```tsx
|
|
972
|
+
// ❌ Wrong
|
|
973
|
+
<SmartInput field="name" label="Name" />
|
|
974
|
+
|
|
975
|
+
// ✅ Correct
|
|
976
|
+
<SmartForm api="/api/submit">
|
|
977
|
+
<SmartInput field="name" label="Name" />
|
|
978
|
+
</SmartForm>
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
### Styles Not Loading
|
|
982
|
+
|
|
983
|
+
**Cause:** CSS not imported.
|
|
279
984
|
|
|
280
|
-
|
|
985
|
+
**Solution:**
|
|
281
986
|
|
|
282
987
|
```tsx
|
|
283
|
-
import
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
988
|
+
import '@algodomain/smart-forms/style.css'
|
|
989
|
+
import 'react-toastify/dist/ReactToastify.css'
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
For Tailwind v4, add `@source` directives:
|
|
993
|
+
|
|
994
|
+
```css
|
|
995
|
+
@source "../node_modules/@algodomain/smart-forms/dist/index.js";
|
|
288
996
|
```
|
|
289
997
|
|
|
290
|
-
|
|
998
|
+
### Form Not Submitting
|
|
999
|
+
|
|
1000
|
+
**Cause:** Missing API endpoint or validation errors.
|
|
1001
|
+
|
|
1002
|
+
**Solution:**
|
|
1003
|
+
|
|
1004
|
+
1. Ensure `api` prop is set
|
|
1005
|
+
2. Check console for validation errors
|
|
1006
|
+
3. Use `logFormData={true}`:
|
|
1007
|
+
|
|
1008
|
+
```tsx
|
|
1009
|
+
<SmartForm api="/api/submit" logFormData={true}>
|
|
1010
|
+
{/* Fields */}
|
|
1011
|
+
</SmartForm>
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
### TypeScript Errors
|
|
1015
|
+
|
|
1016
|
+
**Solution:** Install type definitions:
|
|
1017
|
+
|
|
1018
|
+
```bash
|
|
1019
|
+
npm install @types/react @types/react-dom
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
---
|
|
1023
|
+
|
|
1024
|
+
## 📖 Validation with Zod
|
|
1025
|
+
|
|
1026
|
+
All fields support Zod schemas for validation:
|
|
1027
|
+
|
|
1028
|
+
```tsx
|
|
1029
|
+
import { z } from 'zod'
|
|
1030
|
+
|
|
1031
|
+
// String validation
|
|
1032
|
+
validation={z.string().min(3, "Too short").max(50, "Too long")}
|
|
1033
|
+
|
|
1034
|
+
// Email
|
|
1035
|
+
validation={z.string().email("Invalid email")}
|
|
1036
|
+
|
|
1037
|
+
// Number
|
|
1038
|
+
validation={z.number().min(0).max(100)}
|
|
1039
|
+
|
|
1040
|
+
// Array
|
|
1041
|
+
validation={z.array(z.string()).min(1, "Required")}
|
|
1042
|
+
|
|
1043
|
+
// Date
|
|
1044
|
+
validation={z.date().max(new Date(), "Cannot be future")}
|
|
1045
|
+
|
|
1046
|
+
// Boolean
|
|
1047
|
+
validation={z.boolean().refine(val => val === true, {
|
|
1048
|
+
message: "Must be true"
|
|
1049
|
+
})}
|
|
1050
|
+
|
|
1051
|
+
// Enum
|
|
1052
|
+
validation={z.enum(['option1', 'option2'])}
|
|
1053
|
+
|
|
1054
|
+
// Custom
|
|
1055
|
+
validation={z.string().refine(val => val.includes('@'), {
|
|
1056
|
+
message: "Must contain @"
|
|
1057
|
+
})}
|
|
1058
|
+
```
|
|
291
1059
|
|
|
292
|
-
|
|
1060
|
+
---
|
|
293
1061
|
|
|
294
|
-
|
|
295
|
-
- Multi-step registration
|
|
296
|
-
- Job posting form
|
|
297
|
-
- User profile form
|
|
298
|
-
- Complex validation scenarios
|
|
1062
|
+
## 🤝 Contributing
|
|
299
1063
|
|
|
300
|
-
|
|
1064
|
+
Contributions welcome! Please visit our [GitHub repository](https://github.com/algodomain/smart-forms).
|
|
301
1065
|
|
|
302
|
-
|
|
1066
|
+
## 📄 License
|
|
303
1067
|
|
|
304
|
-
|
|
1068
|
+
MIT License - feel free to use in your projects!
|
|
305
1069
|
|
|
306
|
-
|
|
1070
|
+
## 🙋 Support
|
|
307
1071
|
|
|
308
|
-
|
|
1072
|
+
- **Issues:** [GitHub Issues](https://github.com/algodomain/smart-forms/issues)
|
|
1073
|
+
- **Email:** support@algodomain.com
|
|
1074
|
+
- **npm:** [@algodomain/smart-forms](https://www.npmjs.com/package/@algodomain/smart-forms)
|
|
309
1075
|
|
|
310
|
-
|
|
311
|
-
- GitHub Issues: [github.com/algodomain/smart-forms](https://github.com/algodomain/smart-forms)
|
|
312
|
-
- Documentation: [docs.algodomain.com](https://docs.algodomain.com)
|
|
1076
|
+
---
|
|
313
1077
|
|
|
1078
|
+
**Built with ❤️ by AlgoDomain**
|