@rjsf/core 6.0.1 → 6.0.2
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/core.umd.js +78 -53
- package/dist/index.cjs +77 -50
- package/dist/index.cjs.map +4 -4
- package/dist/index.esm.js +82 -55
- package/dist/index.esm.js.map +4 -4
- package/lib/components/Form.d.ts.map +1 -1
- package/lib/components/Form.js +7 -3
- package/lib/components/constants.d.ts +5 -0
- package/lib/components/constants.d.ts.map +1 -0
- package/lib/components/constants.js +4 -0
- package/lib/components/fields/ArrayField.d.ts.map +1 -1
- package/lib/components/fields/ArrayField.js +33 -16
- package/lib/components/fields/FallbackField.d.ts.map +1 -1
- package/lib/components/fields/FallbackField.js +11 -3
- package/lib/components/fields/ObjectField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.js +7 -9
- package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldTemplate/FieldTemplate.js +2 -1
- package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxWidget.js +4 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/Form.tsx +6 -4
- package/src/components/constants.ts +5 -0
- package/src/components/fields/ArrayField.tsx +45 -29
- package/src/components/fields/FallbackField.tsx +18 -10
- package/src/components/fields/ObjectField.tsx +7 -12
- package/src/components/templates/FieldTemplate/FieldTemplate.tsx +2 -1
- package/src/components/widgets/CheckboxWidget.tsx +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rjsf/core",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "A simple React component capable of building HTML forms out of a JSON schema.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"compileReplacer": "tsc -p tsconfig.replacer.json && move-file lodashReplacer.js lodashReplacer.cjs",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"eslint": "^8.57.1",
|
|
89
89
|
"html": "^1.0.0",
|
|
90
90
|
"jsdom": "^27.0.1",
|
|
91
|
-
"mocha": "^
|
|
91
|
+
"mocha": "^11.7.4",
|
|
92
92
|
"react-portal": "^4.3.0",
|
|
93
93
|
"sinon": "^9.2.4"
|
|
94
94
|
},
|
package/src/components/Form.tsx
CHANGED
|
@@ -51,11 +51,10 @@ import _isEmpty from 'lodash/isEmpty';
|
|
|
51
51
|
import _pick from 'lodash/pick';
|
|
52
52
|
import _set from 'lodash/set';
|
|
53
53
|
import _toPath from 'lodash/toPath';
|
|
54
|
+
import _unset from 'lodash/unset';
|
|
54
55
|
|
|
55
56
|
import getDefaultRegistry from '../getDefaultRegistry';
|
|
56
|
-
|
|
57
|
-
/** Internal only symbol used by the `reset()` function to indicate that a reset operation is happening */
|
|
58
|
-
const IS_RESET = Symbol('reset');
|
|
57
|
+
import { ADDITIONAL_PROPERTY_KEY_REMOVE, IS_RESET } from './constants';
|
|
59
58
|
|
|
60
59
|
/** The properties that are passed to the `Form` */
|
|
61
60
|
export interface FormProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
|
|
@@ -875,7 +874,10 @@ export default class Form<
|
|
|
875
874
|
let retrievedSchema = this.state.retrievedSchema;
|
|
876
875
|
let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
|
|
877
876
|
if (isObject(formData) || Array.isArray(formData)) {
|
|
878
|
-
if (
|
|
877
|
+
if (newValue === ADDITIONAL_PROPERTY_KEY_REMOVE) {
|
|
878
|
+
// For additional properties, we were given the special remove this key value, so unset it
|
|
879
|
+
_unset(formData, path);
|
|
880
|
+
} else if (!isRootPath) {
|
|
879
881
|
// If the newValue is not on the root path, then set it into the form data
|
|
880
882
|
_set(formData, path, newValue);
|
|
881
883
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Internal only symbol used by `Form` & `ObjectField` to mark an additional property element to be removed */
|
|
2
|
+
export const ADDITIONAL_PROPERTY_KEY_REMOVE = Symbol('remove-this-key');
|
|
3
|
+
|
|
4
|
+
/** Internal only symbol used by the `reset()` function to indicate that a reset operation is happening */
|
|
5
|
+
export const IS_RESET = Symbol('reset');
|
|
@@ -153,9 +153,12 @@ function getNewFormDataRow<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
153
153
|
registry: Registry<T[], S, F>,
|
|
154
154
|
schema: S,
|
|
155
155
|
): T {
|
|
156
|
-
const { schemaUtils } = registry;
|
|
156
|
+
const { schemaUtils, globalFormOptions } = registry;
|
|
157
157
|
let itemSchema = schema.items as S;
|
|
158
|
-
if (
|
|
158
|
+
if (globalFormOptions.useFallbackUiForUnsupportedType && !itemSchema) {
|
|
159
|
+
// If we don't have itemSchema and useFallbackUiForUnsupportedType is on, use an empty schema
|
|
160
|
+
itemSchema = {} as S;
|
|
161
|
+
} else if (isFixedItems(schema) && allowAdditionalItems(schema)) {
|
|
159
162
|
itemSchema = schema.additionalItems as S;
|
|
160
163
|
}
|
|
161
164
|
// Cast this as a T to work around schema utils being for T[] caused by the FieldProps<T[], S, F> call on the class
|
|
@@ -840,7 +843,7 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
840
843
|
props: FieldProps<T[], S, F>,
|
|
841
844
|
) {
|
|
842
845
|
const { schema, uiSchema, errorSchema, fieldPathId, registry, formData, onChange } = props;
|
|
843
|
-
const { schemaUtils, translateString } = registry;
|
|
846
|
+
const { globalFormOptions, schemaUtils, translateString } = registry;
|
|
844
847
|
const { keyedFormData, updateKeyedFormData } = useKeyedFormData<T>(formData);
|
|
845
848
|
// All the children will use childFieldPathId if present in the props, falling back to the fieldPathId
|
|
846
849
|
const childFieldPathId = props.childFieldPathId ?? fieldPathId;
|
|
@@ -1027,24 +1030,14 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
1027
1030
|
[onChange, childFieldPathId],
|
|
1028
1031
|
);
|
|
1029
1032
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
return (
|
|
1039
|
-
<UnsupportedFieldTemplate
|
|
1040
|
-
schema={schema}
|
|
1041
|
-
fieldPathId={fieldPathId}
|
|
1042
|
-
reason={translateString(TranslatableString.MissingItems)}
|
|
1043
|
-
registry={registry}
|
|
1044
|
-
/>
|
|
1045
|
-
);
|
|
1046
|
-
}
|
|
1047
|
-
const arrayProps = {
|
|
1033
|
+
const arrayAsMultiProps: ArrayAsFieldProps<T[], S, F> = {
|
|
1034
|
+
...props,
|
|
1035
|
+
formData,
|
|
1036
|
+
fieldPathId: childFieldPathId,
|
|
1037
|
+
onSelectChange: onSelectChange,
|
|
1038
|
+
};
|
|
1039
|
+
const arrayProps: InternalArrayFieldProps<T, S, F> = {
|
|
1040
|
+
...props,
|
|
1048
1041
|
handleAddItem,
|
|
1049
1042
|
handleCopyItem,
|
|
1050
1043
|
handleRemoveItem,
|
|
@@ -1052,18 +1045,41 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
1052
1045
|
keyedFormData,
|
|
1053
1046
|
onChange: handleChange,
|
|
1054
1047
|
};
|
|
1055
|
-
if (
|
|
1048
|
+
if (!(ITEMS_KEY in schema)) {
|
|
1049
|
+
if (!globalFormOptions.useFallbackUiForUnsupportedType) {
|
|
1050
|
+
const uiOptions = getUiOptions<T[], S, F>(uiSchema);
|
|
1051
|
+
const UnsupportedFieldTemplate = getTemplate<'UnsupportedFieldTemplate', T[], S, F>(
|
|
1052
|
+
'UnsupportedFieldTemplate',
|
|
1053
|
+
registry,
|
|
1054
|
+
uiOptions,
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
return (
|
|
1058
|
+
<UnsupportedFieldTemplate
|
|
1059
|
+
schema={schema}
|
|
1060
|
+
fieldPathId={fieldPathId}
|
|
1061
|
+
reason={translateString(TranslatableString.MissingItems)}
|
|
1062
|
+
registry={registry}
|
|
1063
|
+
/>
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
// Add an items schema with type as undefined so it triggers FallbackField later on
|
|
1067
|
+
const fallbackSchema = { ...schema, [ITEMS_KEY]: { type: undefined } };
|
|
1068
|
+
arrayAsMultiProps.schema = fallbackSchema;
|
|
1069
|
+
arrayProps.schema = fallbackSchema;
|
|
1070
|
+
}
|
|
1071
|
+
if (schemaUtils.isMultiSelect(arrayAsMultiProps.schema)) {
|
|
1056
1072
|
// If array has enum or uniqueItems set to true, call renderMultiSelect() to render the default multiselect widget or a custom widget, if specified.
|
|
1057
|
-
return <ArrayAsMultiSelect<T, S, F> {...
|
|
1073
|
+
return <ArrayAsMultiSelect<T, S, F> {...arrayAsMultiProps} />;
|
|
1058
1074
|
}
|
|
1059
1075
|
if (isCustomWidget<T[], S, F>(uiSchema)) {
|
|
1060
|
-
return <ArrayAsCustomWidget<T, S, F> {...
|
|
1076
|
+
return <ArrayAsCustomWidget<T, S, F> {...arrayAsMultiProps} />;
|
|
1061
1077
|
}
|
|
1062
|
-
if (isFixedItems(schema)) {
|
|
1063
|
-
return <FixedArray<T, S, F> {...
|
|
1078
|
+
if (isFixedItems(arrayAsMultiProps.schema)) {
|
|
1079
|
+
return <FixedArray<T, S, F> {...arrayProps} />;
|
|
1064
1080
|
}
|
|
1065
|
-
if (schemaUtils.isFilesArray(schema, uiSchema)) {
|
|
1066
|
-
return <ArrayAsFiles
|
|
1081
|
+
if (schemaUtils.isFilesArray(arrayAsMultiProps.schema, uiSchema)) {
|
|
1082
|
+
return <ArrayAsFiles<T, S, F> {...arrayAsMultiProps} />;
|
|
1067
1083
|
}
|
|
1068
|
-
return <NormalArray<T, S, F> {...
|
|
1084
|
+
return <NormalArray<T, S, F> {...arrayProps} />;
|
|
1069
1085
|
}
|
|
@@ -21,7 +21,7 @@ import { JSONSchema7TypeName } from 'json-schema';
|
|
|
21
21
|
function getFallbackTypeSelectionSchema(title: string): RJSFSchema {
|
|
22
22
|
return {
|
|
23
23
|
type: 'string',
|
|
24
|
-
enum: ['string', 'number', 'boolean'],
|
|
24
|
+
enum: ['string', 'number', 'boolean', 'object', 'array'],
|
|
25
25
|
default: 'string',
|
|
26
26
|
title: title,
|
|
27
27
|
};
|
|
@@ -36,6 +36,9 @@ function getTypeOfFormData(formData: any): JSONSchema7TypeName {
|
|
|
36
36
|
if (dataType === 'string' || dataType === 'number' || dataType === 'boolean') {
|
|
37
37
|
return dataType;
|
|
38
38
|
}
|
|
39
|
+
if (dataType === 'object') {
|
|
40
|
+
return Array.isArray(formData) ? 'array' : 'object';
|
|
41
|
+
}
|
|
39
42
|
// Treat everything else as a string
|
|
40
43
|
return 'string';
|
|
41
44
|
}
|
|
@@ -106,20 +109,14 @@ export default function FallbackField<
|
|
|
106
109
|
};
|
|
107
110
|
|
|
108
111
|
if (!globalFormOptions.useFallbackUiForUnsupportedType) {
|
|
112
|
+
const { reason = translateString(TranslatableString.UnknownFieldType, [String(schema.type)]) } = props;
|
|
109
113
|
const UnsupportedFieldTemplate = getTemplate<'UnsupportedFieldTemplate', T, S, F>(
|
|
110
114
|
'UnsupportedFieldTemplate',
|
|
111
115
|
registry,
|
|
112
116
|
uiOptions,
|
|
113
117
|
);
|
|
114
118
|
|
|
115
|
-
return
|
|
116
|
-
<UnsupportedFieldTemplate
|
|
117
|
-
schema={schema}
|
|
118
|
-
fieldPathId={fieldPathId}
|
|
119
|
-
reason={translateString(TranslatableString.UnknownFieldType, [String(schema.type)])}
|
|
120
|
-
registry={registry}
|
|
121
|
-
/>
|
|
122
|
-
);
|
|
119
|
+
return <UnsupportedFieldTemplate schema={schema} fieldPathId={fieldPathId} reason={reason} registry={registry} />;
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
const FallbackFieldTemplate = getTemplate<'FallbackFieldTemplate', T, S, F>(
|
|
@@ -151,7 +148,18 @@ export default function FallbackField<
|
|
|
151
148
|
required={required}
|
|
152
149
|
/>
|
|
153
150
|
}
|
|
154
|
-
schemaField={
|
|
151
|
+
schemaField={
|
|
152
|
+
<SchemaField
|
|
153
|
+
{...props}
|
|
154
|
+
schema={
|
|
155
|
+
{
|
|
156
|
+
type,
|
|
157
|
+
title: translateString(TranslatableString.Value),
|
|
158
|
+
...(type === 'object' && { additionalProperties: true }),
|
|
159
|
+
} as S
|
|
160
|
+
}
|
|
161
|
+
/>
|
|
162
|
+
}
|
|
155
163
|
/>
|
|
156
164
|
);
|
|
157
165
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
ANY_OF_KEY,
|
|
5
5
|
getTemplate,
|
|
6
6
|
getUiOptions,
|
|
7
|
-
hashObject,
|
|
8
7
|
isFormDataAvailable,
|
|
9
8
|
orderProperties,
|
|
10
9
|
shouldRenderOptionalField,
|
|
@@ -29,7 +28,8 @@ import get from 'lodash/get';
|
|
|
29
28
|
import has from 'lodash/has';
|
|
30
29
|
import isObject from 'lodash/isObject';
|
|
31
30
|
import set from 'lodash/set';
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
import { ADDITIONAL_PROPERTY_KEY_REMOVE } from '../constants';
|
|
33
33
|
|
|
34
34
|
/** Returns a flag indicating whether the `name` field is required in the object schema
|
|
35
35
|
*
|
|
@@ -220,7 +220,6 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
220
220
|
const schema: S = schemaUtils.retrieveSchema(rawSchema, formData, true);
|
|
221
221
|
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
|
|
222
222
|
const { properties: schemaProperties = {} } = schema;
|
|
223
|
-
const formDataHash = hashObject(formData || {});
|
|
224
223
|
// All the children will use childFieldPathId if present in the props, falling back to the fieldPathId
|
|
225
224
|
const childFieldPathId = props.childFieldPathId ?? fieldPathId;
|
|
226
225
|
|
|
@@ -320,15 +319,14 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
320
319
|
[formData, onChange, childFieldPathId, getAvailableKey],
|
|
321
320
|
);
|
|
322
321
|
|
|
323
|
-
/** Handles the remove click which
|
|
322
|
+
/** Handles the remove click which calls the `onChange` callback with the special ADDITIONAL_PROPERTY_FIELD_REMOVE
|
|
323
|
+
* value for the path plus the key to be removed
|
|
324
324
|
*/
|
|
325
325
|
const handleRemoveProperty = useCallback(
|
|
326
326
|
(key: string) => {
|
|
327
|
-
|
|
328
|
-
unset(copiedFormData, key);
|
|
329
|
-
onChange(copiedFormData, childFieldPathId.path);
|
|
327
|
+
onChange(ADDITIONAL_PROPERTY_KEY_REMOVE as T, [...childFieldPathId.path, key]);
|
|
330
328
|
},
|
|
331
|
-
[onChange, childFieldPathId
|
|
329
|
+
[onChange, childFieldPathId],
|
|
332
330
|
);
|
|
333
331
|
|
|
334
332
|
if (!renderOptionalField || hasFormData) {
|
|
@@ -364,10 +362,7 @@ export default function ObjectField<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
364
362
|
const hidden = getUiOptions<T, S, F>(fieldUiSchema).widget === 'hidden';
|
|
365
363
|
const content = (
|
|
366
364
|
<ObjectFieldProperty<T, S, F>
|
|
367
|
-
|
|
368
|
-
// name and the hash of the formData so that react rerenders the components with the updated additional
|
|
369
|
-
// property related callback which will change due to formData changes
|
|
370
|
-
key={addedByAdditionalProperties ? `${name}-${formDataHash}` : name}
|
|
365
|
+
key={name}
|
|
371
366
|
propertyName={name}
|
|
372
367
|
required={isRequired<S>(schema, name)}
|
|
373
368
|
schema={get(schema, [PROPERTIES_KEY, name], {}) as S}
|
|
@@ -29,9 +29,10 @@ export default function FieldTemplate<
|
|
|
29
29
|
if (hidden) {
|
|
30
30
|
return <div className='hidden'>{children}</div>;
|
|
31
31
|
}
|
|
32
|
+
const isCheckbox = uiOptions.widget === 'checkbox';
|
|
32
33
|
return (
|
|
33
34
|
<WrapIfAdditionalTemplate {...props}>
|
|
34
|
-
{displayLabel && <Label label={label} required={required} id={id} />}
|
|
35
|
+
{displayLabel && !isCheckbox && <Label label={label} required={required} id={id} />}
|
|
35
36
|
{displayLabel && description ? description : null}
|
|
36
37
|
{children}
|
|
37
38
|
{errors}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
RJSFSchema,
|
|
10
10
|
StrictRJSFSchema,
|
|
11
11
|
WidgetProps,
|
|
12
|
+
getUiOptions,
|
|
12
13
|
} from '@rjsf/utils';
|
|
13
14
|
|
|
14
15
|
/** The `CheckBoxWidget` is a widget for rendering boolean properties.
|
|
@@ -57,8 +58,10 @@ function CheckboxWidget<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
|
|
|
57
58
|
(event: FocusEvent<HTMLInputElement>) => onFocus(id, event.target.checked),
|
|
58
59
|
[onFocus, id],
|
|
59
60
|
);
|
|
60
|
-
const description = options.description ?? schema.description;
|
|
61
61
|
|
|
62
|
+
const uiOptions = getUiOptions(uiSchema);
|
|
63
|
+
const isCheckboxWidget = uiOptions.widget === 'checkbox';
|
|
64
|
+
const description = isCheckboxWidget ? undefined : (options.description ?? schema.description);
|
|
62
65
|
return (
|
|
63
66
|
<div className={`checkbox ${disabled || readonly ? 'disabled' : ''}`}>
|
|
64
67
|
{!hideLabel && description && (
|