@rjsf/core 6.6.1 → 6.7.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/LICENSE.md +201 -0
- package/dist/core.umd.js +694 -584
- package/dist/index.cjs +1191 -1071
- package/dist/index.cjs.map +4 -4
- package/dist/index.esm.js +1030 -984
- package/dist/index.esm.js.map +4 -4
- package/lib/components/Form.d.ts +16 -13
- package/lib/components/Form.d.ts.map +1 -1
- package/lib/components/Form.js +126 -76
- package/lib/components/RichDescription.d.ts +3 -3
- package/lib/components/RichDescription.d.ts.map +1 -1
- package/lib/components/RichDescription.js +1 -1
- package/lib/components/RichHelp.d.ts +3 -3
- package/lib/components/RichHelp.d.ts.map +1 -1
- package/lib/components/RichHelp.js +1 -1
- package/lib/components/SchemaExamples.d.ts +2 -2
- package/lib/components/SchemaExamples.d.ts.map +1 -1
- package/lib/components/SchemaExamples.js +1 -3
- package/lib/components/fields/ArrayField.d.ts +2 -2
- package/lib/components/fields/ArrayField.d.ts.map +1 -1
- package/lib/components/fields/ArrayField.js +87 -88
- package/lib/components/fields/BooleanField.d.ts +2 -2
- package/lib/components/fields/BooleanField.d.ts.map +1 -1
- package/lib/components/fields/BooleanField.js +2 -5
- package/lib/components/fields/CyclicSchemaField.d.ts +8 -0
- package/lib/components/fields/CyclicSchemaField.d.ts.map +1 -0
- package/lib/components/fields/CyclicSchemaField.js +21 -0
- package/lib/components/fields/FallbackField.d.ts +2 -2
- package/lib/components/fields/FallbackField.d.ts.map +1 -1
- package/lib/components/fields/FallbackField.js +2 -2
- package/lib/components/fields/LayoutGridField.d.ts +8 -10
- package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
- package/lib/components/fields/LayoutGridField.js +5 -4
- package/lib/components/fields/LayoutHeaderField.d.ts +2 -2
- package/lib/components/fields/LayoutHeaderField.d.ts.map +1 -1
- package/lib/components/fields/LayoutHeaderField.js +1 -1
- package/lib/components/fields/LayoutMultiSchemaField.d.ts +2 -2
- package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/LayoutMultiSchemaField.js +4 -1
- package/lib/components/fields/MultiSchemaField.d.ts +2 -41
- package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/MultiSchemaField.js +116 -122
- package/lib/components/fields/NullField.d.ts +1 -1
- package/lib/components/fields/NullField.d.ts.map +1 -1
- package/lib/components/fields/NumberField.d.ts +2 -2
- package/lib/components/fields/NumberField.d.ts.map +1 -1
- package/lib/components/fields/NumberField.js +7 -9
- package/lib/components/fields/ObjectField.d.ts +2 -2
- package/lib/components/fields/ObjectField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.js +28 -26
- package/lib/components/fields/OptionalDataControlsField.d.ts +2 -2
- package/lib/components/fields/OptionalDataControlsField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.d.ts +14 -8
- package/lib/components/fields/SchemaField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.js +43 -30
- package/lib/components/fields/StringField.d.ts +2 -2
- package/lib/components/fields/StringField.d.ts.map +1 -1
- package/lib/components/fields/StringField.js +2 -5
- package/lib/components/fields/index.d.ts +1 -1
- package/lib/components/fields/index.d.ts.map +1 -1
- package/lib/components/fields/index.js +2 -0
- package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +2 -2
- package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldDescriptionTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts +2 -2
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldItemButtonsTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldItemTemplate.d.ts +2 -2
- 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 +2 -2
- package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +2 -2
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.js +1 -1
- package/lib/components/templates/BaseInputTemplate.d.ts +2 -2
- package/lib/components/templates/BaseInputTemplate.d.ts.map +1 -1
- package/lib/components/templates/BaseInputTemplate.js +7 -6
- package/lib/components/templates/ButtonTemplates/AddButton.d.ts +2 -2
- package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/IconButton.d.ts +14 -7
- package/lib/components/templates/ButtonTemplates/IconButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/IconButton.js +14 -6
- package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts +2 -2
- package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts.map +1 -1
- package/lib/components/templates/ButtonTemplates/index.d.ts +1 -1
- package/lib/components/templates/ButtonTemplates/index.d.ts.map +1 -1
- package/lib/components/templates/CyclicSchemaExpandTemplate.d.ts +7 -0
- package/lib/components/templates/CyclicSchemaExpandTemplate.d.ts.map +1 -0
- package/lib/components/templates/CyclicSchemaExpandTemplate.js +12 -0
- package/lib/components/templates/DescriptionField.d.ts +2 -2
- package/lib/components/templates/DescriptionField.d.ts.map +1 -1
- package/lib/components/templates/ErrorList.d.ts +2 -2
- package/lib/components/templates/ErrorList.d.ts.map +1 -1
- package/lib/components/templates/ErrorList.js +2 -4
- package/lib/components/templates/FallbackFieldTemplate.d.ts +2 -2
- package/lib/components/templates/FallbackFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldErrorTemplate.d.ts +2 -2
- package/lib/components/templates/FieldErrorTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldErrorTemplate.js +1 -3
- package/lib/components/templates/FieldHelpTemplate.d.ts +2 -2
- package/lib/components/templates/FieldHelpTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts +2 -2
- package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldTemplate/FieldTemplate.js +1 -1
- package/lib/components/templates/FieldTemplate/Label.d.ts +3 -3
- package/lib/components/templates/FieldTemplate/Label.d.ts.map +1 -1
- package/lib/components/templates/GridTemplate.d.ts +2 -2
- package/lib/components/templates/GridTemplate.d.ts.map +1 -1
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +2 -2
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ObjectFieldTemplate.d.ts +2 -2
- package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ObjectFieldTemplate.js +1 -1
- package/lib/components/templates/OptionalDataControlsTemplate.d.ts +2 -2
- package/lib/components/templates/OptionalDataControlsTemplate.d.ts.map +1 -1
- package/lib/components/templates/OptionalDataControlsTemplate.js +1 -1
- package/lib/components/templates/TitleField.d.ts +2 -2
- package/lib/components/templates/TitleField.d.ts.map +1 -1
- package/lib/components/templates/UnsupportedField.d.ts +2 -2
- package/lib/components/templates/UnsupportedField.d.ts.map +1 -1
- package/lib/components/templates/UnsupportedField.js +2 -2
- package/lib/components/templates/WrapIfAdditionalTemplate.d.ts +2 -2
- package/lib/components/templates/WrapIfAdditionalTemplate.d.ts.map +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.js +1 -1
- package/lib/components/templates/index.d.ts +1 -1
- package/lib/components/templates/index.d.ts.map +1 -1
- package/lib/components/templates/index.js +2 -0
- package/lib/components/widgets/AltDateTimeWidget.d.ts +2 -2
- package/lib/components/widgets/AltDateTimeWidget.d.ts.map +1 -1
- package/lib/components/widgets/AltDateWidget.d.ts +2 -2
- package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
- package/lib/components/widgets/AltDateWidget.js +2 -2
- package/lib/components/widgets/CheckboxWidget.d.ts +2 -2
- package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.d.ts +2 -2
- package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.js +4 -4
- package/lib/components/widgets/ColorWidget.d.ts +2 -2
- package/lib/components/widgets/ColorWidget.d.ts.map +1 -1
- package/lib/components/widgets/DateTimeWidget.d.ts +2 -2
- package/lib/components/widgets/DateTimeWidget.d.ts.map +1 -1
- package/lib/components/widgets/DateTimeWidget.js +2 -2
- package/lib/components/widgets/DateWidget.d.ts +2 -2
- package/lib/components/widgets/DateWidget.d.ts.map +1 -1
- package/lib/components/widgets/EmailWidget.d.ts +2 -2
- package/lib/components/widgets/EmailWidget.d.ts.map +1 -1
- package/lib/components/widgets/FileWidget.d.ts +2 -2
- package/lib/components/widgets/FileWidget.d.ts.map +1 -1
- package/lib/components/widgets/FileWidget.js +6 -4
- package/lib/components/widgets/HiddenWidget.d.ts +2 -2
- package/lib/components/widgets/HiddenWidget.d.ts.map +1 -1
- package/lib/components/widgets/PasswordWidget.d.ts +2 -2
- package/lib/components/widgets/PasswordWidget.d.ts.map +1 -1
- package/lib/components/widgets/RadioWidget.d.ts +2 -2
- package/lib/components/widgets/RadioWidget.d.ts.map +1 -1
- package/lib/components/widgets/RadioWidget.js +4 -4
- package/lib/components/widgets/RangeWidget.d.ts +2 -2
- package/lib/components/widgets/RangeWidget.d.ts.map +1 -1
- package/lib/components/widgets/RatingWidget.d.ts +2 -2
- package/lib/components/widgets/RatingWidget.d.ts.map +1 -1
- package/lib/components/widgets/RatingWidget.js +15 -15
- package/lib/components/widgets/SelectWidget.d.ts +2 -2
- package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
- package/lib/components/widgets/SelectWidget.js +9 -8
- package/lib/components/widgets/TextWidget.d.ts +2 -2
- package/lib/components/widgets/TextWidget.d.ts.map +1 -1
- package/lib/components/widgets/TextareaWidget.d.ts +2 -2
- package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
- package/lib/components/widgets/TextareaWidget.js +5 -5
- package/lib/components/widgets/TimeWidget.d.ts +2 -2
- package/lib/components/widgets/TimeWidget.d.ts.map +1 -1
- package/lib/components/widgets/URLWidget.d.ts +2 -2
- package/lib/components/widgets/URLWidget.d.ts.map +1 -1
- package/lib/components/widgets/UpDownWidget.d.ts +2 -2
- package/lib/components/widgets/UpDownWidget.d.ts.map +1 -1
- package/lib/components/widgets/index.d.ts +1 -1
- package/lib/components/widgets/index.d.ts.map +1 -1
- package/lib/getDefaultRegistry.d.ts +1 -1
- package/lib/getDefaultRegistry.d.ts.map +1 -1
- package/lib/getDefaultRegistry.js +1 -1
- package/lib/getTestRegistry.d.ts +1 -1
- package/lib/getTestRegistry.d.ts.map +1 -1
- package/lib/getTestRegistry.js +1 -1
- package/lib/index.d.ts +10 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/withTheme.d.ts +3 -3
- package/lib/withTheme.d.ts.map +1 -1
- package/lib/withTheme.js +6 -6
- package/package.json +28 -28
- package/src/components/Form.tsx +197 -111
- package/src/components/RichDescription.tsx +3 -10
- package/src/components/RichHelp.tsx +3 -10
- package/src/components/SchemaExamples.tsx +6 -4
- package/src/components/fields/ArrayField.tsx +122 -108
- package/src/components/fields/BooleanField.tsx +4 -9
- package/src/components/fields/CyclicSchemaField.tsx +40 -0
- package/src/components/fields/FallbackField.tsx +4 -8
- package/src/components/fields/LayoutGridField.tsx +21 -19
- package/src/components/fields/LayoutHeaderField.tsx +2 -10
- package/src/components/fields/LayoutMultiSchemaField.tsx +15 -10
- package/src/components/fields/MultiSchemaField.tsx +202 -218
- package/src/components/fields/NullField.tsx +1 -1
- package/src/components/fields/NumberField.tsx +8 -10
- package/src/components/fields/ObjectField.tsx +52 -40
- package/src/components/fields/OptionalDataControlsField.tsx +6 -4
- package/src/components/fields/SchemaField.tsx +66 -51
- package/src/components/fields/StringField.tsx +4 -15
- package/src/components/fields/index.ts +3 -1
- package/src/components/templates/ArrayFieldDescriptionTemplate.tsx +2 -9
- package/src/components/templates/ArrayFieldItemButtonsTemplate.tsx +2 -7
- package/src/components/templates/ArrayFieldItemTemplate.tsx +3 -9
- package/src/components/templates/ArrayFieldTemplate.tsx +2 -9
- package/src/components/templates/ArrayFieldTitleTemplate.tsx +2 -10
- package/src/components/templates/BaseInputTemplate.tsx +16 -23
- package/src/components/templates/ButtonTemplates/AddButton.tsx +2 -1
- package/src/components/templates/ButtonTemplates/IconButton.tsx +16 -7
- package/src/components/templates/ButtonTemplates/SubmitButton.tsx +2 -1
- package/src/components/templates/ButtonTemplates/index.ts +1 -1
- package/src/components/templates/CyclicSchemaExpandTemplate.tsx +31 -0
- package/src/components/templates/DescriptionField.tsx +1 -1
- package/src/components/templates/ErrorList.tsx +8 -15
- package/src/components/templates/FallbackFieldTemplate.tsx +2 -1
- package/src/components/templates/FieldErrorTemplate.tsx +8 -8
- package/src/components/templates/FieldHelpTemplate.tsx +2 -1
- package/src/components/templates/FieldTemplate/FieldTemplate.tsx +2 -8
- package/src/components/templates/FieldTemplate/Label.tsx +2 -2
- package/src/components/templates/GridTemplate.tsx +1 -1
- package/src/components/templates/MultiSchemaFieldTemplate.tsx +1 -1
- package/src/components/templates/ObjectFieldTemplate.tsx +2 -7
- package/src/components/templates/OptionalDataControlsTemplate.tsx +3 -2
- package/src/components/templates/TitleField.tsx +1 -1
- package/src/components/templates/UnsupportedField.tsx +4 -3
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +2 -9
- package/src/components/templates/index.ts +3 -1
- package/src/components/widgets/AltDateTimeWidget.tsx +1 -1
- package/src/components/widgets/AltDateWidget.tsx +7 -13
- package/src/components/widgets/CheckboxWidget.tsx +3 -5
- package/src/components/widgets/CheckboxesWidget.tsx +8 -10
- package/src/components/widgets/ColorWidget.tsx +2 -1
- package/src/components/widgets/DateTimeWidget.tsx +3 -10
- package/src/components/widgets/DateWidget.tsx +2 -1
- package/src/components/widgets/EmailWidget.tsx +2 -1
- package/src/components/widgets/FileWidget.tsx +9 -8
- package/src/components/widgets/HiddenWidget.tsx +1 -1
- package/src/components/widgets/PasswordWidget.tsx +2 -1
- package/src/components/widgets/RadioWidget.tsx +8 -10
- package/src/components/widgets/RangeWidget.tsx +1 -1
- package/src/components/widgets/RatingWidget.tsx +48 -47
- package/src/components/widgets/SelectWidget.tsx +48 -31
- package/src/components/widgets/TextWidget.tsx +2 -1
- package/src/components/widgets/TextareaWidget.tsx +10 -7
- package/src/components/widgets/TimeWidget.tsx +2 -1
- package/src/components/widgets/URLWidget.tsx +2 -1
- package/src/components/widgets/UpDownWidget.tsx +2 -1
- package/src/components/widgets/index.ts +1 -1
- package/src/getDefaultRegistry.ts +2 -9
- package/src/getTestRegistry.tsx +2 -7
- package/src/index.ts +10 -5
- package/src/withTheme.tsx +14 -9
package/lib/components/Form.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Component, createRef } from 'react';
|
|
3
|
-
import { createSchemaUtils, deepEquals, ErrorSchemaBuilder, getChangedFields, getTemplate, getUiOptions, isObject, mergeObjects, shouldRender, SUBMIT_BTN_OPTIONS_KEY, toErrorList, toFieldPathId, UI_DEFINITIONS_KEY, UI_GLOBAL_OPTIONS_KEY, UI_OPTIONS_KEY, validationDataMerge, DEFAULT_ID_SEPARATOR, DEFAULT_ID_PREFIX, ERRORS_KEY, ID_KEY, getUsedFormData, getFieldNames, ANY_OF_KEY, ONE_OF_KEY, } from '@rjsf/utils';
|
|
3
|
+
import { createSchemaUtils, deepEquals, ErrorSchemaBuilder, getChangedFields, getTemplate, getUiOptions, hashObject, isObject, mergeObjects, shouldRender, SUBMIT_BTN_OPTIONS_KEY, toErrorList, toFieldPathId, UI_DEFINITIONS_KEY, UI_GLOBAL_OPTIONS_KEY, UI_OPTIONS_KEY, validationDataMerge, DEFAULT_ID_SEPARATOR, DEFAULT_ID_PREFIX, ERRORS_KEY, ID_KEY, getUsedFormData, getFieldNames, ANY_OF_KEY, ONE_OF_KEY, } from '@rjsf/utils';
|
|
4
4
|
import _cloneDeep from 'lodash-es/cloneDeep.js';
|
|
5
5
|
import _get from 'lodash-es/get.js';
|
|
6
6
|
import _isEmpty from 'lodash-es/isEmpty.js';
|
|
@@ -34,7 +34,7 @@ export default class Form extends Component {
|
|
|
34
34
|
/** Flag to track when we're processing a user-initiated field change.
|
|
35
35
|
* This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
isProcessingUserChange = false;
|
|
38
38
|
/** When the `extraErrors` prop changes, re-merges `schemaValidationErrors` + `extraErrors` + `customErrors` into
|
|
39
39
|
* state before render, ensuring the updated errors are visible immediately in a single render cycle.
|
|
40
40
|
*
|
|
@@ -43,10 +43,10 @@ export default class Form extends Component {
|
|
|
43
43
|
* @returns Partial state with re-merged errors if `extraErrors` changed, or `null` if no update is needed
|
|
44
44
|
*/
|
|
45
45
|
static getDerivedStateFromProps(props, state) {
|
|
46
|
-
if (props.extraErrors !== state.
|
|
46
|
+
if (props.extraErrors !== state.prevExtraErrors) {
|
|
47
47
|
const baseErrors = {
|
|
48
48
|
errors: state.schemaValidationErrors || [],
|
|
49
|
-
errorSchema:
|
|
49
|
+
errorSchema: state.schemaValidationErrorSchema || {},
|
|
50
50
|
};
|
|
51
51
|
let { errors, errorSchema } = baseErrors;
|
|
52
52
|
if (props.extraErrors) {
|
|
@@ -55,7 +55,7 @@ export default class Form extends Component {
|
|
|
55
55
|
if (state.customErrors) {
|
|
56
56
|
({ errors, errorSchema } = validationDataMerge({ errors, errorSchema }, state.customErrors.ErrorSchema, true));
|
|
57
57
|
}
|
|
58
|
-
return {
|
|
58
|
+
return { prevExtraErrors: props.extraErrors, errors, errorSchema };
|
|
59
59
|
}
|
|
60
60
|
return null;
|
|
61
61
|
}
|
|
@@ -74,7 +74,7 @@ export default class Form extends Component {
|
|
|
74
74
|
const formData = propsFormData ?? initialFormData;
|
|
75
75
|
this.state = {
|
|
76
76
|
...this.getStateFromProps(props, formData, undefined, undefined, undefined, true),
|
|
77
|
-
|
|
77
|
+
prevExtraErrors: props.extraErrors,
|
|
78
78
|
};
|
|
79
79
|
if (onChange && !deepEquals(this.state.formData, formData)) {
|
|
80
80
|
onChange(toIChangeEvent(this.state));
|
|
@@ -141,8 +141,8 @@ export default class Form extends Component {
|
|
|
141
141
|
// Prevent oneOf/anyOf option switches from reverting when getStateFromProps
|
|
142
142
|
// re-evaluates and produces stale formData.
|
|
143
143
|
const nextStateDiffersFromProps = !deepEquals(nextState.formData, this.props.formData);
|
|
144
|
-
const wasProcessingUserChange = this.
|
|
145
|
-
this.
|
|
144
|
+
const wasProcessingUserChange = this.isProcessingUserChange;
|
|
145
|
+
this.isProcessingUserChange = false;
|
|
146
146
|
if (wasProcessingUserChange && nextStateDiffersFromProps) {
|
|
147
147
|
// Skip - the user's option switch is already applied via processPendingChange
|
|
148
148
|
return;
|
|
@@ -150,6 +150,7 @@ export default class Form extends Component {
|
|
|
150
150
|
if (nextStateDiffersFromProps && !deepEquals(nextState.formData, prevState.formData) && this.props.onChange) {
|
|
151
151
|
this.props.onChange(toIChangeEvent(nextState));
|
|
152
152
|
}
|
|
153
|
+
// oxlint-disable-next-line react/no-did-update-set-state -- guarded to prevent infinite loop
|
|
153
154
|
this.setState(nextState);
|
|
154
155
|
}
|
|
155
156
|
}
|
|
@@ -160,12 +161,13 @@ export default class Form extends Component {
|
|
|
160
161
|
* @param props - The props passed to the `Form`
|
|
161
162
|
* @param inputFormData - The new or current data for the `Form`
|
|
162
163
|
* @param retrievedSchema - An expanded schema, if not provided, it will be retrieved from the `schema` and `formData`.
|
|
163
|
-
* @param isSchemaChanged - A flag indicating whether the schema has changed.
|
|
164
|
-
* @param formDataChangedFields - The changed fields of `formData`
|
|
165
|
-
* @param skipLiveValidate - Optional flag, if true, means that we are not running live validation
|
|
164
|
+
* @param [isSchemaChanged=false] - A flag indicating whether the schema has changed.
|
|
165
|
+
* @param [formDataChangedFields=[]] - The changed fields of `formData`
|
|
166
|
+
* @param [skipLiveValidate=false] - Optional flag, if true, means that we are not running live validation
|
|
167
|
+
* @param [shouldSanitize=false] - Optional flag, if true, means that we should attempt to sanitize formData
|
|
166
168
|
* @returns - The new state for the `Form`
|
|
167
169
|
*/
|
|
168
|
-
getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = [], skipLiveValidate = false) {
|
|
170
|
+
getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = [], skipLiveValidate = false, shouldSanitize = false) {
|
|
169
171
|
const state = this.state || {};
|
|
170
172
|
const schema = 'schema' in props ? props.schema : this.props.schema;
|
|
171
173
|
const validator = 'validator' in props ? props.validator : this.props.validator;
|
|
@@ -173,6 +175,7 @@ export default class Form extends Component {
|
|
|
173
175
|
const isUncontrolled = props.formData === undefined && this.props.formData === undefined;
|
|
174
176
|
const edit = typeof inputFormData !== 'undefined';
|
|
175
177
|
const liveValidate = 'liveValidate' in props ? props.liveValidate : this.props.liveValidate;
|
|
178
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
176
179
|
const mustValidate = edit && !props.noValidate && liveValidate;
|
|
177
180
|
const experimental_defaultFormStateBehavior = 'experimental_defaultFormStateBehavior' in props
|
|
178
181
|
? props.experimental_defaultFormStateBehavior
|
|
@@ -180,7 +183,7 @@ export default class Form extends Component {
|
|
|
180
183
|
const experimental_customMergeAllOf = 'experimental_customMergeAllOf' in props
|
|
181
184
|
? props.experimental_customMergeAllOf
|
|
182
185
|
: this.props.experimental_customMergeAllOf;
|
|
183
|
-
let schemaUtils = state
|
|
186
|
+
let { schemaUtils } = state;
|
|
184
187
|
if (!schemaUtils ||
|
|
185
188
|
schemaUtils.doesSchemaUtilsDiffer(validator, schema, experimental_defaultFormStateBehavior, experimental_customMergeAllOf)) {
|
|
186
189
|
schemaUtils = createSchemaUtils(validator, schema, experimental_defaultFormStateBehavior, experimental_customMergeAllOf);
|
|
@@ -194,14 +197,44 @@ export default class Form extends Component {
|
|
|
194
197
|
else if (inputFormData === undefined && isUncontrolled) {
|
|
195
198
|
defaultsFormData = state.formData;
|
|
196
199
|
}
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
let formData;
|
|
201
|
+
let computedRetrievedSchema;
|
|
202
|
+
let wasSanitized = false;
|
|
203
|
+
const preventInfiniteSanitize = [];
|
|
204
|
+
do {
|
|
205
|
+
formData = schemaUtils.getDefaultFormState(rootSchema, defaultsFormData, false, state.initialDefaultsGenerated);
|
|
206
|
+
// Only hash when sanitizing, wrapping `formData` in an object to deal with a scalar/undefined value
|
|
207
|
+
const formHash = shouldSanitize ? hashObject({ formData }) : '';
|
|
208
|
+
computedRetrievedSchema = this.updateRetrievedSchema(retrievedSchema ?? schemaUtils.retrieveSchema(rootSchema, formData));
|
|
209
|
+
if (shouldSanitize &&
|
|
210
|
+
!preventInfiniteSanitize.includes(formHash) &&
|
|
211
|
+
!deepEquals(computedRetrievedSchema, state.retrievedSchema)) {
|
|
212
|
+
// Sanitize the form data if shouldSanitize is true, we haven't already processed this same formData AND
|
|
213
|
+
// we have a different retrieved schema from when we last ran the state
|
|
214
|
+
const sanitizedFormData = schemaUtils.sanitizeDataForNewSchema(computedRetrievedSchema, state.retrievedSchema, formData);
|
|
215
|
+
wasSanitized = !deepEquals(sanitizedFormData, formData);
|
|
216
|
+
if (wasSanitized) {
|
|
217
|
+
// Update both the formData AND defaultsFormData due to the sanitize so the loop works with the new data
|
|
218
|
+
formData = sanitizedFormData;
|
|
219
|
+
defaultsFormData = sanitizedFormData;
|
|
220
|
+
const sanitizedFormHash = hashObject({ formData: sanitizedFormData });
|
|
221
|
+
// If we've seen the sanitized data before, we are done
|
|
222
|
+
wasSanitized = !preventInfiniteSanitize.includes(sanitizedFormHash);
|
|
223
|
+
preventInfiniteSanitize.push(sanitizedFormHash);
|
|
224
|
+
}
|
|
225
|
+
preventInfiniteSanitize.push(formHash);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
wasSanitized = false;
|
|
229
|
+
}
|
|
230
|
+
} while (wasSanitized);
|
|
199
231
|
const getCurrentErrors = () => {
|
|
200
232
|
// If the `props.noValidate` option is set or the schema has changed, we reset the error state.
|
|
233
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
201
234
|
if (props.noValidate || isSchemaChanged) {
|
|
202
235
|
return { errors: [], errorSchema: {} };
|
|
203
236
|
}
|
|
204
|
-
|
|
237
|
+
if (!props.liveValidate) {
|
|
205
238
|
return {
|
|
206
239
|
errors: state.schemaValidationErrors || [],
|
|
207
240
|
errorSchema: state.schemaValidationErrorSchema || {},
|
|
@@ -214,8 +247,7 @@ export default class Form extends Component {
|
|
|
214
247
|
};
|
|
215
248
|
let errors;
|
|
216
249
|
let errorSchema;
|
|
217
|
-
let schemaValidationErrors = state
|
|
218
|
-
let schemaValidationErrorSchema = state.schemaValidationErrorSchema;
|
|
250
|
+
let { schemaValidationErrors, schemaValidationErrorSchema } = state;
|
|
219
251
|
// If we are skipping live validate, it means that the state has already been updated with live validation errors
|
|
220
252
|
if (mustValidate && !skipLiveValidate) {
|
|
221
253
|
const liveValidation = this.liveValidate(rootSchema, schemaUtils, state.errorSchema, formData, undefined, state.customErrors, retrievedSchema,
|
|
@@ -237,14 +269,15 @@ export default class Form extends Component {
|
|
|
237
269
|
acc[key] = undefined;
|
|
238
270
|
return acc;
|
|
239
271
|
}, {});
|
|
240
|
-
|
|
272
|
+
schemaValidationErrorSchema = mergeObjects(currentErrors.errorSchema, newErrorSchema, 'preventDuplicates');
|
|
273
|
+
errorSchema = schemaValidationErrorSchema;
|
|
241
274
|
}
|
|
242
|
-
const mergedErrors =
|
|
275
|
+
const mergedErrors = Form.mergeErrors({ errorSchema, errors }, props.extraErrors, state.customErrors);
|
|
243
276
|
errors = mergedErrors.errors;
|
|
244
277
|
errorSchema = mergedErrors.errorSchema;
|
|
245
278
|
}
|
|
246
279
|
// Only store a new registry when the props cause a different one to be created
|
|
247
|
-
const newRegistry =
|
|
280
|
+
const newRegistry = Form.getRegistry(props, rootSchema, schemaUtils);
|
|
248
281
|
const registry = deepEquals(state.registry, newRegistry) ? state.registry : newRegistry;
|
|
249
282
|
// Only compute a new `fieldPathId` when the `idPrefix` is different than the existing fieldPathId's ID_KEY
|
|
250
283
|
const fieldPathId = state.fieldPathId && state.fieldPathId?.[ID_KEY] === registry.globalFormOptions.idPrefix
|
|
@@ -261,7 +294,7 @@ export default class Form extends Component {
|
|
|
261
294
|
errorSchema,
|
|
262
295
|
schemaValidationErrors,
|
|
263
296
|
schemaValidationErrorSchema,
|
|
264
|
-
retrievedSchema:
|
|
297
|
+
retrievedSchema: computedRetrievedSchema,
|
|
265
298
|
initialDefaultsGenerated: true,
|
|
266
299
|
registry,
|
|
267
300
|
};
|
|
@@ -286,19 +319,24 @@ export default class Form extends Component {
|
|
|
286
319
|
* @param [retrievedSchema] - An optionally retrieved schema for per
|
|
287
320
|
*/
|
|
288
321
|
validate(formData, schema = this.state.schema, altSchemaUtils, retrievedSchema) {
|
|
289
|
-
const schemaUtils = altSchemaUtils
|
|
322
|
+
const schemaUtils = altSchemaUtils || this.state.schemaUtils;
|
|
290
323
|
const { customValidate, transformErrors, uiSchema } = this.props;
|
|
291
|
-
|
|
324
|
+
// When a pre-resolved schema is provided (e.g., from live validation), use it directly.
|
|
325
|
+
// Otherwise validate against the original schema so AJV sees the full constraint set.
|
|
326
|
+
const validationSchema = retrievedSchema ?? schema;
|
|
327
|
+
// JSON.stringify drops keys with `undefined` values; JSON.parse on the result gives AJV a clean
|
|
328
|
+
// object that avoids spurious type errors for `type: "string"` fields that were cleared (#4518).
|
|
329
|
+
const validationFormData = formData ? JSON.parse(JSON.stringify(formData)) : undefined;
|
|
292
330
|
return schemaUtils
|
|
293
331
|
.getValidator()
|
|
294
|
-
.validateFormData(
|
|
332
|
+
.validateFormData(validationFormData, validationSchema, customValidate, transformErrors, uiSchema);
|
|
295
333
|
}
|
|
296
334
|
/** Renders any errors contained in the `state` in using the `ErrorList`, if not disabled by `showErrorList`. */
|
|
297
335
|
renderErrors(registry) {
|
|
298
336
|
const { errors, errorSchema, schema, uiSchema } = this.state;
|
|
299
337
|
const options = getUiOptions(uiSchema);
|
|
300
338
|
const ErrorListTemplate = getTemplate('ErrorListTemplate', registry, options);
|
|
301
|
-
if (errors
|
|
339
|
+
if (errors?.length) {
|
|
302
340
|
return (_jsx(ErrorListTemplate, { errors: errors, errorSchema: errorSchema || {}, schema: schema, uiSchema: uiSchema, registry: registry }));
|
|
303
341
|
}
|
|
304
342
|
return null;
|
|
@@ -311,9 +349,8 @@ export default class Form extends Component {
|
|
|
311
349
|
* @return - The `extraErrors` and `customErrors` merged into the `schemaValidation`
|
|
312
350
|
* @private
|
|
313
351
|
*/
|
|
314
|
-
mergeErrors(schemaValidation, extraErrors, customErrors) {
|
|
315
|
-
let errorSchema = schemaValidation
|
|
316
|
-
let errors = schemaValidation.errors;
|
|
352
|
+
static mergeErrors(schemaValidation, extraErrors, customErrors) {
|
|
353
|
+
let { errorSchema, errors } = schemaValidation;
|
|
317
354
|
if (extraErrors) {
|
|
318
355
|
const merged = validationDataMerge(schemaValidation, extraErrors);
|
|
319
356
|
errorSchema = merged.errorSchema;
|
|
@@ -342,15 +379,15 @@ export default class Form extends Component {
|
|
|
342
379
|
*/
|
|
343
380
|
liveValidate(rootSchema, schemaUtils, originalErrorSchema, formData, extraErrors, customErrors, retrievedSchema, mergeIntoOriginalErrorSchema = false) {
|
|
344
381
|
const schemaValidation = this.validate(formData, rootSchema, schemaUtils, retrievedSchema);
|
|
345
|
-
const errors = schemaValidation
|
|
346
|
-
let errorSchema = schemaValidation
|
|
382
|
+
const { errors } = schemaValidation;
|
|
383
|
+
let { errorSchema } = schemaValidation;
|
|
347
384
|
// We merge 'originalErrorSchema' with 'schemaValidation.errorSchema.'; This done to display the raised field error.
|
|
348
385
|
if (mergeIntoOriginalErrorSchema) {
|
|
349
386
|
errorSchema = mergeObjects(originalErrorSchema, schemaValidation.errorSchema, 'preventDuplicates');
|
|
350
387
|
}
|
|
351
388
|
const schemaValidationErrors = errors;
|
|
352
389
|
const schemaValidationErrorSchema = errorSchema;
|
|
353
|
-
const mergedErrors =
|
|
390
|
+
const mergedErrors = Form.mergeErrors({ errorSchema, errors }, extraErrors, customErrors);
|
|
354
391
|
return { ...mergedErrors, schemaValidationErrors, schemaValidationErrorSchema };
|
|
355
392
|
}
|
|
356
393
|
/** Returns the `formData` with only the elements specified in the `fields` list
|
|
@@ -359,18 +396,16 @@ export default class Form extends Component {
|
|
|
359
396
|
* @param fields - The fields to keep while filtering
|
|
360
397
|
* @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
|
|
361
398
|
*/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
};
|
|
399
|
+
// oxlint-disable-next-line class-methods-use-this, typescript/no-deprecated
|
|
400
|
+
getUsedFormData = (formData, fields) => getUsedFormData(formData, fields);
|
|
365
401
|
/** Returns the list of field names from inspecting the `pathSchema` as well as using the `formData`
|
|
366
402
|
*
|
|
367
403
|
* @param pathSchema - The `PathSchema` object for the form
|
|
368
404
|
* @param [formData] - The form data to use while checking for empty objects/arrays
|
|
369
405
|
* @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
|
|
370
406
|
*/
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
};
|
|
407
|
+
// oxlint-disable-next-line class-methods-use-this, typescript/no-deprecated
|
|
408
|
+
getFieldNames = (pathSchema, formData) => getFieldNames(pathSchema, formData);
|
|
374
409
|
/** Returns the `formData` after filtering to remove any extra data not in a form field
|
|
375
410
|
*
|
|
376
411
|
* @param formData - The data for the `Form`
|
|
@@ -424,19 +459,19 @@ export default class Form extends Component {
|
|
|
424
459
|
}
|
|
425
460
|
// Mark that we're processing a user-initiated change.
|
|
426
461
|
// This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
|
|
427
|
-
this.
|
|
462
|
+
this.isProcessingUserChange = true;
|
|
428
463
|
const { newValue, path, id } = this.pendingChanges[0];
|
|
429
464
|
const { newErrorSchema } = this.pendingChanges[0];
|
|
430
|
-
|
|
465
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
466
|
+
const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange, disabled, readonly } = this.props;
|
|
431
467
|
const { formData: oldFormData, schemaUtils, schema, fieldPathId, schemaValidationErrorSchema, errors } = this.state;
|
|
432
|
-
let { customErrors } = this.state;
|
|
468
|
+
let { customErrors, retrievedSchema } = this.state;
|
|
433
469
|
// Use the un-merged AJV-only schema as the base for re-merging extraErrors. Mirrors the
|
|
434
470
|
// pattern in getStateFromProps/getDerivedStateFromProps and avoids the duplication that
|
|
435
471
|
// happened when state.errorSchema (already containing merged extraErrors) was passed in.
|
|
436
472
|
let mergeBaseErrorSchema = schemaValidationErrorSchema;
|
|
437
473
|
const rootPathId = fieldPathId.path[0] || '';
|
|
438
474
|
const isRootPath = !path || path.length === 0 || (path.length === 1 && path[0] === rootPathId);
|
|
439
|
-
let retrievedSchema = this.state.retrievedSchema;
|
|
440
475
|
let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
|
|
441
476
|
// When switching from null to an object option in oneOf, MultiSchemaField sends
|
|
442
477
|
// an object with property names but undefined values (e.g., {types: undefined, content: undefined}).
|
|
@@ -448,13 +483,18 @@ export default class Form extends Component {
|
|
|
448
483
|
const wasPreviouslyNull = oldFormData === null || oldFormData === undefined;
|
|
449
484
|
const inputForDefaults = hasOnlyUndefinedValues && wasPreviouslyNull ? undefined : formData;
|
|
450
485
|
if (isObject(formData) || Array.isArray(formData)) {
|
|
486
|
+
// Tracks if the user cleared a plain (non-oneOf/anyOf) leaf field.
|
|
487
|
+
// The key is removed twice: once before getStateFromProps so inputForDefaults
|
|
488
|
+
// reflects an empty field for conditional schema resolution, and once after so
|
|
489
|
+
// the user's clear overrides any schema default getStateFromProps re-applied (#5125)
|
|
490
|
+
// and AJV never receives { key: undefined } for type:"string" fields (#4518).
|
|
491
|
+
let plainLeafWasCleared = false;
|
|
451
492
|
if (newValue === ADDITIONAL_PROPERTY_KEY_REMOVE) {
|
|
452
|
-
// For additional properties,
|
|
493
|
+
// For additional properties, this key was explicitly removed, so unset it
|
|
453
494
|
_unset(formData, path);
|
|
454
495
|
}
|
|
455
496
|
else if (!isRootPath) {
|
|
456
|
-
//
|
|
457
|
-
let unsetPath = false;
|
|
497
|
+
// Set the new value at its path in the form data.
|
|
458
498
|
let valueForPath = newValue;
|
|
459
499
|
if (newValue === undefined) {
|
|
460
500
|
const lastSegment = path[path.length - 1];
|
|
@@ -466,35 +506,42 @@ export default class Form extends Component {
|
|
|
466
506
|
const { field } = schemaUtils.findFieldInSchema(schema, path, oldFormData);
|
|
467
507
|
const leaf = field;
|
|
468
508
|
const isOneOfOrAnyOfLeaf = leaf && (ONE_OF_KEY in leaf || ANY_OF_KEY in leaf);
|
|
469
|
-
//
|
|
470
|
-
//
|
|
471
|
-
//
|
|
472
|
-
// mergeDefaults does not immediately re-apply a branch default when clearing those widgets.
|
|
509
|
+
// oneOf/anyOf and unresolved leaves keep `undefined` so mergeDefaults doesn't
|
|
510
|
+
// re-apply a branch default when the user clears the widget.
|
|
511
|
+
// Plain resolved leaves use plainLeafWasCleared instead (see below).
|
|
473
512
|
if (!isOneOfOrAnyOfLeaf && leaf !== undefined) {
|
|
474
|
-
|
|
513
|
+
plainLeafWasCleared = true;
|
|
475
514
|
}
|
|
476
515
|
}
|
|
477
516
|
}
|
|
478
|
-
if (
|
|
479
|
-
|
|
517
|
+
if (plainLeafWasCleared) {
|
|
518
|
+
_set(formData, path, undefined);
|
|
480
519
|
}
|
|
481
520
|
else {
|
|
482
521
|
_set(formData, path, valueForPath);
|
|
483
522
|
}
|
|
484
523
|
}
|
|
485
|
-
|
|
486
|
-
|
|
524
|
+
const shouldSanitize = retrievedSchema && !isRootPath && !isObject(newValue) && !Array.isArray(newValue) && !disabled && !readonly;
|
|
525
|
+
// Skip live validation here; it runs later in this function.
|
|
526
|
+
const newState = this.getStateFromProps(this.props, inputForDefaults, undefined, undefined, undefined, true, shouldSanitize);
|
|
487
527
|
formData = newState.formData;
|
|
488
528
|
retrievedSchema = newState.retrievedSchema;
|
|
529
|
+
// Re-set to undefined after merging defaults so the user's clear is preserved in
|
|
530
|
+
// state (#5125 regression: without this, clearing a second field re-applies the
|
|
531
|
+
// default to previously-cleared fields). The undefined key is stripped from the
|
|
532
|
+
// formData copy passed to AJV via JSON.parse(JSON.stringify(...)) so the validator never
|
|
533
|
+
// sees { [key]: undefined } for type:"string" or patternProperties fields (#4518).
|
|
534
|
+
if (plainLeafWasCleared && formData) {
|
|
535
|
+
_set(formData, path, undefined);
|
|
536
|
+
}
|
|
489
537
|
}
|
|
490
538
|
const mustValidate = !noValidate && (liveValidate === true || liveValidate === 'onChange');
|
|
491
|
-
let state = { formData,
|
|
539
|
+
let state = { formData, retrievedSchema };
|
|
492
540
|
let newFormData = formData;
|
|
493
541
|
if (omitExtraData === true && (liveOmit === true || liveOmit === 'onChange')) {
|
|
542
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
494
543
|
newFormData = this.omitExtraData(formData);
|
|
495
|
-
state = {
|
|
496
|
-
formData: newFormData,
|
|
497
|
-
};
|
|
544
|
+
state = { ...state, formData: newFormData };
|
|
498
545
|
}
|
|
499
546
|
if (newErrorSchema) {
|
|
500
547
|
// First check to see if there is an existing validation error on this path...
|
|
@@ -517,10 +564,10 @@ export default class Form extends Component {
|
|
|
517
564
|
customErrors = new ErrorSchemaBuilder();
|
|
518
565
|
}
|
|
519
566
|
if (isRootPath) {
|
|
520
|
-
const
|
|
521
|
-
if (
|
|
567
|
+
const pathErrors = _get(newErrorSchema, ERRORS_KEY);
|
|
568
|
+
if (pathErrors) {
|
|
522
569
|
// only set errors when there are some
|
|
523
|
-
customErrors.setErrors(
|
|
570
|
+
customErrors.setErrors(pathErrors);
|
|
524
571
|
}
|
|
525
572
|
}
|
|
526
573
|
else {
|
|
@@ -535,16 +582,12 @@ export default class Form extends Component {
|
|
|
535
582
|
// If there are pending changes in the queue, skip live validation since it will happen with the last change
|
|
536
583
|
if (mustValidate && this.pendingChanges.length === 1) {
|
|
537
584
|
const liveValidation = this.liveValidate(schema, schemaUtils, mergeBaseErrorSchema, newFormData, extraErrors, customErrors, retrievedSchema);
|
|
538
|
-
state = { formData: newFormData, ...liveValidation, customErrors };
|
|
585
|
+
state = { ...state, formData: newFormData, ...liveValidation, customErrors };
|
|
539
586
|
}
|
|
540
587
|
else if (!noValidate && newErrorSchema) {
|
|
541
588
|
// Merging 'newErrorSchema' into 'errorSchema' to display the custom raised errors.
|
|
542
|
-
const mergedErrors =
|
|
543
|
-
state = {
|
|
544
|
-
formData: newFormData,
|
|
545
|
-
...mergedErrors,
|
|
546
|
-
customErrors,
|
|
547
|
-
};
|
|
589
|
+
const mergedErrors = Form.mergeErrors({ errorSchema: mergeBaseErrorSchema, errors }, extraErrors, customErrors);
|
|
590
|
+
state = { ...state, formData: newFormData, ...mergedErrors, customErrors };
|
|
548
591
|
}
|
|
549
592
|
this.setState(state, () => {
|
|
550
593
|
if (onChange) {
|
|
@@ -588,7 +631,7 @@ export default class Form extends Component {
|
|
|
588
631
|
initialDefaultsGenerated: false,
|
|
589
632
|
customErrors: undefined,
|
|
590
633
|
};
|
|
591
|
-
this.setState(state, () => onChange
|
|
634
|
+
this.setState(state, () => onChange?.(toIChangeEvent({ ...this.state, ...state })));
|
|
592
635
|
};
|
|
593
636
|
/** Callback function to handle when a field on the form is blurred. Calls the `onBlur` callback for the `Form` if it
|
|
594
637
|
* was provided. Also runs any live validation and/or live omit operations if the flags indicate they should happen
|
|
@@ -608,6 +651,7 @@ export default class Form extends Component {
|
|
|
608
651
|
let newFormData = formData;
|
|
609
652
|
let state = { formData: newFormData };
|
|
610
653
|
if (omitExtraData === true && liveOmit === 'onBlur') {
|
|
654
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
611
655
|
newFormData = this.omitExtraData(formData);
|
|
612
656
|
state = { formData: newFormData };
|
|
613
657
|
}
|
|
@@ -657,9 +701,11 @@ export default class Form extends Component {
|
|
|
657
701
|
return;
|
|
658
702
|
}
|
|
659
703
|
event.persist();
|
|
704
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
660
705
|
const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
|
|
661
706
|
let { formData: newFormData } = this.state;
|
|
662
707
|
if (omitExtraData === true) {
|
|
708
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
663
709
|
newFormData = this.omitExtraData(newFormData);
|
|
664
710
|
}
|
|
665
711
|
if (noValidate || this.validateFormWithFormData(newFormData)) {
|
|
@@ -686,8 +732,9 @@ export default class Form extends Component {
|
|
|
686
732
|
* @returns - The `GlobalFormOptions` from the props
|
|
687
733
|
* @private
|
|
688
734
|
*/
|
|
689
|
-
getGlobalFormOptions(props) {
|
|
735
|
+
static getGlobalFormOptions(props) {
|
|
690
736
|
const { uiSchema = {}, experimental_componentUpdateStrategy, idSeparator = DEFAULT_ID_SEPARATOR, idPrefix = DEFAULT_ID_PREFIX, nameGenerator, useFallbackUiForUnsupportedType = false, } = props;
|
|
737
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
691
738
|
const rootFieldId = uiSchema['ui:rootFieldId'];
|
|
692
739
|
// Omit any options that are undefined or null
|
|
693
740
|
return {
|
|
@@ -699,7 +746,7 @@ export default class Form extends Component {
|
|
|
699
746
|
};
|
|
700
747
|
}
|
|
701
748
|
/** Computed the registry for the form using the given `props`, `schema` and `schemaUtils` */
|
|
702
|
-
getRegistry(props, schema, schemaUtils) {
|
|
749
|
+
static getRegistry(props, schema, schemaUtils) {
|
|
703
750
|
const { translateString: customTranslateString, uiSchema = {} } = props;
|
|
704
751
|
const { fields, templates, widgets, formContext, translateString } = getDefaultRegistry();
|
|
705
752
|
return {
|
|
@@ -718,7 +765,7 @@ export default class Form extends Component {
|
|
|
718
765
|
schemaUtils,
|
|
719
766
|
translateString: customTranslateString || translateString,
|
|
720
767
|
globalUiOptions: uiSchema[UI_GLOBAL_OPTIONS_KEY],
|
|
721
|
-
globalFormOptions:
|
|
768
|
+
globalFormOptions: Form.getGlobalFormOptions(props),
|
|
722
769
|
uiSchemaDefinitions: uiSchema[UI_DEFINITIONS_KEY] ?? {},
|
|
723
770
|
};
|
|
724
771
|
}
|
|
@@ -758,8 +805,9 @@ export default class Form extends Component {
|
|
|
758
805
|
// some themes (e.g. shadcn) use button elements instead of native inputs for radio groups
|
|
759
806
|
field = this.formElement.current.querySelector(`input[id^="${elementId}"], button[id^="${elementId}"]`);
|
|
760
807
|
}
|
|
761
|
-
if (field
|
|
808
|
+
if (field?.length) {
|
|
762
809
|
// If we got a list with length > 0
|
|
810
|
+
// oxlint-disable-next-line prefer-destructuring
|
|
763
811
|
field = field[0];
|
|
764
812
|
}
|
|
765
813
|
if (field) {
|
|
@@ -777,7 +825,7 @@ export default class Form extends Component {
|
|
|
777
825
|
const { errors: prevErrors } = this.state;
|
|
778
826
|
const schemaValidation = this.validate(formData);
|
|
779
827
|
// Always merge extraErrors so they remain visible in state regardless of extraErrorsBlockSubmit.
|
|
780
|
-
const { errors, errorSchema } = extraErrors ?
|
|
828
|
+
const { errors, errorSchema } = extraErrors ? Form.mergeErrors(schemaValidation, extraErrors) : schemaValidation;
|
|
781
829
|
// hasError gates submission: schema errors always block; extraErrors only block when
|
|
782
830
|
// extraErrorsBlockSubmit is set (non-breaking default: extraErrors are informational only).
|
|
783
831
|
const hasError = schemaValidation.errors.length > 0 || (extraErrors && extraErrorsBlockSubmit);
|
|
@@ -800,6 +848,7 @@ export default class Form extends Component {
|
|
|
800
848
|
onError(errors);
|
|
801
849
|
}
|
|
802
850
|
else {
|
|
851
|
+
// oxlint-disable-next-line no-console
|
|
803
852
|
console.error('Form validation failed', errors);
|
|
804
853
|
}
|
|
805
854
|
});
|
|
@@ -833,6 +882,7 @@ export default class Form extends Component {
|
|
|
833
882
|
const { omitExtraData } = this.props;
|
|
834
883
|
let { formData: newFormData } = this.state;
|
|
835
884
|
if (omitExtraData === true) {
|
|
885
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
836
886
|
newFormData = this.omitExtraData(newFormData);
|
|
837
887
|
}
|
|
838
888
|
return this.validateFormWithFormData(newFormData);
|
|
@@ -843,7 +893,7 @@ export default class Form extends Component {
|
|
|
843
893
|
render() {
|
|
844
894
|
const { children, id, className = '', tagName, name, method, target, action, autoComplete, enctype, acceptCharset, noHtml5Validate = false, disabled, readonly, showErrorList = 'top', _internalFormWrapper, } = this.props;
|
|
845
895
|
const { schema, uiSchema, formData, errorSchema, fieldPathId, registry } = this.state;
|
|
846
|
-
const { SchemaField:
|
|
896
|
+
const { SchemaField: SchemaFieldComponent } = registry.fields;
|
|
847
897
|
const { SubmitButton } = registry.templates.ButtonTemplates;
|
|
848
898
|
// The `semantic-ui` and `material-ui` themes have `_internalFormWrapper`s that take an `as` prop that is the
|
|
849
899
|
// PropTypes.elementType to use for the inner tag, so we'll need to pass `tagName` along if it is provided.
|
|
@@ -855,6 +905,6 @@ export default class Form extends Component {
|
|
|
855
905
|
submitOptions = { ...submitOptions, props: { ...submitOptions.props, disabled: true } };
|
|
856
906
|
}
|
|
857
907
|
const submitUiSchema = { [UI_OPTIONS_KEY]: { [SUBMIT_BTN_OPTIONS_KEY]: submitOptions } };
|
|
858
|
-
return (_jsxs(FormTag, { className: className
|
|
908
|
+
return (_jsxs(FormTag, { className: className || 'rjsf', id: id, name: name, method: method, target: target, action: action, autoComplete: autoComplete, encType: enctype, acceptCharset: acceptCharset, noValidate: noHtml5Validate, onSubmit: this.onSubmit, as: as, ref: this.formElement, children: [showErrorList === 'top' && this.renderErrors(registry), _jsx(SchemaFieldComponent, { name: '', schema: schema, uiSchema: uiSchema, errorSchema: errorSchema, fieldPathId: fieldPathId, formData: formData, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, registry: registry, disabled: disabled, readonly: readonly }), children || _jsx(SubmitButton, { uiSchema: submitUiSchema, registry: registry }), showErrorList === 'bottom' && this.renderErrors(registry)] }));
|
|
859
909
|
}
|
|
860
910
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
3
3
|
export interface RichDescriptionProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
|
|
4
4
|
/** The description text for a field, potentially containing markdown */
|
|
5
5
|
description: string | ReactElement;
|
|
@@ -12,7 +12,7 @@ export interface RichDescriptionProps<T = any, S extends StrictRJSFSchema = RJSF
|
|
|
12
12
|
*
|
|
13
13
|
* @param props - The `RichDescriptionProps` for this component
|
|
14
14
|
*/
|
|
15
|
-
declare function RichDescription<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({ description, registry, uiSchema }: RichDescriptionProps<T, S, F>): string | import("react
|
|
15
|
+
declare function RichDescription<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({ description, registry, uiSchema }: RichDescriptionProps<T, S, F>): string | import("react").JSX.Element;
|
|
16
16
|
declare namespace RichDescription {
|
|
17
17
|
var TEST_IDS: import("@rjsf/utils").TestIdShape;
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichDescription.d.ts","sourceRoot":"","sources":["../../src/components/RichDescription.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RichDescription.d.ts","sourceRoot":"","sources":["../../src/components/RichDescription.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAMrG,MAAM,WAAW,oBAAoB,CACnC,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,gBAAgB,GAAG,UAAU,EACvC,CAAC,SAAS,eAAe,GAAG,GAAG;IAE/B,wEAAwE;IACxE,WAAW,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,kDAAkD;IAClD,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,4BAA4B;IAC5B,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,iBAAwB,eAAe,CACrC,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,gBAAgB,GAAG,UAAU,EACvC,CAAC,SAAS,eAAe,GAAG,GAAG,EAC/B,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAa,EAAE,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,wCAYxE;kBAhBuB,eAAe;;;eAAf,eAAe"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { getTestIds, getUiOptions
|
|
2
|
+
import { getTestIds, getUiOptions } from '@rjsf/utils';
|
|
3
3
|
import { Markdown } from 'markdown-to-jsx/react';
|
|
4
4
|
const TEST_IDS = getTestIds();
|
|
5
5
|
/** Renders the given `description` in the props as
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
3
3
|
export interface RichHelpProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
|
|
4
4
|
/** The description text for a field, potentially containing markdown */
|
|
5
5
|
help: string | ReactElement;
|
|
@@ -12,7 +12,7 @@ export interface RichHelpProps<T = any, S extends StrictRJSFSchema = RJSFSchema,
|
|
|
12
12
|
*
|
|
13
13
|
* @param props - The `RichHelpProps` for this component
|
|
14
14
|
*/
|
|
15
|
-
declare function RichHelp<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({ help, registry, uiSchema, }: RichHelpProps<T, S, F>): string | import("react
|
|
15
|
+
declare function RichHelp<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>({ help, registry, uiSchema, }: RichHelpProps<T, S, F>): string | import("react").JSX.Element;
|
|
16
16
|
declare namespace RichHelp {
|
|
17
17
|
var TEST_IDS: import("@rjsf/utils").TestIdShape;
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichHelp.d.ts","sourceRoot":"","sources":["../../src/components/RichHelp.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RichHelp.d.ts","sourceRoot":"","sources":["../../src/components/RichHelp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAMrG,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG;IAC9G,wEAAwE;IACxE,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,4BAA4B;IAC5B,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,iBAAwB,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG,EAAE,EAClH,IAAI,EACJ,QAAQ,EACR,QAAa,GACd,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,wCAYxB;kBAhBuB,QAAQ;;;eAAR,QAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { getTestIds, getUiOptions
|
|
2
|
+
import { getTestIds, getUiOptions } from '@rjsf/utils';
|
|
3
3
|
import { Markdown } from 'markdown-to-jsx/react';
|
|
4
4
|
const TEST_IDS = getTestIds();
|
|
5
5
|
/** Renders the given `description` in the props as
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
1
|
+
import type { RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
2
2
|
export interface SchemaExamplesProps<S extends StrictRJSFSchema = RJSFSchema> {
|
|
3
3
|
/** The id of the input element this datalist is for */
|
|
4
4
|
id: string;
|
|
@@ -12,5 +12,5 @@ export interface SchemaExamplesProps<S extends StrictRJSFSchema = RJSFSchema> {
|
|
|
12
12
|
*
|
|
13
13
|
* @param props - The `SchemaExamplesProps` for this component
|
|
14
14
|
*/
|
|
15
|
-
export default function SchemaExamples<S extends StrictRJSFSchema = RJSFSchema>(props: SchemaExamplesProps<S>): import("react
|
|
15
|
+
export default function SchemaExamples<S extends StrictRJSFSchema = RJSFSchema>(props: SchemaExamplesProps<S>): import("react").JSX.Element | null;
|
|
16
16
|
//# sourceMappingURL=SchemaExamples.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaExamples.d.ts","sourceRoot":"","sources":["../../src/components/SchemaExamples.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SchemaExamples.d.ts","sourceRoot":"","sources":["../../src/components/SchemaExamples.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGhE,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,gBAAgB,GAAG,UAAU;IAC1E,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,MAAM,EAAE,CAAC,CAAC;CACX;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAC,SAAS,gBAAgB,GAAG,UAAU,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,sCAoB5G"}
|
|
@@ -17,7 +17,5 @@ export default function SchemaExamples(props) {
|
|
|
17
17
|
.concat(schemaDefault !== undefined && !examples.map(String).includes(String(schemaDefault))
|
|
18
18
|
? [schemaDefault]
|
|
19
19
|
: [])
|
|
20
|
-
.map((example) => {
|
|
21
|
-
return _jsx("option", { value: example }, String(example));
|
|
22
|
-
}) }, `datalist_${id}`));
|
|
20
|
+
.map((example) => (_jsx("option", { value: example }, String(example)))) }, `datalist_${id}`));
|
|
23
21
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FieldProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
1
|
+
import type { FieldProps, FormContextType, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
|
|
2
2
|
/** The `ArrayField` component is used to render a field in the schema that is of type `array`. It supports both normal
|
|
3
3
|
* and fixed array, allowing user to add and remove elements from the array data.
|
|
4
4
|
*/
|
|
5
|
-
export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(props: FieldProps<T[], S, F>): import("react
|
|
5
|
+
export default function ArrayField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(props: FieldProps<T[], S, F>): import("react").JSX.Element;
|
|
6
6
|
//# sourceMappingURL=ArrayField.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArrayField.d.ts","sourceRoot":"","sources":["../../../src/components/fields/ArrayField.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ArrayField.d.ts","sourceRoot":"","sources":["../../../src/components/fields/ArrayField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAKV,UAAU,EACV,eAAe,EAEf,UAAU,EACV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AAs1BrB;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,SAAS,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG,EAClH,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,+BAsP7B"}
|