@rjsf/utils 6.0.0-alpha.0 → 6.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/dist/index.js +1347 -642
  2. package/dist/index.js.map +4 -4
  3. package/dist/utils.esm.js +1324 -619
  4. package/dist/utils.esm.js.map +4 -4
  5. package/dist/utils.umd.js +1266 -590
  6. package/lib/ErrorSchemaBuilder.d.ts +8 -4
  7. package/lib/ErrorSchemaBuilder.js +10 -8
  8. package/lib/ErrorSchemaBuilder.js.map +1 -1
  9. package/lib/allowAdditionalItems.d.ts +1 -1
  10. package/lib/allowAdditionalItems.js +1 -1
  11. package/lib/allowAdditionalItems.js.map +1 -1
  12. package/lib/asNumber.js.map +1 -1
  13. package/lib/canExpand.d.ts +2 -2
  14. package/lib/canExpand.js +2 -2
  15. package/lib/canExpand.js.map +1 -1
  16. package/lib/constIsAjvDataReference.d.ts +9 -0
  17. package/lib/constIsAjvDataReference.js +15 -0
  18. package/lib/constIsAjvDataReference.js.map +1 -0
  19. package/lib/constants.d.ts +15 -3
  20. package/lib/constants.js +15 -3
  21. package/lib/constants.js.map +1 -1
  22. package/lib/createErrorHandler.d.ts +1 -1
  23. package/lib/createErrorHandler.js +2 -2
  24. package/lib/createErrorHandler.js.map +1 -1
  25. package/lib/createSchemaUtils.d.ts +3 -2
  26. package/lib/createSchemaUtils.js +56 -46
  27. package/lib/createSchemaUtils.js.map +1 -1
  28. package/lib/dataURItoBlob.js.map +1 -1
  29. package/lib/dateRangeOptions.d.ts +1 -1
  30. package/lib/dateRangeOptions.js +1 -1
  31. package/lib/dateRangeOptions.js.map +1 -1
  32. package/lib/deepEquals.js +1 -1
  33. package/lib/deepEquals.js.map +1 -1
  34. package/lib/englishStringTranslator.d.ts +1 -1
  35. package/lib/englishStringTranslator.js +1 -1
  36. package/lib/enumOptionsDeselectValue.d.ts +1 -1
  37. package/lib/enumOptionsDeselectValue.js +4 -4
  38. package/lib/enumOptionsDeselectValue.js.map +1 -1
  39. package/lib/enumOptionsIndexForValue.d.ts +1 -1
  40. package/lib/enumOptionsIndexForValue.js +1 -1
  41. package/lib/enumOptionsIndexForValue.js.map +1 -1
  42. package/lib/enumOptionsIsSelected.d.ts +1 -1
  43. package/lib/enumOptionsIsSelected.js +3 -3
  44. package/lib/enumOptionsIsSelected.js.map +1 -1
  45. package/lib/enumOptionsSelectValue.d.ts +1 -1
  46. package/lib/enumOptionsSelectValue.js +2 -2
  47. package/lib/enumOptionsSelectValue.js.map +1 -1
  48. package/lib/enumOptionsValueForIndex.d.ts +1 -1
  49. package/lib/enumOptionsValueForIndex.js.map +1 -1
  50. package/lib/enums.d.ts +2 -0
  51. package/lib/enums.js +2 -0
  52. package/lib/enums.js.map +1 -1
  53. package/lib/findSchemaDefinition.d.ts +5 -3
  54. package/lib/findSchemaDefinition.js +54 -11
  55. package/lib/findSchemaDefinition.js.map +1 -1
  56. package/lib/getChangedFields.d.ts +17 -0
  57. package/lib/getChangedFields.js +42 -0
  58. package/lib/getChangedFields.js.map +1 -0
  59. package/lib/getDateElementProps.d.ts +1 -1
  60. package/lib/getDateElementProps.js.map +1 -1
  61. package/lib/getDiscriminatorFieldFromSchema.d.ts +1 -1
  62. package/lib/getDiscriminatorFieldFromSchema.js +4 -3
  63. package/lib/getDiscriminatorFieldFromSchema.js.map +1 -1
  64. package/lib/getInputProps.d.ts +1 -1
  65. package/lib/getInputProps.js +4 -1
  66. package/lib/getInputProps.js.map +1 -1
  67. package/lib/getOptionMatchingSimpleDiscriminator.d.ts +1 -1
  68. package/lib/getOptionMatchingSimpleDiscriminator.js +2 -2
  69. package/lib/getOptionMatchingSimpleDiscriminator.js.map +1 -1
  70. package/lib/getSchemaType.d.ts +2 -1
  71. package/lib/getSchemaType.js +3 -2
  72. package/lib/getSchemaType.js.map +1 -1
  73. package/lib/getSubmitButtonOptions.d.ts +1 -1
  74. package/lib/getSubmitButtonOptions.js +2 -2
  75. package/lib/getSubmitButtonOptions.js.map +1 -1
  76. package/lib/getTemplate.d.ts +1 -1
  77. package/lib/getTemplate.js +9 -0
  78. package/lib/getTemplate.js.map +1 -1
  79. package/lib/getTestIds.d.ts +17 -0
  80. package/lib/getTestIds.js +34 -0
  81. package/lib/getTestIds.js.map +1 -0
  82. package/lib/getUiOptions.d.ts +1 -1
  83. package/lib/getUiOptions.js +2 -2
  84. package/lib/getUiOptions.js.map +1 -1
  85. package/lib/getWidget.d.ts +1 -1
  86. package/lib/getWidget.js +3 -3
  87. package/lib/getWidget.js.map +1 -1
  88. package/lib/guessType.d.ts +1 -1
  89. package/lib/guessType.js.map +1 -1
  90. package/lib/hasWidget.d.ts +1 -1
  91. package/lib/hasWidget.js +1 -1
  92. package/lib/hasWidget.js.map +1 -1
  93. package/lib/hashForSchema.d.ts +23 -1
  94. package/lib/hashForSchema.js +24 -6
  95. package/lib/hashForSchema.js.map +1 -1
  96. package/lib/idGenerators.d.ts +8 -1
  97. package/lib/idGenerators.js +11 -2
  98. package/lib/idGenerators.js.map +1 -1
  99. package/lib/index.d.ts +63 -60
  100. package/lib/index.js +63 -60
  101. package/lib/index.js.map +1 -1
  102. package/lib/isConstant.d.ts +1 -1
  103. package/lib/isConstant.js +1 -1
  104. package/lib/isCustomWidget.d.ts +1 -1
  105. package/lib/isCustomWidget.js +1 -1
  106. package/lib/isFixedItems.d.ts +1 -1
  107. package/lib/isFixedItems.js +1 -1
  108. package/lib/isObject.d.ts +2 -2
  109. package/lib/isObject.js +11 -4
  110. package/lib/isObject.js.map +1 -1
  111. package/lib/lookupFromFormContext.d.ts +11 -0
  112. package/lib/lookupFromFormContext.js +20 -0
  113. package/lib/lookupFromFormContext.js.map +1 -0
  114. package/lib/mergeDefaultsWithFormData.d.ts +8 -2
  115. package/lib/mergeDefaultsWithFormData.js +39 -10
  116. package/lib/mergeDefaultsWithFormData.js.map +1 -1
  117. package/lib/mergeObjects.d.ts +1 -1
  118. package/lib/mergeObjects.js +1 -1
  119. package/lib/mergeObjects.js.map +1 -1
  120. package/lib/mergeSchemas.d.ts +1 -1
  121. package/lib/mergeSchemas.js +4 -4
  122. package/lib/mergeSchemas.js.map +1 -1
  123. package/lib/optionsList.d.ts +9 -7
  124. package/lib/optionsList.js +30 -19
  125. package/lib/optionsList.js.map +1 -1
  126. package/lib/orderProperties.js.map +1 -1
  127. package/lib/pad.js.map +1 -1
  128. package/lib/parseDateString.d.ts +1 -1
  129. package/lib/parseDateString.js +1 -1
  130. package/lib/parseDateString.js.map +1 -1
  131. package/lib/parser/ParserValidator.d.ts +1 -1
  132. package/lib/parser/ParserValidator.js +6 -6
  133. package/lib/parser/ParserValidator.js.map +1 -1
  134. package/lib/parser/index.d.ts +2 -2
  135. package/lib/parser/index.js +1 -1
  136. package/lib/parser/schemaParser.d.ts +2 -2
  137. package/lib/parser/schemaParser.js +6 -6
  138. package/lib/parser/schemaParser.js.map +1 -1
  139. package/lib/rangeSpec.d.ts +2 -2
  140. package/lib/rangeSpec.js.map +1 -1
  141. package/lib/replaceStringParameters.js.map +1 -1
  142. package/lib/schema/findFieldInSchema.d.ts +19 -0
  143. package/lib/schema/findFieldInSchema.js +61 -0
  144. package/lib/schema/findFieldInSchema.js.map +1 -0
  145. package/lib/schema/findSelectedOptionInXxxOf.d.ts +16 -0
  146. package/lib/schema/findSelectedOptionInXxxOf.js +34 -0
  147. package/lib/schema/findSelectedOptionInXxxOf.js.map +1 -0
  148. package/lib/schema/getClosestMatchingOption.d.ts +5 -3
  149. package/lib/schema/getClosestMatchingOption.js +28 -20
  150. package/lib/schema/getClosestMatchingOption.js.map +1 -1
  151. package/lib/schema/getDefaultFormState.d.ts +60 -13
  152. package/lib/schema/getDefaultFormState.js +316 -167
  153. package/lib/schema/getDefaultFormState.js.map +1 -1
  154. package/lib/schema/getDisplayLabel.d.ts +3 -2
  155. package/lib/schema/getDisplayLabel.js +10 -9
  156. package/lib/schema/getDisplayLabel.js.map +1 -1
  157. package/lib/schema/getFirstMatchingOption.d.ts +1 -1
  158. package/lib/schema/getFirstMatchingOption.js +70 -2
  159. package/lib/schema/getFirstMatchingOption.js.map +1 -1
  160. package/lib/schema/getFromSchema.d.ts +14 -0
  161. package/lib/schema/getFromSchema.js +39 -0
  162. package/lib/schema/getFromSchema.js.map +1 -0
  163. package/lib/schema/index.d.ts +15 -14
  164. package/lib/schema/index.js +15 -14
  165. package/lib/schema/index.js.map +1 -1
  166. package/lib/schema/isFilesArray.d.ts +3 -2
  167. package/lib/schema/isFilesArray.js +5 -4
  168. package/lib/schema/isFilesArray.js.map +1 -1
  169. package/lib/schema/isMultiSelect.d.ts +3 -2
  170. package/lib/schema/isMultiSelect.js +4 -3
  171. package/lib/schema/isMultiSelect.js.map +1 -1
  172. package/lib/schema/isSelect.d.ts +3 -2
  173. package/lib/schema/isSelect.js +5 -4
  174. package/lib/schema/isSelect.js.map +1 -1
  175. package/lib/schema/retrieveSchema.d.ts +30 -12
  176. package/lib/schema/retrieveSchema.js +153 -70
  177. package/lib/schema/retrieveSchema.js.map +1 -1
  178. package/lib/schema/sanitizeDataForNewSchema.d.ts +3 -2
  179. package/lib/schema/sanitizeDataForNewSchema.js +12 -11
  180. package/lib/schema/sanitizeDataForNewSchema.js.map +1 -1
  181. package/lib/schema/toIdSchema.d.ts +3 -2
  182. package/lib/schema/toIdSchema.js +30 -27
  183. package/lib/schema/toIdSchema.js.map +1 -1
  184. package/lib/schema/toPathSchema.d.ts +3 -2
  185. package/lib/schema/toPathSchema.js +22 -20
  186. package/lib/schema/toPathSchema.js.map +1 -1
  187. package/lib/schemaRequiresTrueValue.d.ts +1 -1
  188. package/lib/schemaRequiresTrueValue.js.map +1 -1
  189. package/lib/shouldRender.js +1 -1
  190. package/lib/toConstant.d.ts +1 -1
  191. package/lib/toConstant.js +1 -1
  192. package/lib/toConstant.js.map +1 -1
  193. package/lib/toDateString.d.ts +1 -1
  194. package/lib/toErrorList.d.ts +1 -1
  195. package/lib/toErrorList.js +2 -2
  196. package/lib/toErrorList.js.map +1 -1
  197. package/lib/toErrorSchema.d.ts +1 -1
  198. package/lib/toErrorSchema.js +2 -2
  199. package/lib/toErrorSchema.js.map +1 -1
  200. package/lib/tsconfig.tsbuildinfo +1 -1
  201. package/lib/types.d.ts +172 -142
  202. package/lib/unwrapErrorHandler.d.ts +1 -1
  203. package/lib/unwrapErrorHandler.js +1 -1
  204. package/lib/unwrapErrorHandler.js.map +1 -1
  205. package/lib/utcToLocal.js +1 -1
  206. package/lib/utcToLocal.js.map +1 -1
  207. package/lib/validationDataMerge.d.ts +1 -1
  208. package/lib/validationDataMerge.js +3 -3
  209. package/lib/validationDataMerge.js.map +1 -1
  210. package/lib/withIdRefPrefix.d.ts +1 -1
  211. package/lib/withIdRefPrefix.js +2 -2
  212. package/lib/withIdRefPrefix.js.map +1 -1
  213. package/package.json +37 -26
  214. package/src/ErrorSchemaBuilder.ts +15 -8
  215. package/src/canExpand.ts +2 -2
  216. package/src/constIsAjvDataReference.ts +17 -0
  217. package/src/constants.ts +17 -3
  218. package/src/createSchemaUtils.ts +140 -50
  219. package/src/dataURItoBlob.ts +1 -1
  220. package/src/dateRangeOptions.ts +1 -1
  221. package/src/enumOptionsDeselectValue.ts +4 -5
  222. package/src/enumOptionsIndexForValue.ts +1 -1
  223. package/src/enumOptionsIsSelected.ts +4 -5
  224. package/src/enumOptionsSelectValue.ts +1 -1
  225. package/src/enumOptionsValueForIndex.ts +1 -1
  226. package/src/enums.ts +2 -0
  227. package/src/findSchemaDefinition.ts +55 -10
  228. package/src/getChangedFields.ts +40 -0
  229. package/src/getDateElementProps.ts +2 -2
  230. package/src/getDiscriminatorFieldFromSchema.ts +2 -1
  231. package/src/getInputProps.ts +6 -2
  232. package/src/getOptionMatchingSimpleDiscriminator.ts +2 -2
  233. package/src/getSchemaType.ts +3 -2
  234. package/src/getSubmitButtonOptions.ts +1 -1
  235. package/src/getTemplate.ts +12 -1
  236. package/src/getTestIds.ts +40 -0
  237. package/src/getUiOptions.ts +2 -2
  238. package/src/getWidget.tsx +2 -2
  239. package/src/hasWidget.ts +1 -1
  240. package/src/hashForSchema.ts +26 -6
  241. package/src/idGenerators.ts +10 -0
  242. package/src/index.ts +21 -2
  243. package/src/isCustomWidget.ts +1 -1
  244. package/src/isObject.ts +12 -5
  245. package/src/labelValue.ts +2 -2
  246. package/src/lookupFromFormContext.ts +26 -0
  247. package/src/mergeDefaultsWithFormData.ts +54 -9
  248. package/src/mergeObjects.ts +24 -21
  249. package/src/optionsList.ts +31 -22
  250. package/src/parser/ParserValidator.ts +5 -5
  251. package/src/parser/schemaParser.ts +6 -6
  252. package/src/schema/findFieldInSchema.ts +138 -0
  253. package/src/schema/findSelectedOptionInXxxOf.ts +53 -0
  254. package/src/schema/getClosestMatchingOption.ts +38 -11
  255. package/src/schema/getDefaultFormState.ts +461 -193
  256. package/src/schema/getDisplayLabel.ts +7 -4
  257. package/src/schema/getFirstMatchingOption.ts +79 -4
  258. package/src/schema/getFromSchema.ts +100 -0
  259. package/src/schema/index.ts +6 -4
  260. package/src/schema/isFilesArray.ts +18 -3
  261. package/src/schema/isMultiSelect.ts +10 -4
  262. package/src/schema/isSelect.ts +5 -3
  263. package/src/schema/retrieveSchema.ts +268 -78
  264. package/src/schema/sanitizeDataForNewSchema.ts +52 -11
  265. package/src/schema/toIdSchema.ts +69 -43
  266. package/src/schema/toPathSchema.ts +49 -16
  267. package/src/toErrorList.ts +2 -2
  268. package/src/types.ts +278 -184
  269. package/src/validationDataMerge.ts +1 -1
  270. package/src/withIdRefPrefix.ts +1 -1
  271. package/LICENSE.md +0 -201
  272. package/lib/schema/getMatchingOption.d.ts +0 -14
  273. package/lib/schema/getMatchingOption.js +0 -85
  274. package/lib/schema/getMatchingOption.js.map +0 -1
  275. package/lib/schema/mergeValidationData.d.ts +0 -14
  276. package/lib/schema/mergeValidationData.js +0 -28
  277. package/lib/schema/mergeValidationData.js.map +0 -1
  278. package/src/schema/getMatchingOption.ts +0 -103
  279. package/src/schema/mergeValidationData.ts +0 -38
