@rjsf/utils 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 (303) hide show
  1. package/dist/index.js +2544 -5
  2. package/dist/index.js.map +7 -0
  3. package/dist/utils.esm.js +1228 -2113
  4. package/dist/utils.esm.js.map +7 -1
  5. package/dist/utils.umd.js +2414 -0
  6. package/lib/ErrorSchemaBuilder.d.ts +60 -0
  7. package/lib/ErrorSchemaBuilder.js +103 -0
  8. package/lib/ErrorSchemaBuilder.js.map +1 -0
  9. package/lib/allowAdditionalItems.d.ts +8 -0
  10. package/lib/allowAdditionalItems.js +14 -0
  11. package/lib/allowAdditionalItems.js.map +1 -0
  12. package/lib/asNumber.d.ts +10 -0
  13. package/lib/asNumber.js +36 -0
  14. package/lib/asNumber.js.map +1 -0
  15. package/lib/canExpand.d.ts +11 -0
  16. package/lib/canExpand.js +26 -0
  17. package/lib/canExpand.js.map +1 -0
  18. package/lib/constants.d.ts +31 -0
  19. package/lib/constants.js +32 -0
  20. package/lib/constants.js.map +1 -0
  21. package/lib/createErrorHandler.d.ts +7 -0
  22. package/lib/createErrorHandler.js +31 -0
  23. package/lib/createErrorHandler.js.map +1 -0
  24. package/lib/createSchemaUtils.d.ts +10 -0
  25. package/lib/createSchemaUtils.js +207 -0
  26. package/lib/createSchemaUtils.js.map +1 -0
  27. package/lib/dataURItoBlob.d.ts +16 -0
  28. package/lib/dataURItoBlob.js +43 -0
  29. package/lib/dataURItoBlob.js.map +1 -0
  30. package/lib/deepEquals.d.ts +8 -0
  31. package/lib/deepEquals.js +19 -0
  32. package/lib/deepEquals.js.map +1 -0
  33. package/lib/englishStringTranslator.d.ts +10 -0
  34. package/lib/englishStringTranslator.js +13 -0
  35. package/lib/englishStringTranslator.js.map +1 -0
  36. package/lib/enumOptionsDeselectValue.d.ts +14 -0
  37. package/lib/enumOptionsDeselectValue.js +22 -0
  38. package/lib/enumOptionsDeselectValue.js.map +1 -0
  39. package/lib/enumOptionsIndexForValue.d.ts +13 -0
  40. package/lib/enumOptionsIndexForValue.js +22 -0
  41. package/lib/enumOptionsIndexForValue.js.map +1 -0
  42. package/lib/enumOptionsIsSelected.d.ts +8 -0
  43. package/lib/enumOptionsIsSelected.js +14 -0
  44. package/lib/enumOptionsIsSelected.js.map +1 -0
  45. package/lib/enumOptionsSelectValue.d.ts +10 -0
  46. package/lib/enumOptionsSelectValue.js +23 -0
  47. package/lib/enumOptionsSelectValue.js.map +1 -0
  48. package/lib/enumOptionsValueForIndex.d.ts +13 -0
  49. package/lib/enumOptionsValueForIndex.js +21 -0
  50. package/lib/enumOptionsValueForIndex.js.map +1 -0
  51. package/lib/enums.d.ts +72 -0
  52. package/lib/enums.js +76 -0
  53. package/lib/enums.js.map +1 -0
  54. package/lib/findSchemaDefinition.d.ts +20 -0
  55. package/lib/findSchemaDefinition.js +49 -0
  56. package/lib/findSchemaDefinition.js.map +1 -0
  57. package/lib/getDiscriminatorFieldFromSchema.d.ts +8 -0
  58. package/lib/getDiscriminatorFieldFromSchema.js +20 -0
  59. package/lib/getDiscriminatorFieldFromSchema.js.map +1 -0
  60. package/lib/getInputProps.d.ts +10 -0
  61. package/lib/getInputProps.js +41 -0
  62. package/lib/getInputProps.js.map +1 -0
  63. package/lib/getSchemaType.d.ts +13 -0
  64. package/lib/getSchemaType.js +29 -0
  65. package/lib/getSchemaType.js.map +1 -0
  66. package/lib/getSubmitButtonOptions.d.ts +10 -0
  67. package/lib/getSubmitButtonOptions.js +25 -0
  68. package/lib/getSubmitButtonOptions.js.map +1 -0
  69. package/lib/getTemplate.d.ts +10 -0
  70. package/lib/getTemplate.js +19 -0
  71. package/lib/getTemplate.js.map +1 -0
  72. package/lib/getUiOptions.d.ts +9 -0
  73. package/lib/getUiOptions.js +25 -0
  74. package/lib/getUiOptions.js.map +1 -0
  75. package/lib/getWidget.d.ts +13 -0
  76. package/lib/getWidget.js +118 -0
  77. package/lib/getWidget.js.map +1 -0
  78. package/lib/guessType.d.ts +7 -0
  79. package/lib/guessType.js +29 -0
  80. package/lib/guessType.js.map +1 -0
  81. package/lib/hasWidget.d.ts +10 -0
  82. package/lib/hasWidget.js +23 -0
  83. package/lib/hasWidget.js.map +1 -0
  84. package/lib/hashForSchema.d.ts +8 -0
  85. package/lib/hashForSchema.js +29 -0
  86. package/lib/hashForSchema.js.map +1 -0
  87. package/lib/idGenerators.d.ts +47 -0
  88. package/lib/idGenerators.js +73 -0
  89. package/lib/idGenerators.js.map +1 -0
  90. package/lib/index.d.ts +57 -0
  91. package/lib/index.js +58 -0
  92. package/lib/index.js.map +1 -0
  93. package/lib/isConstant.d.ts +8 -0
  94. package/lib/isConstant.js +11 -0
  95. package/lib/isConstant.js.map +1 -0
  96. package/lib/isCustomWidget.d.ts +7 -0
  97. package/lib/isCustomWidget.js +13 -0
  98. package/lib/isCustomWidget.js.map +1 -0
  99. package/lib/isFixedItems.d.ts +8 -0
  100. package/lib/isFixedItems.js +11 -0
  101. package/lib/isFixedItems.js.map +1 -0
  102. package/lib/isObject.d.ts +7 -0
  103. package/lib/isObject.js +16 -0
  104. package/lib/isObject.js.map +1 -0
  105. package/lib/labelValue.d.ts +13 -0
  106. package/lib/labelValue.js +4 -0
  107. package/lib/labelValue.js.map +1 -0
  108. package/lib/localToUTC.d.ts +6 -0
  109. package/lib/localToUTC.js +9 -0
  110. package/lib/localToUTC.js.map +1 -0
  111. package/lib/mergeDefaultsWithFormData.d.ts +17 -0
  112. package/lib/mergeDefaultsWithFormData.js +43 -0
  113. package/lib/mergeDefaultsWithFormData.js.map +1 -0
  114. package/lib/mergeObjects.d.ts +11 -0
  115. package/lib/mergeObjects.js +35 -0
  116. package/lib/mergeObjects.js.map +1 -0
  117. package/lib/mergeSchemas.d.ts +10 -0
  118. package/lib/mergeSchemas.js +35 -0
  119. package/lib/mergeSchemas.js.map +1 -0
  120. package/lib/optionsList.d.ts +10 -0
  121. package/lib/optionsList.js +36 -0
  122. package/lib/optionsList.js.map +1 -0
  123. package/lib/orderProperties.d.ts +11 -0
  124. package/lib/orderProperties.js +38 -0
  125. package/lib/orderProperties.js.map +1 -0
  126. package/lib/pad.d.ts +7 -0
  127. package/lib/pad.js +14 -0
  128. package/lib/pad.js.map +1 -0
  129. package/lib/parseDateString.d.ts +9 -0
  130. package/lib/parseDateString.js +32 -0
  131. package/lib/parseDateString.js.map +1 -0
  132. package/lib/parser/ParserValidator.d.ts +70 -0
  133. package/lib/parser/ParserValidator.js +93 -0
  134. package/lib/parser/ParserValidator.js.map +1 -0
  135. package/lib/parser/index.d.ts +4 -0
  136. package/lib/parser/index.js +3 -0
  137. package/lib/parser/index.js.map +1 -0
  138. package/lib/parser/schemaParser.d.ts +9 -0
  139. package/lib/parser/schemaParser.js +48 -0
  140. package/lib/parser/schemaParser.js.map +1 -0
  141. package/lib/rangeSpec.d.ts +9 -0
  142. package/lib/rangeSpec.js +20 -0
  143. package/lib/rangeSpec.js.map +1 -0
  144. package/lib/replaceStringParameters.d.ts +9 -0
  145. package/lib/replaceStringParameters.js +23 -0
  146. package/lib/replaceStringParameters.js.map +1 -0
  147. package/lib/schema/getClosestMatchingOption.d.ts +49 -0
  148. package/lib/schema/getClosestMatchingOption.js +154 -0
  149. package/lib/schema/getClosestMatchingOption.js.map +1 -0
  150. package/lib/schema/getDefaultFormState.d.ts +66 -0
  151. package/lib/schema/getDefaultFormState.js +351 -0
  152. package/lib/schema/getDefaultFormState.js.map +1 -0
  153. package/lib/schema/getDisplayLabel.d.ts +12 -0
  154. package/lib/schema/getDisplayLabel.js +39 -0
  155. package/lib/schema/getDisplayLabel.js.map +1 -0
  156. package/lib/schema/getFirstMatchingOption.d.ts +13 -0
  157. package/lib/schema/getFirstMatchingOption.js +16 -0
  158. package/lib/schema/getFirstMatchingOption.js.map +1 -0
  159. package/lib/schema/getMatchingOption.d.ts +14 -0
  160. package/lib/schema/getMatchingOption.js +80 -0
  161. package/lib/schema/getMatchingOption.js.map +1 -0
  162. package/lib/schema/index.d.ts +14 -0
  163. package/lib/schema/index.js +15 -0
  164. package/lib/schema/index.js.map +1 -0
  165. package/lib/schema/isFilesArray.d.ts +10 -0
  166. package/lib/schema/isFilesArray.js +21 -0
  167. package/lib/schema/isFilesArray.js.map +1 -0
  168. package/lib/schema/isMultiSelect.d.ts +9 -0
  169. package/lib/schema/isMultiSelect.js +15 -0
  170. package/lib/schema/isMultiSelect.js.map +1 -0
  171. package/lib/schema/isSelect.d.ts +9 -0
  172. package/lib/schema/isSelect.js +21 -0
  173. package/lib/schema/isSelect.js.map +1 -0
  174. package/lib/schema/mergeValidationData.d.ts +14 -0
  175. package/lib/schema/mergeValidationData.js +28 -0
  176. package/lib/schema/mergeValidationData.js.map +1 -0
  177. package/lib/schema/retrieveSchema.d.ts +170 -0
  178. package/lib/schema/retrieveSchema.js +437 -0
  179. package/lib/schema/retrieveSchema.js.map +1 -0
  180. package/lib/schema/sanitizeDataForNewSchema.d.ts +49 -0
  181. package/lib/schema/sanitizeDataForNewSchema.js +173 -0
  182. package/lib/schema/sanitizeDataForNewSchema.js.map +1 -0
  183. package/lib/schema/toIdSchema.d.ts +13 -0
  184. package/lib/schema/toIdSchema.js +59 -0
  185. package/lib/schema/toIdSchema.js.map +1 -0
  186. package/lib/schema/toPathSchema.d.ts +11 -0
  187. package/lib/schema/toPathSchema.js +68 -0
  188. package/lib/schema/toPathSchema.js.map +1 -0
  189. package/lib/schemaRequiresTrueValue.d.ts +11 -0
  190. package/lib/schemaRequiresTrueValue.js +34 -0
  191. package/lib/schemaRequiresTrueValue.js.map +1 -0
  192. package/lib/shouldRender.d.ts +10 -0
  193. package/lib/shouldRender.js +14 -0
  194. package/lib/shouldRender.js.map +1 -0
  195. package/lib/toConstant.d.ts +9 -0
  196. package/lib/toConstant.js +18 -0
  197. package/lib/toConstant.js.map +1 -0
  198. package/lib/toDateString.d.ts +9 -0
  199. package/lib/toDateString.js +14 -0
  200. package/lib/toDateString.js.map +1 -0
  201. package/lib/toErrorList.d.ts +8 -0
  202. package/lib/toErrorList.js +34 -0
  203. package/lib/toErrorList.js.map +1 -0
  204. package/lib/toErrorSchema.d.ts +21 -0
  205. package/lib/toErrorSchema.js +41 -0
  206. package/lib/toErrorSchema.js.map +1 -0
  207. package/lib/types.d.ts +982 -0
  208. package/lib/types.js +2 -0
  209. package/lib/types.js.map +1 -0
  210. package/lib/unwrapErrorHandler.d.ts +7 -0
  211. package/lib/unwrapErrorHandler.js +21 -0
  212. package/lib/unwrapErrorHandler.js.map +1 -0
  213. package/lib/utcToLocal.d.ts +6 -0
  214. package/lib/utcToLocal.js +26 -0
  215. package/lib/utcToLocal.js.map +1 -0
  216. package/lib/validationDataMerge.d.ts +11 -0
  217. package/lib/validationDataMerge.js +26 -0
  218. package/lib/validationDataMerge.js.map +1 -0
  219. package/lib/withIdRefPrefix.d.ts +8 -0
  220. package/lib/withIdRefPrefix.js +47 -0
  221. package/lib/withIdRefPrefix.js.map +1 -0
  222. package/package.json +20 -13
  223. package/src/ErrorSchemaBuilder.ts +112 -0
  224. package/src/allowAdditionalItems.ts +15 -0
  225. package/src/asNumber.ts +38 -0
  226. package/src/canExpand.ts +31 -0
  227. package/src/constants.ts +31 -0
  228. package/src/createErrorHandler.ts +33 -0
  229. package/src/createSchemaUtils.ts +298 -0
  230. package/src/dataURItoBlob.ts +42 -0
  231. package/src/deepEquals.ts +19 -0
  232. package/src/englishStringTranslator.ts +14 -0
  233. package/src/enumOptionsDeselectValue.ts +28 -0
  234. package/src/enumOptionsIndexForValue.ts +27 -0
  235. package/src/enumOptionsIsSelected.ts +19 -0
  236. package/src/enumOptionsSelectValue.ts +28 -0
  237. package/src/enumOptionsValueForIndex.ts +26 -0
  238. package/src/enums.ts +74 -0
  239. package/src/findSchemaDefinition.ts +54 -0
  240. package/src/getDiscriminatorFieldFromSchema.ts +21 -0
  241. package/src/getInputProps.ts +55 -0
  242. package/src/getSchemaType.ts +37 -0
  243. package/src/getSubmitButtonOptions.ts +32 -0
  244. package/src/getTemplate.ts +26 -0
  245. package/src/getUiOptions.ts +32 -0
  246. package/src/getWidget.tsx +133 -0
  247. package/src/guessType.ts +28 -0
  248. package/src/hasWidget.ts +27 -0
  249. package/src/hashForSchema.ts +31 -0
  250. package/src/idGenerators.ts +81 -0
  251. package/src/index.ts +118 -0
  252. package/src/isConstant.ts +12 -0
  253. package/src/isCustomWidget.ts +19 -0
  254. package/src/isFixedItems.ts +12 -0
  255. package/src/isObject.ts +15 -0
  256. package/src/labelValue.ts +16 -0
  257. package/src/localToUTC.ts +8 -0
  258. package/src/mergeDefaultsWithFormData.ts +53 -0
  259. package/src/mergeObjects.ts +39 -0
  260. package/src/mergeSchemas.ts +38 -0
  261. package/src/optionsList.ts +41 -0
  262. package/src/orderProperties.ts +44 -0
  263. package/src/pad.ts +13 -0
  264. package/src/parseDateString.ts +33 -0
  265. package/src/parser/ParserValidator.ts +132 -0
  266. package/src/parser/index.ts +6 -0
  267. package/src/parser/schemaParser.ts +60 -0
  268. package/src/rangeSpec.ts +22 -0
  269. package/src/replaceStringParameters.ts +22 -0
  270. package/src/schema/getClosestMatchingOption.ts +191 -0
  271. package/src/schema/getDefaultFormState.ts +447 -0
  272. package/src/schema/getDisplayLabel.ts +59 -0
  273. package/src/schema/getFirstMatchingOption.ts +27 -0
  274. package/src/schema/getMatchingOption.ts +95 -0
  275. package/src/schema/index.ts +29 -0
  276. package/src/schema/isFilesArray.ts +27 -0
  277. package/src/schema/isMultiSelect.ts +21 -0
  278. package/src/schema/isSelect.ts +26 -0
  279. package/src/schema/mergeValidationData.ts +38 -0
  280. package/src/schema/retrieveSchema.ts +614 -0
  281. package/src/schema/sanitizeDataForNewSchema.ts +197 -0
  282. package/src/schema/toIdSchema.ts +105 -0
  283. package/src/schema/toPathSchema.ts +121 -0
  284. package/src/schemaRequiresTrueValue.ts +40 -0
  285. package/src/shouldRender.ts +16 -0
  286. package/src/toConstant.ts +19 -0
  287. package/src/toDateString.ts +15 -0
  288. package/src/toErrorList.ts +41 -0
  289. package/src/toErrorSchema.ts +43 -0
  290. package/src/types.ts +1139 -0
  291. package/src/unwrapErrorHandler.ts +25 -0
  292. package/src/utcToLocal.ts +30 -0
  293. package/src/validationDataMerge.ts +31 -0
  294. package/src/withIdRefPrefix.ts +49 -0
  295. package/dist/index.d.ts +0 -1911
  296. package/dist/utils.cjs.development.js +0 -3522
  297. package/dist/utils.cjs.development.js.map +0 -1
  298. package/dist/utils.cjs.production.min.js +0 -2
  299. package/dist/utils.cjs.production.min.js.map +0 -1
  300. package/dist/utils.umd.development.js +0 -3504
  301. package/dist/utils.umd.development.js.map +0 -1
  302. package/dist/utils.umd.production.min.js +0 -2
  303. package/dist/utils.umd.production.min.js.map +0 -1
