@coxy/react-validator 2.0.4 → 2.0.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/.eslintrc.js +1 -3
- package/.prettierrc.js +10 -0
- package/dist/context.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/rules.d.ts +2 -8
- package/dist/rules.js +44 -27
- package/dist/types.d.ts +24 -0
- package/dist/types.js +2 -0
- package/dist/use-validator.d.ts +2 -1
- package/dist/validator-field.d.ts +3 -11
- package/dist/validator-field.js +11 -6
- package/dist/validator-wrapper.d.ts +9 -2
- package/dist/validator-wrapper.js +16 -1
- package/dist/validator.d.ts +1 -8
- package/package.json +4 -1
- package/src/context.ts +6 -3
- package/src/index.ts +1 -0
- package/src/rules.ts +63 -52
- package/src/types.ts +27 -0
- package/src/use-validator.test.tsx +3 -3
- package/src/use-validator.ts +3 -3
- package/src/validator-field.test.tsx +35 -43
- package/src/validator-field.tsx +21 -24
- package/src/validator-wrapper.test.tsx +35 -35
- package/src/validator-wrapper.tsx +27 -9
- package/src/validator.test.tsx +1 -1
- package/src/validator.ts +11 -27
package/.eslintrc.js
CHANGED
package/.prettierrc.js
ADDED
package/dist/context.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { Validity } from './types';
|
|
2
3
|
export declare const Context: import("react").Context<{
|
|
3
4
|
registerField: (field: string | number) => void;
|
|
4
5
|
unregisterField: (field: string | number) => void;
|
|
6
|
+
customErrors: Array<Validity>;
|
|
5
7
|
}>;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
17
|
exports.useValidator = exports.Validator = exports.ValidatorWrapper = exports.ValidatorField = exports.rules = void 0;
|
|
4
18
|
var rules_1 = require("./rules");
|
|
@@ -11,3 +25,4 @@ var validator_1 = require("./validator");
|
|
|
11
25
|
Object.defineProperty(exports, "Validator", { enumerable: true, get: function () { return validator_1.Validator; } });
|
|
12
26
|
var use_validator_1 = require("./use-validator");
|
|
13
27
|
Object.defineProperty(exports, "useValidator", { enumerable: true, get: function () { return use_validator_1.useValidator; } });
|
|
28
|
+
__exportStar(require("./types"), exports);
|
package/dist/rules.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare type
|
|
3
|
-
export interface RuleInstance {
|
|
4
|
-
rule: (value: Value) => boolean;
|
|
5
|
-
message: string | Fn;
|
|
6
|
-
}
|
|
7
|
-
export declare type ValidatorRules = RuleInstance[];
|
|
1
|
+
import { ValidatorRule } from './types';
|
|
2
|
+
export declare type ValidatorRules = ValidatorRule[];
|
|
8
3
|
export declare const rules: {
|
|
9
4
|
notEmpty: {
|
|
10
5
|
rule: (value: any) => boolean;
|
|
@@ -35,4 +30,3 @@ export declare const rules: {
|
|
|
35
30
|
message: string;
|
|
36
31
|
}[];
|
|
37
32
|
};
|
|
38
|
-
export {};
|
package/dist/rules.js
CHANGED
|
@@ -3,41 +3,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.rules = void 0;
|
|
4
4
|
const emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
5
5
|
exports.rules = {
|
|
6
|
-
notEmpty: [
|
|
6
|
+
notEmpty: [
|
|
7
|
+
{
|
|
7
8
|
rule: (value) => value !== '' && value.length > 0,
|
|
8
|
-
message: 'Value is required'
|
|
9
|
-
}
|
|
10
|
-
|
|
9
|
+
message: 'Value is required',
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
bool: [
|
|
13
|
+
{
|
|
11
14
|
rule: (value) => !!value,
|
|
12
|
-
message: 'Value is required'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
+
message: 'Value is required',
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
password: [
|
|
19
|
+
{
|
|
15
20
|
rule: (value) => value.length > 0,
|
|
16
|
-
message: 'Password field cannot be empty'
|
|
17
|
-
},
|
|
21
|
+
message: 'Password field cannot be empty',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
18
24
|
rule: (value) => value.length > 5,
|
|
19
|
-
message: 'Password field can not be less than 6 characters'
|
|
20
|
-
}
|
|
21
|
-
|
|
25
|
+
message: 'Password field can not be less than 6 characters',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
email: [
|
|
29
|
+
{
|
|
22
30
|
rule: (value) => !!value && value !== '' && value.length !== 0,
|
|
23
|
-
message: 'Email is required'
|
|
24
|
-
},
|
|
31
|
+
message: 'Email is required',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
25
34
|
rule: (value) => emailReg.test(String(value).toLowerCase()),
|
|
26
|
-
message: 'Email is invalid'
|
|
27
|
-
}
|
|
28
|
-
|
|
35
|
+
message: 'Email is invalid',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
min: (min) => [
|
|
39
|
+
{
|
|
29
40
|
rule: (value) => parseFloat(value) > min,
|
|
30
|
-
message: `The value must be greater than ${min}
|
|
31
|
-
}
|
|
32
|
-
|
|
41
|
+
message: `The value must be greater than ${min}`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
max: (max) => [
|
|
45
|
+
{
|
|
33
46
|
rule: (value) => parseFloat(value) < max,
|
|
34
|
-
message: `The value must be smaller ${max}
|
|
35
|
-
}
|
|
36
|
-
|
|
47
|
+
message: `The value must be smaller ${max}`,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
length: (min, max) => [
|
|
51
|
+
{
|
|
37
52
|
rule: (value) => String(value).length >= min,
|
|
38
|
-
message: `No less than ${min} symbols
|
|
39
|
-
},
|
|
53
|
+
message: `No less than ${min} symbols`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
40
56
|
rule: (value) => (max !== undefined ? String(value).length <= max : true),
|
|
41
|
-
message: `No more than ${max} symbols
|
|
42
|
-
}
|
|
57
|
+
message: `No more than ${max} symbols`,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
43
60
|
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ValidatorRules } from './rules';
|
|
2
|
+
import { Value } from './validator-field';
|
|
3
|
+
declare type Fn = (value: Value) => string;
|
|
4
|
+
export interface ValidatorRule {
|
|
5
|
+
rule: (value: Value) => boolean;
|
|
6
|
+
message: string | Fn;
|
|
7
|
+
}
|
|
8
|
+
export interface ErrorMessage {
|
|
9
|
+
message: string;
|
|
10
|
+
isValid: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface Validity {
|
|
13
|
+
message: string;
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
errors?: ErrorMessage[];
|
|
16
|
+
id?: string | number;
|
|
17
|
+
}
|
|
18
|
+
export interface FieldParams {
|
|
19
|
+
value: Value;
|
|
20
|
+
rules: ValidatorRules;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
id?: string | number;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
package/dist/types.js
ADDED
package/dist/use-validator.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ValidatorRules } from './rules';
|
|
2
|
-
import {
|
|
2
|
+
import { Value } from './validator-field';
|
|
3
|
+
import { Validity } from './types';
|
|
3
4
|
export declare function useValidator(value: Value, rules: ValidatorRules): [boolean, Pick<Validity, 'message' | 'errors'>];
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
import { Validity } from 'types';
|
|
2
3
|
import { ValidatorRules } from './rules';
|
|
3
4
|
export declare type Value = any;
|
|
4
|
-
export interface ErrorMessage {
|
|
5
|
-
message: string;
|
|
6
|
-
isValid: boolean;
|
|
7
|
-
}
|
|
8
|
-
export interface Validity {
|
|
9
|
-
message: string;
|
|
10
|
-
isValid: boolean;
|
|
11
|
-
errors?: ErrorMessage[];
|
|
12
|
-
id?: string | number;
|
|
13
|
-
}
|
|
14
5
|
declare type Fn = (validity: Validity, value: Value) => ReactNode;
|
|
15
6
|
interface Props {
|
|
16
7
|
rules?: ValidatorRules;
|
|
@@ -20,6 +11,7 @@ interface Props {
|
|
|
20
11
|
children?: ReactNode | Fn;
|
|
21
12
|
unregisterField: (val: any) => void;
|
|
22
13
|
registerField: (val: any) => void;
|
|
14
|
+
customErrors: Array<Validity>;
|
|
23
15
|
}
|
|
24
|
-
export declare function ValidatorField(props: Omit<Props, 'registerField' | 'unregisterField'>): JSX.Element;
|
|
16
|
+
export declare function ValidatorField(props: Omit<Props, 'registerField' | 'unregisterField' | 'customErrors'>): JSX.Element;
|
|
25
17
|
export {};
|
package/dist/validator-field.js
CHANGED
|
@@ -13,21 +13,26 @@ class ValidationFieldWrapper extends react_1.Component {
|
|
|
13
13
|
this.props.registerField(this);
|
|
14
14
|
}
|
|
15
15
|
validate() {
|
|
16
|
+
const props = this.props;
|
|
17
|
+
const customError = (props.customErrors || []).find((item) => item.id === props.id);
|
|
18
|
+
if (customError) {
|
|
19
|
+
return customError;
|
|
20
|
+
}
|
|
16
21
|
const field = new validator_1.Field({
|
|
17
|
-
rules:
|
|
18
|
-
required:
|
|
19
|
-
value:
|
|
20
|
-
id:
|
|
22
|
+
rules: props.rules,
|
|
23
|
+
required: props.required,
|
|
24
|
+
value: props.value,
|
|
25
|
+
id: props.id,
|
|
21
26
|
});
|
|
22
27
|
return field.validate();
|
|
23
28
|
}
|
|
24
29
|
render() {
|
|
25
30
|
const { children, value } = this.props;
|
|
26
31
|
const validity = this.validate();
|
|
27
|
-
return
|
|
32
|
+
return typeof children === 'function' ? children(validity, value) : children;
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
function ValidatorField(props) {
|
|
31
|
-
return ((0, jsx_runtime_1.jsx)(context_1.Context.Consumer, { children: (data) => ((0, jsx_runtime_1.jsx)(ValidationFieldWrapper, Object.assign({}, props, { registerField: data.registerField, unregisterField: data.unregisterField }))) }));
|
|
36
|
+
return ((0, jsx_runtime_1.jsx)(context_1.Context.Consumer, { children: (data) => ((0, jsx_runtime_1.jsx)(ValidationFieldWrapper, Object.assign({}, props, { customErrors: data.customErrors, registerField: data.registerField, unregisterField: data.unregisterField }))) }));
|
|
32
37
|
}
|
|
33
38
|
exports.ValidatorField = ValidatorField;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Component, ReactNode, RefObject } from 'react';
|
|
2
|
+
import { Validity } from './types';
|
|
3
|
+
import { Field } from './validator';
|
|
2
4
|
interface ComponentProps {
|
|
3
5
|
children?: ReactNode;
|
|
4
6
|
stopAtFirstError?: boolean;
|
|
@@ -6,12 +8,17 @@ interface ComponentProps {
|
|
|
6
8
|
}
|
|
7
9
|
export declare class ValidatorWrapper extends Component<ComponentProps> {
|
|
8
10
|
fields: any[];
|
|
11
|
+
state: {
|
|
12
|
+
customErrors: any[];
|
|
13
|
+
};
|
|
9
14
|
constructor(props: any, ctx: any);
|
|
10
15
|
componentWillUnmount(): void;
|
|
11
16
|
registerField(field: any): void;
|
|
12
17
|
unregisterField(field: any): void;
|
|
13
|
-
getField(id: any):
|
|
14
|
-
|
|
18
|
+
getField(id: any): Field | null;
|
|
19
|
+
setCustomError(customError: Validity): void;
|
|
20
|
+
clearCustomErrors(): void;
|
|
21
|
+
validate(): Validity;
|
|
15
22
|
render(): JSX.Element;
|
|
16
23
|
}
|
|
17
24
|
export {};
|
|
@@ -9,6 +9,9 @@ class ValidatorWrapper extends react_1.Component {
|
|
|
9
9
|
constructor(props, ctx) {
|
|
10
10
|
super(props, ctx);
|
|
11
11
|
this.fields = [];
|
|
12
|
+
this.state = {
|
|
13
|
+
customErrors: [],
|
|
14
|
+
};
|
|
12
15
|
this.registerField = this.registerField.bind(this);
|
|
13
16
|
this.unregisterField = this.unregisterField.bind(this);
|
|
14
17
|
}
|
|
@@ -28,6 +31,14 @@ class ValidatorWrapper extends react_1.Component {
|
|
|
28
31
|
getField(id) {
|
|
29
32
|
return this.fields.find((field) => field.props.id === id) || null;
|
|
30
33
|
}
|
|
34
|
+
setCustomError(customError) {
|
|
35
|
+
this.setState({
|
|
36
|
+
customErrors: [...this.state.customErrors, customError],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
clearCustomErrors() {
|
|
40
|
+
this.setState({ customErrors: [] });
|
|
41
|
+
}
|
|
31
42
|
validate() {
|
|
32
43
|
const validator = new validator_1.Validator({ stopAtFirstError: this.props.stopAtFirstError });
|
|
33
44
|
this.fields.forEach((comp) => {
|
|
@@ -36,7 +47,11 @@ class ValidatorWrapper extends react_1.Component {
|
|
|
36
47
|
return validator.validate();
|
|
37
48
|
}
|
|
38
49
|
render() {
|
|
39
|
-
return ((0, jsx_runtime_1.jsx)(context_1.Context.Provider, Object.assign({ value: {
|
|
50
|
+
return ((0, jsx_runtime_1.jsx)(context_1.Context.Provider, Object.assign({ value: {
|
|
51
|
+
customErrors: this.state.customErrors,
|
|
52
|
+
registerField: this.registerField,
|
|
53
|
+
unregisterField: this.unregisterField,
|
|
54
|
+
} }, { children: this.props.children })));
|
|
40
55
|
}
|
|
41
56
|
}
|
|
42
57
|
exports.ValidatorWrapper = ValidatorWrapper;
|
package/dist/validator.d.ts
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ValidatorRules } from './rules';
|
|
3
|
-
export interface FieldParams {
|
|
4
|
-
value: Value;
|
|
5
|
-
rules: ValidatorRules;
|
|
6
|
-
required?: boolean;
|
|
7
|
-
id?: string | number;
|
|
8
|
-
}
|
|
1
|
+
import { FieldParams, Validity } from './types';
|
|
9
2
|
export declare class Field {
|
|
10
3
|
private rules;
|
|
11
4
|
private required;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coxy/react-validator",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "🚀 Simple validation form for React or NodeJS apps. useValidator are included ;)",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -45,14 +45,17 @@
|
|
|
45
45
|
"coveralls": "3.1.1",
|
|
46
46
|
"eslint": "8.25.0",
|
|
47
47
|
"eslint-config-standard": "17.0.0",
|
|
48
|
+
"eslint-config-prettier": "8.8.0",
|
|
48
49
|
"eslint-plugin-import": "2.26.0",
|
|
49
50
|
"eslint-plugin-jsx-a11y": "6.6.1",
|
|
50
51
|
"eslint-plugin-n": "15.3.0",
|
|
51
52
|
"eslint-plugin-promise": "6.0.1",
|
|
52
53
|
"eslint-plugin-filename-rules": "1.2.0",
|
|
53
54
|
"eslint-plugin-react": "7.31.8",
|
|
55
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
54
56
|
"jest": "29.1.2",
|
|
55
57
|
"jest-environment-jsdom": "29.1.2",
|
|
58
|
+
"prettier": "2.8.7",
|
|
56
59
|
"react-dom": "18.2.0",
|
|
57
60
|
"react-test-renderer": "18.2.0",
|
|
58
61
|
"ts-jest": "29.0.3",
|
package/src/context.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createContext } from 'react'
|
|
2
2
|
|
|
3
|
+
import { Validity } from './types'
|
|
4
|
+
|
|
3
5
|
export const Context = createContext<{
|
|
4
|
-
registerField:(field: string | number) => void
|
|
5
|
-
unregisterField:(field: string | number) => void
|
|
6
|
-
|
|
6
|
+
registerField: (field: string | number) => void
|
|
7
|
+
unregisterField: (field: string | number) => void
|
|
8
|
+
customErrors: Array<Validity>
|
|
9
|
+
}>(null)
|
package/src/index.ts
CHANGED
package/src/rules.ts
CHANGED
|
@@ -1,59 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValidatorRule } from './types'
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line
|
|
4
|
-
const emailReg =
|
|
4
|
+
const emailReg =
|
|
5
|
+
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
|
5
6
|
|
|
6
|
-
type
|
|
7
|
+
export type ValidatorRules = ValidatorRule[]
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const rules = {
|
|
10
|
+
notEmpty: [
|
|
11
|
+
{
|
|
12
|
+
rule: (value) => value !== '' && value.length > 0,
|
|
13
|
+
message: 'Value is required',
|
|
14
|
+
},
|
|
15
|
+
],
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
bool: [
|
|
18
|
+
{
|
|
19
|
+
rule: (value) => !!value,
|
|
20
|
+
message: 'Value is required',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
24
|
+
password: [
|
|
25
|
+
{
|
|
26
|
+
rule: (value) => value.length > 0,
|
|
27
|
+
message: 'Password field cannot be empty',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
rule: (value) => value.length > 5,
|
|
31
|
+
message: 'Password field can not be less than 6 characters',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
|
|
35
|
+
email: [
|
|
36
|
+
{
|
|
37
|
+
rule: (value) => !!value && value !== '' && value.length !== 0,
|
|
38
|
+
message: 'Email is required',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
rule: (value) => emailReg.test(String(value).toLowerCase()),
|
|
42
|
+
message: 'Email is invalid',
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
|
|
46
|
+
min: (min) => [
|
|
47
|
+
{
|
|
48
|
+
rule: (value) => parseFloat(value) > min,
|
|
49
|
+
message: `The value must be greater than ${min}`,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
max: (max) => [
|
|
54
|
+
{
|
|
55
|
+
rule: (value) => parseFloat(value) < max,
|
|
56
|
+
message: `The value must be smaller ${max}`,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
|
|
60
|
+
length: (min, max?) => [
|
|
61
|
+
{
|
|
62
|
+
rule: (value) => String(value).length >= min,
|
|
63
|
+
message: `No less than ${min} symbols`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
rule: (value) => (max !== undefined ? String(value).length <= max : true),
|
|
67
|
+
message: `No more than ${max} symbols`,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
59
70
|
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ValidatorRules } from './rules'
|
|
2
|
+
import { Value } from './validator-field'
|
|
3
|
+
type Fn = (value: Value) => string
|
|
4
|
+
|
|
5
|
+
export interface ValidatorRule {
|
|
6
|
+
rule: (value: Value) => boolean
|
|
7
|
+
message: string | Fn
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ErrorMessage {
|
|
11
|
+
message: string
|
|
12
|
+
isValid: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface Validity {
|
|
16
|
+
message: string
|
|
17
|
+
isValid: boolean
|
|
18
|
+
errors?: ErrorMessage[]
|
|
19
|
+
id?: string | number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface FieldParams {
|
|
23
|
+
value: Value
|
|
24
|
+
rules: ValidatorRules
|
|
25
|
+
required?: boolean
|
|
26
|
+
id?: string | number
|
|
27
|
+
}
|
|
@@ -25,7 +25,7 @@ afterEach(() => {
|
|
|
25
25
|
jest.useFakeTimers()
|
|
26
26
|
|
|
27
27
|
it('check state change and hide field', () => {
|
|
28
|
-
function Comp
|
|
28
|
+
function Comp() {
|
|
29
29
|
const [value, setValue] = useState(false)
|
|
30
30
|
const [isValid, validateObject] = useValidator(value, rules.bool)
|
|
31
31
|
|
|
@@ -39,8 +39,8 @@ it('check state change and hide field', () => {
|
|
|
39
39
|
|
|
40
40
|
return (
|
|
41
41
|
<>
|
|
42
|
-
<span data-testid=
|
|
43
|
-
<span data-testid=
|
|
42
|
+
<span data-testid='test1'>{isValid ? 'true' : 'false'}</span>
|
|
43
|
+
<span data-testid='test2'>{validateObject.message || 'true'}</span>
|
|
44
44
|
</>
|
|
45
45
|
)
|
|
46
46
|
}
|
package/src/use-validator.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Validator } from './validator'
|
|
2
2
|
import { ValidatorRules } from './rules'
|
|
3
|
-
import {
|
|
3
|
+
import { Value } from './validator-field'
|
|
4
|
+
import { Validity } from './types'
|
|
4
5
|
|
|
5
|
-
export function useValidator
|
|
6
|
+
export function useValidator(value: Value, rules: ValidatorRules): [boolean, Pick<Validity, 'message' | 'errors'>] {
|
|
6
7
|
const validator = new Validator()
|
|
7
8
|
validator.addField({ value, rules })
|
|
8
9
|
const { isValid, ...validateObject } = validator.validate()
|
|
9
10
|
return [isValid, validateObject]
|
|
10
11
|
}
|
|
11
|
-
|
|
@@ -14,20 +14,20 @@ it('render without wrapper', () => {
|
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
it('normal render', () => {
|
|
17
|
-
render(
|
|
17
|
+
render(
|
|
18
18
|
<ValidatorWrapper>
|
|
19
|
-
<ValidatorField rules={[]} value=
|
|
20
|
-
</ValidatorWrapper
|
|
21
|
-
)
|
|
19
|
+
<ValidatorField rules={[]} value='' />
|
|
20
|
+
</ValidatorWrapper>,
|
|
21
|
+
)
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
it('check context validator', () => {
|
|
25
25
|
const validator = createRef<ValidatorWrapper>()
|
|
26
|
-
render(
|
|
26
|
+
render(
|
|
27
27
|
<ValidatorWrapper ref={validator}>
|
|
28
28
|
<ValidatorField rules={[]} />
|
|
29
|
-
</ValidatorWrapper
|
|
30
|
-
)
|
|
29
|
+
</ValidatorWrapper>,
|
|
30
|
+
)
|
|
31
31
|
|
|
32
32
|
const validateResult = validator.current.validate()
|
|
33
33
|
|
|
@@ -39,16 +39,16 @@ it('check failed validation', () => {
|
|
|
39
39
|
const validator1 = createRef<ValidatorWrapper>()
|
|
40
40
|
const validator2 = createRef<ValidatorWrapper>()
|
|
41
41
|
|
|
42
|
-
render(
|
|
42
|
+
render(
|
|
43
43
|
<>
|
|
44
44
|
<ValidatorWrapper ref={validator1}>
|
|
45
|
-
<ValidatorField rules={rules.email} value=
|
|
45
|
+
<ValidatorField rules={rules.email} value='test' />
|
|
46
46
|
</ValidatorWrapper>
|
|
47
47
|
<ValidatorWrapper ref={validator2}>
|
|
48
|
-
<ValidatorField rules={rules.email} value=
|
|
48
|
+
<ValidatorField rules={rules.email} value='' />
|
|
49
49
|
</ValidatorWrapper>
|
|
50
|
-
|
|
51
|
-
)
|
|
50
|
+
</>,
|
|
51
|
+
)
|
|
52
52
|
|
|
53
53
|
act(() => {
|
|
54
54
|
const validateResult1 = validator1.current.validate()
|
|
@@ -70,7 +70,7 @@ jest.useFakeTimers()
|
|
|
70
70
|
it('check state change and hide field', () => {
|
|
71
71
|
const validator1 = createRef<ValidatorWrapper>()
|
|
72
72
|
|
|
73
|
-
function Comp
|
|
73
|
+
function Comp() {
|
|
74
74
|
const [st, setSt] = useState(true)
|
|
75
75
|
|
|
76
76
|
useEffect(() => {
|
|
@@ -83,10 +83,8 @@ it('check state change and hide field', () => {
|
|
|
83
83
|
|
|
84
84
|
return (
|
|
85
85
|
<ValidatorWrapper ref={validator1}>
|
|
86
|
-
<ValidatorField rules={rules.email} value=
|
|
87
|
-
{st &&
|
|
88
|
-
<ValidatorField rules={rules.email} value="" />
|
|
89
|
-
)}
|
|
86
|
+
<ValidatorField rules={rules.email} value='test' />
|
|
87
|
+
{st && <ValidatorField rules={rules.email} value='' />}
|
|
90
88
|
</ValidatorWrapper>
|
|
91
89
|
)
|
|
92
90
|
}
|
|
@@ -104,11 +102,11 @@ it('check state change and hide field', () => {
|
|
|
104
102
|
|
|
105
103
|
it('check success validation', () => {
|
|
106
104
|
const validator = createRef<ValidatorWrapper>()
|
|
107
|
-
render(
|
|
105
|
+
render(
|
|
108
106
|
<ValidatorWrapper ref={validator}>
|
|
109
|
-
<ValidatorField rules={rules.email} value=
|
|
110
|
-
</ValidatorWrapper
|
|
111
|
-
)
|
|
107
|
+
<ValidatorField rules={rules.email} value='email@email.com' />
|
|
108
|
+
</ValidatorWrapper>,
|
|
109
|
+
)
|
|
112
110
|
|
|
113
111
|
const validateResult = validator.current.validate()
|
|
114
112
|
|
|
@@ -118,17 +116,13 @@ it('check success validation', () => {
|
|
|
118
116
|
|
|
119
117
|
it('check success validation fot child function', () => {
|
|
120
118
|
const validator = createRef<ValidatorWrapper>()
|
|
121
|
-
render(
|
|
119
|
+
render(
|
|
122
120
|
<ValidatorWrapper ref={validator}>
|
|
123
|
-
<ValidatorField rules={rules.email} value=
|
|
124
|
-
{({ isValid, message }) =>
|
|
125
|
-
<>
|
|
126
|
-
{!isValid && <div>{message}</div>}
|
|
127
|
-
</>
|
|
128
|
-
)}
|
|
121
|
+
<ValidatorField rules={rules.email} value='email@email.com'>
|
|
122
|
+
{({ isValid, message }) => <>{!isValid && <div>{message}</div>}</>}
|
|
129
123
|
</ValidatorField>
|
|
130
|
-
</ValidatorWrapper
|
|
131
|
-
)
|
|
124
|
+
</ValidatorWrapper>,
|
|
125
|
+
)
|
|
132
126
|
|
|
133
127
|
const validateResult = validator.current.validate()
|
|
134
128
|
|
|
@@ -138,21 +132,19 @@ it('check success validation fot child function', () => {
|
|
|
138
132
|
|
|
139
133
|
it('check custom rule message function', () => {
|
|
140
134
|
const validator = createRef<ValidatorWrapper>()
|
|
141
|
-
const rule = [
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
const rule = [
|
|
136
|
+
{
|
|
137
|
+
rule: (value) => value !== 'test',
|
|
138
|
+
message: (value) => `test message ${value}`,
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
render(
|
|
146
142
|
<ValidatorWrapper ref={validator}>
|
|
147
|
-
<ValidatorField rules={rule} value=
|
|
148
|
-
{({ isValid, message }) =>
|
|
149
|
-
<>
|
|
150
|
-
{!isValid && <div>{message}</div>}
|
|
151
|
-
</>
|
|
152
|
-
)}
|
|
143
|
+
<ValidatorField rules={rule} value='test'>
|
|
144
|
+
{({ isValid, message }) => <>{!isValid && <div>{message}</div>}</>}
|
|
153
145
|
</ValidatorField>
|
|
154
|
-
</ValidatorWrapper
|
|
155
|
-
)
|
|
146
|
+
</ValidatorWrapper>,
|
|
147
|
+
)
|
|
156
148
|
|
|
157
149
|
const validateResult = validator.current.validate()
|
|
158
150
|
|
package/src/validator-field.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, ReactNode } from 'react'
|
|
2
|
+
import { Validity } from 'types'
|
|
2
3
|
|
|
3
4
|
import { Context } from './context'
|
|
4
5
|
import { Field } from './validator'
|
|
@@ -6,62 +7,58 @@ import { ValidatorRules } from './rules'
|
|
|
6
7
|
|
|
7
8
|
export type Value = any
|
|
8
9
|
|
|
9
|
-
export interface ErrorMessage {
|
|
10
|
-
message: string
|
|
11
|
-
isValid: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface Validity {
|
|
15
|
-
message: string
|
|
16
|
-
isValid: boolean
|
|
17
|
-
errors?: ErrorMessage[]
|
|
18
|
-
id?: string | number
|
|
19
|
-
}
|
|
20
|
-
|
|
21
10
|
type Fn = (validity: Validity, value: Value) => ReactNode
|
|
22
11
|
|
|
23
12
|
interface Props {
|
|
24
|
-
rules?: ValidatorRules
|
|
25
|
-
required?: boolean
|
|
13
|
+
rules?: ValidatorRules
|
|
14
|
+
required?: boolean
|
|
26
15
|
value?: Value
|
|
27
16
|
id?: string | number
|
|
28
17
|
children?: ReactNode | Fn
|
|
29
18
|
unregisterField: (val: any) => void
|
|
30
19
|
registerField: (val: any) => void
|
|
20
|
+
customErrors: Array<Validity>
|
|
31
21
|
}
|
|
32
22
|
|
|
33
23
|
class ValidationFieldWrapper extends Component<Props> {
|
|
34
|
-
componentWillUnmount
|
|
24
|
+
componentWillUnmount() {
|
|
35
25
|
this.props.unregisterField(this)
|
|
36
26
|
}
|
|
37
27
|
|
|
38
|
-
componentDidMount
|
|
28
|
+
componentDidMount() {
|
|
39
29
|
this.props.registerField(this)
|
|
40
30
|
}
|
|
41
31
|
|
|
42
|
-
validate
|
|
32
|
+
validate(): Validity {
|
|
33
|
+
const props = this.props
|
|
34
|
+
const customError = (props.customErrors || []).find((item) => item.id === props.id)
|
|
35
|
+
if (customError) {
|
|
36
|
+
return customError
|
|
37
|
+
}
|
|
38
|
+
|
|
43
39
|
const field = new Field({
|
|
44
|
-
rules:
|
|
45
|
-
required:
|
|
46
|
-
value:
|
|
47
|
-
id:
|
|
40
|
+
rules: props.rules,
|
|
41
|
+
required: props.required,
|
|
42
|
+
value: props.value,
|
|
43
|
+
id: props.id,
|
|
48
44
|
})
|
|
49
45
|
return field.validate()
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
render
|
|
48
|
+
render() {
|
|
53
49
|
const { children, value } = this.props
|
|
54
50
|
const validity = this.validate()
|
|
55
|
-
return
|
|
51
|
+
return typeof children === 'function' ? children(validity, value) : children
|
|
56
52
|
}
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
export function ValidatorField
|
|
55
|
+
export function ValidatorField(props: Omit<Props, 'registerField' | 'unregisterField' | 'customErrors'>) {
|
|
60
56
|
return (
|
|
61
57
|
<Context.Consumer>
|
|
62
58
|
{(data) => (
|
|
63
59
|
<ValidationFieldWrapper
|
|
64
60
|
{...props}
|
|
61
|
+
customErrors={data.customErrors}
|
|
65
62
|
registerField={data.registerField}
|
|
66
63
|
unregisterField={data.unregisterField}
|
|
67
64
|
/>
|
|
@@ -15,7 +15,7 @@ it('render without child', () => {
|
|
|
15
15
|
|
|
16
16
|
it('check wrapper validator', () => {
|
|
17
17
|
const validator = createRef<ValidatorWrapper>()
|
|
18
|
-
render(
|
|
18
|
+
render(
|
|
19
19
|
<ValidatorWrapper ref={validator}>
|
|
20
20
|
<ValidatorField rules={[]} />
|
|
21
21
|
<ValidatorField rules={[]} />
|
|
@@ -23,8 +23,8 @@ it('check wrapper validator', () => {
|
|
|
23
23
|
<ValidatorField rules={[]} />
|
|
24
24
|
<ValidatorField rules={[]} />
|
|
25
25
|
<ValidatorField rules={[]} />
|
|
26
|
-
</ValidatorWrapper
|
|
27
|
-
)
|
|
26
|
+
</ValidatorWrapper>,
|
|
27
|
+
)
|
|
28
28
|
|
|
29
29
|
expect(typeof validator.current).toBe('object')
|
|
30
30
|
expect(typeof validator.current.validate).toBe('function')
|
|
@@ -32,12 +32,12 @@ it('check wrapper validator', () => {
|
|
|
32
32
|
|
|
33
33
|
it('check getField validator', () => {
|
|
34
34
|
const validator = createRef<ValidatorWrapper>()
|
|
35
|
-
render(
|
|
35
|
+
render(
|
|
36
36
|
<ValidatorWrapper ref={validator}>
|
|
37
|
-
<ValidatorField rules={[]} id=
|
|
38
|
-
<ValidatorField rules={[]} id=
|
|
39
|
-
</ValidatorWrapper
|
|
40
|
-
)
|
|
37
|
+
<ValidatorField rules={[]} id='test' />
|
|
38
|
+
<ValidatorField rules={[]} id='test-fields' />
|
|
39
|
+
</ValidatorWrapper>,
|
|
40
|
+
)
|
|
41
41
|
expect(typeof validator.current.getField).toBe('function')
|
|
42
42
|
const field = validator.current.getField('test')
|
|
43
43
|
|
|
@@ -50,11 +50,11 @@ it('check getField validator', () => {
|
|
|
50
50
|
|
|
51
51
|
it('check getField undefined field', () => {
|
|
52
52
|
const validator = createRef<ValidatorWrapper>()
|
|
53
|
-
render(
|
|
53
|
+
render(
|
|
54
54
|
<ValidatorWrapper ref={validator}>
|
|
55
|
-
<ValidatorField rules={[]} id=
|
|
56
|
-
</ValidatorWrapper
|
|
57
|
-
)
|
|
55
|
+
<ValidatorField rules={[]} id='test-empty-field' />
|
|
56
|
+
</ValidatorWrapper>,
|
|
57
|
+
)
|
|
58
58
|
|
|
59
59
|
const field = validator.current.getField('8')
|
|
60
60
|
expect(field).toBe(null)
|
|
@@ -62,13 +62,13 @@ it('check getField undefined field', () => {
|
|
|
62
62
|
|
|
63
63
|
it('check stopAtFirstError validator', () => {
|
|
64
64
|
const validator = createRef<ValidatorWrapper>()
|
|
65
|
-
render(
|
|
65
|
+
render(
|
|
66
66
|
<ValidatorWrapper ref={validator} stopAtFirstError>
|
|
67
|
-
<ValidatorField rules={[]} value=
|
|
68
|
-
<ValidatorField rules={rules.email} value=
|
|
69
|
-
<ValidatorField rules={rules.password} value=
|
|
70
|
-
</ValidatorWrapper
|
|
71
|
-
)
|
|
67
|
+
<ValidatorField rules={[]} value='test' />
|
|
68
|
+
<ValidatorField rules={rules.email} value='test' />
|
|
69
|
+
<ValidatorField rules={rules.password} value='' />
|
|
70
|
+
</ValidatorWrapper>,
|
|
71
|
+
)
|
|
72
72
|
const fieldValidate = validator.current.validate()
|
|
73
73
|
expect(fieldValidate.isValid).toBe(false)
|
|
74
74
|
expect(fieldValidate.message).toBe('Email is invalid')
|
|
@@ -77,11 +77,11 @@ it('check stopAtFirstError validator', () => {
|
|
|
77
77
|
|
|
78
78
|
it('check unregisterField, registerField', () => {
|
|
79
79
|
const validator = createRef<ValidatorWrapper>()
|
|
80
|
-
render(
|
|
80
|
+
render(
|
|
81
81
|
<ValidatorWrapper ref={validator}>
|
|
82
|
-
<ValidatorField rules={[]} id=
|
|
83
|
-
</ValidatorWrapper
|
|
84
|
-
)
|
|
82
|
+
<ValidatorField rules={[]} id='test-register-field' />
|
|
83
|
+
</ValidatorWrapper>,
|
|
84
|
+
)
|
|
85
85
|
|
|
86
86
|
expect(typeof validator.current.registerField).toBe('function')
|
|
87
87
|
expect(typeof validator.current.unregisterField).toBe('function')
|
|
@@ -92,10 +92,10 @@ it('check filed in field', () => {
|
|
|
92
92
|
render(
|
|
93
93
|
<ValidatorWrapper ref={validator}>
|
|
94
94
|
<ValidatorField rules={[]}>
|
|
95
|
-
<ValidatorField rules={[]} id=
|
|
96
|
-
<ValidatorField rules={[]} id=
|
|
95
|
+
<ValidatorField rules={[]} id='check-validate-field-1' />
|
|
96
|
+
<ValidatorField rules={[]} id='check-validate-field-2' />
|
|
97
97
|
</ValidatorField>
|
|
98
|
-
</ValidatorWrapper
|
|
98
|
+
</ValidatorWrapper>,
|
|
99
99
|
)
|
|
100
100
|
|
|
101
101
|
expect(typeof validator.current).toBe('object')
|
|
@@ -107,14 +107,14 @@ it('check filed in field', () => {
|
|
|
107
107
|
it('check wrapper in wrapper', () => {
|
|
108
108
|
const validatorOut = createRef<ValidatorWrapper>()
|
|
109
109
|
const validatorIn = createRef<ValidatorWrapper>()
|
|
110
|
-
render(
|
|
110
|
+
render(
|
|
111
111
|
<ValidatorWrapper ref={validatorOut}>
|
|
112
|
-
<ValidatorField rules={rules.email} value=
|
|
112
|
+
<ValidatorField rules={rules.email} value='' />
|
|
113
113
|
<ValidatorWrapper ref={validatorIn}>
|
|
114
|
-
<ValidatorField rules={rules.password} value=
|
|
114
|
+
<ValidatorField rules={rules.password} value='successpasswword' />
|
|
115
115
|
</ValidatorWrapper>
|
|
116
|
-
</ValidatorWrapper
|
|
117
|
-
)
|
|
116
|
+
</ValidatorWrapper>,
|
|
117
|
+
)
|
|
118
118
|
expect(validatorIn.current.validate().isValid).toBe(true)
|
|
119
119
|
expect(validatorOut.current.validate().isValid).toBe(false)
|
|
120
120
|
})
|
|
@@ -122,16 +122,16 @@ it('check wrapper in wrapper', () => {
|
|
|
122
122
|
it('check two validators', () => {
|
|
123
123
|
const validatorSuccess = createRef<ValidatorWrapper>()
|
|
124
124
|
const validatorFailed = createRef<ValidatorWrapper>()
|
|
125
|
-
render(
|
|
125
|
+
render(
|
|
126
126
|
<>
|
|
127
127
|
<ValidatorWrapper ref={validatorSuccess}>
|
|
128
|
-
<ValidatorField rules={rules.password} value=
|
|
128
|
+
<ValidatorField rules={rules.password} value='successpasswword' />
|
|
129
129
|
</ValidatorWrapper>
|
|
130
130
|
<ValidatorWrapper ref={validatorFailed}>
|
|
131
|
-
<ValidatorField rules={rules.email} value=
|
|
131
|
+
<ValidatorField rules={rules.email} value='' />
|
|
132
132
|
</ValidatorWrapper>
|
|
133
|
-
|
|
134
|
-
)
|
|
133
|
+
</>,
|
|
134
|
+
)
|
|
135
135
|
|
|
136
136
|
expect(validatorFailed.current.validate().isValid).toBe(false)
|
|
137
137
|
expect(validatorSuccess.current.validate().isValid).toBe(true)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Component, ReactNode, RefObject } from 'react'
|
|
2
2
|
|
|
3
|
+
import { Validity } from './types'
|
|
3
4
|
import { Context } from './context'
|
|
4
|
-
import { Validator } from './validator'
|
|
5
|
+
import { Field, Validator } from './validator'
|
|
5
6
|
|
|
6
7
|
interface ComponentProps {
|
|
7
8
|
children?: ReactNode
|
|
@@ -11,33 +12,46 @@ interface ComponentProps {
|
|
|
11
12
|
|
|
12
13
|
export class ValidatorWrapper extends Component<ComponentProps> {
|
|
13
14
|
fields = []
|
|
15
|
+
state = {
|
|
16
|
+
customErrors: [],
|
|
17
|
+
}
|
|
14
18
|
|
|
15
|
-
constructor
|
|
19
|
+
constructor(props, ctx) {
|
|
16
20
|
super(props, ctx)
|
|
17
21
|
this.registerField = this.registerField.bind(this)
|
|
18
22
|
this.unregisterField = this.unregisterField.bind(this)
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
componentWillUnmount
|
|
25
|
+
componentWillUnmount() {
|
|
22
26
|
this.fields = []
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
registerField
|
|
29
|
+
registerField(field) {
|
|
26
30
|
if (field && !this.fields.includes(field)) {
|
|
27
31
|
this.fields.push(field)
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
unregisterField
|
|
35
|
+
unregisterField(field) {
|
|
32
36
|
const index = this.fields.indexOf(field)
|
|
33
37
|
if (index > -1) this.fields.splice(index, 1)
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
getField
|
|
40
|
+
getField(id): Field | null {
|
|
37
41
|
return this.fields.find((field) => field.props.id === id) || null
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
setCustomError(customError: Validity) {
|
|
45
|
+
this.setState({
|
|
46
|
+
customErrors: [...this.state.customErrors, customError],
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
clearCustomErrors() {
|
|
51
|
+
this.setState({ customErrors: [] })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
validate(): Validity {
|
|
41
55
|
const validator = new Validator({ stopAtFirstError: this.props.stopAtFirstError })
|
|
42
56
|
this.fields.forEach((comp) => {
|
|
43
57
|
validator.addField(comp.props)
|
|
@@ -45,10 +59,14 @@ export class ValidatorWrapper extends Component<ComponentProps> {
|
|
|
45
59
|
return validator.validate()
|
|
46
60
|
}
|
|
47
61
|
|
|
48
|
-
render
|
|
62
|
+
render() {
|
|
49
63
|
return (
|
|
50
64
|
<Context.Provider
|
|
51
|
-
value={{
|
|
65
|
+
value={{
|
|
66
|
+
customErrors: this.state.customErrors,
|
|
67
|
+
registerField: this.registerField,
|
|
68
|
+
unregisterField: this.unregisterField,
|
|
69
|
+
}}
|
|
52
70
|
>
|
|
53
71
|
{this.props.children}
|
|
54
72
|
</Context.Provider>
|
package/src/validator.test.tsx
CHANGED
package/src/validator.ts
CHANGED
|
@@ -1,40 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Value } from './validator-field'
|
|
2
2
|
import { ValidatorRules } from './rules'
|
|
3
|
-
|
|
4
|
-
export interface FieldParams {
|
|
5
|
-
value: Value
|
|
6
|
-
rules: ValidatorRules,
|
|
7
|
-
required?: boolean
|
|
8
|
-
id?: string|number
|
|
9
|
-
}
|
|
3
|
+
import { FieldParams, Validity } from './types'
|
|
10
4
|
|
|
11
5
|
export class Field {
|
|
12
6
|
private rules: ValidatorRules
|
|
13
7
|
private required: boolean
|
|
14
8
|
private value: Value
|
|
15
|
-
public id: string|number
|
|
9
|
+
public id: string | number
|
|
16
10
|
|
|
17
|
-
constructor
|
|
18
|
-
rules,
|
|
19
|
-
required,
|
|
20
|
-
value,
|
|
21
|
-
id
|
|
22
|
-
}: FieldParams) {
|
|
11
|
+
constructor({ rules, required, value, id }: FieldParams) {
|
|
23
12
|
this.rules = rules
|
|
24
13
|
this.required = required
|
|
25
14
|
this.value = value
|
|
26
15
|
this.id = id
|
|
27
16
|
}
|
|
28
17
|
|
|
29
|
-
validate
|
|
18
|
+
validate(): Validity {
|
|
30
19
|
let isValid = true
|
|
31
20
|
let message = ''
|
|
32
|
-
const {
|
|
33
|
-
rules,
|
|
34
|
-
value,
|
|
35
|
-
required,
|
|
36
|
-
id
|
|
37
|
-
} = this
|
|
21
|
+
const { rules, value, required, id } = this
|
|
38
22
|
|
|
39
23
|
const isEmptyValue = !value && parseFloat(value) !== 0
|
|
40
24
|
|
|
@@ -65,27 +49,27 @@ export class Validator {
|
|
|
65
49
|
private fields: Field[]
|
|
66
50
|
private params: ValidatorParams
|
|
67
51
|
|
|
68
|
-
constructor
|
|
52
|
+
constructor(params?: ValidatorParams) {
|
|
69
53
|
this.params = params || null
|
|
70
54
|
this.fields = []
|
|
71
55
|
}
|
|
72
56
|
|
|
73
|
-
addField
|
|
57
|
+
addField(params: FieldParams): Field {
|
|
74
58
|
const field = new Field(params)
|
|
75
59
|
this.fields.push(field)
|
|
76
60
|
return field
|
|
77
61
|
}
|
|
78
62
|
|
|
79
|
-
removeField
|
|
63
|
+
removeField(field: Field): void {
|
|
80
64
|
const index = this.fields.indexOf(field)
|
|
81
65
|
if (index > -1) this.fields.splice(index, 1)
|
|
82
66
|
}
|
|
83
67
|
|
|
84
|
-
getField
|
|
68
|
+
getField(id: Field['id']): Field {
|
|
85
69
|
return this.fields.find((field) => field.id === id) || null
|
|
86
70
|
}
|
|
87
71
|
|
|
88
|
-
validate
|
|
72
|
+
validate(): Validity {
|
|
89
73
|
let prevResult
|
|
90
74
|
const statuses = this.fields.map((field) => {
|
|
91
75
|
if (this.params?.stopAtFirstError && prevResult && prevResult.isValid === false) {
|