@rjsf/core 6.3.1 → 6.4.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/dist/core.umd.js CHANGED
@@ -82,7 +82,8 @@
82
82
  } = props;
83
83
  const { widgets: widgets2, schemaUtils, globalFormOptions, globalUiOptions } = registry;
84
84
  const itemsSchema = schemaUtils.retrieveSchema(schema.items, items);
85
- const enumOptions = utils.optionsList(itemsSchema, uiSchema);
85
+ const itemsUiSchema = uiSchema?.items ?? {};
86
+ const enumOptions = utils.optionsList(itemsSchema, itemsUiSchema);
86
87
  const { widget = "select", title: uiTitle, ...options } = utils.getUiOptions(uiSchema, globalUiOptions);
87
88
  const Widget = utils.getWidget(schema, widget, widgets2);
88
89
  const label = uiTitle ?? schema.title ?? name;
@@ -3771,6 +3772,34 @@
3771
3772
  * This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
3772
3773
  */
3773
3774
  _isProcessingUserChange = false;
3775
+ /** When the `extraErrors` prop changes, re-merges `schemaValidationErrors` + `extraErrors` + `customErrors` into
3776
+ * state before render, ensuring the updated errors are visible immediately in a single render cycle.
3777
+ *
3778
+ * @param props - The current props
3779
+ * @param state - The current state
3780
+ * @returns Partial state with re-merged errors if `extraErrors` changed, or `null` if no update is needed
3781
+ */
3782
+ static getDerivedStateFromProps(props, state) {
3783
+ if (props.extraErrors !== state._prevExtraErrors) {
3784
+ const baseErrors = {
3785
+ errors: state.schemaValidationErrors || [],
3786
+ errorSchema: state.schemaValidationErrorSchema || {}
3787
+ };
3788
+ let { errors, errorSchema } = baseErrors;
3789
+ if (props.extraErrors) {
3790
+ ({ errors, errorSchema } = utils.validationDataMerge(baseErrors, props.extraErrors));
3791
+ }
3792
+ if (state.customErrors) {
3793
+ ({ errors, errorSchema } = utils.validationDataMerge(
3794
+ { errors, errorSchema },
3795
+ state.customErrors.ErrorSchema,
3796
+ true
3797
+ ));
3798
+ }
3799
+ return { _prevExtraErrors: props.extraErrors, errors, errorSchema };
3800
+ }
3801
+ return null;
3802
+ }
3774
3803
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
3775
3804
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
3776
3805
  * state construction.
@@ -3784,7 +3813,10 @@
3784
3813
  }
3785
3814
  const { formData: propsFormData, initialFormData, onChange } = props;
3786
3815
  const formData = propsFormData ?? initialFormData;
3787
- this.state = this.getStateFromProps(props, formData, void 0, void 0, void 0, true);
3816
+ this.state = {
3817
+ ...this.getStateFromProps(props, formData, void 0, void 0, void 0, true),
3818
+ _prevExtraErrors: props.extraErrors
3819
+ };
3788
3820
  if (onChange && !utils.deepEquals(this.state.formData, formData)) {
3789
3821
  onChange(toIChangeEvent(this.state));
3790
3822
  }
@@ -4471,17 +4503,9 @@
4471
4503
  const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
4472
4504
  const { errors: prevErrors } = this.state;
4473
4505
  const schemaValidation = this.validate(formData);
