@rjsf/core 5.18.4 → 5.18.6

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.
Files changed (36) hide show
  1. package/dist/core.umd.js +101 -78
  2. package/dist/index.esm.js +101 -74
  3. package/dist/index.esm.js.map +3 -3
  4. package/dist/index.js +101 -74
  5. package/dist/index.js.map +3 -3
  6. package/lib/components/Form.d.ts +16 -2
  7. package/lib/components/Form.js +78 -57
  8. package/lib/components/Form.js.map +1 -1
  9. package/lib/components/fields/ArrayField.d.ts +2 -2
  10. package/lib/components/fields/NumberField.js +1 -1
  11. package/lib/components/fields/NumberField.js.map +1 -1
  12. package/lib/components/fields/ObjectField.js +5 -2
  13. package/lib/components/fields/ObjectField.js.map +1 -1
  14. package/lib/components/fields/SchemaField.js +4 -3
  15. package/lib/components/fields/SchemaField.js.map +1 -1
  16. package/lib/components/templates/BaseInputTemplate.js +2 -2
  17. package/lib/components/templates/BaseInputTemplate.js.map +1 -1
  18. package/lib/components/templates/WrapIfAdditionalTemplate.js +1 -1
  19. package/lib/components/templates/WrapIfAdditionalTemplate.js.map +1 -1
  20. package/lib/components/widgets/CheckboxesWidget.js +2 -2
  21. package/lib/components/widgets/CheckboxesWidget.js.map +1 -1
  22. package/lib/components/widgets/RadioWidget.js +2 -2
  23. package/lib/components/widgets/RadioWidget.js.map +1 -1
  24. package/lib/components/widgets/TextareaWidget.js +2 -2
  25. package/lib/components/widgets/TextareaWidget.js.map +1 -1
  26. package/lib/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +6 -6
  28. package/src/components/Form.tsx +40 -21
  29. package/src/components/fields/NumberField.tsx +1 -1
  30. package/src/components/fields/ObjectField.tsx +6 -3
  31. package/src/components/fields/SchemaField.tsx +3 -3
  32. package/src/components/templates/BaseInputTemplate.tsx +5 -2
  33. package/src/components/templates/WrapIfAdditionalTemplate.tsx +1 -1
  34. package/src/components/widgets/CheckboxesWidget.tsx +4 -4
  35. package/src/components/widgets/RadioWidget.tsx +4 -4
  36. package/src/components/widgets/TextareaWidget.tsx +2 -2
package/dist/core.umd.js CHANGED
@@ -1063,7 +1063,7 @@
1063
1063
  [onChange]
1064
1064
  );
1065
1065
  if (typeof lastValue === "string" && typeof value === "number") {
1066
- const re = new RegExp(`${value}`.replace(".", "\\.") + "\\.?0*$");
1066
+ const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
1067
1067
  if (lastValue.match(re)) {
1068
1068
  value = lastValue;
1069
1069
  }
@@ -1180,20 +1180,23 @@
1180
1180
  const { formData, onChange, registry } = this.props;
1181
1181
  const newFormData = { ...formData };
1182
1182
  let type = void 0;
1183
+ let defaultValue = void 0;
1183
1184
  if (isObject(schema.additionalProperties)) {
1184
1185
  type = schema.additionalProperties.type;
1186
+ defaultValue = schema.additionalProperties.default;
1185
1187
  let apSchema = schema.additionalProperties;
1186
1188
  if (utils.REF_KEY in apSchema) {
1187
1189
  const { schemaUtils } = registry;
1188
1190
  apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[utils.REF_KEY] }, formData);
1189
1191
  type = apSchema.type;
1192
+ defaultValue = apSchema.default;
1190
1193
  }
1191
1194
  if (!type && (utils.ANY_OF_KEY in apSchema || utils.ONE_OF_KEY in apSchema)) {
1192
1195
  type = "object";
1193
1196
  }
