@paragrav/rhf-utils 0.0.18 → 0.0.20

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.
Files changed (88) hide show
  1. package/dist/cjs/errors/flattenFieldErrors.d.ts +14 -0
  2. package/dist/cjs/errors/flattenFieldErrors.js +16 -0
  3. package/dist/cjs/errors/getFlatFieldErrors.d.ts +16 -0
  4. package/dist/cjs/errors/getFlatFieldErrors.js +40 -0
  5. package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.js +7 -4
  6. package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.utils.d.ts +3 -1
  7. package/dist/cjs/errors/nonfield/FormNonFieldErrorMarker.utils.js +7 -3
  8. package/dist/cjs/errors/nonfield/utils.d.ts +15 -7
  9. package/dist/cjs/errors/nonfield/utils.js +14 -72
  10. package/dist/cjs/errors/orphan/useFormErrorsHasOnlyOrphans.d.ts +2 -0
  11. package/dist/cjs/errors/orphan/useFormErrorsHasOnlyOrphans.js +19 -0
  12. package/dist/cjs/errors/orphan/useOrphanFormErrors.d.ts +3 -0
  13. package/dist/cjs/errors/orphan/useOrphanFormErrors.js +18 -0
  14. package/dist/cjs/errors/orphan/useOrphanFormErrorsToConsoleError.d.ts +7 -0
  15. package/dist/cjs/errors/{orphans/useFormErrorOrphansToConsoleError.js → orphan/useOrphanFormErrorsToConsoleError.js} +6 -8
  16. package/dist/cjs/errors/orphan/utils.d.ts +3 -0
  17. package/dist/cjs/errors/orphan/utils.js +21 -0
  18. package/dist/cjs/errors/root/useRootFormFieldErrors.d.ts +6 -0
  19. package/dist/cjs/errors/root/{useFormRootFieldErrors.js → useRootFormFieldErrors.js} +2 -2
  20. package/dist/cjs/errors/root/utils.d.ts +5 -1
  21. package/dist/cjs/errors/root/utils.js +15 -4
  22. package/dist/cjs/errors/useFormErrorConsoleDebug.d.ts +8 -0
  23. package/dist/cjs/errors/useFormErrorConsoleDebug.js +22 -0
  24. package/dist/cjs/errors/useFormErrorsIfAny.d.ts +6 -0
  25. package/dist/cjs/errors/useFormErrorsIfAny.js +13 -0
  26. package/dist/cjs/errors/useFormFlatFieldErrors.d.ts +5 -0
  27. package/dist/cjs/errors/useFormFlatFieldErrors.js +12 -0
  28. package/dist/cjs/main.d.ts +7 -4
  29. package/dist/cjs/main.js +14 -8
  30. package/dist/cjs/utils.d.ts +1 -0
  31. package/dist/cjs/utils.js +5 -0
  32. package/dist/esm/errors/flattenFieldErrors.mjs +5 -0
  33. package/dist/esm/errors/getFlatFieldErrors.mjs +21 -0
  34. package/dist/esm/errors/nonfield/FormNonFieldErrorMarker.mjs +4 -4
  35. package/dist/esm/errors/nonfield/FormNonFieldErrorMarker.utils.mjs +4 -3
  36. package/dist/esm/errors/nonfield/utils.mjs +2 -12
  37. package/dist/esm/errors/orphan/useFormErrorsHasOnlyOrphans.mjs +10 -0
  38. package/dist/esm/errors/orphan/useOrphanFormErrors.mjs +14 -0
  39. package/dist/esm/errors/{orphans/useFormErrorOrphansToConsoleError.mjs → orphan/useOrphanFormErrorsToConsoleError.mjs} +2 -2
  40. package/dist/esm/errors/orphan/utils.mjs +20 -0
  41. package/dist/esm/errors/root/{useFormRootFieldErrors.mjs → useRootFormFieldErrors.mjs} +1 -1
  42. package/dist/esm/errors/root/utils.mjs +8 -3
  43. package/dist/esm/errors/useFormErrorConsoleDebug.mjs +8 -0
  44. package/dist/esm/errors/useFormErrorsIfAny.mjs +9 -0
  45. package/dist/esm/errors/useFormFlatFieldErrors.mjs +6 -0
  46. package/dist/esm/main.mjs +20 -14
  47. package/dist/esm/utils.mjs +4 -0
  48. package/dist/types/errors/flattenFieldErrors.d.ts +15 -0
  49. package/dist/types/errors/getFlatFieldErrors.d.ts +17 -0
  50. package/dist/types/errors/nonfield/FormNonFieldErrorMarker.utils.d.ts +3 -1
  51. package/dist/types/errors/nonfield/utils.d.ts +15 -7
  52. package/dist/types/errors/orphan/useFormErrorsHasOnlyOrphans.d.ts +2 -0
  53. package/dist/types/errors/orphan/useOrphanFormErrors.d.ts +4 -0
  54. package/dist/types/errors/orphan/useOrphanFormErrorsToConsoleError.d.ts +8 -0
  55. package/dist/types/errors/orphan/utils.d.ts +4 -0
  56. package/dist/types/errors/root/useRootFormFieldErrors.d.ts +6 -0
  57. package/dist/types/errors/root/utils.d.ts +5 -1
  58. package/dist/types/errors/useFormErrorConsoleDebug.d.ts +8 -0
  59. package/dist/types/errors/useFormErrorsIfAny.d.ts +6 -0
  60. package/dist/types/errors/useFormFlatFieldErrors.d.ts +5 -0
  61. package/dist/types/main.d.ts +7 -4
  62. package/dist/types/utils.d.ts +1 -0
  63. package/package.json +63 -14
  64. package/dist/cjs/errors/orphans/FormErrorNonFieldMarker.d.ts +0 -14
  65. package/dist/cjs/errors/orphans/FormErrorNonFieldMarker.js +0 -20
  66. package/dist/cjs/errors/orphans/useFormErrorOrphansToConsoleError.d.ts +0 -9
  67. package/dist/cjs/errors/orphans/useFormOrphanErrors.d.ts +0 -3
  68. package/dist/cjs/errors/orphans/useFormOrphanErrors.js +0 -17
  69. package/dist/cjs/errors/orphans/utils.d.ts +0 -15
  70. package/dist/cjs/errors/orphans/utils.js +0 -27
  71. package/dist/cjs/errors/root/useFormRootFieldErrors.d.ts +0 -6
  72. package/dist/cjs/errors/roots/useFormRootFieldErrors.d.ts +0 -2
  73. package/dist/cjs/errors/roots/useFormRootFieldErrors.js +0 -9
  74. package/dist/cjs/errors/roots/utils.d.ts +0 -7
  75. package/dist/cjs/errors/roots/utils.js +0 -13
  76. package/dist/cjs/errors/utils.d.ts +0 -9
  77. package/dist/cjs/errors/utils.js +0 -65
  78. package/dist/esm/errors/orphans/useFormOrphanErrors.mjs +0 -13
  79. package/dist/esm/errors/orphans/utils.mjs +0 -17
  80. package/dist/esm/node_modules/flat/index.mjs +0 -22
  81. package/dist/types/errors/orphans/FormErrorNonFieldMarker.d.ts +0 -14
  82. package/dist/types/errors/orphans/useFormErrorOrphansToConsoleError.d.ts +0 -10
  83. package/dist/types/errors/orphans/useFormOrphanErrors.d.ts +0 -4
  84. package/dist/types/errors/orphans/utils.d.ts +0 -16
  85. package/dist/types/errors/root/useFormRootFieldErrors.d.ts +0 -6
  86. package/dist/types/errors/roots/useFormRootFieldErrors.d.ts +0 -2
  87. package/dist/types/errors/roots/utils.d.ts +0 -8
  88. 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$/;
