@ttoss/forms 0.17.11 → 0.17.13
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 +81 -8
- package/dist/esm/index.js +76 -8
- package/dist/index.js +62 -10
- package/package.json +8 -5
- package/src/ErrorMessage.tsx +28 -6
- package/src/i18n.ts +31 -0
- package/src/index.ts +2 -0
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```shell
|
|
8
|
-
|
|
8
|
+
pnpm i @ttoss/forms @ttoss/react-i18n
|
|
9
|
+
pnpm i --save-dev @ttoss/i18n-cli
|
|
9
10
|
```
|
|
10
11
|
|
|
11
12
|
## Quick Start
|
|
@@ -13,6 +14,7 @@ yarn add @ttoss/forms
|
|
|
13
14
|
```tsx
|
|
14
15
|
import { Button } from '@ttoss/ui';
|
|
15
16
|
import { Form, FormField, yupResolver, useForm, yup } from '@ttoss/forms';
|
|
17
|
+
import { I18nProvider } from '@ttoss/react-i18n';
|
|
16
18
|
|
|
17
19
|
const schema = yup.object({
|
|
18
20
|
firstName: yup.string().required('First name is required'),
|
|
@@ -27,16 +29,20 @@ export const FormComponent = () => {
|
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
return (
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
<I18nProvider>
|
|
33
|
+
<Form {...formMethods} onSubmit={action('onSubmit')}>
|
|
34
|
+
<FormField.Input name="firstName" label="First Name" />
|
|
35
|
+
<FormField.Input name="age" label="Age" />
|
|
36
|
+
<FormField.Checkbox name="receiveEmails" label="Receive Emails" />
|
|
37
|
+
<Button type="submit">Submit</Button>
|
|
38
|
+
</Form>
|
|
39
|
+
</I18nProvider>
|
|
36
40
|
);
|
|
37
41
|
};
|
|
38
42
|
```
|
|
39
43
|
|
|
44
|
+
**WARNING:** I18n is necessary as `Forms` module has some integrations with it.
|
|
45
|
+
|
|
40
46
|
## FormFieldSelect support for Default Value
|
|
41
47
|
|
|
42
48
|
FormFieldSelect has support for default values, by assigning the first option defined or the value passed to it in the parameter `defaultValue`.
|
|
@@ -148,4 +154,71 @@ const RenderForm = () => {
|
|
|
148
154
|
};
|
|
149
155
|
```
|
|
150
156
|
|
|
151
|
-
|
|
157
|
+
## Yup Validation
|
|
158
|
+
|
|
159
|
+
You can also use yup and all of API from react-hook-form importing `import { yup, useForm } from @ttoss/forms`
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
const FirstNameForm = () => {
|
|
163
|
+
const schema = yup.object({
|
|
164
|
+
firstName: yup.string().required(),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const formMethods = useForm({
|
|
168
|
+
resolver: yupResolver(schema),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<Form {...formMethods} onSubmit={onSubmit}>
|
|
173
|
+
<FormField
|
|
174
|
+
name="firstName"
|
|
175
|
+
label="First Name"
|
|
176
|
+
defaultValue={''}
|
|
177
|
+
render={({ field }) => {
|
|
178
|
+
return <Input {...field} />;
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
<Button type="submit">Submit</Button>
|
|
182
|
+
</Form>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
When field is invalid according with schema requirements, it gonna return the default. In this example, for required fields, it gonna be `Field is required`.
|
|
188
|
+
|
|
189
|
+
You can translate the message or change the generic message by configuring the messages in the json i18n definition. To use this, please, refer to the docs on [React-i18n](https://ttoss.dev/docs/modules/packages/react-i18n/) and [i18n-CLI](https://ttoss.dev/docs/modules/packages/i18n-cli/).
|
|
190
|
+
|
|
191
|
+
### Custom Error messages
|
|
192
|
+
|
|
193
|
+
You can, also, pass custom error messages to the validation constraints in schema. It's really recommended that you use i18n pattern to create your custom message.
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
const ComponentForm = () => {
|
|
197
|
+
const {
|
|
198
|
+
intl: { formatMessage },
|
|
199
|
+
} = useI18n();
|
|
200
|
+
|
|
201
|
+
const schema = useMemo(() => {
|
|
202
|
+
return yup.object({
|
|
203
|
+
name: yup.string().required(
|
|
204
|
+
formatMessage({
|
|
205
|
+
defaultMessage: 'Name must be not null',
|
|
206
|
+
description: 'Name required constraint',
|
|
207
|
+
})
|
|
208
|
+
),
|
|
209
|
+
age: yup.number().min(
|
|
210
|
+
18,
|
|
211
|
+
formatMessage(
|
|
212
|
+
{
|
|
213
|
+
defaultMessage: 'You should be {age} years old or more',
|
|
214
|
+
description: 'Min Age Constriant message',
|
|
215
|
+
},
|
|
216
|
+
{ age: 18 }
|
|
217
|
+
)
|
|
218
|
+
),
|
|
219
|
+
});
|
|
220
|
+
}, [formatMessage]);
|
|
221
|
+
|
|
222
|
+
// ...
|
|
223
|
+
};
|
|
224
|
+
```
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
|
|
3
|
+
// tsup.inject.js
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
// src/i18n.ts
|
|
7
|
+
import { defineMessage } from "@ttoss/react-i18n";
|
|
8
|
+
import { setLocale } from "yup";
|
|
9
|
+
setLocale({
|
|
10
|
+
mixed: {
|
|
11
|
+
required: defineMessage({
|
|
12
|
+
id: "MfWGyg",
|
|
13
|
+
defaultMessage: [{
|
|
14
|
+
"type": 0,
|
|
15
|
+
"value": "Field is required"
|
|
16
|
+
}]
|
|
17
|
+
}),
|
|
18
|
+
notType: ({
|
|
19
|
+
type
|
|
20
|
+
}) => {
|
|
21
|
+
return {
|
|
22
|
+
...defineMessage({
|
|
23
|
+
id: "ZhaPt0",
|
|
24
|
+
defaultMessage: [{
|
|
25
|
+
"type": 0,
|
|
26
|
+
"value": "Invalid Value for Field of type "
|
|
27
|
+
}, {
|
|
28
|
+
"type": 1,
|
|
29
|
+
"value": "type"
|
|
30
|
+
}]
|
|
31
|
+
}),
|
|
32
|
+
values: {
|
|
33
|
+
type
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
string: {
|
|
39
|
+
min: ({
|
|
40
|
+
min
|
|
41
|
+
}) => {
|
|
42
|
+
return {
|
|
43
|
+
...defineMessage({
|
|
44
|
+
id: "D1C6fR",
|
|
45
|
+
defaultMessage: [{
|
|
46
|
+
"type": 0,
|
|
47
|
+
"value": "Field must be at least "
|
|
48
|
+
}, {
|
|
49
|
+
"type": 1,
|
|
50
|
+
"value": "min"
|
|
51
|
+
}, {
|
|
52
|
+
"type": 0,
|
|
53
|
+
"value": " characters"
|
|
54
|
+
}]
|
|
55
|
+
}),
|
|
56
|
+
values: {
|
|
57
|
+
min
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
3
64
|
// src/index.ts
|
|
4
65
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
5
66
|
export * from "react-hook-form";
|
|
@@ -34,9 +95,12 @@ import * as React2 from "react";
|
|
|
34
95
|
|
|
35
96
|
// src/ErrorMessage.tsx
|
|
36
97
|
import { useFormContext } from "react-hook-form";
|
|
98
|
+
import { FormattedMessage } from "@ttoss/react-i18n";
|
|
37
99
|
import { HelpText } from "@ttoss/ui";
|
|
38
|
-
import { ErrorMessage as HookFormErrorMessage } from "@hookform/error-message";
|
|
39
100
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
101
|
+
var isMessageDescriptor = possibleMessageDescriptor => {
|
|
102
|
+
return possibleMessageDescriptor !== void 0 && possibleMessageDescriptor.defaultMessage !== void 0;
|
|
103
|
+
};
|
|
40
104
|
var ErrorMessage = ({
|
|
41
105
|
name,
|
|
42
106
|
disabled
|
|
@@ -46,13 +110,17 @@ var ErrorMessage = ({
|
|
|
46
110
|
errors
|
|
47
111
|
}
|
|
48
112
|
} = useFormContext();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
113
|
+
const error = errors[name];
|
|
114
|
+
if (!error) return null;
|
|
115
|
+
const {
|
|
116
|
+
message
|
|
117
|
+
} = error;
|
|
118
|
+
return error && /* @__PURE__ */jsx2(HelpText, {
|
|
119
|
+
negative: true,
|
|
120
|
+
disabled,
|
|
121
|
+
children: isMessageDescriptor(message) ? /* @__PURE__ */jsx2(FormattedMessage, {
|
|
122
|
+
...message
|
|
123
|
+
}) : message
|
|
56
124
|
});
|
|
57
125
|
};
|
|
58
126
|
|
package/dist/index.js
CHANGED
|
@@ -50,10 +50,55 @@ __export(src_exports, {
|
|
|
50
50
|
FormGroup: () => FormGroup,
|
|
51
51
|
useFormGroup: () => useFormGroup,
|
|
52
52
|
yup: () => yup,
|
|
53
|
-
yupResolver: () =>
|
|
53
|
+
yupResolver: () => import_yup2.yupResolver
|
|
54
54
|
});
|
|
55
55
|
module.exports = __toCommonJS(src_exports);
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
// tsup.inject.js
|
|
58
|
+
var React = __toESM(require("react"));
|
|
59
|
+
|
|
60
|
+
// src/i18n.ts
|
|
61
|
+
var import_react_i18n = require("@ttoss/react-i18n");
|
|
62
|
+
var import_yup = require("yup");
|
|
63
|
+
(0, import_yup.setLocale)({
|
|
64
|
+
mixed: {
|
|
65
|
+
required: (0, import_react_i18n.defineMessage)({
|
|
66
|
+
defaultMessage: "Field is required",
|
|
67
|
+
description: "Field is required"
|
|
68
|
+
}),
|
|
69
|
+
notType: ({
|
|
70
|
+
type
|
|
71
|
+
}) => {
|
|
72
|
+
return {
|
|
73
|
+
...(0, import_react_i18n.defineMessage)({
|
|
74
|
+
defaultMessage: "Invalid Value for Field of type {type}",
|
|
75
|
+
description: "Invalid Value"
|
|
76
|
+
}),
|
|
77
|
+
values: {
|
|
78
|
+
type
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
string: {
|
|
84
|
+
min: ({
|
|
85
|
+
min
|
|
86
|
+
}) => {
|
|
87
|
+
return {
|
|
88
|
+
...(0, import_react_i18n.defineMessage)({
|
|
89
|
+
defaultMessage: "Field must be at least {min} characters",
|
|
90
|
+
description: "Min length field"
|
|
91
|
+
}),
|
|
92
|
+
values: {
|
|
93
|
+
min
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// src/index.ts
|
|
101
|
+
var import_yup2 = require("@hookform/resolvers/yup");
|
|
57
102
|
__reExport(src_exports, require("react-hook-form"), module.exports);
|
|
58
103
|
var yup = __toESM(require("yup"));
|
|
59
104
|
|
|
@@ -86,9 +131,12 @@ var React2 = __toESM(require("react"));
|
|
|
86
131
|
|
|
87
132
|
// src/ErrorMessage.tsx
|
|
88
133
|
var import_react_hook_form2 = require("react-hook-form");
|
|
134
|
+
var import_react_i18n2 = require("@ttoss/react-i18n");
|
|
89
135
|
var import_ui2 = require("@ttoss/ui");
|
|
90
|
-
var import_error_message = require("@hookform/error-message");
|
|
91
136
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
137
|
+
var isMessageDescriptor = possibleMessageDescriptor => {
|
|
138
|
+
return possibleMessageDescriptor !== void 0 && possibleMessageDescriptor.defaultMessage !== void 0;
|
|
139
|
+
};
|
|
92
140
|
var ErrorMessage = ({
|
|
93
141
|
name,
|
|
94
142
|
disabled
|
|
@@ -98,13 +146,17 @@ var ErrorMessage = ({
|
|
|
98
146
|
errors
|
|
99
147
|
}
|
|
100
148
|
} = (0, import_react_hook_form2.useFormContext)();
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
149
|
+
const error = errors[name];
|
|
150
|
+
if (!error) return null;
|
|
151
|
+
const {
|
|
152
|
+
message
|
|
153
|
+
} = error;
|
|
154
|
+
return error && /* @__PURE__ */(0, import_jsx_runtime2.jsx)(import_ui2.HelpText, {
|
|
155
|
+
negative: true,
|
|
156
|
+
disabled,
|
|
157
|
+
children: isMessageDescriptor(message) ? /* @__PURE__ */(0, import_jsx_runtime2.jsx)(import_react_i18n2.FormattedMessage, {
|
|
158
|
+
...message
|
|
159
|
+
}) : message
|
|
108
160
|
});
|
|
109
161
|
};
|
|
110
162
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/forms",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.13",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -12,30 +12,33 @@
|
|
|
12
12
|
"dist",
|
|
13
13
|
"src"
|
|
14
14
|
],
|
|
15
|
-
"sideEffects":
|
|
15
|
+
"sideEffects": true,
|
|
16
16
|
"typings": "dist/index.d.ts",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@hookform/error-message": "^2.0.1",
|
|
19
18
|
"@hookform/resolvers": "^3.1.0",
|
|
20
19
|
"react-hook-form": "^7.43.9",
|
|
21
20
|
"yup": "^1.1.1"
|
|
22
21
|
},
|
|
23
22
|
"peerDependencies": {
|
|
24
23
|
"react": ">=16.8.0",
|
|
25
|
-
"@ttoss/
|
|
24
|
+
"@ttoss/react-i18n": "^1.23.0",
|
|
25
|
+
"@ttoss/ui": "^1.36.11"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/jest": "^29.5.1",
|
|
29
29
|
"@types/react": "^18.2.6",
|
|
30
30
|
"jest": "^29.5.0",
|
|
31
31
|
"react": "^18.2.0",
|
|
32
|
+
"react-error-boundary": "^4.0.9",
|
|
32
33
|
"react-hook-form": "^7.43.9",
|
|
33
34
|
"theme-ui": "^0.15.7",
|
|
34
35
|
"tsup": "^6.7.0",
|
|
35
36
|
"yup": "^1.1.1",
|
|
36
37
|
"@ttoss/config": "^1.30.0",
|
|
38
|
+
"@ttoss/i18n-cli": "^0.5.0",
|
|
39
|
+
"@ttoss/react-i18n": "^1.23.0",
|
|
37
40
|
"@ttoss/test-utils": "^1.23.1",
|
|
38
|
-
"@ttoss/ui": "^1.36.
|
|
41
|
+
"@ttoss/ui": "^1.36.11"
|
|
39
42
|
},
|
|
40
43
|
"publishConfig": {
|
|
41
44
|
"access": "public"
|
package/src/ErrorMessage.tsx
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { FieldName, FieldValues, useFormContext } from 'react-hook-form';
|
|
2
|
+
import { FormattedMessage, MessageDescriptor } from '@ttoss/react-i18n';
|
|
2
3
|
import { HelpText } from '@ttoss/ui';
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
type ModifiedDescriptor = MessageDescriptor & { values?: any };
|
|
6
|
+
|
|
7
|
+
const isMessageDescriptor = (
|
|
8
|
+
possibleMessageDescriptor: unknown
|
|
9
|
+
): possibleMessageDescriptor is ModifiedDescriptor => {
|
|
10
|
+
return (
|
|
11
|
+
possibleMessageDescriptor !== undefined &&
|
|
12
|
+
(possibleMessageDescriptor as ModifiedDescriptor).defaultMessage !==
|
|
13
|
+
undefined
|
|
14
|
+
);
|
|
15
|
+
};
|
|
4
16
|
|
|
5
17
|
export const ErrorMessage = <TFieldValues extends FieldValues = FieldValues>({
|
|
6
18
|
name,
|
|
@@ -13,11 +25,21 @@ export const ErrorMessage = <TFieldValues extends FieldValues = FieldValues>({
|
|
|
13
25
|
formState: { errors },
|
|
14
26
|
} = useFormContext<TFieldValues>();
|
|
15
27
|
|
|
28
|
+
const error = errors[name];
|
|
29
|
+
|
|
30
|
+
if (!error) return null;
|
|
31
|
+
|
|
32
|
+
const { message } = error;
|
|
33
|
+
|
|
16
34
|
return (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
error && (
|
|
36
|
+
<HelpText negative disabled={disabled}>
|
|
37
|
+
{isMessageDescriptor(message) ? (
|
|
38
|
+
<FormattedMessage {...message} />
|
|
39
|
+
) : (
|
|
40
|
+
(message as string)
|
|
41
|
+
)}
|
|
42
|
+
</HelpText>
|
|
43
|
+
)
|
|
22
44
|
);
|
|
23
45
|
};
|
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineMessage } from '@ttoss/react-i18n';
|
|
2
|
+
import { setLocale } from 'yup';
|
|
3
|
+
|
|
4
|
+
setLocale({
|
|
5
|
+
mixed: {
|
|
6
|
+
required: defineMessage({
|
|
7
|
+
defaultMessage: 'Field is required',
|
|
8
|
+
description: 'Field is required',
|
|
9
|
+
}),
|
|
10
|
+
notType: ({ type }) => {
|
|
11
|
+
return {
|
|
12
|
+
...defineMessage({
|
|
13
|
+
defaultMessage: 'Invalid Value for Field of type {type}',
|
|
14
|
+
description: 'Invalid Value',
|
|
15
|
+
}),
|
|
16
|
+
values: { type },
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
string: {
|
|
21
|
+
min: ({ min }) => {
|
|
22
|
+
return {
|
|
23
|
+
...defineMessage({
|
|
24
|
+
defaultMessage: 'Field must be at least {min} characters',
|
|
25
|
+
description: 'Min length field',
|
|
26
|
+
}),
|
|
27
|
+
values: { min },
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|