@rjsf/core 5.24.5 → 5.24.8

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 (224) hide show
  1. package/dist/core.umd.js +602 -601
  2. package/dist/index.esm.js +602 -601
  3. package/dist/index.esm.js.map +2 -2
  4. package/dist/index.js +602 -601
  5. package/dist/index.js.map +2 -2
  6. package/lib/components/Form.d.ts +1 -0
  7. package/lib/components/Form.d.ts.map +1 -0
  8. package/lib/components/Form.js +293 -293
  9. package/lib/components/fields/ArrayField.d.ts +1 -0
  10. package/lib/components/fields/ArrayField.d.ts.map +1 -0
  11. package/lib/components/fields/ArrayField.js +190 -194
  12. package/lib/components/fields/BooleanField.d.ts +1 -0
  13. package/lib/components/fields/BooleanField.d.ts.map +1 -0
  14. package/lib/components/fields/BooleanField.js +3 -5
  15. package/lib/components/fields/MultiSchemaField.d.ts +1 -0
  16. package/lib/components/fields/MultiSchemaField.d.ts.map +1 -0
  17. package/lib/components/fields/MultiSchemaField.js +30 -31
  18. package/lib/components/fields/NullField.d.ts +1 -0
  19. package/lib/components/fields/NullField.d.ts.map +1 -0
  20. package/lib/components/fields/NullField.js +0 -1
  21. package/lib/components/fields/NumberField.d.ts +1 -0
  22. package/lib/components/fields/NumberField.d.ts.map +1 -0
  23. package/lib/components/fields/NumberField.js +0 -1
  24. package/lib/components/fields/ObjectField.d.ts +1 -0
  25. package/lib/components/fields/ObjectField.d.ts.map +1 -0
  26. package/lib/components/fields/ObjectField.js +139 -145
  27. package/lib/components/fields/SchemaField.d.ts +1 -0
  28. package/lib/components/fields/SchemaField.d.ts.map +1 -0
  29. package/lib/components/fields/SchemaField.js +7 -9
  30. package/lib/components/fields/StringField.d.ts +1 -0
  31. package/lib/components/fields/StringField.d.ts.map +1 -0
  32. package/lib/components/fields/StringField.js +1 -3
  33. package/lib/components/fields/index.d.ts +1 -0
  34. package/lib/components/fields/index.d.ts.map +1 -0
  35. package/lib/components/fields/index.js +8 -9
  36. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +1 -0
  37. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts.map +1 -0
  38. package/lib/components/templates/ArrayFieldDescriptionTemplate.js +0 -1
  39. package/lib/components/templates/ArrayFieldItemTemplate.d.ts +1 -0
  40. package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -0
  41. package/lib/components/templates/ArrayFieldItemTemplate.js +0 -1
  42. package/lib/components/templates/ArrayFieldTemplate.d.ts +1 -0
  43. package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -0
  44. package/lib/components/templates/ArrayFieldTemplate.js +0 -1
  45. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -0
  46. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -0
  47. package/lib/components/templates/ArrayFieldTitleTemplate.js +0 -1
  48. package/lib/components/templates/BaseInputTemplate.d.ts +1 -0
  49. package/lib/components/templates/BaseInputTemplate.d.ts.map +1 -0
  50. package/lib/components/templates/BaseInputTemplate.js +0 -1
  51. package/lib/components/templates/ButtonTemplates/AddButton.d.ts +1 -0
  52. package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -0
  53. package/lib/components/templates/ButtonTemplates/AddButton.js +1 -2
  54. package/lib/components/templates/ButtonTemplates/IconButton.d.ts +1 -0
  55. package/lib/components/templates/ButtonTemplates/IconButton.d.ts.map +1 -0
  56. package/lib/components/templates/ButtonTemplates/IconButton.js +0 -1
  57. package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts +1 -0
  58. package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts.map +1 -0
  59. package/lib/components/templates/ButtonTemplates/SubmitButton.js +0 -1
  60. package/lib/components/templates/ButtonTemplates/index.d.ts +1 -0
  61. package/lib/components/templates/ButtonTemplates/index.d.ts.map +1 -0
  62. package/lib/components/templates/ButtonTemplates/index.js +3 -4
  63. package/lib/components/templates/DescriptionField.d.ts +1 -0
  64. package/lib/components/templates/DescriptionField.d.ts.map +1 -0
  65. package/lib/components/templates/DescriptionField.js +0 -1
  66. package/lib/components/templates/ErrorList.d.ts +1 -0
  67. package/lib/components/templates/ErrorList.d.ts.map +1 -0
  68. package/lib/components/templates/ErrorList.js +0 -1
  69. package/lib/components/templates/FieldErrorTemplate.d.ts +1 -0
  70. package/lib/components/templates/FieldErrorTemplate.d.ts.map +1 -0
  71. package/lib/components/templates/FieldErrorTemplate.js +0 -1
  72. package/lib/components/templates/FieldHelpTemplate.d.ts +1 -0
  73. package/lib/components/templates/FieldHelpTemplate.d.ts.map +1 -0
  74. package/lib/components/templates/FieldHelpTemplate.js +0 -1
  75. package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts +1 -0
  76. package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts.map +1 -0
  77. package/lib/components/templates/FieldTemplate/FieldTemplate.js +1 -2
  78. package/lib/components/templates/FieldTemplate/Label.d.ts +1 -0
  79. package/lib/components/templates/FieldTemplate/Label.d.ts.map +1 -0
  80. package/lib/components/templates/FieldTemplate/Label.js +0 -1
  81. package/lib/components/templates/FieldTemplate/index.d.ts +2 -1
  82. package/lib/components/templates/FieldTemplate/index.d.ts.map +1 -0
  83. package/lib/components/templates/FieldTemplate/index.js +1 -2
  84. package/lib/components/templates/ObjectFieldTemplate.d.ts +1 -0
  85. package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -0
  86. package/lib/components/templates/ObjectFieldTemplate.js +0 -1
  87. package/lib/components/templates/TitleField.d.ts +1 -0
  88. package/lib/components/templates/TitleField.d.ts.map +1 -0
  89. package/lib/components/templates/TitleField.js +0 -1
  90. package/lib/components/templates/UnsupportedField.d.ts +1 -0
  91. package/lib/components/templates/UnsupportedField.d.ts.map +1 -0
  92. package/lib/components/templates/UnsupportedField.js +0 -1
  93. package/lib/components/templates/WrapIfAdditionalTemplate.d.ts +1 -0
  94. package/lib/components/templates/WrapIfAdditionalTemplate.d.ts.map +1 -0
  95. package/lib/components/templates/WrapIfAdditionalTemplate.js +1 -2
  96. package/lib/components/templates/index.d.ts +1 -0
  97. package/lib/components/templates/index.d.ts.map +1 -0
  98. package/lib/components/templates/index.js +15 -16
  99. package/lib/components/widgets/AltDateTimeWidget.d.ts +1 -0
  100. package/lib/components/widgets/AltDateTimeWidget.d.ts.map +1 -0
  101. package/lib/components/widgets/AltDateTimeWidget.js +0 -1
  102. package/lib/components/widgets/AltDateWidget.d.ts +1 -0
  103. package/lib/components/widgets/AltDateWidget.d.ts.map +1 -0
  104. package/lib/components/widgets/AltDateWidget.js +0 -1
  105. package/lib/components/widgets/CheckboxWidget.d.ts +1 -0
  106. package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -0
  107. package/lib/components/widgets/CheckboxWidget.js +1 -3
  108. package/lib/components/widgets/CheckboxesWidget.d.ts +1 -0
  109. package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -0
  110. package/lib/components/widgets/CheckboxesWidget.js +0 -1
  111. package/lib/components/widgets/ColorWidget.d.ts +1 -0
  112. package/lib/components/widgets/ColorWidget.d.ts.map +1 -0
  113. package/lib/components/widgets/ColorWidget.js +0 -1
  114. package/lib/components/widgets/DateTimeWidget.d.ts +1 -0
  115. package/lib/components/widgets/DateTimeWidget.d.ts.map +1 -0
  116. package/lib/components/widgets/DateTimeWidget.js +0 -1
  117. package/lib/components/widgets/DateWidget.d.ts +1 -0
  118. package/lib/components/widgets/DateWidget.d.ts.map +1 -0
  119. package/lib/components/widgets/DateWidget.js +0 -1
  120. package/lib/components/widgets/EmailWidget.d.ts +1 -0
  121. package/lib/components/widgets/EmailWidget.d.ts.map +1 -0
  122. package/lib/components/widgets/EmailWidget.js +0 -1
  123. package/lib/components/widgets/FileWidget.d.ts +1 -0
  124. package/lib/components/widgets/FileWidget.d.ts.map +1 -0
  125. package/lib/components/widgets/FileWidget.js +1 -3
  126. package/lib/components/widgets/HiddenWidget.d.ts +1 -0
  127. package/lib/components/widgets/HiddenWidget.d.ts.map +1 -0
  128. package/lib/components/widgets/HiddenWidget.js +0 -1
  129. package/lib/components/widgets/PasswordWidget.d.ts +1 -0
  130. package/lib/components/widgets/PasswordWidget.d.ts.map +1 -0
  131. package/lib/components/widgets/PasswordWidget.js +0 -1
  132. package/lib/components/widgets/RadioWidget.d.ts +1 -0
  133. package/lib/components/widgets/RadioWidget.d.ts.map +1 -0
  134. package/lib/components/widgets/RadioWidget.js +0 -1
  135. package/lib/components/widgets/RangeWidget.d.ts +1 -0
  136. package/lib/components/widgets/RangeWidget.d.ts.map +1 -0
  137. package/lib/components/widgets/RangeWidget.js +0 -1
  138. package/lib/components/widgets/SelectWidget.d.ts +1 -0
  139. package/lib/components/widgets/SelectWidget.d.ts.map +1 -0
  140. package/lib/components/widgets/SelectWidget.js +0 -1
  141. package/lib/components/widgets/TextWidget.d.ts +1 -0
  142. package/lib/components/widgets/TextWidget.d.ts.map +1 -0
  143. package/lib/components/widgets/TextWidget.js +0 -1
  144. package/lib/components/widgets/TextareaWidget.d.ts +1 -0
  145. package/lib/components/widgets/TextareaWidget.d.ts.map +1 -0
  146. package/lib/components/widgets/TextareaWidget.js +0 -1
  147. package/lib/components/widgets/TimeWidget.d.ts +1 -0
  148. package/lib/components/widgets/TimeWidget.d.ts.map +1 -0
  149. package/lib/components/widgets/TimeWidget.js +0 -1
  150. package/lib/components/widgets/URLWidget.d.ts +1 -0
  151. package/lib/components/widgets/URLWidget.d.ts.map +1 -0
  152. package/lib/components/widgets/URLWidget.js +0 -1
  153. package/lib/components/widgets/UpDownWidget.d.ts +1 -0
  154. package/lib/components/widgets/UpDownWidget.d.ts.map +1 -0
  155. package/lib/components/widgets/UpDownWidget.js +0 -1
  156. package/lib/components/widgets/index.d.ts +1 -0
  157. package/lib/components/widgets/index.d.ts.map +1 -0
  158. package/lib/components/widgets/index.js +19 -20
  159. package/lib/getDefaultRegistry.d.ts +1 -0
  160. package/lib/getDefaultRegistry.d.ts.map +1 -0
  161. package/lib/getDefaultRegistry.js +3 -4
  162. package/lib/index.d.ts +4 -3
  163. package/lib/index.d.ts.map +1 -0
  164. package/lib/index.js +3 -4
  165. package/lib/tsconfig.tsbuildinfo +1 -1
  166. package/lib/withTheme.d.ts +2 -1
  167. package/lib/withTheme.d.ts.map +1 -0
  168. package/lib/withTheme.js +6 -8
  169. package/package.json +31 -9
  170. package/src/tsconfig.json +14 -3
  171. package/lib/components/Form.js.map +0 -1
  172. package/lib/components/fields/ArrayField.js.map +0 -1
  173. package/lib/components/fields/BooleanField.js.map +0 -1
  174. package/lib/components/fields/MultiSchemaField.js.map +0 -1
  175. package/lib/components/fields/NullField.js.map +0 -1
  176. package/lib/components/fields/NumberField.js.map +0 -1
  177. package/lib/components/fields/ObjectField.js.map +0 -1
  178. package/lib/components/fields/SchemaField.js.map +0 -1
  179. package/lib/components/fields/StringField.js.map +0 -1
  180. package/lib/components/fields/index.js.map +0 -1
  181. package/lib/components/templates/ArrayFieldDescriptionTemplate.js.map +0 -1
  182. package/lib/components/templates/ArrayFieldItemTemplate.js.map +0 -1
  183. package/lib/components/templates/ArrayFieldTemplate.js.map +0 -1
  184. package/lib/components/templates/ArrayFieldTitleTemplate.js.map +0 -1
  185. package/lib/components/templates/BaseInputTemplate.js.map +0 -1
  186. package/lib/components/templates/ButtonTemplates/AddButton.js.map +0 -1
  187. package/lib/components/templates/ButtonTemplates/IconButton.js.map +0 -1
  188. package/lib/components/templates/ButtonTemplates/SubmitButton.js.map +0 -1
  189. package/lib/components/templates/ButtonTemplates/index.js.map +0 -1
  190. package/lib/components/templates/DescriptionField.js.map +0 -1
  191. package/lib/components/templates/ErrorList.js.map +0 -1
  192. package/lib/components/templates/FieldErrorTemplate.js.map +0 -1
  193. package/lib/components/templates/FieldHelpTemplate.js.map +0 -1
  194. package/lib/components/templates/FieldTemplate/FieldTemplate.js.map +0 -1
  195. package/lib/components/templates/FieldTemplate/Label.js.map +0 -1
  196. package/lib/components/templates/FieldTemplate/index.js.map +0 -1
  197. package/lib/components/templates/ObjectFieldTemplate.js.map +0 -1
  198. package/lib/components/templates/TitleField.js.map +0 -1
  199. package/lib/components/templates/UnsupportedField.js.map +0 -1
  200. package/lib/components/templates/WrapIfAdditionalTemplate.js.map +0 -1
  201. package/lib/components/templates/index.js.map +0 -1
  202. package/lib/components/widgets/AltDateTimeWidget.js.map +0 -1
  203. package/lib/components/widgets/AltDateWidget.js.map +0 -1
  204. package/lib/components/widgets/CheckboxWidget.js.map +0 -1
  205. package/lib/components/widgets/CheckboxesWidget.js.map +0 -1
  206. package/lib/components/widgets/ColorWidget.js.map +0 -1
  207. package/lib/components/widgets/DateTimeWidget.js.map +0 -1
  208. package/lib/components/widgets/DateWidget.js.map +0 -1
  209. package/lib/components/widgets/EmailWidget.js.map +0 -1
  210. package/lib/components/widgets/FileWidget.js.map +0 -1
  211. package/lib/components/widgets/HiddenWidget.js.map +0 -1
  212. package/lib/components/widgets/PasswordWidget.js.map +0 -1
  213. package/lib/components/widgets/RadioWidget.js.map +0 -1
  214. package/lib/components/widgets/RangeWidget.js.map +0 -1
  215. package/lib/components/widgets/SelectWidget.js.map +0 -1
  216. package/lib/components/widgets/TextWidget.js.map +0 -1
  217. package/lib/components/widgets/TextareaWidget.js.map +0 -1
  218. package/lib/components/widgets/TimeWidget.js.map +0 -1
  219. package/lib/components/widgets/URLWidget.js.map +0 -1
  220. package/lib/components/widgets/UpDownWidget.js.map +0 -1
  221. package/lib/components/widgets/index.js.map +0 -1
  222. package/lib/getDefaultRegistry.js.map +0 -1
  223. package/lib/index.js.map +0 -1
  224. package/lib/withTheme.js.map +0 -1
