@ttoss/forms 0.5.12 → 0.6.0

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 ADDED
@@ -0,0 +1,40 @@
1
+ # @ttoss/forms
2
+
3
+ **@ttoss/forms** is a library of React form components for building form components. It is built on top of [React Hook Form](https://react-hook-form.com/) and [Yup](https://github.com/jquense/yup).
4
+
5
+ ## Installation
6
+
7
+ ```shell
8
+ yarn add @ttoss/forms react-hook-form yup
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import * as yup from 'yup';
15
+ import { Button } from '@ttoss/ui';
16
+ import { Form, FormField, yupResolver } from '@ttoss/forms';
17
+ import { useForm } from 'react-hook-form';
18
+
19
+ const schema = yup.object({
20
+ firstName: yup.string().required('First name is required'),
21
+ age: yup.number().required('Age is required'),
22
+ receiveEmails: yup.boolean(),
23
+ });
24
+
25
+ export const FormComponent = () => {
26
+ const formMethods = useForm({
27
+ mode: 'all',
28
+ resolver: yupResolver(schema),
29
+ });
30
+
31
+ return (
32
+ <Form {...formMethods} onSubmit={action('onSubmit')}>
33
+ <FormField.Input name="firstName" label="First Name" />
34
+ <FormField.Input name="age" label="Age" />
35
+ <FormField.Checkbox name="receiveEmails" label="Receive Emails" />
36
+ <Button type="submit">Submit</Button>
37
+ </Form>
38
+ );
39
+ };
40
+ ```
package/dist/esm/index.js CHANGED
@@ -18,15 +18,17 @@ var Form = ({
18
18
  children: /* @__PURE__ */ jsx(Box, {
19
19
  as: "form",
20
20
  variant: "forms.form",
21
- onSubmit: formMethods.handleSubmit((data) => onSubmit(data)),
21
+ onSubmit: formMethods.handleSubmit((data) => {
22
+ return onSubmit(data);
23
+ }),
22
24
  sx,
23
25
  children
24
26
  })
25
27
  });
26
28
  };
27
29
 
28
- // src/FormFieldInput.tsx
29
- import { Box as Box2, Input, Label } from "@ttoss/ui";
30
+ // src/FormFieldCheckbox.tsx
31
+ import { Box as Box2, Checkbox, Flex, Label } from "@ttoss/ui";
30
32
 
31
33
  // src/ErrorMessage.tsx
32
34
  import { useFormContext } from "react-hook-form";
@@ -49,27 +51,67 @@ var ErrorMessage = ({
49
51
  });
50
52
  };
51
53
 
52
- // src/FormFieldInput.tsx
54
+ // src/FormFieldCheckbox.tsx
53
55
  import { useController } from "react-hook-form";
