@ttoss/forms 0.17.12 → 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 CHANGED
@@ -5,7 +5,8 @@
5
5
  ## Installation
6
6
 
7
7
  ```shell
8
- yarn add @ttoss/forms
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
- <Form {...formMethods} onSubmit={action('onSubmit')}>
31
- <FormField.Input name="firstName" label="First Name" />
32
- <FormField.Input name="age" label="Age" />
33
- <FormField.Checkbox name="receiveEmails" label="Receive Emails" />
34
- <Button type="submit">Submit</Button>
35
- </Form>
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
- > NOTE: You can also use yup and all of API from react-hook-form importing `import { yup, useForm } from @ttoss/forms`
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
- return /* @__PURE__ */jsx2(HookFormErrorMessage, {
50
- errors,
51
- name,
52
- as: /* @__PURE__ */jsx2(HelpText, {
53
- negative: true,
54
- disabled
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: () => import_yup.yupResolver
53
+ yupResolver: () => import_yup2.yupResolver
54
54
  });
55
55
  module.exports = __toCommonJS(src_exports);
56
- var import_yup = require("@hookform/resolvers/yup");
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
- return /* @__PURE__ */(0, import_jsx_runtime2.jsx)(import_error_message.ErrorMessage, {
102
- errors,
103
- name,
104
- as: /* @__PURE__ */(0, import_jsx_runtime2.jsx)(import_ui2.HelpText, {
105
- negative: true,
106
- disabled
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.12",
3
+ "version": "0.17.13",
4
4
  "license": "UNLICENSED",
5
5
  "author": "ttoss",
6
6
  "contributors": [
@@ -12,16 +12,16 @@
12
12
  "dist",
13
13
  "src"
14
14
  ],
15
- "sideEffects": false,
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",
24
+ "@ttoss/react-i18n": "^1.23.0",
25
25
  "@ttoss/ui": "^1.36.11"
26
26
  },
27
27
  "devDependencies": {
@@ -29,11 +29,14 @@
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
41
  "@ttoss/ui": "^1.36.11"
39
42
  },
@@ -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
- import { ErrorMessage as HookFormErrorMessage } from '@hookform/error-message';
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
- <HookFormErrorMessage
18
- errors={errors}
19
- name={name as any}
20
- as={<HelpText negative disabled={disabled} />}
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
+ });
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import './i18n';
2
+
1
3
  export { yupResolver } from '@hookform/resolvers/yup';
2
4
  export * from 'react-hook-form';
3
5
  export * as yup from 'yup';