package/dist/core.umd.js CHANGED
@@ -29,189 +29,6 @@
29
29
  */
30
30
  constructor(props) {
31
31
  super(props);
32
- /** Returns the default form information for an item based on the schema for that item. Deals with the possibility
33
- * that the schema is fixed and allows additional items.
34
- */
35
- this._getNewFormDataRow = () => {
36
- const { schema, registry } = this.props;
37
- const { schemaUtils } = registry;
38
- let itemSchema = schema.items;
39
- if (utils.isFixedItems(schema) && utils.allowAdditionalItems(schema)) {
40
- itemSchema = schema.additionalItems;
41
- }
42
- return schemaUtils.getDefaultFormState(itemSchema);
43
- };
44
- /** Callback handler for when the user clicks on the add button. Creates a new row of keyed form data at the end of
45
- * the list, adding it into the state, and then returning `onChange()` with the plain form data converted from the
46
- * keyed data
47
- *
48
- * @param event - The event for the click
49
- */
50
- this.onAddClick = (event) => {
51
- this._handleAddClick(event);
52
- };
53
- /** Callback handler for when the user clicks on the add button on an existing array element. Creates a new row of
54
- * keyed form data inserted at the `index`, adding it into the state, and then returning `onChange()` with the plain
55
- * form data converted from the keyed data
56
- *
57
- * @param index - The index at which the add button is clicked
58
- */
59
- this.onAddIndexClick = (index) => {
60
- return (event) => {
61
- this._handleAddClick(event, index);
62
- };
63
- };
64
- /** Callback handler for when the user clicks on the copy button on an existing array element. Clones the row of
65
- * keyed form data at the `index` into the next position in the state, and then returning `onChange()` with the plain
66
- * form data converted from the keyed data
67
- *
68
- * @param index - The index at which the copy button is clicked
69
- */
70
- this.onCopyIndexClick = (index) => {
71
- return (event) => {
72
- if (event) {
73
- event.preventDefault();
74
- }
75
- const { onChange, errorSchema } = this.props;
76
- const { keyedFormData } = this.state;
77
- let newErrorSchema;
78
- if (errorSchema) {
79
- newErrorSchema = {};
80
- for (const idx in errorSchema) {
81
- const i = parseInt(idx);
82
- if (i <= index) {
83
- set(newErrorSchema, [i], errorSchema[idx]);
84
- } else if (i > index) {
85
- set(newErrorSchema, [i + 1], errorSchema[idx]);
86
- }
87
- }
88
- }
89
- const newKeyedFormDataRow = {
90
- key: generateRowId(),
91
- item: cloneDeep(keyedFormData[index].item)
92
- };
93
- const newKeyedFormData = [...keyedFormData];
94
- if (index !== void 0) {
95
- newKeyedFormData.splice(index + 1, 0, newKeyedFormDataRow);
96
- } else {
97
- newKeyedFormData.push(newKeyedFormDataRow);
98
- }
99
- this.setState(
100
- {
101
- keyedFormData: newKeyedFormData,
102
- updatedKeyedFormData: true
103
- },
104
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
105
- );
106
- };
107
- };
108
- /** Callback handler for when the user clicks on the remove button on an existing array element. Removes the row of
109
- * keyed form data at the `index` in the state, and then returning `onChange()` with the plain form data converted
110
- * from the keyed data
111
- *
112
- * @param index - The index at which the remove button is clicked
113
- */
114
- this.onDropIndexClick = (index) => {
115
- return (event) => {
116
- if (event) {
117
- event.preventDefault();
118
- }
119
- const { onChange, errorSchema } = this.props;
120
- const { keyedFormData } = this.state;
121
- let newErrorSchema;
122
- if (errorSchema) {
123
- newErrorSchema = {};
124
- for (const idx in errorSchema) {
125
- const i = parseInt(idx);
126
- if (i < index) {
127
- set(newErrorSchema, [i], errorSchema[idx]);
128
- } else if (i > index) {
129
- set(newErrorSchema, [i - 1], errorSchema[idx]);
130
- }
131
- }
132
- }
133
- const newKeyedFormData = keyedFormData.filter((_, i) => i !== index);
134
- this.setState(
135
- {
136
- keyedFormData: newKeyedFormData,
137
- updatedKeyedFormData: true
138
- },
139
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
140
- );
141
- };
142
- };
143
- /** Callback handler for when the user clicks on one of the move item buttons on an existing array element. Moves the
144
- * row of keyed form data at the `index` to the `newIndex` in the state, and then returning `onChange()` with the
145
- * plain form data converted from the keyed data
146
- *
147
- * @param index - The index of the item to move
148
- * @param newIndex - The index to where the item is to be moved
149
- */
150
- this.onReorderClick = (index, newIndex) => {
151
- return (event) => {
152
- if (event) {
153
- event.preventDefault();
154
- event.currentTarget.blur();
155
- }
156
- const { onChange, errorSchema } = this.props;
157
- let newErrorSchema;
158
- if (errorSchema) {
159
- newErrorSchema = {};
160
- for (const idx in errorSchema) {
161
- const i = parseInt(idx);
162
- if (i == index) {
163
- set(newErrorSchema, [newIndex], errorSchema[index]);
164
- } else if (i == newIndex) {
165
- set(newErrorSchema, [index], errorSchema[newIndex]);
166
- } else {
167
- set(newErrorSchema, [idx], errorSchema[i]);
168
- }
169
- }
170
- }
171
- const { keyedFormData } = this.state;
172
- function reOrderArray() {
173
- const _newKeyedFormData = keyedFormData.slice();
174
- _newKeyedFormData.splice(index, 1);
175
- _newKeyedFormData.splice(newIndex, 0, keyedFormData[index]);
176
- return _newKeyedFormData;
177
- }
178
- const newKeyedFormData = reOrderArray();
179
- this.setState(
180
- {
181
- keyedFormData: newKeyedFormData
182
- },
183
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
184
- );
185
- };
186
- };
187
- /** Callback handler used to deal with changing the value of the data in the array at the `index`. Calls the
188
- * `onChange` callback with the updated form data
189
- *
190
- * @param index - The index of the item being changed
191
- */
192
- this.onChangeForIndex = (index) => {
193
- return (value, newErrorSchema, id) => {
194
- const { formData, onChange, errorSchema } = this.props;
195
- const arrayData = Array.isArray(formData) ? formData : [];
196
- const newFormData = arrayData.map((item, i) => {
197
- const jsonValue = typeof value === "undefined" ? null : value;
198
- return index === i ? jsonValue : item;
199
- });
200
- onChange(
201
- newFormData,
202
- errorSchema && errorSchema && {
203
- ...errorSchema,
204
- [index]: newErrorSchema
205
- },
206
- id
207
- );
208
- };
209
- };
210
- /** Callback handler used to change the value for a checkbox */
211
- this.onSelectChange = (value) => {
212
- const { onChange, idSchema } = this.props;
213
- onChange(value, void 0, idSchema && idSchema.$id);
214
- };
215
32
  const { formData = [] } = props;
216
33
  const keyedFormData = generateKeyedFormData(formData);
217
34
  this.state = {
@@ -286,6 +103,18 @@
286
103
  }
287
104
  return addable;
288
105
  }
