@coxy/react-validator 1.3.2 → 2.0.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/.eslintignore +1 -1
- package/.eslintrc.js +25 -8
- package/README.md +10 -0
- package/babel.config.js +3 -0
- package/dist/context.d.ts +5 -0
- package/dist/context.js +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +13 -0
- package/dist/rules.d.ts +37 -0
- package/dist/rules.js +43 -0
- package/dist/use-validator.d.ts +3 -0
- package/dist/use-validator.js +22 -0
- package/dist/validator-field.d.ts +25 -0
- package/dist/validator-field.jsx +34 -0
- package/dist/validator-wrapper.d.ts +17 -0
- package/dist/validator-wrapper.jsx +43 -0
- package/dist/validator.d.ts +28 -0
- package/dist/validator.js +72 -0
- package/example/example.jsx +29 -26
- package/example/index.html +2 -0
- package/example/webpack.config.js +15 -7
- package/jest.config.ts +10 -0
- package/package.json +35 -28
- package/src/context.test.ts +7 -0
- package/src/context.ts +6 -0
- package/src/index.test.ts +7 -0
- package/src/index.ts +5 -0
- package/src/jest.d.ts +1 -0
- package/src/rules.test.ts +127 -0
- package/src/{rules.js → rules.ts} +26 -15
- package/src/use-validator.test.tsx +58 -0
- package/src/use-validator.ts +10 -0
- package/src/validator-field.test.tsx +161 -0
- package/src/validator-field.tsx +71 -0
- package/src/validator-wrapper.test.tsx +138 -0
- package/src/validator-wrapper.tsx +58 -0
- package/src/validator.test.tsx +30 -0
- package/src/validator.ts +105 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +39 -0
- package/.babelrc.js +0 -14
- package/build/index.js +0 -1
- package/jest.config.js +0 -5
- package/src/context.js +0 -3
- package/src/context.test.js +0 -9
- package/src/index.js +0 -11
- package/src/index.test.js +0 -9
- package/src/rules.test.js +0 -130
- package/src/validator-field.jsx +0 -72
- package/src/validator-field.test.js +0 -187
- package/src/validator-wrapper.jsx +0 -63
- package/src/validator-wrapper.test.js +0 -174
- package/src/validator.js +0 -82
- package/src/validator.test.js +0 -36
- package/webpack.config.js +0 -32
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createRef } from 'react'
|
|
6
|
+
import { render } from '@testing-library/react'
|
|
7
|
+
|
|
8
|
+
import { ValidatorWrapper } from './validator-wrapper'
|
|
9
|
+
import { ValidatorField } from './validator-field'
|
|
10
|
+
import { rules } from './rules'
|
|
11
|
+
|
|
12
|
+
it('render without child', () => {
|
|
13
|
+
expect(() => shallow(<ValidatorWrapper />)).toThrowError()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('check wrapper validator', () => {
|
|
17
|
+
const validator = createRef<ValidatorWrapper>()
|
|
18
|
+
render((
|
|
19
|
+
<ValidatorWrapper ref={validator}>
|
|
20
|
+
<ValidatorField rules={[]} />
|
|
21
|
+
<ValidatorField rules={[]} />
|
|
22
|
+
<ValidatorField rules={[]} />
|
|
23
|
+
<ValidatorField rules={[]} />
|
|
24
|
+
<ValidatorField rules={[]} />
|
|
25
|
+
<ValidatorField rules={[]} />
|
|
26
|
+
</ValidatorWrapper>
|
|
27
|
+
))
|
|
28
|
+
|
|
29
|
+
expect(typeof validator.current).toBe('object')
|
|
30
|
+
expect(typeof validator.current.validate).toBe('function')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('check getField validator', () => {
|
|
34
|
+
const validator = createRef<ValidatorWrapper>()
|
|
35
|
+
render((
|
|
36
|
+
<ValidatorWrapper ref={validator}>
|
|
37
|
+
<ValidatorField rules={[]} id="test" />
|
|
38
|
+
<ValidatorField rules={[]} id="test-fields" />
|
|
39
|
+
</ValidatorWrapper>
|
|
40
|
+
))
|
|
41
|
+
expect(typeof validator.current.getField).toBe('function')
|
|
42
|
+
const field = validator.current.getField('test')
|
|
43
|
+
|
|
44
|
+
expect(typeof field.validate).toBe('function')
|
|
45
|
+
const fieldValidate = field.validate()
|
|
46
|
+
|
|
47
|
+
expect(fieldValidate.isValid).toBe(true)
|
|
48
|
+
expect(fieldValidate.message).toBe('')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('check getField undefined field', () => {
|
|
52
|
+
const validator = createRef<ValidatorWrapper>()
|
|
53
|
+
render((
|
|
54
|
+
<ValidatorWrapper ref={validator}>
|
|
55
|
+
<ValidatorField rules={[]} id="test-empty-field" />
|
|
56
|
+
</ValidatorWrapper>
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
const field = validator.current.getField('8')
|
|
60
|
+
expect(field).toBe(null)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('check stopAtFirstError validator', () => {
|
|
64
|
+
const validator = createRef<ValidatorWrapper>()
|
|
65
|
+
render((
|
|
66
|
+
<ValidatorWrapper ref={validator} stopAtFirstError>
|
|
67
|
+
<ValidatorField rules={[]} value="test" />
|
|
68
|
+
<ValidatorField rules={rules.email} value="test" />
|
|
69
|
+
<ValidatorField rules={rules.password} value="" />
|
|
70
|
+
</ValidatorWrapper>
|
|
71
|
+
))
|
|
72
|
+
const fieldValidate = validator.current.validate()
|
|
73
|
+
expect(fieldValidate.isValid).toBe(false)
|
|
74
|
+
expect(fieldValidate.message).toBe('Email is invalid')
|
|
75
|
+
expect(fieldValidate.errors.length).toBe(1)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('check unregisterField, registerField', () => {
|
|
79
|
+
const validator = createRef<ValidatorWrapper>()
|
|
80
|
+
render((
|
|
81
|
+
<ValidatorWrapper ref={validator}>
|
|
82
|
+
<ValidatorField rules={[]} id="test-register-field" />
|
|
83
|
+
</ValidatorWrapper>
|
|
84
|
+
))
|
|
85
|
+
|
|
86
|
+
expect(typeof validator.current.registerField).toBe('function')
|
|
87
|
+
expect(typeof validator.current.unregisterField).toBe('function')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('check filed in field', () => {
|
|
91
|
+
const validator = createRef<ValidatorWrapper>()
|
|
92
|
+
render(
|
|
93
|
+
<ValidatorWrapper ref={validator}>
|
|
94
|
+
<ValidatorField rules={[]}>
|
|
95
|
+
<ValidatorField rules={[]} id="check-validate-field-1" />
|
|
96
|
+
<ValidatorField rules={[]} id="check-validate-field-2" />
|
|
97
|
+
</ValidatorField>
|
|
98
|
+
</ValidatorWrapper>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
expect(typeof validator.current).toBe('object')
|
|
102
|
+
expect(typeof validator.current.validate).toBe('function')
|
|
103
|
+
const result = validator.current.validate()
|
|
104
|
+
expect(result.isValid).toBe(true)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('check wrapper in wrapper', () => {
|
|
108
|
+
const validatorOut = createRef<ValidatorWrapper>()
|
|
109
|
+
const validatorIn = createRef<ValidatorWrapper>()
|
|
110
|
+
render((
|
|
111
|
+
<ValidatorWrapper ref={validatorOut}>
|
|
112
|
+
<ValidatorField rules={rules.email} value="" />
|
|
113
|
+
<ValidatorWrapper ref={validatorIn}>
|
|
114
|
+
<ValidatorField rules={rules.password} value="successpasswword" />
|
|
115
|
+
</ValidatorWrapper>
|
|
116
|
+
</ValidatorWrapper>
|
|
117
|
+
))
|
|
118
|
+
expect(validatorIn.current.validate().isValid).toBe(true)
|
|
119
|
+
expect(validatorOut.current.validate().isValid).toBe(false)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('check two validators', () => {
|
|
123
|
+
const validatorSuccess = createRef<ValidatorWrapper>()
|
|
124
|
+
const validatorFailed = createRef<ValidatorWrapper>()
|
|
125
|
+
render((
|
|
126
|
+
<>
|
|
127
|
+
<ValidatorWrapper ref={validatorSuccess}>
|
|
128
|
+
<ValidatorField rules={rules.password} value="successpasswword" />
|
|
129
|
+
</ValidatorWrapper>
|
|
130
|
+
<ValidatorWrapper ref={validatorFailed}>
|
|
131
|
+
<ValidatorField rules={rules.email} value="" />
|
|
132
|
+
</ValidatorWrapper>
|
|
133
|
+
</>
|
|
134
|
+
))
|
|
135
|
+
|
|
136
|
+
expect(validatorFailed.current.validate().isValid).toBe(false)
|
|
137
|
+
expect(validatorSuccess.current.validate().isValid).toBe(true)
|
|
138
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* eslint react/sort-comp: [0], camelcase: [0] */
|
|
2
|
+
import { Component, ReactNode, RefObject } from 'react'
|
|
3
|
+
|
|
4
|
+
import { Context } from './context'
|
|
5
|
+
import { Validator } from './validator'
|
|
6
|
+
|
|
7
|
+
interface ComponentProps {
|
|
8
|
+
children?: ReactNode
|
|
9
|
+
stopAtFirstError?: boolean
|
|
10
|
+
ref?: RefObject<any>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ValidatorWrapper extends Component<ComponentProps> {
|
|
14
|
+
fields = [];
|
|
15
|
+
|
|
16
|
+
constructor (props, ctx) {
|
|
17
|
+
super(props, ctx)
|
|
18
|
+
this.registerField = this.registerField.bind(this)
|
|
19
|
+
this.unregisterField = this.unregisterField.bind(this)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
componentWillUnmount () {
|
|
23
|
+
this.fields = []
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
registerField (field) {
|
|
27
|
+
if (field && !this.fields.includes(field)) {
|
|
28
|
+
this.fields.push(field)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
unregisterField (field) {
|
|
33
|
+
const index = this.fields.indexOf(field)
|
|
34
|
+
if (index > -1) this.fields.splice(index, 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getField (id) {
|
|
38
|
+
return this.fields.find((field) => field.props.id === id) || null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
validate () {
|
|
42
|
+
const validator = new Validator({ stopAtFirstError: this.props.stopAtFirstError })
|
|
43
|
+
this.fields.forEach((comp) => {
|
|
44
|
+
validator.addField(comp.props)
|
|
45
|
+
})
|
|
46
|
+
return validator.validate()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
render () {
|
|
50
|
+
return (
|
|
51
|
+
<Context.Provider
|
|
52
|
+
value={{ registerField: this.registerField, unregisterField: this.unregisterField }}
|
|
53
|
+
>
|
|
54
|
+
{this.props.children}
|
|
55
|
+
</Context.Provider>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { rules } from './rules'
|
|
2
|
+
import { Validator } from './validator'
|
|
3
|
+
|
|
4
|
+
it('check normal create validator', () => {
|
|
5
|
+
const validator = new Validator()
|
|
6
|
+
expect(typeof validator).toBe('object')
|
|
7
|
+
expect(typeof validator.validate).toBe('function')
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('check normal add and remove fields', () => {
|
|
11
|
+
const validator = new Validator({ stopAtFirstError: true })
|
|
12
|
+
const fieldPassword = validator.addField({
|
|
13
|
+
rules: rules.password,
|
|
14
|
+
value: '',
|
|
15
|
+
id: 'for-remove'
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
expect(typeof fieldPassword).toBe('object')
|
|
19
|
+
|
|
20
|
+
const fieldSearchPassword = validator.getField('for-remove')
|
|
21
|
+
|
|
22
|
+
expect(typeof fieldSearchPassword).toBe('object')
|
|
23
|
+
expect(typeof fieldSearchPassword.validate).toBe('function')
|
|
24
|
+
expect(fieldPassword.id === fieldSearchPassword.id).toBe(true)
|
|
25
|
+
|
|
26
|
+
let newFieldSearchPassword = validator.getField('for-remove')
|
|
27
|
+
validator.removeField(newFieldSearchPassword)
|
|
28
|
+
newFieldSearchPassword = validator.getField('for-remove')
|
|
29
|
+
expect(newFieldSearchPassword === null).toBe(true)
|
|
30
|
+
})
|
package/src/validator.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Validity, Value } from './validator-field'
|
|
2
|
+
import { ValidatorRules } from './rules'
|
|
3
|
+
|
|
4
|
+
export interface FieldParams {
|
|
5
|
+
value: Value
|
|
6
|
+
rules: ValidatorRules,
|
|
7
|
+
required?: boolean
|
|
8
|
+
id?: string | number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class Field {
|
|
12
|
+
private rules: ValidatorRules;
|
|
13
|
+
private required: boolean;
|
|
14
|
+
private value: Value;
|
|
15
|
+
public id: string | number;
|
|
16
|
+
constructor ({
|
|
17
|
+
rules,
|
|
18
|
+
required,
|
|
19
|
+
value,
|
|
20
|
+
id
|
|
21
|
+
}: FieldParams) {
|
|
22
|
+
this.rules = rules
|
|
23
|
+
this.required = required
|
|
24
|
+
this.value = value
|
|
25
|
+
this.id = id
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
validate (): Validity {
|
|
29
|
+
let isValid = true
|
|
30
|
+
let message = ''
|
|
31
|
+
const {
|
|
32
|
+
rules,
|
|
33
|
+
value,
|
|
34
|
+
required,
|
|
35
|
+
id
|
|
36
|
+
} = this
|
|
37
|
+
|
|
38
|
+
const isEmptyValue = !value && parseFloat(value) !== 0
|
|
39
|
+
|
|
40
|
+
if (!rules.length || (isEmptyValue && required === false)) {
|
|
41
|
+
return { isValid, message, id }
|
|
42
|
+
}
|
|
43
|
+
rules.forEach((instance) => {
|
|
44
|
+
if (isValid) {
|
|
45
|
+
isValid = instance.rule(value)
|
|
46
|
+
if (!isValid) {
|
|
47
|
+
if (typeof instance.message === 'function') {
|
|
48
|
+
message = instance.message(value)
|
|
49
|
+
} else {
|
|
50
|
+
message = instance.message
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
return { isValid, message, id }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ValidatorParams {
|
|
60
|
+
stopAtFirstError: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class Validator {
|
|
64
|
+
private fields: Field[];
|
|
65
|
+
private params: ValidatorParams;
|
|
66
|
+
|
|
67
|
+
constructor (params?: ValidatorParams) {
|
|
68
|
+
this.params = params || null
|
|
69
|
+
this.fields = []
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
addField (params: FieldParams): Field {
|
|
73
|
+
const field = new Field(params)
|
|
74
|
+
this.fields.push(field)
|
|
75
|
+
return field
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
removeField (field: Field): void {
|
|
79
|
+
const index = this.fields.indexOf(field)
|
|
80
|
+
if (index > -1) this.fields.splice(index, 1)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getField (id: Field['id']): Field {
|
|
84
|
+
return this.fields.find((field) => field.id === id) || null
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
validate (): Validity {
|
|
88
|
+
let prevResult
|
|
89
|
+
const statuses = this.fields.map((field) => {
|
|
90
|
+
if (this.params?.stopAtFirstError && prevResult && prevResult.isValid === false) {
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
prevResult = field.validate()
|
|
94
|
+
return prevResult
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const errors = statuses.filter((inst) => inst && inst.isValid === false)
|
|
98
|
+
|
|
99
|
+
if (errors.length) {
|
|
100
|
+
const { isValid, message } = errors[0]
|
|
101
|
+
return { isValid, message, errors }
|
|
102
|
+
}
|
|
103
|
+
return { isValid: true, message: '' }
|
|
104
|
+
}
|
|
105
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"esModuleInterop": true,
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"module": "CommonJS",
|
|
6
|
+
"removeComments": true,
|
|
7
|
+
"emitDecoratorMetadata": true,
|
|
8
|
+
"experimentalDecorators": true,
|
|
9
|
+
"target": "es2017",
|
|
10
|
+
"sourceMap": false,
|
|
11
|
+
"composite": true,
|
|
12
|
+
"incremental": true,
|
|
13
|
+
"noUnusedLocals": true,
|
|
14
|
+
"noUnusedParameters": false,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"outDir": "./dist",
|
|
17
|
+
"rootDir": "src",
|
|
18
|
+
"baseUrl": "./src",
|
|
19
|
+
"lib": [
|
|
20
|
+
"dom",
|
|
21
|
+
"dom.iterable",
|
|
22
|
+
"esnext"
|
|
23
|
+
],
|
|
24
|
+
"allowJs": true,
|
|
25
|
+
"skipLibCheck": true,
|
|
26
|
+
"strict": false,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"moduleResolution": "node",
|
|
29
|
+
"jsx": "preserve"
|
|
30
|
+
},
|
|
31
|
+
"include": [
|
|
32
|
+
"src",
|
|
33
|
+
"src/**/*"
|
|
34
|
+
],
|
|
35
|
+
"exclude": [
|
|
36
|
+
"node_modules",
|
|
37
|
+
"dist"
|
|
38
|
+
]
|
|
39
|
+
}
|
package/.babelrc.js
DELETED
package/build/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports=(()=>{"use strict";var e={942:(e,t,r)=>{r.r(t),r.d(t,{Validator:()=>p,ValidatorField:()=>x,default:()=>A,rules:()=>V});const n=require("react");var i=r.n(n);const o=require("prop-types");var u=r.n(o);const s=i().createContext("@coxy/Validator");function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function c(e,t,r){return t&&a(e.prototype,t),r&&a(e,r),e}var f=function(){function e(t){var r=t.rules,n=t.required,i=t.value,o=t.id;l(this,e),this.rules=r,this.required=n,this.value=i,this.id=o}return c(e,[{key:"validate",value:function(){var e=!0,t="",r=this.rules,n=this.value,i=this.required,o=this.id,u=!n&&0!==parseFloat(n);return!r.length||u&&!1===i||r.forEach((function(r){e&&((e=r.rule(n))||"function"==typeof(t=r.message)&&(t=t(n)))})),{isValid:e,message:t,id:o}}}]),e}(),p=function(){function e(t){l(this,e),this.params=t||{},this.fields=[]}return c(e,[{key:"addField",value:function(e){var t=new f(e);return this.fields.push(t),t}},{key:"removeField",value:function(e){var t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},{key:"getField",value:function(e){return this.fields.find((function(t){return t.id===e}))||null}},{key:"validate",value:function(){var e,t=this,r=this.fields.map((function(r){return t.params.stopAtFirstError&&e&&!1===e.isValid?null:e=r.validate()})).filter((function(e){return e&&!1===e.isValid}));if(r.length){var n=r[0];return{isValid:n.isValid,message:n.message,errors:r}}return{isValid:!0,message:""}}}]),e}();function d(e){return(d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function y(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function h(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function v(e,t){return(v=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function b(e,t){return!t||"object"!==d(t)&&"function"!=typeof t?g(e):t}function g(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function m(e){return(m=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function O(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var F=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&v(e,t)}(l,e);var t,r,n,o,u=(n=l,o=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,t=m(n);if(o){var r=m(this).constructor;e=Reflect.construct(t,arguments,r)}else e=t.apply(this,arguments);return b(this,e)});function l(){var e;y(this,l);for(var t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return O(g(e=u.call.apply(u,[this].concat(r))),"fields",[]),e.registerField=e.registerField.bind(g(e)),e.unregisterField=e.unregisterField.bind(g(e)),e}return t=l,(r=[{key:"componentWillUnmount",value:function(){this.fields=[]}},{key:"registerField",value:function(e){e&&!this.fields.includes(e)&&this.fields.push(e)}},{key:"unregisterField",value:function(e){var t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},{key:"getField",value:function(e){return this.fields.find((function(t){return t.props.id===e}))||null}},{key:"validate",value:function(){var e=new p({stopAtFirstError:this.props.stopAtFirstError});return this.fields.forEach((function(t){e.addField(t.props)})),e.validate()}},{key:"render",value:function(){return i().createElement(s.Provider,{value:{registerField:this.registerField,unregisterField:this.unregisterField}},this.props.children)}}])&&h(t.prototype,r),l}(n.Component);F.propTypes={children:u().node.isRequired,stopAtFirstError:u().bool},F.defaultProps={stopAtFirstError:!1};const w=F;function P(){return(P=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function j(e){return(j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function S(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function E(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function _(e,t){return(_=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function k(e,t){return!t||"object"!==j(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function q(e){return(q=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var R=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_(e,t)}(u,e);var t,r,n,i,o=(n=u,i=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,t=q(n);if(i){var r=q(this).constructor;e=Reflect.construct(t,arguments,r)}else e=t.apply(this,arguments);return k(this,e)});function u(){return S(this,u),o.apply(this,arguments)}return t=u,(r=[{key:"componentWillUnmount",value:function(){this.props.unregisterField(this)}},{key:"componentDidMount",value:function(){this.props.registerField(this)}},{key:"validate",value:function(){return new f({rules:this.props.rules,required:this.props.required,value:this.props.value,id:this.props.id}).validate()}},{key:"render",value:function(){var e=this.props,t=e.children,r=e.value,n=this.validate();return"function"==typeof t?t(n,r):t}}])&&E(t.prototype,r),u}(n.Component);function x(e){return i().createElement(s.Consumer,null,(function(t){return i().createElement(R,P({},e,{registerField:t.registerField,unregisterField:t.unregisterField}))}))}R.propTypes={registerField:u().func.isRequired,unregisterField:u().func.isRequired,children:u().oneOfType([u().node,u().func]),rules:u().arrayOf(u().shape({message:u().oneOfType([u().string,u().func]),rule:u().func})),id:u().string,required:u().bool,value:u().any},R.defaultProps={rules:[],children:null,required:!0,value:void 0,id:""};var T=/^(([^<>()\[\]\\.,;:\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,}))$/;const V={notEmpty:[{rule:function(e){return""!==e&&e.length>0},message:"Value is required"}],bool:[{rule:function(e){return!!e},message:"Value is required"}],password:[{rule:function(e){return e.length>0},message:"Password field cannot be empty"},{rule:function(e){return e.length>5},message:"Password field can not be less than 6 characters"}],email:[{rule:function(e){return!!e&&""!==e&&0!==e.length},message:"Email is required"},{rule:function(e){return T.test(String(e).toLowerCase())},message:"Email is invalid"}],min:function(e){return[{rule:function(t){return parseFloat(t)>e},message:"The value must be greater than ".concat(e)}]},max:function(e){return[{rule:function(t){return parseFloat(t)<e},message:"The value must be smaller ".concat(e)}]},length:function(e,t){return[{rule:function(t){return String(t).length>=e},message:"No less than ".concat(e," symbols")},{rule:function(e){return void 0===t||String(e).length<=t},message:"No more than ".concat(t," symbols")}]}},A=w}},t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={exports:{}};return e[n](i,i.exports,r),i.exports}return r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r(942)})();
|
package/jest.config.js
DELETED
package/src/context.js
DELETED
package/src/context.test.js
DELETED
package/src/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import ValidatorWrapper from './validator-wrapper';
|
|
2
|
-
import ValidatorField from './validator-field';
|
|
3
|
-
import Validator from './validator';
|
|
4
|
-
import rules from './rules';
|
|
5
|
-
|
|
6
|
-
export default ValidatorWrapper;
|
|
7
|
-
export {
|
|
8
|
-
ValidatorField,
|
|
9
|
-
Validator,
|
|
10
|
-
rules,
|
|
11
|
-
};
|
package/src/index.test.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/* eslint-env jest */
|
|
2
|
-
|
|
3
|
-
import ValidatorWrapper, { ValidatorField, rules } from './index';
|
|
4
|
-
|
|
5
|
-
it('renders with or without a name', () => {
|
|
6
|
-
expect(typeof ValidatorWrapper).toBe('function');
|
|
7
|
-
expect(typeof ValidatorField).toBe('function');
|
|
8
|
-
expect(typeof rules).toBe('object');
|
|
9
|
-
});
|
package/src/rules.test.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/* eslint-env jest */
|
|
2
|
-
|
|
3
|
-
import rules from './rules';
|
|
4
|
-
|
|
5
|
-
it('check rule email', () => {
|
|
6
|
-
expect(rules.email.length).toBe(2);
|
|
7
|
-
|
|
8
|
-
let result = null;
|
|
9
|
-
// email.length > 0
|
|
10
|
-
result = rules.email[0].rule('test');
|
|
11
|
-
expect(result).toBe(true);
|
|
12
|
-
|
|
13
|
-
// email check regexp
|
|
14
|
-
result = rules.email[1].rule('test');
|
|
15
|
-
expect(result).toBe(false);
|
|
16
|
-
|
|
17
|
-
// email check regexp
|
|
18
|
-
result = rules.email[1].rule('test@gmail.com');
|
|
19
|
-
expect(result).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('check rule password', () => {
|
|
23
|
-
expect(rules.password.length).toBe(2);
|
|
24
|
-
|
|
25
|
-
let result = null;
|
|
26
|
-
// password.length > 0
|
|
27
|
-
result = rules.password[0].rule('test');
|
|
28
|
-
expect(result).toBe(true);
|
|
29
|
-
|
|
30
|
-
// password.length > 5
|
|
31
|
-
result = rules.password[1].rule('test');
|
|
32
|
-
expect(result).toBe(false);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('check rule bool', () => {
|
|
36
|
-
expect(rules.bool.length).toBe(1);
|
|
37
|
-
|
|
38
|
-
let result = null;
|
|
39
|
-
result = rules.bool[0].rule(true);
|
|
40
|
-
expect(result).toBe(true);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('check rule notEmpty', () => {
|
|
44
|
-
expect(rules.notEmpty.length).toBe(1);
|
|
45
|
-
|
|
46
|
-
let result = null;
|
|
47
|
-
result = rules.notEmpty[0].rule('');
|
|
48
|
-
expect(result).toBe(false);
|
|
49
|
-
|
|
50
|
-
result = rules.notEmpty[0].rule('test');
|
|
51
|
-
expect(result).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('check rule min', () => {
|
|
55
|
-
expect(rules.min(1).length).toBe(1);
|
|
56
|
-
expect(typeof rules.min).toBe('function');
|
|
57
|
-
|
|
58
|
-
let result = null;
|
|
59
|
-
result = rules.min(10)[0].rule('');
|
|
60
|
-
expect(result).toBe(false);
|
|
61
|
-
|
|
62
|
-
result = rules.min(9)[0].rule('testtesttest');
|
|
63
|
-
expect(result).toBe(false);
|
|
64
|
-
|
|
65
|
-
result = rules.min(9)[0].rule('11');
|
|
66
|
-
expect(result).toBe(true);
|
|
67
|
-
|
|
68
|
-
result = rules.min(9)[0].rule(10);
|
|
69
|
-
expect(result).toBe(true);
|
|
70
|
-
|
|
71
|
-
result = rules.min(9)[0].rule('8');
|
|
72
|
-
expect(result).toBe(false);
|
|
73
|
-
|
|
74
|
-
result = rules.min(9)[0].rule(7);
|
|
75
|
-
expect(result).toBe(false);
|
|
76
|
-
|
|
77
|
-
result = rules.min(-1)[0].rule('');
|
|
78
|
-
expect(result).toBe(false);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('check rule max', () => {
|
|
82
|
-
let result = null;
|
|
83
|
-
result = rules.max(10)[0].rule('');
|
|
84
|
-
expect(result).toBe(false);
|
|
85
|
-
|
|
86
|
-
result = rules.max(9)[0].rule('testtesttest');
|
|
87
|
-
expect(result).toBe(false);
|
|
88
|
-
|
|
89
|
-
result = rules.max(9)[0].rule('11');
|
|
90
|
-
expect(result).toBe(false);
|
|
91
|
-
|
|
92
|
-
result = rules.max(9)[0].rule(10);
|
|
93
|
-
expect(result).toBe(false);
|
|
94
|
-
|
|
95
|
-
result = rules.max(9)[0].rule('5');
|
|
96
|
-
expect(result).toBe(true);
|
|
97
|
-
|
|
98
|
-
result = rules.max(9)[0].rule(5);
|
|
99
|
-
expect(result).toBe(true);
|
|
100
|
-
|
|
101
|
-
result = rules.max(-1)[0].rule('');
|
|
102
|
-
expect(result).toBe(false);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('check rule length', () => {
|
|
106
|
-
let result = null;
|
|
107
|
-
result = rules.length(1)[0].rule('');
|
|
108
|
-
expect(result).toBe(false);
|
|
109
|
-
|
|
110
|
-
result = rules.length(1)[0].rule('1');
|
|
111
|
-
expect(result).toBe(true);
|
|
112
|
-
|
|
113
|
-
result = rules.length(1, 10)[0].rule('testtesttest');
|
|
114
|
-
expect(result).toBe(true);
|
|
115
|
-
|
|
116
|
-
result = rules.length(1, 10)[1].rule('testtesttest');
|
|
117
|
-
expect(result).toBe(false);
|
|
118
|
-
|
|
119
|
-
result = rules.length(1, 10)[0].rule('lol');
|
|
120
|
-
expect(result).toBe(true);
|
|
121
|
-
|
|
122
|
-
result = rules.length(1, 10)[1].rule('lol');
|
|
123
|
-
expect(result).toBe(true);
|
|
124
|
-
|
|
125
|
-
result = rules.length(1)[1].rule('test undefined 2 param');
|
|
126
|
-
expect(result).toBe(true);
|
|
127
|
-
|
|
128
|
-
result = rules.length(10)[0].rule('tes');
|
|
129
|
-
expect(result).toBe(false);
|
|
130
|
-
});
|
package/src/validator-field.jsx
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/* eslint react/jsx-props-no-spreading: [0], react/sort-comp: [0], camelcase: [0] */
|
|
2
|
-
import React, { Component } from 'react';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
import Context from './context';
|
|
5
|
-
import { Field } from './validator';
|
|
6
|
-
|
|
7
|
-
class ValidationFieldWrapper extends Component {
|
|
8
|
-
componentWillUnmount() {
|
|
9
|
-
this.props.unregisterField(this);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
componentDidMount() {
|
|
13
|
-
this.props.registerField(this);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
validate() {
|
|
17
|
-
const field = new Field({
|
|
18
|
-
rules: this.props.rules,
|
|
19
|
-
required: this.props.required,
|
|
20
|
-
value: this.props.value,
|
|
21
|
-
id: this.props.id,
|
|
22
|
-
});
|
|
23
|
-
return field.validate();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
render() {
|
|
27
|
-
const { children, value } = this.props;
|
|
28
|
-
const validity = this.validate();
|
|
29
|
-
return (typeof children === 'function' ? children(validity, value) : children);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default function ValidationField(props) {
|
|
34
|
-
return (
|
|
35
|
-
<Context.Consumer>
|
|
36
|
-
{(data) => (
|
|
37
|
-
<ValidationFieldWrapper
|
|
38
|
-
{...props}
|
|
39
|
-
registerField={data.registerField}
|
|
40
|
-
unregisterField={data.unregisterField}
|
|
41
|
-
/>
|
|
42
|
-
)}
|
|
43
|
-
</Context.Consumer>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
ValidationFieldWrapper.propTypes = {
|
|
48
|
-
// from context
|
|
49
|
-
registerField: PropTypes.func.isRequired,
|
|
50
|
-
unregisterField: PropTypes.func.isRequired,
|
|
51
|
-
|
|
52
|
-
children: PropTypes.oneOfType([
|
|
53
|
-
PropTypes.node,
|
|
54
|
-
PropTypes.func,
|
|
55
|
-
]),
|
|
56
|
-
rules: PropTypes.arrayOf(PropTypes.shape({
|
|
57
|
-
message: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
|
58
|
-
rule: PropTypes.func,
|
|
59
|
-
})),
|
|
60
|
-
|
|
61
|
-
id: PropTypes.string,
|
|
62
|
-
required: PropTypes.bool,
|
|
63
|
-
value: PropTypes.any, // eslint-disable-line
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
ValidationFieldWrapper.defaultProps = {
|
|
67
|
-
rules: [],
|
|
68
|
-
children: null,
|
|
69
|
-
required: true,
|
|
70
|
-
value: undefined,
|
|
71
|
-
id: '',
|
|
72
|
-
};
|