@rjsf/core 5.11.2 → 5.12.0

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