@rjsf/utils 6.0.0-beta.9 → 6.0.1

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 (113) hide show
  1. package/dist/{index.js → index.cjs} +563 -200
  2. package/dist/index.cjs.map +7 -0
  3. package/dist/utils.esm.js +562 -199
  4. package/dist/utils.esm.js.map +4 -4
  5. package/dist/utils.umd.js +533 -193
  6. package/lib/ErrorSchemaBuilder.d.ts +2 -2
  7. package/lib/constants.d.ts +3 -0
  8. package/lib/constants.js +3 -0
  9. package/lib/constants.js.map +1 -1
  10. package/lib/createSchemaUtils.js +25 -18
  11. package/lib/createSchemaUtils.js.map +1 -1
  12. package/lib/enums.d.ts +13 -3
  13. package/lib/enums.js +13 -3
  14. package/lib/enums.js.map +1 -1
  15. package/lib/findSchemaDefinition.d.ts +6 -0
  16. package/lib/findSchemaDefinition.js +44 -3
  17. package/lib/findSchemaDefinition.js.map +1 -1
  18. package/lib/getDateElementProps.d.ts +1 -2
  19. package/lib/getTestIds.js +2 -2
  20. package/lib/getTestIds.js.map +1 -1
  21. package/lib/getUiOptions.js +4 -0
  22. package/lib/getUiOptions.js.map +1 -1
  23. package/lib/getWidget.js +3 -3
  24. package/lib/getWidget.js.map +1 -1
  25. package/lib/guessType.d.ts +1 -1
  26. package/lib/idGenerators.d.ts +22 -15
  27. package/lib/idGenerators.js +17 -8
  28. package/lib/idGenerators.js.map +1 -1
  29. package/lib/index.d.ts +16 -6
  30. package/lib/index.js +13 -4
  31. package/lib/index.js.map +1 -1
  32. package/lib/isFormDataAvailable.d.ts +7 -0
  33. package/lib/isFormDataAvailable.js +13 -0
  34. package/lib/isFormDataAvailable.js.map +1 -0
  35. package/lib/isRootSchema.d.ts +13 -0
  36. package/lib/isRootSchema.js +25 -0
  37. package/lib/isRootSchema.js.map +1 -0
  38. package/lib/mergeDefaultsWithFormData.js +14 -2
  39. package/lib/mergeDefaultsWithFormData.js.map +1 -1
  40. package/lib/nameGenerators.d.ts +13 -0
  41. package/lib/nameGenerators.js +30 -0
  42. package/lib/nameGenerators.js.map +1 -0
  43. package/lib/schema/getDefaultFormState.d.ts +17 -3
  44. package/lib/schema/getDefaultFormState.js +66 -26
  45. package/lib/schema/getDefaultFormState.js.map +1 -1
  46. package/lib/schema/getDisplayLabel.js +2 -2
  47. package/lib/schema/getDisplayLabel.js.map +1 -1
  48. package/lib/schema/index.d.ts +1 -2
  49. package/lib/schema/index.js +1 -2
  50. package/lib/schema/index.js.map +1 -1
  51. package/lib/schema/retrieveSchema.d.ts +10 -5
  52. package/lib/schema/retrieveSchema.js +40 -17
  53. package/lib/schema/retrieveSchema.js.map +1 -1
  54. package/lib/shallowEquals.d.ts +8 -0
  55. package/lib/shallowEquals.js +36 -0
  56. package/lib/shallowEquals.js.map +1 -0
  57. package/lib/shouldRender.d.ts +8 -2
  58. package/lib/shouldRender.js +17 -2
  59. package/lib/shouldRender.js.map +1 -1
  60. package/lib/shouldRenderOptionalField.d.ts +18 -0
  61. package/lib/shouldRenderOptionalField.js +47 -0
  62. package/lib/shouldRenderOptionalField.js.map +1 -0
  63. package/lib/toFieldPathId.d.ts +14 -0
  64. package/lib/toFieldPathId.js +26 -0
  65. package/lib/toFieldPathId.js.map +1 -0
  66. package/lib/tsconfig.tsbuildinfo +1 -1
  67. package/lib/types.d.ts +196 -105
  68. package/lib/useAltDateWidgetProps.d.ts +39 -0
  69. package/lib/useAltDateWidgetProps.js +71 -0
  70. package/lib/useAltDateWidgetProps.js.map +1 -0
  71. package/lib/useDeepCompareMemo.d.ts +8 -0
  72. package/lib/useDeepCompareMemo.js +17 -0
  73. package/lib/useDeepCompareMemo.js.map +1 -0
  74. package/lib/useFileWidgetProps.d.ts +29 -0
  75. package/lib/useFileWidgetProps.js +119 -0
  76. package/lib/useFileWidgetProps.js.map +1 -0
  77. package/lib/validationDataMerge.d.ts +2 -1
  78. package/lib/validationDataMerge.js +3 -2
  79. package/lib/validationDataMerge.js.map +1 -1
  80. package/package.json +13 -14
  81. package/src/ErrorSchemaBuilder.ts +2 -2
  82. package/src/constants.ts +3 -0
  83. package/src/createSchemaUtils.ts +25 -26
  84. package/src/enums.ts +13 -3
  85. package/src/findSchemaDefinition.ts +51 -3
  86. package/src/getDateElementProps.ts +1 -1
  87. package/src/getTestIds.ts +2 -2
  88. package/src/getUiOptions.ts +4 -0
  89. package/src/getWidget.tsx +3 -3
  90. package/src/idGenerators.ts +35 -25
  91. package/src/index.ts +36 -5
  92. package/src/isFormDataAvailable.ts +13 -0
  93. package/src/isRootSchema.ts +30 -0
  94. package/src/mergeDefaultsWithFormData.ts +16 -2
  95. package/src/nameGenerators.ts +43 -0
  96. package/src/schema/getDefaultFormState.ts +87 -31
  97. package/src/schema/getDisplayLabel.ts +2 -2
  98. package/src/schema/index.ts +0 -2
  99. package/src/schema/retrieveSchema.ts +43 -7
  100. package/src/shallowEquals.ts +41 -0
  101. package/src/shouldRender.ts +27 -2
  102. package/src/shouldRenderOptionalField.ts +56 -0
  103. package/src/toFieldPathId.ts +34 -0
  104. package/src/types.ts +229 -113
  105. package/src/useAltDateWidgetProps.tsx +163 -0
  106. package/src/useDeepCompareMemo.ts +17 -0
  107. package/src/useFileWidgetProps.ts +155 -0
  108. package/src/validationDataMerge.ts +7 -1
  109. package/dist/index.js.map +0 -7
  110. package/lib/schema/toIdSchema.d.ts +0 -14
  111. package/lib/schema/toIdSchema.js +0 -62
  112. package/lib/schema/toIdSchema.js.map +0 -1
  113. package/src/schema/toIdSchema.ts +0 -131
