@rjsf/utils 6.0.0-beta.2 → 6.0.0-beta.20
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.
- package/dist/{index.js → index.cjs} +241 -205
- package/dist/index.cjs.map +7 -0
- package/dist/utils.esm.js +240 -204
- package/dist/utils.esm.js.map +4 -4
- package/dist/utils.umd.js +235 -200
- package/lib/canExpand.d.ts +1 -1
- package/lib/constants.d.ts +3 -0
- package/lib/constants.js +3 -0
- package/lib/constants.js.map +1 -1
- package/lib/createSchemaUtils.js +19 -14
- package/lib/createSchemaUtils.js.map +1 -1
- package/lib/enums.d.ts +3 -3
- package/lib/enums.js +3 -3
- package/lib/findSchemaDefinition.d.ts +7 -1
- package/lib/findSchemaDefinition.js +48 -6
- package/lib/findSchemaDefinition.js.map +1 -1
- package/lib/getTestIds.js +2 -2
- package/lib/getTestIds.js.map +1 -1
- package/lib/getUiOptions.js +4 -0
- package/lib/getUiOptions.js.map +1 -1
- package/lib/getWidget.js +3 -3
- package/lib/getWidget.js.map +1 -1
- package/lib/idGenerators.d.ts +15 -15
- package/lib/idGenerators.js +8 -8
- package/lib/idGenerators.js.map +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/mergeDefaultsWithFormData.js +14 -2
- package/lib/mergeDefaultsWithFormData.js.map +1 -1
- package/lib/schema/findFieldInSchema.d.ts +1 -1
- package/lib/schema/findFieldInSchema.js +1 -1
- package/lib/schema/getDefaultFormState.d.ts +11 -2
- package/lib/schema/getDefaultFormState.js +59 -22
- package/lib/schema/getDefaultFormState.js.map +1 -1
- package/lib/schema/getDisplayLabel.js +2 -2
- package/lib/schema/getDisplayLabel.js.map +1 -1
- package/lib/schema/index.d.ts +1 -2
- package/lib/schema/index.js +1 -2
- package/lib/schema/index.js.map +1 -1
- package/lib/schema/retrieveSchema.d.ts +1 -1
- package/lib/schema/retrieveSchema.js +6 -6
- package/lib/schema/retrieveSchema.js.map +1 -1
- package/lib/shallowEquals.d.ts +8 -0
- package/lib/shallowEquals.js +36 -0
- package/lib/shallowEquals.js.map +1 -0
- package/lib/shouldRender.d.ts +8 -2
- package/lib/shouldRender.js +17 -2
- package/lib/shouldRender.js.map +1 -1
- package/lib/toFieldPathId.d.ts +12 -0
- package/lib/toFieldPathId.js +19 -0
- package/lib/toFieldPathId.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.d.ts +97 -66
- package/package.json +13 -14
- package/src/constants.ts +3 -0
- package/src/createSchemaUtils.ts +19 -25
- package/src/enums.ts +3 -3
- package/src/findSchemaDefinition.ts +55 -6
- package/src/getTestIds.ts +2 -2
- package/src/getUiOptions.ts +4 -0
- package/src/getWidget.tsx +3 -3
- package/src/idGenerators.ts +25 -25
- package/src/index.ts +6 -0
- package/src/mergeDefaultsWithFormData.ts +16 -2
- package/src/schema/findFieldInSchema.ts +1 -1
- package/src/schema/getDefaultFormState.ts +76 -32
- package/src/schema/getDisplayLabel.ts +2 -2
- package/src/schema/index.ts +0 -2
- package/src/schema/retrieveSchema.ts +7 -5
- package/src/shallowEquals.ts +41 -0
- package/src/shouldRender.ts +27 -2
- package/src/toFieldPathId.ts +24 -0
- package/src/types.ts +107 -70
- package/dist/index.js.map +0 -7
- package/lib/schema/toIdSchema.d.ts +0 -14
- package/lib/schema/toIdSchema.js +0 -62
- package/lib/schema/toIdSchema.js.map +0 -1
- package/src/schema/toIdSchema.ts +0 -131
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import jsonpointer from 'jsonpointer';
|
|
2
2
|
import omit from 'lodash/omit';
|
|
3
3
|
|
|
4
|
-
import {
|
|
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';
|
|
8
15
|
import UriResolver from 'fast-uri';
|
|
16
|
+
import get from 'lodash/get';
|
|
9
17
|
|
|
10
18
|
/** Looks for the `$id` pointed by `ref` in the schema definitions embedded in
|
|
11
19
|
* a JSON Schema bundle
|
|
@@ -19,7 +27,16 @@ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(sc
|
|
|
19
27
|
return schema;
|
|
20
28
|
}
|
|
21
29
|
for (const subSchema of Object.values(schema)) {
|
|
22
|
-
if (
|
|
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)) {
|
|
23
40
|
const result = findEmbeddedSchemaRecursive<S>(subSchema as S, ref);
|
|
24
41
|
if (result !== undefined) {
|
|
25
42
|
return result as S;
|
|
@@ -29,6 +46,31 @@ function findEmbeddedSchemaRecursive<S extends StrictRJSFSchema = RJSFSchema>(sc
|
|
|
29
46
|
return undefined;
|
|
30
47
|
}
|
|
31
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
|
+
|
|
32
74
|
/** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first
|
|
33
75
|
* location, the `object` minus the `key: value` and in the second location the `value`.
|
|
34
76
|
*
|
|
@@ -51,7 +93,7 @@ export function splitKeyElementFromObject(key: string, object: GenericObjectType
|
|
|
51
93
|
* @param $ref - The ref string for which the schema definition is desired
|
|
52
94
|
* @param [rootSchema={}] - The root schema in which to search for the definition
|
|
53
95
|
* @param recurseList - List of $refs already resolved to prevent recursion
|
|
54
|
-
* @param baseURI - The base URI to be used for resolving relative references
|
|
96
|
+
* @param [baseURI=rootSchema['$id']] - The base URI to be used for resolving relative references
|
|
55
97
|
* @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
|
|
56
98
|
* @throws - Error indicating that no schema for that reference could be resolved
|
|
57
99
|
*/
|
|
@@ -59,7 +101,7 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
|
|
|
59
101
|
$ref?: string,
|
|
60
102
|
rootSchema: S = {} as S,
|
|
61
103
|
recurseList: string[] = [],
|
|
62
|
-
baseURI: string | undefined =
|
|
104
|
+
baseURI: string | undefined = get(rootSchema, [ID_KEY]),
|
|
63
105
|
): S {
|
|
64
106
|
const ref = $ref || '';
|
|
65
107
|
let current: S | undefined = undefined;
|
|
@@ -102,7 +144,14 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
|
|
|
102
144
|
const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
|
|
103
145
|
const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref], baseURI);
|
|
104
146
|
if (Object.keys(remaining).length > 0) {
|
|
105
|
-
|
|
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
|
+
}
|
|
106
155
|
}
|
|
107
156
|
return subSchema;
|
|
108
157
|
}
|
|
@@ -123,7 +172,7 @@ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFS
|
|
|
123
172
|
export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
|
|
124
173
|
$ref?: string,
|
|
125
174
|
rootSchema: S = {} as S,
|
|
126
|
-
baseURI: string | undefined =
|
|
175
|
+
baseURI: string | undefined = get(rootSchema, [ID_KEY]),
|
|
127
176
|
): S {
|
|
128
177
|
const recurseList: string[] = [];
|
|
129
178
|
return findSchemaDefinitionRecursive($ref, rootSchema, recurseList, baseURI);
|
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,
|
|
34
|
+
ids.set(prop, uniqueId('test-id-'));
|
|
35
35
|
}
|
|
36
36
|
return ids.get(prop);
|
|
37
37
|
},
|
package/src/getUiOptions.ts
CHANGED
|
@@ -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
|
}
|
package/src/idGenerators.ts
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
1
|
import isString from 'lodash/isString';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
21
|
-
return idGenerator
|
|
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
|
|
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
|
|
30
|
-
return idGenerator
|
|
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
|
|
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
|
|
39
|
-
return idGenerator
|
|
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
|
|
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
|
|
48
|
-
return idGenerator
|
|
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
|
|
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
|
|
57
|
-
return idGenerator
|
|
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
|
|
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
|
|
69
|
-
const examples = includeExamples ? ` ${examplesId
|
|
70
|
-
return `${errorId
|
|
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,10 @@ 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
|
|
85
|
+
* @param id - Either simple string id or an FieldPathId from which to extract it
|
|
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
|
|
90
|
-
return idGenerator
|
|
89
|
+
export function buttonId(id: FieldPathId | string, btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove') {
|
|
90
|
+
return idGenerator(id, btn);
|
|
91
91
|
}
|
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';
|
|
@@ -58,6 +59,7 @@ import toConstant from './toConstant';
|
|
|
58
59
|
import toDateString from './toDateString';
|
|
59
60
|
import toErrorList from './toErrorList';
|
|
60
61
|
import toErrorSchema from './toErrorSchema';
|
|
62
|
+
import toFieldPathId from './toFieldPathId';
|
|
61
63
|
import unwrapErrorHandler from './unwrapErrorHandler';
|
|
62
64
|
import utcToLocal from './utcToLocal';
|
|
63
65
|
import validationDataMerge from './validationDataMerge';
|
|
@@ -130,6 +132,7 @@ export {
|
|
|
130
132
|
rangeSpec,
|
|
131
133
|
replaceStringParameters,
|
|
132
134
|
schemaRequiresTrueValue,
|
|
135
|
+
shallowEquals,
|
|
133
136
|
shouldRender,
|
|
134
137
|
sortedJSONStringify,
|
|
135
138
|
titleId,
|
|
@@ -137,8 +140,11 @@ export {
|
|
|
137
140
|
toDateString,
|
|
138
141
|
toErrorList,
|
|
139
142
|
toErrorSchema,
|
|
143
|
+
toFieldPathId,
|
|
140
144
|
unwrapErrorHandler,
|
|
141
145
|
utcToLocal,
|
|
142
146
|
validationDataMerge,
|
|
143
147
|
withIdRefPrefix,
|
|
144
148
|
};
|
|
149
|
+
|
|
150
|
+
export type { ComponentUpdateStrategy } from './shouldRender';
|
|
@@ -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
|
-
|
|
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
|
-
((!
|
|
105
|
+
((!(defaults === undefined) && isNil(formData)) || (typeof formData === 'number' && isNaN(formData)))) ||
|
|
92
106
|
(overrideFormDataWithDefaults && !isNil(formData))
|
|
93
107
|
) {
|
|
94
108
|
return defaults;
|
|
@@ -22,7 +22,7 @@ export const NOT_FOUND_SCHEMA = { title: '!@#$_UNKNOWN_$#@!' };
|
|
|
22
22
|
*
|
|
23
23
|
* @param validator - An implementation of the `ValidatorType` interface that will be forwarded to all the APIs
|
|
24
24
|
* @param rootSchema - The root schema that will be forwarded to all the APIs
|
|
25
|
-
|
|
25
|
+
* @param schema - The node within the JSON schema in which to search
|
|
26
26
|
* @param path - The keys in the path to the desired field
|
|
27
27
|
* @param [formData={}] - The form data that is used to determine which anyOf/oneOf option to descend
|
|
28
28
|
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
@@ -84,6 +84,24 @@ export function getInnerSchemaForArrayItem<S extends StrictRJSFSchema = RJSFSche
|
|
|
84
84
|
return {} as S;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/** Checks if the given `schema` contains the `null` type along with another type AND if the `default` contained within
|
|
88
|
+
* the schema is `null` AND the `computedDefault` is empty. If all of those conditions are true, then the `schema`'s
|
|
89
|
+
* default should be `null` rather than `computedDefault`.
|
|
90
|
+
*
|
|
91
|
+
* @param schema - The schema to inspect
|
|
92
|
+
* @param computedDefault - The computed default for the schema
|
|
93
|
+
* @returns - Flag indicating whether a null should be returned instead of the computedDefault
|
|
94
|
+
*/
|
|
95
|
+
export function computeDefaultBasedOnSchemaTypeAndDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema>(
|
|
96
|
+
schema: S,
|
|
97
|
+
computedDefault: T,
|
|
98
|
+
) {
|
|
99
|
+
const { default: schemaDefault, type } = schema;
|
|
100
|
+
const shouldReturnNullAsDefault =
|
|
101
|
+
Array.isArray(type) && type.includes('null') && isEmpty(computedDefault) && schemaDefault === null;
|
|
102
|
+
return shouldReturnNullAsDefault ? (null as T) : computedDefault;
|
|
103
|
+
}
|
|
104
|
+
|
|
87
105
|
/** Either add `computedDefault` at `key` into `obj` or not add it based on its value, the value of
|
|
88
106
|
* `includeUndefinedValues`, the value of `emptyObjectFields` and if its parent field is required. Generally undefined
|
|
89
107
|
* `computedDefault` values are added only when `includeUndefinedValues` is either true/"excludeObjectChildren". If `
|
|
@@ -115,10 +133,18 @@ function maybeAddDefaultToObject<T = any>(
|
|
|
115
133
|
isConst = false,
|
|
116
134
|
) {
|
|
117
135
|
const { emptyObjectFields = 'populateAllDefaults' } = experimental_defaultFormStateBehavior;
|
|
118
|
-
|
|
119
|
-
|
|
136
|
+
|
|
137
|
+
if (includeUndefinedValues === true || isConst) {
|
|
138
|
+
// If includeUndefinedValues is explicitly true
|
|
120
139
|
// Or if the schema has a const property defined, then we should always return the computedDefault since it's coming from the const.
|
|
121
140
|
obj[key] = computedDefault;
|
|
141
|
+
} else if (includeUndefinedValues === 'excludeObjectChildren') {
|
|
142
|
+
// Fix for Issue #4709: When in 'excludeObjectChildren' mode, don't set primitive fields to empty objects
|
|
143
|
+
// Only add the computed default if it's not an empty object placeholder for a primitive field
|
|
144
|
+
if (!isObject(computedDefault) || !isEmpty(computedDefault)) {
|
|
145
|
+
obj[key] = computedDefault;
|
|
146
|
+
}
|
|
147
|
+
// If computedDefault is an empty object {}, don't add it - let the field stay undefined
|
|
122
148
|
} else if (emptyObjectFields !== 'skipDefaults') {
|
|
123
149
|
// If isParentRequired is undefined, then we are at the root level of the schema so defer to the requiredness of
|
|
124
150
|
// the field key itself in the `requiredField` list
|
|
@@ -204,7 +230,7 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
204
230
|
required,
|
|
205
231
|
shouldMergeDefaultsIntoFormData = false,
|
|
206
232
|
} = computeDefaultsProps;
|
|
207
|
-
|
|
233
|
+
let formData: T = (isObject(rawFormData) ? rawFormData : {}) as T;
|
|
208
234
|
const schema: S = isObject(rawSchema) ? rawSchema : ({} as S);
|
|
209
235
|
// Compute the defaults recursively: give highest priority to deepest nodes.
|
|
210
236
|
let defaults: T | T[] | undefined = parentDefaults;
|
|
@@ -212,9 +238,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
212
238
|
let schemaToCompute: S | null = null;
|
|
213
239
|
let experimental_dfsb_to_compute = experimental_defaultFormStateBehavior;
|
|
214
240
|
let updatedRecurseList = _recurseList;
|
|
215
|
-
|
|
216
241
|
if (
|
|
217
|
-
schema[CONST_KEY] &&
|
|
242
|
+
schema[CONST_KEY] !== undefined &&
|
|
218
243
|
experimental_defaultFormStateBehavior?.constAsDefaults !== 'never' &&
|
|
219
244
|
!constIsAjvDataReference(schema)
|
|
220
245
|
) {
|
|
@@ -240,6 +265,13 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
240
265
|
if (schemaToCompute && !defaults) {
|
|
241
266
|
defaults = schema.default as T | undefined;
|
|
242
267
|
}
|
|
268
|
+
|
|
269
|
+
// If shouldMergeDefaultsIntoFormData is true
|
|
270
|
+
// And the schemaToCompute is set and the rawFormData is not an object
|
|
271
|
+
// Then set the formData to the rawFormData
|
|
272
|
+
if (shouldMergeDefaultsIntoFormData && schemaToCompute && !isObject(rawFormData)) {
|
|
273
|
+
formData = rawFormData as T;
|
|
274
|
+
}
|
|
243
275
|
} else if (DEPENDENCIES_KEY in schema) {
|
|
244
276
|
// Get the default if set from properties to ensure the dependencies conditions are resolved based on it
|
|
245
277
|
const defaultFormData: T = {
|
|
@@ -328,7 +360,7 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
328
360
|
experimental_defaultFormStateBehavior: experimental_dfsb_to_compute,
|
|
329
361
|
experimental_customMergeAllOf,
|
|
330
362
|
parentDefaults: defaults as T | undefined,
|
|
331
|
-
rawFormData: formData as T,
|
|
363
|
+
rawFormData: (rawFormData ?? formData) as T,
|
|
332
364
|
required,
|
|
333
365
|
shouldMergeDefaultsIntoFormData,
|
|
334
366
|
});
|
|
@@ -432,7 +464,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
432
464
|
required,
|
|
433
465
|
shouldMergeDefaultsIntoFormData,
|
|
434
466
|
}: ComputeDefaultsProps<T, S> = {},
|
|
435
|
-
defaults?: T | T[]
|
|
467
|
+
defaults?: T | T[],
|
|
436
468
|
): T {
|
|
437
469
|
{
|
|
438
470
|
const formData: T = (isObject(rawFormData) ? rawFormData : {}) as T;
|
|
@@ -467,6 +499,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
467
499
|
required: retrievedSchema.required?.includes(key),
|
|
468
500
|
shouldMergeDefaultsIntoFormData,
|
|
469
501
|
});
|
|
502
|
+
|
|
470
503
|
maybeAddDefaultToObject<T>(
|
|
471
504
|
acc,
|
|
472
505
|
key,
|
|
@@ -477,6 +510,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
477
510
|
experimental_defaultFormStateBehavior,
|
|
478
511
|
hasConst,
|
|
479
512
|
);
|
|
513
|
+
|
|
480
514
|
return acc;
|
|
481
515
|
},
|
|
482
516
|
{},
|
|
@@ -523,7 +557,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
523
557
|
);
|
|
524
558
|
});
|
|
525
559
|
}
|
|
526
|
-
return objectDefaults;
|
|
560
|
+
return computeDefaultBasedOnSchemaTypeAndDefaults<T, S>(rawSchema, objectDefaults);
|
|
527
561
|
}
|
|
528
562
|
}
|
|
529
563
|
|
|
@@ -547,8 +581,8 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
547
581
|
required,
|
|
548
582
|
shouldMergeDefaultsIntoFormData,
|
|
549
583
|
}: ComputeDefaultsProps<T, S> = {},
|
|
550
|
-
defaults?: T
|
|
551
|
-
): T
|
|
584
|
+
defaults?: T[],
|
|
585
|
+
): T[] | undefined {
|
|
552
586
|
const schema: S = rawSchema;
|
|
553
587
|
|
|
554
588
|
const arrayMinItemsStateBehavior = experimental_defaultFormStateBehavior?.arrayMinItems ?? {};
|
|
@@ -560,7 +594,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
560
594
|
const computeSkipPopulate = arrayMinItemsStateBehavior?.computeSkipPopulate ?? (() => false);
|
|
561
595
|
const isSkipEmptyDefaults = experimental_defaultFormStateBehavior?.emptyObjectFields === 'skipEmptyDefaults';
|
|
562
596
|
|
|
563
|
-
const emptyDefault = isSkipEmptyDefaults ? undefined : [];
|
|
597
|
+
const emptyDefault: T[] | undefined = isSkipEmptyDefaults ? undefined : [];
|
|
564
598
|
|
|
565
599
|
// Inject defaults into existing array defaults
|
|
566
600
|
if (Array.isArray(defaults)) {
|
|
@@ -582,7 +616,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
582
616
|
if (Array.isArray(rawFormData)) {
|
|
583
617
|
const schemaItem: S = getInnerSchemaForArrayItem<S>(schema);
|
|
584
618
|
if (neverPopulate) {
|
|
585
|
-
defaults = rawFormData;
|
|
619
|
+
defaults = rawFormData as typeof defaults;
|
|
586
620
|
} else {
|
|
587
621
|
const itemDefaults = rawFormData.map((item: T, idx: number) => {
|
|
588
622
|
return computeDefaults<T, S, F>(validator, schemaItem, {
|
|
@@ -619,6 +653,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
619
653
|
}
|
|
620
654
|
}
|
|
621
655
|
|
|
656
|
+
let arrayDefault: T[] | undefined;
|
|
622
657
|
const defaultsLength = Array.isArray(defaults) ? defaults.length : 0;
|
|
623
658
|
if (
|
|
624
659
|
!schema.minItems ||
|
|
@@ -626,27 +661,29 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
626
661
|
computeSkipPopulate<T, S, F>(validator, schema, rootSchema) ||
|
|
627
662
|
schema.minItems <= defaultsLength
|
|
628
663
|
) {
|
|
629
|
-
|
|
664
|
+
arrayDefault = defaults ? defaults : emptyDefault;
|
|
665
|
+
} else {
|
|
666
|
+
const defaultEntries: T[] = (defaults || []) as T[];
|
|
667
|
+
const fillerSchema: S = getInnerSchemaForArrayItem<S>(schema, AdditionalItemsHandling.Invert);
|
|
668
|
+
const fillerDefault = fillerSchema.default;
|
|
669
|
+
|
|
670
|
+
// Calculate filler entries for remaining items (minItems - existing raw data/defaults)
|
|
671
|
+
const fillerEntries: T[] = Array.from({ length: schema.minItems - defaultsLength }, () =>
|
|
672
|
+
computeDefaults<any, S, F>(validator, fillerSchema, {
|
|
673
|
+
parentDefaults: fillerDefault,
|
|
674
|
+
rootSchema,
|
|
675
|
+
_recurseList,
|
|
676
|
+
experimental_defaultFormStateBehavior,
|
|
677
|
+
experimental_customMergeAllOf,
|
|
678
|
+
required,
|
|
679
|
+
shouldMergeDefaultsIntoFormData,
|
|
680
|
+
}),
|
|
681
|
+
) as T[];
|
|
682
|
+
// then fill up the rest with either the item default or empty, up to minItems
|
|
683
|
+
arrayDefault = defaultEntries.concat(fillerEntries);
|
|
630
684
|
}
|
|
631
685
|
|
|
632
|
-
|
|
633
|
-
const fillerSchema: S = getInnerSchemaForArrayItem<S>(schema, AdditionalItemsHandling.Invert);
|
|
634
|
-
const fillerDefault = fillerSchema.default;
|
|
635
|
-
|
|
636
|
-
// Calculate filler entries for remaining items (minItems - existing raw data/defaults)
|
|
637
|
-
const fillerEntries: T[] = new Array(schema.minItems - defaultsLength).fill(
|
|
638
|
-
computeDefaults<any, S, F>(validator, fillerSchema, {
|
|
639
|
-
parentDefaults: fillerDefault,
|
|
640
|
-
rootSchema,
|
|
641
|
-
_recurseList,
|
|
642
|
-
experimental_defaultFormStateBehavior,
|
|
643
|
-
experimental_customMergeAllOf,
|
|
644
|
-
required,
|
|
645
|
-
shouldMergeDefaultsIntoFormData,
|
|
646
|
-
}),
|
|
647
|
-
) as T[];
|
|
648
|
-
// then fill up the rest with either the item default or empty, up to minItems
|
|
649
|
-
return defaultEntries.concat(fillerEntries);
|
|
686
|
+
return computeDefaultBasedOnSchemaTypeAndDefaults<T[] | undefined, S>(rawSchema, arrayDefault);
|
|
650
687
|
}
|
|
651
688
|
|
|
652
689
|
/** Computes the default value based on the schema type.
|
|
@@ -673,7 +710,7 @@ export function getDefaultBasedOnSchemaType<
|
|
|
673
710
|
return getObjectDefaults(validator, rawSchema, computeDefaultsProps, defaults);
|
|
674
711
|
}
|
|
675
712
|
case 'array': {
|
|
676
|
-
return getArrayDefaults(validator, rawSchema, computeDefaultsProps, defaults);
|
|
713
|
+
return getArrayDefaults(validator, rawSchema, computeDefaultsProps, defaults as T[]);
|
|
677
714
|
}
|
|
678
715
|
}
|
|
679
716
|
}
|
|
@@ -722,6 +759,13 @@ export default function getDefaultFormState<
|
|
|
722
759
|
shouldMergeDefaultsIntoFormData: true,
|
|
723
760
|
});
|
|
724
761
|
|
|
762
|
+
if (schema.type !== 'object' && isObject(schema.default)) {
|
|
763
|
+
return {
|
|
764
|
+
...defaults,
|
|
765
|
+
...formData,
|
|
766
|
+
} as T;
|
|
767
|
+
}
|
|
768
|
+
|
|
725
769
|
// If the formData is an object or an array, add additional properties from formData and override formData with
|
|
726
770
|
// defaults since the defaults are already merged with formData.
|
|
727
771
|
if (isObject(formData) || Array.isArray(formData)) {
|
|
@@ -52,10 +52,10 @@ export default function getDisplayLabel<
|
|
|
52
52
|
if (schemaType === 'object') {
|
|
53
53
|
displayLabel = false;
|
|
54
54
|
}
|
|
55
|
-
if (schemaType === 'boolean' && !uiSchema[UI_WIDGET_KEY]) {
|
|
55
|
+
if (schemaType === 'boolean' && uiSchema && !uiSchema[UI_WIDGET_KEY]) {
|
|
56
56
|
displayLabel = false;
|
|
57
57
|
}
|
|
58
|
-
if (uiSchema[UI_FIELD_KEY]) {
|
|
58
|
+
if (uiSchema && uiSchema[UI_FIELD_KEY]) {
|
|
59
59
|
displayLabel = false;
|
|
60
60
|
}
|
|
61
61
|
return displayLabel;
|
package/src/schema/index.ts
CHANGED
|
@@ -10,7 +10,6 @@ import isMultiSelect from './isMultiSelect';
|
|
|
10
10
|
import isSelect from './isSelect';
|
|
11
11
|
import retrieveSchema from './retrieveSchema';
|
|
12
12
|
import sanitizeDataForNewSchema from './sanitizeDataForNewSchema';
|
|
13
|
-
import toIdSchema from './toIdSchema';
|
|
14
13
|
import toPathSchema from './toPathSchema';
|
|
15
14
|
|
|
16
15
|
export {
|
|
@@ -26,6 +25,5 @@ export {
|
|
|
26
25
|
isSelect,
|
|
27
26
|
retrieveSchema,
|
|
28
27
|
sanitizeDataForNewSchema,
|
|
29
|
-
toIdSchema,
|
|
30
28
|
toPathSchema,
|
|
31
29
|
};
|
|
@@ -241,6 +241,7 @@ export function resolveSchema<T = any, S extends StrictRJSFSchema = RJSFSchema,
|
|
|
241
241
|
expandAllBranches,
|
|
242
242
|
recurseList,
|
|
243
243
|
formData,
|
|
244
|
+
experimental_customMergeAllOf,
|
|
244
245
|
);
|
|
245
246
|
if (updatedSchemas.length > 1 || updatedSchemas[0] !== schema) {
|
|
246
247
|
// return the updatedSchemas array if it has either multiple schemas within it
|
|
@@ -255,6 +256,7 @@ export function resolveSchema<T = any, S extends StrictRJSFSchema = RJSFSchema,
|
|
|
255
256
|
expandAllBranches,
|
|
256
257
|
recurseList,
|
|
257
258
|
formData,
|
|
259
|
+
experimental_customMergeAllOf,
|
|
258
260
|
);
|
|
259
261
|
return resolvedSchemas.flatMap((s) => {
|
|
260
262
|
return retrieveSchemaInternal<T, S, F>(
|
|
@@ -334,7 +336,7 @@ export function resolveReference<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
334
336
|
* @param schema - The schema for which resolving all references is desired
|
|
335
337
|
* @param rootSchema - The root schema that will be forwarded to all the APIs
|
|
336
338
|
* @param recurseList - List of $refs already resolved to prevent recursion
|
|
337
|
-
* @param baseURI - The base URI to be used for resolving relative references
|
|
339
|
+
* @param [baseURI] - The base URI to be used for resolving relative references
|
|
338
340
|
* @returns - given schema will all references resolved or the original schema if no internal `$refs` were resolved
|
|
339
341
|
*/
|
|
340
342
|
export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
|
|
@@ -430,9 +432,9 @@ export function stubExistingAdditionalProperties<
|
|
|
430
432
|
if (!isEmpty(matchingProperties)) {
|
|
431
433
|
schema.properties[key] = retrieveSchema<T, S, F>(
|
|
432
434
|
validator,
|
|
433
|
-
{
|
|
435
|
+
{ [ALL_OF_KEY]: Object.values(matchingProperties) } as S,
|
|
434
436
|
rootSchema,
|
|
435
|
-
formData as T,
|
|
437
|
+
get(formData, [key]) as T,
|
|
436
438
|
experimental_customMergeAllOf,
|
|
437
439
|
);
|
|
438
440
|
set(schema.properties, [key, ADDITIONAL_PROPERTY_FLAG], true);
|
|
@@ -445,7 +447,7 @@ export function stubExistingAdditionalProperties<
|
|
|
445
447
|
if (REF_KEY in schema.additionalProperties!) {
|
|
446
448
|
additionalProperties = retrieveSchema<T, S, F>(
|
|
447
449
|
validator,
|
|
448
|
-
{
|
|
450
|
+
{ [REF_KEY]: get(schema.additionalProperties, [REF_KEY]) } as S,
|
|
449
451
|
rootSchema,
|
|
450
452
|
formData as T,
|
|
451
453
|
experimental_customMergeAllOf,
|
|
@@ -578,7 +580,7 @@ export function retrieveSchemaInternal<
|
|
|
578
580
|
validator,
|
|
579
581
|
{ allOf: [schema.properties[key], ...Object.values(matchingProperties)] } as S,
|
|
580
582
|
rootSchema,
|
|
581
|
-
rawFormData as T,
|
|
583
|
+
get(rawFormData, [key]) as T,
|
|
582
584
|
experimental_customMergeAllOf,
|
|
583
585
|
);
|
|
584
586
|
}
|