@rjsf/core 6.0.0-beta.2 → 6.0.0-beta.20

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 (93) hide show
  1. package/dist/core.umd.js +469 -360
  2. package/dist/{index.js → index.cjs} +640 -519
  3. package/dist/index.cjs.map +7 -0
  4. package/dist/index.esm.js +706 -566
  5. package/dist/index.esm.js.map +4 -4
  6. package/lib/components/Form.d.ts +66 -16
  7. package/lib/components/Form.d.ts.map +1 -1
  8. package/lib/components/Form.js +138 -59
  9. package/lib/components/fields/ArrayField.d.ts +17 -7
  10. package/lib/components/fields/ArrayField.d.ts.map +1 -1
  11. package/lib/components/fields/ArrayField.js +92 -59
  12. package/lib/components/fields/BooleanField.d.ts.map +1 -1
  13. package/lib/components/fields/BooleanField.js +7 -2
  14. package/lib/components/fields/LayoutGridField.d.ts +27 -25
  15. package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
  16. package/lib/components/fields/LayoutGridField.js +83 -53
  17. package/lib/components/fields/LayoutHeaderField.d.ts +1 -1
  18. package/lib/components/fields/LayoutHeaderField.js +3 -3
  19. package/lib/components/fields/LayoutMultiSchemaField.js +6 -5
  20. package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
  21. package/lib/components/fields/MultiSchemaField.js +13 -9
  22. package/lib/components/fields/NullField.js +3 -3
  23. package/lib/components/fields/NumberField.d.ts.map +1 -1
  24. package/lib/components/fields/NumberField.js +3 -3
  25. package/lib/components/fields/ObjectField.d.ts +3 -3
  26. package/lib/components/fields/ObjectField.d.ts.map +1 -1
  27. package/lib/components/fields/ObjectField.js +18 -25
  28. package/lib/components/fields/SchemaField.d.ts.map +1 -1
  29. package/lib/components/fields/SchemaField.js +17 -17
  30. package/lib/components/fields/StringField.d.ts.map +1 -1
  31. package/lib/components/fields/StringField.js +7 -2
  32. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +1 -1
  33. package/lib/components/templates/ArrayFieldDescriptionTemplate.js +3 -3
  34. package/lib/components/templates/ArrayFieldItemButtonsTemplate.js +2 -2
  35. package/lib/components/templates/ArrayFieldTemplate.js +3 -3
  36. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -1
  37. package/lib/components/templates/ArrayFieldTitleTemplate.js +3 -3
  38. package/lib/components/templates/FieldErrorTemplate.js +2 -2
  39. package/lib/components/templates/FieldHelpTemplate.js +2 -2
  40. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +8 -0
  41. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -0
  42. package/lib/components/templates/MultiSchemaFieldTemplate.js +10 -0
  43. package/lib/components/templates/ObjectFieldTemplate.js +2 -2
  44. package/lib/components/templates/UnsupportedField.js +3 -3
  45. package/lib/components/templates/index.d.ts.map +1 -1
  46. package/lib/components/templates/index.js +2 -0
  47. package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
  48. package/lib/components/widgets/AltDateWidget.js +15 -18
  49. package/lib/components/widgets/CheckboxesWidget.js +2 -2
  50. package/lib/getDefaultRegistry.d.ts.map +1 -1
  51. package/lib/getDefaultRegistry.js +2 -1
  52. package/lib/getTestRegistry.d.ts +5 -0
  53. package/lib/getTestRegistry.d.ts.map +1 -0
  54. package/lib/getTestRegistry.js +19 -0
  55. package/lib/index.d.ts +2 -1
  56. package/lib/index.d.ts.map +1 -1
  57. package/lib/index.js +2 -1
  58. package/lib/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +18 -19
  60. package/src/components/Form.tsx +183 -73
  61. package/src/components/fields/ArrayField.tsx +99 -67
  62. package/src/components/fields/BooleanField.tsx +12 -3
  63. package/src/components/fields/LayoutGridField.tsx +95 -82
  64. package/src/components/fields/LayoutHeaderField.tsx +3 -3
  65. package/src/components/fields/LayoutMultiSchemaField.tsx +5 -5
  66. package/src/components/fields/MultiSchemaField.tsx +51 -35
  67. package/src/components/fields/NullField.tsx +3 -3
  68. package/src/components/fields/NumberField.tsx +11 -3
  69. package/src/components/fields/ObjectField.tsx +19 -36
  70. package/src/components/fields/SchemaField.tsx +24 -30
  71. package/src/components/fields/StringField.tsx +12 -3
  72. package/src/components/templates/ArrayFieldDescriptionTemplate.tsx +3 -3
  73. package/src/components/templates/ArrayFieldItemButtonsTemplate.tsx +5 -5
  74. package/src/components/templates/ArrayFieldTemplate.tsx +5 -5
  75. package/src/components/templates/ArrayFieldTitleTemplate.tsx +3 -3
  76. package/src/components/templates/BaseInputTemplate.tsx +3 -3
  77. package/src/components/templates/FieldErrorTemplate.tsx +2 -2
  78. package/src/components/templates/FieldHelpTemplate.tsx +2 -2
  79. package/src/components/templates/MultiSchemaFieldTemplate.tsx +20 -0
  80. package/src/components/templates/ObjectFieldTemplate.tsx +5 -5
  81. package/src/components/templates/UnsupportedField.tsx +3 -3
  82. package/src/components/templates/WrapIfAdditionalTemplate.tsx +1 -1
  83. package/src/components/templates/index.ts +2 -0
  84. package/src/components/widgets/AltDateWidget.tsx +21 -23
  85. package/src/components/widgets/CheckboxWidget.tsx +2 -2
  86. package/src/components/widgets/CheckboxesWidget.tsx +3 -3
  87. package/src/components/widgets/RadioWidget.tsx +1 -1
  88. package/src/components/widgets/SelectWidget.tsx +1 -1
  89. package/src/components/widgets/TextareaWidget.tsx +1 -1
  90. package/src/getDefaultRegistry.ts +10 -1
  91. package/src/getTestRegistry.tsx +34 -0
  92. package/src/index.ts +2 -1
  93. package/dist/index.js.map +0 -7
