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.
@@ -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: isSubmitting !== null && isSubmitting !== void 0 ? isSubmitting : false,
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);
@@ -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, useState } from "react";
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
- setValidating(true);
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,
@@ -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
- * _Recommended_: You can also provide a second argument to `validationError`
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
- * _Recommended_: You can also provide a second argument to `validationError`
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
@@ -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: isSubmitting !== null && isSubmitting !== void 0 ? isSubmitting : false,
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
- setValidating(true);
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
- * _Recommended_: You can also provide a second argument to `validationError`
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
- * _Recommended_: You can also provide a second argument to `validationError`
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remix-validated-form",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0",
4
4
  "description": "Form component and utils for easy form validation in remix",
5
5
  "browser": "./browser/index.js",
6
6
  "main": "./build/index.js",
@@ -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: isSubmitting ?? false,
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, useState } from "react";
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
- setValidating(true);
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
- * _Recommended_: You can also provide a second argument to `validationError`
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";