remix-validated-form 4.0.2 → 4.1.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/.turbo/turbo-build.log +2 -2
- package/README.md +4 -4
- package/browser/ValidatedForm.d.ts +2 -2
- package/browser/ValidatedForm.js +142 -151
- package/browser/components.d.ts +5 -8
- package/browser/components.js +5 -5
- package/browser/hooks.d.ts +19 -14
- package/browser/hooks.js +41 -39
- package/browser/index.d.ts +1 -1
- package/browser/index.js +1 -0
- package/browser/internal/constants.d.ts +3 -0
- package/browser/internal/constants.js +3 -0
- package/browser/internal/formContext.d.ts +7 -49
- package/browser/internal/formContext.js +1 -1
- package/browser/internal/getInputProps.js +4 -3
- package/browser/internal/hooks.d.ts +22 -0
- package/browser/internal/hooks.js +110 -0
- package/browser/internal/state.d.ts +269 -0
- package/browser/internal/state.js +82 -0
- package/browser/internal/util.d.ts +1 -0
- package/browser/internal/util.js +2 -0
- package/browser/lowLevelHooks.d.ts +0 -0
- package/browser/lowLevelHooks.js +1 -0
- package/browser/server.d.ts +5 -0
- package/browser/server.js +5 -0
- package/browser/userFacingFormContext.d.ts +56 -0
- package/browser/userFacingFormContext.js +40 -0
- package/browser/validation/createValidator.js +4 -0
- package/browser/validation/types.d.ts +3 -0
- package/build/ValidatedForm.d.ts +2 -2
- package/build/ValidatedForm.js +138 -147
- package/build/hooks.d.ts +19 -14
- package/build/hooks.js +43 -45
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -0
- package/build/internal/constants.d.ts +3 -0
- package/build/internal/constants.js +7 -0
- package/build/internal/formContext.d.ts +7 -49
- package/build/internal/formContext.js +2 -2
- package/build/internal/getInputProps.js +7 -3
- package/build/internal/hooks.d.ts +22 -0
- package/build/internal/hooks.js +130 -0
- package/build/internal/state.d.ts +269 -0
- package/build/internal/state.js +92 -0
- package/build/internal/util.d.ts +1 -0
- package/build/internal/util.js +3 -1
- package/build/server.d.ts +5 -0
- package/build/server.js +7 -1
- package/build/userFacingFormContext.d.ts +56 -0
- package/build/userFacingFormContext.js +44 -0
- package/build/validation/createValidator.js +4 -0
- package/build/validation/types.d.ts +3 -0
- package/package.json +3 -1
- package/src/ValidatedForm.tsx +205 -203
- package/src/hooks.ts +71 -54
- package/src/index.ts +1 -1
- package/src/internal/constants.ts +4 -0
- package/src/internal/formContext.ts +8 -49
- package/src/internal/getInputProps.ts +6 -4
- package/src/internal/hooks.ts +191 -0
- package/src/internal/state.ts +210 -0
- package/src/internal/util.ts +4 -0
- package/src/server.ts +16 -0
- package/src/userFacingFormContext.ts +129 -0
- package/src/validation/createValidator.ts +4 -0
- package/src/validation/types.ts +3 -1
package/src/server.ts
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
import { json } from "@remix-run/server-runtime";
|
2
|
+
import {
|
3
|
+
formDefaultValuesKey,
|
4
|
+
FORM_DEFAULTS_FIELD,
|
5
|
+
} from "./internal/constants";
|
2
6
|
import {
|
3
7
|
ValidatorError,
|
4
8
|
ValidationErrorResponseData,
|
@@ -27,7 +31,19 @@ export function validationError(
|
|
27
31
|
fieldErrors: error.fieldErrors,
|
28
32
|
subaction: error.subaction,
|
29
33
|
repopulateFields,
|
34
|
+
formId: error.formId,
|
30
35
|
},
|
31
36
|
{ status: 422 }
|
32
37
|
);
|
33
38
|
}
|
39
|
+
|
40
|
+
export type FormDefaults = {
|
41
|
+
[formDefaultsKey: `${typeof FORM_DEFAULTS_FIELD}_${string}`]: any;
|
42
|
+
};
|
43
|
+
|
44
|
+
export const setFormDefaults = <DataType = any>(
|
45
|
+
formId: string,
|
46
|
+
defaultValues: Partial<DataType>
|
47
|
+
): FormDefaults => ({
|
48
|
+
[formDefaultValuesKey(formId)]: defaultValues,
|
49
|
+
});
|
@@ -0,0 +1,129 @@
|
|
1
|
+
import { useCallback } from "react";
|
2
|
+
import { useIsSubmitting, useIsValid } from "./hooks";
|
3
|
+
import {
|
4
|
+
useClearError,
|
5
|
+
useContextSelectAtom,
|
6
|
+
useDefaultValuesForForm,
|
7
|
+
useFieldErrorsForForm,
|
8
|
+
useHydratableSelector,
|
9
|
+
useInternalFormContext,
|
10
|
+
useSetTouched,
|
11
|
+
} from "./internal/hooks";
|
12
|
+
import {
|
13
|
+
actionAtom,
|
14
|
+
defaultValuesAtom,
|
15
|
+
fieldErrorsAtom,
|
16
|
+
hasBeenSubmittedAtom,
|
17
|
+
registerReceiveFocusAtom,
|
18
|
+
touchedFieldsAtom,
|
19
|
+
validateFieldAtom,
|
20
|
+
} from "./internal/state";
|
21
|
+
import { FieldErrors, TouchedFields } from "./validation/types";
|
22
|
+
|
23
|
+
export type FormContextValue = {
|
24
|
+
/**
|
25
|
+
* All the errors in all the fields in the form.
|
26
|
+
*/
|
27
|
+
fieldErrors: FieldErrors;
|
28
|
+
/**
|
29
|
+
* Clear the errors of the specified fields.
|
30
|
+
*/
|
31
|
+
clearError: (...names: string[]) => void;
|
32
|
+
/**
|
33
|
+
* Validate the specified field.
|
34
|
+
*/
|
35
|
+
validateField: (fieldName: string) => Promise<string | null>;
|
36
|
+
/**
|
37
|
+
* The `action` prop of the form.
|
38
|
+
*/
|
39
|
+
action?: string;
|
40
|
+
/**
|
41
|
+
* Whether or not the form is submitting.
|
42
|
+
*/
|
43
|
+
isSubmitting: boolean;
|
44
|
+
/**
|
45
|
+
* Whether or not a submission has been attempted.
|
46
|
+
* This is true once the form has been submitted, even if there were validation errors.
|
47
|
+
* Resets to false when the form is reset.
|
48
|
+
*/
|
49
|
+
hasBeenSubmitted: boolean;
|
50
|
+
/**
|
51
|
+
* Whether or not the form is valid.
|
52
|
+
*/
|
53
|
+
isValid: boolean;
|
54
|
+
/**
|
55
|
+
* The default values of the form.
|
56
|
+
*/
|
57
|
+
defaultValues?: { [fieldName: string]: any };
|
58
|
+
/**
|
59
|
+
* Register a custom focus handler to be used when
|
60
|
+
* the field needs to receive focus due to a validation error.
|
61
|
+
*/
|
62
|
+
registerReceiveFocus: (fieldName: string, handler: () => void) => () => void;
|
63
|
+
/**
|
64
|
+
* Any fields that have been touched by the user.
|
65
|
+
*/
|
66
|
+
touchedFields: TouchedFields;
|
67
|
+
/**
|
68
|
+
* Change the touched state of the specified field.
|
69
|
+
*/
|
70
|
+
setFieldTouched: (fieldName: string, touched: boolean) => void;
|
71
|
+
};
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Provides access to some of the internal state of the form.
|
75
|
+
*/
|
76
|
+
export const useFormContext = (formId?: string): FormContextValue => {
|
77
|
+
// Try to access context so we get our error specific to this hook if it's not there
|
78
|
+
const context = useInternalFormContext(formId, "useFormContext");
|
79
|
+
|
80
|
+
const action = useContextSelectAtom(context.formId, actionAtom);
|
81
|
+
const isSubmitting = useIsSubmitting(formId);
|
82
|
+
const hasBeenSubmitted = useContextSelectAtom(
|
83
|
+
context.formId,
|
84
|
+
hasBeenSubmittedAtom
|
85
|
+
);
|
86
|
+
const isValid = useIsValid(formId);
|
87
|
+
const defaultValues = useHydratableSelector(
|
88
|
+
context,
|
89
|
+
defaultValuesAtom,
|
90
|
+
useDefaultValuesForForm(context)
|
91
|
+
);
|
92
|
+
const fieldErrors = useHydratableSelector(
|
93
|
+
context,
|
94
|
+
fieldErrorsAtom,
|
95
|
+
useFieldErrorsForForm(context)
|
96
|
+
);
|
97
|
+
|
98
|
+
const setFieldTouched = useSetTouched(context);
|
99
|
+
const touchedFields = useContextSelectAtom(context.formId, touchedFieldsAtom);
|
100
|
+
const validateField = useContextSelectAtom(context.formId, validateFieldAtom);
|
101
|
+
const registerReceiveFocus = useContextSelectAtom(
|
102
|
+
context.formId,
|
103
|
+
registerReceiveFocusAtom
|
104
|
+
);
|
105
|
+
|
106
|
+
const internalClearError = useClearError(context);
|
107
|
+
const clearError = useCallback(
|
108
|
+
(...names: string[]) => {
|
109
|
+
names.forEach((name) => {
|
110
|
+
internalClearError(name);
|
111
|
+
});
|
112
|
+
},
|
113
|
+
[internalClearError]
|
114
|
+
);
|
115
|
+
|
116
|
+
return {
|
117
|
+
isSubmitting,
|
118
|
+
hasBeenSubmitted,
|
119
|
+
isValid,
|
120
|
+
defaultValues,
|
121
|
+
clearError,
|
122
|
+
fieldErrors: fieldErrors ?? {},
|
123
|
+
action,
|
124
|
+
setFieldTouched,
|
125
|
+
touchedFields,
|
126
|
+
validateField,
|
127
|
+
registerReceiveFocus,
|
128
|
+
};
|
129
|
+
};
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { CreateValidatorArg, GenericObject, Validator } from "..";
|
2
|
+
import { FORM_ID_FIELD } from "../internal/constants";
|
2
3
|
import { objectFromPathEntries } from "../internal/flatten";
|
3
4
|
|
4
5
|
const preprocessFormData = (data: GenericObject | FormData): GenericObject => {
|
@@ -28,8 +29,10 @@ export function createValidator<T>(
|
|
28
29
|
error: {
|
29
30
|
fieldErrors: result.error,
|
30
31
|
subaction: data.subaction,
|
32
|
+
formId: data[FORM_ID_FIELD],
|
31
33
|
},
|
32
34
|
submittedData: data,
|
35
|
+
formId: data[FORM_ID_FIELD],
|
33
36
|
};
|
34
37
|
}
|
35
38
|
|
@@ -37,6 +40,7 @@ export function createValidator<T>(
|
|
37
40
|
data: result.data,
|
38
41
|
error: undefined,
|
39
42
|
submittedData: data,
|
43
|
+
formId: data[FORM_ID_FIELD],
|
40
44
|
};
|
41
45
|
},
|
42
46
|
validateField: (data: GenericObject | FormData, field: string) =>
|
package/src/validation/types.ts
CHANGED
@@ -6,16 +6,18 @@ export type GenericObject = { [key: string]: any };
|
|
6
6
|
|
7
7
|
export type ValidatorError = {
|
8
8
|
subaction?: string;
|
9
|
+
formId?: string;
|
9
10
|
fieldErrors: FieldErrors;
|
10
11
|
};
|
11
12
|
|
12
13
|
export type ValidationErrorResponseData = {
|
13
14
|
subaction?: string;
|
15
|
+
formId?: string;
|
14
16
|
fieldErrors: FieldErrors;
|
15
17
|
repopulateFields?: unknown;
|
16
18
|
};
|
17
19
|
|
18
|
-
export type BaseResult = { submittedData: GenericObject };
|
20
|
+
export type BaseResult = { submittedData: GenericObject; formId?: string };
|
19
21
|
export type ErrorResult = BaseResult & {
|
20
22
|
error: ValidatorError;
|
21
23
|
data: undefined;
|