@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/index.js CHANGED
@@ -1132,7 +1132,7 @@ function NumberField(props) {
1132
1132
  [onChange]
1133
1133
  );
1134
1134
  if (typeof lastValue === "string" && typeof value === "number") {
1135
- const re = new RegExp(`${value}`.replace(".", "\\.") + "\\.?0*$");
1135
+ const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
1136
1136
  if (lastValue.match(re)) {
1137
1137
  value = lastValue;
1138
1138
  }
@@ -1260,20 +1260,23 @@ var ObjectField = class extends import_react4.Component {
1260
1260
  const { formData, onChange, registry } = this.props;
1261
1261
  const newFormData = { ...formData };
1262
1262
  let type = void 0;
1263
+ let defaultValue = void 0;
1263
1264
  if ((0, import_isObject3.default)(schema.additionalProperties)) {
1264
1265
  type = schema.additionalProperties.type;
1266
+ defaultValue = schema.additionalProperties.default;
1265
1267
  let apSchema = schema.additionalProperties;
1266
1268
  if (import_utils5.REF_KEY in apSchema) {
1267
1269
  const { schemaUtils } = registry;
1268
1270
  apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[import_utils5.REF_KEY] }, formData);
1269
1271
  type = apSchema.type;
1272
+ defaultValue = apSchema.default;
1270
1273
  }
1271
1274
  if (!type && (import_utils5.ANY_OF_KEY in apSchema || import_utils5.ONE_OF_KEY in apSchema)) {
1272
1275
  type = "object";
1273
1276
  }
1274
1277
  }
1275
1278
  const newKey = this.getAvailableKey("newKey", newFormData);
1276
- (0, import_set2.default)(newFormData, newKey, this.getDefaultValue(type));
1279
+ (0, import_set2.default)(newFormData, newKey, defaultValue ?? this.getDefaultValue(type));
1277
1280
  onChange(newFormData);
1278
1281
  };
1279
1282
  }
