remix-validated-form 4.0.0-beta.0 → 4.0.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/browser/ValidatedForm.js +6 -1
- package/browser/hooks.d.ts +0 -9
- package/browser/hooks.js +3 -17
- package/browser/server.d.ts +1 -1
- package/browser/server.js +1 -1
- package/build/ValidatedForm.js +6 -1
- package/build/hooks.d.ts +0 -9
- package/build/hooks.js +2 -16
- package/build/server.d.ts +1 -1
- package/build/server.js +1 -1
- package/package.json +1 -1
- package/src/ValidatedForm.tsx +6 -1
- package/src/hooks.ts +3 -23
- package/src/server.ts +1 -1
- package/src/types.ts +0 -1
package/browser/ValidatedForm.js
CHANGED
@@ -115,6 +115,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
115
115
|
const backendError = useErrorResponseForThisForm(fetcher, subaction);
|
116
116
|
const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
|
117
117
|
const isSubmitting = useIsSubmitting(action, subaction, fetcher);
|
118
|
+
const [isValidating, setIsValidating] = useState(false);
|
118
119
|
const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
|
119
120
|
const [touchedFields, setTouchedFields] = useState({});
|
120
121
|
const [hasBeenSubmitted, setHasBeenSubmitted] = useState(false);
|
@@ -122,6 +123,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
122
123
|
const formRef = useRef(null);
|
123
124
|
useSubmitComplete(isSubmitting, () => {
|
124
125
|
var _a;
|
126
|
+
setIsValidating(false);
|
125
127
|
if (!backendError && resetAfterSubmit) {
|
126
128
|
(_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
|
127
129
|
}
|
@@ -131,7 +133,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
131
133
|
fieldErrors,
|
132
134
|
action,
|
133
135
|
defaultValues: defaultsToUse,
|
134
|
-
isSubmitting:
|
136
|
+
isSubmitting: isValidating || isSubmitting,
|
135
137
|
isValid: Object.keys(fieldErrors).length === 0,
|
136
138
|
touchedFields,
|
137
139
|
setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
|
@@ -177,6 +179,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
177
179
|
fieldErrors,
|
178
180
|
action,
|
179
181
|
defaultsToUse,
|
182
|
+
isValidating,
|
180
183
|
isSubmitting,
|
181
184
|
touchedFields,
|
182
185
|
hasBeenSubmitted,
|
@@ -208,8 +211,10 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
208
211
|
return (_jsx(Form, { ref: mergeRefs([formRef, formRefProp]), ...rest, action: action, onSubmit: async (e) => {
|
209
212
|
e.preventDefault();
|
210
213
|
setHasBeenSubmitted(true);
|
214
|
+
setIsValidating(true);
|
211
215
|
const result = await validator.validate(getDataFromForm(e.currentTarget));
|
212
216
|
if (result.error) {
|
217
|
+
setIsValidating(false);
|
213
218
|
setFieldErrors(result.error.fieldErrors);
|
214
219
|
if (!disableFocusOnError) {
|
215
220
|
focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
|
package/browser/hooks.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { GetInputProps, ValidationBehaviorOptions } from "./internal/getInputProps";
|
2
|
-
import { ValidationState } from "./types";
|
3
2
|
export declare type FieldProps = {
|
4
3
|
/**
|
5
4
|
* The validation error message if there is one.
|
@@ -13,14 +12,6 @@ export declare type FieldProps = {
|
|
13
12
|
* Validates the field.
|
14
13
|
*/
|
15
14
|
validate: () => void;
|
16
|
-
/**
|
17
|
-
* The validation state of the field.
|
18
|
-
* - idle: the field has not been validated yet.
|
19
|
-
* - validating: the field is currently being validated.
|
20
|
-
* - valid: the field is valid.
|
21
|
-
* - invalid: the field is invalid.
|
22
|
-
*/
|
23
|
-
validationState: ValidationState;
|
24
15
|
/**
|
25
16
|
* The default value of the field, if there is one.
|
26
17
|
*/
|
package/browser/hooks.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import get from "lodash/get";
|
2
2
|
import toPath from "lodash/toPath";
|
3
|
-
import { useContext, useEffect, useMemo
|
3
|
+
import { useContext, useEffect, useMemo } from "react";
|
4
4
|
import { FormContext } from "./internal/formContext";
|
5
5
|
import { createGetInputProps, } from "./internal/getInputProps";
|
6
6
|
const useInternalFormContext = (hookName) => {
|
@@ -16,37 +16,24 @@ export const useField = (name, options) => {
|
|
16
16
|
const { fieldErrors, clearError, validateField, defaultValues, registerReceiveFocus, touchedFields, setFieldTouched, hasBeenSubmitted, } = useInternalFormContext("useField");
|
17
17
|
const isTouched = !!touchedFields[name];
|
18
18
|
const { handleReceiveFocus } = options !== null && options !== void 0 ? options : {};
|
19
|
-
const [isValidating, setValidating] = useState(false);
|
20
19
|
useEffect(() => {
|
21
20
|
if (handleReceiveFocus)
|
22
21
|
return registerReceiveFocus(name, handleReceiveFocus);
|
23
22
|
}, [handleReceiveFocus, name, registerReceiveFocus]);
|
24
23
|
const field = useMemo(() => {
|
25
|
-
const error = fieldErrors[name];
|
26
|
-
const getValidationState = () => {
|
27
|
-
if (isValidating)
|
28
|
-
return "validating";
|
29
|
-
if (error)
|
30
|
-
return "invalid";
|
31
|
-
if (!isTouched && !hasBeenSubmitted)
|
32
|
-
return "idle";
|
33
|
-
return "valid";
|
34
|
-
};
|
35
24
|
const helpers = {
|
36
|
-
error,
|
25
|
+
error: fieldErrors[name],
|
37
26
|
clearError: () => {
|
38
27
|
clearError(name);
|
39
28
|
},
|
40
29
|
validate: () => {
|
41
|
-
|
42
|
-
validateField(name).then((error) => setValidating(false));
|
30
|
+
validateField(name);
|
43
31
|
},
|
44
32
|
defaultValue: defaultValues
|
45
33
|
? get(defaultValues, toPath(name), undefined)
|
46
34
|
: undefined,
|
47
35
|
touched: isTouched,
|
48
36
|
setTouched: (touched) => setFieldTouched(name, touched),
|
49
|
-
validationState: getValidationState(),
|
50
37
|
};
|
51
38
|
const getInputProps = createGetInputProps({
|
52
39
|
...helpers,
|
@@ -65,7 +52,6 @@ export const useField = (name, options) => {
|
|
65
52
|
isTouched,
|
66
53
|
hasBeenSubmitted,
|
67
54
|
options === null || options === void 0 ? void 0 : options.validationBehavior,
|
68
|
-
isValidating,
|
69
55
|
clearError,
|
70
56
|
validateField,
|
71
57
|
setFieldTouched,
|
package/browser/server.d.ts
CHANGED
@@ -4,7 +4,7 @@ import { ValidatorError } from "./validation/types";
|
|
4
4
|
* When you return this from your action, `ValidatedForm` on the frontend will automatically
|
5
5
|
* display the errors on the correct fields on the correct form.
|
6
6
|
*
|
7
|
-
*
|
7
|
+
* You can also provide a second argument to `validationError`
|
8
8
|
* to specify how to repopulate the form when JS is disabled.
|
9
9
|
*
|
10
10
|
* @example
|
package/browser/server.js
CHANGED
@@ -4,7 +4,7 @@ import { json } from "@remix-run/server-runtime";
|
|
4
4
|
* When you return this from your action, `ValidatedForm` on the frontend will automatically
|
5
5
|
* display the errors on the correct fields on the correct form.
|
6
6
|
*
|
7
|
-
*
|
7
|
+
* You can also provide a second argument to `validationError`
|
8
8
|
* to specify how to repopulate the form when JS is disabled.
|
9
9
|
*
|
10
10
|
* @example
|
package/build/ValidatedForm.js
CHANGED
@@ -140,6 +140,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
140
140
|
const backendError = useErrorResponseForThisForm(fetcher, subaction);
|
141
141
|
const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
|
142
142
|
const isSubmitting = useIsSubmitting(action, subaction, fetcher);
|
143
|
+
const [isValidating, setIsValidating] = (0, react_2.useState)(false);
|
143
144
|
const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
|
144
145
|
const [touchedFields, setTouchedFields] = (0, react_2.useState)({});
|
145
146
|
const [hasBeenSubmitted, setHasBeenSubmitted] = (0, react_2.useState)(false);
|
@@ -147,6 +148,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
147
148
|
const formRef = (0, react_2.useRef)(null);
|
148
149
|
(0, submissionCallbacks_1.useSubmitComplete)(isSubmitting, () => {
|
149
150
|
var _a;
|
151
|
+
setIsValidating(false);
|
150
152
|
if (!backendError && resetAfterSubmit) {
|
151
153
|
(_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
|
152
154
|
}
|
@@ -156,7 +158,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
156
158
|
fieldErrors,
|
157
159
|
action,
|
158
160
|
defaultValues: defaultsToUse,
|
159
|
-
isSubmitting:
|
161
|
+
isSubmitting: isValidating || isSubmitting,
|
160
162
|
isValid: Object.keys(fieldErrors).length === 0,
|
161
163
|
touchedFields,
|
162
164
|
setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
|
@@ -202,6 +204,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
202
204
|
fieldErrors,
|
203
205
|
action,
|
204
206
|
defaultsToUse,
|
207
|
+
isValidating,
|
205
208
|
isSubmitting,
|
206
209
|
touchedFields,
|
207
210
|
hasBeenSubmitted,
|
@@ -233,8 +236,10 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
233
236
|
return ((0, jsx_runtime_1.jsx)(Form, { ref: (0, util_1.mergeRefs)([formRef, formRefProp]), ...rest, action: action, onSubmit: async (e) => {
|
234
237
|
e.preventDefault();
|
235
238
|
setHasBeenSubmitted(true);
|
239
|
+
setIsValidating(true);
|
236
240
|
const result = await validator.validate(getDataFromForm(e.currentTarget));
|
237
241
|
if (result.error) {
|
242
|
+
setIsValidating(false);
|
238
243
|
setFieldErrors(result.error.fieldErrors);
|
239
244
|
if (!disableFocusOnError) {
|
240
245
|
focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
|
package/build/hooks.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { GetInputProps, ValidationBehaviorOptions } from "./internal/getInputProps";
|
2
|
-
import { ValidationState } from "./types";
|
3
2
|
export declare type FieldProps = {
|
4
3
|
/**
|
5
4
|
* The validation error message if there is one.
|
@@ -13,14 +12,6 @@ export declare type FieldProps = {
|
|
13
12
|
* Validates the field.
|
14
13
|
*/
|
15
14
|
validate: () => void;
|
16
|
-
/**
|
17
|
-
* The validation state of the field.
|
18
|
-
* - idle: the field has not been validated yet.
|
19
|
-
* - validating: the field is currently being validated.
|
20
|
-
* - valid: the field is valid.
|
21
|
-
* - invalid: the field is invalid.
|
22
|
-
*/
|
23
|
-
validationState: ValidationState;
|
24
15
|
/**
|
25
16
|
* The default value of the field, if there is one.
|
26
17
|
*/
|
package/build/hooks.js
CHANGED
@@ -22,37 +22,24 @@ const useField = (name, options) => {
|
|
22
22
|
const { fieldErrors, clearError, validateField, defaultValues, registerReceiveFocus, touchedFields, setFieldTouched, hasBeenSubmitted, } = useInternalFormContext("useField");
|
23
23
|
const isTouched = !!touchedFields[name];
|
24
24
|
const { handleReceiveFocus } = options !== null && options !== void 0 ? options : {};
|
25
|
-
const [isValidating, setValidating] = (0, react_1.useState)(false);
|
26
25
|
(0, react_1.useEffect)(() => {
|
27
26
|
if (handleReceiveFocus)
|
28
27
|
return registerReceiveFocus(name, handleReceiveFocus);
|
29
28
|
}, [handleReceiveFocus, name, registerReceiveFocus]);
|
30
29
|
const field = (0, react_1.useMemo)(() => {
|
31
|
-
const error = fieldErrors[name];
|
32
|
-
const getValidationState = () => {
|
33
|
-
if (isValidating)
|
34
|
-
return "validating";
|
35
|
-
if (error)
|
36
|
-
return "invalid";
|
37
|
-
if (!isTouched && !hasBeenSubmitted)
|
38
|
-
return "idle";
|
39
|
-
return "valid";
|
40
|
-
};
|
41
30
|
const helpers = {
|
42
|
-
error,
|
31
|
+
error: fieldErrors[name],
|
43
32
|
clearError: () => {
|
44
33
|
clearError(name);
|
45
34
|
},
|
46
35
|
validate: () => {
|
47
|
-
|
48
|
-
validateField(name).then((error) => setValidating(false));
|
36
|
+
validateField(name);
|
49
37
|
},
|
50
38
|
defaultValue: defaultValues
|
51
39
|
? (0, get_1.default)(defaultValues, (0, toPath_1.default)(name), undefined)
|
52
40
|
: undefined,
|
53
41
|
touched: isTouched,
|
54
42
|
setTouched: (touched) => setFieldTouched(name, touched),
|
55
|
-
validationState: getValidationState(),
|
56
43
|
};
|
57
44
|
const getInputProps = (0, getInputProps_1.createGetInputProps)({
|
58
45
|
...helpers,
|
@@ -71,7 +58,6 @@ const useField = (name, options) => {
|
|
71
58
|
isTouched,
|
72
59
|
hasBeenSubmitted,
|
73
60
|
options === null || options === void 0 ? void 0 : options.validationBehavior,
|
74
|
-
isValidating,
|
75
61
|
clearError,
|
76
62
|
validateField,
|
77
63
|
setFieldTouched,
|
package/build/server.d.ts
CHANGED
@@ -4,7 +4,7 @@ import { ValidatorError } from "./validation/types";
|
|
4
4
|
* When you return this from your action, `ValidatedForm` on the frontend will automatically
|
5
5
|
* display the errors on the correct fields on the correct form.
|
6
6
|
*
|
7
|
-
*
|
7
|
+
* You can also provide a second argument to `validationError`
|
8
8
|
* to specify how to repopulate the form when JS is disabled.
|
9
9
|
*
|
10
10
|
* @example
|
package/build/server.js
CHANGED
@@ -7,7 +7,7 @@ const server_runtime_1 = require("@remix-run/server-runtime");
|
|
7
7
|
* When you return this from your action, `ValidatedForm` on the frontend will automatically
|
8
8
|
* display the errors on the correct fields on the correct form.
|
9
9
|
*
|
10
|
-
*
|
10
|
+
* You can also provide a second argument to `validationError`
|
11
11
|
* to specify how to repopulate the form when JS is disabled.
|
12
12
|
*
|
13
13
|
* @example
|
package/package.json
CHANGED
package/src/ValidatedForm.tsx
CHANGED
@@ -225,6 +225,7 @@ export function ValidatedForm<DataType>({
|
|
225
225
|
backendError?.fieldErrors
|
226
226
|
);
|
227
227
|
const isSubmitting = useIsSubmitting(action, subaction, fetcher);
|
228
|
+
const [isValidating, setIsValidating] = useState(false);
|
228
229
|
const defaultsToUse = useDefaultValues(
|
229
230
|
backendError?.repopulateFields,
|
230
231
|
defaultValues
|
@@ -234,6 +235,7 @@ export function ValidatedForm<DataType>({
|
|
234
235
|
const submit = useSubmit();
|
235
236
|
const formRef = useRef<HTMLFormElement>(null);
|
236
237
|
useSubmitComplete(isSubmitting, () => {
|
238
|
+
setIsValidating(false);
|
237
239
|
if (!backendError && resetAfterSubmit) {
|
238
240
|
formRef.current?.reset();
|
239
241
|
}
|
@@ -245,7 +247,7 @@ export function ValidatedForm<DataType>({
|
|
245
247
|
fieldErrors,
|
246
248
|
action,
|
247
249
|
defaultValues: defaultsToUse,
|
248
|
-
isSubmitting:
|
250
|
+
isSubmitting: isValidating || isSubmitting,
|
249
251
|
isValid: Object.keys(fieldErrors).length === 0,
|
250
252
|
touchedFields,
|
251
253
|
setFieldTouched: (fieldName: string, touched: boolean) =>
|
@@ -294,6 +296,7 @@ export function ValidatedForm<DataType>({
|
|
294
296
|
fieldErrors,
|
295
297
|
action,
|
296
298
|
defaultsToUse,
|
299
|
+
isValidating,
|
297
300
|
isSubmitting,
|
298
301
|
touchedFields,
|
299
302
|
hasBeenSubmitted,
|
@@ -339,10 +342,12 @@ export function ValidatedForm<DataType>({
|
|
339
342
|
onSubmit={async (e) => {
|
340
343
|
e.preventDefault();
|
341
344
|
setHasBeenSubmitted(true);
|
345
|
+
setIsValidating(true);
|
342
346
|
const result = await validator.validate(
|
343
347
|
getDataFromForm(e.currentTarget)
|
344
348
|
);
|
345
349
|
if (result.error) {
|
350
|
+
setIsValidating(false);
|
346
351
|
setFieldErrors(result.error.fieldErrors);
|
347
352
|
if (!disableFocusOnError) {
|
348
353
|
focusFirstInvalidInput(
|
package/src/hooks.ts
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
import get from "lodash/get";
|
2
2
|
import toPath from "lodash/toPath";
|
3
|
-
import { useContext, useEffect, useMemo
|
3
|
+
import { useContext, useEffect, useMemo } from "react";
|
4
4
|
import { FormContext } from "./internal/formContext";
|
5
5
|
import {
|
6
6
|
createGetInputProps,
|
7
7
|
GetInputProps,
|
8
8
|
ValidationBehaviorOptions,
|
9
9
|
} from "./internal/getInputProps";
|
10
|
-
import { ValidationState } from "./types";
|
11
10
|
|
12
11
|
const useInternalFormContext = (hookName: string) => {
|
13
12
|
const context = useContext(FormContext);
|
@@ -31,14 +30,6 @@ export type FieldProps = {
|
|
31
30
|
* Validates the field.
|
32
31
|
*/
|
33
32
|
validate: () => void;
|
34
|
-
/**
|
35
|
-
* The validation state of the field.
|
36
|
-
* - idle: the field has not been validated yet.
|
37
|
-
* - validating: the field is currently being validated.
|
38
|
-
* - valid: the field is valid.
|
39
|
-
* - invalid: the field is invalid.
|
40
|
-
*/
|
41
|
-
validationState: ValidationState;
|
42
33
|
/**
|
43
34
|
* The default value of the field, if there is one.
|
44
35
|
*/
|
@@ -88,7 +79,6 @@ export const useField = (
|
|
88
79
|
|
89
80
|
const isTouched = !!touchedFields[name];
|
90
81
|
const { handleReceiveFocus } = options ?? {};
|
91
|
-
const [isValidating, setValidating] = useState(false);
|
92
82
|
|
93
83
|
useEffect(() => {
|
94
84
|
if (handleReceiveFocus)
|
@@ -96,28 +86,19 @@ export const useField = (
|
|
96
86
|
}, [handleReceiveFocus, name, registerReceiveFocus]);
|
97
87
|
|
98
88
|
const field = useMemo<FieldProps>(() => {
|
99
|
-
const error = fieldErrors[name];
|
100
|
-
const getValidationState = (): ValidationState => {
|
101
|
-
if (isValidating) return "validating";
|
102
|
-
if (error) return "invalid";
|
103
|
-
if (!isTouched && !hasBeenSubmitted) return "idle";
|
104
|
-
return "valid";
|
105
|
-
};
|
106
89
|
const helpers = {
|
107
|
-
error,
|
90
|
+
error: fieldErrors[name],
|
108
91
|
clearError: () => {
|
109
92
|
clearError(name);
|
110
93
|
},
|
111
94
|
validate: () => {
|
112
|
-
|
113
|
-
validateField(name).then((error) => setValidating(false));
|
95
|
+
validateField(name);
|
114
96
|
},
|
115
97
|
defaultValue: defaultValues
|
116
98
|
? get(defaultValues, toPath(name), undefined)
|
117
99
|
: undefined,
|
118
100
|
touched: isTouched,
|
119
101
|
setTouched: (touched: boolean) => setFieldTouched(name, touched),
|
120
|
-
validationState: getValidationState(),
|
121
102
|
};
|
122
103
|
const getInputProps = createGetInputProps({
|
123
104
|
...helpers,
|
@@ -136,7 +117,6 @@ export const useField = (
|
|
136
117
|
isTouched,
|
137
118
|
hasBeenSubmitted,
|
138
119
|
options?.validationBehavior,
|
139
|
-
isValidating,
|
140
120
|
clearError,
|
141
121
|
validateField,
|
142
122
|
setFieldTouched,
|
package/src/server.ts
CHANGED
@@ -9,7 +9,7 @@ import {
|
|
9
9
|
* When you return this from your action, `ValidatedForm` on the frontend will automatically
|
10
10
|
* display the errors on the correct fields on the correct form.
|
11
11
|
*
|
12
|
-
*
|
12
|
+
* You can also provide a second argument to `validationError`
|
13
13
|
* to specify how to repopulate the form when JS is disabled.
|
14
14
|
*
|
15
15
|
* @example
|
package/src/types.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export type ValidationState = "idle" | "validating" | "valid" | "invalid";
|