@rjsf/core 6.0.0-beta.8 → 6.0.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/README.md +2 -0
- package/dist/core.umd.js +2042 -1987
- package/dist/index.cjs +4909 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.esm.js +2509 -2389
- package/dist/index.esm.js.map +4 -4
- package/lib/components/Form.d.ts +137 -34
- package/lib/components/Form.d.ts.map +1 -1
- package/lib/components/Form.js +318 -173
- package/lib/components/fields/ArrayField.d.ts +2 -187
- package/lib/components/fields/ArrayField.d.ts.map +1 -1
- package/lib/components/fields/ArrayField.js +526 -492
- package/lib/components/fields/BooleanField.d.ts.map +1 -1
- package/lib/components/fields/BooleanField.js +8 -3
- package/lib/components/fields/FallbackField.d.ts +7 -0
- package/lib/components/fields/FallbackField.d.ts.map +1 -0
- package/lib/components/fields/FallbackField.js +72 -0
- package/lib/components/fields/LayoutGridField.d.ts +109 -186
- package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
- package/lib/components/fields/LayoutGridField.js +426 -426
- package/lib/components/fields/LayoutHeaderField.d.ts +1 -1
- package/lib/components/fields/LayoutHeaderField.js +3 -3
- package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/LayoutMultiSchemaField.js +6 -6
- package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/MultiSchemaField.js +16 -10
- package/lib/components/fields/NullField.js +3 -3
- package/lib/components/fields/NumberField.d.ts.map +1 -1
- package/lib/components/fields/NumberField.js +3 -3
- package/lib/components/fields/ObjectField.d.ts +2 -68
- package/lib/components/fields/ObjectField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.js +163 -163
- package/lib/components/fields/OptionalDataControlsField.d.ts +8 -0
- package/lib/components/fields/OptionalDataControlsField.d.ts.map +1 -0
- package/lib/components/fields/OptionalDataControlsField.js +43 -0
- package/lib/components/fields/SchemaField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.js +52 -30
- package/lib/components/fields/StringField.d.ts.map +1 -1
- package/lib/components/fields/StringField.js +8 -3
- package/lib/components/fields/index.d.ts.map +1 -1
- package/lib/components/fields/index.js +4 -0
- package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +1 -1
- package/lib/components/templates/ArrayFieldDescriptionTemplate.js +3 -3
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts +3 -3
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.js +3 -8
- package/lib/components/templates/ArrayFieldItemTemplate.d.ts +3 -3
- package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldItemTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldTemplate.d.ts +1 -1
- package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTemplate.js +4 -5
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.js +3 -3
- package/lib/components/templates/BaseInputTemplate.js +2 -2
- package/lib/components/templates/ButtonTemplates/AddButton.d.ts +1 -1
- package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/AddButton.js +2 -2
- package/lib/components/templates/FallbackFieldTemplate.d.ts +7 -0
- package/lib/components/templates/FallbackFieldTemplate.d.ts.map +1 -0
- package/lib/components/templates/FallbackFieldTemplate.js +12 -0
- package/lib/components/templates/FieldErrorTemplate.js +2 -2
- package/lib/components/templates/FieldHelpTemplate.js +2 -2
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +8 -0
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -0
- package/lib/components/templates/MultiSchemaFieldTemplate.js +10 -0
- package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ObjectFieldTemplate.js +3 -2
- package/lib/components/templates/OptionalDataControlsTemplate.d.ts +11 -0
- package/lib/components/templates/OptionalDataControlsTemplate.d.ts.map +1 -0
- package/lib/components/templates/OptionalDataControlsTemplate.js +20 -0
- package/lib/components/templates/TitleField.d.ts.map +1 -1
- package/lib/components/templates/TitleField.js +2 -2
- package/lib/components/templates/UnsupportedField.js +3 -3
- package/lib/components/templates/WrapIfAdditionalTemplate.js +2 -2
- package/lib/components/templates/index.d.ts.map +1 -1
- package/lib/components/templates/index.js +6 -0
- package/lib/components/widgets/AltDateWidget.d.ts +1 -1
- package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
- package/lib/components/widgets/AltDateWidget.js +5 -46
- package/lib/components/widgets/CheckboxWidget.d.ts +1 -1
- package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxWidget.js +2 -2
- package/lib/components/widgets/CheckboxesWidget.d.ts +1 -1
- package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.js +4 -4
- package/lib/components/widgets/FileWidget.d.ts.map +1 -1
- package/lib/components/widgets/FileWidget.js +7 -87
- package/lib/components/widgets/HiddenWidget.d.ts +1 -1
- package/lib/components/widgets/HiddenWidget.d.ts.map +1 -1
- package/lib/components/widgets/HiddenWidget.js +2 -2
- package/lib/components/widgets/RadioWidget.d.ts +1 -1
- package/lib/components/widgets/RadioWidget.d.ts.map +1 -1
- package/lib/components/widgets/RadioWidget.js +2 -2
- package/lib/components/widgets/RatingWidget.d.ts +1 -1
- package/lib/components/widgets/RatingWidget.d.ts.map +1 -1
- package/lib/components/widgets/RatingWidget.js +2 -2
- package/lib/components/widgets/SelectWidget.d.ts +1 -1
- package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
- package/lib/components/widgets/SelectWidget.js +2 -2
- package/lib/components/widgets/TextareaWidget.d.ts +1 -1
- package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
- package/lib/components/widgets/TextareaWidget.js +2 -2
- package/lib/getDefaultRegistry.d.ts.map +1 -1
- package/lib/getDefaultRegistry.js +6 -1
- package/lib/getTestRegistry.d.ts +5 -0
- package/lib/getTestRegistry.d.ts.map +1 -0
- package/lib/getTestRegistry.js +23 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -20
- package/src/components/Form.tsx +468 -206
- package/src/components/fields/ArrayField.tsx +871 -723
- package/src/components/fields/BooleanField.tsx +14 -5
- package/src/components/fields/FallbackField.tsx +157 -0
- package/src/components/fields/LayoutGridField.tsx +626 -603
- package/src/components/fields/LayoutHeaderField.tsx +3 -3
- package/src/components/fields/LayoutMultiSchemaField.tsx +9 -10
- package/src/components/fields/MultiSchemaField.tsx +57 -36
- package/src/components/fields/NullField.tsx +3 -3
- package/src/components/fields/NumberField.tsx +11 -3
- package/src/components/fields/ObjectField.tsx +308 -239
- package/src/components/fields/OptionalDataControlsField.tsx +84 -0
- package/src/components/fields/SchemaField.tsx +75 -94
- package/src/components/fields/StringField.tsx +14 -5
- package/src/components/fields/index.ts +4 -0
- package/src/components/templates/ArrayFieldDescriptionTemplate.tsx +3 -3
- package/src/components/templates/ArrayFieldItemButtonsTemplate.tsx +16 -21
- package/src/components/templates/ArrayFieldItemTemplate.tsx +3 -3
- package/src/components/templates/ArrayFieldTemplate.tsx +11 -18
- package/src/components/templates/ArrayFieldTitleTemplate.tsx +4 -3
- package/src/components/templates/BaseInputTemplate.tsx +5 -5
- package/src/components/templates/ButtonTemplates/AddButton.tsx +2 -0
- package/src/components/templates/FallbackFieldTemplate.tsx +28 -0
- package/src/components/templates/FieldErrorTemplate.tsx +2 -2
- package/src/components/templates/FieldHelpTemplate.tsx +2 -2
- package/src/components/templates/MultiSchemaFieldTemplate.tsx +20 -0
- package/src/components/templates/ObjectFieldTemplate.tsx +12 -7
- package/src/components/templates/OptionalDataControlsTemplate.tsx +43 -0
- package/src/components/templates/TitleField.tsx +6 -1
- package/src/components/templates/UnsupportedField.tsx +3 -3
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +5 -5
- package/src/components/templates/index.ts +6 -0
- package/src/components/widgets/AltDateWidget.tsx +8 -126
- package/src/components/widgets/CheckboxWidget.tsx +4 -3
- package/src/components/widgets/CheckboxesWidget.tsx +5 -4
- package/src/components/widgets/FileWidget.tsx +11 -102
- package/src/components/widgets/HiddenWidget.tsx +2 -1
- package/src/components/widgets/RadioWidget.tsx +3 -2
- package/src/components/widgets/RatingWidget.tsx +2 -1
- package/src/components/widgets/SelectWidget.tsx +3 -2
- package/src/components/widgets/TextareaWidget.tsx +3 -2
- package/src/getDefaultRegistry.ts +14 -1
- package/src/getTestRegistry.tsx +38 -0
- package/src/index.ts +2 -1
- package/dist/index.js +0 -4834
- package/dist/index.js.map +0 -7
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldProps,
|
|
3
|
+
FormContextType,
|
|
4
|
+
getSchemaType,
|
|
5
|
+
getTemplate,
|
|
6
|
+
getUiOptions,
|
|
7
|
+
isFormDataAvailable,
|
|
8
|
+
optionalControlsId,
|
|
9
|
+
OptionalDataControlsTemplateProps,
|
|
10
|
+
RJSFSchema,
|
|
11
|
+
StrictRJSFSchema,
|
|
12
|
+
TranslatableString,
|
|
13
|
+
} from '@rjsf/utils';
|
|
14
|
+
|
|
15
|
+
/** The `OptionalDataControlsField` component is used to render the optional data controls for the field associated
|
|
16
|
+
* with the given props.
|
|
17
|
+
*
|
|
18
|
+
* @param props - The `FieldProps` for this template
|
|
19
|
+
*/
|
|
20
|
+
export default function OptionalDataControlsField<
|
|
21
|
+
T = any,
|
|
22
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
23
|
+
F extends FormContextType = any,
|
|
24
|
+
>(props: FieldProps<T, S, F>) {
|
|
25
|
+
const {
|
|
26
|
+
schema,
|
|
27
|
+
uiSchema = {},
|
|
28
|
+
formData,
|
|
29
|
+
disabled = false,
|
|
30
|
+
readonly = false,
|
|
31
|
+
onChange,
|
|
32
|
+
errorSchema,
|
|
33
|
+
fieldPathId,
|
|
34
|
+
registry,
|
|
35
|
+
} = props;
|
|
36
|
+
|
|
37
|
+
const { globalUiOptions = {}, schemaUtils, translateString } = registry;
|
|
38
|
+
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
|
|
39
|
+
const OptionalDataControlsTemplate = getTemplate<'OptionalDataControlsTemplate', T, S, F>(
|
|
40
|
+
'OptionalDataControlsTemplate',
|
|
41
|
+
registry,
|
|
42
|
+
uiOptions,
|
|
43
|
+
);
|
|
44
|
+
const hasFormData = isFormDataAvailable<T>(formData);
|
|
45
|
+
let id: string;
|
|
46
|
+
let label: string | undefined;
|
|
47
|
+
let onAddClick: OptionalDataControlsTemplateProps['onAddClick'];
|
|
48
|
+
let onRemoveClick: OptionalDataControlsTemplateProps['onRemoveClick'];
|
|
49
|
+
if (disabled || readonly) {
|
|
50
|
+
id = optionalControlsId(fieldPathId, 'Msg');
|
|
51
|
+
label = hasFormData ? undefined : translateString(TranslatableString.OptionalObjectEmptyMsg);
|
|
52
|
+
} else {
|
|
53
|
+
const labelEnum = hasFormData ? TranslatableString.OptionalObjectRemove : TranslatableString.OptionalObjectAdd;
|
|
54
|
+
label = translateString(labelEnum);
|
|
55
|
+
if (hasFormData) {
|
|
56
|
+
id = optionalControlsId(fieldPathId, 'Remove');
|
|
57
|
+
onRemoveClick = () => onChange(undefined as T, fieldPathId.path, errorSchema);
|
|
58
|
+
} else {
|
|
59
|
+
id = optionalControlsId(fieldPathId, 'Add');
|
|
60
|
+
onAddClick = () => {
|
|
61
|
+
// If it has form data, store an empty object, otherwise get the default form state and use it
|
|
62
|
+
let newFormData: unknown = schemaUtils.getDefaultFormState(schema, formData, 'excludeObjectChildren');
|
|
63
|
+
if (newFormData === undefined) {
|
|
64
|
+
// If new form data ended up being undefined, and we have pushed the add button we need to actually add data
|
|
65
|
+
newFormData = getSchemaType<S>(schema) === 'array' ? [] : {};
|
|
66
|
+
}
|
|
67
|
+
onChange(newFormData as T, fieldPathId.path, errorSchema);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return (
|
|
72
|
+
label && (
|
|
73
|
+
<OptionalDataControlsTemplate
|
|
74
|
+
id={id}
|
|
75
|
+
registry={registry}
|
|
76
|
+
schema={schema}
|
|
77
|
+
uiSchema={uiSchema}
|
|
78
|
+
label={label}
|
|
79
|
+
onAddClick={onAddClick}
|
|
80
|
+
onRemoveClick={onRemoveClick}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { useCallback, Component, ComponentType } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
ADDITIONAL_PROPERTY_FLAG,
|
|
4
|
-
|
|
4
|
+
ANY_OF_KEY,
|
|
5
5
|
descriptionId,
|
|
6
6
|
ErrorSchema,
|
|
7
|
+
Field,
|
|
8
|
+
FieldPathId,
|
|
9
|
+
FieldPathList,
|
|
7
10
|
FieldProps,
|
|
8
11
|
FieldTemplateProps,
|
|
9
12
|
FormContextType,
|
|
@@ -11,12 +14,14 @@ import {
|
|
|
11
14
|
getTemplate,
|
|
12
15
|
getUiOptions,
|
|
13
16
|
ID_KEY,
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
isFormDataAvailable,
|
|
18
|
+
ONE_OF_KEY,
|
|
16
19
|
Registry,
|
|
17
20
|
RJSFSchema,
|
|
21
|
+
shouldRender,
|
|
22
|
+
shouldRenderOptionalField,
|
|
18
23
|
StrictRJSFSchema,
|
|
19
|
-
|
|
24
|
+
toFieldPathId,
|
|
20
25
|
UI_OPTIONS_KEY,
|
|
21
26
|
UIOptionsType,
|
|
22
27
|
} from '@rjsf/utils';
|
|
@@ -40,18 +45,16 @@ const COMPONENT_TYPES: { [key: string]: string } = {
|
|
|
40
45
|
*
|
|
41
46
|
* @param schema - The schema from which to obtain the type
|
|
42
47
|
* @param uiOptions - The UI Options that may affect the component decision
|
|
43
|
-
* @param idSchema - The id that is passed to the `UnsupportedFieldTemplate`
|
|
44
48
|
* @param registry - The registry from which fields and templates are obtained
|
|
45
49
|
* @returns - The `Field` component that is used to render the actual field data
|
|
46
50
|
*/
|
|
47
51
|
function getFieldComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
48
52
|
schema: S,
|
|
49
53
|
uiOptions: UIOptionsType<T, S, F>,
|
|
50
|
-
idSchema: IdSchema<T>,
|
|
51
54
|
registry: Registry<T, S, F>,
|
|
52
55
|
): ComponentType<FieldProps<T, S, F>> {
|
|
53
56
|
const field = uiOptions.field;
|
|
54
|
-
const { fields
|
|
57
|
+
const { fields } = registry;
|
|
55
58
|
if (typeof field === 'function') {
|
|
56
59
|
return field;
|
|
57
60
|
}
|
|
@@ -75,24 +78,7 @@ function getFieldComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
75
78
|
return () => null;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
return componentName in fields
|
|
79
|
-
? fields[componentName]
|
|
80
|
-
: () => {
|
|
81
|
-
const UnsupportedFieldTemplate = getTemplate<'UnsupportedFieldTemplate', T, S, F>(
|
|
82
|
-
'UnsupportedFieldTemplate',
|
|
83
|
-
registry,
|
|
84
|
-
uiOptions,
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<UnsupportedFieldTemplate
|
|
89
|
-
schema={schema}
|
|
90
|
-
idSchema={idSchema}
|
|
91
|
-
reason={translateString(TranslatableString.UnknownFieldType, [String(schema.type)])}
|
|
92
|
-
registry={registry}
|
|
93
|
-
/>
|
|
94
|
-
);
|
|
95
|
-
};
|
|
81
|
+
return componentName in fields ? fields[componentName] : fields['FallbackField'];
|
|
96
82
|
}
|
|
97
83
|
|
|
98
84
|
/** The `SchemaFieldRender` component is the work-horse of react-jsonschema-form, determining what kind of real field to
|
|
@@ -106,21 +92,21 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
106
92
|
) {
|
|
107
93
|
const {
|
|
108
94
|
schema: _schema,
|
|
109
|
-
|
|
95
|
+
fieldPathId,
|
|
110
96
|
uiSchema,
|
|
111
97
|
formData,
|
|
112
98
|
errorSchema,
|
|
113
|
-
idPrefix,
|
|
114
|
-
idSeparator,
|
|
115
99
|
name,
|
|
116
100
|
onChange,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
101
|
+
onKeyRename,
|
|
102
|
+
onKeyRenameBlur,
|
|
103
|
+
onRemoveProperty,
|
|
104
|
+
required = false,
|
|
120
105
|
registry,
|
|
121
106
|
wasPropertyKeyModified = false,
|
|
122
107
|
} = props;
|
|
123
|
-
const {
|
|
108
|
+
const { schemaUtils, globalFormOptions, globalUiOptions, fields } = registry;
|
|
109
|
+
const { AnyOfField: _AnyOfField, OneOfField: _OneOfField } = fields;
|
|
124
110
|
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalUiOptions);
|
|
125
111
|
const FieldTemplate = getTemplate<'FieldTemplate', T, S, F>('FieldTemplate', registry, uiOptions);
|
|
126
112
|
const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
|
|
@@ -131,24 +117,20 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
131
117
|
const FieldHelpTemplate = getTemplate<'FieldHelpTemplate', T, S, F>('FieldHelpTemplate', registry, uiOptions);
|
|
132
118
|
const FieldErrorTemplate = getTemplate<'FieldErrorTemplate', T, S, F>('FieldErrorTemplate', registry, uiOptions);
|
|
133
119
|
const schema = schemaUtils.retrieveSchema(_schema, formData);
|
|
134
|
-
const fieldId =
|
|
135
|
-
const idSchema = mergeObjects(
|
|
136
|
-
schemaUtils.toIdSchema(schema, fieldId, formData, idPrefix, idSeparator),
|
|
137
|
-
_idSchema,
|
|
138
|
-
) as IdSchema<T>;
|
|
120
|
+
const fieldId = fieldPathId[ID_KEY];
|
|
139
121
|
|
|
140
122
|
/** Intermediary `onChange` handler for field components that will inject the `id` of the current field into the
|
|
141
123
|
* `onChange` chain if it is not already being provided from a deeper level in the hierarchy
|
|
142
124
|
*/
|
|
143
125
|
const handleFieldComponentChange = useCallback(
|
|
144
|
-
(formData: T | undefined, newErrorSchema?: ErrorSchema<T>, id?: string) => {
|
|
126
|
+
(formData: T | undefined, path: FieldPathList, newErrorSchema?: ErrorSchema<T>, id?: string) => {
|
|
145
127
|
const theId = id || fieldId;
|
|
146
|
-
return onChange(formData, newErrorSchema, theId);
|
|
128
|
+
return onChange(formData, path, newErrorSchema, theId);
|
|
147
129
|
},
|
|
148
130
|
[fieldId, onChange],
|
|
149
131
|
);
|
|
150
132
|
|
|
151
|
-
const FieldComponent = getFieldComponent<T, S, F>(schema, uiOptions,
|
|
133
|
+
const FieldComponent = getFieldComponent<T, S, F>(schema, uiOptions, registry);
|
|
152
134
|
const disabled = Boolean(uiOptions.disabled ?? props.disabled);
|
|
153
135
|
const readonly = Boolean(uiOptions.readonly ?? (props.readonly || props.schema.readOnly || schema.readOnly));
|
|
154
136
|
const uiSchemaHideError = uiOptions.hideError;
|
|
@@ -159,7 +141,40 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
159
141
|
return null;
|
|
160
142
|
}
|
|
161
143
|
|
|
162
|
-
|
|
144
|
+
let displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
|
|
145
|
+
|
|
146
|
+
/** If the schema `anyOf` or 'oneOf' can be rendered as a select control, don't render the selection and let
|
|
147
|
+
* `StringField` component handle rendering unless there is a field override and that field replaces the any or one of
|
|
148
|
+
*/
|
|
149
|
+
const isReplacingAnyOrOneOf = uiOptions.field && uiOptions.fieldReplacesAnyOrOneOf === true;
|
|
150
|
+
let XxxOfField: Field<T, S, F> | undefined;
|
|
151
|
+
let XxxOfOptions: S[] | undefined;
|
|
152
|
+
// When rendering the `XxxOfField` we'll need to change the fieldPathId of the main component, remembering the
|
|
153
|
+
// fieldPathId of the children for the ObjectField and ArrayField
|
|
154
|
+
let fieldPathIdProps: { fieldPathId: FieldPathId; childFieldPathId?: FieldPathId } = { fieldPathId };
|
|
155
|
+
if ((ANY_OF_KEY in schema || ONE_OF_KEY in schema) && !isReplacingAnyOrOneOf && !schemaUtils.isSelect(schema)) {
|
|
156
|
+
if (schema[ANY_OF_KEY]) {
|
|
157
|
+
XxxOfField = _AnyOfField;
|
|
158
|
+
XxxOfOptions = schema[ANY_OF_KEY].map((_schema) =>
|
|
159
|
+
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
160
|
+
);
|
|
161
|
+
} else if (schema[ONE_OF_KEY]) {
|
|
162
|
+
XxxOfField = _OneOfField;
|
|
163
|
+
XxxOfOptions = schema[ONE_OF_KEY].map((_schema) =>
|
|
164
|
+
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
// When the anyOf/oneOf is an optional data control render AND it does not have form data, hide the label
|
|
168
|
+
const isOptionalRender = shouldRenderOptionalField<T, S, F>(registry, schema, required, uiSchema);
|
|
169
|
+
const hasFormData = isFormDataAvailable<T>(formData);
|
|
170
|
+
displayLabel = displayLabel && (!isOptionalRender || hasFormData);
|
|
171
|
+
fieldPathIdProps = {
|
|
172
|
+
childFieldPathId: fieldPathId,
|
|
173
|
+
// The main FieldComponent will add `XxxOf` onto the fieldPathId to avoid duplication with the rendering of the
|
|
174
|
+
// same FieldComponent by the `XxxOfField`
|
|
175
|
+
fieldPathId: toFieldPathId('XxxOf', globalFormOptions, fieldPathId),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
163
178
|
|
|
164
179
|
const { __errors, ...fieldErrorSchema } = errorSchema || {};
|
|
165
180
|
// See #439: uiSchema: Don't pass consumed class names or style to child components
|
|
@@ -172,7 +187,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
172
187
|
<FieldComponent
|
|
173
188
|
{...props}
|
|
174
189
|
onChange={handleFieldComponentChange}
|
|
175
|
-
|
|
190
|
+
{...fieldPathIdProps}
|
|
176
191
|
schema={schema}
|
|
177
192
|
uiSchema={fieldUiSchema}
|
|
178
193
|
disabled={disabled}
|
|
@@ -180,12 +195,11 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
180
195
|
hideError={hideError}
|
|
181
196
|
autofocus={autofocus}
|
|
182
197
|
errorSchema={fieldErrorSchema as ErrorSchema}
|
|
183
|
-
formContext={formContext}
|
|
184
198
|
rawErrors={__errors}
|
|
185
199
|
/>
|
|
186
200
|
);
|
|
187
201
|
|
|
188
|
-
const id =
|
|
202
|
+
const id = fieldPathId[ID_KEY];
|
|
189
203
|
|
|
190
204
|
// If this schema has a title defined, but the user has set a new key/label, retain their input.
|
|
191
205
|
let label;
|
|
@@ -213,7 +227,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
213
227
|
const helpComponent = (
|
|
214
228
|
<FieldHelpTemplate
|
|
215
229
|
help={help}
|
|
216
|
-
|
|
230
|
+
fieldPathId={fieldPathId}
|
|
217
231
|
schema={schema}
|
|
218
232
|
uiSchema={uiSchema}
|
|
219
233
|
hasErrors={!hideError && __errors && __errors.length > 0}
|
|
@@ -225,11 +239,11 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
225
239
|
* unless it can be rendered as select control
|
|
226
240
|
*/
|
|
227
241
|
const errorsComponent =
|
|
228
|
-
hideError || (
|
|
242
|
+
hideError || (XxxOfField && !schemaUtils.isSelect(schema)) ? undefined : (
|
|
229
243
|
<FieldErrorTemplate
|
|
230
244
|
errors={__errors}
|
|
231
245
|
errorSchema={errorSchema}
|
|
232
|
-
|
|
246
|
+
fieldPathId={fieldPathId}
|
|
233
247
|
schema={schema}
|
|
234
248
|
uiSchema={uiSchema}
|
|
235
249
|
registry={registry}
|
|
@@ -238,7 +252,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
238
252
|
const fieldProps: Omit<FieldTemplateProps<T, S, F>, 'children'> = {
|
|
239
253
|
description: (
|
|
240
254
|
<DescriptionFieldTemplate
|
|
241
|
-
id={descriptionId
|
|
255
|
+
id={descriptionId(id)}
|
|
242
256
|
description={description}
|
|
243
257
|
schema={schema}
|
|
244
258
|
uiSchema={uiSchema}
|
|
@@ -254,8 +268,9 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
254
268
|
label,
|
|
255
269
|
hidden,
|
|
256
270
|
onChange,
|
|
257
|
-
|
|
258
|
-
|
|
271
|
+
onKeyRename,
|
|
272
|
+
onKeyRenameBlur,
|
|
273
|
+
onRemoveProperty,
|
|
259
274
|
required,
|
|
260
275
|
disabled,
|
|
261
276
|
readonly,
|
|
@@ -263,68 +278,29 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
263
278
|
displayLabel,
|
|
264
279
|
classNames: classNames.join(' ').trim(),
|
|
265
280
|
style: uiOptions.style,
|
|
266
|
-
formContext,
|
|
267
281
|
formData,
|
|
268
282
|
schema,
|
|
269
283
|
uiSchema,
|
|
270
284
|
registry,
|
|
271
285
|
};
|
|
272
286
|
|
|
273
|
-
const _AnyOfField = registry.fields.AnyOfField;
|
|
274
|
-
const _OneOfField = registry.fields.OneOfField;
|
|
275
|
-
const isReplacingAnyOrOneOf = uiSchema?.['ui:field'] && uiSchema?.['ui:fieldReplacesAnyOrOneOf'] === true;
|
|
276
|
-
|
|
277
287
|
return (
|
|
278
288
|
<FieldTemplate {...fieldProps}>
|
|
279
289
|
<>
|
|
280
290
|
{field}
|
|
281
|
-
{
|
|
282
|
-
|
|
283
|
-
render the selection and let `StringField` component handle
|
|
284
|
-
rendering
|
|
285
|
-
*/}
|
|
286
|
-
{schema.anyOf && !isReplacingAnyOrOneOf && !schemaUtils.isSelect(schema) && (
|
|
287
|
-
<_AnyOfField
|
|
291
|
+
{XxxOfField && (
|
|
292
|
+
<XxxOfField
|
|
288
293
|
name={name}
|
|
289
294
|
disabled={disabled}
|
|
290
295
|
readonly={readonly}
|
|
291
296
|
hideError={hideError}
|
|
292
297
|
errorSchema={errorSchema}
|
|
293
298
|
formData={formData}
|
|
294
|
-
|
|
295
|
-
idPrefix={idPrefix}
|
|
296
|
-
idSchema={idSchema}
|
|
297
|
-
idSeparator={idSeparator}
|
|
299
|
+
fieldPathId={fieldPathId}
|
|
298
300
|
onBlur={props.onBlur}
|
|
299
301
|
onChange={props.onChange}
|
|
300
302
|
onFocus={props.onFocus}
|
|
301
|
-
options={
|
|
302
|
-
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
303
|
-
)}
|
|
304
|
-
registry={registry}
|
|
305
|
-
required={required}
|
|
306
|
-
schema={schema}
|
|
307
|
-
uiSchema={uiSchema}
|
|
308
|
-
/>
|
|
309
|
-
)}
|
|
310
|
-
{schema.oneOf && !isReplacingAnyOrOneOf && !schemaUtils.isSelect(schema) && (
|
|
311
|
-
<_OneOfField
|
|
312
|
-
name={name}
|
|
313
|
-
disabled={disabled}
|
|
314
|
-
readonly={readonly}
|
|
315
|
-
hideError={hideError}
|
|
316
|
-
errorSchema={errorSchema}
|
|
317
|
-
formData={formData}
|
|
318
|
-
formContext={formContext}
|
|
319
|
-
idPrefix={idPrefix}
|
|
320
|
-
idSchema={idSchema}
|
|
321
|
-
idSeparator={idSeparator}
|
|
322
|
-
onBlur={props.onBlur}
|
|
323
|
-
onChange={props.onChange}
|
|
324
|
-
onFocus={props.onFocus}
|
|
325
|
-
options={schema.oneOf.map((_schema) =>
|
|
326
|
-
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
327
|
-
)}
|
|
303
|
+
options={XxxOfOptions}
|
|
328
304
|
registry={registry}
|
|
329
305
|
required={required}
|
|
330
306
|
schema={schema}
|
|
@@ -343,7 +319,12 @@ class SchemaField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
343
319
|
FieldProps<T, S, F>
|
|
344
320
|
> {
|
|
345
321
|
shouldComponentUpdate(nextProps: Readonly<FieldProps<T, S, F>>) {
|
|
346
|
-
|
|
322
|
+
const {
|
|
323
|
+
registry: { globalFormOptions },
|
|
324
|
+
} = this.props;
|
|
325
|
+
const { experimental_componentUpdateStrategy = 'customDeep' } = globalFormOptions;
|
|
326
|
+
|
|
327
|
+
return shouldRender(this, nextProps, this.state, experimental_componentUpdateStrategy);
|
|
347
328
|
}
|
|
348
329
|
|
|
349
330
|
render() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
1
2
|
import {
|
|
2
3
|
getWidget,
|
|
3
4
|
getUiOptions,
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
FormContextType,
|
|
8
9
|
RJSFSchema,
|
|
9
10
|
StrictRJSFSchema,
|
|
11
|
+
ErrorSchema,
|
|
10
12
|
} from '@rjsf/utils';
|
|
11
13
|
|
|
12
14
|
/** The `StringField` component is used to render a schema field that represents a string type
|
|
@@ -20,7 +22,7 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
20
22
|
schema,
|
|
21
23
|
name,
|
|
22
24
|
uiSchema,
|
|
23
|
-
|
|
25
|
+
fieldPathId,
|
|
24
26
|
formData,
|
|
25
27
|
required,
|
|
26
28
|
disabled = false,
|
|
@@ -34,7 +36,7 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
34
36
|
hideError,
|
|
35
37
|
} = props;
|
|
36
38
|
const { title, format } = schema;
|
|
37
|
-
const { widgets,
|
|
39
|
+
const { widgets, schemaUtils, globalUiOptions } = registry;
|
|
38
40
|
const enumOptions = schemaUtils.isSelect(schema) ? optionsList<T, S, F>(schema, uiSchema) : undefined;
|
|
39
41
|
let defaultWidget = enumOptions ? 'select' : 'text';
|
|
40
42
|
if (format && hasWidget<T, S, F>(schema, format, widgets)) {
|
|
@@ -44,28 +46,35 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
44
46
|
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
|
|
45
47
|
const label = uiTitle ?? title ?? name;
|
|
46
48
|
const Widget = getWidget<T, S, F>(schema, widget, widgets);
|
|
49
|
+
const onWidgetChange = useCallback(
|
|
50
|
+
(value: T | undefined, errorSchema?: ErrorSchema, id?: string) => {
|
|
51
|
+
// String field change passes an empty path array to the parent field which adds the appropriate path
|
|
52
|
+
return onChange(value, fieldPathId.path, errorSchema, id);
|
|
53
|
+
},
|
|
54
|
+
[onChange, fieldPathId],
|
|
55
|
+
);
|
|
47
56
|
return (
|
|
48
57
|
<Widget
|
|
49
58
|
options={{ ...options, enumOptions }}
|
|
50
59
|
schema={schema}
|
|
51
60
|
uiSchema={uiSchema}
|
|
52
|
-
id={
|
|
61
|
+
id={fieldPathId.$id}
|
|
53
62
|
name={name}
|
|
54
63
|
label={label}
|
|
55
64
|
hideLabel={!displayLabel}
|
|
56
65
|
hideError={hideError}
|
|
57
66
|
value={formData}
|
|
58
|
-
onChange={
|
|
67
|
+
onChange={onWidgetChange}
|
|
59
68
|
onBlur={onBlur}
|
|
60
69
|
onFocus={onFocus}
|
|
61
70
|
required={required}
|
|
62
71
|
disabled={disabled}
|
|
63
72
|
readonly={readonly}
|
|
64
|
-
formContext={formContext}
|
|
65
73
|
autofocus={autofocus}
|
|
66
74
|
registry={registry}
|
|
67
75
|
placeholder={placeholder}
|
|
68
76
|
rawErrors={rawErrors}
|
|
77
|
+
htmlName={fieldPathId.name}
|
|
69
78
|
/>
|
|
70
79
|
);
|
|
71
80
|
}
|
|
@@ -2,12 +2,14 @@ import { Field, FormContextType, RegistryFieldsType, RJSFSchema, StrictRJSFSchem
|
|
|
2
2
|
|
|
3
3
|
import ArrayField from './ArrayField';
|
|
4
4
|
import BooleanField from './BooleanField';
|
|
5
|
+
import FallbackField from './FallbackField';
|
|
5
6
|
import LayoutGridField from './LayoutGridField';
|
|
6
7
|
import LayoutHeaderField from './LayoutHeaderField';
|
|
7
8
|
import LayoutMultiSchemaField from './LayoutMultiSchemaField';
|
|
8
9
|
import MultiSchemaField from './MultiSchemaField';
|
|
9
10
|
import NumberField from './NumberField';
|
|
10
11
|
import ObjectField from './ObjectField';
|
|
12
|
+
import OptionalDataControlsField from './OptionalDataControlsField';
|
|
11
13
|
import SchemaField from './SchemaField';
|
|
12
14
|
import StringField from './StringField';
|
|
13
15
|
import NullField from './NullField';
|
|
@@ -22,12 +24,14 @@ function fields<
|
|
|
22
24
|
ArrayField: ArrayField as unknown as Field<T, S, F>,
|
|
23
25
|
// ArrayField falls back to SchemaField if ArraySchemaField is not defined, which it isn't by default
|
|
24
26
|
BooleanField,
|
|
27
|
+
FallbackField,
|
|
25
28
|
LayoutGridField,
|
|
26
29
|
LayoutHeaderField,
|
|
27
30
|
LayoutMultiSchemaField,
|
|
28
31
|
NumberField,
|
|
29
32
|
ObjectField,
|
|
30
33
|
OneOfField: MultiSchemaField,
|
|
34
|
+
OptionalDataControlsField,
|
|
31
35
|
SchemaField,
|
|
32
36
|
StringField,
|
|
33
37
|
NullField,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '@rjsf/utils';
|
|
10
10
|
|
|
11
11
|
/** The `ArrayFieldDescriptionTemplate` component renders a `DescriptionFieldTemplate` with an `id` derived from
|
|
12
|
-
* the `
|
|
12
|
+
* the `fieldPathId`.
|
|
13
13
|
*
|
|
14
14
|
* @param props - The `ArrayFieldDescriptionProps` for the component
|
|
15
15
|
*/
|
|
@@ -18,7 +18,7 @@ export default function ArrayFieldDescriptionTemplate<
|
|
|
18
18
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
19
19
|
F extends FormContextType = any,
|
|
20
20
|
>(props: ArrayFieldDescriptionProps<T, S, F>) {
|
|
21
|
-
const {
|
|
21
|
+
const { fieldPathId, description, registry, schema, uiSchema } = props;
|
|
22
22
|
const options = getUiOptions<T, S, F>(uiSchema, registry.globalUiOptions);
|
|
23
23
|
const { label: displayLabel = true } = options;
|
|
24
24
|
if (!description || !displayLabel) {
|
|
@@ -31,7 +31,7 @@ export default function ArrayFieldDescriptionTemplate<
|
|
|
31
31
|
);
|
|
32
32
|
return (
|
|
33
33
|
<DescriptionFieldTemplate
|
|
34
|
-
id={descriptionId
|
|
34
|
+
id={descriptionId(fieldPathId)}
|
|
35
35
|
description={description}
|
|
36
36
|
schema={schema}
|
|
37
37
|
uiSchema={uiSchema}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
1
|
import {
|
|
3
|
-
|
|
2
|
+
ArrayFieldItemButtonsTemplateProps,
|
|
4
3
|
buttonId,
|
|
5
4
|
FormContextType,
|
|
6
5
|
RJSFSchema,
|
|
@@ -10,72 +9,68 @@ import {
|
|
|
10
9
|
/** The `ArrayFieldTemplateItemButtons` component is the template used to render the buttons associate3d with items of
|
|
11
10
|
* an array.
|
|
12
11
|
*
|
|
13
|
-
* @param props - The `
|
|
12
|
+
* @param props - The `ArrayFieldItemButtonsTemplateProps` props for the component
|
|
14
13
|
*/
|
|
15
14
|
export default function ArrayFieldItemButtonsTemplate<
|
|
16
15
|
T = any,
|
|
17
16
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
18
17
|
F extends FormContextType = any,
|
|
19
|
-
>(props:
|
|
18
|
+
>(props: ArrayFieldItemButtonsTemplateProps<T, S, F>) {
|
|
20
19
|
const {
|
|
21
20
|
disabled,
|
|
22
21
|
hasCopy,
|
|
23
22
|
hasMoveDown,
|
|
24
23
|
hasMoveUp,
|
|
25
24
|
hasRemove,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
fieldPathId,
|
|
26
|
+
onCopyItem,
|
|
27
|
+
onRemoveItem,
|
|
28
|
+
onMoveDownItem,
|
|
29
|
+
onMoveUpItem,
|
|
31
30
|
readonly,
|
|
32
31
|
registry,
|
|
33
32
|
uiSchema,
|
|
34
33
|
} = props;
|
|
35
34
|
const { CopyButton, MoveDownButton, MoveUpButton, RemoveButton } = registry.templates.ButtonTemplates;
|
|
36
|
-
const onCopyClick = useMemo(() => onCopyIndexClick(index), [index, onCopyIndexClick]);
|
|
37
|
-
const onRemoveClick = useMemo(() => onDropIndexClick(index), [index, onDropIndexClick]);
|
|
38
|
-
const onArrowUpClick = useMemo(() => onReorderClick(index, index - 1), [index, onReorderClick]);
|
|
39
|
-
const onArrowDownClick = useMemo(() => onReorderClick(index, index + 1), [index, onReorderClick]);
|
|
40
35
|
|
|
41
36
|
return (
|
|
42
37
|
<>
|
|
43
38
|
{(hasMoveUp || hasMoveDown) && (
|
|
44
39
|
<MoveUpButton
|
|
45
|
-
id={buttonId
|
|
40
|
+
id={buttonId(fieldPathId, 'moveUp')}
|
|
46
41
|
className='rjsf-array-item-move-up'
|
|
47
42
|
disabled={disabled || readonly || !hasMoveUp}
|
|
48
|
-
onClick={
|
|
43
|
+
onClick={onMoveUpItem}
|
|
49
44
|
uiSchema={uiSchema}
|
|
50
45
|
registry={registry}
|
|
51
46
|
/>
|
|
52
47
|
)}
|
|
53
48
|
{(hasMoveUp || hasMoveDown) && (
|
|
54
49
|
<MoveDownButton
|
|
55
|
-
id={buttonId
|
|
50
|
+
id={buttonId(fieldPathId, 'moveDown')}
|
|
56
51
|
className='rjsf-array-item-move-down'
|
|
57
52
|
disabled={disabled || readonly || !hasMoveDown}
|
|
58
|
-
onClick={
|
|
53
|
+
onClick={onMoveDownItem}
|
|
59
54
|
uiSchema={uiSchema}
|
|
60
55
|
registry={registry}
|
|
61
56
|
/>
|
|
62
57
|
)}
|
|
63
58
|
{hasCopy && (
|
|
64
59
|
<CopyButton
|
|
65
|
-
id={buttonId
|
|
60
|
+
id={buttonId(fieldPathId, 'copy')}
|
|
66
61
|
className='rjsf-array-item-copy'
|
|
67
62
|
disabled={disabled || readonly}
|
|
68
|
-
onClick={
|
|
63
|
+
onClick={onCopyItem}
|
|
69
64
|
uiSchema={uiSchema}
|
|
70
65
|
registry={registry}
|
|
71
66
|
/>
|
|
72
67
|
)}
|
|
73
68
|
{hasRemove && (
|
|
74
69
|
<RemoveButton
|
|
75
|
-
id={buttonId
|
|
70
|
+
id={buttonId(fieldPathId, 'remove')}
|
|
76
71
|
className='rjsf-array-item-remove'
|
|
77
72
|
disabled={disabled || readonly}
|
|
78
|
-
onClick={
|
|
73
|
+
onClick={onRemoveItem}
|
|
79
74
|
uiSchema={uiSchema}
|
|
80
75
|
registry={registry}
|
|
81
76
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
ArrayFieldItemTemplateProps,
|
|
4
4
|
FormContextType,
|
|
5
5
|
getTemplate,
|
|
6
6
|
getUiOptions,
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
|
|
11
11
|
/** The `ArrayFieldItemTemplate` component is the template used to render an items of an array.
|
|
12
12
|
*
|
|
13
|
-
* @param props - The `
|
|
13
|
+
* @param props - The `ArrayFieldItemTemplateProps` props for the component
|
|
14
14
|
*/
|
|
15
15
|
export default function ArrayFieldItemTemplate<
|
|
16
16
|
T = any,
|
|
17
17
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
18
18
|
F extends FormContextType = any,
|
|
19
|
-
>(props:
|
|
19
|
+
>(props: ArrayFieldItemTemplateProps<T, S, F>) {
|
|
20
20
|
const { children, className, buttonsProps, hasToolbar, registry, uiSchema } = props;
|
|
21
21
|
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
|
22
22
|
const ArrayFieldItemButtonsTemplate = getTemplate<'ArrayFieldItemButtonsTemplate', T, S, F>(
|