@@ -1,15 +1,18 @@
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
6
  const jsx_runtime_1 = require("react/jsx-runtime");
4
- const FormNonFieldErrorMarker_utils_1 = require("./FormNonFieldErrorMarker.utils");
7
+ const FormNonFieldErrorMarker_utils_1 = __importDefault(require("./FormNonFieldErrorMarker.utils"));
5
8
  /**
6
9
  * Empty, hidden marker to indicate a non-field error is presented to user.
7
10
  */
8
11
  const FormNonFieldErrorMarker = ({ path }) => {
9
- const attribute = {
10
- [FormNonFieldErrorMarker_utils_1.FormNonFieldErrorMarkerHtmlAttribute]: path,
12
+ const dataAttribute = {
13
+ [FormNonFieldErrorMarker_utils_1.default]: path,
11
14
  };
12
15
  return ((0, jsx_runtime_1.jsx)("div", { role: "alert", "aria-hidden": "true" // hide from screen readers
13
- , style: { display: 'none' }, ...attribute }));
16
+ , style: { display: 'none' }, ...dataAttribute }));
14
17
  };
15
18
  exports.default = FormNonFieldErrorMarker;
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * HTML data attribute for {@link FormNonFieldErrorMarker}.
3
3
  */
4
- export declare const FormNonFieldErrorMarkerHtmlAttribute = "data-paragrav-rhf-utils-nonfield-error-marker-path";
4
+ declare const FormNonFieldErrorMarkerHtmlAttribute = "data-paragrav-rhf-utils-nonfield-error-marker-path";
5
+ export default FormNonFieldErrorMarkerHtmlAttribute;
5
6
  export declare const getFormNonFieldErrorMarkerQuerySelector: (path: string) => string;
