remix-validated-form 5.1.5 → 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.
Files changed (75) hide show
  1. package/.turbo/turbo-build.log +18 -18
  2. package/dist/index.cjs.js +3 -0
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +3 -0
  5. package/dist/index.esm.js.map +1 -1
  6. package/package.json +1 -1
  7. package/.turbo/turbo-dev.log +0 -0
  8. package/.turbo/turbo-typecheck.log +0 -1
  9. package/browser/ValidatedForm.d.ts +0 -50
  10. package/browser/ValidatedForm.js +0 -210
  11. package/browser/hooks.d.ts +0 -67
  12. package/browser/hooks.js +0 -84
  13. package/browser/index.d.ts +0 -7
  14. package/browser/index.js +0 -7
  15. package/browser/internal/MultiValueMap.d.ts +0 -11
  16. package/browser/internal/MultiValueMap.js +0 -43
  17. package/browser/internal/constants.d.ts +0 -3
  18. package/browser/internal/constants.js +0 -3
  19. package/browser/internal/flatten.d.ts +0 -1
  20. package/browser/internal/flatten.js +0 -7
  21. package/browser/internal/formContext.d.ts +0 -12
  22. package/browser/internal/formContext.js +0 -2
  23. package/browser/internal/getInputProps.d.ts +0 -29
  24. package/browser/internal/getInputProps.js +0 -51
  25. package/browser/internal/hooks.d.ts +0 -35
  26. package/browser/internal/hooks.js +0 -118
  27. package/browser/internal/hydratable.d.ts +0 -14
  28. package/browser/internal/hydratable.js +0 -14
  29. package/browser/internal/logic/getCheckboxChecked.d.ts +0 -1
  30. package/browser/internal/logic/getCheckboxChecked.js +0 -9
  31. package/browser/internal/logic/getRadioChecked.d.ts +0 -1
  32. package/browser/internal/logic/getRadioChecked.js +0 -15
  33. package/browser/internal/logic/nestedObjectToPathObject.d.ts +0 -1
  34. package/browser/internal/logic/nestedObjectToPathObject.js +0 -47
  35. package/browser/internal/logic/requestSubmit.d.ts +0 -5
  36. package/browser/internal/logic/requestSubmit.js +0 -66
  37. package/browser/internal/reset.d.ts +0 -28
  38. package/browser/internal/reset.js +0 -13
  39. package/browser/internal/state/arrayUtil.d.ts +0 -12
  40. package/browser/internal/state/arrayUtil.js +0 -350
  41. package/browser/internal/state/atomUtils.d.ts +0 -38
  42. package/browser/internal/state/atomUtils.js +0 -5
  43. package/browser/internal/state/cleanup.d.ts +0 -2
  44. package/browser/internal/state/cleanup.js +0 -6
  45. package/browser/internal/state/controlledFieldStore.d.ts +0 -26
  46. package/browser/internal/state/controlledFieldStore.js +0 -70
  47. package/browser/internal/state/controlledFields.d.ts +0 -7
  48. package/browser/internal/state/controlledFields.js +0 -36
  49. package/browser/internal/state/createFormStore.d.ts +0 -79
  50. package/browser/internal/state/createFormStore.js +0 -306
  51. package/browser/internal/state/fieldArray.d.ts +0 -28
  52. package/browser/internal/state/fieldArray.js +0 -74
  53. package/browser/internal/state/storeFamily.d.ts +0 -9
  54. package/browser/internal/state/storeFamily.js +0 -18
  55. package/browser/internal/state/storeHooks.d.ts +0 -3
  56. package/browser/internal/state/storeHooks.js +0 -4
  57. package/browser/internal/state/types.d.ts +0 -1
  58. package/browser/internal/state/types.js +0 -1
  59. package/browser/internal/state.d.ts +0 -343
  60. package/browser/internal/state.js +0 -64
  61. package/browser/internal/submissionCallbacks.d.ts +0 -1
  62. package/browser/internal/submissionCallbacks.js +0 -13
  63. package/browser/internal/util.d.ts +0 -5
  64. package/browser/internal/util.js +0 -32
  65. package/browser/server.d.ts +0 -21
  66. package/browser/server.js +0 -27
  67. package/browser/unreleased/formStateHooks.d.ts +0 -64
  68. package/browser/unreleased/formStateHooks.js +0 -76
  69. package/browser/userFacingFormContext.d.ts +0 -85
  70. package/browser/userFacingFormContext.js +0 -41
  71. package/browser/validation/createValidator.d.ts +0 -7
  72. package/browser/validation/createValidator.js +0 -43
  73. package/browser/validation/types.d.ts +0 -58
  74. package/browser/validation/types.js +0 -1
  75. package/stats.html +0 -4044
@@ -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;