@ttoss/forms 0.43.1 → 0.43.8
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 +63 -647
- package/dist/Brazil/index.d.ts +1 -1
- package/dist/{FormFieldPhone--tC0Hlcf.d.ts → FormFieldPhone-Dp3kaJbz.d.ts} +25 -1
- package/dist/esm/Brazil/index.js +1 -1
- package/dist/esm/MultistepForm/index.js +2 -2
- package/dist/esm/{chunk-U7QBQHMU.js → chunk-NEIQETLB.js} +81 -10
- package/dist/esm/{chunk-3M2OR5NH.js → chunk-UT6OKRDR.js} +2 -55
- package/dist/esm/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +12 -12
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
|
|
193
|
-
|
|
194
|
-
### 1. Schema-based Validation (Recommended)
|
|
195
|
-
|
|
196
|
-
Use Zod schemas with `zodResolver` for complex validation logic:
|
|
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:**
|
|
84
|
+
There are two ways to validate form fields — choose one per field, they cannot be mixed.
|
|
212
85
|
|
|
213
|
-
-
|
|
214
|
-
- Type-safe with TypeScript
|
|
215
|
-
- Reusable schemas
|
|
216
|
-
- Complex validation patterns
|
|
217
|
-
- Schema composition
|
|
86
|
+
**Schema-based validation** (`zodResolver`) is recommended for cross-field validation, complex business logic, and reusable/type-safe schemas.
|
|
218
87
|
|
|
219
|
-
|
|
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,398 +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:
|
|
282
|
-
|
|
283
|
-
```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:
|
|
122
|
+
To disable all fields at once, pass `disabled` to `useForm`:
|
|
290
123
|
|
|
291
124
|
```tsx
|
|
292
|
-
const
|
|
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
|
-
};
|
|
125
|
+
const formMethods = useForm({ disabled: isSubmitting });
|
|
303
126
|
```
|
|
304
127
|
|
|
305
|
-
|
|
128
|
+
### Available Components
|
|
306
129
|
|
|
307
|
-
|
|
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 |
|
|
308
147
|
|
|
309
|
-
|
|
310
|
-
<FormFieldInput name="email" label="Email" disabled />
|
|
311
|
-
```
|
|
148
|
+
### FormFieldCurrencyInput — Locale Separators
|
|
312
149
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
```tsx
|
|
316
|
-
const formMethods = useForm({
|
|
317
|
-
disabled: false,
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
// This field will be disabled even though the form is enabled
|
|
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
|
-
```
|
|
382
|
-
|
|
383
|
-
### FormFieldTextarea
|
|
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/).
|
|
159
|
+
### FormFieldPhone — Key Props
|
|
560
160
|
|
|
561
|
-
|
|
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
|
-
### FormFieldPhone
|
|
575
|
-
|
|
576
|
-
Generic phone number field with an optional country-code dropdown. By default it renders a dropdown populated with `COMMON_PHONE_COUNTRY_CODES` (15 common countries + a Manual entry). The component manages the selected country code internally — no external state is needed.
|
|
577
|
-
|
|
578
|
-
```tsx
|
|
579
|
-
import { FormFieldPhone, COMMON_PHONE_COUNTRY_CODES } from '@ttoss/forms';
|
|
580
|
-
|
|
581
|
-
// Minimal — dropdown defaults to COMMON_PHONE_COUNTRY_CODES, starts in Manual mode
|
|
582
|
-
<FormFieldPhone name="phone" label="Phone" />
|
|
583
|
-
|
|
584
|
-
// Set an initial country code (US +1)
|
|
585
|
-
<FormFieldPhone name="phone" label="Phone" defaultCountryCode="+1" />
|
|
586
|
-
|
|
587
|
-
// React to country-code changes without managing state
|
|
588
|
-
<FormFieldPhone
|
|
589
|
-
name="phone"
|
|
590
|
-
label="Phone"
|
|
591
|
-
defaultCountryCode="+1"
|
|
592
|
-
onCountryCodeChange={(code) => console.log('selected', code)}
|
|
593
|
-
/>
|
|
594
|
-
|
|
595
|
-
// No dropdown — plain masked input with a fixed country code
|
|
596
|
-
<FormFieldPhone
|
|
597
|
-
name="phone"
|
|
598
|
-
label="Phone"
|
|
599
|
-
defaultCountryCode="+1"
|
|
600
|
-
format="(###) ###-####"
|
|
601
|
-
countryCodeOptions={[]}
|
|
602
|
-
/>
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
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 the user can type any international number freely (the value is stored with a `+` prefix).
|
|
606
|
-
|
|
607
|
-
**Key props:**
|
|
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.
|
|
608
162
|
|
|
609
163
|
- `defaultCountryCode`: Initial calling code (e.g. `'+1'`). Defaults to the first entry in `countryCodeOptions`.
|
|
610
|
-
- `format`: Pattern string
|
|
611
|
-
- `countryCodeOptions`:
|
|
612
|
-
- `onCountryCodeChange`:
|
|
613
|
-
|
|
614
|
-
### FormFieldCreditCardNumber
|
|
615
|
-
|
|
616
|
-
Credit card input with automatic formatting.
|
|
617
|
-
|
|
618
|
-
```tsx
|
|
619
|
-
<FormFieldCreditCardNumber name="cardNumber" label="Card Number" />
|
|
620
|
-
```
|
|
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' }`).
|
|
621
168
|
|
|
622
169
|
### Brazil-Specific Fields
|
|
623
170
|
|
|
@@ -631,161 +178,30 @@ import {
|
|
|
631
178
|
} from '@ttoss/forms/brazil';
|
|
632
179
|
```
|
|
633
180
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
```tsx
|
|
639
|
-
<FormFieldCEP name="cep" label="CEP" />
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
#### FormFieldCNPJ
|
|
643
|
-
|
|
644
|
-
Brazilian tax ID (CNPJ) input with validation and formatting.
|
|
645
|
-
|
|
646
|
-
```tsx
|
|
647
|
-
<FormFieldCNPJ name="cnpj" label="CNPJ" />
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
The package also exports `isCnpjValid(cnpj: string)` for standalone validation.
|
|
651
|
-
|
|
652
|
-
#### FormFieldPhone
|
|
653
|
-
|
|
654
|
-
Brazilian phone number input with automatic formatting and the `+55` country code pre-set.
|
|
655
|
-
|
|
656
|
-
```tsx
|
|
657
|
-
<FormFieldPhone name="phone" label="Phone" />
|
|
658
|
-
```
|
|
181
|
+
- `FormFieldCEP` — postal code with automatic formatting
|
|
182
|
+
- `FormFieldCNPJ` — tax ID with validation and formatting
|
|
183
|
+
- `FormFieldPhone` — phone with `+55` country code pre-set
|
|
659
184
|
|
|
660
185
|
## FormGroup
|
|
661
186
|
|
|
662
|
-
Groups related fields with an optional title, description, and layout direction.
|
|
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).
|
|
663
188
|
|
|
664
|
-
|
|
665
|
-
<FormGroup title="Personal Information" direction="row">
|
|
666
|
-
<FormFieldInput name="firstName" label="First Name" />
|
|
667
|
-
<FormFieldInput name="lastName" label="Last Name" />
|
|
668
|
-
</FormGroup>
|
|
669
|
-
|
|
670
|
-
<FormGroup title="Address" description="Where we'll send your order">
|
|
671
|
-
<FormFieldInput name="street" label="Street" />
|
|
672
|
-
<FormFieldInput name="city" label="City" />
|
|
673
|
-
</FormGroup>
|
|
674
|
-
```
|
|
189
|
+
**Props:** `title`, `description`, `direction` (`'row'` | `'column'`, default `'column'`), `name`.
|
|
675
190
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
```tsx
|
|
679
|
-
<FormGroup title="Personal details">
|
|
680
|
-
<FormFieldInput name="firstName" label="First name" />
|
|
681
|
-
<FormFieldInput name="lastName" label="Last name" />
|
|
682
|
-
|
|
683
|
-
<FormGroup title="Address" direction="row">
|
|
684
|
-
<FormFieldInput name="city" label="City" />
|
|
685
|
-
<FormFieldInput name="zip" label="ZIP" />
|
|
686
|
-
</FormGroup>
|
|
687
|
-
</FormGroup>
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
To display a group-level validation error (e.g. for an array field), pass the `name` prop:
|
|
691
|
-
|
|
692
|
-
```tsx
|
|
693
|
-
<FormGroup name="items" title="Items">
|
|
694
|
-
{fields.map((field, i) => (
|
|
695
|
-
<FormFieldInput key={field.id} name={`items[${i}].value`} label="Value" />
|
|
696
|
-
))}
|
|
697
|
-
</FormGroup>
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
**Props:**
|
|
701
|
-
|
|
702
|
-
- `title`: Optional heading displayed above the group's children
|
|
703
|
-
- `description`: Optional description displayed below the title
|
|
704
|
-
- `direction`: Layout direction (`'row'` | `'column'`, default: `'column'`)
|
|
705
|
-
- `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.
|
|
706
192
|
|
|
707
193
|
## Multistep Forms
|
|
708
194
|
|
|
709
|
-
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.
|
|
710
196
|
|
|
711
197
|
```tsx
|
|
712
198
|
import { MultistepForm } from '@ttoss/forms/multistep-form';
|
|
713
|
-
import { FormFieldInput, z } from '@ttoss/forms';
|
|
714
|
-
|
|
715
|
-
const steps = [
|
|
716
|
-
{
|
|
717
|
-
label: 'Step 1',
|
|
718
|
-
question: 'What is your name?',
|
|
719
|
-
fields: <FormFieldInput name="name" label="Name" />,
|
|
720
|
-
schema: z.object({
|
|
721
|
-
name: z.string().min(1, 'Name is required'),
|
|
722
|
-
}),
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
label: 'Step 2',
|
|
726
|
-
question: 'How old are you?',
|
|
727
|
-
fields: <FormFieldInput type="number" name="age" label="Age" />,
|
|
728
|
-
defaultValues: { age: 18 },
|
|
729
|
-
schema: z.object({
|
|
730
|
-
age: z.number().min(18, 'Must be at least 18'),
|
|
731
|
-
}),
|
|
732
|
-
},
|
|
733
|
-
];
|
|
734
|
-
|
|
735
|
-
const MyForm = () => {
|
|
736
|
-
return (
|
|
737
|
-
<MultistepForm
|
|
738
|
-
steps={steps}
|
|
739
|
-
onSubmit={(data) => console.log(data)}
|
|
740
|
-
footer="© 2024 Company"
|
|
741
|
-
header={{
|
|
742
|
-
variant: 'logo',
|
|
743
|
-
src: '/logo.png',
|
|
744
|
-
onClose: () => console.log('closed'),
|
|
745
|
-
}}
|
|
746
|
-
/>
|
|
747
|
-
);
|
|
748
|
-
};
|
|
749
199
|
```
|
|
750
200
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
- `steps`: Array of step configurations
|
|
754
|
-
- `onSubmit`: Handler called with complete form data
|
|
755
|
-
- `footer`: Footer text
|
|
756
|
-
- `header`: Header configuration (see below)
|
|
757
|
-
|
|
758
|
-
### Step Configuration
|
|
759
|
-
|
|
760
|
-
Each step object contains:
|
|
761
|
-
|
|
762
|
-
- `label`: Step label for navigation
|
|
763
|
-
- `question`: Question or instruction text
|
|
764
|
-
- `fields`: React element(s) containing form fields
|
|
765
|
-
- `schema`: Zod validation schema
|
|
766
|
-
- `defaultValues`: Optional default values for step fields
|
|
767
|
-
|
|
768
|
-
### Header Types
|
|
769
|
-
|
|
770
|
-
**Logo Header:**
|
|
201
|
+
**`MultistepForm` props:** `steps`, `onSubmit`, `footer`, `header`.
|
|
771
202
|
|
|
772
|
-
|
|
773
|
-
{
|
|
774
|
-
variant: 'logo',
|
|
775
|
-
src: '/path/to/logo.png',
|
|
776
|
-
onClose: () => console.log('Close clicked')
|
|
777
|
-
}
|
|
778
|
-
```
|
|
203
|
+
**Step object:** `label`, `question`, `fields`, `schema`, `defaultValues`.
|
|
779
204
|
|
|
780
|
-
|
|
205
|
+
**`header` variants:** `{ variant: 'logo', src, onClose }` or `{ variant: 'titled', title, leftIcon, rightIcon, onLeftIconClick, onRightIconClick }`.
|
|
781
206
|
|
|
782
|
-
|
|
783
|
-
{
|
|
784
|
-
variant: 'titled',
|
|
785
|
-
title: 'Form Title',
|
|
786
|
-
leftIcon: 'arrow-left',
|
|
787
|
-
rightIcon: 'close',
|
|
788
|
-
onLeftIconClick: () => console.log('Back'),
|
|
789
|
-
onRightIconClick: () => console.log('Close')
|
|
790
|
-
}
|
|
791
|
-
```
|
|
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';
|
|
@@ -143,6 +143,19 @@ type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName e
|
|
|
143
143
|
* caller wants to react to country-code changes.
|
|
144
144
|
*/
|
|
145
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;
|
|
146
159
|
};
|
|
147
160
|
/**
|
|
148
161
|
* Generic phone number form field that supports an optional country code prefix.
|
|
@@ -217,7 +230,18 @@ type FormFieldPhoneProps<TFieldValues extends FieldValues = FieldValues, TName e
|
|
|
217
230
|
* countryCodeOptions={[]}
|
|
218
231
|
* />
|
|
219
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
|
+
* ```
|
|
220
244
|
*/
|
|
221
|
-
declare const FormFieldPhone: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ disabled, defaultCountryCode: countryCodeProp, format, countryCodeOptions, onCountryCodeChange, ...props }: FormFieldPhoneProps<TFieldValues, TName>) => react_jsx_runtime.JSX.Element;
|
|
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;
|
|
222
246
|
|
|
223
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(({
|
|
@@ -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) {
|
|
@@ -381,6 +437,7 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
381
437
|
format,
|
|
382
438
|
countryCodeOptions = COMMON_PHONE_COUNTRY_CODES,
|
|
383
439
|
onCountryCodeChange,
|
|
440
|
+
countryCodeName,
|
|
384
441
|
...props
|
|
385
442
|
}) => {
|
|
386
443
|
const {
|
|
@@ -399,9 +456,13 @@ 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;
|
|
403
465
|
const handleCountryCodeChange = /* @__PURE__ */__name(code => {
|
|
404
|
-
setCountryCode(code);
|
|
405
466
|
onCountryCodeChange?.(code);
|
|
406
467
|
}, "handleCountryCodeChange");
|
|
407
468
|
const isManual = countryCode === MANUAL_PHONE_COUNTRY_CODE;
|
|
@@ -414,7 +475,16 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
414
475
|
return countryCode && !isManual ? `${countryCode} ${baseFormat}` : baseFormat;
|
|
415
476
|
}, "getFormat");
|
|
416
477
|
const showDropdown = countryCodeOptions.length > 0;
|
|
417
|
-
|
|
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, {
|
|
418
488
|
id,
|
|
419
489
|
label,
|
|
420
490
|
name,
|
|
@@ -473,7 +543,8 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
473
543
|
return inputNode;
|
|
474
544
|
}
|
|
475
545
|
return /* @__PURE__ */React4.createElement(PhoneDropdownWrapper, {
|
|
476
|
-
|
|
546
|
+
countryCodeFieldName,
|
|
547
|
+
defaultCountryCode,
|
|
477
548
|
countryCodeOptions,
|
|
478
549
|
disabled: disabled ?? field.disabled,
|
|
479
550
|
onCountryCodeChange: handleCountryCodeChange,
|
|
@@ -483,7 +554,7 @@ var FormFieldPhone = /* @__PURE__ */__name(({
|
|
|
483
554
|
inputNode
|
|
484
555
|
});
|
|
485
556
|
}, "render")
|
|
486
|
-
});
|
|
557
|
+
}));
|
|
487
558
|
}, "FormFieldPhone");
|
|
488
559
|
|
|
489
560
|
// src/Brazil/FormFieldCNPJ.tsx
|
|
@@ -658,4 +729,4 @@ var FormFieldCPF = /* @__PURE__ */__name(({
|
|
|
658
729
|
}, "render")
|
|
659
730
|
});
|
|
660
731
|
}, "FormFieldCPF");
|
|
661
|
-
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.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -40,25 +40,25 @@
|
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": ">=16.8.0",
|
|
43
|
-
"@ttoss/components": "^2.
|
|
44
|
-
"@ttoss/
|
|
45
|
-
"@ttoss/
|
|
43
|
+
"@ttoss/components": "^2.14.5",
|
|
44
|
+
"@ttoss/ui": "^6.9.5",
|
|
45
|
+
"@ttoss/react-i18n": "^2.2.5"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/jest": "^30.0.0",
|
|
49
49
|
"@types/react": "^19.2.14",
|
|
50
|
-
"jest": "^30.
|
|
50
|
+
"jest": "^30.3.0",
|
|
51
51
|
"react": "^19.2.4",
|
|
52
52
|
"react-error-boundary": "^6.1.0",
|
|
53
53
|
"tsup": "^8.5.1",
|
|
54
54
|
"yup": "^1.7.1",
|
|
55
|
-
"@ttoss/
|
|
56
|
-
"@ttoss/
|
|
57
|
-
"@ttoss/
|
|
58
|
-
"@ttoss/react-icons": "^0.
|
|
59
|
-
"@ttoss/test-utils": "^4.
|
|
60
|
-
"@ttoss/react-i18n": "^2.
|
|
61
|
-
"@ttoss/ui": "^6.
|
|
55
|
+
"@ttoss/components": "^2.14.5",
|
|
56
|
+
"@ttoss/i18n-cli": "^0.8.5",
|
|
57
|
+
"@ttoss/config": "^1.37.5",
|
|
58
|
+
"@ttoss/react-icons": "^0.7.5",
|
|
59
|
+
"@ttoss/test-utils": "^4.2.5",
|
|
60
|
+
"@ttoss/react-i18n": "^2.2.5",
|
|
61
|
+
"@ttoss/ui": "^6.9.5"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public",
|