106
+ /** Returns the default form information for an item based on the schema for that item. Deals with the possibility
107
+ * that the schema is fixed and allows additional items.
108
+ */
109
+ _getNewFormDataRow = () => {
110
+ const { schema, registry } = this.props;
111
+ const { schemaUtils } = registry;
112
+ let itemSchema = schema.items;
113
+ if (utils.isFixedItems(schema) && utils.allowAdditionalItems(schema)) {
114
+ itemSchema = schema.additionalItems;
115
+ }
116
+ return schemaUtils.getDefaultFormState(itemSchema);
117
+ };
289
118
  /** Callback handler for when the user clicks on the add or add at index buttons. Creates a new row of keyed form data
290
119
  * either at the end of the list (when index is not specified) or inserted at the `index` when it is, adding it into
291
120
  * the state, and then returning `onChange()` with the plain form data converted from the keyed data
@@ -329,6 +158,177 @@
329
158
  () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
330
159
  );
331
160
  }
161
+ /** Callback handler for when the user clicks on the add button. Creates a new row of keyed form data at the end of
162
+ * the list, adding it into the state, and then returning `onChange()` with the plain form data converted from the
163
+ * keyed data
164
+ *
165
+ * @param event - The event for the click
166
+ */
167
+ onAddClick = (event) => {
168
+ this._handleAddClick(event);
169
+ };
170
+ /** Callback handler for when the user clicks on the add button on an existing array element. Creates a new row of
171
+ * keyed form data inserted at the `index`, adding it into the state, and then returning `onChange()` with the plain
172
+ * form data converted from the keyed data
173
+ *
174
+ * @param index - The index at which the add button is clicked
175
+ */
176
+ onAddIndexClick = (index) => {
177
+ return (event) => {
178
+ this._handleAddClick(event, index);
179
+ };
180
+ };
181
+ /** Callback handler for when the user clicks on the copy button on an existing array element. Clones the row of
182
+ * keyed form data at the `index` into the next position in the state, and then returning `onChange()` with the plain
183
+ * form data converted from the keyed data
184
+ *
185
+ * @param index - The index at which the copy button is clicked
186
+ */
187
+ onCopyIndexClick = (index) => {
188
+ return (event) => {
189
+ if (event) {
190
+ event.preventDefault();
191
+ }
192
+ const { onChange, errorSchema } = this.props;
193
+ const { keyedFormData } = this.state;
194
+ let newErrorSchema;
195
+ if (errorSchema) {
196
+ newErrorSchema = {};
197
+ for (const idx in errorSchema) {
198
+ const i = parseInt(idx);
199
+ if (i <= index) {
200
+ set(newErrorSchema, [i], errorSchema[idx]);
201
+ } else if (i > index) {
202
+ set(newErrorSchema, [i + 1], errorSchema[idx]);
203
+ }
204
+ }
205
+ }
206
+ const newKeyedFormDataRow = {
207
+ key: generateRowId(),
208
+ item: cloneDeep(keyedFormData[index].item)
209
+ };
210
+ const newKeyedFormData = [...keyedFormData];
211
+ if (index !== void 0) {
212
+ newKeyedFormData.splice(index + 1, 0, newKeyedFormDataRow);
213
+ } else {
214
+ newKeyedFormData.push(newKeyedFormDataRow);
215
+ }
216
+ this.setState(
217
+ {
218
+ keyedFormData: newKeyedFormData,
219
+ updatedKeyedFormData: true
220
+ },
221
+ () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
222
+ );
223
+ };
224
+ };
225
+ /** Callback handler for when the user clicks on the remove button on an existing array element. Removes the row of
226
+ * keyed form data at the `index` in the state, and then returning `onChange()` with the plain form data converted
227
+ * from the keyed data
228
+ *
229
+ * @param index - The index at which the remove button is clicked
230
+ */
231
+ onDropIndexClick = (index) => {
232
+ return (event) => {
233
+ if (event) {
234
+ event.preventDefault();
235
+ }
236
+ const { onChange, errorSchema } = this.props;
237
+ const { keyedFormData } = this.state;
238
+ let newErrorSchema;
239
+ if (errorSchema) {
240
+ newErrorSchema = {};
241
+ for (const idx in errorSchema) {
242
+ const i = parseInt(idx);
243
+ if (i < index) {
244
+ set(newErrorSchema, [i], errorSchema[idx]);
245
+ } else if (i > index) {
246
+ set(newErrorSchema, [i - 1], errorSchema[idx]);
247
+ }
248
+ }
249
+ }
250
+ const newKeyedFormData = keyedFormData.filter((_, i) => i !== index);
251
+ this.setState(
252
+ {
253
+ keyedFormData: newKeyedFormData,
254
+ updatedKeyedFormData: true
255
+ },
256
+ () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
257
+ );
258
+ };
259
+ };
260
+ /** Callback handler for when the user clicks on one of the move item buttons on an existing array element. Moves the
261
+ * row of keyed form data at the `index` to the `newIndex` in the state, and then returning `onChange()` with the
262
+ * plain form data converted from the keyed data
263
+ *
264
+ * @param index - The index of the item to move
265
+ * @param newIndex - The index to where the item is to be moved
266
+ */
267
+ onReorderClick = (index, newIndex) => {
268
+ return (event) => {
269
+ if (event) {
270
+ event.preventDefault();
271
+ event.currentTarget.blur();
272
+ }
273
+ const { onChange, errorSchema } = this.props;
274
+ let newErrorSchema;
275
+ if (errorSchema) {
276
+ newErrorSchema = {};
277
+ for (const idx in errorSchema) {
278
+ const i = parseInt(idx);
279
+ if (i == index) {
280
+ set(newErrorSchema, [newIndex], errorSchema[index]);
281
+ } else if (i == newIndex) {
282
+ set(newErrorSchema, [index], errorSchema[newIndex]);
283
+ } else {
284
+ set(newErrorSchema, [idx], errorSchema[i]);
285
+ }
286
+ }
287
+ }
288
+ const { keyedFormData } = this.state;
289
+ function reOrderArray() {
290
+ const _newKeyedFormData = keyedFormData.slice();
291
+ _newKeyedFormData.splice(index, 1);
292
+ _newKeyedFormData.splice(newIndex, 0, keyedFormData[index]);
293
+ return _newKeyedFormData;
294
+ }
295
+ const newKeyedFormData = reOrderArray();
296
+ this.setState(
297
+ {
298
+ keyedFormData: newKeyedFormData
299
+ },
300
+ () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
301
+ );
302
+ };
303
+ };
304
+ /** Callback handler used to deal with changing the value of the data in the array at the `index`. Calls the
305
+ * `onChange` callback with the updated form data
306
+ *
307
+ * @param index - The index of the item being changed
308
+ */
309
+ onChangeForIndex = (index) => {
310
+ return (value, newErrorSchema, id) => {
311
+ const { formData, onChange, errorSchema } = this.props;
312
+ const arrayData = Array.isArray(formData) ? formData : [];
313
+ const newFormData = arrayData.map((item, i) => {
314
+ const jsonValue = typeof value === "undefined" ? null : value;
315
+ return index === i ? jsonValue : item;
316
+ });
317
+ onChange(
318
+ newFormData,
319
+ errorSchema && errorSchema && {
320
+ ...errorSchema,
321
+ [index]: newErrorSchema
322
+ },
323
+ id
324
+ );
325
+ };
326
+ };
327
+ /** Callback handler used to change the value for a checkbox */
328
+ onSelectChange = (value) => {
329
+ const { onChange, idSchema } = this.props;
330
+ onChange(value, void 0, idSchema && idSchema.$id);
331
+ };
332
332
  /** Renders the `ArrayField` depending on the specific needs of the schema and uischema elements
333
333
  */
