@ttoss/forms 0.43.0 → 0.43.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 +64 -608
- package/dist/Brazil/index.d.ts +2 -2
- package/dist/{FormFieldPhone-BKeOS0i6.d.ts → FormFieldPhone-Dp3kaJbz.d.ts} +44 -14
- package/dist/esm/Brazil/index.js +2 -2
- package/dist/esm/MultistepForm/index.js +2 -2
- package/dist/esm/{chunk-ZORKZWD7.js → chunk-NEIQETLB.js} +86 -11
- package/dist/esm/{chunk-4YLT3VPV.js → chunk-UT6OKRDR.js} +2 -55
- package/dist/esm/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -39,13 +39,9 @@ export const FormComponent = () => {
|
|
|
39
39
|
resolver: zodResolver(schema),
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
const onSubmit = (data) => {
|
|
43
|
-
console.log(data);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
42
|
return (
|
|
47
43
|
<I18nProvider>
|
|
48
|
-
<Form {...formMethods} onSubmit={
|
|
44
|
+
<Form {...formMethods} onSubmit={(data) => console.log(data)}>
|
|
49
45
|
<FormFieldInput name="firstName" label="First Name" />
|
|
50
46
|
<FormFieldInput name="age" label="Age" type="number" />
|
|
51
47
|
<FormFieldCheckbox name="receiveEmails" label="Receive Emails" />
|
|
@@ -56,169 +52,40 @@ export const FormComponent = () => {
|
|
|
56
52
|
};
|
|
57
53
|
```
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
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
|
+
All React Hook Form APIs (`useForm`, `useController`, `useFieldArray`, `useFormContext`, etc.) are re-exported from `@ttoss/forms`. See the [React Hook Form documentation](https://react-hook-form.com/docs) for details.
|
|
62
56
|
|
|
63
57
|
## Zod Validation (Recommended)
|
|
64
58
|
|
|
65
|
-
Import `z` and `zodResolver` directly from `@ttoss/forms` for
|
|
66
|
-
|
|
67
|
-
```tsx
|
|
68
|
-
import { Form, FormFieldInput, useForm, z, zodResolver } from '@ttoss/forms';
|
|
69
|
-
|
|
70
|
-
const schema = z.object({
|
|
71
|
-
firstName: z.string().min(1, 'First name is required'),
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const MyForm = () => {
|
|
75
|
-
const formMethods = useForm({
|
|
76
|
-
resolver: zodResolver(schema),
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<Form {...formMethods} onSubmit={(data) => console.log(data)}>
|
|
81
|
-
<FormFieldInput name="firstName" label="First Name" defaultValue="" />
|
|
82
|
-
<Button type="submit">Submit</Button>
|
|
83
|
-
</Form>
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Validation Messages
|
|
89
|
-
|
|
90
|
-
Invalid fields display default error messages like "Field is required". These messages are defined using i18n and can be customized for each locale.
|
|
91
|
-
|
|
92
|
-
#### Default Zod Messages
|
|
93
|
-
|
|
94
|
-
The package provides internationalized default messages for common Zod validation errors. These are automatically extracted when you run `pnpm run i18n`:
|
|
95
|
-
|
|
96
|
-
- **Required field**: `"Field is required"`
|
|
97
|
-
- **Type mismatch**: `"Invalid Value for Field of type {expected}"`
|
|
98
|
-
- **Minimum length**: `"Field must be at least {min} characters"`
|
|
99
|
-
|
|
100
|
-
To customize these messages for your locale, extract the i18n messages and translate them in your application's i18n files (e.g., `i18n/compiled/pt-BR.json`). See the [i18n-CLI documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/) for more details.
|
|
59
|
+
Import `z` and `zodResolver` directly from `@ttoss/forms`. Invalid fields display i18n-backed default messages (`"Field is required"`, `"Invalid Value for Field of type {expected}"`, `"Field must be at least {min} characters"`). Run `pnpm run i18n` to extract them and translate per locale in your app's i18n files. See the [i18n-CLI documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/) for details.
|
|
101
60
|
|
|
102
61
|
### Custom Validations
|
|
103
62
|
|
|
104
|
-
The package extends Zod with custom validation methods
|
|
105
|
-
|
|
106
|
-
#### CPF Validation
|
|
63
|
+
The package extends Zod with custom validation methods:
|
|
107
64
|
|
|
108
65
|
```tsx
|
|
109
|
-
import { z } from '@ttoss/forms';
|
|
66
|
+
import { z, passwordSchema } from '@ttoss/forms';
|
|
110
67
|
|
|
111
68
|
const schema = z.object({
|
|
112
|
-
cpf: z.string().cpf(), //
|
|
113
|
-
|
|
114
|
-
|
|
69
|
+
cpf: z.string().cpf(), // "Invalid CPF"
|
|
70
|
+
cnpj: z.string().cnpj('Invalid CNPJ'), // custom message
|
|
71
|
+
password: passwordSchema({ required: true }), // min 8 chars
|
|
72
|
+
optionalPassword: passwordSchema(), // empty or min 8 chars
|
|
115
73
|
});
|
|
116
74
|
```
|
|
117
75
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
````
|
|
121
|
-
|
|
122
|
-
```tsx
|
|
123
|
-
import { z } from '@ttoss/forms';
|
|
124
|
-
|
|
125
|
-
const schema = z.object({
|
|
126
|
-
cnpj: z.string().cnpj(), // Uses default message: "Invalid CNPJ"
|
|
127
|
-
// Or with custom message:
|
|
128
|
-
cnpjCustom: z.string().cnpj('CNPJ inválido'),
|
|
129
|
-
});
|
|
130
|
-
````
|
|
131
|
-
|
|
132
|
-
#### Password Validation
|
|
133
|
-
|
|
134
|
-
```tsx
|
|
135
|
-
import { passwordSchema } from '@ttoss/forms';
|
|
136
|
-
import { z } from '@ttoss/forms';
|
|
137
|
-
|
|
138
|
-
const schema = z.object({
|
|
139
|
-
// Required password (minimum 8 characters)
|
|
140
|
-
password: passwordSchema({ required: true }),
|
|
141
|
-
|
|
142
|
-
// Optional password (accepts empty string or minimum 8 characters)
|
|
143
|
-
optionalPassword: passwordSchema(),
|
|
144
|
-
});
|
|
145
|
-
```
|
|
76
|
+
Also exports `isCnpjValid(cnpj: string)` for standalone validation.
|
|
146
77
|
|
|
147
78
|
## Yup Validation (Deprecated)
|
|
148
79
|
|
|
149
|
-
> **DEPRECATION WARNING:** Yup support
|
|
150
|
-
|
|
151
|
-
For legacy projects still using Yup, you can import `yup` and `yupResolver` from `@ttoss/forms`:
|
|
152
|
-
|
|
153
|
-
```tsx
|
|
154
|
-
import { Form, FormFieldInput, useForm, yup, yupResolver } from '@ttoss/forms';
|
|
155
|
-
|
|
156
|
-
const schema = yup.object({
|
|
157
|
-
firstName: yup.string().required(),
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
const MyForm = () => {
|
|
161
|
-
const formMethods = useForm({
|
|
162
|
-
resolver: yupResolver(schema),
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
return (
|
|
166
|
-
<Form {...formMethods} onSubmit={(data) => console.log(data)}>
|
|
167
|
-
<FormFieldInput name="firstName" label="First Name" />
|
|
168
|
-
<Button type="submit">Submit</Button>
|
|
169
|
-
</Form>
|
|
170
|
-
);
|
|
171
|
-
};
|
|
172
|
-
```
|
|
80
|
+
> **DEPRECATION WARNING:** Yup support will be removed in a future major version. `yup` and `yupResolver` are still exported from `@ttoss/forms` for legacy projects, but new projects should use Zod.
|
|
173
81
|
|
|
174
82
|
## Validation Approaches
|
|
175
83
|
|
|
176
|
-
There are two ways to validate form fields
|
|
177
|
-
|
|
178
|
-
**IMPORTANT:** You cannot mix both validation methods for the same field—choose either schema-based or field-level validation per field.
|
|
179
|
-
|
|
180
|
-
**When to use schema validation:**
|
|
181
|
-
|
|
182
|
-
- Cross-field validation
|
|
183
|
-
- Complex business logic
|
|
184
|
-
- Reusable validation patterns
|
|
185
|
-
- Type-safe validation with TypeScript
|
|
186
|
-
|
|
187
|
-
**When to use `rules`:**
|
|
188
|
-
|
|
189
|
-
- Simple, field-specific validations
|
|
190
|
-
- Dynamic validation based on component state
|
|
191
|
-
- Quick prototyping
|
|
192
|
-
- Single-field conditional logic
|
|
84
|
+
There are two ways to validate form fields — choose one per field, they cannot be mixed.
|
|
193
85
|
|
|
194
|
-
|
|
86
|
+
**Schema-based validation** (`zodResolver`) is recommended for cross-field validation, complex business logic, and reusable/type-safe schemas.
|
|
195
87
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
```tsx
|
|
199
|
-
import { z, zodResolver } from '@ttoss/forms';
|
|
200
|
-
|
|
201
|
-
const schema = z.object({
|
|
202
|
-
email: z.string().email(),
|
|
203
|
-
age: z.number().min(18).max(100),
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const formMethods = useForm({
|
|
207
|
-
resolver: zodResolver(schema),
|
|
208
|
-
});
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**Advantages:**
|
|
212
|
-
|
|
213
|
-
- Centralized validation logic
|
|
214
|
-
- Type-safe with TypeScript
|
|
215
|
-
- Reusable schemas
|
|
216
|
-
- Complex validation patterns
|
|
217
|
-
- Schema composition
|
|
218
|
-
|
|
219
|
-
### 2. Field-level Validation
|
|
220
|
-
|
|
221
|
-
Use the `rules` prop on individual form fields for simpler validations:
|
|
88
|
+
**Field-level validation** (`rules` prop) suits simple, field-specific cases:
|
|
222
89
|
|
|
223
90
|
```tsx
|
|
224
91
|
<FormFieldInput
|
|
@@ -226,358 +93,78 @@ Use the `rules` prop on individual form fields for simpler validations:
|
|
|
226
93
|
label="Username"
|
|
227
94
|
rules={{
|
|
228
95
|
required: 'Username is required',
|
|
229
|
-
minLength: {
|
|
230
|
-
value: 3,
|
|
231
|
-
message: 'Username must be at least 3 characters',
|
|
232
|
-
},
|
|
96
|
+
minLength: { value: 3, message: 'Min 3 characters' },
|
|
233
97
|
pattern: {
|
|
234
98
|
value: /^[a-zA-Z0-9_]+$/,
|
|
235
|
-
message: '
|
|
236
|
-
},
|
|
237
|
-
}}
|
|
238
|
-
/>
|
|
239
|
-
|
|
240
|
-
<FormFieldInput
|
|
241
|
-
name="email"
|
|
242
|
-
label="Email"
|
|
243
|
-
rules={{
|
|
244
|
-
required: 'Email is required',
|
|
245
|
-
validate: (value) => {
|
|
246
|
-
return value.includes('@') || 'Invalid email format';
|
|
99
|
+
message: 'Letters, numbers, underscores only',
|
|
247
100
|
},
|
|
248
101
|
}}
|
|
249
102
|
/>
|
|
250
103
|
```
|
|
251
104
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
- `required`: Field is required (string message or boolean)
|
|
255
|
-
- `min`: Minimum value (for numbers)
|
|
256
|
-
- `max`: Maximum value (for numbers)
|
|
257
|
-
- `minLength`: Minimum string length
|
|
258
|
-
- `maxLength`: Maximum string length
|
|
259
|
-
- `pattern`: RegExp pattern
|
|
260
|
-
- `validate`: Custom validation function or object of functions
|
|
105
|
+
Available `rules` keys: `required`, `min`, `max`, `minLength`, `maxLength`, `pattern`, `validate`.
|
|
261
106
|
|
|
262
107
|
## Form Field Components
|
|
263
108
|
|
|
264
|
-
|
|
109
|
+
> **Interactive examples for every component are available at [storybook.ttoss.dev](https://storybook.ttoss.dev/) under the Forms section.**
|
|
110
|
+
|
|
111
|
+
All form field components share these common props:
|
|
265
112
|
|
|
266
113
|
- `name` (required): Field name in the form
|
|
267
114
|
- `label`: Field label text
|
|
268
|
-
- `disabled`: Disables the field
|
|
115
|
+
- `disabled`: Disables the field (field-level overrides form-level `disabled`)
|
|
269
116
|
- `defaultValue`: Initial field value
|
|
270
117
|
- `tooltip`: Label tooltip configuration
|
|
271
118
|
- `warning`: Warning message displayed below the field
|
|
272
|
-
- `auxiliaryCheckbox`: Optional
|
|
119
|
+
- `auxiliaryCheckbox`: Optional checkbox rendered between the field and error message — useful for confirmation or terms acceptance. Props: `name`, `label`, `disabled`, `defaultValue`.
|
|
273
120
|
- `sx`: Theme-UI styling object
|
|
274
121
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
You can disable form fields in two ways:
|
|
278
|
-
|
|
279
|
-
**1. Disable the entire form:**
|
|
280
|
-
|
|
281
|
-
Set `disabled: true` in `useForm` to disable all fields at once:
|
|
122
|
+
To disable all fields at once, pass `disabled` to `useForm`:
|
|
282
123
|
|
|
283
124
|
```tsx
|
|
284
|
-
const formMethods = useForm({
|
|
285
|
-
disabled: true, // Disables all fields
|
|
286
|
-
});
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
This is particularly useful for preventing user interaction during asynchronous operations:
|
|
290
|
-
|
|
291
|
-
```tsx
|
|
292
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
293
|
-
|
|
294
|
-
const formMethods = useForm({
|
|
295
|
-
disabled: isSubmitting, // Disable form during submission
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const onSubmit = async (data) => {
|
|
299
|
-
setIsSubmitting(true);
|
|
300
|
-
await saveData(data);
|
|
301
|
-
setIsSubmitting(false);
|
|
302
|
-
};
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
**2. Disable individual fields:**
|
|
306
|
-
|
|
307
|
-
Use the `disabled` prop on specific form field components:
|
|
308
|
-
|
|
309
|
-
```tsx
|
|
310
|
-
<FormFieldInput name="email" label="Email" disabled />
|
|
125
|
+
const formMethods = useForm({ disabled: isSubmitting });
|
|
311
126
|
```
|
|
312
127
|
|
|
313
|
-
|
|
128
|
+
### Available Components
|
|
314
129
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
130
|
+
| Component | Description |
|
|
131
|
+
| --------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `FormFieldInput` | Text input — supports all HTML input types |
|
|
133
|
+
| `FormFieldPassword` | Password input with show/hide toggle |
|
|
134
|
+
| `FormFieldTextarea` | Multi-line text input |
|
|
135
|
+
| `FormFieldCheckbox` | Single checkbox |
|
|
136
|
+
| `FormFieldSwitch` | Toggle switch |
|
|
137
|
+
| `FormFieldRadio` | Radio button group |
|
|
138
|
+
| `FormFieldRadioCard` | Radio buttons styled as cards |
|
|
139
|
+
| `FormFieldRadioCardIcony` | Radio cards with icon support |
|
|
140
|
+
| `FormFieldSelect` | Dropdown — defaults to first option; `placeholder` and `defaultValue` cannot be used together |
|
|
141
|
+
| `FormFieldSegmentedControl` | Segmented buttons wrapping `SegmentedControl` from `@ttoss/ui`; `variant` defaults to `"secondary"` |
|
|
142
|
+
| `FormFieldNumericFormat` | Numeric input with decimals/thousands formatting |
|
|
143
|
+
| `FormFieldCurrencyInput` | Currency input with locale-based separators (see below) |
|
|
144
|
+
| `FormFieldPatternFormat` | Input with custom format patterns |
|
|
145
|
+
| `FormFieldPhone` | Phone input with optional country-code dropdown (see below) |
|
|
146
|
+
| `FormFieldCreditCardNumber` | Credit card input with automatic formatting |
|
|
319
147
|
|
|
320
|
-
|
|
321
|
-
<FormFieldInput name="id" label="ID" disabled />;
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Auxiliary Checkbox
|
|
325
|
-
|
|
326
|
-
Form fields can include an optional auxiliary checkbox rendered between the field and error message. This is useful for input confirmation, terms acceptance, or conditional display of other fields.
|
|
327
|
-
|
|
328
|
-
```tsx
|
|
329
|
-
<FormFieldInput
|
|
330
|
-
name="email"
|
|
331
|
-
label="Email"
|
|
332
|
-
auxiliaryCheckbox={{
|
|
333
|
-
name: 'confirmEmail',
|
|
334
|
-
label: 'Send me promotional emails',
|
|
335
|
-
}}
|
|
336
|
-
/>
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
The auxiliary checkbox can be disabled independently of the main field:
|
|
340
|
-
|
|
341
|
-
```tsx
|
|
342
|
-
<FormFieldInput
|
|
343
|
-
name="email"
|
|
344
|
-
label="Email"
|
|
345
|
-
auxiliaryCheckbox={{
|
|
346
|
-
name: 'confirmEmail',
|
|
347
|
-
label: 'Send me promotional emails',
|
|
348
|
-
disabled: true, // Checkbox is disabled, but email field is enabled
|
|
349
|
-
}}
|
|
350
|
-
/>
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
**Props for `auxiliaryCheckbox`:**
|
|
354
|
-
|
|
355
|
-
- `name` (required): Field name for the checkbox
|
|
356
|
-
- `label` (required): Checkbox label text
|
|
357
|
-
- `disabled`: Disables the checkbox (independent of field disabled state)
|
|
358
|
-
- `defaultValue`: Initial checkbox value
|
|
359
|
-
|
|
360
|
-
The auxiliary checkbox's disabled state is the logical OR of its own `disabled` prop and the field's disabled state.
|
|
361
|
-
|
|
362
|
-
### FormFieldInput
|
|
363
|
-
|
|
364
|
-
Text input field supporting all HTML input types.
|
|
365
|
-
|
|
366
|
-
```tsx
|
|
367
|
-
<FormFieldInput
|
|
368
|
-
name="email"
|
|
369
|
-
label="Email"
|
|
370
|
-
type="email"
|
|
371
|
-
placeholder="Enter your email"
|
|
372
|
-
/>
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### FormFieldPassword
|
|
376
|
-
|
|
377
|
-
Password input with show/hide toggle.
|
|
378
|
-
|
|
379
|
-
```tsx
|
|
380
|
-
<FormFieldPassword name="password" label="Password" />
|
|
381
|
-
```
|
|
148
|
+
### FormFieldCurrencyInput — Locale Separators
|
|
382
149
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
Multi-line text input.
|
|
386
|
-
|
|
387
|
-
```tsx
|
|
388
|
-
<FormFieldTextarea name="description" label="Description" rows={4} />
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### FormFieldCheckbox
|
|
392
|
-
|
|
393
|
-
Single checkbox or checkbox group.
|
|
394
|
-
|
|
395
|
-
```tsx
|
|
396
|
-
<FormFieldCheckbox name="terms" label="I accept the terms" />
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### FormFieldSwitch
|
|
400
|
-
|
|
401
|
-
Toggle switch component.
|
|
402
|
-
|
|
403
|
-
```tsx
|
|
404
|
-
<FormFieldSwitch name="notifications" label="Enable notifications" />
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### FormFieldRadio
|
|
408
|
-
|
|
409
|
-
Radio button group.
|
|
410
|
-
|
|
411
|
-
```tsx
|
|
412
|
-
const options = [
|
|
413
|
-
{ value: 'option1', label: 'Option 1' },
|
|
414
|
-
{ value: 'option2', label: 'Option 2' },
|
|
415
|
-
];
|
|
416
|
-
|
|
417
|
-
<FormFieldRadio name="choice" label="Choose one" options={options} />;
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
### FormFieldRadioCard
|
|
421
|
-
|
|
422
|
-
Radio buttons styled as cards.
|
|
423
|
-
|
|
424
|
-
```tsx
|
|
425
|
-
<FormFieldRadioCard name="plan" label="Select Plan" options={options} />
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
### FormFieldRadioCardIcony
|
|
429
|
-
|
|
430
|
-
Radio cards with icon support.
|
|
431
|
-
|
|
432
|
-
```tsx
|
|
433
|
-
const options = [
|
|
434
|
-
{ value: 'card', label: 'Credit Card', icon: 'credit-card' },
|
|
435
|
-
{ value: 'bank', label: 'Bank Transfer', icon: 'bank' },
|
|
436
|
-
];
|
|
437
|
-
|
|
438
|
-
<FormFieldRadioCardIcony
|
|
439
|
-
name="payment"
|
|
440
|
-
label="Payment Method"
|
|
441
|
-
options={options}
|
|
442
|
-
/>;
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
### FormFieldSelect
|
|
446
|
-
|
|
447
|
-
Dropdown select field.
|
|
448
|
-
|
|
449
|
-
```tsx
|
|
450
|
-
const options = [
|
|
451
|
-
{ value: 'ferrari', label: 'Ferrari' },
|
|
452
|
-
{ value: 'mercedes', label: 'Mercedes' },
|
|
453
|
-
{ value: 'bmw', label: 'BMW' },
|
|
454
|
-
];
|
|
455
|
-
|
|
456
|
-
<FormFieldSelect name="car" label="Choose a car" options={options} />;
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
#### FormFieldSelect Default Values
|
|
460
|
-
|
|
461
|
-
`FormFieldSelect` defaults to the first option or a specified `defaultValue`:
|
|
462
|
-
|
|
463
|
-
```tsx
|
|
464
|
-
// Defaults to "Ferrari"
|
|
465
|
-
<FormFieldSelect name="car" label="Cars" options={options} />
|
|
466
|
-
|
|
467
|
-
// Defaults to "Mercedes"
|
|
468
|
-
<FormFieldSelect
|
|
469
|
-
name="car"
|
|
470
|
-
label="Cars"
|
|
471
|
-
options={options}
|
|
472
|
-
defaultValue="Mercedes"
|
|
473
|
-
/>
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
### FormFieldSegmentedControl
|
|
477
|
-
|
|
478
|
-
Segmented control field wrapping the `SegmentedControl` from `@ttoss/ui`. Use this field when you want a compact set of mutually-exclusive options presented as segmented buttons.
|
|
479
|
-
|
|
480
|
-
Props are the common form field props plus any `SegmentedControl` props (except `value` and `className`). Notably, the `variant` prop is supported and defaults to `"secondary"` if not provided.
|
|
481
|
-
|
|
482
|
-
```tsx
|
|
483
|
-
<FormFieldSegmentedControl
|
|
484
|
-
name="viewMode"
|
|
485
|
-
label="View"
|
|
486
|
-
options={[
|
|
487
|
-
{ value: 'list', label: 'List' },
|
|
488
|
-
{ value: 'grid', label: 'Grid' },
|
|
489
|
-
]}
|
|
490
|
-
variant="primary" // optional, defaults to "secondary"
|
|
491
|
-
defaultValue="list"
|
|
492
|
-
/>
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
When using a `placeholder`, an empty option is automatically added if not present:
|
|
496
|
-
|
|
497
|
-
```tsx
|
|
498
|
-
<FormFieldSelect
|
|
499
|
-
name="car"
|
|
500
|
-
label="Cars"
|
|
501
|
-
options={options}
|
|
502
|
-
placeholder="Select a car"
|
|
503
|
-
/>
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
**Note:** `placeholder` and `defaultValue` cannot be used together.
|
|
507
|
-
|
|
508
|
-
For dynamic options from async data, reset the field after loading:
|
|
509
|
-
|
|
510
|
-
```tsx
|
|
511
|
-
const { resetField } = useForm();
|
|
512
|
-
const [options, setOptions] = useState([]);
|
|
513
|
-
|
|
514
|
-
useEffect(() => {
|
|
515
|
-
// Fetch options
|
|
516
|
-
const fetchedOptions = await fetchData();
|
|
517
|
-
setOptions(fetchedOptions);
|
|
518
|
-
resetField('car', { defaultValue: 'Ferrari' });
|
|
519
|
-
}, []);
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
### FormFieldNumericFormat
|
|
523
|
-
|
|
524
|
-
Numeric input with formatting support (decimals, thousands separators).
|
|
525
|
-
|
|
526
|
-
```tsx
|
|
527
|
-
<FormFieldNumericFormat
|
|
528
|
-
name="price"
|
|
529
|
-
label="Price"
|
|
530
|
-
thousandSeparator=","
|
|
531
|
-
decimalScale={2}
|
|
532
|
-
/>
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
### FormFieldCurrencyInput
|
|
536
|
-
|
|
537
|
-
Currency input with locale-based formatting. The decimal and thousand separators are automatically determined by the locale set in the `I18nProvider`.
|
|
538
|
-
|
|
539
|
-
```tsx
|
|
540
|
-
<FormFieldCurrencyInput name="amount" label="Amount" prefix="$" />
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
#### Customizing Separators per Locale
|
|
544
|
-
|
|
545
|
-
The component uses i18n messages to determine the decimal and thousand separators based on the current locale. You can customize these for each locale in your application:
|
|
546
|
-
|
|
547
|
-
1. First, extract the i18n messages by running `pnpm run i18n` in your package
|
|
548
|
-
2. In your application's i18n files (e.g., `i18n/compiled/pt-BR.json`), add the custom separators:
|
|
150
|
+
The decimal and thousand separators are driven by i18n. To customize per locale, add to your app's i18n file (e.g., `i18n/compiled/pt-BR.json`):
|
|
549
151
|
|
|
550
152
|
```json
|
|
551
153
|
{
|
|
552
|
-
"JnCaDG": ",",
|
|
553
|
-
"0+4wTp": "."
|
|
154
|
+
"JnCaDG": ",",
|
|
155
|
+
"0+4wTp": "."
|
|
554
156
|
}
|
|
555
157
|
```
|
|
556
158
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
For more information about the i18n workflow, see the [i18n-CLI documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/).
|
|
560
|
-
|
|
561
|
-
### FormFieldPatternFormat
|
|
562
|
-
|
|
563
|
-
Input with custom format patterns.
|
|
564
|
-
|
|
565
|
-
```tsx
|
|
566
|
-
<FormFieldPatternFormat
|
|
567
|
-
name="phone"
|
|
568
|
-
label="Phone"
|
|
569
|
-
format="+1 (###) ###-####"
|
|
570
|
-
mask="_"
|
|
571
|
-
/>
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
### FormFieldCreditCardNumber
|
|
159
|
+
### FormFieldPhone — Key Props
|
|
575
160
|
|
|
576
|
-
|
|
161
|
+
The submitted value always includes the country code prefix (e.g. `{ phone: '+15555555555' }`). When the user selects the **Manual** entry, the mask is removed and any international number can be typed freely.
|
|
577
162
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
163
|
+
- `defaultCountryCode`: Initial calling code (e.g. `'+1'`). Defaults to the first entry in `countryCodeOptions`.
|
|
164
|
+
- `format`: Pattern string for the local number part (e.g. `'(###) ###-####'`).
|
|
165
|
+
- `countryCodeOptions`: Defaults to `COMMON_PHONE_COUNTRY_CODES`. Pass `[]` to hide the dropdown.
|
|
166
|
+
- `onCountryCodeChange`: Callback fired when the user picks a different country code.
|
|
167
|
+
- `countryCodeName`: Stores the selected country code as a separate form field (e.g. `{ phone: '+15555555555', countryCode: '+1' }`).
|
|
581
168
|
|
|
582
169
|
### Brazil-Specific Fields
|
|
583
170
|
|
|
@@ -591,161 +178,30 @@ import {
|
|
|
591
178
|
} from '@ttoss/forms/brazil';
|
|
592
179
|
```
|
|
593
180
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
```tsx
|
|
599
|
-
<FormFieldCEP name="cep" label="CEP" />
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
#### FormFieldCNPJ
|
|
603
|
-
|
|
604
|
-
Brazilian tax ID (CNPJ) input with validation and formatting.
|
|
605
|
-
|
|
606
|
-
```tsx
|
|
607
|
-
<FormFieldCNPJ name="cnpj" label="CNPJ" />
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
The package also exports `isCnpjValid(cnpj: string)` for standalone validation.
|
|
611
|
-
|
|
612
|
-
#### FormFieldPhone
|
|
613
|
-
|
|
614
|
-
Brazilian phone number input with formatting.
|
|
615
|
-
|
|
616
|
-
```tsx
|
|
617
|
-
<FormFieldPhone name="phone" label="Phone" />
|
|
618
|
-
```
|
|
181
|
+
- `FormFieldCEP` — postal code with automatic formatting
|
|
182
|
+
- `FormFieldCNPJ` — tax ID with validation and formatting
|
|
183
|
+
- `FormFieldPhone` — phone with `+55` country code pre-set
|
|
619
184
|
|
|
620
185
|
## FormGroup
|
|
621
186
|
|
|
622
|
-
Groups related fields with an optional title, description, and layout direction.
|
|
623
|
-
|
|
624
|
-
```tsx
|
|
625
|
-
<FormGroup title="Personal Information" direction="row">
|
|
626
|
-
<FormFieldInput name="firstName" label="First Name" />
|
|
627
|
-
<FormFieldInput name="lastName" label="Last Name" />
|
|
628
|
-
</FormGroup>
|
|
629
|
-
|
|
630
|
-
<FormGroup title="Address" description="Where we'll send your order">
|
|
631
|
-
<FormFieldInput name="street" label="Street" />
|
|
632
|
-
<FormFieldInput name="city" label="City" />
|
|
633
|
-
</FormGroup>
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
Nest `FormGroup` components to create hierarchical sections:
|
|
637
|
-
|
|
638
|
-
```tsx
|
|
639
|
-
<FormGroup title="Personal details">
|
|
640
|
-
<FormFieldInput name="firstName" label="First name" />
|
|
641
|
-
<FormFieldInput name="lastName" label="Last name" />
|
|
642
|
-
|
|
643
|
-
<FormGroup title="Address" direction="row">
|
|
644
|
-
<FormFieldInput name="city" label="City" />
|
|
645
|
-
<FormFieldInput name="zip" label="ZIP" />
|
|
646
|
-
</FormGroup>
|
|
647
|
-
</FormGroup>
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
To display a group-level validation error (e.g. for an array field), pass the `name` prop:
|
|
651
|
-
|
|
652
|
-
```tsx
|
|
653
|
-
<FormGroup name="items" title="Items">
|
|
654
|
-
{fields.map((field, i) => (
|
|
655
|
-
<FormFieldInput key={field.id} name={`items[${i}].value`} label="Value" />
|
|
656
|
-
))}
|
|
657
|
-
</FormGroup>
|
|
658
|
-
```
|
|
187
|
+
Groups related fields with an optional title, description, and layout direction. Pass `name` to display a group-level validation error (e.g. for array fields).
|
|
659
188
|
|
|
660
|
-
**Props:**
|
|
189
|
+
**Props:** `title`, `description`, `direction` (`'row'` | `'column'`, default `'column'`), `name`.
|
|
661
190
|
|
|
662
|
-
-
|
|
663
|
-
- `description`: Optional description displayed below the title
|
|
664
|
-
- `direction`: Layout direction (`'row'` | `'column'`, default: `'column'`)
|
|
665
|
-
- `name`: Field name used to display a group-level validation error message
|
|
191
|
+
See [Storybook](https://storybook.ttoss.dev/?path=/story/forms-formgroup) for nested group examples.
|
|
666
192
|
|
|
667
193
|
## Multistep Forms
|
|
668
194
|
|
|
669
|
-
Import from `@ttoss/forms/multistep-form
|
|
195
|
+
Import from `@ttoss/forms/multistep-form`. Each step provides its own `schema` (Zod) and `fields` (React elements); data is accumulated and passed to `onSubmit` on the final step.
|
|
670
196
|
|
|
671
197
|
```tsx
|
|
672
198
|
import { MultistepForm } from '@ttoss/forms/multistep-form';
|
|
673
|
-
import { FormFieldInput, z } from '@ttoss/forms';
|
|
674
|
-
|
|
675
|
-
const steps = [
|
|
676
|
-
{
|
|
677
|
-
label: 'Step 1',
|
|
678
|
-
question: 'What is your name?',
|
|
679
|
-
fields: <FormFieldInput name="name" label="Name" />,
|
|
680
|
-
schema: z.object({
|
|
681
|
-
name: z.string().min(1, 'Name is required'),
|
|
682
|
-
}),
|
|
683
|
-
},
|
|
684
|
-
{
|
|
685
|
-
label: 'Step 2',
|
|
686
|
-
question: 'How old are you?',
|
|
687
|
-
fields: <FormFieldInput type="number" name="age" label="Age" />,
|
|
688
|
-
defaultValues: { age: 18 },
|
|
689
|
-
schema: z.object({
|
|
690
|
-
age: z.number().min(18, 'Must be at least 18'),
|
|
691
|
-
}),
|
|
692
|
-
},
|
|
693
|
-
];
|
|
694
|
-
|
|
695
|
-
const MyForm = () => {
|
|
696
|
-
return (
|
|
697
|
-
<MultistepForm
|
|
698
|
-
steps={steps}
|
|
699
|
-
onSubmit={(data) => console.log(data)}
|
|
700
|
-
footer="© 2024 Company"
|
|
701
|
-
header={{
|
|
702
|
-
variant: 'logo',
|
|
703
|
-
src: '/logo.png',
|
|
704
|
-
onClose: () => console.log('closed'),
|
|
705
|
-
}}
|
|
706
|
-
/>
|
|
707
|
-
);
|
|
708
|
-
};
|
|
709
199
|
```
|
|
710
200
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
- `steps`: Array of step configurations
|
|
714
|
-
- `onSubmit`: Handler called with complete form data
|
|
715
|
-
- `footer`: Footer text
|
|
716
|
-
- `header`: Header configuration (see below)
|
|
717
|
-
|
|
718
|
-
### Step Configuration
|
|
719
|
-
|
|
720
|
-
Each step object contains:
|
|
201
|
+
**`MultistepForm` props:** `steps`, `onSubmit`, `footer`, `header`.
|
|
721
202
|
|
|
722
|
-
|
|
723
|
-
- `question`: Question or instruction text
|
|
724
|
-
- `fields`: React element(s) containing form fields
|
|
725
|
-
- `schema`: Zod validation schema
|
|
726
|
-
- `defaultValues`: Optional default values for step fields
|
|
203
|
+
**Step object:** `label`, `question`, `fields`, `schema`, `defaultValues`.
|
|
727
204
|
|
|
728
|
-
|
|
205
|
+
**`header` variants:** `{ variant: 'logo', src, onClose }` or `{ variant: 'titled', title, leftIcon, rightIcon, onLeftIconClick, onRightIconClick }`.
|
|
729
206
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
```tsx
|
|
733
|
-
{
|
|
734
|
-
variant: 'logo',
|
|
735
|
-
src: '/path/to/logo.png',
|
|
736
|
-
onClose: () => console.log('Close clicked')
|
|
737
|
-
}
|
|
738
|
-
```
|
|
739
|
-
|
|
740
|
-
**Titled Header:**
|
|
741
|
-
|
|
742
|
-
```tsx
|
|
743
|
-
{
|
|
744
|
-
variant: 'titled',
|
|
745
|
-
title: 'Form Title',
|
|
746
|
-
leftIcon: 'arrow-left',
|
|
747
|
-
rightIcon: 'close',
|
|
748
|
-
onLeftIconClick: () => console.log('Back'),
|
|
749
|
-
onRightIconClick: () => console.log('Close')
|
|
750
|
-
}
|
|
751
|
-
```
|
|
207
|
+
See [Storybook](https://storybook.ttoss.dev/?path=/story/forms-multistepform) for an interactive example.
|
package/dist/Brazil/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { FieldValues, FieldPath } from 'react-hook-form';
|
|
3
|
-
import { a as FormFieldPatternFormatProps, F as FormFieldProps, d as FormFieldPhoneProps$1 } from '../FormFieldPhone-
|
|
3
|
+
import { a as FormFieldPatternFormatProps, F as FormFieldProps, d as FormFieldPhoneProps$1 } from '../FormFieldPhone-Dp3kaJbz.js';
|
|
4
4
|
import { PatternFormatProps, NumberFormatBaseProps } from 'react-number-format';
|
|
5
5
|
import '@ttoss/ui';
|
|
6
6
|
import 'react';
|
|
@@ -19,7 +19,7 @@ declare const FormFieldCPF: <TFieldValues extends FieldValues = FieldValues, TNa
|
|
|
19
19
|
type FormFieldCPFOrCNPJProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = FormFieldProps<TFieldValues, TName> & Omit<NumberFormatBaseProps, 'name' | 'format'>;
|
|
20
20
|
declare const FormFieldCPFOrCNPJ: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ disabled, ...props }: FormFieldCPFOrCNPJProps<TFieldValues, TName>) => react_jsx_runtime.JSX.Element;
|
|
21
21
|
|
|
22
|
-
type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = Omit<FormFieldPhoneProps$1<TFieldValues, TName>, '
|
|
22
|
+
type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = Omit<FormFieldPhoneProps$1<TFieldValues, TName>, 'defaultCountryCode' | 'format'>;
|
|
23
23
|
/**
|
|
24
24
|
* Brazilian phone number form field.
|
|
25
25
|
*
|
|
@@ -109,11 +109,12 @@ declare const COMMON_PHONE_COUNTRY_CODES: CountryCodeOption[];
|
|
|
109
109
|
|
|
110
110
|
type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = FormFieldProps<TFieldValues, TName> & Omit<PatternFormatProps, 'name' | 'format'> & {
|
|
111
111
|
/**
|
|
112
|
-
* The country calling code to display as a literal prefix in the input.
|
|
112
|
+
* The initial country calling code to display as a literal prefix in the input.
|
|
113
113
|
* For example, '+55' for Brazil or '+1' for the United States.
|
|
114
114
|
* Defaults to the first entry in `countryCodeOptions` when not provided.
|
|
115
|
+
* The component manages the selected code internally — no external state needed.
|
|
115
116
|
*/
|
|
116
|
-
|
|
117
|
+
defaultCountryCode?: string;
|
|
117
118
|
/**
|
|
118
119
|
* The pattern format for the local part of the phone number.
|
|
119
120
|
* Accepts either a static string (e.g., '(##) #####-####') or a function
|
|
@@ -136,11 +137,25 @@ type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName e
|
|
|
136
137
|
*/
|
|
137
138
|
countryCodeOptions?: CountryCodeOption[];
|
|
138
139
|
/**
|
|
139
|
-
*
|
|
140
|
-
* the country code via the dropdown.
|
|
141
|
-
*
|
|
140
|
+
* Optional callback fired with the newly selected country code value when
|
|
141
|
+
* the user changes the country code via the dropdown. The component
|
|
142
|
+
* manages the selected code internally, so this is only needed when the
|
|
143
|
+
* caller wants to react to country-code changes.
|
|
142
144
|
*/
|
|
143
145
|
onCountryCodeChange?: (countryCode: string) => void;
|
|
146
|
+
/**
|
|
147
|
+
* When provided, the selected country code is stored as a separate field
|
|
148
|
+
* in the form under this name (e.g. `'countryCode'`). This allows the
|
|
149
|
+
* submitted form data to include both the full phone value and the
|
|
150
|
+
* selected calling code independently.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```tsx
|
|
154
|
+
* // Form data: { phone: '+15555555555', countryCode: '+1' }
|
|
155
|
+
* <FormFieldPhone name="phone" label="Phone" countryCodeName="countryCode" />
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
countryCodeName?: string;
|
|
144
159
|
};
|
|
145
160
|
/**
|
|
146
161
|
* Generic phone number form field that supports an optional country code prefix.
|
|
@@ -168,26 +183,30 @@ type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName e
|
|
|
168
183
|
*
|
|
169
184
|
* @example
|
|
170
185
|
* ```tsx
|
|
171
|
-
* // Default: dropdown with COMMON_PHONE_COUNTRY_CODES,
|
|
172
|
-
*
|
|
186
|
+
* // Default: dropdown with COMMON_PHONE_COUNTRY_CODES, country code managed internally.
|
|
187
|
+
* // The submitted value includes the country code prefix (e.g. '+15555555555').
|
|
188
|
+
* <FormFieldPhone name="phone" label="Phone" />
|
|
173
189
|
* ```
|
|
174
190
|
*
|
|
175
191
|
* @example
|
|
176
192
|
* ```tsx
|
|
177
|
-
* //
|
|
178
|
-
*
|
|
179
|
-
*
|
|
193
|
+
* // Set a custom initial country code; the component manages further changes.
|
|
194
|
+
* <FormFieldPhone name="phone" label="Phone" defaultCountryCode="+55" />
|
|
195
|
+
* ```
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```tsx
|
|
199
|
+
* // Listen for country-code changes without managing state externally.
|
|
180
200
|
* <FormFieldPhone
|
|
181
201
|
* name="phone"
|
|
182
202
|
* label="Phone"
|
|
183
|
-
*
|
|
184
|
-
* onCountryCodeChange={setCountryCode}
|
|
203
|
+
* onCountryCodeChange={(code) => console.log('selected', code)}
|
|
185
204
|
* />
|
|
186
205
|
* ```
|
|
187
206
|
*
|
|
188
207
|
* @example
|
|
189
208
|
* ```tsx
|
|
190
|
-
* // No dropdown — plain phone input; value includes the prefix
|
|
209
|
+
* // No dropdown — plain phone input; value includes the prefix.
|
|
191
210
|
* // e.g. { phone: '+15555555555' }
|
|
192
211
|
* <FormFieldPhone
|
|
193
212
|
* name="phone"
|
|
@@ -211,7 +230,18 @@ type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName e
|
|
|
211
230
|
* countryCodeOptions={[]}
|
|
212
231
|
* />
|
|
213
232
|
* ```
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```tsx
|
|
236
|
+
* // Store the selected country code as a separate form field.
|
|
237
|
+
* // Submitted data: { phone: '+15555555555', countryCode: '+1' }
|
|
238
|
+
* <FormFieldPhone
|
|
239
|
+
* name="phone"
|
|
240
|
+
* label="Phone"
|
|
241
|
+
* countryCodeName="countryCode"
|
|
242
|
+
* />
|
|
243
|
+
* ```
|
|
214
244
|
*/
|
|
215
|
-
declare const FormFieldPhone: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ disabled,
|
|
245
|
+
declare const FormFieldPhone: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ disabled, defaultCountryCode: countryCodeProp, format, countryCodeOptions, onCountryCodeChange, countryCodeName, ...props }: FormFieldPhoneProps<TFieldValues, TName>) => react_jsx_runtime.JSX.Element;
|
|
216
246
|
|
|
217
247
|
export { type CountryCodeOption as C, type FormFieldProps as F, MANUAL_PHONE_COUNTRY_CODE as M, type FormFieldPatternFormatProps as a, FormField as b, FormFieldPatternFormat as c, type FormFieldPhoneProps as d, FormFieldPhone as e, COMMON_PHONE_COUNTRY_CODES as f };
|
package/dist/esm/Brazil/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { FormField, FormFieldCNPJ, FormFieldCPF, FormFieldPatternFormat, FormFieldPhone, __name, isCnpjValid, isCpfValid } from "../chunk-
|
|
3
|
+
import { FormField, FormFieldCNPJ, FormFieldCPF, FormFieldPatternFormat, FormFieldPhone, __name, isCnpjValid, isCpfValid } from "../chunk-NEIQETLB.js";
|
|
4
4
|
|
|
5
5
|
// src/Brazil/FormFieldCEP.tsx
|
|
6
6
|
var FormFieldCEP = /* @__PURE__ */__name(({
|
|
@@ -84,7 +84,7 @@ var FormFieldPhone2 = /* @__PURE__ */__name(({
|
|
|
84
84
|
}) => {
|
|
85
85
|
return /* @__PURE__ */React.createElement(FormFieldPhone, {
|
|
86
86
|
...props,
|
|
87
|
-
|
|
87
|
+
defaultCountryCode: BRAZIL_COUNTRY_CODE,
|
|
88
88
|
format: getBrazilPhoneFormat,
|
|
89
89
|
placeholder,
|
|
90
90
|
countryCodeOptions
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { Form, useForm, yupResolver } from "../chunk-
|
|
4
|
-
import { __name } from "../chunk-
|
|
3
|
+
import { Form, useForm, yupResolver } from "../chunk-UT6OKRDR.js";
|
|
4
|
+
import { __name } from "../chunk-NEIQETLB.js";
|
|
5
5
|
|
|
6
6
|
// src/MultistepForm/MultistepForm.tsx
|
|
7
7
|
import { Flex as Flex6 } from "@ttoss/ui";
|
|
@@ -268,6 +268,59 @@ var FormFieldPatternFormat = /* @__PURE__ */__name(({
|
|
|
268
268
|
});
|
|
269
269
|
}, "FormFieldPatternFormat");
|
|
270
270
|
|
|
271
|
+
// src/FormFieldSelect.tsx
|
|
272
|
+
import { Select } from "@ttoss/ui";
|
|
273
|
+
var FormFieldSelect = /* @__PURE__ */__name(({
|
|
274
|
+
disabled,
|
|
275
|
+
...props
|
|
276
|
+
}) => {
|
|
277
|
+
const {
|
|
278
|
+
label,
|
|
279
|
+
name,
|
|
280
|
+
labelTooltip,
|
|
281
|
+
warning,
|
|
282
|
+
sx,
|
|
283
|
+
css,
|
|
284
|
+
rules,
|
|
285
|
+
id,
|
|
286
|
+
defaultValue,
|
|
287
|
+
onBlur,
|
|
288
|
+
onChange,
|
|
289
|
+
...selectProps
|
|
290
|
+
} = props;
|
|
291
|
+
return /* @__PURE__ */React.createElement(FormField, {
|
|
292
|
+
id,
|
|
293
|
+
label,
|
|
294
|
+
name,
|
|
295
|
+
labelTooltip,
|
|
296
|
+
warning,
|
|
297
|
+
sx,
|
|
298
|
+
css,
|
|
299
|
+
defaultValue,
|
|
300
|
+
rules,
|
|
301
|
+
disabled,
|
|
302
|
+
render: /* @__PURE__ */__name(({
|
|
303
|
+
field,
|
|
304
|
+
fieldState
|
|
305
|
+
}) => {
|
|
306
|
+
return /* @__PURE__ */React.createElement(Select, {
|
|
307
|
+
...selectProps,
|
|
308
|
+
...field,
|
|
309
|
+
onBlur: /* @__PURE__ */__name(e => {
|
|
310
|
+
field.onBlur();
|
|
311
|
+
onBlur?.(e);
|
|
312
|
+
}, "onBlur"),
|
|
313
|
+
onChange: /* @__PURE__ */__name(newValue => {
|
|
314
|
+
field.onChange(newValue);
|
|
315
|
+
onChange?.(newValue);
|
|
316
|
+
}, "onChange"),
|
|
317
|
+
isDisabled: disabled ?? field.disabled,
|
|
318
|
+
"aria-invalid": fieldState.error ? "true" : void 0
|
|
319
|
+
});
|
|
320
|
+
}, "render")
|
|
321
|
+
});
|
|
322
|
+
}, "FormFieldSelect");
|
|
323
|
+
|
|
271
324
|
// src/phoneCountryCodes.ts
|
|
272
325
|
var MANUAL_PHONE_COUNTRY_CODE = "manual";
|
|
273
326
|
var COMMON_PHONE_COUNTRY_CODES = [{
|
|
@@ -336,12 +389,14 @@ var COMMON_PHONE_COUNTRY_CODES = [{
|
|
|
336
389
|
}];
|
|
337
390
|
|
|
338
391
|
// src/FormFieldPhone.tsx
|
|
339
|
-
import { Box, Flex as Flex3, Input as Input2
|
|
392
|
+
import { Box, Flex as Flex3, Input as Input2 } from "@ttoss/ui";
|
|
340
393
|
import * as React4 from "react";
|
|
394
|
+
import { useFormContext as useFormContext3 } from "react-hook-form";
|
|
341
395
|
import { NumericFormat, PatternFormat as PatternFormat2 } from "react-number-format";
|
|
342
396
|
var PhoneDropdownWrapper = /* @__PURE__ */__name(({
|
|
343
397
|
id,
|
|
344
|
-
|
|
398
|
+
countryCodeFieldName,
|
|
399
|
+
defaultCountryCode,
|
|
345
400
|
countryCodeOptions,
|
|
346
401
|
disabled,
|
|
347
402
|
onCountryCodeChange,
|
|
@@ -357,9 +412,10 @@ var PhoneDropdownWrapper = /* @__PURE__ */__name(({
|
|
|
357
412
|
sx: {
|
|
358
413
|
minWidth: "180px"
|
|
359
414
|
}
|
|
360
|
-
}, /* @__PURE__ */React4.createElement(
|
|
415
|
+
}, /* @__PURE__ */React4.createElement(FormFieldSelect, {
|
|
416
|
+
name: countryCodeFieldName,
|
|
417
|
+
defaultValue: defaultCountryCode,
|
|
361
418
|
options: countryCodeOptions,
|
|
362
|
-
value: countryCode,
|
|
363
419
|
disabled,
|
|
364
420
|
onChange: /* @__PURE__ */__name(value => {
|
|
365
421
|
if (value !== void 0) {
|
|
@@ -377,10 +433,11 @@ var PhoneDropdownWrapper = /* @__PURE__ */__name(({
|
|
|
377
433
|
}, "PhoneDropdownWrapper");
|
|
378
434
|
var FormFieldPhone = /* @__PURE__ */__name(({
|
|
379
435
|
disabled,
|
|
380
|
-
|
|
436
|
+
defaultCountryCode: countryCodeProp,
|
|
381
437
|
format,
|
|
382
438
|
countryCodeOptions = COMMON_PHONE_COUNTRY_CODES,
|
|
383
439
|
onCountryCodeChange,
|
|
440
|
+
countryCodeName,
|
|
384
441
|
...props
|
|
385
442
|
}) => {
|
|
386
443
|
const {
|
|
@@ -399,7 +456,15 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
399
456
|
placeholder,
|
|
400
457
|
...patternFormatProps
|
|
401
458
|
} = props;
|
|
402
|
-
const
|
|
459
|
+
const {
|
|
460
|
+
watch
|
|
461
|
+
} = useFormContext3();
|
|
462
|
+
const countryCodeFieldName = countryCodeName ?? `${String(name)}CountryCode`;
|
|
463
|
+
const defaultCountryCode = countryCodeProp ?? countryCodeOptions[0]?.value ?? void 0;
|
|
464
|
+
const countryCode = watch(countryCodeFieldName) ?? defaultCountryCode;
|
|
465
|
+
const handleCountryCodeChange = /* @__PURE__ */__name(code => {
|
|
466
|
+
onCountryCodeChange?.(code);
|
|
467
|
+
}, "handleCountryCodeChange");
|
|
403
468
|
const isManual = countryCode === MANUAL_PHONE_COUNTRY_CODE;
|
|
404
469
|
const getFormat = /* @__PURE__ */__name(value => {
|
|
405
470
|
const selectedOption = countryCodeOptions.find(opt => {
|
|
@@ -410,7 +475,16 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
410
475
|
return countryCode && !isManual ? `${countryCode} ${baseFormat}` : baseFormat;
|
|
411
476
|
}, "getFormat");
|
|
412
477
|
const showDropdown = countryCodeOptions.length > 0;
|
|
413
|
-
|
|
478
|
+
const hiddenCountryCodeSelect = !showDropdown && countryCodeName ? /* @__PURE__ */React4.createElement(Box, {
|
|
479
|
+
sx: {
|
|
480
|
+
display: "none"
|
|
481
|
+
}
|
|
482
|
+
}, /* @__PURE__ */React4.createElement(FormFieldSelect, {
|
|
483
|
+
name: countryCodeName,
|
|
484
|
+
defaultValue: defaultCountryCode,
|
|
485
|
+
options: []
|
|
486
|
+
})) : null;
|
|
487
|
+
return /* @__PURE__ */React4.createElement(React4.Fragment, null, hiddenCountryCodeSelect, /* @__PURE__ */React4.createElement(FormField, {
|
|
414
488
|
id,
|
|
415
489
|
label,
|
|
416
490
|
name,
|
|
@@ -469,17 +543,18 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
469
543
|
return inputNode;
|
|
470
544
|
}
|
|
471
545
|
return /* @__PURE__ */React4.createElement(PhoneDropdownWrapper, {
|
|
472
|
-
|
|
546
|
+
countryCodeFieldName,
|
|
547
|
+
defaultCountryCode,
|
|
473
548
|
countryCodeOptions,
|
|
474
549
|
disabled: disabled ?? field.disabled,
|
|
475
|
-
onCountryCodeChange,
|
|
550
|
+
onCountryCodeChange: handleCountryCodeChange,
|
|
476
551
|
onPhoneReset: /* @__PURE__ */__name(() => {
|
|
477
552
|
return field.onChange("");
|
|
478
553
|
}, "onPhoneReset"),
|
|
479
554
|
inputNode
|
|
480
555
|
});
|
|
481
556
|
}, "render")
|
|
482
|
-
});
|
|
557
|
+
}));
|
|
483
558
|
}, "FormFieldPhone");
|
|
484
559
|
|
|
485
560
|
// src/Brazil/FormFieldCNPJ.tsx
|
|
@@ -654,4 +729,4 @@ var FormFieldCPF = /* @__PURE__ */__name(({
|
|
|
654
729
|
}, "render")
|
|
655
730
|
});
|
|
656
731
|
}, "FormFieldCPF");
|
|
657
|
-
export { __name, FormErrorMessage, FormField, FormFieldPatternFormat, MANUAL_PHONE_COUNTRY_CODE, COMMON_PHONE_COUNTRY_CODES, FormFieldPhone, isCnpjValid, FormFieldCNPJ, isCpfValid, FormFieldCPF };
|
|
732
|
+
export { __name, FormErrorMessage, FormField, FormFieldPatternFormat, FormFieldSelect, MANUAL_PHONE_COUNTRY_CODE, COMMON_PHONE_COUNTRY_CODES, FormFieldPhone, isCnpjValid, FormFieldCNPJ, isCpfValid, FormFieldCPF };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { FormErrorMessage, FormField, FormFieldPatternFormat, __name, isCnpjValid, isCpfValid } from "./chunk-
|
|
3
|
+
import { FormErrorMessage, FormField, FormFieldPatternFormat, __name, isCnpjValid, isCpfValid } from "./chunk-NEIQETLB.js";
|
|
4
4
|
|
|
5
5
|
// src/Form.tsx
|
|
6
6
|
import { Box as Box2 } from "@ttoss/ui";
|
|
@@ -797,59 +797,6 @@ var FormFieldSegmentedControl = /* @__PURE__ */__name(({
|
|
|
797
797
|
});
|
|
798
798
|
}, "FormFieldSegmentedControl");
|
|
799
799
|
|
|
800
|
-
// src/FormFieldSelect.tsx
|
|
801
|
-
import { Select } from "@ttoss/ui";
|
|
802
|
-
var FormFieldSelect = /* @__PURE__ */__name(({
|
|
803
|
-
disabled,
|
|
804
|
-
...props
|
|
805
|
-
}) => {
|
|
806
|
-
const {
|
|
807
|
-
label,
|
|
808
|
-
name,
|
|
809
|
-
labelTooltip,
|
|
810
|
-
warning,
|
|
811
|
-
sx,
|
|
812
|
-
css,
|
|
813
|
-
rules,
|
|
814
|
-
id,
|
|
815
|
-
defaultValue,
|
|
816
|
-
onBlur,
|
|
817
|
-
onChange,
|
|
818
|
-
...selectProps
|
|
819
|
-
} = props;
|
|
820
|
-
return /* @__PURE__ */React.createElement(FormField, {
|
|
821
|
-
id,
|
|
822
|
-
label,
|
|
823
|
-
name,
|
|
824
|
-
labelTooltip,
|
|
825
|
-
warning,
|
|
826
|
-
sx,
|
|
827
|
-
css,
|
|
828
|
-
defaultValue,
|
|
829
|
-
rules,
|
|
830
|
-
disabled,
|
|
831
|
-
render: /* @__PURE__ */__name(({
|
|
832
|
-
field,
|
|
833
|
-
fieldState
|
|
834
|
-
}) => {
|
|
835
|
-
return /* @__PURE__ */React.createElement(Select, {
|
|
836
|
-
...selectProps,
|
|
837
|
-
...field,
|
|
838
|
-
onBlur: /* @__PURE__ */__name(e => {
|
|
839
|
-
field.onBlur();
|
|
840
|
-
onBlur?.(e);
|
|
841
|
-
}, "onBlur"),
|
|
842
|
-
onChange: /* @__PURE__ */__name(newValue => {
|
|
843
|
-
field.onChange(newValue);
|
|
844
|
-
onChange?.(newValue);
|
|
845
|
-
}, "onChange"),
|
|
846
|
-
isDisabled: disabled ?? field.disabled,
|
|
847
|
-
"aria-invalid": fieldState.error ? "true" : void 0
|
|
848
|
-
});
|
|
849
|
-
}, "render")
|
|
850
|
-
});
|
|
851
|
-
}, "FormFieldSelect");
|
|
852
|
-
|
|
853
800
|
// src/FormFieldSwitch.tsx
|
|
854
801
|
import { Switch } from "@ttoss/ui";
|
|
855
802
|
var FormFieldSwitch = /* @__PURE__ */__name(({
|
|
@@ -1124,4 +1071,4 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
|
|
1124
1071
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
1125
1072
|
import { Controller, FormProvider as FormProvider2, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch } from "react-hook-form";
|
|
1126
1073
|
export * from "react-hook-form";
|
|
1127
|
-
export { FormActions, useFormGroup, FormGroup, Form, FormFieldCheckbox, FormFieldCreditCardNumber, FormFieldNumericFormat, FormFieldCurrencyInput, FormFieldDatePicker, FormFieldInput, FormFieldPassword, FormFieldRadio, FormFieldRadioCard, FormFieldRadioCardIcony, FormFieldSegmentedControl,
|
|
1074
|
+
export { FormActions, useFormGroup, FormGroup, Form, FormFieldCheckbox, FormFieldCreditCardNumber, FormFieldNumericFormat, FormFieldCurrencyInput, FormFieldDatePicker, FormFieldInput, FormFieldPassword, FormFieldRadio, FormFieldRadioCard, FormFieldRadioCardIcony, FormFieldSegmentedControl, FormFieldSwitch, FormFieldTextarea, yup2 as yup, z3 as z, yupResolver, zodResolver, Controller, FormProvider2 as FormProvider, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
import { Controller, Form, FormActions, FormFieldCheckbox, FormFieldCreditCardNumber, FormFieldCurrencyInput, FormFieldDatePicker, FormFieldInput, FormFieldNumericFormat, FormFieldPassword, FormFieldRadio, FormFieldRadioCard, FormFieldRadioCardIcony, FormFieldSegmentedControl,
|
|
3
|
-
import { COMMON_PHONE_COUNTRY_CODES, FormErrorMessage, FormField, FormFieldPatternFormat, FormFieldPhone, MANUAL_PHONE_COUNTRY_CODE } from "./chunk-
|
|
2
|
+
import { Controller, Form, FormActions, FormFieldCheckbox, FormFieldCreditCardNumber, FormFieldCurrencyInput, FormFieldDatePicker, FormFieldInput, FormFieldNumericFormat, FormFieldPassword, FormFieldRadio, FormFieldRadioCard, FormFieldRadioCardIcony, FormFieldSegmentedControl, FormFieldSwitch, FormFieldTextarea, FormGroup, FormProvider, useController, useFieldArray, useForm, useFormContext, useFormGroup, useFormState, useWatch, yup, yupResolver, z, zodResolver } from "./chunk-UT6OKRDR.js";
|
|
3
|
+
import { COMMON_PHONE_COUNTRY_CODES, FormErrorMessage, FormField, FormFieldPatternFormat, FormFieldPhone, FormFieldSelect, MANUAL_PHONE_COUNTRY_CODE } from "./chunk-NEIQETLB.js";
|
|
4
4
|
export { COMMON_PHONE_COUNTRY_CODES, Controller, Form, FormActions, FormErrorMessage, FormField, FormFieldCheckbox, FormFieldCreditCardNumber, FormFieldCurrencyInput, FormFieldDatePicker, FormFieldInput, FormFieldNumericFormat, FormFieldPassword, FormFieldPatternFormat, FormFieldPhone, FormFieldRadio, FormFieldRadioCard, FormFieldRadioCardIcony, FormFieldSegmentedControl, FormFieldSelect, FormFieldSwitch, FormFieldTextarea, FormGroup, FormProvider, MANUAL_PHONE_COUNTRY_CODE, useController, useFieldArray, useForm, useFormContext, useFormGroup, useFormState, useWatch, yup, yupResolver, z, zodResolver };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import * as React from 'react';
|
|
|
4
4
|
import { FieldValues, FormProviderProps, FieldName, FieldPath } from 'react-hook-form';
|
|
5
5
|
export * from 'react-hook-form';
|
|
6
6
|
export { Controller, FormProvider, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch } from 'react-hook-form';
|
|
7
|
-
import { F as FormFieldProps, a as FormFieldPatternFormatProps } from './FormFieldPhone-
|
|
8
|
-
export { f as COMMON_PHONE_COUNTRY_CODES, C as CountryCodeOption, b as FormField, c as FormFieldPatternFormat, e as FormFieldPhone, d as FormFieldPhoneProps, M as MANUAL_PHONE_COUNTRY_CODE } from './FormFieldPhone-
|
|
7
|
+
import { F as FormFieldProps, a as FormFieldPatternFormatProps } from './FormFieldPhone-Dp3kaJbz.js';
|
|
8
|
+
export { f as COMMON_PHONE_COUNTRY_CODES, C as CountryCodeOption, b as FormField, c as FormFieldPatternFormat, e as FormFieldPhone, d as FormFieldPhoneProps, M as MANUAL_PHONE_COUNTRY_CODE } from './FormFieldPhone-Dp3kaJbz.js';
|
|
9
9
|
import { NumericFormatProps } from 'react-number-format';
|
|
10
10
|
import { DateRange } from '@ttoss/components/DatePicker';
|
|
11
11
|
import './typings.d-BzNUo1mD.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/forms",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": ">=16.8.0",
|
|
43
|
-
"@ttoss/
|
|
43
|
+
"@ttoss/components": "^2.13.2",
|
|
44
44
|
"@ttoss/ui": "^6.8.0",
|
|
45
|
-
"@ttoss/
|
|
45
|
+
"@ttoss/react-i18n": "^2.1.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/jest": "^30.0.0",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"react-error-boundary": "^6.1.0",
|
|
53
53
|
"tsup": "^8.5.1",
|
|
54
54
|
"yup": "^1.7.1",
|
|
55
|
-
"@ttoss/
|
|
55
|
+
"@ttoss/config": "^1.36.0",
|
|
56
56
|
"@ttoss/i18n-cli": "^0.7.39",
|
|
57
57
|
"@ttoss/react-i18n": "^2.1.0",
|
|
58
58
|
"@ttoss/react-icons": "^0.6.0",
|
|
59
59
|
"@ttoss/test-utils": "^4.1.0",
|
|
60
|
-
"@ttoss/
|
|
61
|
-
"@ttoss/
|
|
60
|
+
"@ttoss/components": "^2.13.2",
|
|
61
|
+
"@ttoss/ui": "^6.8.0"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public",
|