@rjsf/core 5.24.10 → 6.0.0-beta.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/core.umd.js +982 -196
- package/dist/index.esm.js +1366 -490
- package/dist/index.esm.js.map +4 -4
- package/dist/index.js +1452 -616
- package/dist/index.js.map +4 -4
- package/lib/components/Form.d.ts +0 -7
- package/lib/components/Form.d.ts.map +1 -1
- package/lib/components/Form.js +2 -5
- package/lib/components/fields/ArrayField.d.ts +19 -9
- package/lib/components/fields/ArrayField.d.ts.map +1 -1
- package/lib/components/fields/ArrayField.js +22 -12
- package/lib/components/fields/BooleanField.d.ts.map +1 -1
- package/lib/components/fields/BooleanField.js +3 -9
- package/lib/components/fields/LayoutGridField.d.ts +480 -0
- package/lib/components/fields/LayoutGridField.d.ts.map +1 -0
- package/lib/components/fields/LayoutGridField.js +711 -0
- package/lib/components/fields/LayoutHeaderField.d.ts +12 -0
- package/lib/components/fields/LayoutHeaderField.d.ts.map +1 -0
- package/lib/components/fields/LayoutHeaderField.js +23 -0
- package/lib/components/fields/LayoutMultiSchemaField.d.ts +28 -0
- package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -0
- package/lib/components/fields/LayoutMultiSchemaField.js +114 -0
- package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.js +29 -23
- package/lib/components/fields/SchemaField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.js +2 -8
- package/lib/components/fields/index.d.ts.map +1 -1
- package/lib/components/fields/index.js +6 -0
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts +8 -0
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts.map +1 -0
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.js +17 -0
- 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 +7 -5
- 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 +3 -3
- package/lib/components/templates/ButtonTemplates/IconButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/IconButton.js +4 -4
- package/lib/components/templates/GridTemplate.d.ts +8 -0
- package/lib/components/templates/GridTemplate.d.ts.map +1 -0
- package/lib/components/templates/GridTemplate.js +10 -0
- package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ObjectFieldTemplate.js +2 -2
- package/lib/components/templates/WrapIfAdditionalTemplate.d.ts.map +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.js +9 -4
- package/lib/components/templates/index.d.ts.map +1 -1
- package/lib/components/templates/index.js +4 -0
- package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
- package/lib/components/widgets/FileWidget.js +1 -1
- package/lib/components/widgets/RadioWidget.js +3 -3
- package/lib/components/widgets/RatingWidget.d.ts +15 -0
- package/lib/components/widgets/RatingWidget.d.ts.map +1 -0
- package/lib/components/widgets/RatingWidget.js +63 -0
- package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
- package/lib/components/widgets/SelectWidget.js +4 -4
- package/lib/components/widgets/index.d.ts.map +1 -1
- package/lib/components/widgets/index.js +2 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/withTheme.d.ts.map +1 -1
- package/lib/withTheme.js +1 -0
- package/package.json +44 -35
- package/src/components/Form.tsx +24 -30
- package/src/components/fields/ArrayField.tsx +34 -24
- package/src/components/fields/BooleanField.tsx +6 -14
- package/src/components/fields/LayoutGridField.tsx +967 -0
- package/src/components/fields/LayoutHeaderField.tsx +49 -0
- package/src/components/fields/LayoutMultiSchemaField.tsx +228 -0
- package/src/components/fields/NullField.tsx +1 -1
- package/src/components/fields/NumberField.tsx +2 -2
- package/src/components/fields/ObjectField.tsx +32 -28
- package/src/components/fields/SchemaField.tsx +14 -22
- package/src/components/fields/StringField.tsx +2 -2
- package/src/components/fields/index.ts +7 -1
- package/src/components/templates/ArrayFieldDescriptionTemplate.tsx +2 -2
- package/src/components/templates/ArrayFieldItemButtonsTemplate.tsx +85 -0
- package/src/components/templates/ArrayFieldItemTemplate.tsx +18 -57
- package/src/components/templates/ArrayFieldTemplate.tsx +10 -8
- package/src/components/templates/ArrayFieldTitleTemplate.tsx +2 -2
- package/src/components/templates/BaseInputTemplate.tsx +4 -4
- package/src/components/templates/ButtonTemplates/IconButton.tsx +9 -36
- package/src/components/templates/ButtonTemplates/SubmitButton.tsx +1 -1
- package/src/components/templates/ButtonTemplates/index.ts +1 -1
- package/src/components/templates/DescriptionField.tsx +1 -1
- package/src/components/templates/FieldErrorTemplate.tsx +1 -1
- package/src/components/templates/FieldHelpTemplate.tsx +1 -1
- package/src/components/templates/FieldTemplate/FieldTemplate.tsx +2 -2
- package/src/components/templates/GridTemplate.tsx +15 -0
- package/src/components/templates/ObjectFieldTemplate.tsx +5 -3
- package/src/components/templates/TitleField.tsx +1 -1
- package/src/components/templates/UnsupportedField.tsx +1 -1
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +14 -4
- package/src/components/templates/index.ts +4 -0
- package/src/components/widgets/AltDateWidget.tsx +9 -6
- package/src/components/widgets/CheckboxWidget.tsx +4 -4
- package/src/components/widgets/CheckboxesWidget.tsx +2 -2
- package/src/components/widgets/ColorWidget.tsx +1 -1
- package/src/components/widgets/DateTimeWidget.tsx +1 -1
- package/src/components/widgets/DateWidget.tsx +1 -1
- package/src/components/widgets/EmailWidget.tsx +1 -1
- package/src/components/widgets/FileWidget.tsx +4 -4
- package/src/components/widgets/PasswordWidget.tsx +1 -1
- package/src/components/widgets/RadioWidget.tsx +3 -3
- package/src/components/widgets/RangeWidget.tsx +1 -1
- package/src/components/widgets/RatingWidget.tsx +129 -0
- package/src/components/widgets/SelectWidget.tsx +4 -3
- package/src/components/widgets/TextWidget.tsx +1 -1
- package/src/components/widgets/TextareaWidget.tsx +3 -3
- package/src/components/widgets/TimeWidget.tsx +1 -1
- package/src/components/widgets/URLWidget.tsx +1 -1
- package/src/components/widgets/UpDownWidget.tsx +1 -1
- package/src/components/widgets/index.ts +3 -1
- package/src/getDefaultRegistry.ts +1 -1
- package/src/tsconfig.json +0 -3
- package/src/withTheme.tsx +4 -3
- package/LICENSE.md +0 -201
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getTemplate,
|
|
3
|
+
getUiOptions,
|
|
4
|
+
titleId,
|
|
5
|
+
FieldProps,
|
|
6
|
+
FormContextType,
|
|
7
|
+
RJSFSchema,
|
|
8
|
+
StrictRJSFSchema,
|
|
9
|
+
TemplatesType,
|
|
10
|
+
} from '@rjsf/utils';
|
|
11
|
+
|
|
12
|
+
/** The `LayoutHeaderField` component renders a `TitleFieldTemplate` with an `id` derived from the `idSchema`
|
|
13
|
+
* and whether it is `required` from the props. The `title` is derived from the props as follows:
|
|
14
|
+
* - If there is a title in the `uiSchema`, it is displayed
|
|
15
|
+
* - Else, if there is an explicit `title` passed in the props, it is displayed
|
|
16
|
+
* - Otherwise, if there is a title in the `schema`, it is displayed
|
|
17
|
+
* - Finally, the `name` prop is displayed as the title
|
|
18
|
+
*
|
|
19
|
+
* @param props - The `LayoutHeaderField` for the component
|
|
20
|
+
*/
|
|
21
|
+
export default function LayoutHeaderField<
|
|
22
|
+
T = any,
|
|
23
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
24
|
+
F extends FormContextType = any,
|
|
25
|
+
>(props: FieldProps<T, S, F>) {
|
|
26
|
+
const { idSchema, title, schema, uiSchema, required, registry, name } = props;
|
|
27
|
+
const options = getUiOptions<T, S, F>(uiSchema, registry.globalUiOptions);
|
|
28
|
+
const { title: uiTitle } = options;
|
|
29
|
+
const { title: schemaTitle } = schema;
|
|
30
|
+
const fieldTitle = uiTitle || title || schemaTitle || name;
|
|
31
|
+
if (!fieldTitle) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const TitleFieldTemplate: TemplatesType<T, S, F>['TitleFieldTemplate'] = getTemplate<'TitleFieldTemplate', T, S, F>(
|
|
35
|
+
'TitleFieldTemplate',
|
|
36
|
+
registry,
|
|
37
|
+
options,
|
|
38
|
+
);
|
|
39
|
+
return (
|
|
40
|
+
<TitleFieldTemplate
|
|
41
|
+
id={titleId<T>(idSchema)}
|
|
42
|
+
title={fieldTitle}
|
|
43
|
+
required={required}
|
|
44
|
+
schema={schema}
|
|
45
|
+
uiSchema={uiSchema}
|
|
46
|
+
registry={registry}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ANY_OF_KEY,
|
|
4
|
+
CONST_KEY,
|
|
5
|
+
DEFAULT_KEY,
|
|
6
|
+
EnumOptionsType,
|
|
7
|
+
ERRORS_KEY,
|
|
8
|
+
FieldProps,
|
|
9
|
+
FormContextType,
|
|
10
|
+
getDiscriminatorFieldFromSchema,
|
|
11
|
+
hashObject,
|
|
12
|
+
ID_KEY,
|
|
13
|
+
ONE_OF_KEY,
|
|
14
|
+
optionsList,
|
|
15
|
+
PROPERTIES_KEY,
|
|
16
|
+
RJSFSchema,
|
|
17
|
+
getTemplate,
|
|
18
|
+
getUiOptions,
|
|
19
|
+
getWidget,
|
|
20
|
+
SchemaUtilsType,
|
|
21
|
+
StrictRJSFSchema,
|
|
22
|
+
UiSchema,
|
|
23
|
+
} from '@rjsf/utils';
|
|
24
|
+
import get from 'lodash/get';
|
|
25
|
+
import has from 'lodash/has';
|
|
26
|
+
import isEmpty from 'lodash/isEmpty';
|
|
27
|
+
import noop from 'lodash/noop';
|
|
28
|
+
import omit from 'lodash/omit';
|
|
29
|
+
import set from 'lodash/set';
|
|
30
|
+
|
|
31
|
+
/** Gets the selected option from the list of `options`, using the `selectorField` to search inside each `option` for
|
|
32
|
+
* the `properties[selectorField].default(or const)` that matches the given `value`.
|
|
33
|
+
*
|
|
34
|
+
* @param options - The list of schemas each representing a choice in the `oneOf`
|
|
35
|
+
* @param selectorField - The name of the field that is common in all of the schemas that represents the selector field
|
|
36
|
+
* @param value - The current value of the selector field from the data
|
|
37
|
+
*/
|
|
38
|
+
export function getSelectedOption<S extends StrictRJSFSchema = RJSFSchema>(
|
|
39
|
+
options: EnumOptionsType<S>[],
|
|
40
|
+
selectorField: string,
|
|
41
|
+
value: unknown,
|
|
42
|
+
): S | undefined {
|
|
43
|
+
const defaultValue = '!@#!@$@#$!@$#';
|
|
44
|
+
const schemaOptions: S[] = options.map(({ schema }) => schema!);
|
|
45
|
+
return schemaOptions.find((option) => {
|
|
46
|
+
const selector = get(option, [PROPERTIES_KEY, selectorField]);
|
|
47
|
+
const result = get(selector, DEFAULT_KEY, get(selector, CONST_KEY, defaultValue));
|
|
48
|
+
return result === value;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Computes the `enumOptions` array from the schema and options.
|
|
53
|
+
*
|
|
54
|
+
* @param schema - The schema that contains the `options`
|
|
55
|
+
* @param options - The options from the `schema`
|
|
56
|
+
* @param schemaUtils - The SchemaUtilsType object used to call retrieveSchema,
|
|
57
|
+
* @param [uiSchema] - The optional uiSchema for the schema
|
|
58
|
+
* @param [formData] - The optional formData associated with the schema
|
|
59
|
+
* @returns - The list of enumOptions for the `schema` and `options`
|
|
60
|
+
* @throws - Error when no enum options were computed
|
|
61
|
+
*/
|
|
62
|
+
export function computeEnumOptions<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
63
|
+
schema: S,
|
|
64
|
+
options: S[],
|
|
65
|
+
schemaUtils: SchemaUtilsType<T, S, F>,
|
|
66
|
+
uiSchema?: UiSchema<T, S, F>,
|
|
67
|
+
formData?: T,
|
|
68
|
+
): EnumOptionsType<S>[] {
|
|
69
|
+
const realOptions = options.map((opt: S) => schemaUtils.retrieveSchema(opt, formData));
|
|
70
|
+
let tempSchema = schema;
|
|
71
|
+
if (has(schema, ONE_OF_KEY)) {
|
|
72
|
+
tempSchema = { ...schema, [ONE_OF_KEY]: realOptions };
|
|
73
|
+
} else if (has(schema, ANY_OF_KEY)) {
|
|
74
|
+
tempSchema = { ...schema, [ANY_OF_KEY]: realOptions };
|
|
75
|
+
}
|
|
76
|
+
const enumOptions = optionsList<T, S, F>(tempSchema, uiSchema);
|
|
77
|
+
if (!enumOptions) {
|
|
78
|
+
throw new Error(`No enumOptions were computed from the schema ${JSON.stringify(tempSchema)}`);
|
|
79
|
+
}
|
|
80
|
+
return enumOptions;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The `LayoutMultiSchemaField` is an adaptation of the `MultiSchemaField` but changed considerably to only
|
|
84
|
+
* support `anyOf`/`oneOf` fields that are being displayed in a `LayoutGridField` where the field selection is shown as
|
|
85
|
+
* a radio group by default. It expects that a `selectorField` is provided (either directly via the `discriminator`
|
|
86
|
+
* field or indirectly via `ui:optionsSchemaSelector` in the `uiSchema`) to help determine which `anyOf`/`oneOf` schema
|
|
87
|
+
* is active. If no `selectorField` is specified, then an error is thrown.
|
|
88
|
+
*/
|
|
89
|
+
export default function LayoutMultiSchemaField<
|
|
90
|
+
T = any,
|
|
91
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
92
|
+
F extends FormContextType = any,
|
|
93
|
+
>(props: FieldProps<T, S, F>) {
|
|
94
|
+
const {
|
|
95
|
+
name,
|
|
96
|
+
baseType,
|
|
97
|
+
disabled = false,
|
|
98
|
+
formData,
|
|
99
|
+
idSchema,
|
|
100
|
+
onBlur,
|
|
101
|
+
onChange,
|
|
102
|
+
options,
|
|
103
|
+
onFocus,
|
|
104
|
+
registry,
|
|
105
|
+
uiSchema,
|
|
106
|
+
schema,
|
|
107
|
+
formContext,
|
|
108
|
+
autofocus,
|
|
109
|
+
readonly,
|
|
110
|
+
required,
|
|
111
|
+
errorSchema,
|
|
112
|
+
hideError = false,
|
|
113
|
+
} = props;
|
|
114
|
+
const { widgets, schemaUtils, globalUiOptions } = registry;
|
|
115
|
+
const [enumOptions, setEnumOptions] = useState(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData)!);
|
|
116
|
+
const id = get(idSchema, ID_KEY);
|
|
117
|
+
const discriminator = getDiscriminatorFieldFromSchema(schema);
|
|
118
|
+
const FieldErrorTemplate = getTemplate<'FieldErrorTemplate', T, S, F>('FieldErrorTemplate', registry, options);
|
|
119
|
+
const FieldTemplate = getTemplate<'FieldTemplate', T, S, F>('FieldTemplate', registry, options);
|
|
120
|
+
const schemaHash = hashObject(schema);
|
|
121
|
+
const optionsHash = hashObject(options);
|
|
122
|
+
const uiSchemaHash = uiSchema ? hashObject(uiSchema) : '';
|
|
123
|
+
const formDataHash = formData ? hashObject(formData) : '';
|
|
124
|
+
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
setEnumOptions(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData));
|
|
127
|
+
// We are using hashes in place of the dependencies
|
|
128
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
129
|
+
}, [schemaHash, optionsHash, schemaUtils, uiSchemaHash, formDataHash]);
|
|
130
|
+
const {
|
|
131
|
+
widget = discriminator ? 'radio' : 'select',
|
|
132
|
+
title = '',
|
|
133
|
+
placeholder = '',
|
|
134
|
+
optionsSchemaSelector: selectorField = discriminator,
|
|
135
|
+
hideError: uiSchemaHideError,
|
|
136
|
+
...uiOptions
|
|
137
|
+
} = getUiOptions<T, S, F>(uiSchema);
|
|
138
|
+
if (!selectorField) {
|
|
139
|
+
throw new Error('No selector field provided for the LayoutMultiSchemaField');
|
|
140
|
+
}
|
|
141
|
+
const selectedOption = get(formData, selectorField);
|
|
142
|
+
let optionSchema: S = get(enumOptions[0]?.schema, [PROPERTIES_KEY, selectorField], {}) as S;
|
|
143
|
+
const option = getSelectedOption<S>(enumOptions, selectorField, selectedOption);
|
|
144
|
+
// If the subschema doesn't declare a type, infer the type from the parent schema
|
|
145
|
+
optionSchema = optionSchema?.type ? optionSchema : ({ ...optionSchema, type: option?.type || baseType } as S);
|
|
146
|
+
const Widget = getWidget<T, S, F>(optionSchema!, widget, widgets);
|
|
147
|
+
|
|
148
|
+
// The following code was copied from `@rjsf`'s `SchemaField`
|
|
149
|
+
// Set hideError to the value provided in the uiSchema, otherwise stick with the prop to propagate to children
|
|
150
|
+
const hideFieldError = uiSchemaHideError === undefined ? hideError : Boolean(uiSchemaHideError);
|
|
151
|
+
|
|
152
|
+
const rawErrors = get(errorSchema, [ERRORS_KEY], []) as string[];
|
|
153
|
+
const fieldErrorSchema = omit(errorSchema, [ERRORS_KEY]);
|
|
154
|
+
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
|
|
155
|
+
|
|
156
|
+
/** Callback function that updates the selected option and adjusts the form data based on the structure of the new
|
|
157
|
+
* option, calling the `onChange` callback with the adjusted formData.
|
|
158
|
+
*
|
|
159
|
+
* @param opt - If the option is undefined, we are going to clear the selection otherwise we
|
|
160
|
+
* will use it as the index of the new option to select
|
|
161
|
+
*/
|
|
162
|
+
const onOptionChange = (opt?: unknown) => {
|
|
163
|
+
const newOption = getSelectedOption<S>(enumOptions, selectorField, opt);
|
|
164
|
+
const oldOption = getSelectedOption<S>(enumOptions, selectorField, selectedOption);
|
|
165
|
+
|
|
166
|
+
let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData);
|
|
167
|
+
if (newFormData && newOption) {
|
|
168
|
+
// Call getDefaultFormState to make sure defaults are populated on change.
|
|
169
|
+
newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, 'excludeObjectChildren') as T;
|
|
170
|
+
}
|
|
171
|
+
if (newFormData) {
|
|
172
|
+
set(newFormData, selectorField, opt);
|
|
173
|
+
}
|
|
174
|
+
onChange(newFormData, undefined, id);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// filtering the options based on the type of widget because `selectField` does not recognize the `convertOther` prop
|
|
178
|
+
const widgetOptions = { enumOptions, ...uiOptions };
|
|
179
|
+
const errors =
|
|
180
|
+
!hideFieldError && rawErrors.length > 0 ? (
|
|
181
|
+
<FieldErrorTemplate idSchema={idSchema} schema={schema} errors={rawErrors} registry={registry} />
|
|
182
|
+
) : undefined;
|
|
183
|
+
const ignored = (value: string) => noop;
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<FieldTemplate
|
|
187
|
+
id={id}
|
|
188
|
+
schema={schema}
|
|
189
|
+
label={(title || schema.title) ?? ''}
|
|
190
|
+
disabled={disabled || (Array.isArray(enumOptions) && isEmpty(enumOptions))}
|
|
191
|
+
uiSchema={uiSchema}
|
|
192
|
+
formContext={formContext}
|
|
193
|
+
required={required}
|
|
194
|
+
readonly={!!readonly}
|
|
195
|
+
registry={registry}
|
|
196
|
+
displayLabel={displayLabel}
|
|
197
|
+
errors={errors}
|
|
198
|
+
onChange={onChange}
|
|
199
|
+
onDropPropertyClick={ignored}
|
|
200
|
+
onKeyChange={ignored}
|
|
201
|
+
>
|
|
202
|
+
<Widget
|
|
203
|
+
id={id}
|
|
204
|
+
name={name}
|
|
205
|
+
schema={schema}
|
|
206
|
+
label={(title || schema.title) ?? ''}
|
|
207
|
+
disabled={disabled || (Array.isArray(enumOptions) && isEmpty(enumOptions))}
|
|
208
|
+
uiSchema={uiSchema}
|
|
209
|
+
formContext={formContext}
|
|
210
|
+
autofocus={autofocus}
|
|
211
|
+
readonly={readonly}
|
|
212
|
+
required={required}
|
|
213
|
+
registry={registry}
|
|
214
|
+
multiple={false}
|
|
215
|
+
rawErrors={rawErrors}
|
|
216
|
+
hideError={hideFieldError}
|
|
217
|
+
hideLabel={!displayLabel}
|
|
218
|
+
errorSchema={fieldErrorSchema}
|
|
219
|
+
placeholder={placeholder}
|
|
220
|
+
onChange={onOptionChange}
|
|
221
|
+
onBlur={onBlur}
|
|
222
|
+
onFocus={onFocus}
|
|
223
|
+
value={selectedOption}
|
|
224
|
+
options={widgetOptions}
|
|
225
|
+
/>
|
|
226
|
+
</FieldTemplate>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -7,7 +7,7 @@ import { FieldProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf
|
|
|
7
7
|
* @param props - The `FieldProps` for this template
|
|
8
8
|
*/
|
|
9
9
|
function NullField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
10
|
-
props: FieldProps<T, S, F
|
|
10
|
+
props: FieldProps<T, S, F>,
|
|
11
11
|
) {
|
|
12
12
|
const { formData, onChange } = props;
|
|
13
13
|
useEffect(() => {
|
|
@@ -31,7 +31,7 @@ const trailingCharMatcher = /[0.]0*$/;
|
|
|
31
31
|
* value is passed to the input instead of the formData value
|
|
32
32
|
*/
|
|
33
33
|
function NumberField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
34
|
-
props: FieldProps<T, S, F
|
|
34
|
+
props: FieldProps<T, S, F>,
|
|
35
35
|
) {
|
|
36
36
|
const { registry, onChange, formData, value: initialValue } = props;
|
|
37
37
|
const [lastValue, setLastValue] = useState(initialValue);
|
|
@@ -64,7 +64,7 @@ function NumberField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
64
64
|
|
|
65
65
|
onChange(processed as unknown as T, errorSchema, id);
|
|
66
66
|
},
|
|
67
|
-
[onChange]
|
|
67
|
+
[onChange],
|
|
68
68
|
);
|
|
69
69
|
|
|
70
70
|
if (typeof lastValue === 'string' && typeof value === 'number') {
|
|
@@ -86,7 +86,7 @@ class ObjectField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
86
86
|
...errorSchema,
|
|
87
87
|
[name]: newErrorSchema,
|
|
88
88
|
},
|
|
89
|
-
id
|
|
89
|
+
id,
|
|
90
90
|
);
|
|
91
91
|
};
|
|
92
92
|
};
|
|
@@ -158,7 +158,7 @@ class ObjectField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
158
158
|
errorSchema && {
|
|
159
159
|
...errorSchema,
|
|
160
160
|
[value]: newErrorSchema,
|
|
161
|
-
}
|
|
161
|
+
},
|
|
162
162
|
);
|
|
163
163
|
};
|
|
164
164
|
};
|
|
@@ -195,36 +195,40 @@ class ObjectField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
195
195
|
* @param schema - The schema element to which the new property is being added
|
|
196
196
|
*/
|
|
197
197
|
handleAddClick = (schema: S) => () => {
|
|
198
|
-
if (!schema.additionalProperties) {
|
|
198
|
+
if (!(schema.additionalProperties || schema.patternProperties)) {
|
|
199
199
|
return;
|
|
200
200
|
}
|
|
201
201
|
const { formData, onChange, registry } = this.props;
|
|
202
202
|
const newFormData = { ...formData } as T;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
type =
|
|
209
|
-
constValue =
|
|
210
|
-
defaultValue =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
203
|
+
const newKey = this.getAvailableKey('newKey', newFormData);
|
|
204
|
+
if (schema.patternProperties) {
|
|
205
|
+
// Cast this to make the `set` work properly
|
|
206
|
+
set(newFormData as GenericObjectType, newKey, null);
|
|
207
|
+
} else {
|
|
208
|
+
let type: RJSFSchema['type'] = undefined;
|
|
209
|
+
let constValue: RJSFSchema['const'] = undefined;
|
|
210
|
+
let defaultValue: RJSFSchema['default'] = undefined;
|
|
211
|
+
if (isObject(schema.additionalProperties)) {
|
|
212
|
+
type = schema.additionalProperties.type;
|
|
213
|
+
constValue = schema.additionalProperties.const;
|
|
214
|
+
defaultValue = schema.additionalProperties.default;
|
|
215
|
+
let apSchema = schema.additionalProperties;
|
|
216
|
+
if (REF_KEY in apSchema) {
|
|
217
|
+
const { schemaUtils } = registry;
|
|
218
|
+
apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[REF_KEY] } as S, formData);
|
|
219
|
+
type = apSchema.type;
|
|
220
|
+
constValue = apSchema.const;
|
|
221
|
+
defaultValue = apSchema.default;
|
|
222
|
+
}
|
|
223
|
+
if (!type && (ANY_OF_KEY in apSchema || ONE_OF_KEY in apSchema)) {
|
|
224
|
+
type = 'object';
|
|
225
|
+
}
|
|
221
226
|
}
|
|
222
|
-
}
|
|
223
227
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
const newValue = constValue ?? defaultValue ?? this.getDefaultValue(type);
|
|
229
|
+
// Cast this to make the `set` work properly
|
|
230
|
+
set(newFormData as GenericObjectType, newKey, newValue);
|
|
231
|
+
}
|
|
228
232
|
|
|
229
233
|
onChange(newFormData);
|
|
230
234
|
};
|
|
@@ -266,7 +270,7 @@ class ObjectField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
266
270
|
} catch (err) {
|
|
267
271
|
return (
|
|
268
272
|
<div>
|
|
269
|
-
<p className='config-error' style={{ color: 'red' }}>
|
|
273
|
+
<p className='rjsf-config-error' style={{ color: 'red' }}>
|
|
270
274
|
<Markdown options={{ disableParsingRawHTML: true }}>
|
|
271
275
|
{translateString(TranslatableString.InvalidObjectField, [name || 'root', (err as Error).message])}
|
|
272
276
|
</Markdown>
|
|
@@ -294,7 +298,7 @@ class ObjectField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
|
|
|
294
298
|
key={name}
|
|
295
299
|
name={name}
|
|
296
300
|
required={this.isRequired(name)}
|
|
297
|
-
schema={get(schema, [PROPERTIES_KEY, name], {})}
|
|
301
|
+
schema={get(schema, [PROPERTIES_KEY, name], {}) as S}
|
|
298
302
|
uiSchema={fieldUiSchema}
|
|
299
303
|
errorSchema={get(errorSchema, name)}
|
|
300
304
|
idSchema={fieldIdSchema}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, Component } from 'react';
|
|
1
|
+
import { useCallback, Component, ComponentType } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
ADDITIONAL_PROPERTY_FLAG,
|
|
4
4
|
deepEquals,
|
|
@@ -49,15 +49,15 @@ function getFieldComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
49
49
|
schema: S,
|
|
50
50
|
uiOptions: UIOptionsType<T, S, F>,
|
|
51
51
|
idSchema: IdSchema<T>,
|
|
52
|
-
registry: Registry<T, S, F
|
|
53
|
-
) {
|
|
52
|
+
registry: Registry<T, S, F>,
|
|
53
|
+
): ComponentType<FieldProps<T, S, F>> {
|
|
54
54
|
const field = uiOptions.field;
|
|
55
55
|
const { fields, translateString } = registry;
|
|
56
56
|
if (typeof field === 'function') {
|
|
57
57
|
return field;
|
|
58
58
|
}
|
|
59
59
|
if (typeof field === 'string' && field in fields) {
|
|
60
|
-
return fields[field]
|
|
60
|
+
return fields[field] as ComponentType<FieldProps<T, S, F>>;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const schemaType = getSchemaType(schema);
|
|
@@ -82,7 +82,7 @@ function getFieldComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
82
82
|
const UnsupportedFieldTemplate = getTemplate<'UnsupportedFieldTemplate', T, S, F>(
|
|
83
83
|
'UnsupportedFieldTemplate',
|
|
84
84
|
registry,
|
|
85
|
-
uiOptions
|
|
85
|
+
uiOptions,
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
return (
|
|
@@ -103,7 +103,7 @@ function getFieldComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
103
103
|
* @param props - The `FieldProps` for this component
|
|
104
104
|
*/
|
|
105
105
|
function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
106
|
-
props: FieldProps<T, S, F
|
|
106
|
+
props: FieldProps<T, S, F>,
|
|
107
107
|
) {
|
|
108
108
|
const {
|
|
109
109
|
schema: _schema,
|
|
@@ -127,7 +127,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
127
127
|
const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
|
|
128
128
|
'DescriptionFieldTemplate',
|
|
129
129
|
registry,
|
|
130
|
-
uiOptions
|
|
130
|
+
uiOptions,
|
|
131
131
|
);
|
|
132
132
|
const FieldHelpTemplate = getTemplate<'FieldHelpTemplate', T, S, F>('FieldHelpTemplate', registry, uiOptions);
|
|
133
133
|
const FieldErrorTemplate = getTemplate<'FieldErrorTemplate', T, S, F>('FieldErrorTemplate', registry, uiOptions);
|
|
@@ -135,7 +135,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
135
135
|
const fieldId = _idSchema[ID_KEY];
|
|
136
136
|
const idSchema = mergeObjects(
|
|
137
137
|
schemaUtils.toIdSchema(schema, fieldId, formData, idPrefix, idSeparator),
|
|
138
|
-
_idSchema
|
|
138
|
+
_idSchema,
|
|
139
139
|
) as IdSchema<T>;
|
|
140
140
|
|
|
141
141
|
/** Intermediary `onChange` handler for field components that will inject the `id` of the current field into the
|
|
@@ -146,7 +146,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
146
146
|
const theId = id || fieldId;
|
|
147
147
|
return onChange(formData, newErrorSchema, theId);
|
|
148
148
|
},
|
|
149
|
-
[fieldId, onChange]
|
|
149
|
+
[fieldId, onChange],
|
|
150
150
|
);
|
|
151
151
|
|
|
152
152
|
const FieldComponent = getFieldComponent<T, S, F>(schema, uiOptions, idSchema, registry);
|
|
@@ -180,7 +180,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
180
180
|
readonly={readonly}
|
|
181
181
|
hideError={hideError}
|
|
182
182
|
autofocus={autofocus}
|
|
183
|
-
errorSchema={fieldErrorSchema}
|
|
183
|
+
errorSchema={fieldErrorSchema as ErrorSchema}
|
|
184
184
|
formContext={formContext}
|
|
185
185
|
rawErrors={__errors}
|
|
186
186
|
/>
|
|
@@ -209,17 +209,9 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
209
209
|
const help = uiOptions.help;
|
|
210
210
|
const hidden = uiOptions.widget === 'hidden';
|
|
211
211
|
|
|
212
|
-
const classNames = ['
|
|
212
|
+
const classNames = ['rjsf-field', `rjsf-field-${getSchemaType(schema)}`];
|
|
213
213
|
if (!hideError && __errors && __errors.length > 0) {
|
|
214
|
-
classNames.push('field-error
|
|
215
|
-
}
|
|
216
|
-
if (uiSchema?.classNames) {
|
|
217
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
218
|
-
console.warn(
|
|
219
|
-
"'uiSchema.classNames' is deprecated and may be removed in a major release; Use 'ui:classNames' instead."
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
classNames.push(uiSchema.classNames);
|
|
214
|
+
classNames.push('rjsf-field-error');
|
|
223
215
|
}
|
|
224
216
|
if (uiOptions.classNames) {
|
|
225
217
|
classNames.push(uiOptions.classNames);
|
|
@@ -314,7 +306,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
314
306
|
onChange={props.onChange}
|
|
315
307
|
onFocus={props.onFocus}
|
|
316
308
|
options={schema.anyOf.map((_schema) =>
|
|
317
|
-
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData)
|
|
309
|
+
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
318
310
|
)}
|
|
319
311
|
registry={registry}
|
|
320
312
|
required={required}
|
|
@@ -338,7 +330,7 @@ function SchemaFieldRender<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
338
330
|
onChange={props.onChange}
|
|
339
331
|
onFocus={props.onFocus}
|
|
340
332
|
options={schema.oneOf.map((_schema) =>
|
|
341
|
-
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData)
|
|
333
|
+
schemaUtils.retrieveSchema(isObject(_schema) ? (_schema as S) : ({} as S), formData),
|
|
342
334
|
)}
|
|
343
335
|
registry={registry}
|
|
344
336
|
required={required}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
* @param props - The `FieldProps` for this template
|
|
15
15
|
*/
|
|
16
16
|
function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
17
|
-
props: FieldProps<T, S, F
|
|
17
|
+
props: FieldProps<T, S, F>,
|
|
18
18
|
) {
|
|
19
19
|
const {
|
|
20
20
|
schema,
|
|
@@ -35,7 +35,7 @@ function StringField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
|
|
|
35
35
|
} = props;
|
|
36
36
|
const { title, format } = schema;
|
|
37
37
|
const { widgets, formContext, schemaUtils, globalUiOptions } = registry;
|
|
38
|
-
const enumOptions = schemaUtils.isSelect(schema) ? optionsList<
|
|
38
|
+
const enumOptions = schemaUtils.isSelect(schema) ? optionsList<T, S, F>(schema, uiSchema) : undefined;
|
|
39
39
|
let defaultWidget = enumOptions ? 'select' : 'text';
|
|
40
40
|
if (format && hasWidget<T, S, F>(schema, format, widgets)) {
|
|
41
41
|
defaultWidget = format;
|
|
@@ -2,6 +2,9 @@ import { Field, FormContextType, RegistryFieldsType, RJSFSchema, StrictRJSFSchem
|
|
|
2
2
|
|
|
3
3
|
import ArrayField from './ArrayField';
|
|
4
4
|
import BooleanField from './BooleanField';
|
|
5
|
+
import LayoutGridField from './LayoutGridField';
|
|
6
|
+
import LayoutHeaderField from './LayoutHeaderField';
|
|
7
|
+
import LayoutMultiSchemaField from './LayoutMultiSchemaField';
|
|
5
8
|
import MultiSchemaField from './MultiSchemaField';
|
|
6
9
|
import NumberField from './NumberField';
|
|
7
10
|
import ObjectField from './ObjectField';
|
|
@@ -12,13 +15,16 @@ import NullField from './NullField';
|
|
|
12
15
|
function fields<
|
|
13
16
|
T = any,
|
|
14
17
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
15
|
-
F extends FormContextType = any
|
|
18
|
+
F extends FormContextType = any,
|
|
16
19
|
>(): RegistryFieldsType<T, S, F> {
|
|
17
20
|
return {
|
|
18
21
|
AnyOfField: MultiSchemaField,
|
|
19
22
|
ArrayField: ArrayField as unknown as Field<T, S, F>,
|
|
20
23
|
// ArrayField falls back to SchemaField if ArraySchemaField is not defined, which it isn't by default
|
|
21
24
|
BooleanField,
|
|
25
|
+
LayoutGridField,
|
|
26
|
+
LayoutHeaderField,
|
|
27
|
+
LayoutMultiSchemaField,
|
|
22
28
|
NumberField,
|
|
23
29
|
ObjectField,
|
|
24
30
|
OneOfField: MultiSchemaField,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
export default function ArrayFieldDescriptionTemplate<
|
|
17
17
|
T = any,
|
|
18
18
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
19
|
-
F extends FormContextType = any
|
|
19
|
+
F extends FormContextType = any,
|
|
20
20
|
>(props: ArrayFieldDescriptionProps<T, S, F>) {
|
|
21
21
|
const { idSchema, description, registry, schema, uiSchema } = props;
|
|
22
22
|
const options = getUiOptions<T, S, F>(uiSchema, registry.globalUiOptions);
|
|
@@ -27,7 +27,7 @@ export default function ArrayFieldDescriptionTemplate<
|
|
|
27
27
|
const DescriptionFieldTemplate = getTemplate<'DescriptionFieldTemplate', T, S, F>(
|
|
28
28
|
'DescriptionFieldTemplate',
|
|
29
29
|
registry,
|
|
30
|
-
options
|
|
30
|
+
options,
|
|
31
31
|
);
|
|
32
32
|
return (
|
|
33
33
|
<DescriptionFieldTemplate
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ArrayFieldItemButtonsTemplateType,
|
|
4
|
+
buttonId,
|
|
5
|
+
FormContextType,
|
|
6
|
+
RJSFSchema,
|
|
7
|
+
StrictRJSFSchema,
|
|
8
|
+
} from '@rjsf/utils';
|
|
9
|
+
|
|
10
|
+
/** The `ArrayFieldTemplateItemButtons` component is the template used to render the buttons associate3d with items of
|
|
11
|
+
* an array.
|
|
12
|
+
*
|
|
13
|
+
* @param props - The `ArrayFieldItemButtonsTemplateType` props for the component
|
|
14
|
+
*/
|
|
15
|
+
export default function ArrayFieldItemButtonsTemplate<
|
|
16
|
+
T = any,
|
|
17
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
18
|
+
F extends FormContextType = any,
|
|
19
|
+
>(props: ArrayFieldItemButtonsTemplateType<T, S, F>) {
|
|
20
|
+
const {
|
|
21
|
+
disabled,
|
|
22
|
+
hasCopy,
|
|
23
|
+
hasMoveDown,
|
|
24
|
+
hasMoveUp,
|
|
25
|
+
hasRemove,
|
|
26
|
+
idSchema,
|
|
27
|
+
index,
|
|
28
|
+
onCopyIndexClick,
|
|
29
|
+
onDropIndexClick,
|
|
30
|
+
onReorderClick,
|
|
31
|
+
readonly,
|
|
32
|
+
registry,
|
|
33
|
+
uiSchema,
|
|
34
|
+
} = props;
|
|
35
|
+
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
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
{(hasMoveUp || hasMoveDown) && (
|
|
44
|
+
<MoveUpButton
|
|
45
|
+
id={buttonId<T>(idSchema, 'moveUp')}
|
|
46
|
+
className='rjsf-array-item-move-up'
|
|
47
|
+
disabled={disabled || readonly || !hasMoveUp}
|
|
48
|
+
onClick={onArrowUpClick}
|
|
49
|
+
uiSchema={uiSchema}
|
|
50
|
+
registry={registry}
|
|
51
|
+
/>
|
|
52
|
+
)}
|
|
53
|
+
{(hasMoveUp || hasMoveDown) && (
|
|
54
|
+
<MoveDownButton
|
|
55
|
+
id={buttonId<T>(idSchema, 'moveDown')}
|
|
56
|
+
className='rjsf-array-item-move-down'
|
|
57
|
+
disabled={disabled || readonly || !hasMoveDown}
|
|
58
|
+
onClick={onArrowDownClick}
|
|
59
|
+
uiSchema={uiSchema}
|
|
60
|
+
registry={registry}
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
{hasCopy && (
|
|
64
|
+
<CopyButton
|
|
65
|
+
id={buttonId<T>(idSchema, 'copy')}
|
|
66
|
+
className='rjsf-array-item-copy'
|
|
67
|
+
disabled={disabled || readonly}
|
|
68
|
+
onClick={onCopyClick}
|
|
69
|
+
uiSchema={uiSchema}
|
|
70
|
+
registry={registry}
|
|
71
|
+
/>
|
|
72
|
+
)}
|
|
73
|
+
{hasRemove && (
|
|
74
|
+
<RemoveButton
|
|
75
|
+
id={buttonId<T>(idSchema, 'remove')}
|
|
76
|
+
className='rjsf-array-item-remove'
|
|
77
|
+
disabled={disabled || readonly}
|
|
78
|
+
onClick={onRemoveClick}
|
|
79
|
+
uiSchema={uiSchema}
|
|
80
|
+
registry={registry}
|
|
81
|
+
/>
|
|
82
|
+
)}
|
|
83
|
+
</>
|
|
84
|
+
);
|
|
85
|
+
}
|