remix-validated-form 4.6.0 → 4.6.1-beta.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/dist/remix-validated-form.cjs.js +4 -4
- package/dist/remix-validated-form.cjs.js.map +1 -1
- package/dist/remix-validated-form.es.js +224 -1860
- package/dist/remix-validated-form.es.js.map +1 -1
- package/dist/remix-validated-form.umd.js +4 -4
- package/dist/remix-validated-form.umd.js.map +1 -1
- package/dist/types/internal/flatten.d.ts +1 -1
- package/package.json +5 -4
- package/src/ValidatedForm.tsx +2 -2
- package/src/internal/flatten.ts +4 -3
- package/src/internal/getInputProps.ts +2 -2
- package/src/internal/hooks.ts +3 -3
- package/src/internal/state/arrayUtil.ts +5 -6
- package/src/internal/state/createFormStore.ts +7 -10
- package/src/internal/util.ts +2 -2
- package/src/validation/createValidator.ts +2 -2
- package/src/validation/validation.test.ts +2 -2
- package/stats.html +4044 -0
@@ -1 +1 @@
|
|
1
|
-
export declare const objectFromPathEntries: (entries: [string, any][]) =>
|
1
|
+
export declare const objectFromPathEntries: (entries: [string, any][]) => Record<string, any>;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "remix-validated-form",
|
3
|
-
"version": "4.6.0",
|
3
|
+
"version": "4.6.1-beta.0",
|
4
4
|
"description": "Form component and utils for easy form validation in remix",
|
5
5
|
"browser": "./dist/remix-validated-form.cjs.js",
|
6
6
|
"main": "./dist/remix-validated-form.umd.js",
|
@@ -39,17 +39,18 @@
|
|
39
39
|
"devDependencies": {
|
40
40
|
"@remix-run/react": "^1.6.5",
|
41
41
|
"@testing-library/react": "^13.3.0",
|
42
|
-
"@types/lodash": "^4.14.178",
|
43
42
|
"@types/react": "^18.0.9",
|
44
43
|
"fetch-blob": "^3.1.3",
|
45
44
|
"react": "^18.1.0",
|
45
|
+
"ts-toolbelt": "^9.6.0",
|
46
46
|
"tsconfig": "*",
|
47
|
-
"typescript": "^4.
|
47
|
+
"typescript": "^4.8.4",
|
48
48
|
"vite-config": "*"
|
49
49
|
},
|
50
50
|
"dependencies": {
|
51
51
|
"immer": "^9.0.12",
|
52
|
-
"
|
52
|
+
"remeda": "^1.2.0",
|
53
|
+
"setGet": "*",
|
53
54
|
"tiny-invariant": "^1.2.0",
|
54
55
|
"zustand": "^4.0.0-rc.1"
|
55
56
|
}
|
package/src/ValidatedForm.tsx
CHANGED
@@ -4,7 +4,6 @@ import {
|
|
4
4
|
useFetcher,
|
5
5
|
useSubmit,
|
6
6
|
} from "@remix-run/react";
|
7
|
-
import uniq from "lodash/uniq";
|
8
7
|
import React, {
|
9
8
|
ComponentProps,
|
10
9
|
FormEvent,
|
@@ -15,6 +14,7 @@ import React, {
|
|
15
14
|
useRef,
|
16
15
|
useState,
|
17
16
|
} from "react";
|
17
|
+
import * as R from "remeda";
|
18
18
|
import { useIsSubmitting, useIsValid } from "./hooks";
|
19
19
|
import { FORM_ID_FIELD } from "./internal/constants";
|
20
20
|
import {
|
@@ -108,7 +108,7 @@ const focusFirstInvalidInput = (
|
|
108
108
|
})
|
109
109
|
.filter(nonNull)
|
110
110
|
.filter((name) => name in fieldErrors);
|
111
|
-
const uniqueNamesInOrder = uniq(namesInOrder);
|
111
|
+
const uniqueNamesInOrder = R.uniq(namesInOrder);
|
112
112
|
|
113
113
|
for (const fieldName of uniqueNamesInOrder) {
|
114
114
|
if (customFocusHandlers.has(fieldName)) {
|
package/src/internal/flatten.ts
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
import
|
1
|
+
import * as R from "remeda";
|
2
2
|
import { MultiValueMap } from "./MultiValueMap";
|
3
3
|
|
4
4
|
export const objectFromPathEntries = (entries: [string, any][]) => {
|
5
5
|
const map = new MultiValueMap<string, any>();
|
6
6
|
entries.forEach(([key, value]) => map.add(key, value));
|
7
7
|
return [...map.entries()].reduce(
|
8
|
-
(acc, [key, value]) =>
|
9
|
-
|
8
|
+
(acc, [key, value]) =>
|
9
|
+
R.set(acc, key, value.length === 1 ? value[0] : value),
|
10
|
+
{} as Record<string, any>
|
10
11
|
);
|
11
12
|
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import * as R from "remeda";
|
2
2
|
import { getCheckboxChecked } from "./logic/getCheckboxChecked";
|
3
3
|
import { getRadioChecked } from "./logic/getRadioChecked";
|
4
4
|
|
@@ -89,6 +89,6 @@ export const createGetInputProps = ({
|
|
89
89
|
inputProps.defaultValue = defaultValue;
|
90
90
|
}
|
91
91
|
|
92
|
-
return omitBy(inputProps, (value) => value === undefined) as T;
|
92
|
+
return R.omitBy(inputProps, (value) => value === undefined) as T;
|
93
93
|
};
|
94
94
|
};
|
package/src/internal/hooks.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { useActionData, useMatches, useTransition } from "@remix-run/react";
|
2
|
-
import lodashGet from "lodash/get";
|
3
2
|
import { useCallback, useContext } from "react";
|
3
|
+
import { getPath } from "setGet";
|
4
4
|
import invariant from "tiny-invariant";
|
5
5
|
import { FieldErrors, ValidationErrorResponseData } from "..";
|
6
6
|
import { formDefaultValuesKey } from "./constants";
|
@@ -145,7 +145,7 @@ export const useCurrentDefaultValueForField = (
|
|
145
145
|
formId: InternalFormId,
|
146
146
|
field: string
|
147
147
|
) =>
|
148
|
-
useFormStore(formId, (state) =>
|
148
|
+
useFormStore(formId, (state) => getPath(state.currentDefaultValues, field));
|
149
149
|
|
150
150
|
export const useFieldDefaultValue = (
|
151
151
|
name: string,
|
@@ -154,7 +154,7 @@ export const useFieldDefaultValue = (
|
|
154
154
|
const defaultValues = useDefaultValuesForForm(context);
|
155
155
|
const state = useCurrentDefaultValueForField(context.formId, name);
|
156
156
|
|
157
|
-
return defaultValues.map((val) =>
|
157
|
+
return defaultValues.map((val) => getPath(val, name)).hydrateTo(state);
|
158
158
|
};
|
159
159
|
|
160
160
|
export const useInternalIsSubmitting = (formId: InternalFormId) =>
|
@@ -1,5 +1,4 @@
|
|
1
|
-
import
|
2
|
-
import lodashSet from "lodash/set";
|
1
|
+
import { getPath, setPath } from "setGet";
|
3
2
|
import invariant from "tiny-invariant";
|
4
3
|
|
5
4
|
////
|
@@ -8,10 +7,10 @@ import invariant from "tiny-invariant";
|
|
8
7
|
////
|
9
8
|
|
10
9
|
export const getArray = (values: any, field: string): unknown[] => {
|
11
|
-
const value =
|
10
|
+
const value = getPath(values, field);
|
12
11
|
if (value === undefined || value === null) {
|
13
12
|
const newValue: unknown[] = [];
|
14
|
-
|
13
|
+
setPath(values, field, newValue);
|
15
14
|
return newValue;
|
16
15
|
}
|
17
16
|
invariant(
|
@@ -94,8 +93,8 @@ export const mutateAsArray = (
|
|
94
93
|
for (const [key, value] of Object.entries(obj)) {
|
95
94
|
if (key.startsWith(field) && key !== field) {
|
96
95
|
beforeKeys.add(key);
|
96
|
+
setPath(arr, key.substring(field.length), value);
|
97
97
|
}
|
98
|
-
lodashSet(arr, key.substring(field.length), value);
|
99
98
|
}
|
100
99
|
|
101
100
|
mutate(arr);
|
@@ -105,7 +104,7 @@ export const mutateAsArray = (
|
|
105
104
|
|
106
105
|
const newKeys = getDeepArrayPaths(arr);
|
107
106
|
for (const key of newKeys) {
|
108
|
-
const val =
|
107
|
+
const val = getPath(arr, key);
|
109
108
|
obj[`${field}${key}`] = val;
|
110
109
|
}
|
111
110
|
};
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { WritableDraft } from "immer/dist/internal";
|
2
|
-
import
|
3
|
-
import lodashSet from "lodash/set";
|
2
|
+
import { getPath, setPath } from "setGet";
|
4
3
|
import invariant from "tiny-invariant";
|
5
4
|
import create, { GetState } from "zustand";
|
6
5
|
import { immer } from "zustand/middleware/immer";
|
@@ -12,7 +11,6 @@ import {
|
|
12
11
|
} from "../../validation/types";
|
13
12
|
import { requestSubmit } from "../logic/requestSubmit";
|
14
13
|
import * as arrayUtil from "./arrayUtil";
|
15
|
-
import { useControlledFieldStore } from "./controlledFieldStore";
|
16
14
|
import { InternalFormId } from "./types";
|
17
15
|
|
18
16
|
export type SyncedFormProps = {
|
@@ -302,26 +300,25 @@ const createFormState = (
|
|
302
300
|
|
303
301
|
// When nested within a field array, we should leave resetting up to the field array
|
304
302
|
if (!isNested) {
|
305
|
-
|
303
|
+
setPath(
|
306
304
|
state.controlledFields.values,
|
307
305
|
fieldName,
|
308
|
-
|
306
|
+
getPath(state.formProps?.defaultValues, fieldName)
|
309
307
|
);
|
310
|
-
|
308
|
+
setPath(
|
311
309
|
state.currentDefaultValues,
|
312
310
|
fieldName,
|
313
|
-
|
311
|
+
getPath(state.formProps?.defaultValues, fieldName)
|
314
312
|
);
|
315
313
|
}
|
316
314
|
|
317
315
|
delete state.controlledFields.refCounts[fieldName];
|
318
316
|
});
|
319
317
|
},
|
320
|
-
getValue: (fieldName) =>
|
321
|
-
lodashGet(get().controlledFields.values, fieldName),
|
318
|
+
getValue: (fieldName) => getPath(get().controlledFields.values, fieldName),
|
322
319
|
setValue: (fieldName, value) => {
|
323
320
|
set((state) => {
|
324
|
-
|
321
|
+
setPath(state.controlledFields.values, fieldName, value);
|
325
322
|
});
|
326
323
|
get().controlledFields.kickoffValueUpdate(fieldName);
|
327
324
|
},
|
package/src/internal/util.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import isEqual from "lodash/isEqual";
|
2
1
|
import type React from "react";
|
3
2
|
import { useEffect, useLayoutEffect, useRef } from "react";
|
3
|
+
import * as R from "remeda";
|
4
4
|
|
5
5
|
export const omit = (obj: any, ...keys: string[]) => {
|
6
6
|
const result = { ...obj };
|
@@ -29,7 +29,7 @@ export const useIsomorphicLayoutEffect =
|
|
29
29
|
|
30
30
|
export const useDeepEqualsMemo = <T>(item: T): T => {
|
31
31
|
const ref = useRef<T>(item);
|
32
|
-
const areEqual = ref.current === item ||
|
32
|
+
const areEqual = ref.current === item || R.equals(ref.current, item);
|
33
33
|
useEffect(() => {
|
34
34
|
if (!areEqual) {
|
35
35
|
ref.current = item;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import * as R from "remeda";
|
2
2
|
import { CreateValidatorArg, GenericObject, Validator } from "..";
|
3
3
|
import { FORM_ID_FIELD } from "../internal/constants";
|
4
4
|
import { objectFromPathEntries } from "../internal/flatten";
|
@@ -12,7 +12,7 @@ const preprocessFormData = (data: GenericObject | FormData): GenericObject => {
|
|
12
12
|
};
|
13
13
|
|
14
14
|
const omitInternalFields = (data: GenericObject): GenericObject =>
|
15
|
-
omit(data, FORM_ID_FIELD);
|
15
|
+
R.omit(data, [FORM_ID_FIELD]);
|
16
16
|
|
17
17
|
/**
|
18
18
|
* Used to create a validator for a form.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { anyString, TestFormData } from "@remix-validated-form/test-utils";
|
2
2
|
import { withYup } from "@remix-validated-form/with-yup/src";
|
3
3
|
import { withZod } from "@remix-validated-form/with-zod";
|
4
|
-
import
|
4
|
+
import * as R from "remeda";
|
5
5
|
import { Validator } from "remix-validated-form/src";
|
6
6
|
import { objectFromPathEntries } from "remix-validated-form/src/internal/flatten";
|
7
7
|
import { describe, it, expect } from "vitest";
|
@@ -120,7 +120,7 @@ describe("Validation", () => {
|
|
120
120
|
[FORM_ID_FIELD]: "something",
|
121
121
|
};
|
122
122
|
expect(await validator.validate(person)).toEqual({
|
123
|
-
data: omit(person, FORM_ID_FIELD),
|
123
|
+
data: R.omit(person as any, [FORM_ID_FIELD]),
|
124
124
|
error: undefined,
|
125
125
|
submittedData: person,
|
126
126
|
formId: "something",
|