@rjsf/core 6.1.1 → 6.2.3

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 (35) hide show
  1. package/dist/core.umd.js +65 -44
  2. package/dist/index.cjs +65 -44
  3. package/dist/index.cjs.map +3 -3
  4. package/dist/index.esm.js +68 -47
  5. package/dist/index.esm.js.map +3 -3
  6. package/lib/components/Form.d.ts +17 -5
  7. package/lib/components/Form.d.ts.map +1 -1
  8. package/lib/components/Form.js +35 -49
  9. package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
  10. package/lib/components/fields/LayoutMultiSchemaField.js +1 -1
  11. package/lib/components/fields/SchemaField.d.ts.map +1 -1
  12. package/lib/components/fields/SchemaField.js +1 -0
  13. package/lib/components/templates/BaseInputTemplate.d.ts.map +1 -1
  14. package/lib/components/templates/BaseInputTemplate.js +7 -1
  15. package/lib/components/templates/ButtonTemplates/IconButton.d.ts +1 -0
  16. package/lib/components/templates/ButtonTemplates/IconButton.d.ts.map +1 -1
  17. package/lib/components/templates/ButtonTemplates/IconButton.js +4 -0
  18. package/lib/components/templates/ButtonTemplates/index.d.ts.map +1 -1
  19. package/lib/components/templates/ButtonTemplates/index.js +2 -1
  20. package/lib/components/templates/ObjectFieldTemplate.d.ts +1 -1
  21. package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
  22. package/lib/components/templates/ObjectFieldTemplate.js +6 -0
  23. package/lib/components/widgets/TextareaWidget.d.ts +0 -6
  24. package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
  25. package/lib/components/widgets/TextareaWidget.js +0 -4
  26. package/lib/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +7 -10
  28. package/src/components/Form.tsx +53 -62
  29. package/src/components/fields/LayoutMultiSchemaField.tsx +1 -0
  30. package/src/components/fields/SchemaField.tsx +1 -0
  31. package/src/components/templates/BaseInputTemplate.tsx +13 -1
  32. package/src/components/templates/ButtonTemplates/IconButton.tsx +24 -0
  33. package/src/components/templates/ButtonTemplates/index.ts +2 -1
  34. package/src/components/templates/ObjectFieldTemplate.tsx +9 -0
  35. package/src/components/widgets/TextareaWidget.tsx +0 -5