@@ -1,8 +1,9 @@
1
1
  import deepEquals from './deepEquals';
2
2
  import {
3
- ErrorSchema,
3
+ Experimental_CustomMergeAllOf,
4
4
  Experimental_DefaultFormStateBehavior,
5
5
  FormContextType,
6
+ FoundFieldType,
6
7
  GlobalUISchemaOptions,
7
8
  IdSchema,
8
9
  PathSchema,
@@ -10,19 +11,19 @@ import {
10
11
  SchemaUtilsType,
11
12
  StrictRJSFSchema,
12
13
  UiSchema,
13
- ValidationData,
14
14
  ValidatorType,
15
15
  } from './types';
16
16
  import {
17
+ findFieldInSchema,
18
+ findSelectedOptionInXxxOf,
17
19
  getDefaultFormState,
18
20
  getDisplayLabel,
19
21
  getClosestMatchingOption,
20
22
  getFirstMatchingOption,
21
- getMatchingOption,
23
+ getFromSchema,
22
24
  isFilesArray,
23
25
  isMultiSelect,
24
26
  isSelect,
25
- mergeValidationData,
26
27
  retrieveSchema,
27
28
  sanitizeDataForNewSchema,
28
29
  toIdSchema,
@@ -30,9 +31,10 @@ import {
30
31
  } from './schema';
31
32
 
32
33
  /** 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.
34
+ * that one does not have to explicitly pass the `validator`, `rootSchema`, `experimental_defaultFormStateBehavior` or
35
+ * `experimental_customMergeAllOf` to each method. Since these generally do not change across a `Form`, this allows for
36
+ * providing a simplified set of APIs to the `@rjsf/core` components and the various themes as well. This class
37
+ * implements the `SchemaUtilsType` interface.
36
38
  */
37
39
  class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
38
40
  implements SchemaUtilsType<T, S, F>
@@ -40,21 +42,25 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
40
42
  rootSchema: S;
41
43
  validator: ValidatorType<T, S, F>;
42
44
  experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior;
45
+ experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>;
43
46
 
44
47
  /** Constructs the `SchemaUtils` instance with the given `validator` and `rootSchema` stored as instance variables
45
48
  *
46
49
  * @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs
47
50
  * @param rootSchema - The root schema that will be forwarded to all the APIs
48
51
  * @param experimental_defaultFormStateBehavior - Configuration flags to allow users to override default form state behavior
52
+ * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
49
53
  */
50
54
  constructor(
51
55
  validator: ValidatorType<T, S, F>,
52
56
  rootSchema: S,
53
- experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior
57
+ experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior,
58
+ experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,
54
59
  ) {
55
60
  this.rootSchema = rootSchema;
56
61
  this.validator = validator;
57
62
  this.experimental_defaultFormStateBehavior = experimental_defaultFormStateBehavior;
63
+ this.experimental_customMergeAllOf = experimental_customMergeAllOf;
58
64
  }
59
65
 
60
66
  /** Returns the `ValidatorType` in the `SchemaUtilsType`
@@ -72,12 +78,14 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
72
78
  * @param validator - An implementation of the `ValidatorType` interface that will be compared against the current one
73
79
  * @param rootSchema - The root schema that will be compared against the current one
74
80
  * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior
81
+ * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
75
82
  * @returns - True if the `SchemaUtilsType` differs from the given `validator` or `rootSchema`
76
83
  */
77
84
  doesSchemaUtilsDiffer(
78
85
  validator: ValidatorType<T, S, F>,
79
86
  rootSchema: S,
80
- experimental_defaultFormStateBehavior = {}
87
+ experimental_defaultFormStateBehavior = {},
88
+ experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,
81
89
  ): boolean {
82
90
  if (!validator || !rootSchema) {
83
91
  return false;
@@ -85,7 +93,51 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
85
93
  return (
86
94
  this.validator !== validator ||
87
95
  !deepEquals(this.rootSchema, rootSchema) ||
88
- !deepEquals(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior)
96
+ !deepEquals(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior) ||
97
+ this.experimental_customMergeAllOf !== experimental_customMergeAllOf
98
+ );
99
+ }
100
+
101
+ /** Finds the field specified by the `path` within the root or recursed `schema`. If there is no field for the specified
102
+ * `path`, then the default `{ field: undefined, isRequired: undefined }` is returned. It determines whether a leaf
103
+ * field is in the `required` list for its parent and if so, it is marked as required on return.
104
+ *
105
+ * @param schema - The current node within the JSON schema
106
+ * @param path - The remaining keys in the path to the desired field
107
+ * @param [formData] - The form data that is used to determine which oneOf option
108
+ * @returns - An object that contains the field and its required state. If no field can be found then
109
+ * `{ field: undefined, isRequired: undefined }` is returned.
110
+ */
111
+ findFieldInSchema(schema: S, path: string | string[], formData?: T): FoundFieldType<S> {
112
+ return findFieldInSchema(
113
+ this.validator,
114
+ this.rootSchema,
115
+ schema,
116
+ path,
117
+ formData,
118
+ this.experimental_customMergeAllOf,
119
+ );
120
+ }
121
+
122
+ /** Finds the oneOf option inside the `schema['any/oneOf']` list which has the `properties[selectorField].default` that
123
+ * matches the `formData[selectorField]` value. For the purposes of this function, `selectorField` is either
124
+ * `schema.discriminator.propertyName` or `fallbackField`.
125
+ *
126
+ * @param schema - The schema element in which to search for the selected oneOf option
127
+ * @param fallbackField - The field to use as a backup selector field if the schema does not have a required field
128
+ * @param xxx - Either `oneOf` or `anyOf`, defines which value is being sought
129
+ * @param [formData={}] - The form data that is used to determine which oneOf option
130
+ * @returns - The anyOf/oneOf option that matches the selector field in the schema or undefined if nothing is selected
131
+ */
132
+ findSelectedOptionInXxxOf(schema: S, fallbackField: string, xxx: 'anyOf' | `oneOf`, formData: T): S | undefined {
133
+ return findSelectedOptionInXxxOf(
134
+ this.validator,
135
+ this.rootSchema,
136
+ schema,
137
+ fallbackField,
138
+ xxx,
139
+ formData,
140
+ this.experimental_customMergeAllOf,
89
141
  );
90
142
  }
91
143
 
@@ -102,7 +154,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
102
154
  getDefaultFormState(
103
155
  schema: S,
104
156
  formData?: T,
105
- includeUndefinedValues: boolean | 'excludeObjectChildren' = false
157
+ includeUndefinedValues: boolean | 'excludeObjectChildren' = false,
106
158
  ): T | T[] | undefined {
107
159
  return getDefaultFormState<T, S, F>(
108
160
  this.validator,
@@ -110,7 +162,8 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
110
162
  formData,
111
163
  this.rootSchema,
112
164
  includeUndefinedValues,
113
- this.experimental_defaultFormStateBehavior
165
+ this.experimental_defaultFormStateBehavior,
166
+ this.experimental_customMergeAllOf,
114
167
  );
115
168
  }
116
169
 
@@ -123,7 +176,14 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
123
176
  * @returns - True if the label should be displayed or false if it should not
124
177
  */
125
178
  getDisplayLabel(schema: S, uiSchema?: UiSchema<T, S, F>, globalOptions?: GlobalUISchemaOptions) {
126
- return getDisplayLabel<T, S, F>(this.validator, schema, uiSchema, this.rootSchema, globalOptions);
179
+ return getDisplayLabel<T, S, F>(
180
+ this.validator,
181
+ schema,
182
+ uiSchema,
183
+ this.rootSchema,
184
+ globalOptions,
185
+ this.experimental_customMergeAllOf,
186
+ );
127
187
  }
128
188
 
129
189
  /** Determines which of the given `options` provided most closely matches the `formData`.
@@ -143,7 +203,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
143
203
  formData: T | undefined,
144
204
  options: S[],
145
205
  selectedOption?: number,
146
- discriminatorField?: string
206
+ discriminatorField?: string,
147
207
  ): number {
148
208
  return getClosestMatchingOption<T, S, F>(
149
209
  this.validator,
@@ -151,7 +211,8 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
151
211
  formData,
152
212
  options,
153
213
  selectedOption,
154
- discriminatorField
214
+ discriminatorField,
215
+ this.experimental_customMergeAllOf,
155
216
  );
156
217
  }
157
218
 
@@ -168,18 +229,26 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
168
229
  return getFirstMatchingOption<T, S, F>(this.validator, formData, options, this.rootSchema, discriminatorField);
169
230
  }
170
231
 
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.
232
+ /** Helper that acts like lodash's `get` but additionally retrieves `$ref`s as needed to get the path for schemas
233
+ * containing potentially nested `$ref`s.
173
234
  *
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
235
+ * @param schema - The current node within the JSON schema recursion
236
+ * @param path - The remaining keys in the path to the desired property
237
+ * @param defaultValue - The value to return if a value is not found for the `pathList` path
238
+ * @returns - The internal schema from the `schema` for the given `path` or the `defaultValue` if not found
180
239
  */
181
- getMatchingOption(formData: T | undefined, options: S[], discriminatorField?: string) {
182
- return getMatchingOption<T, S, F>(this.validator, formData, options, this.rootSchema, discriminatorField);
240
+ getFromSchema(schema: S, path: string | string[], defaultValue: T): T;
241
+ getFromSchema(schema: S, path: string | string[], defaultValue: S): S;
242
+ getFromSchema(schema: S, path: string | string[], defaultValue: T | S): T | S {
243
+ return getFromSchema<T, S, F>(
244
+ this.validator,
245
+ this.rootSchema,
246
+ schema,
247
+ path,
248
+ // @ts-expect-error TS2769: No overload matches this call
249
+ defaultValue,
250
+ this.experimental_customMergeAllOf,
251
+ );
183
252
  }
184
253
 
185
254
  /** Checks to see if the `schema` and `uiSchema` combination represents an array of files
@@ -189,7 +258,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
189
258
  * @returns - True if schema/uiSchema contains an array of files, otherwise false
190
259
  */
191
260
  isFilesArray(schema: S, uiSchema?: UiSchema<T, S, F>) {
192
- return isFilesArray<T, S, F>(this.validator, schema, uiSchema, this.rootSchema);
261
+ return isFilesArray<T, S, F>(this.validator, schema, uiSchema, this.rootSchema, this.experimental_customMergeAllOf);
193
262
  }
194
263
 
195
264
  /** Checks to see if the `schema` combination represents a multi-select
@@ -198,7 +267,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
198
267
  * @returns - True if schema contains a multi-select, otherwise false
199
268
  */
200
269
  isMultiSelect(schema: S) {
201
- return isMultiSelect<T, S, F>(this.validator, schema, this.rootSchema);
270
+ return isMultiSelect<T, S, F>(this.validator, schema, this.rootSchema, this.experimental_customMergeAllOf);
202
271
  }
203
272
 
204
273
  /** Checks to see if the `schema` combination represents a select
@@ -207,22 +276,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
207
276
  * @returns - True if schema contains a select, otherwise false
208
277
  */
209
278
  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);
279
+ return isSelect<T, S, F>(this.validator, schema, this.rootSchema, this.experimental_customMergeAllOf);
226
280
  }
227
281
 
228
282
  /** Retrieves an expanded schema that has had all of its conditions, additional properties, references and
@@ -234,7 +288,13 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
234
288
  * @returns - The schema having its conditions, additional properties, references and dependencies resolved
235
289
  */
236
290
  retrieveSchema(schema: S, rawFormData?: T) {
237
- return retrieveSchema<T, S, F>(this.validator, schema, this.rootSchema, rawFormData);
291
+ return retrieveSchema<T, S, F>(
292
+ this.validator,
293
+ schema,
294
+ this.rootSchema,
295
+ rawFormData,
296
+ this.experimental_customMergeAllOf,
297
+ );
238
298
  }
239
299
 
240
300
  /** Sanitize the `data` associated with the `oldSchema` so it is considered appropriate for the `newSchema`. If the
@@ -249,7 +309,14 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
249
309
  * to `undefined`. Will return `undefined` if the new schema is not an object containing properties.
250
310
  */
251
311
  sanitizeDataForNewSchema(newSchema?: S, oldSchema?: S, data?: any): T {
252
- return sanitizeDataForNewSchema(this.validator, this.rootSchema, newSchema, oldSchema, data);
312
+ return sanitizeDataForNewSchema(
313
+ this.validator,
314
+ this.rootSchema,
315
+ newSchema,
316
+ oldSchema,
317
+ data,
318
+ this.experimental_customMergeAllOf,
319
+ );
253
320
  }
254
321
 
255
322
  /** Generates an `IdSchema` object for the `schema`, recursively
@@ -262,7 +329,16 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
262
329
  * @returns - The `IdSchema` object for the `schema`
263
330
  */
264
331
  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);
332
+ return toIdSchema<T, S, F>(
333
+ this.validator,
334
+ schema,
335
+ id,
336
+ this.rootSchema,
337
+ formData,
338
+ idPrefix,
339
+ idSeparator,
340
+ this.experimental_customMergeAllOf,
341
+ );
266
342
  }
