@rjsf/utils 6.2.5 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +88 -4
- package/dist/index.cjs.map +3 -3
- package/dist/utils.esm.js +84 -0
- package/dist/utils.esm.js.map +3 -3
- package/dist/utils.umd.js +84 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/constants.js.map +1 -1
- package/lib/createSchemaUtils.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/parser/ParserValidator.js.map +1 -1
- package/lib/resolveUiSchema.d.ts +32 -0
- package/lib/resolveUiSchema.js +119 -0
- package/lib/resolveUiSchema.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.d.ts +18 -0
- package/package.json +3 -3
- package/src/constants.ts +1 -0
- package/src/createSchemaUtils.ts +5 -3
- package/src/index.ts +3 -0
- package/src/parser/ParserValidator.ts +5 -3
- package/src/resolveUiSchema.ts +156 -0
- package/src/types.ts +23 -2
package/lib/types.d.ts
CHANGED
|
@@ -413,6 +413,10 @@ export interface Registry<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
|
|
|
413
413
|
readonly globalFormOptions: GlobalFormOptions;
|
|
414
414
|
/** The optional global UI Options that are available for all templates, fields and widgets to access */
|
|
415
415
|
globalUiOptions?: GlobalUISchemaOptions;
|
|
416
|
+
/** The optional uiSchema definitions extracted from the root uiSchema, keyed by `$ref` paths.
|
|
417
|
+
* Used to automatically apply uiSchema when a schema with a matching `$ref` is resolved.
|
|
418
|
+
*/
|
|
419
|
+
uiSchemaDefinitions?: UiSchemaDefinitions<T, S, F>;
|
|
416
420
|
}
|
|
417
421
|
/** The properties that are passed to a `Field` implementation */
|
|
418
422
|
export interface FieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> extends GenericObjectType, RJSFBaseProps<T, S, F>, Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
|
|
@@ -892,6 +896,14 @@ export type UIOptionsType<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
|
|
|
892
896
|
* Handles both standard arrays and readonly arrays.
|
|
893
897
|
*/
|
|
894
898
|
export type ArrayElement<A> = A extends readonly (infer E)[] ? E : A;
|
|
899
|
+
/** Type describing the uiSchema definitions that can be applied to schemas referenced by `$ref`.
|
|
900
|
+
* Keys are the full `$ref` path (e.g., '#/$defs/node', '#/definitions/address').
|
|
901
|
+
* When a schema with a matching `$ref` is resolved, the corresponding uiSchema definition
|
|
902
|
+
* is automatically applied and merged with any local uiSchema overrides.
|
|
903
|
+
*/
|
|
904
|
+
export type UiSchemaDefinitions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
|
|
905
|
+
[refPath: string]: UiSchema<T, S, F>;
|
|
906
|
+
};
|
|
895
907
|
/** Type describing the well-known properties of the `UiSchema` while also supporting all user defined properties,
|
|
896
908
|
* starting with `ui:`.
|
|
897
909
|
*/
|
|
@@ -920,6 +932,12 @@ export type UiSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
920
932
|
* When using a function, it receives the item data, index, and optionally the form context as parameters.
|
|
921
933
|
*/
|
|
922
934
|
items?: UiSchema<ArrayElement<T>, S, F> | ((itemData: ArrayElement<T>, index: number, formContext?: F) => UiSchema<ArrayElement<T>, S, F>);
|
|
935
|
+
/** An object containing uiSchema definitions keyed by JSON Schema `$ref` paths.
|
|
936
|
+
* When a schema with a `$ref` is resolved, the corresponding uiSchema definition is automatically
|
|
937
|
+
* applied and merged with any local uiSchema overrides at that path.
|
|
938
|
+
* Keys must be full `$ref` paths (e.g., '#/$defs/node', '#/definitions/address').
|
|
939
|
+
*/
|
|
940
|
+
'ui:definitions'?: UiSchemaDefinitions<T, S, F>;
|
|
923
941
|
};
|
|
924
942
|
/** A `CustomValidator` function takes in a `formData`, `errors`, `uiSchema` and `errorSchema` objects and returns the given `errors`
|
|
925
943
|
* object back, while potentially adding additional messages to the `errors`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rjsf/utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"@x0k/json-schema-merge": "^1.0.2",
|
|
69
69
|
"fast-uri": "^3.1.0",
|
|
70
70
|
"jsonpointer": "^5.0.1",
|
|
71
|
-
"lodash": "^4.17.
|
|
72
|
-
"lodash-es": "^4.17.
|
|
71
|
+
"lodash": "^4.17.23",
|
|
72
|
+
"lodash-es": "^4.17.23",
|
|
73
73
|
"react-is": "^18.3.1"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
package/src/constants.ts
CHANGED
|
@@ -45,6 +45,7 @@ export const UI_FIELD_KEY = 'ui:field';
|
|
|
45
45
|
export const UI_WIDGET_KEY = 'ui:widget';
|
|
46
46
|
export const UI_OPTIONS_KEY = 'ui:options';
|
|
47
47
|
export const UI_GLOBAL_OPTIONS_KEY = 'ui:globalOptions';
|
|
48
|
+
export const UI_DEFINITIONS_KEY = 'ui:definitions';
|
|
48
49
|
|
|
49
50
|
/** The JSON Schema version strings
|
|
50
51
|
*/
|
package/src/createSchemaUtils.ts
CHANGED
|
@@ -38,9 +38,11 @@ import get from 'lodash/get';
|
|
|
38
38
|
* providing a simplified set of APIs to the `@rjsf/core` components and the various themes as well. This class
|
|
39
39
|
* implements the `SchemaUtilsType` interface.
|
|
40
40
|
*/
|
|
41
|
-
class SchemaUtils<
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
class SchemaUtils<
|
|
42
|
+
T = any,
|
|
43
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
44
|
+
F extends FormContextType = any,
|
|
45
|
+
> implements SchemaUtilsType<T, S, F> {
|
|
44
46
|
rootSchema: S;
|
|
45
47
|
validator: ValidatorType<T, S, F>;
|
|
46
48
|
experimental_defaultFormStateBehavior: Experimental_DefaultFormStateBehavior;
|
package/src/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ import pad from './pad';
|
|
|
58
58
|
import parseDateString from './parseDateString';
|
|
59
59
|
import rangeSpec from './rangeSpec';
|
|
60
60
|
import replaceStringParameters from './replaceStringParameters';
|
|
61
|
+
import resolveUiSchema, { expandUiSchemaDefinitions } from './resolveUiSchema';
|
|
61
62
|
import schemaRequiresTrueValue from './schemaRequiresTrueValue';
|
|
62
63
|
import shouldRender, { ComponentUpdateStrategy } from './shouldRender';
|
|
63
64
|
import shouldRenderOptionalField from './shouldRenderOptionalField';
|
|
@@ -152,6 +153,8 @@ export {
|
|
|
152
153
|
parseDateString,
|
|
153
154
|
rangeSpec,
|
|
154
155
|
replaceStringParameters,
|
|
156
|
+
resolveUiSchema,
|
|
157
|
+
expandUiSchemaDefinitions,
|
|
155
158
|
schemaRequiresTrueValue,
|
|
156
159
|
shallowEquals,
|
|
157
160
|
shouldRender,
|
|
@@ -29,9 +29,11 @@ export type SchemaMap<S extends StrictRJSFSchema = RJSFSchema> = {
|
|
|
29
29
|
* the hashed value of the schema. NOTE: After hashing the schema, an $id with the hash value is added to the
|
|
30
30
|
* schema IF that schema doesn't already have an $id, prior to putting the schema into the map.
|
|
31
31
|
*/
|
|
32
|
-
export default class ParserValidator<
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
export default class ParserValidator<
|
|
33
|
+
T = any,
|
|
34
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
35
|
+
F extends FormContextType = any,
|
|
36
|
+
> implements ValidatorType<T, S, F> {
|
|
35
37
|
/** The rootSchema provided during construction of the class */
|
|
36
38
|
readonly rootSchema: S;
|
|
37
39
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ADDITIONAL_PROPERTIES_KEY,
|
|
3
|
+
ALL_OF_KEY,
|
|
4
|
+
ANY_OF_KEY,
|
|
5
|
+
ITEMS_KEY,
|
|
6
|
+
ONE_OF_KEY,
|
|
7
|
+
PROPERTIES_KEY,
|
|
8
|
+
REF_KEY,
|
|
9
|
+
} from './constants';
|
|
10
|
+
import findSchemaDefinition from './findSchemaDefinition';
|
|
11
|
+
import isObject from './isObject';
|
|
12
|
+
import mergeObjects from './mergeObjects';
|
|
13
|
+
import { FormContextType, GenericObjectType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from './types';
|
|
14
|
+
|
|
15
|
+
// Keywords where child schemas map to uiSchema at the SAME key
|
|
16
|
+
const SAME_KEY_KEYWORDS = [ITEMS_KEY, ADDITIONAL_PROPERTIES_KEY] as const;
|
|
17
|
+
|
|
18
|
+
// Keywords where child schemas are in an array, each mapping to uiSchema[keyword][i]
|
|
19
|
+
const ARRAY_KEYWORDS = [ONE_OF_KEY, ANY_OF_KEY, ALL_OF_KEY] as const;
|
|
20
|
+
|
|
21
|
+
/** Expands `ui:definitions` into the uiSchema by walking the schema tree and finding all `$ref`s.
|
|
22
|
+
* Called once at form initialization to pre-expand definitions into the uiSchema structure.
|
|
23
|
+
*
|
|
24
|
+
* For recursive schemas, expansion stops at recursion points to avoid infinite loops.
|
|
25
|
+
* Runtime resolution via `resolveUiSchema` handles these cases using registry definitions.
|
|
26
|
+
*
|
|
27
|
+
* @param currentSchema - The current schema node being processed
|
|
28
|
+
* @param uiSchema - The uiSchema at the current path
|
|
29
|
+
* @param registry - The registry containing rootSchema and uiSchemaDefinitions
|
|
30
|
+
* @param visited - Set of $refs already visited (to detect recursion)
|
|
31
|
+
* @returns - The expanded uiSchema with definitions merged in
|
|
32
|
+
*/
|
|
33
|
+
export function expandUiSchemaDefinitions<
|
|
34
|
+
T = any,
|
|
35
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
36
|
+
F extends FormContextType = any,
|
|
37
|
+
>(
|
|
38
|
+
currentSchema: S,
|
|
39
|
+
uiSchema: UiSchema<T, S, F>,
|
|
40
|
+
registry: Registry<T, S, F>,
|
|
41
|
+
visited: Set<string> = new Set(),
|
|
42
|
+
): UiSchema<T, S, F> {
|
|
43
|
+
const { rootSchema, uiSchemaDefinitions: definitions } = registry;
|
|
44
|
+
let result = { ...uiSchema };
|
|
45
|
+
let resolvedSchema = currentSchema;
|
|
46
|
+
|
|
47
|
+
const ref = currentSchema[REF_KEY] as string | undefined;
|
|
48
|
+
const isRecursive = ref && visited.has(ref);
|
|
49
|
+
|
|
50
|
+
if (ref) {
|
|
51
|
+
visited.add(ref);
|
|
52
|
+
|
|
53
|
+
if (definitions && ref in definitions) {
|
|
54
|
+
result = mergeObjects(definitions[ref] as GenericObjectType, result as GenericObjectType) as UiSchema<T, S, F>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (isRecursive) {
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
resolvedSchema = findSchemaDefinition<S>(ref, rootSchema as S);
|
|
63
|
+
} catch {
|
|
64
|
+
resolvedSchema = currentSchema;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Process properties (each property maps to uiSchema[propName] - flattened)
|
|
69
|
+
const properties = resolvedSchema[PROPERTIES_KEY];
|
|
70
|
+
if (properties && isObject(properties)) {
|
|
71
|
+
for (const [propName, propSchema] of Object.entries(properties as Record<string, S>)) {
|
|
72
|
+
const propUiSchema = (result[propName] || {}) as UiSchema<T, S, F>;
|
|
73
|
+
const expanded = expandUiSchemaDefinitions(propSchema, propUiSchema, registry, new Set(visited));
|
|
74
|
+
if (Object.keys(expanded).length > 0) {
|
|
75
|
+
result[propName] = expanded;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Process keywords where child maps to same key in uiSchema (items, additionalProperties)
|
|
81
|
+
for (const keyword of SAME_KEY_KEYWORDS) {
|
|
82
|
+
const subSchema = resolvedSchema[keyword];
|
|
83
|
+
if (subSchema && isObject(subSchema) && !Array.isArray(subSchema)) {
|
|
84
|
+
const currentUiSchema = result[keyword];
|
|
85
|
+
if (typeof currentUiSchema !== 'function') {
|
|
86
|
+
const subUiSchema = ((currentUiSchema as GenericObjectType) || {}) as UiSchema<T, S, F>;
|
|
87
|
+
const expanded = expandUiSchemaDefinitions(subSchema as S, subUiSchema, registry, new Set(visited));
|
|
88
|
+
if (Object.keys(expanded).length > 0) {
|
|
89
|
+
(result as GenericObjectType)[keyword] = expanded;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Process array keywords (oneOf, anyOf, allOf) - each option maps to uiSchema[keyword][i]
|
|
96
|
+
for (const keyword of ARRAY_KEYWORDS) {
|
|
97
|
+
const schemaOptions = resolvedSchema[keyword];
|
|
98
|
+
if (Array.isArray(schemaOptions) && schemaOptions.length > 0) {
|
|
99
|
+
const currentUiSchemaArray = (result as GenericObjectType)[keyword];
|
|
100
|
+
const uiSchemaArray: UiSchema<T, S, F>[] = Array.isArray(currentUiSchemaArray) ? [...currentUiSchemaArray] : [];
|
|
101
|
+
|
|
102
|
+
let hasExpanded = false;
|
|
103
|
+
for (let i = 0; i < schemaOptions.length; i++) {
|
|
104
|
+
const optionSchema = schemaOptions[i] as S;
|
|
105
|
+
const optionUiSchema = (uiSchemaArray[i] || {}) as UiSchema<T, S, F>;
|
|
106
|
+
const expanded = expandUiSchemaDefinitions(optionSchema, optionUiSchema, registry, new Set(visited));
|
|
107
|
+
if (Object.keys(expanded).length > 0) {
|
|
108
|
+
uiSchemaArray[i] = expanded;
|
|
109
|
+
hasExpanded = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (hasExpanded) {
|
|
114
|
+
(result as GenericObjectType)[keyword] = uiSchemaArray;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Resolves the uiSchema for a given schema, considering `ui:definitions` stored in the registry.
|
|
123
|
+
*
|
|
124
|
+
* This function is called at runtime for each field. It handles recursive schemas where the
|
|
125
|
+
* pre-expansion in `expandUiSchemaDefinitions` couldn't go deeper.
|
|
126
|
+
*
|
|
127
|
+
* When the schema contains a `$ref`, this function looks up the corresponding uiSchema definition
|
|
128
|
+
* from `registry.uiSchemaDefinitions` and merges it with any local uiSchema overrides.
|
|
129
|
+
*
|
|
130
|
+
* Resolution order (later sources override earlier):
|
|
131
|
+
* 1. `ui:definitions[$ref]` - base definition from registry
|
|
132
|
+
* 2. `localUiSchema` - local overrides at current path
|
|
133
|
+
*
|
|
134
|
+
* @param schema - The JSON schema (may still contain `$ref` for recursive schemas)
|
|
135
|
+
* @param localUiSchema - The uiSchema at the current path (local overrides)
|
|
136
|
+
* @param registry - The registry containing `uiSchemaDefinitions`
|
|
137
|
+
* @returns - The resolved uiSchema with definitions merged in
|
|
138
|
+
*/
|
|
139
|
+
export default function resolveUiSchema<
|
|
140
|
+
T = any,
|
|
141
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
142
|
+
F extends FormContextType = any,
|
|
143
|
+
>(schema: S, localUiSchema: UiSchema<T, S, F> | undefined, registry: Registry<T, S, F>): UiSchema<T, S, F> {
|
|
144
|
+
const ref = schema[REF_KEY] as string | undefined;
|
|
145
|
+
const definitionUiSchema = ref ? registry.uiSchemaDefinitions?.[ref] : undefined;
|
|
146
|
+
|
|
147
|
+
if (!definitionUiSchema) {
|
|
148
|
+
return localUiSchema || {};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!localUiSchema || Object.keys(localUiSchema).length === 0) {
|
|
152
|
+
return { ...definitionUiSchema };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return mergeObjects(definitionUiSchema as GenericObjectType, localUiSchema as GenericObjectType) as UiSchema<T, S, F>;
|
|
156
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -478,11 +478,16 @@ export interface Registry<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
|
|
|
478
478
|
readonly globalFormOptions: GlobalFormOptions;
|
|
479
479
|
/** The optional global UI Options that are available for all templates, fields and widgets to access */
|
|
480
480
|
globalUiOptions?: GlobalUISchemaOptions;
|
|
481
|
+
/** The optional uiSchema definitions extracted from the root uiSchema, keyed by `$ref` paths.
|
|
482
|
+
* Used to automatically apply uiSchema when a schema with a matching `$ref` is resolved.
|
|
483
|
+
*/
|
|
484
|
+
uiSchemaDefinitions?: UiSchemaDefinitions<T, S, F>;
|
|
481
485
|
}
|
|
482
486
|
|
|
483
487
|
/** The properties that are passed to a `Field` implementation */
|
|
484
488
|
export interface FieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
|
|
485
|
-
extends
|
|
489
|
+
extends
|
|
490
|
+
GenericObjectType,
|
|
486
491
|
RJSFBaseProps<T, S, F>,
|
|
487
492
|
Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
|
|
488
493
|
/** The FieldPathId of the field in the hierarchy */
|
|
@@ -896,7 +901,8 @@ export interface MultiSchemaFieldTemplateProps<
|
|
|
896
901
|
|
|
897
902
|
/** The properties that are passed to a `Widget` implementation */
|
|
898
903
|
export interface WidgetProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
|
|
899
|
-
extends
|
|
904
|
+
extends
|
|
905
|
+
GenericObjectType,
|
|
900
906
|
RJSFBaseProps<T, S, F>,
|
|
901
907
|
Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
|
|
902
908
|
/** The generated id for this widget, used to provide unique `name`s and `id`s for the HTML field elements rendered by
|
|
@@ -1113,6 +1119,15 @@ export type UIOptionsType<
|
|
|
1113
1119
|
*/
|
|
1114
1120
|
export type ArrayElement<A> = A extends readonly (infer E)[] ? E : A;
|
|
1115
1121
|
|
|
1122
|
+
/** Type describing the uiSchema definitions that can be applied to schemas referenced by `$ref`.
|
|
1123
|
+
* Keys are the full `$ref` path (e.g., '#/$defs/node', '#/definitions/address').
|
|
1124
|
+
* When a schema with a matching `$ref` is resolved, the corresponding uiSchema definition
|
|
1125
|
+
* is automatically applied and merged with any local uiSchema overrides.
|
|
1126
|
+
*/
|
|
1127
|
+
export type UiSchemaDefinitions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
|
|
1128
|
+
[refPath: string]: UiSchema<T, S, F>;
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1116
1131
|
/** Type describing the well-known properties of the `UiSchema` while also supporting all user defined properties,
|
|
1117
1132
|
* starting with `ui:`.
|
|
1118
1133
|
*/
|
|
@@ -1148,6 +1163,12 @@ export type UiSchema<
|
|
|
1148
1163
|
items?:
|
|
1149
1164
|
| UiSchema<ArrayElement<T>, S, F>
|
|
1150
1165
|
| ((itemData: ArrayElement<T>, index: number, formContext?: F) => UiSchema<ArrayElement<T>, S, F>);
|
|
1166
|
+
/** An object containing uiSchema definitions keyed by JSON Schema `$ref` paths.
|
|
1167
|
+
* When a schema with a `$ref` is resolved, the corresponding uiSchema definition is automatically
|
|
1168
|
+
* applied and merged with any local uiSchema overrides at that path.
|
|
1169
|
+
* Keys must be full `$ref` paths (e.g., '#/$defs/node', '#/definitions/address').
|
|
1170
|
+
*/
|
|
1171
|
+
'ui:definitions'?: UiSchemaDefinitions<T, S, F>;
|
|
1151
1172
|
};
|
|
1152
1173
|
|
|
1153
1174
|
/** A `CustomValidator` function takes in a `formData`, `errors`, `uiSchema` and `errorSchema` objects and returns the given `errors`
|