@rjsf/core 6.6.0 → 6.6.2
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 +454 -373
- package/dist/index.cjs +416 -334
- package/dist/index.cjs.map +3 -3
- package/dist/index.esm.js +418 -415
- package/dist/index.esm.js.map +3 -3
- package/lib/components/Form.d.ts +14 -11
- package/lib/components/Form.d.ts.map +1 -1
- package/lib/components/Form.js +97 -62
- package/lib/components/RichDescription.d.ts +2 -2
- package/lib/components/RichDescription.d.ts.map +1 -1
- package/lib/components/RichDescription.js +1 -1
- package/lib/components/RichHelp.d.ts +2 -2
- package/lib/components/RichHelp.d.ts.map +1 -1
- package/lib/components/RichHelp.js +1 -1
- package/lib/components/SchemaExamples.d.ts +1 -1
- package/lib/components/SchemaExamples.d.ts.map +1 -1
- package/lib/components/SchemaExamples.js +1 -3
- package/lib/components/fields/ArrayField.d.ts +1 -1
- 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 +1 -1
- package/lib/components/fields/BooleanField.d.ts.map +1 -1
- package/lib/components/fields/BooleanField.js +2 -5
- package/lib/components/fields/FallbackField.d.ts +1 -1
- 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 +7 -9
- 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 +1 -1
- 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 +1 -1
- 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 +9 -3
- package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
- package/lib/components/fields/MultiSchemaField.js +27 -9
- 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 +1 -1
- 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 +1 -1
- package/lib/components/fields/ObjectField.d.ts.map +1 -1
- package/lib/components/fields/ObjectField.js +27 -25
- package/lib/components/fields/OptionalDataControlsField.d.ts +1 -1
- package/lib/components/fields/OptionalDataControlsField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.d.ts +1 -1
- package/lib/components/fields/SchemaField.d.ts.map +1 -1
- package/lib/components/fields/SchemaField.js +7 -7
- package/lib/components/fields/StringField.d.ts +1 -1
- 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/templates/ArrayFieldDescriptionTemplate.d.ts +1 -1
- 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 +1 -1
- 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 +1 -1
- package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldItemTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldTemplate.d.ts +1 -1
- package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTemplate.js +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -1
- package/lib/components/templates/ArrayFieldTitleTemplate.js +1 -1
- package/lib/components/templates/BaseInputTemplate.d.ts +1 -1
- 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 +1 -1
- 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 +1 -1
- 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/DescriptionField.d.ts +1 -1
- package/lib/components/templates/DescriptionField.d.ts.map +1 -1
- package/lib/components/templates/ErrorList.d.ts +1 -1
- 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 +1 -1
- package/lib/components/templates/FallbackFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldErrorTemplate.d.ts +1 -1
- 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 +1 -1
- package/lib/components/templates/FieldHelpTemplate.d.ts.map +1 -1
- package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts +1 -1
- 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 +2 -2
- package/lib/components/templates/FieldTemplate/Label.d.ts.map +1 -1
- package/lib/components/templates/GridTemplate.d.ts +1 -1
- package/lib/components/templates/GridTemplate.d.ts.map +1 -1
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +1 -1
- package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -1
- package/lib/components/templates/ObjectFieldTemplate.d.ts +1 -1
- 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 +1 -1
- 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 +1 -1
- package/lib/components/templates/TitleField.d.ts.map +1 -1
- package/lib/components/templates/UnsupportedField.d.ts +1 -1
- package/lib/components/templates/UnsupportedField.d.ts.map +1 -1
- package/lib/components/templates/UnsupportedField.js +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.d.ts +1 -1
- 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/widgets/AltDateTimeWidget.d.ts +1 -1
- package/lib/components/widgets/AltDateTimeWidget.d.ts.map +1 -1
- package/lib/components/widgets/AltDateWidget.d.ts +1 -1
- package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
- package/lib/components/widgets/AltDateWidget.js +2 -2
- package/lib/components/widgets/CheckboxWidget.d.ts +1 -1
- package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.d.ts +1 -1
- package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.js +2 -2
- package/lib/components/widgets/ColorWidget.d.ts +1 -1
- package/lib/components/widgets/ColorWidget.d.ts.map +1 -1
- package/lib/components/widgets/DateTimeWidget.d.ts +1 -1
- 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 +1 -1
- package/lib/components/widgets/DateWidget.d.ts.map +1 -1
- package/lib/components/widgets/EmailWidget.d.ts +1 -1
- package/lib/components/widgets/EmailWidget.d.ts.map +1 -1
- package/lib/components/widgets/FileWidget.d.ts +1 -1
- 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 +1 -1
- package/lib/components/widgets/HiddenWidget.d.ts.map +1 -1
- package/lib/components/widgets/PasswordWidget.d.ts +1 -1
- package/lib/components/widgets/PasswordWidget.d.ts.map +1 -1
- package/lib/components/widgets/RadioWidget.d.ts +1 -1
- package/lib/components/widgets/RadioWidget.d.ts.map +1 -1
- package/lib/components/widgets/RadioWidget.js +2 -2
- package/lib/components/widgets/RangeWidget.d.ts +1 -1
- package/lib/components/widgets/RangeWidget.d.ts.map +1 -1
- package/lib/components/widgets/RatingWidget.d.ts +1 -1
- package/lib/components/widgets/RatingWidget.d.ts.map +1 -1
- package/lib/components/widgets/RatingWidget.js +15 -15
- package/lib/components/widgets/SelectWidget.d.ts +1 -1
- package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
- package/lib/components/widgets/SelectWidget.js +4 -4
- package/lib/components/widgets/TextWidget.d.ts +1 -1
- package/lib/components/widgets/TextWidget.d.ts.map +1 -1
- package/lib/components/widgets/TextareaWidget.d.ts +1 -1
- package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
- package/lib/components/widgets/TextareaWidget.js +2 -2
- package/lib/components/widgets/TimeWidget.d.ts +1 -1
- package/lib/components/widgets/TimeWidget.d.ts.map +1 -1
- package/lib/components/widgets/URLWidget.d.ts +1 -1
- package/lib/components/widgets/URLWidget.d.ts.map +1 -1
- package/lib/components/widgets/UpDownWidget.d.ts +1 -1
- 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 +6 -7
- package/src/components/Form.tsx +164 -97
- 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/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 +29 -16
- package/src/components/fields/NullField.tsx +1 -1
- package/src/components/fields/NumberField.tsx +8 -10
- package/src/components/fields/ObjectField.tsx +48 -39
- package/src/components/fields/OptionalDataControlsField.tsx +6 -4
- package/src/components/fields/SchemaField.tsx +22 -19
- package/src/components/fields/StringField.tsx +4 -15
- package/src/components/fields/index.ts +1 -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 +15 -19
- 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/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 +3 -2
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +2 -9
- package/src/components/templates/index.ts +1 -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 +6 -8
- 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 +6 -8
- package/src/components/widgets/RangeWidget.tsx +1 -1
- package/src/components/widgets/RatingWidget.tsx +48 -47
- package/src/components/widgets/SelectWidget.tsx +12 -10
- package/src/components/widgets/TextWidget.tsx +2 -1
- package/src/components/widgets/TextareaWidget.tsx +7 -4
- 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/src/components/Form.tsx
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import type { ElementType, FormEvent, ReactNode, Ref, RefObject } from 'react';
|
|
2
|
+
import { Component, createRef } from 'react';
|
|
3
|
+
import type {
|
|
4
4
|
CustomValidator,
|
|
5
|
-
deepEquals,
|
|
6
5
|
ErrorSchema,
|
|
7
|
-
ErrorSchemaBuilder,
|
|
8
6
|
ErrorTransformer,
|
|
9
7
|
FieldPathId,
|
|
10
8
|
FieldPathList,
|
|
11
9
|
FormContextType,
|
|
12
|
-
getChangedFields,
|
|
13
|
-
getTemplate,
|
|
14
|
-
getUiOptions,
|
|
15
|
-
isObject,
|
|
16
|
-
mergeObjects,
|
|
17
10
|
PathSchema,
|
|
18
11
|
StrictRJSFSchema,
|
|
19
12
|
Registry,
|
|
@@ -22,26 +15,37 @@ import {
|
|
|
22
15
|
RJSFSchema,
|
|
23
16
|
RJSFValidationError,
|
|
24
17
|
SchemaUtilsType,
|
|
18
|
+
TemplatesType,
|
|
19
|
+
UiSchema,
|
|
20
|
+
ValidationData,
|
|
21
|
+
ValidatorType,
|
|
22
|
+
Experimental_DefaultFormStateBehavior,
|
|
23
|
+
Experimental_CustomMergeAllOf,
|
|
24
|
+
GlobalFormOptions,
|
|
25
|
+
NameGeneratorFunction,
|
|
26
|
+
} from '@rjsf/utils';
|
|
27
|
+
import {
|
|
28
|
+
createSchemaUtils,
|
|
29
|
+
deepEquals,
|
|
30
|
+
ErrorSchemaBuilder,
|
|
31
|
+
getChangedFields,
|
|
32
|
+
getTemplate,
|
|
33
|
+
getUiOptions,
|
|
34
|
+
hashObject,
|
|
35
|
+
isObject,
|
|
36
|
+
mergeObjects,
|
|
25
37
|
shouldRender,
|
|
26
38
|
SUBMIT_BTN_OPTIONS_KEY,
|
|
27
|
-
TemplatesType,
|
|
28
39
|
toErrorList,
|
|
29
40
|
toFieldPathId,
|
|
30
|
-
UiSchema,
|
|
31
41
|
UI_DEFINITIONS_KEY,
|
|
32
42
|
UI_GLOBAL_OPTIONS_KEY,
|
|
33
43
|
UI_OPTIONS_KEY,
|
|
34
|
-
ValidationData,
|
|
35
44
|
validationDataMerge,
|
|
36
|
-
ValidatorType,
|
|
37
|
-
Experimental_DefaultFormStateBehavior,
|
|
38
|
-
Experimental_CustomMergeAllOf,
|
|
39
45
|
DEFAULT_ID_SEPARATOR,
|
|
40
46
|
DEFAULT_ID_PREFIX,
|
|
41
|
-
GlobalFormOptions,
|
|
42
47
|
ERRORS_KEY,
|
|
43
48
|
ID_KEY,
|
|
44
|
-
NameGeneratorFunction,
|
|
45
49
|
getUsedFormData,
|
|
46
50
|
getFieldNames,
|
|
47
51
|
ANY_OF_KEY,
|
|
@@ -193,6 +197,7 @@ export interface FormProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
193
197
|
*
|
|
194
198
|
* NOTE: In a future major release, the `boolean` options for this flag will be removed
|
|
195
199
|
*/
|
|
200
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
196
201
|
liveValidate?: 'onChange' | 'onBlur' | DeprecatedBooleanOption;
|
|
197
202
|
/** Flag that describes when live omit will be performed. Live omit happens only when `omitExtraData` is also set to
|
|
198
203
|
* to `true` and the form's data is updated by the user.
|
|
@@ -204,6 +209,7 @@ export interface FormProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
204
209
|
*
|
|
205
210
|
* NOTE: In a future major release, the `boolean` options for this flag will be removed
|
|
206
211
|
*/
|
|
212
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
207
213
|
liveOmit?: 'onChange' | 'onBlur' | DeprecatedBooleanOption;
|
|
208
214
|
/** If set to true, then extra form data values that are not in any form field will be removed whenever `onSubmit` is
|
|
209
215
|
* called. Set to `false` by default.
|
|
@@ -315,7 +321,7 @@ export interface FormState<T = any, S extends StrictRJSFSchema = RJSFSchema, F e
|
|
|
315
321
|
/** The registry (re)computed only when props changed */
|
|
316
322
|
registry: Registry<T, S, F>;
|
|
317
323
|
/** Tracks the previous `extraErrors` prop reference so that `getDerivedStateFromProps` can detect changes */
|
|
318
|
-
|
|
324
|
+
prevExtraErrors?: ErrorSchema<T>;
|
|
319
325
|
}
|
|
320
326
|
|
|
321
327
|
/** The event data passed when changes have been made to the form, includes everything from the `FormState` except
|
|
@@ -380,7 +386,7 @@ export default class Form<
|
|
|
380
386
|
/** Flag to track when we're processing a user-initiated field change.
|
|
381
387
|
* This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
|
|
382
388
|
*/
|
|
383
|
-
private
|
|
389
|
+
private isProcessingUserChange = false;
|
|
384
390
|
|
|
385
391
|
/** When the `extraErrors` prop changes, re-merges `schemaValidationErrors` + `extraErrors` + `customErrors` into
|
|
386
392
|
* state before render, ensuring the updated errors are visible immediately in a single render cycle.
|
|
@@ -393,10 +399,10 @@ export default class Form<
|
|
|
393
399
|
props: FormProps<T, S, F>,
|
|
394
400
|
state: FormState<T, S, F>,
|
|
395
401
|
): Partial<FormState<T, S, F>> | null {
|
|
396
|
-
if (props.extraErrors !== state.
|
|
402
|
+
if (props.extraErrors !== state.prevExtraErrors) {
|
|
397
403
|
const baseErrors: ValidationData<T> = {
|
|
398
404
|
errors: state.schemaValidationErrors || [],
|
|
399
|
-
errorSchema:
|
|
405
|
+
errorSchema: state.schemaValidationErrorSchema || {},
|
|
400
406
|
};
|
|
401
407
|
let { errors, errorSchema } = baseErrors;
|
|
402
408
|
if (props.extraErrors) {
|
|
@@ -409,7 +415,7 @@ export default class Form<
|
|
|
409
415
|
true,
|
|
410
416
|
));
|
|
411
417
|
}
|
|
412
|
-
return {
|
|
418
|
+
return { prevExtraErrors: props.extraErrors, errors, errorSchema };
|
|
413
419
|
}
|
|
414
420
|
return null;
|
|
415
421
|
}
|
|
@@ -431,7 +437,7 @@ export default class Form<
|
|
|
431
437
|
const formData = propsFormData ?? initialFormData;
|
|
432
438
|
this.state = {
|
|
433
439
|
...this.getStateFromProps(props, formData, undefined, undefined, undefined, true),
|
|
434
|
-
|
|
440
|
+
prevExtraErrors: props.extraErrors,
|
|
435
441
|
};
|
|
436
442
|
if (onChange && !deepEquals(this.state.formData, formData)) {
|
|
437
443
|
onChange(toIChangeEvent(this.state));
|
|
@@ -515,8 +521,8 @@ export default class Form<
|
|
|
515
521
|
// Prevent oneOf/anyOf option switches from reverting when getStateFromProps
|
|
516
522
|
// re-evaluates and produces stale formData.
|
|
517
523
|
const nextStateDiffersFromProps = !deepEquals(nextState.formData, this.props.formData);
|
|
518
|
-
const wasProcessingUserChange = this.
|
|
519
|
-
this.
|
|
524
|
+
const wasProcessingUserChange = this.isProcessingUserChange;
|
|
525
|
+
this.isProcessingUserChange = false;
|
|
520
526
|
|
|
521
527
|
if (wasProcessingUserChange && nextStateDiffersFromProps) {
|
|
522
528
|
// Skip - the user's option switch is already applied via processPendingChange
|
|
@@ -526,6 +532,7 @@ export default class Form<
|
|
|
526
532
|
if (nextStateDiffersFromProps && !deepEquals(nextState.formData, prevState.formData) && this.props.onChange) {
|
|
527
533
|
this.props.onChange(toIChangeEvent(nextState));
|
|
528
534
|
}
|
|
535
|
+
// oxlint-disable-next-line react/no-did-update-set-state -- guarded to prevent infinite loop
|
|
529
536
|
this.setState(nextState);
|
|
530
537
|
}
|
|
531
538
|
}
|
|
@@ -537,9 +544,10 @@ export default class Form<
|
|
|
537
544
|
* @param props - The props passed to the `Form`
|
|
538
545
|
* @param inputFormData - The new or current data for the `Form`
|
|
539
546
|
* @param retrievedSchema - An expanded schema, if not provided, it will be retrieved from the `schema` and `formData`.
|
|
540
|
-
* @param isSchemaChanged - A flag indicating whether the schema has changed.
|
|
541
|
-
* @param formDataChangedFields - The changed fields of `formData`
|
|
542
|
-
* @param skipLiveValidate - Optional flag, if true, means that we are not running live validation
|
|
547
|
+
* @param [isSchemaChanged=false] - A flag indicating whether the schema has changed.
|
|
548
|
+
* @param [formDataChangedFields=[]] - The changed fields of `formData`
|
|
549
|
+
* @param [skipLiveValidate=false] - Optional flag, if true, means that we are not running live validation
|
|
550
|
+
* @param [shouldSanitize=false] - Optional flag, if true, means that we should attempt to sanitize formData
|
|
543
551
|
* @returns - The new state for the `Form`
|
|
544
552
|
*/
|
|
545
553
|
getStateFromProps(
|
|
@@ -549,6 +557,7 @@ export default class Form<
|
|
|
549
557
|
isSchemaChanged = false,
|
|
550
558
|
formDataChangedFields: string[] = [],
|
|
551
559
|
skipLiveValidate = false,
|
|
560
|
+
shouldSanitize = false,
|
|
552
561
|
): FormState<T, S, F> {
|
|
553
562
|
const state: FormState<T, S, F> = this.state || {};
|
|
554
563
|
const schema = 'schema' in props ? props.schema : this.props.schema;
|
|
@@ -557,6 +566,7 @@ export default class Form<
|
|
|
557
566
|
const isUncontrolled = props.formData === undefined && this.props.formData === undefined;
|
|
558
567
|
const edit = typeof inputFormData !== 'undefined';
|
|
559
568
|
const liveValidate = 'liveValidate' in props ? props.liveValidate : this.props.liveValidate;
|
|
569
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
560
570
|
const mustValidate = edit && !props.noValidate && liveValidate;
|
|
561
571
|
const experimental_defaultFormStateBehavior =
|
|
562
572
|
'experimental_defaultFormStateBehavior' in props
|
|
@@ -566,7 +576,7 @@ export default class Form<
|
|
|
566
576
|
'experimental_customMergeAllOf' in props
|
|
567
577
|
? props.experimental_customMergeAllOf
|
|
568
578
|
: this.props.experimental_customMergeAllOf;
|
|
569
|
-
let schemaUtils
|
|
579
|
+
let { schemaUtils } = state;
|
|
570
580
|
if (
|
|
571
581
|
!schemaUtils ||
|
|
572
582
|
schemaUtils.doesSchemaUtilsDiffer(
|
|
@@ -593,21 +603,57 @@ export default class Form<
|
|
|
593
603
|
} else if (inputFormData === undefined && isUncontrolled) {
|
|
594
604
|
defaultsFormData = state.formData;
|
|
595
605
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
606
|
+
let formData: T;
|
|
607
|
+
let computedRetrievedSchema: S;
|
|
608
|
+
let wasSanitized = false;
|
|
609
|
+
const preventInfiniteSanitize: string[] = [];
|
|
610
|
+
do {
|
|
611
|
+
formData = schemaUtils.getDefaultFormState(
|
|
612
|
+
rootSchema,
|
|
613
|
+
defaultsFormData,
|
|
614
|
+
false,
|
|
615
|
+
state.initialDefaultsGenerated,
|
|
616
|
+
) as T;
|
|
617
|
+
// Only hash when sanitizing, wrapping `formData` in an object to deal with a scalar/undefined value
|
|
618
|
+
const formHash = shouldSanitize ? hashObject({ formData }) : '';
|
|
619
|
+
computedRetrievedSchema = this.updateRetrievedSchema(
|
|
620
|
+
retrievedSchema ?? schemaUtils.retrieveSchema(rootSchema, formData),
|
|
621
|
+
);
|
|
622
|
+
if (
|
|
623
|
+
shouldSanitize &&
|
|
624
|
+
!preventInfiniteSanitize.includes(formHash) &&
|
|
625
|
+
!deepEquals(computedRetrievedSchema, state.retrievedSchema)
|
|
626
|
+
) {
|
|
627
|
+
// Sanitize the form data if shouldSanitize is true, we haven't already processed this same formData AND
|
|
628
|
+
// we have a different retrieved schema from when we last ran the state
|
|
629
|
+
const sanitizedFormData = schemaUtils.sanitizeDataForNewSchema(
|
|
630
|
+
computedRetrievedSchema,
|
|
631
|
+
state.retrievedSchema,
|
|
632
|
+
formData,
|
|
633
|
+
);
|
|
634
|
+
wasSanitized = !deepEquals(sanitizedFormData, formData);
|
|
635
|
+
if (wasSanitized) {
|
|
636
|
+
// Update both the formData AND defaultsFormData due to the sanitize so the loop works with the new data
|
|
637
|
+
formData = sanitizedFormData;
|
|
638
|
+
defaultsFormData = sanitizedFormData;
|
|
639
|
+
const sanitizedFormHash = hashObject({ formData: sanitizedFormData });
|
|
640
|
+
// If we've seen the sanitized data before, we are done
|
|
641
|
+
wasSanitized = !preventInfiniteSanitize.includes(sanitizedFormHash);
|
|
642
|
+
preventInfiniteSanitize.push(sanitizedFormHash);
|
|
643
|
+
}
|
|
644
|
+
preventInfiniteSanitize.push(formHash);
|
|
645
|
+
} else {
|
|
646
|
+
wasSanitized = false;
|
|
647
|
+
}
|
|
648
|
+
} while (wasSanitized);
|
|
605
649
|
|
|
606
650
|
const getCurrentErrors = (): ValidationData<T> => {
|
|
607
651
|
// If the `props.noValidate` option is set or the schema has changed, we reset the error state.
|
|
652
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
608
653
|
if (props.noValidate || isSchemaChanged) {
|
|
609
654
|
return { errors: [], errorSchema: {} };
|
|
610
|
-
}
|
|
655
|
+
}
|
|
656
|
+
if (!props.liveValidate) {
|
|
611
657
|
return {
|
|
612
658
|
errors: state.schemaValidationErrors || [],
|
|
613
659
|
errorSchema: state.schemaValidationErrorSchema || {},
|
|
@@ -621,8 +667,7 @@ export default class Form<
|
|
|
621
667
|
|
|
622
668
|
let errors: RJSFValidationError[];
|
|
623
669
|
let errorSchema: ErrorSchema<T> | undefined;
|
|
624
|
-
let schemaValidationErrors
|
|
625
|
-
let schemaValidationErrorSchema: ErrorSchema<T> = state.schemaValidationErrorSchema;
|
|
670
|
+
let { schemaValidationErrors, schemaValidationErrorSchema } = state;
|
|
626
671
|
// If we are skipping live validate, it means that the state has already been updated with live validation errors
|
|
627
672
|
if (mustValidate && !skipLiveValidate) {
|
|
628
673
|
const liveValidation = this.liveValidate(
|
|
@@ -647,26 +692,24 @@ export default class Form<
|
|
|
647
692
|
errorSchema = currentErrors.errorSchema;
|
|
648
693
|
// We only update the error schema for changed fields if mustValidate is false
|
|
649
694
|
if (formDataChangedFields.length > 0 && !mustValidate) {
|
|
650
|
-
const newErrorSchema = formDataChangedFields.reduce(
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
{} as Record<string, undefined>,
|
|
656
|
-
);
|
|
657
|
-
errorSchema = schemaValidationErrorSchema = mergeObjects(
|
|
695
|
+
const newErrorSchema = formDataChangedFields.reduce<Record<string, undefined>>((acc, key) => {
|
|
696
|
+
acc[key] = undefined;
|
|
697
|
+
return acc;
|
|
698
|
+
}, {});
|
|
699
|
+
schemaValidationErrorSchema = mergeObjects(
|
|
658
700
|
currentErrors.errorSchema,
|
|
659
701
|
newErrorSchema,
|
|
660
702
|
'preventDuplicates',
|
|
661
703
|
) as ErrorSchema<T>;
|
|
704
|
+
errorSchema = schemaValidationErrorSchema;
|
|
662
705
|
}
|
|
663
|
-
const mergedErrors =
|
|
706
|
+
const mergedErrors = Form.mergeErrors<T>({ errorSchema, errors }, props.extraErrors, state.customErrors);
|
|
664
707
|
errors = mergedErrors.errors;
|
|
665
708
|
errorSchema = mergedErrors.errorSchema;
|
|
666
709
|
}
|
|
667
710
|
|
|
668
711
|
// Only store a new registry when the props cause a different one to be created
|
|
669
|
-
const newRegistry =
|
|
712
|
+
const newRegistry = Form.getRegistry(props, rootSchema, schemaUtils);
|
|
670
713
|
const registry = deepEquals(state.registry, newRegistry) ? state.registry : newRegistry;
|
|
671
714
|
|
|
672
715
|
// Only compute a new `fieldPathId` when the `idPrefix` is different than the existing fieldPathId's ID_KEY
|
|
@@ -685,7 +728,7 @@ export default class Form<
|
|
|
685
728
|
errorSchema,
|
|
686
729
|
schemaValidationErrors,
|
|
687
730
|
schemaValidationErrorSchema,
|
|
688
|
-
retrievedSchema:
|
|
731
|
+
retrievedSchema: computedRetrievedSchema,
|
|
689
732
|
initialDefaultsGenerated: true,
|
|
690
733
|
registry,
|
|
691
734
|
};
|
|
@@ -717,12 +760,14 @@ export default class Form<
|
|
|
717
760
|
altSchemaUtils?: SchemaUtilsType<T, S, F>,
|
|
718
761
|
retrievedSchema?: S,
|
|
719
762
|
): ValidationData<T> {
|
|
720
|
-
const schemaUtils = altSchemaUtils
|
|
763
|
+
const schemaUtils = altSchemaUtils || this.state.schemaUtils;
|
|
721
764
|
const { customValidate, transformErrors, uiSchema } = this.props;
|
|
722
|
-
|
|
765
|
+
// When a pre-resolved schema is provided (e.g., from live validation), use it directly.
|
|
766
|
+
// Otherwise validate against the original schema so AJV sees the full constraint set.
|
|
767
|
+
const validationSchema = retrievedSchema ?? schema;
|
|
723
768
|
return schemaUtils
|
|
724
769
|
.getValidator()
|
|
725
|
-
.validateFormData(formData,
|
|
770
|
+
.validateFormData(formData, validationSchema, customValidate, transformErrors, uiSchema);
|
|
726
771
|
}
|
|
727
772
|
|
|
728
773
|
/** Renders any errors contained in the `state` in using the `ErrorList`, if not disabled by `showErrorList`. */
|
|
@@ -753,13 +798,12 @@ export default class Form<
|
|
|
753
798
|
* @return - The `extraErrors` and `customErrors` merged into the `schemaValidation`
|
|
754
799
|
* @private
|
|
755
800
|
*/
|
|
756
|
-
private mergeErrors(
|
|
801
|
+
private static mergeErrors<T = any>(
|
|
757
802
|
schemaValidation: ValidationData<T>,
|
|
758
803
|
extraErrors?: FormProps['extraErrors'],
|
|
759
804
|
customErrors?: ErrorSchemaBuilder,
|
|
760
805
|
): ValidationData<T> {
|
|
761
|
-
let errorSchema
|
|
762
|
-
let errors: RJSFValidationError[] = schemaValidation.errors;
|
|
806
|
+
let { errorSchema, errors } = schemaValidation;
|
|
763
807
|
if (extraErrors) {
|
|
764
808
|
const merged = validationDataMerge(schemaValidation, extraErrors);
|
|
765
809
|
errorSchema = merged.errorSchema;
|
|
@@ -798,8 +842,8 @@ export default class Form<
|
|
|
798
842
|
mergeIntoOriginalErrorSchema = false,
|
|
799
843
|
) {
|
|
800
844
|
const schemaValidation = this.validate(formData, rootSchema, schemaUtils, retrievedSchema);
|
|
801
|
-
const errors = schemaValidation
|
|
802
|
-
let errorSchema = schemaValidation
|
|
845
|
+
const { errors } = schemaValidation;
|
|
846
|
+
let { errorSchema } = schemaValidation;
|
|
803
847
|
// We merge 'originalErrorSchema' with 'schemaValidation.errorSchema.'; This done to display the raised field error.
|
|
804
848
|
if (mergeIntoOriginalErrorSchema) {
|
|
805
849
|
errorSchema = mergeObjects(
|
|
@@ -810,7 +854,7 @@ export default class Form<
|
|
|
810
854
|
}
|
|
811
855
|
const schemaValidationErrors = errors;
|
|
812
856
|
const schemaValidationErrorSchema = errorSchema;
|
|
813
|
-
const mergedErrors =
|
|
857
|
+
const mergedErrors = Form.mergeErrors<T>({ errorSchema, errors }, extraErrors, customErrors);
|
|
814
858
|
return { ...mergedErrors, schemaValidationErrors, schemaValidationErrorSchema };
|
|
815
859
|
}
|
|
816
860
|
|
|
@@ -820,9 +864,8 @@ export default class Form<
|
|
|
820
864
|
* @param fields - The fields to keep while filtering
|
|
821
865
|
* @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
|
|
822
866
|
*/
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
};
|
|
867
|
+
// oxlint-disable-next-line class-methods-use-this, typescript/no-deprecated
|
|
868
|
+
getUsedFormData = (formData: T | undefined, fields: string[]): T | undefined => getUsedFormData(formData, fields);
|
|
826
869
|
|
|
827
870
|
/** Returns the list of field names from inspecting the `pathSchema` as well as using the `formData`
|
|
828
871
|
*
|
|
@@ -830,9 +873,8 @@ export default class Form<
|
|
|
830
873
|
* @param [formData] - The form data to use while checking for empty objects/arrays
|
|
831
874
|
* @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
|
|
832
875
|
*/
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
};
|
|
876
|
+
// oxlint-disable-next-line class-methods-use-this, typescript/no-deprecated
|
|
877
|
+
getFieldNames = (pathSchema: PathSchema<T>, formData?: T): string[][] => getFieldNames(pathSchema, formData);
|
|
836
878
|
|
|
837
879
|
/** Returns the `formData` after filtering to remove any extra data not in a form field
|
|
838
880
|
*
|
|
@@ -890,20 +932,20 @@ export default class Form<
|
|
|
890
932
|
}
|
|
891
933
|
// Mark that we're processing a user-initiated change.
|
|
892
934
|
// This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
|
|
893
|
-
this.
|
|
935
|
+
this.isProcessingUserChange = true;
|
|
894
936
|
const { newValue, path, id } = this.pendingChanges[0];
|
|
895
937
|
const { newErrorSchema } = this.pendingChanges[0];
|
|
896
|
-
|
|
938
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
939
|
+
const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange, disabled, readonly } = this.props;
|
|
897
940
|
const { formData: oldFormData, schemaUtils, schema, fieldPathId, schemaValidationErrorSchema, errors } = this.state;
|
|
898
|
-
let { customErrors } = this.state;
|
|
941
|
+
let { customErrors, retrievedSchema } = this.state;
|
|
899
942
|
// Use the un-merged AJV-only schema as the base for re-merging extraErrors. Mirrors the
|
|
900
943
|
// pattern in getStateFromProps/getDerivedStateFromProps and avoids the duplication that
|
|
901
944
|
// happened when state.errorSchema (already containing merged extraErrors) was passed in.
|
|
902
|
-
let mergeBaseErrorSchema: ErrorSchema<T> = schemaValidationErrorSchema
|
|
945
|
+
let mergeBaseErrorSchema: ErrorSchema<T> = schemaValidationErrorSchema;
|
|
903
946
|
const rootPathId = fieldPathId.path[0] || '';
|
|
904
947
|
|
|
905
948
|
const isRootPath = !path || path.length === 0 || (path.length === 1 && path[0] === rootPathId);
|
|
906
|
-
let retrievedSchema = this.state.retrievedSchema;
|
|
907
949
|
let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
|
|
908
950
|
|
|
909
951
|
// When switching from null to an object option in oneOf, MultiSchemaField sends
|
|
@@ -951,21 +993,30 @@ export default class Form<
|
|
|
951
993
|
_set(formData, path, valueForPath);
|
|
952
994
|
}
|
|
953
995
|
}
|
|
996
|
+
const shouldSanitize =
|
|
997
|
+
retrievedSchema && !isRootPath && !isObject(newValue) && !Array.isArray(newValue) && !disabled && !readonly;
|
|
954
998
|
// Pass true to skip live validation in `getStateFromProps()` since we will do it a bit later
|
|
955
|
-
const newState = this.getStateFromProps(
|
|
999
|
+
const newState = this.getStateFromProps(
|
|
1000
|
+
this.props,
|
|
1001
|
+
inputForDefaults,
|
|
1002
|
+
undefined,
|
|
1003
|
+
undefined,
|
|
1004
|
+
undefined,
|
|
1005
|
+
true,
|
|
1006
|
+
shouldSanitize,
|
|
1007
|
+
);
|
|
956
1008
|
formData = newState.formData;
|
|
957
1009
|
retrievedSchema = newState.retrievedSchema;
|
|
958
1010
|
}
|
|
959
1011
|
|
|
960
1012
|
const mustValidate = !noValidate && (liveValidate === true || liveValidate === 'onChange');
|
|
961
|
-
let state: Partial<FormState<T, S, F>> = { formData,
|
|
1013
|
+
let state: Partial<FormState<T, S, F>> = { formData, retrievedSchema };
|
|
962
1014
|
let newFormData = formData;
|
|
963
1015
|
|
|
964
1016
|
if (omitExtraData === true && (liveOmit === true || liveOmit === 'onChange')) {
|
|
1017
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
965
1018
|
newFormData = this.omitExtraData(formData);
|
|
966
|
-
state = {
|
|
967
|
-
formData: newFormData,
|
|
968
|
-
};
|
|
1019
|
+
state = { ...state, formData: newFormData };
|
|
969
1020
|
}
|
|
970
1021
|
|
|
971
1022
|
if (newErrorSchema) {
|
|
@@ -977,20 +1028,20 @@ export default class Form<
|
|
|
977
1028
|
// Apply the user-supplied newErrorSchema onto a clone of the AJV-only base, so that
|
|
978
1029
|
// mergeErrors below sees the user's error at this path without mutating shared state.
|
|
979
1030
|
if (!isRootPath) {
|
|
980
|
-
mergeBaseErrorSchema = _cloneDeep(schemaValidationErrorSchema)
|
|
1031
|
+
mergeBaseErrorSchema = _cloneDeep(schemaValidationErrorSchema);
|
|
981
1032
|
_set(mergeBaseErrorSchema, path, newErrorSchema);
|
|
982
1033
|
} else {
|
|
983
|
-
mergeBaseErrorSchema = newErrorSchema
|
|
1034
|
+
mergeBaseErrorSchema = newErrorSchema;
|
|
984
1035
|
}
|
|
985
1036
|
} else {
|
|
986
1037
|
if (!customErrors) {
|
|
987
1038
|
customErrors = new ErrorSchemaBuilder<T>();
|
|
988
1039
|
}
|
|
989
1040
|
if (isRootPath) {
|
|
990
|
-
const
|
|
991
|
-
if (
|
|
1041
|
+
const pathErrors = _get(newErrorSchema, ERRORS_KEY);
|
|
1042
|
+
if (pathErrors) {
|
|
992
1043
|
// only set errors when there are some
|
|
993
|
-
customErrors.setErrors(
|
|
1044
|
+
customErrors.setErrors(pathErrors);
|
|
994
1045
|
}
|
|
995
1046
|
} else {
|
|
996
1047
|
_set(customErrors.ErrorSchema, path, newErrorSchema);
|
|
@@ -1011,16 +1062,17 @@ export default class Form<
|
|
|
1011
1062
|
customErrors,
|
|
1012
1063
|
retrievedSchema,
|
|
1013
1064
|
);
|
|
1014
|
-
state = { formData: newFormData, ...liveValidation, customErrors };
|
|
1065
|
+
state = { ...state, formData: newFormData, ...liveValidation, customErrors };
|
|
1015
1066
|
} else if (!noValidate && newErrorSchema) {
|
|
1016
1067
|
// Merging 'newErrorSchema' into 'errorSchema' to display the custom raised errors.
|
|
1017
|
-
const mergedErrors =
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
...mergedErrors,
|
|
1068
|
+
const mergedErrors = Form.mergeErrors<T>(
|
|
1069
|
+
{ errorSchema: mergeBaseErrorSchema, errors },
|
|
1070
|
+
extraErrors,
|
|
1021
1071
|
customErrors,
|
|
1022
|
-
|
|
1072
|
+
);
|
|
1073
|
+
state = { ...state, formData: newFormData, ...mergedErrors, customErrors };
|
|
1023
1074
|
}
|
|
1075
|
+
|
|
1024
1076
|
this.setState(state as FormState<T, S, F>, () => {
|
|
1025
1077
|
if (onChange) {
|
|
1026
1078
|
onChange(toIChangeEvent({ ...this.state, ...state }), id);
|
|
@@ -1094,6 +1146,7 @@ export default class Form<
|
|
|
1094
1146
|
let newFormData: T | undefined = formData;
|
|
1095
1147
|
let state: Partial<FormState<T, S, F>> = { formData: newFormData };
|
|
1096
1148
|
if (omitExtraData === true && liveOmit === 'onBlur') {
|
|
1149
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
1097
1150
|
newFormData = this.omitExtraData(formData);
|
|
1098
1151
|
state = { formData: newFormData };
|
|
1099
1152
|
}
|
|
@@ -1154,10 +1207,12 @@ export default class Form<
|
|
|
1154
1207
|
}
|
|
1155
1208
|
|
|
1156
1209
|
event.persist();
|
|
1210
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
1157
1211
|
const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
|
|
1158
1212
|
let { formData: newFormData } = this.state;
|
|
1159
1213
|
|
|
1160
1214
|
if (omitExtraData === true) {
|
|
1215
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
1161
1216
|
newFormData = this.omitExtraData(newFormData);
|
|
1162
1217
|
}
|
|
1163
1218
|
|
|
@@ -1189,7 +1244,11 @@ export default class Form<
|
|
|
1189
1244
|
* @returns - The `GlobalFormOptions` from the props
|
|
1190
1245
|
* @private
|
|
1191
1246
|
*/
|
|
1192
|
-
private getGlobalFormOptions
|
|
1247
|
+
private static getGlobalFormOptions<
|
|
1248
|
+
T = any,
|
|
1249
|
+
S extends StrictRJSFSchema = RJSFSchema,
|
|
1250
|
+
F extends FormContextType = any,
|
|
1251
|
+
>(props: FormProps<T, S, F>): GlobalFormOptions {
|
|
1193
1252
|
const {
|
|
1194
1253
|
uiSchema = {},
|
|
1195
1254
|
experimental_componentUpdateStrategy,
|
|
@@ -1198,6 +1257,7 @@ export default class Form<
|
|
|
1198
1257
|
nameGenerator,
|
|
1199
1258
|
useFallbackUiForUnsupportedType = false,
|
|
1200
1259
|
} = props;
|
|
1260
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
1201
1261
|
const rootFieldId = uiSchema['ui:rootFieldId'];
|
|
1202
1262
|
// Omit any options that are undefined or null
|
|
1203
1263
|
return {
|
|
@@ -1210,7 +1270,11 @@ export default class Form<
|
|
|
1210
1270
|
}
|
|
1211
1271
|
|
|
1212
1272
|
/** Computed the registry for the form using the given `props`, `schema` and `schemaUtils` */
|
|
1213
|
-
getRegistry
|
|
1273
|
+
static getRegistry<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
1274
|
+
props: FormProps<T, S, F>,
|
|
1275
|
+
schema: S,
|
|
1276
|
+
schemaUtils: SchemaUtilsType<T, S, F>,
|
|
1277
|
+
): Registry<T, S, F> {
|
|
1214
1278
|
const { translateString: customTranslateString, uiSchema = {} } = props;
|
|
1215
1279
|
const { fields, templates, widgets, formContext, translateString } = getDefaultRegistry<T, S, F>();
|
|
1216
1280
|
return {
|
|
@@ -1229,7 +1293,7 @@ export default class Form<
|
|
|
1229
1293
|
schemaUtils,
|
|
1230
1294
|
translateString: customTranslateString || translateString,
|
|
1231
1295
|
globalUiOptions: uiSchema[UI_GLOBAL_OPTIONS_KEY],
|
|
1232
|
-
globalFormOptions:
|
|
1296
|
+
globalFormOptions: Form.getGlobalFormOptions(props),
|
|
1233
1297
|
uiSchemaDefinitions: uiSchema[UI_DEFINITIONS_KEY] ?? {},
|
|
1234
1298
|
};
|
|
1235
1299
|
}
|
|
@@ -1273,6 +1337,7 @@ export default class Form<
|
|
|
1273
1337
|
}
|
|
1274
1338
|
if (field && field.length) {
|
|
1275
1339
|
// If we got a list with length > 0
|
|
1340
|
+
// oxlint-disable-next-line prefer-destructuring
|
|
1276
1341
|
field = field[0];
|
|
1277
1342
|
}
|
|
1278
1343
|
if (field) {
|
|
@@ -1291,7 +1356,7 @@ export default class Form<
|
|
|
1291
1356
|
const { errors: prevErrors } = this.state;
|
|
1292
1357
|
const schemaValidation = this.validate(formData);
|
|
1293
1358
|
// Always merge extraErrors so they remain visible in state regardless of extraErrorsBlockSubmit.
|
|
1294
|
-
const { errors, errorSchema } = extraErrors ?
|
|
1359
|
+
const { errors, errorSchema } = extraErrors ? Form.mergeErrors<T>(schemaValidation, extraErrors) : schemaValidation;
|
|
1295
1360
|
// hasError gates submission: schema errors always block; extraErrors only block when
|
|
1296
1361
|
// extraErrorsBlockSubmit is set (non-breaking default: extraErrors are informational only).
|
|
1297
1362
|
const hasError = schemaValidation.errors.length > 0 || (extraErrors && extraErrorsBlockSubmit);
|
|
@@ -1314,6 +1379,7 @@ export default class Form<
|
|
|
1314
1379
|
if (onError) {
|
|
1315
1380
|
onError(errors);
|
|
1316
1381
|
} else {
|
|
1382
|
+
// oxlint-disable-next-line no-console
|
|
1317
1383
|
console.error('Form validation failed', errors);
|
|
1318
1384
|
}
|
|
1319
1385
|
},
|
|
@@ -1347,6 +1413,7 @@ export default class Form<
|
|
|
1347
1413
|
const { omitExtraData } = this.props;
|
|
1348
1414
|
let { formData: newFormData } = this.state;
|
|
1349
1415
|
if (omitExtraData === true) {
|
|
1416
|
+
// oxlint-disable-next-line typescript/no-deprecated
|
|
1350
1417
|
newFormData = this.omitExtraData(newFormData);
|
|
1351
1418
|
}
|
|
1352
1419
|
return this.validateFormWithFormData(newFormData);
|
|
@@ -1376,7 +1443,7 @@ export default class Form<
|
|
|
1376
1443
|
} = this.props;
|
|
1377
1444
|
|
|
1378
1445
|
const { schema, uiSchema, formData, errorSchema, fieldPathId, registry } = this.state;
|
|
1379
|
-
const { SchemaField:
|
|
1446
|
+
const { SchemaField: SchemaFieldComponent } = registry.fields;
|
|
1380
1447
|
const { SubmitButton } = registry.templates.ButtonTemplates;
|
|
1381
1448
|
// The `semantic-ui` and `material-ui` themes have `_internalFormWrapper`s that take an `as` prop that is the
|
|
1382
1449
|
// PropTypes.elementType to use for the inner tag, so we'll need to pass `tagName` along if it is provided.
|
|
@@ -1392,7 +1459,7 @@ export default class Form<
|
|
|
1392
1459
|
|
|
1393
1460
|
return (
|
|
1394
1461
|
<FormTag
|
|
1395
|
-
className={className
|
|
1462
|
+
className={className || 'rjsf'}
|
|
1396
1463
|
id={id}
|
|
1397
1464
|
name={name}
|
|
1398
1465
|
method={method}
|
|
@@ -1407,7 +1474,7 @@ export default class Form<
|
|
|
1407
1474
|
ref={this.formElement}
|
|
1408
1475
|
>
|
|
1409
1476
|
{showErrorList === 'top' && this.renderErrors(registry)}
|
|
1410
|
-
<
|
|
1477
|
+
<SchemaFieldComponent
|
|
1411
1478
|
name=''
|
|
1412
1479
|
schema={schema}
|
|
1413
1480
|
uiSchema={uiSchema}
|
|
@@ -1422,7 +1489,7 @@ export default class Form<
|
|
|
1422
1489
|
readonly={readonly}
|
|
1423
1490
|
/>
|
|
1424
1491
|
|
|
1425
|
-
{children
|
|
1492
|
+
{children || <SubmitButton uiSchema={submitUiSchema} registry={registry} />}
|
|
1426
1493
|
{showErrorList === 'bottom' && this.renderErrors(registry)}
|
|
1427
1494
|
</FormTag>
|
|
1428
1495
|
);
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Registry,
|
|
5
|
-
RJSFSchema,
|
|
6
|
-
StrictRJSFSchema,
|
|
7
|
-
UiSchema,
|
|
8
|
-
getTestIds,
|
|
9
|
-
getUiOptions,
|
|
10
|
-
} from '@rjsf/utils';
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
3
|
+
import { getTestIds, getUiOptions } from '@rjsf/utils';
|
|
11
4
|
import { Markdown } from 'markdown-to-jsx/react';
|
|
12
5
|
|
|
13
6
|
const TEST_IDS = getTestIds();
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Registry,
|
|
5
|
-
RJSFSchema,
|
|
6
|
-
StrictRJSFSchema,
|
|
7
|
-
UiSchema,
|
|
8
|
-
getTestIds,
|
|
9
|
-
getUiOptions,
|
|
10
|
-
} from '@rjsf/utils';
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
|
|
3
|
+
import { getTestIds, getUiOptions } from '@rjsf/utils';
|
|
11
4
|
import { Markdown } from 'markdown-to-jsx/react';
|
|
12
5
|
|
|
13
6
|
const TEST_IDS = getTestIds();
|