4474
- let errors = schemaValidation.errors;
4475
- let errorSchema = schemaValidation.errorSchema;
4476
- const schemaValidationErrors = errors;
4477
- const schemaValidationErrorSchema = errorSchema;
4478
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
4506
+ const { errors, errorSchema } = extraErrors ? this.mergeErrors(schemaValidation, extraErrors) : schemaValidation;
4507
+ const hasError = schemaValidation.errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
4479
4508
  if (hasError) {
4480
- if (extraErrors) {
4481
- const merged = utils.validationDataMerge(schemaValidation, extraErrors);
4482
- errorSchema = merged.errorSchema;
4483
- errors = merged.errors;
4484
- }
4485
4509
  if (focusOnFirstError) {
4486
4510
  if (typeof focusOnFirstError === "function") {
4487
4511
  focusOnFirstError(errors[0]);
@@ -4493,8 +4517,8 @@
4493
4517
  {
4494
4518
  errors,
4495
4519
  errorSchema,
4496
- schemaValidationErrors,
4497
- schemaValidationErrorSchema
4520
+ schemaValidationErrors: schemaValidation.errors,
4521
+ schemaValidationErrorSchema: schemaValidation.errorSchema
4498
4522
  },
4499
4523
  () => {
4500
4524
  if (onError) {
@@ -4504,6 +4528,13 @@
4504
4528
  }
4505
4529
  }
4506
4530
  );
4531
+ } else if (errors.length > 0) {
4532
+ this.setState({
4533
+ errors,
4534
+ errorSchema,
4535
+ schemaValidationErrors: [],
4536
+ schemaValidationErrorSchema: {}
4537
+ });
4507
4538
  } else if (prevErrors.length > 0) {
4508
4539
  this.setState({
4509
4540
  errors: [],
package/dist/index.cjs CHANGED
@@ -139,7 +139,8 @@ function ArrayAsMultiSelect(props) {
139
139
  } = props;
140
140
  const { widgets: widgets2, schemaUtils, globalFormOptions, globalUiOptions } = registry;
141
141
  const itemsSchema = schemaUtils.retrieveSchema(schema.items, items);
142
- const enumOptions = (0, import_utils.optionsList)(itemsSchema, uiSchema);
142
+ const itemsUiSchema = uiSchema?.items ?? {};
143
+ const enumOptions = (0, import_utils.optionsList)(itemsSchema, itemsUiSchema);
143
144
  const { widget = "select", title: uiTitle, ...options } = (0, import_utils.getUiOptions)(uiSchema, globalUiOptions);
144
145
  const Widget = (0, import_utils.getWidget)(schema, widget, widgets2);
145
146
  const label = uiTitle ?? schema.title ?? name;
@@ -4117,6 +4118,34 @@ var Form = class extends import_react21.Component {
4117
4118
  * This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
4118
4119
  */
4119
4120
  _isProcessingUserChange = false;
4121
+ /** When the `extraErrors` prop changes, re-merges `schemaValidationErrors` + `extraErrors` + `customErrors` into
4122
+ * state before render, ensuring the updated errors are visible immediately in a single render cycle.
4123
+ *
4124
+ * @param props - The current props
4125
+ * @param state - The current state
4126
+ * @returns Partial state with re-merged errors if `extraErrors` changed, or `null` if no update is needed
4127
+ */
4128
+ static getDerivedStateFromProps(props, state) {
4129
+ if (props.extraErrors !== state._prevExtraErrors) {
4130
+ const baseErrors = {
4131
+ errors: state.schemaValidationErrors || [],
4132
+ errorSchema: state.schemaValidationErrorSchema || {}
4133
+ };
4134
+ let { errors, errorSchema } = baseErrors;
4135
+ if (props.extraErrors) {
4136
+ ({ errors, errorSchema } = (0, import_utils50.validationDataMerge)(baseErrors, props.extraErrors));
4137
+ }
4138
+ if (state.customErrors) {
4139
+ ({ errors, errorSchema } = (0, import_utils50.validationDataMerge)(
4140
+ { errors, errorSchema },
4141
+ state.customErrors.ErrorSchema,
4142
+ true
4143
+ ));
4144
+ }
4145
+ return { _prevExtraErrors: props.extraErrors, errors, errorSchema };
4146
+ }
4147
+ return null;
4148
+ }
4120
4149
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
4121
4150
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
4122
4151
  * state construction.
@@ -4130,7 +4159,10 @@ var Form = class extends import_react21.Component {
4130
4159
  }
4131
4160
  const { formData: propsFormData, initialFormData, onChange } = props;
4132
4161
  const formData = propsFormData ?? initialFormData;
4133
- this.state = this.getStateFromProps(props, formData, void 0, void 0, void 0, true);
4162
+ this.state = {
4163
+ ...this.getStateFromProps(props, formData, void 0, void 0, void 0, true),
4164
+ _prevExtraErrors: props.extraErrors
4165
+ };
4134
4166
  if (onChange && !(0, import_utils50.deepEquals)(this.state.formData, formData)) {
4135
4167
  onChange(toIChangeEvent(this.state));
4136
4168
  }
@@ -4817,17 +4849,9 @@ var Form = class extends import_react21.Component {
4817
4849
  const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
4818
4850
  const { errors: prevErrors } = this.state;
4819
4851
  const schemaValidation = this.validate(formData);
4820
- let errors = schemaValidation.errors;
4821
- let errorSchema = schemaValidation.errorSchema;
4822
- const schemaValidationErrors = errors;
4823
- const schemaValidationErrorSchema = errorSchema;
4824
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
4852
+ const { errors, errorSchema } = extraErrors ? this.mergeErrors(schemaValidation, extraErrors) : schemaValidation;
4853
+ const hasError = schemaValidation.errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
4825
4854
  if (hasError) {
4826
- if (extraErrors) {
4827
- const merged = (0, import_utils50.validationDataMerge)(schemaValidation, extraErrors);
4828
- errorSchema = merged.errorSchema;
4829
- errors = merged.errors;
4830
- }
4831
4855
  if (focusOnFirstError) {
4832
4856
  if (typeof focusOnFirstError === "function") {
4833
4857
  focusOnFirstError(errors[0]);
@@ -4839,8 +4863,8 @@ var Form = class extends import_react21.Component {
4839
4863
  {
4840
4864
  errors,
4841
4865
  errorSchema,
4842
- schemaValidationErrors,
4843
- schemaValidationErrorSchema
4866
+ schemaValidationErrors: schemaValidation.errors,
4867
+ schemaValidationErrorSchema: schemaValidation.errorSchema
4844
4868
  },
4845
4869
  () => {
4846
4870
  if (onError) {
@@ -4850,6 +4874,13 @@ var Form = class extends import_react21.Component {
4850
4874
  }
4851
4875
  }
4852
4876
  );
4877
+ } else if (errors.length > 0) {
4878
+ this.setState({
4879
+ errors,
4880
+ errorSchema,
4881
+ schemaValidationErrors: [],
4882
+ schemaValidationErrorSchema: {}
4883
+ });
4853
4884
  } else if (prevErrors.length > 0) {
4854
4885
  this.setState({
4855
4886
  errors: [],