334
334
  render() {
@@ -877,30 +877,6 @@
877
877
  */
878
878
  constructor(props) {
879
879
  super(props);
880
- /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
881
- * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
882
- * the `onChange` handler.
883
- *
884
- * @param option - The new option value being selected
885
- */
886
- this.onOptionChange = (option) => {
887
- const { selectedOption, retrievedOptions } = this.state;
888
- const { formData, onChange, registry } = this.props;
889
- const { schemaUtils } = registry;
890
- const intOption = option !== void 0 ? parseInt(option, 10) : -1;
891
- if (intOption === selectedOption) {
892
- return;
893
- }
894
- const newOption = intOption >= 0 ? retrievedOptions[intOption] : void 0;
895
- const oldOption = selectedOption >= 0 ? retrievedOptions[selectedOption] : void 0;
896
- let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData);
897
- if (newOption) {
898
- newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
899
- }
900
- this.setState({ selectedOption: intOption }, () => {
901
- onChange(newFormData, void 0, this.getFieldId());
902
- });
903
- };
904
880
  const {
905
881
  formData,
906
882
  options,
@@ -955,6 +931,30 @@
955
931
  const option = schemaUtils.getClosestMatchingOption(formData, options, selectedOption, discriminator);
956
932
  return option;
957
933
  }
934
+ /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
935
+ * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
936
+ * the `onChange` handler.
937
+ *
938
+ * @param option - The new option value being selected
939
+ */
940
+ onOptionChange = (option) => {
941
+ const { selectedOption, retrievedOptions } = this.state;
942
+ const { formData, onChange, registry } = this.props;
943
+ const { schemaUtils } = registry;
944
+ const intOption = option !== void 0 ? parseInt(option, 10) : -1;
945
+ if (intOption === selectedOption) {
946
+ return;
947
+ }
948
+ const newOption = intOption >= 0 ? retrievedOptions[intOption] : void 0;
949
+ const oldOption = selectedOption >= 0 ? retrievedOptions[selectedOption] : void 0;
950
+ let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData);
951
+ if (newOption) {
952
+ newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
953
+ }
954
+ this.setState({ selectedOption: intOption }, () => {
955
+ onChange(newFormData, void 0, this.getFieldId());
956
+ });
957
+ };
958
958
  getFieldId() {
959
959
  const { idSchema, schema } = this.props;
960
960
  return `${idSchema.$id}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`;
@@ -1081,138 +1081,11 @@
1081
1081
  }
1082
1082
  var NumberField_default = NumberField;
