@ttoss/forms 0.5.11 → 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 +40 -0
- package/dist/esm/index.js +78 -33
- package/dist/index.d.ts +5 -0
- package/dist/index.js +79 -33
- package/package.json +12 -11
- package/src/Form.tsx +3 -1
- package/src/FormField.tsx +3 -0
- package/src/FormFieldCheckbox.tsx +38 -0
- package/src/FormFieldRadio.tsx +1 -1
- package/src/FormFieldSelect.tsx +2 -3
- package/src/index.ts +1 -0
- package/src/FormFieldInput.spec.tsx +0 -70
- package/src/FormFieldRadio.spec.tsx +0 -69
- package/src/FormFieldSelect.spec.tsx +0 -73
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) =>
|
|
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/
|
|
29
|
-
import { Box as Box2,
|
|
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/
|
|
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
|
|
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__ */
|
|
108
|
+
return /* @__PURE__ */ jsxs2(Box3, {
|
|
67
109
|
children: [
|
|
68
|
-
label && /* @__PURE__ */
|
|
110
|
+
label && /* @__PURE__ */ jsx4(Label2, {
|
|
69
111
|
htmlFor: id,
|
|
70
112
|
children: label
|
|
71
113
|
}),
|
|
72
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
89
|
-
import { useController as
|
|
90
|
-
import { jsx as
|
|
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
|
-
} =
|
|
140
|
+
} = useController3({
|
|
99
141
|
name,
|
|
100
142
|
defaultValue: ""
|
|
101
143
|
});
|
|
102
|
-
return /* @__PURE__ */
|
|
144
|
+
return /* @__PURE__ */ jsxs3(Box4, {
|
|
103
145
|
children: [
|
|
104
|
-
label && /* @__PURE__ */
|
|
146
|
+
label && /* @__PURE__ */ jsx5(Label3, {
|
|
105
147
|
children: label
|
|
106
148
|
}),
|
|
107
|
-
/* @__PURE__ */
|
|
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__ */
|
|
152
|
+
return /* @__PURE__ */ jsxs3(Label3, {
|
|
112
153
|
htmlFor: id,
|
|
113
154
|
children: [
|
|
114
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
137
|
-
import { useController as
|
|
138
|
-
import { jsx as
|
|
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
|
-
} =
|
|
188
|
+
} = useController4({
|
|
148
189
|
name,
|
|
149
190
|
defaultValue: ""
|
|
150
191
|
});
|
|
151
192
|
const id = `form-field-select-${name}`;
|
|
152
|
-
return /* @__PURE__ */
|
|
193
|
+
return /* @__PURE__ */ jsxs4(Box5, {
|
|
153
194
|
children: [
|
|
154
|
-
label && /* @__PURE__ */
|
|
195
|
+
label && /* @__PURE__ */ jsx6(Label4, {
|
|
155
196
|
htmlFor: id,
|
|
156
197
|
children: label
|
|
157
198
|
}),
|
|
158
|
-
/* @__PURE__ */
|
|
199
|
+
/* @__PURE__ */ jsx6(Select, {
|
|
159
200
|
ref,
|
|
160
201
|
name,
|
|
161
202
|
onChange,
|
|
162
203
|
onBlur,
|
|
163
204
|
value,
|
|
164
205
|
arrow,
|
|
165
|
-
|
|
206
|
+
id,
|
|
166
207
|
children: options.map((option) => {
|
|
167
|
-
return /* @__PURE__ */
|
|
208
|
+
return /* @__PURE__ */ jsx6("option", {
|
|
168
209
|
value: option.value,
|
|
169
|
-
id,
|
|
170
210
|
children: option.label
|
|
171
|
-
},
|
|
211
|
+
}, option.label);
|
|
172
212
|
})
|
|
173
213
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
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) =>
|
|
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/
|
|
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/
|
|
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
|
|
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,
|
|
141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ui4.Box, {
|
|
99
142
|
children: [
|
|
100
|
-
label && /* @__PURE__ */ (0,
|
|
143
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ui4.Label, {
|
|
101
144
|
htmlFor: id,
|
|
102
145
|
children: label
|
|
103
146
|
}),
|
|
104
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
121
|
-
var
|
|
122
|
-
var
|
|
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,
|
|
173
|
+
} = (0, import_react_hook_form5.useController)({
|
|
131
174
|
name,
|
|
132
175
|
defaultValue: ""
|
|
133
176
|
});
|
|
134
|
-
return /* @__PURE__ */ (0,
|
|
177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Box, {
|
|
135
178
|
children: [
|
|
136
|
-
label && /* @__PURE__ */ (0,
|
|
179
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ui5.Label, {
|
|
137
180
|
children: label
|
|
138
181
|
}),
|
|
139
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ui5.Label, {
|
|
144
186
|
htmlFor: id,
|
|
145
187
|
children: [
|
|
146
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
169
|
-
var
|
|
170
|
-
var
|
|
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,
|
|
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,
|
|
226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui6.Box, {
|
|
185
227
|
children: [
|
|
186
|
-
label && /* @__PURE__ */ (0,
|
|
228
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui6.Label, {
|
|
187
229
|
htmlFor: id,
|
|
188
230
|
children: label
|
|
189
231
|
}),
|
|
190
|
-
/* @__PURE__ */ (0,
|
|
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
|
-
|
|
239
|
+
id,
|
|
198
240
|
children: options.map((option) => {
|
|
199
|
-
return /* @__PURE__ */ (0,
|
|
241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", {
|
|
200
242
|
value: option.value,
|
|
201
|
-
id,
|
|
202
243
|
children: option.label
|
|
203
|
-
},
|
|
244
|
+
}, option.label);
|
|
204
245
|
})
|
|
205
246
|
}),
|
|
206
|
-
/* @__PURE__ */ (0,
|
|
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.
|
|
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.
|
|
21
|
+
"@hookform/error-message": "^2.0.1",
|
|
22
|
+
"@hookform/resolvers": "^2.9.10"
|
|
22
23
|
},
|
|
23
24
|
"peerDependencies": {
|
|
24
|
-
"@ttoss/ui": "^1.
|
|
25
|
+
"@ttoss/ui": "^1.23.0",
|
|
25
26
|
"react": "^18.2.0",
|
|
26
|
-
"react-hook-form": "^7.
|
|
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.
|
|
32
|
-
"@ttoss/ui": "^1.23.
|
|
33
|
-
"@types/jest": "^29.
|
|
34
|
-
"jest": "^29.
|
|
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.
|
|
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": "
|
|
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) =>
|
|
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
|
+
};
|
package/src/FormFieldRadio.tsx
CHANGED
|
@@ -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
|
|
29
|
+
<Box>
|
|
30
30
|
{options.map((option) => {
|
|
31
31
|
const id = `form-field-radio-${name}-${option.value}`;
|
|
32
32
|
|
package/src/FormFieldSelect.tsx
CHANGED
|
@@ -39,17 +39,16 @@ export const FormFieldSelect = <
|
|
|
39
39
|
onBlur={onBlur}
|
|
40
40
|
value={value}
|
|
41
41
|
arrow={arrow}
|
|
42
|
-
|
|
42
|
+
id={id}
|
|
43
43
|
>
|
|
44
44
|
{options.map((option) => {
|
|
45
45
|
return (
|
|
46
|
-
<option key={
|
|
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,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
|
-
});
|