package/dist/core.umd.js CHANGED
@@ -1,12 +1,12 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@rjsf/utils'), require('lodash/forEach'), require('lodash/get'), require('lodash/isEmpty'), require('lodash/isNil'), require('lodash/pick'), require('lodash/toPath'), require('lodash/cloneDeep'), require('lodash/isObject'), require('lodash/set'), require('nanoid'), require('react/jsx-runtime'), require('lodash/each'), require('lodash/flatten'), require('lodash/has'), require('lodash/includes'), require('lodash/intersection'), require('lodash/isFunction'), require('lodash/isEqual'), require('lodash/isPlainObject'), require('lodash/isString'), require('lodash/isUndefined'), require('lodash/noop'), require('lodash/omit'), require('markdown-to-jsx'), require('lodash/unset')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'react', '@rjsf/utils', 'lodash/forEach', 'lodash/get', 'lodash/isEmpty', 'lodash/isNil', 'lodash/pick', 'lodash/toPath', 'lodash/cloneDeep', 'lodash/isObject', 'lodash/set', 'nanoid', 'react/jsx-runtime', 'lodash/each', 'lodash/flatten', 'lodash/has', 'lodash/includes', 'lodash/intersection', 'lodash/isFunction', 'lodash/isEqual', 'lodash/isPlainObject', 'lodash/isString', 'lodash/isUndefined', 'lodash/noop', 'lodash/omit', 'markdown-to-jsx', 'lodash/unset'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.JSONSchemaForm = {}, global.react, global.utils, global._forEach, global.get2, global.isEmpty, global._isNil, global._pick, global._toPath, global.cloneDeep2, global.isObject, global.set, global.nanoid, global.jsxRuntime, global.each, global.flatten, global.has, global.includes, global.intersection, global.isFunction, global.isEqual, global.isPlainObject, global.isString, global.isUndefined, global.noop, global.omit3, global.Markdown, global.unset));
5
- })(this, (function (exports, react, utils, _forEach, get2, isEmpty, _isNil, _pick, _toPath, cloneDeep2, isObject, set, nanoid, jsxRuntime, each, flatten, has, includes, intersection, isFunction, isEqual, isPlainObject, isString, isUndefined, noop, omit3, Markdown, unset) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@rjsf/utils'), require('lodash/cloneDeep'), require('lodash/forEach'), require('lodash/get'), require('lodash/isEmpty'), require('lodash/isNil'), require('lodash/pick'), require('lodash/set'), require('lodash/toPath'), require('lodash/isObject'), require('lodash/uniqueId'), require('react/jsx-runtime'), require('lodash/each'), require('lodash/flatten'), require('lodash/has'), require('lodash/includes'), require('lodash/intersection'), require('lodash/isFunction'), require('lodash/isEqual'), require('lodash/isPlainObject'), require('lodash/isString'), require('lodash/isUndefined'), require('lodash/last'), require('lodash/noop'), require('lodash/omit'), require('markdown-to-jsx'), require('lodash/unset'), require('@rjsf/validator-ajv8')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react', '@rjsf/utils', 'lodash/cloneDeep', 'lodash/forEach', 'lodash/get', 'lodash/isEmpty', 'lodash/isNil', 'lodash/pick', 'lodash/set', 'lodash/toPath', 'lodash/isObject', 'lodash/uniqueId', 'react/jsx-runtime', 'lodash/each', 'lodash/flatten', 'lodash/has', 'lodash/includes', 'lodash/intersection', 'lodash/isFunction', 'lodash/isEqual', 'lodash/isPlainObject', 'lodash/isString', 'lodash/isUndefined', 'lodash/last', 'lodash/noop', 'lodash/omit', 'markdown-to-jsx', 'lodash/unset', '@rjsf/validator-ajv8'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.JSONSchemaForm = {}, global.react, global.utils, global._cloneDeep, global._forEach, global.get2, global.isEmpty, global._isNil, global._pick, global.set, global._toPath, global.isObject, global.uniqueId, global.jsxRuntime, global.each, global.flatten, global.has, global.includes, global.intersection, global.isFunction, global.isEqual, global.isPlainObject, global.isString, global.isUndefined, global.last, global.noop, global.omit3, global.Markdown, global.unset, global.validator));
5
+ })(this, (function (exports, react, utils, _cloneDeep, _forEach, get2, isEmpty, _isNil, _pick, set, _toPath, isObject, uniqueId, jsxRuntime, each, flatten, has, includes, intersection, isFunction, isEqual, isPlainObject, isString, isUndefined, last, noop, omit3, Markdown, unset, validator) { 'use strict';
6
6
 
7
7
  // src/components/Form.tsx
8
8
  function generateRowId() {
9
- return nanoid.nanoid();
9
+ return uniqueId("rjsf-array-item-");
10
10
  }
11
11
  function generateKeyedFormData(formData) {
12
12
  return !Array.isArray(formData) ? [] : formData.map((item) => {
@@ -126,7 +126,7 @@
126
126
  if (event) {
127
127
  event.preventDefault();
128
128
  }
129
- const { onChange, errorSchema } = this.props;
129
+ const { onChange, errorSchema, fieldPathId } = this.props;
130
130
  const { keyedFormData } = this.state;
131
131
  let newErrorSchema;
132
132
  if (errorSchema) {
@@ -155,7 +155,8 @@
155
155
  keyedFormData: newKeyedFormData,
156
156
  updatedKeyedFormData: true
157
157
  },
158
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
158
+ // add click will pass the empty `path` array to the onChange which adds the appropriate path
159
+ () => onChange(keyedToPlainFormData(newKeyedFormData), fieldPathId.path, newErrorSchema)
159
160
  );
160
161
  }
161
162
  /** Callback handler for when the user clicks on the add button. Creates a new row of keyed form data at the end of
@@ -189,7 +190,7 @@
189
190
  if (event) {
190
191
  event.preventDefault();
191
192
  }
192
- const { onChange, errorSchema } = this.props;
193
+ const { onChange, errorSchema, fieldPathId } = this.props;
193
194
  const { keyedFormData } = this.state;
194
195
  let newErrorSchema;
195
196
  if (errorSchema) {
@@ -205,7 +206,7 @@
205
206
  }
206
207
  const newKeyedFormDataRow = {
207
208
  key: generateRowId(),
208
- item: cloneDeep2(keyedFormData[index].item)
209
+ item: _cloneDeep(keyedFormData[index].item)
209
210
  };
210
211
  const newKeyedFormData = [...keyedFormData];
211
212
  if (index !== void 0) {
@@ -218,7 +219,7 @@
218
219
  keyedFormData: newKeyedFormData,
219
220
  updatedKeyedFormData: true
220
221
  },
221
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
222
+ () => onChange(keyedToPlainFormData(newKeyedFormData), fieldPathId.path, newErrorSchema)
222
223
  );
223
224
  };
224
225
  };
@@ -233,7 +234,7 @@
233
234
  if (event) {
234
235
  event.preventDefault();
235
236
  }
236
- const { onChange, errorSchema } = this.props;
237
+ const { onChange, errorSchema, fieldPathId } = this.props;
237
238
  const { keyedFormData } = this.state;
238
239
  let newErrorSchema;
239
240
  if (errorSchema) {
@@ -253,7 +254,7 @@
253
254
  keyedFormData: newKeyedFormData,
254
255
  updatedKeyedFormData: true
255
256
  },
256
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
257
+ () => onChange(keyedToPlainFormData(newKeyedFormData), fieldPathId.path, newErrorSchema)
257
258
  );
258
259
  };
259
260
  };
@@ -270,7 +271,7 @@
270
271
  event.preventDefault();
271
272
  event.currentTarget.blur();
272
273
  }
273
- const { onChange, errorSchema } = this.props;
274
+ const { onChange, errorSchema, fieldPathId } = this.props;
274
275
  let newErrorSchema;
275
276
  if (errorSchema) {
276
277
  newErrorSchema = {};
@@ -297,7 +298,7 @@
297
298
  {
298
299
  keyedFormData: newKeyedFormData
299
300
  },
300
- () => onChange(keyedToPlainFormData(newKeyedFormData), newErrorSchema)
301
+ () => onChange(keyedToPlainFormData(newKeyedFormData), fieldPathId.path, newErrorSchema)
301
302
  );
302
303
  };
303
304
  };
@@ -307,32 +308,49 @@
307
308
  * @param index - The index of the item being changed
308
309
  */
309
310
  onChangeForIndex = (index) => {
310
- return (value, newErrorSchema, id) => {
311
- const { formData, onChange, errorSchema } = this.props;
312
- const arrayData = Array.isArray(formData) ? formData : [];
313
- const newFormData = arrayData.map((item, i) => {
314
- const jsonValue = typeof value === "undefined" ? null : value;
315
- return index === i ? jsonValue : item;
316
- });
311
+ return (value, path, newErrorSchema, id) => {
312
+ const { onChange } = this.props;
317
313
  onChange(
318
- newFormData,
319
- errorSchema && errorSchema && {
320
- ...errorSchema,
321
- [index]: newErrorSchema
322
- },
314
+ // We need to treat undefined items as nulls to have validation.
315
+ // See https://github.com/tdegrunt/jsonschema/issues/206
316
+ value === void 0 ? null : value,
317
+ path,
318
+ newErrorSchema,
323
319
  id
324
320
  );
325
321
  };
326
322
  };
327
323
  /** Callback handler used to change the value for a checkbox */
328
324
  onSelectChange = (value) => {
329
- const { onChange, idSchema } = this.props;
330
- onChange(value, void 0, idSchema && idSchema.$id);
325
+ const { onChange, fieldPathId } = this.props;
326
+ onChange(value, fieldPathId.path, void 0, fieldPathId && fieldPathId.$id);
331
327
  };
328
+ /** Helper method to compute item UI schema for both normal and fixed arrays
329
+ * Handles both static object and dynamic function cases
330
+ *
331
+ * @param uiSchema - The parent UI schema containing items definition
332
+ * @param item - The item data
333
+ * @param index - The index of the item
334
+ * @param formContext - The form context
335
+ * @returns The computed UI schema for the item
336
+ */
337
+ computeItemUiSchema(uiSchema, item, index, formContext) {
338
+ if (typeof uiSchema.items === "function") {
339
+ try {
340
+ const result = uiSchema.items(item, index, formContext);
341
+ return result;
342
+ } catch (e) {
343
+ console.error(`Error executing dynamic uiSchema.items function for item at index ${index}:`, e);
344
+ return void 0;
345
+ }
346
+ } else {
347
+ return uiSchema.items;
348
+ }
349
+ }
332
350
  /** Renders the `ArrayField` depending on the specific needs of the schema and uischema elements
333
351
  */
334
352
  render() {
335
- const { schema, uiSchema, idSchema, registry } = this.props;
353
+ const { schema, uiSchema, fieldPathId, registry } = this.props;
336
354
  const { schemaUtils, translateString } = registry;
337
355
  if (!(utils.ITEMS_KEY in schema)) {
338
356
  const uiOptions = utils.getUiOptions(uiSchema);
@@ -345,7 +363,7 @@
345
363
  UnsupportedFieldTemplate,
346
364
  {
347
365
  schema,
348
- idSchema,
366
+ fieldPathId,
349
367
  reason: translateString(utils.TranslatableString.MissingItems),
350
368
  registry
351
369
  }
@@ -372,7 +390,7 @@
372
390
  schema,
373
391
  uiSchema = {},
374
392
  errorSchema,
375
- idSchema,
393
+ fieldPathId,
376
394
  name,
377
395
  title,
378
396
  disabled = false,
@@ -382,13 +400,11 @@
382
400
  registry,
383
401
  onBlur,
384
402
  onFocus,
385
- idPrefix,
386
- idSeparator = "_",
387
403
  rawErrors
388
404
  } = this.props;
389
405
  const { keyedFormData } = this.state;
390
406
  const fieldTitle = schema.title || title || name;
391
- const { schemaUtils, formContext } = registry;
407
+ const { schemaUtils, formContext, globalFormOptions } = registry;
392
408
  const uiOptions = utils.getUiOptions(uiSchema);
393
409
  const _schemaItems = isObject(schema.items) ? schema.items : {};
394
410
  const itemsSchema = schemaUtils.retrieveSchema(_schemaItems);
@@ -401,8 +417,8 @@
401
417
  const itemCast = item;
402
418
  const itemSchema = schemaUtils.retrieveSchema(_schemaItems, itemCast);
403
419
  const itemErrorSchema = errorSchema ? errorSchema[index] : void 0;
404
- const itemIdPrefix = idSchema.$id + idSeparator + index;
405
- const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
420
+ const itemFieldPathId = utils.toFieldPathId(index, globalFormOptions, fieldPathId);
421
+ const itemUiSchema = this.computeItemUiSchema(uiSchema, item, index, formContext);
406
422
  return this.renderArrayFieldItem({
407
423
  key,
408
424
  index,
@@ -412,10 +428,10 @@
412
428
  canMoveUp: index > 0,
413
429
  canMoveDown: index < formData.length - 1,
414
430
  itemSchema,
415
- itemIdSchema,
431
+ itemFieldPathId,
416
432
  itemErrorSchema,
417
433
  itemData: itemCast,
418
- itemUiSchema: uiSchema.items,
434
+ itemUiSchema,
419
435
  autofocus: autofocus && index === 0,
420
436
  onBlur,
421
437
  onFocus,
@@ -425,14 +441,13 @@
425
441
  }),
426
442
  className: `rjsf-field rjsf-field-array rjsf-field-array-of-${itemsSchema.type}`,
427
443
  disabled,
428
- idSchema,
444
+ fieldPathId,
429
445
  uiSchema,
430
446
  onAddClick: this.onAddClick,
431
447
  readonly,
432
448
  required,
433
449
  schema,
434
450
  title: fieldTitle,
435
- formContext,
436
451
  formData,
437
452
  rawErrors,
438
453
  registry
@@ -445,7 +460,7 @@
445
460
  renderCustomWidget() {
446
461
  const {
447
462
  schema,
448
- idSchema,
463
+ fieldPathId,
449
464
  uiSchema,
450
465
  disabled = false,
451
466
  readonly = false,
@@ -468,7 +483,7 @@
468
483
  return /* @__PURE__ */ jsxRuntime.jsx(
469
484
  Widget,
470
485
  {
471
- id: idSchema.$id,
486
+ id: fieldPathId.$id,
472
487
  name,
473
488
  multiple: true,
474
489
  onChange: this.onSelectChange,
@@ -497,7 +512,7 @@
497
512
  renderMultiSelect() {
498
513
  const {
499
514
  schema,
500
- idSchema,
515
+ fieldPathId,
501
516
  uiSchema,
502
517
  formData: items = [],
503
518
  disabled = false,
@@ -521,7 +536,7 @@
521
536
  return /* @__PURE__ */ jsxRuntime.jsx(
522
537
  Widget,
523
538
  {
524
- id: idSchema.$id,
539
+ id: fieldPathId.$id,
525
540
  name,
526
541
  multiple: true,
527
542
  onChange: this.onSelectChange,
@@ -550,7 +565,7 @@
550
565
  const {
551
566
  schema,
552
567
  uiSchema,
553
- idSchema,
568
+ fieldPathId,
554
569
  name,
555
570
  disabled = false,
556
571
  readonly = false,
@@ -571,7 +586,7 @@
571
586
  Widget,
572
587
  {
573
588
  options,
574
- id: idSchema.$id,
589
+ id: fieldPathId.$id,
575
590
  name,
576
591
  multiple: true,
577
592
  onChange: this.onSelectChange,
@@ -600,9 +615,7 @@
600
615
  uiSchema = {},
601
616
  formData = [],
602
617
  errorSchema,
603
- idPrefix,
604
- idSeparator = "_",
605
- idSchema,
618
+ fieldPathId,
606
619
  name,
607
620
  title,
608
621
  disabled = false,
@@ -618,7 +631,7 @@
618
631
  let { formData: items = [] } = this.props;
619
632
  const fieldTitle = schema.title || title || name;
620
633
  const uiOptions = utils.getUiOptions(uiSchema);
621
- const { schemaUtils, formContext } = registry;
634
+ const { schemaUtils, formContext, globalFormOptions } = registry;
622
635
  const _schemaItems = isObject(schema.items) ? schema.items : [];
623
636
  const itemSchemas = _schemaItems.map(
624
637
  (item, index) => schemaUtils.retrieveSchema(item, formData[index])
@@ -633,16 +646,24 @@
633
646
  canAdd,
634
647
  className: "rjsf-field rjsf-field-array rjsf-field-array-fixed-items",
635
648
  disabled,
636
- idSchema,
649
+ fieldPathId,
637
650
  formData,
638
651
  items: keyedFormData.map((keyedItem, index) => {
639
652
  const { key, item } = keyedItem;
640
653
  const itemCast = item;
641
654
  const additional = index >= itemSchemas.length;
642
655
  const itemSchema = (additional && isObject(schema.additionalItems) ? schemaUtils.retrieveSchema(schema.additionalItems, itemCast) : itemSchemas[index]) || {};
643
- const itemIdPrefix = idSchema.$id + idSeparator + index;
644
- const itemIdSchema = schemaUtils.toIdSchema(itemSchema, itemIdPrefix, itemCast, idPrefix, idSeparator);
645
- const itemUiSchema = additional ? uiSchema.additionalItems || {} : Array.isArray(uiSchema.items) ? uiSchema.items[index] : uiSchema.items || {};
656
+ const itemFieldPathId = utils.toFieldPathId(index, globalFormOptions, fieldPathId);
657
+ let itemUiSchema;
658
+ if (additional) {
659
+ itemUiSchema = uiSchema.additionalItems;
660
+ } else {
661
+ if (Array.isArray(uiSchema.items)) {
662
+ itemUiSchema = uiSchema.items[index];
663
+ } else {
664
+ itemUiSchema = this.computeItemUiSchema(uiSchema, item, index, formContext);
665
+ }
666
+ }
646
667
  const itemErrorSchema = errorSchema ? errorSchema[index] : void 0;
647
668
  return this.renderArrayFieldItem({
648
669
  key,
@@ -656,7 +677,7 @@
656
677
  itemSchema,
657
678
  itemData: itemCast,
658
679
  itemUiSchema,
659
- itemIdSchema,
680
+ itemFieldPathId,
660
681
  itemErrorSchema,
661
682
  autofocus: autofocus && index === 0,
662
683
  onBlur,
@@ -672,7 +693,6 @@
672
693
  schema,
673
694
  uiSchema,
674
695
  title: fieldTitle,
675
- formContext,
676
696
  errorSchema,
677
697
  rawErrors
678
698
  };
@@ -696,7 +716,7 @@
696
716
  itemSchema,
697
717
  itemData,
698
718
  itemUiSchema,
699
- itemIdSchema,
719
+ itemFieldPathId,
700
720
  itemErrorSchema,
701
721
  autofocus,
702
722
  onBlur,
@@ -705,7 +725,7 @@
705
725
  totalItems,
706
726
  title
707
727
  } = props;
708
- const { disabled, hideError, idPrefix, idSeparator, readonly, uiSchema, registry, formContext } = this.props;
728
+ const { disabled, hideError, readonly, uiSchema, registry, formContext } = this.props;
709
729
  const {
710
730
  fields: { ArraySchemaField, SchemaField: SchemaField2 },
711
731
  globalUiOptions
@@ -732,9 +752,7 @@
732
752
  formData: itemData,
733
753
  formContext,
734
754
  errorSchema: itemErrorSchema,
735
- idPrefix,
736
- idSeparator,
737
- idSchema: itemIdSchema,
755
+ fieldPathId: itemFieldPathId,
738
756
  required: this.isItemRequired(itemSchema),
739
757
  onChange: this.onChangeForIndex(index),
740
758
  onBlur,
@@ -748,7 +766,7 @@
748
766
  }
749
767
  ),
750
768
  buttonsProps: {
751
- idSchema: itemIdSchema,
769
+ fieldPathId: itemFieldPathId,
752
770
  disabled,
753
771
  readonly,
754
772
  canAdd,
@@ -785,7 +803,7 @@
785
803
  schema,
786
804
  name,
787
805
  uiSchema,
788
- idSchema,
806
+ fieldPathId,
789
807
  formData,
790
808
  registry,
791
809
  required,
@@ -847,15 +865,21 @@
847
865
  enumOptions = utils.optionsList({ enum: enums }, uiSchema);
848
866
  }
849
867
  }
868
+ const onWidgetChange = react.useCallback(
869
+ (value, errorSchema, id) => {
870
+ return onChange(value, fieldPathId.path, errorSchema, id);
871
+ },
872
+ [onChange, fieldPathId]
873
+ );
850
874
  return /* @__PURE__ */ jsxRuntime.jsx(
851
875
  Widget,
852
876
  {
853
877
  options: { ...options, enumOptions },
854
878
  schema,
855
879
  uiSchema,
856
- id: idSchema.$id,
880
+ id: fieldPathId.$id,
857
881
  name,
858
- onChange,
882
+ onChange: onWidgetChange,
859
883
  onFocus,
860
884
  onBlur,
861
885
  label,
@@ -875,10 +899,12 @@
875
899
  var BooleanField_default = BooleanField;
876
900
  var LOOKUP_REGEX = /^\$lookup=(.+)/;
877
901
  var LAYOUT_GRID_UI_OPTION = "layoutGrid";
878
- var UI_GLOBAL_OPTIONS = "ui:global_options";
879
902
  function getNonNullishValue(value, fallback) {
880
903
  return value ?? fallback;
881
904
  }
905
+ function isNumericIndex(str) {
906
+ return /^\d+?$/.test(str);
907
+ }
882
908
  var LayoutGridField = class _LayoutGridField extends react.PureComponent {
883
909
  static defaultProps = {
884
910
  layoutGridSchema: void 0
@@ -898,7 +924,7 @@
898
924
  * @param [forceReadonly] - Optional flag indicating whether the Form itself is in readonly mode
899
925
  */
900
926
  static computeFieldUiSchema(field, uiProps, uiSchema, schemaReadonly, forceReadonly) {
901
- const globalUiOptions = get2(uiSchema, [UI_GLOBAL_OPTIONS], {});
927
+ const globalUiOptions = get2(uiSchema, [utils.UI_GLOBAL_OPTIONS_KEY], {});
902
928
  const localUiSchema = get2(uiSchema, field);
903
929
  const localUiOptions = { ...get2(localUiSchema, [utils.UI_OPTIONS_KEY], {}), ...uiProps, ...globalUiOptions };
904
930
  const fieldUiSchema = { ...localUiSchema };
@@ -906,7 +932,7 @@
906
932
  set(fieldUiSchema, [utils.UI_OPTIONS_KEY], localUiOptions);
907
933
  }
908
934
  if (!isEmpty(globalUiOptions)) {
909
- set(fieldUiSchema, [UI_GLOBAL_OPTIONS], globalUiOptions);
935
+ set(fieldUiSchema, [utils.UI_GLOBAL_OPTIONS_KEY], globalUiOptions);
910
936
  }
911
937
  let { readonly: uiReadonly } = utils.getUiOptions(fieldUiSchema);
912
938
  if (forceReadonly === true || isUndefined(uiReadonly) && schemaReadonly === true) {
@@ -978,60 +1004,74 @@
978
1004
  }
979
1005
  return { children, gridProps };
980
1006
  }
981
- /** Generates an idSchema for the `schema` using `@rjsf`'s `toIdSchema` util, passing the `baseIdSchema`'s `$id` value
982
- * as the id prefix.
1007
+ /** Computes the `rawSchema` and `fieldPathId` for a `schema` and a `potentialIndex`. If the `schema` is of type array,
1008
+ * has an `ITEMS_KEY` element and `potentialIndex` represents a numeric value, the element at `ITEMS_KEY` is checked
1009
+ * to see if it is an array. If it is AND the `potentialIndex`th element is available, it is used as the `rawSchema`,
1010
+ * otherwise the last value of the element is used. If it is not, then the element is used as the `rawSchema`. In
1011
+ * either case, an `fieldPathId` is computed for the array index. If the `schema` does not represent an array or the
1012
+ * `potentialIndex` is not a numeric value, then `rawSchema` is returned as undefined and given `fieldPathId` is returned
1013
+ * as is.
983
1014
  *
984
- * @param schemaUtils - The `SchemaUtilsType` used to call `toIdSchema`
985
- * @param schema - The schema to generate the idSchema for
986
- * @param baseIdSchema - The IdSchema for the base
987
- * @param formData - The formData to pass the `toIdSchema`
988
- * @param [idSeparator] - The param to pass into the `toIdSchema` util which will use it to join the `idSchema` paths
989
- * @returns - The generated `idSchema` for the `schema`
1015
+ * @param schema - The schema to generate the fieldPathId for
1016
+ * @param fieldPathId - The FieldPathId for the schema
1017
+ * @param potentialIndex - A string containing a potential index
1018
+ * @returns - An object containing the `rawSchema` and `fieldPathId` of an array item, otherwise an undefined `rawSchema`
990
1019
  */
991
- static getIdSchema(schemaUtils, baseIdSchema, formData, schema = {}, idSeparator) {
992
- const baseId = get2(baseIdSchema, utils.ID_KEY);
993
- return schemaUtils.toIdSchema(schema, baseId, formData, baseId, idSeparator);
1020
+ static computeArraySchemasIfPresent(schema, fieldPathId, potentialIndex) {
1021
+ let rawSchema;
1022
+ if (isNumericIndex(potentialIndex) && schema && schema?.type === "array" && has(schema, utils.ITEMS_KEY)) {
1023
+ const index = Number(potentialIndex);
1024
+ const items = schema[utils.ITEMS_KEY];
1025
+ if (Array.isArray(items)) {
1026
+ if (index > items.length) {
1027
+ rawSchema = last(items);
1028
+ } else {
1029
+ rawSchema = items[index];
1030
+ }
1031
+ } else {
1032
+ rawSchema = items;
1033
+ }
1034
+ fieldPathId = {
1035
+ [utils.ID_KEY]: fieldPathId[utils.ID_KEY],
1036
+ path: [...fieldPathId.path.slice(0, fieldPathId.path.length - 1), index]
1037
+ };
1038
+ }
1039
+ return { rawSchema, fieldPathId };
994
1040
  }
995
1041
  /** Given a `dottedPath` to a field in the `initialSchema`, iterate through each individual path in the schema until
996
1042
  * the leaf path is found and returned (along with whether that leaf path `isRequired`) OR no schema exists for an
997
1043
  * element in the path. If the leaf schema element happens to be a oneOf/anyOf then also return the oneOf/anyOf as
998
1044
  * `options`.
999
1045
  *
1000
- * @param schemaUtils - The `SchemaUtilsType` used to call `retrieveSchema`
1046
+ * @param registry - The registry
1001
1047
  * @param dottedPath - The dotted-path to the field for which to get the schema
1002
1048
  * @param initialSchema - The initial schema to start the search from
1003
1049
  * @param formData - The formData, useful for resolving a oneOf/anyOf selection in the path hierarchy
1004
- * @param initialIdSchema - The initial idSchema to start the search from
1005
- * @param [idSeparator] - The param to pass into the `toIdSchema` util which will use it to join the `idSchema` paths
1050
+ * @param initialFieldIdPath - The initial fieldPathId to start the search from
1006
1051
  * @returns - An object containing the destination schema, isRequired and isReadonly flags for the field and options
1007
1052
  * info if a oneOf/anyOf
1008
1053
  */
1009
- static getSchemaDetailsForField(schemaUtils, dottedPath, initialSchema, formData, initialIdSchema, idSeparator) {
1054
+ static getSchemaDetailsForField(registry, dottedPath, initialSchema, formData, initialFieldIdPath) {
1055
+ const { schemaUtils, globalFormOptions } = registry;
1010
1056
  let rawSchema = initialSchema;
1011
- let idSchema = initialIdSchema;
1057
+ let fieldPathId = initialFieldIdPath;
1012
1058
  const parts = dottedPath.split(".");
1013
1059
  const leafPath = parts.pop();
1014
1060
  let schema = schemaUtils.retrieveSchema(rawSchema, formData);
1015
1061
  let innerData = formData;
1016
1062
  let isReadonly = schema.readOnly;
1017
1063
  parts.forEach((part) => {
1064
+ fieldPathId = utils.toFieldPathId(part, globalFormOptions, fieldPathId);
1018
1065
  if (has(schema, utils.PROPERTIES_KEY)) {
1019
1066
  rawSchema = get2(schema, [utils.PROPERTIES_KEY, part], {});
1020
- idSchema = get2(idSchema, part, {});
1021
1067
  } else if (schema && (has(schema, utils.ONE_OF_KEY) || has(schema, utils.ANY_OF_KEY))) {
1022
1068
  const xxx = has(schema, utils.ONE_OF_KEY) ? utils.ONE_OF_KEY : utils.ANY_OF_KEY;
1023
1069
  const selectedSchema = schemaUtils.findSelectedOptionInXxxOf(schema, part, xxx, innerData);
1024
- const selectedIdSchema = _LayoutGridField.getIdSchema(
1025
- schemaUtils,
1026
- idSchema,
1027
- formData,
1028
- selectedSchema,
1029
- idSeparator
1030
- );
1031
1070
  rawSchema = get2(selectedSchema, [utils.PROPERTIES_KEY, part], {});
1032
- idSchema = get2(selectedIdSchema, part, {});
1033
1071
  } else {
1034
- rawSchema = {};
1072
+ const result = _LayoutGridField.computeArraySchemasIfPresent(schema, fieldPathId, part);
1073
+ rawSchema = result.rawSchema ?? {};
1074
+ fieldPathId = result.fieldPathId;
1035
1075
  }
1036
1076
  innerData = get2(innerData, part, {});
1037
1077
  schema = schemaUtils.retrieveSchema(rawSchema, innerData);
@@ -1046,13 +1086,17 @@
1046
1086
  if (schema && (has(schema, utils.ONE_OF_KEY) || has(schema, utils.ANY_OF_KEY))) {
1047
1087
  const xxx = has(schema, utils.ONE_OF_KEY) ? utils.ONE_OF_KEY : utils.ANY_OF_KEY;
1048
1088
  schema = schemaUtils.findSelectedOptionInXxxOf(schema, leafPath, xxx, innerData);
1049
- const rawIdSchema = _LayoutGridField.getIdSchema(schemaUtils, idSchema, formData, schema, idSeparator);
1050
- idSchema = utils.mergeObjects(rawIdSchema, idSchema);
1051
1089
  }
1090
+ fieldPathId = utils.toFieldPathId(leafPath, globalFormOptions, fieldPathId);
1052
1091
  isRequired = schema !== void 0 && Array.isArray(schema.required) && includes(schema.required, leafPath);
1053
- schema = get2(schema, [utils.PROPERTIES_KEY, leafPath]);
1054
- schema = schema ? schemaUtils.retrieveSchema(schema) : schema;
1055
- idSchema = get2(idSchema, leafPath, {});
1092
+ const result = _LayoutGridField.computeArraySchemasIfPresent(schema, fieldPathId, leafPath);
1093
+ if (result.rawSchema) {
1094
+ schema = result.rawSchema;
1095
+ fieldPathId = result.fieldPathId;
1096
+ } else {
1097
+ schema = get2(schema, [utils.PROPERTIES_KEY, leafPath]);
1098
+ schema = schema ? schemaUtils.retrieveSchema(schema) : schema;
1099
+ }
1056
1100
  isReadonly = getNonNullishValue(schema?.readOnly, isReadonly);
1057
1101
  if (schema && (has(schema, utils.ONE_OF_KEY) || has(schema, utils.ANY_OF_KEY))) {
1058
1102
  const xxx = has(schema, utils.ONE_OF_KEY) ? utils.ONE_OF_KEY : utils.ANY_OF_KEY;
@@ -1060,7 +1104,7 @@
1060
1104
  optionsInfo = { options: schema[xxx], hasDiscriminator: !!discriminator };
1061
1105
  }
1062
1106
  }
1063
- return { schema, isRequired, isReadonly, optionsInfo, idSchema };
1107
+ return { schema, isRequired, isReadonly, optionsInfo, fieldPathId };
1064
1108
  }
1065
1109
  /** Gets the custom render component from the `render`, by either determining that it is either already a function or
1066
1110
  * it is a non-function value that can be used to look up the function in the registry. If no function can be found,
@@ -1096,7 +1140,7 @@
1096
1140
  if (isString(gridSchema) || isUndefined(gridSchema)) {
1097
1141
  name = gridSchema ?? "";
1098
1142
  } else {
1099
- const { name: innerName, render, ...innerProps } = gridSchema;
1143
+ const { name: innerName = "", render, ...innerProps } = gridSchema;
1100
1144
  name = innerName;
1101
1145
  uiProps = innerProps;
1102
1146
  if (!isEmpty(uiProps)) {
@@ -1129,19 +1173,17 @@
1129
1173
  * elements, they will then be passed on to the `onChange` handler of the `LayoutFieldGrid`.
1130
1174
  *
1131
1175
  * @param dottedPath - The dotted-path to the field for which to generate the onChange handler
1132
- * @returns - The `onChange` handling function for the `dottedPath` field
1176
+ * @returns - The `onChange` handling function for the `dottedPath` field of the `schemaType` type
1133
1177
  */
1134
1178
  onFieldChange = (dottedPath) => {
1135
- return (value, errSchema, id) => {
1136
- const { onChange, errorSchema, formData } = this.props;
1137
- const newFormData = cloneDeep2(formData || {});
1179
+ return (value, path, errSchema, id) => {
1180
+ const { onChange, errorSchema } = this.props;
1138
1181
  let newErrorSchema = errorSchema;
1139
1182
  if (errSchema && errorSchema) {
1140
- newErrorSchema = cloneDeep2(errorSchema);
1183
+ newErrorSchema = _cloneDeep(errorSchema);
1141
1184
  set(newErrorSchema, dottedPath, errSchema);
1142
1185
  }
1143
- set(newFormData, dottedPath, value);
1144
- onChange(newFormData, newErrorSchema, id);
1186
+ onChange(value, path, newErrorSchema, id);
1145
1187
  };
1146
1188
  };
1147
1189
  /** Renders the `children` of the `GridType.CONDITION` if it passes. The `layoutGridSchema` for the
@@ -1229,20 +1271,20 @@
1229
1271
  const GridTemplate2 = utils.getTemplate("GridTemplate", registry, uiOptions);
1230
1272
  return /* @__PURE__ */ jsxRuntime.jsx(GridTemplate2, { ...gridProps, "data-testid": _LayoutGridField.TEST_IDS.row, children: this.renderChildren(children) });
1231
1273
  }
1232
- /** Iterates through all the `childrenLayoutGridSchema`, rendering a nested `LayoutGridField` for each item in the
1274
+ /** Iterates through all the `childrenLayoutGrfieldPathId`, rendering a nested `LayoutGridField` for each item in the
1233
1275
  * list, passing all the props for the current `LayoutGridField` along, updating the `schema` by calling
1234
1276
  * `retrieveSchema()` on it to resolve any `$ref`s. In addition to the updated `schema`, each item in
1235
- * `childrenLayoutGridSchema` is passed as `layoutGridSchema`.
1277
+ * `childrenLayoutGrfieldPathId` is passed as `layoutGridSchema`.
1236
1278
  *
1237
- * @param childrenLayoutGridSchema - The list of strings or objects that represents the configurations for the
1279
+ * @param childrenLayoutGrfieldPathId - The list of strings or objects that represents the configurations for the
1238
1280
  * children fields
1239
1281
  * @returns - The nested `LayoutGridField`s
1240
1282
  */
1241
- renderChildren(childrenLayoutGridSchema) {
1283
+ renderChildren(childrenLayoutGrfieldPathId) {
1242
1284
  const { registry, schema: rawSchema, formData } = this.props;
1243
1285
  const { schemaUtils } = registry;
1244
1286
  const schema = schemaUtils.retrieveSchema(rawSchema, formData);
1245
- return childrenLayoutGridSchema.map((layoutGridSchema) => /* @__PURE__ */ react.createElement(
1287
+ return childrenLayoutGrfieldPathId.map((layoutGridSchema) => /* @__PURE__ */ react.createElement(
1246
1288
  _LayoutGridField,
1247
1289
  {
1248
1290
  ...this.props,
@@ -1258,7 +1300,7 @@
1258
1300
  * specified props for that component. If `name` exists, we take the name, the initial & root schemas and the formData
1259
1301
  * and get the destination schema, is required state and optional oneOf/anyOf options for it. If the destination
1260
1302
  * schema was located along with oneOf/anyOf options then a `LayoutMultiSchemaField` will be rendered with the
1261
- * `uiSchema`, `errorSchema`, `idSchema` and `formData` drilled down to the dotted-path field, spreading any other
1303
+ * `uiSchema`, `errorSchema`, `fieldPathId` and `formData` drilled down to the dotted-path field, spreading any other
1262
1304
  * props from `gridSchema` into the `ui:options`. If the destination schema located without any oneOf/anyOf options,
1263
1305
  * then a `SchemaField` will be rendered with the same props as mentioned in the previous sentence. If no destination
1264
1306
  * schema was located, but a custom render component was found, then it will be rendered with many of the non-event
@@ -1272,18 +1314,17 @@
1272
1314
  schema: initialSchema,
1273
1315
  uiSchema,
1274
1316
  errorSchema,
1275
- idSchema,
1317
+ fieldPathId,
1276
1318
  onBlur,
1277
1319
  onFocus,
1278
1320
  formData,
1279
1321
  readonly,
1280
1322
  registry,
1281
- idSeparator,
1282
1323
  layoutGridSchema,
1283
1324
  // Used to pull this out of otherProps since we don't want to pass it through
1284
1325
  ...otherProps
1285
1326
  } = this.props;
1286
- const { fields: fields2, schemaUtils } = registry;
1327
+ const { fields: fields2 } = registry;
1287
1328
  const { SchemaField: SchemaField2, LayoutMultiSchemaField: LayoutMultiSchemaField2 } = fields2;
1288
1329
  const uiComponentProps = _LayoutGridField.computeUIComponentPropsFromGridSchema(registry, gridSchema);
1289
1330
  if (uiComponentProps.rendered) {
@@ -1295,15 +1336,8 @@
1295
1336
  isRequired,
1296
1337
  isReadonly,
1297
1338
  optionsInfo,
1298
- idSchema: fieldIdSchema
1299
- } = _LayoutGridField.getSchemaDetailsForField(
1300
- schemaUtils,
1301
- name,
1302
- initialSchema,
1303
- formData,
1304
- idSchema,
1305
- idSeparator
1306
- );
1339
+ fieldPathId: fieldIdSchema
1340
+ } = _LayoutGridField.getSchemaDetailsForField(registry, name, initialSchema, formData, fieldPathId);
1307
1341
  if (schema) {
1308
1342
  const Field = optionsInfo?.hasDiscriminator ? LayoutMultiSchemaField2 : SchemaField2;
1309
1343
  const { fieldUiSchema, uiReadonly } = _LayoutGridField.computeFieldUiSchema(
@@ -1324,8 +1358,7 @@
1324
1358
  schema,
1325
1359
  uiSchema: fieldUiSchema,
1326
1360
  errorSchema: get2(errorSchema, name),
1327
- idSchema: fieldIdSchema,
1328
- idSeparator,
1361
+ fieldPathId: fieldIdSchema,
1329
1362
  formData: get2(formData, name),
1330
1363
  onChange: this.onFieldChange(name),
1331
1364
  onBlur,
@@ -1348,8 +1381,7 @@
1348
1381
  errorSchema,
1349
1382
  uiSchema,
1350
1383
  schema: initialSchema,
1351
- idSchema,
1352
- idSeparator,
1384
+ fieldPathId,
1353
1385
  onBlur,
1354
1386
  onFocus,
1355
1387
  registry,
@@ -1391,7 +1423,7 @@
1391
1423
  }
1392
1424
  };
1393
1425
  function LayoutHeaderField(props) {
1394
- const { idSchema, title, schema, uiSchema, required, registry, name } = props;
1426
+ const { fieldPathId, title, schema, uiSchema, required, registry, name } = props;
1395
1427
  const options = utils.getUiOptions(uiSchema, registry.globalUiOptions);
1396
1428
  const { title: uiTitle } = options;
1397
1429
  const { title: schemaTitle } = schema;
@@ -1407,7 +1439,7 @@
1407
1439
  return /* @__PURE__ */ jsxRuntime.jsx(
1408
1440
  TitleFieldTemplate,
1409
1441
  {
1410
- id: utils.titleId(idSchema),
1442
+ id: utils.titleId(fieldPathId),
1411
1443
  title: fieldTitle,
1412
1444
  required,
1413
1445
  schema,
@@ -1445,7 +1477,7 @@
1445
1477
  baseType,
1446
1478
  disabled = false,
1447
1479
  formData,
1448
- idSchema,
1480
+ fieldPathId,
1449
1481
  onBlur,
1450
1482
  onChange,
1451
1483
  options,
@@ -1462,7 +1494,7 @@
1462
1494
  } = props;
1463
1495
  const { widgets: widgets2, schemaUtils, globalUiOptions } = registry;
1464
1496
  const [enumOptions, setEnumOptions] = react.useState(computeEnumOptions(schema, options, schemaUtils, uiSchema, formData));
1465
- const id = get2(idSchema, utils.ID_KEY);
1497
+ const id = get2(fieldPathId, utils.ID_KEY);
1466
1498
  const discriminator = utils.getDiscriminatorFieldFromSchema(schema);
1467
1499
  const FieldErrorTemplate2 = utils.getTemplate("FieldErrorTemplate", registry, options);
1468
1500
  const FieldTemplate2 = utils.getTemplate("FieldTemplate", registry, options);
@@ -1503,10 +1535,10 @@
1503
1535
  if (newFormData) {
1504
1536
  set(newFormData, selectorField, opt);
1505
1537
  }
1506
- onChange(newFormData, void 0, id);
1538
+ onChange(newFormData, fieldPathId.path, void 0, id);
1507
1539
  };
1508
1540
  const widgetOptions = { enumOptions, ...uiOptions };
1509
- const errors = !hideFieldError && rawErrors.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(FieldErrorTemplate2, { idSchema, schema, errors: rawErrors, registry }) : void 0;
1541
+ const errors = !hideFieldError && rawErrors.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(FieldErrorTemplate2, { fieldPathId, schema, errors: rawErrors, registry }) : void 0;
1510
1542
  const ignored = (value) => noop;
1511
1543
  return /* @__PURE__ */ jsxRuntime.jsx(
1512
1544
  FieldTemplate2,
@@ -1516,7 +1548,6 @@
1516
1548
  label: (title || schema.title) ?? "",
1517
1549
  disabled: disabled || Array.isArray(enumOptions) && isEmpty(enumOptions),
1518
1550
  uiSchema,
1519
- formContext,
1520
1551
  required,
1521
1552
  readonly: !!readonly,
1522
1553
  registry,
@@ -1580,7 +1611,7 @@
1580
1611
  * @param prevState - The previous `AnyOfFieldState` for this template
1581
1612
  */
1582
1613
  componentDidUpdate(prevProps, prevState) {
1583
- const { formData, options, idSchema } = this.props;
1614
+ const { formData, options, fieldPathId } = this.props;
1584
1615
  const { selectedOption } = this.state;
1585
1616
  let newState = this.state;
1586
1617
  if (!utils.deepEquals(prevProps.options, options)) {
@@ -1590,7 +1621,7 @@
1590
1621
  const retrievedOptions = options.map((opt) => schemaUtils.retrieveSchema(opt, formData));
1591
1622
  newState = { selectedOption, retrievedOptions };
1592
1623
  }
1593
- if (!utils.deepEquals(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
1624
+ if (!utils.deepEquals(formData, prevProps.formData) && fieldPathId.$id === prevProps.fieldPathId.$id) {
1594
1625
  const { retrievedOptions } = newState;
1595
1626
  const matchingOption = this.getMatchingOption(selectedOption, formData, retrievedOptions);
1596
1627
  if (prevState && matchingOption !== selectedOption) {
@@ -1624,7 +1655,7 @@
1624
1655
  */
1625
1656
  onOptionChange = (option) => {
1626
1657
  const { selectedOption, retrievedOptions } = this.state;
1627
- const { formData, onChange, registry } = this.props;
1658
+ const { formData, onChange, registry, fieldPathId } = this.props;
1628
1659
  const { schemaUtils } = registry;
1629
1660
  const intOption = option !== void 0 ? parseInt(option, 10) : -1;
1630
1661
  if (intOption === selectedOption) {
@@ -1637,12 +1668,12 @@
1637
1668
  newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
1638
1669
  }
1639
1670
  this.setState({ selectedOption: intOption }, () => {
1640
- onChange(newFormData, void 0, this.getFieldId());
1671
+ onChange(newFormData, fieldPathId.path, void 0, this.getFieldId());
1641
1672
  });
1642
1673
  };
1643
1674
  getFieldId() {
1644
- const { idSchema, schema } = this.props;
1645
- return `${idSchema.$id}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`;
1675
+ const { fieldPathId, schema } = this.props;
1676
+ return `${fieldPathId.$id}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`;
1646
1677
  }
1647
1678
  /** Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData`
1648
1679
  */
@@ -1661,6 +1692,11 @@
1661
1692
  } = this.props;
1662
1693
  const { widgets: widgets2, fields: fields2, translateString, globalUiOptions, schemaUtils } = registry;
1663
1694
  const { SchemaField: _SchemaField } = fields2;
1695
+ const MultiSchemaFieldTemplate2 = utils.getTemplate(
1696
+ "MultiSchemaFieldTemplate",
1697
+ registry,
1698
+ globalUiOptions
1699
+ );
1664
1700
  const { selectedOption, retrievedOptions } = this.state;
1665
1701
  const {
1666
1702
  widget = "select",
@@ -1707,34 +1743,42 @@
1707
1743
  value: index
1708
1744
  };
1709
1745
  });
1710
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel panel-default panel-body", children: [
1711
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "form-group", children: /* @__PURE__ */ jsxRuntime.jsx(
1712
- Widget,
1713
- {
1714
- id: this.getFieldId(),
1715
- name: `${name}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`,
1716
- schema: { type: "number", default: 0 },
1717
- onChange: this.onOptionChange,
1718
- onBlur,
1719
- onFocus,
1720
- disabled: disabled || isEmpty(enumOptions),
1721
- multiple: false,
1722
- rawErrors,
1723
- errorSchema: fieldErrorSchema,
1724
- value: selectedOption >= 0 ? selectedOption : void 0,
1725
- options: { enumOptions, ...uiOptions },
1726
- registry,
1727
- formContext,
1728
- placeholder,
1729
- autocomplete,
1730
- autofocus,
1731
- label: title ?? name,
1732
- hideLabel: !displayLabel,
1733
- readonly
1734
- }
1735
- ) }),
1736
- optionSchema && optionSchema.type !== "null" && /* @__PURE__ */ jsxRuntime.jsx(_SchemaField, { ...this.props, schema: optionSchema, uiSchema: optionUiSchema })
1737
- ] });
1746
+ const selector = /* @__PURE__ */ jsxRuntime.jsx(
1747
+ Widget,
1748
+ {
1749
+ id: this.getFieldId(),
1750
+ name: `${name}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`,
1751
+ schema: { type: "number", default: 0 },
1752
+ onChange: this.onOptionChange,
1753
+ onBlur,
1754
+ onFocus,
1755
+ disabled: disabled || isEmpty(enumOptions),
1756
+ multiple: false,
1757
+ rawErrors,
1758
+ errorSchema: fieldErrorSchema,
1759
+ value: selectedOption >= 0 ? selectedOption : void 0,
1760
+ options: { enumOptions, ...uiOptions },
1761
+ registry,
1762
+ formContext,
1763
+ placeholder,
1764
+ autocomplete,
1765
+ autofocus,
1766
+ label: title ?? name,
1767
+ hideLabel: !displayLabel,
1768
+ readonly
1769
+ }
1770
+ );
1771
+ const optionsSchemaField = optionSchema && optionSchema.type !== "null" && /* @__PURE__ */ jsxRuntime.jsx(_SchemaField, { ...this.props, schema: optionSchema, uiSchema: optionUiSchema }) || null;
1772
+ return /* @__PURE__ */ jsxRuntime.jsx(
1773
+ MultiSchemaFieldTemplate2,
1774
+ {
1775
+ schema,
1776
+ registry,
1777
+ uiSchema,
1778
+ selector,
1779
+ optionSchemaField: optionsSchemaField
1780
+ }
1781
+ );
1738
1782
  }
1739
1783
  };
1740
1784
  var MultiSchemaField_default = AnyOfField;
@@ -1746,13 +1790,13 @@
1746
1790
  const { StringField: StringField2 } = registry.fields;
1747
1791
  let value = formData;
1748
1792
  const handleChange = react.useCallback(
1749
- (value2, errorSchema, id) => {
1793
+ (value2, path, errorSchema, id) => {
1750
1794
  setLastValue(value2);
1751
1795
  if (`${value2}`.charAt(0) === ".") {
1752
1796
  value2 = `0${value2}`;
1753
1797
  }
1754
1798
  const processed = typeof value2 === "string" && value2.match(trailingCharMatcherWithPrefix) ? utils.asNumber(value2.replace(trailingCharMatcher, "")) : utils.asNumber(value2);
1755
- onChange(processed, errorSchema, id);
1799
+ onChange(processed, path, errorSchema, id);
1756
1800
  },
1757
1801
  [onChange]
1758
1802
  );
@@ -1789,20 +1833,12 @@
1789
1833
  * @returns - The onPropertyChange callback for the `name` property
1790
1834
  */
1791
1835
  onPropertyChange = (name, addedByAdditionalProperties = false) => {
1792
- return (value, newErrorSchema, id) => {
1793
- const { formData, onChange, errorSchema } = this.props;
1836
+ return (value, path, newErrorSchema, id) => {
1837
+ const { onChange } = this.props;
1794
1838
  if (value === void 0 && addedByAdditionalProperties) {
1795
1839
  value = "";
1796
1840
  }
1797
- const newFormData = { ...formData, [name]: value };
1798
- onChange(
1799
- newFormData,
1800
- errorSchema && errorSchema && {
1801
- ...errorSchema,
1802
- [name]: newErrorSchema
1803
- },
1804
- id
1805
- );
1841
+ onChange(value, path, newErrorSchema, id);
1806
1842
  };
1807
1843
  };
1808
1844
  /** Returns a callback to handle the onDropPropertyClick event for the given `key` which removes the old `key` data
@@ -1814,10 +1850,10 @@
1814
1850
  onDropPropertyClick = (key) => {
1815
1851
  return (event) => {
1816
1852
  event.preventDefault();
1817
- const { onChange, formData } = this.props;
1853
+ const { onChange, formData, fieldPathId } = this.props;
1818
1854
  const copiedFormData = { ...formData };
1819
1855
  unset(copiedFormData, key);
1820
- onChange(copiedFormData);
1856
+ onChange(copiedFormData, fieldPathId.path);
1821
1857
  };
1822
1858
  };
1823
1859
  /** Computes the next available key name from the `preferredKey`, indexing through the already existing keys until one
@@ -1844,11 +1880,11 @@
1844
1880
  * @returns - The key change callback function
1845
1881
  */
1846
1882
  onKeyChange = (oldValue) => {
1847
- return (value, newErrorSchema) => {
1883
+ return (value) => {
1848
1884
  if (oldValue === value) {
1849
1885
  return;
1850
1886
  }
1851
- const { formData, onChange, errorSchema } = this.props;
1887
+ const { formData, onChange, fieldPathId } = this.props;
1852
1888
  value = this.getAvailableKey(value, formData);
1853
1889
  const newFormData = {
1854
1890
  ...formData
@@ -1860,13 +1896,7 @@
1860
1896
  });
1861
1897
  const renamedObj = Object.assign({}, ...keyValues);
1862
1898
  this.setState({ wasPropertyKeyModified: true });
1863
- onChange(
1864
- renamedObj,
1865
- errorSchema && errorSchema && {
1866
- ...errorSchema,
1867
- [value]: newErrorSchema
1868
- }
1869
- );
1899
+ onChange(renamedObj, fieldPathId.path);
1870
1900
  };
1871
1901
  };
1872
1902
  /** Returns a default value to be used for a new additional schema property of the given `type`
@@ -1902,7 +1932,7 @@
1902
1932
  if (!(schema.additionalProperties || schema.patternProperties)) {
1903
1933
  return;
1904
1934
  }
1905
- const { formData, onChange, registry } = this.props;
1935
+ const { formData, onChange, registry, fieldPathId } = this.props;
1906
1936
  const newFormData = { ...formData };
1907
1937
  const newKey = this.getAvailableKey("newKey", newFormData);
1908
1938
  if (schema.patternProperties) {
@@ -1930,7 +1960,7 @@
1930
1960
  const newValue = constValue ?? defaultValue ?? this.getDefaultValue(type);
1931
1961
  set(newFormData, newKey, newValue);
1932
1962
  }
1933
- onChange(newFormData);
1963
+ onChange(newFormData, fieldPathId.path);
1934
1964
  };
1935
1965
  /** Renders the `ObjectField` from the given props
1936
1966
  */
@@ -1940,20 +1970,18 @@
1940
1970
  uiSchema = {},
1941
1971
  formData,
1942
1972
  errorSchema,
1943
- idSchema,
1973
+ fieldPathId,
1944
1974
  name,
1945
1975
  required = false,
1946
1976
  disabled,
1947
1977
  readonly,
1948
1978
  hideError,
1949
- idPrefix,
1950
- idSeparator,
1951
1979
  onBlur,
1952
1980
  onFocus,
1953
1981
  registry,
1954
1982
  title
1955
1983
  } = this.props;
1956
- const { fields: fields2, formContext, schemaUtils, translateString, globalUiOptions } = registry;
1984
+ const { fields: fields2, formContext, schemaUtils, translateString, globalFormOptions, globalUiOptions } = registry;
1957
1985
  const { SchemaField: SchemaField2 } = fields2;
1958
1986
  const schema = schemaUtils.retrieveSchema(rawSchema, formData);
1959
1987
  const uiOptions = utils.getUiOptions(uiSchema, globalUiOptions);
@@ -1979,7 +2007,7 @@
1979
2007
  const addedByAdditionalProperties = has(schema, [utils.PROPERTIES_KEY, name2, utils.ADDITIONAL_PROPERTY_FLAG]);
1980
2008
  const fieldUiSchema = addedByAdditionalProperties ? uiSchema.additionalProperties : uiSchema[name2];
1981
2009
  const hidden = utils.getUiOptions(fieldUiSchema).widget === "hidden";
1982
- const fieldIdSchema = get2(idSchema, [name2], {});
2010
+ const innerFieldIdPathId = utils.toFieldPathId(name2, globalFormOptions, fieldPathId);
1983
2011
  return {
1984
2012
  content: /* @__PURE__ */ jsxRuntime.jsx(
1985
2013
  SchemaField2,
@@ -1989,9 +2017,7 @@
1989
2017
  schema: get2(schema, [utils.PROPERTIES_KEY, name2], {}),
1990
2018
  uiSchema: fieldUiSchema,
1991
2019
  errorSchema: get2(errorSchema, name2),
1992
- idSchema: fieldIdSchema,
1993
- idPrefix,
1994
- idSeparator,
2020
+ fieldPathId: innerFieldIdPathId,
1995
2021
  formData: get2(formData, name2),
1996
2022
  formContext,
1997
2023
  wasPropertyKeyModified: this.state.wasPropertyKeyModified,
@@ -2017,7 +2043,7 @@
2017
2043
  readonly,
2018
2044
  disabled,
2019
2045
  required,
2020
- idSchema,
2046
+ fieldPathId,
2021
2047
  uiSchema,
2022
2048
  errorSchema,
2023
2049
  schema,
@@ -2038,7 +2064,7 @@
2038
2064
  string: "StringField",
2039
2065
  null: "NullField"
2040
2066
  };
2041
- function getFieldComponent(schema, uiOptions, idSchema, registry) {
2067
+ function getFieldComponent(schema, uiOptions, fieldPathId, registry) {
2042
2068
  const field = uiOptions.field;
2043
2069
  const { fields: fields2, translateString } = registry;
2044
2070
  if (typeof field === "function") {
@@ -2067,7 +2093,7 @@
2067
2093
  UnsupportedFieldTemplate,
2068
2094
  {
2069
2095
  schema,
2070
- idSchema,
2096
+ fieldPathId,
2071
2097
  reason: translateString(utils.TranslatableString.UnknownFieldType, [String(schema.type)]),
2072
2098
  registry
2073
2099
  }
@@ -2077,12 +2103,10 @@
2077
2103
  function SchemaFieldRender(props) {
2078
2104
  const {
2079
2105
  schema: _schema,
2080
- idSchema: _idSchema,
2106
+ fieldPathId,
2081
2107
  uiSchema,
2082
2108
  formData,
2083
2109
  errorSchema,
2084
- idPrefix,
2085
- idSeparator,
2086
2110
  name,
2087
2111
  onChange,
2088
2112
  onKeyChange,
@@ -2102,19 +2126,15 @@
2102
2126
  const FieldHelpTemplate2 = utils.getTemplate("FieldHelpTemplate", registry, uiOptions);
2103
2127
  const FieldErrorTemplate2 = utils.getTemplate("FieldErrorTemplate", registry, uiOptions);
2104
2128
  const schema = schemaUtils.retrieveSchema(_schema, formData);
2105
- const fieldId = _idSchema[utils.ID_KEY];
2106
- const idSchema = utils.mergeObjects(
2107
- schemaUtils.toIdSchema(schema, fieldId, formData, idPrefix, idSeparator),
2108
- _idSchema
2109
- );
2129
+ const fieldId = fieldPathId[utils.ID_KEY];
2110
2130
  const handleFieldComponentChange = react.useCallback(
2111
- (formData2, newErrorSchema, id2) => {
2131
+ (formData2, path, newErrorSchema, id2) => {
2112
2132
  const theId = id2 || fieldId;
2113
- return onChange(formData2, newErrorSchema, theId);
2133
+ return onChange(formData2, path, newErrorSchema, theId);
2114
2134
  },
2115
2135
  [fieldId, onChange]
2116
2136
  );
2117
- const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
2137
+ const FieldComponent = getFieldComponent(schema, uiOptions, fieldPathId, registry);
2118
2138
  const disabled = Boolean(uiOptions.disabled ?? props.disabled);
2119
2139
  const readonly = Boolean(uiOptions.readonly ?? (props.readonly || props.schema.readOnly || schema.readOnly));
2120
2140
  const uiSchemaHideError = uiOptions.hideError;
@@ -2134,7 +2154,7 @@
2134
2154
  {
2135
2155
  ...props,
2136
2156
  onChange: handleFieldComponentChange,
2137
- idSchema,
2157
+ fieldPathId,
2138
2158
  schema,
2139
2159
  uiSchema: fieldUiSchema,
2140
2160
  disabled,
@@ -2146,7 +2166,7 @@
2146
2166
  rawErrors: __errors
2147
2167
  }
2148
2168
  );
2149
- const id = idSchema[utils.ID_KEY];
2169
+ const id = fieldPathId[utils.ID_KEY];
2150
2170
  let label;
2151
2171
  if (wasPropertyKeyModified) {
2152
2172
  label = name;
@@ -2167,7 +2187,7 @@
2167
2187
  FieldHelpTemplate2,
2168
2188
  {
2169
2189
  help,
2170
- idSchema,
2190
+ fieldPathId,
2171
2191
  schema,
2172
2192
  uiSchema,
2173
2193
  hasErrors: !hideError && __errors && __errors.length > 0,
@@ -2179,7 +2199,7 @@
2179
2199
  {
2180
2200
  errors: __errors,
2181
2201
  errorSchema,
2182
- idSchema,
2202
+ fieldPathId,
2183
2203
  schema,
2184
2204
  uiSchema,
2185
2205
  registry
@@ -2214,7 +2234,6 @@
2214
2234
  displayLabel,
2215
2235
  classNames: classNames.join(" ").trim(),
2216
2236
  style: uiOptions.style,
2217
- formContext,
2218
2237
  formData,
2219
2238
  schema,
2220
2239
  uiSchema,
@@ -2235,9 +2254,7 @@
2235
2254
  errorSchema,
2236
2255
  formData,
2237
2256
  formContext,
2238
- idPrefix,
2239
- idSchema,
2240
- idSeparator,
2257
+ fieldPathId,
2241
2258
  onBlur: props.onBlur,
2242
2259
  onChange: props.onChange,
2243
2260
  onFocus: props.onFocus,
@@ -2260,9 +2277,7 @@
2260
2277
  errorSchema,
2261
2278
  formData,
2262
2279
  formContext,
2263
- idPrefix,
2264
- idSchema,
2265
- idSeparator,
2280
+ fieldPathId,
2266
2281
  onBlur: props.onBlur,
2267
2282
  onChange: props.onChange,
2268
2283
  onFocus: props.onFocus,
@@ -2279,7 +2294,11 @@
2279
2294
  }
2280
2295
  var SchemaField = class extends react.Component {
2281
2296
  shouldComponentUpdate(nextProps) {
2282
- return !utils.deepEquals(this.props, nextProps);
2297
+ const {
2298
+ registry: { globalFormOptions }
2299
+ } = this.props;
2300
+ const { experimental_componentUpdateStrategy = "customDeep" } = globalFormOptions;
2301
+ return utils.shouldRender(this, nextProps, this.state, experimental_componentUpdateStrategy);
2283
2302
  }
2284
2303
  render() {
2285
2304
  return /* @__PURE__ */ jsxRuntime.jsx(SchemaFieldRender, { ...this.props });
@@ -2291,7 +2310,7 @@
2291
2310
  schema,
2292
2311
  name,
2293
2312
  uiSchema,
2294
- idSchema,
2313
+ fieldPathId,
2295
2314
  formData,
2296
2315
  required,
2297
2316
  disabled = false,
@@ -2315,19 +2334,25 @@
2315
2334
  const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
2316
2335
  const label = uiTitle ?? title ?? name;
2317
2336
  const Widget = utils.getWidget(schema, widget, widgets2);
2337
+ const onWidgetChange = react.useCallback(
2338
+ (value, errorSchema, id) => {
2339
+ return onChange(value, fieldPathId.path, errorSchema, id);
2340
+ },
2341
+ [onChange, fieldPathId]
2342
+ );
2318
2343
  return /* @__PURE__ */ jsxRuntime.jsx(
2319
2344
  Widget,
2320
2345
  {
2321
2346
  options: { ...options, enumOptions },
2322
2347
  schema,
2323
2348
  uiSchema,
2324
- id: idSchema.$id,
2349
+ id: fieldPathId.$id,
2325
2350
  name,
2326
2351
  label,
2327
2352
  hideLabel: !displayLabel,
2328
2353
  hideError,
2329
2354
  value: formData,
2330
- onChange,
2355
+ onChange: onWidgetChange,
2331
2356
  onBlur,
2332
2357
  onFocus,
2333
2358
  required,
@@ -2343,12 +2368,12 @@
2343
2368
  }
2344
2369
  var StringField_default = StringField;
2345
2370
  function NullField(props) {
2346
- const { formData, onChange } = props;
2371
+ const { name, formData, onChange } = props;
2347
2372
  react.useEffect(() => {
2348
2373
  if (formData === void 0) {
2349
- onChange(null);
2374
+ onChange(null, [name]);
2350
2375
  }
2351
- }, [formData, onChange]);
2376
+ }, [name, formData, onChange]);
2352
2377
  return null;
2353
2378
  }
2354
2379
  var NullField_default = NullField;
@@ -2373,7 +2398,7 @@
2373
2398
  }
2374
2399
  var fields_default = fields;
2375
2400
  function ArrayFieldDescriptionTemplate(props) {
2376
- const { idSchema, description, registry, schema, uiSchema } = props;
2401
+ const { fieldPathId, description, registry, schema, uiSchema } = props;
2377
2402
  const options = utils.getUiOptions(uiSchema, registry.globalUiOptions);
2378
2403
  const { label: displayLabel = true } = options;
2379
2404
  if (!description || !displayLabel) {
@@ -2387,7 +2412,7 @@
2387
2412
  return /* @__PURE__ */ jsxRuntime.jsx(
2388
2413
  DescriptionFieldTemplate,
2389
2414
  {
2390
- id: utils.descriptionId(idSchema),
2415
+ id: utils.descriptionId(fieldPathId),
2391
2416
  description,
2392
2417
  schema,
2393
2418
  uiSchema,
@@ -2431,7 +2456,7 @@
2431
2456
  hasMoveDown,
2432
2457
  hasMoveUp,
2433
2458
  hasRemove,
2434
- idSchema,
2459
+ fieldPathId,
2435
2460
  index,
2436
2461
  onCopyIndexClick,
2437
2462
  onDropIndexClick,
@@ -2449,7 +2474,7 @@
2449
2474
  (hasMoveUp || hasMoveDown) && /* @__PURE__ */ jsxRuntime.jsx(
2450
2475
  MoveUpButton2,
2451
2476
  {
2452
- id: utils.buttonId(idSchema, "moveUp"),
2477
+ id: utils.buttonId(fieldPathId, "moveUp"),
2453
2478
  className: "rjsf-array-item-move-up",
2454
2479
  disabled: disabled || readonly || !hasMoveUp,
2455
2480
  onClick: onArrowUpClick,
@@ -2460,7 +2485,7 @@
2460
2485
  (hasMoveUp || hasMoveDown) && /* @__PURE__ */ jsxRuntime.jsx(
2461
2486
  MoveDownButton2,
2462
2487
  {
2463
- id: utils.buttonId(idSchema, "moveDown"),
2488
+ id: utils.buttonId(fieldPathId, "moveDown"),
2464
2489
  className: "rjsf-array-item-move-down",
2465
2490
  disabled: disabled || readonly || !hasMoveDown,
2466
2491
  onClick: onArrowDownClick,
@@ -2471,7 +2496,7 @@
2471
2496
  hasCopy && /* @__PURE__ */ jsxRuntime.jsx(
2472
2497
  CopyButton2,
2473
2498
  {
2474
- id: utils.buttonId(idSchema, "copy"),
2499
+ id: utils.buttonId(fieldPathId, "copy"),
2475
2500
  className: "rjsf-array-item-copy",
2476
2501
  disabled: disabled || readonly,
2477
2502
  onClick: onCopyClick,
@@ -2482,7 +2507,7 @@
2482
2507
  hasRemove && /* @__PURE__ */ jsxRuntime.jsx(
2483
2508
  RemoveButton2,
2484
2509
  {
2485
- id: utils.buttonId(idSchema, "remove"),
2510
+ id: utils.buttonId(fieldPathId, "remove"),
2486
2511
  className: "rjsf-array-item-remove",
2487
2512
  disabled: disabled || readonly,
2488
2513
  onClick: onRemoveClick,
@@ -2497,7 +2522,7 @@
2497
2522
  canAdd,
2498
2523
  className,
2499
2524
  disabled,
2500
- idSchema,
2525
+ fieldPathId,
2501
2526
  uiSchema,
2502
2527
  items,
2503
2528
  onAddClick,
@@ -2526,11 +2551,11 @@
2526
2551
  const {
2527
2552
  ButtonTemplates: { AddButton: AddButton2 }
2528
2553
  } = registry.templates;
2529
- return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className, id: idSchema.$id, children: [
2554
+ return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className, id: fieldPathId.$id, children: [
2530
2555
  /* @__PURE__ */ jsxRuntime.jsx(
2531
2556
  ArrayFieldTitleTemplate2,
2532
2557
  {
2533
- idSchema,
2558
+ fieldPathId,
2534
2559
  title: uiOptions.title || title,
2535
2560
  required,
2536
2561
  schema,
@@ -2541,7 +2566,7 @@
2541
2566
  /* @__PURE__ */ jsxRuntime.jsx(
2542
2567
  ArrayFieldDescriptionTemplate2,
2543
2568
  {
2544
- idSchema,
2569
+ fieldPathId,
2545
2570
  description: uiOptions.description || schema.description,
2546
2571
  schema,
2547
2572
  uiSchema,
@@ -2552,7 +2577,7 @@
2552
2577
  canAdd && /* @__PURE__ */ jsxRuntime.jsx(
2553
2578
  AddButton2,
2554
2579
  {
2555
- id: utils.buttonId(idSchema, "add"),
2580
+ id: utils.buttonId(fieldPathId, "add"),
2556
2581
  className: "rjsf-array-item-add",
2557
2582
  onClick: onAddClick,
2558
2583
  disabled: disabled || readonly,
@@ -2563,7 +2588,7 @@
2563
2588
  ] });
2564
2589
  }
2565
2590
  function ArrayFieldTitleTemplate(props) {
2566
- const { idSchema, title, schema, uiSchema, required, registry } = props;
2591
+ const { fieldPathId, title, schema, uiSchema, required, registry } = props;
2567
2592
  const options = utils.getUiOptions(uiSchema, registry.globalUiOptions);
2568
2593
  const { label: displayLabel = true } = options;
2569
2594
  if (!title || !displayLabel) {
@@ -2577,7 +2602,7 @@
2577
2602
  return /* @__PURE__ */ jsxRuntime.jsx(
2578
2603
  TitleFieldTemplate,
2579
2604
  {
2580
- id: utils.titleId(idSchema),
2605
+ id: utils.titleId(fieldPathId),
2581
2606
  title,
2582
2607
  required,
2583
2608
  schema,
@@ -2793,21 +2818,21 @@
2793
2818
  // src/components/templates/FieldTemplate/index.ts
2794
2819
  var FieldTemplate_default = FieldTemplate;
2795
2820
  function FieldErrorTemplate(props) {
2796
- const { errors = [], idSchema } = props;
2821
+ const { errors = [], fieldPathId } = props;
2797
2822
  if (errors.length === 0) {
2798
2823
  return null;
2799
2824
  }
2800
- const id = utils.errorId(idSchema);
2825
+ const id = utils.errorId(fieldPathId);
2801
2826
  return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("ul", { id, className: "error-detail bs-callout bs-callout-info", children: errors.filter((elem) => !!elem).map((error, index) => {
2802
2827
  return /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-danger", children: error }, index);
2803
2828
  }) }) });
2804
2829
  }
2805
2830
  function FieldHelpTemplate(props) {
2806
- const { idSchema, help } = props;
2831
+ const { fieldPathId, help } = props;
2807
2832
  if (!help) {
2808
2833
  return null;
2809
2834
  }
2810
- const id = utils.helpId(idSchema);
2835
+ const id = utils.helpId(fieldPathId);
2811
2836
  if (typeof help === "string") {
2812
2837
  return /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "help-block", children: help });
2813
2838
  }
@@ -2817,12 +2842,19 @@
2817
2842
  const { children, column, className, ...rest } = props;
2818
2843
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...rest, children });
2819
2844
  }
2845
+ function MultiSchemaFieldTemplate(props) {
2846
+ const { selector, optionSchemaField } = props;
2847
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel panel-default panel-body", children: [
2848
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "form-group", children: selector }),
2849
+ optionSchemaField
2850
+ ] });
2851
+ }
2820
2852
  function ObjectFieldTemplate(props) {
2821
2853
  const {
2822
2854
  description,
2823
2855
  disabled,
2824
2856
  formData,
2825
- idSchema,
2857
+ fieldPathId,
2826
2858
  onAddClick,
2827
2859
  properties,
2828
2860
  readonly,
@@ -2842,11 +2874,11 @@
2842
2874
  const {
2843
2875
  ButtonTemplates: { AddButton: AddButton2 }
2844
2876
  } = registry.templates;
2845
- return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { id: idSchema.$id, children: [
2877
+ return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { id: fieldPathId.$id, children: [
2846
2878
  title && /* @__PURE__ */ jsxRuntime.jsx(
2847
2879
  TitleFieldTemplate,
2848
2880
  {
2849
- id: utils.titleId(idSchema),
2881
+ id: utils.titleId(fieldPathId),
2850
2882
  title,
2851
2883
  required,
2852
2884
  schema,
@@ -2857,7 +2889,7 @@
2857
2889
  description && /* @__PURE__ */ jsxRuntime.jsx(
2858
2890
  DescriptionFieldTemplate,
2859
2891
  {
2860
- id: utils.descriptionId(idSchema),
2892
+ id: utils.descriptionId(fieldPathId),
2861
2893
  description,
2862
2894
  schema,
2863
2895
  uiSchema,
@@ -2868,7 +2900,7 @@
2868
2900
  utils.canExpand(schema, uiSchema, formData) && /* @__PURE__ */ jsxRuntime.jsx(
2869
2901
  AddButton2,
2870
2902
  {
2871
- id: utils.buttonId(idSchema, "add"),
2903
+ id: utils.buttonId(fieldPathId, "add"),
2872
2904
  className: "rjsf-object-property-expand",
2873
2905
  onClick: onAddClick(schema),
2874
2906
  disabled: disabled || readonly,
@@ -2887,13 +2919,13 @@
2887
2919
  ] });
2888
2920
  }
2889
2921
  function UnsupportedField(props) {
2890
- const { schema, idSchema, reason, registry } = props;
2922
+ const { schema, fieldPathId, reason, registry } = props;
2891
2923
  const { translateString } = registry;
2892
2924
  let translateEnum = utils.TranslatableString.UnsupportedField;
2893
2925
  const translateParams = [];
2894
- if (idSchema && idSchema.$id) {
2926
+ if (fieldPathId && fieldPathId.$id) {
2895
2927
  translateEnum = utils.TranslatableString.UnsupportedFieldWithId;
2896
- translateParams.push(idSchema.$id);
2928
+ translateParams.push(fieldPathId.$id);
2897
2929
  }
2898
2930
  if (reason) {
2899
2931
  translateEnum = translateEnum === utils.TranslatableString.UnsupportedField ? utils.TranslatableString.UnsupportedFieldWithReason : utils.TranslatableString.UnsupportedFieldWithIdAndReason;
@@ -2981,6 +3013,7 @@
2981
3013
  FieldErrorTemplate,
2982
3014
  FieldHelpTemplate,
2983
3015
  GridTemplate,
3016
+ MultiSchemaFieldTemplate,
2984
3017
  ObjectFieldTemplate,
2985
3018
  TitleFieldTemplate: TitleField,
2986
3019
  UnsupportedFieldTemplate: UnsupportedField_default,
@@ -3044,25 +3077,24 @@
3044
3077
  value
3045
3078
  }) {
3046
3079
  const { translateString } = registry;
3047
- const [lastValue, setLastValue] = react.useState(value);
3048
- const [state, setState] = react.useReducer(
3049
- (state2, action) => {
3050
- return { ...state2, ...action };
3080
+ const [state, setState] = react.useState(utils.parseDateString(value, time));
3081
+ react.useEffect(() => {
3082
+ setState(utils.parseDateString(value, time));
3083
+ }, [time, value]);
3084
+ const handleChange = react.useCallback(
3085
+ (property, value2) => {
3086
+ const nextState = {
3087
+ ...state,
3088
+ [property]: typeof value2 === "undefined" ? -1 : value2
3089
+ };
3090
+ if (readyForChange(nextState)) {
3091
+ onChange(utils.toDateString(nextState, time));
3092
+ } else {
3093
+ setState(nextState);
3094
+ }
3051
3095
  },
3052
- utils.parseDateString(value, time)
3096
+ [state, onChange, time]
3053
3097
  );
3054
- react.useEffect(() => {
3055
- const stateValue = utils.toDateString(state, time);
3056
- if (readyForChange(state) && stateValue !== value) {
3057
- onChange(stateValue);
3058
- } else if (lastValue !== value) {
3059
- setLastValue(value);
3060
- setState(utils.parseDateString(value, time));
3061
- }
3062
- }, [time, value, onChange, state, lastValue]);
3063
- const handleChange = react.useCallback((property, value2) => {
3064
- setState({ [property]: value2 });
3065
- }, []);
3066
3098
  const handleSetNow = react.useCallback(
3067
3099
  (event) => {
3068
3100
  event.preventDefault();
@@ -3072,7 +3104,7 @@
3072
3104
  const nextState = utils.parseDateString((/* @__PURE__ */ new Date()).toJSON(), time);
3073
3105
  onChange(utils.toDateString(nextState, time));
3074
3106
  },
3075
- [disabled, readonly, time]
3107
+ [disabled, readonly, time, onChange]
3076
3108
  );
3077
3109
  const handleClear = react.useCallback(
3078
3110
  (event) => {
@@ -3200,11 +3232,11 @@
3200
3232
  const checkboxesValues = Array.isArray(value) ? value : [value];
3201
3233
  const handleBlur = react.useCallback(
3202
3234
  ({ target }) => onBlur(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
3203
- [onBlur, id]
3235
+ [onBlur, id, enumOptions, emptyValue]
3204
3236
  );
3205
3237
  const handleFocus = react.useCallback(
3206
3238
  ({ target }) => onFocus(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
3207
- [onFocus, id]
3239
+ [onFocus, id, enumOptions, emptyValue]
3208
3240
  );
3209
3241
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
3210
3242
  const checked = utils.enumOptionsIsSelected(option.value, checkboxesValues);
@@ -3773,7 +3805,8 @@
3773
3805
  widgets: widgets_default(),
3774
3806
  rootSchema: {},
3775
3807
  formContext: {},
3776
- translateString: utils.englishStringTranslator
3808
+ translateString: utils.englishStringTranslator,
3809
+ globalFormOptions: { idPrefix: utils.DEFAULT_ID_PREFIX, idSeparator: utils.DEFAULT_ID_SEPARATOR }
3777
3810
  };
3778
3811
  }
3779
3812
  var Form = class extends react.Component {
@@ -3781,6 +3814,9 @@
3781
3814
  * provide any possible type here
3782
3815
  */
3783
3816
  formElement;
3817
+ /** The list of pending changes
3818
+ */
3819
+ pendingChanges = [];
3784
3820
  /** Constructs the `Form` from the `props`. Will setup the initial state from the props. It will also call the
3785
3821
  * `onChange` handler if the initially provided `formData` is modified to add missing default values as part of the
3786
3822
  * state construction.
@@ -3819,8 +3855,10 @@
3819
3855
  getSnapshotBeforeUpdate(prevProps, prevState) {
3820
3856
  if (!utils.deepEquals(this.props, prevProps)) {
3821
3857
  const formDataChangedFields = utils.getChangedFields(this.props.formData, prevProps.formData);
3858
+ const stateDataChangedFields = utils.getChangedFields(this.props.formData, this.state.formData);
3822
3859
  const isSchemaChanged = !utils.deepEquals(prevProps.schema, this.props.schema);
3823
3860
  const isFormDataChanged = formDataChangedFields.length > 0 || !utils.deepEquals(prevProps.formData, this.props.formData);
3861
+ const isStateDataChanged = stateDataChangedFields.length > 0 || !utils.deepEquals(this.state.formData, this.props.formData);
3824
3862
  const nextState = this.getStateFromProps(
3825
3863
  this.props,
3826
3864
  this.props.formData,
@@ -3829,7 +3867,9 @@
3829
3867
  // match one of the subSchemas, the retrieved schema must be updated.
3830
3868
  isSchemaChanged || isFormDataChanged ? void 0 : this.state.retrievedSchema,
3831
3869
  isSchemaChanged,
3832
- formDataChangedFields
3870
+ formDataChangedFields,
3871
+ // Skip live validation for this request if no form data has changed from the last state
3872
+ !isStateDataChanged
3833
3873
  );
3834
3874
  const shouldUpdate = !utils.deepEquals(nextState, prevState);
3835
3875
  return { nextState, shouldUpdate };
@@ -3866,35 +3906,37 @@
3866
3906
  * @param retrievedSchema - An expanded schema, if not provided, it will be retrieved from the `schema` and `formData`.
3867
3907
  * @param isSchemaChanged - A flag indicating whether the schema has changed.
3868
3908
  * @param formDataChangedFields - The changed fields of `formData`
3909
+ * @param skipLiveValidate - Optional flag, if true, means that we are not running live validation
3869
3910
  * @returns - The new state for the `Form`
3870
3911
  */
3871
- getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = []) {
3912
+ getStateFromProps(props, inputFormData, retrievedSchema, isSchemaChanged = false, formDataChangedFields = [], skipLiveValidate = false) {
3872
3913
  const state = this.state || {};
3873
3914
  const schema = "schema" in props ? props.schema : this.props.schema;
3915
+ const validator2 = "validator" in props ? props.validator : this.props.validator;
3874
3916
  const uiSchema = ("uiSchema" in props ? props.uiSchema : this.props.uiSchema) || {};
3875
3917
  const edit = typeof inputFormData !== "undefined";
3876
3918
  const liveValidate = "liveValidate" in props ? props.liveValidate : this.props.liveValidate;
3877
3919
  const mustValidate = edit && !props.noValidate && liveValidate;
3878
- const rootSchema = schema;
3879
3920
  const experimental_defaultFormStateBehavior = "experimental_defaultFormStateBehavior" in props ? props.experimental_defaultFormStateBehavior : this.props.experimental_defaultFormStateBehavior;
3880
3921
  const experimental_customMergeAllOf = "experimental_customMergeAllOf" in props ? props.experimental_customMergeAllOf : this.props.experimental_customMergeAllOf;
3881
3922
  let schemaUtils = state.schemaUtils;
3882
3923
  if (!schemaUtils || schemaUtils.doesSchemaUtilsDiffer(
3883
- props.validator,
3884
- rootSchema,
3924
+ validator2,
3925
+ schema,
3885
3926
  experimental_defaultFormStateBehavior,
3886
3927
  experimental_customMergeAllOf
3887
3928
  )) {
3888
3929
  schemaUtils = utils.createSchemaUtils(
3889
- props.validator,
3890
- rootSchema,
3930
+ validator2,
3931
+ schema,
3891
3932
  experimental_defaultFormStateBehavior,
3892
3933
  experimental_customMergeAllOf
3893
3934
  );
3894
3935
  }
3895
- const formData = schemaUtils.getDefaultFormState(schema, inputFormData);
3936
+ const rootSchema = schemaUtils.getRootSchema();
3937
+ const formData = schemaUtils.getDefaultFormState(rootSchema, inputFormData);
3896
3938
  const _retrievedSchema = this.updateRetrievedSchema(
3897
- retrievedSchema ?? schemaUtils.retrieveSchema(schema, formData)
3939
+ retrievedSchema ?? schemaUtils.retrieveSchema(rootSchema, formData)
3898
3940
  );
3899
3941
  const getCurrentErrors = () => {
3900
3942
  if (props.noValidate || isSchemaChanged) {
@@ -3914,8 +3956,8 @@
3914
3956
  let errorSchema;
3915
3957
  let schemaValidationErrors = state.schemaValidationErrors;
3916
3958
  let schemaValidationErrorSchema = state.schemaValidationErrorSchema;
3917
- if (mustValidate) {
3918
- const schemaValidation = this.validate(formData, schema, schemaUtils, _retrievedSchema);
3959
+ if (mustValidate && !skipLiveValidate) {
3960
+ const schemaValidation = this.validate(formData, rootSchema, schemaUtils, _retrievedSchema);
3919
3961
  errors = schemaValidation.errors;
3920
3962
  if (retrievedSchema === void 0) {
3921
3963
  errorSchema = schemaValidation.errorSchema;
@@ -3932,7 +3974,7 @@
3932
3974
  const currentErrors = getCurrentErrors();
3933
3975
  errors = currentErrors.errors;
3934
3976
  errorSchema = currentErrors.errorSchema;
3935
- if (formDataChangedFields.length > 0) {
3977
+ if (formDataChangedFields.length > 0 && !mustValidate) {
3936
3978
  const newErrorSchema = formDataChangedFields.reduce(
3937
3979
  (acc, key) => {
3938
3980
  acc[key] = void 0;
@@ -3952,18 +3994,12 @@
3952
3994
  errorSchema = merged.errorSchema;
3953
3995
  errors = merged.errors;
3954
3996
  }
3955
- const idSchema = schemaUtils.toIdSchema(
3956
- _retrievedSchema,
3957
- uiSchema["ui:rootFieldId"],
3958
- formData,
3959
- props.idPrefix,
3960
- props.idSeparator
3961
- );
3997
+ const fieldPathId = utils.toFieldPathId("", this.getGlobalFormOptions(this.props));
3962
3998
  const nextState = {
3963
3999
  schemaUtils,
3964
- schema,
4000
+ schema: rootSchema,
3965
4001
  uiSchema,
3966
- idSchema,
4002
+ fieldPathId,
3967
4003
  formData,
3968
4004
  edit,
3969
4005
  errors,
@@ -3981,7 +4017,8 @@
3981
4017
  * @returns - True if the component should be updated, false otherwise
3982
4018
  */
3983
4019
  shouldComponentUpdate(nextProps, nextState) {
3984
- return utils.shouldRender(this, nextProps, nextState);
4020
+ const { experimental_componentUpdateStrategy = "customDeep" } = this.props;
4021
+ return utils.shouldRender(this, nextProps, nextState, experimental_componentUpdateStrategy);
3985
4022
  }
3986
4023
  /** Gets the previously raised customValidate errors.
3987
4024
  *
@@ -3993,8 +4030,7 @@
3993
4030
  let customValidateErrors = {};
3994
4031
  if (typeof customValidate === "function") {
3995
4032
  const errorHandler = customValidate(prevFormData, utils.createErrorHandler(prevFormData), uiSchema);
3996
- const userErrorSchema = utils.unwrapErrorHandler(errorHandler);
3997
- customValidateErrors = userErrorSchema;
4033
+ customValidateErrors = utils.unwrapErrorHandler(errorHandler);
3998
4034
  }
3999
4035
  return customValidateErrors;
4000
4036
  }
@@ -4003,9 +4039,10 @@
4003
4039
  *
4004
4040
  * @param formData - The new form data to validate
4005
4041
  * @param schema - The schema used to validate against
4006
- * @param altSchemaUtils - The alternate schemaUtils to use for validation
4042
+ * @param [altSchemaUtils] - The alternate schemaUtils to use for validation
4043
+ * @param [retrievedSchema] - An optionally retrieved schema for per
4007
4044
  */
4008
- validate(formData, schema = this.props.schema, altSchemaUtils, retrievedSchema) {
4045
+ validate(formData, schema = this.state.schema, altSchemaUtils, retrievedSchema) {
4009
4046
  const schemaUtils = altSchemaUtils ? altSchemaUtils : this.state.schemaUtils;
4010
4047
  const { customValidate, transformErrors, uiSchema } = this.props;
4011
4048
  const resolvedSchema = retrievedSchema ?? schemaUtils.retrieveSchema(schema, formData);
@@ -4014,7 +4051,6 @@
4014
4051
  /** Renders any errors contained in the `state` in using the `ErrorList`, if not disabled by `showErrorList`. */
4015
4052
  renderErrors(registry) {
4016
4053
  const { errors, errorSchema, schema, uiSchema } = this.state;
4017
- const { formContext } = this.props;
4018
4054
  const options = utils.getUiOptions(uiSchema);
4019
4055
  const ErrorListTemplate = utils.getTemplate("ErrorListTemplate", registry, options);
4020
4056
  if (errors && errors.length) {
@@ -4025,7 +4061,6 @@
4025
4061
  errorSchema: errorSchema || {},
4026
4062
  schema,
4027
4063
  uiSchema,
4028
- formContext,
4029
4064
  registry
4030
4065
  }
4031
4066
  );
@@ -4053,19 +4088,23 @@
4053
4088
  * @param [formData] - The form data to use while checking for empty objects/arrays
4054
4089
  */
4055
4090
  getFieldNames = (pathSchema, formData) => {
4091
+ const formValueHasData = (value, isLeaf) => typeof value !== "object" || isEmpty(value) || isLeaf && !isEmpty(value);
4056
4092
  const getAllPaths = (_obj, acc = [], paths = [[]]) => {
4057
- Object.keys(_obj).forEach((key) => {
4058
- if (typeof _obj[key] === "object") {
4093
+ const objKeys = Object.keys(_obj);
4094
+ objKeys.forEach((key) => {
4095
+ const data = _obj[key];
4096
+ if (typeof data === "object") {
4059
4097
  const newPaths = paths.map((path) => [...path, key]);
4060
- if (_obj[key][utils.RJSF_ADDITIONAL_PROPERTIES_FLAG] && _obj[key][utils.NAME_KEY] !== "") {
4061
- acc.push(_obj[key][utils.NAME_KEY]);
4098
+ if (data[utils.RJSF_ADDITIONAL_PROPERTIES_FLAG] && data[utils.NAME_KEY] !== "") {
4099
+ acc.push(data[utils.NAME_KEY]);
4062
4100
  } else {
4063
- getAllPaths(_obj[key], acc, newPaths);
4101
+ getAllPaths(data, acc, newPaths);
4064
4102
  }
4065
- } else if (key === utils.NAME_KEY && _obj[key] !== "") {
4103
+ } else if (key === utils.NAME_KEY && data !== "") {
4066
4104
  paths.forEach((path) => {
4067
4105
  const formValue = get2(formData, path);
4068
- if (typeof formValue !== "object" || isEmpty(formValue) || Array.isArray(formValue) && formValue.every((val) => typeof val !== "object")) {
4106
+ const isLeaf = objKeys.length === 1;
4107
+ if (formValueHasData(formValue, isLeaf) || Array.isArray(formValue) && formValue.every((val) => formValueHasData(val, isLeaf))) {
4069
4108
  acc.push(path);
4070
4109
  }
4071
4110
  });
@@ -4085,10 +4124,15 @@
4085
4124
  const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
4086
4125
  const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
4087
4126
  const fieldNames = this.getFieldNames(pathSchema, formData);
4088
- const newFormData = this.getUsedFormData(formData, fieldNames);
4089
- return newFormData;
4127
+ return this.getUsedFormData(formData, fieldNames);
4090
4128
  };
4091
- // Filtering errors based on your retrieved schema to only show errors for properties in the selected branch.
4129
+ /** Filtering errors based on your retrieved schema to only show errors for properties in the selected branch.
4130
+ *
4131
+ * @param schemaErrors - The schema errors to filter
4132
+ * @param [resolvedSchema] - An optionally resolved schema to use for performance reasons
4133
+ * @param [formData] - The formData to help filter errors
4134
+ * @private
4135
+ */
4092
4136
  filterErrorsBasedOnSchema(schemaErrors, resolvedSchema, formData) {
4093
4137
  const { retrievedSchema, schemaUtils } = this.state;
4094
4138
  const _retrievedSchema = resolvedSchema ?? retrievedSchema;
@@ -4096,7 +4140,7 @@
4096
4140
  const fieldNames = this.getFieldNames(pathSchema, formData);
4097
4141
  const filteredErrors = _pick(schemaErrors, fieldNames);
4098
4142
  if (resolvedSchema?.type !== "object" && resolvedSchema?.type !== "array") {
4099
- filteredErrors.__errors = schemaErrors.__errors;
4143
+ filteredErrors[utils.ERRORS_KEY] = schemaErrors[utils.ERRORS_KEY];
4100
4144
  }
4101
4145
  const prevCustomValidateErrors = this.getPreviousCustomValidateErrors();
4102
4146
  const filterPreviousCustomErrors = (errors = [], prevCustomErrors) => {
@@ -4112,9 +4156,14 @@
4112
4156
  const prevCustomValidateErrorAtKey = previousCustomValidateErrors[errorKey];
4113
4157
  if (_isNil(errorAtKey) || Array.isArray(errorAtKey) && errorAtKey.length === 0) {
4114
4158
  delete errors[errorKey];
4115
- } else if (utils.isObject(errorAtKey) && utils.isObject(prevCustomValidateErrorAtKey) && Array.isArray(prevCustomValidateErrorAtKey?.__errors)) {
4116
- errors[errorKey] = filterPreviousCustomErrors(errorAtKey.__errors, prevCustomValidateErrorAtKey.__errors);
4117
- } else if (typeof errorAtKey === "object" && !Array.isArray(errorAtKey.__errors)) {
4159
+ } else if (utils.isObject(errorAtKey) && utils.isObject(prevCustomValidateErrorAtKey) && Array.isArray(prevCustomValidateErrorAtKey?.[utils.ERRORS_KEY])) {
4160
+ errors[errorKey] = {
4161
+ [utils.ERRORS_KEY]: filterPreviousCustomErrors(
4162
+ errorAtKey[utils.ERRORS_KEY],
4163
+ prevCustomValidateErrorAtKey?.[utils.ERRORS_KEY]
4164
+ )
4165
+ };
4166
+ } else if (typeof errorAtKey === "object" && !Array.isArray(errorAtKey[utils.ERRORS_KEY])) {
4118
4167
  filterNilOrEmptyErrors(errorAtKey, previousCustomValidateErrors[errorKey]);
4119
4168
  }
4120
4169
  });
@@ -4122,23 +4171,46 @@
4122
4171
  };
4123
4172
  return filterNilOrEmptyErrors(filteredErrors, prevCustomValidateErrors);
4124
4173
  }
4125
- /** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
4126
- * `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
4127
- * then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
4128
- * in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
4129
- * updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
4130
- * callback will be called if specified with the updated state.
4174
+ /** Pushes the given change information into the `pendingChanges` array and then calls `processPendingChanges()` if
4175
+ * the array only contains a single pending change.
4131
4176
  *
4132
- * @param formData - The new form data from a change to a field
4133
- * @param newErrorSchema - The new `ErrorSchema` based on the field change
4134
- * @param id - The id of the field that caused the change
4177
+ * @param newValue - The new form data from a change to a field
4178
+ * @param path - The path to the change into which to set the formData
4179
+ * @param [newErrorSchema] - The new `ErrorSchema` based on the field change
4180
+ * @param [id] - The id of the field that caused the change
4135
4181
  */
4136
- onChange = (formData, newErrorSchema, id) => {
4182
+ onChange = (newValue, path, newErrorSchema, id) => {
4183
+ this.pendingChanges.push({ newValue, path, newErrorSchema, id });
4184
+ if (this.pendingChanges.length === 1) {
4185
+ this.processPendingChange();
4186
+ }
4187
+ };
4188
+ /** Function to handle changes made to a field in the `Form`. This handler gets the first change from the
4189
+ * `pendingChanges` list, containing the `newValue` for the `formData` and the `path` at which the `newValue` is to be
4190
+ * updated, along with a new, optional `ErrorSchema` for that same `path` and potentially the `id` of the field being
4191
+ * changed. It will first update the `formData` with any missing default fields and then, if `omitExtraData` and
4192
+ * `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not in a form field. Then, the
4193
+ * resulting `formData` will be validated if required. The state will be updated with the new updated (potentially
4194
+ * filtered) `formData`, any errors that resulted from validation. Finally the `onChange` callback will be called, if
4195
+ * specified, with the updated state and the `processPendingChange()` function is called again.
4196
+ */
4197
+ processPendingChange() {
4198
+ if (this.pendingChanges.length === 0) {
4199
+ return;
4200
+ }
4201
+ const { newValue, path, id } = this.pendingChanges[0];
4202
+ let { newErrorSchema } = this.pendingChanges[0];
4137
4203
  const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
4138
- const { schemaUtils, schema } = this.state;
4204
+ const { formData: oldFormData, schemaUtils, schema, errorSchema, fieldPathId } = this.state;
4205
+ const rootPathId = fieldPathId.path[0] || "";
4206
+ const isRootPath = !path || path.length === 0 || path.length === 1 && path[0] === rootPathId;
4139
4207
  let retrievedSchema = this.state.retrievedSchema;
4208
+ let formData = isRootPath ? newValue : _cloneDeep(oldFormData);
4140
4209
  if (utils.isObject(formData) || Array.isArray(formData)) {
4141
- const newState = this.getStateFromProps(this.props, formData);
4210
+ if (!isRootPath) {
4211
+ set(formData, path, newValue);
4212
+ }
4213
+ const newState = this.getStateFromProps(this.props, formData, void 0, void 0, void 0, true);
4142
4214
  formData = newState.formData;
4143
4215
  retrievedSchema = newState.retrievedSchema;
4144
4216
  }
@@ -4151,38 +4223,49 @@
4151
4223
  formData: newFormData
4152
4224
  };
4153
4225
  }
4154
- if (mustValidate) {
4226
+ if (newErrorSchema && !isRootPath) {
4227
+ const errorSchemaCopy = _cloneDeep(errorSchema);
4228
+ set(errorSchemaCopy, path, newErrorSchema);
4229
+ newErrorSchema = errorSchemaCopy;
4230
+ }
4231
+ if (mustValidate && this.pendingChanges.length === 1) {
4155
4232
  const schemaValidation = this.validate(newFormData, schema, schemaUtils, retrievedSchema);
4156
4233
  let errors = schemaValidation.errors;
4157
- let errorSchema = schemaValidation.errorSchema;
4234
+ let errorSchema2 = schemaValidation.errorSchema;
4158
4235
  const schemaValidationErrors = errors;
4159
- const schemaValidationErrorSchema = errorSchema;
4236
+ const schemaValidationErrorSchema = errorSchema2;
4160
4237
  if (extraErrors) {
4161
4238
  const merged = utils.validationDataMerge(schemaValidation, extraErrors);
4162
- errorSchema = merged.errorSchema;
4239
+ errorSchema2 = merged.errorSchema;
4163
4240
  errors = merged.errors;
4164
4241
  }
4165
4242
  if (newErrorSchema) {
4166
4243
  const filteredErrors = this.filterErrorsBasedOnSchema(newErrorSchema, retrievedSchema, newFormData);
4167
- errorSchema = utils.mergeObjects(errorSchema, filteredErrors, "preventDuplicates");
4244
+ errorSchema2 = utils.mergeObjects(errorSchema2, filteredErrors, "preventDuplicates");
4168
4245
  }
4169
4246
  state = {
4170
4247
  formData: newFormData,
4171
4248
  errors,
4172
- errorSchema,
4249
+ errorSchema: errorSchema2,
4173
4250
  schemaValidationErrors,
4174
4251
  schemaValidationErrorSchema
4175
4252
  };
4176
4253
  } else if (!noValidate && newErrorSchema) {
4177
- const errorSchema = extraErrors ? utils.mergeObjects(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
4254
+ const errorSchema2 = extraErrors ? utils.mergeObjects(newErrorSchema, extraErrors, "preventDuplicates") : newErrorSchema;
4178
4255
  state = {
4179
4256
  formData: newFormData,
4180
- errorSchema,
4181
- errors: utils.toErrorList(errorSchema)
4257
+ errorSchema: errorSchema2,
4258
+ errors: utils.toErrorList(errorSchema2)
4182
4259
  };
4183
4260
  }
4184
- this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
4185
- };
4261
+ this.setState(state, () => {
4262
+ if (onChange) {
4263
+ onChange({ ...this.state, ...state }, id);
4264
+ }
4265
+ this.pendingChanges.shift();
4266
+ this.processPendingChange();
4267
+ });
4268
+ }
4186
4269
  /**
4187
4270
  * If the retrievedSchema has changed the new retrievedSchema is returned.
4188
4271
  * Otherwise, the old retrievedSchema is returned to persist reference.
@@ -4277,10 +4360,26 @@
4277
4360
  );
4278
4361
  }
4279
4362
  };
4363
+ /** Extracts the `GlobalFormOptions` from the given Form `props`
4364
+ *
4365
+ * @param props - The form props to extract the global form options from
4366
+ * @returns - The `GlobalFormOptions` from the props
4367
+ * @private
4368
+ */
4369
+ getGlobalFormOptions(props) {
4370
+ const {
4371
+ uiSchema = {},
4372
+ experimental_componentUpdateStrategy,
4373
+ idSeparator = utils.DEFAULT_ID_SEPARATOR,
4374
+ idPrefix = utils.DEFAULT_ID_PREFIX
4375
+ } = props;
4376
+ const rootFieldId = uiSchema["ui:rootFieldId"];
4377
+ return { idPrefix: rootFieldId || idPrefix, idSeparator, experimental_componentUpdateStrategy };
4378
+ }
4280
4379
  /** Returns the registry for the form */
4281
4380
  getRegistry() {
4282
4381
  const { translateString: customTranslateString, uiSchema = {} } = this.props;
4283
- const { schemaUtils } = this.state;
4382
+ const { schema, schemaUtils } = this.state;
4284
4383
  const { fields: fields2, templates: templates2, widgets: widgets2, formContext, translateString } = getDefaultRegistry();
4285
4384
  return {
4286
4385
  fields: { ...fields2, ...this.props.fields },
@@ -4293,11 +4392,12 @@
4293
4392
  }
4294
4393
  },
4295
4394
  widgets: { ...widgets2, ...this.props.widgets },
4296
- rootSchema: this.props.schema,
4395
+ rootSchema: schema,
4297
4396
  formContext: this.props.formContext || formContext,
4298
4397
  schemaUtils,
4299
4398
  translateString: customTranslateString || translateString,
4300
- globalUiOptions: uiSchema[utils.UI_GLOBAL_OPTIONS_KEY]
4399
+ globalUiOptions: uiSchema[utils.UI_GLOBAL_OPTIONS_KEY],
4400
+ globalFormOptions: this.getGlobalFormOptions(this.props)
4301
4401
  };
4302
4402
  }
4303
4403
  /** Provides a function that can be used to programmatically submit the `Form` */
@@ -4412,8 +4512,6 @@
4412
4512
  const {
4413
4513
  children,
4414
4514
  id,
4415
- idPrefix,
4416
- idSeparator,
4417
4515
  className = "",
4418
4516
  tagName,
4419
4517
  name,
@@ -4426,11 +4524,10 @@
4426
4524
  noHtml5Validate = false,
4427
4525
  disabled,
4428
4526
  readonly,
4429
- formContext,
4430
4527
  showErrorList = "top",
4431
4528
  _internalFormWrapper
4432
4529
  } = this.props;
4433
- const { schema, uiSchema, formData, errorSchema, idSchema } = this.state;
4530
+ const { schema, uiSchema, formData, errorSchema, fieldPathId } = this.state;
4434
4531
  const registry = this.getRegistry();
4435
4532
  const { SchemaField: _SchemaField } = registry.fields;
4436
4533
  const { SubmitButton: SubmitButton2 } = registry.templates.ButtonTemplates;
@@ -4466,10 +4563,7 @@
4466
4563
  schema,
4467
4564
  uiSchema,
4468
4565
  errorSchema,
4469
- idSchema,
4470
- idPrefix,
4471
- idSeparator,
4472
- formContext,
4566
+ fieldPathId,
4473
4567
  formData,
4474
4568
  onChange: this.onChange,
4475
4569
  onBlur: this.onBlur,
@@ -4513,6 +4607,20 @@
4513
4607
  }
4514
4608
  );
4515
4609
  }
4610
+ function getTestRegistry(rootSchema, fields2 = {}, templates2 = {}, widgets2 = {}, formContext = {}, globalFormOptions = { idPrefix: utils.DEFAULT_ID_PREFIX, idSeparator: utils.DEFAULT_ID_SEPARATOR }) {
4611
+ const defaults = getDefaultRegistry();
4612
+ const schemaUtils = utils.createSchemaUtils(validator, rootSchema);
4613
+ return {
4614
+ fields: { ...defaults.fields, ...fields2 },
4615
+ templates: { ...defaults.templates, ...templates2 },
4616
+ widgets: { ...defaults.widgets, ...widgets2 },
4617
+ formContext,
4618
+ rootSchema,
4619
+ schemaUtils,
4620
+ translateString: utils.englishStringTranslator,
4621
+ globalFormOptions
4622
+ };
4623
+ }
4516
4624
 
4517
4625
  // src/index.ts
4518
4626
  var index_default = Form;
@@ -4520,6 +4628,7 @@
4520
4628
  exports.RichDescription = RichDescription;
4521
4629
  exports.default = index_default;
4522
4630
  exports.getDefaultRegistry = getDefaultRegistry;
4631
+ exports.getTestRegistry = getTestRegistry;
4523
4632
  exports.withTheme = withTheme;
4524
4633
 
4525
4634
  Object.defineProperty(exports, '__esModule', { value: true });