1083
1083
  var ObjectField = class extends react.Component {
1084
- constructor() {
1085
- super(...arguments);
1086
- /** Set up the initial state */
1087
- this.state = {
1088
- wasPropertyKeyModified: false,
1089
- additionalProperties: {}
1090
- };
1091
- /** Returns the `onPropertyChange` handler for the `name` field. Handles the special case where a user is attempting
1092
- * to clear the data for a field added as an additional property. Calls the `onChange()` handler with the updated
1093
- * formData.
1094
- *
1095
- * @param name - The name of the property
1096
- * @param addedByAdditionalProperties - Flag indicating whether this property is an additional property
1097
- * @returns - The onPropertyChange callback for the `name` property
1098
- */
1099
- this.onPropertyChange = (name, addedByAdditionalProperties = false) => {
1100
- return (value, newErrorSchema, id) => {
1101
- const { formData, onChange, errorSchema } = this.props;
1102
- if (value === void 0 && addedByAdditionalProperties) {
1103
- value = "";
1104
- }
1105
- const newFormData = { ...formData, [name]: value };
1106
- onChange(
1107
- newFormData,
1108
- errorSchema && errorSchema && {
1109
- ...errorSchema,
1110
- [name]: newErrorSchema
1111
- },
1112
- id
1113
- );
1114
- };
1115
- };
1116
- /** Returns a callback to handle the onDropPropertyClick event for the given `key` which removes the old `key` data
1117
- * and calls the `onChange` callback with it
1118
- *
1119
- * @param key - The key for which the drop callback is desired
1120
- * @returns - The drop property click callback
1121
- */
1122
- this.onDropPropertyClick = (key) => {
1123
- return (event) => {
1124
- event.preventDefault();
1125
- const { onChange, formData } = this.props;
1126
- const copiedFormData = { ...formData };
1127
- unset(copiedFormData, key);
1128
- onChange(copiedFormData);
1129
- };
1130
- };
1131
- /** Computes the next available key name from the `preferredKey`, indexing through the already existing keys until one
1132
- * that is already not assigned is found.
1133
- *
1134
- * @param preferredKey - The preferred name of a new key
1135
- * @param [formData] - The form data in which to check if the desired key already exists
1136
- * @returns - The name of the next available key from `preferredKey`
1137
- */
1138
- this.getAvailableKey = (preferredKey, formData) => {
1139
- const { uiSchema, registry } = this.props;
1140
- const { duplicateKeySuffixSeparator = "-" } = utils.getUiOptions(uiSchema, registry.globalUiOptions);
1141
- let index = 0;
1142
- let newKey = preferredKey;
1143
- while (has(formData, newKey)) {
1144
- newKey = `${preferredKey}${duplicateKeySuffixSeparator}${++index}`;
1145
- }
1146
- return newKey;
1147
- };
1148
- /** Returns a callback function that deals with the rename of a key for an additional property for a schema. That
1149
- * callback will attempt to rename the key and move the existing data to that key, calling `onChange` when it does.
1150
- *
1151
- * @param oldValue - The old value of a field
1152
- * @returns - The key change callback function
1153
- */
1154
- this.onKeyChange = (oldValue) => {
1155
- return (value, newErrorSchema) => {
1156
- if (oldValue === value) {
1157
- return;
1158
- }
1159
- const { formData, onChange, errorSchema } = this.props;
1160
- value = this.getAvailableKey(value, formData);
1161
- const newFormData = {
1162
- ...formData
1163
- };
1164
- const newKeys = { [oldValue]: value };
1165
- const keyValues = Object.keys(newFormData).map((key) => {
1166
- const newKey = newKeys[key] || key;
1167
- return { [newKey]: newFormData[key] };
1168
- });
1169
- const renamedObj = Object.assign({}, ...keyValues);
1170
- this.setState({ wasPropertyKeyModified: true });
1171
- onChange(
1172
- renamedObj,
1173
- errorSchema && errorSchema && {
1174
- ...errorSchema,
1175
- [value]: newErrorSchema
1176
- }
1177
- );
1178
- };
1179
- };
1180
- /** Handles the adding of a new additional property on the given `schema`. Calls the `onChange` callback once the new
1181
- * default data for that field has been added to the formData.
1182
- *
1183
- * @param schema - The schema element to which the new property is being added
1184
- */
1185
- this.handleAddClick = (schema) => () => {
1186
- if (!schema.additionalProperties) {
1187
- return;
1188
- }
1189
- const { formData, onChange, registry } = this.props;
1190
- const newFormData = { ...formData };
1191
- let type = void 0;
1192
- let constValue = void 0;
1193
- let defaultValue = void 0;
1194
- if (isObject(schema.additionalProperties)) {
1195
- type = schema.additionalProperties.type;
1196
- constValue = schema.additionalProperties.const;
1197
- defaultValue = schema.additionalProperties.default;
1198
- let apSchema = schema.additionalProperties;
1199
- if (utils.REF_KEY in apSchema) {
1200
- const { schemaUtils } = registry;
1201
- apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[utils.REF_KEY] }, formData);
1202
- type = apSchema.type;
1203
- constValue = apSchema.const;
1204
- defaultValue = apSchema.default;
1205
- }
1206
- if (!type && (utils.ANY_OF_KEY in apSchema || utils.ONE_OF_KEY in apSchema)) {
1207
- type = "object";
1208
- }
1209
- }
1210
- const newKey = this.getAvailableKey("newKey", newFormData);
1211
- const newValue = constValue ?? defaultValue ?? this.getDefaultValue(type);
1212
- set(newFormData, newKey, newValue);
1213
- onChange(newFormData);
1214
- };
1215
- }
1084
+ /** Set up the initial state */
1085
+ state = {
1086
+ wasPropertyKeyModified: false,
1087
+ additionalProperties: {}
1088
+ };
1216
1089
  /** Returns a flag indicating whether the `name` field is required in the object schema
1217
1090
  *
1218
1091
  * @param name - The name of the field to check for required-ness
@@ -1222,6 +1095,95 @@
1222
1095
  const { schema } = this.props;
1223
1096
  return Array.isArray(schema.required) && schema.required.indexOf(name) !== -1;
1224
1097
  }
1098
+ /** Returns the `onPropertyChange` handler for the `name` field. Handles the special case where a user is attempting
1099
+ * to clear the data for a field added as an additional property. Calls the `onChange()` handler with the updated
1100
+ * formData.
1101
+ *
1102
+ * @param name - The name of the property
1103
+ * @param addedByAdditionalProperties - Flag indicating whether this property is an additional property
1104
+ * @returns - The onPropertyChange callback for the `name` property
1105
+ */
1106
+ onPropertyChange = (name, addedByAdditionalProperties = false) => {
1107
+ return (value, newErrorSchema, id) => {
1108
+ const { formData, onChange, errorSchema } = this.props;
1109
+ if (value === void 0 && addedByAdditionalProperties) {
1110
+ value = "";
1111
+ }
1112
+ const newFormData = { ...formData, [name]: value };
1113
+ onChange(
1114
+ newFormData,
1115
+ errorSchema && errorSchema && {
1116
+ ...errorSchema,
1117
+ [name]: newErrorSchema
1118
+ },
1119
+ id
1120
+ );
1121
+ };
1122
+ };
1123
+ /** Returns a callback to handle the onDropPropertyClick event for the given `key` which removes the old `key` data
1124
+ * and calls the `onChange` callback with it
1125
+ *
1126
+ * @param key - The key for which the drop callback is desired
1127
+ * @returns - The drop property click callback
1128
+ */
1129
+ onDropPropertyClick = (key) => {
1130
+ return (event) => {
1131
+ event.preventDefault();
1132
+ const { onChange, formData } = this.props;
1133
+ const copiedFormData = { ...formData };
1134
+ unset(copiedFormData, key);
1135
+ onChange(copiedFormData);
1136
+ };
1137
+ };
1138
+ /** Computes the next available key name from the `preferredKey`, indexing through the already existing keys until one
1139
+ * that is already not assigned is found.
1140
+ *
1141
+ * @param preferredKey - The preferred name of a new key
1142
+ * @param [formData] - The form data in which to check if the desired key already exists
1143
+ * @returns - The name of the next available key from `preferredKey`
1144
+ */
1145
+ getAvailableKey = (preferredKey, formData) => {
1146
+ const { uiSchema, registry } = this.props;
1147
+ const { duplicateKeySuffixSeparator = "-" } = utils.getUiOptions(uiSchema, registry.globalUiOptions);
1148
+ let index = 0;
1149
+ let newKey = preferredKey;
1150
+ while (has(formData, newKey)) {
1151
+ newKey = `${preferredKey}${duplicateKeySuffixSeparator}${++index}`;
1152
+ }
1153
+ return newKey;
1154
+ };
1155
+ /** Returns a callback function that deals with the rename of a key for an additional property for a schema. That
1156
+ * callback will attempt to rename the key and move the existing data to that key, calling `onChange` when it does.
1157
+ *
1158
+ * @param oldValue - The old value of a field
1159
+ * @returns - The key change callback function
1160
+ */
1161
+ onKeyChange = (oldValue) => {
1162
+ return (value, newErrorSchema) => {
1163
+ if (oldValue === value) {
1164
+ return;
1165
+ }
1166
+ const { formData, onChange, errorSchema } = this.props;
1167
+ value = this.getAvailableKey(value, formData);
1168
+ const newFormData = {
1169
+ ...formData
1170
+ };
1171
+ const newKeys = { [oldValue]: value };
1172
+ const keyValues = Object.keys(newFormData).map((key) => {
1173
+ const newKey = newKeys[key] || key;
1174
+ return { [newKey]: newFormData[key] };
1175
+ });
1176
+ const renamedObj = Object.assign({}, ...keyValues);
1177
+ this.setState({ wasPropertyKeyModified: true });
1178
+ onChange(
1179
+ renamedObj,
1180
+ errorSchema && errorSchema && {
1181
+ ...errorSchema,
1182
+ [value]: newErrorSchema
1183
+ }
1184
+ );
1185
+ };
1186
+ };
1225
1187
  /** Returns a default value to be used for a new additional schema property of the given `type`
1226
1188
  *
1227
1189
  * @param type - The type of the new additional schema property
@@ -1246,6 +1208,41 @@
1246
1208
  return translateString(utils.TranslatableString.NewStringDefault);
1247
1209
  }
1248
1210
  }
1211
+ /** Handles the adding of a new additional property on the given `schema`. Calls the `onChange` callback once the new
1212
+ * default data for that field has been added to the formData.
1213
+ *
1214
+ * @param schema - The schema element to which the new property is being added
1215
+ */
1216
+ handleAddClick = (schema) => () => {
1217
+ if (!schema.additionalProperties) {
1218
+ return;
1219
+ }
1220
+ const { formData, onChange, registry } = this.props;
1221
+ const newFormData = { ...formData };
1222
+ let type = void 0;
1223
+ let constValue = void 0;
1224
+ let defaultValue = void 0;
1225
+ if (isObject(schema.additionalProperties)) {
1226
+ type = schema.additionalProperties.type;
1227
+ constValue = schema.additionalProperties.const;
1228
+ defaultValue = schema.additionalProperties.default;
1229
+ let apSchema = schema.additionalProperties;
1230
+ if (utils.REF_KEY in apSchema) {
1231
+ const { schemaUtils } = registry;
1232
+ apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[utils.REF_KEY] }, formData);
1233
+ type = apSchema.type;
1234
+ constValue = apSchema.const;
1235
+ defaultValue = apSchema.default;
1236
+ }
1237
+ if (!type && (utils.ANY_OF_KEY in apSchema || utils.ONE_OF_KEY in apSchema)) {
1238
+ type = "object";
1239
+ }
1240
+ }
1241
+ const newKey = this.getAvailableKey("newKey", newFormData);
1242
+ const newValue = constValue ?? defaultValue ?? this.getDefaultValue(type);
1243
+ set(newFormData, newKey, newValue);
1244
+ onChange(newFormData);
1245
+ };
1249
1246
  /** Renders the `ObjectField` from the given props
1250
1247
  */