7
+ export declare const hasNonFieldErrorMarkerInDOM: (path: string, parentElement: Pick<HTMLElement, 'querySelector'>) => Element | null;
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFormNonFieldErrorMarkerQuerySelector = exports.FormNonFieldErrorMarkerHtmlAttribute = void 0;
3
+ exports.hasNonFieldErrorMarkerInDOM = exports.getFormNonFieldErrorMarkerQuerySelector = void 0;
4
4
  /**
5
5
  * HTML data attribute for {@link FormNonFieldErrorMarker}.
6
6
  */
7
- exports.FormNonFieldErrorMarkerHtmlAttribute = 'data-paragrav-rhf-utils-nonfield-error-marker-path';
8
- const getFormNonFieldErrorMarkerQuerySelector = (path) => `[role="alert"][${exports.FormNonFieldErrorMarkerHtmlAttribute}="${path}"]`;
7
+ const FormNonFieldErrorMarkerHtmlAttribute = 'data-paragrav-rhf-utils-nonfield-error-marker-path';
8
+ exports.default = FormNonFieldErrorMarkerHtmlAttribute;
9
+ // utils
10
+ const getFormNonFieldErrorMarkerQuerySelector = (path) => `[role="alert"][${FormNonFieldErrorMarkerHtmlAttribute}="${path}"]`;
9
11
  exports.getFormNonFieldErrorMarkerQuerySelector = getFormNonFieldErrorMarkerQuerySelector;
12
+ const hasNonFieldErrorMarkerInDOM = (path, parentElement) => parentElement.querySelector((0, exports.getFormNonFieldErrorMarkerQuerySelector)(path));
13
+ exports.hasNonFieldErrorMarkerInDOM = hasNonFieldErrorMarkerInDOM;
@@ -1,9 +1,17 @@
1
- import type { FieldError, FieldErrors } from 'react-hook-form';
1
+ import type { FieldError } from 'react-hook-form';
2
2
  /**
3
- * @returns A flattened {@link FieldErrors} record. (e.g. `{ "address.street": FieldError }`)
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 error is not displayed to user with `FormErrorNonFieldMarker`.
4
16
  */
