remix-validated-form 3.3.0 → 3.4.2
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 -2
- package/browser/internal/flatten.d.ts +0 -3
- package/browser/internal/flatten.js +0 -33
- package/browser/internal/getInputProps.d.ts +10 -2
- package/browser/internal/getInputProps.js +23 -3
- package/browser/internal/test.d.ts +0 -0
- package/browser/internal/test.js +0 -0
- package/browser/internal/useMultiValueMap.d.ts +1 -0
- package/browser/internal/useMultiValueMap.js +11 -0
- package/build/internal/MultiValueMap.d.ts +0 -0
- package/build/internal/MultiValueMap.js +0 -0
- package/build/internal/flatten.d.ts +0 -3
- package/build/internal/flatten.js +1 -35
- package/build/internal/getInputProps.d.ts +10 -2
- package/build/internal/getInputProps.js +23 -3
- package/build/internal/test.d.ts +0 -0
- package/build/internal/test.js +0 -0
- package/package.json +1 -1
- package/src/internal/flatten.ts +0 -44
- package/src/internal/getInputProps.ts +34 -6
package/.turbo/turbo-build.log
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
[2K[1G[2m$ npm run build:browser && npm run build:main[22m
|
2
2
|
|
3
|
-
> remix-validated-form@3.
|
3
|
+
> remix-validated-form@3.4.1 build:browser
|
4
4
|
> tsc --module ESNext --outDir ./browser
|
5
5
|
|
6
6
|
|
7
|
-
> remix-validated-form@3.
|
7
|
+
> remix-validated-form@3.4.1 build:main
|
8
8
|
> tsc --module CommonJS --outDir ./build
|
9
9
|
|
package/README.md
CHANGED
@@ -50,6 +50,8 @@ see the [Validation library support](#validation-library-support) section below.
|
|
50
50
|
npm install @remix-validated-form/with-zod
|
51
51
|
```
|
52
52
|
|
53
|
+
If you're using zod, you might also find `zod-form-data` helpful.
|
54
|
+
|
53
55
|
## Create an input component
|
54
56
|
|
55
57
|
In order to display field errors or do field-by-field validation,
|
@@ -63,7 +65,7 @@ type MyInputProps = {
|
|
63
65
|
label: string;
|
64
66
|
};
|
65
67
|
|
66
|
-
export const MyInput = ({ name, label }:
|
68
|
+
export const MyInput = ({ name, label }: MyInputProps) => {
|
67
69
|
const { error, getInputProps } = useField(name);
|
68
70
|
return (
|
69
71
|
<div>
|
@@ -257,4 +259,4 @@ See the [Remix](https://remix.run/docs/en/v1/api/remix#sessionflashkey-value) do
|
|
257
259
|
|
258
260
|
## Why is my cancel button triggering form submission?
|
259
261
|
Problem: the cancel button has an onClick handler to navigate away from the form route but instead it is submitting the form.
|
260
|
-
A button defaults to `type="submit"` in a form which will submit the form by default. If you want to prevent this you can add `type="reset"` or `type="button"` to the cancel button.
|
262
|
+
A button defaults to `type="submit"` in a form which will submit the form by default. If you want to prevent this you can add `type="reset"` or `type="button"` to the cancel button.
|
@@ -1,4 +1 @@
|
|
1
|
-
import { GenericObject } from "..";
|
2
1
|
export declare const objectFromPathEntries: (entries: [string, any][]) => {};
|
3
|
-
/** Flatten an object so there are no nested objects or arrays */
|
4
|
-
export declare function flatten(obj: GenericObject, preserveEmpty?: boolean): GenericObject;
|
@@ -1,40 +1,7 @@
|
|
1
|
-
// `flatten` is taken from https://github.com/richie5um/FlattenJS. Decided to implement them here instead of using that package because this is a core functionality of the library and this will add more flexibility in case we need to change the implementation.
|
2
|
-
import assign from "lodash/assign";
|
3
|
-
import isArray from "lodash/isArray";
|
4
|
-
import isObject from "lodash/isObject";
|
5
|
-
import keys from "lodash/keys";
|
6
|
-
import mapKeys from "lodash/mapKeys";
|
7
1
|
import set from "lodash/set";
|
8
|
-
import transform from "lodash/transform";
|
9
2
|
import { MultiValueMap } from "./MultiValueMap";
|
10
3
|
export const objectFromPathEntries = (entries) => {
|
11
4
|
const map = new MultiValueMap();
|
12
5
|
entries.forEach(([key, value]) => map.add(key, value));
|
13
6
|
return [...map.entries()].reduce((acc, [key, value]) => set(acc, key, value.length === 1 ? value[0] : value), {});
|
14
7
|
};
|
15
|
-
/** Flatten an object so there are no nested objects or arrays */
|
16
|
-
export function flatten(obj, preserveEmpty = false) {
|
17
|
-
return transform(obj, function (result, value, key) {
|
18
|
-
if (isObject(value)) {
|
19
|
-
let flatMap = mapKeys(flatten(value, preserveEmpty), function (_mvalue, mkey) {
|
20
|
-
if (isArray(value)) {
|
21
|
-
let index = mkey.indexOf(".");
|
22
|
-
if (-1 !== index) {
|
23
|
-
return `${key}[${mkey.slice(0, index)}]${mkey.slice(index)}`;
|
24
|
-
}
|
25
|
-
return `${key}[${mkey}]`;
|
26
|
-
}
|
27
|
-
return `${key}.${mkey}`;
|
28
|
-
});
|
29
|
-
assign(result, flatMap);
|
30
|
-
// Preverve Empty arrays and objects
|
31
|
-
if (preserveEmpty && keys(flatMap).length === 0) {
|
32
|
-
result[key] = value;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
else {
|
36
|
-
result[key] = value;
|
37
|
-
}
|
38
|
-
return result;
|
39
|
-
}, {});
|
40
|
-
}
|
@@ -14,8 +14,16 @@ export declare type CreateGetInputPropsOptions = {
|
|
14
14
|
validationBehavior?: Partial<ValidationBehaviorOptions>;
|
15
15
|
name: string;
|
16
16
|
};
|
17
|
-
declare type HandledProps = "name" | "defaultValue";
|
17
|
+
declare type HandledProps = "name" | "defaultValue" | "defaultChecked";
|
18
18
|
declare type Callbacks = "onChange" | "onBlur";
|
19
|
-
|
19
|
+
declare type MinimalInputProps = {
|
20
|
+
onChange?: (...args: any[]) => void;
|
21
|
+
onBlur?: (...args: any[]) => void;
|
22
|
+
defaultValue?: any;
|
23
|
+
defaultChecked?: boolean;
|
24
|
+
name?: string;
|
25
|
+
type?: string;
|
26
|
+
};
|
27
|
+
export declare type GetInputProps = <T extends MinimalInputProps>(props?: Omit<T, HandledProps | Callbacks> & Partial<Pick<T, Callbacks>>) => T;
|
20
28
|
export declare const createGetInputProps: ({ clearError, validate, defaultValue, touched, setTouched, hasBeenSubmitted, validationBehavior, name, }: CreateGetInputPropsOptions) => GetInputProps;
|
21
29
|
export {};
|
@@ -3,18 +3,28 @@ const defaultValidationBehavior = {
|
|
3
3
|
whenTouched: "onChange",
|
4
4
|
whenSubmitted: "onChange",
|
5
5
|
};
|
6
|
+
const getCheckboxDefaultChecked = (value, defaultValue) => {
|
7
|
+
if (Array.isArray(defaultValue))
|
8
|
+
return defaultValue.includes(value);
|
9
|
+
if (typeof defaultValue === "boolean")
|
10
|
+
return defaultValue;
|
11
|
+
if (typeof defaultValue === "string")
|
12
|
+
return defaultValue === value;
|
13
|
+
return undefined;
|
14
|
+
};
|
6
15
|
export const createGetInputProps = ({ clearError, validate, defaultValue, touched, setTouched, hasBeenSubmitted, validationBehavior, name, }) => {
|
7
16
|
const validationBehaviors = {
|
8
17
|
...defaultValidationBehavior,
|
9
18
|
...validationBehavior,
|
10
19
|
};
|
11
20
|
return (props = {}) => {
|
21
|
+
var _a, _b;
|
12
22
|
const behavior = hasBeenSubmitted
|
13
23
|
? validationBehaviors.whenSubmitted
|
14
24
|
: touched
|
15
25
|
? validationBehaviors.whenTouched
|
16
26
|
: validationBehaviors.initial;
|
17
|
-
const
|
27
|
+
const inputProps = {
|
18
28
|
...props,
|
19
29
|
onChange: (...args) => {
|
20
30
|
var _a;
|
@@ -31,9 +41,19 @@ export const createGetInputProps = ({ clearError, validate, defaultValue, touche
|
|
31
41
|
setTouched(true);
|
32
42
|
return (_a = props === null || props === void 0 ? void 0 : props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, ...args);
|
33
43
|
},
|
34
|
-
defaultValue,
|
35
44
|
name,
|
36
45
|
};
|
37
|
-
|
46
|
+
if (inputProps.type === "checkbox") {
|
47
|
+
const value = (_a = props.value) !== null && _a !== void 0 ? _a : "on";
|
48
|
+
inputProps.defaultChecked = getCheckboxDefaultChecked(value, defaultValue);
|
49
|
+
}
|
50
|
+
else if (inputProps.type === "radio") {
|
51
|
+
const value = (_b = props.value) !== null && _b !== void 0 ? _b : "on";
|
52
|
+
inputProps.defaultChecked = defaultValue === value;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
inputProps.defaultValue = defaultValue;
|
56
|
+
}
|
57
|
+
return inputProps;
|
38
58
|
};
|
39
59
|
};
|
File without changes
|
package/browser/internal/test.js
CHANGED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const useMultiValueMap: <Key, Value>() => () => any;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { MultiValueMap } from "multi-value-map";
|
2
|
+
import { useRef } from "react";
|
3
|
+
export const useMultiValueMap = () => {
|
4
|
+
const ref = useRef(null);
|
5
|
+
return () => {
|
6
|
+
if (ref.current)
|
7
|
+
return ref.current;
|
8
|
+
ref.current = new MultiValueMap();
|
9
|
+
return ref.current;
|
10
|
+
};
|
11
|
+
};
|
File without changes
|
File without changes
|
@@ -1,4 +1 @@
|
|
1
|
-
import { GenericObject } from "..";
|
2
1
|
export declare const objectFromPathEntries: (entries: [string, any][]) => {};
|
3
|
-
/** Flatten an object so there are no nested objects or arrays */
|
4
|
-
export declare function flatten(obj: GenericObject, preserveEmpty?: boolean): GenericObject;
|
@@ -3,15 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.
|
7
|
-
// `flatten` is taken from https://github.com/richie5um/FlattenJS. Decided to implement them here instead of using that package because this is a core functionality of the library and this will add more flexibility in case we need to change the implementation.
|
8
|
-
const assign_1 = __importDefault(require("lodash/assign"));
|
9
|
-
const isArray_1 = __importDefault(require("lodash/isArray"));
|
10
|
-
const isObject_1 = __importDefault(require("lodash/isObject"));
|
11
|
-
const keys_1 = __importDefault(require("lodash/keys"));
|
12
|
-
const mapKeys_1 = __importDefault(require("lodash/mapKeys"));
|
6
|
+
exports.objectFromPathEntries = void 0;
|
13
7
|
const set_1 = __importDefault(require("lodash/set"));
|
14
|
-
const transform_1 = __importDefault(require("lodash/transform"));
|
15
8
|
const MultiValueMap_1 = require("./MultiValueMap");
|
16
9
|
const objectFromPathEntries = (entries) => {
|
17
10
|
const map = new MultiValueMap_1.MultiValueMap();
|
@@ -19,30 +12,3 @@ const objectFromPathEntries = (entries) => {
|
|
19
12
|
return [...map.entries()].reduce((acc, [key, value]) => (0, set_1.default)(acc, key, value.length === 1 ? value[0] : value), {});
|
20
13
|
};
|
21
14
|
exports.objectFromPathEntries = objectFromPathEntries;
|
22
|
-
/** Flatten an object so there are no nested objects or arrays */
|
23
|
-
function flatten(obj, preserveEmpty = false) {
|
24
|
-
return (0, transform_1.default)(obj, function (result, value, key) {
|
25
|
-
if ((0, isObject_1.default)(value)) {
|
26
|
-
let flatMap = (0, mapKeys_1.default)(flatten(value, preserveEmpty), function (_mvalue, mkey) {
|
27
|
-
if ((0, isArray_1.default)(value)) {
|
28
|
-
let index = mkey.indexOf(".");
|
29
|
-
if (-1 !== index) {
|
30
|
-
return `${key}[${mkey.slice(0, index)}]${mkey.slice(index)}`;
|
31
|
-
}
|
32
|
-
return `${key}[${mkey}]`;
|
33
|
-
}
|
34
|
-
return `${key}.${mkey}`;
|
35
|
-
});
|
36
|
-
(0, assign_1.default)(result, flatMap);
|
37
|
-
// Preverve Empty arrays and objects
|
38
|
-
if (preserveEmpty && (0, keys_1.default)(flatMap).length === 0) {
|
39
|
-
result[key] = value;
|
40
|
-
}
|
41
|
-
}
|
42
|
-
else {
|
43
|
-
result[key] = value;
|
44
|
-
}
|
45
|
-
return result;
|
46
|
-
}, {});
|
47
|
-
}
|
48
|
-
exports.flatten = flatten;
|
@@ -14,8 +14,16 @@ export declare type CreateGetInputPropsOptions = {
|
|
14
14
|
validationBehavior?: Partial<ValidationBehaviorOptions>;
|
15
15
|
name: string;
|
16
16
|
};
|
17
|
-
declare type HandledProps = "name" | "defaultValue";
|
17
|
+
declare type HandledProps = "name" | "defaultValue" | "defaultChecked";
|
18
18
|
declare type Callbacks = "onChange" | "onBlur";
|
19
|
-
|
19
|
+
declare type MinimalInputProps = {
|
20
|
+
onChange?: (...args: any[]) => void;
|
21
|
+
onBlur?: (...args: any[]) => void;
|
22
|
+
defaultValue?: any;
|
23
|
+
defaultChecked?: boolean;
|
24
|
+
name?: string;
|
25
|
+
type?: string;
|
26
|
+
};
|
27
|
+
export declare type GetInputProps = <T extends MinimalInputProps>(props?: Omit<T, HandledProps | Callbacks> & Partial<Pick<T, Callbacks>>) => T;
|
20
28
|
export declare const createGetInputProps: ({ clearError, validate, defaultValue, touched, setTouched, hasBeenSubmitted, validationBehavior, name, }: CreateGetInputPropsOptions) => GetInputProps;
|
21
29
|
export {};
|
@@ -6,18 +6,28 @@ const defaultValidationBehavior = {
|
|
6
6
|
whenTouched: "onChange",
|
7
7
|
whenSubmitted: "onChange",
|
8
8
|
};
|
9
|
+
const getCheckboxDefaultChecked = (value, defaultValue) => {
|
10
|
+
if (Array.isArray(defaultValue))
|
11
|
+
return defaultValue.includes(value);
|
12
|
+
if (typeof defaultValue === "boolean")
|
13
|
+
return defaultValue;
|
14
|
+
if (typeof defaultValue === "string")
|
15
|
+
return defaultValue === value;
|
16
|
+
return undefined;
|
17
|
+
};
|
9
18
|
const createGetInputProps = ({ clearError, validate, defaultValue, touched, setTouched, hasBeenSubmitted, validationBehavior, name, }) => {
|
10
19
|
const validationBehaviors = {
|
11
20
|
...defaultValidationBehavior,
|
12
21
|
...validationBehavior,
|
13
22
|
};
|
14
23
|
return (props = {}) => {
|
24
|
+
var _a, _b;
|
15
25
|
const behavior = hasBeenSubmitted
|
16
26
|
? validationBehaviors.whenSubmitted
|
17
27
|
: touched
|
18
28
|
? validationBehaviors.whenTouched
|
19
29
|
: validationBehaviors.initial;
|
20
|
-
const
|
30
|
+
const inputProps = {
|
21
31
|
...props,
|
22
32
|
onChange: (...args) => {
|
23
33
|
var _a;
|
@@ -34,10 +44,20 @@ const createGetInputProps = ({ clearError, validate, defaultValue, touched, setT
|
|
34
44
|
setTouched(true);
|
35
45
|
return (_a = props === null || props === void 0 ? void 0 : props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, ...args);
|
36
46
|
},
|
37
|
-
defaultValue,
|
38
47
|
name,
|
39
48
|
};
|
40
|
-
|
49
|
+
if (inputProps.type === "checkbox") {
|
50
|
+
const value = (_a = props.value) !== null && _a !== void 0 ? _a : "on";
|
51
|
+
inputProps.defaultChecked = getCheckboxDefaultChecked(value, defaultValue);
|
52
|
+
}
|
53
|
+
else if (inputProps.type === "radio") {
|
54
|
+
const value = (_b = props.value) !== null && _b !== void 0 ? _b : "on";
|
55
|
+
inputProps.defaultChecked = defaultValue === value;
|
56
|
+
}
|
57
|
+
else {
|
58
|
+
inputProps.defaultValue = defaultValue;
|
59
|
+
}
|
60
|
+
return inputProps;
|
41
61
|
};
|
42
62
|
};
|
43
63
|
exports.createGetInputProps = createGetInputProps;
|
package/build/internal/test.d.ts
CHANGED
File without changes
|
package/build/internal/test.js
CHANGED
File without changes
|
package/package.json
CHANGED
package/src/internal/flatten.ts
CHANGED
@@ -1,12 +1,4 @@
|
|
1
|
-
// `flatten` is taken from https://github.com/richie5um/FlattenJS. Decided to implement them here instead of using that package because this is a core functionality of the library and this will add more flexibility in case we need to change the implementation.
|
2
|
-
import assign from "lodash/assign";
|
3
|
-
import isArray from "lodash/isArray";
|
4
|
-
import isObject from "lodash/isObject";
|
5
|
-
import keys from "lodash/keys";
|
6
|
-
import mapKeys from "lodash/mapKeys";
|
7
1
|
import set from "lodash/set";
|
8
|
-
import transform from "lodash/transform";
|
9
|
-
import { GenericObject } from "..";
|
10
2
|
import { MultiValueMap } from "./MultiValueMap";
|
11
3
|
|
12
4
|
export const objectFromPathEntries = (entries: [string, any][]) => {
|
@@ -17,39 +9,3 @@ export const objectFromPathEntries = (entries: [string, any][]) => {
|
|
17
9
|
{}
|
18
10
|
);
|
19
11
|
};
|
20
|
-
|
21
|
-
/** Flatten an object so there are no nested objects or arrays */
|
22
|
-
export function flatten(obj: GenericObject, preserveEmpty = false) {
|
23
|
-
return transform(
|
24
|
-
obj,
|
25
|
-
function (result: GenericObject, value, key) {
|
26
|
-
if (isObject(value)) {
|
27
|
-
let flatMap = mapKeys(
|
28
|
-
flatten(value, preserveEmpty),
|
29
|
-
function (_mvalue, mkey) {
|
30
|
-
if (isArray(value)) {
|
31
|
-
let index = mkey.indexOf(".");
|
32
|
-
if (-1 !== index) {
|
33
|
-
return `${key}[${mkey.slice(0, index)}]${mkey.slice(index)}`;
|
34
|
-
}
|
35
|
-
return `${key}[${mkey}]`;
|
36
|
-
}
|
37
|
-
return `${key}.${mkey}`;
|
38
|
-
}
|
39
|
-
);
|
40
|
-
|
41
|
-
assign(result, flatMap);
|
42
|
-
|
43
|
-
// Preverve Empty arrays and objects
|
44
|
-
if (preserveEmpty && keys(flatMap).length === 0) {
|
45
|
-
result[key] = value;
|
46
|
-
}
|
47
|
-
} else {
|
48
|
-
result[key] = value;
|
49
|
-
}
|
50
|
-
|
51
|
-
return result;
|
52
|
-
},
|
53
|
-
{}
|
54
|
-
);
|
55
|
-
}
|
@@ -17,10 +17,19 @@ export type CreateGetInputPropsOptions = {
|
|
17
17
|
name: string;
|
18
18
|
};
|
19
19
|
|
20
|
-
type HandledProps = "name" | "defaultValue";
|
20
|
+
type HandledProps = "name" | "defaultValue" | "defaultChecked";
|
21
21
|
type Callbacks = "onChange" | "onBlur";
|
22
22
|
|
23
|
-
|
23
|
+
type MinimalInputProps = {
|
24
|
+
onChange?: (...args: any[]) => void;
|
25
|
+
onBlur?: (...args: any[]) => void;
|
26
|
+
defaultValue?: any;
|
27
|
+
defaultChecked?: boolean;
|
28
|
+
name?: string;
|
29
|
+
type?: string;
|
30
|
+
};
|
31
|
+
|
32
|
+
export type GetInputProps = <T extends MinimalInputProps>(
|
24
33
|
props?: Omit<T, HandledProps | Callbacks> & Partial<Pick<T, Callbacks>>
|
25
34
|
) => T;
|
26
35
|
|
@@ -30,6 +39,13 @@ const defaultValidationBehavior: ValidationBehaviorOptions = {
|
|
30
39
|
whenSubmitted: "onChange",
|
31
40
|
};
|
32
41
|
|
42
|
+
const getCheckboxDefaultChecked = (value: string, defaultValue: any) => {
|
43
|
+
if (Array.isArray(defaultValue)) return defaultValue.includes(value);
|
44
|
+
if (typeof defaultValue === "boolean") return defaultValue;
|
45
|
+
if (typeof defaultValue === "string") return defaultValue === value;
|
46
|
+
return undefined;
|
47
|
+
};
|
48
|
+
|
33
49
|
export const createGetInputProps = ({
|
34
50
|
clearError,
|
35
51
|
validate,
|
@@ -45,14 +61,14 @@ export const createGetInputProps = ({
|
|
45
61
|
...validationBehavior,
|
46
62
|
};
|
47
63
|
|
48
|
-
return <T extends
|
64
|
+
return <T extends MinimalInputProps>(props = {} as any) => {
|
49
65
|
const behavior = hasBeenSubmitted
|
50
66
|
? validationBehaviors.whenSubmitted
|
51
67
|
: touched
|
52
68
|
? validationBehaviors.whenTouched
|
53
69
|
: validationBehaviors.initial;
|
54
70
|
|
55
|
-
const
|
71
|
+
const inputProps: T = {
|
56
72
|
...props,
|
57
73
|
onChange: (...args: unknown[]) => {
|
58
74
|
if (behavior === "onChange") validate();
|
@@ -64,10 +80,22 @@ export const createGetInputProps = ({
|
|
64
80
|
setTouched(true);
|
65
81
|
return props?.onBlur?.(...args);
|
66
82
|
},
|
67
|
-
defaultValue,
|
68
83
|
name,
|
69
84
|
};
|
70
85
|
|
71
|
-
|
86
|
+
if (inputProps.type === "checkbox") {
|
87
|
+
const value = props.value ?? "on";
|
88
|
+
inputProps.defaultChecked = getCheckboxDefaultChecked(
|
89
|
+
value,
|
90
|
+
defaultValue
|
91
|
+
);
|
92
|
+
} else if (inputProps.type === "radio") {
|
93
|
+
const value = props.value ?? "on";
|
94
|
+
inputProps.defaultChecked = defaultValue === value;
|
95
|
+
} else {
|
96
|
+
inputProps.defaultValue = defaultValue;
|
97
|
+
}
|
98
|
+
|
99
|
+
return inputProps;
|
72
100
|
};
|
73
101
|
};
|