Skip to content

Commit 174932f

Browse files
Merge pull request #118 from Enterwell/stage
Stage
2 parents 7d26b2e + f860d5e commit 174932f

File tree

12 files changed

+220
-2683
lines changed

12 files changed

+220
-2683
lines changed

.babelrc

Lines changed: 0 additions & 13 deletions
This file was deleted.

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
buildAndTest:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: actions/checkout@v2
19-
- uses: actions/setup-node@v1
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-node@v4
2020
with:
21-
node-version: 16
21+
node-version: 18
2222
- run: yarn install
2323
- run: yarn build
2424
- run: yarn test

.github/workflows/npm-publish.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414
buildAndPublish:
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/checkout@v2
18-
- uses: actions/setup-node@v1
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-node@v4
1919
with:
20-
node-version: 16
20+
node-version: 18
2121
registry-url: "https://registry.npmjs.org"
2222
- run: yarn install
2323
- run: yarn build

.github/workflows/version-check.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: "Checkout repository"
13-
uses: actions/checkout@v2
13+
uses: actions/checkout@v4
1414
with:
1515
fetch-depth: 0
1616

@@ -38,7 +38,7 @@ jobs:
3838
3939
- name: add-comment
4040
if: ${{ steps.versions-comparison.outputs.version-valid == 0 }}
41-
uses: peter-evans/create-or-update-comment@v2
41+
uses: peter-evans/create-or-update-comment@v3
4242
with:
4343
issue-number: ${{ github.event.pull_request.number }}
4444
body: |

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.0] - 2023-12-19
9+
10+
### Added
11+
12+
- `isValidIpAddress` validation function
13+
14+
### Changed
15+
16+
- Updated Node from 16 to 18
17+
- Replaced babel with vite
18+
19+
### Fixed
20+
21+
- Fixed some typescript type and documentation
22+
823
## [1.3.0] - 2023-11-07
924

