@coxy/react-validator 2.0.7 → 4.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/README.md +145 -120
- package/biome.json +34 -0
- package/dist/index.d.mts +106 -0
- package/dist/index.d.ts +106 -6
- package/dist/index.js +2 -28
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/example/example.tsx +26 -26
- package/example/index.html +2 -7
- package/example/tsconfig.json +6 -11
- package/package.json +26 -36
- package/src/context.ts +8 -3
- package/src/custom-errors.test.tsx +73 -0
- package/src/index.test.ts +19 -4
- package/src/index.ts +4 -3
- package/src/rules.test.ts +15 -10
- package/src/rules.ts +15 -15
- package/src/types.ts +3 -2
- package/src/use-validator.test.tsx +4 -7
- package/src/use-validator.ts +3 -3
- package/src/validator-field.test.tsx +45 -18
- package/src/validator-field.tsx +44 -53
- package/src/validator-wrapper.test.tsx +41 -27
- package/src/validator-wrapper.tsx +60 -57
- package/src/validator.test.tsx +10 -0
- package/src/validator.ts +10 -10
- package/tsconfig.json +6 -16
- package/tsup.config.ts +14 -0
- package/.eslintignore +0 -2
- package/.eslintrc.js +0 -5
- package/.prettierrc.js +0 -10
- package/CHANGELOG.md +0 -49
- package/dist/context.d.ts +0 -7
- package/dist/context.js +0 -5
- package/dist/rules.d.ts +0 -32
- package/dist/rules.js +0 -60
- package/dist/types.d.ts +0 -24
- package/dist/types.js +0 -2
- package/dist/use-validator.d.ts +0 -4
- package/dist/use-validator.js +0 -22
- package/dist/validator-field.d.ts +0 -17
- package/dist/validator-field.js +0 -38
- package/dist/validator-wrapper.d.ts +0 -24
- package/dist/validator-wrapper.js +0 -57
- package/dist/validator.d.ts +0 -21
- package/dist/validator.js +0 -72
- package/src/jest.d.ts +0 -1
- package/tsconfig.build.json +0 -12
package/README.md
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# @Coxy/react-validator
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
[](https://travis-ci.org/dsshard/react-validator)
|
|
6
|
-
[](https://codecov.io/gh/dsshard/react-validator)
|
|
7
|
-
[](https://coveralls.io/github/dsshard/react-validator?branch=master)
|
|
8
|
-
[](https://david-dm.org/dsshard/react-validator)
|
|
9
|
-
[](https://codeclimate.com/github/dsshard/react-validator/maintainability)
|
|
10
|
-
[](https://bundlephobia.com/result?p=@coxy/react-validator)
|
|
11
|
-
[]()
|
|
3
|
+
---
|
|
12
4
|
|
|
5
|
+
# Simple React Form Validation
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
@Coxy/react-validator provides a simple and flexible way to validate forms in React.
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
> Supports data validation both **in-browser** and **on Node.js**.
|
|
17
10
|
|
|
11
|
+
> Requires React **\>=16.3**.
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
---
|
|
20
14
|
|
|
21
|
-
#
|
|
15
|
+
# Installation
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @coxy/react-validator
|
|
19
|
+
# or
|
|
20
|
+
yarn add @coxy/react-validator
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Quick Start Example
|
|
24
26
|
|
|
25
|
-
```
|
|
27
|
+
```tsx
|
|
26
28
|
import React, { useState } from 'react';
|
|
27
29
|
import { ValidatorWrapper, rules, ValidatorField } from '@coxy/react-validator';
|
|
28
30
|
|
|
@@ -34,174 +36,197 @@ const handleSubmit = () => {
|
|
|
34
36
|
console.log(isValid, message, errors);
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
37
|
-
|
|
39
|
+
alert('Form is valid!');
|
|
38
40
|
};
|
|
39
41
|
|
|
40
|
-
export default ()
|
|
41
|
-
const [email,
|
|
42
|
+
export default function Example() {
|
|
43
|
+
const [email, setEmail] = useState('');
|
|
42
44
|
|
|
43
45
|
return (
|
|
44
46
|
<ValidatorWrapper ref={validator}>
|
|
45
|
-
|
|
46
47
|
<ValidatorField value={email} rules={rules.email}>
|
|
47
48
|
{({ isValid, message }) => (
|
|
48
49
|
<>
|
|
49
|
-
<input value={email} onChange={({ target: { value } }) =>
|
|
50
|
-
{!isValid && <div>{message}</div>}
|
|
50
|
+
<input value={email} onChange={({ target: { value } }) => setEmail(value)} />
|
|
51
|
+
{!isValid && <div style={{ color: 'red' }}>{message}</div>}
|
|
51
52
|
</>
|
|
52
53
|
)}
|
|
53
54
|
</ValidatorField>
|
|
54
55
|
|
|
55
|
-
<ValidatorField value={email} rules={rules.email}>
|
|
56
|
-
<input value={email} onChange={({ target: { value } }) => handleChange(value)} />
|
|
57
|
-
</ValidatorField>
|
|
58
|
-
|
|
59
|
-
{/* This is also possible :) */}
|
|
60
|
-
<ValidatorField value={email} rules={rules.email} />
|
|
61
|
-
|
|
62
56
|
<button onClick={handleSubmit} type="button">
|
|
63
57
|
Submit
|
|
64
58
|
</button>
|
|
65
|
-
|
|
66
59
|
</ValidatorWrapper>
|
|
67
60
|
);
|
|
68
|
-
}
|
|
61
|
+
}
|
|
69
62
|
```
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
More examples available [here](example/example.tsx).
|
|
65
|
+
|
|
66
|
+
---
|
|
74
67
|
|
|
75
|
-
|
|
68
|
+
# Built-in Validation Rules
|
|
76
69
|
|
|
70
|
+
Create your own rules easily, or use the built-in ones:
|
|
77
71
|
|
|
78
72
|
```javascript
|
|
79
73
|
const rules = {
|
|
80
|
-
email: [
|
|
81
|
-
rule: value => value !== ''
|
|
82
|
-
message: '
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
message: '
|
|
86
|
-
|
|
87
|
-
|
|
74
|
+
email: [
|
|
75
|
+
{ rule: value => value.trim() !== '', message: 'Value is required' },
|
|
76
|
+
{ rule: value => value.includes('@'), message: '@ is required' },
|
|
77
|
+
],
|
|
78
|
+
password: [
|
|
79
|
+
{ rule: value => value.length >= 6, message: 'Password must be at least 6 characters' },
|
|
80
|
+
],
|
|
81
|
+
notEmpty: [
|
|
82
|
+
{ rule: value => !!value && value.trim() !== '', message: 'Field cannot be empty' },
|
|
83
|
+
],
|
|
84
|
+
boolean: [
|
|
85
|
+
{ rule: value => typeof value === 'boolean', message: 'Must be a boolean value' },
|
|
86
|
+
],
|
|
87
|
+
min: (min) => ([
|
|
88
|
+
{ rule: value => Number(value) >= min, message: `Must be at least ${min}` },
|
|
89
|
+
]),
|
|
90
|
+
max: (max) => ([
|
|
91
|
+
{ rule: value => Number(value) <= max, message: `Must be at most ${max}` },
|
|
92
|
+
]),
|
|
93
|
+
length: (min, max) => ([
|
|
94
|
+
{ rule: value => value.length >= min, message: `Must be at least ${min} characters` },
|
|
95
|
+
...(max ? [{ rule: value => value.length <= max, message: `Must be at most ${max} characters` }] : [])
|
|
96
|
+
]),
|
|
97
|
+
};
|
|
88
98
|
```
|
|
89
99
|
|
|
90
|
-
|
|
100
|
+
| Name | Type | Description |
|
|
101
|
+
|-------------|----------|-----------------------------------------------------------|
|
|
102
|
+
| email | Array | Validate non-empty email with regex check. |
|
|
103
|
+
| password | Array | Validate non-empty password with min length. |
|
|
104
|
+
| notEmpty | Array | Check if a string is not empty. |
|
|
105
|
+
| boolean | Array | Ensure a boolean value is present. |
|
|
106
|
+
| min(n) | Function | Validate number is >= `n`. |
|
|
107
|
+
| max(n) | Function | Validate number is <= `n`. |
|
|
108
|
+
| length(a,b) | Function | Validate string length is between `a` and `b` (optional). |
|
|
91
109
|
|
|
92
|
-
|
|
93
|
-
|--------------|----------|-------------------------------------------------------------------------|
|
|
94
|
-
| email | | Check email for empty string and regexp |
|
|
95
|
-
| password | | Check password for empty string and length |
|
|
96
|
-
| notEmpty | | Check if the string is not empty |
|
|
97
|
-
| boolean | | Will check that the value is present |
|
|
98
|
-
| min | function | min\(3\) \-> Check the number |
|
|
99
|
-
| max | function | max\(5\) \-> Check the number |
|
|
100
|
-
| length | function | length\(3, 5\) \-> Check string length \(second parameter is optional\) |
|
|
110
|
+
---
|
|
101
111
|
|
|
102
|
-
|
|
112
|
+
# React API
|
|
103
113
|
|
|
104
|
-
|
|
114
|
+
## `<ValidatorWrapper />` Props
|
|
105
115
|
|
|
106
|
-
|
|
116
|
+
| Name | Default | Required | Description |
|
|
117
|
+
|------------------|---------|----------|----------------------------------------------------|
|
|
118
|
+
| ref | null | No | React ref or useRef for control. |
|
|
119
|
+
| stopAtFirstError | false | No | Stop validating after the first error. |
|
|
107
120
|
|
|
108
|
-
|
|
109
|
-
|------------------|-------------|--------------|--------------------------------------------------------|
|
|
110
|
-
| ref | null | no | React\.ref or useRef |
|
|
111
|
-
| stopAtFirstError | false | no | The validator will stop checking after the first error |
|
|
121
|
+
## `<ValidatorField />` Props
|
|
112
122
|
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
| Name | Default | Required | Description |
|
|
124
|
+
|----------|-----------|----------|---------------------------------------|
|
|
125
|
+
| value | undefined | Yes | Value to validate. |
|
|
126
|
+
| rules | [] | Yes | Validation rules array. |
|
|
127
|
+
| required | true | No | Whether the field is required. |
|
|
128
|
+
| id | null | No | ID for the field (for manual access). |
|
|
115
129
|
|
|
116
|
-
|
|
117
|
-
|--------------|-----------------|------------------|-------------------------------|
|
|
118
|
-
| value | undefined | yes | Value for validation |
|
|
119
|
-
| rules | \[\] | yes | Array of rules for validation |
|
|
120
|
-
| required | true | no | The field will be required |
|
|
121
|
-
| id | null | no | ID for get field |
|
|
130
|
+
## `useValidator`
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
# React api useValidator
|
|
132
|
+
Validate a value directly in your component:
|
|
125
133
|
|
|
126
|
-
```
|
|
134
|
+
```tsx
|
|
135
|
+
import { useValidator, rules } from '@coxy/react-validator';
|
|
127
136
|
|
|
128
|
-
const [isValid, { errors }] = useValidator('test
|
|
129
|
-
console.log(isValid, errors) // false
|
|
137
|
+
const [isValid, { errors }] = useValidator('test@example.com', rules.email);
|
|
130
138
|
|
|
139
|
+
console.log(isValid); // true or false
|
|
140
|
+
console.log(errors); // array of error messages
|
|
131
141
|
```
|
|
132
142
|
|
|
133
|
-
|
|
134
|
-
# Api for inline validation
|
|
143
|
+
---
|
|
135
144
|
|
|
136
|
-
|
|
145
|
+
# Validator Class (Node.js / Manual Usage)
|
|
137
146
|
|
|
138
|
-
|
|
139
|
-
|------------------|-------------|--------------|--------------------------------------------------------|
|
|
140
|
-
| stopAtFirstError | false | no | The validator will stop checking after the first error |
|
|
147
|
+
Use it server-side or in custom flows.
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
#### Validator.addField()
|
|
149
|
+
## Validator Constructor Options
|
|
144
150
|
|
|
145
|
-
|
|
151
|
+
| Name | Default | Required | Description |
|
|
152
|
+
|------------------|---------|----------|------------------------------------------------------|
|
|
153
|
+
| stopAtFirstError | false | No | Stop validating after first error across all fields. |
|
|
146
154
|
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
## Methods
|
|
156
|
+
|
|
157
|
+
### `.addField()`
|
|
149
158
|
|
|
159
|
+
```javascript
|
|
150
160
|
const validator = new Validator({ stopAtFirstError: true });
|
|
161
|
+
|
|
151
162
|
const field = validator.addField({
|
|
152
|
-
|
|
153
|
-
|
|
163
|
+
rules: rules.password,
|
|
164
|
+
value: '12345',
|
|
154
165
|
});
|
|
155
166
|
```
|
|
156
|
-
|
|
157
|
-
#### Validator.getField()
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
### `.getField(id)`
|
|
160
169
|
|
|
161
170
|
```javascript
|
|
162
|
-
|
|
171
|
+
const field = validator.getField('password-field');
|
|
172
|
+
console.log(field);
|
|
173
|
+
```
|
|
163
174
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
id: 'test-field-name'
|
|
169
|
-
});
|
|
170
|
-
console.log(validator.getField('test-field-name')) // Field Class
|
|
175
|
+
### `.removeField(field)`
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
validator.removeField(field);
|
|
171
179
|
```
|
|
172
|
-
|
|
173
|
-
#### Validator.removeField()
|
|
174
180
|
|
|
175
|
-
|
|
181
|
+
### `.validate()`
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
const { isValid, message, errors } = validator.validate();
|
|
185
|
+
console.log(isValid, errors);
|
|
186
|
+
```
|
|
176
187
|
|
|
188
|
+
## Full Server-Side Example
|
|
177
189
|
|
|
178
190
|
```javascript
|
|
179
|
-
import { Validator } from '@coxy/react-validator';
|
|
191
|
+
import { Validator, rules } from '@coxy/react-validator';
|
|
180
192
|
|
|
181
|
-
const validator = new Validator(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
const validator = new Validator();
|
|
194
|
+
|
|
195
|
+
validator.addField({
|
|
196
|
+
id: 'email',
|
|
197
|
+
rules: rules.email,
|
|
198
|
+
value: 'test@domain.com',
|
|
186
199
|
});
|
|
187
200
|
|
|
188
|
-
validator.
|
|
189
|
-
|
|
201
|
+
validator.addField({
|
|
202
|
+
id: 'password',
|
|
203
|
+
rules: rules.password,
|
|
204
|
+
value: '1234567',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const result = validator.validate();
|
|
208
|
+
|
|
209
|
+
if (result.isValid) {
|
|
210
|
+
console.log('Validation passed!');
|
|
211
|
+
} else {
|
|
212
|
+
console.error('Validation failed:', result.errors);
|
|
213
|
+
}
|
|
190
214
|
```
|
|
191
215
|
|
|
192
|
-
|
|
193
|
-
#### Validator.validate()
|
|
216
|
+
---
|
|
194
217
|
|
|
195
|
-
|
|
218
|
+
# License
|
|
196
219
|
|
|
197
|
-
|
|
198
|
-
import { Validator } from '@coxy/react-validator';
|
|
220
|
+
MIT © [Dsshard](https://github.com/dsshard)
|
|
199
221
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
# Notes
|
|
225
|
+
|
|
226
|
+
- Lightweight, flexible, easy to integrate.
|
|
227
|
+
- Server-side and client-side validation supported.
|
|
228
|
+
- Create custom rules for different scenarios.
|
|
229
|
+
- Easy to add dynamic validation logic.
|
|
230
|
+
|
|
231
|
+
> **Fun Fact:** Early validation of user inputs in a form can reduce backend server load by up to **40%** compared to server-only validation!
|
|
205
232
|
|
|
206
|
-
console.log(validator.validate());
|
|
207
|
-
```
|
package/biome.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": {
|
|
3
|
+
"includes": ["src/**/*", "example/example.tsx"]
|
|
4
|
+
},
|
|
5
|
+
"formatter": {
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"indentStyle": "space",
|
|
8
|
+
"indentWidth": 2,
|
|
9
|
+
"lineWidth": 120,
|
|
10
|
+
"formatWithErrors": false
|
|
11
|
+
},
|
|
12
|
+
"javascript": {
|
|
13
|
+
"formatter": {
|
|
14
|
+
"quoteStyle": "single",
|
|
15
|
+
"semicolons": "asNeeded",
|
|
16
|
+
"trailingCommas": "all"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"linter": {
|
|
20
|
+
"enabled": true,
|
|
21
|
+
"rules": {
|
|
22
|
+
"recommended": true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"json": {
|
|
26
|
+
"formatter": {
|
|
27
|
+
"indentStyle": "space",
|
|
28
|
+
"indentWidth": 2
|
|
29
|
+
},
|
|
30
|
+
"linter": {
|
|
31
|
+
"enabled": true
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type Value = any;
|
|
5
|
+
type Fn$1 = (validity: Validity, value: Value) => ReactNode;
|
|
6
|
+
declare const ValidatorField: react.ForwardRefExoticComponent<FieldParams & {
|
|
7
|
+
children?: ReactNode | Fn$1;
|
|
8
|
+
} & react.RefAttributes<unknown>>;
|
|
9
|
+
|
|
10
|
+
type Fn = (value: Value) => string;
|
|
11
|
+
interface ValidatorRule {
|
|
12
|
+
rule: (value: Value) => boolean;
|
|
13
|
+
message: string | Fn;
|
|
14
|
+
}
|
|
15
|
+
interface ErrorMessage {
|
|
16
|
+
message: string;
|
|
17
|
+
isValid: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface Validity {
|
|
20
|
+
message: string;
|
|
21
|
+
isValid: boolean;
|
|
22
|
+
errors?: ErrorMessage[];
|
|
23
|
+
id?: string | number;
|
|
24
|
+
}
|
|
25
|
+
interface FieldParams {
|
|
26
|
+
value: Value;
|
|
27
|
+
rules: ValidatorRules;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
id?: string | number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type ValidatorRules = ValidatorRule[];
|
|
33
|
+
declare const rules: {
|
|
34
|
+
notEmpty: {
|
|
35
|
+
rule: (value: string) => boolean;
|
|
36
|
+
message: string;
|
|
37
|
+
}[];
|
|
38
|
+
bool: {
|
|
39
|
+
rule: (value: string) => boolean;
|
|
40
|
+
message: string;
|
|
41
|
+
}[];
|
|
42
|
+
password: {
|
|
43
|
+
rule: (value: string) => boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}[];
|
|
46
|
+
email: {
|
|
47
|
+
rule: (value: string) => boolean;
|
|
48
|
+
message: string;
|
|
49
|
+
}[];
|
|
50
|
+
min: (min: number) => {
|
|
51
|
+
rule: (value: string) => boolean;
|
|
52
|
+
message: string;
|
|
53
|
+
}[];
|
|
54
|
+
max: (max: number) => {
|
|
55
|
+
rule: (value: string) => boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
}[];
|
|
58
|
+
length: (min: number, max?: number) => {
|
|
59
|
+
rule: (value: string) => boolean;
|
|
60
|
+
message: string;
|
|
61
|
+
}[];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
declare function useValidator(value: Value, rules: ValidatorRules): [boolean, Pick<Validity, 'message' | 'errors'>];
|
|
65
|
+
|
|
66
|
+
declare class Field {
|
|
67
|
+
protected rules: ValidatorRules;
|
|
68
|
+
protected required: boolean;
|
|
69
|
+
protected value: Value;
|
|
70
|
+
id: string | number;
|
|
71
|
+
constructor({ rules, required, value, id }: FieldParams);
|
|
72
|
+
validate(): Validity;
|
|
73
|
+
}
|
|
74
|
+
interface ValidatorParams {
|
|
75
|
+
stopAtFirstError: boolean;
|
|
76
|
+
}
|
|
77
|
+
declare class Validator {
|
|
78
|
+
private fields;
|
|
79
|
+
private params;
|
|
80
|
+
constructor(params?: ValidatorParams);
|
|
81
|
+
addField(params: FieldParams): Field;
|
|
82
|
+
removeField(field: Field): void;
|
|
83
|
+
getField(id: Field['id']): Field;
|
|
84
|
+
validate(): Validity;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface RegisteredFieldHandle {
|
|
88
|
+
props: FieldParams;
|
|
89
|
+
validate: () => Validity;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface ComponentProps {
|
|
93
|
+
children?: ReactNode;
|
|
94
|
+
stopAtFirstError?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface ValidatorWrapper {
|
|
97
|
+
validate: () => Validity;
|
|
98
|
+
getField: (id: string | number) => RegisteredFieldHandle | null;
|
|
99
|
+
registerField: (field: RegisteredFieldHandle) => void;
|
|
100
|
+
unregisterField: (field: RegisteredFieldHandle) => void;
|
|
101
|
+
setCustomError: (customError: Validity) => void;
|
|
102
|
+
clearCustomErrors: () => void;
|
|
103
|
+
}
|
|
104
|
+
declare const ValidatorWrapper: react.ForwardRefExoticComponent<ComponentProps & react.RefAttributes<ValidatorWrapper>>;
|
|
105
|
+
|
|
106
|
+
export { type ErrorMessage, type FieldParams, Validator, ValidatorField, type ValidatorRule, ValidatorWrapper, type Validity, rules, useValidator };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,106 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type Value = any;
|
|
5
|
+
type Fn$1 = (validity: Validity, value: Value) => ReactNode;
|
|
6
|
+
declare const ValidatorField: react.ForwardRefExoticComponent<FieldParams & {
|
|
7
|
+
children?: ReactNode | Fn$1;
|
|
8
|
+
} & react.RefAttributes<unknown>>;
|
|
9
|
+
|
|
10
|
+
type Fn = (value: Value) => string;
|
|
11
|
+
interface ValidatorRule {
|
|
12
|
+
rule: (value: Value) => boolean;
|
|
13
|
+
message: string | Fn;
|
|
14
|
+
}
|
|
15
|
+
interface ErrorMessage {
|
|
16
|
+
message: string;
|
|
17
|
+
isValid: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface Validity {
|
|
20
|
+
message: string;
|
|
21
|
+
isValid: boolean;
|
|
22
|
+
errors?: ErrorMessage[];
|
|
23
|
+
id?: string | number;
|
|
24
|
+
}
|
|
25
|
+
interface FieldParams {
|
|
26
|
+
value: Value;
|
|
27
|
+
rules: ValidatorRules;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
id?: string | number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type ValidatorRules = ValidatorRule[];
|
|
33
|
+
declare const rules: {
|
|
34
|
+
notEmpty: {
|
|
35
|
+
rule: (value: string) => boolean;
|
|
36
|
+
message: string;
|
|
37
|
+
}[];
|
|
38
|
+
bool: {
|
|
39
|
+
rule: (value: string) => boolean;
|
|
40
|
+
message: string;
|
|
41
|
+
}[];
|
|
42
|
+
password: {
|
|
43
|
+
rule: (value: string) => boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}[];
|
|
46
|
+
email: {
|
|
47
|
+
rule: (value: string) => boolean;
|
|
48
|
+
message: string;
|
|
49
|
+
}[];
|
|
50
|
+
min: (min: number) => {
|
|
51
|
+
rule: (value: string) => boolean;
|
|
52
|
+
message: string;
|
|
53
|
+
}[];
|
|
54
|
+
max: (max: number) => {
|
|
55
|
+
rule: (value: string) => boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
}[];
|
|
58
|
+
length: (min: number, max?: number) => {
|
|
59
|
+
rule: (value: string) => boolean;
|
|
60
|
+
message: string;
|
|
61
|
+
}[];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
declare function useValidator(value: Value, rules: ValidatorRules): [boolean, Pick<Validity, 'message' | 'errors'>];
|
|
65
|
+
|
|
66
|
+
declare class Field {
|
|
67
|
+
protected rules: ValidatorRules;
|
|
68
|
+
protected required: boolean;
|
|
69
|
+
protected value: Value;
|
|
70
|
+
id: string | number;
|
|
71
|
+
constructor({ rules, required, value, id }: FieldParams);
|
|
72
|
+
validate(): Validity;
|
|
73
|
+
}
|
|
74
|
+
interface ValidatorParams {
|
|
75
|
+
stopAtFirstError: boolean;
|
|
76
|
+
}
|
|
77
|
+
declare class Validator {
|
|
78
|
+
private fields;
|
|
79
|
+
private params;
|
|
80
|
+
constructor(params?: ValidatorParams);
|
|
81
|
+
addField(params: FieldParams): Field;
|
|
82
|
+
removeField(field: Field): void;
|
|
83
|
+
getField(id: Field['id']): Field;
|
|
84
|
+
validate(): Validity;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface RegisteredFieldHandle {
|
|
88
|
+
props: FieldParams;
|
|
89
|
+
validate: () => Validity;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface ComponentProps {
|
|
93
|
+
children?: ReactNode;
|
|
94
|
+
stopAtFirstError?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface ValidatorWrapper {
|
|
97
|
+
validate: () => Validity;
|
|
98
|
+
getField: (id: string | number) => RegisteredFieldHandle | null;
|
|
99
|
+
registerField: (field: RegisteredFieldHandle) => void;
|
|
100
|
+
unregisterField: (field: RegisteredFieldHandle) => void;
|
|
101
|
+
setCustomError: (customError: Validity) => void;
|
|
102
|
+
clearCustomErrors: () => void;
|
|
103
|
+
}
|
|
104
|
+
declare const ValidatorWrapper: react.ForwardRefExoticComponent<ComponentProps & react.RefAttributes<ValidatorWrapper>>;
|
|
105
|
+
|
|
106
|
+
export { type ErrorMessage, type FieldParams, Validator, ValidatorField, type ValidatorRule, ValidatorWrapper, type Validity, rules, useValidator };
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.useValidator = exports.Validator = exports.ValidatorWrapper = exports.ValidatorField = exports.rules = void 0;
|
|
18
|
-
var rules_1 = require("./rules");
|
|
19
|
-
Object.defineProperty(exports, "rules", { enumerable: true, get: function () { return rules_1.rules; } });
|
|
20
|
-
var validator_field_1 = require("./validator-field");
|
|
21
|
-
Object.defineProperty(exports, "ValidatorField", { enumerable: true, get: function () { return validator_field_1.ValidatorField; } });
|
|
22
|
-
var validator_wrapper_1 = require("./validator-wrapper");
|
|
23
|
-
Object.defineProperty(exports, "ValidatorWrapper", { enumerable: true, get: function () { return validator_wrapper_1.ValidatorWrapper; } });
|
|
24
|
-
var validator_1 = require("./validator");
|
|
25
|
-
Object.defineProperty(exports, "Validator", { enumerable: true, get: function () { return validator_1.Validator; } });
|
|
26
|
-
var use_validator_1 = require("./use-validator");
|
|
27
|
-
Object.defineProperty(exports, "useValidator", { enumerable: true, get: function () { return use_validator_1.useValidator; } });
|
|
28
|
-
__exportStar(require("./types"), exports);
|
|
1
|
+
'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var h=/^(([^<>()[\]\\.,;:\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,}))$/,x={notEmpty:[{rule:r=>r!==""&&r.length>0,message:"Value is required"}],bool:[{rule:r=>!!r,message:"Value is required"}],password:[{rule:r=>r.length>0,message:"Password field cannot be empty"},{rule:r=>r.length>5,message:"Password field can not be less than 6 characters"}],email:[{rule:r=>!!r&&r!==""&&r.length!==0,message:"Email is required"},{rule:r=>h.test(String(r).toLowerCase()),message:"Email is invalid"}],min:r=>[{rule:e=>Number.parseFloat(e)>r,message:`The value must be greater than ${r}`}],max:r=>[{rule:e=>Number.parseFloat(e)<r,message:`The value must be smaller ${r}`}],length:(r,e)=>[{rule:t=>String(t).length>=r,message:`No less than ${r} symbols`},{rule:t=>e!==void 0?String(t).length<=e:true,message:`No more than ${e} symbols`}]};var V=class{rules;required;value;id;constructor({rules:e,required:t,value:s,id:i}){this.rules=e,this.required=t,this.value=s,this.id=i;}validate(){let e=true,t="",{rules:s,value:i,required:d,id:u}=this,n=!i&&Number.parseFloat(i)!==0;if(!s.length||n&&d===false)return {isValid:e,message:t,id:u};for(let a of s)e&&(e=a.rule(i),e||(typeof a.message=="function"?t=a.message(i):t=a.message));return {isValid:e,message:t,id:u}}},c=class{fields;params;constructor(e){this.params=e||null,this.fields=[];}addField(e){let t=new V(e);return this.fields.push(t),t}removeField(e){let t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1);}getField(e){return this.fields.find(t=>t.id===e)||null}validate(){let e,s=this.fields.map(i=>this.params?.stopAtFirstError&&e&&e.isValid===false?null:(e=i.validate(),e)).filter(i=>i&&i.isValid===false);if(s.length){let{isValid:i,message:d}=s[0];return {isValid:i,message:d,errors:s}}return {isValid:true,message:""}}};function b(r,e){let t=new c;t.addField({value:r,rules:e});let{isValid:s,...i}=t.validate();return [s,i]}var v=react.createContext(null);var w=react.forwardRef(function(e,t){let{children:s,value:i}=e,{customErrors:d,registerField:u,unregisterField:n}=react.useContext(v),a=react.useRef(e);a.current=e;let g=react.useRef(d);g.current=d;let p=react.useRef(null);p.current||(p.current={get props(){return a.current},validate:()=>{let m=a.current,y=g.current.find(o=>o.id===m.id);return y||new V({rules:m.rules,required:m.required,value:m.value,id:m.id}).validate()}}),react.useEffect(()=>(u(p.current),()=>{n(p.current);}),[u,n]);let F=p.current.validate();return typeof s=="function"?s(F,i):s});var S=react.forwardRef(function({children:e,stopAtFirstError:t},s){let i=react.useRef([]),[d,u]=react.useState([]),n=react.useCallback(l=>{l&&!i.current.includes(l)&&i.current.push(l);},[]),a=react.useCallback(l=>{let o=i.current.indexOf(l);o>-1&&i.current.splice(o,1);},[]),g=react.useCallback(l=>i.current.find(o=>o?.props?.id===l)||null,[]),p=react.useCallback(l=>{u(o=>[...o,l]);},[]),F=react.useCallback(()=>{u([]);},[]),m=react.useCallback(()=>{let l=new c({stopAtFirstError:t});for(let o of i.current)l.addField(o.props);return l.validate()},[t]);react.useImperativeHandle(s,()=>({validate:m,getField:g,registerField:n,unregisterField:a,setCustomError:p,clearCustomErrors:F}),[m,g,n,a,p,F]);let y=react.useMemo(()=>({customErrors:d,registerField:n,unregisterField:a}),[d,n,a]);return jsxRuntime.jsx(v.Provider,{value:y,children:e})});exports.Validator=c;exports.ValidatorField=w;exports.ValidatorWrapper=S;exports.rules=x;exports.useValidator=b;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|