package/dist/index.esm.js CHANGED
@@ -9,8 +9,6 @@ import {
9
9
  getUiOptions as getUiOptions21,
10
10
  isObject as isObject6,
11
11
  mergeObjects,
12
- NAME_KEY,
13
- RJSF_ADDITIONAL_PROPERTIES_FLAG,
14
12
  shouldRender as shouldRender2,
15
13
  SUBMIT_BTN_OPTIONS_KEY,
16
14
  toErrorList,
@@ -21,7 +19,9 @@ import {
21
19
  DEFAULT_ID_SEPARATOR as DEFAULT_ID_SEPARATOR2,
22
20
  DEFAULT_ID_PREFIX as DEFAULT_ID_PREFIX2,
23
21
  ERRORS_KEY as ERRORS_KEY3,
24
- ID_KEY as ID_KEY5
22
+ ID_KEY as ID_KEY5,
23
+ getUsedFormData,
24
+ getFieldNames
25
25
  } from "@rjsf/utils";
26
26
  import _cloneDeep from "lodash/cloneDeep";
27
27
  import _get from "lodash/get";
@@ -1613,6 +1613,7 @@ function LayoutMultiSchemaField(props) {
1613
1613
  return /* @__PURE__ */ jsx6(
1614
1614
  FieldTemplate2,
1615
1615
  {
1616
+ fieldPathId,
1616
1617
  id,
1617
1618
  schema,
1618
1619
  label: (title || schema.title) ?? "",
@@ -2473,6 +2474,7 @@ function SchemaFieldRender(props) {
2473
2474
  rawHelp: typeof help === "string" ? help : void 0,
2474
2475
  errors: errorsComponent,
2475
2476
  rawErrors: hideError ? void 0 : __errors,
2477
+ fieldPathId,
2476
2478
  id,
2477
2479
  label,
2478
2480
  hidden,
@@ -2912,6 +2914,7 @@ function BaseInputTemplate(props) {
2912
2914
  // remove this from ...rest
2913
2915
  ...rest
2914
2916
  } = props;
2917
+ const { ClearButton: ClearButton2 } = registry.templates.ButtonTemplates;
2915
2918
  if (!id) {
2916
2919
  console.log("No id for", props);
2917
2920
  throw new Error(`no id for props ${JSON.stringify(props)}`);
@@ -2938,6 +2941,14 @@ function BaseInputTemplate(props) {
2938
2941
  ({ target }) => onFocus(id, target && target.value),
2939
2942
  [onFocus, id]
2940
2943
  );
2944
+ const _onClear = useCallback7(
2945
+ (e) => {
2946
+ e.preventDefault();
2947
+ e.stopPropagation();
2948
+ onChange(options.emptyValue ?? "");
2949
+ },
2950
+ [onChange, options.emptyValue]
2951
+ );
2941
2952
  return /* @__PURE__ */ jsxs6(Fragment3, { children: [
2942
2953
  /* @__PURE__ */ jsx18(
2943
2954
  "input",
@@ -2957,6 +2968,7 @@ function BaseInputTemplate(props) {
2957
2968
  "aria-describedby": ariaDescribedByIds(id, !!schema.examples)
2958
2969
  }
2959
2970
  ),
2971
+ options.allowClearTextInputs && !readonly && !disabled && inputValue && /* @__PURE__ */ jsx18(ClearButton2, { registry, onClick: _onClear }),
2960
2972
  Array.isArray(schema.examples) && /* @__PURE__ */ jsx18("datalist", { id: examplesId(id), children: schema.examples.concat(schema.default && !schema.examples.includes(schema.default) ? [schema.default] : []).map((example) => {
2961
2973
  return /* @__PURE__ */ jsx18("option", { value: example }, example);
2962
2974
  }) }, `datalist_${id}`)
@@ -3008,6 +3020,30 @@ function RemoveButton(props) {
3008
3020
  } = props;
3009
3021
  return /* @__PURE__ */ jsx20(IconButton, { title: translateString(TranslatableString7.RemoveButton), ...props, iconType: "danger", icon: "remove" });
3010
3022
  }
3023
+ function ClearButton({
3024
+ id,
3025
+ className,
3026
+ onClick,
3027
+ disabled,
3028
+ registry,
3029
+ ...props
3030
+ }) {
3031
+ const { translateString } = registry;
3032
+ return /* @__PURE__ */ jsx20(
3033
+ IconButton,
3034
+ {
3035
+ id,
3036
+ iconType: "default",
3037
+ icon: "remove",
3038
+ className: "btn-clear col-xs-12",
3039
+ title: translateString(TranslatableString7.ClearButton),
3040
+ onClick,
3041
+ disabled,
3042
+ registry,
3043
+ ...props
3044
+ }
3045
+ );
3046
+ }
3011
3047
 
3012
3048
  // src/components/templates/ButtonTemplates/AddButton.tsx
3013
3049
  import { jsx as jsx21 } from "react/jsx-runtime";
@@ -3048,7 +3084,8 @@ function buttonTemplates() {
3048
3084
  CopyButton,
3049
3085
  MoveDownButton,
3050
3086
  MoveUpButton,
3051
- RemoveButton
3087
+ RemoveButton,
3088
+ ClearButton
3052
3089
  };
3053
3090
  }
3054
3091
  var ButtonTemplates_default = buttonTemplates;
@@ -3265,6 +3302,10 @@ function ObjectFieldTemplate(props) {
3265
3302
  registry,
3266
3303
  options
3267
3304
  );
3305
+ const isPureUnionSchema = (schema.oneOf || schema.anyOf) && !schema.properties && properties.length === 0;
3306
+ if (isPureUnionSchema) {
3307
+ return null;
3308
+ }
3268
3309
  const showOptionalDataControlInTitle = !readonly && !disabled;
3269
3310
  const {
3270
3311
  ButtonTemplates: { AddButton: AddButton2 }
@@ -4135,10 +4176,6 @@ function TextareaWidget({
4135
4176
  }
4136
4177
  );
4137
4178
  }
4138
- TextareaWidget.defaultProps = {
4139
- autofocus: false,
4140
- options: {}
4141
- };
4142
4179
  var TextareaWidget_default = TextareaWidget;
4143
4180
 
4144
4181
  // src/components/widgets/TextWidget.tsx
@@ -4239,6 +4276,10 @@ var Form = class extends Component3 {
4239
4276
  /** The list of pending changes
4240
4277
  */
4241
4278
  pendingChanges = [];
4279
+ /** Flag to track when we're processing a user-initiated field change.
4280
+ * This prevents componentDidUpdate from reverting oneOf/anyOf option switches.
4281
+ */
4282
+ _isProcessingUserChange = false;
4242
4283
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
4243
4284
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
4244
4285
  * state construction.
@@ -4315,7 +4356,13 @@ var Form = class extends Component3 {
4315
4356
  componentDidUpdate(_, prevState, snapshot) {
4316
4357
  if (snapshot.shouldUpdate) {
4317
4358
  const { nextState } = snapshot;
4318
- if (!deepEquals2(nextState.formData, this.props.formData) && !deepEquals2(nextState.formData, prevState.formData) && this.props.onChange) {
4359
+ const nextStateDiffersFromProps = !deepEquals2(nextState.formData, this.props.formData);
4360
+ const wasProcessingUserChange = this._isProcessingUserChange;
4361
+ this._isProcessingUserChange = false;
4362
+ if (wasProcessingUserChange && nextStateDiffersFromProps) {
4363
+ return;
4364
+ }
4365
+ if (nextStateDiffersFromProps && !deepEquals2(nextState.formData, prevState.formData) && this.props.onChange) {
4319
4366
  this.props.onChange(toIChangeEvent(nextState));
4320
4367
  }
4321
4368
  this.setState(nextState);
@@ -4551,60 +4598,30 @@ var Form = class extends Component3 {
4551
4598
  *
4552
4599
  * @param formData - The data for the `Form`
4553
4600
  * @param fields - The fields to keep while filtering
4601
+ * @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
4554
4602
  */
4555
4603
  getUsedFormData = (formData, fields2) => {
4556
- if (fields2.length === 0 && typeof formData !== "object") {
4557
- return formData;
4558
- }
4559
- const data = _pick(formData, fields2);
4560
- if (Array.isArray(formData)) {
4561
- return Object.keys(data).map((key) => data[key]);
4562
- }
4563
- return data;
4604
+ return getUsedFormData(formData, fields2);
4564
4605
  };
4565
4606
  /** Returns the list of field names from inspecting the `pathSchema` as well as using the `formData`
4566
4607
  *
4567
4608
  * @param pathSchema - The `PathSchema` object for the form
4568
4609
  * @param [formData] - The form data to use while checking for empty objects/arrays
4610
+ * @deprecated - To be removed as an exported `Form` function in a future release; there isn't a planned replacement
4569
4611
  */
4570
4612
  getFieldNames = (pathSchema, formData) => {
4571
- const formValueHasData = (value, isLeaf) => typeof value !== "object" || _isEmpty(value) || isLeaf && !_isEmpty(value);
4572
- const getAllPaths = (_obj, acc = [], paths = [[]]) => {
4573
- const objKeys = Object.keys(_obj);
4574
- objKeys.forEach((key) => {
4575
- const data = _obj[key];
4576
- if (typeof data === "object") {
4577
- const newPaths = paths.map((path) => [...path, key]);
4578
- if (data[RJSF_ADDITIONAL_PROPERTIES_FLAG] && data[NAME_KEY] !== "") {
4579
- acc.push(data[NAME_KEY]);
4580
- } else {
4581
- getAllPaths(data, acc, newPaths);
4582
- }
4583
- } else if (key === NAME_KEY && data !== "") {
4584
- paths.forEach((path) => {
4585
- const formValue = _get(formData, path);
4586
- const isLeaf = objKeys.length === 1;
4587
- if (formValueHasData(formValue, isLeaf) || Array.isArray(formValue) && formValue.every((val) => formValueHasData(val, isLeaf))) {
4588
- acc.push(path);
4589
- }
4590
- });
4591
- }
4592
- });
4593
- return acc;
4594
- };
4595
- return getAllPaths(pathSchema);
4613
+ return getFieldNames(pathSchema, formData);
4596
4614
  };
4597
4615
  /** Returns the `formData` after filtering to remove any extra data not in a form field
4598
4616
  *
4599
4617
  * @param formData - The data for the `Form`
4600
4618
  * @returns The `formData` after omitting extra data
4619
+ * @deprecated - To be removed as an exported `Form` function in a future release, use `SchemaUtils.omitExtraData`
4620
+ * instead.
4601
4621
  */
4602
4622
  omitExtraData = (formData) => {
4603
4623
  const { schema, schemaUtils } = this.state;
4604
- const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
4605
- const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
4606
- const fieldNames = this.getFieldNames(pathSchema, formData);
4607
- return this.getUsedFormData(formData, fieldNames);
4624
+ return schemaUtils.omitExtraData(schema, formData);
4608
4625
  };
4609
4626
  /** Allows a user to set a value for the provided `fieldPath`, which must be either a dotted path to the field OR a
4610
4627
  * `FieldPathList`. To set the root element, used either `''` or `[]` for the path. Passing undefined will clear the
@@ -4646,6 +4663,7 @@ var Form = class extends Component3 {
4646
4663
  if (this.pendingChanges.length === 0) {
4647
4664
  return;
4648
4665
  }
4666
+ this._isProcessingUserChange = true;
4649
4667
  const { newValue, path, id } = this.pendingChanges[0];
4650
4668
  const { newErrorSchema } = this.pendingChanges[0];
4651
4669
  const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
@@ -4655,13 +4673,16 @@ var Form = class extends Component3 {
4655
4673
  const isRootPath = !path || path.length === 0 || path.length === 1 && path[0] === rootPathId;
4656
4674
  let retrievedSchema = this.state.retrievedSchema;
4657
4675
  let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
4676
+ const hasOnlyUndefinedValues = isObject6(formData) && Object.keys(formData).length > 0 && Object.values(formData).every((v) => v === void 0);
4677
+ const wasPreviouslyNull = oldFormData === null || oldFormData === void 0;
4678
+ const inputForDefaults = hasOnlyUndefinedValues && wasPreviouslyNull ? void 0 : formData;
4658
4679
  if (isObject6(formData) || Array.isArray(formData)) {
4659
4680
  if (newValue === ADDITIONAL_PROPERTY_KEY_REMOVE) {
4660
4681
  _unset(formData, path);
4661
4682
  } else if (!isRootPath) {
4662
4683
  _set(formData, path, newValue);
4663
4684
  }
4664
- const newState = this.getStateFromProps(this.props, formData, void 0, void 0, void 0, true);
4685
+ const newState = this.getStateFromProps(this.props, inputForDefaults, void 0, void 0, void 0, true);
4665
4686
  formData = newState.formData;
4666
4687
  retrievedSchema = newState.retrievedSchema;
4667
4688
  }