@monkvision/common 4.2.9 → 4.3.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/HOOKS.md CHANGED
@@ -83,6 +83,45 @@ function TestComponent() {
83
83
  This custom hook creates an interval that calls the provided callback every `delay` milliseconds. If `delay` is `null`
84
84
  or less than 0, the callback will not be called.
85
85
 
86
+ ### useForm
87
+
88
+ ```tsx
89
+ import { useTranslation } from 'react-i18next';
90
+ import { useForm, required, email } from '@monkvision/common';
91
+ import { Button, TextField } from '@monkvision/common-ui-web';
92
+
93
+ function TestComponent() {
94
+ const { t } = useTranslation();
95
+ const form = useForm({
96
+ initialValues: {
97
+ email: '',
98
+ },
99
+ validate: {
100
+ email,
101
+ },
102
+ });
103
+
104
+ return (
105
+ <form onSubmit={() => console.log('Submit')}>
106
+ <label htmlFor='email'>Email</label>
107
+ <TextField
108
+ id='email'
109
+ focusColor={form.isInputErrorDisplayed('email') ? 'alert-base' : 'primary-base'}
110
+ assistiveText={
111
+ form.isInputErrorDisplayed('email')
112
+ ? t(`form.errors.${form.getInputError('email')}`)
113
+ : undefined
114
+ }
115
+ highlighted={form.isInputErrorDisplayed('email')}
116
+ {...form.getInputProps('email')}
117
+ />
118
+ <Button type='submit'>Confirm</Button>
119
+ </form>
120
+ );
121
+ }
122
+ ```
123
+ Custom hook used to manage forms in ReactJs.
124
+
86
125
  ### useLangProp
87
126
  ```tsx
88
127
  import { useLangProp } from '@monkvision/common';
@@ -137,6 +137,48 @@ Returns the value of a given environment variable. If the value does not exist,
137
137
 
138
138
  ---
139
139
 
140
+ # Form Validation Utils
141
+ ### mergeValidationFunctions
142
+ ```typescript
143
+ import { mergeValidationFunctions } from '@monkvision/common';
144
+
145
+ const merged = mergeValidationFunctions(
146
+ (value: any) => typeof value === 'string' && value.length > 3 ? null : 'too-short',
147
+ (value: any) => typeof value === 'string' && value.length < 3 ? null : 'too-long',
148
+ );
149
+ console.log(merged('ab')); // Output : 'too-short'
150
+ console.log(merged('abcd')); // Output : 'too-long'
151
+ console.log(merged(123)); // Output : 'too-short'
152
+ console.log(merged('abc')); // Output : null
153
+ ```
154
+ Util function used to merge multiple validation functions into a single one. The first error discovered will be
155
+ returned.
156
+
157
+ ### required
158
+ ```typescript
159
+ import { required } from '@monkvision/common';
160
+
161
+ console.log(required('')); // Output : 'required'
162
+ console.log(required(null)); // Output : 'required'
163
+ console.log(required(12)); // Output : null
164
+ console.log(merged('abc')); // Output : null
165
+ console.log(merged(false)); // Output : null
166
+ ```
167
+ Validation function for required fields.
168
+
169
+ ### email
170
+ ```typescript
171
+ import { email } from '@monkvision/common';
172
+
173
+ console.log(email('')); // Output : 'required'
174
+ console.log(email('abc')); // Output : 'emailNotValid'
175
+ console.log(email(123)); // Output : 'emailNotValid'
176
+ console.log(email('test@acvauctions.com')); // Output : null'
177
+ ```
178
+ Validation function for valid email fields.
179
+
180
+ ---
181
+
140
182
  # Mimetype Utils
141
183
  ### MIMETYPE_FILE_EXTENSIONS
142
184
  ```typescript
@@ -10,3 +10,4 @@ export * from './useSearchParams';
10
10
  export * from './useInterval';
11
11
  export * from './useAsyncInterval';
12
12
  export * from './useObjectMemo';
13
+ export * from './useForm';
@@ -26,3 +26,4 @@ __exportStar(require("./useSearchParams"), exports);
26
26
  __exportStar(require("./useInterval"), exports);
27
27
  __exportStar(require("./useAsyncInterval"), exports);
28
28
  __exportStar(require("./useObjectMemo"), exports);
29
+ __exportStar(require("./useForm"), exports);
@@ -0,0 +1,63 @@
1
+ import { FormValidationFunction } from '../utils';
2
+ /**
3
+ * Base type definition for form initial values.
4
+ */
5
+ export type FormValuesBaseType = Record<string, any>;
6
+ /**
7
+ * Type definitions for the input properties that needs to be passed to a form input.
8
+ */
9
+ export interface FormInputProps<T extends FormValuesBaseType> {
10
+ value: T[keyof T];
11
+ onChange: (value: T[keyof T]) => void;
12
+ onBlur: () => void;
13
+ }
14
+ /**
15
+ * Options used to set up a form using the `useForm` hook.
16
+ */
17
+ export interface FormOptions<T extends FormValuesBaseType> {
18
+ /**
19
+ * Initial values of the form. This property is used to set the global shape of the form.
20
+ */
21
+ initialValues: T;
22
+ /**
23
+ * Optional validation functions used to validate the form fields.
24
+ */
25
+ validate?: {
26
+ [Key in keyof T]?: FormValidationFunction<T[Key]>;
27
+ };
28
+ }
29
+ /**
30
+ * Form handler used to manage a form using the `useForm` hook.
31
+ */
32
+ export interface Form<T extends FormValuesBaseType> {
33
+ /**
34
+ * Function used to get the value of a form input.
35
+ */
36
+ getInputValue: (name: keyof T) => T[keyof T];
37
+ /**
38
+ * Function used to get the pass through props of a form input.
39
+ */
40
+ getInputProps: (name: keyof T) => FormInputProps<T>;
41
+ /**
42
+ * Function indicating if the form is valid or not (i.e. every input in the form is valid).
43
+ */
44
+ isValid: () => boolean;
45
+ /**
46
+ * Function that returns the validation error of the given form input.
47
+ */
48
+ getInputError: (name: keyof T) => string | null;
49
+ /**
50
+ * Function indicating if the error message under a form input should be displayed or not.
51
+ */
52
+ isInputErrorDisplayed: (name: keyof T) => boolean;
53
+ /**
54
+ * Function indicating if a form input has been touched or is dirty.
55
+ */
56
+ isInputTouchedOrDirty: (name: keyof T) => boolean;
57
+ }
58
+ /**
59
+ * Custom hook used to manage forms in ReactJs. Please refer to
60
+ * [the official documentation](https://github.com/monkvision/monkjs/blob/main/packages/common/README/HOOKS.md) for more
61
+ * details on how to use this hook.
62
+ */
63
+ export declare function useForm<T extends FormValuesBaseType = FormValuesBaseType>({ initialValues, validate, }: FormOptions<T>): Form<T>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.useForm = void 0;
15
+ var react_1 = require("react");
16
+ var useObjectMemo_1 = require("./useObjectMemo");
17
+ function mapFormValues(values, val) {
18
+ return Object.keys(values).reduce(function (prev, curr) {
19
+ var _a;
20
+ return (__assign(__assign({}, prev), (_a = {}, _a[curr] = val, _a)));
21
+ }, {});
22
+ }
23
+ /**
24
+ * Custom hook used to manage forms in ReactJs. Please refer to
25
+ * [the official documentation](https://github.com/monkvision/monkjs/blob/main/packages/common/README/HOOKS.md) for more
26
+ * details on how to use this hook.
27
+ */
28
+ function useForm(_a) {
29
+ var initialValues = _a.initialValues, validate = _a.validate;
30
+ var _b = (0, react_1.useState)(initialValues), values = _b[0], setValues = _b[1];
31
+ var _c = (0, react_1.useState)(mapFormValues(initialValues, false)), touchedInputs = _c[0], setTouchedInputs = _c[1];
32
+ var touch = (0, react_1.useCallback)(function (name) {
33
+ setTouchedInputs(function (previousValues) {
34
+ var _a;
35
+ return (__assign(__assign({}, previousValues), (_a = {}, _a[name] = true, _a)));
36
+ });
37
+ }, []);
38
+ var getInputValue = (0, react_1.useCallback)(function (name) { return values[name]; }, [values]);
39
+ var getInputProps = (0, react_1.useCallback)(function (name) { return ({
40
+ value: values[name],
41
+ onChange: function (value) {
42
+ setValues(function (previousValues) {
43
+ var _a;
44
+ return (__assign(__assign({}, previousValues), (_a = {}, _a[name] = value, _a)));
45
+ });
46
+ touch(name);
47
+ },
48
+ onBlur: function () {
49
+ touch(name);
50
+ },
51
+ }); }, [values, touch]);
52
+ var getInputError = (0, react_1.useCallback)(function (name) { var _a, _b; return (_b = (_a = validate === null || validate === void 0 ? void 0 : validate[name]) === null || _a === void 0 ? void 0 : _a.call(validate, values[name])) !== null && _b !== void 0 ? _b : null; }, [validate, values]);
53
+ var isValid = (0, react_1.useCallback)(function () { return Object.keys(initialValues).every(function (name) { return getInputError(name) === null; }); }, [initialValues, getInputError]);
54
+ var isInputTouchedOrDirty = (0, react_1.useCallback)(function (name) { return touchedInputs[name] || values[name] !== initialValues[name]; }, [touchedInputs, values, initialValues]);
55
+ var isInputErrorDisplayed = (0, react_1.useCallback)(function (name) { return isInputTouchedOrDirty(name) && !!getInputError(name); }, [isInputTouchedOrDirty, getInputError]);
56
+ return (0, useObjectMemo_1.useObjectMemo)({
57
+ getInputValue: getInputValue,
58
+ getInputProps: getInputProps,
59
+ isValid: isValid,
60
+ getInputError: getInputError,
61
+ isInputErrorDisplayed: isInputErrorDisplayed,
62
+ isInputTouchedOrDirty: isInputTouchedOrDirty,
63
+ });
64
+ }
65
+ exports.useForm = useForm;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Basic type definition for a form validation function that can be used with the `useForm` hook.
3
+ */
4
+ export type FormValidationFunction<K> = (value: K) => string | null;
5
+ /**
6
+ * Basic form validation errors returned by avaliable validation functions in the SDK.
7
+ */
8
+ export declare enum BasicValidationErrors {
9
+ /**
10
+ * Error returned when the field is required by no value has been passed.
11
+ */
12
+ REQUIRED = "required",
13
+ /**
14
+ * Error returned when the value is not a valid email.
15
+ */
16
+ EMAIL_NOT_VALID = "emailNotValid"
17
+ }
18
+ /**
19
+ * Util function used to merge multiple validation functions into a single one. The first error discovered will be
20
+ * returned.
21
+ */
22
+ export declare function mergeValidationFunctions<K>(...validateFunctions: FormValidationFunction<K>[]): FormValidationFunction<K>;
23
+ /**
24
+ * Validation function for required fields.
25
+ */
26
+ export declare function required(value: any): string | null;
27
+ /**
28
+ * Validation function for valid email fields.
29
+ */
30
+ export declare function email(value: any): string | null;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.email = exports.required = exports.mergeValidationFunctions = exports.BasicValidationErrors = void 0;
4
+ var EMAIL_REGEX = /^((?!\.)[\w\-_.]*[^.])(@\w+)(\.\w+(\.\w+)?[^.\W])$/;
5
+ /**
6
+ * Basic form validation errors returned by avaliable validation functions in the SDK.
7
+ */
8
+ var BasicValidationErrors;
9
+ (function (BasicValidationErrors) {
10
+ /**
11
+ * Error returned when the field is required by no value has been passed.
12
+ */
13
+ BasicValidationErrors["REQUIRED"] = "required";
14
+ /**
15
+ * Error returned when the value is not a valid email.
16
+ */
17
+ BasicValidationErrors["EMAIL_NOT_VALID"] = "emailNotValid";
18
+ })(BasicValidationErrors = exports.BasicValidationErrors || (exports.BasicValidationErrors = {}));
19
+ /**
20
+ * Util function used to merge multiple validation functions into a single one. The first error discovered will be
21
+ * returned.
22
+ */
23
+ function mergeValidationFunctions() {
24
+ var validateFunctions = [];
25
+ for (var _i = 0; _i < arguments.length; _i++) {
26
+ validateFunctions[_i] = arguments[_i];
27
+ }
28
+ return function (value) {
29
+ for (var i = 0; i < validateFunctions.length; i++) {
30
+ var error = validateFunctions[i](value);
31
+ if (error) {
32
+ return error;
33
+ }
34
+ }
35
+ return null;
36
+ };
37
+ }
38
+ exports.mergeValidationFunctions = mergeValidationFunctions;
39
+ /**
40
+ * Validation function for required fields.
41
+ */
42
+ function required(value) {
43
+ return value !== null && value !== undefined && value !== ''
44
+ ? null
45
+ : BasicValidationErrors.REQUIRED;
46
+ }
47
+ exports.required = required;
48
+ /**
49
+ * Validation function for valid email fields.
50
+ */
51
+ function email(value) {
52
+ var error = required(value);
53
+ if (error) {
54
+ return error;
55
+ }
56
+ return typeof value === 'string' && value.match(EMAIL_REGEX) !== null
57
+ ? null
58
+ : BasicValidationErrors.EMAIL_NOT_VALID;
59
+ }
60
+ exports.email = email;
@@ -8,3 +8,4 @@ export * from './browser.utils';
8
8
  export * from './env.utils';
9
9
  export * from './state.utils';
10
10
  export * from './config.utils';
11
+ export * from './formValidation.utils';
@@ -24,3 +24,4 @@ __exportStar(require("./browser.utils"), exports);
24
24
  __exportStar(require("./env.utils"), exports);
25
25
  __exportStar(require("./state.utils"), exports);
26
26
  __exportStar(require("./config.utils"), exports);
27
+ __exportStar(require("./formValidation.utils"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monkvision/common",
3
- "version": "4.2.9",
3
+ "version": "4.3.0",
4
4
  "license": "BSD-3-Clause-Clear",
5
5
  "packageManager": "yarn@3.2.4",
6
6
  "description": "MonkJs common logic package",
@@ -28,10 +28,10 @@
28
28
  "lint:fix": "yarn run prettier:fix && yarn run eslint:fix"
29
29
  },
30
30
  "dependencies": {
31
- "@monkvision/analytics": "4.2.9",
32
- "@monkvision/monitoring": "4.2.9",
33
- "@monkvision/sights": "4.2.9",
34
- "@monkvision/types": "4.2.9",
31
+ "@monkvision/analytics": "4.3.0",
32
+ "@monkvision/monitoring": "4.3.0",
33
+ "@monkvision/sights": "4.3.0",
34
+ "@monkvision/types": "4.3.0",
35
35
  "i18next": "^23.4.5",
36
36
  "jsonwebtoken": "^9.0.2",
37
37
  "jwt-decode": "^4.0.0",
@@ -47,13 +47,13 @@
47
47
  "react-router-dom": "^6.22.3"
48
48
  },
49
49
  "devDependencies": {
50
- "@monkvision/eslint-config-base": "4.2.9",
51
- "@monkvision/eslint-config-typescript": "4.2.9",
52
- "@monkvision/eslint-config-typescript-react": "4.2.9",
53
- "@monkvision/jest-config": "4.2.9",
54
- "@monkvision/prettier-config": "4.2.9",
55
- "@monkvision/test-utils": "4.2.9",
56
- "@monkvision/typescript-config": "4.2.9",
50
+ "@monkvision/eslint-config-base": "4.3.0",
51
+ "@monkvision/eslint-config-typescript": "4.3.0",
52
+ "@monkvision/eslint-config-typescript-react": "4.3.0",
53
+ "@monkvision/jest-config": "4.3.0",
54
+ "@monkvision/prettier-config": "4.3.0",
55
+ "@monkvision/test-utils": "4.3.0",
56
+ "@monkvision/typescript-config": "4.3.0",
57
57
  "@testing-library/react": "^12.1.5",
58
58
  "@testing-library/react-hooks": "^8.0.1",
59
59
  "@types/jest": "^29.2.2",
@@ -96,5 +96,5 @@
96
96
  "url": "https://github.com/monkvision/monkjs/issues"
97
97
  },
98
98
  "homepage": "https://github.com/monkvision/monkjs",
99
- "gitHead": "7454a8e35d2722a1c88c65d5aea1a302d559b161"
99
+ "gitHead": "afd80da7a5eaa1c16fd1f81e9b889d960f1b0c26"
100
100
  }