@rjsf/antd 5.11.2 → 5.12.1
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/antd.esm.js +891 -1117
- package/dist/antd.esm.js.map +7 -1
- package/dist/antd.umd.js +1184 -0
- package/dist/index.js +1347 -5
- package/dist/index.js.map +7 -0
- package/lib/components/DatePicker/index.d.ts +48 -0
- package/lib/components/DatePicker/index.js +5 -0
- package/lib/components/DatePicker/index.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +17 -0
- package/lib/index.js.map +1 -0
- package/lib/templates/ArrayFieldItemTemplate/index.d.ts +7 -0
- package/lib/templates/ArrayFieldItemTemplate/index.js +21 -0
- package/lib/templates/ArrayFieldItemTemplate/index.js.map +1 -0
- package/lib/templates/ArrayFieldTemplate/index.d.ts +7 -0
- package/lib/templates/ArrayFieldTemplate/index.js +38 -0
- package/lib/templates/ArrayFieldTemplate/index.js.map +1 -0
- package/lib/templates/BaseInputTemplate/index.d.ts +9 -0
- package/lib/templates/BaseInputTemplate/index.js +31 -0
- package/lib/templates/BaseInputTemplate/index.js.map +1 -0
- package/lib/templates/DescriptionField/index.d.ts +7 -0
- package/lib/templates/DescriptionField/index.js +13 -0
- package/lib/templates/DescriptionField/index.js.map +1 -0
- package/lib/templates/ErrorList/index.d.ts +7 -0
- package/lib/templates/ErrorList/index.js +16 -0
- package/lib/templates/ErrorList/index.js.map +1 -0
- package/lib/templates/FieldErrorTemplate/index.d.ts +7 -0
- package/lib/templates/FieldErrorTemplate/index.js +15 -0
- package/lib/templates/FieldErrorTemplate/index.js.map +1 -0
- package/lib/templates/FieldTemplate/index.d.ts +8 -0
- package/lib/templates/FieldTemplate/index.js +34 -0
- package/lib/templates/FieldTemplate/index.js.map +1 -0
- package/lib/templates/IconButton/index.d.ts +10 -0
- package/lib/templates/IconButton/index.js +36 -0
- package/lib/templates/IconButton/index.js.map +1 -0
- package/lib/templates/ObjectFieldTemplate/index.d.ts +9 -0
- package/lib/templates/ObjectFieldTemplate/index.js +71 -0
- package/lib/templates/ObjectFieldTemplate/index.js.map +1 -0
- package/lib/templates/SubmitButton/index.d.ts +5 -0
- package/lib/templates/SubmitButton/index.js +13 -0
- package/lib/templates/SubmitButton/index.js.map +1 -0
- package/lib/templates/TitleField/index.d.ts +7 -0
- package/lib/templates/TitleField/index.js +34 -0
- package/lib/templates/TitleField/index.js.map +1 -0
- package/lib/templates/WrapIfAdditionalTemplate/index.d.ts +8 -0
- package/lib/templates/WrapIfAdditionalTemplate/index.js +34 -0
- package/lib/templates/WrapIfAdditionalTemplate/index.js.map +1 -0
- package/lib/templates/index.d.ts +4 -0
- package/lib/templates/index.js +36 -0
- package/lib/templates/index.js.map +1 -0
- package/lib/widgets/AltDateTimeWidget/index.d.ts +15 -0
- package/lib/widgets/AltDateTimeWidget/index.js +8 -0
- package/lib/widgets/AltDateTimeWidget/index.js.map +1 -0
- package/lib/widgets/AltDateWidget/index.d.ts +15 -0
- package/lib/widgets/AltDateWidget/index.js +89 -0
- package/lib/widgets/AltDateWidget/index.js.map +1 -0
- package/lib/widgets/CheckboxWidget/index.d.ts +8 -0
- package/lib/widgets/CheckboxWidget/index.js +23 -0
- package/lib/widgets/CheckboxWidget/index.js.map +1 -0
- package/lib/widgets/CheckboxesWidget/index.d.ts +8 -0
- package/lib/widgets/CheckboxesWidget/index.js +26 -0
- package/lib/widgets/CheckboxesWidget/index.js.map +1 -0
- package/lib/widgets/DateTimeWidget/index.d.ts +8 -0
- package/lib/widgets/DateTimeWidget/index.js +22 -0
- package/lib/widgets/DateTimeWidget/index.js.map +1 -0
- package/lib/widgets/DateWidget/index.d.ts +8 -0
- package/lib/widgets/DateWidget/index.js +22 -0
- package/lib/widgets/DateWidget/index.js.map +1 -0
- package/lib/widgets/PasswordWidget/index.d.ts +7 -0
- package/lib/widgets/PasswordWidget/index.js +17 -0
- package/lib/widgets/PasswordWidget/index.js.map +1 -0
- package/lib/widgets/RadioWidget/index.d.ts +8 -0
- package/lib/widgets/RadioWidget/index.js +19 -0
- package/lib/widgets/RadioWidget/index.js.map +1 -0
- package/lib/widgets/RangeWidget/index.d.ts +8 -0
- package/lib/widgets/RangeWidget/index.js +26 -0
- package/lib/widgets/RangeWidget/index.js.map +1 -0
- package/lib/widgets/SelectWidget/index.d.ts +8 -0
- package/lib/widgets/SelectWidget/index.js +36 -0
- package/lib/widgets/SelectWidget/index.js.map +1 -0
- package/lib/widgets/TextareaWidget/index.d.ts +7 -0
- package/lib/widgets/TextareaWidget/index.js +23 -0
- package/lib/widgets/TextareaWidget/index.js.map +1 -0
- package/lib/widgets/index.d.ts +4 -0
- package/lib/widgets/index.js +28 -0
- package/lib/widgets/index.js.map +1 -0
- package/package.json +24 -16
- package/src/components/DatePicker/index.ts +6 -0
- package/src/index.less +38 -0
- package/src/index.ts +33 -0
- package/src/templates/ArrayFieldItemTemplate/index.tsx +90 -0
- package/src/templates/ArrayFieldTemplate/index.tsx +132 -0
- package/src/templates/BaseInputTemplate/index.tsx +105 -0
- package/src/templates/DescriptionField/index.tsx +17 -0
- package/src/templates/ErrorList/index.tsx +37 -0
- package/src/templates/FieldErrorTemplate/index.tsx +25 -0
- package/src/templates/FieldTemplate/index.tsx +114 -0
- package/src/templates/IconButton/index.tsx +94 -0
- package/src/templates/ObjectFieldTemplate/index.tsx +175 -0
- package/src/templates/SubmitButton/index.tsx +20 -0
- package/src/templates/TitleField/index.tsx +57 -0
- package/src/templates/WrapIfAdditionalTemplate/index.tsx +124 -0
- package/src/templates/index.ts +43 -0
- package/src/widgets/AltDateTimeWidget/index.tsx +17 -0
- package/src/widgets/AltDateWidget/index.tsx +197 -0
- package/src/widgets/CheckboxWidget/index.tsx +52 -0
- package/src/widgets/CheckboxesWidget/index.tsx +75 -0
- package/src/widgets/DateTimeWidget/index.tsx +54 -0
- package/src/widgets/DateWidget/index.tsx +52 -0
- package/src/widgets/PasswordWidget/index.tsx +46 -0
- package/src/widgets/RadioWidget/index.tsx +73 -0
- package/src/widgets/RangeWidget/index.tsx +69 -0
- package/src/widgets/SelectWidget/index.tsx +97 -0
- package/src/widgets/TextareaWidget/index.tsx +67 -0
- package/src/widgets/index.ts +35 -0
- package/dist/antd.cjs.development.js +0 -1643
- package/dist/antd.cjs.development.js.map +0 -1
- package/dist/antd.cjs.production.min.js +0 -2
- package/dist/antd.cjs.production.min.js.map +0 -1
- package/dist/antd.umd.development.js +0 -1617
- package/dist/antd.umd.development.js.map +0 -1
- package/dist/antd.umd.production.min.js +0 -2
- package/dist/antd.umd.production.min.js.map +0 -1
- package/dist/index.d.ts +0 -16
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getTemplate,
|
|
3
|
+
getUiOptions,
|
|
4
|
+
ArrayFieldTemplateProps,
|
|
5
|
+
ArrayFieldTemplateItemType,
|
|
6
|
+
FormContextType,
|
|
7
|
+
GenericObjectType,
|
|
8
|
+
RJSFSchema,
|
|
9
|
+
StrictRJSFSchema,
|
|
10
|
+
} from '@rjsf/utils';
|
|
11
|
+
import classNames from 'classnames';
|
|
12
|
+
import Col from 'antd/lib/col';
|
|
13
|
+
import Row from 'antd/lib/row';
|
|
14
|
+
import { ConfigConsumer, ConfigConsumerProps } from 'antd/lib/config-provider/context';
|
|
15
|
+
|
|
16
|
+
const DESCRIPTION_COL_STYLE = {
|
|
17
|
+
paddingBottom: '8px',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** The `ArrayFieldTemplate` component is the template used to render all items in an array.
|
|
21
|
+
*
|
|
22
|
+
* @param props - The `ArrayFieldTemplateItemType` props for the component
|
|
23
|
+
*/
|
|
24
|
+
export default function ArrayFieldTemplate<
|
|
25
|
+
T = any,
|
|
26
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
27
|
+
F extends FormContextType = any
|
|
28
|
+
>(props: ArrayFieldTemplateProps<T, S, F>) {
|
|
29
|
+
const {
|
|
30
|
+
canAdd,
|
|
31
|
+
className,
|
|
32
|
+
disabled,
|
|
33
|
+
formContext,
|
|
34
|
+
idSchema,
|
|
35
|
+
items,
|
|
36
|
+
onAddClick,
|
|
37
|
+
readonly,
|
|
38
|
+
registry,
|
|
39
|
+
required,
|
|
40
|
+
schema,
|
|
41
|
+
title,
|
|
42
|
+
uiSchema,
|
|
43
|
+
} = props;
|
|
44
|
+
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
45
|
+
const ArrayFieldDescriptionTemplate = getTemplate<'ArrayFieldDescriptionTemplate', T, S, F>(
|
|
46
|
+
'ArrayFieldDescriptionTemplate',
|
|
47
|
+
registry,
|
|
48
|
+
uiOptions
|
|
49
|
+
);
|
|
50
|
+
const ArrayFieldItemTemplate = getTemplate<'ArrayFieldItemTemplate', T, S, F>(
|
|
51
|
+
'ArrayFieldItemTemplate',
|
|
52
|
+
registry,
|
|
53
|
+
uiOptions
|
|
54
|
+
);
|
|
55
|
+
const ArrayFieldTitleTemplate = getTemplate<'ArrayFieldTitleTemplate', T, S, F>(
|
|
56
|
+
'ArrayFieldTitleTemplate',
|
|
57
|
+
registry,
|
|
58
|
+
uiOptions
|
|
59
|
+
);
|
|
60
|
+
// Button templates are not overridden in the uiSchema
|
|
61
|
+
const {
|
|
62
|
+
ButtonTemplates: { AddButton },
|
|
63
|
+
} = registry.templates;
|
|
64
|
+
const { labelAlign = 'right', rowGutter = 24 } = formContext as GenericObjectType;
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<ConfigConsumer>
|
|
68
|
+
{(configProps: ConfigConsumerProps) => {
|
|
69
|
+
const { getPrefixCls } = configProps;
|
|
70
|
+
const prefixCls = getPrefixCls('form');
|
|
71
|
+
const labelClsBasic = `${prefixCls}-item-label`;
|
|
72
|
+
const labelColClassName = classNames(
|
|
73
|
+
labelClsBasic,
|
|
74
|
+
labelAlign === 'left' && `${labelClsBasic}-left`
|
|
75
|
+
// labelCol.className,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<fieldset className={className} id={idSchema.$id}>
|
|
80
|
+
<Row gutter={rowGutter}>
|
|
81
|
+
{(uiOptions.title || title) && (
|
|
82
|
+
<Col className={labelColClassName} span={24}>
|
|
83
|
+
<ArrayFieldTitleTemplate
|
|
84
|
+
idSchema={idSchema}
|
|
85
|
+
required={required}
|
|
86
|
+
title={uiOptions.title || title}
|
|
87
|
+
schema={schema}
|
|
88
|
+
uiSchema={uiSchema}
|
|
89
|
+
registry={registry}
|
|
90
|
+
/>
|
|
91
|
+
</Col>
|
|
92
|
+
)}
|
|
93
|
+
{(uiOptions.description || schema.description) && (
|
|
94
|
+
<Col span={24} style={DESCRIPTION_COL_STYLE}>
|
|
95
|
+
<ArrayFieldDescriptionTemplate
|
|
96
|
+
description={uiOptions.description || schema.description}
|
|
97
|
+
idSchema={idSchema}
|
|
98
|
+
schema={schema}
|
|
99
|
+
uiSchema={uiSchema}
|
|
100
|
+
registry={registry}
|
|
101
|
+
/>
|
|
102
|
+
</Col>
|
|
103
|
+
)}
|
|
104
|
+
<Col className='row array-item-list' span={24}>
|
|
105
|
+
{items &&
|
|
106
|
+
items.map(({ key, ...itemProps }: ArrayFieldTemplateItemType<T, S, F>) => (
|
|
107
|
+
<ArrayFieldItemTemplate key={key} {...itemProps} />
|
|
108
|
+
))}
|
|
109
|
+
</Col>
|
|
110
|
+
|
|
111
|
+
{canAdd && (
|
|
112
|
+
<Col span={24}>
|
|
113
|
+
<Row gutter={rowGutter} justify='end'>
|
|
114
|
+
<Col flex='192px'>
|
|
115
|
+
<AddButton
|
|
116
|
+
className='array-item-add'
|
|
117
|
+
disabled={disabled || readonly}
|
|
118
|
+
onClick={onAddClick}
|
|
119
|
+
uiSchema={uiSchema}
|
|
120
|
+
registry={registry}
|
|
121
|
+
/>
|
|
122
|
+
</Col>
|
|
123
|
+
</Row>
|
|
124
|
+
</Col>
|
|
125
|
+
)}
|
|
126
|
+
</Row>
|
|
127
|
+
</fieldset>
|
|
128
|
+
);
|
|
129
|
+
}}
|
|
130
|
+
</ConfigConsumer>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ChangeEvent, FocusEvent } from 'react';
|
|
2
|
+
import Input from 'antd/lib/input';
|
|
3
|
+
import InputNumber from 'antd/lib/input-number';
|
|
4
|
+
import {
|
|
5
|
+
ariaDescribedByIds,
|
|
6
|
+
BaseInputTemplateProps,
|
|
7
|
+
examplesId,
|
|
8
|
+
getInputProps,
|
|
9
|
+
FormContextType,
|
|
10
|
+
GenericObjectType,
|
|
11
|
+
RJSFSchema,
|
|
12
|
+
StrictRJSFSchema,
|
|
13
|
+
} from '@rjsf/utils';
|
|
14
|
+
|
|
15
|
+
const INPUT_STYLE = {
|
|
16
|
+
width: '100%',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
|
|
20
|
+
* It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
|
|
21
|
+
* It can be customized/overridden for other themes or individual implementations as needed.
|
|
22
|
+
*
|
|
23
|
+
* @param props - The `WidgetProps` for this template
|
|
24
|
+
*/
|
|
25
|
+
export default function BaseInputTemplate<
|
|
26
|
+
T = any,
|
|
27
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
28
|
+
F extends FormContextType = any
|
|
29
|
+
>(props: BaseInputTemplateProps<T, S, F>) {
|
|
30
|
+
const {
|
|
31
|
+
disabled,
|
|
32
|
+
formContext,
|
|
33
|
+
id,
|
|
34
|
+
onBlur,
|
|
35
|
+
onChange,
|
|
36
|
+
onChangeOverride,
|
|
37
|
+
onFocus,
|
|
38
|
+
options,
|
|
39
|
+
placeholder,
|
|
40
|
+
readonly,
|
|
41
|
+
schema,
|
|
42
|
+
value,
|
|
43
|
+
type,
|
|
44
|
+
} = props;
|
|
45
|
+
const inputProps = getInputProps<T, S, F>(schema, type, options, false);
|
|
46
|
+
const { readonlyAsDisabled = true } = formContext as GenericObjectType;
|
|
47
|
+
|
|
48
|
+
const handleNumberChange = (nextValue: number | null) => onChange(nextValue);
|
|
49
|
+
|
|
50
|
+
const handleTextChange = onChangeOverride
|
|
51
|
+
? onChangeOverride
|
|
52
|
+
: ({ target }: ChangeEvent<HTMLInputElement>) => onChange(target.value === '' ? options.emptyValue : target.value);
|
|
53
|
+
|
|
54
|
+
const handleBlur = ({ target }: FocusEvent<HTMLInputElement>) => onBlur(id, target.value);
|
|
55
|
+
|
|
56
|
+
const handleFocus = ({ target }: FocusEvent<HTMLInputElement>) => onFocus(id, target.value);
|
|
57
|
+
|
|
58
|
+
const input =
|
|
59
|
+
inputProps.type === 'number' || inputProps.type === 'integer' ? (
|
|
60
|
+
<InputNumber
|
|
61
|
+
disabled={disabled || (readonlyAsDisabled && readonly)}
|
|
62
|
+
id={id}
|
|
63
|
+
name={id}
|
|
64
|
+
onBlur={!readonly ? handleBlur : undefined}
|
|
65
|
+
onChange={!readonly ? handleNumberChange : undefined}
|
|
66
|
+
onFocus={!readonly ? handleFocus : undefined}
|
|
67
|
+
placeholder={placeholder}
|
|
68
|
+
style={INPUT_STYLE}
|
|
69
|
+
list={schema.examples ? examplesId<T>(id) : undefined}
|
|
70
|
+
{...inputProps}
|
|
71
|
+
value={value}
|
|
72
|
+
aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)}
|
|
73
|
+
/>
|
|
74
|
+
) : (
|
|
75
|
+
<Input
|
|
76
|
+
disabled={disabled || (readonlyAsDisabled && readonly)}
|
|
77
|
+
id={id}
|
|
78
|
+
name={id}
|
|
79
|
+
onBlur={!readonly ? handleBlur : undefined}
|
|
80
|
+
onChange={!readonly ? handleTextChange : undefined}
|
|
81
|
+
onFocus={!readonly ? handleFocus : undefined}
|
|
82
|
+
placeholder={placeholder}
|
|
83
|
+
style={INPUT_STYLE}
|
|
84
|
+
list={schema.examples ? examplesId<T>(id) : undefined}
|
|
85
|
+
{...inputProps}
|
|
86
|
+
value={value}
|
|
87
|
+
aria-describedby={ariaDescribedByIds<T>(id, !!schema.examples)}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
{input}
|
|
94
|
+
{Array.isArray(schema.examples) && (
|
|
95
|
+
<datalist id={examplesId<T>(id)}>
|
|
96
|
+
{(schema.examples as string[])
|
|
97
|
+
.concat(schema.default && !schema.examples.includes(schema.default) ? ([schema.default] as string[]) : [])
|
|
98
|
+
.map((example) => {
|
|
99
|
+
return <option key={example} value={example} />;
|
|
100
|
+
})}
|
|
101
|
+
</datalist>
|
|
102
|
+
)}
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DescriptionFieldProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
2
|
+
|
|
3
|
+
/** The `DescriptionField` is the template to use to render the description of a field
|
|
4
|
+
*
|
|
5
|
+
* @param props - The `DescriptionFieldProps` for this component
|
|
6
|
+
*/
|
|
7
|
+
export default function DescriptionField<
|
|
8
|
+
T = any,
|
|
9
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
10
|
+
F extends FormContextType = any
|
|
11
|
+
>(props: DescriptionFieldProps<T, S, F>) {
|
|
12
|
+
const { id, description } = props;
|
|
13
|
+
if (!description) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return <span id={id}>{description}</span>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Alert from 'antd/lib/alert';
|
|
2
|
+
import List from 'antd/lib/list';
|
|
3
|
+
import Space from 'antd/lib/space';
|
|
4
|
+
import ExclamationCircleOutlined from '@ant-design/icons/ExclamationCircleOutlined';
|
|
5
|
+
import { ErrorListProps, FormContextType, RJSFSchema, StrictRJSFSchema, TranslatableString } from '@rjsf/utils';
|
|
6
|
+
|
|
7
|
+
/** The `ErrorList` component is the template that renders the all the errors associated with the fields in the `Form`
|
|
8
|
+
*
|
|
9
|
+
* @param props - The `ErrorListProps` for this component
|
|
10
|
+
*/
|
|
11
|
+
export default function ErrorList<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({
|
|
12
|
+
errors,
|
|
13
|
+
registry,
|
|
14
|
+
}: ErrorListProps<T, S, F>) {
|
|
15
|
+
const { translateString } = registry;
|
|
16
|
+
const renderErrors = () => (
|
|
17
|
+
<List className='list-group' size='small'>
|
|
18
|
+
{errors.map((error, index) => (
|
|
19
|
+
<List.Item key={index}>
|
|
20
|
+
<Space>
|
|
21
|
+
<ExclamationCircleOutlined />
|
|
22
|
+
{error.stack}
|
|
23
|
+
</Space>
|
|
24
|
+
</List.Item>
|
|
25
|
+
))}
|
|
26
|
+
</List>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Alert
|
|
31
|
+
className='panel panel-danger errors'
|
|
32
|
+
description={renderErrors()}
|
|
33
|
+
message={translateString(TranslatableString.ErrorsLabel)}
|
|
34
|
+
type='error'
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FieldErrorProps, FormContextType, RJSFSchema, StrictRJSFSchema, errorId } from '@rjsf/utils';
|
|
2
|
+
|
|
3
|
+
/** The `FieldErrorTemplate` component renders the errors local to the particular field
|
|
4
|
+
*
|
|
5
|
+
* @param props - The `FieldErrorProps` for the errors being rendered
|
|
6
|
+
*/
|
|
7
|
+
export default function FieldErrorTemplate<
|
|
8
|
+
T = any,
|
|
9
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
10
|
+
F extends FormContextType = any
|
|
11
|
+
>(props: FieldErrorProps<T, S, F>) {
|
|
12
|
+
const { errors = [], idSchema } = props;
|
|
13
|
+
if (errors.length === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const id = errorId<T>(idSchema);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div id={id}>
|
|
20
|
+
{errors.map((error) => (
|
|
21
|
+
<div key={`field-${id}-error-${error}`}>{error}</div>
|
|
22
|
+
))}
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import Form from 'antd/lib/form';
|
|
2
|
+
import {
|
|
3
|
+
FieldTemplateProps,
|
|
4
|
+
FormContextType,
|
|
5
|
+
RJSFSchema,
|
|
6
|
+
StrictRJSFSchema,
|
|
7
|
+
getTemplate,
|
|
8
|
+
getUiOptions,
|
|
9
|
+
GenericObjectType,
|
|
10
|
+
} from '@rjsf/utils';
|
|
11
|
+
|
|
12
|
+
const VERTICAL_LABEL_COL = { span: 24 };
|
|
13
|
+
const VERTICAL_WRAPPER_COL = { span: 24 };
|
|
14
|
+
|
|
15
|
+
/** The `FieldTemplate` component is the template used by `SchemaField` to render any field. It renders the field
|
|
16
|
+
* content, (label, description, children, errors and help) inside of a `WrapIfAdditional` component.
|
|
17
|
+
*
|
|
18
|
+
* @param props - The `FieldTemplateProps` for this component
|
|
19
|
+
*/
|
|
20
|
+
export default function FieldTemplate<
|
|
21
|
+
T = any,
|
|
22
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
23
|
+
F extends FormContextType = any
|
|
24
|
+
>(props: FieldTemplateProps<T, S, F>) {
|
|
25
|
+
const {
|
|
26
|
+
children,
|
|
27
|
+
classNames,
|
|
28
|
+
style,
|
|
29
|
+
description,
|
|
30
|
+
disabled,
|
|
31
|
+
displayLabel,
|
|
32
|
+
errors,
|
|
33
|
+
formContext,
|
|
34
|
+
help,
|
|
35
|
+
hidden,
|
|
36
|
+
id,
|
|
37
|
+
label,
|
|
38
|
+
onDropPropertyClick,
|
|
39
|
+
onKeyChange,
|
|
40
|
+
rawErrors,
|
|
41
|
+
rawDescription,
|
|
42
|
+
rawHelp,
|
|
43
|
+
readonly,
|
|
44
|
+
registry,
|
|
45
|
+
required,
|
|
46
|
+
schema,
|
|
47
|
+
uiSchema,
|
|
48
|
+
} = props;
|
|
49
|
+
const {
|
|
50
|
+
colon,
|
|
51
|
+
labelCol = VERTICAL_LABEL_COL,
|
|
52
|
+
wrapperCol = VERTICAL_WRAPPER_COL,
|
|
53
|
+
wrapperStyle,
|
|
54
|
+
descriptionLocation = 'below',
|
|
55
|
+
} = formContext as GenericObjectType;
|
|
56
|
+
|
|
57
|
+
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
58
|
+
const WrapIfAdditionalTemplate = getTemplate<'WrapIfAdditionalTemplate', T, S, F>(
|
|
59
|
+
'WrapIfAdditionalTemplate',
|
|
60
|
+
registry,
|
|
61
|
+
uiOptions
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (hidden) {
|
|
65
|
+
return <div className='field-hidden'>{children}</div>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// check to see if there is rawDescription(string) before using description(ReactNode)
|
|
69
|
+
// to prevent showing a blank description area
|
|
70
|
+
const descriptionNode = rawDescription ? description : undefined;
|
|
71
|
+
const descriptionProps: GenericObjectType = {};
|
|
72
|
+
switch (descriptionLocation) {
|
|
73
|
+
case 'tooltip':
|
|
74
|
+
descriptionProps.tooltip = descriptionNode;
|
|
75
|
+
break;
|
|
76
|
+
case 'below':
|
|
77
|
+
default:
|
|
78
|
+
descriptionProps.extra = descriptionNode;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<WrapIfAdditionalTemplate
|
|
84
|
+
classNames={classNames}
|
|
85
|
+
style={style}
|
|
86
|
+
disabled={disabled}
|
|
87
|
+
id={id}
|
|
88
|
+
label={label}
|
|
89
|
+
onDropPropertyClick={onDropPropertyClick}
|
|
90
|
+
onKeyChange={onKeyChange}
|
|
91
|
+
readonly={readonly}
|
|
92
|
+
required={required}
|
|
93
|
+
schema={schema}
|
|
94
|
+
uiSchema={uiSchema}
|
|
95
|
+
registry={registry}
|
|
96
|
+
>
|
|
97
|
+
<Form.Item
|
|
98
|
+
colon={colon}
|
|
99
|
+
hasFeedback={schema.type !== 'array' && schema.type !== 'object'}
|
|
100
|
+
help={(!!rawHelp && help) || (rawErrors?.length ? errors : undefined)}
|
|
101
|
+
htmlFor={id}
|
|
102
|
+
label={displayLabel && label}
|
|
103
|
+
labelCol={labelCol}
|
|
104
|
+
required={required}
|
|
105
|
+
style={wrapperStyle}
|
|
106
|
+
validateStatus={rawErrors?.length ? 'error' : undefined}
|
|
107
|
+
wrapperCol={wrapperCol}
|
|
108
|
+
{...descriptionProps}
|
|
109
|
+
>
|
|
110
|
+
{children}
|
|
111
|
+
</Form.Item>
|
|
112
|
+
</WrapIfAdditionalTemplate>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import Button, { ButtonProps, ButtonType } from 'antd/lib/button';
|
|
2
|
+
import ArrowDownOutlined from '@ant-design/icons/ArrowDownOutlined';
|
|
3
|
+
import ArrowUpOutlined from '@ant-design/icons/ArrowUpOutlined';
|
|
4
|
+
import CopyOutlined from '@ant-design/icons/CopyOutlined';
|
|
5
|
+
import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
|
|
6
|
+
import PlusCircleOutlined from '@ant-design/icons/PlusCircleOutlined';
|
|
7
|
+
import {
|
|
8
|
+
getUiOptions,
|
|
9
|
+
FormContextType,
|
|
10
|
+
IconButtonProps,
|
|
11
|
+
RJSFSchema,
|
|
12
|
+
StrictRJSFSchema,
|
|
13
|
+
TranslatableString,
|
|
14
|
+
} from '@rjsf/utils';
|
|
15
|
+
|
|
16
|
+
// The `type` for IconButtonProps collides with the `type` for `ButtonProps` so omit it to avoid Typescript issue
|
|
17
|
+
export type AntdIconButtonProps<
|
|
18
|
+
T = any,
|
|
19
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
20
|
+
F extends FormContextType = any
|
|
21
|
+
> = Omit<IconButtonProps<T, S, F>, 'type'>;
|
|
22
|
+
|
|
23
|
+
export default function IconButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
24
|
+
props: AntdIconButtonProps<T, S, F> & ButtonProps
|
|
25
|
+
) {
|
|
26
|
+
const { iconType = 'default', icon, uiSchema, registry, ...otherProps } = props;
|
|
27
|
+
return <Button type={iconType as ButtonType} icon={icon} {...otherProps} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function AddButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
31
|
+
props: AntdIconButtonProps<T, S, F>
|
|
32
|
+
) {
|
|
33
|
+
const {
|
|
34
|
+
registry: { translateString },
|
|
35
|
+
} = props;
|
|
36
|
+
return (
|
|
37
|
+
<IconButton
|
|
38
|
+
title={translateString(TranslatableString.AddItemButton)}
|
|
39
|
+
{...props}
|
|
40
|
+
block
|
|
41
|
+
iconType='primary'
|
|
42
|
+
icon={<PlusCircleOutlined />}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function CopyButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
48
|
+
props: AntdIconButtonProps<T, S, F>
|
|
49
|
+
) {
|
|
50
|
+
const {
|
|
51
|
+
registry: { translateString },
|
|
52
|
+
} = props;
|
|
53
|
+
return <IconButton title={translateString(TranslatableString.CopyButton)} {...props} icon={<CopyOutlined />} />;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function MoveDownButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
57
|
+
props: AntdIconButtonProps<T, S, F>
|
|
58
|
+
) {
|
|
59
|
+
const {
|
|
60
|
+
registry: { translateString },
|
|
61
|
+
} = props;
|
|
62
|
+
return (
|
|
63
|
+
<IconButton title={translateString(TranslatableString.MoveDownButton)} {...props} icon={<ArrowDownOutlined />} />
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function MoveUpButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
68
|
+
props: AntdIconButtonProps<T, S, F>
|
|
69
|
+
) {
|
|
70
|
+
const {
|
|
71
|
+
registry: { translateString },
|
|
72
|
+
} = props;
|
|
73
|
+
return <IconButton title={translateString(TranslatableString.MoveUpButton)} {...props} icon={<ArrowUpOutlined />} />;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function RemoveButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
77
|
+
props: AntdIconButtonProps<T, S, F>
|
|
78
|
+
) {
|
|
79
|
+
// The `block` prop is not part of the `IconButtonProps` defined in the template, so get it from the uiSchema instead
|
|
80
|
+
const options = getUiOptions<T, S, F>(props.uiSchema);
|
|
81
|
+
const {
|
|
82
|
+
registry: { translateString },
|
|
83
|
+
} = props;
|
|
84
|
+
return (
|
|
85
|
+
<IconButton
|
|
86
|
+
title={translateString(TranslatableString.RemoveButton)}
|
|
87
|
+
{...props}
|
|
88
|
+
danger
|
|
89
|
+
block={!!options.block}
|
|
90
|
+
iconType='primary'
|
|
91
|
+
icon={<DeleteOutlined />}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import isObject from 'lodash/isObject';
|
|
3
|
+
import isNumber from 'lodash/isNumber';
|
|
4
|
+
import isString from 'lodash/isString';
|
|
5
|
+
import {
|
|
6
|
+
FormContextType,
|
|
7
|
+
GenericObjectType,
|
|
8
|
+
ObjectFieldTemplateProps,
|
|
9
|
+
ObjectFieldTemplatePropertyType,
|
|
10
|
+
RJSFSchema,
|
|
11
|
+
StrictRJSFSchema,
|
|
12
|
+
UiSchema,
|
|
13
|
+
canExpand,
|
|
14
|
+
descriptionId,
|
|
15
|
+
getTemplate,
|
|
16
|
+
getUiOptions,
|
|
17
|
+
titleId,
|
|
18
|
+
} from '@rjsf/utils';
|
|
19
|
+
import Col from 'antd/lib/col';
|
|
20
|
+
import Row from 'antd/lib/row';
|
|
21
|
+
import { ConfigConsumer, ConfigConsumerProps } from 'antd/lib/config-provider/context';
|
|
22
|
+
|
|
23
|
+
const DESCRIPTION_COL_STYLE = {
|
|
24
|
+
paddingBottom: '8px',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** The `ObjectFieldTemplate` is the template to use to render all the inner properties of an object along with the
|
|
28
|
+
* title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
|
|
29
|
+
* the properties.
|
|
30
|
+
*
|
|
31
|
+
* @param props - The `ObjectFieldTemplateProps` for this component
|
|
32
|
+
*/
|
|
33
|
+
export default function ObjectFieldTemplate<
|
|
34
|
+
T = any,
|
|
35
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
36
|
+
F extends FormContextType = any
|
|
37
|
+
>(props: ObjectFieldTemplateProps<T, S, F>) {
|
|
38
|
+
const {
|
|
39
|
+
description,
|
|
40
|
+
disabled,
|
|
41
|
+
formContext,
|
|
42
|
+
formData,
|
|
43
|
+
idSchema,
|
|
44
|
+
onAddClick,
|
|
45
|
+
properties,
|
|
46
|
+
readonly,
|
|
47
|
+
required,
|
|
48
|
+
registry,
|
|
49
|
+
schema,
|
|
50
|
+
title,
|
|
51
|
+
uiSchema,
|
|
52
|
+
} = props;
|
|
53
|
+
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
54
|
+
const TitleFieldTemplate = getTemplate<'TitleFieldTemplate', T, S, F>('TitleFieldTemplate', registry, uiOptions);
|
|
55
|
+
const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
|
|
56
|
+
'DescriptionFieldTemplate',
|
|
57
|
+
registry,
|
|
58
|
+
uiOptions
|
|
59
|
+
);
|
|
60
|
+
// Button templates are not overridden in the uiSchema
|
|
61
|
+
const {
|
|
62
|
+
ButtonTemplates: { AddButton },
|
|
63
|
+
} = registry.templates;
|
|
64
|
+
const { colSpan = 24, labelAlign = 'right', rowGutter = 24 } = formContext as GenericObjectType;
|
|
65
|
+
|
|
66
|
+
const findSchema = (element: ObjectFieldTemplatePropertyType): S => element.content.props.schema;
|
|
67
|
+
|
|
68
|
+
const findSchemaType = (element: ObjectFieldTemplatePropertyType) => findSchema(element).type;
|
|
69
|
+
|
|
70
|
+
const findUiSchema = (element: ObjectFieldTemplatePropertyType): UiSchema<T, S, F> | undefined =>
|
|
71
|
+
element.content.props.uiSchema;
|
|
72
|
+
|
|
73
|
+
const findUiSchemaField = (element: ObjectFieldTemplatePropertyType) => getUiOptions(findUiSchema(element)).field;
|
|
74
|
+
|
|
75
|
+
const findUiSchemaWidget = (element: ObjectFieldTemplatePropertyType) => getUiOptions(findUiSchema(element)).widget;
|
|
76
|
+
|
|
77
|
+
const calculateColSpan = (element: ObjectFieldTemplatePropertyType) => {
|
|
78
|
+
const type = findSchemaType(element);
|
|
79
|
+
const field = findUiSchemaField(element);
|
|
80
|
+
const widget = findUiSchemaWidget(element);
|
|
81
|
+
|
|
82
|
+
const defaultColSpan =
|
|
83
|
+
properties.length < 2 || // Single or no field in object.
|
|
84
|
+
type === 'object' ||
|
|
85
|
+
type === 'array' ||
|
|
86
|
+
widget === 'textarea'
|
|
87
|
+
? 24
|
|
88
|
+
: 12;
|
|
89
|
+
|
|
90
|
+
if (isObject(colSpan)) {
|
|
91
|
+
const colSpanObj: GenericObjectType = colSpan;
|
|
92
|
+
if (isString(widget)) {
|
|
93
|
+
return colSpanObj[widget];
|
|
94
|
+
}
|
|
95
|
+
if (isString(field)) {
|
|
96
|
+
return colSpanObj[field];
|
|
97
|
+
}
|
|
98
|
+
if (isString(type)) {
|
|
99
|
+
return colSpanObj[type];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (isNumber(colSpan)) {
|
|
103
|
+
return colSpan;
|
|
104
|
+
}
|
|
105
|
+
return defaultColSpan;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<ConfigConsumer>
|
|
110
|
+
{(configProps: ConfigConsumerProps) => {
|
|
111
|
+
const { getPrefixCls } = configProps;
|
|
112
|
+
const prefixCls = getPrefixCls('form');
|
|
113
|
+
const labelClsBasic = `${prefixCls}-item-label`;
|
|
114
|
+
const labelColClassName = classNames(
|
|
115
|
+
labelClsBasic,
|
|
116
|
+
labelAlign === 'left' && `${labelClsBasic}-left`
|
|
117
|
+
// labelCol.className,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<fieldset id={idSchema.$id}>
|
|
122
|
+
<Row gutter={rowGutter}>
|
|
123
|
+
{title && (
|
|
124
|
+
<Col className={labelColClassName} span={24}>
|
|
125
|
+
<TitleFieldTemplate
|
|
126
|
+
id={titleId<T>(idSchema)}
|
|
127
|
+
title={title}
|
|
128
|
+
required={required}
|
|
129
|
+
schema={schema}
|
|
130
|
+
uiSchema={uiSchema}
|
|
131
|
+
registry={registry}
|
|
132
|
+
/>
|
|
133
|
+
</Col>
|
|
134
|
+
)}
|
|
135
|
+
{description && (
|
|
136
|
+
<Col span={24} style={DESCRIPTION_COL_STYLE}>
|
|
137
|
+
<DescriptionFieldTemplate
|
|
138
|
+
id={descriptionId<T>(idSchema)}
|
|
139
|
+
description={description}
|
|
140
|
+
schema={schema}
|
|
141
|
+
uiSchema={uiSchema}
|
|
142
|
+
registry={registry}
|
|
143
|
+
/>
|
|
144
|
+
</Col>
|
|
145
|
+
)}
|
|
146
|
+
{properties
|
|
147
|
+
.filter((e) => !e.hidden)
|
|
148
|
+
.map((element: ObjectFieldTemplatePropertyType) => (
|
|
149
|
+
<Col key={element.name} span={calculateColSpan(element)}>
|
|
150
|
+
{element.content}
|
|
151
|
+
</Col>
|
|
152
|
+
))}
|
|
153
|
+
</Row>
|
|
154
|
+
|
|
155
|
+
{canExpand(schema, uiSchema, formData) && (
|
|
156
|
+
<Col span={24}>
|
|
157
|
+
<Row gutter={rowGutter} justify='end'>
|
|
158
|
+
<Col flex='192px'>
|
|
159
|
+
<AddButton
|
|
160
|
+
className='object-property-expand'
|
|
161
|
+
disabled={disabled || readonly}
|
|
162
|
+
onClick={onAddClick(schema)}
|
|
163
|
+
uiSchema={uiSchema}
|
|
164
|
+
registry={registry}
|
|
165
|
+
/>
|
|
166
|
+
</Col>
|
|
167
|
+
</Row>
|
|
168
|
+
</Col>
|
|
169
|
+
)}
|
|
170
|
+
</fieldset>
|
|
171
|
+
);
|
|
172
|
+
}}
|
|
173
|
+
</ConfigConsumer>
|
|
174
|
+
);
|
|
175
|
+
}
|