@paragrav/rhf-utils 0.0.17 → 0.0.19
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/dist/cjs/errors/flattenFieldErrors.d.ts +14 -0
- package/dist/cjs/errors/flattenFieldErrors.js +16 -0
- package/dist/cjs/errors/getFlatFieldErrors.d.ts +16 -0
- package/dist/cjs/errors/getFlatFieldErrors.js +40 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.d.ts +10 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.js +15 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.spec.d.ts +1 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.spec.js +15 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.utils.d.ts +6 -0
- package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.utils.js +11 -0
- package/dist/cjs/errors/nonfield/utils.d.ts +17 -0
- package/dist/cjs/errors/nonfield/utils.js +20 -0
- package/dist/cjs/errors/orphans/useFormErrorsHasOnlyOrphan.d.ts +2 -0
- package/dist/cjs/errors/orphans/useFormErrorsHasOnlyOrphan.js +21 -0
- package/dist/cjs/errors/orphans/useFormOrphanErrors.d.ts +1 -6
- package/dist/cjs/errors/orphans/useFormOrphanErrors.js +5 -8
- package/dist/cjs/errors/orphans/utils.d.ts +2 -2
- package/dist/cjs/errors/orphans/utils.js +18 -17
- package/dist/cjs/errors/root/useFormRootFieldErrors.d.ts +6 -0
- package/dist/cjs/errors/{roots → root}/useFormRootFieldErrors.js +5 -1
- package/dist/cjs/errors/{roots → root}/utils.d.ts +5 -1
- package/dist/cjs/errors/root/utils.js +24 -0
- package/dist/cjs/errors/useFormContextErrorsIfAny.d.ts +6 -0
- package/dist/cjs/errors/useFormContextErrorsIfAny.js +13 -0
- package/dist/cjs/errors/useFormErrorConsoleDebug.d.ts +8 -0
- package/dist/cjs/errors/useFormErrorConsoleDebug.js +22 -0
- package/dist/cjs/main.d.ts +4 -2
- package/dist/cjs/main.js +8 -5
- package/dist/cjs/utils.d.ts +1 -0
- package/dist/cjs/utils.js +5 -0
- package/dist/esm/errors/flattenFieldErrors.mjs +5 -0
- package/dist/esm/errors/getFlatFieldErrors.mjs +21 -0
- package/dist/esm/errors/nonfield/FormNonFieldErrorMarker.mjs +19 -0
- package/dist/esm/errors/nonfield/FormNonFieldErrorMarker.utils.mjs +6 -0
- package/dist/esm/errors/nonfield/utils.mjs +4 -0
- package/dist/esm/errors/orphans/useFormOrphanErrors.mjs +8 -7
- package/dist/esm/errors/orphans/utils.mjs +15 -13
- package/dist/esm/errors/{roots → root}/useFormRootFieldErrors.mjs +1 -1
- package/dist/esm/errors/root/utils.mjs +11 -0
- package/dist/esm/errors/useFormContextErrorsIfAny.mjs +9 -0
- package/dist/esm/errors/useFormErrorConsoleDebug.mjs +8 -0
- package/dist/esm/main.mjs +16 -13
- package/dist/esm/utils.mjs +4 -0
- package/dist/types/errors/flattenFieldErrors.d.ts +15 -0
- package/dist/types/errors/getFlatFieldErrors.d.ts +17 -0
- package/dist/types/errors/nonfield/FormNonFieldErrorMarker.d.ts +10 -0
- package/dist/types/errors/nonfield/FormNonFieldErrorMarker.spec.d.ts +1 -0
- package/dist/types/errors/nonfield/FormNonFieldErrorMarker.utils.d.ts +6 -0
- package/dist/types/errors/nonfield/utils.d.ts +18 -0
- package/dist/types/errors/orphans/useFormErrorsHasOnlyOrphan.d.ts +2 -0
- package/dist/types/errors/orphans/useFormOrphanErrors.d.ts +1 -6
- package/dist/types/errors/orphans/utils.d.ts +2 -2
- package/dist/types/errors/root/useFormRootFieldErrors.d.ts +6 -0
- package/dist/types/errors/{roots → root}/utils.d.ts +5 -1
- package/dist/types/errors/useFormContextErrorsIfAny.d.ts +6 -0
- package/dist/types/errors/useFormErrorConsoleDebug.d.ts +8 -0
- package/dist/types/main.d.ts +4 -2
- package/dist/types/utils.d.ts +1 -0
- package/package.json +9 -5
- package/dist/cjs/errors/orphans/FormErrorNonFieldMarker.d.ts +0 -14
- package/dist/cjs/errors/orphans/FormErrorNonFieldMarker.js +0 -20
- package/dist/cjs/errors/roots/useFormRootFieldErrors.d.ts +0 -2
- package/dist/cjs/errors/roots/utils.js +0 -13
- package/dist/cjs/errors/utils.d.ts +0 -9
- package/dist/cjs/errors/utils.js +0 -65
- package/dist/esm/errors/orphans/FormErrorNonFieldMarker.mjs +0 -19
- package/dist/esm/errors/roots/utils.mjs +0 -6
- package/dist/esm/errors/utils.mjs +0 -14
- package/dist/esm/node_modules/flat/index.mjs +0 -22
- package/dist/types/errors/orphans/FormErrorNonFieldMarker.d.ts +0 -14
- package/dist/types/errors/roots/useFormRootFieldErrors.d.ts +0 -2
- package/dist/types/errors/utils.d.ts +0 -10
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FieldErrors } from 'react-hook-form';
|
|
2
|
+
/**
|
|
3
|
+
* Only flattens a {@link FieldErrors} object.
|
|
4
|
+
* @returns e.g.,
|
|
5
|
+
* ```
|
|
6
|
+
* {
|
|
7
|
+
* "address.street.type": "too_short",
|
|
8
|
+
* "address.street.ref.value": "123",
|
|
9
|
+
* "address.street.message": "Required."
|
|
10
|
+
* }
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
declare const flattenFieldErrors: (errors: FieldErrors) => Record<string, unknown>;
|
|
14
|
+
export default flattenFieldErrors;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const flat_1 = require("flat");
|
|
4
|
+
/**
|
|
5
|
+
* Only flattens a {@link FieldErrors} object.
|
|
6
|
+
* @returns e.g.,
|
|
7
|
+
* ```
|
|
8
|
+
* {
|
|
9
|
+
* "address.street.type": "too_short",
|
|
10
|
+
* "address.street.ref.value": "123",
|
|
11
|
+
* "address.street.message": "Required."
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
const flattenFieldErrors = (errors) => (0, flat_1.flatten)(errors);
|
|
16
|
+
exports.default = flattenFieldErrors;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FieldError, FieldErrors } from 'react-hook-form';
|
|
2
|
+
export type FlatFieldErrors = Record<string, FieldError>;
|
|
3
|
+
/**
|
|
4
|
+
* Get {@link FlatFieldErrors} from {@link FieldErrors}.
|
|
5
|
+
* This makes it easy to work with potentially deeply-nested {@link FieldErrors}.
|
|
6
|
+
*
|
|
7
|
+
* @param errors {@link FieldErrors} object.
|
|
8
|
+
* @returns FlatFieldErrors object.
|
|
9
|
+
*
|
|
10
|
+
* e.g.,
|
|
11
|
+
* ```
|
|
12
|
+
* [ "address.street", { "address.street": { type: "too_short", ref: { value: "123" }, message: "Required." } } ]
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare const getFlatFieldErrors: (errors: FieldErrors) => FlatFieldErrors;
|
|
16
|
+
export default getFlatFieldErrors;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
7
|
+
const flattenFieldErrors_1 = __importDefault(require("./flattenFieldErrors"));
|
|
8
|
+
/**
|
|
9
|
+
* Get {@link FlatFieldErrors} from {@link FieldErrors}.
|
|
10
|
+
* This makes it easy to work with potentially deeply-nested {@link FieldErrors}.
|
|
11
|
+
*
|
|
12
|
+
* @param errors {@link FieldErrors} object.
|
|
13
|
+
* @returns FlatFieldErrors object.
|
|
14
|
+
*
|
|
15
|
+
* e.g.,
|
|
16
|
+
* ```
|
|
17
|
+
* [ "address.street", { "address.street": { type: "too_short", ref: { value: "123" }, message: "Required." } } ]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
const getFlatFieldErrors = (errors) => {
|
|
21
|
+
const flattened = (0, flattenFieldErrors_1.default)(errors);
|
|
22
|
+
const keys = Object.keys(flattened);
|
|
23
|
+
return Object.fromEntries(keys.reduce((entries, key) => {
|
|
24
|
+
// look for leaf node, which would have required `type` prop (e.g., `name.type`, `address.street.type`)
|
|
25
|
+
// remove `regexEndsWithType` suffix to get flat field path (e.g., `name`, `address.street`)
|
|
26
|
+
const path = key.replace(regexEndsWithType, '');
|
|
27
|
+
// if nothing replaced, then it's not a leaf node
|
|
28
|
+
if (path === key)
|
|
29
|
+
return entries;
|
|
30
|
+
// find field error in FieldErrors object
|
|
31
|
+
// has dual-purpose of confirming that each path is valid
|
|
32
|
+
const fieldError = (0, react_hook_form_1.get)(errors, path, undefined);
|
|
33
|
+
if (!fieldError)
|
|
34
|
+
return entries;
|
|
35
|
+
entries.push([path, fieldError]);
|
|
36
|
+
return entries;
|
|
37
|
+
}, []));
|
|
38
|
+
};
|
|
39
|
+
exports.default = getFlatFieldErrors;
|
|
40
|
+
const regexEndsWithType = /\.type$/;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
type Props = {
|
|
3
|
+
/** Flat field name. (e.g., `address.street`) */
|
|
4
|
+
path: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
8
|
+
*/
|
|
9
|
+
declare const FormNonFieldErrorMarker: React.FC<Props>;
|
|
10
|
+
export default FormNonFieldErrorMarker;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const FormNonFieldErrorMarker_utils_1 = require("./FormNonFieldErrorMarker.utils");
|
|
5
|
+
/**
|
|
6
|
+
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
7
|
+
*/
|
|
8
|
+
const FormNonFieldErrorMarker = ({ path }) => {
|
|
9
|
+
const dataAttribute = {
|
|
10
|
+
[FormNonFieldErrorMarker_utils_1.FormNonFieldErrorMarkerHtmlAttribute]: path,
|
|
11
|
+
};
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)("div", { role: "alert", "aria-hidden": "true" // hide from screen readers
|
|
13
|
+
, style: { display: 'none' }, ...dataAttribute }));
|
|
14
|
+
};
|
|
15
|
+
exports.default = FormNonFieldErrorMarker;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const experimental_ct_react_1 = require("@playwright/experimental-ct-react");
|
|
8
|
+
const FormNonFieldErrorMarker_1 = __importDefault(require("./FormNonFieldErrorMarker"));
|
|
9
|
+
const FormNonFieldErrorMarker_utils_1 = require("./FormNonFieldErrorMarker.utils");
|
|
10
|
+
const path = 'test';
|
|
11
|
+
const querySelector = (0, FormNonFieldErrorMarker_utils_1.getFormNonFieldErrorMarkerQuerySelector)(path);
|
|
12
|
+
(0, experimental_ct_react_1.test)('FormNonFieldErrorMarker can be located via query', async ({ page, mount, }) => {
|
|
13
|
+
await mount((0, jsx_runtime_1.jsx)(FormNonFieldErrorMarker_1.default, { path: path }));
|
|
14
|
+
await (0, experimental_ct_react_1.expect)(page.locator(querySelector)).toBeAttached();
|
|
15
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML data attribute for {@link FormNonFieldErrorMarker}.
|
|
3
|
+
*/
|
|
4
|
+
export declare const FormNonFieldErrorMarkerHtmlAttribute = "data-paragrav-rhf-utils-nonfield-error-marker-path";
|
|
5
|
+
export declare const getFormNonFieldErrorMarkerQuerySelector: (path: string) => string;
|
|
6
|
+
export declare const hasNonFieldErrorMarkerInDOM: (path: string, parentElement: Pick<HTMLElement, 'querySelector'>) => Element | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasNonFieldErrorMarkerInDOM = exports.getFormNonFieldErrorMarkerQuerySelector = exports.FormNonFieldErrorMarkerHtmlAttribute = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* HTML data attribute for {@link FormNonFieldErrorMarker}.
|
|
6
|
+
*/
|
|
7
|
+
exports.FormNonFieldErrorMarkerHtmlAttribute = 'data-paragrav-rhf-utils-nonfield-error-marker-path';
|
|
8
|
+
const getFormNonFieldErrorMarkerQuerySelector = (path) => `[role="alert"][${exports.FormNonFieldErrorMarkerHtmlAttribute}="${path}"]`;
|
|
9
|
+
exports.getFormNonFieldErrorMarkerQuerySelector = getFormNonFieldErrorMarkerQuerySelector;
|
|
10
|
+
const hasNonFieldErrorMarkerInDOM = (path, parentElement) => parentElement.querySelector((0, exports.getFormNonFieldErrorMarkerQuerySelector)(path));
|
|
11
|
+
exports.hasNonFieldErrorMarkerInDOM = hasNonFieldErrorMarkerInDOM;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FieldError } from 'react-hook-form';
|
|
2
|
+
/**
|
|
3
|
+
* Determine if {@link FieldError} is a non-field error (i.e., has `ref`).
|
|
4
|
+
*
|
|
5
|
+
* A non-field error has no association to an input via {@link FieldError.ref}.
|
|
6
|
+
*
|
|
7
|
+
* These fall into one of two categories:
|
|
8
|
+
* - Root, which are typically displayed to user at bottom/top of form.
|
|
9
|
+
* - Non-root, which fall into two main sub-sets:
|
|
10
|
+
* - Non-orphan (displayed -- typically manually)
|
|
11
|
+
* - e.g., array min/max validation
|
|
12
|
+
* - Orphan (undisplayed), which are typically caused by one of the following cases:
|
|
13
|
+
* - The input is missing.
|
|
14
|
+
* - The schema is incorrect.
|
|
15
|
+
* - The non-field error is not displayed to user with `FormErrorNonFieldMarker`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const isNonFieldError: (error: FieldError) => boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isNonFieldError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Determine if {@link FieldError} is a non-field error (i.e., has `ref`).
|
|
6
|
+
*
|
|
7
|
+
* A non-field error has no association to an input via {@link FieldError.ref}.
|
|
8
|
+
*
|
|
9
|
+
* These fall into one of two categories:
|
|
10
|
+
* - Root, which are typically displayed to user at bottom/top of form.
|
|
11
|
+
* - Non-root, which fall into two main sub-sets:
|
|
12
|
+
* - Non-orphan (displayed -- typically manually)
|
|
13
|
+
* - e.g., array min/max validation
|
|
14
|
+
* - Orphan (undisplayed), which are typically caused by one of the following cases:
|
|
15
|
+
* - The input is missing.
|
|
16
|
+
* - The schema is incorrect.
|
|
17
|
+
* - The non-field error is not displayed to user with `FormErrorNonFieldMarker`.
|
|
18
|
+
*/
|
|
19
|
+
const isNonFieldError = (error) => !error.ref;
|
|
20
|
+
exports.isNonFieldError = isNonFieldError;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("@/utils");
|
|
7
|
+
const useFormContextErrorsIfAny_1 = __importDefault(require("../useFormContextErrorsIfAny"));
|
|
8
|
+
const useFormOrphanErrors_1 = __importDefault(require("./useFormOrphanErrors"));
|
|
9
|
+
const useFormErrorsHasOnlyOrphan = (formRef) => {
|
|
10
|
+
const orphans = (0, useFormOrphanErrors_1.default)(formRef);
|
|
11
|
+
const errors = (0, useFormContextErrorsIfAny_1.default)();
|
|
12
|
+
// no errors
|
|
13
|
+
if (!errors)
|
|
14
|
+
return false;
|
|
15
|
+
// no orphans
|
|
16
|
+
if ((0, utils_1.isEmptyObject)(orphans))
|
|
17
|
+
return false;
|
|
18
|
+
// equal length
|
|
19
|
+
return Object.keys(orphans).length === Object.keys(errors).length;
|
|
20
|
+
};
|
|
21
|
+
exports.default = useFormErrorsHasOnlyOrphan;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
* Root field errors from form.
|
|
4
|
-
* These are typically displayed at the bottom of the form.
|
|
5
|
-
* (Root errors have to processed this way due to (potentially) recursive types.)
|
|
6
|
-
*/
|
|
7
|
-
declare const useFormOrphanErrors: (formRef: React.RefObject<HTMLFormElement>) => Record<string, import("react-hook-form").FieldError>;
|
|
2
|
+
declare const useFormOrphanErrors: (formRef: React.RefObject<HTMLFormElement>) => import("@/errors/getFlatFieldErrors").FlatFieldErrors;
|
|
8
3
|
export default useFormOrphanErrors;
|
|
@@ -3,20 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("@/utils");
|
|
6
7
|
const useFormErrorsOnChange_1 = __importDefault(require("../useFormErrorsOnChange"));
|
|
7
|
-
const
|
|
8
|
-
/**
|
|
9
|
-
* Root field errors from form.
|
|
10
|
-
* These are typically displayed at the bottom of the form.
|
|
11
|
-
* (Root errors have to processed this way due to (potentially) recursive types.)
|
|
12
|
-
*/
|
|
8
|
+
const utils_2 = require("./utils");
|
|
13
9
|
const useFormOrphanErrors = (formRef) => (0, useFormErrorsOnChange_1.default)((errors) => {
|
|
14
|
-
if
|
|
10
|
+
// if no errors, return early
|
|
11
|
+
if ((0, utils_1.isEmptyObject)(errors))
|
|
15
12
|
return {};
|
|
16
13
|
if (!formRef.current) {
|
|
17
14
|
console.error(errors);
|
|
18
15
|
throw new Error('This should not happen.');
|
|
19
16
|
}
|
|
20
|
-
return (0,
|
|
17
|
+
return (0, utils_2.getRootFlatFieldErrors)(errors, formRef.current);
|
|
21
18
|
});
|
|
22
19
|
exports.default = useFormOrphanErrors;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { FieldErrors } from 'react-hook-form';
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
2
|
+
import type { FlatFieldErrors } from '../getFlatFieldErrors';
|
|
3
|
+
export declare const getRootFlatFieldErrors: (errors: FieldErrors, parentElement: Pick<HTMLElement, 'querySelector'>) => FlatFieldErrors;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
(path) => !formElement.querySelector(`[role="alert"][${FormErrorNonFieldMarker_1.FormErrorNonFieldMarkerHtmlAttribute}="${path}"]`));
|
|
6
|
+
exports.getRootFlatFieldErrors = void 0;
|
|
7
|
+
const getFlatFieldErrors_1 = __importDefault(require("../getFlatFieldErrors"));
|
|
8
|
+
const FormNonFieldErrorMarker_utils_1 = require("../nonfield/FormNonFieldErrorMarker.utils");
|
|
9
|
+
const utils_1 = require("../nonfield/utils");
|
|
10
|
+
const utils_2 = require("../root/utils");
|
|
11
|
+
const getRootFlatFieldErrors = (errors, parentElement) => {
|
|
12
|
+
const flatFieldErrors = (0, getFlatFieldErrors_1.default)(errors);
|
|
13
|
+
return Object.fromEntries(Object.entries(flatFieldErrors).filter(([path, error]) =>
|
|
14
|
+
// not root path
|
|
15
|
+
!(0, utils_2.isFormErrorPathRoot)(path) &&
|
|
16
|
+
// non-field
|
|
17
|
+
(0, utils_1.isNonFieldError)(error) &&
|
|
18
|
+
// does not have marker
|
|
19
|
+
!(0, FormNonFieldErrorMarker_utils_1.hasNonFieldErrorMarkerInDOM)(path, parentElement)));
|
|
18
20
|
};
|
|
19
|
-
exports.
|
|
20
|
-
//
|
|
21
|
+
exports.getRootFlatFieldErrors = getRootFlatFieldErrors;
|
|
@@ -5,5 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const useFormErrorsOnChange_1 = __importDefault(require("../useFormErrorsOnChange"));
|
|
7
7
|
const utils_1 = require("./utils");
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Root field errors from form.
|
|
10
|
+
* These are typically displayed at the bottom of the form.
|
|
11
|
+
*/
|
|
12
|
+
const useFormRootFieldErrors = () => (0, useFormErrorsOnChange_1.default)(utils_1.getRootFlatFieldErrors);
|
|
9
13
|
exports.default = useFormRootFieldErrors;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { FieldErrors } from 'react-hook-form';
|
|
2
|
+
import type { FlatFieldErrors } from '../getFlatFieldErrors';
|
|
2
3
|
/**
|
|
3
4
|
* Determine if an error path is root. (e.g., `root` or `root.nested`)
|
|
4
5
|
* @param path Flat path. (e.g., 'root.nested')
|
|
5
6
|
*/
|
|
6
7
|
export declare const isFormErrorPathRoot: (path: string) => boolean;
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export declare const getRootFlatFieldErrors: (errors: FieldErrors) => FlatFieldErrors;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getRootFlatFieldErrors = exports.isFormErrorPathRoot = void 0;
|
|
7
|
+
const getFlatFieldErrors_1 = __importDefault(require("../getFlatFieldErrors"));
|
|
8
|
+
const ROOT = 'root';
|
|
9
|
+
/**
|
|
10
|
+
* Determine if an error path is root. (e.g., `root` or `root.nested`)
|
|
11
|
+
* @param path Flat path. (e.g., 'root.nested')
|
|
12
|
+
*/
|
|
13
|
+
const isFormErrorPathRoot = (path) => path === ROOT || path.startsWith(ROOT + '.');
|
|
14
|
+
exports.isFormErrorPathRoot = isFormErrorPathRoot;
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
const getRootFlatFieldErrors = (errors) => {
|
|
19
|
+
const flatFieldErrors = (0, getFlatFieldErrors_1.default)(errors);
|
|
20
|
+
return Object.fromEntries(Object.entries(flatFieldErrors)
|
|
21
|
+
// only include entries whose paths are "root"
|
|
22
|
+
.filter(([path]) => (0, exports.isFormErrorPathRoot)(path)));
|
|
23
|
+
};
|
|
24
|
+
exports.getRootFlatFieldErrors = getRootFlatFieldErrors;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns errors only if there are errors.
|
|
3
|
+
* Allows simple typeguard without `isEmpty` dependency.
|
|
4
|
+
*/
|
|
5
|
+
declare const useFormContextErrorsIfAny: () => false | import("react-hook-form").FieldErrors<import("react-hook-form").FieldValues>;
|
|
6
|
+
export default useFormContextErrorsIfAny;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
4
|
+
const utils_1 = require("@/utils");
|
|
5
|
+
/**
|
|
6
|
+
* Returns errors only if there are errors.
|
|
7
|
+
* Allows simple typeguard without `isEmpty` dependency.
|
|
8
|
+
*/
|
|
9
|
+
const useFormContextErrorsIfAny = () => {
|
|
10
|
+
const { errors } = (0, react_hook_form_1.useFormState)();
|
|
11
|
+
return (0, utils_1.isEmptyObject)(errors) ? false : errors;
|
|
12
|
+
};
|
|
13
|
+
exports.default = useFormContextErrorsIfAny;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output form errors to console.debug() for easier debugging for certain condition.
|
|
3
|
+
* (e.g., in dev/staging environments or certain users)
|
|
4
|
+
*
|
|
5
|
+
* `console.debug()` is unlikely to trigger any automated console capture reporting.
|
|
6
|
+
*/
|
|
7
|
+
declare const useFormErrorConsoleDebug: (condition: boolean) => void;
|
|
8
|
+
export default useFormErrorConsoleDebug;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const useFormContextErrorsIfAny_1 = __importDefault(require("./useFormContextErrorsIfAny"));
|
|
7
|
+
/**
|
|
8
|
+
* Output form errors to console.debug() for easier debugging for certain condition.
|
|
9
|
+
* (e.g., in dev/staging environments or certain users)
|
|
10
|
+
*
|
|
11
|
+
* `console.debug()` is unlikely to trigger any automated console capture reporting.
|
|
12
|
+
*/
|
|
13
|
+
const useFormErrorConsoleDebug = (condition) => {
|
|
14
|
+
const errors = (0, useFormContextErrorsIfAny_1.default)();
|
|
15
|
+
if (!condition)
|
|
16
|
+
return;
|
|
17
|
+
if (!errors)
|
|
18
|
+
return;
|
|
19
|
+
// eslint-disable-next-line no-console
|
|
20
|
+
console.debug('useFormErrorConsoleDebug', errors);
|
|
21
|
+
};
|
|
22
|
+
exports.default = useFormErrorConsoleDebug;
|
package/dist/cjs/main.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as FormNonFieldErrorMarker } from './errors/nonfield/FormNonFieldErrorMarker';
|
|
2
|
+
export { FormNonFieldErrorMarkerHtmlAttribute } from './errors/nonfield/FormNonFieldErrorMarker.utils';
|
|
2
3
|
export { default as useFormErrorOrphansToConsoleError } from './errors/orphans/useFormErrorOrphansToConsoleError';
|
|
3
4
|
export { default as useFormOrphanErrors } from './errors/orphans/useFormOrphanErrors';
|
|
4
|
-
export { default as useFormRootFieldErrors } from './errors/
|
|
5
|
+
export { default as useFormRootFieldErrors } from './errors/root/useFormRootFieldErrors';
|
|
6
|
+
export { default as useFormErrorConsoleDebug } from './errors/useFormErrorConsoleDebug';
|
|
5
7
|
export { default as useFormErrorsEffect } from './errors/useFormErrorsEffect';
|
|
6
8
|
export { default as useFormErrorsOnChange } from './errors/useFormErrorsOnChange';
|
|
7
9
|
export { default as useFormRequestSubmit } from './errors/useFormRequestSubmit';
|
package/dist/cjs/main.js
CHANGED
|
@@ -3,16 +3,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useFormRequestSubmit = exports.useFormErrorsOnChange = exports.useFormErrorsEffect = exports.useFormRootFieldErrors = exports.useFormOrphanErrors = exports.useFormErrorOrphansToConsoleError = exports.
|
|
7
|
-
var
|
|
8
|
-
Object.defineProperty(exports, "
|
|
9
|
-
|
|
6
|
+
exports.useFormRequestSubmit = exports.useFormErrorsOnChange = exports.useFormErrorsEffect = exports.useFormErrorConsoleDebug = exports.useFormRootFieldErrors = exports.useFormOrphanErrors = exports.useFormErrorOrphansToConsoleError = exports.FormNonFieldErrorMarkerHtmlAttribute = exports.FormNonFieldErrorMarker = void 0;
|
|
7
|
+
var FormNonFieldErrorMarker_1 = require("./errors/nonfield/FormNonFieldErrorMarker");
|
|
8
|
+
Object.defineProperty(exports, "FormNonFieldErrorMarker", { enumerable: true, get: function () { return __importDefault(FormNonFieldErrorMarker_1).default; } });
|
|
9
|
+
var FormNonFieldErrorMarker_utils_1 = require("./errors/nonfield/FormNonFieldErrorMarker.utils");
|
|
10
|
+
Object.defineProperty(exports, "FormNonFieldErrorMarkerHtmlAttribute", { enumerable: true, get: function () { return FormNonFieldErrorMarker_utils_1.FormNonFieldErrorMarkerHtmlAttribute; } });
|
|
10
11
|
var useFormErrorOrphansToConsoleError_1 = require("./errors/orphans/useFormErrorOrphansToConsoleError");
|
|
11
12
|
Object.defineProperty(exports, "useFormErrorOrphansToConsoleError", { enumerable: true, get: function () { return __importDefault(useFormErrorOrphansToConsoleError_1).default; } });
|
|
12
13
|
var useFormOrphanErrors_1 = require("./errors/orphans/useFormOrphanErrors");
|
|
13
14
|
Object.defineProperty(exports, "useFormOrphanErrors", { enumerable: true, get: function () { return __importDefault(useFormOrphanErrors_1).default; } });
|
|
14
|
-
var useFormRootFieldErrors_1 = require("./errors/
|
|
15
|
+
var useFormRootFieldErrors_1 = require("./errors/root/useFormRootFieldErrors");
|
|
15
16
|
Object.defineProperty(exports, "useFormRootFieldErrors", { enumerable: true, get: function () { return __importDefault(useFormRootFieldErrors_1).default; } });
|
|
17
|
+
var useFormErrorConsoleDebug_1 = require("./errors/useFormErrorConsoleDebug");
|
|
18
|
+
Object.defineProperty(exports, "useFormErrorConsoleDebug", { enumerable: true, get: function () { return __importDefault(useFormErrorConsoleDebug_1).default; } });
|
|
16
19
|
var useFormErrorsEffect_1 = require("./errors/useFormErrorsEffect");
|
|
17
20
|
Object.defineProperty(exports, "useFormErrorsEffect", { enumerable: true, get: function () { return __importDefault(useFormErrorsEffect_1).default; } });
|
|
18
21
|
var useFormErrorsOnChange_1 = require("./errors/useFormErrorsOnChange");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isEmptyObject: (obj: Record<string, unknown>) => boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { get as f } from "react-hook-form";
|
|
2
|
+
import d from "./flattenFieldErrors.mjs";
|
|
3
|
+
const i = (e) => {
|
|
4
|
+
const c = d(e), s = Object.keys(c);
|
|
5
|
+
return Object.fromEntries(
|
|
6
|
+
s.reduce(
|
|
7
|
+
(t, o) => {
|
|
8
|
+
const r = o.replace(l, "");
|
|
9
|
+
if (r === o)
|
|
10
|
+
return t;
|
|
11
|
+
const n = f(e, r, void 0);
|
|
12
|
+
return n && t.push([r, n]), t;
|
|
13
|
+
},
|
|
14
|
+
[]
|
|
15
|
+
// entries
|
|
16
|
+
)
|
|
17
|
+
);
|
|
18
|
+
}, l = /\.type$/;
|
|
19
|
+
export {
|
|
20
|
+
i as default
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { FormNonFieldErrorMarkerHtmlAttribute as e } from "./FormNonFieldErrorMarker.utils.mjs";
|
|
3
|
+
const a = ({ path: r }) => {
|
|
4
|
+
const o = {
|
|
5
|
+
[e]: r
|
|
6
|
+
};
|
|
7
|
+
return /* @__PURE__ */ t(
|
|
8
|
+
"div",
|
|
9
|
+
{
|
|
10
|
+
role: "alert",
|
|
11
|
+
"aria-hidden": "true",
|
|
12
|
+
style: { display: "none" },
|
|
13
|
+
...o
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
}, d = a;
|
|
17
|
+
export {
|
|
18
|
+
d as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
const o = "data-paragrav-rhf-utils-nonfield-error-marker-path", t = (r) => `[role="alert"][${o}="${r}"]`, a = (r, e) => e.querySelector(t(r));
|
|
2
|
+
export {
|
|
3
|
+
o as FormNonFieldErrorMarkerHtmlAttribute,
|
|
4
|
+
t as getFormNonFieldErrorMarkerQuerySelector,
|
|
5
|
+
a as hasNonFieldErrorMarkerInDOM
|
|
6
|
+
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import "react";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { isEmptyObject as t } from "../../utils.mjs";
|
|
3
|
+
import e from "../useFormErrorsOnChange.mjs";
|
|
4
|
+
import { getRootFlatFieldErrors as n } from "./utils.mjs";
|
|
5
|
+
const s = (o) => e((r) => {
|
|
6
|
+
if (t(r))
|
|
6
7
|
return {};
|
|
7
8
|
if (!o.current)
|
|
8
9
|
throw console.error(r), new Error("This should not happen.");
|
|
9
|
-
return
|
|
10
|
-
}),
|
|
10
|
+
return n(r, o.current);
|
|
11
|
+
}), a = s;
|
|
11
12
|
export {
|
|
12
|
-
|
|
13
|
+
a as default
|
|
13
14
|
};
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const e =
|
|
7
|
-
return
|
|
8
|
-
e
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import m from "../getFlatFieldErrors.mjs";
|
|
2
|
+
import { hasNonFieldErrorMarkerInDOM as s } from "../nonfield/FormNonFieldErrorMarker.utils.mjs";
|
|
3
|
+
import { isNonFieldError as l } from "../nonfield/utils.mjs";
|
|
4
|
+
import { isFormErrorPathRoot as n } from "../root/utils.mjs";
|
|
5
|
+
const d = (o, t) => {
|
|
6
|
+
const e = m(o);
|
|
7
|
+
return Object.fromEntries(
|
|
8
|
+
Object.entries(e).filter(
|
|
9
|
+
([r, i]) => (
|
|
10
|
+
// not root path
|
|
11
|
+
!n(r) && // non-field
|
|
12
|
+
l(i) && // does not have marker
|
|
13
|
+
!s(r, t)
|
|
14
|
+
)
|
|
12
15
|
)
|
|
13
16
|
);
|
|
14
17
|
};
|
|
15
18
|
export {
|
|
16
|
-
|
|
17
|
-
p as getOrphanFieldErrorsWithMarkerCheck
|
|
19
|
+
d as getRootFlatFieldErrors
|
|
18
20
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import s from "../getFlatFieldErrors.mjs";
|
|
2
|
+
const t = "root", i = (r) => r === t || r.startsWith(t + "."), n = (r) => {
|
|
3
|
+
const o = s(r);
|
|
4
|
+
return Object.fromEntries(
|
|
5
|
+
Object.entries(o).filter(([e]) => i(e))
|
|
6
|
+
);
|
|
7
|
+
};
|
|
8
|
+
export {
|
|
9
|
+
n as getRootFlatFieldErrors,
|
|
10
|
+
i as isFormErrorPathRoot
|
|
11
|
+
};
|
package/dist/esm/main.mjs
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import { default as e
|
|
2
|
-
import {
|
|
1
|
+
import { default as e } from "./errors/nonfield/FormNonFieldErrorMarker.mjs";
|
|
2
|
+
import { FormNonFieldErrorMarkerHtmlAttribute as s } from "./errors/nonfield/FormNonFieldErrorMarker.utils.mjs";
|
|
3
|
+
import { default as m } from "./errors/orphans/useFormErrorOrphansToConsoleError.mjs";
|
|
3
4
|
import { default as u } from "./errors/orphans/useFormOrphanErrors.mjs";
|
|
4
|
-
import { default as
|
|
5
|
-
import { default as
|
|
6
|
-
import { default as
|
|
7
|
-
import { default as i } from "./errors/
|
|
5
|
+
import { default as F } from "./errors/root/useFormRootFieldErrors.mjs";
|
|
6
|
+
import { default as p } from "./errors/useFormErrorConsoleDebug.mjs";
|
|
7
|
+
import { default as x } from "./errors/useFormErrorsEffect.mjs";
|
|
8
|
+
import { default as i } from "./errors/useFormErrorsOnChange.mjs";
|
|
9
|
+
import { default as h } from "./errors/useFormRequestSubmit.mjs";
|
|
8
10
|
export {
|
|
9
|
-
e as
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
e as FormNonFieldErrorMarker,
|
|
12
|
+
s as FormNonFieldErrorMarkerHtmlAttribute,
|
|
13
|
+
p as useFormErrorConsoleDebug,
|
|
14
|
+
m as useFormErrorOrphansToConsoleError,
|
|
15
|
+
x as useFormErrorsEffect,
|
|
16
|
+
i as useFormErrorsOnChange,
|
|
14
17
|
u as useFormOrphanErrors,
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
h as useFormRequestSubmit,
|
|
19
|
+
F as useFormRootFieldErrors
|
|
17
20
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FieldErrors } from 'react-hook-form';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Only flattens a {@link FieldErrors} object.
|
|
5
|
+
* @returns e.g.,
|
|
6
|
+
* ```
|
|
7
|
+
* {
|
|
8
|
+
* "address.street.type": "too_short",
|
|
9
|
+
* "address.street.ref.value": "123",
|
|
10
|
+
* "address.street.message": "Required."
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
declare const flattenFieldErrors: (errors: FieldErrors) => Record<string, unknown>;
|
|
15
|
+
export default flattenFieldErrors;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FieldError, FieldErrors } from 'react-hook-form';
|
|
2
|
+
|
|
3
|
+
export type FlatFieldErrors = Record<string, FieldError>;
|
|
4
|
+
/**
|
|
5
|
+
* Get {@link FlatFieldErrors} from {@link FieldErrors}.
|
|
6
|
+
* This makes it easy to work with potentially deeply-nested {@link FieldErrors}.
|
|
7
|
+
*
|
|
8
|
+
* @param errors {@link FieldErrors} object.
|
|
9
|
+
* @returns FlatFieldErrors object.
|
|
10
|
+
*
|
|
11
|
+
* e.g.,
|
|
12
|
+
* ```
|
|
13
|
+
* [ "address.street", { "address.street": { type: "too_short", ref: { value: "123" }, message: "Required." } } ]
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare const getFlatFieldErrors: (errors: FieldErrors) => FlatFieldErrors;
|
|
17
|
+
export default getFlatFieldErrors;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
type Props = {
|
|
3
|
+
/** Flat field name. (e.g., `address.street`) */
|
|
4
|
+
path: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
8
|
+
*/
|
|
9
|
+
declare const FormNonFieldErrorMarker: React.FC<Props>;
|
|
10
|
+
export default FormNonFieldErrorMarker;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML data attribute for {@link FormNonFieldErrorMarker}.
|
|
3
|
+
*/
|
|
4
|
+
export declare const FormNonFieldErrorMarkerHtmlAttribute = "data-paragrav-rhf-utils-nonfield-error-marker-path";
|
|
5
|
+
export declare const getFormNonFieldErrorMarkerQuerySelector: (path: string) => string;
|
|
6
|
+
export declare const hasNonFieldErrorMarkerInDOM: (path: string, parentElement: Pick<HTMLElement, 'querySelector'>) => Element | null;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FieldError } from 'react-hook-form';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determine if {@link FieldError} is a non-field error (i.e., has `ref`).
|
|
5
|
+
*
|
|
6
|
+
* A non-field error has no association to an input via {@link FieldError.ref}.
|
|
7
|
+
*
|
|
8
|
+
* These fall into one of two categories:
|
|
9
|
+
* - Root, which are typically displayed to user at bottom/top of form.
|
|
10
|
+
* - Non-root, which fall into two main sub-sets:
|
|
11
|
+
* - Non-orphan (displayed -- typically manually)
|
|
12
|
+
* - e.g., array min/max validation
|
|
13
|
+
* - Orphan (undisplayed), which are typically caused by one of the following cases:
|
|
14
|
+
* - The input is missing.
|
|
15
|
+
* - The schema is incorrect.
|
|
16
|
+
* - The non-field error is not displayed to user with `FormErrorNonFieldMarker`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const isNonFieldError: (error: FieldError) => boolean;
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* Root field errors from form.
|
|
5
|
-
* These are typically displayed at the bottom of the form.
|
|
6
|
-
* (Root errors have to processed this way due to (potentially) recursive types.)
|
|
7
|
-
*/
|
|
8
|
-
declare const useFormOrphanErrors: (formRef: React.RefObject<HTMLFormElement>) => Record<string, import('react-hook-form').FieldError>;
|
|
3
|
+
declare const useFormOrphanErrors: (formRef: React.RefObject<HTMLFormElement>) => import('../getFlatFieldErrors').FlatFieldErrors;
|
|
9
4
|
export default useFormOrphanErrors;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
+
import { FlatFieldErrors } from '../getFlatFieldErrors';
|
|
1
2
|
import { FieldErrors } from 'react-hook-form';
|
|
2
3
|
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const getOrphanFieldErrorsWithMarkerCheck: (errors: FieldErrors, formElement: HTMLFormElement) => Record<string, import('react-hook-form').FieldError>;
|
|
4
|
+
export declare const getRootFlatFieldErrors: (errors: FieldErrors, parentElement: Pick<HTMLElement, 'querySelector'>) => FlatFieldErrors;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FlatFieldErrors } from '../getFlatFieldErrors';
|
|
1
2
|
import { FieldErrors } from 'react-hook-form';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -5,4 +6,7 @@ import { FieldErrors } from 'react-hook-form';
|
|
|
5
6
|
* @param path Flat path. (e.g., 'root.nested')
|
|
6
7
|
*/
|
|
7
8
|
export declare const isFormErrorPathRoot: (path: string) => boolean;
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
export declare const getRootFlatFieldErrors: (errors: FieldErrors) => FlatFieldErrors;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns errors only if there are errors.
|
|
3
|
+
* Allows simple typeguard without `isEmpty` dependency.
|
|
4
|
+
*/
|
|
5
|
+
declare const useFormContextErrorsIfAny: () => false | import('react-hook-form').FieldErrors<import("react-hook-form").FieldValues>;
|
|
6
|
+
export default useFormContextErrorsIfAny;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output form errors to console.debug() for easier debugging for certain condition.
|
|
3
|
+
* (e.g., in dev/staging environments or certain users)
|
|
4
|
+
*
|
|
5
|
+
* `console.debug()` is unlikely to trigger any automated console capture reporting.
|
|
6
|
+
*/
|
|
7
|
+
declare const useFormErrorConsoleDebug: (condition: boolean) => void;
|
|
8
|
+
export default useFormErrorConsoleDebug;
|
package/dist/types/main.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as FormNonFieldErrorMarker } from './errors/nonfield/FormNonFieldErrorMarker';
|
|
2
|
+
export { FormNonFieldErrorMarkerHtmlAttribute } from './errors/nonfield/FormNonFieldErrorMarker.utils';
|
|
2
3
|
export { default as useFormErrorOrphansToConsoleError } from './errors/orphans/useFormErrorOrphansToConsoleError';
|
|
3
4
|
export { default as useFormOrphanErrors } from './errors/orphans/useFormOrphanErrors';
|
|
4
|
-
export { default as useFormRootFieldErrors } from './errors/
|
|
5
|
+
export { default as useFormRootFieldErrors } from './errors/root/useFormRootFieldErrors';
|
|
6
|
+
export { default as useFormErrorConsoleDebug } from './errors/useFormErrorConsoleDebug';
|
|
5
7
|
export { default as useFormErrorsEffect } from './errors/useFormErrorsEffect';
|
|
6
8
|
export { default as useFormErrorsOnChange } from './errors/useFormErrorsOnChange';
|
|
7
9
|
export { default as useFormRequestSubmit } from './errors/useFormRequestSubmit';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isEmptyObject: (obj: Record<string, unknown>) => boolean;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@paragrav/rhf-utils",
|
|
3
3
|
"author": "paragrav.dev",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.19",
|
|
6
6
|
"description": "Integration utilities for react-hook-form.",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"files": [
|
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
"types": "./dist/types/main.d.ts",
|
|
21
21
|
"default": "./dist/esm/main.mjs"
|
|
22
22
|
}
|
|
23
|
+
},
|
|
24
|
+
"./useFormErrorConsoleDebug": {
|
|
25
|
+
"types": "./dist/types/errors/useFormErrorConsoleDebug.d.ts",
|
|
26
|
+
"require": "./dist/cjs/errors/useFormErrorConsoleDebug.cjs",
|
|
27
|
+
"import": "./dist/esm/errors/useFormErrorConsoleDebug.mjs"
|
|
23
28
|
}
|
|
24
29
|
},
|
|
25
30
|
"sideEffects": false,
|
|
@@ -37,10 +42,9 @@
|
|
|
37
42
|
"tsc": "tsc",
|
|
38
43
|
"validate": "npm run tsc & npm run lint & npm run test & npm run test:ct"
|
|
39
44
|
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"flat": "^6.0.1"
|
|
42
|
-
},
|
|
43
45
|
"peerDependencies": {
|
|
46
|
+
"flat": "^6",
|
|
47
|
+
"react": "^18",
|
|
44
48
|
"react-hook-form": "^7"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
@@ -58,10 +62,10 @@
|
|
|
58
62
|
"eslint-plugin-react": "^7.34.1",
|
|
59
63
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
60
64
|
"eslint-plugin-simple-import-sort": "^12.0.0",
|
|
65
|
+
"happy-dom": "^14.3.9",
|
|
61
66
|
"husky": "^9.0.11",
|
|
62
67
|
"lint-staged": "^15.2.2",
|
|
63
68
|
"prettier": "^3.2.5",
|
|
64
|
-
"react": "^18.2.0",
|
|
65
69
|
"react-dom": "^18.2.0",
|
|
66
70
|
"rollup": "^4.13.0",
|
|
67
71
|
"typescript": "^5.4.3",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
type Props = {
|
|
3
|
-
/** Flat field name. (e.g., `address.street`) */
|
|
4
|
-
path: string;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
8
|
-
*/
|
|
9
|
-
declare const FormErrorNonFieldMarker: React.FC<Props>;
|
|
10
|
-
export default FormErrorNonFieldMarker;
|
|
11
|
-
/**
|
|
12
|
-
* HTML data attribute for {@link FormErrorNonFieldMarker}.
|
|
13
|
-
*/
|
|
14
|
-
export declare const FormErrorNonFieldMarkerHtmlAttribute = "data-paragrav-rhf-utils-marker-path";
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FormErrorNonFieldMarkerHtmlAttribute = void 0;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
/**
|
|
6
|
-
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
7
|
-
*/
|
|
8
|
-
const FormErrorNonFieldMarker = ({ path }) => {
|
|
9
|
-
const attribute = {
|
|
10
|
-
[exports.FormErrorNonFieldMarkerHtmlAttribute]: path,
|
|
11
|
-
};
|
|
12
|
-
return ((0, jsx_runtime_1.jsx)("div", { role: "alert", "aria-hidden": "true" // hide from screen readers
|
|
13
|
-
, style: { display: 'none' }, ...attribute }));
|
|
14
|
-
};
|
|
15
|
-
exports.default = FormErrorNonFieldMarker;
|
|
16
|
-
// utils
|
|
17
|
-
/**
|
|
18
|
-
* HTML data attribute for {@link FormErrorNonFieldMarker}.
|
|
19
|
-
*/
|
|
20
|
-
exports.FormErrorNonFieldMarkerHtmlAttribute = 'data-paragrav-rhf-utils-marker-path';
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRootFieldErrorList = exports.isFormErrorPathRoot = void 0;
|
|
4
|
-
const utils_1 = require("../utils");
|
|
5
|
-
const ROOT = 'root';
|
|
6
|
-
/**
|
|
7
|
-
* Determine if an error path is root. (e.g., `root` or `root.nested`)
|
|
8
|
-
* @param path Flat path. (e.g., 'root.nested')
|
|
9
|
-
*/
|
|
10
|
-
const isFormErrorPathRoot = (path) => path === ROOT || path.startsWith(ROOT + '.');
|
|
11
|
-
exports.isFormErrorPathRoot = isFormErrorPathRoot;
|
|
12
|
-
const getRootFieldErrorList = (errors) => (0, utils_1.getFieldErrorListByFilter)(errors, exports.isFormErrorPathRoot);
|
|
13
|
-
exports.getRootFieldErrorList = getRootFieldErrorList;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { FieldError, FieldErrors } from 'react-hook-form';
|
|
2
|
-
/**
|
|
3
|
-
* @returns A flattened {@link FieldErrors} record.
|
|
4
|
-
*/
|
|
5
|
-
export declare const getFieldErrorsByFilter: (errors: FieldErrors, where?: ((path: string, flattenedErrors: Record<string, unknown>) => boolean) | undefined) => Record<string, FieldError>;
|
|
6
|
-
/**
|
|
7
|
-
* @returns An array of field errors. (Not a record.)
|
|
8
|
-
*/
|
|
9
|
-
export declare const getFieldErrorListByFilter: (errors: FieldErrors, where?: ((path: string, flattenedErrors: Record<string, unknown>) => boolean) | undefined) => FieldError[];
|
package/dist/cjs/errors/utils.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFieldErrorListByFilter = exports.getFieldErrorsByFilter = void 0;
|
|
4
|
-
const flat_1 = require("flat");
|
|
5
|
-
const react_hook_form_1 = require("react-hook-form");
|
|
6
|
-
/**
|
|
7
|
-
* @returns A flattened {@link FieldErrors} record.
|
|
8
|
-
*/
|
|
9
|
-
const getFieldErrorsByFilter = (errors, where) => {
|
|
10
|
-
const keys = getFieldErrorOrphanKeysByFilter(errors, where);
|
|
11
|
-
const record = keys.reduce((acc, path) => {
|
|
12
|
-
acc[path] = (0, react_hook_form_1.get)(errors, path);
|
|
13
|
-
return acc;
|
|
14
|
-
}, {});
|
|
15
|
-
return record;
|
|
16
|
-
};
|
|
17
|
-
exports.getFieldErrorsByFilter = getFieldErrorsByFilter;
|
|
18
|
-
/**
|
|
19
|
-
* @returns An array of field errors. (Not a record.)
|
|
20
|
-
*/
|
|
21
|
-
const getFieldErrorListByFilter = (errors, where) => {
|
|
22
|
-
const keys = getFieldErrorOrphanKeysByFilter(errors, where);
|
|
23
|
-
const fieldErrors = keys.map((key) => {
|
|
24
|
-
return (0, react_hook_form_1.get)(errors, key);
|
|
25
|
-
});
|
|
26
|
-
return fieldErrors;
|
|
27
|
-
};
|
|
28
|
-
exports.getFieldErrorListByFilter = getFieldErrorListByFilter;
|
|
29
|
-
/**
|
|
30
|
-
* RHF uses deeply-nested object for errors, which reflects the structure of the form.
|
|
31
|
-
* And the type is quite complex. All this complicates the process of finding errors.
|
|
32
|
-
* This function automatically looks only for keys that end with `.ref`.
|
|
33
|
-
* (This makes sure we only look at the leaf nodes of the object tree.)
|
|
34
|
-
* This function also automatically removes the `.ref` suffix from the keys.
|
|
35
|
-
*
|
|
36
|
-
* @param where Filter callback.
|
|
37
|
-
* @param map Transformer callback.
|
|
38
|
-
* @returns Tuple of field errors and keys.
|
|
39
|
-
*/
|
|
40
|
-
const getFieldErrorOrphanKeysByFilter = (errors, where) => {
|
|
41
|
-
/**
|
|
42
|
-
* e.g.:
|
|
43
|
-
* ```js
|
|
44
|
-
* { root: { ref: undefined, message: 'Form is invalid.' }, email: { ref: Object, message: 'Invalid.' } }
|
|
45
|
-
* ```
|
|
46
|
-
* flattens to:
|
|
47
|
-
* ```js
|
|
48
|
-
* { 'root.ref': undefined, 'root.message': 'Form is invalid.', 'email.ref': Object, 'email.message': 'Invalid.' }
|
|
49
|
-
* ```
|
|
50
|
-
* returns (if no additional filter/map specified)
|
|
51
|
-
* ```js
|
|
52
|
-
* [ 'root', 'email' ]
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
const flattenedErrors = (0, flat_1.flatten)(errors);
|
|
56
|
-
const flattenedErrorObjectKeys = Object.keys(flattenedErrors);
|
|
57
|
-
// look for leaf node, which would have ref prop (e.g., `orphan_field.ref`)
|
|
58
|
-
const flattenedErrorObjectKeysEndingWithDotRef = flattenedErrorObjectKeys.filter((key) => key.match(regexEndsWithDotRef));
|
|
59
|
-
// remove `.ref` suffix to get flat field path (e.g., `name`, `address.street`)
|
|
60
|
-
const paths = flattenedErrorObjectKeysEndingWithDotRef.map((flattenedKey) => flattenedKey.replace(regexEndsWithDotRef, ''));
|
|
61
|
-
// filter via callback
|
|
62
|
-
const flattenedKeysFiltered = paths.filter((path) => where ? where(path, flattenedErrors) : true);
|
|
63
|
-
return flattenedKeysFiltered;
|
|
64
|
-
};
|
|
65
|
-
const regexEndsWithDotRef = /\.ref$/;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
-
const o = ({ path: r }) => {
|
|
3
|
-
const t = {
|
|
4
|
-
[a]: r
|
|
5
|
-
};
|
|
6
|
-
return /* @__PURE__ */ e(
|
|
7
|
-
"div",
|
|
8
|
-
{
|
|
9
|
-
role: "alert",
|
|
10
|
-
"aria-hidden": "true",
|
|
11
|
-
style: { display: "none" },
|
|
12
|
-
...t
|
|
13
|
-
}
|
|
14
|
-
);
|
|
15
|
-
}, n = o, a = "data-paragrav-rhf-utils-marker-path";
|
|
16
|
-
export {
|
|
17
|
-
a as FormErrorNonFieldMarkerHtmlAttribute,
|
|
18
|
-
n as default
|
|
19
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { flatten as f } from "../node_modules/flat/index.mjs";
|
|
2
|
-
import { get as d } from "react-hook-form";
|
|
3
|
-
const p = (e, t) => i(e, t).reduce((r, s) => (r[s] = d(e, s), r), {}), F = (e, t) => i(e, t).map((r) => d(e, r)), i = (e, t) => {
|
|
4
|
-
const o = f(e);
|
|
5
|
-
return Object.keys(o).filter((n) => n.match(l)).map(
|
|
6
|
-
(n) => n.replace(l, "")
|
|
7
|
-
).filter(
|
|
8
|
-
(n) => t ? t(n, o) : !0
|
|
9
|
-
);
|
|
10
|
-
}, l = /\.ref$/;
|
|
11
|
-
export {
|
|
12
|
-
F as getFieldErrorListByFilter,
|
|
13
|
-
p as getFieldErrorsByFilter
|
|
14
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
function d(t) {
|
|
2
|
-
return t && t.constructor && typeof t.constructor.isBuffer == "function" && t.constructor.isBuffer(t);
|
|
3
|
-
}
|
|
4
|
-
function A(t) {
|
|
5
|
-
return t;
|
|
6
|
-
}
|
|
7
|
-
function B(t, n) {
|
|
8
|
-
n = n || {};
|
|
9
|
-
const l = n.delimiter || ".", m = n.maxDepth, o = n.transformKey || A, f = {};
|
|
10
|
-
function i(s, u, r) {
|
|
11
|
-
r = r || 1, Object.keys(s).forEach(function(c) {
|
|
12
|
-
const e = s[c], x = n.safe && Array.isArray(e), a = Object.prototype.toString.call(e), O = d(e), b = a === "[object Object]" || a === "[object Array]", y = u ? u + l + o(c) : o(c);
|
|
13
|
-
if (!x && !O && b && Object.keys(e).length && (!n.maxDepth || r < m))
|
|
14
|
-
return i(e, y, r + 1);
|
|
15
|
-
f[y] = e;
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
return i(t), f;
|
|
19
|
-
}
|
|
20
|
-
export {
|
|
21
|
-
B as flatten
|
|
22
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
type Props = {
|
|
3
|
-
/** Flat field name. (e.g., `address.street`) */
|
|
4
|
-
path: string;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Empty, hidden marker to indicate a non-field error is presented to user.
|
|
8
|
-
*/
|
|
9
|
-
declare const FormErrorNonFieldMarker: React.FC<Props>;
|
|
10
|
-
export default FormErrorNonFieldMarker;
|
|
11
|
-
/**
|
|
12
|
-
* HTML data attribute for {@link FormErrorNonFieldMarker}.
|
|
13
|
-
*/
|
|
14
|
-
export declare const FormErrorNonFieldMarkerHtmlAttribute = "data-paragrav-rhf-utils-marker-path";
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { FieldError, FieldErrors } from 'react-hook-form';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @returns A flattened {@link FieldErrors} record.
|
|
5
|
-
*/
|
|
6
|
-
export declare const getFieldErrorsByFilter: (errors: FieldErrors, where?: ((path: string, flattenedErrors: Record<string, unknown>) => boolean) | undefined) => Record<string, FieldError>;
|
|
7
|
-
/**
|
|
8
|
-
* @returns An array of field errors. (Not a record.)
|
|
9
|
-
*/
|
|
10
|
-
export declare const getFieldErrorListByFilter: (errors: FieldErrors, where?: ((path: string, flattenedErrors: Record<string, unknown>) => boolean) | undefined) => FieldError[];
|