@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,55 @@
1
+ import rangeSpec from './rangeSpec';
2
+ import { FormContextType, InputPropsType, RJSFSchema, StrictRJSFSchema, UIOptionsType } from './types';
3
+
4
+ /** Using the `schema`, `defaultType` and `options`, extract out the props for the <input> element that make sense.
5
+ *
6
+ * @param schema - The schema for the field provided by the widget
7
+ * @param [defaultType] - The default type, if any, for the field provided by the widget
8
+ * @param [options={}] - The UI Options for the field provided by the widget
9
+ * @param [autoDefaultStepAny=true] - Determines whether to auto-default step=any when the type is number and no step
10
+ * @returns - The extracted `InputPropsType` object
11
+ */
12
+ export default function getInputProps<
13
+ T = any,
14
+ S extends StrictRJSFSchema = RJSFSchema,
15
+ F extends FormContextType = any
16
+ >(
17
+ schema: RJSFSchema,
18
+ defaultType?: string,
19
+ options: UIOptionsType<T, S, F> = {},
20
+ autoDefaultStepAny = true
21
+ ): InputPropsType {
22
+ const inputProps: InputPropsType = {
23
+ type: defaultType || 'text',
24
+ ...rangeSpec(schema),
25
+ };
26
+
27
+ // If options.inputType is set use that as the input type
28
+ if (options.inputType) {
29
+ inputProps.type = options.inputType;
30
+ } else if (!defaultType) {
31
+ // If the schema is of type number or integer, set the input type to number
32
+ if (schema.type === 'number') {
33
+ inputProps.type = 'number';
34
+ // Only add step if one isn't already defined and we are auto-defaulting the "any" step
35
+ if (autoDefaultStepAny && inputProps.step === undefined) {
36
+ // Setting step to 'any' fixes a bug in Safari where decimals are not
37
+ // allowed in number inputs
38
+ inputProps.step = 'any';
39
+ }
40
+ } else if (schema.type === 'integer') {
41
+ inputProps.type = 'number';
42
+ // Only add step if one isn't already defined
43
+ if (inputProps.step === undefined) {
44
+ // Since this is integer, you always want to step up or down in multiples of 1
45
+ inputProps.step = 1;
46
+ }
47
+ }
48
+ }
49
+
50
+ if (options.autocomplete) {
51
+ inputProps.autoComplete = options.autocomplete;
52
+ }
53
+
54
+ return inputProps;
55
+ }
@@ -0,0 +1,37 @@
1
+ import guessType from './guessType';
2
+ import { RJSFSchema, StrictRJSFSchema } from './types';
3
+
4
+ /** Gets the type of a given `schema`. If the type is not explicitly defined, then an attempt is made to infer it from
5
+ * other elements of the schema as follows:
6
+ * - schema.const: Returns the `guessType()` of that value
7
+ * - schema.enum: Returns `string`
8
+ * - schema.properties: Returns `object`
9
+ * - schema.additionalProperties: Returns `object`
10
+ * - type is an array with a length of 2 and one type is 'null': Returns the other type
11
+ *
12
+ * @param schema - The schema for which to get the type
13
+ * @returns - The type of the schema
14
+ */
15
+ export default function getSchemaType<S extends StrictRJSFSchema = RJSFSchema>(
16
+ schema: S
17
+ ): string | string[] | undefined {
18
+ let { type } = schema;
19
+
20
+ if (!type && schema.const) {
21
+ return guessType(schema.const);
22
+ }
23
+
24
+ if (!type && schema.enum) {
25
+ return 'string';
26
+ }
27
+
28
+ if (!type && (schema.properties || schema.additionalProperties)) {
29
+ return 'object';
30
+ }
31
+
32
+ if (Array.isArray(type) && type.length === 2 && type.includes('null')) {
33
+ type = type.find((type) => type !== 'null');
34
+ }
35
+
36
+ return type;
37
+ }
@@ -0,0 +1,32 @@
1
+ import { SUBMIT_BTN_OPTIONS_KEY } from './constants';
2
+ import getUiOptions from './getUiOptions';
3
+ import { FormContextType, RJSFSchema, StrictRJSFSchema, UiSchema, UISchemaSubmitButtonOptions } from './types';
4
+
5
+ /** The default submit button options, exported for testing purposes
6
+ */
7
+ export const DEFAULT_OPTIONS: UISchemaSubmitButtonOptions = {
8
+ props: {
9
+ disabled: false,
10
+ },
11
+ submitText: 'Submit',
12
+ norender: false,
13
+ };
14
+
15
+ /** Extracts any `ui:submitButtonOptions` from the `uiSchema` and merges them onto the `DEFAULT_OPTIONS`
16
+ *
17
+ * @param [uiSchema={}] - the UI Schema from which to extract submit button props
18
+ * @returns - The merging of the `DEFAULT_OPTIONS` with any custom ones
19
+ */
20
+ export default function getSubmitButtonOptions<
21
+ T = any,
22
+ S extends StrictRJSFSchema = RJSFSchema,
23
+ F extends FormContextType = any
24
+ >(uiSchema: UiSchema<T, S, F> = {}): UISchemaSubmitButtonOptions {
25
+ const uiOptions = getUiOptions<T, S, F>(uiSchema);
26
+ if (uiOptions && uiOptions[SUBMIT_BTN_OPTIONS_KEY]) {
27
+ const options = uiOptions[SUBMIT_BTN_OPTIONS_KEY] as UISchemaSubmitButtonOptions;
28
+ return { ...DEFAULT_OPTIONS, ...options };
29
+ }
30
+
31
+ return DEFAULT_OPTIONS;
32
+ }
@@ -0,0 +1,26 @@
1
+ import { FormContextType, TemplatesType, Registry, UIOptionsType, StrictRJSFSchema, RJSFSchema } from './types';
2
+
3
+ /** Returns the template with the given `name` from either the `uiSchema` if it is defined or from the `registry`
4
+ * otherwise. NOTE, since `ButtonTemplates` are not overridden in `uiSchema` only those in the `registry` are returned.
5
+ *
6
+ * @param name - The name of the template to fetch, restricted to the keys of `TemplatesType`
7
+ * @param registry - The `Registry` from which to read the template
8
+ * @param [uiOptions={}] - The `UIOptionsType` from which to read an alternate template
9
+ * @returns - The template from either the `uiSchema` or `registry` for the `name`
10
+ */
11
+ export default function getTemplate<
12
+ Name extends keyof TemplatesType<T, S, F>,
13
+ T = any,
14
+ S extends StrictRJSFSchema = RJSFSchema,
15
+ F extends FormContextType = any
16
+ >(name: Name, registry: Registry<T, S, F>, uiOptions: UIOptionsType<T, S, F> = {}): TemplatesType<T, S, F>[Name] {
17
+ const { templates } = registry;
18
+ if (name === 'ButtonTemplates') {
19
+ return templates[name];
20
+ }
21
+ return (
22
+ // Evaluating uiOptions[name] results in TS2590: Expression produces a union type that is too complex to represent
23
+ // To avoid that, we cast uiOptions to `any` before accessing the name field
24
+ ((uiOptions as any)[name] as TemplatesType<T, S, F>[Name]) || templates[name]
25
+ );
26
+ }
@@ -0,0 +1,32 @@
1
+ import { UI_OPTIONS_KEY, UI_WIDGET_KEY } from './constants';
2
+ import isObject from './isObject';
3
+ import { FormContextType, GlobalUISchemaOptions, RJSFSchema, StrictRJSFSchema, UIOptionsType, UiSchema } from './types';
4
+
5
+ /** Get all passed options from ui:options, and ui:<optionName>, returning them in an object with the `ui:`
6
+ * stripped off. Any `globalOptions` will always be returned, unless they are overridden by options in the `uiSchema`.
7
+ *
8
+ * @param [uiSchema={}] - The UI Schema from which to get any `ui:xxx` options
9
+ * @param [globalOptions={}] - The optional Global UI Schema from which to get any fallback `xxx` options
10
+ * @returns - An object containing all the `ui:xxx` options with the `ui:` stripped off along with all `globalOptions`
11
+ */
12
+ export default function getUiOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
13
+ uiSchema: UiSchema<T, S, F> = {},
14
+ globalOptions: GlobalUISchemaOptions = {}
15
+ ): UIOptionsType<T, S, F> {
16
+ return Object.keys(uiSchema)
17
+ .filter((key) => key.indexOf('ui:') === 0)
18
+ .reduce(
19
+ (options, key) => {
20
+ const value = uiSchema[key];
21
+ if (key === UI_WIDGET_KEY && isObject(value)) {
22
+ console.error('Setting options via ui:widget object is no longer supported, use ui:options instead');
23
+ return options;
24
+ }
25
+ if (key === UI_OPTIONS_KEY && isObject(value)) {
26
+ return { ...options, ...value };
27
+ }
28
+ return { ...options, [key.substring(3)]: value };
29
+ },
30
+ { ...globalOptions }
31
+ );
32
+ }
@@ -0,0 +1,133 @@
1
+ import { createElement } from 'react';
2
+ import ReactIs from 'react-is';
3
+ import get from 'lodash/get';
4
+ import set from 'lodash/set';
5
+
6
+ import { FormContextType, RJSFSchema, Widget, RegistryWidgetsType, StrictRJSFSchema } from './types';
7
+ import getSchemaType from './getSchemaType';
8
+
9
+ /** The map of schema types to widget type to widget name
10
+ */
11
+ const widgetMap: { [k: string]: { [j: string]: string } } = {
12
+ boolean: {
13
+ checkbox: 'CheckboxWidget',
14
+ radio: 'RadioWidget',
15
+ select: 'SelectWidget',
16
+ hidden: 'HiddenWidget',
17
+ },
18
+ string: {
19
+ text: 'TextWidget',
20
+ password: 'PasswordWidget',
21
+ email: 'EmailWidget',
22
+ hostname: 'TextWidget',
23
+ ipv4: 'TextWidget',
24
+ ipv6: 'TextWidget',
25
+ uri: 'URLWidget',
26
+ 'data-url': 'FileWidget',
27
+ radio: 'RadioWidget',
28
+ select: 'SelectWidget',
29
+ textarea: 'TextareaWidget',
30
+ hidden: 'HiddenWidget',
31
+ date: 'DateWidget',
32
+ datetime: 'DateTimeWidget',
33
+ 'date-time': 'DateTimeWidget',
34
+ 'alt-date': 'AltDateWidget',
35
+ 'alt-datetime': 'AltDateTimeWidget',
36
+ time: 'TimeWidget',
37
+ color: 'ColorWidget',
38
+ file: 'FileWidget',
39
+ },
40
+ number: {
41
+ text: 'TextWidget',
42
+ select: 'SelectWidget',
43
+ updown: 'UpDownWidget',
44
+ range: 'RangeWidget',
45
+ radio: 'RadioWidget',
46
+ hidden: 'HiddenWidget',
47
+ },
48
+ integer: {
49
+ text: 'TextWidget',
50
+ select: 'SelectWidget',
51
+ updown: 'UpDownWidget',
52
+ range: 'RangeWidget',
53
+ radio: 'RadioWidget',
54
+ hidden: 'HiddenWidget',
55
+ },
56
+ array: {
57
+ select: 'SelectWidget',
58
+ checkboxes: 'CheckboxesWidget',
59
+ files: 'FileWidget',
60
+ hidden: 'HiddenWidget',
61
+ },
62
+ };
63
+
64
+ /** Wraps the given widget with stateless functional component that will merge any `defaultProps.options` with the
65
+ * `options` that are provided in the props. It will add the wrapper component as a `MergedWidget` property onto the
66
+ * `Widget` so that future attempts to wrap `AWidget` will return the already existing wrapper.
67
+ *
68
+ * @param AWidget - A widget that will be wrapped or one that is already wrapped
69
+ * @returns - The wrapper widget
70
+ */
71
+ function mergeWidgetOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
72
+ AWidget: Widget<T, S, F>
73
+ ) {
74
+ let MergedWidget: Widget<T, S, F> | undefined = get(AWidget, 'MergedWidget');
75
+ // cache return value as property of widget for proper react reconciliation
76
+ if (!MergedWidget) {
77
+ const defaultOptions = (AWidget.defaultProps && AWidget.defaultProps.options) || {};
78
+ MergedWidget = ({ options, ...props }) => {
79
+ return <AWidget options={{ ...defaultOptions, ...options }} {...props} />;
80
+ };
81
+ set(AWidget, 'MergedWidget', MergedWidget);
82
+ }
83
+ return MergedWidget;
84
+ }
85
+
86
+ /** Given a schema representing a field to render and either the name or actual `Widget` implementation, returns the
87
+ * React component that is used to render the widget. If the `widget` is already a React component, then it is wrapped
88
+ * with a `MergedWidget`. Otherwise an attempt is made to look up the widget inside of the `registeredWidgets` map based
89
+ * on the schema type and `widget` name. If no widget component can be found an `Error` is thrown.
90
+ *
91
+ * @param schema - The schema for the field
92
+ * @param [widget] - Either the name of the widget OR a `Widget` implementation to use
93
+ * @param [registeredWidgets={}] - A registry of widget name to `Widget` implementation
94
+ * @returns - The `Widget` component to use
95
+ * @throws - An error if there is no `Widget` component that can be returned
96
+ */
97
+ export default function getWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
98
+ schema: RJSFSchema,
99
+ widget?: Widget<T, S, F> | string,
100
+ registeredWidgets: RegistryWidgetsType<T, S, F> = {}
101
+ ): Widget<T, S, F> {
102
+ const type = getSchemaType(schema);
103
+
104
+ if (
105
+ typeof widget === 'function' ||
106
+ (widget && ReactIs.isForwardRef(createElement(widget))) ||
107
+ ReactIs.isMemo(widget)
108
+ ) {
109
+ return mergeWidgetOptions<T, S, F>(widget as Widget<T, S, F>);
110
+ }
111
+
112
+ if (typeof widget !== 'string') {
113
+ throw new Error(`Unsupported widget definition: ${typeof widget}`);
114
+ }
115
+
116
+ if (widget in registeredWidgets) {
117
+ const registeredWidget = registeredWidgets[widget];
118
+ return getWidget<T, S, F>(schema, registeredWidget, registeredWidgets);
119
+ }
120
+
121
+ if (typeof type === 'string') {
122
+ if (!(type in widgetMap)) {
123
+ throw new Error(`No widget for type '${type}'`);
124
+ }
125
+
126
+ if (widget in widgetMap[type]) {
127
+ const registeredWidget = registeredWidgets[widgetMap[type][widget]];
128
+ return getWidget<T, S, F>(schema, registeredWidget, registeredWidgets);
129
+ }
130
+ }
131
+
132
+ throw new Error(`No widget '${widget}' for type '${type}'`);
133
+ }
@@ -0,0 +1,28 @@
1
+ /** Given a specific `value` attempts to guess the type of a schema element. In the case where we have to implicitly
2
+ * create a schema, it is useful to know what type to use based on the data we are defining.
3
+ *
4
+ * @param value - The value from which to guess the type
5
+ * @returns - The best guess for the object type
6
+ */
7
+ export default function guessType(value: any) {
8
+ if (Array.isArray(value)) {
9
+ return 'array';
10
+ }
11
+ if (typeof value === 'string') {
12
+ return 'string';
13
+ }
14
+ if (value == null) {
15
+ return 'null';
16
+ }
17
+ if (typeof value === 'boolean') {
18
+ return 'boolean';
19
+ }
20
+ if (!isNaN(value)) {
21
+ return 'number';
22
+ }
23
+ if (typeof value === 'object') {
24
+ return 'object';
25
+ }
26
+ // Default to string if we can't figure it out
27
+ return 'string';
28
+ }
@@ -0,0 +1,27 @@
1
+ import getWidget from './getWidget';
2
+ import { FormContextType, RegistryWidgetsType, RJSFSchema, StrictRJSFSchema, Widget } from './types';
3
+
4
+ /** Detects whether the `widget` exists for the `schema` with the associated `registryWidgets` and returns true if it
5
+ * does, or false if it doesn't.
6
+ *
7
+ * @param schema - The schema for the field
8
+ * @param widget - Either the name of the widget OR a `Widget` implementation to use
9
+ * @param [registeredWidgets={}] - A registry of widget name to `Widget` implementation
10
+ * @returns - True if the widget exists, false otherwise
11
+ */
12
+ export default function hasWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
13
+ schema: RJSFSchema,
14
+ widget: Widget<T, S, F> | string,
15
+ registeredWidgets: RegistryWidgetsType<T, S, F> = {}
16
+ ) {
17
+ try {
18
+ getWidget(schema, widget, registeredWidgets);
19
+ return true;
20
+ } catch (e) {
21
+ const err: Error = e as Error;
22
+ if (err.message && (err.message.startsWith('No widget') || err.message.startsWith('Unsupported widget'))) {
23
+ return false;
24
+ }
25
+ throw e;
26
+ }
27
+ }
@@ -0,0 +1,31 @@
1
+ import { RJSFSchema, StrictRJSFSchema } from './types';
2
+
3
+ /** JS has no built-in hashing function, so rolling our own
4
+ * based on Java's hashing fn:
5
+ * http://www.java2s.com/example/nodejs-utility-method/string-hash/hashcode-4dc2b.html
6
+ *
7
+ * @param string - The string for which to get the hash
8
+ * @returns - The resulting hash of the string in hex format
9
+ */
10
+ function hashString(string: string): string {
11
+ let hash = 0;
12
+ for (let i = 0; i < string.length; i += 1) {
13
+ const chr = string.charCodeAt(i);
14
+ hash = (hash << 5) - hash + chr;
15
+ hash = hash & hash; // Convert to 32bit integer
16
+ }
17
+ return hash.toString(16);
18
+ }
19
+
20
+ /** Stringifies the schema and returns the hash of the resulting string. Sorts schema fields
21
+ * in consistent order before stringify to prevent different hash ids for the same schema.
22
+ *
23
+ * @param schema - The schema for which the hash is desired
24
+ * @returns - The string obtained from the hash of the stringified schema
25
+ */
26
+ export default function hashForSchema<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
27
+ const allKeys = new Set<string>();
28
+ // solution source: https://stackoverflow.com/questions/16167581/sort-object-properties-and-json-stringify/53593328#53593328
29
+ JSON.stringify(schema, (key, value) => (allKeys.add(key), value));
30
+ return hashString(JSON.stringify(schema, Array.from(allKeys).sort()));
31
+ }
@@ -0,0 +1,81 @@
1
+ import isString from 'lodash/isString';
2
+
3
+ import { IdSchema } from './types';
4
+ import { ID_KEY } from './constants';
5
+
6
+ /** Generates a consistent `id` pattern for a given `id` and a `suffix`
7
+ *
8
+ * @param id - Either simple string id or an IdSchema from which to extract it
9
+ * @param suffix - The suffix to append to the id
10
+ */
11
+ function idGenerator<T = any>(id: IdSchema<T> | string, suffix: string) {
12
+ const theId = isString(id) ? id : id[ID_KEY];
13
+ return `${theId}__${suffix}`;
14
+ }
15
+ /** Return a consistent `id` for the field description element
16
+ *
17
+ * @param id - Either simple string id or an IdSchema from which to extract it
18
+ * @returns - The consistent id for the field description element from the given `id`
19
+ */
20
+ export function descriptionId<T = any>(id: IdSchema<T> | string) {
21
+ return idGenerator<T>(id, 'description');
22
+ }
23
+
24
+ /** Return a consistent `id` for the field error element
25
+ *
26
+ * @param id - Either simple string id or an IdSchema from which to extract it
27
+ * @returns - The consistent id for the field error element from the given `id`
28
+ */
29
+ export function errorId<T = any>(id: IdSchema<T> | string) {
30
+ return idGenerator<T>(id, 'error');
31
+ }
32
+
33
+ /** Return a consistent `id` for the field examples element
34
+ *
35
+ * @param id - Either simple string id or an IdSchema from which to extract it
36
+ * @returns - The consistent id for the field examples element from the given `id`
37
+ */
38
+ export function examplesId<T = any>(id: IdSchema<T> | string) {
39
+ return idGenerator<T>(id, 'examples');
40
+ }
41
+
42
+ /** Return a consistent `id` for the field help element
43
+ *
44
+ * @param id - Either simple string id or an IdSchema from which to extract it
45
+ * @returns - The consistent id for the field help element from the given `id`
46
+ */
47
+ export function helpId<T = any>(id: IdSchema<T> | string) {
48
+ return idGenerator<T>(id, 'help');
49
+ }
50
+
51
+ /** Return a consistent `id` for the field title element
52
+ *
53
+ * @param id - Either simple string id or an IdSchema from which to extract it
54
+ * @returns - The consistent id for the field title element from the given `id`
55
+ */
56
+ export function titleId<T = any>(id: IdSchema<T> | string) {
57
+ return idGenerator<T>(id, 'title');
58
+ }
59
+
60
+ /** Return a list of element ids that contain additional information about the field that can be used to as the aria
61
+ * description of the field. This is correctly omitting `titleId` which would be "labeling" rather than "describing" the
62
+ * element.
63
+ *
64
+ * @param id - Either simple string id or an IdSchema from which to extract it
65
+ * @param [includeExamples=false] - Optional flag, if true, will add the `examplesId` into the list
66
+ * @returns - The string containing the list of ids for use in an `aria-describedBy` attribute
67
+ */
68
+ export function ariaDescribedByIds<T = any>(id: IdSchema<T> | string, includeExamples = false) {
69
+ const examples = includeExamples ? ` ${examplesId<T>(id)}` : '';
70
+ return `${errorId<T>(id)} ${descriptionId<T>(id)} ${helpId<T>(id)}${examples}`;
71
+ }
72
+
73
+ /** Return a consistent `id` for the `optionIndex`s of a `Radio` or `Checkboxes` widget
74
+ *
75
+ * @param id - The id of the parent component for the option
76
+ * @param optionIndex - The index of the option for which the id is desired
77
+ * @returns - An id for the option index based on the parent `id`
78
+ */
79
+ export function optionId(id: string, optionIndex: number) {
80
+ return `${id}-${optionIndex}`;
81
+ }
package/src/index.ts ADDED
@@ -0,0 +1,118 @@
1
+ import allowAdditionalItems from './allowAdditionalItems';
2
+ import asNumber from './asNumber';
3
+ import canExpand from './canExpand';
4
+ import createErrorHandler from './createErrorHandler';
5
+ import createSchemaUtils from './createSchemaUtils';
6
+ import dataURItoBlob from './dataURItoBlob';
7
+ import deepEquals from './deepEquals';
8
+ import englishStringTranslator from './englishStringTranslator';
9
+ import enumOptionsDeselectValue from './enumOptionsDeselectValue';
10
+ import enumOptionsIndexForValue from './enumOptionsIndexForValue';
11
+ import enumOptionsIsSelected from './enumOptionsIsSelected';
12
+ import enumOptionsSelectValue from './enumOptionsSelectValue';
13
+ import enumOptionsValueForIndex from './enumOptionsValueForIndex';
14
+ import ErrorSchemaBuilder from './ErrorSchemaBuilder';
15
+ import findSchemaDefinition from './findSchemaDefinition';
16
+ import getDiscriminatorFieldFromSchema from './getDiscriminatorFieldFromSchema';
17
+ import getInputProps from './getInputProps';
18
+ import getSchemaType from './getSchemaType';
19
+ import getSubmitButtonOptions from './getSubmitButtonOptions';
20
+ import getTemplate from './getTemplate';
21
+ import getUiOptions from './getUiOptions';
22
+ import getWidget from './getWidget';
23
+ import guessType from './guessType';
24
+ import hashForSchema from './hashForSchema';
25
+ import hasWidget from './hasWidget';
26
+ import { ariaDescribedByIds, descriptionId, errorId, examplesId, helpId, optionId, titleId } from './idGenerators';
27
+ import isConstant from './isConstant';
28
+ import isCustomWidget from './isCustomWidget';
29
+ import isFixedItems from './isFixedItems';
30
+ import isObject from './isObject';
31
+ import labelValue from './labelValue';
32
+ import localToUTC from './localToUTC';
33
+ import mergeDefaultsWithFormData from './mergeDefaultsWithFormData';
34
+ import mergeObjects from './mergeObjects';
35
+ import mergeSchemas from './mergeSchemas';
36
+ import optionsList from './optionsList';
37
+ import orderProperties from './orderProperties';
38
+ import pad from './pad';
39
+ import parseDateString from './parseDateString';
40
+ import rangeSpec from './rangeSpec';
41
+ import replaceStringParameters from './replaceStringParameters';
42
+ import schemaRequiresTrueValue from './schemaRequiresTrueValue';
43
+ import shouldRender from './shouldRender';
44
+ import toConstant from './toConstant';
45
+ import toDateString from './toDateString';
46
+ import toErrorList from './toErrorList';
47
+ import toErrorSchema from './toErrorSchema';
48
+ import unwrapErrorHandler from './unwrapErrorHandler';
49
+ import utcToLocal from './utcToLocal';
50
+ import validationDataMerge from './validationDataMerge';
51
+ import withIdRefPrefix from './withIdRefPrefix';
52
+
53
+ export * from './types';
54
+ export * from './enums';
55
+
56
+ export * from './constants';
57
+ export * from './parser';
58
+ export * from './schema';
59
+
60
+ export {
61
+ allowAdditionalItems,
62
+ ariaDescribedByIds,
63
+ asNumber,
64
+ canExpand,
65
+ createErrorHandler,
66
+ createSchemaUtils,
67
+ dataURItoBlob,
68
+ deepEquals,
69
+ descriptionId,
70
+ englishStringTranslator,
71
+ enumOptionsDeselectValue,
72
+ enumOptionsIndexForValue,
73
+ enumOptionsIsSelected,
74
+ enumOptionsSelectValue,
75
+ enumOptionsValueForIndex,
76
+ errorId,
77
+ examplesId,
78
+ ErrorSchemaBuilder,
79
+ findSchemaDefinition,
80
+ getDiscriminatorFieldFromSchema,
81
+ getInputProps,
82
+ getSchemaType,
83
+ getSubmitButtonOptions,
84
+ getTemplate,
85
+ getUiOptions,
86
+ getWidget,
87
+ guessType,
88
+ hasWidget,
89
+ hashForSchema,
90
+ helpId,
91
+ isConstant,
92
+ isCustomWidget,
93
+ isFixedItems,
94
+ isObject,
95
+ labelValue,
96
+ localToUTC,
97
+ mergeDefaultsWithFormData,
98
+ mergeObjects,
99
+ mergeSchemas,
100
+ optionId,
101
+ optionsList,
102
+ orderProperties,
103
+ pad,
104
+ parseDateString,
105
+ rangeSpec,
106
+ replaceStringParameters,
107
+ schemaRequiresTrueValue,
108
+ shouldRender,
109
+ titleId,
110
+ toConstant,
111
+ toDateString,
112
+ toErrorList,
113
+ toErrorSchema,
114
+ unwrapErrorHandler,
115
+ utcToLocal,
116
+ validationDataMerge,
117
+ withIdRefPrefix,
118
+ };
@@ -0,0 +1,12 @@
1
+ import { CONST_KEY } from './constants';
2
+ import { RJSFSchema, StrictRJSFSchema } from './types';
3
+
4
+ /** This function checks if the given `schema` matches a single constant value. This happens when either the schema has
5
+ * an `enum` array with a single value or there is a `const` defined.
6
+ *
7
+ * @param schema - The schema for a field
8
+ * @returns - True if the `schema` has a single constant value, false otherwise
9
+ */
10
+ export default function isConstant<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
11
+ return (Array.isArray(schema.enum) && schema.enum.length === 1) || CONST_KEY in schema;
12
+ }
@@ -0,0 +1,19 @@
1
+ import getUiOptions from './getUiOptions';
2
+ import { FormContextType, RJSFSchema, StrictRJSFSchema, UiSchema } from './types';
3
+
4
+ /** Checks to see if the `uiSchema` contains the `widget` field and that the widget is not `hidden`
5
+ *
6
+ * @param uiSchema - The UI Schema from which to detect if it is customized
7
+ * @returns - True if the `uiSchema` describes a custom widget, false otherwise
8
+ */
9
+ export default function isCustomWidget<
10
+ T = any,
11
+ S extends StrictRJSFSchema = RJSFSchema,
12
+ F extends FormContextType = any
13
+ >(uiSchema: UiSchema<T, S, F> = {}) {
14
+ return (
15
+ // TODO: Remove the `&& uiSchema['ui:widget'] !== 'hidden'` once we support hidden widgets for arrays.
16
+ // https://rjsf-team.github.io/react-jsonschema-form/docs/usage/widgets/#hidden-widgets
17
+ 'widget' in getUiOptions<T, S, F>(uiSchema) && getUiOptions<T, S, F>(uiSchema)['widget'] !== 'hidden'
18
+ );
19
+ }
@@ -0,0 +1,12 @@
1
+ import isObject from './isObject';
2
+ import { RJSFSchema, StrictRJSFSchema } from './types';
3
+
4
+ /** Detects whether the given `schema` contains fixed items. This is the case when `schema.items` is a non-empty array
5
+ * that only contains objects.
6
+ *
7
+ * @param schema - The schema in which to check for fixed items
8
+ * @returns - True if there are fixed items in the schema, false otherwise
9
+ */
10
+ export default function isFixedItems<S extends StrictRJSFSchema = RJSFSchema>(schema: S) {
11
+ return Array.isArray(schema.items) && schema.items.length > 0 && schema.items.every((item) => isObject(item));
12
+ }
@@ -0,0 +1,15 @@
1
+ /** Determines whether a `thing` is an object for the purposes of RSJF. In this case, `thing` is an object if it has
2
+ * the type `object` but is NOT null, an array or a File.
3
+ *
4
+ * @param thing - The thing to check to see whether it is an object
5
+ * @returns - True if it is a non-null, non-array, non-File object
6
+ */
7
+ export default function isObject(thing: any) {
8
+ if (typeof File !== 'undefined' && thing instanceof File) {
9
+ return false;
10
+ }
11
+ if (typeof Date !== 'undefined' && thing instanceof Date) {
12
+ return false;
13
+ }
14
+ return typeof thing === 'object' && thing !== null && !Array.isArray(thing);
15
+ }