267
343
 
268
344
  /** Generates an `PathSchema` object for the `schema`, recursively
@@ -273,7 +349,14 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
273
349
  * @returns - The `PathSchema` object for the `schema`
274
350
  */
275
351
  toPathSchema(schema: S, name?: string, formData?: T): PathSchema<T> {
276
- return toPathSchema<T, S, F>(this.validator, schema, name, this.rootSchema, formData);
352
+ return toPathSchema<T, S, F>(
353
+ this.validator,
354
+ schema,
355
+ name,
356
+ this.rootSchema,
357
+ formData,
358
+ this.experimental_customMergeAllOf,
359
+ );
277
360
  }
278
361
  }
279
362
 
@@ -283,16 +366,23 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
283
366
  * @param validator - an implementation of the `ValidatorType` interface that will be forwarded to all the APIs
284
367
  * @param rootSchema - The root schema that will be forwarded to all the APIs
285
368
  * @param [experimental_defaultFormStateBehavior] Optional configuration object, if provided, allows users to override default form state behavior
369
+ * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
286
370
  * @returns - An implementation of a `SchemaUtilsType` interface
287
371
  */
288
372
  export default function createSchemaUtils<
289
373
  T = any,
290
374
  S extends StrictRJSFSchema = RJSFSchema,
291
- F extends FormContextType = any
375
+ F extends FormContextType = any,
292
376
  >(
293
377
  validator: ValidatorType<T, S, F>,
294
378
  rootSchema: S,
295
- experimental_defaultFormStateBehavior = {}
379
+ experimental_defaultFormStateBehavior = {},
380
+ experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,
296
381
  ): SchemaUtilsType<T, S, F> {
297
- return new SchemaUtils<T, S, F>(validator, rootSchema, experimental_defaultFormStateBehavior);
382
+ return new SchemaUtils<T, S, F>(
383
+ validator,
384
+ rootSchema,
385
+ experimental_defaultFormStateBehavior,
386
+ experimental_customMergeAllOf,
387
+ );
298
388
  }