54
56
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
55
- var FormFieldInput = ({
57
+ var FormFieldCheckbox = ({
56
58
  label,
57
59
  name
58
60
  }) => {
59
61
  const {
60
62
  field: { onChange, onBlur, value, ref }
61
63
  } = useController({
64
+ name,
65
+ defaultValue: false
66
+ });
67
+ const id = `form-field-checkbox-${name}`;
68
+ return /* @__PURE__ */ jsxs(Box2, {
69
+ children: [
70
+ /* @__PURE__ */ jsxs(Flex, {
71
+ sx: { alignItems: "center" },
72
+ children: [
73
+ /* @__PURE__ */ jsx3(Checkbox, {
74
+ id,
75
+ ref,
76
+ checked: value,
77
+ onChange,
78
+ onBlur
79
+ }),
80
+ label && /* @__PURE__ */ jsx3(Label, {
81
+ htmlFor: id,
82
+ children: label
83
+ })
84
+ ]
85
+ }),
86
+ /* @__PURE__ */ jsx3(ErrorMessage, {
87
+ name
88
+ })
89
+ ]
90
+ });
91
+ };
92
+
93
+ // src/FormFieldInput.tsx
94
+ import { Box as Box3, Input, Label as Label2 } from "@ttoss/ui";
95
+ import { useController as useController2 } from "react-hook-form";
96
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
97
+ var FormFieldInput = ({
98
+ label,
99
+ name
100
+ }) => {
101
+ const {
102
+ field: { onChange, onBlur, value, ref }
103
+ } = useController2({
62
104
  name,
63
105
  defaultValue: ""
64
106
  });
65
107
  const id = `form-field-input-${name}`;
66
- return /* @__PURE__ */ jsxs(Box2, {
108
+ return /* @__PURE__ */ jsxs2(Box3, {
67
109
  children: [
68
- label && /* @__PURE__ */ jsx3(Label, {
110
+ label && /* @__PURE__ */ jsx4(Label2, {
69
111
  htmlFor: id,
70
112
  children: label
71
113
  }),
72
- /* @__PURE__ */ jsx3(Input, {
114
+ /* @__PURE__ */ jsx4(Input, {
73
115
  ref,
74
116
  onChange,
75
117
  onBlur,
@@ -77,7 +119,7 @@ var FormFieldInput = ({
77
119
  name,
78
120
  id
79
121
  }),
80
- /* @__PURE__ */ jsx3(ErrorMessage, {
122
+ /* @__PURE__ */ jsx4(ErrorMessage, {
81
123
  name
82
124
  })
83
125
  ]
@@ -85,9 +127,9 @@ var FormFieldInput = ({
85
127
  };
86
128
 
87
129
  // src/FormFieldRadio.tsx
88
- import { Box as Box3, Label as Label2, Radio } from "@ttoss/ui";
89
- import { useController as useController2 } from "react-hook-form";
90
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
130
+ import { Box as Box4, Label as Label3, Radio } from "@ttoss/ui";
131
+ import { useController as useController3 } from "react-hook-form";
132
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
91
133
  var FormFieldRadio = ({
92
134
  label,
93
135
  name,
@@ -95,23 +137,22 @@ var FormFieldRadio = ({
95
137
  }) => {
96
138
  const {
97
139
  field: { onChange, onBlur, value, ref }
98
- } = useController2({
140
+ } = useController3({
99
141
  name,
100
142
  defaultValue: ""
101
143
  });
102
- return /* @__PURE__ */ jsxs2(Box3, {
144
+ return /* @__PURE__ */ jsxs3(Box4, {
103
145
  children: [
104
- label && /* @__PURE__ */ jsx4(Label2, {
146
+ label && /* @__PURE__ */ jsx5(Label3, {
105
147
  children: label
106
148
  }),
107
- /* @__PURE__ */ jsx4(Box3, {
108
- variant: "form.radios",
149
+ /* @__PURE__ */ jsx5(Box4, {
109
150
  children: options.map((option) => {
110
151
  const id = `form-field-radio-${name}-${option.value}`;
111
- return /* @__PURE__ */ jsxs2(Label2, {
152
+ return /* @__PURE__ */ jsxs3(Label3, {
112
153
  htmlFor: id,
113
154
  children: [
114
- /* @__PURE__ */ jsx4(Radio, {
155
+ /* @__PURE__ */ jsx5(Radio, {
115
156
  ref,
116
157
  onChange,
117
158
  onBlur,
@@ -125,7 +166,7 @@ var FormFieldRadio = ({
125
166
  }, id);
126
167
  })
127
168
  }),
128
- /* @__PURE__ */ jsx4(ErrorMessage, {
169
+ /* @__PURE__ */ jsx5(ErrorMessage, {
129
170
  name
130
171
  })
131
172
  ]
@@ -133,9 +174,9 @@ var FormFieldRadio = ({
133
174
  };
134
175
 
135
176
  // src/FormFieldSelect.tsx
136
- import { Box as Box4, Label as Label3, Select } from "@ttoss/ui";
137
- import { useController as useController3 } from "react-hook-form";
138
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
177
+ import { Box as Box5, Label as Label4, Select } from "@ttoss/ui";
178
+ import { useController as useController4 } from "react-hook-form";
179
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
139
180
  var FormFieldSelect = ({
140
181
  label,
141
182
  name,
@@ -144,34 +185,33 @@ var FormFieldSelect = ({
144
185
  }) => {
145
186
  const {
146
187
  field: { onChange, onBlur, value, ref }
147
- } = useController3({
188
+ } = useController4({
148
189
  name,
149
190
  defaultValue: ""
150
191
  });
151
192
  const id = `form-field-select-${name}`;
152
- return /* @__PURE__ */ jsxs3(Box4, {
193
+ return /* @__PURE__ */ jsxs4(Box5, {
153
194
  children: [
154
- label && /* @__PURE__ */ jsx5(Label3, {
195
+ label && /* @__PURE__ */ jsx6(Label4, {
155
196
  htmlFor: id,
156
197
  children: label
157
198
  }),
158
- /* @__PURE__ */ jsx5(Select, {
199
+ /* @__PURE__ */ jsx6(Select, {
159
200
  ref,
160
201
  name,
161
202
  onChange,
162
203
  onBlur,
163
204
  value,
164
205
  arrow,
165
- variant: "form.select",
206
+ id,
166
207
  children: options.map((option) => {
167
- return /* @__PURE__ */ jsx5("option", {
208
+ return /* @__PURE__ */ jsx6("option", {
168
209
  value: option.value,
169
- id,
170
210
  children: option.label
171
- }, id);
211
+ }, option.label);
172
212
  })
173
213
  }),
174
- /* @__PURE__ */ jsx5(ErrorMessage, {
214
+ /* @__PURE__ */ jsx6(ErrorMessage, {
175
215
  name
176
216
  })
177
217
  ]
@@ -185,7 +225,12 @@ var FormField = () => {
185
225
  FormField.Input = FormFieldInput;
186
226
  FormField.Radio = FormFieldRadio;
187
227
  FormField.Select = FormFieldSelect;
228
+ FormField.Checkbox = FormFieldCheckbox;
229
+
230
+ // src/index.ts
231
+ import { yupResolver } from "@hookform/resolvers/yup";
188
232
  export {
189
233
  Form,
190
- FormField
234
+ FormField,
235
+ yupResolver
191
236
  };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as react_hook_form from 'react-hook-form';
2
2
  import { FieldValues } from 'react-hook-form';
3
3
  import * as React from 'react';
4
4
  import { BoxProps } from '@ttoss/ui';
5
+ export { yupResolver } from '@hookform/resolvers/yup';
5
6
 
6
7
  declare const Form: <TFieldValues extends FieldValues = FieldValues>({ children, onSubmit, sx, ...formMethods }: {
7
8
  children?: React.ReactNode;
@@ -34,6 +35,10 @@ declare const FormField: {
34
35
  }[];
35
36
  arrow?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
36
37
  }) => JSX.Element;
38
+ Checkbox: <TFieldValues_3 extends react_hook_form.FieldValues = react_hook_form.FieldValues>({ label, name, }: {
39
+ label?: string | undefined;
40
+ name: react_hook_form.Path<TFieldValues_3>;
41
+ }) => JSX.Element;
37
42
  };
38
43
 
39
44
  export { Form, FormField };
package/dist/index.js CHANGED
@@ -28,7 +28,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
28
28
  var src_exports = {};
29
29
  __export(src_exports, {
30
30
  Form: () => Form,
31
- FormField: () => FormField
31
+ FormField: () => FormField,
32
+ yupResolver: () => import_yup.yupResolver
32
33
  });
33
34
  module.exports = __toCommonJS(src_exports);
34
35
 
@@ -50,14 +51,16 @@ var Form = ({
50
51
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.Box, {
51
52
  as: "form",
52
53
  variant: "forms.form",
53
- onSubmit: formMethods.handleSubmit((data) => onSubmit(data)),
54
+ onSubmit: formMethods.handleSubmit((data) => {
55
+ return onSubmit(data);
56
+ }),
54
57
  sx,
55
58
  children
56
59
  })
57
60
  });
58
61
  };
59
62
 
60
- // src/FormFieldInput.tsx
63
+ // src/FormFieldCheckbox.tsx
61
64
  var import_ui3 = require("@ttoss/ui");
62
65
 
63
66
  // src/ErrorMessage.tsx
@@ -81,27 +84,67 @@ var ErrorMessage = ({
81
84
  });
82
85
  };
83
86
 
84
- // src/FormFieldInput.tsx
87
+ // src/FormFieldCheckbox.tsx
85
88
  var import_react_hook_form3 = require("react-hook-form");
86
89
  var import_jsx_runtime3 = require("react/jsx-runtime");
87
- var FormFieldInput = ({
90
+ var FormFieldCheckbox = ({
88
91
  label,
89
92
  name
90
93
  }) => {
91
94
  const {
92
95
  field: { onChange, onBlur, value, ref }
93
96
  } = (0, import_react_hook_form3.useController)({
97
+ name,
98
+ defaultValue: false
99
+ });
100
+ const id = `form-field-checkbox-${name}`;
101
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Box, {
102
+ children: [
103
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Flex, {
104
+ sx: { alignItems: "center" },
105
+ children: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Checkbox, {
107
+ id,
108
+ ref,
109
+ checked: value,
110
+ onChange,
111
+ onBlur
112
+ }),
113
+ label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Label, {
114
+ htmlFor: id,
115
+ children: label
116
+ })
117
+ ]
118
+ }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorMessage, {
120
+ name
121
+ })
122
+ ]
123
+ });
124
+ };
125
+
126
+ // src/FormFieldInput.tsx
127
+ var import_ui4 = require("@ttoss/ui");
128
+ var import_react_hook_form4 = require("react-hook-form");
129
+ var import_jsx_runtime4 = require("react/jsx-runtime");
130
+ var FormFieldInput = ({
131
+ label,
132
+ name
133
+ }) => {
134
+ const {
135
+ field: { onChange, onBlur, value, ref }
136
+ } = (0, import_react_hook_form4.useController)({
94
137
  name,
95
138
  defaultValue: ""
96
139
  });
97
140
  const id = `form-field-input-${name}`;
98
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ui3.Box, {
141
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Box, {
99
142
  children: [
100
- label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Label, {
143
+ label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Label, {
101
144
  htmlFor: id,
102
145
  children: label
103
146
  }),
104
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ui3.Input, {
147
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Input, {
105
148
  ref,
106
149
  onChange,
107
150
  onBlur,
@@ -109,7 +152,7 @@ var FormFieldInput = ({
109
152
  name,
110
153
  id
111
154
  }),
112
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorMessage, {
155
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ErrorMessage, {
113
156
  name
114
157
  })
115
158
  ]
@@ -117,9 +160,9 @@ var FormFieldInput = ({
117
160
  };
118
161
 
119
162
  // src/FormFieldRadio.tsx
120
- var import_ui4 = require("@ttoss/ui");
121
- var import_react_hook_form4 = require("react-hook-form");
122
- var import_jsx_runtime4 = require("react/jsx-runtime");
163
+ var import_ui5 = require("@ttoss/ui");
164
+ var import_react_hook_form5 = require("react-hook-form");
165
+ var import_jsx_runtime5 = require("react/jsx-runtime");
123
166
  var FormFieldRadio = ({
124
167
  label,
125
168
  name,
@@ -127,23 +170,22 @@ var FormFieldRadio = ({
127
170
  }) => {
128
171
  const {
129
172
  field: { onChange, onBlur, value, ref }
130
- } = (0, import_react_hook_form4.useController)({
173
+ } = (0, import_react_hook_form5.useController)({
131
174
  name,
132
175
  defaultValue: ""
133
176
  });
134
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Box, {
177
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Box, {
135
178
  children: [
136
- label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Label, {
179
+ label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Label, {
137
180
  children: label
138
181
  }),
139
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Box, {
140
- variant: "form.radios",
182
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Box, {
141
183
  children: options.map((option) => {
142
184
  const id = `form-field-radio-${name}-${option.value}`;
143
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Label, {
185
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Label, {
144
186
  htmlFor: id,
145
187
  children: [
146
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Radio, {
188
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Radio, {
147
189
  ref,
148
190
  onChange,
149
191
  onBlur,
@@ -157,7 +199,7 @@ var FormFieldRadio = ({
157
199
  }, id);
158
200
  })
159
201
  }),
160
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ErrorMessage, {
202
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, {
161
203
  name
162
204
  })
163
205
  ]
@@ -165,9 +207,9 @@ var FormFieldRadio = ({
165
207
  };
166
208
 
167
209
  // src/FormFieldSelect.tsx
168
- var import_ui5 = require("@ttoss/ui");
169
- var import_react_hook_form5 = require("react-hook-form");
170
- var import_jsx_runtime5 = require("react/jsx-runtime");
210
+ var import_ui6 = require("@ttoss/ui");
211
+ var import_react_hook_form6 = require("react-hook-form");
212
+ var import_jsx_runtime6 = require("react/jsx-runtime");
171
213
  var FormFieldSelect = ({
172
214
  label,
173
215
  name,
@@ -176,34 +218,33 @@ var FormFieldSelect = ({
176
218
  }) => {
177
219
  const {
178
220
  field: { onChange, onBlur, value, ref }
179
- } = (0, import_react_hook_form5.useController)({
221
+ } = (0, import_react_hook_form6.useController)({
180
222
  name,
181
223
  defaultValue: ""
182
224
  });
183
225
  const id = `form-field-select-${name}`;
184
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Box, {
226
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Box, {
185
227
  children: [
186
- label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Label, {
228
+ label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Label, {
187
229
  htmlFor: id,
188
230
  children: label
189
231
  }),
190
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Select, {
232
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Select, {
191
233
  ref,
192
234
  name,
193
235
  onChange,
194
236
  onBlur,
195
237
  value,
196
238
  arrow,
197
- variant: "form.select",
239
+ id,
198
240
  children: options.map((option) => {
199
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", {
241
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", {
200
242
  value: option.value,
201
- id,
202
243
  children: option.label
203
- }, id);
244
+ }, option.label);
204
245
  })
205
246
  }),
206
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, {
247
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ErrorMessage, {
207
248
  name
208
249
  })
209
250
  ]
@@ -217,8 +258,13 @@ var FormField = () => {
217
258
  FormField.Input = FormFieldInput;
218
259
  FormField.Radio = FormFieldRadio;
219
260
  FormField.Select = FormFieldSelect;
261
+ FormField.Checkbox = FormFieldCheckbox;
262
+
263
+ // src/index.ts
264
+ var import_yup = require("@hookform/resolvers/yup");
220
265
  // Annotate the CommonJS export names for ESM import in node:
221
266
  0 && (module.exports = {
222
267
  Form,
223
- FormField
268
+ FormField,
269
+ yupResolver
224
270
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/forms",
3
- "version": "0.5.12",
3
+ "version": "0.6.0",
4
4
  "license": "UNLICENSED",
5
5
  "author": "ttoss",
6
6
  "contributors": [
@@ -18,22 +18,23 @@
18
18
  },
19
19
  "typings": "dist/index.d.ts",
20
20
  "dependencies": {
21
- "@hookform/error-message": "^2.0.0"
21
+ "@hookform/error-message": "^2.0.1",
22
+ "@hookform/resolvers": "^2.9.10"
22
23
  },
23
24
  "peerDependencies": {
24
- "@ttoss/ui": "^1.19.1",
25
+ "@ttoss/ui": "^1.23.0",
25
26
  "react": "^18.2.0",
26
- "react-hook-form": "^7.36.1"
27
+ "react-hook-form": "^7.39.7",
28
+ "yup": "^0.32.11"
27
29
  },
28
30
  "devDependencies": {
29
- "@hookform/resolvers": "^2.9.8",
30
31
  "@ttoss/config": "^1.18.3",
31
- "@ttoss/test-utils": "^1.16.10",
32
- "@ttoss/ui": "^1.23.1",
33
- "@types/jest": "^29.0.3",
34
- "jest": "^29.0.3",
32
+ "@ttoss/test-utils": "^1.17.0",
33
+ "@ttoss/ui": "^1.23.2",
34
+ "@types/jest": "^29.2.3",
35
+ "jest": "^29.3.1",
35
36
  "react": "^18.2.0",
36
- "react-hook-form": "^7.36.1",
37
+ "react-hook-form": "^7.39.7",
37
38
  "yup": "^0.32.11"
38
39
  },
39
40
  "engines": {
@@ -42,5 +43,5 @@
42
43
  "publishConfig": {
43
44
  "access": "public"
44
45
  },
45
- "gitHead": "e9c6b47f9b2ff9a44358a16c9feff84ba9342346"
46
+ "gitHead": "eaf4015635a5476a3b59beb3c35284404c1f07d5"
46
47
  }
package/src/Form.tsx CHANGED
@@ -17,7 +17,9 @@ export const Form = <TFieldValues extends FieldValues = FieldValues>({
17
17
  <Box
18
18
  as="form"
19
19
  variant="forms.form"
20
- onSubmit={formMethods.handleSubmit((data) => onSubmit(data))}
20
+ onSubmit={formMethods.handleSubmit((data) => {
21
+ return onSubmit(data);
22
+ })}
21
23
  sx={sx}
22
24
  >
23
25
  {children}
package/src/FormField.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ import { FormFieldCheckbox } from './FormFieldCheckbox';
1
2
  import { FormFieldInput } from './FormFieldInput';
2
3
  import { FormFieldRadio } from './FormFieldRadio';
3
4
  import { FormFieldSelect } from './FormFieldSelect';
@@ -11,4 +12,6 @@ FormField.Input = FormFieldInput;
11
12
  FormField.Radio = FormFieldRadio;
12
13
  FormField.Select = FormFieldSelect;
13
14
 
15
+ FormField.Checkbox = FormFieldCheckbox;
16
+
14
17
  export { FormField };
@@ -0,0 +1,38 @@
1
+ import { Box, Checkbox, Flex, Label } from '@ttoss/ui';
2
+ import { ErrorMessage } from './ErrorMessage';
3
+ import { FieldValues, Path, useController } from 'react-hook-form';
4
+
5
+ export const FormFieldCheckbox = <
6
+ TFieldValues extends FieldValues = FieldValues
7
+ >({
8
+ label,
9
+ name,
10
+ }: {
11
+ label?: string;
12
+ name: Path<TFieldValues>;
13
+ }) => {
14
+ const {
15
+ field: { onChange, onBlur, value, ref },
16
+ } = useController<any>({
17
+ name,
18
+ defaultValue: false,
19
+ });
20
+
21
+ const id = `form-field-checkbox-${name}`;
22
+
23
+ return (
24
+ <Box>
25
+ <Flex sx={{ alignItems: 'center' }}>
26
+ <Checkbox
27
+ id={id}
28
+ ref={ref}
29
+ checked={value}
30
+ onChange={onChange}
31
+ onBlur={onBlur}
32
+ />
33
+ {label && <Label htmlFor={id}>{label}</Label>}
34
+ </Flex>
35
+ <ErrorMessage name={name} />
36
+ </Box>
37
+ );
38
+ };
@@ -26,7 +26,7 @@ export const FormFieldRadio = <TFieldValues extends FieldValues = FieldValues>({
26
26
  return (
27
27
  <Box>
28
28
  {label && <Label>{label}</Label>}
29
- <Box variant="form.radios">
29
+ <Box>
30
30
  {options.map((option) => {
31
31
  const id = `form-field-radio-${name}-${option.value}`;
32
32
 
@@ -39,17 +39,16 @@ export const FormFieldSelect = <
39
39
  onBlur={onBlur}
40
40
  value={value}
41
41
  arrow={arrow}
42
- variant="form.select"
42
+ id={id}
43
43
  >
44
44
  {options.map((option) => {
45
45
  return (
46
- <option key={id} value={option.value} id={id}>
46
+ <option key={option.label} value={option.value}>
47
47
  {option.label}
48
48
  </option>
49
49
  );
50
50
  })}
51
51
  </Select>
52
-
53
52
  <ErrorMessage name={name} />
54
53
  </Box>
55
54
  );
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { Form } from './Form';
2
2
  export { FormField } from './FormField';
3
+ export { yupResolver } from '@hookform/resolvers/yup';
@@ -1,70 +0,0 @@
1
- import * as yup from 'yup';
2
- import { Button } from '@ttoss/ui';
3
- import { Form } from './Form';
4
- import { FormFieldInput } from './FormFieldInput';
5
- import { render, screen, userEvent } from '@ttoss/test-utils';
6
- import { useForm } from 'react-hook-form';
7
- import { yupResolver } from '@hookform/resolvers/yup';
8
-
9
- test('call onSubmit with correct data', async () => {
10
- const user = userEvent.setup({ delay: null });
11
-
12
- const onSubmit = jest.fn();
13
-
14
- const RenderForm = () => {
15
- const formMethods = useForm();
16
-
17
- return (
18
- <Form {...formMethods} onSubmit={onSubmit}>
19
- <FormFieldInput name="input1" label="Input 1" />
20
- <FormFieldInput name="input2" label="Input 2" />
21
- <Button type="submit">Submit</Button>
22
- </Form>
23
- );
24
- };
25
-
26
- render(<RenderForm />);
27
-
28
- await user.type(screen.getByLabelText('Input 1'), 'input1');
29
-
30
- await user.type(screen.getByLabelText('Input 2'), 'input2');
31
-
32
- await user.click(screen.getByText('Submit'));
33
-
34
- expect(onSubmit).toHaveBeenCalledWith({ input1: 'input1', input2: 'input2' });
35
- });
36
-
37
- test('should display error messages', async () => {
38
- const user = userEvent.setup({ delay: null });
39
-
40
- const onSubmit = jest.fn();
41
-
42
- const schema = yup.object({
43
- firstName: yup.string().required('First name is required'),
44
- age: yup.number().required('Age is required'),
45
- });
46
-
47
- const RenderForm = () => {
48
- const formMethods = useForm({
49
- defaultValues: {
50
- age: 0,
51
- },
52
- mode: 'all',
53
- resolver: yupResolver(schema),
54
- });
55
-
56
- return (
57
- <Form {...formMethods} onSubmit={onSubmit}>
58
- <FormFieldInput name="firstName" label="First Name" />
59
- <FormFieldInput name="age" label="Age" />
60
- <Button type="submit">Submit</Button>
61
- </Form>
62
- );
63
- };
64
-
65
- render(<RenderForm />);
66
-
67
- await user.click(screen.getByText('Submit'));
68
-
69
- expect(await screen.findByText('First name is required')).toBeInTheDocument();
70
- });
@@ -1,69 +0,0 @@
1
- import * as yup from 'yup';
2
- import { Button } from '@ttoss/ui';
3
- import { Form } from './Form';
4
- import { FormFieldRadio } from './FormFieldRadio';
5
- import { render, screen, userEvent } from '@ttoss/test-utils';
6
- import { useForm } from 'react-hook-form';
7
- import { yupResolver } from '@hookform/resolvers/yup';
8
-
9
- const RADIO_OPTIONS = [
10
- { value: 'Ferrari', label: 'Ferrari' },
11
- { value: 'Mercedes', label: 'Mercedes' },
12
- { value: 'BMW', label: 'BMW' },
13
- ];
14
-
15
- test('call onSubmit with correct data', async () => {
16
- const user = userEvent.setup({ delay: null });
17
-
18
- const onSubmit = jest.fn();
19
-
20
- const RenderForm = () => {
21
- const formMethods = useForm();
22
-
23
- return (
24
- <Form {...formMethods} onSubmit={onSubmit}>
25
- <FormFieldRadio name="car" label="Cars" options={RADIO_OPTIONS} />
26
- <Button type="submit">Submit</Button>
27
- </Form>
28
- );
29
- };
30
-
31
- render(<RenderForm />);
32
-
33
- await user.click(screen.getByLabelText('BMW'));
34
-
35
- await user.click(screen.getByText('Submit'));
36
-
37
- expect(onSubmit).toHaveBeenCalledWith({ car: 'BMW' });
38
- });
39
-
40
- test('should display error messages', async () => {
41
- const user = userEvent.setup({ delay: null });
42
-
43
- const onSubmit = jest.fn();
44
-
45
- const schema = yup.object({
46
- car: yup.string().required('Car is required'),
47
- });
48
-
49
- const RenderForm = () => {
50
- const formMethods = useForm({
51
- mode: 'all',
52
- resolver: yupResolver(schema),
53
- });
54
-
55
- return (
56
- <Form {...formMethods} onSubmit={onSubmit}>
57
- <FormFieldRadio name="car" label="Cars" options={RADIO_OPTIONS} />
58
-
59
- <Button type="submit">Submit</Button>
60
- </Form>
61
- );
62
- };
63
-
64
- render(<RenderForm />);
65
-
66
- await user.click(screen.getByText('Submit'));
67
-
68
- expect(await screen.findByText('Car is required')).toBeInTheDocument();
69
- });
@@ -1,73 +0,0 @@
1
- import * as yup from 'yup';
2
- import { Button } from '@ttoss/ui';
3
- import { Form } from './Form';
4
- import { FormFieldSelect } from './FormFieldSelect';
5
- import { render, screen, userEvent } from '@ttoss/test-utils';
6
- import { useForm } from 'react-hook-form';
7
- import { yupResolver } from '@hookform/resolvers/yup';
8
-
9
- const RADIO_OPTIONS = [
10
- { value: '', label: 'Select a car' },
11
- { value: 'Ferrari', label: 'Ferrari' },
12
- { value: 'Mercedes', label: 'Mercedes' },
13
- { value: 'BMW', label: 'BMW' },
14
- ];
15
-
16
- test('call onSubmit with correct data', async () => {
17
- const user = userEvent.setup({ delay: null });
18
-
19
- const onSubmit = jest.fn();
20
-
21
- const RenderForm = () => {
22
- const formMethods = useForm();
23
-
24
- return (
25
- <Form {...formMethods} onSubmit={onSubmit}>
26
- <FormFieldSelect name="car" label="Cars" options={RADIO_OPTIONS} />
27
- <Button type="submit">Submit</Button>
28
- </Form>
29
- );
30
- };
31
-
32
- render(<RenderForm />);
33
-
34
- await user.selectOptions(
35
- screen.getByRole('combobox'),
36
- screen.getByText('BMW')
37
- );
38
-
39
- await user.click(screen.getByText('Submit'));
40
-
41
- expect(onSubmit).toHaveBeenCalledWith({ car: 'BMW' });
42
- });
43
-
44
- test('should display error messages', async () => {
45
- const user = userEvent.setup({ delay: null });
46
-
47
- const onSubmit = jest.fn();
48
-
49
- const schema = yup.object({
50
- car: yup.string().required('Car is required'),
51
- });
52
-
53
- const RenderForm = () => {
54
- const formMethods = useForm({
55
- mode: 'all',
56
- resolver: yupResolver(schema),
57
- });
58
-
59
- return (
60
- <Form {...formMethods} onSubmit={onSubmit}>
61
- <FormFieldSelect name="car" label="Cars" options={RADIO_OPTIONS} />
62
-
63
- <Button type="submit">Submit</Button>
64
- </Form>
65
- );
66
- };
67
-
68
- render(<RenderForm />);
69
-
70
- await user.click(screen.getByText('Submit'));
71
-
72
- expect(await screen.findByText('Car is required')).toBeInTheDocument();
73
- });