@4riders/reform 3.0.24
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/LICENSE +21 -0
- package/README.md +266 -0
- package/dist/index.d.ts +2715 -0
- package/dist/index.es.js +1715 -0
- package/dist/index.es.js.map +1 -0
- package/package.json +70 -0
- package/src/index.ts +90 -0
- package/src/reform/ArrayHelper.ts +164 -0
- package/src/reform/Form.tsx +81 -0
- package/src/reform/FormManager.ts +494 -0
- package/src/reform/Reform.ts +15 -0
- package/src/reform/components/BaseCheckboxField.tsx +72 -0
- package/src/reform/components/BaseDateField.tsx +84 -0
- package/src/reform/components/BaseRadioField.tsx +72 -0
- package/src/reform/components/BaseSelectField.tsx +103 -0
- package/src/reform/components/BaseTextAreaField.tsx +87 -0
- package/src/reform/components/BaseTextField.tsx +135 -0
- package/src/reform/components/InputHTMLProps.tsx +89 -0
- package/src/reform/observers/observer.ts +131 -0
- package/src/reform/observers/observerPath.ts +327 -0
- package/src/reform/observers/useObservers.ts +232 -0
- package/src/reform/useForm.ts +246 -0
- package/src/reform/useFormContext.tsx +37 -0
- package/src/reform/useFormField.ts +75 -0
- package/src/reform/useRender.ts +12 -0
- package/src/yop/MessageProvider.ts +204 -0
- package/src/yop/Metadata.ts +304 -0
- package/src/yop/ObjectsUtil.ts +811 -0
- package/src/yop/TypesUtil.ts +148 -0
- package/src/yop/ValidationContext.ts +207 -0
- package/src/yop/Yop.ts +430 -0
- package/src/yop/constraints/CommonConstraints.ts +124 -0
- package/src/yop/constraints/Constraint.ts +135 -0
- package/src/yop/constraints/MinMaxConstraints.ts +53 -0
- package/src/yop/constraints/OneOfConstraint.ts +40 -0
- package/src/yop/constraints/TestConstraint.ts +176 -0
- package/src/yop/decorators/array.ts +157 -0
- package/src/yop/decorators/boolean.ts +69 -0
- package/src/yop/decorators/date.ts +73 -0
- package/src/yop/decorators/email.ts +66 -0
- package/src/yop/decorators/file.ts +69 -0
- package/src/yop/decorators/id.ts +35 -0
- package/src/yop/decorators/ignored.ts +40 -0
- package/src/yop/decorators/instance.ts +110 -0
- package/src/yop/decorators/number.ts +73 -0
- package/src/yop/decorators/string.ts +90 -0
- package/src/yop/decorators/test.ts +41 -0
- package/src/yop/decorators/time.ts +112 -0
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@4riders/reform",
|
|
3
|
+
"version": "3.0.24",
|
|
4
|
+
"description": "Reform is a powerful, type-safe, and extensible validation and form management library for TypeScript and React",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "./dist/index.es.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"registry": "https://registry.npmjs.org/"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/4riders/reform#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/4riders/reform.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/4riders/reform/issues"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"react",
|
|
24
|
+
"form",
|
|
25
|
+
"typescript"
|
|
26
|
+
],
|
|
27
|
+
"author": "Franck Wolff <franck.wolff@4riders.net>",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src"
|
|
31
|
+
],
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"import": "./dist/index.es.js",
|
|
35
|
+
"types": "./dist/index.d.ts"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc && vite build",
|
|
40
|
+
"test": "vitest --run",
|
|
41
|
+
"prepublishOnly": "NODE_ENV=release tsc && vite build",
|
|
42
|
+
"typedoc": "typedoc --options typedoc.json"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": ">=18",
|
|
46
|
+
"react-dom": ">=18"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@babel/core": "^7.29.0",
|
|
50
|
+
"@babel/plugin-proposal-decorators": "^7.29.0",
|
|
51
|
+
"@rolldown/plugin-babel": "^0.2.2",
|
|
52
|
+
"@testing-library/dom": "^10.4.1",
|
|
53
|
+
"@testing-library/react": "^16.3.2",
|
|
54
|
+
"@types/babel__core": "^7.20.5",
|
|
55
|
+
"@types/node": "^25.5.0",
|
|
56
|
+
"@types/react": "^18.3.28",
|
|
57
|
+
"@types/react-dom": "^18.3.7",
|
|
58
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
59
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
60
|
+
"jsdom": "^29.0.1",
|
|
61
|
+
"react": "^18.3.1",
|
|
62
|
+
"react-dom": "^18.3.1",
|
|
63
|
+
"typedoc": "^0.28.18",
|
|
64
|
+
"typescript": "^6.0.2",
|
|
65
|
+
"vite": "^8.0.3",
|
|
66
|
+
"vite-plugin-dts": "^4.5.4",
|
|
67
|
+
"vitest": "^4.1.2"
|
|
68
|
+
},
|
|
69
|
+
"packageManager": "yarn@4.13.0"
|
|
70
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* @categoryDescription Property Decorators
|
|
5
|
+
* Property decorators are a powerful feature in Javascript that allow you to annotate and modify the behavior of class properties.
|
|
6
|
+
* In the context of form management, property decorators can be used to define metadata for form fields, such as validation rules,
|
|
7
|
+
* input types, or custom behavior. By applying decorators to your form model classes, you can easily specify how each field should
|
|
8
|
+
* be handled without having to write additional boilerplate code. This makes it easier to maintain and extend your form models as your
|
|
9
|
+
* application grows.
|
|
10
|
+
*
|
|
11
|
+
* @categoryDescription Class Decorators
|
|
12
|
+
* Class decorators are a type of decorator in JavaScript that can be applied to classes to modify their behavior or add metadata.
|
|
13
|
+
* In the context of form management, class decorators can be used to define metadata for form models, such as validation rules.
|
|
14
|
+
*
|
|
15
|
+
* @categoryDescription Shared Constraints
|
|
16
|
+
* Shared constraints are common validation rules that can be applied to form fields or entire form models. They define the conditions
|
|
17
|
+
* that the field values must satisfy in order to be considered valid. Constraints can be simple, such as checking if a value is required
|
|
18
|
+
* or if it falls within a certain range, or they can be complex, involving custom logic that depends on multiple fields.
|
|
19
|
+
*
|
|
20
|
+
* @categoryDescription Observers
|
|
21
|
+
* Observers allow you to react to changes in other fields by specifying a path to observe and a callback function that
|
|
22
|
+
* receives context about the change. The observer paths support a flexible syntax for targeting specific fields, including
|
|
23
|
+
* wildcards, absolute and relative paths.
|
|
24
|
+
*
|
|
25
|
+
* @categoryDescription Form Management
|
|
26
|
+
* Form management involves handling the state and behavior of forms in a web application. This includes managing form data, validation,
|
|
27
|
+
* and user interactions. A form management library can provide tools and utilities to simplify these tasks, allowing developers to
|
|
28
|
+
* focus on building the user interface and business logic of their applications.
|
|
29
|
+
*
|
|
30
|
+
* @categoryDescription Base Inputs Components
|
|
31
|
+
* Base input components are reusable building blocks for creating form fields in a web application. They provide a consistent interface and
|
|
32
|
+
* behavior for common input types, such as text fields, checkboxes, radio buttons, and select dropdowns.
|
|
33
|
+
*
|
|
34
|
+
* @categoryDescription Validation Management
|
|
35
|
+
* Validation management involves defining and enforcing rules for validating form data. This can include simple checks, such as ensuring
|
|
36
|
+
* that a field is not empty, as well as more complex rules that involve multiple fields or custom logic.
|
|
37
|
+
*
|
|
38
|
+
* @categoryDescription Localization
|
|
39
|
+
* Localization is the process of adapting a product or content to a specific locale or market. In the context of form management, localization
|
|
40
|
+
* involves providing translations for error messages.
|
|
41
|
+
*
|
|
42
|
+
* @categoryDescription Utilities
|
|
43
|
+
* Utilities are helper functions or classes that provide common functionality that can be reused across different parts of an application. In the
|
|
44
|
+
* context of form management, utilities include functions for manipulating and comparing form data.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
export * from "./reform/ArrayHelper"
|
|
48
|
+
export * from "./reform/Form"
|
|
49
|
+
export * from "./reform/FormManager"
|
|
50
|
+
export * from "./reform/observers/observer"
|
|
51
|
+
export * from "./reform/observers/useObservers"
|
|
52
|
+
export * from "./reform/Reform"
|
|
53
|
+
export * from "./reform/useForm"
|
|
54
|
+
export * from "./reform/useFormContext"
|
|
55
|
+
export * from "./reform/useFormField"
|
|
56
|
+
export * from "./reform/useRender"
|
|
57
|
+
|
|
58
|
+
export * from "./reform/components/BaseCheckboxField"
|
|
59
|
+
export * from "./reform/components/BaseDateField"
|
|
60
|
+
export * from "./reform/components/BaseRadioField"
|
|
61
|
+
export * from "./reform/components/BaseSelectField"
|
|
62
|
+
export * from "./reform/components/BaseTextAreaField"
|
|
63
|
+
export * from "./reform/components/BaseTextField"
|
|
64
|
+
export * from "./reform/components/InputHTMLProps"
|
|
65
|
+
|
|
66
|
+
export * from "./yop/constraints/CommonConstraints"
|
|
67
|
+
export * from "./yop/constraints/Constraint"
|
|
68
|
+
export * from "./yop/constraints/MinMaxConstraints"
|
|
69
|
+
export * from "./yop/constraints/OneOfConstraint"
|
|
70
|
+
export * from "./yop/constraints/TestConstraint"
|
|
71
|
+
|
|
72
|
+
export * from "./yop/decorators/array"
|
|
73
|
+
export * from "./yop/decorators/boolean"
|
|
74
|
+
export * from "./yop/decorators/date"
|
|
75
|
+
export * from "./yop/decorators/email"
|
|
76
|
+
export * from "./yop/decorators/file"
|
|
77
|
+
export * from "./yop/decorators/id"
|
|
78
|
+
export * from "./yop/decorators/ignored"
|
|
79
|
+
export * from "./yop/decorators/instance"
|
|
80
|
+
export * from "./yop/decorators/number"
|
|
81
|
+
export * from "./yop/decorators/string"
|
|
82
|
+
export * from "./yop/decorators/test"
|
|
83
|
+
export * from "./yop/decorators/time"
|
|
84
|
+
|
|
85
|
+
export * from "./yop/MessageProvider"
|
|
86
|
+
export * from "./yop/Metadata"
|
|
87
|
+
export * from "./yop/ObjectsUtil"
|
|
88
|
+
export * from "./yop/TypesUtil"
|
|
89
|
+
export * from "./yop/ValidationContext"
|
|
90
|
+
export * from "./yop/Yop"
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Path } from "../yop/ObjectsUtil"
|
|
2
|
+
import { FormManager, InternalFormManager } from "./FormManager"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Utility class for manipulating array fields in a form model, with automatic touch, validation, and rendering. See {@link FormManager.array} for details.
|
|
6
|
+
* @template T - The type of array elements.
|
|
7
|
+
* @category Form Management
|
|
8
|
+
*/
|
|
9
|
+
export class ArrayHelper<T = any> {
|
|
10
|
+
|
|
11
|
+
private array: T[] | undefined
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates an ArrayHelper for a given form and path.
|
|
15
|
+
* @param form - The form manager instance.
|
|
16
|
+
* @param path - The path to the array field in the form.
|
|
17
|
+
*/
|
|
18
|
+
constructor(readonly form: InternalFormManager<any>, readonly path: string | Path) {
|
|
19
|
+
this.array = form.getValue<T[]>(path)
|
|
20
|
+
if (!Array.isArray(this.array))
|
|
21
|
+
this.array = undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Tells if the field at the given path was an array.
|
|
26
|
+
* @returns True if the field was an array, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
isArray() {
|
|
29
|
+
return this.array != null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Appends an element to the array.
|
|
34
|
+
* @param element - The element to append.
|
|
35
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
36
|
+
*/
|
|
37
|
+
append(element: T, commit = true) {
|
|
38
|
+
this.array!.push(element)
|
|
39
|
+
this.form.touch(this.path)
|
|
40
|
+
this.commit(commit)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Replaces the element at the given index.
|
|
45
|
+
* @param index - The index to replace.
|
|
46
|
+
* @param element - The new element.
|
|
47
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
48
|
+
*/
|
|
49
|
+
replace(index: number, element: T, commit = true) {
|
|
50
|
+
this.array![index] = element
|
|
51
|
+
const touched = this.form.getTouchedValue<any[]>(this.path)
|
|
52
|
+
if (touched == null)
|
|
53
|
+
this.form.touch(this.path)
|
|
54
|
+
else if (Array.isArray(touched))
|
|
55
|
+
touched[index] = undefined
|
|
56
|
+
this.commit(commit)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Inserts an element at the given index.
|
|
61
|
+
* @param index - The index to insert at.
|
|
62
|
+
* @param element - The element to insert.
|
|
63
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
64
|
+
*/
|
|
65
|
+
insert(index: number, element: T, commit = true) {
|
|
66
|
+
this.array!.splice(index, 0, element)
|
|
67
|
+
const touched = this.form.getTouchedValue<any[]>(this.path)
|
|
68
|
+
if (touched == null)
|
|
69
|
+
this.form.touch(this.path)
|
|
70
|
+
else if (Array.isArray(touched))
|
|
71
|
+
touched.splice(index, 0, undefined)
|
|
72
|
+
this.commit(commit)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Removes the element at the given index.
|
|
77
|
+
* @param index - The index to remove.
|
|
78
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
79
|
+
*/
|
|
80
|
+
remove(index: number, commit = true) {
|
|
81
|
+
this.array!.splice(index, 1)
|
|
82
|
+
const touched = this.form.getTouchedValue<any[]>(this.path)
|
|
83
|
+
if (touched == null)
|
|
84
|
+
this.form.touch(this.path)
|
|
85
|
+
else if (Array.isArray(touched))
|
|
86
|
+
touched.splice(index, 1)
|
|
87
|
+
this.commit(commit)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Swaps two elements in the array.
|
|
92
|
+
* @param index1 - The first index.
|
|
93
|
+
* @param index2 - The second index.
|
|
94
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
95
|
+
*/
|
|
96
|
+
swap(index1: number, index2: number, commit = true) {
|
|
97
|
+
const action = <T>(array: T[]) => {
|
|
98
|
+
const value1 = array[index1]
|
|
99
|
+
array[index1] = array[index2]
|
|
100
|
+
array[index2] = value1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
action(this.array!)
|
|
104
|
+
const touched = this.form.getTouchedValue<any[]>(this.path)
|
|
105
|
+
if (touched == null)
|
|
106
|
+
this.form.touch(this.path)
|
|
107
|
+
else if (Array.isArray(touched))
|
|
108
|
+
action(touched)
|
|
109
|
+
this.commit(commit)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Moves an element from one index to another.
|
|
114
|
+
* @param from - The source index.
|
|
115
|
+
* @param to - The destination index.
|
|
116
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
117
|
+
*/
|
|
118
|
+
move(from: number, to: number, commit = true) {
|
|
119
|
+
if (from !== to) {
|
|
120
|
+
const action = from < to ?
|
|
121
|
+
<T>(array: T[]) => {
|
|
122
|
+
const fromElement = array[from]
|
|
123
|
+
for (let i = from; i < to; i++)
|
|
124
|
+
array[i] = array[i + 1]
|
|
125
|
+
array[to] = fromElement
|
|
126
|
+
} :
|
|
127
|
+
<T>(array: T[]) => {
|
|
128
|
+
const toElement = array[to]
|
|
129
|
+
for (let i = to; i > from; i--)
|
|
130
|
+
array[i + 1] = array[i]
|
|
131
|
+
array[from] = toElement
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
action(this.array!)
|
|
135
|
+
const touched = this.form.getTouchedValue<any[]>(this.path)
|
|
136
|
+
if (touched == null)
|
|
137
|
+
this.form.touch(this.path)
|
|
138
|
+
else if (Array.isArray(touched))
|
|
139
|
+
action(touched)
|
|
140
|
+
this.commit(commit)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Removes all elements from the array.
|
|
146
|
+
* @param commit - Whether to validate and render after the operation (default: true).
|
|
147
|
+
*/
|
|
148
|
+
clear(commit = true) {
|
|
149
|
+
this.array!.splice(0, this.array!.length)
|
|
150
|
+
this.form.setTouchedValue(this.path, true)
|
|
151
|
+
this.commit(commit)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Validates and renders the form if value is true.
|
|
156
|
+
* @param value - Whether to commit (validate and render).
|
|
157
|
+
*/
|
|
158
|
+
private commit(value: boolean) {
|
|
159
|
+
if (value) {
|
|
160
|
+
this.form.validate()
|
|
161
|
+
this.form.render()
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { FormHTMLAttributes, useCallback } from "react"
|
|
2
|
+
import { FormContext } from "./useFormContext"
|
|
3
|
+
import React from "react"
|
|
4
|
+
import { renderToStaticMarkup } from "react-dom/server"
|
|
5
|
+
import { FormManager, InternalFormManager } from "./FormManager"
|
|
6
|
+
import { ValidationStatus } from "../yop/ValidationContext"
|
|
7
|
+
import { Reform } from "./Reform"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Props for the Form component.
|
|
11
|
+
* @property form - The form manager instance.
|
|
12
|
+
* @property disabled - Whether the form is disabled.
|
|
13
|
+
* @category Form Management
|
|
14
|
+
*/
|
|
15
|
+
export interface FormProps extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
|
|
16
|
+
|
|
17
|
+
/** The form manager instance. */
|
|
18
|
+
form: FormManager<unknown>
|
|
19
|
+
/** Whether the form is disabled. */
|
|
20
|
+
disabled?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* React component for rendering an HTML form with context, error display, and automatic form disabling. All children of
|
|
25
|
+
* this component will have access to the form manager via context, and they will be enclosed in an HTML `fieldset` that is disabled according to the
|
|
26
|
+
* `disabled` prop. If there are any validation errors, and if the debug option `displayFormErrors` is enabled (see {@link Reform.displayFormErrors}),
|
|
27
|
+
* they will be displayed in a formatted block below the form.
|
|
28
|
+
*
|
|
29
|
+
* Example usage:
|
|
30
|
+
* ```tsx
|
|
31
|
+
* const form = useForm(MyFormModel, onSubmit)
|
|
32
|
+
* return (
|
|
33
|
+
* <Form form={form} autoComplete="off" noValidate disabled={form.submitting}>
|
|
34
|
+
* // form fields here, using form context
|
|
35
|
+
* <button type="submit">Submit</button>
|
|
36
|
+
* </Form>
|
|
37
|
+
* )
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @param props - The Form props.
|
|
41
|
+
* @returns The rendered Form component.
|
|
42
|
+
* @category Form Management
|
|
43
|
+
*/
|
|
44
|
+
export function Form(props: FormProps) {
|
|
45
|
+
const { form, children, disabled, ...formAttrs } = props
|
|
46
|
+
|
|
47
|
+
const formRef = useCallback((htmlForm: HTMLFormElement) => {
|
|
48
|
+
(form as InternalFormManager<any>).htmlForm = htmlForm
|
|
49
|
+
}, [form])
|
|
50
|
+
|
|
51
|
+
const errors = new Map<string, ValidationStatus>([...form.statuses].filter(([_, status]) => status.level === "error"))
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<FormContext.Provider value={ form }>
|
|
55
|
+
<form ref={ formRef } onSubmit={ (e) => form.submit(e) } { ...formAttrs }>
|
|
56
|
+
<fieldset disabled={ disabled }>{ children }</fieldset>
|
|
57
|
+
|
|
58
|
+
{ errors.size > 0 && Reform.displayFormErrors &&
|
|
59
|
+
<div style={{
|
|
60
|
+
all: "initial",
|
|
61
|
+
display: "block",
|
|
62
|
+
marginTop: "1em",
|
|
63
|
+
padding: "1em",
|
|
64
|
+
fontFamily: "monospace",
|
|
65
|
+
border: "2px solid firebrick",
|
|
66
|
+
borderInline: "2px solid firebrick",
|
|
67
|
+
color: "firebrick",
|
|
68
|
+
background: "white",
|
|
69
|
+
whiteSpace: "pre-wrap"
|
|
70
|
+
}}>
|
|
71
|
+
{ JSON.stringify(
|
|
72
|
+
Object.fromEntries(errors.entries()),
|
|
73
|
+
(key, value) => key === "message" && React.isValidElement(value) ? renderToStaticMarkup(value) : value,
|
|
74
|
+
4
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
}
|
|
78
|
+
</form>
|
|
79
|
+
</FormContext.Provider>
|
|
80
|
+
)
|
|
81
|
+
}
|