@ttoss/forms 0.32.0 → 0.32.2
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 +408 -220
- package/dist/Brazil/index.d.ts +10 -35
- package/dist/FormFieldPatternFormat-CxkCeniP.d.ts +39 -0
- package/dist/esm/Brazil/index.js +32 -14
- package/dist/esm/MultistepForm/index.js +2 -1
- package/dist/esm/chunk-WZLEU3SB.js +812 -0
- package/dist/esm/chunk-X42ZUF2A.js +360 -0
- package/dist/esm/index.js +2 -1
- package/dist/index.d.ts +47 -109
- package/package.json +17 -17
- package/dist/FormFieldPatternFormat-3gBOUVd9.d.ts +0 -20
- package/dist/esm/chunk-7OXUGQSF.js +0 -983
package/README.md
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
# @ttoss/forms
|
|
2
2
|
|
|
3
|
-
**@ttoss/forms**
|
|
4
|
-
|
|
5
|
-
## ESM Only
|
|
6
|
-
|
|
7
|
-
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
|
|
3
|
+
**@ttoss/forms** provides React form components built on [React Hook Form](https://react-hook-form.com/) and [Yup](https://github.com/jquense/yup), with integrated i18n support and theme styling.
|
|
8
4
|
|
|
9
5
|
## Installation
|
|
10
6
|
|
|
@@ -13,13 +9,20 @@ pnpm i @ttoss/forms @ttoss/react-i18n @ttoss/ui @emotion/react
|
|
|
13
9
|
pnpm i --save-dev @ttoss/i18n-cli
|
|
14
10
|
```
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
**Note:** This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). I18n configuration is required—see [@ttoss/react-i18n](https://ttoss.dev/docs/modules/packages/react-i18n/) for setup details.
|
|
17
13
|
|
|
18
|
-
##
|
|
14
|
+
## Quick Start
|
|
19
15
|
|
|
20
16
|
```tsx
|
|
21
17
|
import { Button } from '@ttoss/ui';
|
|
22
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
Form,
|
|
20
|
+
FormFieldCheckbox,
|
|
21
|
+
FormFieldInput,
|
|
22
|
+
useForm,
|
|
23
|
+
yup,
|
|
24
|
+
yupResolver,
|
|
25
|
+
} from '@ttoss/forms';
|
|
23
26
|
import { I18nProvider } from '@ttoss/react-i18n';
|
|
24
27
|
|
|
25
28
|
const schema = yup.object({
|
|
@@ -34,12 +37,16 @@ export const FormComponent = () => {
|
|
|
34
37
|
resolver: yupResolver(schema),
|
|
35
38
|
});
|
|
36
39
|
|
|
40
|
+
const onSubmit = (data) => {
|
|
41
|
+
console.log(data);
|
|
42
|
+
};
|
|
43
|
+
|
|
37
44
|
return (
|
|
38
45
|
<I18nProvider>
|
|
39
|
-
<Form {...formMethods} onSubmit={
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
<
|
|
46
|
+
<Form {...formMethods} onSubmit={onSubmit}>
|
|
47
|
+
<FormFieldInput name="firstName" label="First Name" />
|
|
48
|
+
<FormFieldInput name="age" label="Age" type="number" />
|
|
49
|
+
<FormFieldCheckbox name="receiveEmails" label="Receive Emails" />
|
|
43
50
|
<Button type="submit">Submit</Button>
|
|
44
51
|
</Form>
|
|
45
52
|
</I18nProvider>
|
|
@@ -47,240 +54,434 @@ export const FormComponent = () => {
|
|
|
47
54
|
};
|
|
48
55
|
```
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
## React Hook Form Integration
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
It exposes all the API from react-hook-form, so you can use all the methods and properties from it. Check the [React Hook Form](https://react-hook-form.com/docs) documentation for more details.
|
|
59
|
+
All React Hook Form APIs are re-exported from `@ttoss/forms`, including hooks like `useForm`, `useController`, `useFieldArray`, and `useFormContext`. See the [React Hook Form documentation](https://react-hook-form.com/docs) for complete API details.
|
|
55
60
|
|
|
56
61
|
## Yup Validation
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
Import `yup` and `yupResolver` directly from `@ttoss/forms`:
|
|
59
64
|
|
|
60
65
|
```tsx
|
|
61
|
-
|
|
62
|
-
const schema = yup.object({
|
|
63
|
-
firstName: yup.string().required(),
|
|
64
|
-
});
|
|
66
|
+
import { Form, FormFieldInput, useForm, yup, yupResolver } from '@ttoss/forms';
|
|
65
67
|
|
|
68
|
+
const schema = yup.object({
|
|
69
|
+
firstName: yup.string().required(),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const MyForm = () => {
|
|
66
73
|
const formMethods = useForm({
|
|
67
74
|
resolver: yupResolver(schema),
|
|
68
75
|
});
|
|
69
76
|
|
|
70
77
|
return (
|
|
71
|
-
<Form {...formMethods} onSubmit={
|
|
72
|
-
<
|
|
73
|
-
name="firstName"
|
|
74
|
-
label="First Name"
|
|
75
|
-
defaultValue={''}
|
|
76
|
-
render={({ field }) => {
|
|
77
|
-
return <Input {...field} />;
|
|
78
|
-
}}
|
|
79
|
-
/>
|
|
78
|
+
<Form {...formMethods} onSubmit={(data) => console.log(data)}>
|
|
79
|
+
<FormFieldInput name="firstName" label="First Name" defaultValue="" />
|
|
80
80
|
<Button type="submit">Submit</Button>
|
|
81
81
|
</Form>
|
|
82
82
|
);
|
|
83
83
|
};
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
### Validation Messages
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
Invalid fields display default error messages like "Field is required". Customize these messages via i18n configuration—see [React-i18n](https://ttoss.dev/docs/modules/packages/react-i18n/) and [i18n-CLI](https://ttoss.dev/docs/modules/packages/i18n-cli/).
|
|
89
89
|
|
|
90
|
-
### Custom Error
|
|
90
|
+
### Custom Error Messages
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
Provide custom error messages using i18n patterns:
|
|
93
93
|
|
|
94
94
|
```tsx
|
|
95
|
-
|
|
95
|
+
import { useI18n } from '@ttoss/react-i18n';
|
|
96
|
+
import { useMemo } from 'react';
|
|
97
|
+
|
|
98
|
+
const MyForm = () => {
|
|
96
99
|
const {
|
|
97
100
|
intl: { formatMessage },
|
|
98
101
|
} = useI18n();
|
|
99
102
|
|
|
100
|
-
const schema = useMemo(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
103
|
+
const schema = useMemo(
|
|
104
|
+
() =>
|
|
105
|
+
yup.object({
|
|
106
|
+
name: yup.string().required(
|
|
107
|
+
formatMessage({
|
|
108
|
+
defaultMessage: 'Name must not be null',
|
|
109
|
+
description: 'Name required constraint',
|
|
110
|
+
})
|
|
111
|
+
),
|
|
112
|
+
age: yup.number().min(
|
|
113
|
+
18,
|
|
114
|
+
formatMessage(
|
|
115
|
+
{
|
|
116
|
+
defaultMessage: 'You must be {age} years old or more',
|
|
117
|
+
description: 'Min age constraint message',
|
|
118
|
+
},
|
|
119
|
+
{ age: 18 }
|
|
120
|
+
)
|
|
121
|
+
),
|
|
122
|
+
}),
|
|
123
|
+
[formatMessage]
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// ... rest of form implementation
|
|
122
127
|
};
|
|
123
128
|
```
|
|
124
129
|
|
|
125
|
-
##
|
|
130
|
+
## Validation Approaches
|
|
126
131
|
|
|
127
|
-
|
|
132
|
+
There are two ways to validate form fields in `@ttoss/forms`: schema-based validation using Yup schemas with `yupResolver`, and field-level validation using the `rules` prop on individual form fields.
|
|
133
|
+
|
|
134
|
+
**IMPORTANT:** You cannot mix both validation methods for the same field—choose either schema-based or field-level validation per field.
|
|
135
|
+
|
|
136
|
+
**When to use schema validation:**
|
|
137
|
+
|
|
138
|
+
- Cross-field validation
|
|
139
|
+
- Complex business logic
|
|
140
|
+
- Reusable validation patterns
|
|
141
|
+
- Type-safe validation with TypeScript
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
**When to use `rules`:**
|
|
130
144
|
|
|
131
|
-
|
|
145
|
+
- Simple, field-specific validations
|
|
146
|
+
- Dynamic validation based on component state
|
|
147
|
+
- Quick prototyping
|
|
148
|
+
- Single-field conditional logic
|
|
149
|
+
|
|
150
|
+
### 1. Schema-based Validation (Recommended)
|
|
151
|
+
|
|
152
|
+
Use Yup schemas with `yupResolver` for complex validation logic:
|
|
132
153
|
|
|
133
154
|
```tsx
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
155
|
+
const schema = yup.object({
|
|
156
|
+
email: yup.string().email().required(),
|
|
157
|
+
age: yup.number().min(18).max(100).required(),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const formMethods = useForm({
|
|
161
|
+
resolver: yupResolver(schema),
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Advantages:**
|
|
166
|
+
|
|
167
|
+
- Centralized validation logic
|
|
168
|
+
- Type-safe with TypeScript
|
|
169
|
+
- Reusable schemas
|
|
170
|
+
- Complex validation patterns
|
|
171
|
+
- Schema composition
|
|
172
|
+
|
|
173
|
+
### 2. Field-level Validation
|
|
174
|
+
|
|
175
|
+
Use the `rules` prop on individual form fields for simpler validations:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
<FormFieldInput
|
|
179
|
+
name="username"
|
|
180
|
+
label="Username"
|
|
181
|
+
rules={{
|
|
182
|
+
required: 'Username is required',
|
|
183
|
+
minLength: {
|
|
184
|
+
value: 3,
|
|
185
|
+
message: 'Username must be at least 3 characters',
|
|
186
|
+
},
|
|
187
|
+
pattern: {
|
|
188
|
+
value: /^[a-zA-Z0-9_]+$/,
|
|
189
|
+
message: 'Only letters, numbers, and underscores allowed',
|
|
190
|
+
},
|
|
191
|
+
}}
|
|
192
|
+
/>
|
|
193
|
+
|
|
194
|
+
<FormFieldInput
|
|
195
|
+
name="email"
|
|
196
|
+
label="Email"
|
|
197
|
+
rules={{
|
|
198
|
+
required: 'Email is required',
|
|
199
|
+
validate: (value) => {
|
|
200
|
+
return value.includes('@') || 'Invalid email format';
|
|
201
|
+
},
|
|
202
|
+
}}
|
|
203
|
+
/>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Available validation rules:**
|
|
207
|
+
|
|
208
|
+
- `required`: Field is required (string message or boolean)
|
|
209
|
+
- `min`: Minimum value (for numbers)
|
|
210
|
+
- `max`: Maximum value (for numbers)
|
|
211
|
+
- `minLength`: Minimum string length
|
|
212
|
+
- `maxLength`: Maximum string length
|
|
213
|
+
- `pattern`: RegExp pattern
|
|
214
|
+
- `validate`: Custom validation function or object of functions
|
|
215
|
+
|
|
216
|
+
## Form Field Components
|
|
217
|
+
|
|
218
|
+
All form field components share common props:
|
|
219
|
+
|
|
220
|
+
- `name` (required): Field name in the form
|
|
221
|
+
- `label`: Field label text
|
|
222
|
+
- `disabled`: Disables the field
|
|
223
|
+
- `defaultValue`: Initial field value
|
|
224
|
+
- `tooltip`: Label tooltip configuration
|
|
225
|
+
- `inputTooltip`: Input field tooltip configuration
|
|
226
|
+
- `warning`: Warning message displayed below the field
|
|
227
|
+
- `sx`: Theme-UI styling object
|
|
228
|
+
|
|
229
|
+
### FormFieldInput
|
|
230
|
+
|
|
231
|
+
Text input field supporting all HTML input types.
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
<FormFieldInput
|
|
235
|
+
name="email"
|
|
236
|
+
label="Email"
|
|
237
|
+
type="email"
|
|
238
|
+
placeholder="Enter your email"
|
|
239
|
+
/>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### FormFieldPassword
|
|
243
|
+
|
|
244
|
+
Password input with show/hide toggle.
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
<FormFieldPassword name="password" label="Password" />
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### FormFieldTextarea
|
|
251
|
+
|
|
252
|
+
Multi-line text input.
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
<FormFieldTextarea name="description" label="Description" rows={4} />
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### FormFieldCheckbox
|
|
259
|
+
|
|
260
|
+
Single checkbox or checkbox group.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
<FormFieldCheckbox name="terms" label="I accept the terms" />
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### FormFieldSwitch
|
|
267
|
+
|
|
268
|
+
Toggle switch component.
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
<FormFieldSwitch name="notifications" label="Enable notifications" />
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### FormFieldRadio
|
|
275
|
+
|
|
276
|
+
Radio button group.
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
const options = [
|
|
280
|
+
{ value: 'option1', label: 'Option 1' },
|
|
281
|
+
{ value: 'option2', label: 'Option 2' },
|
|
138
282
|
];
|
|
139
283
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const formMethods = useForm();
|
|
284
|
+
<FormFieldRadio name="choice" label="Choose one" options={options} />;
|
|
285
|
+
```
|
|
143
286
|
|
|
144
|
-
|
|
145
|
-
<Form {...formMethods} onSubmit={onSubmit}>
|
|
146
|
-
<FormFieldSelect name="car" label="Cars" options={RADIO_OPTIONS} />
|
|
147
|
-
<Button type="submit">Submit</Button>
|
|
148
|
-
</Form>
|
|
149
|
-
);
|
|
150
|
-
};
|
|
287
|
+
### FormFieldRadioCard
|
|
151
288
|
|
|
152
|
-
|
|
153
|
-
const RenderForm = () => {
|
|
154
|
-
const formMethods = useForm();
|
|
289
|
+
Radio buttons styled as cards.
|
|
155
290
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
<FormFieldSelect
|
|
159
|
-
name="car"
|
|
160
|
-
label="Cars"
|
|
161
|
-
options={RADIO_OPTIONS}
|
|
162
|
-
defaultValue="Mercedes"
|
|
163
|
-
/>
|
|
164
|
-
<Button type="submit">Submit</Button>
|
|
165
|
-
</Form>
|
|
166
|
-
);
|
|
167
|
-
};
|
|
291
|
+
```tsx
|
|
292
|
+
<FormFieldRadioCard name="plan" label="Select Plan" options={options} />
|
|
168
293
|
```
|
|
169
294
|
|
|
170
|
-
|
|
295
|
+
### FormFieldRadioCardIcony
|
|
296
|
+
|
|
297
|
+
Radio cards with icon support.
|
|
171
298
|
|
|
172
299
|
```tsx
|
|
173
|
-
const
|
|
174
|
-
|
|
300
|
+
const options = [
|
|
301
|
+
{ value: 'card', label: 'Credit Card', icon: 'credit-card' },
|
|
302
|
+
{ value: 'bank', label: 'Bank Transfer', icon: 'bank' },
|
|
303
|
+
];
|
|
175
304
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
label="Cars"
|
|
182
|
-
options={RADIO_OPTIONS}
|
|
183
|
-
placeholder="Select a car"
|
|
184
|
-
/>
|
|
185
|
-
<Button type="submit">Submit</Button>
|
|
186
|
-
</Form>
|
|
187
|
-
);
|
|
188
|
-
};
|
|
305
|
+
<FormFieldRadioCardIcony
|
|
306
|
+
name="payment"
|
|
307
|
+
label="Payment Method"
|
|
308
|
+
options={options}
|
|
309
|
+
/>;
|
|
189
310
|
```
|
|
190
311
|
|
|
191
|
-
|
|
312
|
+
### FormFieldSelect
|
|
313
|
+
|
|
314
|
+
Dropdown select field.
|
|
192
315
|
|
|
193
316
|
```tsx
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
placeholder="Select a car"
|
|
202
|
-
defaultValue="Ferrari"
|
|
203
|
-
/>
|
|
204
|
-
<Button type="submit">Submit</Button>
|
|
205
|
-
</Form>
|
|
206
|
-
);
|
|
317
|
+
const options = [
|
|
318
|
+
{ value: 'ferrari', label: 'Ferrari' },
|
|
319
|
+
{ value: 'mercedes', label: 'Mercedes' },
|
|
320
|
+
{ value: 'bmw', label: 'BMW' },
|
|
321
|
+
];
|
|
322
|
+
|
|
323
|
+
<FormFieldSelect name="car" label="Choose a car" options={options} />;
|
|
207
324
|
```
|
|
208
325
|
|
|
209
|
-
|
|
326
|
+
#### FormFieldSelect Default Values
|
|
327
|
+
|
|
328
|
+
`FormFieldSelect` defaults to the first option or a specified `defaultValue`:
|
|
210
329
|
|
|
211
330
|
```tsx
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
331
|
+
// Defaults to "Ferrari"
|
|
332
|
+
<FormFieldSelect name="car" label="Cars" options={options} />
|
|
333
|
+
|
|
334
|
+
// Defaults to "Mercedes"
|
|
335
|
+
<FormFieldSelect
|
|
336
|
+
name="car"
|
|
337
|
+
label="Cars"
|
|
338
|
+
options={options}
|
|
339
|
+
defaultValue="Mercedes"
|
|
340
|
+
/>
|
|
341
|
+
```
|
|
221
342
|
|
|
222
|
-
|
|
223
|
-
// some fetch operation here
|
|
343
|
+
When using a `placeholder`, an empty option is automatically added if not present:
|
|
224
344
|
|
|
225
|
-
|
|
345
|
+
```tsx
|
|
346
|
+
<FormFieldSelect
|
|
347
|
+
name="car"
|
|
348
|
+
label="Cars"
|
|
349
|
+
options={options}
|
|
350
|
+
placeholder="Select a car"
|
|
351
|
+
/>
|
|
352
|
+
```
|
|
226
353
|
|
|
227
|
-
|
|
228
|
-
resetField('car', { defaultValue: 'Ferrari' });
|
|
229
|
-
}, []);
|
|
354
|
+
**Note:** `placeholder` and `defaultValue` cannot be used together.
|
|
230
355
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
356
|
+
For dynamic options from async data, reset the field after loading:
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
const { resetField } = useForm();
|
|
360
|
+
const [options, setOptions] = useState([]);
|
|
361
|
+
|
|
362
|
+
useEffect(() => {
|
|
363
|
+
// Fetch options
|
|
364
|
+
const fetchedOptions = await fetchData();
|
|
365
|
+
setOptions(fetchedOptions);
|
|
366
|
+
resetField('car', { defaultValue: 'Ferrari' });
|
|
367
|
+
}, []);
|
|
238
368
|
```
|
|
239
369
|
|
|
240
|
-
###
|
|
370
|
+
### FormFieldNumericFormat
|
|
241
371
|
|
|
242
|
-
|
|
372
|
+
Numeric input with formatting support (decimals, thousands separators).
|
|
243
373
|
|
|
244
374
|
```tsx
|
|
245
|
-
|
|
246
|
-
|
|
375
|
+
<FormFieldNumericFormat
|
|
376
|
+
name="price"
|
|
377
|
+
label="Price"
|
|
378
|
+
thousandSeparator=","
|
|
379
|
+
decimalScale={2}
|
|
380
|
+
/>
|
|
381
|
+
```
|
|
247
382
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
383
|
+
### FormFieldCurrencyInput
|
|
384
|
+
|
|
385
|
+
Currency input with locale-based formatting.
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
<FormFieldCurrencyInput
|
|
389
|
+
name="amount"
|
|
390
|
+
label="Amount"
|
|
391
|
+
prefix="$"
|
|
392
|
+
decimalsLimit={2}
|
|
393
|
+
/>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### FormFieldPatternFormat
|
|
397
|
+
|
|
398
|
+
Input with custom format patterns.
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
<FormFieldPatternFormat
|
|
402
|
+
name="phone"
|
|
403
|
+
label="Phone"
|
|
404
|
+
format="+1 (###) ###-####"
|
|
405
|
+
mask="_"
|
|
406
|
+
/>
|
|
262
407
|
```
|
|
263
408
|
|
|
264
|
-
|
|
409
|
+
### FormFieldCreditCardNumber
|
|
265
410
|
|
|
266
|
-
|
|
267
|
-
- `direction`: The direction of the group. It can be `row` or `column`.
|
|
268
|
-
- `name`: The name of the group. It is used to render the group error message.
|
|
411
|
+
Credit card input with automatic formatting.
|
|
269
412
|
|
|
270
|
-
|
|
413
|
+
```tsx
|
|
414
|
+
<FormFieldCreditCardNumber name="cardNumber" label="Card Number" />
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Brazil-Specific Fields
|
|
271
418
|
|
|
272
|
-
|
|
419
|
+
Import from `@ttoss/forms/brazil`:
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
import {
|
|
423
|
+
FormFieldCEP,
|
|
424
|
+
FormFieldCNPJ,
|
|
425
|
+
FormFieldPhone,
|
|
426
|
+
} from '@ttoss/forms/brazil';
|
|
427
|
+
```
|
|
273
428
|
|
|
274
|
-
|
|
429
|
+
#### FormFieldCEP
|
|
275
430
|
|
|
276
|
-
|
|
431
|
+
Brazilian postal code (CEP) input with automatic formatting.
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
<FormFieldCEP name="cep" label="CEP" />
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### FormFieldCNPJ
|
|
438
|
+
|
|
439
|
+
Brazilian tax ID (CNPJ) input with validation and formatting.
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
<FormFieldCNPJ name="cnpj" label="CNPJ" />
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
The package also exports `isCnpjValid(cnpj: string)` for standalone validation.
|
|
446
|
+
|
|
447
|
+
#### FormFieldPhone
|
|
448
|
+
|
|
449
|
+
Brazilian phone number input with formatting.
|
|
450
|
+
|
|
451
|
+
```tsx
|
|
452
|
+
<FormFieldPhone name="phone" label="Phone" />
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## FormGroup
|
|
456
|
+
|
|
457
|
+
Groups related fields with optional label and layout direction.
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
<FormGroup label="Personal Information" direction="row">
|
|
461
|
+
<FormFieldInput name="firstName" label="First Name" />
|
|
462
|
+
<FormFieldInput name="lastName" label="Last Name" />
|
|
463
|
+
</FormGroup>
|
|
464
|
+
|
|
465
|
+
<FormGroup label="Address">
|
|
466
|
+
<FormFieldInput name="street" label="Street" />
|
|
467
|
+
<FormFieldInput name="city" label="City" />
|
|
468
|
+
</FormGroup>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Props:**
|
|
472
|
+
|
|
473
|
+
- `label`: Group label
|
|
474
|
+
- `direction`: Layout direction (`'row'` | `'column'`)
|
|
475
|
+
- `name`: Group name for error messages
|
|
476
|
+
|
|
477
|
+
## Multistep Forms
|
|
478
|
+
|
|
479
|
+
Import from `@ttoss/forms/multistep-form`:
|
|
277
480
|
|
|
278
481
|
```tsx
|
|
279
|
-
import * as React from 'react';
|
|
280
|
-
import { FormFieldInput, yup } from '@ttoss/forms';
|
|
281
482
|
import { MultistepForm } from '@ttoss/forms/multistep-form';
|
|
483
|
+
import { FormFieldInput, yup } from '@ttoss/forms';
|
|
282
484
|
|
|
283
|
-
// Define your steps
|
|
284
485
|
const steps = [
|
|
285
486
|
{
|
|
286
487
|
label: 'Step 1',
|
|
@@ -294,83 +495,70 @@ const steps = [
|
|
|
294
495
|
label: 'Step 2',
|
|
295
496
|
question: 'How old are you?',
|
|
296
497
|
fields: <FormFieldInput type="number" name="age" label="Age" />,
|
|
297
|
-
defaultValues: {
|
|
298
|
-
age: 18,
|
|
299
|
-
},
|
|
498
|
+
defaultValues: { age: 18 },
|
|
300
499
|
schema: yup.object({
|
|
301
500
|
age: yup
|
|
302
501
|
.number()
|
|
303
|
-
.min(18, '
|
|
502
|
+
.min(18, 'Must be at least 18')
|
|
304
503
|
.required('Age is required'),
|
|
305
504
|
}),
|
|
306
505
|
},
|
|
307
|
-
// Add more steps as needed
|
|
308
506
|
];
|
|
309
507
|
|
|
310
|
-
const
|
|
508
|
+
const MyForm = () => {
|
|
311
509
|
return (
|
|
312
510
|
<MultistepForm
|
|
313
|
-
// ...other props
|
|
314
511
|
steps={steps}
|
|
315
|
-
// submit the full form on submit
|
|
316
512
|
onSubmit={(data) => console.log(data)}
|
|
513
|
+
footer="© 2024 Company"
|
|
514
|
+
header={{
|
|
515
|
+
variant: 'logo',
|
|
516
|
+
src: '/logo.png',
|
|
517
|
+
onClose: () => console.log('closed'),
|
|
518
|
+
}}
|
|
317
519
|
/>
|
|
318
520
|
);
|
|
319
521
|
};
|
|
320
522
|
```
|
|
321
523
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
The `MultistepForm` component accepts the following props:
|
|
325
|
-
|
|
326
|
-
- `steps`: An array of objects representing each step of the form.
|
|
327
|
-
- `onSubmit`: A function that is called when the form is completely filled and submitted.
|
|
328
|
-
- `footer`: An string with the text to show on form's footer.
|
|
329
|
-
- `header`: [Header Props](#header-props)
|
|
524
|
+
### MultistepForm Props
|
|
330
525
|
|
|
331
|
-
|
|
526
|
+
- `steps`: Array of step configurations
|
|
527
|
+
- `onSubmit`: Handler called with complete form data
|
|
528
|
+
- `footer`: Footer text
|
|
529
|
+
- `header`: Header configuration (see below)
|
|
332
530
|
|
|
333
|
-
|
|
334
|
-
- `question`: The question or instruction presented to the user at this step.
|
|
335
|
-
- `fields`: The form fields for this step.
|
|
336
|
-
- `schema`: A `yup` schema for validating the fields at this step.
|
|
337
|
-
- `defaultValues`: An optional object with default values to this step.
|
|
531
|
+
### Step Configuration
|
|
338
532
|
|
|
339
|
-
|
|
533
|
+
Each step object contains:
|
|
340
534
|
|
|
341
|
-
-
|
|
535
|
+
- `label`: Step label for navigation
|
|
536
|
+
- `question`: Question or instruction text
|
|
537
|
+
- `fields`: React element(s) containing form fields
|
|
538
|
+
- `schema`: Yup validation schema
|
|
539
|
+
- `defaultValues`: Optional default values for step fields
|
|
342
540
|
|
|
343
|
-
|
|
344
|
-
- `src`: The source URL for the logo image.
|
|
345
|
-
- `onClose`: A function to handle the close button click event.
|
|
541
|
+
### Header Types
|
|
346
542
|
|
|
347
|
-
|
|
348
|
-
- `variant`: Set to `'titled'`.
|
|
349
|
-
- `title`: The title text.
|
|
350
|
-
- `leftIcon` and `rightIcon`: Icon types for left and right icons.
|
|
351
|
-
- `onLeftIconClick` and `onRightIconClick`: Functions to handle clicks on left and right icons.
|
|
352
|
-
|
|
353
|
-
#### Customizing Headers
|
|
354
|
-
|
|
355
|
-
1. **Logo Header:**
|
|
543
|
+
**Logo Header:**
|
|
356
544
|
|
|
357
545
|
```tsx
|
|
358
|
-
|
|
546
|
+
{
|
|
359
547
|
variant: 'logo',
|
|
360
|
-
src: 'path
|
|
361
|
-
onClose: () => console.log('Close
|
|
362
|
-
}
|
|
548
|
+
src: '/path/to/logo.png',
|
|
549
|
+
onClose: () => console.log('Close clicked')
|
|
550
|
+
}
|
|
363
551
|
```
|
|
364
552
|
|
|
365
|
-
|
|
553
|
+
**Titled Header:**
|
|
366
554
|
|
|
367
555
|
```tsx
|
|
368
|
-
|
|
556
|
+
{
|
|
369
557
|
variant: 'titled',
|
|
370
|
-
title: '
|
|
371
|
-
leftIcon: '
|
|
372
|
-
rightIcon: '
|
|
373
|
-
onLeftIconClick: () => console.log('
|
|
374
|
-
onRightIconClick: () => console.log('
|
|
375
|
-
}
|
|
558
|
+
title: 'Form Title',
|
|
559
|
+
leftIcon: 'arrow-left',
|
|
560
|
+
rightIcon: 'close',
|
|
561
|
+
onLeftIconClick: () => console.log('Back'),
|
|
562
|
+
onRightIconClick: () => console.log('Close')
|
|
563
|
+
}
|
|
376
564
|
```
|