remix-validated-form 4.6.2 → 4.6.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.2",
3
+ "version": "4.6.4",
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
+ "set-get": "*",
46
+ "ts-toolbelt": "^9.6.0",
46
47
  "tsconfig": "*",
47
- "typescript": "^4.5.3",
48
+ "typescript": "^4.8.4",
48
49
  "vite-config": "*"
49
50
  },
50
51
  "dependencies": {
51
52
  "immer": "^9.0.12",
52
- "lodash": "^4.17.21",
53
+ "remeda": "^1.2.0",
53
54
  "tiny-invariant": "^1.2.0",
54
55
  "zustand": "^4.0.0-rc.1"
55
56
  }
@@ -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)) {
@@ -1,11 +1,12 @@
1
- import set from "lodash/set";
1
+ import { setPath } from "set-get";
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]) => set(acc, key, value.length === 1 ? value[0] : value),
9
- {}
8
+ (acc, [key, value]) =>
9
+ setPath(acc, key, value.length === 1 ? value[0] : value),
10
+ {} as Record<string, any>
10
11
  );
11
12
  };
@@ -1,4 +1,4 @@
1
- import omitBy from "lodash/omitBy";
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
  };
@@ -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 "set-get";
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) => lodashGet(state.currentDefaultValues, field));
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) => lodashGet(val, name)).hydrateTo(state);
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 lodashGet from "lodash/get";
2
- import lodashSet from "lodash/set";
1
+ import { getPath, setPath } from "set-get";
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 = lodashGet(values, field);
10
+ const value = getPath(values, field);
12
11
  if (value === undefined || value === null) {
13
12
  const newValue: unknown[] = [];
14
- lodashSet(values, field, newValue);
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,8 +104,10 @@ export const mutateAsArray = (
105
104
 
106
105
  const newKeys = getDeepArrayPaths(arr);
107
106
  for (const key of newKeys) {
108
- const val = lodashGet(arr, key);
109
- obj[`${field}${key}`] = val;
107
+ const val = getPath(arr, key);
108
+ if (val !== undefined) {
109
+ obj[`${field}${key}`] = val;
110
+ }
110
111
  }
111
112
  };
112
113
 
@@ -355,6 +356,19 @@ if (import.meta.vitest) {
355
356
  });
356
357
  });
357
358
 
359
+ it("should not create keys for `undefined`", () => {
360
+ const values = {
361
+ "myField[0]": "foo",
362
+ };
363
+ mutateAsArray("myField", values, (arr) => {
364
+ arr.unshift(undefined);
365
+ });
366
+ expect(Object.keys(values)).toHaveLength(1);
367
+ expect(values).toEqual({
368
+ "myField[1]": "foo",
369
+ });
370
+ });
371
+
358
372
  it("should handle remove", () => {
359
373
  const values = {
360
374
  myField: "something",
@@ -1,6 +1,5 @@
1
1
  import { WritableDraft } from "immer/dist/internal";
2
- import lodashGet from "lodash/get";
3
- import lodashSet from "lodash/set";
2
+ import { getPath, setPath } from "set-get";
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
- lodashSet(
303
+ setPath(
306
304
  state.controlledFields.values,
307
305
  fieldName,
308
- lodashGet(state.formProps?.defaultValues, fieldName)
306
+ getPath(state.formProps?.defaultValues, fieldName)
309
307
  );
310
- lodashSet(
308
+ setPath(
311
309
  state.currentDefaultValues,
312
310
  fieldName,
313
- lodashGet(state.formProps?.defaultValues, fieldName)
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
- lodashSet(state.controlledFields.values, fieldName, value);
321
+ setPath(state.controlledFields.values, fieldName, value);
325
322
  });
326
323
  get().controlledFields.kickoffValueUpdate(fieldName);
327
324
  },
@@ -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 || isEqual(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 omit from "lodash/omit";
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 omit from "lodash/omit";
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",