@@ -0,0 +1,298 @@
1
+ import deepEquals from './deepEquals';
2
+ import {
3
+ ErrorSchema,
4
+ Experimental_DefaultFormStateBehavior,
5
+ FormContextType,
6
+ GlobalUISchemaOptions,
7
+ IdSchema,
8
+ PathSchema,
9
+ RJSFSchema,
10
+ SchemaUtilsType,
11
+ StrictRJSFSchema,
12
+ UiSchema,
13
+ ValidationData,
14
+ ValidatorType,
15
+ } from './types';
16
+ import {
17
+ getDefaultFormState,
18
+ getDisplayLabel,
19
+ getClosestMatchingOption,
20
+ getFirstMatchingOption,
21
+ getMatchingOption,
22
+ isFilesArray,
23
+ isMultiSelect,
24
+ isSelect,
25
+ mergeValidationData,
26
+ retrieveSchema,
27
+ sanitizeDataForNewSchema,
28
+ toIdSchema,
29
+ toPathSchema,
30
+ } from './schema';
31
+
32
+ /** The `SchemaUtils` class provides a wrapper around the publicly exported APIs in the `utils/schema` directory such
33
+ * that one does not have to explicitly pass the `validator`, `rootSchema`, or `experimental_defaultFormStateBehavior` to each method.
34
+ * Since these generally do not change across a `Form`, this allows for providing a simplified set of APIs to the
35
+ * `@rjsf/core` components and the various themes as well. This class implements the `SchemaUtilsType` interface.
36
+ */
37
+ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
38
+ implements SchemaUtilsType<T, S, F>
39
+ {
40
+ rootSchema: S;
41
+ validator: ValidatorType<T, S, F>;
42
+ experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior;
43
+
44
+ /** Constructs the `SchemaUtils` instance with the given `validator` and `rootSchema` stored as instance variables
45
+ *
46
+ * @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs
47
+ * @param rootSchema - The root schema that will be forwarded to all the APIs
48
+ * @param experimental_defaultFormStateBehavior - Configuration flags to allow users to override default form state behavior
49
+ */
50
+ constructor(
51
+ validator: ValidatorType<T, S, F>,
52
+ rootSchema: S,
53
+ experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior
54
+ ) {
55
+ this.rootSchema = rootSchema;
56
+ this.validator = validator;
57
+ this.experimental_defaultFormStateBehavior = experimental_defaultFormStateBehavior;
58
+ }
59
+
60
+ /** Returns the `ValidatorType` in the `SchemaUtilsType`
61
+ *
62
+ * @returns - The `ValidatorType`
63
+ */
64
+ getValidator() {
65
+ return this.validator;
66
+ }
67
+
68
+ /** Determines whether either the `validator` and `rootSchema` differ from the ones associated with this instance of
69
+ * the `SchemaUtilsType`. If either `validator` or `rootSchema` are falsy, then return false to prevent the creation
70
+ * of a new `SchemaUtilsType` with incomplete properties.
71
+ *
72
+ * @param validator - An implementation of the `ValidatorType` interface that will be compared against the current one
73
+ * @param rootSchema - The root schema that will be compared against the current one
74
+ * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior
75
+ * @returns - True if the `SchemaUtilsType` differs from the given `validator` or `rootSchema`
76
+ */
77
+ doesSchemaUtilsDiffer(
78
+ validator: ValidatorType<T, S, F>,
79
+ rootSchema: S,
80
+ experimental_defaultFormStateBehavior = {}
81
+ ): boolean {
82
+ if (!validator || !rootSchema) {
83
+ return false;
84
+ }
85
+ return (
86
+ this.validator !== validator ||
87
+ !deepEquals(this.rootSchema, rootSchema) ||
88
+ !deepEquals(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior)
89
+ );
90
+ }
91
+
92
+ /** Returns the superset of `formData` that includes the given set updated to include any missing fields that have
93
+ * computed to have defaults provided in the `schema`.
94
+ *
95
+ * @param schema - The schema for which the default state is desired
96
+ * @param [formData] - The current formData, if any, onto which to provide any missing defaults
97
+ * @param [includeUndefinedValues=false] - Optional flag, if true, cause undefined values to be added as defaults.
98
+ * If "excludeObjectChildren", pass `includeUndefinedValues` as false when computing defaults for any nested
99
+ * object properties.
100
+ * @returns - The resulting `formData` with all the defaults provided
101
+ */
102
+ getDefaultFormState(
103
+ schema: S,
104
+ formData?: T,
105
+ includeUndefinedValues: boolean | 'excludeObjectChildren' = false
106
+ ): T | T[] | undefined {
107
+ return getDefaultFormState<T, S, F>(
108
+ this.validator,
109
+ schema,
110
+ formData,
111
+ this.rootSchema,
112
+ includeUndefinedValues,
113
+ this.experimental_defaultFormStateBehavior
114
+ );
115
+ }
116
+
117
+ /** Determines whether the combination of `schema` and `uiSchema` properties indicates that the label for the `schema`
118
+ * should be displayed in a UI.
119
+ *
120
+ * @param schema - The schema for which the display label flag is desired
121
+ * @param [uiSchema] - The UI schema from which to derive potentially displayable information
122
+ * @param [globalOptions={}] - The optional Global UI Schema from which to get any fallback `xxx` options
123
+ * @returns - True if the label should be displayed or false if it should not
124
+ */
125
+ getDisplayLabel(schema: S, uiSchema?: UiSchema<T, S, F>, globalOptions?: GlobalUISchemaOptions) {
126
+ return getDisplayLabel<T, S, F>(this.validator, schema, uiSchema, this.rootSchema, globalOptions);
127
+ }
128
+
129
+ /** Determines which of the given `options` provided most closely matches the `formData`.
130
+ * Returns the index of the option that is valid and is the closest match, or 0 if there is no match.
131
+ *
132
+ * The closest match is determined using the number of matching properties, and more heavily favors options with
133
+ * matching readOnly, default, or const values.
134
+ *
135
+ * @param formData - The form data associated with the schema
136
+ * @param options - The list of options that can be selected from
137
+ * @param [selectedOption] - The index of the currently selected option, defaulted to -1 if not specified
138
+ * @param [discriminatorField] - The optional name of the field within the options object whose value is used to
139
+ * determine which option is selected
140
+ * @returns - The index of the option that is the closest match to the `formData` or the `selectedOption` if no match
141
+ */
142
+ getClosestMatchingOption(
143
+ formData: T | undefined,
144
+ options: S[],
145
+ selectedOption?: number,
146
+ discriminatorField?: string
147
+ ): number {
148
+ return getClosestMatchingOption<T, S, F>(
149
+ this.validator,
150
+ this.rootSchema,
151
+ formData,
152
+ options,
153
+ selectedOption,
154
+ discriminatorField
155
+ );
156
+ }
157
+
158
+ /** Given the `formData` and list of `options`, attempts to find the index of the first option that matches the data.
159
+ * Always returns the first option if there is nothing that matches.
160
+ *
161
+ * @param formData - The current formData, if any, used to figure out a match
162
+ * @param options - The list of options to find a matching options from
163
+ * @param [discriminatorField] - The optional name of the field within the options object whose value is used to
164
+ * determine which option is selected
165
+ * @returns - The firstindex of the matched option or 0 if none is available
166
+ */
167
+ getFirstMatchingOption(formData: T | undefined, options: S[], discriminatorField?: string): number {
168
+ return getFirstMatchingOption<T, S, F>(this.validator, formData, options, this.rootSchema, discriminatorField);
169
+ }
170
+
171
+ /** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data.
172
+ * Deprecated, use `getFirstMatchingOption()` instead.
173
+ *
174
+ * @param formData - The current formData, if any, onto which to provide any missing defaults
175
+ * @param options - The list of options to find a matching options from
176
+ * @param [discriminatorField] - The optional name of the field within the options object whose value is used to
177
+ * determine which option is selected
178
+ * @returns - The index of the matched option or 0 if none is available
179
+ * @deprecated
180
+ */
181
+ getMatchingOption(formData: T | undefined, options: S[], discriminatorField?: string) {
182
+ return getMatchingOption<T, S, F>(this.validator, formData, options, this.rootSchema, discriminatorField);
183
+ }
184
+
185
+ /** Checks to see if the `schema` and `uiSchema` combination represents an array of files
186
+ *
187
+ * @param schema - The schema for which check for array of files flag is desired
188
+ * @param [uiSchema] - The UI schema from which to check the widget
189
+ * @returns - True if schema/uiSchema contains an array of files, otherwise false
190
+ */
191
+ isFilesArray(schema: S, uiSchema?: UiSchema<T, S, F>) {
192
+ return isFilesArray<T, S, F>(this.validator, schema, uiSchema, this.rootSchema);
193
+ }
194
+
195
+ /** Checks to see if the `schema` combination represents a multi-select
196
+ *
197
+ * @param schema - The schema for which check for a multi-select flag is desired
198
+ * @returns - True if schema contains a multi-select, otherwise false
199
+ */
200
+ isMultiSelect(schema: S) {
201
+ return isMultiSelect<T, S, F>(this.validator, schema, this.rootSchema);
202
+ }
203
+
204
+ /** Checks to see if the `schema` combination represents a select
205
+ *
206
+ * @param schema - The schema for which check for a select flag is desired
207
+ * @returns - True if schema contains a select, otherwise false
208
+ */
209
+ isSelect(schema: S) {
210
+ return isSelect<T, S, F>(this.validator, schema, this.rootSchema);
211
+ }
212
+
213
+ /** Merges the errors in `additionalErrorSchema` into the existing `validationData` by combining the hierarchies in
214
+ * the two `ErrorSchema`s and then appending the error list from the `additionalErrorSchema` obtained by calling
215
+ * `getValidator().toErrorList()` onto the `errors` in the `validationData`. If no `additionalErrorSchema` is passed,
216
+ * then `validationData` is returned.
217
+ *
218
+ * @param validationData - The current `ValidationData` into which to merge the additional errors
219
+ * @param [additionalErrorSchema] - The additional set of errors
220
+ * @returns - The `validationData` with the additional errors from `additionalErrorSchema` merged into it, if provided.
221
+ * @deprecated - Use the `validationDataMerge()` function exported from `@rjsf/utils` instead. This function will be
222
+ * removed in the next major release.
223
+ */
224
+ mergeValidationData(validationData: ValidationData<T>, additionalErrorSchema?: ErrorSchema<T>): ValidationData<T> {
225
+ return mergeValidationData<T, S, F>(this.validator, validationData, additionalErrorSchema);
226
+ }
227
+
228
+ /** Retrieves an expanded schema that has had all of its conditions, additional properties, references and
229
+ * dependencies resolved and merged into the `schema` given a `rawFormData` that is used to do the potentially
230
+ * recursive resolution.
231
+ *
232
+ * @param schema - The schema for which retrieving a schema is desired
233
+ * @param [rawFormData] - The current formData, if any, to assist retrieving a schema
234
+ * @returns - The schema having its conditions, additional properties, references and dependencies resolved
235
+ */
236
+ retrieveSchema(schema: S, rawFormData?: T) {
237
+ return retrieveSchema<T, S, F>(this.validator, schema, this.rootSchema, rawFormData);
238
+ }
239
+
240
+ /** Sanitize the `data` associated with the `oldSchema` so it is considered appropriate for the `newSchema`. If the
241
+ * new schema does not contain any properties, then `undefined` is returned to clear all the form data. Due to the
242
+ * nature of schemas, this sanitization happens recursively for nested objects of data. Also, any properties in the
243
+ * old schemas that are non-existent in the new schema are set to `undefined`.
244
+ *
245
+ * @param [newSchema] - The new schema for which the data is being sanitized
246
+ * @param [oldSchema] - The old schema from which the data originated
247
+ * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined
248
+ * @returns - The new form data, with all the fields uniquely associated with the old schema set
249
+ * to `undefined`. Will return `undefined` if the new schema is not an object containing properties.
250
+ */
251
+ sanitizeDataForNewSchema(newSchema?: S, oldSchema?: S, data?: any): T {
252
+ return sanitizeDataForNewSchema(this.validator, this.rootSchema, newSchema, oldSchema, data);
253
+ }
254
+
255
+ /** Generates an `IdSchema` object for the `schema`, recursively
256
+ *
257
+ * @param schema - The schema for which the display label flag is desired
258
+ * @param [id] - The base id for the schema
259
+ * @param [formData] - The current formData, if any, onto which to provide any missing defaults
260
+ * @param [idPrefix='root'] - The prefix to use for the id
261
+ * @param [idSeparator='_'] - The separator to use for the path segments in the id
262
+ * @returns - The `IdSchema` object for the `schema`
263
+ */
264
+ toIdSchema(schema: S, id?: string | null, formData?: T, idPrefix = 'root', idSeparator = '_'): IdSchema<T> {
265
+ return toIdSchema<T, S, F>(this.validator, schema, id, this.rootSchema, formData, idPrefix, idSeparator);
266
+ }
267
+
268
+ /** Generates an `PathSchema` object for the `schema`, recursively
269
+ *
270
+ * @param schema - The schema for which the display label flag is desired
271
+ * @param [name] - The base name for the schema
272
+ * @param [formData] - The current formData, if any, onto which to provide any missing defaults
273
+ * @returns - The `PathSchema` object for the `schema`
274
+ */
275
+ toPathSchema(schema: S, name?: string, formData?: T): PathSchema<T> {
276
+ return toPathSchema<T, S, F>(this.validator, schema, name, this.rootSchema, formData);
277
+ }
278
+ }
279
+
280
+ /** Creates a `SchemaUtilsType` interface that is based around the given `validator` and `rootSchema` parameters. The
281
+ * resulting interface implementation will forward the `validator` and `rootSchema` to all the wrapped APIs.
282
+ *
283
+ * @param validator - an implementation of the `ValidatorType` interface that will be forwarded to all the APIs
284
+ * @param rootSchema - The root schema that will be forwarded to all the APIs
285
+ * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior
286
+ * @returns - An implementation of a `SchemaUtilsType` interface
287
+ */
288
+ export default function createSchemaUtils<
289
+ T = any,
290
+ S extends StrictRJSFSchema = RJSFSchema,
291
+ F extends FormContextType = any
292
+ >(
293
+ validator: ValidatorType<T, S, F>,
294
+ rootSchema: S,
295
+ experimental_defaultFormStateBehavior = {}
296
+ ): SchemaUtilsType<T, S, F> {
297
+ return new SchemaUtils<T, S, F>(validator, rootSchema, experimental_defaultFormStateBehavior);
298
+ }
@@ -0,0 +1,42 @@
1
+ /** Given the `FileReader.readAsDataURL()` based `dataURI` extracts that data into an actual Blob along with the name
2
+ * of that Blob if provided in the URL. If no name is provided, then the name falls back to `unknown`.
3
+ *
4
+ * @param dataURI - The `DataUrl` potentially containing name and raw data to be converted to a Blob
5
+ * @returns - an object containing a Blob and its name, extracted from the URI
6
+ */
7
+ export default function dataURItoBlob(dataURI: string) {
8
+ // Split metadata from data
9
+ const splitted: string[] = dataURI.split(',');
10
+ // Split params
11
+ const params: string[] = splitted[0].split(';');
12
+ // Get mime-type from params
13
+ const type: string = params[0].replace('data:', '');
14
+ // Filter the name property from params
15
+ const properties = params.filter((param) => {
16
+ return param.split('=')[0] === 'name';
17
+ });
18
+ // Look for the name and use unknown if no name property.
19
+ let name: string;
20
+ if (properties.length !== 1) {
21
+ name = 'unknown';
22
+ } else {
23
+ // Because we filtered out the other property,
24
+ // we only have the name case here, which we decode to make it human-readable
25
+ name = decodeURI(properties[0].split('=')[1]);
26
+ }
27
+
28
+ // Built the Uint8Array Blob parameter from the base64 string.
29
+ try {
30
+ const binary = atob(splitted[1]);
31
+ const array = [];
32
+ for (let i = 0; i < binary.length; i++) {
33
+ array.push(binary.charCodeAt(i));
34
+ }
35
+ // Create the blob object
36
+ const blob = new window.Blob([new Uint8Array(array)], { type });
37
+
38
+ return { blob, name };
39
+ } catch (error) {
40
+ return { blob: { size: 0, type: (error as Error).message }, name: dataURI };
41
+ }
42
+ }
@@ -0,0 +1,19 @@
1
+ import isEqualWith from 'lodash/isEqualWith';
2
+
3
+ /** Implements a deep equals using the `lodash.isEqualWith` function, that provides a customized comparator that
4
+ * assumes all functions are equivalent.
5
+ *
6
+ * @param a - The first element to compare
7
+ * @param b - The second element to compare
8
+ * @returns - True if the `a` and `b` are deeply equal, false otherwise
9
+ */
10
+ export default function deepEquals(a: any, b: any): boolean {
11
+ return isEqualWith(a, b, (obj: any, other: any) => {
12
+ if (typeof obj === 'function' && typeof other === 'function') {
13
+ // Assume all functions are equivalent
14
+ // see https://github.com/rjsf-team/react-jsonschema-form/issues/255
15
+ return true;
16
+ }
17
+ return undefined; // fallback to default isEquals behavior
18
+ });
19
+ }
@@ -0,0 +1,14 @@
1
+ import { TranslatableString } from './enums';
2
+ import replaceStringParameters from './replaceStringParameters';
3
+
4
+ /** Translates a `TranslatableString` value `stringToTranslate` into english. When a `params` array is provided, each
5
+ * value in the array is used to replace any of the replaceable parameters in the `stringToTranslate` using the `%1`,
6
+ * `%2`, etc. replacement specifiers.
7
+ *
8
+ * @param stringToTranslate - The `TranslatableString` value to convert to english
9
+ * @param params - The optional list of replaceable parameter values to substitute into the english string
10
+ * @returns - The `stringToTranslate` itself with any replaceable parameter values substituted
11
+ */
12
+ export default function englishStringTranslator(stringToTranslate: TranslatableString, params?: string[]): string {
13
+ return replaceStringParameters(stringToTranslate, params);
14
+ }
@@ -0,0 +1,28 @@
1
+ import isEqual from 'lodash/isEqual';
2
+
3
+ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
4
+ import enumOptionsValueForIndex from './enumOptionsValueForIndex';
5
+
6
+ /** Removes the enum option value at the `valueIndex` from the currently `selected` (list of) value(s). If `selected` is
7
+ * a list, then that list is updated to remove the enum option value with the `valueIndex` in `allEnumOptions`. If it is
8
+ * a single value, then if the enum option value with the `valueIndex` in `allEnumOptions` matches `selected`, undefined
9
+ * is returned, otherwise the `selected` value is returned.
10
+ *
11
+ * @param valueIndex - The index of the value to be removed from the selected list or single value
12
+ * @param selected - The current (list of) selected value(s)
13
+ * @param [allEnumOptions=[]] - The list of all the known enumOptions
14
+ * @returns - The updated `selected` with the enum option value at `valueIndex` in `allEnumOptions` removed from it,
15
+ * unless `selected` is a single value. In that case, if the `valueIndex` value matches `selected`, returns
16
+ * undefined, otherwise `selected`.
17
+ */
18
+ export default function enumOptionsDeselectValue<S extends StrictRJSFSchema = RJSFSchema>(
19
+ valueIndex: string | number,
20
+ selected?: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][],
21
+ allEnumOptions: EnumOptionsType<S>[] = []
22
+ ): EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][] | undefined {
23
+ const value = enumOptionsValueForIndex<S>(valueIndex, allEnumOptions);
24
+ if (Array.isArray(selected)) {
25
+ return selected.filter((v) => !isEqual(v, value));
26
+ }
27
+ return isEqual(value, selected) ? undefined : selected;
28
+ }
@@ -0,0 +1,27 @@
1
+ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
2
+ import enumOptionsIsSelected from './enumOptionsIsSelected';
3
+
4
+ /** Returns the index(es) of the options in `allEnumOptions` whose value(s) match the ones in `value`. All the
5
+ * `enumOptions` are filtered based on whether they are a "selected" `value` and the index of each selected one is then
6
+ * stored in an array. If `multiple` is true, that array is returned, otherwise the first element in the array is
7
+ * returned.
8
+ *
9
+ * @param value - The single value or list of values for which indexes are desired
10
+ * @param [allEnumOptions=[]] - The list of all the known enumOptions
11
+ * @param [multiple=false] - Optional flag, if true will return a list of index, otherwise a single one
12
+ * @returns - A single string index for the first `value` in `allEnumOptions`, if not `multiple`. Otherwise, the list
13
+ * of indexes for (each of) the value(s) in `value`.
14
+ */
15
+ export default function enumOptionsIndexForValue<S extends StrictRJSFSchema = RJSFSchema>(
16
+ value: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][],
17
+ allEnumOptions: EnumOptionsType<S>[] = [],
18
+ multiple = false
19
+ ): string | string[] | undefined {
20
+ const selectedIndexes: string[] = allEnumOptions
21
+ .map((opt, index) => (enumOptionsIsSelected(opt.value, value) ? String(index) : undefined))
22
+ .filter((opt) => typeof opt !== 'undefined') as string[];
23
+ if (!multiple) {
24
+ return selectedIndexes[0];
25
+ }
26
+ return selectedIndexes;
27
+ }
@@ -0,0 +1,19 @@
1
+ import isEqual from 'lodash/isEqual';
2
+
3
+ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
4
+
5
+ /** Determines whether the given `value` is (one of) the `selected` value(s).
6
+ *
7
+ * @param value - The value being checked to see if it is selected
8
+ * @param selected - The current selected value or list of values
9
+ * @returns - true if the `value` is one of the `selected` ones, false otherwise
10
+ */
11
+ export default function enumOptionsIsSelected<S extends StrictRJSFSchema = RJSFSchema>(
12
+ value: EnumOptionsType<S>['value'],
13
+ selected: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][]
14
+ ) {
15
+ if (Array.isArray(selected)) {
16
+ return selected.some((sel) => isEqual(sel, value));
17
+ }
18
+ return isEqual(selected, value);
19
+ }
@@ -0,0 +1,28 @@
1
+ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
2
+ import enumOptionsValueForIndex from './enumOptionsValueForIndex';
3
+ import { isNil } from 'lodash';
4
+
5
+ /** Add the enum option value at the `valueIndex` to the list of `selected` values in the proper order as defined by
6
+ * `allEnumOptions`
7
+ *
8
+ * @param valueIndex - The index of the value that should be selected
9
+ * @param selected - The current list of selected values
10
+ * @param [allEnumOptions=[]] - The list of all the known enumOptions
11
+ * @returns - The updated list of selected enum values with enum value at the `valueIndex` added to it
12
+ */
13
+ export default function enumOptionsSelectValue<S extends StrictRJSFSchema = RJSFSchema>(
14
+ valueIndex: string | number,
15
+ selected: EnumOptionsType<S>['value'][],
16
+ allEnumOptions: EnumOptionsType<S>[] = []
17
+ ) {
18
+ const value = enumOptionsValueForIndex<S>(valueIndex, allEnumOptions);
19
+ if (!isNil(value)) {
20
+ const index = allEnumOptions.findIndex((opt) => value === opt.value);
21
+ const all = allEnumOptions.map(({ value: val }) => val);
22
+ const updated = selected.slice(0, index).concat(value, selected.slice(index));
23
+ // As inserting values at predefined index positions doesn't work with empty
24
+ // arrays, we need to reorder the updated selection to match the initial order
25
+ return updated.sort((a, b) => Number(all.indexOf(a) > all.indexOf(b)));
26
+ }
27
+ return selected;
28
+ }
@@ -0,0 +1,26 @@
1
+ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
2
+
3
+ /** Returns the value(s) from `allEnumOptions` at the index(es) provided by `valueIndex`. If `valueIndex` is not an
4
+ * array AND the index is not valid for `allEnumOptions`, `emptyValue` is returned. If `valueIndex` is an array, AND it
5
+ * contains an invalid index, the returned array will have the resulting undefined values filtered out, leaving only
6
+ * valid values or in the worst case, an empty array.
7
+ *
8
+ * @param valueIndex - The index(es) of the value(s) that should be returned
9
+ * @param [allEnumOptions=[]] - The list of all the known enumOptions
10
+ * @param [emptyValue] - The value to return when the non-array `valueIndex` does not refer to a real option
11
+ * @returns - The single or list of values specified by the single or list of indexes if they are valid. Otherwise,
12
+ * `emptyValue` or an empty list.
13
+ */
14
+ export default function enumOptionsValueForIndex<S extends StrictRJSFSchema = RJSFSchema>(
15
+ valueIndex: string | number | Array<string | number>,
16
+ allEnumOptions: EnumOptionsType<S>[] = [],
17
+ emptyValue?: EnumOptionsType<S>['value']
18
+ ): EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][] | undefined {
19
+ if (Array.isArray(valueIndex)) {
20
+ return valueIndex.map((index) => enumOptionsValueForIndex(index, allEnumOptions)).filter((val) => val);
21
+ }
22
+ // So Number(null) and Number('') both return 0, so use emptyValue for those two values
23
+ const index = valueIndex === '' || valueIndex === null ? -1 : Number(valueIndex);
24
+ const option = allEnumOptions[index];
25
+ return option ? option.value : emptyValue;
26
+ }
package/src/enums.ts ADDED
@@ -0,0 +1,74 @@
1
+ /** An enumeration of all the translatable strings used by `@rjsf/core` and its themes. The value of each of the
2
+ * enumeration keys is expected to be the actual english string. Some strings contain replaceable parameter values
3
+ * as indicated by `%1`, `%2`, etc. The number after the `%` indicates the order of the parameter. The ordering of
4
+ * parameters is important because some languages may choose to put the second parameter before the first in its
5
+ * translation. Also, some strings are rendered using `markdown-to-jsx` and thus support markdown and inline html.
6
+ */
7
+ export enum TranslatableString {
8
+ /** Fallback title of an array item, used by ArrayField */
9
+ ArrayItemTitle = 'Item',
10
+ /** Missing items reason, used by ArrayField */
11
+ MissingItems = 'Missing items definition',
12
+ /** Yes label, used by BooleanField */
13
+ YesLabel = 'Yes',
14
+ /** No label, used by BooleanField */
15
+ NoLabel = 'No',
16
+ /** Close label, used by ErrorList */
17
+ CloseLabel = 'Close',
18
+ /** Errors label, used by ErrorList */
19
+ ErrorsLabel = 'Errors',
20
+ /** New additionalProperties string default value, used by ObjectField */
21
+ NewStringDefault = 'New Value',
22
+ /** Add button title, used by AddButton */
23
+ AddButton = 'Add',
24
+ /** Add button title, used by AddButton */
25
+ AddItemButton = 'Add Item',
26
+ /** Copy button title, used by IconButton */
27
+ CopyButton = 'Copy',
28
+ /** Move down button title, used by IconButton */
29
+ MoveDownButton = 'Move down',
30
+ /** Move up button title, used by IconButton */
31
+ MoveUpButton = 'Move up',
32
+ /** Remove button title, used by IconButton */
33
+ RemoveButton = 'Remove',
34
+ /** Now label, used by AltDateWidget */
35
+ NowLabel = 'Now',
36
+ /** Clear label, used by AltDateWidget */
37
+ ClearLabel = 'Clear',
38
+ /** Aria date label, used by DateWidget */
39
+ AriaDateLabel = 'Select a date',
40
+ /** File preview label, used by FileWidget */
41
+ PreviewLabel = 'Preview',
42
+ /** Decrement button aria label, used by UpDownWidget */
43
+ DecrementAriaLabel = 'Decrease value by 1',
44
+ /** Increment button aria label, used by UpDownWidget */
45
+ IncrementAriaLabel = 'Increase value by 1',
46
+ // Strings with replaceable parameters
47
+ /** Unknown field type reason, where %1 will be replaced with the type as provided by SchemaField */
48
+ UnknownFieldType = 'Unknown field type %1',
49
+ /** Option prefix, where %1 will be replaced with the option index as provided by MultiSchemaField */
50
+ OptionPrefix = 'Option %1',
51
+ /** Option prefix, where %1 and %2 will be replaced by the schema title and option index, respectively as provided by
52
+ * MultiSchemaField
53
+ */
54
+ TitleOptionPrefix = '%1 option %2',
55
+ /** Key label, where %1 will be replaced by the label as provided by WrapIfAdditionalTemplate */
56
+ KeyLabel = '%1 Key',
57
+ // Strings with replaceable parameters AND/OR that support markdown and html
58
+ /** Invalid object field configuration as provided by the ObjectField */
59
+ InvalidObjectField = 'Invalid "%1" object field configuration: <em>%2</em>.',
60
+ /** Unsupported field schema, used by UnsupportedField */
61
+ UnsupportedField = 'Unsupported field schema.',
62
+ /** Unsupported field schema, where %1 will be replaced by the idSchema.$id as provided by UnsupportedField */
63
+ UnsupportedFieldWithId = 'Unsupported field schema for field <code>%1</code>.',
64
+ /** Unsupported field schema, where %1 will be replaced by the reason string as provided by UnsupportedField */
65
+ UnsupportedFieldWithReason = 'Unsupported field schema: <em>%1</em>.',
66
+ /** Unsupported field schema, where %1 and %2 will be replaced by the idSchema.$id and reason strings, respectively,
67
+ * as provided by UnsupportedField
68
+ */
69
+ UnsupportedFieldWithIdAndReason = 'Unsupported field schema for field <code>%1</code>: <em>%2</em>.',
70
+ /** File name, type and size info, where %1, %2 and %3 will be replaced by the file name, file type and file size as
71
+ * provided by FileWidget
72
+ */
73
+ FilesInfo = '<strong>%1</strong> (%2, %3 bytes)',
74
+ }
@@ -0,0 +1,54 @@
1
+ import jsonpointer from 'jsonpointer';
2
+ import omit from 'lodash/omit';
3
+
4
+ import { REF_KEY } from './constants';
5
+ import { GenericObjectType, RJSFSchema, StrictRJSFSchema } from './types';
6
+
7
+ /** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first
8
+ * location, the `object` minus the `key: value` and in the second location the `value`.
9
+ *
10
+ * @param key - The key from the object to extract
11
+ * @param object - The object from which to extract the element
12
+ * @returns - An array with the first value being the object minus the `key` element and the second element being the
13
+ * value from `object[key]`
14
+ */
15
+ export function splitKeyElementFromObject(key: string, object: GenericObjectType) {
16
+ const value = object[key];
17
+ const remaining = omit(object, [key]);
18
+ return [remaining, value];
19
+ }
20
+
21
+ /** Given the name of a `$ref` from within a schema, using the `rootSchema`, look up and return the sub-schema using the
22
+ * path provided by that reference. If `#` is not the first character of the reference, or the path does not exist in
23
+ * the schema, then throw an Error. Otherwise return the sub-schema. Also deals with nested `$ref`s in the sub-schema.
24
+ *
25
+ * @param $ref - The ref string for which the schema definition is desired
26
+ * @param [rootSchema={}] - The root schema in which to search for the definition
27
+ * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
28
+ * @throws - Error indicating that no schema for that reference exists
29
+ */
30
+ export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
31
+ $ref?: string,
32
+ rootSchema: S = {} as S
33
+ ): S {
34
+ let ref = $ref || '';
35
+ if (ref.startsWith('#')) {
36
+ // Decode URI fragment representation.
37
+ ref = decodeURIComponent(ref.substring(1));
38
+ } else {
39
+ throw new Error(`Could not find a definition for ${$ref}.`);
40
+ }
41
+ const current: S = jsonpointer.get(rootSchema, ref);
42
+ if (current === undefined) {
43
+ throw new Error(`Could not find a definition for ${$ref}.`);
44
+ }
45
+ if (current[REF_KEY]) {
46
+ const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
47
+ const subSchema = findSchemaDefinition<S>(theRef, rootSchema);
48
+ if (Object.keys(remaining).length > 0) {
49
+ return { ...remaining, ...subSchema };
50
+ }
51
+ return subSchema;
52
+ }
53
+ return current;
54
+ }
@@ -0,0 +1,21 @@
1
+ import get from 'lodash/get';
2
+ import isString from 'lodash/isString';
3
+
4
+ import { RJSFSchema, StrictRJSFSchema } from './types';
5
+
6
+ /** Returns the `discriminator.propertyName` when defined in the `schema` if it is a string. A warning is generated when
7
+ * it is not a string. Returns `undefined` when a valid discriminator is not present.
8
+ *
9
+ * @param schema - The schema from which the discriminator is potentially obtained
10
+ * @returns - The `discriminator.propertyName` if it exists in the schema, otherwise `undefined`
11
+ */
12
+ export default function getDiscriminatorFieldFromSchema<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
13
+ let discriminator: string | undefined;
14
+ const maybeString = get(schema, 'discriminator.propertyName', undefined);
15
+ if (isString(maybeString)) {
16
+ discriminator = maybeString;
17
+ } else if (maybeString !== undefined) {
18
+ console.warn(`Expecting discriminator to be a string, got "${typeof maybeString}" instead`);
19
+ }
20
+ return discriminator;
21
+ }