1251
1248
  render() {
@@ -2988,6 +2985,10 @@
2988
2985
  };
2989
2986
  }
2990
2987
  var Form = class extends react.Component {
2988
+ /** The ref used to hold the `form` element, this needs to be `any` because `tagName` or `_internalFormWrapper` can
2989
+ * provide any possible type here
2990
+ */
2991
+ formElement;
2991
2992
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
2992
2993
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
2993
2994
  * state construction.
@@ -2996,268 +2997,6 @@
2996
2997
  */
2997
2998
  constructor(props) {
2998
2999
  super(props);
2999
- /** Returns the `formData` with only the elements specified in the `fields` list
3000
- *
3001
- * @param formData - The data for the `Form`
3002
- * @param fields - The fields to keep while filtering
3003
- */
3004
- this.getUsedFormData = (formData, fields2) => {
3005
- if (fields2.length === 0 && typeof formData !== "object") {
3006
- return formData;
3007
- }
3008
- const data = _pick(formData, fields2);
3009
- if (Array.isArray(formData)) {
3010
- return Object.keys(data).map((key) => data[key]);
3011
- }
3012
- return data;
3013
- };
3014
- /** Returns the list of field names from inspecting the `pathSchema` as well as using the `formData`
3015
- *
3016
- * @param pathSchema - The `PathSchema` object for the form
3017
- * @param [formData] - The form data to use while checking for empty objects/arrays
3018
- */
3019
- this.getFieldNames = (pathSchema, formData) => {
3020
- const getAllPaths = (_obj, acc = [], paths = [[]]) => {
3021
- Object.keys(_obj).forEach((key) => {
3022
- if (typeof _obj[key] === "object") {
3023
- const newPaths = paths.map((path) => [...path, key]);
3024
- if (_obj[key][utils.RJSF_ADDITIONAL_PROPERTIES_FLAG] && _obj[key][utils.NAME_KEY] !== "") {
3025
- acc.push(_obj[key][utils.NAME_KEY]);
3026
- } else {
3027
- getAllPaths(_obj[key], acc, newPaths);
3028
- }
3029
- } else if (key === utils.NAME_KEY && _obj[key] !== "") {
3030
- paths.forEach((path) => {
3031
- const formValue = get3(formData, path);
3032
- if (typeof formValue !== "object" || isEmpty(formValue) || Array.isArray(formValue) && formValue.every((val) => typeof val !== "object")) {
3033
- acc.push(path);
3034
- }
3035
- });
3036
- }
3037
- });
3038
- return acc;
3039
- };
3040
- return getAllPaths(pathSchema);
3041
- };
3042
- /** Returns the `formData` after filtering to remove any extra data not in a form field
3043
- *
3044
- * @param formData - The data for the `Form`
3045
- * @returns The `formData` after omitting extra data
3046
- */
3047
- this.omitExtraData = (formData) => {
3048
- const { schema, schemaUtils } = this.state;
3049
- const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3050
- const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3051
- const fieldNames = this.getFieldNames(pathSchema, formData);
3052
- const newFormData = this.getUsedFormData(formData, fieldNames);
3053
- return newFormData;
3054
- };
3055
- /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
3056
- * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
3057
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
3058
- * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
3059
- * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
3060
- * callback will be called if specified with the updated state.
3061
- *
3062
- * @param formData - The new form data from a change to a field
3063
- * @param newErrorSchema - The new `ErrorSchema` based on the field change
3064
- * @param id - The id of the field that caused the change
3065
- */
3066
- this.onChange = (formData, newErrorSchema, id) => {
3067
- const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
3068
- const { schemaUtils, schema } = this.state;
3069
- let retrievedSchema = this.state.retrievedSchema;
3070
- if (utils.isObject(formData) || Array.isArray(formData)) {
3071
- const newState = this.getStateFromProps(this.props, formData);
3072
- formData = newState.formData;
3073
- retrievedSchema = newState.retrievedSchema;
3074
- }
3075
- const mustValidate = !noValidate && liveValidate;
3076
- let state = { formData, schema };
3077
- let newFormData = formData;
3078
- if (omitExtraData === true && liveOmit === true) {
3079
- newFormData = this.omitExtraData(formData);
3080
- state = {
3081
- formData: newFormData
3082
- };
3083
- }
3084
- if (mustValidate) {
3085
- const schemaValidation = this.validate(newFormData, schema, schemaUtils, retrievedSchema);
3086
- let errors = schemaValidation.errors;
3087
- let errorSchema = schemaValidation.errorSchema;
3088
- const schemaValidationErrors = errors;
3089
- const schemaValidationErrorSchema = errorSchema;
3090
- if (extraErrors) {
3091
- const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3092
- errorSchema = merged.errorSchema;
3093
- errors = merged.errors;
3094
- }
3095
- if (newErrorSchema) {
3096
- const filteredErrors = this.filterErrorsBasedOnSchema(newErrorSchema, retrievedSchema, newFormData);
3097
- errorSchema = utils.mergeObjects(errorSchema, filteredErrors, "preventDuplicates");
3098
- }
3099
- state = {
3100
- formData: newFormData,
3101
- errors,
3102
- errorSchema,
3103
- schemaValidationErrors,
3104
- schemaValidationErrorSchema
3105
- };
3106
- } else if (!noValidate && newErrorSchema) {
3107
- const errorSchema = extraErrors ? utils.mergeObjects(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
3108
- state = {
3109
- formData: newFormData,
3110
- errorSchema,
3111
- errors: utils.toErrorList(errorSchema)
3112
- };
3113
- }
3114
- this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
3115
- };
3116
- /**
3117
- * Callback function to handle reset form data.
3118
- * - Reset all fields with default values.
3119
- * - Reset validations and errors
3120
- *
3121
- */
3122
- this.reset = () => {
3123
- const { onChange } = this.props;
3124
- const newState = this.getStateFromProps(this.props, void 0);
3125
- const newFormData = newState.formData;
3126
- const state = {
3127
- formData: newFormData,
3128
- errorSchema: {},
3129
- errors: [],
3130
- schemaValidationErrors: [],
3131
- schemaValidationErrorSchema: {}
3132
- };
3133
- this.setState(state, () => onChange && onChange({ ...this.state, ...state }));
3134
- };
3135
- /** Callback function to handle when a field on the form is blurred. Calls the `onBlur` callback for the `Form` if it
3136
- * was provided.
3137
- *
3138
- * @param id - The unique `id` of the field that was blurred
3139
- * @param data - The data associated with the field that was blurred
3140
- */
3141
- this.onBlur = (id, data) => {
3142
- const { onBlur } = this.props;
3143
- if (onBlur) {
3144
- onBlur(id, data);
3145
- }
3146
- };
3147
- /** Callback function to handle when a field on the form is focused. Calls the `onFocus` callback for the `Form` if it
3148
- * was provided.
3149
- *
3150
- * @param id - The unique `id` of the field that was focused
3151
- * @param data - The data associated with the field that was focused
3152
- */
3153
- this.onFocus = (id, data) => {
3154
- const { onFocus } = this.props;
3155
- if (onFocus) {
3156
- onFocus(id, data);
3157
- }
3158
- };
3159
- /** Callback function to handle when the form is submitted. First, it prevents the default event behavior. Nothing
3160
- * happens if the target and currentTarget of the event are not the same. It will omit any extra data in the
3161
- * `formData` in the state if `omitExtraData` is true. It will validate the resulting `formData`, reporting errors
3162
- * via the `onError()` callback unless validation is disabled. Finally, it will add in any `extraErrors` and then call
3163
- * back the `onSubmit` callback if it was provided.
3164
- *
3165
- * @param event - The submit HTML form event
3166
- */
3167
- this.onSubmit = (event) => {
3168
- event.preventDefault();
3169
- if (event.target !== event.currentTarget) {
3170
- return;
3171
- }
3172
- event.persist();
3173
- const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
3174
- let { formData: newFormData } = this.state;
3175
- if (omitExtraData === true) {
3176
- newFormData = this.omitExtraData(newFormData);
3177
- }
3178
- if (noValidate || this.validateFormWithFormData(newFormData)) {
3179
- const errorSchema = extraErrors || {};
3180
- const errors = extraErrors ? utils.toErrorList(extraErrors) : [];
3181
- this.setState(
3182
- {
3183
- formData: newFormData,
3184
- errors,
3185
- errorSchema,
3186
- schemaValidationErrors: [],
3187
- schemaValidationErrorSchema: {}
3188
- },
3189
- () => {
3190
- if (onSubmit) {
3191
- onSubmit({ ...this.state, formData: newFormData, status: "submitted" }, event);
3192
- }
3193
- }
3194
- );
3195
- }
3196
- };
3197
- /** Provides a function that can be used to programmatically submit the `Form` */
3198
- this.submit = () => {
3199
- if (this.formElement.current) {
3200
- const submitCustomEvent = new CustomEvent("submit", {
3201
- cancelable: true
3202
- });
3203
- submitCustomEvent.preventDefault();
3204
- this.formElement.current.dispatchEvent(submitCustomEvent);
3205
- this.formElement.current.requestSubmit();
3206
- }
3207
- };
3208
- /** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
3209
- * If `onError` is provided, then it will be called with the list of errors.
3210
- *
3211
- * @param formData - The form data to validate
3212
- * @returns - True if the form is valid, false otherwise.
3213
- */
3214
- this.validateFormWithFormData = (formData) => {
3215
- const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3216
- const { errors: prevErrors } = this.state;
3217
- const schemaValidation = this.validate(formData);
3218
- let errors = schemaValidation.errors;
3219
- let errorSchema = schemaValidation.errorSchema;
3220
- const schemaValidationErrors = errors;
3221
- const schemaValidationErrorSchema = errorSchema;
3222
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3223
- if (hasError) {
3224
- if (extraErrors) {
3225
- const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3226
- errorSchema = merged.errorSchema;
3227
- errors = merged.errors;
3228
- }
3229
- if (focusOnFirstError) {
3230
- if (typeof focusOnFirstError === "function") {
3231
- focusOnFirstError(errors[0]);
3232
- } else {
3233
- this.focusOnError(errors[0]);
3234
- }
3235
- }
3236
- this.setState(
3237
- {
3238
- errors,
3239
- errorSchema,
3240
- schemaValidationErrors,
3241
- schemaValidationErrorSchema
3242
- },
3243
- () => {
3244
- if (onError) {
3245
- onError(errors);
3246
- } else {
3247
- console.error("Form validation failed", errors);
3248
- }
3249
- }
3250
- );
3251
- } else if (prevErrors.length > 0) {
3252
- this.setState({
3253
- errors: [],
3254
- errorSchema: {},
3255
- schemaValidationErrors: [],
3256
- schemaValidationErrorSchema: {}
3257
- });
3258
- }
3259
- return !hasError;
3260
- };
3261
3000
  if (!props.validator) {
3262
3001
  throw new Error("A validator is required for Form functionality to work");
3263
3002
  }
@@ -3501,6 +3240,62 @@
3501
3240
  }
3502
3241
  return null;
3503
3242
  }
3243
+ /** Returns the `formData` with only the elements specified in the `fields` list
3244
+ *
3245
+ * @param formData - The data for the `Form`
3246
+ * @param fields - The fields to keep while filtering
3247
+ */
3248
+ getUsedFormData = (formData, fields2) => {
3249
+ if (fields2.length === 0 && typeof formData !== "object") {
3250
+ return formData;
3251
+ }
3252
+ const data = _pick(formData, fields2);
3253
+ if (Array.isArray(formData)) {
3254
+ return Object.keys(data).map((key) => data[key]);
3255
+ }
3256
+ return data;
3257
+ };
3258
+ /** Returns the list of field names from inspecting the `pathSchema` as well as using the `formData`
3259
+ *
3260
+ * @param pathSchema - The `PathSchema` object for the form
3261
+ * @param [formData] - The form data to use while checking for empty objects/arrays
3262
+ */
3263
+ getFieldNames = (pathSchema, formData) => {
3264
+ const getAllPaths = (_obj, acc = [], paths = [[]]) => {
3265
+ Object.keys(_obj).forEach((key) => {
3266
+ if (typeof _obj[key] === "object") {
3267
+ const newPaths = paths.map((path) => [...path, key]);
3268
+ if (_obj[key][utils.RJSF_ADDITIONAL_PROPERTIES_FLAG] && _obj[key][utils.NAME_KEY] !== "") {
3269
+ acc.push(_obj[key][utils.NAME_KEY]);
3270
+ } else {
3271
+ getAllPaths(_obj[key], acc, newPaths);
3272
+ }
3273
+ } else if (key === utils.NAME_KEY && _obj[key] !== "") {
3274
+ paths.forEach((path) => {
3275
+ const formValue = get3(formData, path);
3276
+ if (typeof formValue !== "object" || isEmpty(formValue) || Array.isArray(formValue) && formValue.every((val) => typeof val !== "object")) {
3277
+ acc.push(path);
3278
+ }
3279
+ });
3280
+ }
3281
+ });
3282
+ return acc;
3283
+ };
3284
+ return getAllPaths(pathSchema);
3285
+ };
3286
+ /** Returns the `formData` after filtering to remove any extra data not in a form field
3287
+ *
3288
+ * @param formData - The data for the `Form`
3289
+ * @returns The `formData` after omitting extra data
3290
+ */
3291
+ omitExtraData = (formData) => {
3292
+ const { schema, schemaUtils } = this.state;
3293
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3294
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3295
+ const fieldNames = this.getFieldNames(pathSchema, formData);
3296
+ const newFormData = this.getUsedFormData(formData, fieldNames);
3297
+ return newFormData;
3298
+ };
3504
3299
  // Filtering errors based on your retrieved schema to only show errors for properties in the selected branch.
3505
3300
  filterErrorsBasedOnSchema(schemaErrors, resolvedSchema, formData) {
3506
3301
  const { retrievedSchema, schemaUtils } = this.state;
@@ -3535,6 +3330,67 @@
3535
3330
  };
3536
3331
  return filterNilOrEmptyErrors(filteredErrors, prevCustomValidateErrors);
3537
3332
  }
