@rjsf/core 6.0.0-beta.13 → 6.0.0-beta.15

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 (46) hide show
  1. package/dist/core.umd.js +243 -125
  2. package/dist/index.esm.js +285 -161
  3. package/dist/index.esm.js.map +3 -3
  4. package/dist/index.js +309 -186
  5. package/dist/index.js.map +3 -3
  6. package/lib/components/Form.d.ts +44 -13
  7. package/lib/components/Form.d.ts.map +1 -1
  8. package/lib/components/Form.js +84 -27
  9. package/lib/components/fields/ArrayField.d.ts +14 -4
  10. package/lib/components/fields/ArrayField.d.ts.map +1 -1
  11. package/lib/components/fields/ArrayField.js +73 -27
  12. package/lib/components/fields/BooleanField.d.ts.map +1 -1
  13. package/lib/components/fields/BooleanField.js +6 -1
  14. package/lib/components/fields/LayoutGridField.d.ts +19 -1
  15. package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
  16. package/lib/components/fields/LayoutGridField.js +62 -12
  17. package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
  18. package/lib/components/fields/LayoutMultiSchemaField.js +2 -1
  19. package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
  20. package/lib/components/fields/MultiSchemaField.js +2 -1
  21. package/lib/components/fields/NullField.js +3 -3
  22. package/lib/components/fields/NumberField.js +2 -2
  23. package/lib/components/fields/ObjectField.d.ts +2 -2
  24. package/lib/components/fields/ObjectField.d.ts.map +1 -1
  25. package/lib/components/fields/ObjectField.js +16 -19
  26. package/lib/components/fields/SchemaField.js +2 -2
  27. package/lib/components/fields/StringField.d.ts.map +1 -1
  28. package/lib/components/fields/StringField.js +6 -1
  29. package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
  30. package/lib/components/widgets/AltDateWidget.js +15 -18
  31. package/lib/components/widgets/CheckboxesWidget.js +2 -2
  32. package/lib/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +11 -12
  34. package/src/components/Form.tsx +99 -25
  35. package/src/components/fields/ArrayField.tsx +74 -28
  36. package/src/components/fields/BooleanField.tsx +10 -1
  37. package/src/components/fields/LayoutGridField.tsx +69 -11
  38. package/src/components/fields/LayoutMultiSchemaField.tsx +2 -1
  39. package/src/components/fields/MultiSchemaField.tsx +2 -1
  40. package/src/components/fields/NullField.tsx +3 -3
  41. package/src/components/fields/NumberField.tsx +2 -2
  42. package/src/components/fields/ObjectField.tsx +16 -26
  43. package/src/components/fields/SchemaField.tsx +2 -2
  44. package/src/components/fields/StringField.tsx +10 -1
  45. package/src/components/widgets/AltDateWidget.tsx +20 -22
  46. package/src/components/widgets/CheckboxesWidget.tsx +2 -2
package/dist/index.esm.js CHANGED
@@ -19,11 +19,13 @@ import {
19
19
  createErrorHandler,
20
20
  unwrapErrorHandler
21
21
  } from "@rjsf/utils";
22
+ import _cloneDeep from "lodash/cloneDeep";
22
23
  import _forEach from "lodash/forEach";
23
24
  import _get from "lodash/get";
24
25
  import _isEmpty from "lodash/isEmpty";
25
26
  import _isNil from "lodash/isNil";
26
27
  import _pick from "lodash/pick";
28
+ import _set from "lodash/set";
27
29
  import _toPath from "lodash/toPath";
28
30
 
29
31
  // src/getDefaultRegistry.ts
@@ -46,10 +48,10 @@ import cloneDeep from "lodash/cloneDeep";
46
48
  import get from "lodash/get";
47
49
  import isObject from "lodash/isObject";
48
50
  import set from "lodash/set";
49
- import { nanoid } from "nanoid";
51
+ import uniqueId from "lodash/uniqueId";
50
52
  import { jsx } from "react/jsx-runtime";
51
53
  function generateRowId() {
52
- return nanoid();
54
+ return uniqueId("rjsf-array-item-");
53
55
  }