1194
1197
  }
1195
1198
  const newKey = this.getAvailableKey("newKey", newFormData);
1196
- set(newFormData, newKey, this.getDefaultValue(type));
1199
+ set(newFormData, newKey, defaultValue ?? this.getDefaultValue(type));
1197
1200
  onChange(newFormData);
1198
1201
  };
1199
1202
  }
@@ -1241,8 +1244,8 @@
1241
1244
  idSchema,
1242
1245
  name,
1243
1246
  required = false,
1244
- disabled = false,
1245
- readonly = false,
1247
+ disabled,
1248
+ readonly,
1246
1249
  hideError,
1247
1250
  idPrefix,
1248
1251
  idSeparator,
@@ -1413,11 +1416,11 @@
1413
1416
  [fieldId, onChange]
1414
1417
  );
1415
1418
  const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
1416
- const disabled = Boolean(props.disabled || uiOptions.disabled);
1417
- const readonly = Boolean(props.readonly || uiOptions.readonly || props.schema.readOnly || schema.readOnly);
1419
+ const disabled = Boolean(uiOptions.disabled ?? props.disabled);
1420
+ const readonly = Boolean(uiOptions.readonly ?? props.readonly ?? props.schema.readOnly ?? schema.readOnly);
1418
1421
  const uiSchemaHideError = uiOptions.hideError;
1419
1422
  const hideError = uiSchemaHideError === void 0 ? props.hideError : Boolean(uiSchemaHideError);
1420
- const autofocus = Boolean(props.autofocus || uiOptions.autofocus);
1423
+ const autofocus = Boolean(uiOptions.autofocus ?? props.autofocus);
1421
1424
  if (Object.keys(schema).length === 0) {
1422
1425
  return null;
1423
1426
  }
@@ -1915,9 +1918,12 @@
1915
1918
  ({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
1916
1919
  [onChange, options]
1917
1920
  );
1918
- const _onBlur = react.useCallback(({ target: { value: value2 } }) => onBlur(id, value2), [onBlur, id]);
1921
+ const _onBlur = react.useCallback(
1922
+ ({ target }) => onBlur(id, target && target.value),
1923
+ [onBlur, id]
1924
+ );
1919
1925
  const _onFocus = react.useCallback(
1920
- ({ target: { value: value2 } }) => onFocus(id, value2),
1926
+ ({ target }) => onFocus(id, target && target.value),
1921
1927
  [onFocus, id]
1922
1928
  );
1923
1929
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -2241,7 +2247,7 @@
2241
2247
  className: "form-control",
2242
2248
  type: "text",
2243
2249
  id: `${id}-key`,
2244
- onBlur: (event) => onKeyChange(event.target.value),
2250
+ onBlur: ({ target }) => onKeyChange(target && target.value),
2245
2251
  defaultValue: label
2246
2252
  }
2247
2253
  )
