@limetech/lime-elements 39.20.0 → 39.22.0

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 (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/limel-chip_2.cjs.entry.js +2 -2
  3. package/dist/cjs/limel-form.cjs.entry.js +1111 -263
  4. package/dist/collection/components/chip-set/chip-set.js +3 -2
  5. package/dist/esm/{_baseEach-CL_-rBMy.js → _baseEach-C4UJIc96.js} +1 -1
  6. package/dist/esm/{_baseIsEqual-BfXMsuGh.js → _baseIsEqual-DCZXUzsZ.js} +1 -1
  7. package/dist/esm/{_baseIteratee-kS1-0_xD.js → _baseIteratee-CI-QZdpx.js} +1 -1
  8. package/dist/esm/{_getAllKeysIn-BKpeslPJ.js → _getAllKeysIn-v-KlW5r_.js} +1 -1
  9. package/dist/esm/{cloneDeep-BXAw5H-1.js → cloneDeep-V4fB8wfG.js} +2 -2
  10. package/dist/esm/{difference-DMAjHh-t.js → difference-CWrdq-hd.js} +1 -1
  11. package/dist/esm/{isEmpty-DrFXbHWO.js → isEmpty-BFxMjh_H.js} +1 -1
  12. package/dist/esm/{isEqual-CpaoJ_AF.js → isEqual-CsrptmTU.js} +1 -1
  13. package/dist/esm/limel-chip_2.entry.js +5 -5
  14. package/dist/esm/limel-dialog.entry.js +2 -2
  15. package/dist/esm/limel-file-dropzone_2.entry.js +3 -3
  16. package/dist/esm/limel-form.entry.js +1127 -279
  17. package/dist/esm/limel-prosemirror-adapter.entry.js +4 -4
  18. package/dist/esm/limel-tab-bar.entry.js +3 -3
  19. package/dist/esm/limel-table.entry.js +5 -5
  20. package/dist/esm/{pickBy-BEA90LIZ.js → pickBy-D8CUtxE4.js} +2 -2
  21. package/dist/lime-elements/lime-elements.esm.js +1 -1
  22. package/dist/lime-elements/p-29a59535.entry.js +13 -0
  23. package/dist/lime-elements/p-34d1d00a.entry.js +1 -0
  24. package/dist/lime-elements/{p-4ca67b17.entry.js → p-48db87d3.entry.js} +1 -1
  25. package/dist/lime-elements/{p-757896f5.entry.js → p-4e9baf08.entry.js} +1 -1
  26. package/dist/lime-elements/{p-BbU4FGNT.js → p-7uuv3HUP.js} +1 -1
  27. package/dist/lime-elements/{p-4ce682cf.entry.js → p-8139d26a.entry.js} +1 -1
  28. package/dist/lime-elements/{p-CMjGNANG.js → p-BTHqaZIi.js} +1 -1
  29. package/dist/lime-elements/p-Bj622DVt.js +1 -0
  30. package/dist/lime-elements/p-C3Myy3mA.js +1 -0
  31. package/dist/lime-elements/{p-xQsJdKrq.js → p-CXgJVvTe.js} +1 -1
  32. package/dist/lime-elements/p-CxfAgSVd.js +1 -0
  33. package/dist/lime-elements/{p-DFWcgJ_i.js → p-DNIqLXTL.js} +1 -1
  34. package/dist/lime-elements/p-DbC-smVQ.js +1 -0
  35. package/dist/lime-elements/p-SvuA3Boo.js +1 -0
  36. package/dist/lime-elements/{p-cffc137e.entry.js → p-e720f65c.entry.js} +3 -3
  37. package/dist/lime-elements/{p-8065425a.entry.js → p-fd4a4f87.entry.js} +1 -1
  38. package/dist/types/components/chip-set/chip-set.d.ts +1 -0
  39. package/dist/types/components/chip-set/chip.types.d.ts +4 -0
  40. package/dist/types/components.d.ts +4 -0
  41. package/package.json +4 -4
  42. package/dist/lime-elements/p-B3zCFNAw.js +0 -1
  43. package/dist/lime-elements/p-B6bNnxRu.js +0 -1
  44. package/dist/lime-elements/p-BCMRfUKp.js +0 -1
  45. package/dist/lime-elements/p-DTXIk0fN.js +0 -1
  46. package/dist/lime-elements/p-UGKt6Ywx.js +0 -1
  47. package/dist/lime-elements/p-cae35eb0.entry.js +0 -1
  48. package/dist/lime-elements/p-e60ffc0a.entry.js +0 -13
@@ -1,23 +1,23 @@
1
1
  import { r as registerInstance, c as createEvent, h as h$1, a as getElement } from './index-DBTJNfo7.js';
2
2
  import { g as getDefaultExportFromCjs } from './_commonjsHelpers-B85MJLTf.js';
3
- import { i as isBuffer, a as isTypedArray, b as isArguments, S as Stack, k as keys, c as SetCache, d as cacheHas, e as baseIsEqual, f as baseTimes, g as Set$1, s as setToArray } from './_baseIsEqual-BfXMsuGh.js';
4
- import { t as toString, a as arrayMap, b as baseGet, c as baseIteratee, d as castPath, e as toKey, h as hasIn, s as stringToPath, g as get } from './_baseIteratee-kS1-0_xD.js';
5
- import { b as basePickBy, a as baseSet, h as has, p as pickBy, n as negate } from './pickBy-BEA90LIZ.js';
6
- import { i as isEqual } from './isEqual-CpaoJ_AF.js';
3
+ import { t as toString$1, a as arrayMap, b as baseGet, c as baseIteratee, d as castPath, e as toKey, h as hasIn, s as stringToPath, g as get } from './_baseIteratee-CI-QZdpx.js';
4
+ import { b as basePickBy, a as baseSet, h as has, p as pickBy, n as negate } from './pickBy-D8CUtxE4.js';
5
+ import { i as isBuffer, a as isTypedArray, b as isArguments, S as Stack, k as keys$1, c as SetCache, d as cacheHas, e as baseTimes, f as Set$1, s as setToArray } from './_baseIsEqual-DCZXUzsZ.js';
7
6
  import { i as identity$1 } from './identity-CK4jS9_E.js';
8
7
  import { t as toFinite, i as isIterateeCall } from './_isIterateeCall-CTcCv8Mb.js';
9
- import { c as copyObject, a as copyArray, b as cloneBuffer, d as cloneTypedArray, i as initCloneObject, e as arrayEach, f as baseClone, g as baseCreate, h as cloneDeep } from './cloneDeep-BXAw5H-1.js';
10
- import { b as baseFor, a as baseEach, c as baseForOwn } from './_baseEach-CL_-rBMy.js';
11
- import { g as getPrototype, k as keysIn, a as getAllKeysIn } from './_getAllKeysIn-BKpeslPJ.js';
8
+ import { c as copyObject, a as copyArray, b as cloneBuffer, d as cloneTypedArray, i as initCloneObject, e as arrayEach, f as baseClone, g as baseCreate, h as cloneDeep } from './cloneDeep-V4fB8wfG.js';
9
+ import { b as baseFor, a as baseEach, c as baseForOwn } from './_baseEach-C4UJIc96.js';
10
+ import { g as getPrototype, k as keysIn, a as getAllKeysIn } from './_getAllKeysIn-v-KlW5r_.js';
12
11
  import { i as isArray } from './isArray-B8VKuhvH.js';
13
12
  import { e as eq, i as isFunction } from './eq-D7VMHFyO.js';
14
13
  import { b as baseGetTag, i as isObject$1 } from './isObject-BJQylLSL.js';
15
14
  import { b as baseAssignValue } from './_assignValue-DOEO9byf.js';
16
- import { b as baseRest, a as baseFlatten, s as setToString, o as overRest, i as isArrayLikeObject, c as baseIndexOf, d as arrayIncludes, e as difference } from './difference-DMAjHh-t.js';
15
+ import { b as baseRest, a as baseFlatten, s as setToString, o as overRest, i as isArrayLikeObject, c as baseIndexOf, d as arrayIncludes, e as difference } from './difference-CWrdq-hd.js';
17
16
  import { i as isObjectLike } from './isObjectLike-oiMYqRQ0.js';
18
- import { i as isEmpty } from './isEmpty-DrFXbHWO.js';
17
+ import { i as isEmpty } from './isEmpty-BFxMjh_H.js';
19
18
  import { i as isSymbol } from './isSymbol-ClAke5ga.js';
20
19
  import { i as isArrayLike } from './isArrayLike-D1QkaJU2.js';
20
+ import { i as isEqual } from './isEqual-CsrptmTU.js';
21
21
  import { m as moment } from './moment-DQRNe8qq.js';
22
22
  import { i as isMultiple } from './multiple-BylwpiM6.js';
23
23
  import './_getNative-aN4R8EiP.js';
@@ -147,7 +147,7 @@ var funcProto = Function.prototype,
147
147
  var funcToString = funcProto.toString;
148
148
 
149
149
  /** Used to check objects for own properties. */
150
- var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
150
+ var hasOwnProperty$2 = objectProto$1.hasOwnProperty;
151
151
 
152
152
  /** Used to infer the `Object` constructor. */
153
153
  var objectCtorString = funcToString.call(Object);
@@ -188,7 +188,7 @@ function isPlainObject(value) {
188
188
  if (proto === null) {
189
189
  return true;
190
190
  }
191
- var Ctor = hasOwnProperty$1.call(proto, 'constructor') && proto.constructor;
191
+ var Ctor = hasOwnProperty$2.call(proto, 'constructor') && proto.constructor;
192
192
  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
193
193
  funcToString.call(Ctor) == objectCtorString;
194
194
  }
@@ -335,7 +335,7 @@ function stringToArray(string) {
335
335
  */
336
336
  function createCaseFirst(methodName) {
337
337
  return function(string) {
338
- string = toString(string);
338
+ string = toString$1(string);
339
339
 
340
340
  var strSymbols = hasUnicode(string)
341
341
  ? stringToArray(string)
@@ -388,7 +388,7 @@ var upperFirst = createCaseFirst('toUpperCase');
388
388
  * // => 'Fred'
389
389
  */
390
390
  function capitalize(string) {
391
- return upperFirst(toString(string).toLowerCase());
391
+ return upperFirst(toString$1(string).toLowerCase());
392
392
  }
393
393
 
394
394
  /**
@@ -745,7 +745,7 @@ function baseValues(object, props) {
745
745
  * // => ['h', 'i']
746
746
  */
747
747
  function values(object) {
748
- return object == null ? [] : baseValues(object, keys(object));
748
+ return object == null ? [] : baseValues(object, keys$1(object));
749
749
  }
750
750
 
751
751
  /* Built-in method references for those with the same name as other `lodash` methods. */
@@ -904,44 +904,6 @@ function parent(object, path) {
904
904
  return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
905
905
  }
906
906
 
907
- /**
908
- * This method is like `_.isEqual` except that it accepts `customizer` which
909
- * is invoked to compare values. If `customizer` returns `undefined`, comparisons
910
- * are handled by the method instead. The `customizer` is invoked with up to
911
- * six arguments: (objValue, othValue [, index|key, object, other, stack]).
912
- *
913
- * @static
914
- * @memberOf _
915
- * @since 4.0.0
916
- * @category Lang
917
- * @param {*} value The value to compare.
918
- * @param {*} other The other value to compare.
919
- * @param {Function} [customizer] The function to customize comparisons.
920
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
921
- * @example
922
- *
923
- * function isGreeting(value) {
924
- * return /^h(?:i|ello)$/.test(value);
925
- * }
926
- *
927
- * function customizer(objValue, othValue) {
928
- * if (isGreeting(objValue) && isGreeting(othValue)) {
929
- * return true;
930
- * }
931
- * }
932
- *
933
- * var array = ['hello', 'goodbye'];
934
- * var other = ['hi', 'goodbye'];
935
- *
936
- * _.isEqualWith(array, other, customizer);
937
- * // => true
938
- */
939
- function isEqualWith(value, other, customizer) {
940
- customizer = typeof customizer == 'function' ? customizer : undefined;
941
- var result = customizer ? customizer(value, other) : undefined;
942
- return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
943
- }
944
-
945
907
  /** `Object#toString` result references. */
946
908
  var numberTag = '[object Number]';
947
909
 
@@ -1098,7 +1060,7 @@ var merge = createAssigner(function(object, source, srcIndex) {
1098
1060
  var objectProto = Object.prototype;
1099
1061
 
1100
1062
  /** Used to check objects for own properties. */
1101
- var hasOwnProperty = objectProto.hasOwnProperty;
1063
+ var hasOwnProperty$1 = objectProto.hasOwnProperty;
1102
1064
 
1103
1065
  /**
1104
1066
  * The base implementation of `_.unset`.
@@ -1125,7 +1087,7 @@ function baseUnset(object, path) {
1125
1087
  var key = toKey(path[index]);
1126
1088
 
1127
1089
  // Always block "__proto__" anywhere in the path if it's not expected
1128
- if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
1090
+ if (key === '__proto__' && !hasOwnProperty$1.call(object, '__proto__')) {
1129
1091
  return false;
1130
1092
  }
1131
1093
 
@@ -1430,7 +1392,7 @@ function toPath(value) {
1430
1392
  if (isArray(value)) {
1431
1393
  return arrayMap(value, toKey);
1432
1394
  }
1433
- return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
1395
+ return isSymbol(value) ? [value] : copyArray(stringToPath(toString$1(value)));
1434
1396
  }
1435
1397
 
1436
1398
  /**
@@ -1621,7 +1583,7 @@ var idCounter = 0;
1621
1583
  */
1622
1584
  function uniqueId(prefix) {
1623
1585
  var id = ++idCounter;
1624
- return toString(prefix) + id;
1586
+ return toString$1(prefix) + id;
1625
1587
  }
1626
1588
 
1627
1589
  /**
@@ -18533,23 +18495,633 @@ function createErrorHandler(formData) {
18533
18495
  return handler;
18534
18496
  }
18535
18497
 
18536
- /** Implements a deep equals using the `lodash.isEqualWith` function, that provides a customized comparator that
18537
- * assumes all functions are equivalent.
18498
+ const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
18499
+ // eslint-disable-next-line @typescript-eslint/unbound-method
18500
+ const { hasOwnProperty } = Object.prototype;
18501
+ /**
18502
+ * Combine two comparators into a single comparators.
18503
+ */
18504
+ function combineComparators(comparatorA, comparatorB) {
18505
+ return function isEqual(a, b, state) {
18506
+ return comparatorA(a, b, state) && comparatorB(a, b, state);
18507
+ };
18508
+ }
18509
+ /**
18510
+ * Wrap the provided `areItemsEqual` method to manage the circular state, allowing
18511
+ * for circular references to be safely included in the comparison without creating
18512
+ * stack overflows.
18513
+ */
18514
+ function createIsCircular(areItemsEqual) {
18515
+ return function isCircular(a, b, state) {
18516
+ if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {
18517
+ return areItemsEqual(a, b, state);
18518
+ }
18519
+ const { cache } = state;
18520
+ const cachedA = cache.get(a);
18521
+ const cachedB = cache.get(b);
18522
+ if (cachedA && cachedB) {
18523
+ return cachedA === b && cachedB === a;
18524
+ }
18525
+ cache.set(a, b);
18526
+ cache.set(b, a);
18527
+ const result = areItemsEqual(a, b, state);
18528
+ cache.delete(a);
18529
+ cache.delete(b);
18530
+ return result;
18531
+ };
18532
+ }
18533
+ /**
18534
+ * Get the properties to strictly examine, which include both own properties that are
18535
+ * not enumerable and symbol properties.
18536
+ */
18537
+ function getStrictProperties(object) {
18538
+ return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
18539
+ }
18540
+ /**
18541
+ * Whether the object contains the property passed as an own property.
18542
+ */
18543
+ const hasOwn =
18544
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18545
+ Object.hasOwn || ((object, property) => hasOwnProperty.call(object, property));
18546
+
18547
+ const PREACT_VNODE = '__v';
18548
+ const PREACT_OWNER = '__o';
18549
+ const REACT_OWNER = '_owner';
18550
+ const { getOwnPropertyDescriptor, keys } = Object;
18551
+ /**
18552
+ * Whether the values passed are equal based on a [SameValue](https://262.ecma-international.org/7.0/#sec-samevalue) basis.
18553
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`) or both are `NaN`.
18554
+ *
18555
+ * @note
18556
+ * When available in the environment, this is just a re-export of the global
18557
+ * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) method.
18558
+ */
18559
+ const sameValueEqual =
18560
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18561
+ Object.is
18562
+ || function sameValueEqual(a, b) {
18563
+ return a === b ? a !== 0 || 1 / a === 1 / b : a !== a && b !== b;
18564
+ };
18565
+ /**
18566
+ * Whether the values passed are equal based on a
18567
+ * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
18568
+ * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
18538
18569
  *
18539
- * @param a - The first element to compare
18540
- * @param b - The second element to compare
18541
- * @returns - True if the `a` and `b` are deeply equal, false otherwise
18570
+ * @note
18571
+ * This is mainly available as a convenience function, such as being a default when a function to determine equality between
18572
+ * two objects is used.
18573
+ */
18574
+ function strictEqual(a, b) {
18575
+ return a === b;
18576
+ }
18577
+ /**
18578
+ * Whether the array buffers are equal in value.
18579
+ */
18580
+ function areArrayBuffersEqual(a, b) {
18581
+ return a.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a), new Uint8Array(b));
18582
+ }
18583
+ /**
18584
+ * Whether the arrays are equal in value.
18585
+ */
18586
+ function areArraysEqual(a, b, state) {
18587
+ let index = a.length;
18588
+ if (b.length !== index) {
18589
+ return false;
18590
+ }
18591
+ while (index-- > 0) {
18592
+ if (!state.equals(a[index], b[index], index, index, a, b, state)) {
18593
+ return false;
18594
+ }
18595
+ }
18596
+ return true;
18597
+ }
18598
+ /**
18599
+ * Whether the dataviews are equal in value.
18600
+ */
18601
+ function areDataViewsEqual(a, b) {
18602
+ return (a.byteLength === b.byteLength
18603
+ && areTypedArraysEqual(new Uint8Array(a.buffer, a.byteOffset, a.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength)));
18604
+ }
18605
+ /**
18606
+ * Whether the dates passed are equal in value.
18607
+ */
18608
+ function areDatesEqual(a, b) {
18609
+ return sameValueEqual(a.getTime(), b.getTime());
18610
+ }
18611
+ /**
18612
+ * Whether the errors passed are equal in value.
18613
+ */
18614
+ function areErrorsEqual(a, b) {
18615
+ return a.name === b.name && a.message === b.message && a.cause === b.cause && a.stack === b.stack;
18616
+ }
18617
+ /**
18618
+ * Whether the `Map`s are equal in value.
18542
18619
  */
18543
- function deepEquals(a, b) {
18544
- return isEqualWith(a, b, (obj, other) => {
18545
- if (typeof obj === 'function' && typeof other === 'function') {
18546
- // Assume all functions are equivalent
18547
- // see https://github.com/rjsf-team/react-jsonschema-form/issues/255
18620
+ function areMapsEqual(a, b, state) {
18621
+ const size = a.size;
18622
+ if (size !== b.size) {
18623
+ return false;
18624
+ }
18625
+ if (!size) {
18626
+ return true;
18627
+ }
18628
+ const matchedIndices = new Array(size);
18629
+ const aIterable = a.entries();
18630
+ let aResult;
18631
+ let bResult;
18632
+ let index = 0;
18633
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18634
+ while ((aResult = aIterable.next())) {
18635
+ if (aResult.done) {
18636
+ break;
18637
+ }
18638
+ const bIterable = b.entries();
18639
+ let hasMatch = false;
18640
+ let matchIndex = 0;
18641
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18642
+ while ((bResult = bIterable.next())) {
18643
+ if (bResult.done) {
18644
+ break;
18645
+ }
18646
+ if (matchedIndices[matchIndex]) {
18647
+ matchIndex++;
18648
+ continue;
18649
+ }
18650
+ const aEntry = aResult.value;
18651
+ const bEntry = bResult.value;
18652
+ if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state)
18653
+ && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
18654
+ hasMatch = matchedIndices[matchIndex] = true;
18655
+ break;
18656
+ }
18657
+ matchIndex++;
18658
+ }
18659
+ if (!hasMatch) {
18660
+ return false;
18661
+ }
18662
+ index++;
18663
+ }
18664
+ return true;
18665
+ }
18666
+ /**
18667
+ * Whether the objects are equal in value.
18668
+ */
18669
+ function areObjectsEqual(a, b, state) {
18670
+ const properties = keys(a);
18671
+ let index = properties.length;
18672
+ if (keys(b).length !== index) {
18673
+ return false;
18674
+ }
18675
+ // Decrementing `while` showed faster results than either incrementing or
18676
+ // decrementing `for` loop and than an incrementing `while` loop. Declarative
18677
+ // methods like `some` / `every` were not used to avoid incurring the garbage
18678
+ // cost of anonymous callbacks.
18679
+ while (index-- > 0) {
18680
+ if (!isPropertyEqual(a, b, state, properties[index])) {
18681
+ return false;
18682
+ }
18683
+ }
18684
+ return true;
18685
+ }
18686
+ /**
18687
+ * Whether the objects are equal in value with strict property checking.
18688
+ */
18689
+ function areObjectsEqualStrict(a, b, state) {
18690
+ const properties = getStrictProperties(a);
18691
+ let index = properties.length;
18692
+ if (getStrictProperties(b).length !== index) {
18693
+ return false;
18694
+ }
18695
+ let property;
18696
+ let descriptorA;
18697
+ let descriptorB;
18698
+ // Decrementing `while` showed faster results than either incrementing or
18699
+ // decrementing `for` loop and than an incrementing `while` loop. Declarative
18700
+ // methods like `some` / `every` were not used to avoid incurring the garbage
18701
+ // cost of anonymous callbacks.
18702
+ while (index-- > 0) {
18703
+ property = properties[index];
18704
+ if (!isPropertyEqual(a, b, state, property)) {
18705
+ return false;
18706
+ }
18707
+ descriptorA = getOwnPropertyDescriptor(a, property);
18708
+ descriptorB = getOwnPropertyDescriptor(b, property);
18709
+ if ((descriptorA || descriptorB)
18710
+ && (!descriptorA
18711
+ || !descriptorB
18712
+ || descriptorA.configurable !== descriptorB.configurable
18713
+ || descriptorA.enumerable !== descriptorB.enumerable
18714
+ || descriptorA.writable !== descriptorB.writable)) {
18715
+ return false;
18716
+ }
18717
+ }
18718
+ return true;
18719
+ }
18720
+ /**
18721
+ * Whether the primitive wrappers passed are equal in value.
18722
+ */
18723
+ function arePrimitiveWrappersEqual(a, b) {
18724
+ return sameValueEqual(a.valueOf(), b.valueOf());
18725
+ }
18726
+ /**
18727
+ * Whether the regexps passed are equal in value.
18728
+ */
18729
+ function areRegExpsEqual(a, b) {
18730
+ return a.source === b.source && a.flags === b.flags;
18731
+ }
18732
+ /**
18733
+ * Whether the `Set`s are equal in value.
18734
+ */
18735
+ function areSetsEqual(a, b, state) {
18736
+ const size = a.size;
18737
+ if (size !== b.size) {
18738
+ return false;
18739
+ }
18740
+ if (!size) {
18741
+ return true;
18742
+ }
18743
+ const matchedIndices = new Array(size);
18744
+ const aIterable = a.values();
18745
+ let aResult;
18746
+ let bResult;
18747
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18748
+ while ((aResult = aIterable.next())) {
18749
+ if (aResult.done) {
18750
+ break;
18751
+ }
18752
+ const bIterable = b.values();
18753
+ let hasMatch = false;
18754
+ let matchIndex = 0;
18755
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
18756
+ while ((bResult = bIterable.next())) {
18757
+ if (bResult.done) {
18758
+ break;
18759
+ }
18760
+ if (!matchedIndices[matchIndex]
18761
+ && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
18762
+ hasMatch = matchedIndices[matchIndex] = true;
18763
+ break;
18764
+ }
18765
+ matchIndex++;
18766
+ }
18767
+ if (!hasMatch) {
18768
+ return false;
18769
+ }
18770
+ }
18771
+ return true;
18772
+ }
18773
+ /**
18774
+ * Whether the TypedArray instances are equal in value.
18775
+ */
18776
+ function areTypedArraysEqual(a, b) {
18777
+ let index = a.byteLength;
18778
+ if (b.byteLength !== index || a.byteOffset !== b.byteOffset) {
18779
+ return false;
18780
+ }
18781
+ while (index-- > 0) {
18782
+ if (a[index] !== b[index]) {
18783
+ return false;
18784
+ }
18785
+ }
18786
+ return true;
18787
+ }
18788
+ /**
18789
+ * Whether the URL instances are equal in value.
18790
+ */
18791
+ function areUrlsEqual(a, b) {
18792
+ return (a.hostname === b.hostname
18793
+ && a.pathname === b.pathname
18794
+ && a.protocol === b.protocol
18795
+ && a.port === b.port
18796
+ && a.hash === b.hash
18797
+ && a.username === b.username
18798
+ && a.password === b.password);
18799
+ }
18800
+ function isPropertyEqual(a, b, state, property) {
18801
+ if ((property === REACT_OWNER || property === PREACT_OWNER || property === PREACT_VNODE)
18802
+ && (a.$$typeof || b.$$typeof)) {
18803
+ return true;
18804
+ }
18805
+ return hasOwn(b, property) && state.equals(a[property], b[property], property, property, a, b, state);
18806
+ }
18807
+
18808
+ // eslint-disable-next-line @typescript-eslint/unbound-method
18809
+ const toString = Object.prototype.toString;
18810
+ /**
18811
+ * Create a comparator method based on the type-specific equality comparators passed.
18812
+ */
18813
+ function createEqualityComparator(config) {
18814
+ const supportedComparatorMap = createSupportedComparatorMap(config);
18815
+ const { areArraysEqual, areDatesEqual, areFunctionsEqual, areMapsEqual, areNumbersEqual, areObjectsEqual, areRegExpsEqual, areSetsEqual, getUnsupportedCustomComparator, } = config;
18816
+ /**
18817
+ * compare the value of the two objects and return true if they are equivalent in values
18818
+ */
18819
+ return function comparator(a, b, state) {
18820
+ // If the items are strictly equal, no need to do a value comparison.
18821
+ if (a === b) {
18548
18822
  return true;
18549
18823
  }
18550
- return undefined; // fallback to default isEquals behavior
18551
- });
18824
+ // If either of the items are nullish and fail the strictly equal check
18825
+ // above, then they must be unequal.
18826
+ if (a == null || b == null) {
18827
+ return false;
18828
+ }
18829
+ const type = typeof a;
18830
+ if (type !== typeof b) {
18831
+ return false;
18832
+ }
18833
+ if (type !== 'object') {
18834
+ if (type === 'number' || type === 'bigint') {
18835
+ return areNumbersEqual(a, b, state);
18836
+ }
18837
+ if (type === 'function') {
18838
+ return areFunctionsEqual(a, b, state);
18839
+ }
18840
+ // If a primitive value that is not strictly equal, it must be unequal.
18841
+ return false;
18842
+ }
18843
+ const constructor = a.constructor;
18844
+ // Checks are listed in order of commonality of use-case:
18845
+ // 1. Common complex object types (plain object, array)
18846
+ // 2. Common data values (date, regexp)
18847
+ // 3. Less-common complex object types (map, set)
18848
+ // 4. Less-common data values (promise, primitive wrappers)
18849
+ // Inherently this is both subjective and assumptive, however
18850
+ // when reviewing comparable libraries in the wild this order
18851
+ // appears to be generally consistent.
18852
+ // Constructors should match, otherwise there is potential for false positives
18853
+ // between class and subclass or custom object and POJO.
18854
+ if (constructor !== b.constructor) {
18855
+ return false;
18856
+ }
18857
+ // Try to fast-path equality checks for other complex object types in the
18858
+ // same realm to avoid capturing the string tag. Strict equality is used
18859
+ // instead of `instanceof` because it is more performant for the common
18860
+ // use-case. If someone is creating a subclass from a native class, it will be
18861
+ // handled with the string tag comparison.
18862
+ if (constructor === Object) {
18863
+ return areObjectsEqual(a, b, state);
18864
+ }
18865
+ if (constructor === Array) {
18866
+ return areArraysEqual(a, b, state);
18867
+ }
18868
+ if (constructor === Date) {
18869
+ return areDatesEqual(a, b, state);
18870
+ }
18871
+ if (constructor === RegExp) {
18872
+ return areRegExpsEqual(a, b, state);
18873
+ }
18874
+ if (constructor === Map) {
18875
+ return areMapsEqual(a, b, state);
18876
+ }
18877
+ if (constructor === Set) {
18878
+ return areSetsEqual(a, b, state);
18879
+ }
18880
+ if (constructor === Promise) {
18881
+ // Avoid tag checks for promise values, since we know if they are not referentially equal
18882
+ // then they are not equal.
18883
+ return false;
18884
+ }
18885
+ // `isArray()` works on subclasses and is cross-realm, so we can avoid capturing
18886
+ // the string tag or doing an `instanceof` in edge cases.
18887
+ if (Array.isArray(a)) {
18888
+ return areArraysEqual(a, b, state);
18889
+ }
18890
+ // Since this is a custom object, capture the string tag to determining its type.
18891
+ // This is reasonably performant in modern environments like v8 and SpiderMonkey.
18892
+ const tag = toString.call(a);
18893
+ const supportedComparator = supportedComparatorMap[tag];
18894
+ if (supportedComparator) {
18895
+ return supportedComparator(a, b, state);
18896
+ }
18897
+ const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, state, tag);
18898
+ if (unsupportedCustomComparator) {
18899
+ return unsupportedCustomComparator(a, b, state);
18900
+ }
18901
+ // If not matching any tags that require a specific type of comparison, then we hard-code false because
18902
+ // the only thing remaining is strict equality, which has already been compared. This is for a few reasons:
18903
+ // - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only
18904
+ // comparison that can be made.
18905
+ // - For types that can be introspected but do not have an objective definition of what
18906
+ // equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.
18907
+ // In all cases, these decisions should be reevaluated based on changes to the language and
18908
+ // common development practices.
18909
+ return false;
18910
+ };
18911
+ }
18912
+ /**
18913
+ * Create the configuration object used for building comparators.
18914
+ */
18915
+ function createEqualityComparatorConfig({ circular, createCustomConfig, strict, }) {
18916
+ let config = {
18917
+ areArrayBuffersEqual,
18918
+ areArraysEqual: strict ? areObjectsEqualStrict : areArraysEqual,
18919
+ areDataViewsEqual,
18920
+ areDatesEqual: areDatesEqual,
18921
+ areErrorsEqual: areErrorsEqual,
18922
+ areFunctionsEqual: strictEqual,
18923
+ areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
18924
+ areNumbersEqual: sameValueEqual,
18925
+ areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
18926
+ arePrimitiveWrappersEqual: arePrimitiveWrappersEqual,
18927
+ areRegExpsEqual: areRegExpsEqual,
18928
+ areSetsEqual: strict ? combineComparators(areSetsEqual, areObjectsEqualStrict) : areSetsEqual,
18929
+ areTypedArraysEqual: strict
18930
+ ? combineComparators(areTypedArraysEqual, areObjectsEqualStrict)
18931
+ : areTypedArraysEqual,
18932
+ areUrlsEqual: areUrlsEqual,
18933
+ getUnsupportedCustomComparator: undefined,
18934
+ };
18935
+ if (createCustomConfig) {
18936
+ config = Object.assign({}, config, createCustomConfig(config));
18937
+ }
18938
+ if (circular) {
18939
+ const areArraysEqual = createIsCircular(config.areArraysEqual);
18940
+ const areMapsEqual = createIsCircular(config.areMapsEqual);
18941
+ const areObjectsEqual = createIsCircular(config.areObjectsEqual);
18942
+ const areSetsEqual = createIsCircular(config.areSetsEqual);
18943
+ config = Object.assign({}, config, {
18944
+ areArraysEqual,
18945
+ areMapsEqual,
18946
+ areObjectsEqual,
18947
+ areSetsEqual,
18948
+ });
18949
+ }
18950
+ return config;
18951
+ }
18952
+ /**
18953
+ * Default equality comparator pass-through, used as the standard `isEqual` creator for
18954
+ * use inside the built comparator.
18955
+ */
18956
+ function createInternalEqualityComparator(compare) {
18957
+ return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
18958
+ return compare(a, b, state);
18959
+ };
18552
18960
  }
18961
+ /**
18962
+ * Create the `isEqual` function used by the consuming application.
18963
+ */
18964
+ function createIsEqual({ circular, comparator, createState, equals, strict }) {
18965
+ if (createState) {
18966
+ return function isEqual(a, b) {
18967
+ const { cache = circular ? new WeakMap() : undefined, meta } = createState();
18968
+ return comparator(a, b, {
18969
+ cache,
18970
+ equals,
18971
+ meta,
18972
+ strict,
18973
+ });
18974
+ };
18975
+ }
18976
+ if (circular) {
18977
+ return function isEqual(a, b) {
18978
+ return comparator(a, b, {
18979
+ cache: new WeakMap(),
18980
+ equals,
18981
+ meta: undefined,
18982
+ strict,
18983
+ });
18984
+ };
18985
+ }
18986
+ const state = {
18987
+ cache: undefined,
18988
+ equals,
18989
+ meta: undefined,
18990
+ strict,
18991
+ };
18992
+ return function isEqual(a, b) {
18993
+ return comparator(a, b, state);
18994
+ };
18995
+ }
18996
+ /**
18997
+ * Create a map of `toString()` values to their respective handlers for `tag`-based lookups.
18998
+ */
18999
+ function createSupportedComparatorMap({ areArrayBuffersEqual, areArraysEqual, areDataViewsEqual, areDatesEqual, areErrorsEqual, areFunctionsEqual, areMapsEqual, areNumbersEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, areUrlsEqual, }) {
19000
+ return {
19001
+ '[object Arguments]': areObjectsEqual,
19002
+ '[object Array]': areArraysEqual,
19003
+ '[object ArrayBuffer]': areArrayBuffersEqual,
19004
+ '[object AsyncGeneratorFunction]': areFunctionsEqual,
19005
+ '[object BigInt]': areNumbersEqual,
19006
+ '[object BigInt64Array]': areTypedArraysEqual,
19007
+ '[object BigUint64Array]': areTypedArraysEqual,
19008
+ '[object Boolean]': arePrimitiveWrappersEqual,
19009
+ '[object DataView]': areDataViewsEqual,
19010
+ '[object Date]': areDatesEqual,
19011
+ // If an error tag, it should be tested explicitly. Like RegExp, the properties are not
19012
+ // enumerable, and therefore will give false positives if tested like a standard object.
19013
+ '[object Error]': areErrorsEqual,
19014
+ '[object Float16Array]': areTypedArraysEqual,
19015
+ '[object Float32Array]': areTypedArraysEqual,
19016
+ '[object Float64Array]': areTypedArraysEqual,
19017
+ '[object Function]': areFunctionsEqual,
19018
+ '[object GeneratorFunction]': areFunctionsEqual,
19019
+ '[object Int8Array]': areTypedArraysEqual,
19020
+ '[object Int16Array]': areTypedArraysEqual,
19021
+ '[object Int32Array]': areTypedArraysEqual,
19022
+ '[object Map]': areMapsEqual,
19023
+ '[object Number]': arePrimitiveWrappersEqual,
19024
+ '[object Object]': (a, b, state) =>
19025
+ // The exception for value comparison is custom `Promise`-like class instances. These should
19026
+ // be treated the same as standard `Promise` objects, which means strict equality, and if
19027
+ // it reaches this point then that strict equality comparison has already failed.
19028
+ typeof a.then !== 'function' && typeof b.then !== 'function' && areObjectsEqual(a, b, state),
19029
+ // For RegExp, the properties are not enumerable, and therefore will give false positives if
19030
+ // tested like a standard object.
19031
+ '[object RegExp]': areRegExpsEqual,
19032
+ '[object Set]': areSetsEqual,
19033
+ '[object String]': arePrimitiveWrappersEqual,
19034
+ '[object URL]': areUrlsEqual,
19035
+ '[object Uint8Array]': areTypedArraysEqual,
19036
+ '[object Uint8ClampedArray]': areTypedArraysEqual,
19037
+ '[object Uint16Array]': areTypedArraysEqual,
19038
+ '[object Uint32Array]': areTypedArraysEqual,
19039
+ };
19040
+ }
19041
+
19042
+ /**
19043
+ * Whether the items passed are deeply-equal in value.
19044
+ */
19045
+ createCustomEqual();
19046
+ /**
19047
+ * Whether the items passed are deeply-equal in value based on strict comparison.
19048
+ */
19049
+ createCustomEqual({ strict: true });
19050
+ /**
19051
+ * Whether the items passed are deeply-equal in value, including circular references.
19052
+ */
19053
+ createCustomEqual({ circular: true });
19054
+ /**
19055
+ * Whether the items passed are deeply-equal in value, including circular references,
19056
+ * based on strict comparison.
19057
+ */
19058
+ createCustomEqual({
19059
+ circular: true,
19060
+ strict: true,
19061
+ });
19062
+ /**
19063
+ * Whether the items passed are shallowly-equal in value.
19064
+ */
19065
+ createCustomEqual({
19066
+ createInternalComparator: () => sameValueEqual,
19067
+ });
19068
+ /**
19069
+ * Whether the items passed are shallowly-equal in value based on strict comparison
19070
+ */
19071
+ createCustomEqual({
19072
+ strict: true,
19073
+ createInternalComparator: () => sameValueEqual,
19074
+ });
19075
+ /**
19076
+ * Whether the items passed are shallowly-equal in value, including circular references.
19077
+ */
19078
+ createCustomEqual({
19079
+ circular: true,
19080
+ createInternalComparator: () => sameValueEqual,
19081
+ });
19082
+ /**
19083
+ * Whether the items passed are shallowly-equal in value, including circular references,
19084
+ * based on strict comparison.
19085
+ */
19086
+ createCustomEqual({
19087
+ circular: true,
19088
+ createInternalComparator: () => sameValueEqual,
19089
+ strict: true,
19090
+ });
19091
+ /**
19092
+ * Create a custom equality comparison method.
19093
+ *
19094
+ * This can be done to create very targeted comparisons in extreme hot-path scenarios
19095
+ * where the standard methods are not performant enough, but can also be used to provide
19096
+ * support for legacy environments that do not support expected features like
19097
+ * `RegExp.prototype.flags` out of the box.
19098
+ */
19099
+ function createCustomEqual(options = {}) {
19100
+ const { circular = false, createInternalComparator: createCustomInternalComparator, createState, strict = false, } = options;
19101
+ const config = createEqualityComparatorConfig(options);
19102
+ const comparator = createEqualityComparator(config);
19103
+ const equals = createCustomInternalComparator
19104
+ ? createCustomInternalComparator(comparator)
19105
+ : createInternalEqualityComparator(comparator);
19106
+ return createIsEqual({ circular, comparator, createState, equals, strict });
19107
+ }
19108
+
19109
+ /** Implements a deep equals using `fast-equals.createCustomEqual`. Functions
19110
+ * are always considered equal, and circular references are tracked to avoid
19111
+ * infinite recursion on self-referential inputs.
19112
+ *
19113
+ * @param a - The first element to compare
19114
+ * @param b - The second element to compare
19115
+ * @returns - True if the `a` and `b` are deeply equal, false otherwise
19116
+ */
19117
+ const deepEquals = createCustomEqual({
19118
+ circular: true,
19119
+ createCustomConfig: () => ({
19120
+ areFunctionsEqual(_a, b) {
19121
+ return typeof b === 'function';
19122
+ },
19123
+ }),
19124
+ });
18553
19125
 
18554
19126
  const objProto = Object.prototype;
18555
19127
  function isRecordEmpty(rec) {
@@ -21612,7 +22184,7 @@ function findSelectedOptionInXxxOf(validator, rootSchema, schema, fallbackField,
21612
22184
  const data = get(formData, selectorField);
21613
22185
  if (data !== undefined) {
21614
22186
  return xxxOfs.find((xxx) => {
21615
- return isEqual(get(xxx, [PROPERTIES_KEY, selectorField, DEFAULT_KEY], get(xxx, [PROPERTIES_KEY, selectorField, CONST_KEY])), data);
22187
+ return deepEquals(get(xxx, [PROPERTIES_KEY, selectorField, DEFAULT_KEY], get(xxx, [PROPERTIES_KEY, selectorField, CONST_KEY])), data);
21616
22188
  });
21617
22189
  }
21618
22190
  }
@@ -22496,11 +23068,6 @@ function getObjectDefaults(validator, rawSchema, { rawFormData, rootSchema = {},
22496
23068
  ? retrievedSchema.additionalProperties
22497
23069
  : {};
22498
23070
  const keys = new Set();
22499
- if (isObject(defaults)) {
22500
- Object.keys(defaults)
22501
- .filter((key) => !retrievedSchema.properties || !retrievedSchema.properties[key])
22502
- .forEach((key) => keys.add(key));
22503
- }
22504
23071
  const formDataRequired = [];
22505
23072
  Object.keys(formData)
22506
23073
  .filter((key) => !retrievedSchema.properties || !retrievedSchema.properties[key])
@@ -22508,6 +23075,14 @@ function getObjectDefaults(validator, rawSchema, { rawFormData, rootSchema = {},
22508
23075
  keys.add(key);
22509
23076
  formDataRequired.push(key);
22510
23077
  });
23078
+ // Only seed keys from schema defaults when formData has no additionalProperties of its own.
23079
+ // If the user already has data (e.g. after a key rename), injecting default keys would
23080
+ // re-add stale entries that no longer exist in formData.
23081
+ if (isObject(defaults) && formDataRequired.length === 0) {
23082
+ Object.keys(defaults)
23083
+ .filter((key) => !retrievedSchema.properties || !retrievedSchema.properties[key])
23084
+ .forEach((key) => keys.add(key));
23085
+ }
22511
23086
  keys.forEach((key) => {
22512
23087
  var _a;
22513
23088
  const computedDefault = computeDefaults(validator, additionalPropertiesSchema, {
@@ -23496,6 +24071,67 @@ function englishStringTranslator(stringToTranslate, params) {
23496
24071
  return replaceStringParameters(stringToTranslate, params);
23497
24072
  }
23498
24073
 
24074
+ /** Determines whether the given `value` is (one of) the `selected` value(s).
24075
+ *
24076
+ * @param value - The value being checked to see if it is selected
24077
+ * @param selected - The current selected value or list of values
24078
+ * @returns - true if the `value` is one of the `selected` ones, false otherwise
24079
+ */
24080
+ function enumOptionsIsSelected(value, selected) {
24081
+ if (Array.isArray(selected)) {
24082
+ return selected.some((sel) => deepEquals(sel, value));
24083
+ }
24084
+ return deepEquals(selected, value);
24085
+ }
24086
+
24087
+ /** Returns the index(es) of the options in `allEnumOptions` whose value(s) match the ones in `value`. All the
24088
+ * `enumOptions` are filtered based on whether they are a "selected" `value` and the index of each selected one is then
24089
+ * stored in an array. If `multiple` is true, that array is returned, otherwise the first element in the array is
24090
+ * returned.
24091
+ *
24092
+ * @param value - The single value or list of values for which indexes are desired
24093
+ * @param [allEnumOptions=[]] - The list of all the known enumOptions
24094
+ * @param [multiple=false] - Optional flag, if true will return a list of index, otherwise a single one
24095
+ * @returns - A single string index for the first `value` in `allEnumOptions`, if not `multiple`. Otherwise, the list
24096
+ * of indexes for (each of) the value(s) in `value`.
24097
+ */
24098
+ function enumOptionsIndexForValue(value, allEnumOptions = [], multiple = false) {
24099
+ const selectedIndexes = allEnumOptions
24100
+ .map((opt, index) => (enumOptionsIsSelected(opt.value, value) ? String(index) : undefined))
24101
+ .filter((opt) => typeof opt !== 'undefined');
24102
+ if (!multiple) {
24103
+ return selectedIndexes[0];
24104
+ }
24105
+ return selectedIndexes;
24106
+ }
24107
+
24108
+ /** Computes the value to pass to a select element's `value` attribute.
24109
+ *
24110
+ * When `format` is `'realValue'`, converts form data values to strings.
24111
+ * When `format` is `'indexed'` (the default), resolves to index-based values via
24112
+ * `enumOptionsIndexForValue`. Returns `emptyValue` when the current value is empty.
24113
+ *
24114
+ * @param value - The current form data value
24115
+ * @param enumOptions - The available enum options
24116
+ * @param multiple - Whether the select allows multiple selections
24117
+ * @param [format='indexed'] - How option values are encoded on the DOM
24118
+ * @param emptyValue - The value to return when the selection is empty
24119
+ * @returns The value to use for the select element's `value` attribute
24120
+ */
24121
+ function enumOptionSelectedValue(value, enumOptions, multiple, format = 'indexed', emptyValue) {
24122
+ const isEmpty = typeof value === 'undefined' ||
24123
+ (multiple && Array.isArray(value) && value.length < 1) ||
24124
+ (!multiple && value === emptyValue);
24125
+ if (isEmpty) {
24126
+ return emptyValue;
24127
+ }
24128
+ if (format === 'realValue') {
24129
+ return multiple ? value.map(String) : String(value);
24130
+ }
24131
+ const indexes = enumOptionsIndexForValue(value, enumOptions, multiple);
24132
+ return typeof indexes === 'undefined' ? emptyValue : indexes;
24133
+ }
24134
+
23499
24135
  /** Returns the value(s) from `allEnumOptions` at the index(es) provided by `valueIndex`. If `valueIndex` is not an
23500
24136
  * array AND the index is not valid for `allEnumOptions`, `emptyValue` is returned. If `valueIndex` is an array, AND it
23501
24137
  * contains an invalid index, the returned array will have the resulting undefined values filtered out, leaving only
@@ -23520,6 +24156,84 @@ function enumOptionsValueForIndex(valueIndex, allEnumOptions = [], emptyValue) {
23520
24156
  return option ? option.value : emptyValue;
23521
24157
  }
23522
24158
 
24159
+ /** Resolves a single DOM value string back to its typed enum value in `'realValue'` mode.
24160
+ *
24161
+ * First attempts a reverse lookup by matching `String(opt.value)` against the input.
24162
+ * If no option matches and the input parses as a valid index, falls back to the
24163
+ * option at that index — this is how object/array enum values round-trip, since
24164
+ * they are encoded as indices by the encoder.
24165
+ *
24166
+ * @param value - A single string value from a DOM attribute
24167
+ * @param enumOptions - The available enum options
24168
+ * @param emptyValue - The value to return when the input is empty, options are missing, or no match is found
24169
+ * @returns The original typed enum value, or `emptyValue`
24170
+ */
24171
+ function decodeSingle(value, enumOptions, emptyValue) {
24172
+ if (value === '' || !Array.isArray(enumOptions)) {
24173
+ return emptyValue;
24174
+ }
24175
+ const match = enumOptions.find((opt) => String(opt.value) === value);
24176
+ if (match) {
24177
+ return match.value;
24178
+ }
24179
+ // Fallback: value might be an index (for object/array enum values)
24180
+ const index = Number(value);
24181
+ if (!isNaN(index) && index >= 0 && index < enumOptions.length) {
24182
+ return enumOptions[index].value;
24183
+ }
24184
+ return emptyValue;
24185
+ }
24186
+ /** Decodes a string from a DOM value attribute back to a typed enum value.
24187
+ *
24188
+ * When `format` is `'realValue'`, does a reverse lookup: finds the enum option
24189
+ * whose `String(value)` matches the input string and returns the original typed value.
24190
+ * For object/array values that were encoded as indices, falls back to index resolution.
24191
+ *
24192
+ * When `format` is `'indexed'` (the default), uses index-based resolution via
24193
+ * `enumOptionsValueForIndex`.
24194
+ *
24195
+ * @param value - The string value(s) from the DOM
24196
+ * @param enumOptions - The available enum options
24197
+ * @param [format='indexed'] - How the values were encoded on the DOM
24198
+ * @param emptyValue - The value to return for empty/missing selections
24199
+ * @returns The original typed enum value(s)
24200
+ */
24201
+ function enumOptionValueDecoder(value, enumOptions, format = 'indexed', emptyValue) {
24202
+ if (format !== 'realValue') {
24203
+ return enumOptionsValueForIndex(value, enumOptions, emptyValue);
24204
+ }
24205
+ if (Array.isArray(value)) {
24206
+ return value.map((v) => decodeSingle(v, enumOptions, emptyValue));
24207
+ }
24208
+ return decodeSingle(value, enumOptions, emptyValue);
24209
+ }
24210
+
24211
+ /** Encodes an enum option value into a string for a DOM value attribute.
24212
+ *
24213
+ * When `format` is `'realValue'`, primitive values are converted via `String()`.
24214
+ * Non-primitive values (objects, arrays) fall back to the index since
24215
+ * `String()` would produce `"[object Object]"`.
24216
+ *
24217
+ * When `format` is `'indexed'` (the default), returns the index as a string.
24218
+ *
24219
+ * @param value - The typed enum value
24220
+ * @param index - The option's position in the enumOptions array
24221
+ * @param [format='indexed'] - How to encode the value for the DOM attribute
24222
+ * @returns The string to use as the DOM value attribute
24223
+ */
24224
+ function enumOptionValueEncoder(value, index, format = 'indexed') {
24225
+ if (format !== 'realValue') {
24226
+ return String(index);
24227
+ }
24228
+ if (isNil(value)) {
24229
+ return '';
24230
+ }
24231
+ if (typeof value === 'object') {
24232
+ return String(index);
24233
+ }
24234
+ return String(value);
24235
+ }
24236
+
23523
24237
  /** Removes the enum option value at the `valueIndex` from the currently `selected` (list of) value(s). If `selected` is
23524
24238
  * a list, then that list is updated to remove the enum option value with the `valueIndex` in `allEnumOptions`. If it is
23525
24239
  * a single value, then if the enum option value with the `valueIndex` in `allEnumOptions` matches `selected`, undefined
@@ -23540,40 +24254,6 @@ function enumOptionsDeselectValue(valueIndex, selected, allEnumOptions = []) {
23540
24254
  return deepEquals(value, selected) ? undefined : selected;
23541
24255
  }
23542
24256
 
23543
- /** Determines whether the given `value` is (one of) the `selected` value(s).
23544
- *
23545
- * @param value - The value being checked to see if it is selected
23546
- * @param selected - The current selected value or list of values
23547
- * @returns - true if the `value` is one of the `selected` ones, false otherwise
23548
- */
23549
- function enumOptionsIsSelected(value, selected) {
23550
- if (Array.isArray(selected)) {
23551
- return selected.some((sel) => deepEquals(sel, value));
23552
- }
23553
- return deepEquals(selected, value);
23554
- }
23555
-
23556
- /** Returns the index(es) of the options in `allEnumOptions` whose value(s) match the ones in `value`. All the
23557
- * `enumOptions` are filtered based on whether they are a "selected" `value` and the index of each selected one is then
23558
- * stored in an array. If `multiple` is true, that array is returned, otherwise the first element in the array is
23559
- * returned.
23560
- *
23561
- * @param value - The single value or list of values for which indexes are desired
23562
- * @param [allEnumOptions=[]] - The list of all the known enumOptions
23563
- * @param [multiple=false] - Optional flag, if true will return a list of index, otherwise a single one
23564
- * @returns - A single string index for the first `value` in `allEnumOptions`, if not `multiple`. Otherwise, the list
23565
- * of indexes for (each of) the value(s) in `value`.
23566
- */
23567
- function enumOptionsIndexForValue(value, allEnumOptions = [], multiple = false) {
23568
- const selectedIndexes = allEnumOptions
23569
- .map((opt, index) => (enumOptionsIsSelected(opt.value, value) ? String(index) : undefined))
23570
- .filter((opt) => typeof opt !== 'undefined');
23571
- if (!multiple) {
23572
- return selectedIndexes[0];
23573
- }
23574
- return selectedIndexes;
23575
- }
23576
-
23577
24257
  /** Add the enum option value at the `valueIndex` to the list of `selected` values in the proper order as defined by
23578
24258
  * `allEnumOptions`
23579
24259
  *
@@ -23719,14 +24399,14 @@ function getChangedFields(a, b) {
23719
24399
  return [];
23720
24400
  }
23721
24401
  if (aIsPlainObject && !bIsPlainObject) {
23722
- return keys(a);
24402
+ return keys$1(a);
23723
24403
  }
23724
24404
  else if (!aIsPlainObject && bIsPlainObject) {
23725
- return keys(b);
24405
+ return keys$1(b);
23726
24406
  }
23727
24407
  else {
23728
- const unequalFields = keys(pickBy(a, (value, key) => !deepEquals(value, get(b, key))));
23729
- const diffFields = difference(keys(b), keys(a));
24408
+ const unequalFields = keys$1(pickBy(a, (value, key) => !deepEquals(value, get(b, key))));
24409
+ const diffFields = difference(keys$1(b), keys$1(a));
23730
24410
  return [...unequalFields, ...diffFields];
23731
24411
  }
23732
24412
  }
@@ -23819,6 +24499,15 @@ function getInputProps(schema, defaultType, options = {}, autoDefaultStepAny = t
23819
24499
  }
23820
24500
  }
23821
24501
  }
24502
+ // For date/time input types, propagate formatMinimum/formatMaximum to min/max
24503
+ if (['date', 'datetime-local', 'time', 'week', 'month'].includes(inputProps.type)) {
24504
+ if (schema.formatMinimum !== undefined) {
24505
+ inputProps.min = schema.formatMinimum;
24506
+ }
24507
+ if (schema.formatMaximum !== undefined) {
24508
+ inputProps.max = schema.formatMaximum;
24509
+ }
24510
+ }
23822
24511
  if (options.autocomplete) {
23823
24512
  inputProps.autoComplete = options.autocomplete;
23824
24513
  }
@@ -23828,6 +24517,23 @@ function getInputProps(schema, defaultType, options = {}, autoDefaultStepAny = t
23828
24517
  return inputProps;
23829
24518
  }
23830
24519
 
24520
+ /** Resolves the effective `optionValueFormat` for enum-backed widgets.
24521
+ *
24522
+ * Provides a single source of truth for the default DOM encoding format
24523
+ * (`'indexed'`) used by `SelectWidget`, `RadioWidget`, and `CheckboxesWidget`.
24524
+ * Widgets should call this helper once and pass the result to
24525
+ * `enumOptionValueEncoder`, `enumOptionValueDecoder`, and `enumOptionSelectedValue`
24526
+ * rather than reading `options.optionValueFormat` directly.
24527
+ *
24528
+ * @param options - The widget options (typically from the `options` prop, already
24529
+ * resolved from `ui:options` and `ui:globalOptions`)
24530
+ * @returns The resolved `OptionValueFormat`, defaulting to `'indexed'` when not set
24531
+ */
24532
+ function getOptionValueFormat(options) {
24533
+ var _a;
24534
+ return (_a = options === null || options === void 0 ? void 0 : options.optionValueFormat) !== null && _a !== void 0 ? _a : 'indexed';
24535
+ }
24536
+
23831
24537
  /** The default submit button options, exported for testing purposes
23832
24538
  */
23833
24539
  const DEFAULT_OPTIONS = {
@@ -24244,12 +24950,12 @@ function isFormDataAvailable(formData) {
24244
24950
  */
24245
24951
  function isRootSchema(registry, schemaToCompare) {
24246
24952
  const { rootSchema, schemaUtils } = registry;
24247
- if (isEqual(schemaToCompare, rootSchema)) {
24953
+ if (deepEquals(schemaToCompare, rootSchema)) {
24248
24954
  return true;
24249
24955
  }
24250
24956
  if (REF_KEY in rootSchema) {
24251
24957
  const resolvedSchema = schemaUtils.retrieveSchema(rootSchema);
24252
- return isEqual(schemaToCompare, omit(resolvedSchema, RJSF_REF_KEY));
24958
+ return deepEquals(schemaToCompare, omit(resolvedSchema, RJSF_REF_KEY));
24253
24959
  }
24254
24960
  return false;
24255
24961
  }
@@ -24284,6 +24990,111 @@ function lookupFromFormContext(regOrFc, toLookup, fallback) {
24284
24990
  return get(regOrFc, [...lookupPath, toLookup], fallback);
24285
24991
  }
24286
24992
 
24993
+ /** Determines whether a value is considered "empty" for the purposes of optional object pruning.
24994
+ * A value is empty if it is `undefined`, `null`, an empty string, or an object where all own
24995
+ * properties are themselves empty.
24996
+ *
24997
+ * @param value - The value to check
24998
+ * @returns True if the value is considered empty
24999
+ */
25000
+ function isValueEmpty(value) {
25001
+ if (isNil(value) || value === '') {
25002
+ return true;
25003
+ }
25004
+ if (Array.isArray(value)) {
25005
+ // An empty array is considered empty; a non-empty array is not
25006
+ return value.length === 0;
25007
+ }
25008
+ if (isObject(value)) {
25009
+ const obj = value;
25010
+ const keys = Object.keys(obj);
25011
+ return keys.every((key) => isValueEmpty(obj[key]));
25012
+ }
25013
+ return false;
25014
+ }
25015
+ /** Recursively removes optional objects from the `formData` that are empty (i.e., all their fields
25016
+ * are undefined, null, empty strings, or themselves empty optional objects). This solves the problem
25017
+ * where interacting with fields inside an optional object "activates" it permanently, making the
25018
+ * form unsubmittable when the optional object has required inner fields.
25019
+ *
25020
+ * An object property is considered "optional" when it is NOT listed in its parent schema's `required`
25021
+ * array.
25022
+ *
25023
+ * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
25024
+ * @param schema - The JSON schema describing the `formData`
25025
+ * @param [rootSchema] - The root schema, used primarily to look up `$ref`s
25026
+ * @param [formData] - The current form data to prune
25027
+ * @returns - A new copy of `formData` with empty optional objects removed, or `undefined` if the
25028
+ * entire formData was pruned
25029
+ */
25030
+ function removeOptionalEmptyObjects(validator, schema, rootSchema, formData) {
25031
+ if (!isObject(schema)) {
25032
+ return formData;
25033
+ }
25034
+ const resolvedSchema = retrieveSchema(validator, schema, rootSchema, formData);
25035
+ if (Array.isArray(formData)) {
25036
+ const itemsSchema = resolvedSchema.items;
25037
+ if (!itemsSchema) {
25038
+ return formData;
25039
+ }
25040
+ let hasChanges = false;
25041
+ const mapped = formData.map((item, index) => {
25042
+ let itemSchema = itemsSchema;
25043
+ if (Array.isArray(itemsSchema)) {
25044
+ itemSchema = itemsSchema[index] || resolvedSchema.additionalItems || {};
25045
+ }
25046
+ const cleaned = removeOptionalEmptyObjects(validator, itemSchema, rootSchema, item);
25047
+ if (cleaned !== item) {
25048
+ hasChanges = true;
25049
+ }
25050
+ return cleaned === undefined ? {} : cleaned;
25051
+ });
25052
+ // Although T is an array type here, we still need to cast it back to T since TS
25053
+ // doesn't narrow the generic T automatically
25054
+ return hasChanges ? mapped : formData;
25055
+ }
25056
+ const { properties, required: requiredFields = [] } = resolvedSchema;
25057
+ if (!isObject(formData) || !properties) {
25058
+ return formData;
25059
+ }
25060
+ const result = {};
25061
+ const data = formData;
25062
+ let hasAnyValue = false;
25063
+ for (const key of Object.keys(data)) {
25064
+ const value = data[key];
25065
+ const propertySchema = (properties[key] || {});
25066
+ const isRequired = requiredFields.includes(key);
25067
+ const isObj = isObject(value);
25068
+ const isArr = Array.isArray(value);
25069
+ if ((isObj || isArr) && properties[key]) {
25070
+ // Recursively process nested objects and arrays
25071
+ const cleaned = removeOptionalEmptyObjects(validator, propertySchema, rootSchema, value);
25072
+ if (!isRequired && isValueEmpty(cleaned)) {
25073
+ // This is an optional property and the cleaned result is empty — omit it
25074
+ continue;
25075
+ }
25076
+ result[key] = cleaned;
25077
+ hasAnyValue = true;
25078
+ }
25079
+ else if (!isRequired && isValueEmpty(value) && properties[key]) {
25080
+ // Optional scalar property that is empty — omit it
25081
+ continue;
25082
+ }
25083
+ else {
25084
+ result[key] = value;
25085
+ if (!isValueEmpty(value)) {
25086
+ hasAnyValue = true;
25087
+ }
25088
+ }
25089
+ }
25090
+ // If the entire object ended up empty after pruning, return undefined so that the
25091
+ // caller (which may itself be a recursive call) can decide whether to keep or drop it
25092
+ if (!hasAnyValue && Object.keys(result).length === 0) {
25093
+ return undefined;
25094
+ }
25095
+ return result;
25096
+ }
25097
+
24287
25098
  /** Given a list of `properties` and an `order` list, returns a list that contains the `properties` ordered correctly.
24288
25099
  * If `order` is not an array, then the untouched `properties` list is returned. Otherwise `properties` is ordered per
24289
25100
  * the `order` list. If `order` contains a '*' then any `properties` that are not mentioned explicity in `order` will be
@@ -24354,104 +25165,18 @@ function parseDateString(dateString, includeTime = true) {
24354
25165
  };
24355
25166
  }
24356
25167
 
24357
- // Keywords where child schemas map to uiSchema at the SAME key
24358
- const SAME_KEY_KEYWORDS = [ITEMS_KEY, ADDITIONAL_PROPERTIES_KEY];
24359
- // Keywords where child schemas are in an array, each mapping to uiSchema[keyword][i]
24360
- const ARRAY_KEYWORDS = [ONE_OF_KEY, ANY_OF_KEY, ALL_OF_KEY];
24361
- /** Expands `ui:definitions` into the uiSchema by walking the schema tree and finding all `$ref`s.
24362
- * Called once at form initialization to pre-expand definitions into the uiSchema structure.
24363
- *
24364
- * For recursive schemas, expansion stops at recursion points to avoid infinite loops.
24365
- * Runtime resolution via `resolveUiSchema` handles these cases using registry definitions.
24366
- *
24367
- * @param currentSchema - The current schema node being processed
24368
- * @param uiSchema - The uiSchema at the current path
24369
- * @param registry - The registry containing rootSchema and uiSchemaDefinitions
24370
- * @param visited - Set of $refs already visited (to detect recursion)
24371
- * @returns - The expanded uiSchema with definitions merged in
24372
- */
24373
- function expandUiSchemaDefinitions(currentSchema, uiSchema, registry, visited = new Set()) {
24374
- const { rootSchema, uiSchemaDefinitions: definitions } = registry;
24375
- let result = { ...uiSchema };
24376
- let resolvedSchema = currentSchema;
24377
- const ref = currentSchema[REF_KEY];
24378
- const isRecursive = ref && visited.has(ref);
24379
- if (ref) {
24380
- visited.add(ref);
24381
- if (definitions && ref in definitions) {
24382
- result = mergeObjects(definitions[ref], result);
24383
- }
24384
- if (isRecursive) {
24385
- return result;
24386
- }
24387
- try {
24388
- resolvedSchema = findSchemaDefinition(ref, rootSchema);
24389
- }
24390
- catch (_a) {
24391
- resolvedSchema = currentSchema;
24392
- }
24393
- }
24394
- // Process properties (each property maps to uiSchema[propName] - flattened)
24395
- const properties = resolvedSchema[PROPERTIES_KEY];
24396
- if (properties && isObject(properties)) {
24397
- for (const [propName, propSchema] of Object.entries(properties)) {
24398
- const propUiSchema = (result[propName] || {});
24399
- const expanded = expandUiSchemaDefinitions(propSchema, propUiSchema, registry, new Set(visited));
24400
- if (Object.keys(expanded).length > 0) {
24401
- result[propName] = expanded;
24402
- }
24403
- }
24404
- }
24405
- // Process keywords where child maps to same key in uiSchema (items, additionalProperties)
24406
- for (const keyword of SAME_KEY_KEYWORDS) {
24407
- const subSchema = resolvedSchema[keyword];
24408
- if (subSchema && isObject(subSchema) && !Array.isArray(subSchema)) {
24409
- const currentUiSchema = result[keyword];
24410
- if (typeof currentUiSchema !== 'function') {
24411
- const subUiSchema = (currentUiSchema || {});
24412
- const expanded = expandUiSchemaDefinitions(subSchema, subUiSchema, registry, new Set(visited));
24413
- if (Object.keys(expanded).length > 0) {
24414
- result[keyword] = expanded;
24415
- }
24416
- }
24417
- }
24418
- }
24419
- // Process array keywords (oneOf, anyOf, allOf) - each option maps to uiSchema[keyword][i]
24420
- for (const keyword of ARRAY_KEYWORDS) {
24421
- const schemaOptions = resolvedSchema[keyword];
24422
- if (Array.isArray(schemaOptions) && schemaOptions.length > 0) {
24423
- const currentUiSchemaArray = result[keyword];
24424
- const uiSchemaArray = Array.isArray(currentUiSchemaArray) ? [...currentUiSchemaArray] : [];
24425
- let hasExpanded = false;
24426
- for (let i = 0; i < schemaOptions.length; i++) {
24427
- const optionSchema = schemaOptions[i];
24428
- const optionUiSchema = (uiSchemaArray[i] || {});
24429
- const expanded = expandUiSchemaDefinitions(optionSchema, optionUiSchema, registry, new Set(visited));
24430
- if (Object.keys(expanded).length > 0) {
24431
- uiSchemaArray[i] = expanded;
24432
- hasExpanded = true;
24433
- }
24434
- }
24435
- if (hasExpanded) {
24436
- result[keyword] = uiSchemaArray;
24437
- }
24438
- }
24439
- }
24440
- return result;
24441
- }
24442
25168
  /** Resolves the uiSchema for a given schema, considering `ui:definitions` stored in the registry.
24443
25169
  *
24444
- * This function is called at runtime for each field. It handles recursive schemas where the
24445
- * pre-expansion in `expandUiSchemaDefinitions` couldn't go deeper.
24446
- *
24447
- * When the schema contains a `$ref`, this function looks up the corresponding uiSchema definition
24448
- * from `registry.uiSchemaDefinitions` and merges it with any local uiSchema overrides.
25170
+ * Called at runtime for each field. When the schema contains a `$ref`, looks up the corresponding
25171
+ * uiSchema definition from `registry.uiSchemaDefinitions` and merges it with local overrides.
25172
+ * For schemas with `oneOf`/`anyOf` branches, also populates `uiSchema[keyword][i]` for branches
25173
+ * whose `$ref` matches a definition, so `MultiSchemaField` can read dropdown option titles.
24449
25174
  *
24450
25175
  * Resolution order (later sources override earlier):
24451
25176
  * 1. `ui:definitions[$ref]` - base definition from registry
24452
25177
  * 2. `localUiSchema` - local overrides at current path
24453
25178
  *
24454
- * @param schema - The JSON schema (may still contain `$ref` for recursive schemas)
25179
+ * @param schema - The JSON schema (may contain `$ref` or `RJSF_REF_KEY`)
24455
25180
  * @param localUiSchema - The uiSchema at the current path (local overrides)
24456
25181
  * @param registry - The registry containing `uiSchemaDefinitions`
24457
25182
  * @returns - The resolved uiSchema with definitions merged in
@@ -24459,14 +25184,54 @@ function expandUiSchemaDefinitions(currentSchema, uiSchema, registry, visited =
24459
25184
  function resolveUiSchema(schema, localUiSchema, registry) {
24460
25185
  var _a, _b;
24461
25186
  const ref = ((_a = schema[RJSF_REF_KEY]) !== null && _a !== void 0 ? _a : schema[REF_KEY]);
24462
- const definitionUiSchema = ref ? (_b = registry.uiSchemaDefinitions) === null || _b === void 0 ? void 0 : _b[ref] : undefined;
25187
+ const definitions = registry.uiSchemaDefinitions;
25188
+ const definitionUiSchema = ref && definitions ? definitions[ref] : undefined;
25189
+ let result;
24463
25190
  if (!definitionUiSchema) {
24464
- return localUiSchema || {};
25191
+ result = localUiSchema || {};
25192
+ }
25193
+ else if (!localUiSchema || isEmpty(localUiSchema)) {
25194
+ result = { ...definitionUiSchema };
24465
25195
  }
24466
- if (!localUiSchema || Object.keys(localUiSchema).length === 0) {
24467
- return { ...definitionUiSchema };
25196
+ else {
25197
+ result = mergeObjects(definitionUiSchema, localUiSchema);
24468
25198
  }
24469
- return mergeObjects(definitionUiSchema, localUiSchema);
25199
+ // Walk oneOf/anyOf branches to populate uiSchema[keyword][i] so MultiSchemaField
25200
+ // can read dropdown option titles at the parent level.
25201
+ if (definitions) {
25202
+ let resolvedSchema = schema;
25203
+ if (ref && schema[REF_KEY] && !schema[RJSF_REF_KEY]) {
25204
+ try {
25205
+ resolvedSchema = findSchemaDefinition(ref, registry.rootSchema);
25206
+ }
25207
+ catch (e) {
25208
+ console.warn('could not resolve $ref in resolveUiSchema:\n', e);
25209
+ return result;
25210
+ }
25211
+ }
25212
+ for (const keyword of [ONE_OF_KEY, ANY_OF_KEY]) {
25213
+ const schemaOptions = resolvedSchema[keyword];
25214
+ if (!Array.isArray(schemaOptions) || schemaOptions.length === 0) {
25215
+ continue;
25216
+ }
25217
+ const currentUiSchemaArray = result[keyword];
25218
+ const uiSchemaArray = Array.isArray(currentUiSchemaArray) ? [...currentUiSchemaArray] : [];
25219
+ let hasExpanded = false;
25220
+ for (let i = 0; i < schemaOptions.length; i++) {
25221
+ const option = schemaOptions[i];
25222
+ const optionRef = ((_b = option === null || option === void 0 ? void 0 : option[RJSF_REF_KEY]) !== null && _b !== void 0 ? _b : option === null || option === void 0 ? void 0 : option[REF_KEY]);
25223
+ if (optionRef && optionRef in definitions) {
25224
+ const optionUiSchema = (uiSchemaArray[i] || {});
25225
+ uiSchemaArray[i] = mergeObjects(definitions[optionRef], optionUiSchema);
25226
+ hasExpanded = true;
25227
+ }
25228
+ }
25229
+ if (hasExpanded) {
25230
+ result[keyword] = uiSchemaArray;
25231
+ }
25232
+ }
25233
+ }
25234
+ return result;
24470
25235
  }
24471
25236
 
24472
25237
  /** Check to see if a `schema` specifies that a value must be true. This happens when:
@@ -24777,7 +25542,7 @@ function useAltDateWidgetProps(props) {
24777
25542
  */
24778
25543
  function useDeepCompareMemo(newValue) {
24779
25544
  const valueRef = reactExports.useRef(newValue);
24780
- if (!isEqual(newValue, valueRef.current)) {
25545
+ if (!deepEquals(newValue, valueRef.current)) {
24781
25546
  valueRef.current = newValue;
24782
25547
  }
24783
25548
  return valueRef.current;
@@ -25702,10 +26467,12 @@ function ArrayField$1(props) {
25702
26467
  * @param index - The index of the item being changed
25703
26468
  */
25704
26469
  const handleChange = reactExports.useCallback((value, path, newErrorSchema, id) => {
26470
+ const lastPathIsItemIndex = typeof path.at(-1) === 'number';
25705
26471
  onChange(
25706
26472
  // We need to treat undefined items as nulls to have validation.
25707
26473
  // See https://github.com/tdegrunt/jsonschema/issues/206
25708
- value === undefined ? null : value, path, newErrorSchema, id);
26474
+ // Only set to null for array items, and not for object properties within array items
26475
+ lastPathIsItemIndex && value === undefined ? null : value, path, newErrorSchema, id);
25709
26476
  }, [onChange]);
25710
26477
  /** Callback handler used to change the value for a checkbox */
25711
26478
  const onSelectChange = reactExports.useCallback((value) => {
@@ -27021,11 +27788,14 @@ function ObjectField$1(props) {
27021
27788
  const { schema: rawSchema, uiSchema = {}, formData, errorSchema, fieldPathId, name, required = false, disabled, readonly, hideError, onBlur, onFocus, onChange, registry, title, } = props;
27022
27789
  const { fields, schemaUtils, translateString, globalUiOptions } = registry;
27023
27790
  const { OptionalDataControlsField } = fields;
27791
+ const formDataRef = reactExports.useRef(formData);
27792
+ formDataRef.current = formData;
27024
27793
  const schema = schemaUtils.retrieveSchema(rawSchema, formData, true);
27025
27794
  const uiOptions = getUiOptions(uiSchema, globalUiOptions);
27026
27795
  const { properties: schemaProperties = {} } = schema;
27027
27796
  // All the children will use childFieldPathId if present in the props, falling back to the fieldPathId
27028
27797
  const childFieldPathId = props.childFieldPathId ?? fieldPathId;
27798
+ const lastRenamedProperty = reactExports.useRef({ previousKey: '', currentKey: undefined });
27029
27799
  const templateTitle = uiOptions.title ?? schema.title ?? title ?? name;
27030
27800
  const description = uiOptions.description ?? schema.description;
27031
27801
  const renderOptionalField = shouldRenderOptionalField(registry, schema, required, uiSchema);
@@ -27085,6 +27855,10 @@ function ObjectField$1(props) {
27085
27855
  // Cast this to make the `set` work properly
27086
27856
  set(newFormData, newKey, newValue);
27087
27857
  }
27858
+ if (lastRenamedProperty.current.previousKey === newKey) {
27859
+ lastRenamedProperty.current.currentKey = newKey;
27860
+ lastRenamedProperty.current.previousKey = getAvailableKey(newKey, newFormData);
27861
+ }
27088
27862
  onChange(newFormData, childFieldPathId.path);
27089
27863
  }, [formData, onChange, registry, childFieldPathId, getAvailableKey, schema]);
27090
27864
  /** Returns a callback function that deals with the rename of a key for an additional property for a schema. That
@@ -27096,9 +27870,10 @@ function ObjectField$1(props) {
27096
27870
  */
27097
27871
  const handleKeyRename = reactExports.useCallback((oldKey, newKey) => {
27098
27872
  if (oldKey !== newKey) {
27099
- const actualNewKey = getAvailableKey(newKey, formData);
27873
+ const currentFormData = formDataRef.current;
27874
+ const actualNewKey = getAvailableKey(newKey, currentFormData);
27100
27875
  const newFormData = {
27101
- ...formData,
27876
+ ...currentFormData,
27102
27877
  };
27103
27878
  const newKeys = { [oldKey]: actualNewKey };
27104
27879
  const keyValues = Object.keys(newFormData).map((key) => {
@@ -27106,15 +27881,31 @@ function ObjectField$1(props) {
27106
27881
  return { [newKey]: newFormData[key] };
27107
27882
  });
27108
27883
  const renamedObj = Object.assign({}, ...keyValues);
27884
+ formDataRef.current = renamedObj;
27885
+ if (oldKey !== lastRenamedProperty.current.currentKey) {
27886
+ lastRenamedProperty.current.previousKey = oldKey;
27887
+ }
27888
+ lastRenamedProperty.current.currentKey = actualNewKey;
27109
27889
  onChange(renamedObj, childFieldPathId.path);
27110
27890
  }
27111
- }, [formData, onChange, childFieldPathId, getAvailableKey]);
27891
+ }, [onChange, childFieldPathId, getAvailableKey]);
27112
27892
  /** Handles the remove click which calls the `onChange` callback with the special ADDITIONAL_PROPERTY_FIELD_REMOVE
27113
27893
  * value for the path plus the key to be removed
27114
27894
  */
27115
27895
  const handleRemoveProperty = reactExports.useCallback((key) => {
27116
27896
  onChange(ADDITIONAL_PROPERTY_KEY_REMOVE, [...childFieldPathId.path, key]);
27117
27897
  }, [onChange, childFieldPathId]);
27898
+ /** Returns the stable React key for a property. For the most recently renamed
27899
+ * additional property, returns the previous key so that React reuses the
27900
+ * existing component instance instead of unmounting/remounting it. This
27901
+ * preserves DOM focus naturally without manual focus management.
27902
+ */
27903
+ const getStableKey = reactExports.useCallback((property) => {
27904
+ if (lastRenamedProperty.current.currentKey === property) {
27905
+ return lastRenamedProperty.current.previousKey;
27906
+ }
27907
+ return property;
27908
+ }, []);
27118
27909
  if (!renderOptionalField || hasFormData) {
27119
27910
  try {
27120
27911
  const properties = Object.keys(schemaProperties);
@@ -27134,7 +27925,7 @@ function ObjectField$1(props) {
27134
27925
  const addedByAdditionalProperties = has(schema, [PROPERTIES_KEY, name, ADDITIONAL_PROPERTY_FLAG]);
27135
27926
  const fieldUiSchema = addedByAdditionalProperties ? uiSchema.additionalProperties : uiSchema[name];
27136
27927
  const hidden = getUiOptions(fieldUiSchema).widget === 'hidden';
27137
- const content = (jsxRuntimeExports.jsx(ObjectFieldProperty, { propertyName: name, required: isRequired(schema, name), schema: get(schema, [PROPERTIES_KEY, name], {}), uiSchema: fieldUiSchema, errorSchema: get(errorSchema, [name]), fieldPathId: childFieldPathId, formData: get(formData, [name]), handleKeyRename: handleKeyRename, handleRemoveProperty: handleRemoveProperty, addedByAdditionalProperties: addedByAdditionalProperties, onChange: onChange, onBlur: onBlur, onFocus: onFocus, registry: registry, disabled: disabled, readonly: readonly, hideError: hideError }, name));
27928
+ const content = (jsxRuntimeExports.jsx(ObjectFieldProperty, { propertyName: name, required: isRequired(schema, name), schema: get(schema, [PROPERTIES_KEY, name], {}), uiSchema: fieldUiSchema, errorSchema: get(errorSchema, [name]), fieldPathId: childFieldPathId, formData: get(formData, [name]), handleKeyRename: handleKeyRename, handleRemoveProperty: handleRemoveProperty, addedByAdditionalProperties: addedByAdditionalProperties, onChange: onChange, onBlur: onBlur, onFocus: onFocus, registry: registry, disabled: disabled, readonly: readonly, hideError: hideError }, getStableKey(name)));
27138
27929
  return {
27139
27930
  content,
27140
27931
  name,
@@ -27879,7 +28670,7 @@ function WrapIfAdditionalTemplate(props) {
27879
28670
  return (jsxRuntimeExports.jsx("div", { className: uiClassNames, style: style, children: children }));
27880
28671
  }
27881
28672
  const margin = hasDescription ? 46 : 26;
27882
- return (jsxRuntimeExports.jsx("div", { className: uiClassNames, style: style, children: jsxRuntimeExports.jsxs("div", { className: 'row', children: [jsxRuntimeExports.jsx("div", { className: 'col-xs-5 form-additional', children: jsxRuntimeExports.jsxs("div", { className: 'form-group', children: [displayLabel && jsxRuntimeExports.jsx(Label, { label: keyLabel, required: required, id: `${id}-key` }), displayLabel && rawDescription && jsxRuntimeExports.jsx("div", { children: "\u00A0" }), jsxRuntimeExports.jsx("input", { className: 'form-control', type: 'text', id: `${id}-key`, onBlur: onKeyRenameBlur, defaultValue: label })] }) }), jsxRuntimeExports.jsx("div", { className: 'form-additional form-group col-xs-5', children: children }), jsxRuntimeExports.jsx("div", { className: 'col-xs-2', style: { marginTop: displayLabel ? `${margin}px` : undefined }, children: jsxRuntimeExports.jsx(RemoveButton, { id: buttonId(id, 'remove'), className: 'rjsf-object-property-remove btn-block', style: { border: '0' }, disabled: disabled || readonly, onClick: onRemoveProperty, uiSchema: uiSchema, registry: registry }) })] }) }));
28673
+ return (jsxRuntimeExports.jsx("div", { className: uiClassNames, style: style, children: jsxRuntimeExports.jsxs("div", { className: 'row', children: [jsxRuntimeExports.jsx("div", { className: 'col-xs-5 form-additional', children: jsxRuntimeExports.jsxs("div", { className: 'form-group', children: [displayLabel && jsxRuntimeExports.jsx(Label, { label: keyLabel, required: required, id: `${id}-key` }), displayLabel && rawDescription && jsxRuntimeExports.jsx("div", { children: "\u00A0" }), jsxRuntimeExports.jsx("input", { className: 'form-control', type: 'text', id: `${id}-key`, onBlur: onKeyRenameBlur, defaultValue: label }, label)] }) }), jsxRuntimeExports.jsx("div", { className: 'form-additional form-group col-xs-5', children: children }), jsxRuntimeExports.jsx("div", { className: 'col-xs-2', style: { marginTop: displayLabel ? `${margin}px` : undefined }, children: jsxRuntimeExports.jsx(RemoveButton, { id: buttonId(id, 'remove'), className: 'rjsf-object-property-remove btn-block', style: { border: '0' }, disabled: disabled || readonly, onClick: onRemoveProperty, uiSchema: uiSchema, registry: registry }) })] }) }));
27883
28674
  }
27884
28675
 
27885
28676
  function templates() {
@@ -27952,10 +28743,12 @@ function CheckboxWidget({ schema, uiSchema, options, id, value, disabled, readon
27952
28743
  *
27953
28744
  * @param props - The `WidgetProps` for this component
27954
28745
  */
27955
- function CheckboxesWidget({ id, disabled, options: { inline = false, enumOptions, enumDisabled, emptyValue }, value, autofocus = false, readonly, onChange, onBlur, onFocus, htmlName, }) {
28746
+ function CheckboxesWidget({ id, disabled, options, value, autofocus = false, readonly, onChange, onBlur, onFocus, htmlName, }) {
28747
+ const { inline = false, enumOptions, enumDisabled, emptyValue } = options;
28748
+ const optionValueFormat = getOptionValueFormat(options);
27956
28749
  const checkboxesValues = Array.isArray(value) ? value : [value];
27957
- const handleBlur = reactExports.useCallback(({ target }) => onBlur(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)), [onBlur, id, enumOptions, emptyValue]);
27958
- const handleFocus = reactExports.useCallback(({ target }) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)), [onFocus, id, enumOptions, emptyValue]);
28750
+ const handleBlur = reactExports.useCallback(({ target }) => onBlur(id, enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)), [onBlur, id, enumOptions, emptyValue, optionValueFormat]);
28751
+ const handleFocus = reactExports.useCallback(({ target }) => onFocus(id, enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)), [onFocus, id, enumOptions, emptyValue, optionValueFormat]);
27959
28752
  return (jsxRuntimeExports.jsx("div", { className: 'checkboxes', id: id, children: Array.isArray(enumOptions) &&
27960
28753
  enumOptions.map((option, index) => {
27961
28754
  const checked = enumOptionsIsSelected(option.value, checkboxesValues);
@@ -27969,7 +28762,7 @@ function CheckboxesWidget({ id, disabled, options: { inline = false, enumOptions
27969
28762
  onChange(enumOptionsDeselectValue(index, checkboxesValues, enumOptions));
27970
28763
  }
27971
28764
  };
27972
- const checkbox = (jsxRuntimeExports.jsxs("span", { children: [jsxRuntimeExports.jsx("input", { type: 'checkbox', id: optionId(id, index), name: htmlName || id, checked: checked, value: String(index), disabled: disabled || itemDisabled || readonly, autoFocus: autofocus && index === 0, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, "aria-describedby": ariaDescribedByIds(id) }), jsxRuntimeExports.jsx("span", { children: option.label })] }));
28765
+ const checkbox = (jsxRuntimeExports.jsxs("span", { children: [jsxRuntimeExports.jsx("input", { type: 'checkbox', id: optionId(id, index), name: htmlName || id, checked: checked, value: enumOptionValueEncoder(option.value, index, optionValueFormat), disabled: disabled || itemDisabled || readonly, autoFocus: autofocus && index === 0, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, "aria-describedby": ariaDescribedByIds(id) }), jsxRuntimeExports.jsx("span", { children: option.label })] }));
27973
28766
  return inline ? (jsxRuntimeExports.jsx("label", { className: `checkbox-inline ${disabledCls}`, children: checkbox }, index)) : (jsxRuntimeExports.jsx("div", { className: `checkbox ${disabledCls}`, children: jsxRuntimeExports.jsx("label", { children: checkbox }) }, index));
27974
28767
  }) }));
27975
28768
  }
@@ -28087,15 +28880,16 @@ function PasswordWidget(props) {
28087
28880
  */
28088
28881
  function RadioWidget({ options, value, required, disabled, readonly, autofocus = false, onBlur, onFocus, onChange, id, htmlName, }) {
28089
28882
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
28090
- const handleBlur = reactExports.useCallback(({ target }) => onBlur(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)), [onBlur, enumOptions, emptyValue, id]);
28091
- const handleFocus = reactExports.useCallback(({ target }) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)), [onFocus, enumOptions, emptyValue, id]);
28883
+ const optionValueFormat = getOptionValueFormat(options);
28884
+ const handleBlur = reactExports.useCallback(({ target }) => onBlur(id, enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)), [onBlur, enumOptions, emptyValue, id, optionValueFormat]);
28885
+ const handleFocus = reactExports.useCallback(({ target }) => onFocus(id, enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)), [onFocus, enumOptions, emptyValue, id, optionValueFormat]);
28092
28886
  return (jsxRuntimeExports.jsx("div", { className: 'field-radio-group', id: id, role: 'radiogroup', children: Array.isArray(enumOptions) &&
28093
28887
  enumOptions.map((option, i) => {
28094
28888
  const checked = enumOptionsIsSelected(option.value, value);
28095
28889
  const itemDisabled = Array.isArray(enumDisabled) && enumDisabled.indexOf(option.value) !== -1;
28096
28890
  const disabledCls = disabled || itemDisabled || readonly ? 'disabled' : '';
28097
28891
  const handleChange = () => onChange(option.value);
28098
- const radio = (jsxRuntimeExports.jsxs("span", { children: [jsxRuntimeExports.jsx("input", { type: 'radio', id: optionId(id, i), checked: checked, name: htmlName || id, required: required, value: String(i), disabled: disabled || itemDisabled || readonly, autoFocus: autofocus && i === 0, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, "aria-describedby": ariaDescribedByIds(id) }), jsxRuntimeExports.jsx("span", { children: option.label })] }));
28892
+ const radio = (jsxRuntimeExports.jsxs("span", { children: [jsxRuntimeExports.jsx("input", { type: 'radio', id: optionId(id, i), checked: checked, name: htmlName || id, required: required, value: enumOptionValueEncoder(option.value, i, optionValueFormat), disabled: disabled || itemDisabled || readonly, autoFocus: autofocus && i === 0, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, "aria-describedby": ariaDescribedByIds(id) }), jsxRuntimeExports.jsx("span", { children: option.label })] }));
28099
28893
  return inline ? (jsxRuntimeExports.jsx("label", { className: `radio-inline ${disabledCls}`, children: radio }, i)) : (jsxRuntimeExports.jsx("div", { className: `radio ${disabledCls}`, children: jsxRuntimeExports.jsx("label", { children: radio }) }, i));
28100
28894
  }) }));
28101
28895
  }
@@ -28189,24 +28983,25 @@ function getValue(event, multiple) {
28189
28983
  function SelectWidget({ schema, id, options, value, required, disabled, readonly, multiple = false, autofocus = false, onChange, onBlur, onFocus, placeholder, htmlName, }) {
28190
28984
  const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options;
28191
28985
  const emptyValue = multiple ? [] : '';
28986
+ const optionValueFormat = getOptionValueFormat(options);
28192
28987
  const handleFocus = reactExports.useCallback((event) => {
28193
28988
  const newValue = getValue(event, multiple);
28194
- return onFocus(id, enumOptionsValueForIndex(newValue, enumOptions, optEmptyVal));
28195
- }, [onFocus, id, multiple, enumOptions, optEmptyVal]);
28989
+ return onFocus(id, enumOptionValueDecoder(newValue, enumOptions, optionValueFormat, optEmptyVal));
28990
+ }, [onFocus, id, multiple, enumOptions, optEmptyVal, optionValueFormat]);
28196
28991
  const handleBlur = reactExports.useCallback((event) => {
28197
28992
  const newValue = getValue(event, multiple);
28198
- return onBlur(id, enumOptionsValueForIndex(newValue, enumOptions, optEmptyVal));
28199
- }, [onBlur, id, multiple, enumOptions, optEmptyVal]);
28993
+ return onBlur(id, enumOptionValueDecoder(newValue, enumOptions, optionValueFormat, optEmptyVal));
28994
+ }, [onBlur, id, multiple, enumOptions, optEmptyVal, optionValueFormat]);
28200
28995
  const handleChange = reactExports.useCallback((event) => {
28201
28996
  const newValue = getValue(event, multiple);
28202
- return onChange(enumOptionsValueForIndex(newValue, enumOptions, optEmptyVal));
28203
- }, [onChange, multiple, enumOptions, optEmptyVal]);
28204
- const selectedIndexes = enumOptionsIndexForValue(value, enumOptions, multiple);
28997
+ return onChange(enumOptionValueDecoder(newValue, enumOptions, optionValueFormat, optEmptyVal));
28998
+ }, [onChange, multiple, enumOptions, optEmptyVal, optionValueFormat]);
28999
+ const selectValue = enumOptionSelectedValue(value, enumOptions, multiple, optionValueFormat, emptyValue);
28205
29000
  const showPlaceholderOption = !multiple && schema.default === undefined;
28206
- return (jsxRuntimeExports.jsxs("select", { id: id, name: htmlName || id, multiple: multiple, role: 'combobox', className: 'form-control', value: typeof selectedIndexes === 'undefined' ? emptyValue : selectedIndexes, required: required, disabled: disabled || readonly, autoFocus: autofocus, onBlur: handleBlur, onFocus: handleFocus, onChange: handleChange, "aria-describedby": ariaDescribedByIds(id), children: [showPlaceholderOption && jsxRuntimeExports.jsx("option", { value: '', children: placeholder }), Array.isArray(enumOptions) &&
29001
+ return (jsxRuntimeExports.jsxs("select", { id: id, name: htmlName || id, multiple: multiple, role: 'combobox', className: 'form-control', value: selectValue, required: required, disabled: disabled || readonly, autoFocus: autofocus, onBlur: handleBlur, onFocus: handleFocus, onChange: handleChange, "aria-describedby": ariaDescribedByIds(id), children: [showPlaceholderOption && jsxRuntimeExports.jsx("option", { value: '', children: placeholder }), Array.isArray(enumOptions) &&
28207
29002
  enumOptions.map(({ value, label }, i) => {
28208
29003
  const disabled = enumDisabled && enumDisabled.indexOf(value) !== -1;
28209
- return (jsxRuntimeExports.jsx("option", { value: String(i), disabled: disabled, children: label }, i));
29004
+ return (jsxRuntimeExports.jsx("option", { value: enumOptionValueEncoder(value, i, optionValueFormat), disabled: disabled, children: label }, i));
28210
29005
  })] }));
28211
29006
  }
28212
29007
 
@@ -28544,10 +29339,6 @@ let Form$1 = class Form extends reactExports.Component {
28544
29339
  // Only store a new registry when the props cause a different one to be created
28545
29340
  const newRegistry = this.getRegistry(props, rootSchema, schemaUtils);
28546
29341
  const registry = deepEquals(state.registry, newRegistry) ? state.registry : newRegistry;
28547
- // Pre-expand ui:definitions into the uiSchema structure (must happen after registry is created)
28548
- const expandedUiSchema = registry.uiSchemaDefinitions
28549
- ? expandUiSchemaDefinitions(rootSchema, uiSchema, registry)
28550
- : uiSchema;
28551
29342
  // Only compute a new `fieldPathId` when the `idPrefix` is different than the existing fieldPathId's ID_KEY
28552
29343
  const fieldPathId = state.fieldPathId && state.fieldPathId?.[ID_KEY] === registry.globalFormOptions.idPrefix
28553
29344
  ? state.fieldPathId
@@ -28555,7 +29346,7 @@ let Form$1 = class Form extends reactExports.Component {
28555
29346
  const nextState = {
28556
29347
  schemaUtils,
28557
29348
  schema: rootSchema,
28558
- uiSchema: expandedUiSchema,
29349
+ uiSchema,
28559
29350
  fieldPathId,
28560
29351
  formData,
28561
29352
  edit,
@@ -28729,9 +29520,13 @@ let Form$1 = class Form extends reactExports.Component {
28729
29520
  this._isProcessingUserChange = true;
28730
29521
  const { newValue, path, id } = this.pendingChanges[0];
28731
29522
  const { newErrorSchema } = this.pendingChanges[0];
28732
- const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
29523
+ const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange, removeEmptyOptionalObjects } = this.props;
28733
29524
  const { formData: oldFormData, schemaUtils, schema, fieldPathId, schemaValidationErrorSchema, errors } = this.state;
28734
- let { customErrors, errorSchema: originalErrorSchema } = this.state;
29525
+ let { customErrors } = this.state;
29526
+ // Use the un-merged AJV-only schema as the base for re-merging extraErrors. Mirrors the
29527
+ // pattern in getStateFromProps/getDerivedStateFromProps and avoids the duplication that
29528
+ // happened when state.errorSchema (already containing merged extraErrors) was passed in.
29529
+ let mergeBaseErrorSchema = schemaValidationErrorSchema;
28735
29530
  const rootPathId = fieldPathId.path[0] || '';
28736
29531
  const isRootPath = !path || path.length === 0 || (path.length === 1 && path[0] === rootPathId);
28737
29532
  let retrievedSchema = this.state.retrievedSchema;
@@ -28768,18 +29563,27 @@ let Form$1 = class Form extends reactExports.Component {
28768
29563
  formData: newFormData,
28769
29564
  };
28770
29565
  }
29566
+ if (removeEmptyOptionalObjects) {
29567
+ newFormData = removeOptionalEmptyObjects(schemaUtils.getValidator(), schema, schemaUtils.getRootSchema(), newFormData);
29568
+ state = {
29569
+ ...state,
29570
+ formData: newFormData,
29571
+ };
29572
+ }
28771
29573
  if (newErrorSchema) {
28772
29574
  // First check to see if there is an existing validation error on this path...
28773
29575
  // @ts-expect-error TS2590, because getting from the error schema is confusing TS
28774
29576
  const oldValidationError = !isRootPath ? get(schemaValidationErrorSchema, path) : schemaValidationErrorSchema;
28775
29577
  // If there is an old validation error for this path, assume we are updating it directly
28776
29578
  if (!isEmpty(oldValidationError)) {
28777
- // Update the originalErrorSchema "in place" or replace it if it is the root
29579
+ // Apply the user-supplied newErrorSchema onto a clone of the AJV-only base, so that
29580
+ // mergeErrors below sees the user's error at this path without mutating shared state.
28778
29581
  if (!isRootPath) {
28779
- set(originalErrorSchema, path, newErrorSchema);
29582
+ mergeBaseErrorSchema = cloneDeep(schemaValidationErrorSchema);
29583
+ set(mergeBaseErrorSchema, path, newErrorSchema);
28780
29584
  }
28781
29585
  else {
28782
- originalErrorSchema = newErrorSchema;
29586
+ mergeBaseErrorSchema = newErrorSchema;
28783
29587
  }
28784
29588
  }
28785
29589
  else {
@@ -28804,12 +29608,12 @@ let Form$1 = class Form extends reactExports.Component {
28804
29608
  }
28805
29609
  // If there are pending changes in the queue, skip live validation since it will happen with the last change
28806
29610
  if (mustValidate && this.pendingChanges.length === 1) {
28807
- const liveValidation = this.liveValidate(schema, schemaUtils, originalErrorSchema, newFormData, extraErrors, customErrors, retrievedSchema);
29611
+ const liveValidation = this.liveValidate(schema, schemaUtils, mergeBaseErrorSchema, newFormData, extraErrors, customErrors, retrievedSchema);
28808
29612
  state = { formData: newFormData, ...liveValidation, customErrors };
28809
29613
  }
28810
29614
  else if (!noValidate && newErrorSchema) {
28811
29615
  // Merging 'newErrorSchema' into 'errorSchema' to display the custom raised errors.
28812
- const mergedErrors = this.mergeErrors({ errorSchema: originalErrorSchema, errors }, extraErrors, customErrors);
29616
+ const mergedErrors = this.mergeErrors({ errorSchema: mergeBaseErrorSchema, errors }, extraErrors, customErrors);
28813
29617
  state = {
28814
29618
  formData: newFormData,
28815
29619
  ...mergedErrors,
@@ -28868,19 +29672,23 @@ let Form$1 = class Form extends reactExports.Component {
28868
29672
  * @param data - The data associated with the field that was blurred
28869
29673
  */
28870
29674
  onBlur = (id, data) => {
28871
- const { onBlur, omitExtraData, liveOmit, liveValidate } = this.props;
29675
+ const { onBlur, omitExtraData, liveOmit, liveValidate, removeEmptyOptionalObjects } = this.props;
28872
29676
  if (onBlur) {
28873
29677
  onBlur(id, data);
28874
29678
  }
28875
29679
  if ((omitExtraData === true && liveOmit === 'onBlur') || liveValidate === 'onBlur') {
28876
29680
  const { onChange, extraErrors } = this.props;
28877
- const { formData } = this.state;
29681
+ const { formData, schemaUtils, schema } = this.state;
28878
29682
  let newFormData = formData;
28879
29683
  let state = { formData: newFormData };
28880
29684
  if (omitExtraData === true && liveOmit === 'onBlur') {
28881
29685
  newFormData = this.omitExtraData(formData);
28882
29686
  state = { formData: newFormData };
28883
29687
  }
29688
+ if (removeEmptyOptionalObjects) {
29689
+ newFormData = removeOptionalEmptyObjects(schemaUtils.getValidator(), schema, schemaUtils.getRootSchema(), newFormData);
29690
+ state = { ...state, formData: newFormData };
29691
+ }
28884
29692
  if (liveValidate === 'onBlur') {
28885
29693
  const { schema, schemaUtils, errorSchema, customErrors, retrievedSchema } = this.state;
28886
29694
  const liveValidation = this.liveValidate(schema, schemaUtils, errorSchema, newFormData, extraErrors, customErrors, retrievedSchema);
@@ -28927,11 +29735,15 @@ let Form$1 = class Form extends reactExports.Component {
28927
29735
  return;
28928
29736
  }
28929
29737
  event.persist();
28930
- const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
29738
+ const { omitExtraData, extraErrors, noValidate, onSubmit, removeEmptyOptionalObjects } = this.props;
28931
29739
  let { formData: newFormData } = this.state;
28932
29740
  if (omitExtraData === true) {
28933
29741
  newFormData = this.omitExtraData(newFormData);
28934
29742
  }
29743
+ if (removeEmptyOptionalObjects) {
29744
+ const { schemaUtils, schema } = this.state;
29745
+ newFormData = removeOptionalEmptyObjects(schemaUtils.getValidator(), schema, schemaUtils.getRootSchema(), newFormData);
29746
+ }
28935
29747
  if (noValidate || this.validateFormWithFormData(newFormData)) {
28936
29748
  // There are no errors generated through schema validation.
28937
29749
  // Check for user provided errors and update state accordingly.
@@ -29024,8 +29836,9 @@ let Form$1 = class Form extends reactExports.Component {
29024
29836
  const elementId = path.join(idSeparator);
29025
29837
  let field = this.formElement.current.elements[elementId];
29026
29838
  if (!field) {
29027
- // if not an exact match, try finding an input starting with the element id (like radio buttons or checkboxes)
29028
- field = this.formElement.current.querySelector(`input[id^="${elementId}"`);
29839
+ // if not an exact match, try finding a focusable element starting with the element id (like radio buttons or checkboxes)
29840
+ // some themes (e.g. shadcn) use button elements instead of native inputs for radio groups
29841
+ field = this.formElement.current.querySelector(`input[id^="${elementId}"], button[id^="${elementId}"]`);
29029
29842
  }
29030
29843
  if (field && field.length) {
29031
29844
  // If we got a list with length > 0
@@ -29099,11 +29912,15 @@ let Form$1 = class Form extends reactExports.Component {
29099
29912
  * @returns - True if the form is valid, false otherwise.
29100
29913
  */
29101
29914
  validateForm() {
29102
- const { omitExtraData } = this.props;
29915
+ const { omitExtraData, removeEmptyOptionalObjects } = this.props;
29103
29916
  let { formData: newFormData } = this.state;
29104
29917
  if (omitExtraData === true) {
29105
29918
  newFormData = this.omitExtraData(newFormData);
29106
29919
  }
29920
+ if (removeEmptyOptionalObjects) {
29921
+ const { schemaUtils, schema } = this.state;
29922
+ newFormData = removeOptionalEmptyObjects(schemaUtils.getValidator(), schema, schemaUtils.getRootSchema(), newFormData);
29923
+ }
29107
29924
  return this.validateFormWithFormData(newFormData);
29108
29925
  }
29109
29926
  /** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
@@ -35782,13 +36599,50 @@ function createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverr
35782
36599
  return ajv;
35783
36600
  }
35784
36601
 
36602
+ /** Filters duplicate errors from `anyOf`/`oneOf` schema paths according to the `suppressDuplicateFiltering` flag.
36603
+ *
36604
+ * @param errorList - The list of `RJSFValidationError`s to filter
36605
+ * @param [suppressDuplicateFiltering='none'] - Controls which duplicate filtering is suppressed:
36606
+ * - `'none'` (default): filters duplicates for both `anyOf` and `oneOf`
36607
+ * - `'all'`: returns `errorList` unmodified
36608
+ * - `'anyOf'`: suppresses filtering for `anyOf` errors; `oneOf` duplicates are still filtered
36609
+ * - `'oneOf'`: suppresses filtering for `oneOf` errors; `anyOf` duplicates are still filtered
36610
+ */
36611
+ function filterDuplicateErrors(errorList, suppressDuplicateFiltering = 'none') {
36612
+ if (suppressDuplicateFiltering === 'all') {
36613
+ return errorList;
36614
+ }
36615
+ return errorList.reduce((acc, err) => {
36616
+ const { message, schemaPath } = err;
36617
+ // Compute the index only when filtering for that keyword is not suppressed.
36618
+ // 'all' is already handled above; within the reduce, only 'none', 'anyOf', and 'oneOf' are possible.
36619
+ const anyOfIndex = suppressDuplicateFiltering !== 'anyOf' ? schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.indexOf(`/${ANY_OF_KEY}/`) : undefined;
36620
+ const oneOfIndex = suppressDuplicateFiltering !== 'oneOf' ? schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.indexOf(`/${ONE_OF_KEY}/`) : undefined;
36621
+ let schemaPrefix;
36622
+ if (anyOfIndex && anyOfIndex >= 0) {
36623
+ schemaPrefix = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.substring(0, anyOfIndex);
36624
+ }
36625
+ else if (oneOfIndex && oneOfIndex >= 0) {
36626
+ schemaPrefix = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.substring(0, oneOfIndex);
36627
+ }
36628
+ // If there is a schemaPrefix, then search for a duplicate message with the same prefix, otherwise undefined
36629
+ const dup = schemaPrefix
36630
+ ? acc.find((e) => { var _a; return e.message === message && ((_a = e.schemaPath) === null || _a === void 0 ? void 0 : _a.startsWith(schemaPrefix)); })
36631
+ : undefined;
36632
+ if (!dup) {
36633
+ acc.push(err);
36634
+ }
36635
+ return acc;
36636
+ }, []);
36637
+ }
35785
36638
  /** Transforming the error output from ajv to format used by @rjsf/utils.
35786
36639
  * At some point, components should be updated to support ajv.
35787
36640
  *
35788
36641
  * @param errors - The list of AJV errors to convert to `RJSFValidationErrors`
35789
36642
  * @param [uiSchema] - An optional uiSchema that is passed to `transformErrors` and `customValidate`
36643
+ * @param [suppressDuplicateFiltering] - Controls which duplicate filtering is suppressed; see `filterDuplicateErrors`
35790
36644
  */
35791
- function transformRJSFValidationErrors(errors = [], uiSchema) {
36645
+ function transformRJSFValidationErrors(errors = [], uiSchema, suppressDuplicateFiltering) {
35792
36646
  const errorList = errors.map((e) => {
35793
36647
  var _a;
35794
36648
  const { instancePath, keyword, params, schemaPath, parentSchema, ...rest } = e;
@@ -35858,29 +36712,7 @@ function transformRJSFValidationErrors(errors = [], uiSchema) {
35858
36712
  title: uiTitle,
35859
36713
  };
35860
36714
  });
35861
- // Filter out duplicates around anyOf/oneOf messages
35862
- return errorList.reduce((acc, err) => {
35863
- const { message, schemaPath } = err;
35864
- const anyOfIndex = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.indexOf(`/${ANY_OF_KEY}/`);
35865
- const oneOfIndex = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.indexOf(`/${ONE_OF_KEY}/`);
35866
- let schemaPrefix;
35867
- // Look specifically for `/anyOr/` or `/oneOf/` within the schemaPath information
35868
- if (anyOfIndex && anyOfIndex >= 0) {
35869
- schemaPrefix = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.substring(0, anyOfIndex);
35870
- }
35871
- else if (oneOfIndex && oneOfIndex >= 0) {
35872
- schemaPrefix = schemaPath === null || schemaPath === void 0 ? void 0 : schemaPath.substring(0, oneOfIndex);
35873
- }
35874
- // If there is a schemaPrefix, then search for a duplicate message with the same prefix, otherwise undefined
35875
- const dup = schemaPrefix
35876
- ? acc.find((e) => { var _a; return e.message === message && ((_a = e.schemaPath) === null || _a === void 0 ? void 0 : _a.startsWith(schemaPrefix)); })
35877
- : undefined;
35878
- if (!dup) {
35879
- // Only push an error that is not a duplicate
35880
- acc.push(err);
35881
- }
35882
- return acc;
35883
- }, []);
36715
+ return filterDuplicateErrors(errorList, suppressDuplicateFiltering);
35884
36716
  }
35885
36717
  /** This function processes the `formData` with an optional user contributed `customValidate` function, which receives
35886
36718
  * the form data and a `errorHandler` function that will be used to add custom validation errors for each field. Also
@@ -35894,10 +36726,11 @@ function transformRJSFValidationErrors(errors = [], uiSchema) {
35894
36726
  * @param [customValidate] - An optional function that is used to perform custom validation
35895
36727
  * @param [transformErrors] - An optional function that is used to transform errors after AJV validation
35896
36728
  * @param [uiSchema] - An optional uiSchema that is passed to `transformErrors` and `customValidate`
36729
+ * @param [suppressDuplicateFiltering] - Controls which duplicate filtering is suppressed; see `filterDuplicateErrors`
35897
36730
  */
35898
- function processRawValidationErrors(validator, rawErrors, formData, schema, customValidate, transformErrors, uiSchema) {
36731
+ function processRawValidationErrors(validator, rawErrors, formData, schema, customValidate, transformErrors, uiSchema, suppressDuplicateFiltering) {
35899
36732
  const { validationError: invalidSchemaError } = rawErrors;
35900
- let errors = transformRJSFValidationErrors(rawErrors.errors, uiSchema);
36733
+ let errors = transformRJSFValidationErrors(rawErrors.errors, uiSchema, suppressDuplicateFiltering);
35901
36734
  if (invalidSchemaError) {
35902
36735
  errors = [...errors, { stack: invalidSchemaError.message }];
35903
36736
  }
@@ -35932,14 +36765,22 @@ class AJV8Validator {
35932
36765
  * @param [localizer] - If provided, is used to localize a list of Ajv `ErrorObject`s
35933
36766
  */
35934
36767
  constructor(options, localizer) {
35935
- const { additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions, AjvClass, extenderFn } = options;
36768
+ /** True once a `rootSchema` has been registered with Ajv in this lifecycle.
36769
+ *
36770
+ * @private
36771
+ */
36772
+ this.hasRegisteredRootSchema = false;
36773
+ const { additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions, AjvClass, extenderFn, suppressDuplicateFiltering, } = options;
35936
36774
  this.ajv = createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions, AjvClass, extenderFn);
35937
36775
  this.localizer = localizer;
36776
+ this.suppressDuplicateFiltering = suppressDuplicateFiltering;
35938
36777
  }
35939
36778
  /** Resets the internal AJV validator to clear schemas from it. Can be helpful for resetting the validator for tests.
35940
36779
  */
35941
36780
  reset() {
35942
36781
  this.ajv.removeSchema();
36782
+ this.lastSeenRootSchema = undefined;
36783
+ this.hasRegisteredRootSchema = false;
35943
36784
  }
35944
36785
  /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
35945
36786
  * by the playground. Returns the `errors` from the validation
@@ -36027,14 +36868,19 @@ class AJV8Validator {
36027
36868
  */
36028
36869
  validateFormData(formData, schema, customValidate, transformErrors, uiSchema) {
36029
36870
  const rawErrors = this.rawValidation(schema, formData);
36030
- return processRawValidationErrors(this, rawErrors, formData, schema, customValidate, transformErrors, uiSchema);
36871
+ return processRawValidationErrors(this, rawErrors, formData, schema, customValidate, transformErrors, uiSchema, this.suppressDuplicateFiltering);
36031
36872
  }
36032
36873
  /**
36033
36874
  * This function checks if a schema needs to be added and if the root schemas don't match it removes the old root schema from the ajv instance and adds the new one.
36875
+ * When called repeatedly with the same `rootSchema` reference the deep-equality check is skipped.
36876
+ *
36034
36877
  * @param rootSchema - The root schema used to provide $ref resolutions
36035
36878
  */
36036
36879
  handleSchemaUpdate(rootSchema) {
36037
36880
  var _a, _b;
36881
+ if (this.lastSeenRootSchema === rootSchema && this.hasRegisteredRootSchema) {
36882
+ return;
36883
+ }
36038
36884
  const rootSchemaId = (_a = rootSchema[ID_KEY]) !== null && _a !== void 0 ? _a : ROOT_SCHEMA_PREFIX;
36039
36885
  // add the rootSchema ROOT_SCHEMA_PREFIX as id.
36040
36886
  // if schema validator instance doesn't exist, add it.
@@ -36046,6 +36892,8 @@ class AJV8Validator {
36046
36892
  this.ajv.removeSchema(rootSchemaId);
36047
36893
  this.ajv.addSchema(rootSchema, rootSchemaId);
36048
36894
  }
36895
+ this.lastSeenRootSchema = rootSchema;
36896
+ this.hasRegisteredRootSchema = true;
36049
36897
  }
36050
36898
  /** Validates data against a schema, returning true if the data is valid, or
36051
36899
  * false otherwise. If the schema is invalid, then this function will return