@rjsf/core 4.2.3 → 5.0.0-beta.10

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 (187) hide show
  1. package/README.md +4 -2
  2. package/dist/core.cjs.development.js +3392 -4981
  3. package/dist/core.cjs.development.js.map +1 -1
  4. package/dist/core.cjs.production.min.js +1 -1
  5. package/dist/core.cjs.production.min.js.map +1 -1
  6. package/dist/core.esm.js +3330 -4929
  7. package/dist/core.esm.js.map +1 -1
  8. package/dist/core.umd.development.js +4119 -0
  9. package/dist/core.umd.development.js.map +1 -0
  10. package/dist/core.umd.production.min.js +2 -0
  11. package/dist/core.umd.production.min.js.map +1 -0
  12. package/dist/index.d.ts +302 -70
  13. package/package.json +44 -73
  14. package/dist/cjs/components/AddButton.js +0 -39
  15. package/dist/cjs/components/ErrorList.js +0 -41
  16. package/dist/cjs/components/Form.js +0 -588
  17. package/dist/cjs/components/IconButton.js +0 -37
  18. package/dist/cjs/components/fields/ArrayField.js +0 -977
  19. package/dist/cjs/components/fields/BooleanField.js +0 -107
  20. package/dist/cjs/components/fields/DescriptionField.js +0 -50
  21. package/dist/cjs/components/fields/MultiSchemaField.js +0 -275
  22. package/dist/cjs/components/fields/NullField.js +0 -66
  23. package/dist/cjs/components/fields/NumberField.js +0 -156
  24. package/dist/cjs/components/fields/ObjectField.js +0 -366
  25. package/dist/cjs/components/fields/SchemaField.js +0 -546
  26. package/dist/cjs/components/fields/StringField.js +0 -98
  27. package/dist/cjs/components/fields/TitleField.js +0 -42
  28. package/dist/cjs/components/fields/UnsupportedField.js +0 -46
  29. package/dist/cjs/components/fields/index.js +0 -47
  30. package/dist/cjs/components/widgets/AltDateTimeWidget.js +0 -48
  31. package/dist/cjs/components/widgets/AltDateWidget.js +0 -301
  32. package/dist/cjs/components/widgets/BaseInput.js +0 -151
  33. package/dist/cjs/components/widgets/CheckboxWidget.js +0 -85
  34. package/dist/cjs/components/widgets/CheckboxesWidget.js +0 -121
  35. package/dist/cjs/components/widgets/ColorWidget.js +0 -45
  36. package/dist/cjs/components/widgets/DateTimeWidget.js +0 -43
  37. package/dist/cjs/components/widgets/DateWidget.js +0 -39
  38. package/dist/cjs/components/widgets/EmailWidget.js +0 -34
  39. package/dist/cjs/components/widgets/FileWidget.js +0 -215
  40. package/dist/cjs/components/widgets/HiddenWidget.js +0 -36
  41. package/dist/cjs/components/widgets/PasswordWidget.js +0 -34
  42. package/dist/cjs/components/widgets/RadioWidget.js +0 -107
  43. package/dist/cjs/components/widgets/RangeWidget.js +0 -46
  44. package/dist/cjs/components/widgets/SelectWidget.js +0 -151
  45. package/dist/cjs/components/widgets/SubmitButton.js +0 -35
  46. package/dist/cjs/components/widgets/TextWidget.js +0 -31
  47. package/dist/cjs/components/widgets/TextareaWidget.js +0 -81
  48. package/dist/cjs/components/widgets/URLWidget.js +0 -34
  49. package/dist/cjs/components/widgets/UpDownWidget.js +0 -36
  50. package/dist/cjs/components/widgets/index.js +0 -73
  51. package/dist/cjs/defaultRegistry.js +0 -23
  52. package/dist/cjs/index.js +0 -37
  53. package/dist/cjs/types.js +0 -47
  54. package/dist/cjs/utils.js +0 -1407
  55. package/dist/cjs/validate.js +0 -354
  56. package/dist/cjs/withTheme.js +0 -53
  57. package/dist/components/AddButton.d.ts +0 -5
  58. package/dist/components/ErrorList.d.ts +0 -1
  59. package/dist/components/Form.d.ts +0 -48
  60. package/dist/components/IconButton.d.ts +0 -1
  61. package/dist/components/fields/ArrayField.d.ts +0 -51
  62. package/dist/components/fields/BooleanField.d.ts +0 -45
  63. package/dist/components/fields/DescriptionField.d.ts +0 -9
  64. package/dist/components/fields/MultiSchemaField.d.ts +0 -40
  65. package/dist/components/fields/NullField.d.ts +0 -6
  66. package/dist/components/fields/NumberField.d.ts +0 -63
  67. package/dist/components/fields/ObjectField.d.ts +0 -22
  68. package/dist/components/fields/SchemaField.d.ts +0 -39
  69. package/dist/components/fields/StringField.d.ts +0 -45
  70. package/dist/components/fields/TitleField.d.ts +0 -10
  71. package/dist/components/fields/UnsupportedField.d.ts +0 -14
  72. package/dist/components/fields/index.d.ts +0 -26
  73. package/dist/components/widgets/AltDateTimeWidget.d.ts +0 -22
  74. package/dist/components/widgets/AltDateWidget.d.ts +0 -22
  75. package/dist/components/widgets/BaseInput.d.ts +0 -23
  76. package/dist/components/widgets/CheckboxWidget.d.ts +0 -18
  77. package/dist/components/widgets/CheckboxesWidget.d.ts +0 -26
  78. package/dist/components/widgets/ColorWidget.d.ts +0 -15
  79. package/dist/components/widgets/DateTimeWidget.d.ts +0 -8
  80. package/dist/components/widgets/DateWidget.d.ts +0 -8
  81. package/dist/components/widgets/EmailWidget.d.ts +0 -8
  82. package/dist/components/widgets/FileWidget.d.ts +0 -19
  83. package/dist/components/widgets/HiddenWidget.d.ts +0 -12
  84. package/dist/components/widgets/PasswordWidget.d.ts +0 -8
  85. package/dist/components/widgets/RadioWidget.d.ts +0 -22
  86. package/dist/components/widgets/RangeWidget.d.ts +0 -8
  87. package/dist/components/widgets/SelectWidget.d.ts +0 -24
  88. package/dist/components/widgets/SubmitButton.d.ts +0 -3
  89. package/dist/components/widgets/TextWidget.d.ts +0 -9
  90. package/dist/components/widgets/TextareaWidget.d.ts +0 -25
  91. package/dist/components/widgets/URLWidget.d.ts +0 -8
  92. package/dist/components/widgets/UpDownWidget.d.ts +0 -8
  93. package/dist/components/widgets/index.d.ts +0 -43
  94. package/dist/defaultRegistry.d.ts +0 -41
  95. package/dist/es/components/AddButton.js +0 -28
  96. package/dist/es/components/ErrorList.js +0 -31
  97. package/dist/es/components/Form.js +0 -572
  98. package/dist/es/components/IconButton.js +0 -27
  99. package/dist/es/components/fields/ArrayField.js +0 -959
  100. package/dist/es/components/fields/BooleanField.js +0 -93
  101. package/dist/es/components/fields/DescriptionField.js +0 -39
  102. package/dist/es/components/fields/MultiSchemaField.js +0 -261
  103. package/dist/es/components/fields/NullField.js +0 -55
  104. package/dist/es/components/fields/NumberField.js +0 -141
  105. package/dist/es/components/fields/ObjectField.js +0 -351
  106. package/dist/es/components/fields/SchemaField.js +0 -528
  107. package/dist/es/components/fields/StringField.js +0 -84
  108. package/dist/es/components/fields/TitleField.js +0 -30
  109. package/dist/es/components/fields/UnsupportedField.js +0 -35
  110. package/dist/es/components/fields/index.js +0 -26
  111. package/dist/es/components/widgets/AltDateTimeWidget.js +0 -36
  112. package/dist/es/components/widgets/AltDateWidget.js +0 -287
  113. package/dist/es/components/widgets/BaseInput.js +0 -140
  114. package/dist/es/components/widgets/CheckboxWidget.js +0 -73
  115. package/dist/es/components/widgets/CheckboxesWidget.js +0 -108
  116. package/dist/es/components/widgets/ColorWidget.js +0 -34
  117. package/dist/es/components/widgets/DateTimeWidget.js +0 -31
  118. package/dist/es/components/widgets/DateWidget.js +0 -28
  119. package/dist/es/components/widgets/EmailWidget.js +0 -23
  120. package/dist/es/components/widgets/FileWidget.js +0 -201
  121. package/dist/es/components/widgets/HiddenWidget.js +0 -25
  122. package/dist/es/components/widgets/PasswordWidget.js +0 -23
  123. package/dist/es/components/widgets/RadioWidget.js +0 -94
  124. package/dist/es/components/widgets/RangeWidget.js +0 -34
  125. package/dist/es/components/widgets/SelectWidget.js +0 -138
  126. package/dist/es/components/widgets/SubmitButton.js +0 -24
  127. package/dist/es/components/widgets/TextWidget.js +0 -20
  128. package/dist/es/components/widgets/TextareaWidget.js +0 -70
  129. package/dist/es/components/widgets/URLWidget.js +0 -23
  130. package/dist/es/components/widgets/UpDownWidget.js +0 -24
  131. package/dist/es/components/widgets/index.js +0 -43
  132. package/dist/es/defaultRegistry.js +0 -12
  133. package/dist/es/index.js +0 -16
  134. package/dist/es/types.js +0 -34
  135. package/dist/es/utils.js +0 -1309
  136. package/dist/es/validate.js +0 -338
  137. package/dist/es/withTheme.js +0 -39
  138. package/dist/react-jsonschema-form.js +0 -26
  139. package/dist/react-jsonschema-form.js.map +0 -1
  140. package/dist/types.d.ts +0 -50
  141. package/dist/utils.d.ts +0 -81
  142. package/dist/validate.d.ts +0 -21
  143. package/dist/withTheme.d.ts +0 -10
  144. package/index.d.ts +0 -500
  145. package/lib/components/AddButton.js +0 -28
  146. package/lib/components/ErrorList.js +0 -31
  147. package/lib/components/Form.js +0 -572
  148. package/lib/components/IconButton.js +0 -27
  149. package/lib/components/fields/ArrayField.js +0 -959
  150. package/lib/components/fields/BooleanField.js +0 -93
  151. package/lib/components/fields/DescriptionField.js +0 -39
  152. package/lib/components/fields/MultiSchemaField.js +0 -261
  153. package/lib/components/fields/NullField.js +0 -55
  154. package/lib/components/fields/NumberField.js +0 -141
  155. package/lib/components/fields/ObjectField.js +0 -351
  156. package/lib/components/fields/SchemaField.js +0 -528
  157. package/lib/components/fields/StringField.js +0 -84
  158. package/lib/components/fields/TitleField.js +0 -30
  159. package/lib/components/fields/UnsupportedField.js +0 -35
  160. package/lib/components/fields/index.js +0 -26
  161. package/lib/components/widgets/AltDateTimeWidget.js +0 -36
  162. package/lib/components/widgets/AltDateWidget.js +0 -287
  163. package/lib/components/widgets/BaseInput.js +0 -140
  164. package/lib/components/widgets/CheckboxWidget.js +0 -73
  165. package/lib/components/widgets/CheckboxesWidget.js +0 -108
  166. package/lib/components/widgets/ColorWidget.js +0 -34
  167. package/lib/components/widgets/DateTimeWidget.js +0 -31
  168. package/lib/components/widgets/DateWidget.js +0 -28
  169. package/lib/components/widgets/EmailWidget.js +0 -23
  170. package/lib/components/widgets/FileWidget.js +0 -201
  171. package/lib/components/widgets/HiddenWidget.js +0 -25
  172. package/lib/components/widgets/PasswordWidget.js +0 -23
  173. package/lib/components/widgets/RadioWidget.js +0 -94
  174. package/lib/components/widgets/RangeWidget.js +0 -34
  175. package/lib/components/widgets/SelectWidget.js +0 -138
  176. package/lib/components/widgets/SubmitButton.js +0 -24
  177. package/lib/components/widgets/TextWidget.js +0 -20
  178. package/lib/components/widgets/TextareaWidget.js +0 -70
  179. package/lib/components/widgets/URLWidget.js +0 -23
  180. package/lib/components/widgets/UpDownWidget.js +0 -24
  181. package/lib/components/widgets/index.js +0 -43
  182. package/lib/defaultRegistry.js +0 -12
  183. package/lib/index.js +0 -16
  184. package/lib/types.js +0 -34
  185. package/lib/utils.js +0 -1309
  186. package/lib/validate.js +0 -338
  187. package/lib/withTheme.js +0 -39