@@ -2497,11 +2503,11 @@
2497
2503
  }) {
2498
2504
  const checkboxesValues = Array.isArray(value) ? value : [value];
2499
2505
  const handleBlur = react.useCallback(
2500
- ({ target: { value: value2 } }) => onBlur(id, utils.enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2506
+ ({ target }) => onBlur(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2501
2507
  [onBlur, id]
2502
2508
  );
2503
2509
  const handleFocus = react.useCallback(
2504
- ({ target: { value: value2 } }) => onFocus(id, utils.enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2510
+ ({ target }) => onFocus(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2505
2511
  [onFocus, id]
2506
2512
  );
2507
2513
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
@@ -2744,11 +2750,11 @@
2744
2750
  }) {
2745
2751
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
2746
2752
  const handleBlur = react.useCallback(
2747
- ({ target: { value: value2 } }) => onBlur(id, utils.enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2753
+ ({ target }) => onBlur(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2748
2754
  [onBlur, id]
2749
2755
  );
2750
2756
  const handleFocus = react.useCallback(
2751
- ({ target: { value: value2 } }) => onFocus(id, utils.enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2757
+ ({ target }) => onFocus(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2752
2758
  [onFocus, id]
2753
2759
  );
2754
2760
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "field-radio-group", id, children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
@@ -2881,11 +2887,11 @@
2881
2887
  [onChange, options.emptyValue]
2882
2888
  );
2883
2889
  const handleBlur = react.useCallback(
2884
- ({ target: { value: value2 } }) => onBlur(id, value2),
2890
+ ({ target }) => onBlur(id, target && target.value),
2885
2891
  [onBlur, id]
2886
2892
  );
2887
2893
  const handleFocus = react.useCallback(
2888
- ({ target: { value: value2 } }) => onFocus(id, value2),
2894
+ ({ target }) => onFocus(id, target && target.value),
2889
2895
  [id, onFocus]
2890
2896
  );
2891
2897
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -3024,9 +3030,22 @@
3024
3030
  };
3025
3031
  return getAllPaths(pathSchema);
3026
3032
  };
3033
+ /** Returns the `formData` after filtering to remove any extra data not in a form field
3034
+ *
3035
+ * @param formData - The data for the `Form`
3036
+ * @returns The `formData` after omitting extra data
3037
+ */
3038
+ this.omitExtraData = (formData) => {
3039
+ const { schema, schemaUtils } = this.state;
3040
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3041
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3042
+ const fieldNames = this.getFieldNames(pathSchema, formData);
3043
+ const newFormData = this.getUsedFormData(formData, fieldNames);
3044
+ return newFormData;
3045
+ };
3027
3046
  /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
3028
3047
  * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
3029
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filterer to remove any extra data not
3048
+ * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
3030
3049
  * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
3031
3050
  * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
3032
3051
  * callback will be called if specified with the updated state.
@@ -3045,12 +3064,8 @@
3045
3064
  const mustValidate = !noValidate && liveValidate;
3046
3065
  let state = { formData, schema };
3047
3066
  let newFormData = formData;
3048
- let _retrievedSchema;
3049
3067
  if (omitExtraData === true && liveOmit === true) {
3050
- _retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3051
- const pathSchema = schemaUtils.toPathSchema(_retrievedSchema, "", formData);
3052
- const fieldNames = this.getFieldNames(pathSchema, formData);
3053
- newFormData = this.getUsedFormData(formData, fieldNames);
3068
+ newFormData = this.omitExtraData(formData);
3054
3069
  state = {
3055
3070
  formData: newFormData
3056
3071
  };
@@ -3081,9 +3096,6 @@
3081
3096
  errors: utils.toErrorList(errorSchema)
3082
3097
  };
3083
3098
  }
3084
- if (_retrievedSchema) {
3085
- state.retrievedSchema = _retrievedSchema;
3086
- }
3087
3099
  this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
3088
3100
  };
3089
3101
  /**
@@ -3145,14 +3157,10 @@
3145
3157
  event.persist();
3146
3158
  const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
3147
3159
  let { formData: newFormData } = this.state;
3148
- const { schema, schemaUtils } = this.state;
3149
3160
  if (omitExtraData === true) {
3150
- const retrievedSchema = schemaUtils.retrieveSchema(schema, newFormData);
3151
- const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
3152
- const fieldNames = this.getFieldNames(pathSchema, newFormData);
3153
- newFormData = this.getUsedFormData(newFormData, fieldNames);
3161
+ newFormData = this.omitExtraData(newFormData);
3154
3162
  }
3155
- if (noValidate || this.validateForm()) {
3163
+ if (noValidate || this.validateFormWithFormData(newFormData)) {
3156
3164
  const errorSchema = extraErrors || {};
3157
3165
  const errors = extraErrors ? utils.toErrorList(extraErrors) : [];
3158
3166
  this.setState(
@@ -3182,6 +3190,59 @@
3182
3190
  this.formElement.current.requestSubmit();
3183
3191
  }
3184
3192
  };
3193
+ /** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
3194
+ * If `onError` is provided, then it will be called with the list of errors.
3195
+ *
3196
+ * @param formData - The form data to validate
3197
+ * @returns - True if the form is valid, false otherwise.
3198
+ */
3199
+ this.validateFormWithFormData = (formData) => {
3200
+ const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3201
+ const { errors: prevErrors } = this.state;
3202
+ const schemaValidation = this.validate(formData);
3203
+ let errors = schemaValidation.errors;
3204
+ let errorSchema = schemaValidation.errorSchema;
3205
+ const schemaValidationErrors = errors;
3206
+ const schemaValidationErrorSchema = errorSchema;
3207
+ const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3208
+ if (hasError) {
3209
+ if (extraErrors) {
3210
+ const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3211
+ errorSchema = merged.errorSchema;
3212
+ errors = merged.errors;
3213
+ }
3214
+ if (focusOnFirstError) {
3215
+ if (typeof focusOnFirstError === "function") {
3216
+ focusOnFirstError(errors[0]);
3217
+ } else {
3218
+ this.focusOnError(errors[0]);
3219
+ }
3220
+ }
3221
+ this.setState(
3222
+ {
3223
+ errors,
3224
+ errorSchema,
3225
+ schemaValidationErrors,
3226
+ schemaValidationErrorSchema
3227
+ },
3228
+ () => {
3229
+ if (onError) {
3230
+ onError(errors);
3231
+ } else {
3232
+ console.error("Form validation failed", errors);
3233
+ }
3234
+ }
3235
+ );
3236
+ } else if (prevErrors.length > 0) {
3237
+ this.setState({
3238
+ errors: [],
3239
+ errorSchema: {},
3240
+ schemaValidationErrors: [],
3241
+ schemaValidationErrorSchema: {}
3242
+ });
3243
+ }
3244
+ return !hasError;
3245
+ };
3185
3246
  if (!props.validator) {
3186
3247
  throw new Error("A validator is required for Form functionality to work");
3187
3248
  }
@@ -3425,57 +3486,19 @@
3425
3486
  field.focus();
3426
3487
  }
3427
3488
  }
3428
- /** Programmatically validate the form. If `onError` is provided, then it will be called with the list of errors the
3489
+ /** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
3490
+ * any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
3429
3491
  * same way as would happen on form submission.
3430
3492
  *
3431
3493
  * @returns - True if the form is valid, false otherwise.
3432
3494
  */
3433
3495
  validateForm() {
3434
- const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3435
- const { formData, errors: prevErrors } = this.state;
3436
- const schemaValidation = this.validate(formData);
3437
- let errors = schemaValidation.errors;
3438
- let errorSchema = schemaValidation.errorSchema;
3439
- const schemaValidationErrors = errors;
3440
- const schemaValidationErrorSchema = errorSchema;
3441
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3442
- if (hasError) {
3443
- if (extraErrors) {
3444
- const merged = utils.validationDataMerge(schemaValidation, extraErrors);
3445
- errorSchema = merged.errorSchema;
3446
- errors = merged.errors;
3447
- }
3448
- if (focusOnFirstError) {
3449
- if (typeof focusOnFirstError === "function") {
3450
- focusOnFirstError(errors[0]);
3451
- } else {
3452
- this.focusOnError(errors[0]);
3453
- }
3454
- }
3455
- this.setState(
3456
- {
3457
- errors,
3458
- errorSchema,
3459
- schemaValidationErrors,
3460
- schemaValidationErrorSchema
3461
- },
3462
- () => {
3463
- if (onError) {
3464
- onError(errors);
3465
- } else {
3466
- console.error("Form validation failed", errors);
3467
- }
3468
- }
3469
- );
3470
- } else if (prevErrors.length > 0) {
3471
- this.setState({
3472
- errors: [],
3473
- errorSchema: {},
3474
- schemaValidationErrors: [],
3475
- schemaValidationErrorSchema: {}
3476
- });
3496
+ const { omitExtraData } = this.props;
3497
+ let { formData: newFormData } = this.state;
3498
+ if (omitExtraData === true) {
3499
+ newFormData = this.omitExtraData(newFormData);
3477
3500
  }
3478
- return !hasError;
3501
+ return this.validateFormWithFormData(newFormData);
3479
3502
  }
3480
3503
  /** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
3481
3504
  * needed along with the submit button or any children of the form.
@@ -3497,8 +3520,8 @@
3497
3520
  acceptcharset,
3498
3521
  acceptCharset,
3499
3522
  noHtml5Validate = false,
3500
- disabled = false,
3501
- readonly = false,
3523
+ disabled,
3524
+ readonly,
3502
3525
  formContext,
3503
3526
  showErrorList = "top",
3504
3527
  _internalFormWrapper
package/dist/index.esm.js CHANGED
@@ -1134,7 +1134,7 @@ function NumberField(props) {
1134
1134
  [onChange]
1135
1135
  );
1136
1136
  if (typeof lastValue === "string" && typeof value === "number") {
1137
- const re = new RegExp(`${value}`.replace(".", "\\.") + "\\.?0*$");
1137
+ const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
1138
1138
  if (lastValue.match(re)) {
1139
1139
  value = lastValue;
1140
1140
  }
@@ -1272,20 +1272,23 @@ var ObjectField = class extends Component3 {
1272
1272
  const { formData, onChange, registry } = this.props;
1273
1273
  const newFormData = { ...formData };
1274
1274
  let type = void 0;
1275
+ let defaultValue = void 0;
1275
1276
  if (isObject3(schema.additionalProperties)) {
1276
1277
  type = schema.additionalProperties.type;
1278
+ defaultValue = schema.additionalProperties.default;
1277
1279
  let apSchema = schema.additionalProperties;
1278
1280
  if (REF_KEY in apSchema) {
1279
1281
  const { schemaUtils } = registry;
1280
1282
  apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[REF_KEY] }, formData);
1281
1283
  type = apSchema.type;
1284
+ defaultValue = apSchema.default;
1282
1285
  }
1283
1286
  if (!type && (ANY_OF_KEY2 in apSchema || ONE_OF_KEY2 in apSchema)) {
1284
1287
  type = "object";
1285
1288
  }
1286
1289
  }
1287
1290
  const newKey = this.getAvailableKey("newKey", newFormData);
1288
- set2(newFormData, newKey, this.getDefaultValue(type));
1291
+ set2(newFormData, newKey, defaultValue ?? this.getDefaultValue(type));
1289
1292
  onChange(newFormData);
1290
1293
  };
1291
1294
  }
@@ -1333,8 +1336,8 @@ var ObjectField = class extends Component3 {
1333
1336
  idSchema,
1334
1337
  name,
1335
1338
  required = false,
1336
- disabled = false,
1337
- readonly = false,
1339
+ disabled,
1340
+ readonly,
1338
1341
  hideError,
1339
1342
  idPrefix,
1340
1343
  idSeparator,
@@ -1524,11 +1527,11 @@ function SchemaFieldRender(props) {
1524
1527
  [fieldId, onChange]
1525
1528
  );
1526
1529
  const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
1527
- const disabled = Boolean(props.disabled || uiOptions.disabled);
1528
- const readonly = Boolean(props.readonly || uiOptions.readonly || props.schema.readOnly || schema.readOnly);
1530
+ const disabled = Boolean(uiOptions.disabled ?? props.disabled);
1531
+ const readonly = Boolean(uiOptions.readonly ?? props.readonly ?? props.schema.readOnly ?? schema.readOnly);
1529
1532
  const uiSchemaHideError = uiOptions.hideError;
1530
1533
  const hideError = uiSchemaHideError === void 0 ? props.hideError : Boolean(uiSchemaHideError);
1531
- const autofocus = Boolean(props.autofocus || uiOptions.autofocus);
1534
+ const autofocus = Boolean(uiOptions.autofocus ?? props.autofocus);
1532
1535
  if (Object.keys(schema).length === 0) {
1533
1536
  return null;
1534
1537
  }
@@ -2073,9 +2076,12 @@ function BaseInputTemplate(props) {
2073
2076
  ({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
2074
2077
  [onChange, options]
2075
2078
  );
2076
- const _onBlur = useCallback3(({ target: { value: value2 } }) => onBlur(id, value2), [onBlur, id]);
2079
+ const _onBlur = useCallback3(
2080
+ ({ target }) => onBlur(id, target && target.value),
2081
+ [onBlur, id]
2082
+ );
2077
2083
  const _onFocus = useCallback3(
2078
- ({ target: { value: value2 } }) => onFocus(id, value2),
2084
+ ({ target }) => onFocus(id, target && target.value),
2079
2085
  [onFocus, id]
2080
2086
  );
2081
2087
  return /* @__PURE__ */ jsxs6(Fragment2, { children: [
@@ -2467,7 +2473,7 @@ function WrapIfAdditionalTemplate(props) {
2467
2473
  className: "form-control",
2468
2474
  type: "text",
2469
2475
  id: `${id}-key`,
2470
- onBlur: (event) => onKeyChange(event.target.value),
2476
+ onBlur: ({ target }) => onKeyChange(target && target.value),
2471
2477
  defaultValue: label
2472
2478
  }
2473
2479
  )
@@ -2761,11 +2767,11 @@ function CheckboxesWidget({
2761
2767
  }) {
2762
2768
  const checkboxesValues = Array.isArray(value) ? value : [value];
2763
2769
  const handleBlur = useCallback6(
2764
- ({ target: { value: value2 } }) => onBlur(id, enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2770
+ ({ target }) => onBlur(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2765
2771
  [onBlur, id]
2766
2772
  );
2767
2773
  const handleFocus = useCallback6(
2768
- ({ target: { value: value2 } }) => onFocus(id, enumOptionsValueForIndex(value2, enumOptions, emptyValue)),
2774
+ ({ target }) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
2769
2775
  [onFocus, id]
2770
2776
  );
2771
2777
  return /* @__PURE__ */ jsx29("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
@@ -3056,11 +3062,11 @@ function RadioWidget({
3056
3062
  }) {
3057
3063
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
3058
3064
  const handleBlur = useCallback9(
3059
- ({ target: { value: value2 } }) => onBlur(id, enumOptionsValueForIndex2(value2, enumOptions, emptyValue)),
3065
+ ({ target }) => onBlur(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
3060
3066
  [onBlur, id]
3061
3067
  );
3062
3068
  const handleFocus = useCallback9(
3063
- ({ target: { value: value2 } }) => onFocus(id, enumOptionsValueForIndex2(value2, enumOptions, emptyValue)),
3069
+ ({ target }) => onFocus(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
3064
3070
  [onFocus, id]
3065
3071
  );
3066
3072
  return /* @__PURE__ */ jsx37("div", { className: "field-radio-group", id, children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
@@ -3210,11 +3216,11 @@ function TextareaWidget({
3210
3216
  [onChange, options.emptyValue]
3211
3217
  );
3212
3218
  const handleBlur = useCallback11(
3213
- ({ target: { value: value2 } }) => onBlur(id, value2),
3219
+ ({ target }) => onBlur(id, target && target.value),
3214
3220
  [onBlur, id]
3215
3221
  );
3216
3222
  const handleFocus = useCallback11(
3217
- ({ target: { value: value2 } }) => onFocus(id, value2),
3223
+ ({ target }) => onFocus(id, target && target.value),
3218
3224
  [id, onFocus]
3219
3225
  );
3220
3226
  return /* @__PURE__ */ jsx40(
@@ -3373,9 +3379,22 @@ var Form = class extends Component5 {
3373
3379
  };
3374
3380
  return getAllPaths(pathSchema);
3375
3381
  };
3382
+ /** Returns the `formData` after filtering to remove any extra data not in a form field
3383
+ *
3384
+ * @param formData - The data for the `Form`
3385
+ * @returns The `formData` after omitting extra data
3386
+ */
3387
+ this.omitExtraData = (formData) => {
3388
+ const { schema, schemaUtils } = this.state;
3389
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3390
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3391
+ const fieldNames = this.getFieldNames(pathSchema, formData);
3392
+ const newFormData = this.getUsedFormData(formData, fieldNames);
3393
+ return newFormData;
3394
+ };
3376
3395
  /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
3377
3396
  * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
3378
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filterer to remove any extra data not
3397
+ * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
3379
3398
  * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
3380
3399
  * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
3381
3400
  * callback will be called if specified with the updated state.
@@ -3396,10 +3415,7 @@ var Form = class extends Component5 {
3396
3415
  let newFormData = formData;
3397
3416
  let _retrievedSchema;
3398
3417
  if (omitExtraData === true && liveOmit === true) {
3399
- _retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3400
- const pathSchema = schemaUtils.toPathSchema(_retrievedSchema, "", formData);
3401
- const fieldNames = this.getFieldNames(pathSchema, formData);
3402
- newFormData = this.getUsedFormData(formData, fieldNames);
3418
+ newFormData = this.omitExtraData(formData);
3403
3419
  state = {
3404
3420
  formData: newFormData
3405
3421
  };
@@ -3494,14 +3510,10 @@ var Form = class extends Component5 {
3494
3510
  event.persist();
3495
3511
  const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
3496
3512
  let { formData: newFormData } = this.state;
3497
- const { schema, schemaUtils } = this.state;
3498
3513
  if (omitExtraData === true) {
3499
- const retrievedSchema = schemaUtils.retrieveSchema(schema, newFormData);
3500
- const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
3501
- const fieldNames = this.getFieldNames(pathSchema, newFormData);
3502
- newFormData = this.getUsedFormData(newFormData, fieldNames);
3514
+ newFormData = this.omitExtraData(newFormData);
3503
3515
  }
3504
- if (noValidate || this.validateForm()) {
3516
+ if (noValidate || this.validateFormWithFormData(newFormData)) {
3505
3517
  const errorSchema = extraErrors || {};
3506
3518
  const errors = extraErrors ? toErrorList(extraErrors) : [];
3507
3519
  this.setState(
@@ -3531,6 +3543,59 @@ var Form = class extends Component5 {
3531
3543
  this.formElement.current.requestSubmit();
3532
3544
  }
3533
3545
  };
3546
+ /** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
3547
+ * If `onError` is provided, then it will be called with the list of errors.
3548
+ *
3549
+ * @param formData - The form data to validate
3550
+ * @returns - True if the form is valid, false otherwise.
3551
+ */
3552
+ this.validateFormWithFormData = (formData) => {
3553
+ const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3554
+ const { errors: prevErrors } = this.state;
3555
+ const schemaValidation = this.validate(formData);
3556
+ let errors = schemaValidation.errors;
3557
+ let errorSchema = schemaValidation.errorSchema;
3558
+ const schemaValidationErrors = errors;
3559
+ const schemaValidationErrorSchema = errorSchema;
3560
+ const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3561
+ if (hasError) {
3562
+ if (extraErrors) {
3563
+ const merged = validationDataMerge(schemaValidation, extraErrors);
3564
+ errorSchema = merged.errorSchema;
3565
+ errors = merged.errors;
3566
+ }
3567
+ if (focusOnFirstError) {
3568
+ if (typeof focusOnFirstError === "function") {
3569
+ focusOnFirstError(errors[0]);
3570
+ } else {
3571
+ this.focusOnError(errors[0]);
3572
+ }
3573
+ }
3574
+ this.setState(
3575
+ {
3576
+ errors,
3577
+ errorSchema,
3578
+ schemaValidationErrors,
3579
+ schemaValidationErrorSchema
3580
+ },
3581
+ () => {
3582
+ if (onError) {
3583
+ onError(errors);
3584
+ } else {
3585
+ console.error("Form validation failed", errors);
3586
+ }
3587
+ }
3588
+ );
3589
+ } else if (prevErrors.length > 0) {
3590
+ this.setState({
3591
+ errors: [],
3592
+ errorSchema: {},
3593
+ schemaValidationErrors: [],
3594
+ schemaValidationErrorSchema: {}
3595
+ });
3596
+ }
3597
+ return !hasError;
3598
+ };
3534
3599
  if (!props.validator) {
3535
3600
  throw new Error("A validator is required for Form functionality to work");
3536
3601
  }
@@ -3774,57 +3839,19 @@ var Form = class extends Component5 {
3774
3839
  field.focus();
3775
3840
  }
3776
3841
  }
3777
- /** Programmatically validate the form. If `onError` is provided, then it will be called with the list of errors the
3842
+ /** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
3843
+ * any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
3778
3844
  * same way as would happen on form submission.
3779
3845
  *
3780
3846
  * @returns - True if the form is valid, false otherwise.
3781
3847
  */
3782
3848
  validateForm() {
3783
- const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3784
- const { formData, errors: prevErrors } = this.state;
3785
- const schemaValidation = this.validate(formData);
3786
- let errors = schemaValidation.errors;
3787
- let errorSchema = schemaValidation.errorSchema;
3788
- const schemaValidationErrors = errors;
3789
- const schemaValidationErrorSchema = errorSchema;
3790
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3791
- if (hasError) {
3792
- if (extraErrors) {
3793
- const merged = validationDataMerge(schemaValidation, extraErrors);
3794
- errorSchema = merged.errorSchema;
3795
- errors = merged.errors;
3796
- }
3797
- if (focusOnFirstError) {
3798
- if (typeof focusOnFirstError === "function") {
3799
- focusOnFirstError(errors[0]);
3800
- } else {
3801
- this.focusOnError(errors[0]);
3802
- }
3803
- }
3804
- this.setState(
3805
- {
3806
- errors,
3807
- errorSchema,
3808
- schemaValidationErrors,
3809
- schemaValidationErrorSchema
3810
- },
3811
- () => {
3812
- if (onError) {
3813
- onError(errors);
3814
- } else {
3815
- console.error("Form validation failed", errors);
3816
- }
3817
- }
3818
- );
3819
- } else if (prevErrors.length > 0) {
3820
- this.setState({
3821
- errors: [],
3822
- errorSchema: {},
3823
- schemaValidationErrors: [],
3824
- schemaValidationErrorSchema: {}
3825
- });
3849
+ const { omitExtraData } = this.props;
3850
+ let { formData: newFormData } = this.state;
3851
+ if (omitExtraData === true) {
3852
+ newFormData = this.omitExtraData(newFormData);
3826
3853
  }
3827
- return !hasError;
3854
+ return this.validateFormWithFormData(newFormData);
3828
3855
  }
3829
3856
  /** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
3830
3857
  * needed along with the submit button or any children of the form.
@@ -3846,8 +3873,8 @@ var Form = class extends Component5 {
3846
3873
  acceptcharset,
3847
3874
  acceptCharset,
3848
3875
  noHtml5Validate = false,
3849
- disabled = false,
3850
- readonly = false,
3876
+ disabled,
3877
+ readonly,
3851
3878
  formContext,
3852
3879
  showErrorList = "top",
3853
3880
  _internalFormWrapper