@rjsf/utils 6.0.0-beta.2 → 6.0.0-beta.21
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} +396 -264
- package/dist/index.cjs.map +7 -0
- package/dist/utils.esm.js +395 -263
- package/dist/utils.esm.js.map +4 -4
- package/dist/utils.umd.js +368 -249
- package/lib/ErrorSchemaBuilder.d.ts +2 -2
- 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 +25 -18
- package/lib/createSchemaUtils.js.map +1 -1
- package/lib/enums.d.ts +9 -3
- package/lib/enums.js +9 -3
- package/lib/enums.js.map +1 -1
- 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/guessType.d.ts +1 -1
- package/lib/idGenerators.d.ts +22 -15
- package/lib/idGenerators.js +17 -8
- package/lib/idGenerators.js.map +1 -1
- package/lib/index.d.ts +10 -4
- package/lib/index.js +9 -4
- package/lib/index.js.map +1 -1
- package/lib/isFormDataAvailable.d.ts +7 -0
- package/lib/isFormDataAvailable.js +13 -0
- package/lib/isFormDataAvailable.js.map +1 -0
- package/lib/isRootSchema.d.ts +13 -0
- package/lib/isRootSchema.js +25 -0
- package/lib/isRootSchema.js.map +1 -0
- 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 +17 -3
- package/lib/schema/getDefaultFormState.js +73 -27
- 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 +11 -6
- package/lib/schema/retrieveSchema.js +42 -19
- 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/shouldRenderOptionalField.d.ts +18 -0
- package/lib/shouldRenderOptionalField.js +47 -0
- package/lib/shouldRenderOptionalField.js.map +1 -0
- 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 +136 -81
- package/lib/validationDataMerge.d.ts +2 -1
- package/lib/validationDataMerge.js +3 -2
- package/lib/validationDataMerge.js.map +1 -1
- package/package.json +13 -14
- package/src/ErrorSchemaBuilder.ts +2 -2
- package/src/constants.ts +3 -0
- package/src/createSchemaUtils.ts +25 -26
- package/src/enums.ts +9 -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 +35 -25
- package/src/index.ts +16 -2
- package/src/isFormDataAvailable.ts +13 -0
- package/src/isRootSchema.ts +30 -0
- package/src/mergeDefaultsWithFormData.ts +16 -2
- package/src/schema/findFieldInSchema.ts +1 -1
- package/src/schema/getDefaultFormState.ts +95 -33
- package/src/schema/getDisplayLabel.ts +2 -2
- package/src/schema/index.ts +0 -2
- package/src/schema/retrieveSchema.ts +46 -10
- package/src/shallowEquals.ts +41 -0
- package/src/shouldRender.ts +27 -2
- package/src/shouldRenderOptionalField.ts +56 -0
- package/src/toFieldPathId.ts +24 -0
- package/src/types.ts +156 -84
- package/src/validationDataMerge.ts +7 -1
- 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
package/src/createSchemaUtils.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
FormContextType,
|
|
6
6
|
FoundFieldType,
|
|
7
7
|
GlobalUISchemaOptions,
|
|
8
|
-
IdSchema,
|
|
9
8
|
PathSchema,
|
|
10
9
|
RJSFSchema,
|
|
11
10
|
SchemaUtilsType,
|
|
@@ -26,9 +25,11 @@ import {
|
|
|
26
25
|
isSelect,
|
|
27
26
|
retrieveSchema,
|
|
28
27
|
sanitizeDataForNewSchema,
|
|
29
|
-
toIdSchema,
|
|
30
28
|
toPathSchema,
|
|
31
29
|
} from './schema';
|
|
30
|
+
import { makeAllReferencesAbsolute } from './findSchemaDefinition';
|
|
31
|
+
import { ID_KEY, JSON_SCHEMA_DRAFT_2020_12, SCHEMA_KEY } from './constants';
|
|
32
|
+
import get from 'lodash/get';
|
|
32
33
|
|
|
33
34
|
/** The `SchemaUtils` class provides a wrapper around the publicly exported APIs in the `utils/schema` directory such
|
|
34
35
|
* that one does not have to explicitly pass the `validator`, `rootSchema`, `experimental_defaultFormStateBehavior` or
|
|
@@ -57,12 +58,24 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
57
58
|
experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior,
|
|
58
59
|
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,
|
|
59
60
|
) {
|
|
60
|
-
|
|
61
|
+
if (rootSchema && rootSchema[SCHEMA_KEY] === JSON_SCHEMA_DRAFT_2020_12) {
|
|
62
|
+
this.rootSchema = makeAllReferencesAbsolute(rootSchema, get(rootSchema, ID_KEY, '#'));
|
|
63
|
+
} else {
|
|
64
|
+
this.rootSchema = rootSchema;
|
|
65
|
+
}
|
|
61
66
|
this.validator = validator;
|
|
62
67
|
this.experimental_defaultFormStateBehavior = experimental_defaultFormStateBehavior;
|
|
63
68
|
this.experimental_customMergeAllOf = experimental_customMergeAllOf;
|
|
64
69
|
}
|
|
65
70
|
|
|
71
|
+
/** Returns the `rootSchema` in the `SchemaUtilsType`
|
|
72
|
+
*
|
|
73
|
+
* @returns - The `rootSchema`
|
|
74
|
+
*/
|
|
75
|
+
getRootSchema() {
|
|
76
|
+
return this.rootSchema;
|
|
77
|
+
}
|
|
78
|
+
|
|
66
79
|
/** Returns the `ValidatorType` in the `SchemaUtilsType`
|
|
67
80
|
*
|
|
68
81
|
* @returns - The `ValidatorType`
|
|
@@ -87,9 +100,12 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
87
100
|
experimental_defaultFormStateBehavior = {},
|
|
88
101
|
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>,
|
|
89
102
|
): boolean {
|
|
103
|
+
// If either validator or rootSchema are falsy, return false to prevent the creation
|
|
104
|
+
// of a new SchemaUtilsType with incomplete properties.
|
|
90
105
|
if (!validator || !rootSchema) {
|
|
91
106
|
return false;
|
|
92
107
|
}
|
|
108
|
+
|
|
93
109
|
return (
|
|
94
110
|
this.validator !== validator ||
|
|
95
111
|
!deepEquals(this.rootSchema, rootSchema) ||
|
|
@@ -149,12 +165,14 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
149
165
|
* @param [includeUndefinedValues=false] - Optional flag, if true, cause undefined values to be added as defaults.
|
|
150
166
|
* If "excludeObjectChildren", pass `includeUndefinedValues` as false when computing defaults for any nested
|
|
151
167
|
* object properties.
|
|
168
|
+
* @param initialDefaultsGenerated - Indicates whether or not initial defaults have been generated
|
|
152
169
|
* @returns - The resulting `formData` with all the defaults provided
|
|
153
170
|
*/
|
|
154
171
|
getDefaultFormState(
|
|
155
172
|
schema: S,
|
|
156
173
|
formData?: T,
|
|
157
174
|
includeUndefinedValues: boolean | 'excludeObjectChildren' = false,
|
|
175
|
+
initialDefaultsGenerated?: boolean,
|
|
158
176
|
): T | T[] | undefined {
|
|
159
177
|
return getDefaultFormState<T, S, F>(
|
|
160
178
|
this.validator,
|
|
@@ -164,6 +182,7 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
164
182
|
includeUndefinedValues,
|
|
165
183
|
this.experimental_defaultFormStateBehavior,
|
|
166
184
|
this.experimental_customMergeAllOf,
|
|
185
|
+
initialDefaultsGenerated,
|
|
167
186
|
);
|
|
168
187
|
}
|
|
169
188
|
|
|
@@ -285,15 +304,17 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
285
304
|
*
|
|
286
305
|
* @param schema - The schema for which retrieving a schema is desired
|
|
287
306
|
* @param [rawFormData] - The current formData, if any, to assist retrieving a schema
|
|
307
|
+
* @param [resolveAnyOfOrOneOfRefs] - Optional flag indicating whether to resolved refs in anyOf/oneOf lists
|
|
288
308
|
* @returns - The schema having its conditions, additional properties, references and dependencies resolved
|
|
289
309
|
*/
|
|
290
|
-
retrieveSchema(schema: S, rawFormData?: T) {
|
|
310
|
+
retrieveSchema(schema: S, rawFormData?: T, resolveAnyOfOrOneOfRefs?: boolean) {
|
|
291
311
|
return retrieveSchema<T, S, F>(
|
|
292
312
|
this.validator,
|
|
293
313
|
schema,
|
|
294
314
|
this.rootSchema,
|
|
295
315
|
rawFormData,
|
|
296
316
|
this.experimental_customMergeAllOf,
|
|
317
|
+
resolveAnyOfOrOneOfRefs,
|
|
297
318
|
);
|
|
298
319
|
}
|
|
299
320
|
|
|
@@ -319,28 +340,6 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
319
340
|
);
|
|
320
341
|
}
|
|
321
342
|
|
|
322
|
-
/** Generates an `IdSchema` object for the `schema`, recursively
|
|
323
|
-
*
|
|
324
|
-
* @param schema - The schema for which the display label flag is desired
|
|
325
|
-
* @param [id] - The base id for the schema
|
|
326
|
-
* @param [formData] - The current formData, if any, onto which to provide any missing defaults
|
|
327
|
-
* @param [idPrefix='root'] - The prefix to use for the id
|
|
328
|
-
* @param [idSeparator='_'] - The separator to use for the path segments in the id
|
|
329
|
-
* @returns - The `IdSchema` object for the `schema`
|
|
330
|
-
*/
|
|
331
|
-
toIdSchema(schema: S, id?: string | null, formData?: T, idPrefix = 'root', idSeparator = '_'): IdSchema<T> {
|
|
332
|
-
return toIdSchema<T, S, F>(
|
|
333
|
-
this.validator,
|
|
334
|
-
schema,
|
|
335
|
-
id,
|
|
336
|
-
this.rootSchema,
|
|
337
|
-
formData,
|
|
338
|
-
idPrefix,
|
|
339
|
-
idSeparator,
|
|
340
|
-
this.experimental_customMergeAllOf,
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
343
|
/** Generates an `PathSchema` object for the `schema`, recursively
|
|
345
344
|
*
|
|
346
345
|
* @param schema - The schema for which the display label flag is desired
|
package/src/enums.ts
CHANGED
|
@@ -45,6 +45,12 @@ export enum TranslatableString {
|
|
|
45
45
|
DecrementAriaLabel = 'Decrease value by 1',
|
|
46
46
|
/** Increment button aria label, used by UpDownWidget */
|
|
47
47
|
IncrementAriaLabel = 'Increase value by 1',
|
|
48
|
+
/** The label for the Add button in for an optional object field */
|
|
49
|
+
OptionalObjectAdd = 'Add data for optional field',
|
|
50
|
+
/** The label for the Remove button in for an optional object field */
|
|
51
|
+
OptionalObjectRemove = 'Remove data for optional field',
|
|
52
|
+
/** The label for when displaying a non-editable form with missing optional field data */
|
|
53
|
+
OptionalObjectEmptyMsg = 'No data for optional field',
|
|
48
54
|
// Strings with replaceable parameters
|
|
49
55
|
/** Unknown field type reason, where %1 will be replaced with the type as provided by SchemaField */
|
|
50
56
|
UnknownFieldType = 'Unknown field type %1',
|
|
@@ -63,7 +69,7 @@ export enum TranslatableString {
|
|
|
63
69
|
InvalidObjectField = 'Invalid "%1" object field configuration: _%2_.',
|
|
64
70
|
/** Unsupported field schema, used by UnsupportedField */
|
|
65
71
|
UnsupportedField = 'Unsupported field schema.',
|
|
66
|
-
/** Unsupported field schema, where %1 will be replaced by the
|
|
72
|
+
/** Unsupported field schema, where %1 will be replaced by the FieldPathId.$id as provided by UnsupportedField.
|
|
67
73
|
* NOTE: Use markdown notation rather than html tags.
|
|
68
74
|
*/
|
|
69
75
|
UnsupportedFieldWithId = 'Unsupported field schema for field `%1`.',
|
|
@@ -71,8 +77,8 @@ export enum TranslatableString {
|
|
|
71
77
|
* NOTE: Use markdown notation rather than html tags.
|
|
72
78
|
*/
|
|
73
79
|
UnsupportedFieldWithReason = 'Unsupported field schema: _%1_.',
|
|
74
|
-
/** Unsupported field schema, where %1 and %2 will be replaced by the
|
|
75
|
-
* as provided by UnsupportedField.
|
|
80
|
+
/** Unsupported field schema, where %1 and %2 will be replaced by the FieldPathId.$id and reason strings,
|
|
81
|
+
* respectively, as provided by UnsupportedField.
|
|
76
82
|
* NOTE: Use markdown notation rather than html tags.
|
|
77
83
|
*/
|
|
78
84
|
UnsupportedFieldWithIdAndReason = 'Unsupported field schema for field `%1`: _%2_.',
|
|
@@ -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,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 -
|
|
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
|
|
90
|
-
return idGenerator
|
|
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';
|
|
18
|
+
import getChangedFields from './getChangedFields';
|
|
17
19
|
import getDateElementProps, { type DateElementFormat } 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';
|
|
@@ -54,16 +60,16 @@ import rangeSpec from './rangeSpec';
|
|
|
54
60
|
import replaceStringParameters from './replaceStringParameters';
|
|
55
61
|
import schemaRequiresTrueValue from './schemaRequiresTrueValue';
|
|
56
62
|
import shouldRender 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';
|
|
62
70
|
import utcToLocal from './utcToLocal';
|
|
63
71
|
import validationDataMerge from './validationDataMerge';
|
|
64
72
|
import withIdRefPrefix from './withIdRefPrefix';
|
|
65
|
-
import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator';
|
|
66
|
-
import getChangedFields from './getChangedFields';
|
|
67
73
|
|
|
68
74
|
export * from './types';
|
|
69
75
|
export * from './enums';
|
|
@@ -115,13 +121,16 @@ export {
|
|
|
115
121
|
isConstant,
|
|
116
122
|
isCustomWidget,
|
|
117
123
|
isFixedItems,
|
|
124
|
+
isFormDataAvailable,
|
|
118
125
|
isObject,
|
|
126
|
+
isRootSchema,
|
|
119
127
|
labelValue,
|
|
120
128
|
localToUTC,
|
|
121
129
|
lookupFromFormContext,
|
|
122
130
|
mergeDefaultsWithFormData,
|
|
123
131
|
mergeObjects,
|
|
124
132
|
mergeSchemas,
|
|
133
|
+
optionalControlsId,
|
|
125
134
|
optionId,
|
|
126
135
|
optionsList,
|
|
127
136
|
orderProperties,
|
|
@@ -130,15 +139,20 @@ export {
|
|
|
130
139
|
rangeSpec,
|
|
131
140
|
replaceStringParameters,
|
|
132
141
|
schemaRequiresTrueValue,
|
|
142
|
+
shallowEquals,
|
|
133
143
|
shouldRender,
|
|
144
|
+
shouldRenderOptionalField,
|
|
134
145
|
sortedJSONStringify,
|
|
135
146
|
titleId,
|
|
136
147
|
toConstant,
|
|
137
148
|
toDateString,
|
|
138
149
|
toErrorList,
|
|
139
150
|
toErrorSchema,
|
|
151
|
+
toFieldPathId,
|
|
140
152
|
unwrapErrorHandler,
|
|
141
153
|
utcToLocal,
|
|
142
154
|
validationDataMerge,
|
|
143
155
|
withIdRefPrefix,
|
|
144
156
|
};
|
|
157
|
+
|
|
158
|
+
export type { ComponentUpdateStrategy } from './shouldRender';
|
|
@@ -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
|
-
|
|
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
|