3333
+ /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
3334
+ * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
3335
+ * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
3336
+ * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
3337
+ * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
3338
+ * callback will be called if specified with the updated state.
3339
+ *
3340
+ * @param formData - The new form data from a change to a field
3341
+ * @param newErrorSchema - The new `ErrorSchema` based on the field change
3342
+ * @param id - The id of the field that caused the change
3343
+ */
3344
+ onChange = (formData, newErrorSchema, id) => {
3345
+ const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
3346
+ const { schemaUtils, schema } = this.state;
3347
+ let retrievedSchema = this.state.retrievedSchema;
3348
+ if (utils.isObject(formData) || Array.isArray(formData)) {
3349
+ const newState = this.getStateFromProps(this.props, formData);
3350
+ formData = newState.formData;
3351
+ retrievedSchema = newState.retrievedSchema;
3352
+ }
3353
+ const mustValidate = !noValidate && liveValidate;
3354
+ let state = { formData, schema };
3355
+ let newFormData = formData;
3356
+ if (omitExtraData === true && liveOmit === true) {
3357
+ newFormData = this.omitExtraData(formData);
3358
+ state = {
3359
+ formData: newFormData
3360
+ };
3361
+ }
3362
+ if (mustValidate) {
3363
+ const schemaValidation = this.validate(newFormData, schema, schemaUtils, retrievedSchema);
3364
+ let errors = schemaValidation.errors;
3365
+ let errorSchema = schemaValidation.errorSchema;
3366
+ const schemaValidationErrors = errors;
3367
+ const schemaValidationErrorSchema = errorSchema;
3368
+ if (extraErrors) {
3369
+ const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3370
+ errorSchema = merged.errorSchema;
3371
+ errors = merged.errors;
3372
+ }
3373
+ if (newErrorSchema) {
3374
+ const filteredErrors = this.filterErrorsBasedOnSchema(newErrorSchema, retrievedSchema, newFormData);
3375
+ errorSchema = utils.mergeObjects(errorSchema, filteredErrors, "preventDuplicates");
3376
+ }
3377
+ state = {
3378
+ formData: newFormData,
3379
+ errors,
3380
+ errorSchema,
3381
+ schemaValidationErrors,
3382
+ schemaValidationErrorSchema
3383
+ };
3384
+ } else if (!noValidate && newErrorSchema) {
3385
+ const errorSchema = extraErrors ? utils.mergeObjects(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
3386
+ state = {
3387
+ formData: newFormData,
3388
+ errorSchema,
3389
+ errors: utils.toErrorList(errorSchema)
3390
+ };
3391
+ }
3392
+ this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
3393
+ };
3538
3394
  /**
3539
3395
  * If the retrievedSchema has changed the new retrievedSchema is returned.
3540
3396
  * Otherwise, the old retrievedSchema is returned to persist reference.
@@ -3548,6 +3404,87 @@
3548
3404
  const isTheSame = utils.deepEquals(retrievedSchema, this.state?.retrievedSchema);
3549
3405
  return isTheSame ? this.state.retrievedSchema : retrievedSchema;
3550
3406
  }
3407
+ /**
3408
+ * Callback function to handle reset form data.
3409
+ * - Reset all fields with default values.
3410
+ * - Reset validations and errors
3411
+ *
3412
+ */
3413
+ reset = () => {
3414
+ const { onChange } = this.props;
3415
+ const newState = this.getStateFromProps(this.props, void 0);
3416
+ const newFormData = newState.formData;
3417
+ const state = {
3418
+ formData: newFormData,
3419
+ errorSchema: {},
3420
+ errors: [],
3421
+ schemaValidationErrors: [],
3422
+ schemaValidationErrorSchema: {}
3423
+ };
3424
+ this.setState(state, () => onChange && onChange({ ...this.state, ...state }));
3425
+ };
3426
+ /** Callback function to handle when a field on the form is blurred. Calls the `onBlur` callback for the `Form` if it
3427
+ * was provided.
3428
+ *
3429
+ * @param id - The unique `id` of the field that was blurred
3430
+ * @param data - The data associated with the field that was blurred
3431
+ */
3432
+ onBlur = (id, data) => {
3433
+ const { onBlur } = this.props;
3434
+ if (onBlur) {
3435
+ onBlur(id, data);
3436
+ }
3437
+ };
3438
+ /** Callback function to handle when a field on the form is focused. Calls the `onFocus` callback for the `Form` if it
3439
+ * was provided.
3440
+ *
3441
+ * @param id - The unique `id` of the field that was focused
3442
+ * @param data - The data associated with the field that was focused
3443
+ */
3444
+ onFocus = (id, data) => {
3445
+ const { onFocus } = this.props;
3446
+ if (onFocus) {
3447
+ onFocus(id, data);
3448
+ }
3449
+ };
3450
+ /** Callback function to handle when the form is submitted. First, it prevents the default event behavior. Nothing
3451
+ * happens if the target and currentTarget of the event are not the same. It will omit any extra data in the
3452
+ * `formData` in the state if `omitExtraData` is true. It will validate the resulting `formData`, reporting errors
3453
+ * via the `onError()` callback unless validation is disabled. Finally, it will add in any `extraErrors` and then call
3454
+ * back the `onSubmit` callback if it was provided.
3455
+ *
3456
+ * @param event - The submit HTML form event
3457
+ */
3458
+ onSubmit = (event) => {
3459
+ event.preventDefault();
3460
+ if (event.target !== event.currentTarget) {
3461
+ return;
3462
+ }
3463
+ event.persist();
3464
+ const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
3465
+ let { formData: newFormData } = this.state;
3466
+ if (omitExtraData === true) {
3467
+ newFormData = this.omitExtraData(newFormData);
3468
+ }
3469
+ if (noValidate || this.validateFormWithFormData(newFormData)) {
3470
+ const errorSchema = extraErrors || {};
3471
+ const errors = extraErrors ? utils.toErrorList(extraErrors) : [];
3472
+ this.setState(
3473
+ {
3474
+ formData: newFormData,
3475
+ errors,
3476
+ errorSchema,
3477
+ schemaValidationErrors: [],
3478
+ schemaValidationErrorSchema: {}
3479
+ },
3480
+ () => {
3481
+ if (onSubmit) {
3482
+ onSubmit({ ...this.state, formData: newFormData, status: "submitted" }, event);
3483
+ }
3484
+ }
3485
+ );
3486
+ }
3487
+ };
3551
3488
  /** Returns the registry for the form */
3552
3489
  getRegistry() {
3553
3490
  const { translateString: customTranslateString, uiSchema = {} } = this.props;
@@ -3571,6 +3508,17 @@
3571
3508
  globalUiOptions: uiSchema[utils.UI_GLOBAL_OPTIONS_KEY]
3572
3509
  };
3573
3510
  }