@@ -0,0 +1,4119 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@rjsf/utils'), require('lodash-es/pick'), require('lodash-es/get'), require('lodash-es/isEmpty'), require('lodash-es/isObject'), require('lodash-es/set'), require('nanoid'), require('lodash-es/unset'), require('lodash-es/has'), require('lodash-es/omit')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react', '@rjsf/utils', 'lodash-es/pick', 'lodash-es/get', 'lodash-es/isEmpty', 'lodash-es/isObject', 'lodash-es/set', 'nanoid', 'lodash-es/unset', 'lodash-es/has', 'lodash-es/omit'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@rjsf/core"] = {}, global.React, global.utils, global._pick, global.get, global._isEmpty, global.isObject, global.set, global.nanoid, global.unset, global.has, global.omit));
5
+ })(this, (function (exports, React, utils, _pick, get, _isEmpty, isObject, set, nanoid, unset, has, omit) { 'use strict';
6
+
7
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
+ var _pick__default = /*#__PURE__*/_interopDefaultLegacy(_pick);
11
+ var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
12
+ var _isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(_isEmpty);
13
+ var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
14
+ var set__default = /*#__PURE__*/_interopDefaultLegacy(set);
15
+ var unset__default = /*#__PURE__*/_interopDefaultLegacy(unset);
16
+ var has__default = /*#__PURE__*/_interopDefaultLegacy(has);
17
+ var omit__default = /*#__PURE__*/_interopDefaultLegacy(omit);
18
+
19
+ /** Used to generate a unique ID for an element in a row */
20
+
21
+ function generateRowId() {
22
+ return nanoid.nanoid();
23
+ }
24
+ /** Converts the `formData` into `KeyedFormDataType` data, using the `generateRowId()` function to create the key
25
+ *
26
+ * @param formData - The data for the form
27
+ * @returns - The `formData` converted into a `KeyedFormDataType` element
28
+ */
29
+
30
+
31
+ function generateKeyedFormData(formData) {
32
+ return !Array.isArray(formData) ? [] : formData.map(item => {
33
+ return {
34
+ key: generateRowId(),
35
+ item
36
+ };
37
+ });
38
+ }
39
+ /** Converts `KeyedFormDataType` data into the inner `formData`
40
+ *
41
+ * @param keyedFormData - The `KeyedFormDataType` to be converted
42
+ * @returns - The inner `formData` item(s) in the `keyedFormData`
43
+ */
44
+
45
+
46
+ function keyedToPlainFormData(keyedFormData) {
47
+ if (Array.isArray(keyedFormData)) {
48
+ return keyedFormData.map(keyedItem => keyedItem.item);
49
+ }
50
+
51
+ return [];
52
+ }
53
+ /** The `ArrayField` component is used to render a field in the schema that is of type `array`. It supports both normal
54
+ * and fixed array, allowing user to add and remove elements from the array data.
55
+ */
56
+
57
+
58
+ class ArrayField extends React.Component {
59
+ /** Constructs an `ArrayField` from the `props`, generating the initial keyed data from the `formData`
60
+ *
61
+ * @param props - The `FieldProps` for this template
62
+ */
63
+ constructor(props) {
64
+ super(props);
65
+
66
+ this._getNewFormDataRow = () => {
67
+ const {
68
+ schema,
69
+ registry
70
+ } = this.props;
71
+ const {
72
+ schemaUtils
73
+ } = registry;
74
+ let itemSchema = schema.items;
75
+
76
+ if (utils.isFixedItems(schema) && utils.allowAdditionalItems(schema)) {
77
+ itemSchema = schema.additionalItems;
78
+ } // Cast this as a T to work around schema utils being for T[] caused by the FieldProps<T[], F> call on the class
79
+
80
+
81
+ return schemaUtils.getDefaultFormState(itemSchema);
82
+ };
83
+
84
+ this.onAddClick = event => {
85
+ if (event) {
86
+ event.preventDefault();
87
+ }
88
+
89
+ const {
90
+ onChange
91
+ } = this.props;
92
+ const {
93
+ keyedFormData
94
+ } = this.state;
95
+ const newKeyedFormDataRow = {
96
+ key: generateRowId(),
97
+ item: this._getNewFormDataRow()
98
+ };
99
+ const newKeyedFormData = [...keyedFormData, newKeyedFormDataRow];
100
+ this.setState({
101
+ keyedFormData: newKeyedFormData,
102
+ updatedKeyedFormData: true
103
+ }, () => onChange(keyedToPlainFormData(newKeyedFormData)));
104
+ };
105
+
106
+ this.onAddIndexClick = index => {
107
+ return event => {
108
+ if (event) {
109
+ event.preventDefault();
110
+ }
111
+
112
+ const {
113
+ onChange
114
+ } = this.props;
115
+ const {
116
+ keyedFormData
117
+ } = this.state;
118
+ const newKeyedFormDataRow = {
119
+ key: generateRowId(),
120
+ item: this._getNewFormDataRow()
121
+ };
122
+ const newKeyedFormData = [...keyedFormData];
123
+ newKeyedFormData.splice(index, 0, newKeyedFormDataRow);
124
+ this.setState({
125
+ keyedFormData: newKeyedFormData,
126
+ updatedKeyedFormData: true
127
+ }, () => onChange(keyedToPlainFormData(newKeyedFormData)));
128
+ };
129
+ };
130
+
131
+ this.onDropIndexClick = index => {
132
+ return event => {
133
+ if (event) {
134
+ event.preventDefault();
135
+ }
136
+
137
+ const {
138
+ onChange,
139
+ errorSchema
140
+ } = this.props;
141
+ const {
142
+ keyedFormData
143
+ } = this.state; // refs #195: revalidate to ensure properly reindexing errors
144
+
145
+ let newErrorSchema;
146
+
147
+ if (errorSchema) {
148
+ newErrorSchema = {};
149
+
150
+ for (const idx in errorSchema) {
151
+ const i = parseInt(idx);
152
+
153
+ if (i < index) {
154
+ set__default["default"](newErrorSchema, [i], errorSchema[idx]);
155
+ } else if (i > index) {
156
+ set__default["default"](newErrorSchema, [i - 1], errorSchema[idx]);
157
+ }
158
+ }
159
+ }
160
+
161
+ const newKeyedFormData = keyedFormData.filter((_, i) => i !== index);
162
+ this.setState({
163
+ keyedFormData: newKeyedFormData,
164
+ updatedKeyedFormData: true
165
+ }, () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema));
166
+ };
167
+ };
168
+
169
+ this.onReorderClick = (index, newIndex) => {
170
+ return event => {
171
+ if (event) {
172
+ event.preventDefault();
173
+ event.currentTarget.blur();
174
+ }
175
+
176
+ const {
177
+ onChange,
178
+ errorSchema
179
+ } = this.props;
180
+ let newErrorSchema;
181
+
182
+ if (this.props.errorSchema) {
183
+ newErrorSchema = {};
184
+
185
+ for (const idx in errorSchema) {
186
+ const i = parseInt(idx);
187
+
188
+ if (i == index) {
189
+ set__default["default"](newErrorSchema, [newIndex], errorSchema[index]);
190
+ } else if (i == newIndex) {
191
+ set__default["default"](newErrorSchema, [index], errorSchema[newIndex]);
192
+ } else {
193
+ set__default["default"](newErrorSchema, [idx], errorSchema[i]);
194
+ }
195
+ }
196
+ }
197
+
198
+ const {
199
+ keyedFormData
200
+ } = this.state;
201
+
202
+ function reOrderArray() {
203
+ // Copy item
204
+ const _newKeyedFormData = keyedFormData.slice(); // Moves item from index to newIndex
205
+
206
+
207
+ _newKeyedFormData.splice(index, 1);
208
+
209
+ _newKeyedFormData.splice(newIndex, 0, keyedFormData[index]);
210
+
211
+ return _newKeyedFormData;
212
+ }
213
+
214
+ const newKeyedFormData = reOrderArray();
215
+ this.setState({
216
+ keyedFormData: newKeyedFormData
217
+ }, () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema));
218
+ };
219
+ };
220
+
221
+ this.onChangeForIndex = index => {
222
+ return (value, newErrorSchema) => {
223
+ const {
224
+ formData,
225
+ onChange,
226
+ errorSchema
227
+ } = this.props;
228
+ const arrayData = Array.isArray(formData) ? formData : [];
229
+ const newFormData = arrayData.map((item, i) => {
230
+ // We need to treat undefined items as nulls to have validation.
231
+ // See https://github.com/tdegrunt/jsonschema/issues/206
232
+ const jsonValue = typeof value === "undefined" ? null : value;
233
+ return index === i ? jsonValue : item;
234
+ });
235
+ onChange(newFormData, errorSchema && errorSchema && { ...errorSchema,
236
+ [index]: newErrorSchema
237
+ });
238
+ };
239
+ };
240
+
241
+ this.onSelectChange = value => {
242
+ const {
243
+ onChange
244
+ } = this.props;
245
+ onChange(value);
246
+ };
247
+
248
+ const {
249
+ formData: _formData = []
250
+ } = props;
251
+
252
+ const _keyedFormData = generateKeyedFormData(_formData);
253
+
254
+ this.state = {
255
+ keyedFormData: _keyedFormData,
256
+ updatedKeyedFormData: false
257
+ };
258
+ }
259
+ /** React lifecycle method that is called when the props are about to change allowing the state to be updated. It
260
+ * regenerates the keyed form data and returns it
261
+ *
262
+ * @param nextProps - The next set of props data
263
+ * @param prevState - The previous set of state data
264
+ */
265
+
266
+
267
+ static getDerivedStateFromProps(nextProps, prevState) {
268
+ // Don't call getDerivedStateFromProps if keyed formdata was just updated.
269
+ if (prevState.updatedKeyedFormData) {
270
+ return {
271
+ updatedKeyedFormData: false
272
+ };
273
+ }
274
+
275
+ const nextFormData = Array.isArray(nextProps.formData) ? nextProps.formData : [];
276
+ const previousKeyedFormData = prevState.keyedFormData || [];
277
+ const newKeyedFormData = nextFormData.length === previousKeyedFormData.length ? previousKeyedFormData.map((previousKeyedFormDatum, index) => {
278
+ return {
279
+ key: previousKeyedFormDatum.key,
280
+ item: nextFormData[index]
281
+ };
282
+ }) : generateKeyedFormData(nextFormData);
283
+ return {
284
+ keyedFormData: newKeyedFormData
285
+ };
286
+ }
287
+ /** Returns the appropriate title for an item by getting first the title from the schema.items, then falling back to
288
+ * the description from the schema.items, and finally the string "Item"
289
+ */
290
+
291
+
292
+ get itemTitle() {
293
+ const {
294
+ schema
295
+ } = this.props;
296
+ return get__default["default"](schema, [utils.ITEMS_KEY, "title"], get__default["default"](schema, [utils.ITEMS_KEY, "description"], "Item"));
297
+ }
298
+ /** Determines whether the item described in the schema is always required, which is determined by whether any item
299
+ * may be null.
300
+ *
301
+ * @param itemSchema - The schema for the item
302
+ * @return - True if the item schema type does not contain the "null" type
303
+ */
304
+
305
+
306
+ isItemRequired(itemSchema) {
307
+ if (Array.isArray(itemSchema.type)) {
308
+ // While we don't yet support composite/nullable jsonschema types, it's
309
+ // future-proof to check for requirement against these.
310
+ return !itemSchema.type.includes("null");
311
+ } // All non-null array item types are inherently required by design
312
+
313
+
314
+ return itemSchema.type !== "null";
315
+ }
316
+ /** Determines whether more items can be added to the array. If the uiSchema indicates the array doesn't allow adding
317
+ * then false is returned. Otherwise, if the schema indicates that there are a maximum number of items and the
318
+ * `formData` matches that value, then false is returned, otherwise true is returned.
319
+ *
320
+ * @param formItems - The list of items in the form
321
+ * @returns - True if the item is addable otherwise false
322
+ */
323
+
324
+
325
+ canAddItem(formItems) {
326
+ const {
327
+ schema,
328
+ uiSchema
329
+ } = this.props;
330
+ let {
331
+ addable
332
+ } = utils.getUiOptions(uiSchema);
333
+
334
+ if (addable !== false) {
335
+ // if ui:options.addable was not explicitly set to false, we can add
336
+ // another item if we have not exceeded maxItems yet
337
+ if (schema.maxItems !== undefined) {
338
+ addable = formItems.length < schema.maxItems;
339
+ } else {
340
+ addable = true;
341
+ }
342
+ }
343
+
344
+ return addable;
345
+ }
346
+ /** Returns the default form information for an item based on the schema for that item. Deals with the possibility
347
+ * that the schema is fixed and allows additional items.
348
+ */
349
+
350
+
351
+ /** Renders the `ArrayField` depending on the specific needs of the schema and uischema elements
352
+ */
353
+ render() {
354
+ const {
355
+ schema,
356
+ uiSchema,
357
+ idSchema,
358
+ registry
359
+ } = this.props;
360
+ const {
361
+ schemaUtils
362
+ } = registry;
363
+
364
+ if (!(utils.ITEMS_KEY in schema)) {
365
+ const uiOptions = utils.getUiOptions(uiSchema);
366
+ const UnsupportedFieldTemplate = utils.getTemplate("UnsupportedFieldTemplate", registry, uiOptions);
367
+ return /*#__PURE__*/React__default["default"].createElement(UnsupportedFieldTemplate, {
368
+ schema: schema,
369
+ idSchema: idSchema,
370
+ reason: "Missing items definition",
371
+ registry: registry
372
+ });
373
+ }
374
+
375
+ if (schemaUtils.isMultiSelect(schema)) {
376
+ // If array has enum or uniqueItems set to true, call renderMultiSelect() to render the default multiselect widget or a custom widget, if specified.
377
+ return this.renderMultiSelect();
378
+ }
379
+
380
+ if (utils.isCustomWidget(uiSchema)) {
381
+ return this.renderCustomWidget();
382
+ }
383
+
384
+ if (utils.isFixedItems(schema)) {
385
+ return this.renderFixedArray();
386
+ }
387
+
388
+ if (schemaUtils.isFilesArray(schema, uiSchema)) {
389
+ return this.renderFiles();
390
+ }
391
+
392
+ return this.renderNormalArray();
393
+ }
394
+ /** Renders a normal array without any limitations of length
395
+ */
396
+
397
+
398
+ renderNormalArray() {
399
+ const {
400
+ schema,
401
+ uiSchema = {},
402
+ errorSchema,
403
+ idSchema,
404
+ name,
405
+ disabled = false,
406
+ readonly = false,
407
+ autofocus = false,
408
+ required = false,
409
+ registry,
410
+ onBlur,
411
+ onFocus,
412
+ idPrefix,
413
+ idSeparator = "_",
414
+ rawErrors
415
+ } = this.props;
416
+ const {
417
+ keyedFormData
418
+ } = this.state;
419
+ const title = schema.title === undefined ? name : schema.title;
420
+ const {
421
+ schemaUtils,
422
+ formContext
423
+ } = registry;
424
+ const uiOptions = utils.getUiOptions(uiSchema);
425
+
426
+ const _schemaItems = isObject__default["default"](schema.items) ? schema.items : {};
427
+
428
+ const itemsSchema = schemaUtils.retrieveSchema(_schemaItems);
429
+ const formData = keyedToPlainFormData(this.state.keyedFormData);
430
+ const arrayProps = {
431
+ canAdd: this.canAddItem(formData),
432
+ items: keyedFormData.map((keyedItem, index) => {
433
+ const {
434
+ key,
435
+ item
436
+ } = keyedItem; // While we are actually dealing with a single item of type T, the types require a T[], so cast
437
+
438
+ const itemCast = item;
439
+ const itemSchema = schemaUtils.retrieveSchema(_schemaItems, itemCast);
440
+ const itemErrorSchema = errorSchema ? errorSchema[index] : undefined;
441
+ const itemIdPrefix = idSchema.$id + idSeparator + index;
442
+ const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
443
+ return this.renderArrayFieldItem({
444
+ key,
445
+ index,
446
+ name: name && name + "-" + index,
447
+ canMoveUp: index > 0,
448
+ canMoveDown: index < formData.length - 1,
449
+ itemSchema: itemSchema,
450
+ itemIdSchema,
451
+ itemErrorSchema,
452
+ itemData: itemCast,
453
+ itemUiSchema: uiSchema.items,
454
+ autofocus: autofocus && index === 0,
455
+ onBlur,
456
+ onFocus,
457
+ rawErrors
458
+ });
459
+ }),
460
+ className: "field field-array field-array-of-" + itemsSchema.type,
461
+ disabled,
462
+ idSchema,
463
+ uiSchema,
464
+ onAddClick: this.onAddClick,
465
+ readonly,
466
+ required,
467
+ schema,
468
+ title,
469
+ formContext,
470
+ formData,
471
+ rawErrors,
472
+ registry
473
+ };
474
+ const Template = utils.getTemplate("ArrayFieldTemplate", registry, uiOptions);
475
+ return /*#__PURE__*/React__default["default"].createElement(Template, { ...arrayProps
476
+ });
477
+ }
478
+ /** Renders an array using the custom widget provided by the user in the `uiSchema`
479
+ */
480
+
481
+
482
+ renderCustomWidget() {
483
+ const {
484
+ schema,
485
+ idSchema,
486
+ uiSchema,
487
+ disabled = false,
488
+ readonly = false,
489
+ autofocus = false,
490
+ required = false,
491
+ hideError,
492
+ placeholder,
493
+ onBlur,
494
+ onFocus,
495
+ formData: items = [],
496
+ registry,
497
+ rawErrors,
498
+ name
499
+ } = this.props;
500
+ const {
501
+ widgets,
502
+ formContext
503
+ } = registry;
504
+ const title = schema.title || name;
505
+ const {
506
+ widget,
507
+ ...options
508
+ } = utils.getUiOptions(uiSchema);
509
+ const Widget = utils.getWidget(schema, widget, widgets);
510
+ return /*#__PURE__*/React__default["default"].createElement(Widget, {
511
+ id: idSchema && idSchema.$id,
512
+ multiple: true,
513
+ onChange: this.onSelectChange,
514
+ onBlur: onBlur,
515
+ onFocus: onFocus,
516
+ options: options,
517
+ schema: schema,
518
+ uiSchema: uiSchema,
519
+ registry: registry,
520
+ value: items,
521
+ disabled: disabled,
522
+ readonly: readonly,
523
+ hideError: hideError,
524
+ required: required,
525
+ label: title,
526
+ placeholder: placeholder,
527
+ formContext: formContext,
528
+ autofocus: autofocus,
529
+ rawErrors: rawErrors
530
+ });
531
+ }
532
+ /** Renders an array as a set of checkboxes
533
+ */
534
+
535
+
536
+ renderMultiSelect() {
537
+ const {
538
+ schema,
539
+ idSchema,
540
+ uiSchema,
541
+ formData: items = [],
542
+ disabled = false,
543
+ readonly = false,
544
+ autofocus = false,
545
+ required = false,
546
+ placeholder,
547
+ onBlur,
548
+ onFocus,
549
+ registry,
550
+ rawErrors,
551
+ name
552
+ } = this.props;
553
+ const {
554
+ widgets,
555
+ schemaUtils,
556
+ formContext
557
+ } = registry;
558
+ const itemsSchema = schemaUtils.retrieveSchema(schema.items, items);
559
+ const title = schema.title || name;
560
+ const enumOptions = utils.optionsList(itemsSchema);
561
+ const {
562
+ widget = "select",
563
+ ...options
564
+ } = utils.getUiOptions(uiSchema);
565
+ const Widget = utils.getWidget(schema, widget, widgets);
566
+ return /*#__PURE__*/React__default["default"].createElement(Widget, {
567
+ id: idSchema && idSchema.$id,
568
+ multiple: true,
569
+ onChange: this.onSelectChange,
570
+ onBlur: onBlur,
571
+ onFocus: onFocus,
572
+ options: { ...options,
573
+ enumOptions
574
+ },
575
+ schema: schema,
576
+ uiSchema: uiSchema,
577
+ registry: registry,
578
+ value: items,
579
+ disabled: disabled,
580
+ readonly: readonly,
581
+ required: required,
582
+ label: title,
583
+ placeholder: placeholder,
584
+ formContext: formContext,
585
+ autofocus: autofocus,
586
+ rawErrors: rawErrors
587
+ });
588
+ }
589
+ /** Renders an array of files using the `FileWidget`
590
+ */
591
+
592
+
593
+ renderFiles() {
594
+ const {
595
+ schema,
596
+ uiSchema,
597
+ idSchema,
598
+ name,
599
+ disabled = false,
600
+ readonly = false,
601
+ autofocus = false,
602
+ required = false,
603
+ onBlur,
604
+ onFocus,
605
+ registry,
606
+ formData: items = [],
607
+ rawErrors
608
+ } = this.props;
609
+ const title = schema.title || name;
610
+ const {
611
+ widgets,
612
+ formContext
613
+ } = registry;
614
+ const {
615
+ widget = "files",
616
+ ...options
617
+ } = utils.getUiOptions(uiSchema);
618
+ const Widget = utils.getWidget(schema, widget, widgets);
619
+ return /*#__PURE__*/React__default["default"].createElement(Widget, {
620
+ options: options,
621
+ id: idSchema && idSchema.$id,
622
+ multiple: true,
623
+ onChange: this.onSelectChange,
624
+ onBlur: onBlur,
625
+ onFocus: onFocus,
626
+ schema: schema,
627
+ uiSchema: uiSchema,
628
+ title: title,
629
+ value: items,
630
+ disabled: disabled,
631
+ readonly: readonly,
632
+ required: required,
633
+ registry: registry,
634
+ formContext: formContext,
635
+ autofocus: autofocus,
636
+ rawErrors: rawErrors,
637
+ label: ""
638
+ });
639
+ }
640
+ /** Renders an array that has a maximum limit of items
641
+ */
642
+
643
+
644
+ renderFixedArray() {
645
+ const {
646
+ schema,
647
+ uiSchema = {},
648
+ formData = [],
649
+ errorSchema,
650
+ idPrefix,
651
+ idSeparator = "_",
652
+ idSchema,
653
+ name,
654
+ disabled = false,
655
+ readonly = false,
656
+ autofocus = false,
657
+ required = false,
658
+ registry,
659
+ onBlur,
660
+ onFocus,
661
+ rawErrors
662
+ } = this.props;
663
+ const {
664
+ keyedFormData
665
+ } = this.state;
666
+ let {
667
+ formData: items = []
668
+ } = this.props;
669
+ const title = schema.title || name;
670
+ const uiOptions = utils.getUiOptions(uiSchema);
671
+ const {
672
+ schemaUtils,
673
+ formContext
674
+ } = registry;
675
+
676
+ const _schemaItems = isObject__default["default"](schema.items) ? schema.items : [];
677
+
678
+ const itemSchemas = _schemaItems.map((item, index) => schemaUtils.retrieveSchema(item, formData[index]));
679
+
680
+ const additionalSchema = isObject__default["default"](schema.additionalItems) ? schemaUtils.retrieveSchema(schema.additionalItems, formData) : null;
681
+
682
+ if (!items || items.length < itemSchemas.length) {
683
+ // to make sure at least all fixed items are generated
684
+ items = items || [];
685
+ items = items.concat(new Array(itemSchemas.length - items.length));
686
+ } // These are the props passed into the render function
687
+
688
+
689
+ const arrayProps = {
690
+ canAdd: this.canAddItem(items) && !!additionalSchema,
691
+ className: "field field-array field-array-fixed-items",
692
+ disabled,
693
+ idSchema,
694
+ formData,
695
+ items: keyedFormData.map((keyedItem, index) => {
696
+ const {
697
+ key,
698
+ item
699
+ } = keyedItem; // While we are actually dealing with a single item of type T, the types require a T[], so cast
700
+
701
+ const itemCast = item;
702
+ const additional = index >= itemSchemas.length;
703
+ const itemSchema = additional && isObject__default["default"](schema.additionalItems) ? schemaUtils.retrieveSchema(schema.additionalItems, itemCast) : itemSchemas[index];
704
+ const itemIdPrefix = idSchema.$id + idSeparator + index;
705
+ const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
706
+ const itemUiSchema = additional ? uiSchema.additionalItems || {} : Array.isArray(uiSchema.items) ? uiSchema.items[index] : uiSchema.items || {};
707
+ const itemErrorSchema = errorSchema ? errorSchema[index] : undefined;
708
+ return this.renderArrayFieldItem({
709
+ key,
710
+ index,
711
+ name: name && name + "-" + index,
712
+ canRemove: additional,
713
+ canMoveUp: index >= itemSchemas.length + 1,
714
+ canMoveDown: additional && index < items.length - 1,
715
+ itemSchema,
716
+ itemData: itemCast,
717
+ itemUiSchema,
718
+ itemIdSchema,
719
+ itemErrorSchema,
720
+ autofocus: autofocus && index === 0,
721
+ onBlur,
722
+ onFocus,
723
+ rawErrors
724
+ });
725
+ }),
726
+ onAddClick: this.onAddClick,
727
+ readonly,
728
+ required,
729
+ registry,
730
+ schema,
731
+ uiSchema,
732
+ title,
733
+ formContext,
734
+ rawErrors
735
+ };
736
+ const Template = utils.getTemplate("ArrayFieldTemplate", registry, uiOptions);
737
+ return /*#__PURE__*/React__default["default"].createElement(Template, { ...arrayProps
738
+ });
739
+ }
740
+ /** Renders the individual array item using a `SchemaField` along with the additional properties required to be send
741
+ * back to the `ArrayFieldItemTemplate`.
742
+ *
743
+ * @param props - The props for the individual array item to be rendered
744
+ */
745
+
746
+
747
+ renderArrayFieldItem(props) {
748
+ const {
749
+ key,
750
+ index,
751
+ name,
752
+ canRemove = true,
753
+ canMoveUp = true,
754
+ canMoveDown = true,
755
+ itemSchema,
756
+ itemData,
757
+ itemUiSchema,
758
+ itemIdSchema,
759
+ itemErrorSchema,
760
+ autofocus,
761
+ onBlur,
762
+ onFocus,
763
+ rawErrors
764
+ } = props;
765
+ const {
766
+ disabled,
767
+ hideError,
768
+ idPrefix,
769
+ idSeparator,
770
+ readonly,
771
+ uiSchema,
772
+ registry,
773
+ formContext
774
+ } = this.props;
775
+ const {
776
+ fields: {
777
+ ArraySchemaField,
778
+ SchemaField
779
+ }
780
+ } = registry;
781
+ const ItemSchemaField = ArraySchemaField || SchemaField;
782
+ const {
783
+ orderable = true,
784
+ removable = true
785
+ } = utils.getUiOptions(uiSchema);
786
+ const has = {
787
+ moveUp: orderable && canMoveUp,
788
+ moveDown: orderable && canMoveDown,
789
+ remove: removable && canRemove,
790
+ toolbar: false
791
+ };
792
+ has.toolbar = Object.keys(has).some(key => has[key]);
793
+ return {
794
+ children: /*#__PURE__*/React__default["default"].createElement(ItemSchemaField, {
795
+ name: name,
796
+ index: index,
797
+ schema: itemSchema,
798
+ uiSchema: itemUiSchema,
799
+ formData: itemData,
800
+ formContext: formContext,
801
+ errorSchema: itemErrorSchema,
802
+ idPrefix: idPrefix,
803
+ idSeparator: idSeparator,
804
+ idSchema: itemIdSchema,
805
+ required: this.isItemRequired(itemSchema),
806
+ onChange: this.onChangeForIndex(index),
807
+ onBlur: onBlur,
808
+ onFocus: onFocus,
809
+ registry: registry,
810
+ disabled: disabled,
811
+ readonly: readonly,
812
+ hideError: hideError,
813
+ autofocus: autofocus,
814
+ rawErrors: rawErrors
815
+ }),
816
+ className: "array-item",
817
+ disabled,
818
+ hasToolbar: has.toolbar,
819
+ hasMoveUp: has.moveUp,
820
+ hasMoveDown: has.moveDown,
821
+ hasRemove: has.remove,
822
+ index,
823
+ key,
824
+ onAddIndexClick: this.onAddIndexClick,
825
+ onDropIndexClick: this.onDropIndexClick,
826
+ onReorderClick: this.onReorderClick,
827
+ readonly,
828
+ registry,
829
+ uiSchema: itemUiSchema
830
+ };
831
+ }
832
+
833
+ }
834
+
835
+ /** The `BooleanField` component is used to render a field in the schema is boolean. It constructs `enumOptions` for the
836
+ * two boolean values based on the various alternatives in the schema.
837
+ *
838
+ * @param props - The `FieldProps` for this template
839
+ */
840
+
841
+ function BooleanField(props) {
842
+ const {
843
+ schema,
844
+ name,
845
+ uiSchema,
846
+ idSchema,
847
+ formData,
848
+ registry,
849
+ required,
850
+ disabled,
851
+ readonly,
852
+ autofocus,
853
+ onChange,
854
+ onFocus,
855
+ onBlur,
856
+ rawErrors
857
+ } = props;
858
+ const {
859
+ title
860
+ } = schema;
861
+ const {
862
+ widgets,
863
+ formContext
864
+ } = registry;
865
+ const {
866
+ widget = "checkbox",
867
+ ...options
868
+ } = utils.getUiOptions(uiSchema);
869
+ const Widget = utils.getWidget(schema, widget, widgets);
870
+ let enumOptions;
871
+
872
+ if (Array.isArray(schema.oneOf)) {
873
+ enumOptions = utils.optionsList({
874
+ oneOf: schema.oneOf.map(option => {
875
+ if (isObject__default["default"](option)) {
876
+ return { ...option,
877
+ title: option.title || (option.const === true ? "Yes" : "No")
878
+ };
879
+ }
880
+
881
+ return undefined;
882
+ }).filter(o => o) // cast away the error that typescript can't grok is fixed
883
+
884
+ });
885
+ } else {
886
+ var _schema$enum;
887
+
888
+ // We deprecated enumNames in v5. It's intentionally omitted from RSJFSchema type, so we need to cast here.
889
+ const schemaWithEnumNames = schema;
890
+ schema.enum = (_schema$enum = schema.enum) != null ? _schema$enum : [true, false];
891
+
892
+ if (!schemaWithEnumNames.enumNames && schema.enum && schema.enum.length === 2 && schema.enum.every(v => typeof v === "boolean")) {
893
+ enumOptions = [{
894
+ value: schema.enum[0],
895
+ label: schema.enum[0] ? "Yes" : "No"
896
+ }, {
897
+ value: schema.enum[1],
898
+ label: schema.enum[1] ? "Yes" : "No"
899
+ }];
900
+ } else {
901
+ enumOptions = utils.optionsList({
902
+ enum: schema.enum,
903
+ // NOTE: enumNames is deprecated, but still supported for now.
904
+ enumNames: schemaWithEnumNames.enumNames
905
+ });
906
+ }
907
+ }
908
+
909
+ return /*#__PURE__*/React__default["default"].createElement(Widget, {
910
+ options: { ...options,
911
+ enumOptions
912
+ },
913
+ schema: schema,
914
+ uiSchema: uiSchema,
915
+ id: idSchema && idSchema.$id,
916
+ onChange: onChange,
917
+ onFocus: onFocus,
918
+ onBlur: onBlur,
919
+ label: title === undefined ? name : title,
920
+ value: formData,
921
+ required: required,
922
+ disabled: disabled,
923
+ readonly: readonly,
924
+ registry: registry,
925
+ formContext: formContext,
926
+ autofocus: autofocus,
927
+ rawErrors: rawErrors
928
+ });
929
+ }
930
+
931
+ /** The `AnyOfField` component is used to render a field in the schema that is an `anyOf`, `allOf` or `oneOf`. It tracks
932
+ * the currently selected option and cleans up any irrelevant data in `formData`.
933
+ *
934
+ * @param props - The `FieldProps` for this template
935
+ */
936
+
937
+ class AnyOfField extends React.Component {
938
+ /** Constructs an `AnyOfField` with the given `props` to initialize the initially selected option in state
939
+ *
940
+ * @param props - The `FieldProps` for this template
941
+ */
942
+ constructor(props) {
943
+ super(props);
944
+
945
+ this.onOptionChange = option => {
946
+ const selectedOption = parseInt(option, 10);
947
+ const {
948
+ formData,
949
+ onChange,
950
+ options,
951
+ registry
952
+ } = this.props;
953
+ const {
954
+ schemaUtils
955
+ } = registry;
956
+ const newOption = schemaUtils.retrieveSchema(options[selectedOption], formData); // If the new option is of type object and the current data is an object,
957
+ // discard properties added using the old option.
958
+
959
+ let newFormData = undefined;
960
+
961
+ if (utils.guessType(formData) === "object" && (newOption.type === "object" || newOption.properties)) {
962
+ newFormData = Object.assign({}, formData);
963
+ const optionsToDiscard = options.slice();
964
+ optionsToDiscard.splice(selectedOption, 1); // Discard any data added using other options
965
+
966
+ for (const option of optionsToDiscard) {
967
+ if (option.properties) {
968
+ for (const key in option.properties) {
969
+ if (key in newFormData) {
970
+ unset__default["default"](newFormData, key);
971
+ }
972
+ }
973
+ }
974
+ }
975
+ } // Call getDefaultFormState to make sure defaults are populated on change.
976
+
977
+
978
+ onChange(schemaUtils.getDefaultFormState(options[selectedOption], newFormData));
979
+ this.setState({
980
+ selectedOption: parseInt(option, 10)
981
+ });
982
+ };
983
+
984
+ const {
985
+ formData: _formData,
986
+ options: _options
987
+ } = this.props;
988
+ this.state = {
989
+ selectedOption: this.getMatchingOption(0, _formData, _options)
990
+ };
991
+ }
992
+ /** React lifecycle methos that is called when the props and/or state for this component is updated. It recomputes the
993
+ * currently selected option based on the overall `formData`
994
+ *
995
+ * @param prevProps - The previous `FieldProps` for this template
996
+ * @param prevState - The previous `AnyOfFieldState` for this template
997
+ */
998
+
999
+
1000
+ componentDidUpdate(prevProps, prevState) {
1001
+ const {
1002
+ formData,
1003
+ options,
1004
+ idSchema
1005
+ } = this.props;
1006
+ const {
1007
+ selectedOption
1008
+ } = this.state;
1009
+
1010
+ if (!utils.deepEquals(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
1011
+ const matchingOption = this.getMatchingOption(selectedOption, formData, options);
1012
+
1013
+ if (!prevState || matchingOption === selectedOption) {
1014
+ return;
1015
+ }
1016
+
1017
+ this.setState({
1018
+ selectedOption: matchingOption
1019
+ });
1020
+ }
1021
+ }
1022
+ /** Determines the best matching option for the given `formData` and `options`.
1023
+ *
1024
+ * @param formData - The new formData
1025
+ * @param options - The list of options to choose from
1026
+ * @return - The index of the `option` that best matches the `formData`
1027
+ */
1028
+
1029
+
1030
+ getMatchingOption(selectedOption, formData, options) {
1031
+ const {
1032
+ schemaUtils
1033
+ } = this.props.registry;
1034
+ const option = schemaUtils.getMatchingOption(formData, options);
1035
+
1036
+ if (option !== 0) {
1037
+ return option;
1038
+ } // If the form data matches none of the options, use the currently selected
1039
+ // option, assuming it's available; otherwise use the first option
1040
+
1041
+
1042
+ return selectedOption || 0;
1043
+ }
1044
+ /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
1045
+ * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
1046
+ * the `onChange` handler.
1047
+ *
1048
+ * @param option -
1049
+ */
1050
+
1051
+
1052
+ /** Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData`
1053
+ */
1054
+ render() {
1055
+ const {
1056
+ name,
1057
+ baseType,
1058
+ disabled = false,
1059
+ readonly = false,
1060
+ hideError = false,
1061
+ errorSchema = {},
1062
+ formData,
1063
+ formContext,
1064
+ idPrefix,
1065
+ idSeparator,
1066
+ idSchema,
1067
+ onBlur,
1068
+ onChange,
1069
+ onFocus,
1070
+ options,
1071
+ registry,
1072
+ uiSchema,
1073
+ schema
1074
+ } = this.props;
1075
+ const {
1076
+ widgets,
1077
+ fields
1078
+ } = registry;
1079
+ const {
1080
+ SchemaField: _SchemaField
1081
+ } = fields;
1082
+ const {
1083
+ selectedOption
1084
+ } = this.state;
1085
+ const {
1086
+ widget = "select",
1087
+ ...uiOptions
1088
+ } = utils.getUiOptions(uiSchema);
1089
+ const Widget = utils.getWidget({
1090
+ type: "number"
1091
+ }, widget, widgets);
1092
+ const option = options[selectedOption] || null;
1093
+ let optionSchema;
1094
+
1095
+ if (option) {
1096
+ // If the subschema doesn't declare a type, infer the type from the
1097
+ // parent schema
1098
+ optionSchema = option.type ? option : Object.assign({}, option, {
1099
+ type: baseType
1100
+ });
1101
+ }
1102
+
1103
+ const enumOptions = options.map((option, index) => ({
1104
+ label: option.title || "Option " + (index + 1),
1105
+ value: index
1106
+ }));
1107
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1108
+ className: "panel panel-default panel-body"
1109
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
1110
+ className: "form-group"
1111
+ }, /*#__PURE__*/React__default["default"].createElement(Widget, {
1112
+ id: "" + idSchema.$id + (schema.oneOf ? "__oneof_select" : "__anyof_select"),
1113
+ schema: {
1114
+ type: "number",
1115
+ default: 0
1116
+ },
1117
+ onChange: this.onOptionChange,
1118
+ onBlur: onBlur,
1119
+ onFocus: onFocus,
1120
+ value: selectedOption,
1121
+ options: {
1122
+ enumOptions
1123
+ },
1124
+ registry: registry,
1125
+ formContext: formContext,
1126
+ ...uiOptions,
1127
+ label: ""
1128
+ })), option !== null && /*#__PURE__*/React__default["default"].createElement(_SchemaField, {
1129
+ name: name,
1130
+ schema: optionSchema,
1131
+ uiSchema: uiSchema,
1132
+ errorSchema: errorSchema,
1133
+ idSchema: idSchema,
1134
+ idPrefix: idPrefix,
1135
+ idSeparator: idSeparator,
1136
+ formData: formData,
1137
+ formContext: formContext,
1138
+ onChange: onChange,
1139
+ onBlur: onBlur,
1140
+ onFocus: onFocus,
1141
+ registry: registry,
1142
+ disabled: disabled,
1143
+ readonly: readonly,
1144
+ hideError: hideError
1145
+ }));
1146
+ }
1147
+
1148
+ }
1149
+
1150
+ // digits followed by any number of 0 characters up until the end of the line.
1151
+ // Ensuring that there is at least one prefixed character is important so that
1152
+ // you don't incorrectly match against "0".
1153
+
1154
+ const trailingCharMatcherWithPrefix = /\.([0-9]*0)*$/; // This is used for trimming the trailing 0 and . characters without affecting
1155
+ // the rest of the string. Its possible to use one RegEx with groups for this
1156
+ // functionality, but it is fairly complex compared to simply defining two
1157
+ // different matchers.
1158
+
1159
+ const trailingCharMatcher = /[0.]0*$/;
1160
+ /**
1161
+ * The NumberField class has some special handling for dealing with trailing
1162
+ * decimal points and/or zeroes. This logic is designed to allow trailing values
1163
+ * to be visible in the input element, but not be represented in the
1164
+ * corresponding form data.
1165
+ *
1166
+ * The algorithm is as follows:
1167
+ *
1168
+ * 1. When the input value changes the value is cached in the component state
1169
+ *
1170
+ * 2. The value is then normalized, removing trailing decimal points and zeros,
1171
+ * then passed to the "onChange" callback
1172
+ *
1173
+ * 3. When the component is rendered, the formData value is checked against the
1174
+ * value cached in the state. If it matches the cached value, the cached
1175
+ * value is passed to the input instead of the formData value
1176
+ */
1177
+
1178
+ function NumberField(props) {
1179
+ const {
1180
+ registry,
1181
+ onChange,
1182
+ formData,
1183
+ value: initialValue
1184
+ } = props;
1185
+ const [lastValue, setLastValue] = React.useState(initialValue);
1186
+ const {
1187
+ StringField
1188
+ } = registry.fields;
1189
+ let value = formData;
1190
+ /** Handle the change from the `StringField` to properly convert to a number
1191
+ *
1192
+ * @param value - The current value for the change occurring
1193
+ */
1194
+
1195
+ const handleChange = React.useCallback(value => {
1196
+ // Cache the original value in component state
1197
+ setLastValue(value); // Normalize decimals that don't start with a zero character in advance so
1198
+ // that the rest of the normalization logic is simpler
1199
+
1200
+ if (("" + value).charAt(0) === ".") {
1201
+ value = "0" + value;
1202
+ } // Check that the value is a string (this can happen if the widget used is a
1203
+ // <select>, due to an enum declaration etc) then, if the value ends in a
1204
+ // trailing decimal point or multiple zeroes, strip the trailing values
1205
+
1206
+
1207
+ const processed = typeof value === "string" && value.match(trailingCharMatcherWithPrefix) ? utils.asNumber(value.replace(trailingCharMatcher, "")) : utils.asNumber(value);
1208
+ onChange(processed);
1209
+ }, [onChange]);
1210
+
1211
+ if (typeof lastValue === "string" && typeof value === "number") {
1212
+ // Construct a regular expression that checks for a string that consists
1213
+ // of the formData value suffixed with zero or one '.' characters and zero
1214
+ // or more '0' characters
1215
+ const re = new RegExp(("" + value).replace(".", "\\.") + "\\.?0*$"); // If the cached "lastValue" is a match, use that instead of the formData
1216
+ // value to prevent the input value from changing in the UI
1217
+
1218
+ if (lastValue.match(re)) {
1219
+ value = lastValue;
1220
+ }
1221
+ }
1222
+
1223
+ return /*#__PURE__*/React__default["default"].createElement(StringField, { ...props,
1224
+ formData: value,
1225
+ onChange: handleChange
1226
+ });
1227
+ }
1228
+
1229
+ /** The `ObjectField` component is used to render a field in the schema that is of type `object`. It tracks whether an
1230
+ * additional property key was modified and what it was modified to
1231
+ *
1232
+ * @param props - The `FieldProps` for this template
1233
+ */
1234
+
1235
+ class ObjectField extends React.Component {
1236
+ constructor() {
1237
+ var _this;
1238
+
1239
+ super(...arguments);
1240
+ _this = this;
1241
+ this.state = {
1242
+ wasPropertyKeyModified: false,
1243
+ additionalProperties: {}
1244
+ };
1245
+
1246
+ this.onPropertyChange = function (name, addedByAdditionalProperties) {
1247
+ if (addedByAdditionalProperties === void 0) {
1248
+ addedByAdditionalProperties = false;
1249
+ }
1250
+
1251
+ return (value, newErrorSchema) => {
1252
+ const {
1253
+ formData,
1254
+ onChange,
1255
+ errorSchema
1256
+ } = _this.props;
1257
+
1258
+ if (value === undefined && addedByAdditionalProperties) {
1259
+ // Don't set value = undefined for fields added by
1260
+ // additionalProperties. Doing so removes them from the
1261
+ // formData, which causes them to completely disappear
1262
+ // (including the input field for the property name). Unlike
1263
+ // fields which are "mandated" by the schema, these fields can
1264
+ // be set to undefined by clicking a "delete field" button, so
1265
+ // set empty values to the empty string.
1266
+ value = "";
1267
+ }
1268
+
1269
+ const newFormData = { ...formData,
1270
+ [name]: value
1271
+ };
1272
+ onChange(newFormData, errorSchema && errorSchema && { ...errorSchema,
1273
+ [name]: newErrorSchema
1274
+ });
1275
+ };
1276
+ };
1277
+
1278
+ this.onDropPropertyClick = key => {
1279
+ return event => {
1280
+ event.preventDefault();
1281
+ const {
1282
+ onChange,
1283
+ formData
1284
+ } = this.props;
1285
+ const copiedFormData = { ...formData
1286
+ };
1287
+ unset__default["default"](copiedFormData, key);
1288
+ onChange(copiedFormData);
1289
+ };
1290
+ };
1291
+
1292
+ this.getAvailableKey = (preferredKey, formData) => {
1293
+ const {
1294
+ uiSchema
1295
+ } = this.props;
1296
+ const {
1297
+ duplicateKeySuffixSeparator = "-"
1298
+ } = utils.getUiOptions(uiSchema);
1299
+ let index = 0;
1300
+ let newKey = preferredKey;
1301
+
1302
+ while (newKey in formData) {
1303
+ newKey = "" + preferredKey + duplicateKeySuffixSeparator + ++index;
1304
+ }
1305
+
1306
+ return newKey;
1307
+ };
1308
+
1309
+ this.onKeyChange = oldValue => {
1310
+ return (value, newErrorSchema) => {
1311
+ if (oldValue === value) {
1312
+ return;
1313
+ }
1314
+
1315
+ const {
1316
+ formData,
1317
+ onChange,
1318
+ errorSchema
1319
+ } = this.props;
1320
+ value = this.getAvailableKey(value, formData);
1321
+ const newFormData = { ...formData
1322
+ };
1323
+ const newKeys = {
1324
+ [oldValue]: value
1325
+ };
1326
+ const keyValues = Object.keys(newFormData).map(key => {
1327
+ const newKey = newKeys[key] || key;
1328
+ return {
1329
+ [newKey]: newFormData[key]
1330
+ };
1331
+ });
1332
+ const renamedObj = Object.assign({}, ...keyValues);
1333
+ this.setState({
1334
+ wasPropertyKeyModified: true
1335
+ });
1336
+ onChange(renamedObj, errorSchema && errorSchema && { ...errorSchema,
1337
+ [value]: newErrorSchema
1338
+ });
1339
+ };
1340
+ };
1341
+
1342
+ this.handleAddClick = schema => () => {
1343
+ if (!isObject__default["default"](schema.additionalProperties)) {
1344
+ return;
1345
+ }
1346
+
1347
+ const {
1348
+ formData,
1349
+ onChange,
1350
+ registry
1351
+ } = this.props;
1352
+ let type = schema.additionalProperties.type;
1353
+ const newFormData = { ...formData
1354
+ };
1355
+
1356
+ if (utils.REF_KEY in schema.additionalProperties) {
1357
+ const {
1358
+ schemaUtils
1359
+ } = registry;
1360
+ const refSchema = schemaUtils.retrieveSchema({
1361
+ $ref: schema.additionalProperties[utils.REF_KEY]
1362
+ }, formData);
1363
+ type = refSchema.type;
1364
+ }
1365
+
1366
+ const newKey = this.getAvailableKey("newKey", newFormData); // Cast this to make the `set` work properly
1367
+
1368
+ set__default["default"](newFormData, newKey, this.getDefaultValue(type));
1369
+ onChange(newFormData);
1370
+ };
1371
+ }
1372
+
1373
+ /** Returns a flag indicating whether the `name` field is required in the object schema
1374
+ *
1375
+ * @param name - The name of the field to check for required-ness
1376
+ * @returns - True if the field `name` is required, false otherwise
1377
+ */
1378
+ isRequired(name) {
1379
+ const {
1380
+ schema
1381
+ } = this.props;
1382
+ return Array.isArray(schema.required) && schema.required.indexOf(name) !== -1;
1383
+ }
1384
+ /** Returns the `onPropertyChange` handler for the `name` field. Handles the special case where a user is attempting
1385
+ * to clear the data for a field added as an additional property. Calls the `onChange()` handler with the updated
1386
+ * formData.
1387
+ *
1388
+ * @param name - The name of the property
1389
+ * @param addedByAdditionalProperties - Flag indicating whether this property is an additional property
1390
+ * @returns - The onPropertyChange callback for the `name` property
1391
+ */
1392
+
1393
+
1394
+ /** Returns a default value to be used for a new additional schema property of the given `type`
1395
+ *
1396
+ * @param type - The type of the new additional schema property
1397
+ */
1398
+ getDefaultValue(type) {
1399
+ switch (type) {
1400
+ case "string":
1401
+ return "New Value";
1402
+
1403
+ case "array":
1404
+ return [];
1405
+
1406
+ case "boolean":
1407
+ return false;
1408
+
1409
+ case "null":
1410
+ return null;
1411
+
1412
+ case "number":
1413
+ return 0;
1414
+
1415
+ case "object":
1416
+ return {};
1417
+
1418
+ default:
1419
+ // We don't have a datatype for some reason (perhaps additionalProperties was true)
1420
+ return "New Value";
1421
+ }
1422
+ }
1423
+ /** Handles the adding of a new additional property on the given `schema`. Calls the `onChange` callback once the new
1424
+ * default data for that field has been added to the formData.
1425
+ *
1426
+ * @param schema - The schema element to which the new property is being added
1427
+ */
1428
+
1429
+
1430
+ /** Renders the `ObjectField` from the given props
1431
+ */
1432
+ render() {
1433
+ const {
1434
+ schema: rawSchema,
1435
+ uiSchema = {},
1436
+ formData,
1437
+ errorSchema,
1438
+ idSchema,
1439
+ name,
1440
+ required = false,
1441
+ disabled = false,
1442
+ readonly = false,
1443
+ hideError,
1444
+ idPrefix,
1445
+ idSeparator,
1446
+ onBlur,
1447
+ onFocus,
1448
+ registry
1449
+ } = this.props;
1450
+ const {
1451
+ fields,
1452
+ formContext,
1453
+ schemaUtils
1454
+ } = registry;
1455
+ const {
1456
+ SchemaField
1457
+ } = fields;
1458
+ const schema = schemaUtils.retrieveSchema(rawSchema, formData);
1459
+ const uiOptions = utils.getUiOptions(uiSchema);
1460
+ const {
1461
+ properties: schemaProperties = {}
1462
+ } = schema;
1463
+ const title = schema.title === undefined ? name : schema.title;
1464
+ const description = uiOptions.description || schema.description;
1465
+ let orderedProperties;
1466
+
1467
+ try {
1468
+ const properties = Object.keys(schemaProperties);
1469
+ orderedProperties = utils.orderProperties(properties, uiOptions.order);
1470
+ } catch (err) {
1471
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", {
1472
+ className: "config-error",
1473
+ style: {
1474
+ color: "red"
1475
+ }
1476
+ }, "Invalid ", name || "root", " object field configuration:", /*#__PURE__*/React__default["default"].createElement("em", null, err.message), "."), /*#__PURE__*/React__default["default"].createElement("pre", null, JSON.stringify(schema)));
1477
+ }
1478
+
1479
+ const Template = utils.getTemplate("ObjectFieldTemplate", registry, uiOptions);
1480
+ const templateProps = {
1481
+ title: uiOptions.title || title,
1482
+ description,
1483
+ properties: orderedProperties.map(name => {
1484
+ const addedByAdditionalProperties = has__default["default"](schema, [utils.PROPERTIES_KEY, name, utils.ADDITIONAL_PROPERTY_FLAG]);
1485
+ const fieldUiSchema = addedByAdditionalProperties ? uiSchema.additionalProperties : uiSchema[name];
1486
+ const hidden = utils.getUiOptions(fieldUiSchema).widget === "hidden";
1487
+ const fieldIdSchema = get__default["default"](idSchema, [name], {});
1488
+ return {
1489
+ content: /*#__PURE__*/React__default["default"].createElement(SchemaField, {
1490
+ key: name,
1491
+ name: name,
1492
+ required: this.isRequired(name),
1493
+ schema: get__default["default"](schema, [utils.PROPERTIES_KEY, name], {}),
1494
+ uiSchema: fieldUiSchema,
1495
+ errorSchema: get__default["default"](errorSchema, name),
1496
+ idSchema: fieldIdSchema,
1497
+ idPrefix: idPrefix,
1498
+ idSeparator: idSeparator,
1499
+ formData: get__default["default"](formData, name),
1500
+ formContext: formContext,
1501
+ wasPropertyKeyModified: this.state.wasPropertyKeyModified,
1502
+ onKeyChange: this.onKeyChange(name),
1503
+ onChange: this.onPropertyChange(name, addedByAdditionalProperties),
1504
+ onBlur: onBlur,
1505
+ onFocus: onFocus,
1506
+ registry: registry,
1507
+ disabled: disabled,
1508
+ readonly: readonly,
1509
+ hideError: hideError,
1510
+ onDropPropertyClick: this.onDropPropertyClick
1511
+ }),
1512
+ name,
1513
+ readonly,
1514
+ disabled,
1515
+ required,
1516
+ hidden
1517
+ };
1518
+ }),
1519
+ readonly,
1520
+ disabled,
1521
+ required,
1522
+ idSchema,
1523
+ uiSchema,
1524
+ schema,
1525
+ formData,
1526
+ formContext,
1527
+ registry
1528
+ };
1529
+ return /*#__PURE__*/React__default["default"].createElement(Template, { ...templateProps,
1530
+ onAddClick: this.handleAddClick
1531
+ });
1532
+ }
1533
+
1534
+ }
1535
+
1536
+ /** The map of component type to FieldName */
1537
+
1538
+ const COMPONENT_TYPES = {
1539
+ array: "ArrayField",
1540
+ boolean: "BooleanField",
1541
+ integer: "NumberField",
1542
+ number: "NumberField",
1543
+ object: "ObjectField",
1544
+ string: "StringField",
1545
+ null: "NullField"
1546
+ };
1547
+ /** Computes and returns which `Field` implementation to return in order to render the field represented by the
1548
+ * `schema`. The `uiOptions` are used to alter what potential `Field` implementation is actually returned. If no
1549
+ * appropriate `Field` implementation can be found then a wrapper around `UnsupportedFieldTemplate` is used.
1550
+ *
1551
+ * @param schema - The schema from which to obtain the type
1552
+ * @param uiOptions - The UI Options that may affect the component decision
1553
+ * @param idSchema - The id that is passed to the `UnsupportedFieldTemplate`
1554
+ * @param registry - The registry from which fields and templates are obtained
1555
+ * @returns - The `Field` component that is used to render the actual field data
1556
+ */
1557
+
1558
+ function getFieldComponent(schema, uiOptions, idSchema, registry) {
1559
+ const field = uiOptions.field;
1560
+ const {
1561
+ fields
1562
+ } = registry;
1563
+
1564
+ if (typeof field === "function") {
1565
+ return field;
1566
+ }
1567
+
1568
+ if (typeof field === "string" && field in fields) {
1569
+ return fields[field];
1570
+ }
1571
+
1572
+ const schemaType = utils.getSchemaType(schema);
1573
+ const type = Array.isArray(schemaType) ? schemaType[0] : schemaType || "";
1574
+ const componentName = COMPONENT_TYPES[type]; // If the type is not defined and the schema uses 'anyOf' or 'oneOf', don't
1575
+ // render a field and let the MultiSchemaField component handle the form display
1576
+
1577
+ if (!componentName && (schema.anyOf || schema.oneOf)) {
1578
+ return () => null;
1579
+ }
1580
+
1581
+ return componentName in fields ? fields[componentName] : () => {
1582
+ const UnsupportedFieldTemplate = utils.getTemplate("UnsupportedFieldTemplate", registry, uiOptions);
1583
+ return /*#__PURE__*/React__default["default"].createElement(UnsupportedFieldTemplate, {
1584
+ schema: schema,
1585
+ idSchema: idSchema,
1586
+ reason: "Unknown field type " + schema.type,
1587
+ registry: registry
1588
+ });
1589
+ };
1590
+ }
1591
+ /** The `SchemaFieldRender` component is the work-horse of react-jsonschema-form, determining what kind of real field to
1592
+ * render based on the `schema`, `uiSchema` and all the other props. It also deals with rendering the `anyOf` and
1593
+ * `oneOf` fields.
1594
+ *
1595
+ * @param props - The `FieldProps` for this component
1596
+ */
1597
+
1598
+
1599
+ function SchemaFieldRender(props) {
1600
+ const {
1601
+ schema: _schema,
1602
+ idSchema: _idSchema,
1603
+ uiSchema,
1604
+ formData,
1605
+ errorSchema,
1606
+ idPrefix,
1607
+ idSeparator,
1608
+ name,
1609
+ onChange,
1610
+ onKeyChange,
1611
+ onDropPropertyClick,
1612
+ required,
1613
+ registry,
1614
+ wasPropertyKeyModified = false
1615
+ } = props;
1616
+ const {
1617
+ formContext,
1618
+ schemaUtils
1619
+ } = registry;
1620
+ const uiOptions = utils.getUiOptions(uiSchema);
1621
+ const FieldTemplate = utils.getTemplate("FieldTemplate", registry, uiOptions);
1622
+ const DescriptionFieldTemplate = utils.getTemplate("DescriptionFieldTemplate", registry, uiOptions);
1623
+ const FieldHelpTemplate = utils.getTemplate("FieldHelpTemplate", registry, uiOptions);
1624
+ const FieldErrorTemplate = utils.getTemplate("FieldErrorTemplate", registry, uiOptions);
1625
+ const schema = schemaUtils.retrieveSchema(_schema, formData);
1626
+ const idSchema = utils.mergeObjects(schemaUtils.toIdSchema(schema, _idSchema.$id, formData, idPrefix, idSeparator), _idSchema);
1627
+ const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
1628
+ const disabled = Boolean(props.disabled || uiOptions.disabled);
1629
+ const readonly = Boolean(props.readonly || uiOptions.readonly || props.schema.readOnly || schema.readOnly);
1630
+ const uiSchemaHideError = uiOptions.hideError; // Set hideError to the value provided in the uiSchema, otherwise stick with the prop to propagate to children
1631
+
1632
+ const hideError = uiSchemaHideError === undefined ? props.hideError : Boolean(uiSchemaHideError);
1633
+ const autofocus = Boolean(props.autofocus || uiOptions.autofocus);
1634
+
1635
+ if (Object.keys(schema).length === 0) {
1636
+ return null;
1637
+ }
1638
+
1639
+ const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema);
1640
+ const {
1641
+ __errors,
1642
+ ...fieldErrorSchema
1643
+ } = errorSchema || {}; // See #439: uiSchema: Don't pass consumed class names to child components
1644
+
1645
+ const fieldUiSchema = omit__default["default"](uiSchema, ["ui:classNames", "classNames"]);
1646
+
1647
+ if ("ui:options" in fieldUiSchema) {
1648
+ fieldUiSchema["ui:options"] = omit__default["default"](fieldUiSchema["ui:options"], ["classNames"]);
1649
+ }
1650
+
1651
+ const field = /*#__PURE__*/React__default["default"].createElement(FieldComponent, { ...props,
1652
+ idSchema: idSchema,
1653
+ schema: schema,
1654
+ uiSchema: fieldUiSchema,
1655
+ disabled: disabled,
1656
+ readonly: readonly,
1657
+ hideError: hideError,
1658
+ autofocus: autofocus,
1659
+ errorSchema: fieldErrorSchema,
1660
+ formContext: formContext,
1661
+ rawErrors: __errors
1662
+ });
1663
+ const id = idSchema[utils.ID_KEY]; // If this schema has a title defined, but the user has set a new key/label, retain their input.
1664
+
1665
+ let label;
1666
+
1667
+ if (wasPropertyKeyModified) {
1668
+ label = name;
1669
+ } else {
1670
+ label = utils.ADDITIONAL_PROPERTY_FLAG in schema ? name : uiOptions.title || props.schema.title || schema.title || name;
1671
+ }
1672
+
1673
+ const description = uiOptions.description || props.schema.description || schema.description || "";
1674
+ const help = uiOptions.help;
1675
+ const hidden = uiOptions.widget === "hidden";
1676
+ const classNames = ["form-group", "field", "field-" + schema.type];
1677
+
1678
+ if (!hideError && __errors && __errors.length > 0) {
1679
+ classNames.push("field-error has-error has-danger");
1680
+ }
1681
+
1682
+ if (uiSchema !== null && uiSchema !== void 0 && uiSchema.classNames) {
1683
+ {
1684
+ console.warn("'uiSchema.classNames' is deprecated and may be removed in a major release; Use 'ui:classNames' instead.");
1685
+ }
1686
+
1687
+ classNames.push(uiSchema.classNames);
1688
+ }
1689
+
1690
+ if (uiOptions.classNames) {
1691
+ classNames.push(uiOptions.classNames);
1692
+ }
1693
+
1694
+ const helpComponent = /*#__PURE__*/React__default["default"].createElement(FieldHelpTemplate, {
1695
+ help: help,
1696
+ idSchema: idSchema,
1697
+ schema: schema,
1698
+ uiSchema: uiSchema,
1699
+ hasErrors: !hideError && __errors && __errors.length > 0,
1700
+ registry: registry
1701
+ });
1702
+ const errorsComponent = hideError ? undefined : /*#__PURE__*/React__default["default"].createElement(FieldErrorTemplate, {
1703
+ errors: __errors,
1704
+ errorSchema: errorSchema,
1705
+ idSchema: idSchema,
1706
+ schema: schema,
1707
+ uiSchema: uiSchema,
1708
+ registry: registry
1709
+ });
1710
+ const fieldProps = {
1711
+ description: /*#__PURE__*/React__default["default"].createElement(DescriptionFieldTemplate, {
1712
+ id: id + "__description",
1713
+ description: description,
1714
+ registry: registry
1715
+ }),
1716
+ rawDescription: description,
1717
+ help: helpComponent,
1718
+ rawHelp: typeof help === "string" ? help : undefined,
1719
+ errors: errorsComponent,
1720
+ rawErrors: hideError ? undefined : __errors,
1721
+ id,
1722
+ label,
1723
+ hidden,
1724
+ onChange,
1725
+ onKeyChange,
1726
+ onDropPropertyClick,
1727
+ required,
1728
+ disabled,
1729
+ readonly,
1730
+ hideError,
1731
+ displayLabel,
1732
+ classNames: classNames.join(" ").trim(),
1733
+ formContext,
1734
+ formData,
1735
+ schema,
1736
+ uiSchema,
1737
+ registry
1738
+ };
1739
+ const _AnyOfField = registry.fields.AnyOfField;
1740
+ const _OneOfField = registry.fields.OneOfField;
1741
+ return /*#__PURE__*/React__default["default"].createElement(FieldTemplate, { ...fieldProps
1742
+ }, /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, field, schema.anyOf && !(uiSchema !== null && uiSchema !== void 0 && uiSchema["ui:field"]) && !schemaUtils.isSelect(schema) && /*#__PURE__*/React__default["default"].createElement(_AnyOfField, {
1743
+ name: name,
1744
+ disabled: disabled,
1745
+ readonly: readonly,
1746
+ hideError: hideError,
1747
+ errorSchema: errorSchema,
1748
+ formData: formData,
1749
+ formContext: formContext,
1750
+ idPrefix: idPrefix,
1751
+ idSchema: idSchema,
1752
+ idSeparator: idSeparator,
1753
+ onBlur: props.onBlur,
1754
+ onChange: props.onChange,
1755
+ onFocus: props.onFocus,
1756
+ options: schema.anyOf.map(_schema => schemaUtils.retrieveSchema(isObject__default["default"](_schema) ? _schema : {}, formData)),
1757
+ baseType: schema.type,
1758
+ registry: registry,
1759
+ schema: schema,
1760
+ uiSchema: uiSchema
1761
+ }), schema.oneOf && !(uiSchema !== null && uiSchema !== void 0 && uiSchema["ui:field"]) && !schemaUtils.isSelect(schema) && /*#__PURE__*/React__default["default"].createElement(_OneOfField, {
1762
+ name: name,
1763
+ disabled: disabled,
1764
+ readonly: readonly,
1765
+ hideError: hideError,
1766
+ errorSchema: errorSchema,
1767
+ formData: formData,
1768
+ formContext: formContext,
1769
+ idPrefix: idPrefix,
1770
+ idSchema: idSchema,
1771
+ idSeparator: idSeparator,
1772
+ onBlur: props.onBlur,
1773
+ onChange: props.onChange,
1774
+ onFocus: props.onFocus,
1775
+ options: schema.oneOf.map(_schema => schemaUtils.retrieveSchema(isObject__default["default"](_schema) ? _schema : {}, formData)),
1776
+ baseType: schema.type,
1777
+ registry: registry,
1778
+ schema: schema,
1779
+ uiSchema: uiSchema
1780
+ })));
1781
+ }
1782
+ /** The `SchemaField` component determines whether it is necessary to rerender the component based on any props changes
1783
+ * and if so, calls the `SchemaFieldRender` component with the props.
1784
+ */
1785
+
1786
+
1787
+ class SchemaField extends React__default["default"].Component {
1788
+ shouldComponentUpdate(nextProps) {
1789
+ return !utils.deepEquals(this.props, nextProps);
1790
+ }
1791
+
1792
+ render() {
1793
+ return /*#__PURE__*/React__default["default"].createElement(SchemaFieldRender, { ...this.props
1794
+ });
1795
+ }
1796
+
1797
+ }
1798
+
1799
+ /** The `StringField` component is used to render a schema field that represents a string type
1800
+ *
1801
+ * @param props - The `FieldProps` for this template
1802
+ */
1803
+
1804
+ function StringField(props) {
1805
+ const {
1806
+ schema,
1807
+ name,
1808
+ uiSchema,
1809
+ idSchema,
1810
+ formData,
1811
+ required,
1812
+ disabled = false,
1813
+ readonly = false,
1814
+ autofocus = false,
1815
+ onChange,
1816
+ onBlur,
1817
+ onFocus,
1818
+ registry,
1819
+ rawErrors
1820
+ } = props;
1821
+ const {
1822
+ title,
1823
+ format
1824
+ } = schema;
1825
+ const {
1826
+ widgets,
1827
+ formContext,
1828
+ schemaUtils
1829
+ } = registry;
1830
+ const enumOptions = schemaUtils.isSelect(schema) ? utils.optionsList(schema) : undefined;
1831
+ let defaultWidget = enumOptions ? "select" : "text";
1832
+
1833
+ if (format && utils.hasWidget(schema, format, widgets)) {
1834
+ defaultWidget = format;
1835
+ }
1836
+
1837
+ const {
1838
+ widget = defaultWidget,
1839
+ placeholder = "",
1840
+ ...options
1841
+ } = utils.getUiOptions(uiSchema);
1842
+ const Widget = utils.getWidget(schema, widget, widgets);
1843
+ return /*#__PURE__*/React__default["default"].createElement(Widget, {
1844
+ options: { ...options,
1845
+ enumOptions
1846
+ },
1847
+ schema: schema,
1848
+ uiSchema: uiSchema,
1849
+ id: idSchema && idSchema.$id,
1850
+ label: title === undefined ? name : title,
1851
+ value: formData,
1852
+ onChange: onChange,
1853
+ onBlur: onBlur,
1854
+ onFocus: onFocus,
1855
+ required: required,
1856
+ disabled: disabled,
1857
+ readonly: readonly,
1858
+ formContext: formContext,
1859
+ autofocus: autofocus,
1860
+ registry: registry,
1861
+ placeholder: placeholder,
1862
+ rawErrors: rawErrors
1863
+ });
1864
+ }
1865
+
1866
+ /** The `NullField` component is used to render a field in the schema is null. It also ensures that the `formData` is
1867
+ * also set to null if it has no value.
1868
+ *
1869
+ * @param props - The `FieldProps` for this template
1870
+ */
1871
+
1872
+ function NullField(props) {
1873
+ const {
1874
+ formData,
1875
+ onChange
1876
+ } = props;
1877
+ React.useEffect(() => {
1878
+ if (formData === undefined) {
1879
+ onChange(null);
1880
+ }
1881
+ }, [formData, onChange]);
1882
+ return null;
1883
+ }
1884
+
1885
+ const fields = {
1886
+ AnyOfField: AnyOfField,
1887
+ ArrayField,
1888
+ // ArrayField falls back to SchemaField if ArraySchemaField is not defined, which it isn't by default
1889
+ BooleanField,
1890
+ NumberField,
1891
+ ObjectField,
1892
+ OneOfField: AnyOfField,
1893
+ SchemaField,
1894
+ StringField,
1895
+ NullField
1896
+ };
1897
+
1898
+ /** The `ArrayFieldDescriptionTemplate` component renders a `DescriptionFieldTemplate` with an `id` derived from
1899
+ * the `idSchema`.
1900
+ *
1901
+ * @param props - The `ArrayFieldDescriptionProps` for the component
1902
+ */
1903
+
1904
+ function ArrayFieldDescriptionTemplate(props) {
1905
+ const {
1906
+ idSchema,
1907
+ description,
1908
+ registry,
1909
+ uiSchema
1910
+ } = props;
1911
+
1912
+ if (!description) {
1913
+ return null;
1914
+ }
1915
+
1916
+ const options = utils.getUiOptions(uiSchema);
1917
+ const DescriptionFieldTemplate = utils.getTemplate("DescriptionFieldTemplate", registry, options);
1918
+ const id = idSchema.$id + "__description";
1919
+ return /*#__PURE__*/React__default["default"].createElement(DescriptionFieldTemplate, {
1920
+ id: id,
1921
+ description: description,
1922
+ registry: registry
1923
+ });
1924
+ }
1925
+
1926
+ /** The `ArrayFieldItemTemplate` component is the template used to render an items of an array.
1927
+ *
1928
+ * @param props - The `ArrayFieldTemplateItemType` props for the component
1929
+ */
1930
+
1931
+ function ArrayFieldItemTemplate(props) {
1932
+ const {
1933
+ children,
1934
+ className,
1935
+ disabled,
1936
+ hasToolbar,
1937
+ hasMoveDown,
1938
+ hasMoveUp,
1939
+ hasRemove,
1940
+ index,
1941
+ onDropIndexClick,
1942
+ onReorderClick,
1943
+ readonly,
1944
+ registry,
1945
+ uiSchema
1946
+ } = props;
1947
+ const {
1948
+ MoveDownButton,
1949
+ MoveUpButton,
1950
+ RemoveButton
1951
+ } = registry.templates.ButtonTemplates;
1952
+ const btnStyle = {
1953
+ flex: 1,
1954
+ paddingLeft: 6,
1955
+ paddingRight: 6,
1956
+ fontWeight: "bold"
1957
+ };
1958
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1959
+ className: className
1960
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
1961
+ className: hasToolbar ? "col-xs-9" : "col-xs-12"
1962
+ }, children), hasToolbar && /*#__PURE__*/React__default["default"].createElement("div", {
1963
+ className: "col-xs-3 array-item-toolbox"
1964
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
1965
+ className: "btn-group",
1966
+ style: {
1967
+ display: "flex",
1968
+ justifyContent: "space-around"
1969
+ }
1970
+ }, (hasMoveUp || hasMoveDown) && /*#__PURE__*/React__default["default"].createElement(MoveUpButton, {
1971
+ style: btnStyle,
1972
+ disabled: disabled || readonly || !hasMoveUp,
1973
+ onClick: onReorderClick(index, index - 1),
1974
+ uiSchema: uiSchema
1975
+ }), (hasMoveUp || hasMoveDown) && /*#__PURE__*/React__default["default"].createElement(MoveDownButton, {
1976
+ style: btnStyle,
1977
+ disabled: disabled || readonly || !hasMoveDown,
1978
+ onClick: onReorderClick(index, index + 1),
1979
+ uiSchema: uiSchema
1980
+ }), hasRemove && /*#__PURE__*/React__default["default"].createElement(RemoveButton, {
1981
+ style: btnStyle,
1982
+ disabled: disabled || readonly,
1983
+ onClick: onDropIndexClick(index),
1984
+ uiSchema: uiSchema
1985
+ }))));
1986
+ }
1987
+
1988
+ /** The `ArrayFieldTemplate` component is the template used to render all items in an array.
1989
+ *
1990
+ * @param props - The `ArrayFieldTemplateItemType` props for the component
1991
+ */
1992
+
1993
+ function ArrayFieldTemplate(props) {
1994
+ const {
1995
+ canAdd,
1996
+ className,
1997
+ disabled,
1998
+ idSchema,
1999
+ uiSchema,
2000
+ items,
2001
+ onAddClick,
2002
+ readonly,
2003
+ registry,
2004
+ required,
2005
+ schema,
2006
+ title
2007
+ } = props;
2008
+ const uiOptions = utils.getUiOptions(uiSchema);
2009
+ const ArrayFieldDescriptionTemplate = utils.getTemplate("ArrayFieldDescriptionTemplate", registry, uiOptions);
2010
+ const ArrayFieldItemTemplate = utils.getTemplate("ArrayFieldItemTemplate", registry, uiOptions);
2011
+ const ArrayFieldTitleTemplate = utils.getTemplate("ArrayFieldTitleTemplate", registry, uiOptions); // Button templates are not overridden in the uiSchema
2012
+
2013
+ const {
2014
+ ButtonTemplates: {
2015
+ AddButton
2016
+ }
2017
+ } = registry.templates;
2018
+ return /*#__PURE__*/React__default["default"].createElement("fieldset", {
2019
+ className: className,
2020
+ id: idSchema.$id
2021
+ }, /*#__PURE__*/React__default["default"].createElement(ArrayFieldTitleTemplate, {
2022
+ idSchema: idSchema,
2023
+ title: uiOptions.title || title,
2024
+ required: required,
2025
+ uiSchema: uiSchema,
2026
+ registry: registry
2027
+ }), (uiOptions.description || schema.description) && /*#__PURE__*/React__default["default"].createElement(ArrayFieldDescriptionTemplate, {
2028
+ idSchema: idSchema,
2029
+ description: uiOptions.description || schema.description,
2030
+ uiSchema: uiSchema,
2031
+ registry: registry
2032
+ }), /*#__PURE__*/React__default["default"].createElement("div", {
2033
+ className: "row array-item-list"
2034
+ }, items && items.map(_ref => {
2035
+ let {
2036
+ key,
2037
+ ...itemProps
2038
+ } = _ref;
2039
+ return /*#__PURE__*/React__default["default"].createElement(ArrayFieldItemTemplate, {
2040
+ key: key,
2041
+ ...itemProps
2042
+ });
2043
+ })), canAdd && /*#__PURE__*/React__default["default"].createElement(AddButton, {
2044
+ className: "array-item-add",
2045
+ onClick: onAddClick,
2046
+ disabled: disabled || readonly,
2047
+ uiSchema: uiSchema
2048
+ }));
2049
+ }
2050
+
2051
+ /** The `ArrayFieldTitleTemplate` component renders a `TitleFieldTemplate` with an `id` derived from
2052
+ * the `idSchema`.
2053
+ *
2054
+ * @param props - The `ArrayFieldTitleProps` for the component
2055
+ */
2056
+
2057
+ function ArrayFieldTitleTemplate(props) {
2058
+ const {
2059
+ idSchema,
2060
+ title,
2061
+ uiSchema,
2062
+ required,
2063
+ registry
2064
+ } = props;
2065
+
2066
+ if (!title) {
2067
+ return null;
2068
+ }
2069
+
2070
+ const options = utils.getUiOptions(uiSchema);
2071
+ const TitleFieldTemplate = utils.getTemplate("TitleFieldTemplate", registry, options);
2072
+ const id = idSchema.$id + "__title";
2073
+ return /*#__PURE__*/React__default["default"].createElement(TitleFieldTemplate, {
2074
+ id: id,
2075
+ title: title,
2076
+ required: required,
2077
+ uiSchema: uiSchema,
2078
+ registry: registry
2079
+ });
2080
+ }
2081
+
2082
+ /** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
2083
+ * It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
2084
+ * It can be customized/overridden for other themes or individual implementations as needed.
2085
+ *
2086
+ * @param props - The `WidgetProps` for this template
2087
+ */
2088
+
2089
+ function BaseInputTemplate(props) {
2090
+ const {
2091
+ id,
2092
+ value,
2093
+ readonly,
2094
+ disabled,
2095
+ autofocus,
2096
+ onBlur,
2097
+ onFocus,
2098
+ onChange,
2099
+ options,
2100
+ schema,
2101
+ uiSchema,
2102
+ formContext,
2103
+ registry,
2104
+ rawErrors,
2105
+ type,
2106
+ ...rest
2107
+ } = props; // Note: since React 15.2.0 we can't forward unknown element attributes, so we
2108
+ // exclude the "options" and "schema" ones here.
2109
+
2110
+ if (!id) {
2111
+ console.log("No id for", props);
2112
+ throw new Error("no id for props " + JSON.stringify(props));
2113
+ }
2114
+
2115
+ const inputProps = { ...rest,
2116
+ ...utils.getInputProps(schema, type, options)
2117
+ };
2118
+ let inputValue;
2119
+
2120
+ if (inputProps.type === "number" || inputProps.type === "integer") {
2121
+ inputValue = value || value === 0 ? value : "";
2122
+ } else {
2123
+ inputValue = value == null ? "" : value;
2124
+ }
2125
+
2126
+ const _onChange = React.useCallback(_ref => {
2127
+ let {
2128
+ target: {
2129
+ value
2130
+ }
2131
+ } = _ref;
2132
+ return onChange(value === "" ? options.emptyValue : value);
2133
+ }, [onChange, options]);
2134
+
2135
+ const _onBlur = React.useCallback(_ref2 => {
2136
+ let {
2137
+ target: {
2138
+ value
2139
+ }
2140
+ } = _ref2;
2141
+ return onBlur(id, value);
2142
+ }, [onBlur, id]);
2143
+
2144
+ const _onFocus = React.useCallback(_ref3 => {
2145
+ let {
2146
+ target: {
2147
+ value
2148
+ }
2149
+ } = _ref3;
2150
+ return onFocus(id, value);
2151
+ }, [onFocus, id]);
2152
+
2153
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("input", {
2154
+ id: id,
2155
+ name: id,
2156
+ className: "form-control",
2157
+ readOnly: readonly,
2158
+ disabled: disabled,
2159
+ autoFocus: autofocus,
2160
+ value: inputValue,
2161
+ ...inputProps,
2162
+ list: schema.examples ? "examples_" + id : undefined,
2163
+ onChange: _onChange,
2164
+ onBlur: _onBlur,
2165
+ onFocus: _onFocus
2166
+ }), Array.isArray(schema.examples) && /*#__PURE__*/React__default["default"].createElement("datalist", {
2167
+ key: "datalist_" + id,
2168
+ id: "examples_" + id
2169
+ }, [...new Set(schema.examples.concat(schema.default ? [schema.default] : []))].map(example => /*#__PURE__*/React__default["default"].createElement("option", {
2170
+ key: example,
2171
+ value: example
2172
+ }))));
2173
+ }
2174
+
2175
+ /** The `SubmitButton` renders a button that represent the `Submit` action on a form
2176
+ */
2177
+
2178
+ function SubmitButton(_ref) {
2179
+ let {
2180
+ uiSchema
2181
+ } = _ref;
2182
+ const {
2183
+ submitText,
2184
+ norender,
2185
+ props: submitButtonProps = {}
2186
+ } = utils.getSubmitButtonOptions(uiSchema);
2187
+
2188
+ if (norender) {
2189
+ return null;
2190
+ }
2191
+
2192
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("button", {
2193
+ type: "submit",
2194
+ ...submitButtonProps,
2195
+ className: "btn btn-info " + submitButtonProps.className
2196
+ }, submitText));
2197
+ }
2198
+
2199
+ function IconButton(props) {
2200
+ const {
2201
+ iconType = "default",
2202
+ icon,
2203
+ className,
2204
+ uiSchema,
2205
+ ...otherProps
2206
+ } = props;
2207
+ return /*#__PURE__*/React__default["default"].createElement("button", {
2208
+ type: "button",
2209
+ className: "btn btn-" + iconType + " " + className,
2210
+ ...otherProps
2211
+ }, /*#__PURE__*/React__default["default"].createElement("i", {
2212
+ className: "glyphicon glyphicon-" + icon
2213
+ }));
2214
+ }
2215
+ function MoveDownButton(props) {
2216
+ return /*#__PURE__*/React__default["default"].createElement(IconButton, {
2217
+ title: "Move down",
2218
+ className: "array-item-move-down",
2219
+ ...props,
2220
+ icon: "arrow-down"
2221
+ });
2222
+ }
2223
+ function MoveUpButton(props) {
2224
+ return /*#__PURE__*/React__default["default"].createElement(IconButton, {
2225
+ title: "Move up",
2226
+ className: "array-item-move-up",
2227
+ ...props,
2228
+ icon: "arrow-up"
2229
+ });
2230
+ }
2231
+ function RemoveButton(props) {
2232
+ return /*#__PURE__*/React__default["default"].createElement(IconButton, {
2233
+ title: "Remove",
2234
+ className: "array-item-remove",
2235
+ ...props,
2236
+ iconType: "danger",
2237
+ icon: "remove"
2238
+ });
2239
+ }
2240
+
2241
+ /** The `AddButton` renders a button that represent the `Add` action on a form
2242
+ */
2243
+
2244
+ function AddButton(_ref) {
2245
+ let {
2246
+ className,
2247
+ onClick,
2248
+ disabled
2249
+ } = _ref;
2250
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2251
+ className: "row"
2252
+ }, /*#__PURE__*/React__default["default"].createElement("p", {
2253
+ className: "col-xs-3 col-xs-offset-9 text-right " + className
2254
+ }, /*#__PURE__*/React__default["default"].createElement(IconButton, {
2255
+ iconType: "info",
2256
+ icon: "plus",
2257
+ className: "btn-add col-xs-12",
2258
+ title: "Add",
2259
+ onClick: onClick,
2260
+ disabled: disabled
2261
+ })));
2262
+ }
2263
+
2264
+ const buttonTemplates = {
2265
+ SubmitButton,
2266
+ AddButton,
2267
+ MoveDownButton,
2268
+ MoveUpButton,
2269
+ RemoveButton
2270
+ };
2271
+
2272
+ /** The `DescriptionField` is the template to use to render the description of a field
2273
+ *
2274
+ * @param props - The `DescriptionFieldProps` for this component
2275
+ */
2276
+
2277
+ function DescriptionField(props) {
2278
+ const {
2279
+ id,
2280
+ description
2281
+ } = props;
2282
+
2283
+ if (!description) {
2284
+ return null;
2285
+ }
2286
+
2287
+ if (typeof description === "string") {
2288
+ return /*#__PURE__*/React__default["default"].createElement("p", {
2289
+ id: id,
2290
+ className: "field-description"
2291
+ }, description);
2292
+ } else {
2293
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2294
+ id: id,
2295
+ className: "field-description"
2296
+ }, description);
2297
+ }
2298
+ }
2299
+
2300
+ /** The `ErrorList` component is the template that renders the all the errors associated with the fields in the `Form`
2301
+ *
2302
+ * @param props - The `ErrorListProps` for this component
2303
+ */
2304
+
2305
+ function ErrorList(_ref) {
2306
+ let {
2307
+ errors
2308
+ } = _ref;
2309
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2310
+ className: "panel panel-danger errors"
2311
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2312
+ className: "panel-heading"
2313
+ }, /*#__PURE__*/React__default["default"].createElement("h3", {
2314
+ className: "panel-title"
2315
+ }, "Errors")), /*#__PURE__*/React__default["default"].createElement("ul", {
2316
+ className: "list-group"
2317
+ }, errors.map((error, i) => {
2318
+ return /*#__PURE__*/React__default["default"].createElement("li", {
2319
+ key: i,
2320
+ className: "list-group-item text-danger"
2321
+ }, error.stack);
2322
+ })));
2323
+ }
2324
+
2325
+ const REQUIRED_FIELD_SYMBOL$1 = "*";
2326
+ /** Renders a label for a field
2327
+ *
2328
+ * @param props - The `LabelProps` for this component
2329
+ */
2330
+
2331
+ function Label(props) {
2332
+ const {
2333
+ label,
2334
+ required,
2335
+ id
2336
+ } = props;
2337
+
2338
+ if (!label) {
2339
+ return null;
2340
+ }
2341
+
2342
+ return /*#__PURE__*/React__default["default"].createElement("label", {
2343
+ className: "control-label",
2344
+ htmlFor: id
2345
+ }, label, required && /*#__PURE__*/React__default["default"].createElement("span", {
2346
+ className: "required"
2347
+ }, REQUIRED_FIELD_SYMBOL$1));
2348
+ }
2349
+
2350
+ /** The `FieldTemplate` component is the template used by `SchemaField` to render any field. It renders the field
2351
+ * content, (label, description, children, errors and help) inside of a `WrapIfAdditional` component.
2352
+ *
2353
+ * @param props - The `FieldTemplateProps` for this component
2354
+ */
2355
+
2356
+ function FieldTemplate(props) {
2357
+ const {
2358
+ id,
2359
+ label,
2360
+ children,
2361
+ errors,
2362
+ help,
2363
+ description,
2364
+ hidden,
2365
+ required,
2366
+ displayLabel,
2367
+ registry,
2368
+ uiSchema
2369
+ } = props;
2370
+ const uiOptions = utils.getUiOptions(uiSchema);
2371
+ const WrapIfAdditionalTemplate = utils.getTemplate("WrapIfAdditionalTemplate", registry, uiOptions);
2372
+
2373
+ if (hidden) {
2374
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2375
+ className: "hidden"
2376
+ }, children);
2377
+ }
2378
+
2379
+ return /*#__PURE__*/React__default["default"].createElement(WrapIfAdditionalTemplate, { ...props
2380
+ }, displayLabel && /*#__PURE__*/React__default["default"].createElement(Label, {
2381
+ label: label,
2382
+ required: required,
2383
+ id: id
2384
+ }), displayLabel && description ? description : null, children, errors, help);
2385
+ }
2386
+
2387
+ /** The `FieldErrorTemplate` component renders the errors local to the particular field
2388
+ *
2389
+ * @param props - The `FieldErrorProps` for the errors being rendered
2390
+ */
2391
+
2392
+ function FieldErrorTemplate(props) {
2393
+ const {
2394
+ errors = [],
2395
+ idSchema
2396
+ } = props;
2397
+
2398
+ if (errors.length === 0) {
2399
+ return null;
2400
+ }
2401
+
2402
+ const id = idSchema.$id + "__error";
2403
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("ul", {
2404
+ id: id,
2405
+ className: "error-detail bs-callout bs-callout-info"
2406
+ }, errors.filter(elem => !!elem).map((error, index) => {
2407
+ return /*#__PURE__*/React__default["default"].createElement("li", {
2408
+ className: "text-danger",
2409
+ key: index
2410
+ }, error);
2411
+ })));
2412
+ }
2413
+
2414
+ /** The `FieldHelpTemplate` component renders any help desired for a field
2415
+ *
2416
+ * @param props - The `FieldHelpProps` to be rendered
2417
+ */
2418
+
2419
+ function FieldHelpTemplate(props) {
2420
+ const {
2421
+ idSchema,
2422
+ help
2423
+ } = props;
2424
+
2425
+ if (!help) {
2426
+ return null;
2427
+ }
2428
+
2429
+ const id = idSchema.$id + "__help";
2430
+
2431
+ if (typeof help === "string") {
2432
+ return /*#__PURE__*/React__default["default"].createElement("p", {
2433
+ id: id,
2434
+ className: "help-block"
2435
+ }, help);
2436
+ }
2437
+
2438
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2439
+ id: id,
2440
+ className: "help-block"
2441
+ }, help);
2442
+ }
2443
+
2444
+ /** The `ObjectFieldTemplate` is the template to use to render all the inner properties of an object along with the
2445
+ * title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
2446
+ * the properties.
2447
+ *
2448
+ * @param props - The `ObjectFieldTemplateProps` for this component
2449
+ */
2450
+
2451
+ function ObjectFieldTemplate(props) {
2452
+ const {
2453
+ description,
2454
+ disabled,
2455
+ formData,
2456
+ idSchema,
2457
+ onAddClick,
2458
+ properties,
2459
+ readonly,
2460
+ registry,
2461
+ required,
2462
+ schema,
2463
+ title,
2464
+ uiSchema
2465
+ } = props;
2466
+ const options = utils.getUiOptions(uiSchema);
2467
+ const TitleFieldTemplate = utils.getTemplate("TitleFieldTemplate", registry, options);
2468
+ const DescriptionFieldTemplate = utils.getTemplate("DescriptionFieldTemplate", registry, options); // Button templates are not overridden in the uiSchema
2469
+
2470
+ const {
2471
+ ButtonTemplates: {
2472
+ AddButton
2473
+ }
2474
+ } = registry.templates;
2475
+ return /*#__PURE__*/React__default["default"].createElement("fieldset", {
2476
+ id: idSchema.$id
2477
+ }, (options.title || title) && /*#__PURE__*/React__default["default"].createElement(TitleFieldTemplate, {
2478
+ id: idSchema.$id + "__title",
2479
+ title: options.title || title,
2480
+ required: required,
2481
+ uiSchema: uiSchema,
2482
+ registry: registry
2483
+ }), (options.description || description) && /*#__PURE__*/React__default["default"].createElement(DescriptionFieldTemplate, {
2484
+ id: idSchema.$id + "__description",
2485
+ description: options.description || description,
2486
+ registry: registry
2487
+ }), properties.map(prop => prop.content), utils.canExpand(schema, uiSchema, formData) && /*#__PURE__*/React__default["default"].createElement(AddButton, {
2488
+ className: "object-property-expand",
2489
+ onClick: onAddClick(schema),
2490
+ disabled: disabled || readonly,
2491
+ uiSchema: uiSchema
2492
+ }));
2493
+ }
2494
+
2495
+ const REQUIRED_FIELD_SYMBOL = "*";
2496
+ /** The `TitleField` is the template to use to render the title of a field
2497
+ *
2498
+ * @param props - The `TitleFieldProps` for this component
2499
+ */
2500
+
2501
+ function TitleField(props) {
2502
+ const {
2503
+ id,
2504
+ title,
2505
+ required
2506
+ } = props;
2507
+ return /*#__PURE__*/React__default["default"].createElement("legend", {
2508
+ id: id
2509
+ }, title, required && /*#__PURE__*/React__default["default"].createElement("span", {
2510
+ className: "required"
2511
+ }, REQUIRED_FIELD_SYMBOL));
2512
+ }
2513
+
2514
+ /** The `UnsupportedField` component is used to render a field in the schema is one that is not supported by
2515
+ * react-jsonschema-form.
2516
+ *
2517
+ * @param props - The `FieldProps` for this template
2518
+ */
2519
+
2520
+ function UnsupportedField(props) {
2521
+ const {
2522
+ schema,
2523
+ idSchema,
2524
+ reason
2525
+ } = props;
2526
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2527
+ className: "unsupported-field"
2528
+ }, /*#__PURE__*/React__default["default"].createElement("p", null, "Unsupported field schema", idSchema && idSchema.$id && /*#__PURE__*/React__default["default"].createElement("span", null, " for", " field ", /*#__PURE__*/React__default["default"].createElement("code", null, idSchema.$id)), reason && /*#__PURE__*/React__default["default"].createElement("em", null, ": ", reason), "."), schema && /*#__PURE__*/React__default["default"].createElement("pre", null, JSON.stringify(schema, null, 2)));
2529
+ }
2530
+
2531
+ /** The `WrapIfAdditional` component is used by the `FieldTemplate` to rename, or remove properties that are
2532
+ * part of an `additionalProperties` part of a schema.
2533
+ *
2534
+ * @param props - The `WrapIfAdditionalProps` for this component
2535
+ */
2536
+
2537
+ function WrapIfAdditionalTemplate(props) {
2538
+ const {
2539
+ id,
2540
+ classNames,
2541
+ disabled,
2542
+ label,
2543
+ onKeyChange,
2544
+ onDropPropertyClick,
2545
+ readonly,
2546
+ required,
2547
+ schema,
2548
+ children,
2549
+ uiSchema,
2550
+ registry
2551
+ } = props; // Button templates are not overridden in the uiSchema
2552
+
2553
+ const {
2554
+ RemoveButton
2555
+ } = registry.templates.ButtonTemplates;
2556
+ const keyLabel = label + " Key"; // i18n ?
2557
+
2558
+ const additional = (utils.ADDITIONAL_PROPERTY_FLAG in schema);
2559
+
2560
+ if (!additional) {
2561
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2562
+ className: classNames
2563
+ }, children);
2564
+ }
2565
+
2566
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2567
+ className: classNames
2568
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2569
+ className: "row"
2570
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2571
+ className: "col-xs-5 form-additional"
2572
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2573
+ className: "form-group"
2574
+ }, /*#__PURE__*/React__default["default"].createElement(Label, {
2575
+ label: keyLabel,
2576
+ required: required,
2577
+ id: id + "-key"
2578
+ }), /*#__PURE__*/React__default["default"].createElement("input", {
2579
+ className: "form-control",
2580
+ type: "text",
2581
+ id: id + "-key",
2582
+ onBlur: event => onKeyChange(event.target.value),
2583
+ defaultValue: label
2584
+ }))), /*#__PURE__*/React__default["default"].createElement("div", {
2585
+ className: "form-additional form-group col-xs-5"
2586
+ }, children), /*#__PURE__*/React__default["default"].createElement("div", {
2587
+ className: "col-xs-2"
2588
+ }, /*#__PURE__*/React__default["default"].createElement(RemoveButton, {
2589
+ className: "array-item-remove btn-block",
2590
+ style: {
2591
+ border: "0"
2592
+ },
2593
+ disabled: disabled || readonly,
2594
+ onClick: onDropPropertyClick(label),
2595
+ uiSchema: uiSchema
2596
+ }))));
2597
+ }
2598
+
2599
+ const templates = {
2600
+ ArrayFieldDescriptionTemplate,
2601
+ ArrayFieldItemTemplate,
2602
+ ArrayFieldTemplate,
2603
+ ArrayFieldTitleTemplate,
2604
+ ButtonTemplates: buttonTemplates,
2605
+ BaseInputTemplate,
2606
+ DescriptionFieldTemplate: DescriptionField,
2607
+ ErrorListTemplate: ErrorList,
2608
+ FieldTemplate,
2609
+ FieldErrorTemplate,
2610
+ FieldHelpTemplate,
2611
+ ObjectFieldTemplate,
2612
+ TitleFieldTemplate: TitleField,
2613
+ UnsupportedFieldTemplate: UnsupportedField,
2614
+ WrapIfAdditionalTemplate
2615
+ };
2616
+
2617
+ function rangeOptions(start, stop) {
2618
+ const options = [];
2619
+
2620
+ for (let i = start; i <= stop; i++) {
2621
+ options.push({
2622
+ value: i,
2623
+ label: utils.pad(i, 2)
2624
+ });
2625
+ }
2626
+
2627
+ return options;
2628
+ }
2629
+
2630
+ function readyForChange(state) {
2631
+ return Object.values(state).every(value => value !== -1);
2632
+ }
2633
+
2634
+ function dateElementProps(state, time, yearsRange) {
2635
+ if (yearsRange === void 0) {
2636
+ yearsRange = [1900, new Date().getFullYear() + 2];
2637
+ }
2638
+
2639
+ const {
2640
+ year,
2641
+ month,
2642
+ day,
2643
+ hour,
2644
+ minute,
2645
+ second
2646
+ } = state;
2647
+ const data = [{
2648
+ type: "year",
2649
+ range: yearsRange,
2650
+ value: year
2651
+ }, {
2652
+ type: "month",
2653
+ range: [1, 12],
2654
+ value: month
2655
+ }, {
2656
+ type: "day",
2657
+ range: [1, 31],
2658
+ value: day
2659
+ }];
2660
+
2661
+ if (time) {
2662
+ data.push({
2663
+ type: "hour",
2664
+ range: [0, 23],
2665
+ value: hour
2666
+ }, {
2667
+ type: "minute",
2668
+ range: [0, 59],
2669
+ value: minute
2670
+ }, {
2671
+ type: "second",
2672
+ range: [0, 59],
2673
+ value: second
2674
+ });
2675
+ }
2676
+
2677
+ return data;
2678
+ }
2679
+
2680
+ function DateElement(_ref) {
2681
+ let {
2682
+ type,
2683
+ range,
2684
+ value,
2685
+ select,
2686
+ rootId,
2687
+ disabled,
2688
+ readonly,
2689
+ autofocus,
2690
+ registry,
2691
+ onBlur,
2692
+ onFocus
2693
+ } = _ref;
2694
+ const id = rootId + "_" + type;
2695
+ const {
2696
+ SelectWidget
2697
+ } = registry.widgets;
2698
+ return /*#__PURE__*/React__default["default"].createElement(SelectWidget, {
2699
+ schema: {
2700
+ type: "integer"
2701
+ },
2702
+ id: id,
2703
+ className: "form-control",
2704
+ options: {
2705
+ enumOptions: rangeOptions(range[0], range[1])
2706
+ },
2707
+ placeholder: type,
2708
+ value: value,
2709
+ disabled: disabled,
2710
+ readonly: readonly,
2711
+ autofocus: autofocus,
2712
+ onChange: value => select(type, value),
2713
+ onBlur: onBlur,
2714
+ onFocus: onFocus,
2715
+ registry: registry,
2716
+ label: ""
2717
+ });
2718
+ }
2719
+ /** The `AltDateWidget` is an alternative widget for rendering date properties.
2720
+ * @param props - The `WidgetProps` for this component
2721
+ */
2722
+
2723
+
2724
+ function AltDateWidget(_ref2) {
2725
+ let {
2726
+ time = false,
2727
+ disabled = false,
2728
+ readonly = false,
2729
+ autofocus = false,
2730
+ options,
2731
+ id,
2732
+ registry,
2733
+ onBlur,
2734
+ onFocus,
2735
+ onChange,
2736
+ value
2737
+ } = _ref2;
2738
+ const [state, setState] = React.useReducer((state, action) => {
2739
+ return { ...state,
2740
+ ...action
2741
+ };
2742
+ }, utils.parseDateString(value, time));
2743
+ React.useEffect(() => {
2744
+ if (value && value !== utils.toDateString(state, time)) {
2745
+ setState(utils.parseDateString(value, time));
2746
+ }
2747
+ }, [value, state, time]);
2748
+ React.useEffect(() => {
2749
+ if (readyForChange(state)) {
2750
+ // Only propagate to parent state if we have a complete date{time}
2751
+ onChange(utils.toDateString(state, time));
2752
+ }
2753
+ }, [state, time, onChange]);
2754
+ const handleChange = React.useCallback((property, value) => {
2755
+ setState({
2756
+ [property]: value
2757
+ });
2758
+ }, []);
2759
+ const handleSetNow = React.useCallback(event => {
2760
+ event.preventDefault();
2761
+
2762
+ if (disabled || readonly) {
2763
+ return;
2764
+ }
2765
+
2766
+ const nowDateObj = utils.parseDateString(new Date().toJSON(), time);
2767
+ setState(nowDateObj);
2768
+ }, [disabled, readonly, time]);
2769
+ const handleClear = React.useCallback(event => {
2770
+ event.preventDefault();
2771
+
2772
+ if (disabled || readonly) {
2773
+ return;
2774
+ }
2775
+
2776
+ setState(utils.parseDateString("", time));
2777
+ onChange(undefined);
2778
+ }, [disabled, readonly, time, onChange]);
2779
+ return /*#__PURE__*/React__default["default"].createElement("ul", {
2780
+ className: "list-inline"
2781
+ }, dateElementProps(state, time, options.yearsRange).map((elemProps, i) => /*#__PURE__*/React__default["default"].createElement("li", {
2782
+ key: i
2783
+ }, /*#__PURE__*/React__default["default"].createElement(DateElement, {
2784
+ rootId: id,
2785
+ select: handleChange,
2786
+ ...elemProps,
2787
+ disabled: disabled,
2788
+ readonly: readonly,
2789
+ registry: registry,
2790
+ onBlur: onBlur,
2791
+ onFocus: onFocus,
2792
+ autofocus: autofocus && i === 0
2793
+ }))), (options.hideNowButton !== "undefined" ? !options.hideNowButton : true) && /*#__PURE__*/React__default["default"].createElement("li", null, /*#__PURE__*/React__default["default"].createElement("a", {
2794
+ href: "#",
2795
+ className: "btn btn-info btn-now",
2796
+ onClick: handleSetNow
2797
+ }, "Now")), (options.hideClearButton !== "undefined" ? !options.hideClearButton : true) && /*#__PURE__*/React__default["default"].createElement("li", null, /*#__PURE__*/React__default["default"].createElement("a", {
2798
+ href: "#",
2799
+ className: "btn btn-warning btn-clear",
2800
+ onClick: handleClear
2801
+ }, "Clear")));
2802
+ }
2803
+
2804
+ /** The `AltDateTimeWidget` is an alternative widget for rendering datetime properties.
2805
+ * It uses the AltDateWidget for rendering, with the `time` prop set to true by default.
2806
+ *
2807
+ * @param props - The `WidgetProps` for this component
2808
+ */
2809
+
2810
+ function AltDateTimeWidget(_ref) {
2811
+ let {
2812
+ time = true,
2813
+ ...props
2814
+ } = _ref;
2815
+ const {
2816
+ AltDateWidget
2817
+ } = props.registry.widgets;
2818
+ return /*#__PURE__*/React__default["default"].createElement(AltDateWidget, {
2819
+ time: time,
2820
+ ...props
2821
+ });
2822
+ }
2823
+
2824
+ /** The `CheckBoxWidget` is a widget for rendering boolean properties.
2825
+ * It is typically used to represent a boolean.
2826
+ *
2827
+ * @param props - The `WidgetProps` for this component
2828
+ */
2829
+
2830
+ function CheckboxWidget(_ref) {
2831
+ let {
2832
+ schema,
2833
+ options,
2834
+ id,
2835
+ value,
2836
+ disabled,
2837
+ readonly,
2838
+ label,
2839
+ autofocus = false,
2840
+ onBlur,
2841
+ onFocus,
2842
+ onChange,
2843
+ registry
2844
+ } = _ref;
2845
+ const DescriptionFieldTemplate = utils.getTemplate("DescriptionFieldTemplate", registry, options); // Because an unchecked checkbox will cause html5 validation to fail, only add
2846
+ // the "required" attribute if the field value must be "true", due to the
2847
+ // "const" or "enum" keywords
2848
+
2849
+ const required = utils.schemaRequiresTrueValue(schema);
2850
+ const handleChange = React.useCallback(event => onChange(event.target.checked), [onChange]);
2851
+ const handleBlur = React.useCallback(event => onBlur(id, event.target.checked), [onBlur, id]);
2852
+ const handleFocus = React.useCallback(event => onFocus(id, event.target.checked), [onFocus, id]);
2853
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2854
+ className: "checkbox " + (disabled || readonly ? "disabled" : "")
2855
+ }, schema.description && /*#__PURE__*/React__default["default"].createElement(DescriptionFieldTemplate, {
2856
+ id: id + "__description",
2857
+ description: schema.description,
2858
+ registry: registry
2859
+ }), /*#__PURE__*/React__default["default"].createElement("label", null, /*#__PURE__*/React__default["default"].createElement("input", {
2860
+ type: "checkbox",
2861
+ id: id,
2862
+ name: id,
2863
+ checked: typeof value === "undefined" ? false : value,
2864
+ required: required,
2865
+ disabled: disabled || readonly,
2866
+ autoFocus: autofocus,
2867
+ onChange: handleChange,
2868
+ onBlur: handleBlur,
2869
+ onFocus: handleFocus
2870
+ }), /*#__PURE__*/React__default["default"].createElement("span", null, label)));
2871
+ }
2872
+
2873
+ function selectValue(value, selected, all) {
2874
+ const at = all.indexOf(value);
2875
+ const updated = selected.slice(0, at).concat(value, selected.slice(at)); // As inserting values at predefined index positions doesn't work with empty
2876
+ // arrays, we need to reorder the updated selection to match the initial order
2877
+
2878
+ return updated.sort((a, b) => Number(all.indexOf(a) > all.indexOf(b)));
2879
+ }
2880
+
2881
+ function deselectValue(value, selected) {
2882
+ return selected.filter(v => v !== value);
2883
+ }
2884
+ /** The `CheckboxesWidget` is a widget for rendering checkbox groups.
2885
+ * It is typically used to represent an array of enums.
2886
+ *
2887
+ * @param props - The `WidgetProps` for this component
2888
+ */
2889
+
2890
+
2891
+ function CheckboxesWidget(_ref) {
2892
+ let {
2893
+ id,
2894
+ disabled,
2895
+ options: {
2896
+ inline = false,
2897
+ enumOptions,
2898
+ enumDisabled
2899
+ },
2900
+ value,
2901
+ autofocus = false,
2902
+ readonly,
2903
+ onChange
2904
+ } = _ref;
2905
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2906
+ className: "checkboxes",
2907
+ id: id
2908
+ }, Array.isArray(enumOptions) && enumOptions.map((option, index) => {
2909
+ const checked = value.indexOf(option.value) !== -1;
2910
+ const itemDisabled = Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) != -1;
2911
+ const disabledCls = disabled || itemDisabled || readonly ? "disabled" : "";
2912
+
2913
+ const handleChange = event => {
2914
+ const all = enumOptions.map(_ref2 => {
2915
+ let {
2916
+ value
2917
+ } = _ref2;
2918
+ return value;
2919
+ });
2920
+
2921
+ if (event.target.checked) {
2922
+ onChange(selectValue(option.value, value, all));
2923
+ } else {
2924
+ onChange(deselectValue(option.value, value));
2925
+ }
2926
+ };
2927
+
2928
+ const checkbox = /*#__PURE__*/React__default["default"].createElement("span", null, /*#__PURE__*/React__default["default"].createElement("input", {
2929
+ type: "checkbox",
2930
+ id: id + "-" + option.value,
2931
+ name: id,
2932
+ checked: checked,
2933
+ disabled: disabled || itemDisabled || readonly,
2934
+ autoFocus: autofocus && index === 0,
2935
+ onChange: handleChange
2936
+ }), /*#__PURE__*/React__default["default"].createElement("span", null, option.label));
2937
+ return inline ? /*#__PURE__*/React__default["default"].createElement("label", {
2938
+ key: option.value,
2939
+ className: "checkbox-inline " + disabledCls
2940
+ }, checkbox) : /*#__PURE__*/React__default["default"].createElement("div", {
2941
+ key: option.value,
2942
+ className: "checkbox " + disabledCls
2943
+ }, /*#__PURE__*/React__default["default"].createElement("label", null, checkbox));
2944
+ }));
2945
+ }
2946
+
2947
+ /** The `ColorWidget` component uses the `BaseInputTemplate` changing the type to `color` and disables it when it is
2948
+ * either disabled or readonly.
2949
+ *
2950
+ * @param props - The `WidgetProps` for this component
2951
+ */
2952
+
2953
+ function ColorWidget(props) {
2954
+ const {
2955
+ disabled,
2956
+ readonly,
2957
+ options,
2958
+ registry
2959
+ } = props;
2960
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
2961
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
2962
+ type: "color",
2963
+ ...props,
2964
+ disabled: disabled || readonly
2965
+ });
2966
+ }
2967
+
2968
+ /** The `DateWidget` component uses the `BaseInputTemplate` changing the type to `date` and transforms
2969
+ * the value to undefined when it is falsy during the `onChange` handling.
2970
+ *
2971
+ * @param props - The `WidgetProps` for this component
2972
+ */
2973
+
2974
+ function DateWidget(props) {
2975
+ const {
2976
+ onChange,
2977
+ options,
2978
+ registry
2979
+ } = props;
2980
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
2981
+ const handleChange = React.useCallback(value => onChange(value || undefined), [onChange]);
2982
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
2983
+ type: "date",
2984
+ ...props,
2985
+ onChange: handleChange
2986
+ });
2987
+ }
2988
+
2989
+ /** The `DateTimeWidget` component uses the `BaseInputTemplate` changing the type to `datetime-local` and transforms
2990
+ * the value to/from utc using the appropriate utility functions.
2991
+ *
2992
+ * @param props - The `WidgetProps` for this component
2993
+ */
2994
+
2995
+ function DateTimeWidget(props) {
2996
+ const {
2997
+ onChange,
2998
+ value,
2999
+ options,
3000
+ registry
3001
+ } = props;
3002
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3003
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3004
+ type: "datetime-local",
3005
+ ...props,
3006
+ value: utils.utcToLocal(value),
3007
+ onChange: value => onChange(utils.localToUTC(value))
3008
+ });
3009
+ }
3010
+
3011
+ /** The `EmailWidget` component uses the `BaseInputTemplate` changing the type to `email`.
3012
+ *
3013
+ * @param props - The `WidgetProps` for this component
3014
+ */
3015
+
3016
+ function EmailWidget(props) {
3017
+ const {
3018
+ options,
3019
+ registry
3020
+ } = props;
3021
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3022
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3023
+ type: "email",
3024
+ ...props
3025
+ });
3026
+ }
3027
+
3028
+ function addNameToDataURL(dataURL, name) {
3029
+ if (dataURL === null) {
3030
+ return null;
3031
+ }
3032
+
3033
+ return dataURL.replace(";base64", ";name=" + encodeURIComponent(name) + ";base64");
3034
+ }
3035
+
3036
+ function processFile(file) {
3037
+ const {
3038
+ name,
3039
+ size,
3040
+ type
3041
+ } = file;
3042
+ return new Promise((resolve, reject) => {
3043
+ const reader = new window.FileReader();
3044
+ reader.onerror = reject;
3045
+
3046
+ reader.onload = event => {
3047
+ var _event$target;
3048
+
3049
+ if (typeof ((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.result) === "string") {
3050
+ resolve({
3051
+ dataURL: addNameToDataURL(event.target.result, name),
3052
+ name,
3053
+ size,
3054
+ type
3055
+ });
3056
+ } else {
3057
+ resolve({
3058
+ dataURL: null,
3059
+ name,
3060
+ size,
3061
+ type
3062
+ });
3063
+ }
3064
+ };
3065
+
3066
+ reader.readAsDataURL(file);
3067
+ });
3068
+ }
3069
+
3070
+ function processFiles(files) {
3071
+ return Promise.all(Array.from(files).map(processFile));
3072
+ }
3073
+
3074
+ function FilesInfo(_ref) {
3075
+ let {
3076
+ filesInfo
3077
+ } = _ref;
3078
+
3079
+ if (filesInfo.length === 0) {
3080
+ return null;
3081
+ }
3082
+
3083
+ return /*#__PURE__*/React__default["default"].createElement("ul", {
3084
+ className: "file-info"
3085
+ }, filesInfo.map((fileInfo, key) => {
3086
+ const {
3087
+ name,
3088
+ size,
3089
+ type
3090
+ } = fileInfo;
3091
+ return /*#__PURE__*/React__default["default"].createElement("li", {
3092
+ key: key
3093
+ }, /*#__PURE__*/React__default["default"].createElement("strong", null, name), " (", type, ", ", size, " bytes)");
3094
+ }));
3095
+ }
3096
+
3097
+ function extractFileInfo(dataURLs) {
3098
+ return dataURLs.filter(dataURL => typeof dataURL !== "undefined").map(dataURL => {
3099
+ const {
3100
+ blob,
3101
+ name
3102
+ } = utils.dataURItoBlob(dataURL);
3103
+ return {
3104
+ name: name,
3105
+ size: blob.size,
3106
+ type: blob.type
3107
+ };
3108
+ });
3109
+ }
3110
+ /**
3111
+ * The `FileWidget` is a widget for rendering file upload fields.
3112
+ * It is typically used with a string property with data-url format.
3113
+ */
3114
+
3115
+
3116
+ function FileWidget(_ref2) {
3117
+ let {
3118
+ multiple,
3119
+ id,
3120
+ readonly,
3121
+ disabled,
3122
+ onChange,
3123
+ value,
3124
+ autofocus = false,
3125
+ options
3126
+ } = _ref2;
3127
+ const extractedFilesInfo = React.useMemo(() => Array.isArray(value) ? extractFileInfo(value) : extractFileInfo([value]), [value]);
3128
+ const [filesInfo, setFilesInfo] = React.useState(extractedFilesInfo);
3129
+ const handleChange = React.useCallback(event => {
3130
+ if (!event.target.files) {
3131
+ return;
3132
+ }
3133
+
3134
+ processFiles(event.target.files).then(filesInfoEvent => {
3135
+ setFilesInfo(filesInfoEvent);
3136
+ const newValue = filesInfoEvent.map(fileInfo => fileInfo.dataURL);
3137
+
3138
+ if (multiple) {
3139
+ onChange(newValue);
3140
+ } else {
3141
+ onChange(newValue[0]);
3142
+ }
3143
+ });
3144
+ }, [multiple, onChange]);
3145
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", null, /*#__PURE__*/React__default["default"].createElement("input", {
3146
+ id: id,
3147
+ name: id,
3148
+ type: "file",
3149
+ disabled: readonly || disabled,
3150
+ onChange: handleChange,
3151
+ defaultValue: "",
3152
+ autoFocus: autofocus,
3153
+ multiple: multiple,
3154
+ accept: options.accept ? String(options.accept) : undefined
3155
+ })), /*#__PURE__*/React__default["default"].createElement(FilesInfo, {
3156
+ filesInfo: filesInfo
3157
+ }));
3158
+ }
3159
+
3160
+ /** The `HiddenWidget` is a widget for rendering a hidden input field.
3161
+ * It is typically used by setting type to "hidden".
3162
+ *
3163
+ * @param props - The `WidgetProps` for this component
3164
+ */
3165
+
3166
+ function HiddenWidget(_ref) {
3167
+ let {
3168
+ id,
3169
+ value
3170
+ } = _ref;
3171
+ return /*#__PURE__*/React__default["default"].createElement("input", {
3172
+ type: "hidden",
3173
+ id: id,
3174
+ name: id,
3175
+ value: typeof value === "undefined" ? "" : value
3176
+ });
3177
+ }
3178
+
3179
+ /** The `PasswordWidget` component uses the `BaseInputTemplate` changing the type to `password`.
3180
+ *
3181
+ * @param props - The `WidgetProps` for this component
3182
+ */
3183
+
3184
+ function PasswordWidget(props) {
3185
+ const {
3186
+ options,
3187
+ registry
3188
+ } = props;
3189
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3190
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3191
+ type: "password",
3192
+ ...props
3193
+ });
3194
+ }
3195
+
3196
+ /** The `RadioWidget` is a widget for rendering a radio group.
3197
+ * It is typically used with a string property constrained with enum options.
3198
+ *
3199
+ * @param props - The `WidgetProps` for this component
3200
+ */
3201
+
3202
+ function RadioWidget(_ref) {
3203
+ let {
3204
+ options,
3205
+ value,
3206
+ required,
3207
+ disabled,
3208
+ readonly,
3209
+ autofocus = false,
3210
+ onBlur,
3211
+ onFocus,
3212
+ onChange,
3213
+ id
3214
+ } = _ref;
3215
+ // Generating a unique field name to identify this set of radio buttons
3216
+ const name = Math.random().toString();
3217
+ const {
3218
+ enumOptions,
3219
+ enumDisabled,
3220
+ inline
3221
+ } = options; // checked={checked} has been moved above name={name}, As mentioned in #349;
3222
+ // this is a temporary fix for radio button rendering bug in React, facebook/react#7630.
3223
+
3224
+ const handleBlur = React.useCallback(event => onBlur(id, event.target.value), [onBlur, id]);
3225
+ const handleFocus = React.useCallback(event => onFocus(id, event.target.value), [onFocus, id]);
3226
+ return /*#__PURE__*/React__default["default"].createElement("div", {
3227
+ className: "field-radio-group",
3228
+ id: id
3229
+ }, Array.isArray(enumOptions) && enumOptions.map((option, i) => {
3230
+ const checked = option.value === value;
3231
+ const itemDisabled = Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) != -1;
3232
+ const disabledCls = disabled || itemDisabled || readonly ? "disabled" : "";
3233
+
3234
+ const handleChange = () => onChange(option.value);
3235
+
3236
+ const radio = /*#__PURE__*/React__default["default"].createElement("span", null, /*#__PURE__*/React__default["default"].createElement("input", {
3237
+ type: "radio",
3238
+ id: id + "-" + option.value,
3239
+ checked: checked,
3240
+ name: name,
3241
+ required: required,
3242
+ value: option.value,
3243
+ disabled: disabled || itemDisabled || readonly,
3244
+ autoFocus: autofocus && i === 0,
3245
+ onChange: handleChange,
3246
+ onBlur: handleBlur,
3247
+ onFocus: handleFocus
3248
+ }), /*#__PURE__*/React__default["default"].createElement("span", null, option.label));
3249
+ return inline ? /*#__PURE__*/React__default["default"].createElement("label", {
3250
+ key: option.value,
3251
+ className: "radio-inline " + disabledCls
3252
+ }, radio) : /*#__PURE__*/React__default["default"].createElement("div", {
3253
+ key: option.value,
3254
+ className: "radio " + disabledCls
3255
+ }, /*#__PURE__*/React__default["default"].createElement("label", null, radio));
3256
+ }));
3257
+ }
3258
+
3259
+ /** The `RangeWidget` component uses the `BaseInputTemplate` changing the type to `range` and wrapping the result
3260
+ * in a div, with the value along side it.
3261
+ *
3262
+ * @param props - The `WidgetProps` for this component
3263
+ */
3264
+
3265
+ function RangeWidget(props) {
3266
+ const {
3267
+ value,
3268
+ registry: {
3269
+ templates: {
3270
+ BaseInputTemplate
3271
+ }
3272
+ }
3273
+ } = props;
3274
+ return /*#__PURE__*/React__default["default"].createElement("div", {
3275
+ className: "field-range-wrapper"
3276
+ }, /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3277
+ type: "range",
3278
+ ...props
3279
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
3280
+ className: "range-view"
3281
+ }, value));
3282
+ }
3283
+
3284
+ function getValue(event, multiple) {
3285
+ if (multiple) {
3286
+ return Array.from(event.target.options).slice().filter(o => o.selected).map(o => o.value);
3287
+ }
3288
+
3289
+ return event.target.value;
3290
+ }
3291
+ /** The `SelectWidget` is a widget for rendering dropdowns.
3292
+ * It is typically used with string properties constrained with enum options.
3293
+ *
3294
+ * @param props - The `WidgetProps` for this component
3295
+ */
3296
+
3297
+
3298
+ function SelectWidget(_ref) {
3299
+ let {
3300
+ schema,
3301
+ id,
3302
+ options,
3303
+ value,
3304
+ required,
3305
+ disabled,
3306
+ readonly,
3307
+ multiple = false,
3308
+ autofocus = false,
3309
+ onChange,
3310
+ onBlur,
3311
+ onFocus,
3312
+ placeholder
3313
+ } = _ref;
3314
+ const {
3315
+ enumOptions,
3316
+ enumDisabled
3317
+ } = options;
3318
+ const emptyValue = multiple ? [] : "";
3319
+ const handleFocus = React.useCallback(event => {
3320
+ const newValue = getValue(event, multiple);
3321
+ return onFocus(id, utils.processSelectValue(schema, newValue, options));
3322
+ }, [onFocus, id, schema, multiple, options]);
3323
+ const handleBlur = React.useCallback(event => {
3324
+ const newValue = getValue(event, multiple);
3325
+ return onBlur(id, utils.processSelectValue(schema, newValue, options));
3326
+ }, [onBlur, id, schema, multiple, options]);
3327
+ const handleChange = React.useCallback(event => {
3328
+ const newValue = getValue(event, multiple);
3329
+ return onChange(utils.processSelectValue(schema, newValue, options));
3330
+ }, [onChange, schema, multiple, options]);
3331
+ return /*#__PURE__*/React__default["default"].createElement("select", {
3332
+ id: id,
3333
+ name: id,
3334
+ multiple: multiple,
3335
+ className: "form-control",
3336
+ value: typeof value === "undefined" ? emptyValue : value,
3337
+ required: required,
3338
+ disabled: disabled || readonly,
3339
+ autoFocus: autofocus,
3340
+ onBlur: handleBlur,
3341
+ onFocus: handleFocus,
3342
+ onChange: handleChange
3343
+ }, !multiple && schema.default === undefined && /*#__PURE__*/React__default["default"].createElement("option", {
3344
+ value: ""
3345
+ }, placeholder), Array.isArray(enumOptions) && enumOptions.map((_ref2, i) => {
3346
+ let {
3347
+ value,
3348
+ label
3349
+ } = _ref2;
3350
+ const disabled = enumDisabled && enumDisabled.indexOf(value) != -1;
3351
+ return /*#__PURE__*/React__default["default"].createElement("option", {
3352
+ key: i,
3353
+ value: value,
3354
+ disabled: disabled
3355
+ }, label);
3356
+ }));
3357
+ }
3358
+
3359
+ /** The `TextareaWidget` is a widget for rendering input fields as textarea.
3360
+ *
3361
+ * @param props - The `WidgetProps` for this component
3362
+ */
3363
+
3364
+ function TextareaWidget(_ref) {
3365
+ let {
3366
+ id,
3367
+ options = {},
3368
+ placeholder,
3369
+ value,
3370
+ required,
3371
+ disabled,
3372
+ readonly,
3373
+ autofocus = false,
3374
+ onChange,
3375
+ onBlur,
3376
+ onFocus
3377
+ } = _ref;
3378
+ const handleChange = React.useCallback(_ref2 => {
3379
+ let {
3380
+ target: {
3381
+ value
3382
+ }
3383
+ } = _ref2;
3384
+ return onChange(value === "" ? options.emptyValue : value);
3385
+ }, [onChange, options.emptyValue]);
3386
+ const handleBlur = React.useCallback(_ref3 => {
3387
+ let {
3388
+ target: {
3389
+ value
3390
+ }
3391
+ } = _ref3;
3392
+ return onBlur(id, value);
3393
+ }, [onBlur, id]);
3394
+ const handleFocus = React.useCallback(_ref4 => {
3395
+ let {
3396
+ target: {
3397
+ value
3398
+ }
3399
+ } = _ref4;
3400
+ return onFocus(id, value);
3401
+ }, [id, onFocus]);
3402
+ return /*#__PURE__*/React__default["default"].createElement("textarea", {
3403
+ id: id,
3404
+ name: id,
3405
+ className: "form-control",
3406
+ value: value ? value : "",
3407
+ placeholder: placeholder,
3408
+ required: required,
3409
+ disabled: disabled,
3410
+ readOnly: readonly,
3411
+ autoFocus: autofocus,
3412
+ rows: options.rows,
3413
+ onBlur: handleBlur,
3414
+ onFocus: handleFocus,
3415
+ onChange: handleChange
3416
+ });
3417
+ }
3418
+
3419
+ TextareaWidget.defaultProps = {
3420
+ autofocus: false,
3421
+ options: {}
3422
+ };
3423
+
3424
+ /** The `TextWidget` component uses the `BaseInputTemplate`.
3425
+ *
3426
+ * @param props - The `WidgetProps` for this component
3427
+ */
3428
+
3429
+ function TextWidget(props) {
3430
+ const {
3431
+ options,
3432
+ registry
3433
+ } = props;
3434
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3435
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, { ...props
3436
+ });
3437
+ }
3438
+
3439
+ /** The `URLWidget` component uses the `BaseInputTemplate` changing the type to `url`.
3440
+ *
3441
+ * @param props - The `WidgetProps` for this component
3442
+ */
3443
+
3444
+ function URLWidget(props) {
3445
+ const {
3446
+ options,
3447
+ registry
3448
+ } = props;
3449
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3450
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3451
+ type: "url",
3452
+ ...props
3453
+ });
3454
+ }
3455
+
3456
+ /** The `UpDownWidget` component uses the `BaseInputTemplate` changing the type to `number`.
3457
+ *
3458
+ * @param props - The `WidgetProps` for this component
3459
+ */
3460
+
3461
+ function UpDownWidget(props) {
3462
+ const {
3463
+ options,
3464
+ registry
3465
+ } = props;
3466
+ const BaseInputTemplate = utils.getTemplate("BaseInputTemplate", registry, options);
3467
+ return /*#__PURE__*/React__default["default"].createElement(BaseInputTemplate, {
3468
+ type: "number",
3469
+ ...props
3470
+ });
3471
+ }
3472
+
3473
+ const widgets = {
3474
+ PasswordWidget,
3475
+ RadioWidget,
3476
+ UpDownWidget,
3477
+ RangeWidget,
3478
+ SelectWidget,
3479
+ TextWidget,
3480
+ DateWidget,
3481
+ DateTimeWidget,
3482
+ AltDateWidget,
3483
+ AltDateTimeWidget,
3484
+ EmailWidget,
3485
+ URLWidget,
3486
+ TextareaWidget,
3487
+ HiddenWidget,
3488
+ ColorWidget,
3489
+ FileWidget,
3490
+ CheckboxWidget,
3491
+ CheckboxesWidget
3492
+ };
3493
+
3494
+ /** The default registry consists of all the fields, templates and widgets provided in the core implementation,
3495
+ * plus an empty `rootSchema` and `formContext. We omit schemaUtils here because it cannot be defaulted without a
3496
+ * rootSchema and validator. It will be added into the computed registry later in the Form.
3497
+ */
3498
+
3499
+ function getDefaultRegistry() {
3500
+ return {
3501
+ fields,
3502
+ templates,
3503
+ widgets,
3504
+ rootSchema: {},
3505
+ formContext: {}
3506
+ };
3507
+ }
3508
+
3509
+ /** The `Form` component renders the outer form and all the fields defined in the `schema` */
3510
+
3511
+ class Form extends React.Component {
3512
+ /** The ref used to hold the `form` element, this needs to be `any` because `tagName` or `_internalFormWrapper` can
3513
+ * provide any possible type here
3514
+ */
3515
+
3516
+ /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
3517
+ * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
3518
+ * state construction.
3519
+ *
3520
+ * @param props - The initial props for the `Form`
3521
+ */
3522
+ constructor(props) {
3523
+ super(props);
3524
+ this.formElement = void 0;
3525
+
3526
+ this.getUsedFormData = (formData, fields) => {
3527
+ // For the case of a single input form
3528
+ if (fields.length === 0 && typeof formData !== "object") {
3529
+ return formData;
3530
+ }
3531
+
3532
+ const data = _pick__default["default"](formData, fields);
3533
+
3534
+ if (Array.isArray(formData)) {
3535
+ return Object.keys(data).map(key => data[key]);
3536
+ }
3537
+
3538
+ return data;
3539
+ };
3540
+
3541
+ this.getFieldNames = (pathSchema, formData) => {
3542
+ const getAllPaths = function (_obj, acc, paths) {
3543
+ if (acc === void 0) {
3544
+ acc = [];
3545
+ }
3546
+
3547
+ if (paths === void 0) {
3548
+ paths = [""];
3549
+ }
3550
+
3551
+ Object.keys(_obj).forEach(key => {
3552
+ if (typeof _obj[key] === "object") {
3553
+ const newPaths = paths.map(path => path + "." + key); // If an object is marked with additionalProperties, all its keys are valid
3554
+
3555
+ if (_obj[key][utils.RJSF_ADDITONAL_PROPERTIES_FLAG] && _obj[key][utils.NAME_KEY] !== "") {
3556
+ acc.push(_obj[key][utils.NAME_KEY]);
3557
+ } else {
3558
+ getAllPaths(_obj[key], acc, newPaths);
3559
+ }
3560
+ } else if (key === utils.NAME_KEY && _obj[key] !== "") {
3561
+ paths.forEach(path => {
3562
+ path = path.replace(/^\./, "");
3563
+
3564
+ const formValue = get__default["default"](formData, path); // adds path to fieldNames if it points to a value
3565
+ // or an empty object/array
3566
+
3567
+
3568
+ if (typeof formValue !== "object" || _isEmpty__default["default"](formValue)) {
3569
+ acc.push(path);
3570
+ }
3571
+ });
3572
+ }
3573
+ });
3574
+ return acc;
3575
+ };
3576
+
3577
+ return getAllPaths(pathSchema);
3578
+ };
3579
+
3580
+ this.onChange = (formData, newErrorSchema) => {
3581
+ const {
3582
+ extraErrors,
3583
+ omitExtraData,
3584
+ liveOmit,
3585
+ noValidate,
3586
+ liveValidate,
3587
+ onChange
3588
+ } = this.props;
3589
+ const {
3590
+ schemaUtils,
3591
+ schema
3592
+ } = this.state;
3593
+
3594
+ if (utils.isObject(formData) || Array.isArray(formData)) {
3595
+ const newState = this.getStateFromProps(this.props, formData);
3596
+ formData = newState.formData;
3597
+ }
3598
+
3599
+ const mustValidate = !noValidate && liveValidate;
3600
+ let state = {
3601
+ formData,
3602
+ schema
3603
+ };
3604
+ let newFormData = formData;
3605
+
3606
+ if (omitExtraData === true && liveOmit === true) {
3607
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3608
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3609
+ const fieldNames = this.getFieldNames(pathSchema, formData);
3610
+ newFormData = this.getUsedFormData(formData, fieldNames);
3611
+ state = {
3612
+ formData: newFormData
3613
+ };
3614
+ }
3615
+
3616
+ if (mustValidate) {
3617
+ const schemaValidation = this.validate(newFormData);
3618
+ let errors = schemaValidation.errors;
3619
+ let errorSchema = schemaValidation.errorSchema;
3620
+ const schemaValidationErrors = errors;
3621
+ const schemaValidationErrorSchema = errorSchema;
3622
+
3623
+ if (extraErrors) {
3624
+ const merged = schemaUtils.mergeValidationData(schemaValidation, extraErrors);
3625
+ errorSchema = merged.errorSchema;
3626
+ errors = merged.errors;
3627
+ }
3628
+
3629
+ state = {
3630
+ formData: newFormData,
3631
+ errors,
3632
+ errorSchema,
3633
+ schemaValidationErrors,
3634
+ schemaValidationErrorSchema
3635
+ };
3636
+ } else if (!noValidate && newErrorSchema) {
3637
+ const errorSchema = extraErrors ? utils.mergeObjects(newErrorSchema, extraErrors, true) : newErrorSchema;
3638
+ state = {
3639
+ formData: newFormData,
3640
+ errorSchema: errorSchema,
3641
+ errors: schemaUtils.getValidator().toErrorList(errorSchema)
3642
+ };
3643
+ }
3644
+
3645
+ this.setState(state, () => onChange && onChange({ ...this.state,
3646
+ ...state
3647
+ }));
3648
+ };
3649
+
3650
+ this.onBlur = (id, data) => {
3651
+ const {
3652
+ onBlur
3653
+ } = this.props;
3654
+
3655
+ if (onBlur) {
3656
+ onBlur(id, data);
3657
+ }
3658
+ };
3659
+
3660
+ this.onFocus = (id, data) => {
3661
+ const {
3662
+ onFocus
3663
+ } = this.props;
3664
+
3665
+ if (onFocus) {
3666
+ onFocus(id, data);
3667
+ }
3668
+ };
3669
+
3670
+ this.onSubmit = event => {
3671
+ event.preventDefault();
3672
+
3673
+ if (event.target !== event.currentTarget) {
3674
+ return;
3675
+ }
3676
+
3677
+ event.persist();
3678
+ const {
3679
+ omitExtraData,
3680
+ extraErrors,
3681
+ noValidate,
3682
+ onSubmit
3683
+ } = this.props;
3684
+ let {
3685
+ formData: newFormData
3686
+ } = this.state;
3687
+ const {
3688
+ schema,
3689
+ schemaUtils
3690
+ } = this.state;
3691
+
3692
+ if (omitExtraData === true) {
3693
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, newFormData);
3694
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
3695
+ const fieldNames = this.getFieldNames(pathSchema, newFormData);
3696
+ newFormData = this.getUsedFormData(newFormData, fieldNames);
3697
+ }
3698
+
3699
+ if (noValidate || this.validateForm()) {
3700
+ // There are no errors generated through schema validation.
3701
+ // Check for user provided errors and update state accordingly.
3702
+ const errorSchema = extraErrors || {};
3703
+ const errors = extraErrors ? schemaUtils.getValidator().toErrorList(extraErrors) : [];
3704
+ this.setState({
3705
+ formData: newFormData,
3706
+ errors,
3707
+ errorSchema,
3708
+ schemaValidationErrors: [],
3709
+ schemaValidationErrorSchema: {}
3710
+ }, () => {
3711
+ if (onSubmit) {
3712
+ onSubmit({ ...this.state,
3713
+ formData: newFormData,
3714
+ status: "submitted"
3715
+ }, event);
3716
+ }
3717
+ });
3718
+ }
3719
+ };
3720
+
3721
+ if (!props.validator) {
3722
+ throw new Error("A validator is required for Form functionality to work");
3723
+ }
3724
+
3725
+ this.state = this.getStateFromProps(props, props.formData);
3726
+
3727
+ if (this.props.onChange && !utils.deepEquals(this.state.formData, this.props.formData)) {
3728
+ this.props.onChange(this.state);
3729
+ }
3730
+
3731
+ this.formElement = /*#__PURE__*/React__default["default"].createRef();
3732
+ }
3733
+ /** React lifecycle method that gets called before new props are provided, updates the state based on new props. It
3734
+ * will also call the`onChange` handler if the `formData` is modified to add missing default values as part of the
3735
+ * state construction.
3736
+ *
3737
+ * @param nextProps - The new set of props about to be applied to the `Form`
3738
+ */
3739
+
3740
+
3741
+ UNSAFE_componentWillReceiveProps(nextProps) {
3742
+ const nextState = this.getStateFromProps(nextProps, nextProps.formData);
3743
+
3744
+ if (!utils.deepEquals(nextState.formData, nextProps.formData) && !utils.deepEquals(nextState.formData, this.state.formData) && nextProps.onChange) {
3745
+ nextProps.onChange(nextState);
3746
+ }
3747
+
3748
+ this.setState(nextState);
3749
+ }
3750
+ /** Extracts the updated state from the given `props` and `inputFormData`. As part of this process, the
3751
+ * `inputFormData` is first processed to add any missing required defaults. After that, the data is run through the
3752
+ * validation process IF required by the `props`.
3753
+ *
3754
+ * @param props - The props passed to the `Form`
3755
+ * @param inputFormData - The new or current data for the `Form`
3756
+ * @returns - The new state for the `Form`
3757
+ */
3758
+
3759
+
3760
+ getStateFromProps(props, inputFormData) {
3761
+ const state = this.state || {};
3762
+ const schema = "schema" in props ? props.schema : this.props.schema;
3763
+ const uiSchema = ("uiSchema" in props ? props.uiSchema : this.props.uiSchema) || {};
3764
+ const edit = typeof inputFormData !== "undefined";
3765
+ const liveValidate = "liveValidate" in props ? props.liveValidate : this.props.liveValidate;
3766
+ const mustValidate = edit && !props.noValidate && liveValidate;
3767
+ const rootSchema = schema;
3768
+ let schemaUtils = state.schemaUtils;
3769
+
3770
+ if (!schemaUtils || schemaUtils.doesSchemaUtilsDiffer(props.validator, rootSchema)) {
3771
+ schemaUtils = utils.createSchemaUtils(props.validator, rootSchema);
3772
+ }
3773
+
3774
+ const formData = schemaUtils.getDefaultFormState(schema, inputFormData);
3775
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3776
+
3777
+ const getCurrentErrors = () => {
3778
+ if (props.noValidate) {
3779
+ return {
3780
+ errors: [],
3781
+ errorSchema: {}
3782
+ };
3783
+ } else if (!props.liveValidate) {
3784
+ return {
3785
+ errors: state.schemaValidationErrors || [],
3786
+ errorSchema: state.schemaValidationErrorSchema || {}
3787
+ };
3788
+ }
3789
+
3790
+ return {
3791
+ errors: state.errors || [],
3792
+ errorSchema: state.errorSchema || {}
3793
+ };
3794
+ };
3795
+
3796
+ let errors;
3797
+ let errorSchema;
3798
+ let schemaValidationErrors = state.schemaValidationErrors;
3799
+ let schemaValidationErrorSchema = state.schemaValidationErrorSchema;
3800
+
3801
+ if (mustValidate) {
3802
+ const schemaValidation = this.validate(formData, schema, schemaUtils);
3803
+ errors = schemaValidation.errors;
3804
+ errorSchema = schemaValidation.errorSchema;
3805
+ schemaValidationErrors = errors;
3806
+ schemaValidationErrorSchema = errorSchema;
3807
+ } else {
3808
+ const currentErrors = getCurrentErrors();
3809
+ errors = currentErrors.errors;
3810
+ errorSchema = currentErrors.errorSchema;
3811
+ }
3812
+
3813
+ if (props.extraErrors) {
3814
+ const merged = schemaUtils.mergeValidationData({
3815
+ errorSchema,
3816
+ errors
3817
+ }, props.extraErrors);
3818
+ errorSchema = merged.errorSchema;
3819
+ errors = merged.errors;
3820
+ }
3821
+
3822
+ const idSchema = schemaUtils.toIdSchema(retrievedSchema, uiSchema["ui:rootFieldId"], formData, props.idPrefix, props.idSeparator);
3823
+ const nextState = {
3824
+ schemaUtils,
3825
+ schema,
3826
+ uiSchema,
3827
+ idSchema,
3828
+ formData,
3829
+ edit,
3830
+ errors,
3831
+ errorSchema,
3832
+ schemaValidationErrors,
3833
+ schemaValidationErrorSchema
3834
+ };
3835
+ return nextState;
3836
+ }
3837
+ /** React lifecycle method that is used to determine whether component should be updated.
3838
+ *
3839
+ * @param nextProps - The next version of the props
3840
+ * @param nextState - The next version of the state
3841
+ * @returns - True if the component should be updated, false otherwise
3842
+ */
3843
+
3844
+
3845
+ shouldComponentUpdate(nextProps, nextState) {
3846
+ return utils.shouldRender(this, nextProps, nextState);
3847
+ }
3848
+ /** Validates the `formData` against the `schema` using the `altSchemaUtils` (if provided otherwise it uses the
3849
+ * `schemaUtils` in the state), returning the results.
3850
+ *
3851
+ * @param formData - The new form data to validate
3852
+ * @param schema - The schema used to validate against
3853
+ * @param altSchemaUtils - The alternate schemaUtils to use for validation
3854
+ */
3855
+
3856
+
3857
+ validate(formData, schema, altSchemaUtils) {
3858
+ if (schema === void 0) {
3859
+ schema = this.props.schema;
3860
+ }
3861
+
3862
+ const schemaUtils = altSchemaUtils ? altSchemaUtils : this.state.schemaUtils;
3863
+ const {
3864
+ customValidate,
3865
+ transformErrors
3866
+ } = this.props;
3867
+ const resolvedSchema = schemaUtils.retrieveSchema(schema, formData);
3868
+ return schemaUtils.getValidator().validateFormData(formData, resolvedSchema, customValidate, transformErrors);
3869
+ }
3870
+ /** Renders any errors contained in the `state` in using the `ErrorList`, if not disabled by `showErrorList`. */
3871
+
3872
+
3873
+ renderErrors(registry) {
3874
+ const {
3875
+ errors,
3876
+ errorSchema,
3877
+ schema,
3878
+ uiSchema
3879
+ } = this.state;
3880
+ const {
3881
+ showErrorList,
3882
+ formContext
3883
+ } = this.props;
3884
+ const options = utils.getUiOptions(uiSchema);
3885
+ const ErrorListTemplate = utils.getTemplate("ErrorListTemplate", registry, options);
3886
+
3887
+ if (errors && errors.length && showErrorList != false) {
3888
+ return /*#__PURE__*/React__default["default"].createElement(ErrorListTemplate, {
3889
+ errors: errors,
3890
+ errorSchema: errorSchema || {},
3891
+ schema: schema,
3892
+ uiSchema: uiSchema,
3893
+ formContext: formContext
3894
+ });
3895
+ }
3896
+
3897
+ return null;
3898
+ }
3899
+ /** Returns the `formData` with only the elements specified in the `fields` list
3900
+ *
3901
+ * @param formData - The data for the `Form`
3902
+ * @param fields - The fields to keep while filtering
3903
+ */
3904
+
3905
+
3906
+ /** Returns the registry for the form */
3907
+ getRegistry() {
3908
+ var _this$props$templates;
3909
+
3910
+ const {
3911
+ schemaUtils
3912
+ } = this.state;
3913
+ const {
3914
+ fields,
3915
+ templates,
3916
+ widgets,
3917
+ formContext
3918
+ } = getDefaultRegistry();
3919
+ return {
3920
+ fields: { ...fields,
3921
+ ...this.props.fields
3922
+ },
3923
+ templates: { ...templates,
3924
+ ...this.props.templates,
3925
+ ButtonTemplates: { ...templates.ButtonTemplates,
3926
+ ...((_this$props$templates = this.props.templates) === null || _this$props$templates === void 0 ? void 0 : _this$props$templates.ButtonTemplates)
3927
+ }
3928
+ },
3929
+ widgets: { ...widgets,
3930
+ ...this.props.widgets
3931
+ },
3932
+ rootSchema: this.props.schema,
3933
+ formContext: this.props.formContext || formContext,
3934
+ schemaUtils
3935
+ };
3936
+ }
3937
+ /** Provides a function that can be used to programmatically submit the `Form` */
3938
+
3939
+
3940
+ submit() {
3941
+ if (this.formElement.current) {
3942
+ this.formElement.current.dispatchEvent(new CustomEvent("submit", {
3943
+ cancelable: true
3944
+ }));
3945
+ this.formElement.current.requestSubmit();
3946
+ }
3947
+ }
3948
+ /** Programmatically validate the form. If `onError` is provided, then it will be called with the list of errors the
3949
+ * same way as would happen on form submission.
3950
+ *
3951
+ * @returns - True if the form is valid, false otherwise.
3952
+ */
3953
+
3954
+
3955
+ validateForm() {
3956
+ const {
3957
+ extraErrors,
3958
+ onError
3959
+ } = this.props;
3960
+ const {
3961
+ formData
3962
+ } = this.state;
3963
+ const {
3964
+ schemaUtils
3965
+ } = this.state;
3966
+ const schemaValidation = this.validate(formData);
3967
+ let errors = schemaValidation.errors;
3968
+ let errorSchema = schemaValidation.errorSchema;
3969
+ const schemaValidationErrors = errors;
3970
+ const schemaValidationErrorSchema = errorSchema;
3971
+
3972
+ if (errors.length > 0) {
3973
+ if (extraErrors) {
3974
+ const merged = schemaUtils.mergeValidationData(schemaValidation, extraErrors);
3975
+ errorSchema = merged.errorSchema;
3976
+ errors = merged.errors;
3977
+ }
3978
+
3979
+ this.setState({
3980
+ errors,
3981
+ errorSchema,
3982
+ schemaValidationErrors,
3983
+ schemaValidationErrorSchema
3984
+ }, () => {
3985
+ if (onError) {
3986
+ onError(errors);
3987
+ } else {
3988
+ console.error("Form validation failed", errors);
3989
+ }
3990
+ });
3991
+ return false;
3992
+ }
3993
+
3994
+ return true;
3995
+ }
3996
+ /** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
3997
+ * needed along with the submit button or any children of the form.
3998
+ */
3999
+
4000
+
4001
+ render() {
4002
+ const {
4003
+ children,
4004
+ id,
4005
+ idPrefix,
4006
+ idSeparator,
4007
+ className = "",
4008
+ tagName,
4009
+ name,
4010
+ method,
4011
+ target,
4012
+ action,
4013
+ autoComplete,
4014
+ enctype,
4015
+ acceptcharset,
4016
+ noHtml5Validate = false,
4017
+ disabled = false,
4018
+ readonly = false,
4019
+ formContext,
4020
+ _internalFormWrapper
4021
+ } = this.props;
4022
+ const {
4023
+ schema,
4024
+ uiSchema,
4025
+ formData,
4026
+ errorSchema,
4027
+ idSchema
4028
+ } = this.state;
4029
+ const registry = this.getRegistry();
4030
+ const {
4031
+ SchemaField: _SchemaField
4032
+ } = registry.fields;
4033
+ const {
4034
+ SubmitButton
4035
+ } = registry.templates.ButtonTemplates; // The `semantic-ui` and `material-ui` themes have `_internalFormWrapper`s that take an `as` prop that is the
4036
+ // PropTypes.elementType to use for the inner tag so we'll need to pass `tagName` along if it is provided.
4037
+ // NOTE, the `as` prop is native to `semantic-ui` and is emulated in the `material-ui` theme
4038
+
4039
+ const as = _internalFormWrapper ? tagName : undefined;
4040
+ const FormTag = _internalFormWrapper || tagName || "form";
4041
+ return /*#__PURE__*/React__default["default"].createElement(FormTag, {
4042
+ className: className ? className : "rjsf",
4043
+ id: id,
4044
+ name: name,
4045
+ method: method,
4046
+ target: target,
4047
+ action: action,
4048
+ autoComplete: autoComplete,
4049
+ encType: enctype,
4050
+ acceptCharset: acceptcharset,
4051
+ noValidate: noHtml5Validate,
4052
+ onSubmit: this.onSubmit,
4053
+ as: as,
4054
+ ref: this.formElement
4055
+ }, this.renderErrors(registry), /*#__PURE__*/React__default["default"].createElement(_SchemaField, {
4056
+ name: "",
4057
+ schema: schema,
4058
+ uiSchema: uiSchema,
4059
+ errorSchema: errorSchema,
4060
+ idSchema: idSchema,
4061
+ idPrefix: idPrefix,
4062
+ idSeparator: idSeparator,
4063
+ formContext: formContext,
4064
+ formData: formData,
4065
+ onChange: this.onChange,
4066
+ onBlur: this.onBlur,
4067
+ onFocus: this.onFocus,
4068
+ registry: registry,
4069
+ disabled: disabled,
4070
+ readonly: readonly
4071
+ }), children ? children : /*#__PURE__*/React__default["default"].createElement(SubmitButton, {
4072
+ uiSchema: uiSchema
4073
+ }));
4074
+ }
4075
+
4076
+ }
4077
+
4078
+ /** A Higher-Order component that creates a wrapper around a `Form` with the overrides from the `WithThemeProps` */
4079
+
4080
+ function withTheme(themeProps) {
4081
+ return /*#__PURE__*/React.forwardRef((_ref, ref) => {
4082
+ var _themeProps$templates, _templates;
4083
+
4084
+ let {
4085
+ fields,
4086
+ widgets,
4087
+ templates,
4088
+ ...directProps
4089
+ } = _ref;
4090
+ fields = { ...themeProps.fields,
4091
+ ...fields
4092
+ };
4093
+ widgets = { ...themeProps.widgets,
4094
+ ...widgets
4095
+ };
4096
+ templates = { ...themeProps.templates,
4097
+ ...templates,
4098
+ ButtonTemplates: { ...(themeProps === null || themeProps === void 0 ? void 0 : (_themeProps$templates = themeProps.templates) === null || _themeProps$templates === void 0 ? void 0 : _themeProps$templates.ButtonTemplates),
4099
+ ...((_templates = templates) === null || _templates === void 0 ? void 0 : _templates.ButtonTemplates)
4100
+ }
4101
+ };
4102
+ return /*#__PURE__*/React__default["default"].createElement(Form, { ...themeProps,
4103
+ ...directProps,
4104
+ fields: fields,
4105
+ widgets: widgets,
4106
+ templates: templates,
4107
+ ref: ref
4108
+ });
4109
+ });
4110
+ }
4111
+
4112
+ exports["default"] = Form;
4113
+ exports.getDefaultRegistry = getDefaultRegistry;
4114
+ exports.withTheme = withTheme;
4115
+
4116
+ Object.defineProperty(exports, '__esModule', { value: true });
4117
+
4118
+ }));
4119
+ //# sourceMappingURL=core.umd.development.js.map