5
- export declare const getNonFieldErrorRecordByFilter: (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 getNonFieldErrorListByFilter: (errors: FieldErrors, where?: ((path: string, flattenedErrors: Record<string, unknown>) => boolean) | undefined) => FieldError[];
17
+ export declare const isNonFieldError: (error: FieldError) => boolean;
@@ -1,78 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNonFieldErrorListByFilter = exports.getNonFieldErrorRecordByFilter = void 0;
4
- const flat_1 = require("flat");
5
- const react_hook_form_1 = require("react-hook-form");
3
+ exports.isNonFieldError = void 0;
6
4
  /**
7
- * @returns A flattened {@link FieldErrors} record. (e.g. `{ "address.street": FieldError }`)
8
- */
9
- const getNonFieldErrorRecordByFilter = (errors, where) => {
10
- const keys = getNonFieldErrorPathsByFilter(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.getNonFieldErrorRecordByFilter = getNonFieldErrorRecordByFilter;
18
- /**
19
- * @returns An array of field errors. (Not a record.)
20
- */
21
- const getNonFieldErrorListByFilter = (errors, where) => {
22
- const keys = getNonFieldErrorPathsByFilter(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.getNonFieldErrorListByFilter = getNonFieldErrorListByFilter;
29
- /**
30
- * Retrieve non-field error paths from {@link FieldErrors} object.
31
- *
32
- * Non-field errors are those without an association to an input via {@link FieldError.ref}.
33
- *
34
- * These fall into one of three categories:
35
- * - Root errors, which are displayed to user at bottom/top of form.
36
- * - Non-field errors (e.g., array min/max validation), which are typically displayed manually to user near relevant fields.
37
- * - Orphan error occurs when a non-field error has not been displayed to user.
38
- * - This is typically caused by one of the following cases:
39
- * - 1. The input is missing.
40
- * - 3. The schema is incorrect.
41
- * - 2. The non-field error is not displayed to user with `FormErrorNonFieldMarker`.
5
+ * Determine if {@link FieldError} is a non-field error (i.e., has `ref`).
42
6
  *
43
- * RHF uses deeply-nested object for errors, which reflects the structure of the form.
44
- * And the type is quite complex. All this complicates the process of finding errors.
45
- * This function automatically looks only for keys that end with `.ref`.
46
- * (This makes sure we only look at the leaf nodes of the object tree.)
47
- * This function also automatically removes the `.ref` suffix from the keys.
7
+ * A non-field error has no association to an input via {@link FieldError.ref}.
48
8
  *
49
- * @param where Filter callback.
50
- * @param map Transformer callback.
51
- * @returns Tuple of field errors and keys.
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 error is not displayed to user with `FormErrorNonFieldMarker`.
52
18
  */
53
- const getNonFieldErrorPathsByFilter = (errors, where) => {
54
- /**
55
- * e.g.:
56
- * ```js
57
- * { root: { ref: undefined, message: 'Form is invalid.' }, email: { ref: Object, message: 'Invalid.' } }
58
- * ```
59
- * flattens to:
60
- * ```js
61
- * { 'root.ref': undefined, 'root.message': 'Form is invalid.', 'email.ref': Object, 'email.message': 'Invalid.' }
62
- * ```
63
- * returns (if no additional filter/map specified)
64
- * ```js
65
- * [ 'root', 'email' ]
66
- * ```
67
- */
68
- const flattenedErrors = (0, flat_1.flatten)(errors);
69
- const flattenedErrorObjectKeys = Object.keys(flattenedErrors);
70
- // look for leaf node, which would have ref prop (e.g., `orphan_field.ref`)
71
- const flattenedErrorObjectKeysEndingWithDotRef = flattenedErrorObjectKeys.filter((key) => key.match(regexEndsWithDotRef));
72
- // remove `.ref` suffix to get flat field path (e.g., `name`, `address.street`)
73
- const paths = flattenedErrorObjectKeysEndingWithDotRef.map((flattenedKey) => flattenedKey.replace(regexEndsWithDotRef, ''));
74
- // filter via callback
75
- const flattenedKeysFiltered = paths.filter((path) => where ? where(path, flattenedErrors) : true);
76
- return flattenedKeysFiltered;
77
- };
78
- const regexEndsWithDotRef = /\.ref$/;
19
+ const isNonFieldError = (error) => !error.ref;
20
+ exports.isNonFieldError = isNonFieldError;
@@ -0,0 +1,2 @@
1
+ declare const useFormErrorsHasOnlyOrphans: (formRef: React.RefObject<HTMLFormElement>) => boolean;
2
+ export default useFormErrorsHasOnlyOrphans;
@@ -0,0 +1,19 @@
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 useFormFlatFieldErrors_1 = __importDefault(require("../useFormFlatFieldErrors"));
8
+ const useOrphanFormErrors_1 = __importDefault(require("./useOrphanFormErrors"));
9
+ const useFormErrorsHasOnlyOrphans = (formRef) => {
10
+ // get flat field errors of orphans and all errors
11
+ const orphans = (0, useOrphanFormErrors_1.default)(formRef);
12
+ const errors = (0, useFormFlatFieldErrors_1.default)();
13
+ // if no orphans, or no errors
14
+ if ([orphans, errors].some(utils_1.isEmptyObject))
15
+ return false;
16
+ // equal length
17
+ return Object.keys(orphans).length === Object.keys(errors).length;
18
+ };
19
+ exports.default = useFormErrorsHasOnlyOrphans;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const useOrphanFormErrors: (formRef: React.RefObject<HTMLFormElement>) => import("@/errors/getFlatFieldErrors").FlatFieldErrors;
3
+ export default useOrphanFormErrors;
@@ -0,0 +1,18 @@
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 useFormErrorsOnChange_1 = __importDefault(require("../useFormErrorsOnChange"));
8
+ const utils_2 = require("./utils");
9
+ const useOrphanFormErrors = (formRef) => (0, useFormErrorsOnChange_1.default)((errors) => {
10
+ // if no errors, return early
11
+ if ((0, utils_1.isEmptyObject)(errors))
12
+ return {};
13
+ // this should never happen
14
+ if (!formRef.current)
15
+ throw new Error();
16
+ return (0, utils_2.getOrphanFlatFieldErrors)(errors, formRef.current);
17
+ });
18
+ exports.default = useOrphanFormErrors;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ /**
3
+ * Outputs orphan errors to `console.error` all errors with `ref: undefined` that do not begin with `root(.*)`.
4
+ * Sentry (or equivalent) should capture.
5
+ */
6
+ declare const useOrphanFormErrorsToConsoleError: (formRef: React.RefObject<HTMLFormElement>) => void;
7
+ export default useOrphanFormErrorsToConsoleError;
@@ -5,25 +5,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const react_hook_form_1 = require("react-hook-form");
8
- const useFormOrphanErrors_1 = __importDefault(require("./useFormOrphanErrors"));
8
+ const useOrphanFormErrors_1 = __importDefault(require("./useOrphanFormErrors"));
9
9
  /**
10
- * Orphans are field errors that do not have a ref.
11
- * (Most commonly `root(.*)`, but these are filtered out. They are handled by `useFormRootFieldErrors`.)
12
- * Outputs to `console.error` all errors with `ref: undefined` that do not begin with `root(.*)`.
10
+ * Outputs orphan errors to `console.error` all errors with `ref: undefined` that do not begin with `root(.*)`.
13
11
  * Sentry (or equivalent) should capture.
14
12
  */
15
- const useFormErrorOrphansToConsoleError = (formRef) => {
13
+ const useOrphanFormErrorsToConsoleError = (formRef) => {
16
14
  const { getValues } = (0, react_hook_form_1.useFormContext)();
17
15
  const { errors } = (0, react_hook_form_1.useFormState)();
18
- const orphans = (0, useFormOrphanErrors_1.default)(formRef);
16
+ const orphans = (0, useOrphanFormErrors_1.default)(formRef);
19
17
  react_1.default.useEffect(() => {
20
18
  if (!Object.keys(orphans).length)
21
19
  return;
22
- console.error('useFormErrorOrphansToConsoleError', {
20
+ console.error('useOrphanFormErrorsToConsoleError', {
23
21
  location: window.location,
24
22
  values: getValues(),
25
23
  orphans,
26
24
  });
27
25
  }, [errors, getValues, orphans]);
28
26
  };
29
- exports.default = useFormErrorOrphansToConsoleError;
27
+ exports.default = useOrphanFormErrorsToConsoleError;
@@ -0,0 +1,3 @@
1
+ import type { FieldErrors } from 'react-hook-form';
2
+ import type { FlatFieldErrors } from '../getFlatFieldErrors';
3
+ export declare const getOrphanFlatFieldErrors: (errors: FieldErrors, parentElement: Pick<HTMLElement, 'querySelector'>) => FlatFieldErrors;
@@ -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
+ exports.getOrphanFlatFieldErrors = 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 getOrphanFlatFieldErrors = (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)));
20
+ };
21
+ exports.getOrphanFlatFieldErrors = getOrphanFlatFieldErrors;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Root field errors from form.
3
+ * These are typically displayed at the bottom of the form.
4
+ */
5
+ declare const useRootFormFieldErrors: () => import("@/errors/getFlatFieldErrors").FlatFieldErrors;
6
+ export default useRootFormFieldErrors;
@@ -9,5 +9,5 @@ const utils_1 = require("./utils");
9
9
  * Root field errors from form.
10
10
  * These are typically displayed at the bottom of the form.
11
11
  */
12
- const useFormRootFieldErrors = () => (0, useFormErrorsOnChange_1.default)(utils_1.getRootFieldErrorList);
13
- exports.default = useFormRootFieldErrors;
12
+ const useRootFormFieldErrors = () => (0, useFormErrorsOnChange_1.default)(utils_1.getRootFlatFieldErrors);
13
+ exports.default = useRootFormFieldErrors;
@@ -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
- export declare const getRootFieldErrorList: (errors: FieldErrors) => import("react-hook-form").FieldError[];
8
+ /**
9
+ *
10
+ */
11
+ export declare const getRootFlatFieldErrors: (errors: FieldErrors) => FlatFieldErrors;
@@ -1,7 +1,10 @@
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.getRootFieldErrorList = exports.isFormErrorPathRoot = void 0;
4
- const utils_1 = require("../nonfield/utils");
6
+ exports.getRootFlatFieldErrors = exports.isFormErrorPathRoot = void 0;
7
+ const getFlatFieldErrors_1 = __importDefault(require("../getFlatFieldErrors"));
5
8
  const ROOT = 'root';
6
9
  /**
7
10
  * Determine if an error path is root. (e.g., `root` or `root.nested`)
@@ -9,5 +12,13 @@ const ROOT = 'root';
9
12
  */
10
13
  const isFormErrorPathRoot = (path) => path === ROOT || path.startsWith(ROOT + '.');
11
14
  exports.isFormErrorPathRoot = isFormErrorPathRoot;
12
- const getRootFieldErrorList = (errors) => (0, utils_1.getNonFieldErrorListByFilter)(errors, exports.isFormErrorPathRoot);
13
- exports.getRootFieldErrorList = getRootFieldErrorList;
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,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 useFormErrorsIfAny_1 = __importDefault(require("./useFormErrorsIfAny"));
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, useFormErrorsIfAny_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;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns errors only if there are errors.
3
+ * Allows simple typeguard without `isEmpty` dependency.
4
+ */
5
+ declare const useFormErrorsIfAny: () => false | import("react-hook-form").FieldErrors<import("react-hook-form").FieldValues>;
6
+ export default useFormErrorsIfAny;
@@ -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 useFormErrorsIfAny = () => {
10
+ const { errors } = (0, react_hook_form_1.useFormState)();
11
+ return (0, utils_1.isEmptyObject)(errors) ? false : errors;
12
+ };
13
+ exports.default = useFormErrorsIfAny;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Use {@link FieldErrors} as {@link FlatFieldErrors}.
3
+ */
4
+ declare const useFormFlatFieldErrors: () => import("./getFlatFieldErrors").FlatFieldErrors;
5
+ export default useFormFlatFieldErrors;
@@ -0,0 +1,12 @@
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 getFlatFieldErrors_1 = __importDefault(require("./getFlatFieldErrors"));
7
+ const useFormErrorsOnChange_1 = __importDefault(require("./useFormErrorsOnChange"));
8
+ /**
9
+ * Use {@link FieldErrors} as {@link FlatFieldErrors}.
10
+ */
11
+ const useFormFlatFieldErrors = () => (0, useFormErrorsOnChange_1.default)(getFlatFieldErrors_1.default);
12
+ exports.default = useFormFlatFieldErrors;
@@ -1,8 +1,11 @@
1
1
  export { default as FormNonFieldErrorMarker } from './errors/nonfield/FormNonFieldErrorMarker';
2
- export { FormNonFieldErrorMarkerHtmlAttribute } from './errors/nonfield/FormNonFieldErrorMarker.utils';
3
- export { default as useFormErrorOrphansToConsoleError } from './errors/orphans/useFormErrorOrphansToConsoleError';
4
- export { default as useFormOrphanErrors } from './errors/orphans/useFormOrphanErrors';
5
- export { default as useFormRootFieldErrors } from './errors/root/useFormRootFieldErrors';
2
+ export { default as FormNonFieldErrorMarkerHtmlAttribute } from './errors/nonfield/FormNonFieldErrorMarker.utils';
3
+ export { default as useFormErrorsHasOnlyOrphans } from './errors/orphan/useFormErrorsHasOnlyOrphans';
4
+ export { default as useOrphanFormErrors } from './errors/orphan/useOrphanFormErrors';
5
+ export { default as useOrphanFormErrorsToConsoleError } from './errors/orphan/useOrphanFormErrorsToConsoleError';
6
+ export { default as useRootFormFieldErrors } from './errors/root/useRootFormFieldErrors';
7
+ export { default as useFormErrorConsoleDebug } from './errors/useFormErrorConsoleDebug';
6
8
  export { default as useFormErrorsEffect } from './errors/useFormErrorsEffect';
9
+ export { default as useFormErrorsIfAny } from './errors/useFormErrorsIfAny';
7
10
  export { default as useFormErrorsOnChange } from './errors/useFormErrorsOnChange';
8
11
  export { default as useFormRequestSubmit } from './errors/useFormRequestSubmit';
package/dist/cjs/main.js CHANGED
@@ -3,19 +3,25 @@ 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.FormNonFieldErrorMarkerHtmlAttribute = exports.FormNonFieldErrorMarker = void 0;
6
+ exports.useFormRequestSubmit = exports.useFormErrorsOnChange = exports.useFormErrorsIfAny = exports.useFormErrorsEffect = exports.useFormErrorConsoleDebug = exports.useRootFormFieldErrors = exports.useOrphanFormErrorsToConsoleError = exports.useOrphanFormErrors = exports.useFormErrorsHasOnlyOrphans = exports.FormNonFieldErrorMarkerHtmlAttribute = exports.FormNonFieldErrorMarker = void 0;
7
7
  var FormNonFieldErrorMarker_1 = require("./errors/nonfield/FormNonFieldErrorMarker");
8
8
  Object.defineProperty(exports, "FormNonFieldErrorMarker", { enumerable: true, get: function () { return __importDefault(FormNonFieldErrorMarker_1).default; } });
9
9
  var FormNonFieldErrorMarker_utils_1 = require("./errors/nonfield/FormNonFieldErrorMarker.utils");
10
- Object.defineProperty(exports, "FormNonFieldErrorMarkerHtmlAttribute", { enumerable: true, get: function () { return FormNonFieldErrorMarker_utils_1.FormNonFieldErrorMarkerHtmlAttribute; } });
11
- var useFormErrorOrphansToConsoleError_1 = require("./errors/orphans/useFormErrorOrphansToConsoleError");
12
- Object.defineProperty(exports, "useFormErrorOrphansToConsoleError", { enumerable: true, get: function () { return __importDefault(useFormErrorOrphansToConsoleError_1).default; } });
13
- var useFormOrphanErrors_1 = require("./errors/orphans/useFormOrphanErrors");
14
- Object.defineProperty(exports, "useFormOrphanErrors", { enumerable: true, get: function () { return __importDefault(useFormOrphanErrors_1).default; } });
15
- var useFormRootFieldErrors_1 = require("./errors/root/useFormRootFieldErrors");
16
- Object.defineProperty(exports, "useFormRootFieldErrors", { enumerable: true, get: function () { return __importDefault(useFormRootFieldErrors_1).default; } });
10
+ Object.defineProperty(exports, "FormNonFieldErrorMarkerHtmlAttribute", { enumerable: true, get: function () { return __importDefault(FormNonFieldErrorMarker_utils_1).default; } });
11
+ var useFormErrorsHasOnlyOrphans_1 = require("./errors/orphan/useFormErrorsHasOnlyOrphans");
12
+ Object.defineProperty(exports, "useFormErrorsHasOnlyOrphans", { enumerable: true, get: function () { return __importDefault(useFormErrorsHasOnlyOrphans_1).default; } });
13
+ var useOrphanFormErrors_1 = require("./errors/orphan/useOrphanFormErrors");
14
+ Object.defineProperty(exports, "useOrphanFormErrors", { enumerable: true, get: function () { return __importDefault(useOrphanFormErrors_1).default; } });
15
+ var useOrphanFormErrorsToConsoleError_1 = require("./errors/orphan/useOrphanFormErrorsToConsoleError");
16
+ Object.defineProperty(exports, "useOrphanFormErrorsToConsoleError", { enumerable: true, get: function () { return __importDefault(useOrphanFormErrorsToConsoleError_1).default; } });
17
+ var useRootFormFieldErrors_1 = require("./errors/root/useRootFormFieldErrors");
18
+ Object.defineProperty(exports, "useRootFormFieldErrors", { enumerable: true, get: function () { return __importDefault(useRootFormFieldErrors_1).default; } });
19
+ var useFormErrorConsoleDebug_1 = require("./errors/useFormErrorConsoleDebug");
20
+ Object.defineProperty(exports, "useFormErrorConsoleDebug", { enumerable: true, get: function () { return __importDefault(useFormErrorConsoleDebug_1).default; } });
17
21
  var useFormErrorsEffect_1 = require("./errors/useFormErrorsEffect");
18
22
  Object.defineProperty(exports, "useFormErrorsEffect", { enumerable: true, get: function () { return __importDefault(useFormErrorsEffect_1).default; } });
23
+ var useFormErrorsIfAny_1 = require("./errors/useFormErrorsIfAny");
24
+ Object.defineProperty(exports, "useFormErrorsIfAny", { enumerable: true, get: function () { return __importDefault(useFormErrorsIfAny_1).default; } });
19
25
  var useFormErrorsOnChange_1 = require("./errors/useFormErrorsOnChange");
20
26
  Object.defineProperty(exports, "useFormErrorsOnChange", { enumerable: true, get: function () { return __importDefault(useFormErrorsOnChange_1).default; } });
21
27
  var useFormRequestSubmit_1 = require("./errors/useFormRequestSubmit");
@@ -0,0 +1 @@
1
+ export declare const isEmptyObject: (obj: Record<string, unknown>) => boolean;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEmptyObject = void 0;
4
+ const isEmptyObject = (obj) => JSON.stringify(obj) === '{}';
5
+ exports.isEmptyObject = isEmptyObject;
@@ -0,0 +1,5 @@
1
+ import { flatten as r } from "flat";
2
+ const o = (t) => r(t);
3
+ export {
4
+ o as default
5
+ };
@@ -0,0 +1,21 @@
1
+ import { get as l } from "react-hook-form";
2
+ import d from "./flattenFieldErrors.mjs";
3
+ const f = (e) => {
4
+ const s = d(e), c = Object.keys(s);
5
+ return Object.fromEntries(
6
+ c.reduce(
7
+ (t, o) => {
8
+ const r = o.replace(a, "");
9
+ if (r === o)
10
+ return t;
11
+ const n = l(e, r, void 0);
12
+ return n && t.push([r, n]), t;
13
+ },
14
+ []
15
+ // entries
16
+ )
17
+ );
18
+ }, u = f, a = /\.type$/;
19
+ export {
20
+ u as default
21
+ };