54
56
  function generateKeyedFormData(formData) {
55
57
  return !Array.isArray(formData) ? [] : formData.map((item) => {
@@ -198,7 +200,8 @@ var ArrayField = class extends Component {
198
200
  keyedFormData: newKeyedFormData,
199
201
  updatedKeyedFormData: true
200
202
  },
201
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
203
+ // add click will pass the empty `path` array to the onChange which adds the appropriate path
204
+ () => onChange(keyedToPlainFormData(newKeyedFormData), [], newErrorSchema)
202
205
  );
203
206
  }
204
207
  /** Callback handler for when the user clicks on the add button. Creates a new row of keyed form data at the end of
@@ -261,7 +264,8 @@ var ArrayField = class extends Component {
261
264
  keyedFormData: newKeyedFormData,
262
265
  updatedKeyedFormData: true
263
266
  },
264
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
267
+ // Copy index will pass the empty `path` array to the onChange which adds the appropriate path
268
+ () => onChange(keyedToPlainFormData(newKeyedFormData), [], newErrorSchema)
265
269
  );
266
270
  };
267
271
  };
@@ -296,7 +300,8 @@ var ArrayField = class extends Component {
296
300
  keyedFormData: newKeyedFormData,
297
301
  updatedKeyedFormData: true
298
302
  },
299
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
303
+ // drop index will pass the empty `path` array to the onChange which adds the appropriate path
304
+ () => onChange(keyedToPlainFormData(newKeyedFormData), [], newErrorSchema)
300
305
  );
301
306
  };
302
307
  };
@@ -340,7 +345,8 @@ var ArrayField = class extends Component {
340
345
  {
341
346
  keyedFormData: newKeyedFormData
342
347
  },
343
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
348
+ // reorder click will pass the empty `path` array to the onChange which adds the appropriate path
349
+ () => onChange(keyedToPlainFormData(newKeyedFormData), [], newErrorSchema)
344
350
  );
345
351
  };
346
352
  };
@@ -350,19 +356,16 @@ var ArrayField = class extends Component {
350
356
  * @param index - The index of the item being changed
351
357
  */
352
358
  onChangeForIndex = (index) => {
353
- return (value, newErrorSchema, id) => {
354
- const { formData, onChange, errorSchema } = this.props;
355
- const arrayData = Array.isArray(formData) ? formData : [];
356
- const newFormData = arrayData.map((item, i) => {
357
- const jsonValue = typeof value === "undefined" ? null : value;
358
- return index === i ? jsonValue : item;
359
- });
359
+ return (value, path, newErrorSchema, id) => {
360
+ const { onChange } = this.props;
361
+ const changePath = Array.isArray(path) ? path.slice() : [];
362
+ changePath.unshift(index);
360
363
  onChange(
361
- newFormData,
362
- errorSchema && errorSchema && {
363
- ...errorSchema,
364
- [index]: newErrorSchema
365
- },
364
+ // We need to treat undefined items as nulls to have validation.
365
+ // See https://github.com/tdegrunt/jsonschema/issues/206
366
+ value === void 0 ? null : value,
367
+ changePath,
368
+ newErrorSchema,
366
369
  id
367
370
  );
368
371
  };
@@ -370,8 +373,30 @@ var ArrayField = class extends Component {
370
373
  /** Callback handler used to change the value for a checkbox */
371
374
  onSelectChange = (value) => {
372
375
  const { onChange, idSchema } = this.props;
373
- onChange(value, void 0, idSchema && idSchema.$id);
376
+ onChange(value, [], void 0, idSchema && idSchema.$id);
374
377
  };
378
+ /** Helper method to compute item UI schema for both normal and fixed arrays
379
+ * Handles both static object and dynamic function cases
380
+ *
381
+ * @param uiSchema - The parent UI schema containing items definition
382
+ * @param item - The item data
383
+ * @param index - The index of the item
384
+ * @param formContext - The form context
385
+ * @returns The computed UI schema for the item
386
+ */
387
+ computeItemUiSchema(uiSchema, item, index, formContext) {
388
+ if (typeof uiSchema.items === "function") {
389
+ try {
390
+ const result = uiSchema.items(item, index, formContext);
391
+ return result;
392
+ } catch (e) {
393
+ console.error(`Error executing dynamic uiSchema.items function for item at index ${index}:`, e);
394
+ return void 0;
395
+ }
396
+ } else {
397
+ return uiSchema.items;
398
+ }
399
+ }
375
400
  /** Renders the `ArrayField` depending on the specific needs of the schema and uischema elements
376
401
  */
377
402
  render() {
@@ -446,6 +471,7 @@ var ArrayField = class extends Component {
446
471
  const itemErrorSchema = errorSchema ? errorSchema[index] : void 0;
447
472
  const itemIdPrefix = idSchema.$id + idSeparator + index;
448
473
  const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
474
+ const itemUiSchema = this.computeItemUiSchema(uiSchema, item, index, formContext);
449
475
  return this.renderArrayFieldItem({
450
476
  key,
451
477
  index,
@@ -458,7 +484,7 @@ var ArrayField = class extends Component {
458
484
  itemIdSchema,
459
485
  itemErrorSchema,
460
486
  itemData: itemCast,
461
- itemUiSchema: uiSchema.items,
487
+ itemUiSchema,
462
488
  autofocus: autofocus && index === 0,
463
489
  onBlur,
464
490
  onFocus,
@@ -685,7 +711,16 @@ var ArrayField = class extends Component {
685
711
  const itemSchema = (additional && isObject(schema.additionalItems) ? schemaUtils.retrieveSchema(schema.additionalItems, itemCast) : itemSchemas[index]) || {};
686
712
  const itemIdPrefix = idSchema.$id + idSeparator + index;
687
713
  const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
688
- const itemUiSchema = additional ? uiSchema.additionalItems || {} : Array.isArray(uiSchema.items) ? uiSchema.items[index] : uiSchema.items || {};
714
+ let itemUiSchema;
715
+ if (additional) {
716
+ itemUiSchema = uiSchema.additionalItems;
717
+ } else {
718
+ if (Array.isArray(uiSchema.items)) {
719
+ itemUiSchema = uiSchema.items[index];
720
+ } else {
721
+ itemUiSchema = this.computeItemUiSchema(uiSchema, item, index, formContext);
722
+ }
723
+ }
689
724
  const itemErrorSchema = errorSchema ? errorSchema[index] : void 0;
690
725
  return this.renderArrayFieldItem({
691
726
  key,
@@ -825,6 +860,7 @@ var ArrayField = class extends Component {
825
860
  var ArrayField_default = ArrayField;
826
861
 
827
862
  // src/components/fields/BooleanField.tsx
863
+ import { useCallback } from "react";
828
864
  import {
829
865
  getWidget as getWidget2,
830
866
  getUiOptions as getUiOptions2,
@@ -900,6 +936,12 @@ function BooleanField(props) {
900
936
  enumOptions = optionsList2({ enum: enums }, uiSchema);
901
937
  }
902
938
  }
939
+ const onWidgetChange = useCallback(
940
+ (value, errorSchema, id) => {
941
+ return onChange(value, [], errorSchema, id);
942
+ },
943
+ [onChange]
944
+ );
903
945
  return /* @__PURE__ */ jsx2(
904
946
  Widget,
905
947
  {
@@ -908,7 +950,7 @@ function BooleanField(props) {
908
950
  uiSchema,
909
951
  id: idSchema.$id,
910
952
  name,
911
- onChange,
953
+ onChange: onWidgetChange,
912
954
  onFocus,
913
955
  onBlur,
914
956
  label,
@@ -943,7 +985,8 @@ import {
943
985
  PROPERTIES_KEY,
944
986
  READONLY_KEY,
945
987
  UI_OPTIONS_KEY,
946
- UI_GLOBAL_OPTIONS_KEY
988
+ UI_GLOBAL_OPTIONS_KEY,
989
+ ITEMS_KEY as ITEMS_KEY2
947
990
  } from "@rjsf/utils";
948
991
  import cloneDeep2 from "lodash/cloneDeep";
949
992
  import each from "lodash/each";
@@ -959,6 +1002,7 @@ import isObject3 from "lodash/isObject";
959
1002
  import isPlainObject from "lodash/isPlainObject";
960
1003
  import isString from "lodash/isString";
961
1004
  import isUndefined from "lodash/isUndefined";
1005
+ import last from "lodash/last";
962
1006
  import set2 from "lodash/set";
963
1007
  import { jsx as jsx3 } from "react/jsx-runtime";
964
1008
  import { createElement } from "react";
@@ -968,6 +1012,9 @@ var LAYOUT_GRID_OPTION = `ui:${LAYOUT_GRID_UI_OPTION}`;
968
1012
  function getNonNullishValue(value, fallback) {
969
1013
  return value ?? fallback;
970
1014
  }
1015
+ function isNumericIndex(str) {
1016
+ return /^\d+?$/.test(str);
1017
+ }
971
1018
  var LayoutGridField = class _LayoutGridField extends PureComponent {
972
1019
  static defaultProps = {
973
1020
  layoutGridSchema: void 0
@@ -1081,6 +1128,38 @@ var LayoutGridField = class _LayoutGridField extends PureComponent {
1081
1128
  const baseId = get2(baseIdSchema, ID_KEY);
1082
1129
  return schemaUtils.toIdSchema(schema, baseId, formData, baseId, idSeparator);
1083
1130
  }
1131
+ /** Computes the `rawSchema` and `idSchema` for a `schema` and a `potentialIndex`. If the `schema` is of type array,
1132
+ * has an `ITEMS_KEY` element and `potentialIndex` represents a numeric value, the element at `ITEMS_KEY` is checked
1133
+ * to see if it is an array. If it is AND the `potentialIndex`th element is available, it is used as the `rawSchema`,
1134
+ * otherwise the last value of the element is used. If it is not, then the element is used as the `rawSchema`. In
1135
+ * either case, an `idSchema` is computed for the array index. If the `schema` does not represent an array or the
1136
+ * `potentialIndex` is not a numeric value, then `rawSchema` is returned as undefined and given `idSchema` is returned
1137
+ * as is.
1138
+ *
1139
+ * @param schema - The schema to generate the idSchema for
1140
+ * @param idSchema - The IdSchema for the schema
1141
+ * @param potentialIndex - A string containing a potential index
1142
+ * @param [idSeparator] - The param to pass into the `toIdSchema` util which will use it to join the `idSchema` paths
1143
+ * @returns - An object containing the `rawSchema` and `idSchema` of an array item, otherwise an undefined `rawSchema`
1144
+ */
1145
+ static computeArraySchemasIfPresent(schema, idSchema, potentialIndex, idSeparator) {
1146
+ let rawSchema;
1147
+ if (isNumericIndex(potentialIndex) && schema && schema?.type === "array" && has(schema, ITEMS_KEY2)) {
1148
+ const index = Number(potentialIndex);
1149
+ const items = schema[ITEMS_KEY2];
1150
+ if (Array.isArray(items)) {
1151
+ if (index > items.length) {
1152
+ rawSchema = last(items);
1153
+ } else {
1154
+ rawSchema = items[index];
1155
+ }
1156
+ } else {
1157
+ rawSchema = items;
1158
+ }
1159
+ idSchema = { [ID_KEY]: `${idSchema[ID_KEY]}${idSeparator ?? "_"}${index}` };
1160
+ }
1161
+ return { rawSchema, idSchema };
1162
+ }
1084
1163
  /** Given a `dottedPath` to a field in the `initialSchema`, iterate through each individual path in the schema until
1085
1164
  * the leaf path is found and returned (along with whether that leaf path `isRequired`) OR no schema exists for an
1086
1165
  * element in the path. If the leaf schema element happens to be a oneOf/anyOf then also return the oneOf/anyOf as
@@ -1120,7 +1199,9 @@ var LayoutGridField = class _LayoutGridField extends PureComponent {
1120
1199
  rawSchema = get2(selectedSchema, [PROPERTIES_KEY, part], {});
1121
1200
  idSchema = get2(selectedIdSchema, part, {});
1122
1201
  } else {
1123
- rawSchema = {};
1202
+ const result = _LayoutGridField.computeArraySchemasIfPresent(schema, idSchema, part, idSeparator);
1203
+ rawSchema = result.rawSchema ?? {};
1204
+ idSchema = result.idSchema;
1124
1205
  }
1125
1206
  innerData = get2(innerData, part, {});
1126
1207
  schema = schemaUtils.retrieveSchema(rawSchema, innerData);
@@ -1139,9 +1220,15 @@ var LayoutGridField = class _LayoutGridField extends PureComponent {
1139
1220
  idSchema = mergeObjects(rawIdSchema, idSchema);
1140
1221
  }
1141
1222
  isRequired = schema !== void 0 && Array.isArray(schema.required) && includes(schema.required, leafPath);
1142
- schema = get2(schema, [PROPERTIES_KEY, leafPath]);
1143
- schema = schema ? schemaUtils.retrieveSchema(schema) : schema;
1144
- idSchema = get2(idSchema, leafPath, {});
1223
+ const result = _LayoutGridField.computeArraySchemasIfPresent(schema, idSchema, leafPath, idSeparator);
1224
+ if (result.rawSchema) {
1225
+ schema = result.rawSchema;
1226
+ idSchema = result.idSchema;
1227
+ } else {
1228
+ schema = get2(schema, [PROPERTIES_KEY, leafPath]);
1229
+ schema = schema ? schemaUtils.retrieveSchema(schema) : schema;
1230
+ idSchema = get2(idSchema, leafPath, {});
1231
+ }
1145
1232
  isReadonly = getNonNullishValue(schema?.readOnly, isReadonly);
1146
1233
  if (schema && (has(schema, ONE_OF_KEY) || has(schema, ANY_OF_KEY))) {
1147
1234
  const xxx = has(schema, ONE_OF_KEY) ? ONE_OF_KEY : ANY_OF_KEY;
@@ -1221,16 +1308,14 @@ var LayoutGridField = class _LayoutGridField extends PureComponent {
1221
1308
  * @returns - The `onChange` handling function for the `dottedPath` field
1222
1309
  */
1223
1310
  onFieldChange = (dottedPath) => {
1224
- return (value, errSchema, id) => {
1225
- const { onChange, errorSchema, formData } = this.props;
1226
- const newFormData = cloneDeep2(formData || {});
1311
+ return (value, path, errSchema, id) => {
1312
+ const { onChange, errorSchema } = this.props;
1227
1313
  let newErrorSchema = errorSchema;
1228
1314
  if (errSchema && errorSchema) {
1229
1315
  newErrorSchema = cloneDeep2(errorSchema);
1230
1316
  set2(newErrorSchema, dottedPath, errSchema);
1231
1317
  }
1232
- set2(newFormData, dottedPath, value);
1233
- onChange(newFormData, newErrorSchema, id);
1318
+ onChange(value, dottedPath.split("."), newErrorSchema, id);
1234
1319
  };
1235
1320
  };
1236
1321
  /** Renders the `children` of the `GridType.CONDITION` if it passes. The `layoutGridSchema` for the
@@ -1625,7 +1710,7 @@ function LayoutMultiSchemaField(props) {
1625
1710
  if (newFormData) {
1626
1711
  set3(newFormData, selectorField, opt);
1627
1712
  }
1628
- onChange(newFormData, void 0, id);
1713
+ onChange(newFormData, [name], void 0, id);
1629
1714
  };
1630
1715
  const widgetOptions = { enumOptions, ...uiOptions };
1631
1716
  const errors = !hideFieldError && rawErrors.length > 0 ? /* @__PURE__ */ jsx5(FieldErrorTemplate2, { idSchema, schema, errors: rawErrors, registry }) : void 0;
@@ -1778,7 +1863,7 @@ var AnyOfField = class extends Component2 {
1778
1863
  newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
1779
1864
  }
1780
1865
  this.setState({ selectedOption: intOption }, () => {
1781
- onChange(newFormData, void 0, this.getFieldId());
1866
+ onChange(newFormData, [], void 0, this.getFieldId());
1782
1867
  });
1783
1868
  };
1784
1869
  getFieldId() {
@@ -1894,7 +1979,7 @@ var AnyOfField = class extends Component2 {
1894
1979
  var MultiSchemaField_default = AnyOfField;
1895
1980
 
1896
1981
  // src/components/fields/NumberField.tsx
1897
- import { useState as useState2, useCallback } from "react";
1982
+ import { useState as useState2, useCallback as useCallback2 } from "react";
1898
1983
  import { asNumber } from "@rjsf/utils";
1899
1984
  import { jsx as jsx7 } from "react/jsx-runtime";
1900
1985
  var trailingCharMatcherWithPrefix = /\.([0-9]*0)*$/;
@@ -1904,14 +1989,14 @@ function NumberField(props) {
1904
1989
  const [lastValue, setLastValue] = useState2(initialValue);
1905
1990
  const { StringField: StringField2 } = registry.fields;
1906
1991
  let value = formData;
1907
- const handleChange = useCallback(
1908
- (value2, errorSchema, id) => {
1992
+ const handleChange = useCallback2(
1993
+ (value2, path, errorSchema, id) => {
1909
1994
  setLastValue(value2);
1910
1995
  if (`${value2}`.charAt(0) === ".") {
1911
1996
  value2 = `0${value2}`;
1912
1997
  }
1913
1998
  const processed = typeof value2 === "string" && value2.match(trailingCharMatcherWithPrefix) ? asNumber(value2.replace(trailingCharMatcher, "")) : asNumber(value2);
1914
- onChange(processed, errorSchema, id);
1999
+ onChange(processed, path, errorSchema, id);
1915
2000
  },
1916
2001
  [onChange]
1917
2002
  );
@@ -1969,20 +2054,14 @@ var ObjectField = class extends Component3 {
1969
2054
  * @returns - The onPropertyChange callback for the `name` property
1970
2055
  */
1971
2056
  onPropertyChange = (name, addedByAdditionalProperties = false) => {
1972
- return (value, newErrorSchema, id) => {
1973
- const { formData, onChange, errorSchema } = this.props;
2057
+ return (value, path, newErrorSchema, id) => {
2058
+ const { onChange } = this.props;
1974
2059
  if (value === void 0 && addedByAdditionalProperties) {
1975
2060
  value = "";
1976
2061
  }
1977
- const newFormData = { ...formData, [name]: value };
1978
- onChange(
1979
- newFormData,
1980
- errorSchema && errorSchema && {
1981
- ...errorSchema,
1982
- [name]: newErrorSchema
1983
- },
1984
- id
1985
- );
2062
+ const changePath = Array.isArray(path) ? path.slice() : [];
2063
+ changePath.unshift(name);
2064
+ onChange(value, changePath, newErrorSchema, id);
1986
2065
  };
1987
2066
  };
1988
2067
  /** Returns a callback to handle the onDropPropertyClick event for the given `key` which removes the old `key` data
@@ -1994,10 +2073,10 @@ var ObjectField = class extends Component3 {
1994
2073
  onDropPropertyClick = (key) => {
1995
2074
  return (event) => {
1996
2075
  event.preventDefault();
1997
- const { onChange, formData } = this.props;
2076
+ const { onChange, formData, name } = this.props;
1998
2077
  const copiedFormData = { ...formData };
1999
2078
  unset(copiedFormData, key);
2000
- onChange(copiedFormData);
2079
+ onChange(copiedFormData, [name]);
2001
2080
  };
2002
2081
  };
2003
2082
  /** Computes the next available key name from the `preferredKey`, indexing through the already existing keys until one
@@ -2024,11 +2103,11 @@ var ObjectField = class extends Component3 {
2024
2103
  * @returns - The key change callback function
2025
2104
  */
2026
2105
  onKeyChange = (oldValue) => {
2027
- return (value, newErrorSchema) => {
2106
+ return (value) => {
2028
2107
  if (oldValue === value) {
2029
2108
  return;
2030
2109
  }
2031
- const { formData, onChange, errorSchema } = this.props;
2110
+ const { formData, onChange } = this.props;
2032
2111
  value = this.getAvailableKey(value, formData);
2033
2112
  const newFormData = {
2034
2113
  ...formData
@@ -2040,13 +2119,7 @@ var ObjectField = class extends Component3 {
2040
2119
  });
2041
2120
  const renamedObj = Object.assign({}, ...keyValues);
2042
2121
  this.setState({ wasPropertyKeyModified: true });
2043
- onChange(
2044
- renamedObj,
2045
- errorSchema && errorSchema && {
2046
- ...errorSchema,
2047
- [value]: newErrorSchema
2048
- }
2049
- );
2122
+ onChange(renamedObj, []);
2050
2123
  };
2051
2124
  };
2052
2125
  /** Returns a default value to be used for a new additional schema property of the given `type`
@@ -2082,7 +2155,7 @@ var ObjectField = class extends Component3 {
2082
2155
  if (!(schema.additionalProperties || schema.patternProperties)) {
2083
2156
  return;
2084
2157
  }
2085
- const { formData, onChange, registry } = this.props;
2158
+ const { formData, name, onChange, registry } = this.props;
2086
2159
  const newFormData = { ...formData };
2087
2160
  const newKey = this.getAvailableKey("newKey", newFormData);
2088
2161
  if (schema.patternProperties) {
@@ -2110,7 +2183,7 @@ var ObjectField = class extends Component3 {
2110
2183
  const newValue = constValue ?? defaultValue ?? this.getDefaultValue(type);
2111
2184
  set4(newFormData, newKey, newValue);
2112
2185
  }
2113
- onChange(newFormData);
2186
+ onChange(newFormData, [name]);
2114
2187
  };
2115
2188
  /** Renders the `ObjectField` from the given props
2116
2189
  */
@@ -2211,7 +2284,7 @@ var ObjectField = class extends Component3 {
2211
2284
  var ObjectField_default = ObjectField;
2212
2285
 
2213
2286
  // src/components/fields/SchemaField.tsx
2214
- import { useCallback as useCallback2, Component as Component4 } from "react";
2287
+ import { useCallback as useCallback3, Component as Component4 } from "react";
2215
2288
  import {
2216
2289
  ADDITIONAL_PROPERTY_FLAG as ADDITIONAL_PROPERTY_FLAG2,
2217
2290
  descriptionId,
@@ -2305,10 +2378,10 @@ function SchemaFieldRender(props) {
2305
2378
  schemaUtils.toIdSchema(schema, fieldId, formData, idPrefix, idSeparator),
2306
2379
  _idSchema
2307
2380
  );
2308
- const handleFieldComponentChange = useCallback2(
2309
- (formData2, newErrorSchema, id2) => {
2381
+ const handleFieldComponentChange = useCallback3(
2382
+ (formData2, path, newErrorSchema, id2) => {
2310
2383
  const theId = id2 || fieldId;
2311
- return onChange(formData2, newErrorSchema, theId);
2384
+ return onChange(formData2, path, newErrorSchema, theId);
2312
2385
  },
2313
2386
  [fieldId, onChange]
2314
2387
  );
@@ -2487,6 +2560,7 @@ var SchemaField = class extends Component4 {
2487
2560
  var SchemaField_default = SchemaField;
2488
2561
 
2489
2562
  // src/components/fields/StringField.tsx
2563
+ import { useCallback as useCallback4 } from "react";
2490
2564
  import {
2491
2565
  getWidget as getWidget5,
2492
2566
  getUiOptions as getUiOptions9,
@@ -2523,6 +2597,12 @@ function StringField(props) {
2523
2597
  const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
2524
2598
  const label = uiTitle ?? title ?? name;
2525
2599
  const Widget = getWidget5(schema, widget, widgets2);
2600
+ const onWidgetChange = useCallback4(
2601
+ (value, errorSchema, id) => {
2602
+ return onChange(value, [], errorSchema, id);
2603
+ },
2604
+ [onChange]
2605
+ );
2526
2606
  return /* @__PURE__ */ jsx10(
2527
2607
  Widget,
2528
2608
  {
@@ -2535,7 +2615,7 @@ function StringField(props) {
2535
2615
  hideLabel: !displayLabel,
2536
2616
  hideError,
2537
2617
  value: formData,
2538
- onChange,
2618
+ onChange: onWidgetChange,
2539
2619
  onBlur,
2540
2620
  onFocus,
2541
2621
  required,
@@ -2554,12 +2634,12 @@ var StringField_default = StringField;
2554
2634
  // src/components/fields/NullField.tsx
2555
2635
  import { useEffect as useEffect2 } from "react";
2556
2636
  function NullField(props) {
2557
- const { formData, onChange } = props;
2637
+ const { name, formData, onChange } = props;
2558
2638
  useEffect2(() => {
2559
2639
  if (formData === void 0) {
2560
- onChange(null);
2640
+ onChange(null, [name]);
2561
2641
  }
2562
- }, [formData, onChange]);
2642
+ }, [name, formData, onChange]);
2563
2643
  return null;
2564
2644
  }
2565
2645
  var NullField_default = NullField;
@@ -2837,7 +2917,7 @@ function ArrayFieldTitleTemplate(props) {
2837
2917
  }
2838
2918
 
2839
2919
  // src/components/templates/BaseInputTemplate.tsx
2840
- import { useCallback as useCallback3 } from "react";
2920
+ import { useCallback as useCallback5 } from "react";
2841
2921
  import {
2842
2922
  ariaDescribedByIds,
2843
2923
  examplesId,
@@ -2884,15 +2964,15 @@ function BaseInputTemplate(props) {
2884
2964
  } else {
2885
2965
  inputValue = value == null ? "" : value;
2886
2966
  }
2887
- const _onChange = useCallback3(
2967
+ const _onChange = useCallback5(
2888
2968
  ({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
2889
2969
  [onChange, options]
2890
2970
  );
2891
- const _onBlur = useCallback3(
2971
+ const _onBlur = useCallback5(
2892
2972
  ({ target }) => onBlur(id, target && target.value),
2893
2973
  [onBlur, id]
2894
2974
  );
2895
- const _onFocus = useCallback3(
2975
+ const _onFocus = useCallback5(
2896
2976
  ({ target }) => onFocus(id, target && target.value),
2897
2977
  [onFocus, id]
2898
2978
  );
@@ -3340,7 +3420,7 @@ function templates() {
3340
3420
  var templates_default = templates;
3341
3421
 
3342
3422
  // src/components/widgets/AltDateWidget.tsx
3343
- import { useCallback as useCallback4, useEffect as useEffect3, useReducer, useState as useState3 } from "react";
3423
+ import { useCallback as useCallback6, useEffect as useEffect3, useState as useState3 } from "react";
3344
3424
  import {
3345
3425
  ariaDescribedByIds as ariaDescribedByIds2,
3346
3426
  dateRangeOptions,
@@ -3406,26 +3486,25 @@ function AltDateWidget({
3406
3486
  value
3407
3487
  }) {
3408
3488
  const { translateString } = registry;
3409
- const [lastValue, setLastValue] = useState3(value);
3410
- const [state, setState] = useReducer(
3411
- (state2, action) => {
3412
- return { ...state2, ...action };
3489
+ const [state, setState] = useState3(parseDateString(value, time));
3490
+ useEffect3(() => {
3491
+ setState(parseDateString(value, time));
3492
+ }, [time, value]);
3493
+ const handleChange = useCallback6(
3494
+ (property, value2) => {
3495
+ const nextState = {
3496
+ ...state,
3497
+ [property]: typeof value2 === "undefined" ? -1 : value2
3498
+ };
3499
+ if (readyForChange(nextState)) {
3500
+ onChange(toDateString(nextState, time));
3501
+ } else {
3502
+ setState(nextState);
3503
+ }
3413
3504
  },
3414
- parseDateString(value, time)
3505
+ [state, onChange, time]
3415
3506
  );
3416
- useEffect3(() => {
3417
- const stateValue = toDateString(state, time);
3418
- if (readyForChange(state) && stateValue !== value) {
3419
- onChange(stateValue);
3420
- } else if (lastValue !== value) {
3421
- setLastValue(value);
3422
- setState(parseDateString(value, time));
3423
- }
3424
- }, [time, value, onChange, state, lastValue]);
3425
- const handleChange = useCallback4((property, value2) => {
3426
- setState({ [property]: value2 });
3427
- }, []);
3428
- const handleSetNow = useCallback4(
3507
+ const handleSetNow = useCallback6(
3429
3508
  (event) => {
3430
3509
  event.preventDefault();
3431
3510
  if (disabled || readonly) {
@@ -3434,9 +3513,9 @@ function AltDateWidget({
3434
3513
  const nextState = parseDateString((/* @__PURE__ */ new Date()).toJSON(), time);
3435
3514
  onChange(toDateString(nextState, time));
3436
3515
  },
3437
- [disabled, readonly, time]
3516
+ [disabled, readonly, time, onChange]
3438
3517
  );
3439
- const handleClear = useCallback4(
3518
+ const handleClear = useCallback6(
3440
3519
  (event) => {
3441
3520
  event.preventDefault();
3442
3521
  if (disabled || readonly) {
@@ -3485,7 +3564,7 @@ function AltDateTimeWidget({
3485
3564
  var AltDateTimeWidget_default = AltDateTimeWidget;
3486
3565
 
3487
3566
  // src/components/widgets/CheckboxWidget.tsx
3488
- import { useCallback as useCallback5 } from "react";
3567
+ import { useCallback as useCallback7 } from "react";
3489
3568
  import {
3490
3569
  ariaDescribedByIds as ariaDescribedByIds3,
3491
3570
  descriptionId as descriptionId4,
@@ -3516,15 +3595,15 @@ function CheckboxWidget({
3516
3595
  options
3517
3596
  );
3518
3597
  const required = schemaRequiresTrueValue(schema);
3519
- const handleChange = useCallback5(
3598
+ const handleChange = useCallback7(
3520
3599
  (event) => onChange(event.target.checked),
3521
3600
  [onChange]
3522
3601
  );
3523
- const handleBlur = useCallback5(
3602
+ const handleBlur = useCallback7(
3524
3603
  (event) => onBlur(id, event.target.checked),
3525
3604
  [onBlur, id]
3526
3605
  );
3527
- const handleFocus = useCallback5(
3606
+ const handleFocus = useCallback7(
3528
3607
  (event) => onFocus(id, event.target.checked),
3529
3608
  [onFocus, id]
3530
3609
  );
@@ -3564,7 +3643,7 @@ function CheckboxWidget({
3564
3643
  var CheckboxWidget_default = CheckboxWidget;
3565
3644
 
3566
3645
  // src/components/widgets/CheckboxesWidget.tsx
3567
- import { useCallback as useCallback6 } from "react";
3646
+ import { useCallback as useCallback8 } from "react";
3568
3647
  import {
3569
3648
  ariaDescribedByIds as ariaDescribedByIds4,
3570
3649
  enumOptionsDeselectValue,
@@ -3586,13 +3665,13 @@ function CheckboxesWidget({
3586
3665
  onFocus
3587
3666
  }) {
3588
3667
  const checkboxesValues = Array.isArray(value) ? value : [value];
3589
- const handleBlur = useCallback6(
3668
+ const handleBlur = useCallback8(
3590
3669
  ({ target }) => onBlur(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
3591
- [onBlur, id]
3670
+ [onBlur, id, enumOptions, emptyValue]
3592
3671
  );
3593
- const handleFocus = useCallback6(
3672
+ const handleFocus = useCallback8(
3594
3673
  ({ target }) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
3595
- [onFocus, id]
3674
+ [onFocus, id, enumOptions, emptyValue]
3596
3675
  );
3597
3676
  return /* @__PURE__ */ jsx36("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
3598
3677
  const checked = enumOptionsIsSelected(option.value, checkboxesValues);
@@ -3639,13 +3718,13 @@ function ColorWidget(props) {
3639
3718
  }
3640
3719
 
3641
3720
  // src/components/widgets/DateWidget.tsx
3642
- import { useCallback as useCallback7 } from "react";
3721
+ import { useCallback as useCallback9 } from "react";
3643
3722
  import { getTemplate as getTemplate16 } from "@rjsf/utils";
3644
3723
  import { jsx as jsx38 } from "react/jsx-runtime";
3645
3724
  function DateWidget(props) {
3646
3725
  const { onChange, options, registry } = props;
3647
3726
  const BaseInputTemplate2 = getTemplate16("BaseInputTemplate", registry, options);
3648
- const handleChange = useCallback7((value) => onChange(value || void 0), [onChange]);
3727
+ const handleChange = useCallback9((value) => onChange(value || void 0), [onChange]);
3649
3728
  return /* @__PURE__ */ jsx38(BaseInputTemplate2, { type: "date", ...props, onChange: handleChange });
3650
3729
  }
3651
3730
 
@@ -3680,7 +3759,7 @@ function EmailWidget(props) {
3680
3759
  }
3681
3760
 
3682
3761
  // src/components/widgets/FileWidget.tsx
3683
- import { useCallback as useCallback8, useMemo as useMemo2 } from "react";
3762
+ import { useCallback as useCallback10, useMemo as useMemo2 } from "react";
3684
3763
  import {
3685
3764
  dataURItoBlob,
3686
3765
  getTemplate as getTemplate19,
@@ -3785,7 +3864,7 @@ function extractFileInfo(dataURLs) {
3785
3864
  function FileWidget(props) {
3786
3865
  const { disabled, readonly, required, multiple, onChange, value, options, registry } = props;
3787
3866
  const BaseInputTemplate2 = getTemplate19("BaseInputTemplate", registry, options);
3788
- const handleChange = useCallback8(
3867
+ const handleChange = useCallback10(
3789
3868
  (event) => {
3790
3869
  if (!event.target.files) {
3791
3870
  return;
@@ -3802,7 +3881,7 @@ function FileWidget(props) {
3802
3881
  [multiple, value, onChange]
3803
3882
  );
3804
3883
  const filesInfo = useMemo2(() => extractFileInfo(Array.isArray(value) ? value : [value]), [value]);
3805
- const rmFile = useCallback8(
3884
+ const rmFile = useCallback10(
3806
3885
  (index) => {
3807
3886
  if (multiple) {
3808
3887
  const newValue = value.filter((_, i) => i !== index);
@@ -3860,7 +3939,7 @@ function PasswordWidget(props) {
3860
3939
  }
3861
3940
 
3862
3941
  // src/components/widgets/RadioWidget.tsx
3863
- import { useCallback as useCallback9 } from "react";
3942
+ import { useCallback as useCallback11 } from "react";
3864
3943
  import {
3865
3944
  ariaDescribedByIds as ariaDescribedByIds5,
3866
3945
  enumOptionsIsSelected as enumOptionsIsSelected2,
@@ -3881,11 +3960,11 @@ function RadioWidget({
3881
3960
  id
3882
3961
  }) {
3883
3962
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
3884
- const handleBlur = useCallback9(
3963
+ const handleBlur = useCallback11(
3885
3964
  ({ target }) => onBlur(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
3886
3965
  [onBlur, enumOptions, emptyValue, id]
3887
3966
  );
3888
- const handleFocus = useCallback9(
3967
+ const handleFocus = useCallback11(
3889
3968
  ({ target }) => onFocus(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
3890
3969
  [onFocus, enumOptions, emptyValue, id]
3891
3970
  );
@@ -3935,7 +4014,7 @@ function RangeWidget(props) {
3935
4014
  }
3936
4015
 
3937
4016
  // src/components/widgets/RatingWidget.tsx
3938
- import { useCallback as useCallback10 } from "react";
4017
+ import { useCallback as useCallback12 } from "react";
3939
4018
  import { Fragment as Fragment5, jsx as jsx46, jsxs as jsxs21 } from "react/jsx-runtime";
3940
4019
  function RatingWidget({
3941
4020
  id,
@@ -3953,7 +4032,7 @@ function RatingWidget({
3953
4032
  const { stars = 5, shape = "star" } = options;
3954
4033
  const numStars = schema.maximum ? Math.min(schema.maximum, 5) : Math.min(Math.max(stars, 1), 5);
3955
4034
  const min = schema.minimum || 0;
3956
- const handleStarClick = useCallback10(
4035
+ const handleStarClick = useCallback12(
3957
4036
  (starValue) => {
3958
4037
  if (!disabled && !readonly) {
3959
4038
  onChange(starValue);
@@ -3961,7 +4040,7 @@ function RatingWidget({
3961
4040
  },
3962
4041
  [onChange, disabled, readonly]
3963
4042
  );
3964
- const handleFocus = useCallback10(
4043
+ const handleFocus = useCallback12(
3965
4044
  (event) => {
3966
4045
  if (onFocus) {
3967
4046
  const starValue = Number(event.target.dataset.value);
@@ -3970,7 +4049,7 @@ function RatingWidget({
3970
4049
  },
3971
4050
  [onFocus, id]
3972
4051
  );
3973
- const handleBlur = useCallback10(
4052
+ const handleBlur = useCallback12(
3974
4053
  (event) => {
3975
4054
  if (onBlur) {
3976
4055
  const starValue = Number(event.target.dataset.value);
@@ -4038,7 +4117,7 @@ function RatingWidget({
4038
4117
  }
4039
4118
 
4040
4119
  // src/components/widgets/SelectWidget.tsx
4041
- import { useCallback as useCallback11 } from "react";
4120
+ import { useCallback as useCallback13 } from "react";
4042
4121
  import {
4043
4122
  ariaDescribedByIds as ariaDescribedByIds6,
4044
4123
  enumOptionsIndexForValue,
@@ -4068,21 +4147,21 @@ function SelectWidget({
4068
4147
  }) {
4069
4148
  const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options;
4070
4149
  const emptyValue = multiple ? [] : "";
4071
- const handleFocus = useCallback11(
4150
+ const handleFocus = useCallback13(
4072
4151
  (event) => {
4073
4152
  const newValue = getValue(event, multiple);
4074
4153
  return onFocus(id, enumOptionsValueForIndex3(newValue, enumOptions, optEmptyVal));
4075
4154
  },
4076
4155
  [onFocus, id, multiple, enumOptions, optEmptyVal]
4077
4156
  );
4078
- const handleBlur = useCallback11(
4157
+ const handleBlur = useCallback13(
4079
4158
  (event) => {
4080
4159
  const newValue = getValue(event, multiple);
4081
4160
  return onBlur(id, enumOptionsValueForIndex3(newValue, enumOptions, optEmptyVal));
4082
4161
  },
4083
4162
  [onBlur, id, multiple, enumOptions, optEmptyVal]
4084
4163
  );
4085
- const handleChange = useCallback11(
4164
+ const handleChange = useCallback13(
4086
4165
  (event) => {
4087
4166
  const newValue = getValue(event, multiple);
4088
4167
  return onChange(enumOptionsValueForIndex3(newValue, enumOptions, optEmptyVal));
@@ -4120,7 +4199,7 @@ function SelectWidget({
4120
4199
  var SelectWidget_default = SelectWidget;
4121
4200
 
4122
4201
  // src/components/widgets/TextareaWidget.tsx
4123
- import { useCallback as useCallback12 } from "react";
4202
+ import { useCallback as useCallback14 } from "react";
4124
4203
  import { ariaDescribedByIds as ariaDescribedByIds7 } from "@rjsf/utils";
4125
4204
  import { jsx as jsx48 } from "react/jsx-runtime";
4126
4205
  function TextareaWidget({
@@ -4136,15 +4215,15 @@ function TextareaWidget({
4136
4215
  onBlur,
4137
4216
  onFocus
4138
4217
  }) {
4139
- const handleChange = useCallback12(
4218
+ const handleChange = useCallback14(
4140
4219
  ({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
4141
4220
  [onChange, options.emptyValue]
4142
4221
  );
4143
- const handleBlur = useCallback12(
4222
+ const handleBlur = useCallback14(
4144
4223
  ({ target }) => onBlur(id, target && target.value),
4145
4224
  [onBlur, id]
4146
4225
  );
4147
- const handleFocus = useCallback12(
4226
+ const handleFocus = useCallback14(
4148
4227
  ({ target }) => onFocus(id, target && target.value),
4149
4228
  [id, onFocus]
4150
4229
  );
@@ -4184,13 +4263,13 @@ function TextWidget(props) {
4184
4263
  }
4185
4264
 
4186
4265
  // src/components/widgets/TimeWidget.tsx
4187
- import { useCallback as useCallback13 } from "react";
4266
+ import { useCallback as useCallback15 } from "react";
4188
4267
  import { getTemplate as getTemplate22 } from "@rjsf/utils";
4189
4268
  import { jsx as jsx50 } from "react/jsx-runtime";
4190
4269
  function TimeWidget(props) {
4191
4270
  const { onChange, options, registry } = props;
4192
4271
  const BaseInputTemplate2 = getTemplate22("BaseInputTemplate", registry, options);
4193
- const handleChange = useCallback13((value) => onChange(value ? `${value}:00` : void 0), [onChange]);
4272
+ const handleChange = useCallback15((value) => onChange(value ? `${value}:00` : void 0), [onChange]);
4194
4273
  return /* @__PURE__ */ jsx50(BaseInputTemplate2, { type: "time", ...props, onChange: handleChange });
4195
4274
  }
4196
4275
 
@@ -4258,6 +4337,9 @@ var Form = class extends Component5 {
4258
4337
  * provide any possible type here
4259
4338
  */
4260
4339
  formElement;
4340
+ /** The list of pending changes
4341
+ */
4342
+ pendingChanges = [];
4261
4343
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
4262
4344
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
4263
4345
  * state construction.
@@ -4296,8 +4378,10 @@ var Form = class extends Component5 {
4296
4378
  getSnapshotBeforeUpdate(prevProps, prevState) {
4297
4379
  if (!deepEquals2(this.props, prevProps)) {
4298
4380
  const formDataChangedFields = getChangedFields(this.props.formData, prevProps.formData);
4381
+ const stateDataChangedFields = getChangedFields(this.props.formData, this.state.formData);
4299
4382
  const isSchemaChanged = !deepEquals2(prevProps.schema, this.props.schema);
4300
4383
  const isFormDataChanged = formDataChangedFields.length > 0 || !deepEquals2(prevProps.formData, this.props.formData);
4384
+ const isStateDataChanged = stateDataChangedFields.length > 0 || !deepEquals2(this.state.formData, this.props.formData);
4301
4385
  const nextState = this.getStateFromProps(
4302
4386
  this.props,
4303
4387
  this.props.formData,
@@ -4306,7 +4390,9 @@ var Form = class extends Component5 {
4306
4390
  // match one of the subSchemas, the retrieved schema must be updated.
4307
4391
  isSchemaChanged || isFormDataChanged ? void 0 : this.state.retrievedSchema,
4308
4392
  isSchemaChanged,
4309
- formDataChangedFields
4393
+ formDataChangedFields,
4394
+ // Skip live validation for this request if no form data has changed from the last state
4395
+ !isStateDataChanged
4310
4396
  );
4311
4397
  const shouldUpdate = !deepEquals2(nextState, prevState);
4312
4398
  return { nextState, shouldUpdate };
@@ -4345,14 +4431,14 @@ var Form = class extends Component5 {
4345
4431
  * @param formDataChangedFields - The changed fields of `formData`
4346
4432
  * @returns - The new state for the `Form`
4347
4433
  */
4348
- getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = []) {
4434
+ getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = [], skipLiveValidate = false) {
4349
4435
  const state = this.state || {};
4350
4436
  const schema = "schema" in props ? props.schema : this.props.schema;
4351
4437
  const validator = "validator" in props ? props.validator : this.props.validator;
4352
4438
  const uiSchema = ("uiSchema" in props ? props.uiSchema : this.props.uiSchema) || {};
4353
4439
  const edit = typeof inputFormData !== "undefined";
4354
4440
  const liveValidate = "liveValidate" in props ? props.liveValidate : this.props.liveValidate;
4355
- const mustValidate = edit && !props.noValidate && liveValidate;
4441
+ const mustValidate = edit && !props.noValidate && liveValidate && !skipLiveValidate;
4356
4442
  const experimental_defaultFormStateBehavior = "experimental_defaultFormStateBehavior" in props ? props.experimental_defaultFormStateBehavior : this.props.experimental_defaultFormStateBehavior;
4357
4443
  const experimental_customMergeAllOf = "experimental_customMergeAllOf" in props ? props.experimental_customMergeAllOf : this.props.experimental_customMergeAllOf;
4358
4444
  let schemaUtils = state.schemaUtils;
@@ -4472,8 +4558,7 @@ var Form = class extends Component5 {
4472
4558
  let customValidateErrors = {};
4473
4559
  if (typeof customValidate === "function") {
4474
4560
  const errorHandler = customValidate(prevFormData, createErrorHandler(prevFormData), uiSchema);
4475
- const userErrorSchema = unwrapErrorHandler(errorHandler);
4476
- customValidateErrors = userErrorSchema;
4561
+ customValidateErrors = unwrapErrorHandler(errorHandler);
4477
4562
  }
4478
4563
  return customValidateErrors;
4479
4564
  }
@@ -4482,7 +4567,8 @@ var Form = class extends Component5 {
4482
4567
  *
4483
4568
  * @param formData - The new form data to validate
4484
4569
  * @param schema - The schema used to validate against
4485
- * @param altSchemaUtils - The alternate schemaUtils to use for validation
4570
+ * @param [altSchemaUtils] - The alternate schemaUtils to use for validation
4571
+ * @param [retrievedSchema] - An optionally retrieved schema for per
4486
4572
  */
4487
4573
  validate(formData, schema = this.state.schema, altSchemaUtils, retrievedSchema) {
4488
4574
  const schemaUtils = altSchemaUtils ? altSchemaUtils : this.state.schemaUtils;
@@ -4564,10 +4650,15 @@ var Form = class extends Component5 {
4564
4650
  const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
4565
4651
  const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
4566
4652
  const fieldNames = this.getFieldNames(pathSchema, formData);
4567
- const newFormData = this.getUsedFormData(formData, fieldNames);
4568
- return newFormData;
4653
+ return this.getUsedFormData(formData, fieldNames);
4569
4654
  };
4570
- // Filtering errors based on your retrieved schema to only show errors for properties in the selected branch.
4655
+ /** Filtering errors based on your retrieved schema to only show errors for properties in the selected branch.
4656
+ *
4657
+ * @param schemaErrors - The schema errors to filter
4658
+ * @param [resolvedSchema] - An optionally resolved schema to use for performance reasons
4659
+ * @param [formData] - The formData to help filter errors
4660
+ * @private
4661
+ */
4571
4662
  filterErrorsBasedOnSchema(schemaErrors, resolvedSchema, formData) {
4572
4663
  const { retrievedSchema, schemaUtils } = this.state;
4573
4664
  const _retrievedSchema = resolvedSchema ?? retrievedSchema;
@@ -4601,23 +4692,45 @@ var Form = class extends Component5 {
4601
4692
  };
4602
4693
  return filterNilOrEmptyErrors(filteredErrors, prevCustomValidateErrors);
4603
4694
  }
4604
- /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
4605
- * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
4606
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
4607
- * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
4608
- * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
4609
- * callback will be called if specified with the updated state.
4695
+ /** Pushes the given change information into the `pendingChanges` array and then calls `processPendingChanges()` if
4696
+ * the array only contains a single pending change.
4610
4697
  *
4611
- * @param formData - The new form data from a change to a field
4612
- * @param newErrorSchema - The new `ErrorSchema` based on the field change
4613
- * @param id - The id of the field that caused the change
4698
+ * @param newValue - The new form data from a change to a field
4699
+ * @param [path] - The path to the change into which to set the formData
4700
+ * @param [newErrorSchema] - The new `ErrorSchema` based on the field change
4701
+ * @param [id] - The id of the field that caused the change
4614
4702
  */
4615
- onChange = (formData, newErrorSchema, id) => {
4616
- const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
4617
- const { schemaUtils, schema } = this.state;
4703
+ onChange = (newValue, path, newErrorSchema, id) => {
4704
+ this.pendingChanges.push({ newValue, path, newErrorSchema, id });
4705
+ if (this.pendingChanges.length === 1) {
4706
+ this.processPendingChange();
4707
+ }
4708
+ };
4709
+ /** Function to handle changes made to a field in the `Form`. This handler gets the first change from the
4710
+ * `pendingChanges` list, containing the `newValue` for the `formData` and the `path` at which the `newValue` is to be
4711
+ * updated, along with a new, optional `ErrorSchema` for that same `path` and potentially the `id` of the field being
4712
+ * changed. It will first update the `formData` with any missing default fields and then, if `omitExtraData` and
4713
+ * `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not in a form field. Then, the
4714
+ * resulting `formData` will be validated if required. The state will be updated with the new updated (potentially
4715
+ * filtered) `formData`, any errors that resulted from validation. Finally the `onChange` callback will be called, if
4716
+ * specified, with the updated state and the `processPendingChange()` function is called again.
4717
+ */
4718
+ processPendingChange() {
4719
+ if (this.pendingChanges.length === 0) {
4720
+ return;
4721
+ }
4722
+ const { newValue, path, id } = this.pendingChanges[0];
4723
+ let { newErrorSchema } = this.pendingChanges[0];
4724
+ const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange, idPrefix = "" } = this.props;
4725
+ const { formData: oldFormData, schemaUtils, schema, errorSchema } = this.state;
4726
+ const isRootPath = !path || path.length === 0 || path.length === 1 && path[0] === idPrefix;
4618
4727
  let retrievedSchema = this.state.retrievedSchema;
4728
+ let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
4619
4729
  if (isObject6(formData) || Array.isArray(formData)) {
4620
- const newState = this.getStateFromProps(this.props, formData);
4730
+ if (!isRootPath) {
4731
+ _set(formData, path, newValue);
4732
+ }
4733
+ const newState = this.getStateFromProps(this.props, formData, void 0, void 0, void 0, true);
4621
4734
  formData = newState.formData;
4622
4735
  retrievedSchema = newState.retrievedSchema;
4623
4736
  }
@@ -4630,38 +4743,49 @@ var Form = class extends Component5 {
4630
4743
  formData: newFormData
4631
4744
  };
4632
4745
  }
4633
- if (mustValidate) {
4746
+ if (newErrorSchema && !isRootPath) {
4747
+ const errorSchemaCopy = _cloneDeep(errorSchema);
4748
+ _set(errorSchemaCopy, path, newErrorSchema);
4749
+ newErrorSchema = errorSchemaCopy;
4750
+ }
4751
+ if (mustValidate && this.pendingChanges.length === 1) {
4634
4752
  const schemaValidation = this.validate(newFormData, schema, schemaUtils, retrievedSchema);
4635
4753
  let errors = schemaValidation.errors;
4636
- let errorSchema = schemaValidation.errorSchema;
4754
+ let errorSchema2 = schemaValidation.errorSchema;
4637
4755
  const schemaValidationErrors = errors;
4638
- const schemaValidationErrorSchema = errorSchema;
4756
+ const schemaValidationErrorSchema = errorSchema2;
4639
4757
  if (extraErrors) {
4640
4758
  const merged = validationDataMerge(schemaValidation, extraErrors);
4641
- errorSchema = merged.errorSchema;
4759
+ errorSchema2 = merged.errorSchema;
4642
4760
  errors = merged.errors;
4643
4761
  }
4644
4762
  if (newErrorSchema) {
4645
4763
  const filteredErrors = this.filterErrorsBasedOnSchema(newErrorSchema, retrievedSchema, newFormData);
4646
- errorSchema = mergeObjects3(errorSchema, filteredErrors, "preventDuplicates");
4764
+ errorSchema2 = mergeObjects3(errorSchema2, filteredErrors, "preventDuplicates");
4647
4765
  }
4648
4766
  state = {
4649
4767
  formData: newFormData,
4650
4768
  errors,
4651
- errorSchema,
4769
+ errorSchema: errorSchema2,
4652
4770
  schemaValidationErrors,
4653
4771
  schemaValidationErrorSchema
4654
4772
  };
4655
4773
  } else if (!noValidate && newErrorSchema) {
4656
- const errorSchema = extraErrors ? mergeObjects3(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
4774
+ const errorSchema2 = extraErrors ? mergeObjects3(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
4657
4775
  state = {
4658
4776
  formData: newFormData,
4659
- errorSchema,
4660
- errors: toErrorList(errorSchema)
4777
+ errorSchema: errorSchema2,
4778
+ errors: toErrorList(errorSchema2)
4661
4779
  };
4662
4780
  }
4663
- this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
4664
- };
4781
+ this.setState(state, () => {
4782
+ if (onChange) {
4783
+ onChange({ ...this.state, ...state }, id);
4784
+ }
4785
+ this.pendingChanges.shift();
4786
+ this.processPendingChange();
4787
+ });
4788
+ }
4665
4789
  /**
4666
4790
  * If the retrievedSchema has changed the new retrievedSchema is returned.
4667
4791
  * Otherwise, the old retrievedSchema is returned to persist reference.
@@ -4896,7 +5020,7 @@ var Form = class extends Component5 {
4896
5020
  const {
4897
5021
  children,
4898
5022
  id,
4899
- idPrefix,
5023
+ idPrefix = "",
4900
5024
  idSeparator,
4901
5025
  className = "",
4902
5026
  tagName,
@@ -4946,7 +5070,7 @@ var Form = class extends Component5 {
4946
5070
  /* @__PURE__ */ jsx53(
4947
5071
  _SchemaField,
4948
5072
  {
4949
- name: "",
5073
+ name: idPrefix,
4950
5074
  schema,
4951
5075
  uiSchema,
4952
5076
  errorSchema,