remix-validated-form 5.1.4 → 5.1.6
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 +10 -10
- package/dist/index.cjs.js +4 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +4 -1
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -4
- package/.turbo/turbo-dev.log +0 -0
- package/.turbo/turbo-typecheck.log +0 -1
- package/browser/ValidatedForm.d.ts +0 -50
- package/browser/ValidatedForm.js +0 -210
- package/browser/hooks.d.ts +0 -67
- package/browser/hooks.js +0 -84
- package/browser/index.d.ts +0 -7
- package/browser/index.js +0 -7
- package/browser/internal/MultiValueMap.d.ts +0 -11
- package/browser/internal/MultiValueMap.js +0 -43
- package/browser/internal/constants.d.ts +0 -3
- package/browser/internal/constants.js +0 -3
- package/browser/internal/flatten.d.ts +0 -1
- package/browser/internal/flatten.js +0 -7
- package/browser/internal/formContext.d.ts +0 -12
- package/browser/internal/formContext.js +0 -2
- package/browser/internal/getInputProps.d.ts +0 -29
- package/browser/internal/getInputProps.js +0 -51
- package/browser/internal/hooks.d.ts +0 -35
- package/browser/internal/hooks.js +0 -118
- package/browser/internal/hydratable.d.ts +0 -14
- package/browser/internal/hydratable.js +0 -14
- package/browser/internal/logic/getCheckboxChecked.d.ts +0 -1
- package/browser/internal/logic/getCheckboxChecked.js +0 -9
- package/browser/internal/logic/getRadioChecked.d.ts +0 -1
- package/browser/internal/logic/getRadioChecked.js +0 -15
- package/browser/internal/logic/nestedObjectToPathObject.d.ts +0 -1
- package/browser/internal/logic/nestedObjectToPathObject.js +0 -47
- package/browser/internal/logic/requestSubmit.d.ts +0 -5
- package/browser/internal/logic/requestSubmit.js +0 -66
- package/browser/internal/reset.d.ts +0 -28
- package/browser/internal/reset.js +0 -13
- package/browser/internal/state/arrayUtil.d.ts +0 -12
- package/browser/internal/state/arrayUtil.js +0 -350
- package/browser/internal/state/atomUtils.d.ts +0 -38
- package/browser/internal/state/atomUtils.js +0 -5
- package/browser/internal/state/cleanup.d.ts +0 -2
- package/browser/internal/state/cleanup.js +0 -6
- package/browser/internal/state/controlledFieldStore.d.ts +0 -26
- package/browser/internal/state/controlledFieldStore.js +0 -70
- package/browser/internal/state/controlledFields.d.ts +0 -7
- package/browser/internal/state/controlledFields.js +0 -36
- package/browser/internal/state/createFormStore.d.ts +0 -79
- package/browser/internal/state/createFormStore.js +0 -306
- package/browser/internal/state/fieldArray.d.ts +0 -28
- package/browser/internal/state/fieldArray.js +0 -74
- package/browser/internal/state/storeFamily.d.ts +0 -9
- package/browser/internal/state/storeFamily.js +0 -18
- package/browser/internal/state/storeHooks.d.ts +0 -3
- package/browser/internal/state/storeHooks.js +0 -4
- package/browser/internal/state/types.d.ts +0 -1
- package/browser/internal/state/types.js +0 -1
- package/browser/internal/state.d.ts +0 -343
- package/browser/internal/state.js +0 -64
- package/browser/internal/submissionCallbacks.d.ts +0 -1
- package/browser/internal/submissionCallbacks.js +0 -13
- package/browser/internal/util.d.ts +0 -5
- package/browser/internal/util.js +0 -32
- package/browser/server.d.ts +0 -21
- package/browser/server.js +0 -27
- package/browser/unreleased/formStateHooks.d.ts +0 -64
- package/browser/unreleased/formStateHooks.js +0 -76
- package/browser/userFacingFormContext.d.ts +0 -85
- package/browser/userFacingFormContext.js +0 -41
- package/browser/validation/createValidator.d.ts +0 -7
- package/browser/validation/createValidator.js +0 -43
- package/browser/validation/types.d.ts +0 -58
- package/browser/validation/types.js +0 -1
- package/stats.html +0 -4044
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { FieldErrors, ValidationErrorResponseData } from "..";
|
|
2
|
-
import { InternalFormContextValue } from "./formContext";
|
|
3
|
-
import { Hydratable } from "./hydratable";
|
|
4
|
-
import { InternalFormId } from "./state/types";
|
|
5
|
-
export declare const useInternalFormContext: (formId?: string | symbol, hookName?: string) => InternalFormContextValue;
|
|
6
|
-
export declare function useErrorResponseForForm({ fetcher, subaction, formId, }: InternalFormContextValue): ValidationErrorResponseData | null;
|
|
7
|
-
export declare const useFieldErrorsForForm: (context: InternalFormContextValue) => Hydratable<FieldErrors | undefined>;
|
|
8
|
-
export declare const useDefaultValuesFromLoader: ({ formId, }: InternalFormContextValue) => any;
|
|
9
|
-
export declare const useDefaultValuesForForm: (context: InternalFormContextValue) => Hydratable<{
|
|
10
|
-
[fieldName: string]: any;
|
|
11
|
-
}>;
|
|
12
|
-
export declare const useHasActiveFormSubmit: ({ fetcher, }: InternalFormContextValue) => boolean;
|
|
13
|
-
export declare const useFieldTouched: (field: string, { formId }: InternalFormContextValue) => readonly [boolean, (touched: boolean) => void];
|
|
14
|
-
export declare const useFieldError: (name: string, context: InternalFormContextValue) => string | undefined;
|
|
15
|
-
export declare const useClearError: (context: InternalFormContextValue) => (field: string) => void;
|
|
16
|
-
export declare const useCurrentDefaultValueForField: (formId: InternalFormId, field: string) => any;
|
|
17
|
-
export declare const useFieldDefaultValue: (name: string, context: InternalFormContextValue) => any;
|
|
18
|
-
export declare const useInternalIsSubmitting: (formId: InternalFormId) => boolean;
|
|
19
|
-
export declare const useInternalIsValid: (formId: InternalFormId) => boolean;
|
|
20
|
-
export declare const useInternalHasBeenSubmitted: (formId: InternalFormId) => boolean;
|
|
21
|
-
export declare const useValidateField: (formId: InternalFormId) => (fieldName: string) => Promise<string | null>;
|
|
22
|
-
export declare const useValidate: (formId: InternalFormId) => () => Promise<import("..").ValidationResult<unknown>>;
|
|
23
|
-
export declare const useRegisterReceiveFocus: (formId: InternalFormId) => (fieldName: string, handler: () => void) => () => void;
|
|
24
|
-
export declare const useSyncedDefaultValues: (formId: InternalFormId) => {
|
|
25
|
-
[fieldName: string]: any;
|
|
26
|
-
};
|
|
27
|
-
export declare const useSetTouched: ({ formId }: InternalFormContextValue) => (field: string, touched: boolean) => void;
|
|
28
|
-
export declare const useTouchedFields: (formId: InternalFormId) => import("..").TouchedFields;
|
|
29
|
-
export declare const useFieldErrors: (formId: InternalFormId) => FieldErrors;
|
|
30
|
-
export declare const useSetFieldErrors: (formId: InternalFormId) => (errors: FieldErrors) => void;
|
|
31
|
-
export declare const useResetFormElement: (formId: InternalFormId) => () => void;
|
|
32
|
-
export declare const useSubmitForm: (formId: InternalFormId) => () => void;
|
|
33
|
-
export declare const useFormActionProp: (formId: InternalFormId) => string | undefined;
|
|
34
|
-
export declare const useFormSubactionProp: (formId: InternalFormId) => string | undefined;
|
|
35
|
-
export declare const useFormValues: (formId: InternalFormId) => () => FormData;
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { useActionData, useMatches, useTransition } from "@remix-run/react";
|
|
2
|
-
import { useCallback, useContext } from "react";
|
|
3
|
-
import { getPath } from "set-get";
|
|
4
|
-
import invariant from "tiny-invariant";
|
|
5
|
-
import { formDefaultValuesKey } from "./constants";
|
|
6
|
-
import { InternalFormContext } from "./formContext";
|
|
7
|
-
import { hydratable } from "./hydratable";
|
|
8
|
-
import { useFormStore } from "./state/storeHooks";
|
|
9
|
-
export const useInternalFormContext = (formId, hookName) => {
|
|
10
|
-
const formContext = useContext(InternalFormContext);
|
|
11
|
-
if (formId)
|
|
12
|
-
return { formId };
|
|
13
|
-
if (formContext)
|
|
14
|
-
return formContext;
|
|
15
|
-
throw new Error(`Unable to determine form for ${hookName}. Please use it inside a ValidatedForm or pass a 'formId'.`);
|
|
16
|
-
};
|
|
17
|
-
export function useErrorResponseForForm({ fetcher, subaction, formId, }) {
|
|
18
|
-
var _a;
|
|
19
|
-
const actionData = useActionData();
|
|
20
|
-
if (fetcher) {
|
|
21
|
-
if ((_a = fetcher.data) === null || _a === void 0 ? void 0 : _a.fieldErrors)
|
|
22
|
-
return fetcher.data;
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
if (!(actionData === null || actionData === void 0 ? void 0 : actionData.fieldErrors))
|
|
26
|
-
return null;
|
|
27
|
-
// If there's an explicit id, we should ignore data that has the wrong id
|
|
28
|
-
if (typeof formId === "string" && actionData.formId)
|
|
29
|
-
return actionData.formId === formId ? actionData : null;
|
|
30
|
-
if ((!subaction && !actionData.subaction) ||
|
|
31
|
-
actionData.subaction === subaction)
|
|
32
|
-
return actionData;
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
export const useFieldErrorsForForm = (context) => {
|
|
36
|
-
const response = useErrorResponseForForm(context);
|
|
37
|
-
const hydrated = useFormStore(context.formId, (state) => state.isHydrated);
|
|
38
|
-
return hydratable.from(response === null || response === void 0 ? void 0 : response.fieldErrors, hydrated);
|
|
39
|
-
};
|
|
40
|
-
export const useDefaultValuesFromLoader = ({ formId, }) => {
|
|
41
|
-
const matches = useMatches();
|
|
42
|
-
if (typeof formId === "string") {
|
|
43
|
-
const dataKey = formDefaultValuesKey(formId);
|
|
44
|
-
// If multiple loaders declare the same default values,
|
|
45
|
-
// we should use the data from the deepest route.
|
|
46
|
-
const match = matches
|
|
47
|
-
.reverse()
|
|
48
|
-
.find((match) => match.data && dataKey in match.data);
|
|
49
|
-
return match === null || match === void 0 ? void 0 : match.data[dataKey];
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
};
|
|
53
|
-
export const useDefaultValuesForForm = (context) => {
|
|
54
|
-
const { formId, defaultValuesProp } = context;
|
|
55
|
-
const hydrated = useFormStore(formId, (state) => state.isHydrated);
|
|
56
|
-
const errorResponse = useErrorResponseForForm(context);
|
|
57
|
-
const defaultValuesFromLoader = useDefaultValuesFromLoader(context);
|
|
58
|
-
// Typical flow is:
|
|
59
|
-
// - Default values only available from props or server
|
|
60
|
-
// - Props have a higher priority than server
|
|
61
|
-
// - State gets hydrated with default values
|
|
62
|
-
// - After submit, we may need to use values from the error
|
|
63
|
-
if (hydrated)
|
|
64
|
-
return hydratable.hydratedData();
|
|
65
|
-
if (errorResponse === null || errorResponse === void 0 ? void 0 : errorResponse.repopulateFields) {
|
|
66
|
-
invariant(typeof errorResponse.repopulateFields === "object", "repopulateFields returned something other than an object");
|
|
67
|
-
return hydratable.serverData(errorResponse.repopulateFields);
|
|
68
|
-
}
|
|
69
|
-
if (defaultValuesProp)
|
|
70
|
-
return hydratable.serverData(defaultValuesProp);
|
|
71
|
-
return hydratable.serverData(defaultValuesFromLoader);
|
|
72
|
-
};
|
|
73
|
-
export const useHasActiveFormSubmit = ({ fetcher, }) => {
|
|
74
|
-
const transition = useTransition();
|
|
75
|
-
const hasActiveSubmission = fetcher
|
|
76
|
-
? fetcher.state === "submitting"
|
|
77
|
-
: !!transition.submission;
|
|
78
|
-
return hasActiveSubmission;
|
|
79
|
-
};
|
|
80
|
-
export const useFieldTouched = (field, { formId }) => {
|
|
81
|
-
const touched = useFormStore(formId, (state) => state.touchedFields[field]);
|
|
82
|
-
const setFieldTouched = useFormStore(formId, (state) => state.setTouched);
|
|
83
|
-
const setTouched = useCallback((touched) => setFieldTouched(field, touched), [field, setFieldTouched]);
|
|
84
|
-
return [touched, setTouched];
|
|
85
|
-
};
|
|
86
|
-
export const useFieldError = (name, context) => {
|
|
87
|
-
const fieldErrors = useFieldErrorsForForm(context);
|
|
88
|
-
const state = useFormStore(context.formId, (state) => state.fieldErrors[name]);
|
|
89
|
-
return fieldErrors.map((fieldErrors) => fieldErrors === null || fieldErrors === void 0 ? void 0 : fieldErrors[name]).hydrateTo(state);
|
|
90
|
-
};
|
|
91
|
-
export const useClearError = (context) => {
|
|
92
|
-
const { formId } = context;
|
|
93
|
-
return useFormStore(formId, (state) => state.clearFieldError);
|
|
94
|
-
};
|
|
95
|
-
export const useCurrentDefaultValueForField = (formId, field) => useFormStore(formId, (state) => getPath(state.currentDefaultValues, field));
|
|
96
|
-
export const useFieldDefaultValue = (name, context) => {
|
|
97
|
-
const defaultValues = useDefaultValuesForForm(context);
|
|
98
|
-
const state = useCurrentDefaultValueForField(context.formId, name);
|
|
99
|
-
return defaultValues.map((val) => getPath(val, name)).hydrateTo(state);
|
|
100
|
-
};
|
|
101
|
-
export const useInternalIsSubmitting = (formId) => useFormStore(formId, (state) => state.isSubmitting);
|
|
102
|
-
export const useInternalIsValid = (formId) => useFormStore(formId, (state) => state.isValid());
|
|
103
|
-
export const useInternalHasBeenSubmitted = (formId) => useFormStore(formId, (state) => state.hasBeenSubmitted);
|
|
104
|
-
export const useValidateField = (formId) => useFormStore(formId, (state) => state.validateField);
|
|
105
|
-
export const useValidate = (formId) => useFormStore(formId, (state) => state.validate);
|
|
106
|
-
const noOpReceiver = () => () => { };
|
|
107
|
-
export const useRegisterReceiveFocus = (formId) => useFormStore(formId, (state) => { var _a, _b; return (_b = (_a = state.formProps) === null || _a === void 0 ? void 0 : _a.registerReceiveFocus) !== null && _b !== void 0 ? _b : noOpReceiver; });
|
|
108
|
-
const defaultDefaultValues = {};
|
|
109
|
-
export const useSyncedDefaultValues = (formId) => useFormStore(formId, (state) => { var _a, _b; return (_b = (_a = state.formProps) === null || _a === void 0 ? void 0 : _a.defaultValues) !== null && _b !== void 0 ? _b : defaultDefaultValues; });
|
|
110
|
-
export const useSetTouched = ({ formId }) => useFormStore(formId, (state) => state.setTouched);
|
|
111
|
-
export const useTouchedFields = (formId) => useFormStore(formId, (state) => state.touchedFields);
|
|
112
|
-
export const useFieldErrors = (formId) => useFormStore(formId, (state) => state.fieldErrors);
|
|
113
|
-
export const useSetFieldErrors = (formId) => useFormStore(formId, (state) => state.setFieldErrors);
|
|
114
|
-
export const useResetFormElement = (formId) => useFormStore(formId, (state) => state.resetFormElement);
|
|
115
|
-
export const useSubmitForm = (formId) => useFormStore(formId, (state) => state.submit);
|
|
116
|
-
export const useFormActionProp = (formId) => useFormStore(formId, (state) => { var _a; return (_a = state.formProps) === null || _a === void 0 ? void 0 : _a.action; });
|
|
117
|
-
export const useFormSubactionProp = (formId) => useFormStore(formId, (state) => { var _a; return (_a = state.formProps) === null || _a === void 0 ? void 0 : _a.subaction; });
|
|
118
|
-
export const useFormValues = (formId) => useFormStore(formId, (state) => state.getValues);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The purpose of this type is to simplify the logic
|
|
3
|
-
* around data that needs to come from the server initially,
|
|
4
|
-
* but from the internal state after hydration.
|
|
5
|
-
*/
|
|
6
|
-
export type Hydratable<T> = {
|
|
7
|
-
hydrateTo: (data: T) => T;
|
|
8
|
-
map: <U>(fn: (data: T) => U) => Hydratable<U>;
|
|
9
|
-
};
|
|
10
|
-
export declare const hydratable: {
|
|
11
|
-
serverData: <T>(data: T) => Hydratable<T>;
|
|
12
|
-
hydratedData: <T_1>() => Hydratable<T_1>;
|
|
13
|
-
from: <T_2>(data: T_2, hydrated: boolean) => Hydratable<T_2>;
|
|
14
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const serverData = (data) => ({
|
|
2
|
-
hydrateTo: () => data,
|
|
3
|
-
map: (fn) => serverData(fn(data)),
|
|
4
|
-
});
|
|
5
|
-
const hydratedData = () => ({
|
|
6
|
-
hydrateTo: (hydratedData) => hydratedData,
|
|
7
|
-
map: () => hydratedData(),
|
|
8
|
-
});
|
|
9
|
-
const from = (data, hydrated) => hydrated ? hydratedData() : serverData(data);
|
|
10
|
-
export const hydratable = {
|
|
11
|
-
serverData,
|
|
12
|
-
hydratedData,
|
|
13
|
-
from,
|
|
14
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const getCheckboxChecked: (checkboxValue: string | undefined, newValue: unknown) => boolean | undefined;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const getCheckboxChecked = (checkboxValue = "on", newValue) => {
|
|
2
|
-
if (Array.isArray(newValue))
|
|
3
|
-
return newValue.some((val) => val === true || val === checkboxValue);
|
|
4
|
-
if (typeof newValue === "boolean")
|
|
5
|
-
return newValue;
|
|
6
|
-
if (typeof newValue === "string")
|
|
7
|
-
return newValue === checkboxValue;
|
|
8
|
-
return undefined;
|
|
9
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const getRadioChecked: (radioValue: string | undefined, newValue: unknown) => boolean | undefined;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const getRadioChecked = (radioValue = "on", newValue) => {
|
|
2
|
-
if (typeof newValue === "string")
|
|
3
|
-
return newValue === radioValue;
|
|
4
|
-
return undefined;
|
|
5
|
-
};
|
|
6
|
-
if (import.meta.vitest) {
|
|
7
|
-
const { it, expect } = import.meta.vitest;
|
|
8
|
-
it("getRadioChecked", () => {
|
|
9
|
-
expect(getRadioChecked("on", "on")).toBe(true);
|
|
10
|
-
expect(getRadioChecked("on", undefined)).toBe(undefined);
|
|
11
|
-
expect(getRadioChecked("trueValue", undefined)).toBe(undefined);
|
|
12
|
-
expect(getRadioChecked("trueValue", "bob")).toBe(false);
|
|
13
|
-
expect(getRadioChecked("trueValue", "trueValue")).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const nestedObjectToPathObject: (val: any, acc: Record<string, any>, path: string) => any;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export const nestedObjectToPathObject = (val, acc, path) => {
|
|
2
|
-
if (Array.isArray(val)) {
|
|
3
|
-
val.forEach((v, index) => nestedObjectToPathObject(v, acc, `${path}[${index}]`));
|
|
4
|
-
return acc;
|
|
5
|
-
}
|
|
6
|
-
if (typeof val === "object") {
|
|
7
|
-
Object.entries(val).forEach(([key, value]) => {
|
|
8
|
-
const nextPath = path ? `${path}.${key}` : key;
|
|
9
|
-
nestedObjectToPathObject(value, acc, nextPath);
|
|
10
|
-
});
|
|
11
|
-
return acc;
|
|
12
|
-
}
|
|
13
|
-
if (val !== undefined) {
|
|
14
|
-
acc[path] = val;
|
|
15
|
-
}
|
|
16
|
-
return acc;
|
|
17
|
-
};
|
|
18
|
-
if (import.meta.vitest) {
|
|
19
|
-
const { describe, expect, it } = import.meta.vitest;
|
|
20
|
-
describe("nestedObjectToPathObject", () => {
|
|
21
|
-
it("should return an object with the correct path", () => {
|
|
22
|
-
const result = nestedObjectToPathObject({
|
|
23
|
-
a: 1,
|
|
24
|
-
b: 2,
|
|
25
|
-
c: { foo: "bar", baz: [true, false] },
|
|
26
|
-
d: [
|
|
27
|
-
{ foo: "bar", baz: [true, false] },
|
|
28
|
-
{ e: true, f: "hi" },
|
|
29
|
-
],
|
|
30
|
-
g: undefined,
|
|
31
|
-
}, {}, "");
|
|
32
|
-
expect(result).toEqual({
|
|
33
|
-
a: 1,
|
|
34
|
-
b: 2,
|
|
35
|
-
"c.foo": "bar",
|
|
36
|
-
"c.baz[0]": true,
|
|
37
|
-
"c.baz[1]": false,
|
|
38
|
-
"d[0].foo": "bar",
|
|
39
|
-
"d[0].baz[0]": true,
|
|
40
|
-
"d[0].baz[1]": false,
|
|
41
|
-
"d[1].e": true,
|
|
42
|
-
"d[1].f": "hi",
|
|
43
|
-
});
|
|
44
|
-
expect(Object.keys(result)).toHaveLength(10);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ponyfill of the HTMLFormElement.requestSubmit() method.
|
|
3
|
-
* Based on polyfill from: https://github.com/javan/form-request-submit-polyfill/blob/main/form-request-submit-polyfill.js
|
|
4
|
-
*/
|
|
5
|
-
export declare const requestSubmit: (element: HTMLFormElement, submitter?: HTMLElement) => void;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ponyfill of the HTMLFormElement.requestSubmit() method.
|
|
3
|
-
* Based on polyfill from: https://github.com/javan/form-request-submit-polyfill/blob/main/form-request-submit-polyfill.js
|
|
4
|
-
*/
|
|
5
|
-
export const requestSubmit = (element, submitter) => {
|
|
6
|
-
// In vitest, let's test the polyfill.
|
|
7
|
-
// Cypress will test the native implementation by nature of using chrome.
|
|
8
|
-
if (typeof Object.getPrototypeOf(element).requestSubmit === "function" &&
|
|
9
|
-
!import.meta.vitest) {
|
|
10
|
-
element.requestSubmit(submitter);
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (submitter) {
|
|
14
|
-
validateSubmitter(element, submitter);
|
|
15
|
-
submitter.click();
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const dummySubmitter = document.createElement("input");
|
|
19
|
-
dummySubmitter.type = "submit";
|
|
20
|
-
dummySubmitter.hidden = true;
|
|
21
|
-
element.appendChild(dummySubmitter);
|
|
22
|
-
dummySubmitter.click();
|
|
23
|
-
element.removeChild(dummySubmitter);
|
|
24
|
-
};
|
|
25
|
-
function validateSubmitter(element, submitter) {
|
|
26
|
-
// Should be redundant, but here for completeness
|
|
27
|
-
const isHtmlElement = submitter instanceof HTMLElement;
|
|
28
|
-
if (!isHtmlElement) {
|
|
29
|
-
raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
|
|
30
|
-
}
|
|
31
|
-
const hasSubmitType = "type" in submitter && submitter.type === "submit";
|
|
32
|
-
if (!hasSubmitType)
|
|
33
|
-
raise(TypeError, "The specified element is not a submit button");
|
|
34
|
-
const isForCorrectForm = "form" in submitter && submitter.form === element;
|
|
35
|
-
if (!isForCorrectForm)
|
|
36
|
-
raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
|
|
37
|
-
}
|
|
38
|
-
function raise(errorConstructor, message, name) {
|
|
39
|
-
throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name);
|
|
40
|
-
}
|
|
41
|
-
if (import.meta.vitest) {
|
|
42
|
-
const { it, expect } = import.meta.vitest;
|
|
43
|
-
it("should validate the submitter", () => {
|
|
44
|
-
const form = document.createElement("form");
|
|
45
|
-
document.body.appendChild(form);
|
|
46
|
-
const submitter = document.createElement("input");
|
|
47
|
-
expect(() => validateSubmitter(null, null)).toThrow();
|
|
48
|
-
expect(() => validateSubmitter(form, null)).toThrow();
|
|
49
|
-
expect(() => validateSubmitter(form, submitter)).toThrow();
|
|
50
|
-
expect(() => validateSubmitter(form, document.createElement("div"))).toThrow();
|
|
51
|
-
submitter.type = "submit";
|
|
52
|
-
expect(() => validateSubmitter(form, submitter)).toThrow();
|
|
53
|
-
form.appendChild(submitter);
|
|
54
|
-
expect(() => validateSubmitter(form, submitter)).not.toThrow();
|
|
55
|
-
form.removeChild(submitter);
|
|
56
|
-
expect(() => validateSubmitter(form, submitter)).toThrow();
|
|
57
|
-
document.body.appendChild(submitter);
|
|
58
|
-
form.id = "test-form";
|
|
59
|
-
submitter.setAttribute("form", "test-form");
|
|
60
|
-
expect(() => validateSubmitter(form, submitter)).not.toThrow();
|
|
61
|
-
const button = document.createElement("button");
|
|
62
|
-
button.type = "submit";
|
|
63
|
-
form.appendChild(button);
|
|
64
|
-
expect(() => validateSubmitter(form, button)).not.toThrow();
|
|
65
|
-
});
|
|
66
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { InternalFormId } from "./state/atomUtils";
|
|
2
|
-
export declare const resetAtom: {
|
|
3
|
-
(param: InternalFormId): import("jotai").Atom<null> & {
|
|
4
|
-
write: (get: {
|
|
5
|
-
<Value>(atom: import("jotai").Atom<Value | Promise<Value>>): Value;
|
|
6
|
-
<Value_1>(atom: import("jotai").Atom<Promise<Value_1>>): Value_1;
|
|
7
|
-
<Value_2>(atom: import("jotai").Atom<Value_2>): Value_2 extends Promise<infer V> ? V : Value_2;
|
|
8
|
-
} & {
|
|
9
|
-
<Value_3>(atom: import("jotai").Atom<Value_3 | Promise<Value_3>>, options: {
|
|
10
|
-
unstable_promise: true;
|
|
11
|
-
}): Value_3 | Promise<Value_3>;
|
|
12
|
-
<Value_4>(atom: import("jotai").Atom<Promise<Value_4>>, options: {
|
|
13
|
-
unstable_promise: true;
|
|
14
|
-
}): Value_4 | Promise<Value_4>;
|
|
15
|
-
<Value_5>(atom: import("jotai").Atom<Value_5>, options: {
|
|
16
|
-
unstable_promise: true;
|
|
17
|
-
}): (Value_5 extends Promise<infer V> ? V : Value_5) | Promise<Value_5 extends Promise<infer V> ? V : Value_5>;
|
|
18
|
-
}, set: {
|
|
19
|
-
<Value_6, Result extends void | Promise<void>>(atom: import("jotai").WritableAtom<Value_6, undefined, Result>): Result;
|
|
20
|
-
<Value_7, Update, Result_1 extends void | Promise<void>>(atom: import("jotai").WritableAtom<Value_7, Update, Result_1>, update: Update): Result_1;
|
|
21
|
-
}, update: unknown) => void;
|
|
22
|
-
onMount?: (<S extends (update?: unknown) => void>(setAtom: S) => void | (() => void)) | undefined;
|
|
23
|
-
} & {
|
|
24
|
-
init: null;
|
|
25
|
-
};
|
|
26
|
-
remove(param: InternalFormId): void;
|
|
27
|
-
setShouldRemove(shouldRemove: ((createdAt: number, param: InternalFormId) => boolean) | null): void;
|
|
28
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { atom } from "jotai";
|
|
2
|
-
import { atomFamily } from "jotai/utils";
|
|
3
|
-
import lodashGet from "lodash/get";
|
|
4
|
-
import { fieldErrorsAtom, formPropsAtom, hasBeenSubmittedAtom, touchedFieldsAtom, } from "./state";
|
|
5
|
-
import { controlledFieldsAtom } from "./state/controlledFields";
|
|
6
|
-
export const resetAtom = atomFamily((formId) => atom(null, (get, set) => {
|
|
7
|
-
set(fieldErrorsAtom(formId), {});
|
|
8
|
-
set(touchedFieldsAtom(formId), {});
|
|
9
|
-
set(hasBeenSubmittedAtom(formId), false);
|
|
10
|
-
const { defaultValues } = get(formPropsAtom(formId));
|
|
11
|
-
const controlledFields = get(controlledFieldsAtom(formId));
|
|
12
|
-
Object.entries(controlledFields).forEach(([name, atom]) => set(atom, lodashGet(defaultValues, name)));
|
|
13
|
-
}));
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare const getArray: (values: any, field: string) => unknown[];
|
|
2
|
-
export declare const swap: (array: unknown[], indexA: number, indexB: number) => void;
|
|
3
|
-
export declare const move: (array: unknown[], from: number, to: number) => void;
|
|
4
|
-
export declare const insert: (array: unknown[], index: number, value: unknown) => void;
|
|
5
|
-
export declare const remove: (array: unknown[], index: number) => void;
|
|
6
|
-
export declare const replace: (array: unknown[], index: number, value: unknown) => void;
|
|
7
|
-
/**
|
|
8
|
-
* The purpose of this helper is to make it easier to update `fieldErrors` and `touchedFields`.
|
|
9
|
-
* We key those objects by full paths to the fields.
|
|
10
|
-
* When we're doing array mutations, that makes it difficult to update those objects.
|
|
11
|
-
*/
|
|
12
|
-
export declare const mutateAsArray: (field: string, obj: Record<string, any>, mutate: (arr: any[]) => void) => void;
|