remix-validated-form 4.0.0 → 4.0.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.
- package/.turbo/turbo-build.log +2 -2
- package/browser/ValidatedForm.d.ts +1 -1
- package/browser/ValidatedForm.js +24 -24
- package/build/ValidatedForm.d.ts +1 -1
- package/build/ValidatedForm.js +23 -23
- package/package.json +1 -1
- package/src/ValidatedForm.tsx +30 -22
package/.turbo/turbo-build.log
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
[2K[1G[2m$ npm run build:browser && npm run build:main[22m
|
2
2
|
|
3
|
-
> remix-validated-form@
|
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@
|
7
|
+
> remix-validated-form@4.0.1-beta.1 build:main
|
8
8
|
> tsc --module CommonJS --outDir ./build
|
9
9
|
|
@@ -47,4 +47,4 @@ export declare type FormProps<DataType> = {
|
|
47
47
|
/**
|
48
48
|
* The primary form component of `remix-validated-form`.
|
49
49
|
*/
|
50
|
-
export declare function ValidatedForm<DataType>({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, ...rest }: FormProps<DataType>): JSX.Element;
|
50
|
+
export declare function ValidatedForm<DataType>({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, method, replace, ...rest }: FormProps<DataType>): JSX.Element;
|
package/browser/ValidatedForm.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { Form as RemixForm, useActionData,
|
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,18 @@ function useFieldErrors(fieldErrorsFromBackend) {
|
|
30
30
|
}, [fieldErrorsFromBackend]);
|
31
31
|
return [fieldErrors, setFieldErrors];
|
32
32
|
}
|
33
|
-
const useIsSubmitting = (
|
34
|
-
const
|
35
|
-
const
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
const
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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 startSubmit = () => setSubmitStarted(true);
|
40
|
+
const endSubmit = () => setSubmitStarted(false);
|
41
|
+
useSubmitComplete(hasActiveSubmission, () => {
|
42
|
+
endSubmit();
|
43
|
+
});
|
44
|
+
return [isSubmitStarted, startSubmit, endSubmit];
|
46
45
|
};
|
47
46
|
const getDataFromForm = (el) => new FormData(el);
|
48
47
|
/**
|
@@ -110,12 +109,11 @@ const focusFirstInvalidInput = (fieldErrors, customFocusHandlers, formElement) =
|
|
110
109
|
/**
|
111
110
|
* The primary form component of `remix-validated-form`.
|
112
111
|
*/
|
113
|
-
export function ValidatedForm({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, ...rest }) {
|
112
|
+
export function ValidatedForm({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, method, replace, ...rest }) {
|
114
113
|
var _a;
|
115
114
|
const backendError = useErrorResponseForThisForm(fetcher, subaction);
|
116
115
|
const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
|
117
|
-
const isSubmitting = useIsSubmitting(
|
118
|
-
const [isValidating, setIsValidating] = useState(false);
|
116
|
+
const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
|
119
117
|
const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
|
120
118
|
const [touchedFields, setTouchedFields] = useState({});
|
121
119
|
const [hasBeenSubmitted, setHasBeenSubmitted] = useState(false);
|
@@ -123,7 +121,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
123
121
|
const formRef = useRef(null);
|
124
122
|
useSubmitComplete(isSubmitting, () => {
|
125
123
|
var _a;
|
126
|
-
|
124
|
+
endSubmit();
|
127
125
|
if (!backendError && resetAfterSubmit) {
|
128
126
|
(_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
|
129
127
|
}
|
@@ -133,7 +131,7 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
133
131
|
fieldErrors,
|
134
132
|
action,
|
135
133
|
defaultValues: defaultsToUse,
|
136
|
-
isSubmitting
|
134
|
+
isSubmitting,
|
137
135
|
isValid: Object.keys(fieldErrors).length === 0,
|
138
136
|
touchedFields,
|
139
137
|
setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
|
@@ -179,7 +177,6 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
179
177
|
fieldErrors,
|
180
178
|
action,
|
181
179
|
defaultsToUse,
|
182
|
-
isValidating,
|
183
180
|
isSubmitting,
|
184
181
|
touchedFields,
|
185
182
|
hasBeenSubmitted,
|
@@ -208,13 +205,13 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
208
205
|
window.removeEventListener("click", handleClick);
|
209
206
|
};
|
210
207
|
}, []);
|
211
|
-
return (_jsx(Form, { ref: mergeRefs([formRef, formRefProp]), ...rest, action: action, onSubmit: async (e) => {
|
208
|
+
return (_jsx(Form, { ref: mergeRefs([formRef, formRefProp]), ...rest, action: action, method: method, replace: replace, onSubmit: async (e) => {
|
212
209
|
e.preventDefault();
|
213
210
|
setHasBeenSubmitted(true);
|
214
|
-
|
211
|
+
startSubmit();
|
215
212
|
const result = await validator.validate(getDataFromForm(e.currentTarget));
|
216
213
|
if (result.error) {
|
217
|
-
|
214
|
+
endSubmit();
|
218
215
|
setFieldErrors(result.error.fieldErrors);
|
219
216
|
if (!disableFocusOnError) {
|
220
217
|
focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
|
@@ -225,7 +222,10 @@ export function ValidatedForm({ validator, onSubmit, children, fetcher, action,
|
|
225
222
|
if (fetcher)
|
226
223
|
fetcher.submit(clickedButtonRef.current || e.currentTarget);
|
227
224
|
else
|
228
|
-
submit(clickedButtonRef.current || e.currentTarget
|
225
|
+
submit(clickedButtonRef.current || e.currentTarget, {
|
226
|
+
method,
|
227
|
+
replace,
|
228
|
+
});
|
229
229
|
clickedButtonRef.current = null;
|
230
230
|
}
|
231
231
|
}, onReset: (event) => {
|
package/build/ValidatedForm.d.ts
CHANGED
@@ -47,4 +47,4 @@ export declare type FormProps<DataType> = {
|
|
47
47
|
/**
|
48
48
|
* The primary form component of `remix-validated-form`.
|
49
49
|
*/
|
50
|
-
export declare function ValidatedForm<DataType>({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, ...rest }: FormProps<DataType>): JSX.Element;
|
50
|
+
export declare function ValidatedForm<DataType>({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, method, replace, ...rest }: FormProps<DataType>): JSX.Element;
|
package/build/ValidatedForm.js
CHANGED
@@ -55,19 +55,18 @@ function useFieldErrors(fieldErrorsFromBackend) {
|
|
55
55
|
}, [fieldErrorsFromBackend]);
|
56
56
|
return [fieldErrors, setFieldErrors];
|
57
57
|
}
|
58
|
-
const useIsSubmitting = (
|
59
|
-
const
|
60
|
-
const
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
const
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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 startSubmit = () => setSubmitStarted(true);
|
65
|
+
const endSubmit = () => setSubmitStarted(false);
|
66
|
+
(0, submissionCallbacks_1.useSubmitComplete)(hasActiveSubmission, () => {
|
67
|
+
endSubmit();
|
68
|
+
});
|
69
|
+
return [isSubmitStarted, startSubmit, endSubmit];
|
71
70
|
};
|
72
71
|
const getDataFromForm = (el) => new FormData(el);
|
73
72
|
/**
|
@@ -135,12 +134,11 @@ const focusFirstInvalidInput = (fieldErrors, customFocusHandlers, formElement) =
|
|
135
134
|
/**
|
136
135
|
* The primary form component of `remix-validated-form`.
|
137
136
|
*/
|
138
|
-
function ValidatedForm({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, ...rest }) {
|
137
|
+
function ValidatedForm({ validator, onSubmit, children, fetcher, action, defaultValues, formRef: formRefProp, onReset, subaction, resetAfterSubmit, disableFocusOnError, method, replace, ...rest }) {
|
139
138
|
var _a;
|
140
139
|
const backendError = useErrorResponseForThisForm(fetcher, subaction);
|
141
140
|
const [fieldErrors, setFieldErrors] = useFieldErrors(backendError === null || backendError === void 0 ? void 0 : backendError.fieldErrors);
|
142
|
-
const isSubmitting = useIsSubmitting(
|
143
|
-
const [isValidating, setIsValidating] = (0, react_2.useState)(false);
|
141
|
+
const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
|
144
142
|
const defaultsToUse = useDefaultValues(backendError === null || backendError === void 0 ? void 0 : backendError.repopulateFields, defaultValues);
|
145
143
|
const [touchedFields, setTouchedFields] = (0, react_2.useState)({});
|
146
144
|
const [hasBeenSubmitted, setHasBeenSubmitted] = (0, react_2.useState)(false);
|
@@ -148,7 +146,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
148
146
|
const formRef = (0, react_2.useRef)(null);
|
149
147
|
(0, submissionCallbacks_1.useSubmitComplete)(isSubmitting, () => {
|
150
148
|
var _a;
|
151
|
-
|
149
|
+
endSubmit();
|
152
150
|
if (!backendError && resetAfterSubmit) {
|
153
151
|
(_a = formRef.current) === null || _a === void 0 ? void 0 : _a.reset();
|
154
152
|
}
|
@@ -158,7 +156,7 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
158
156
|
fieldErrors,
|
159
157
|
action,
|
160
158
|
defaultValues: defaultsToUse,
|
161
|
-
isSubmitting
|
159
|
+
isSubmitting,
|
162
160
|
isValid: Object.keys(fieldErrors).length === 0,
|
163
161
|
touchedFields,
|
164
162
|
setFieldTouched: (fieldName, touched) => setTouchedFields((prev) => ({
|
@@ -204,7 +202,6 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
204
202
|
fieldErrors,
|
205
203
|
action,
|
206
204
|
defaultsToUse,
|
207
|
-
isValidating,
|
208
205
|
isSubmitting,
|
209
206
|
touchedFields,
|
210
207
|
hasBeenSubmitted,
|
@@ -233,13 +230,13 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
233
230
|
window.removeEventListener("click", handleClick);
|
234
231
|
};
|
235
232
|
}, []);
|
236
|
-
return ((0, jsx_runtime_1.jsx)(Form, { ref: (0, util_1.mergeRefs)([formRef, formRefProp]), ...rest, action: action, onSubmit: async (e) => {
|
233
|
+
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
234
|
e.preventDefault();
|
238
235
|
setHasBeenSubmitted(true);
|
239
|
-
|
236
|
+
startSubmit();
|
240
237
|
const result = await validator.validate(getDataFromForm(e.currentTarget));
|
241
238
|
if (result.error) {
|
242
|
-
|
239
|
+
endSubmit();
|
243
240
|
setFieldErrors(result.error.fieldErrors);
|
244
241
|
if (!disableFocusOnError) {
|
245
242
|
focusFirstInvalidInput(result.error.fieldErrors, customFocusHandlers(), formRef.current);
|
@@ -250,7 +247,10 @@ function ValidatedForm({ validator, onSubmit, children, fetcher, action, default
|
|
250
247
|
if (fetcher)
|
251
248
|
fetcher.submit(clickedButtonRef.current || e.currentTarget);
|
252
249
|
else
|
253
|
-
submit(clickedButtonRef.current || e.currentTarget
|
250
|
+
submit(clickedButtonRef.current || e.currentTarget, {
|
251
|
+
method,
|
252
|
+
replace,
|
253
|
+
});
|
254
254
|
clickedButtonRef.current = null;
|
255
255
|
}
|
256
256
|
}, onReset: (event) => {
|
package/package.json
CHANGED
package/src/ValidatedForm.tsx
CHANGED
@@ -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,22 @@ function useFieldErrors(
|
|
106
107
|
}
|
107
108
|
|
108
109
|
const useIsSubmitting = (
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
const
|
114
|
-
|
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
|
+
|
118
|
+
const startSubmit = () => setSubmitStarted(true);
|
119
|
+
const endSubmit = () => setSubmitStarted(false);
|
115
120
|
|
116
|
-
|
117
|
-
|
121
|
+
useSubmitComplete(hasActiveSubmission, () => {
|
122
|
+
endSubmit();
|
123
|
+
});
|
118
124
|
|
119
|
-
|
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;
|
125
|
+
return [isSubmitStarted, startSubmit, endSubmit];
|
125
126
|
};
|
126
127
|
|
127
128
|
const getDataFromForm = (el: HTMLFormElement) => new FormData(el);
|
@@ -218,14 +219,16 @@ export function ValidatedForm<DataType>({
|
|
218
219
|
subaction,
|
219
220
|
resetAfterSubmit,
|
220
221
|
disableFocusOnError,
|
222
|
+
method,
|
223
|
+
replace,
|
221
224
|
...rest
|
222
225
|
}: FormProps<DataType>) {
|
223
226
|
const backendError = useErrorResponseForThisForm(fetcher, subaction);
|
224
227
|
const [fieldErrors, setFieldErrors] = useFieldErrors(
|
225
228
|
backendError?.fieldErrors
|
226
229
|
);
|
227
|
-
const isSubmitting = useIsSubmitting(
|
228
|
-
|
230
|
+
const [isSubmitting, startSubmit, endSubmit] = useIsSubmitting(fetcher);
|
231
|
+
|
229
232
|
const defaultsToUse = useDefaultValues(
|
230
233
|
backendError?.repopulateFields,
|
231
234
|
defaultValues
|
@@ -235,7 +238,7 @@ export function ValidatedForm<DataType>({
|
|
235
238
|
const submit = useSubmit();
|
236
239
|
const formRef = useRef<HTMLFormElement>(null);
|
237
240
|
useSubmitComplete(isSubmitting, () => {
|
238
|
-
|
241
|
+
endSubmit();
|
239
242
|
if (!backendError && resetAfterSubmit) {
|
240
243
|
formRef.current?.reset();
|
241
244
|
}
|
@@ -247,7 +250,7 @@ export function ValidatedForm<DataType>({
|
|
247
250
|
fieldErrors,
|
248
251
|
action,
|
249
252
|
defaultValues: defaultsToUse,
|
250
|
-
isSubmitting
|
253
|
+
isSubmitting,
|
251
254
|
isValid: Object.keys(fieldErrors).length === 0,
|
252
255
|
touchedFields,
|
253
256
|
setFieldTouched: (fieldName: string, touched: boolean) =>
|
@@ -296,7 +299,6 @@ export function ValidatedForm<DataType>({
|
|
296
299
|
fieldErrors,
|
297
300
|
action,
|
298
301
|
defaultsToUse,
|
299
|
-
isValidating,
|
300
302
|
isSubmitting,
|
301
303
|
touchedFields,
|
302
304
|
hasBeenSubmitted,
|
@@ -339,15 +341,17 @@ export function ValidatedForm<DataType>({
|
|
339
341
|
ref={mergeRefs([formRef, formRefProp])}
|
340
342
|
{...rest}
|
341
343
|
action={action}
|
344
|
+
method={method}
|
345
|
+
replace={replace}
|
342
346
|
onSubmit={async (e) => {
|
343
347
|
e.preventDefault();
|
344
348
|
setHasBeenSubmitted(true);
|
345
|
-
|
349
|
+
startSubmit();
|
346
350
|
const result = await validator.validate(
|
347
351
|
getDataFromForm(e.currentTarget)
|
348
352
|
);
|
349
353
|
if (result.error) {
|
350
|
-
|
354
|
+
endSubmit();
|
351
355
|
setFieldErrors(result.error.fieldErrors);
|
352
356
|
if (!disableFocusOnError) {
|
353
357
|
focusFirstInvalidInput(
|
@@ -360,7 +364,11 @@ export function ValidatedForm<DataType>({
|
|
360
364
|
onSubmit && onSubmit(result.data, e);
|
361
365
|
if (fetcher)
|
362
366
|
fetcher.submit(clickedButtonRef.current || e.currentTarget);
|
363
|
-
else
|
367
|
+
else
|
368
|
+
submit(clickedButtonRef.current || e.currentTarget, {
|
369
|
+
method,
|
370
|
+
replace,
|
371
|
+
});
|
364
372
|
clickedButtonRef.current = null;
|
365
373
|
}
|
366
374
|
}}
|