remix-validated-form 4.0.1-beta.1 → 4.0.1-beta.2

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.
@@ -1,9 +1,9 @@
1
1
  $ npm run build:browser && npm run build:main
2
2
 
3
- > remix-validated-form@4.0.0 build:browser
3
+ > remix-validated-form@4.0.1-beta.1 build:browser
4
4
  > tsc --module ESNext --outDir ./browser
5
5
 
6
6
 
7
- > remix-validated-form@4.0.0 build:main
7
+ > remix-validated-form@4.0.1-beta.1 build:main
8
8
  > tsc --module CommonJS --outDir ./build
9
9
 
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Form as RemixForm, useActionData, useFormAction, useSubmit, useTransition, } from "@remix-run/react";
2
+ import { Form as RemixForm, useActionData, useSubmit, useTransition, } from "@remix-run/react";
3
3
  import uniq from "lodash/uniq";
4
4
  import React, { useEffect, useMemo, useRef, useState, } from "react";
5
5
  import invariant from "tiny-invariant";
@@ -30,19 +30,16 @@ function useFieldErrors(fieldErrorsFromBackend) {
30
30
  }, [fieldErrorsFromBackend]);
31
31
  return [fieldErrors, setFieldErrors];
32
32
  }
33
- const useIsSubmitting = (action, subaction, fetcher) => {
34
- const actionForCurrentPage = useFormAction();
35
- const pendingFormSubmit = useTransition().submission;
36
- if (fetcher)
37
- return fetcher.state === "submitting";
38
- if (!pendingFormSubmit)
39
- return false;
40
- const { formData, action: pendingAction } = pendingFormSubmit;
41
- const pendingSubAction = formData.get("subaction");
42
- const expectedAction = action !== null && action !== void 0 ? action : actionForCurrentPage;
43
- if (subaction)
44
- return expectedAction === pendingAction && subaction === pendingSubAction;
45
- return expectedAction === pendingAction && !pendingSubAction;
33
+ const useIsSubmitting = (fetcher) => {
34
+ const [isSubmitStarted, setSubmitStarted] = useState(false);
35
+ const transition = useTransition();
36
+ const hasActiveSubmission = fetcher
37
+ ? fetcher.state === "submitting"
38
+ : !!transition.submission;
39
+ const isSubmitting = hasActiveSubmission && isSubmitStarted;
40
+ const startSubmit = () => setSubmitStarted(true);
41
+ const endSubmit = () => setSubmitStarted(false);
42
+ return [isSubmitting, startSubmit, endSubmit];
46
43
  };
47
44
  const getDataFromForm = (el) => new FormData(el);
48
45
  /**
@@ -114,8 +111,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
114
111
  var _a;
115
112
  const backendError = useErrorResponseForThisForm(fetcher, subaction);
116
113
  const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
117
- const isSubmitting = useIsSubmitting(action, subaction, fetcher);
118
- const [isValidating, setIsValidating] = useState(false);
114
+ const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
119
115
  const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
120
116
  const [touchedFields, setTouchedFields] = useState({});
121
117
  const [hasBeenSubmitted, setHasBeenSubmitted] = useState(false);
@@ -123,7 +119,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
123
119
  const formRef = useRef(null);
124
120
  useSubmitComplete(isSubmitting, () => {
125
121
  var _a;
126
- setIsValidating(false);
122
+ endSubmit();
127
123
  if (!backendError && resetAfterSubmit) {
128
124
  (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
129
125
  }
@@ -133,7 +129,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
133
129
  fieldErrors,
134
130
  action,
135
131
  defaultValues: defaultsToUse,
136
- isSubmitting: isValidating || isSubmitting,
132
+ isSubmitting,
137
133
  isValid: Object.keys(fieldErrors).length === 0,
138
134
  touchedFields,
139
135
  setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
@@ -179,7 +175,6 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
179
175
  fieldErrors,
180
176
  action,
181
177
  defaultsToUse,
182
- isValidating,
183
178
  isSubmitting,
184
179
  touchedFields,
185
180
  hasBeenSubmitted,
@@ -211,10 +206,10 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
211
206
  return (_jsx(Form, { ref: mergeRefs([formRef, formRefProp]), ...rest, action: action, method: method, replace: replace, onSubmit: async (e) => {
212
207
  e.preventDefault();
213
208
  setHasBeenSubmitted(true);
214
- setIsValidating(true);
209
+ startSubmit();
215
210
  const result = await validator.validate(getDataFromForm(e.currentTarget));
216
211
  if (result.error) {
217
- setIsValidating(false);
212
+ endSubmit();
218
213
  setFieldErrors(result.error.fieldErrors);
219
214
  if (!disableFocusOnError) {
220
215
  focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
@@ -55,19 +55,16 @@ function useFieldErrors(fieldErrorsFromBackend) {
55
55
  }, [fieldErrorsFromBackend]);
56
56
  return [fieldErrors, setFieldErrors];
57
57
  }
58
- const useIsSubmitting = (action, subaction, fetcher) => {
59
- const actionForCurrentPage = (0, react_1.useFormAction)();
60
- const pendingFormSubmit = (0, react_1.useTransition)().submission;
61
- if (fetcher)
62
- return fetcher.state === "submitting";
63
- if (!pendingFormSubmit)
64
- return false;
65
- const { formData, action: pendingAction } = pendingFormSubmit;
66
- const pendingSubAction = formData.get("subaction");
67
- const expectedAction = action !== null && action !== void 0 ? action : actionForCurrentPage;
68
- if (subaction)
69
- return expectedAction === pendingAction && subaction === pendingSubAction;
70
- return expectedAction === pendingAction && !pendingSubAction;
58
+ const useIsSubmitting = (fetcher) => {
59
+ const [isSubmitStarted, setSubmitStarted] = (0, react_2.useState)(false);
60
+ const transition = (0, react_1.useTransition)();
61
+ const hasActiveSubmission = fetcher
62
+ ? fetcher.state === "submitting"
63
+ : !!transition.submission;
64
+ const isSubmitting = hasActiveSubmission && isSubmitStarted;
65
+ const startSubmit = () => setSubmitStarted(true);
66
+ const endSubmit = () => setSubmitStarted(false);
67
+ return [isSubmitting, startSubmit, endSubmit];
71
68
  };
72
69
  const getDataFromForm = (el) => new FormData(el);
73
70
  /**
@@ -139,8 +136,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
139
136
  var _a;
140
137
  const backendError = useErrorResponseForThisForm(fetcher, subaction);
141
138
  const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
142
- const isSubmitting = useIsSubmitting(action, subaction, fetcher);
143
- const [isValidating, setIsValidating] = (0, react_2.useState)(false);
139
+ const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
144
140
  const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
145
141
  const [touchedFields, setTouchedFields] = (0, react_2.useState)({});
146
142
  const [hasBeenSubmitted, setHasBeenSubmitted] = (0, react_2.useState)(false);
@@ -148,7 +144,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
148
144
  const formRef = (0, react_2.useRef)(null);
149
145
  (0, submissionCallbacks_1.useSubmitComplete)(isSubmitting, () => {
150
146
  var _a;
151
- setIsValidating(false);
147
+ endSubmit();
152
148
  if (!backendError && resetAfterSubmit) {
153
149
  (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
154
150
  }
@@ -158,7 +154,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
158
154
  fieldErrors,
159
155
  action,
160
156
  defaultValues: defaultsToUse,
161
- isSubmitting: isValidating || isSubmitting,
157
+ isSubmitting,
162
158
  isValid: Object.keys(fieldErrors).length === 0,
163
159
  touchedFields,
164
160
  setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
@@ -204,7 +200,6 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
204
200
  fieldErrors,
205
201
  action,
206
202
  defaultsToUse,
207
- isValidating,
208
203
  isSubmitting,
209
204
  touchedFields,
210
205
  hasBeenSubmitted,
@@ -236,10 +231,10 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
236
231
  return ((0, jsx_runtime_1.jsx)(Form, { ref: (0, util_1.mergeRefs)([formRef, formRefProp]), ...rest, action: action, method: method, replace: replace, onSubmit: async (e) => {
237
232
  e.preventDefault();
238
233
  setHasBeenSubmitted(true);
239
- setIsValidating(true);
234
+ startSubmit();
240
235
  const result = await validator.validate(getDataFromForm(e.currentTarget));
241
236
  if (result.error) {
242
- setIsValidating(false);
237
+ endSubmit();
243
238
  setFieldErrors(result.error.fieldErrors);
244
239
  if (!disableFocusOnError) {
245
240
  focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remix-validated-form",
3
- "version": "4.0.1-beta.1",
3
+ "version": "4.0.1-beta.2",
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",
@@ -6,6 +6,7 @@ import {
6
6
  useSubmit,
7
7
  useTransition,
8
8
  } from "@remix-run/react";
9
+ import { Fetcher } from "@remix-run/react/transition";
9
10
  import uniq from "lodash/uniq";
10
11
  import React, {
11
12
  ComponentProps,
@@ -106,22 +107,19 @@ function useFieldErrors(
106
107
  }
107
108
 
108
109
  const useIsSubmitting = (
109
- action?: string,
110
- subaction?: string,
111
- fetcher?: ReturnType<typeof useFetcher>
112
- ) => {
113
- const actionForCurrentPage = useFormAction();
114
- const pendingFormSubmit = useTransition().submission;
110
+ fetcher?: Fetcher
111
+ ): [boolean, () => void, () => void] => {
112
+ const [isSubmitStarted, setSubmitStarted] = useState(false);
113
+ const transition = useTransition();
114
+ const hasActiveSubmission = fetcher
115
+ ? fetcher.state === "submitting"
116
+ : !!transition.submission;
117
+ const isSubmitting = hasActiveSubmission && isSubmitStarted;
115
118
 
116
- if (fetcher) return fetcher.state === "submitting";
117
- if (!pendingFormSubmit) return false;
119
+ const startSubmit = () => setSubmitStarted(true);
120
+ const endSubmit = () => setSubmitStarted(false);
118
121
 
119
- const { formData, action: pendingAction } = pendingFormSubmit;
120
- const pendingSubAction = formData.get("subaction");
121
- const expectedAction = action ?? actionForCurrentPage;
122
- if (subaction)
123
- return expectedAction === pendingAction && subaction === pendingSubAction;
124
- return expectedAction === pendingAction && !pendingSubAction;
122
+ return [isSubmitting, startSubmit, endSubmit];
125
123
  };
126
124
 
127
125
  const getDataFromForm = (el: HTMLFormElement) => new FormData(el);
@@ -226,8 +224,8 @@ export function ValidatedForm<DataType>({
226
224
  const [fieldErrors, setFieldErrors] = useFieldErrors(
227
225
  backendError?.fieldErrors
228
226
  );
229
- const isSubmitting = useIsSubmitting(action, subaction, fetcher);
230
- const [isValidating, setIsValidating] = useState(false);
227
+ const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
228
+
231
229
  const defaultsToUse = useDefaultValues(
232
230
  backendError?.repopulateFields,
233
231
  defaultValues
@@ -237,7 +235,7 @@ export function ValidatedForm<DataType>({
237
235
  const submit = useSubmit();
238
236
  const formRef = useRef<HTMLFormElement>(null);
239
237
  useSubmitComplete(isSubmitting, () => {
240
- setIsValidating(false);
238
+ endSubmit();
241
239
  if (!backendError && resetAfterSubmit) {
242
240
  formRef.current?.reset();
243
241
  }
@@ -249,7 +247,7 @@ export function ValidatedForm<DataType>({
249
247
  fieldErrors,
250
248
  action,
251
249
  defaultValues: defaultsToUse,
252
- isSubmitting: isValidating || isSubmitting,
250
+ isSubmitting,
253
251
  isValid: Object.keys(fieldErrors).length === 0,
254
252
  touchedFields,
255
253
  setFieldTouched: (fieldName: string, touched: boolean) =>
@@ -298,7 +296,6 @@ export function ValidatedForm<DataType>({
298
296
  fieldErrors,
299
297
  action,
300
298
  defaultsToUse,
301
- isValidating,
302
299
  isSubmitting,
303
300
  touchedFields,
304
301
  hasBeenSubmitted,
@@ -346,12 +343,12 @@ export function ValidatedForm<DataType>({
346
343
  onSubmit={async (e) => {
347
344
  e.preventDefault();
348
345
  setHasBeenSubmitted(true);
349
- setIsValidating(true);
346
+ startSubmit();
350
347
  const result = await validator.validate(
351
348
  getDataFromForm(e.currentTarget)
352
349
  );
353
350
  if (result.error) {
354
- setIsValidating(false);
351
+ endSubmit();
355
352
  setFieldErrors(result.error.fieldErrors);
356
353
  if (!disableFocusOnError) {
357
354
  focusFirstInvalidInput(