@@ -25,7 +25,7 @@ export default function dataURItoBlob(dataURILike: string) {
25
25
  const name = decodeURI(
26
26
  // parse the parameters into key-value pairs, find a key, and extract a value
27
27
  // if no key is found, then the name is unknown
28
- mediaparams.map((param) => param.split('=')).find(([key]) => key === 'name')?.[1] || 'unknown'
28
+ mediaparams.map((param) => param.split('=')).find(([key]) => key === 'name')?.[1] || 'unknown',
29
29
  );
30
30
 
31
31
  // Built the Uint8Array Blob parameter from the base64 string.
@@ -12,7 +12,7 @@ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
12
12
  */
13
13
  export default function dateRangeOptions<S extends StrictRJSFSchema = RJSFSchema>(
14
14
  start: number,
15
- stop: number
15
+ stop: number,
16
16
  ): EnumOptionsType<S>[] {
17
17
  if (start <= 0 && stop <= 0) {
18
18
  start = new Date().getFullYear() + start;
@@ -1,7 +1,6 @@
1
- import isEqual from 'lodash/isEqual';
2
-
3
1
  import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
4
2
  import enumOptionsValueForIndex from './enumOptionsValueForIndex';
3
+ import deepEquals from './deepEquals';
5
4
 
6
5
  /** Removes the enum option value at the `valueIndex` from the currently `selected` (list of) value(s). If `selected` is
7
6
  * a list, then that list is updated to remove the enum option value with the `valueIndex` in `allEnumOptions`. If it is
@@ -18,11 +17,11 @@ import enumOptionsValueForIndex from './enumOptionsValueForIndex';
18
17
  export default function enumOptionsDeselectValue<S extends StrictRJSFSchema = RJSFSchema>(
19
18
  valueIndex: string | number,
20
19
  selected?: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][],
21
- allEnumOptions: EnumOptionsType<S>[] = []
20
+ allEnumOptions: EnumOptionsType<S>[] = [],
22
21
  ): EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][] | undefined {
23
22
  const value = enumOptionsValueForIndex<S>(valueIndex, allEnumOptions);
24
23
  if (Array.isArray(selected)) {
25
- return selected.filter((v) => !isEqual(v, value));
24
+ return selected.filter((v) => !deepEquals(v, value));
26
25
  }
27
- return isEqual(value, selected) ? undefined : selected;
26
+ return deepEquals(value, selected) ? undefined : selected;
28
27
  }
@@ -15,7 +15,7 @@ import enumOptionsIsSelected from './enumOptionsIsSelected';
15
15
  export default function enumOptionsIndexForValue<S extends StrictRJSFSchema = RJSFSchema>(
16
16
  value: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][],
17
17
  allEnumOptions: EnumOptionsType<S>[] = [],
18
- multiple = false
18
+ multiple = false,
19
19
  ): string | string[] | undefined {
20
20
  const selectedIndexes: string[] = allEnumOptions
21
21
  .map((opt, index) => (enumOptionsIsSelected(opt.value, value) ? String(index) : undefined))
@@ -1,6 +1,5 @@
1
- import isEqual from 'lodash/isEqual';
2
-
3
1
  import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
2
+ import deepEquals from './deepEquals';
4
3
 
5
4
  /** Determines whether the given `value` is (one of) the `selected` value(s).
6
5
  *
@@ -10,10 +9,10 @@ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
10
9
  */
11
10
  export default function enumOptionsIsSelected<S extends StrictRJSFSchema = RJSFSchema>(
12
11
  value: EnumOptionsType<S>['value'],
13
- selected: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][]
12
+ selected: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][],
14
13
  ) {
15
14
  if (Array.isArray(selected)) {
16
- return selected.some((sel) => isEqual(sel, value));
15
+ return selected.some((sel) => deepEquals(sel, value));
17
16
  }
18
- return isEqual(selected, value);
17
+ return deepEquals(selected, value);
19
18
  }
@@ -13,7 +13,7 @@ import isNil from 'lodash/isNil';
13
13
  export default function enumOptionsSelectValue<S extends StrictRJSFSchema = RJSFSchema>(
14
14
  valueIndex: string | number,
15
15
  selected: EnumOptionsType<S>['value'][],
16
- allEnumOptions: EnumOptionsType<S>[] = []
16
+ allEnumOptions: EnumOptionsType<S>[] = [],
17
17
  ) {
18
18
  const value = enumOptionsValueForIndex<S>(valueIndex, allEnumOptions);
19
19
  if (!isNil(value)) {
@@ -14,7 +14,7 @@ import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
14
14
  export default function enumOptionsValueForIndex<S extends StrictRJSFSchema = RJSFSchema>(
15
15
  valueIndex: string | number | Array<string | number>,
16
16
  allEnumOptions: EnumOptionsType<S>[] = [],
17
- emptyValue?: EnumOptionsType<S>['value']
17
+ emptyValue?: EnumOptionsType<S>['value'],
18
18
  ): EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][] | undefined {
19
19
  if (Array.isArray(valueIndex)) {
20
20
  return (
package/src/enums.ts CHANGED
@@ -9,6 +9,8 @@ export enum TranslatableString {
9
9
  ArrayItemTitle = 'Item',
10
10
  /** Missing items reason, used by ArrayField */
11
11
  MissingItems = 'Missing items definition',
12
+ /** Empty array message, used by ArrayField */
13
+ EmptyArray = 'No items yet. Use the button below to add some.',
12
14
  /** Yes label, used by BooleanField */
13
15
  YesLabel = 'Yes',
14
16
  /** No label, used by BooleanField */
@@ -1,8 +1,34 @@
1
1
  import jsonpointer from 'jsonpointer';
2
2
  import omit from 'lodash/omit';
3
3
 
4
- import { REF_KEY } from './constants';
4
+ import { ID_KEY, JSON_SCHEMA_DRAFT_2020_12, REF_KEY, SCHEMA_KEY } from './constants';
5
5
  import { GenericObjectType, RJSFSchema, StrictRJSFSchema } from './types';
6
+ import isObject from 'lodash/isObject';
7
+ import isEmpty from 'lodash/isEmpty';
8
+ import UriResolver from 'fast-uri';
9
+ import get from 'lodash/get';
10
+
11
+ /** Looks for the `$id` pointed by `ref` in the schema definitions embedded in
12
+ * a JSON Schema bundle
13
+ *
14
+ * @param schema - The schema wherein `ref` should be searched
15
+ * @param ref - The `$id` of the reference to search for
16
+ * @returns - The schema matching the reference, or `undefined` if no match is found
17
+ */
18
+ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(schema: S, ref: string): S | undefined {
19
+ if (ID_KEY in schema && UriResolver.equal(schema[ID_KEY] as string, ref)) {
20
+ return schema;
21
+ }
22
+ for (const subSchema of Object.values(schema)) {
23
+ if (isObject(subSchema)) {
24
+ const result = findEmbeddedSchemaRecursive<S>(subSchema as S, ref);
25
+ if (result !== undefined) {
26
+ return result as S;
27
+ }
28
+ }
29
+ }
30
+ return undefined;
31
+ }
6
32
 
7
33
  /** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first
8
34
  * location, the `object` minus the `key: value` and in the second location the `value`.
@@ -26,23 +52,40 @@ export function splitKeyElementFromObject(key: string, object: GenericObjectType
26
52
  * @param $ref - The ref string for which the schema definition is desired
27
53
  * @param [rootSchema={}] - The root schema in which to search for the definition
28
54
  * @param recurseList - List of $refs already resolved to prevent recursion
55
+ * @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references
29
56
  * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
30
57
  * @throws - Error indicating that no schema for that reference could be resolved
31
58
  */
32
59
  export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFSchema>(
33
60
  $ref?: string,
34
61
  rootSchema: S = {} as S,
35
- recurseList: string[] = []
62
+ recurseList: string[] = [],
63
+ baseURI: string | undefined = get(rootSchema, [ID_KEY]),
36
64
  ): S {
37
65
  const ref = $ref || '';
38
- let decodedRef;
66
+ let current: S | undefined = undefined;
39
67
  if (ref.startsWith('#')) {
40
68
  // Decode URI fragment representation.
41
- decodedRef = decodeURIComponent(ref.substring(1));
42
- } else {
43
- throw new Error(`Could not find a definition for ${$ref}.`);
69
+ const decodedRef = decodeURIComponent(ref.substring(1));
70
+ if (baseURI === undefined || (ID_KEY in rootSchema && rootSchema[ID_KEY] === baseURI)) {
71
+ current = jsonpointer.get(rootSchema, decodedRef);
72
+ } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {
73
+ current = findEmbeddedSchemaRecursive<S>(rootSchema, baseURI.replace(/\/$/, ''));
74
+ if (current !== undefined) {
75
+ current = jsonpointer.get(current, decodedRef);
76
+ }
77
+ }
78
+ } else if (rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {
79
+ const resolvedRef = baseURI ? UriResolver.resolve(baseURI, ref) : ref;
80
+ const [refId, ...refAnchor] = resolvedRef.replace(/#\/?$/, '').split('#');
81
+ current = findEmbeddedSchemaRecursive<S>(rootSchema, refId.replace(/\/$/, ''));
82
+ if (current !== undefined) {
83
+ baseURI = current[ID_KEY];
84
+ if (!isEmpty(refAnchor)) {
85
+ current = jsonpointer.get(current, decodeURIComponent(refAnchor.join('#')));
86
+ }
87
+ }
44
88
  }
45
- const current: S = jsonpointer.get(rootSchema, decodedRef);
46
89
  if (current === undefined) {
47
90
  throw new Error(`Could not find a definition for ${$ref}.`);
48
91
  }
@@ -58,7 +101,7 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
58
101
  throw new Error(`Definition for ${firstRef} contains a circular reference through ${circularPath}`);
59
102
  }
60
103
  const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
61
- const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref]);
104
+ const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref], baseURI);
62
105
  if (Object.keys(remaining).length > 0) {
63
106
  return { ...remaining, ...subSchema };
64
107
  }
@@ -74,13 +117,15 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
74
117
  *
75
118
  * @param $ref - The ref string for which the schema definition is desired
76
119
  * @param [rootSchema={}] - The root schema in which to search for the definition
120
+ * @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references
77
121
  * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
78
122
  * @throws - Error indicating that no schema for that reference could be resolved
79
123
  */
80
124
  export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
81
125
  $ref?: string,
82
- rootSchema: S = {} as S
126
+ rootSchema: S = {} as S,
127
+ baseURI: string | undefined = get(rootSchema, [ID_KEY]),
83
128
  ): S {
84
129
  const recurseList: string[] = [];
85
- return findSchemaDefinitionRecursive($ref, rootSchema, recurseList);
130
+ return findSchemaDefinitionRecursive($ref, rootSchema, recurseList, baseURI);
86
131
  }
@@ -0,0 +1,40 @@
1
+ import keys from 'lodash/keys';
2
+ import pickBy from 'lodash/pickBy';
3
+ import isPlainObject from 'lodash/isPlainObject';
4
+ import get from 'lodash/get';
5
+ import difference from 'lodash/difference';
6
+ import deepEquals from './deepEquals';
7
+
8
+ /**
9
+ * Compares two objects and returns the names of the fields that have changed.
10
+ * This function iterates over each field of object `a`, using `_.isEqual` to compare the field value
11
+ * with the corresponding field value in object `b`. If the values are different, the field name will
12
+ * be included in the returned array.
13
+ *
14
+ * @param a - The first object, representing the original data to compare.
15
+ * @param b - The second object, representing the updated data to compare.
16
+ * @returns - An array of field names that have changed.
17
+ *
18
+ * @example
19
+ * const a = { name: 'John', age: 30 };
20
+ * const b = { name: 'John', age: 31 };
21
+ * const changedFields = getChangedFields(a, b);
22
+ * console.log(changedFields); // Output: ['age']
23
+ */
24
+ export default function getChangedFields(a: unknown, b: unknown): string[] {
25
+ const aIsPlainObject = isPlainObject(a);
26
+ const bIsPlainObject = isPlainObject(b);
27
+ // If strictly equal or neither of them is a plainObject returns an empty array
28
+ if (a === b || (!aIsPlainObject && !bIsPlainObject)) {
29
+ return [];
30
+ }
31
+ if (aIsPlainObject && !bIsPlainObject) {
32
+ return keys(a);
33
+ } else if (!aIsPlainObject && bIsPlainObject) {
34
+ return keys(b);
35
+ } else {
36
+ const unequalFields = keys(pickBy(a as object, (value, key) => !deepEquals(value, get(b, key))));
37
+ const diffFields = difference(keys(b), keys(a));
38
+ return [...unequalFields, ...diffFields];
39
+ }
40
+ }
@@ -23,7 +23,7 @@ export default function getDateElementProps(
23
23
  date: DateObject,
24
24
  time: boolean,
25
25
  yearRange: [number, number] = [1900, new Date().getFullYear() + 2],
26
- format: DateElementFormat = 'YMD'
26
+ format: DateElementFormat = 'YMD',
27
27
  ) {
28
28
  const { day, month, year, hour, minute, second } = date;
29
29
 
@@ -48,7 +48,7 @@ export default function getDateElementProps(
48
48
  dateElementProp.push(
49
49
  { type: 'hour', range: [0, 23], value: hour },
50
50
  { type: 'minute', range: [0, 59], value: minute },
51
- { type: 'second', range: [0, 59], value: second }
51
+ { type: 'second', range: [0, 59], value: second },
52
52
  );
53
53
  }
54
54
 
@@ -2,6 +2,7 @@ import get from 'lodash/get';
2
2
  import isString from 'lodash/isString';
3
3
 
4
4
  import { RJSFSchema, StrictRJSFSchema } from './types';
5
+ import { DISCRIMINATOR_PATH } from './constants';
5
6
 
6
7
  /** Returns the `discriminator.propertyName` when defined in the `schema` if it is a string. A warning is generated when
7
8
  * it is not a string. Returns `undefined` when a valid discriminator is not present.
@@ -11,7 +12,7 @@ import { RJSFSchema, StrictRJSFSchema } from './types';
11
12
  */
12
13
  export default function getDiscriminatorFieldFromSchema<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
13
14
  let discriminator: string | undefined;
14
- const maybeString = get(schema, 'discriminator.propertyName', undefined);
15
+ const maybeString = get(schema, DISCRIMINATOR_PATH);
15
16
  if (isString(maybeString)) {
16
17
  discriminator = maybeString;
17
18
  } else if (maybeString !== undefined) {