@@ -1321,8 +1324,8 @@ var ObjectField = class extends import_react4.Component {
1321
1324
  idSchema,
1322
1325
  name,
1323
1326
  required = false,
1324
- disabled = false,
1325
- readonly = false,
1327
+ disabled,
1328
+ readonly,
1326
1329
  hideError,
1327
1330
  idPrefix,
1328
1331
  idSeparator,
@@ -1501,11 +1504,11 @@ function SchemaFieldRender(props) {
1501
1504
  [fieldId, onChange]
1502
1505
  );
1503
1506
  const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
1504
- const disabled = Boolean(props.disabled || uiOptions.disabled);
1505
- const readonly = Boolean(props.readonly || uiOptions.readonly || props.schema.readOnly || schema.readOnly);
1507
+ const disabled = Boolean(uiOptions.disabled ?? props.disabled);
1508
+ const readonly = Boolean(uiOptions.readonly ?? props.readonly ?? props.schema.readOnly ?? schema.readOnly);
1506
1509
  const uiSchemaHideError = uiOptions.hideError;
1507
1510
  const hideError = uiSchemaHideError === void 0 ? props.hideError : Boolean(uiSchemaHideError);
1508
- const autofocus = Boolean(props.autofocus || uiOptions.autofocus);
1511
+ const autofocus = Boolean(uiOptions.autofocus ?? props.autofocus);
1509
1512
  if (Object.keys(schema).length === 0) {
1510
1513
  return null;
1511
1514
  }
@@ -2030,9 +2033,12 @@ function BaseInputTemplate(props) {
2030
2033
  ({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
2031
2034
  [onChange, options]
2032
2035
  );
2033
- const _onBlur = (0, import_react7.useCallback)(({ target: { value: value2 } }) => onBlur(id, value2), [onBlur, id]);
2036
+ const _onBlur = (0, import_react7.useCallback)(
2037
+ ({ target }) => onBlur(id, target && target.value),
2038
+ [onBlur, id]
2039
+ );
2034
2040
  const _onFocus = (0, import_react7.useCallback)(
2035
- ({ target: { value: value2 } }) => onFocus(id, value2),
2041
+ ({ target }) => onFocus(id, target && target.value),
2036
2042
  [onFocus, id]
2037
2043
  );
2038
2044
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
@@ -2410,7 +2416,7 @@ function WrapIfAdditionalTemplate(props) {
2410
2416
  className: "form-control",
2411
2417
  type: "text",
2412
2418
  id: `${id}-key`,
2413
- onBlur: (event) => onKeyChange(event.target.value),
2419
+ onBlur: ({ target }) => onKeyChange(target && target.value),
2414
2420
  defaultValue: label
2415
2421
  }
2416
2422
  )
@@ -2684,11 +2690,11 @@ function CheckboxesWidget({
2684
2690
  }) {
2685
2691
  const checkboxesValues = Array.isArray(value) ? value : [value];
2686
2692
  const handleBlur = (0, import_react10.useCallback)(
2687
- ({ target: { value: value2 } }) => onBlur(id, (0, import_utils24.enumOptionsValueForIndex)(value2, enumOptions, emptyValue)),
2693
+ ({ target }) => onBlur(id, (0, import_utils24.enumOptionsValueForIndex)(target && target.value, enumOptions, emptyValue)),
2688
2694
  [onBlur, id]
2689
2695
  );
2690
2696
  const handleFocus = (0, import_react10.useCallback)(
2691
- ({ target: { value: value2 } }) => onFocus(id, (0, import_utils24.enumOptionsValueForIndex)(value2, enumOptions, emptyValue)),
2697
+ ({ target }) => onFocus(id, (0, import_utils24.enumOptionsValueForIndex)(target && target.value, enumOptions, emptyValue)),
2692
2698
  [onFocus, id]
2693
2699
  );
2694
2700
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
@@ -2966,11 +2972,11 @@ function RadioWidget({
2966
2972
  }) {
2967
2973
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
2968
2974
  const handleBlur = (0, import_react13.useCallback)(
2969
- ({ target: { value: value2 } }) => onBlur(id, (0, import_utils31.enumOptionsValueForIndex)(value2, enumOptions, emptyValue)),
2975
+ ({ target }) => onBlur(id, (0, import_utils31.enumOptionsValueForIndex)(target && target.value, enumOptions, emptyValue)),
2970
2976
  [onBlur, id]
2971
2977
  );
2972
2978
  const handleFocus = (0, import_react13.useCallback)(
2973
- ({ target: { value: value2 } }) => onFocus(id, (0, import_utils31.enumOptionsValueForIndex)(value2, enumOptions, emptyValue)),
2979
+ ({ target }) => onFocus(id, (0, import_utils31.enumOptionsValueForIndex)(target && target.value, enumOptions, emptyValue)),
2974
2980
  [onFocus, id]
2975
2981
  );
2976
2982
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "field-radio-group", id, children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
@@ -3116,11 +3122,11 @@ function TextareaWidget({
3116
3122
  [onChange, options.emptyValue]
3117
3123
  );
3118
3124
  const handleBlur = (0, import_react15.useCallback)(
3119
- ({ target: { value: value2 } }) => onBlur(id, value2),
3125
+ ({ target }) => onBlur(id, target && target.value),
3120
3126
  [onBlur, id]
3121
3127
  );
3122
3128
  const handleFocus = (0, import_react15.useCallback)(
3123
- ({ target: { value: value2 } }) => onFocus(id, value2),
3129
+ ({ target }) => onFocus(id, target && target.value),
3124
3130
  [id, onFocus]
3125
3131
  );
3126
3132
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
@@ -3279,9 +3285,22 @@ var Form = class extends import_react17.Component {
3279
3285
  };
3280
3286
  return getAllPaths(pathSchema);
3281
3287
  };
3288
+ /** Returns the `formData` after filtering to remove any extra data not in a form field
3289
+ *
3290
+ * @param formData - The data for the `Form`
3291
+ * @returns The `formData` after omitting extra data
3292
+ */
3293
+ this.omitExtraData = (formData) => {
3294
+ const { schema, schemaUtils } = this.state;
3295
+ const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3296
+ const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
3297
+ const fieldNames = this.getFieldNames(pathSchema, formData);
3298
+ const newFormData = this.getUsedFormData(formData, fieldNames);
3299
+ return newFormData;
3300
+ };
3282
3301
  /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
3283
3302
  * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
3284
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filterer to remove any extra data not
3303
+ * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
3285
3304
  * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
3286
3305
  * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
3287
3306
  * callback will be called if specified with the updated state.
@@ -3302,10 +3321,7 @@ var Form = class extends import_react17.Component {
3302
3321
  let newFormData = formData;
3303
3322
  let _retrievedSchema;
3304
3323
  if (omitExtraData === true && liveOmit === true) {
3305
- _retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
3306
- const pathSchema = schemaUtils.toPathSchema(_retrievedSchema, "", formData);
3307
- const fieldNames = this.getFieldNames(pathSchema, formData);
3308
- newFormData = this.getUsedFormData(formData, fieldNames);
3324
+ newFormData = this.omitExtraData(formData);
3309
3325
  state = {
3310
3326
  formData: newFormData
3311
3327
  };
@@ -3400,14 +3416,10 @@ var Form = class extends import_react17.Component {
3400
3416
  event.persist();
3401
3417
  const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
3402
3418
  let { formData: newFormData } = this.state;
3403
- const { schema, schemaUtils } = this.state;
3404
3419
  if (omitExtraData === true) {
3405
- const retrievedSchema = schemaUtils.retrieveSchema(schema, newFormData);
3406
- const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
3407
- const fieldNames = this.getFieldNames(pathSchema, newFormData);
3408
- newFormData = this.getUsedFormData(newFormData, fieldNames);
3420
+ newFormData = this.omitExtraData(newFormData);
3409
3421
  }
3410
- if (noValidate || this.validateForm()) {
3422
+ if (noValidate || this.validateFormWithFormData(newFormData)) {
3411
3423
  const errorSchema = extraErrors || {};
3412
3424
  const errors = extraErrors ? (0, import_utils39.toErrorList)(extraErrors) : [];
3413
3425
  this.setState(
@@ -3437,6 +3449,59 @@ var Form = class extends import_react17.Component {
3437
3449
  this.formElement.current.requestSubmit();
3438
3450
  }
3439
3451
  };
3452
+ /** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
3453
+ * If `onError` is provided, then it will be called with the list of errors.
3454
+ *
3455
+ * @param formData - The form data to validate
3456
+ * @returns - True if the form is valid, false otherwise.
3457
+ */
3458
+ this.validateFormWithFormData = (formData) => {
3459
+ const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3460
+ const { errors: prevErrors } = this.state;
3461
+ const schemaValidation = this.validate(formData);
3462
+ let errors = schemaValidation.errors;
3463
+ let errorSchema = schemaValidation.errorSchema;
3464
+ const schemaValidationErrors = errors;
3465
+ const schemaValidationErrorSchema = errorSchema;
3466
+ const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3467
+ if (hasError) {
3468
+ if (extraErrors) {
3469
+ const merged = (0, import_utils39.validationDataMerge)(schemaValidation, extraErrors);
3470
+ errorSchema = merged.errorSchema;
3471
+ errors = merged.errors;
3472
+ }
3473
+ if (focusOnFirstError) {
3474
+ if (typeof focusOnFirstError === "function") {
3475
+ focusOnFirstError(errors[0]);
3476
+ } else {
3477
+ this.focusOnError(errors[0]);
3478
+ }
3479
+ }
3480
+ this.setState(
3481
+ {
3482
+ errors,
3483
+ errorSchema,
3484
+ schemaValidationErrors,
3485
+ schemaValidationErrorSchema
3486
+ },
3487
+ () => {
3488
+ if (onError) {
3489
+ onError(errors);
3490
+ } else {
3491
+ console.error("Form validation failed", errors);
3492
+ }
3493
+ }
3494
+ );
3495
+ } else if (prevErrors.length > 0) {
3496
+ this.setState({
3497
+ errors: [],
3498
+ errorSchema: {},
3499
+ schemaValidationErrors: [],
3500
+ schemaValidationErrorSchema: {}
3501
+ });
3502
+ }
3503
+ return !hasError;
3504
+ };
3440
3505
  if (!props.validator) {
3441
3506
  throw new Error("A validator is required for Form functionality to work");
3442
3507
  }
@@ -3680,57 +3745,19 @@ var Form = class extends import_react17.Component {
3680
3745
  field.focus();
3681
3746
  }
3682
3747
  }
3683
- /** Programmatically validate the form. If `onError` is provided, then it will be called with the list of errors the
3748
+ /** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
3749
+ * any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
3684
3750
  * same way as would happen on form submission.
3685
3751
  *
3686
3752
  * @returns - True if the form is valid, false otherwise.
3687
3753
  */
3688
3754
  validateForm() {
3689
- const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
3690
- const { formData, errors: prevErrors } = this.state;
3691
- const schemaValidation = this.validate(formData);
3692
- let errors = schemaValidation.errors;
3693
- let errorSchema = schemaValidation.errorSchema;
3694
- const schemaValidationErrors = errors;
3695
- const schemaValidationErrorSchema = errorSchema;
3696
- const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
3697
- if (hasError) {
3698
- if (extraErrors) {
3699
- const merged = (0, import_utils39.validationDataMerge)(schemaValidation, extraErrors);
3700
- errorSchema = merged.errorSchema;
3701
- errors = merged.errors;
3702
- }
3703
- if (focusOnFirstError) {
3704
- if (typeof focusOnFirstError === "function") {
3705
- focusOnFirstError(errors[0]);
3706
- } else {
3707
- this.focusOnError(errors[0]);
3708
- }
3709
- }
3710
- this.setState(
3711
- {
3712
- errors,
3713
- errorSchema,
3714
- schemaValidationErrors,
3715
- schemaValidationErrorSchema
3716
- },
3717
- () => {
3718
- if (onError) {
3719
- onError(errors);
3720
- } else {
3721
- console.error("Form validation failed", errors);
3722
- }
3723
- }
3724
- );
3725
- } else if (prevErrors.length > 0) {
3726
- this.setState({
3727
- errors: [],
3728
- errorSchema: {},
3729
- schemaValidationErrors: [],
3730
- schemaValidationErrorSchema: {}
3731
- });
3755
+ const { omitExtraData } = this.props;
3756
+ let { formData: newFormData } = this.state;
3757
+ if (omitExtraData === true) {
3758
+ newFormData = this.omitExtraData(newFormData);
3732
3759
  }
3733
- return !hasError;
3760
+ return this.validateFormWithFormData(newFormData);
3734
3761
  }
3735
3762
  /** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
3736
3763
  * needed along with the submit button or any children of the form.
@@ -3752,8 +3779,8 @@ var Form = class extends import_react17.Component {
3752
3779
  acceptcharset,
3753
3780
  acceptCharset,
3754
3781
  noHtml5Validate = false,
3755
- disabled = false,
3756
- readonly = false,
3782
+ disabled,
3783
+ readonly,
3757
3784
  formContext,
3758
3785
  showErrorList = "top",
3759
3786
  _internalFormWrapper