@rjsf/core 6.0.1 → 6.1.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/core.umd.js +139 -91
- package/dist/index.cjs +369 -312
- package/dist/index.cjs.map +4 -4
- package/dist/index.esm.js +248 -188
- 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/RichHelp.d.ts +20 -0
- package/lib/components/RichHelp.d.ts.map +1 -0
- package/lib/components/RichHelp.js +17 -0
- 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 +39 -17
- 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/fields/StringField.d.ts.map +1 -1
- package/lib/components/fields/StringField.js +3 -3
- package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldItemTemplate.js +5 -5
- package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/AddButton.js +1 -1
- package/lib/components/templates/FieldHelpTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldHelpTemplate.js +3 -6
- package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldTemplate/FieldTemplate.js +2 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.d.ts.map +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.js +4 -2
- package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxWidget.js +4 -2
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/Form.tsx +6 -4
- package/src/components/RichHelp.tsx +46 -0
- package/src/components/constants.ts +5 -0
- package/src/components/fields/ArrayField.tsx +52 -29
- package/src/components/fields/FallbackField.tsx +18 -10
- package/src/components/fields/ObjectField.tsx +7 -12
- package/src/components/fields/StringField.tsx +3 -2
- package/src/components/templates/ArrayFieldItemTemplate.tsx +8 -11
- package/src/components/templates/ButtonTemplates/AddButton.tsx +3 -1
- package/src/components/templates/FieldHelpTemplate.tsx +5 -11
- package/src/components/templates/FieldTemplate/FieldTemplate.tsx +2 -1
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +7 -3
- package/src/components/widgets/CheckboxWidget.tsx +4 -1
- package/src/index.ts +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rjsf/core",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
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,46 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
FormContextType,
|
|
4
|
+
Registry,
|
|
5
|
+
RJSFSchema,
|
|
6
|
+
StrictRJSFSchema,
|
|
7
|
+
UiSchema,
|
|
8
|
+
getTestIds,
|
|
9
|
+
getUiOptions,
|
|
10
|
+
} from '@rjsf/utils';
|
|
11
|
+
import Markdown from 'markdown-to-jsx';
|
|
12
|
+
|
|
13
|
+
const TEST_IDS = getTestIds();
|
|
14
|
+
|
|
15
|
+
export interface RichHelpProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
|
|
16
|
+
/** The description text for a field, potentially containing markdown */
|
|
17
|
+
help: string | ReactElement;
|
|
18
|
+
/** The uiSchema object for this base component */
|
|
19
|
+
uiSchema?: UiSchema<T, S, F>;
|
|
20
|
+
/** The `registry` object */
|
|
21
|
+
registry: Registry<T, S, F>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Renders the given `description` in the props as
|
|
25
|
+
*
|
|
26
|
+
* @param props - The `RichHelpProps` for this component
|
|
27
|
+
*/
|
|
28
|
+
export default function RichHelp<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
|
|
29
|
+
help,
|
|
30
|
+
registry,
|
|
31
|
+
uiSchema = {},
|
|
32
|
+
}: RichHelpProps<T, S, F>) {
|
|
33
|
+
const { globalUiOptions } = registry;
|
|
34
|
+
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
|
|
35
|
+
|
|
36
|
+
if (uiOptions.enableMarkdownInHelp && typeof help === 'string') {
|
|
37
|
+
return (
|
|
38
|
+
<Markdown options={{ disableParsingRawHTML: true }} data-testid={TEST_IDS.markdown}>
|
|
39
|
+
{help}
|
|
40
|
+
</Markdown>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return help;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
RichHelp.TEST_IDS = TEST_IDS;
|
|
@@ -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
|
|
@@ -403,7 +406,9 @@ function ArrayFieldItem<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
|
|
|
403
406
|
handleReorderItems,
|
|
404
407
|
} = props;
|
|
405
408
|
const {
|
|
409
|
+
schemaUtils,
|
|
406
410
|
fields: { ArraySchemaField, SchemaField },
|
|
411
|
+
globalUiOptions,
|
|
407
412
|
} = registry;
|
|
408
413
|
const fieldPathId = useDeepCompareMemo<FieldPathId>(itemFieldPathId);
|
|
409
414
|
const ItemSchemaField = ArraySchemaField || SchemaField;
|
|
@@ -412,6 +417,9 @@ function ArrayFieldItem<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
|
|
|
412
417
|
registry,
|
|
413
418
|
uiOptions,
|
|
414
419
|
);
|
|
420
|
+
const displayLabel = schemaUtils.getDisplayLabel(itemSchema, itemUiSchema, globalUiOptions);
|
|
421
|
+
const { description } = getUiOptions(itemUiSchema);
|
|
422
|
+
const hasDescription = !!description || !!itemSchema.description;
|
|
415
423
|
const { orderable = true, removable = true, copyable = false } = uiOptions;
|
|
416
424
|
const has: { [key: string]: boolean } = {
|
|
417
425
|
moveUp: orderable && canMoveUp,
|
|
@@ -507,6 +515,8 @@ function ArrayFieldItem<T = any, S extends StrictRJSFSchema = RJSFSchema, F exte
|
|
|
507
515
|
schema: itemSchema,
|
|
508
516
|
uiSchema: itemUiSchema,
|
|
509
517
|
parentUiSchema,
|
|
518
|
+
displayLabel,
|
|
519
|
+
hasDescription,
|
|
510
520
|
};
|
|
511
521
|
return <ArrayFieldItemTemplate {...templateProps} />;
|
|
512
522
|
}
|
|
@@ -840,7 +850,7 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
840
850
|
props: FieldProps<T[], S, F>,
|
|
841
851
|
) {
|
|
842
852
|
const { schema, uiSchema, errorSchema, fieldPathId, registry, formData, onChange } = props;
|
|
843
|
-
const { schemaUtils, translateString } = registry;
|
|
853
|
+
const { globalFormOptions, schemaUtils, translateString } = registry;
|
|
844
854
|
const { keyedFormData, updateKeyedFormData } = useKeyedFormData<T>(formData);
|
|
845
855
|
// All the children will use childFieldPathId if present in the props, falling back to the fieldPathId
|
|
846
856
|
const childFieldPathId = props.childFieldPathId ?? fieldPathId;
|
|
@@ -1027,24 +1037,14 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
1027
1037
|
[onChange, childFieldPathId],
|
|
1028
1038
|
);
|
|
1029
1039
|
|
|
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 = {
|
|
1040
|
+
const arrayAsMultiProps: ArrayAsFieldProps<T[], S, F> = {
|
|
1041
|
+
...props,
|
|
1042
|
+
formData,
|
|
1043
|
+
fieldPathId: childFieldPathId,
|
|
1044
|
+
onSelectChange: onSelectChange,
|
|
1045
|
+
};
|
|
1046
|
+
const arrayProps: InternalArrayFieldProps<T, S, F> = {
|
|
1047
|
+
...props,
|
|
1048
1048
|
handleAddItem,
|
|
1049
1049
|
handleCopyItem,
|
|
1050
1050
|
handleRemoveItem,
|
|
@@ -1052,18 +1052,41 @@ export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSch
|
|
|
1052
1052
|
keyedFormData,
|
|
1053
1053
|
onChange: handleChange,
|
|
1054
1054
|
};
|
|
1055
|
-
if (
|
|
1055
|
+
if (!(ITEMS_KEY in schema)) {
|
|
1056
|
+
if (!globalFormOptions.useFallbackUiForUnsupportedType) {
|
|
1057
|
+
const uiOptions = getUiOptions<T[], S, F>(uiSchema);
|
|
1058
|
+
const UnsupportedFieldTemplate = getTemplate<'UnsupportedFieldTemplate', T[], S, F>(
|
|
1059
|
+
'UnsupportedFieldTemplate',
|
|
1060
|
+
registry,
|
|
1061
|
+
uiOptions,
|
|
1062
|
+
);
|
|
1063
|
+
|
|
1064
|
+
return (
|
|
1065
|
+
<UnsupportedFieldTemplate
|
|
1066
|
+
schema={schema}
|
|
1067
|
+
fieldPathId={fieldPathId}
|
|
1068
|
+
reason={translateString(TranslatableString.MissingItems)}
|
|
1069
|
+
registry={registry}
|
|
1070
|
+
/>
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
// Add an items schema with type as undefined so it triggers FallbackField later on
|
|
1074
|
+
const fallbackSchema = { ...schema, [ITEMS_KEY]: { type: undefined } };
|
|
1075
|
+
arrayAsMultiProps.schema = fallbackSchema;
|
|
1076
|
+
arrayProps.schema = fallbackSchema;
|
|
1077
|
+
}
|
|
1078
|
+
if (schemaUtils.isMultiSelect(arrayAsMultiProps.schema)) {
|
|
1056
1079
|
// 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> {...
|
|
1080
|
+
return <ArrayAsMultiSelect<T, S, F> {...arrayAsMultiProps} />;
|
|
1058
1081
|
}
|
|
1059
1082
|
if (isCustomWidget<T[], S, F>(uiSchema)) {
|
|
1060
|
-
return <ArrayAsCustomWidget<T, S, F> {...
|
|
1083
|
+
return <ArrayAsCustomWidget<T, S, F> {...arrayAsMultiProps} />;
|
|
1061
1084
|
}
|
|
1062
|
-
if (isFixedItems(schema)) {
|
|
1063
|
-
return <FixedArray<T, S, F> {...
|
|
1085
|
+
if (isFixedItems(arrayAsMultiProps.schema)) {
|
|
1086
|
+
return <FixedArray<T, S, F> {...arrayProps} />;
|
|
1064
1087
|
}
|
|
1065
|
-
if (schemaUtils.isFilesArray(schema, uiSchema)) {
|
|
1066
|
-
return <ArrayAsFiles
|
|
1088
|
+
if (schemaUtils.isFilesArray(arrayAsMultiProps.schema, uiSchema)) {
|
|
1089
|
+
return <ArrayAsFiles<T, S, F> {...arrayAsMultiProps} />;
|
|
1067
1090
|
}
|
|
1068
|
-
return <NormalArray<T, S, F> {...
|
|
1091
|
+
return <NormalArray<T, S, F> {...arrayProps} />;
|
|
1069
1092
|
}
|
|
@@ -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}
|
|
@@ -34,8 +34,9 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
34
34
|
registry,
|
|
35
35
|
rawErrors,
|
|
36
36
|
hideError,
|
|
37
|
+
title,
|
|
37
38
|
} = props;
|
|
38
|
-
const { title, format } = schema;
|
|
39
|
+
const { title: schemaTitle, format } = schema;
|
|
39
40
|
const { widgets, schemaUtils, globalUiOptions } = registry;
|
|
40
41
|
const enumOptions = schemaUtils.isSelect(schema) ? optionsList<T, S, F>(schema, uiSchema) : undefined;
|
|
41
42
|
let defaultWidget = enumOptions ? 'select' : 'text';
|
|
@@ -44,7 +45,7 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
44
45
|
}
|
|
45
46
|
const { widget = defaultWidget, placeholder = '', title: uiTitle, ...options } = getUiOptions<T, S, F>(uiSchema);
|
|
46
47
|
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
|
|
47
|
-
const label = uiTitle ?? title ?? name;
|
|
48
|
+
const label = uiTitle ?? title ?? schemaTitle ?? name;
|
|
48
49
|
const Widget = getWidget<T, S, F>(schema, widget, widgets);
|
|
49
50
|
const onWidgetChange = useCallback(
|
|
50
51
|
(value: T | undefined, errorSchema?: ErrorSchema, id?: string) => {
|
|
@@ -17,7 +17,7 @@ export default function ArrayFieldItemTemplate<
|
|
|
17
17
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
18
18
|
F extends FormContextType = any,
|
|
19
19
|
>(props: ArrayFieldItemTemplateProps<T, S, F>) {
|
|
20
|
-
const { children, className, buttonsProps, hasToolbar, registry, uiSchema } = props;
|
|
20
|
+
const { children, className, buttonsProps, displayLabel, hasDescription, hasToolbar, registry, uiSchema } = props;
|
|
21
21
|
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
22
22
|
const ArrayFieldItemButtonsTemplate = getTemplate<'ArrayFieldItemButtonsTemplate', T, S, F>(
|
|
23
23
|
'ArrayFieldItemButtonsTemplate',
|
|
@@ -30,18 +30,15 @@ export default function ArrayFieldItemTemplate<
|
|
|
30
30
|
paddingRight: 6,
|
|
31
31
|
fontWeight: 'bold',
|
|
32
32
|
};
|
|
33
|
+
const margin = hasDescription ? 31 : 9;
|
|
34
|
+
const containerStyle = { display: 'flex', alignItems: displayLabel ? 'center' : 'baseline' };
|
|
35
|
+
const toolbarStyle = { display: 'flex', justifyContent: 'flex-end', marginTop: displayLabel ? `${margin}px` : 0 };
|
|
33
36
|
return (
|
|
34
|
-
<div className={className}>
|
|
35
|
-
<div className={hasToolbar ? 'col-xs-9' : 'col-xs-12'}>{children}</div>
|
|
37
|
+
<div className={className} style={containerStyle}>
|
|
38
|
+
<div className={hasToolbar ? 'col-xs-9 col-md-10 col-xl-11' : 'col-xs-12'}>{children}</div>
|
|
36
39
|
{hasToolbar && (
|
|
37
|
-
<div className='col-xs-3 array-item-toolbox'>
|
|
38
|
-
<div
|
|
39
|
-
className='btn-group'
|
|
40
|
-
style={{
|
|
41
|
-
display: 'flex',
|
|
42
|
-
justifyContent: 'space-around',
|
|
43
|
-
}}
|
|
44
|
-
>
|
|
40
|
+
<div className='col-xs-3 col-md-2 col-xl-1 array-item-toolbox'>
|
|
41
|
+
<div className='btn-group' style={toolbarStyle}>
|
|
45
42
|
<ArrayFieldItemButtonsTemplate {...buttonsProps} style={btnStyle} />
|
|
46
43
|
</div>
|
|
47
44
|
</div>
|
|
@@ -14,7 +14,9 @@ export default function AddButton<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
14
14
|
const { translateString } = registry;
|
|
15
15
|
return (
|
|
16
16
|
<div className='row'>
|
|
17
|
-
<p
|
|
17
|
+
<p
|
|
18
|
+
className={`col-xs-4 col-sm-2 col-lg-1 col-xs-offset-8 col-sm-offset-10 col-lg-offset-11 text-right ${className}`}
|
|
19
|
+
>
|
|
18
20
|
<IconButton
|
|
19
21
|
id={id}
|
|
20
22
|
iconType='info'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { helpId, FieldHelpProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
2
|
+
import RichHelp from '../RichHelp';
|
|
2
3
|
|
|
3
4
|
/** The `FieldHelpTemplate` component renders any help desired for a field
|
|
4
5
|
*
|
|
@@ -9,21 +10,14 @@ export default function FieldHelpTemplate<
|
|
|
9
10
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
10
11
|
F extends FormContextType = any,
|
|
11
12
|
>(props: FieldHelpProps<T, S, F>) {
|
|
12
|
-
const { fieldPathId, help } = props;
|
|
13
|
+
const { fieldPathId, help, uiSchema, registry } = props;
|
|
13
14
|
if (!help) {
|
|
14
15
|
return null;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
if (typeof help === 'string') {
|
|
18
|
-
return (
|
|
19
|
-
<p id={id} className='help-block'>
|
|
20
|
-
{help}
|
|
21
|
-
</p>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
17
|
+
|
|
24
18
|
return (
|
|
25
|
-
<div id={
|
|
26
|
-
{help}
|
|
19
|
+
<div id={helpId(fieldPathId)} className='help-block'>
|
|
20
|
+
<RichHelp help={help as string} registry={registry} uiSchema={uiSchema} />
|
|
27
21
|
</div>
|
|
28
22
|
);
|
|
29
23
|
}
|
|
@@ -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}
|
|
@@ -25,9 +25,11 @@ export default function WrapIfAdditionalTemplate<
|
|
|
25
25
|
classNames,
|
|
26
26
|
style,
|
|
27
27
|
disabled,
|
|
28
|
+
displayLabel,
|
|
28
29
|
label,
|
|
29
30
|
onKeyRenameBlur,
|
|
30
31
|
onRemoveProperty,
|
|
32
|
+
rawDescription,
|
|
31
33
|
readonly,
|
|
32
34
|
required,
|
|
33
35
|
schema,
|
|
@@ -42,6 +44,7 @@ export default function WrapIfAdditionalTemplate<
|
|
|
42
44
|
const { RemoveButton } = templates.ButtonTemplates;
|
|
43
45
|
const keyLabel = translateString(TranslatableString.KeyLabel, [label]);
|
|
44
46
|
const additional = ADDITIONAL_PROPERTY_FLAG in schema;
|
|
47
|
+
const hasDescription = !!rawDescription;
|
|
45
48
|
|
|
46
49
|
const classNamesList = ['form-group', classNames];
|
|
47
50
|
if (!hideError && rawErrors && rawErrors.length > 0) {
|
|
@@ -56,13 +59,14 @@ export default function WrapIfAdditionalTemplate<
|
|
|
56
59
|
</div>
|
|
57
60
|
);
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
const margin = hasDescription ? 46 : 26;
|
|
60
63
|
return (
|
|
61
64
|
<div className={uiClassNames} style={style}>
|
|
62
65
|
<div className='row'>
|
|
63
66
|
<div className='col-xs-5 form-additional'>
|
|
64
67
|
<div className='form-group'>
|
|
65
|
-
<Label label={keyLabel} required={required} id={`${id}-key`} />
|
|
68
|
+
{displayLabel && <Label label={keyLabel} required={required} id={`${id}-key`} />}
|
|
69
|
+
{displayLabel && rawDescription && <div> </div>}
|
|
66
70
|
<input
|
|
67
71
|
className='form-control'
|
|
68
72
|
type='text'
|
|
@@ -73,7 +77,7 @@ export default function WrapIfAdditionalTemplate<
|
|
|
73
77
|
</div>
|
|
74
78
|
</div>
|
|
75
79
|
<div className='form-additional form-group col-xs-5'>{children}</div>
|
|
76
|
-
<div className='col-xs-2'>
|
|
80
|
+
<div className='col-xs-2' style={{ marginTop: displayLabel ? `${margin}px` : undefined }}>
|
|
77
81
|
<RemoveButton
|
|
78
82
|
id={buttonId(id, 'remove')}
|
|
79
83
|
className='rjsf-object-property-remove btn-block'
|
|
@@ -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 && (
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Form, { FormProps, FormState, IChangeEvent } from './components/Form';
|
|
2
2
|
import RichDescription, { RichDescriptionProps } from './components/RichDescription';
|
|
3
|
+
import RichHelp, { RichHelpProps } from './components/RichHelp';
|
|
3
4
|
import withTheme, { ThemeProps } from './withTheme';
|
|
4
5
|
import getDefaultRegistry from './getDefaultRegistry';
|
|
5
6
|
import getTestRegistry from './getTestRegistry';
|
|
6
7
|
|
|
7
|
-
export type { FormProps, FormState, IChangeEvent, ThemeProps, RichDescriptionProps };
|
|
8
|
+
export type { FormProps, FormState, IChangeEvent, ThemeProps, RichDescriptionProps, RichHelpProps };
|
|
8
9
|
|
|
9
|
-
export { withTheme, getDefaultRegistry, getTestRegistry, RichDescription };
|
|
10
|
+
export { withTheme, getDefaultRegistry, getTestRegistry, RichDescription, RichHelp };
|
|
10
11
|
export default Form;
|