@@ -1,7 +1,14 @@
1
1
  import jsonpointer from 'jsonpointer';
2
2
  import omit from 'lodash/omit';
3
3
 
4
- import { ID_KEY, JSON_SCHEMA_DRAFT_2020_12, REF_KEY, SCHEMA_KEY } from './constants';
4
+ import {
5
+ ALL_OF_KEY,
6
+ ID_KEY,
7
+ JSON_SCHEMA_DRAFT_2019_09,
8
+ JSON_SCHEMA_DRAFT_2020_12,
9
+ REF_KEY,
10
+ SCHEMA_KEY,
11
+ } from './constants';
5
12
  import { GenericObjectType, RJSFSchema, StrictRJSFSchema } from './types';
6
13
  import isObject from 'lodash/isObject';
7
14
  import isEmpty from 'lodash/isEmpty';
@@ -20,7 +27,16 @@ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(sc
20
27
  return schema;
21
28
  }
22
29
  for (const subSchema of Object.values(schema)) {
23
- if (isObject(subSchema)) {
30
+ if (Array.isArray(subSchema)) {
31
+ for (const item of subSchema) {
32
+ if (isObject(item)) {
33
+ const result = findEmbeddedSchemaRecursive<S>(item as S, ref);
34
+ if (result !== undefined) {
35
+ return result as S;
36
+ }
37
+ }
38
+ }
39
+ } else if (isObject(subSchema)) {
24
40
  const result = findEmbeddedSchemaRecursive<S>(subSchema as S, ref);
25
41
  if (result !== undefined) {
26
42
  return result as S;
@@ -30,6 +46,31 @@ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(sc
30
46
  return undefined;
31
47
  }
32
48
 
49
+ /** Parses a JSONSchema and makes all references absolute with respect to
50
+ * the `baseURI` argument
51
+ * @param schema - The schema to be processed
52
+ * @param baseURI - The base URI to be used for resolving relative references
53
+ */
54
+ export function makeAllReferencesAbsolute<S extends StrictRJSFSchema = RJSFSchema>(schema: S, baseURI: string): S {
55
+ const currentURI = get(schema, ID_KEY, baseURI);
56
+ // Make all other references absolute
57
+ if (REF_KEY in schema) {
58
+ schema = { ...schema, [REF_KEY]: UriResolver.resolve(currentURI, schema[REF_KEY]!) };
59
+ }
60
+ // Look for references in nested subschemas
61
+ for (const [key, subSchema] of Object.entries(schema)) {
62
+ if (Array.isArray(subSchema)) {
63
+ schema = {
64
+ ...schema,
65
+ [key]: subSchema.map((item) => (isObject(item) ? makeAllReferencesAbsolute(item as S, currentURI) : item)),
66
+ };
67
+ } else if (isObject(subSchema)) {
68
+ schema = { ...schema, [key]: makeAllReferencesAbsolute(subSchema as S, currentURI) };
69
+ }
70
+ }
71
+ return schema;
72
+ }
73
+
33
74
  /** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first
34
75
  * location, the `object` minus the `key: value` and in the second location the `value`.
35
76
  *
@@ -103,7 +144,14 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
103
144
  const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
104
145
  const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref], baseURI);
105
146
  if (Object.keys(remaining).length > 0) {
106
- return { ...remaining, ...subSchema };
147
+ if (
148
+ rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2019_09 ||
149
+ rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12
150
+ ) {
151
+ return { [ALL_OF_KEY]: [remaining, subSchema] } as S;
152
+ } else {
153
+ return { ...remaining, ...subSchema };
154
+ }
107
155
  }
108
156
  return subSchema;
109
157
  }
@@ -4,7 +4,7 @@ import { type DateObject } from './types';
4
4
  export type DateElementFormat = 'DMY' | 'MDY' | 'YMD';
5
5
 
6
6
  /** Type describing format of DateElement prop */
7
- type DateElementProp = {
7
+ export type DateElementProp = {
8
8
  type: string;
9
9
  range: [number, number];
10
10
  value: number | undefined;
package/src/getTestIds.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { nanoid } from 'nanoid';
2
1
  import get from 'lodash/get';
2
+ import uniqueId from 'lodash/uniqueId';
3
3
 
4
4
  import { TestIdShape } from './types';
5
5
 
@@ -31,7 +31,7 @@ export default function getTestIds(): TestIdShape {
31
31
  {
32
32
  get(_obj, prop) {
33
33
  if (!ids.has(prop)) {
34
- ids.set(prop, nanoid());
34
+ ids.set(prop, uniqueId('test-id-'));
35
35
  }
36
36
  return ids.get(prop);
37
37
  },
@@ -13,6 +13,10 @@ export default function getUiOptions<T = any, S extends StrictRJSFSchema = RJSFS
13
13
  uiSchema: UiSchema<T, S, F> = {},
14
14
  globalOptions: GlobalUISchemaOptions = {},
15
15
  ): UIOptionsType<T, S, F> {
16
+ // Handle null or undefined uiSchema
17
+ if (!uiSchema) {
18
+ return { ...globalOptions };
19
+ }
16
20
  return Object.keys(uiSchema)
17
21
  .filter((key) => key.indexOf('ui:') === 0)
18
22
  .reduce(
package/src/getWidget.tsx CHANGED
@@ -110,7 +110,7 @@ export default function getWidget<T = any, S extends StrictRJSFSchema = RJSFSche
110
110
  }
111
111
 
112
112
  if (typeof widget !== 'string') {
113
- throw new Error(`Unsupported widget definition: ${typeof widget}`);
113
+ throw new Error(`Unsupported widget definition: ${typeof widget} in schema: ${JSON.stringify(schema)}`);
114
114
  }
115
115
 
116
116
  if (widget in registeredWidgets) {
@@ -120,7 +120,7 @@ export default function getWidget<T = any, S extends StrictRJSFSchema = RJSFSche
120
120
 
121
121
  if (typeof type === 'string') {
122
122
  if (!(type in widgetMap)) {
123
- throw new Error(`No widget for type '${type}'`);
123
+ throw new Error(`No widget for type '${type}' in schema: ${JSON.stringify(schema)}`);
124
124
  }
125
125
 
126
126
  if (widget in widgetMap[type]) {
@@ -129,5 +129,5 @@ export default function getWidget<T = any, S extends StrictRJSFSchema = RJSFSche
129
129
  }
130
130
  }
131
131
 
132
- throw new Error(`No widget '${widget}' for type '${type}'`);
132
+ throw new Error(`No widget '${widget}' for type '${type}' in schema: ${JSON.stringify(schema)}`);
133
133
  }
@@ -1,73 +1,73 @@
1
1
  import isString from 'lodash/isString';
2
2
 
3
- import { IdSchema } from './types';
3
+ import { FieldPathId } from './types';
4
4
  import { ID_KEY } from './constants';
5
5
 
6
6
  /** Generates a consistent `id` pattern for a given `id` and a `suffix`
7
7
  *
8
- * @param id - Either simple string id or an IdSchema from which to extract it
8
+ * @param id - Either simple string id or an FieldPathId from which to extract it
9
9
  * @param suffix - The suffix to append to the id
10
10
  */
11
- function idGenerator<T = any>(id: IdSchema<T> | string, suffix: string) {
11
+ function idGenerator(id: FieldPathId | string, suffix: string) {
12
12
  const theId = isString(id) ? id : id[ID_KEY];
13
13
  return `${theId}__${suffix}`;
14
14
  }
15
15
  /** Return a consistent `id` for the field description element
16
16
  *
17
- * @param id - Either simple string id or an IdSchema from which to extract it
17
+ * @param id - Either simple string id or an FieldPathId from which to extract it
18
18
  * @returns - The consistent id for the field description element from the given `id`
19
19
  */
20
- export function descriptionId<T = any>(id: IdSchema<T> | string) {
21
- return idGenerator<T>(id, 'description');
20
+ export function descriptionId(id: FieldPathId | string) {
21
+ return idGenerator(id, 'description');
22
22
  }
23
23
 
24
24
  /** Return a consistent `id` for the field error element
25
25
  *
26
- * @param id - Either simple string id or an IdSchema from which to extract it
26
+ * @param id - Either simple string id or an FieldPathId from which to extract it
27
27
  * @returns - The consistent id for the field error element from the given `id`
28
28
  */
29
- export function errorId<T = any>(id: IdSchema<T> | string) {
30
- return idGenerator<T>(id, 'error');
29
+ export function errorId(id: FieldPathId | string) {
30
+ return idGenerator(id, 'error');
31
31
  }
32
32
 
33
33
  /** Return a consistent `id` for the field examples element
34
34
  *
35
- * @param id - Either simple string id or an IdSchema from which to extract it
35
+ * @param id - Either simple string id or an FieldPathId from which to extract it
36
36
  * @returns - The consistent id for the field examples element from the given `id`
37
37
  */
38
- export function examplesId<T = any>(id: IdSchema<T> | string) {
39
- return idGenerator<T>(id, 'examples');
38
+ export function examplesId(id: FieldPathId | string) {
39
+ return idGenerator(id, 'examples');
40
40
  }
41
41
 
42
42
  /** Return a consistent `id` for the field help element
43
43
  *
44
- * @param id - Either simple string id or an IdSchema from which to extract it
44
+ * @param id - Either simple string id or an FieldPathId from which to extract it
45
45
  * @returns - The consistent id for the field help element from the given `id`
46
46
  */
47
- export function helpId<T = any>(id: IdSchema<T> | string) {
48
- return idGenerator<T>(id, 'help');
47
+ export function helpId(id: FieldPathId | string) {
48
+ return idGenerator(id, 'help');
49
49
  }
50
50
 
51
51
  /** Return a consistent `id` for the field title element
52
52
  *
53
- * @param id - Either simple string id or an IdSchema from which to extract it
53
+ * @param id - Either simple string id or an FieldPathId from which to extract it
54
54
  * @returns - The consistent id for the field title element from the given `id`
55
55
  */
56
- export function titleId<T = any>(id: IdSchema<T> | string) {
57
- return idGenerator<T>(id, 'title');
56
+ export function titleId(id: FieldPathId | string) {
57
+ return idGenerator(id, 'title');
58
58
  }
59
59
 
60
60
  /** Return a list of element ids that contain additional information about the field that can be used to as the aria
61
61
  * description of the field. This is correctly omitting `titleId` which would be "labeling" rather than "describing" the
62
62
  * element.
63
63
  *
64
- * @param id - Either simple string id or an IdSchema from which to extract it
64
+ * @param id - Either simple string id or an FieldPathId from which to extract it
65
65
  * @param [includeExamples=false] - Optional flag, if true, will add the `examplesId` into the list
66
66
  * @returns - The string containing the list of ids for use in an `aria-describedBy` attribute
67
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}`;
68
+ export function ariaDescribedByIds(id: FieldPathId | string, includeExamples = false) {
69
+ const examples = includeExamples ? ` ${examplesId(id)}` : '';
70
+ return `${errorId(id)} ${descriptionId(id)} ${helpId(id)}${examples}`;
71
71
  }
72
72
 
73
73
  /** Return a consistent `id` for the `optionIndex`s of a `Radio` or `Checkboxes` widget
@@ -82,10 +82,20 @@ export function optionId(id: string, optionIndex: number) {
82
82
 
83
83
  /** Return a consistent `id` for the `btn` button element
84
84
  *
85
- * @param id - Either simple string id or an IdSchema from which to extract it
85
+ * @param id - The id of the parent component for the option
86
86
  * @param btn - The button type for which to generate the id
87
87
  * @returns - The consistent id for the button from the given `id` and `btn` type
88
88
  */
89
- export function buttonId<T = any>(id: IdSchema<T> | string, btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove') {
90
- return idGenerator<T>(id, btn);
89
+ export function buttonId(id: FieldPathId | string, btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove') {
90
+ return idGenerator(id, btn);
91
+ }
92
+
93
+ /** Return a consistent `id` for the optional data controls `element`
94
+ *
95
+ * @param id - The id of the parent component for the option
96
+ * @param element - The element type for which to generate the id
97
+ * @returns - The consistent id for the optional data controls element from the given `id` and `element` type
98
+ */
99
+ export function optionalControlsId(id: FieldPathId | string, element: 'Add' | 'Msg' | 'Remove') {
100
+ return idGenerator(id, `optional${element}`);
91
101
  }
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import createSchemaUtils from './createSchemaUtils';
6
6
  import dataURItoBlob from './dataURItoBlob';
7
7
  import dateRangeOptions from './dateRangeOptions';
8
8
  import deepEquals from './deepEquals';
9
+ import shallowEquals from './shallowEquals';
9
10
  import englishStringTranslator from './englishStringTranslator';
10
11
  import enumOptionsDeselectValue from './enumOptionsDeselectValue';
11
12
  import enumOptionsIndexForValue from './enumOptionsIndexForValue';
@@ -14,9 +15,11 @@ import enumOptionsSelectValue from './enumOptionsSelectValue';
14
15
  import enumOptionsValueForIndex from './enumOptionsValueForIndex';
15
16
  import ErrorSchemaBuilder from './ErrorSchemaBuilder';
16
17
  import findSchemaDefinition from './findSchemaDefinition';
17
- import getDateElementProps, { type DateElementFormat } from './getDateElementProps';
18
+ import getChangedFields from './getChangedFields';
19
+ import getDateElementProps, { DateElementFormat, DateElementProp } from './getDateElementProps';
18
20
  import getDiscriminatorFieldFromSchema from './getDiscriminatorFieldFromSchema';
19
21
  import getInputProps from './getInputProps';
22
+ import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';
20
23
  import getSchemaType from './getSchemaType';
21
24
  import getSubmitButtonOptions from './getSubmitButtonOptions';
22
25
  import getTemplate from './getTemplate';
@@ -33,13 +36,16 @@ import {
33
36
  errorId,
34
37
  examplesId,
35
38
  helpId,
39
+ optionalControlsId,
36
40
  optionId,
37
41
  titleId,
38
42
  } from './idGenerators';
39
43
  import isConstant from './isConstant';
40
44
  import isCustomWidget from './isCustomWidget';
41
45
  import isFixedItems from './isFixedItems';
46
+ import isFormDataAvailable from './isFormDataAvailable';
42
47
  import isObject from './isObject';
48
+ import isRootSchema from './isRootSchema';
43
49
  import labelValue from './labelValue';
44
50
  import localToUTC from './localToUTC';
45
51
  import lookupFromFormContext from './lookupFromFormContext';
@@ -53,17 +59,21 @@ import parseDateString from './parseDateString';
53
59
  import rangeSpec from './rangeSpec';
54
60
  import replaceStringParameters from './replaceStringParameters';
55
61
  import schemaRequiresTrueValue from './schemaRequiresTrueValue';
56
- import shouldRender from './shouldRender';
62
+ import shouldRender, { ComponentUpdateStrategy } from './shouldRender';
63
+ import shouldRenderOptionalField from './shouldRenderOptionalField';
57
64
  import toConstant from './toConstant';
58
65
  import toDateString from './toDateString';
59
66
  import toErrorList from './toErrorList';
60
67
  import toErrorSchema from './toErrorSchema';
68
+ import toFieldPathId from './toFieldPathId';
61
69
  import unwrapErrorHandler from './unwrapErrorHandler';
70
+ import useAltDateWidgetProps, { DateElement, DateElementProps, UseAltDateWidgetResult } from './useAltDateWidgetProps';
71
+ import useDeepCompareMemo from './useDeepCompareMemo';
72
+ import useFileWidgetProps, { FileInfoType, UseFileWidgetPropsResult } from './useFileWidgetProps';
62
73
  import utcToLocal from './utcToLocal';
63
74
  import validationDataMerge from './validationDataMerge';
64
75
  import withIdRefPrefix from './withIdRefPrefix';
65
- import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';
66
- import getChangedFields from './getChangedFields';
76
+ import { bracketNameGenerator, dotNotationNameGenerator } from './nameGenerators';
67
77
 
68
78
  export * from './types';
69
79
  export * from './enums';
@@ -72,6 +82,16 @@ export * from './constants';
72
82
  export * from './parser';
73
83
  export * from './schema';
74
84
 
85
+ export type {
86
+ ComponentUpdateStrategy,
87
+ DateElementFormat,
88
+ DateElementProp,
89
+ DateElementProps,
90
+ FileInfoType,
91
+ UseAltDateWidgetResult,
92
+ UseFileWidgetPropsResult,
93
+ };
94
+
75
95
  export {
76
96
  allowAdditionalItems,
77
97
  ariaDescribedByIds,
@@ -80,7 +100,7 @@ export {
80
100
  canExpand,
81
101
  createErrorHandler,
82
102
  createSchemaUtils,
83
- DateElementFormat,
103
+ DateElement,
84
104
  dataURItoBlob,
85
105
  dateRangeOptions,
86
106
  deepEquals,
@@ -115,13 +135,16 @@ export {
115
135
  isConstant,
116
136
  isCustomWidget,
117
137
  isFixedItems,
138
+ isFormDataAvailable,
118
139
  isObject,
140
+ isRootSchema,
119
141
  labelValue,
120
142
  localToUTC,
121
143
  lookupFromFormContext,
122
144
  mergeDefaultsWithFormData,
123
145
  mergeObjects,
124
146
  mergeSchemas,
147
+ optionalControlsId,
125
148
  optionId,
126
149
  optionsList,
127
150
  orderProperties,
@@ -130,15 +153,23 @@ export {
130
153
  rangeSpec,
131
154
  replaceStringParameters,
132
155
  schemaRequiresTrueValue,
156
+ shallowEquals,
133
157
  shouldRender,
158
+ shouldRenderOptionalField,
134
159
  sortedJSONStringify,
135
160
  titleId,
136
161
  toConstant,
137
162
  toDateString,
138
163
  toErrorList,
139
164
  toErrorSchema,
165
+ toFieldPathId,
140
166
  unwrapErrorHandler,
167
+ useAltDateWidgetProps,
168
+ useDeepCompareMemo,
169
+ useFileWidgetProps,
141
170
  utcToLocal,
142
171
  validationDataMerge,
143
172
  withIdRefPrefix,
173
+ bracketNameGenerator,
174
+ dotNotationNameGenerator,
144
175
  };
@@ -0,0 +1,13 @@
1
+ import isNil from 'lodash/isNil';
2
+ import isEmpty from 'lodash/isEmpty';
3
+ import isObject from 'lodash/isObject';
4
+
5
+ /** Determines whether the given `formData` represents valid form data, such as a primitive type, an array, or a
6
+ * non-empty object.
7
+ *
8
+ * @param formData - The data to check
9
+ * @returns - True if `formData` is not undefined, null, a primitive type or an array or an empty object
10
+ */
11
+ export default function isFormDataAvailable<T = any>(formData?: T): boolean {
12
+ return !isNil(formData) && (!isObject(formData) || Array.isArray(formData) || !isEmpty(formData));
13
+ }
@@ -0,0 +1,30 @@
1
+ import isEqual from 'lodash/isEqual';
2
+
3
+ import { FormContextType, Registry, RJSFSchema, StrictRJSFSchema } from './types';
4
+ import { REF_KEY } from './constants';
5
+
6
+ /** Helper to check whether a JSON schema object is the root schema. The schema is a root schema with root `properties`
7
+ * key or a root `$ref` key. If the `schemaToCompare` has a root `oneOf` property, the function will
8
+ * return false. Else if `schemaToCompare` and `rootSchema` are the same object or equal, the function will return
9
+ * `true`. Else if the `rootSchema` has a $ref, it will be resolved using `schemaUtils.resolveSchema` utility. If the
10
+ * resolved schema matches the `schemaToCompare` the function will return `true`. Otherwise, it will return false.
11
+ *
12
+ * @param registry - The `Registry` used to get the `rootSchema` and `schemaUtils`
13
+ * @param schemaToCompare - The JSON schema object to check. If `schemaToCompare` is an root schema, the
14
+ * function will return true.
15
+ * @returns - Flag indicating whether the `schemaToCompare` is the root schema
16
+ */
17
+ export default function isRootSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
18
+ registry: Registry<T, S, F>,
19
+ schemaToCompare: S,
20
+ ): boolean {
21
+ const { rootSchema, schemaUtils } = registry;
22
+ if (isEqual(schemaToCompare, rootSchema)) {
23
+ return true;
24
+ }
25
+ if (REF_KEY in rootSchema) {
26
+ const resolvedSchema = schemaUtils.retrieveSchema(rootSchema);
27
+ return isEqual(schemaToCompare, resolvedSchema);
28
+ }
29
+ return false;
30
+ }
@@ -67,8 +67,22 @@ export default function mergeDefaultsWithFormData<T = any>(
67
67
  const keyValue = get(formData, key);
68
68
  const keyExistsInDefaults = isObject(defaults) && key in (defaults as GenericObjectType);
69
69
  const keyExistsInFormData = key in (formData as GenericObjectType);
70
+ const keyDefault = get(defaults, key) ?? {};
71
+ const defaultValueIsNestedObject = keyExistsInDefaults && Object.entries(keyDefault).some(([, v]) => isObject(v));
72
+
73
+ const keyDefaultIsObject = keyExistsInDefaults && isObject(get(defaults, key));
74
+ const keyHasFormDataObject = keyExistsInFormData && isObject(keyValue);
75
+
76
+ if (keyDefaultIsObject && keyHasFormDataObject && !defaultValueIsNestedObject) {
77
+ acc[key as keyof T] = {
78
+ ...get(defaults, key),
79
+ ...keyValue,
80
+ };
81
+ return acc;
82
+ }
83
+
70
84
  acc[key as keyof T] = mergeDefaultsWithFormData<T>(
71
- defaults ? get(defaults, key) : {},
85
+ get(defaults, key),
72
86
  keyValue,
73
87
  mergeExtraArrayDefaults,
74
88
  defaultSupercedesUndefined,
@@ -88,7 +102,7 @@ export default function mergeDefaultsWithFormData<T = any>(
88
102
  */
89
103
  if (
90
104
  (defaultSupercedesUndefined &&
91
- ((!isNil(defaults) && isNil(formData)) || (typeof formData === 'number' && isNaN(formData)))) ||
105
+ ((!(defaults === undefined) && isNil(formData)) || (typeof formData === 'number' && isNaN(formData)))) ||
92
106
  (overrideFormDataWithDefaults && !isNil(formData))
93
107
  ) {
94
108
  return defaults;
@@ -0,0 +1,43 @@
1
+ import { NameGeneratorFunction, FieldPathList } from './types';
2
+
3
+ /**
4
+ * Generates bracketed names
5
+ * Example: root[tasks][0][title]
6
+ * For multi-value fields (checkboxes, multi-select): root[hobbies][]
7
+ */
8
+ export const bracketNameGenerator: NameGeneratorFunction = (
9
+ path: FieldPathList,
10
+ idPrefix: string,
11
+ isMultiValue?: boolean,
12
+ ): string => {
13
+ if (!path || path.length === 0) {
14
+ return idPrefix;
15
+ }
16
+
17
+ const baseName = path.reduce<string>((acc, pathUnit, index) => {
18
+ if (index === 0) {
19
+ return `${idPrefix}[${String(pathUnit)}]`;
20
+ }
21
+ return `${acc}[${String(pathUnit)}]`;
22
+ }, '');
23
+
24
+ // For multi-value fields, append [] to allow multiple values with the same name
25
+ return isMultiValue ? `${baseName}[]` : baseName;
26
+ };
27
+
28
+ /**
29
+ * Generates dot-notation names
30
+ * Example: root.tasks.0.title
31
+ * Multi-value fields are handled the same as single-value fields in dot notation
32
+ */
33
+ export const dotNotationNameGenerator: NameGeneratorFunction = (
34
+ path: FieldPathList,
35
+ idPrefix: string,
36
+ _isMultiValue?: boolean,
37
+ ): string => {
38
+ if (!path || path.length === 0) {
39
+ return idPrefix;
40
+ }
41
+
42
+ return `${idPrefix}.${path.map(String).join('.')}`;
43
+ };