1025
### Added

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ Step 2:
5959
<div>
6060
<input
6161
className={email.error ? 'error' : 'no-error'}
62-
value={email.value}
63-
onChange={email.onChange}
64-
onBlur={email.onBlur}
62+
{...email.props} // This is shorthand for passing the `value`, `onChange` and `onBlur` properties
6563
/>
6664
{email.error && (
6765
<span className="error-message">Incorrect email!</span>
@@ -83,13 +81,13 @@ Hook that keeps on form field's data.
8381
| ---- | ---- | ---- | ----------- |
8482
| initialValue | _any_ | yes | Field's initial value |
8583
| validationFn | _(any) => boolean or Promise&lt;boolean&gt;_ | yes | Function for validating the field's value |
86-
| config | _{<br>&nbsp;&nbsp;&nbsp;receiveEvent: boolean,<br>&nbsp;&nbsp;&nbsp;reversed: boolean<br>&nbsp;&nbsp;&nbsp;ignoreDirtiness: boolean<br>}_ | no | Additional hook configuration.<br><br><ul><li>`receiveEvent` inidicates whether `onChange` callback will receive whole event or just target's value</li><li>`reversed` indicates whether reversed error logic should be applied (error being `false` when present, instead of `true`)</li><li>`ignoreDirtiness` indicating whether field's dirtiness should be ignored (by default, field is validate on blur, but only if field is dirty ie. if its value has been changed)</li></ul>|
84+
| config | _{<br>&nbsp;&nbsp;&nbsp;receiveEvent?: boolean,<br>&nbsp;&nbsp;&nbsp;reversed?: boolean<br>&nbsp;&nbsp;&nbsp;ignoreDirtiness?: boolean<br>}_ | no | Additional hook configuration.<br><br><ul><li>`receiveEvent` inidicates whether `onChange` callback will receive whole event or just target's value</li><li>`reversed` indicates whether reversed error logic should be applied (error being `false` when present, instead of `true`)</li><li>`ignoreDirtiness` indicating whether field's dirtiness should be ignored (by default, field is validate on blur, but only if field is dirty ie. if its value has been changed)</li></ul>|
8785

8886
#### Returns
8987

9088
| Type <div style="width: 200px"></div> | Description |
9189
|---- | ----------- |
92-
| _{<br>&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;error: boolean<br>&nbsp;&nbsp;&nbsp;onChange: (any, config) => void<br>&nbsp;&nbsp;&nbsp;onBlur: (event, config) => void<br>&nbsp;&nbsp;&nbsp;setValue: (value: any) => void<br>&nbsp;&nbsp;&nbsp;validate: (any, config) => boolean or Promise&lt;boolean&gt;<br>&nbsp;&nbsp;&nbsp;reset: () => void,<br>&nbsp;&nbsp;&nbsp;props: {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onChange: (any, config) => void<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onBlur: (event, config) => void<br>&nbsp;&nbsp;&nbsp;}<br>}_ | Object with field's data and callbacks.<br><br><ul><li>`value` - field's current value</li><li>`error` - is error present flag (`true` if value was validated and didn't pass validation, `false` otherwise)</li><li>`onChange` - callback for change event (change's the value and validates it if previous value wasn't correct)</li><li>`onBlur` - callback for blur event (validates the value)</li><li>`validate` - function for validating field's value</li><li>`reset` - function for resetting field's data</li><li>`props` - set of props that can be spread on standard input elements (same as props in root object, just grouped for better DX)</li></ul><br/>`onChange`, `onBlur` and `validate` functions accept config as last parameter - this will override config from `useValidation` if provided. |
90+
| _{<br>&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;error: boolean<br>&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;setValue: (value: any) => void<br>&nbsp;&nbsp;&nbsp;validate: (any, config?) => boolean or Promise&lt;boolean&gt;<br>&nbsp;&nbsp;&nbsp;reset: () => void,<br>&nbsp;&nbsp;&nbsp;props: {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;}<br>}_ | Object with field's data and callbacks.<br><br><ul><li>`value` - field's current value</li><li>`error` - is error present flag (`true` if value was validated and didn't pass validation, `false` otherwise)</li><li>`onChange` - callback for change event (changes the value and validates it if previous value wasn't correct)</li><li>`onBlur` - callback for blur event (validates the value)</li><li>`setValue` - function for setting the internal value (does not validate the input, enabling support for async data loading)</li><li>`validate` - function for validating field's value</li><li>`reset` - function for resetting field's data</li><li>`props` - set of props that can be spread on standard input elements (same as props in root object, just grouped for better DX)</li></ul><br/>`onChange`, `onBlur` and `validate` functions accept config as last parameter - this will override config from `useValidation` if provided. |
9391

9492
#### Usage example
9593

@@ -221,7 +219,7 @@ Util function for handling the form submit. Form's fields are first validated. I
221219
| Name | Type <div style="width: 200px"></div> | Required | Description |
222220
| ---- | ---- | ---- | ----------- |
223221
| fields | _{<br/>&nbsp;&nbsp;key: {<br>&nbsp;&nbsp;&nbsp;&nbsp;value: any<br>&nbsp;&nbsp;&nbsp;&nbsp;validate: (any) => boolean<br>&nbsp;&nbsp;},<br/>&nbsp;&nbsp;...<br/>}_ | yes | Form field's data (each field must have `value` and `validate` properties - other properties are not important) |
224-
| onSubmit | _(any) => void_ | yes | On submit callback |
222+
| onSubmit | _(any) => object or void_ | yes | On submit callback |
225223

226224
#### Returns
227225

@@ -334,6 +332,10 @@ Is non-empty array validation. Value of the field with this validation function
334332

335333
Is valid email validation. Value od the field with this validation function will be correct if it is non-empty string with valid email address.
336334

335+
### `isValidIpAddress(value)`
336+
337+
Is valid IP address validation. Value od the field with this validation function will be correct if it is a non-empty string with valid IPv4 or IPv6 address.
338+
337339
## Future plans
338340

339341
We noticed that there are few things which could be added to our package in order to make it more flexible and easy to use. Here is what you can expect in the future:

package.json

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enterwell/react-form-validation",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "Form validation functionality for React components",
55
"license": "MIT",
66
"repository": {
@@ -13,10 +13,10 @@
1313
"url": "https://enterwell.net"
1414
},
1515
"engines": {
16-
"node": ">=16"
16+
"node": ">=18"
1717
},
1818
"scripts": {
19-
"build": "babel src/ -d dist",
19+
"build": "vite build",
2020
"test": "cross-env NODE_ENV=test cypress run --component",
2121
"test:open": "cross-env NODE_ENV=test cypress open"
2222
},
@@ -34,22 +34,14 @@
3434
],
3535
"dependencies": {},
3636
"devDependencies": {
37-
"@babel/cli": "7.23.0",
38-
"@babel/core": "7.23.0",
39-
"@babel/preset-env": "7.22.20",
40-
"@babel/preset-react": "7.22.15",
41-
"@cypress/code-coverage": "3.12.1",
4237
"@cypress/react18": "^2.0.0",
4338
"@types/react-dom": "18",
4439
"@vitejs/plugin-react": "^4.1.0",
45-
"babel-loader": "9.1.3",
46-
"babel-plugin-istanbul": "6.1.1",
4740
"cross-env": "7.0.3",
48-
"cypress": "13.3.0",
41+
"cypress": "13.6.0",
4942
"react": "^18",
5043
"react-dom": "^18",
51-
"vite": "4.4.9",
52-
"webpack": "^5.89.0"
44+
"vite": "4.5.0"
5345
},
5446
"peerDependencies": {
5547
"react": "^16.13.1 || ^17 || ^18",

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ export {
1919
isPositiveNumber,
2020
isNegativeNumber,
2121
isNonEmptyArray,
22-
isValidEmail
22+
isValidEmail,
23+
isValidIpAddress
2324
} from './validationFunctions';

src/validationFunctions.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,24 @@ const emailRegex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'
8282
* @returns {boolean} true if value is valid email address (RFC 5322), false otherwise
8383
*/
8484
export const isValidEmail = (v) => isNonEmptyString(v) && emailRegex.test(v);
85+
86+
/**
87+
* Checks if the value is a valid IPv4 or IPv6 address.
88+
*
89+
* @param {any} v Value
90+
* @returns {boolean} true if the value is a valid IPv4 or IPv6 address, false otherwise
91+
*/
92+
export const isValidIpAddress = (v) => {
93+
const ipv4RegExp = /^(\d{1,3}\.){3}\d{1,3}$/;
94+
const ipv6RegExp = /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i;
95+
96+
if (ipv4RegExp.test(v)) {
97+
return v.split('.').every((part) => parseInt(part) <= 255);
98+
}
99+
100+
if (ipv6RegExp.test(v)) {
101+
return v.split(':').every((part) => part.length <= 4);
102+
}
103+
104+
return false;
105+
}

types/index.d.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
export declare interface FieldConfig {
2-
receiveEvent: boolean,
3-
reversed: boolean,
4-
ignoreDirtiness: boolean
2+
receiveEvent?: boolean,
3+
reversed?: boolean,
4+
ignoreDirtiness?: boolean
55
}
66

77
export declare interface Field {
88
value: any,
99
error: boolean,
10-
onChange: (v: any, config: FieldConfig) => void,
11-
onBlur: (event: any, config: FieldConfig) => void,
12-
validate: (v: any, config: FieldConfig) => boolean | Promise<boolean>,
10+
setValue: (v: any) => void,
11+
onChange: (v: any, config?: FieldConfig) => void,
12+
onBlur: (event: any, config?: FieldConfig) => void,
13+
validate: (v: any, config?: FieldConfig) => boolean | Promise<boolean>,
1314
reset: () => void,
1415
props: {
1516
value: Field['value'],
@@ -22,7 +23,7 @@ export declare interface Fields {
2223
[key: string]: Field
2324
}
2425

25-
export declare function useValidation(initialValue: any, validationFn: (() => boolean) | (() => Promise<boolean>), config: FieldConfig): Field;
26+
export declare function useValidation(initialValue: any, validationFn: ((v: any) => boolean) | ((v: any) => Promise<boolean>), config?: FieldConfig): Field;
2627

2728
export declare function extractValues(fields: Fields): object;
2829

@@ -32,7 +33,7 @@ export declare function validateFields(fields: Fields): boolean | Promise<boolea
3233

3334
export declare function resetFields(fields: Fields): void;
3435

35-
export declare function submitForm(fields: Fields, onSubmit: (values: object) => object): Promise<object> | object | undefined;
36+
export declare function submitForm(fields: Fields, onSubmit: (values: object) => object | void): Promise<object> | object | undefined;
3637

3738
export declare function cancelForm(fields: Fields, onCancel: () => void): void;
3839

@@ -55,3 +56,5 @@ export declare function isNegativeNumber(v: any): boolean;
5556
export declare function isNonEmptyArray(v: any): boolean;
5657

5758
export declare function isValidEmail(v: any): boolean;
59+
60+
export declare function isValidIpAddress(v: any): boolean;

0 commit comments

Comments
 (0)