3511
+ /** Provides a function that can be used to programmatically submit the `Form` */
3512
+ submit = () => {
3513
+ if (this.formElement.current) {
3514
+ const submitCustomEvent = new CustomEvent("submit", {
3515
+ cancelable: true
3516
+ });
3517
+ submitCustomEvent.preventDefault();
3518
+ this.formElement.current.dispatchEvent(submitCustomEvent);
3519
+ this.formElement.current.requestSubmit();
3520
+ }
3521
+ };
3574
3522
  /** Attempts to focus on the field associated with the `error`. Uses the `property` field to compute path of the error
3575
3523
  * field, then, using the `idPrefix` and `idSeparator` converts that path into an id. Then the input element with that
3576
3524
  * id is attempted to be found using the `formElement` ref. If it is located, then it is focused.
@@ -3598,6 +3546,59 @@
3598
3546
  field.focus();
3599
3547
  }
3600
3548
  }
3549
+ /** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
3550
+ * If `onError` is provided, then it will be called with the list of errors.
3551
+ *
3552
+ * @param formData - The form data to validate
3553
+ * @returns - True if the form is valid, false otherwise.
3554
+ */
3555
+ validateFormWithFormData = (formData) => {
3556
+ const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3557
+ const { errors: prevErrors } = this.state;
3558
+ const schemaValidation = this.validate(formData);
3559
+ let errors = schemaValidation.errors;
3560
+ let errorSchema = schemaValidation.errorSchema;
3561
+ const schemaValidationErrors = errors;
3562
+ const schemaValidationErrorSchema = errorSchema;
3563
+ const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3564
+ if (hasError) {
3565
+ if (extraErrors) {
3566
+ const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3567
+ errorSchema = merged.errorSchema;
3568
+ errors = merged.errors;
3569
+ }
3570
+ if (focusOnFirstError) {
3571
+ if (typeof focusOnFirstError === "function") {
3572
+ focusOnFirstError(errors[0]);
3573
+ } else {
3574
+ this.focusOnError(errors[0]);
3575
+ }
3576
+ }
3577
+ this.setState(
3578
+ {
3579
+ errors,
3580
+ errorSchema,
3581
+ schemaValidationErrors,
3582
+ schemaValidationErrorSchema
3583
+ },
3584
+ () => {
3585
+ if (onError) {
3586
+ onError(errors);
3587
+ } else {
3588
+ console.error("Form validation failed", errors);
3589
+ }
3590
+ }
3591
+ );
3592
+ } else if (prevErrors.length > 0) {
3593
+ this.setState({
3594
+ errors: [],
3595
+ errorSchema: {},
3596
+ schemaValidationErrors: [],
3597
+ schemaValidationErrorSchema: {}
3598
+ });
3599
+ }
3600
+ return !hasError;
3601
+ };
3601
3602
  /** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
3602
3603
  * any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
3603
3604
  * same way as would happen on form submission.