@rjsf/core 6.6.2 → 6.7.1

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 (162) hide show
  1. package/LICENSE.md +201 -0
  2. package/dist/core.umd.js +312 -252
  3. package/dist/index.cjs +947 -878
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.esm.js +741 -667
  6. package/dist/index.esm.js.map +4 -4
  7. package/lib/components/Form.d.ts +2 -2
  8. package/lib/components/Form.d.ts.map +1 -1
  9. package/lib/components/Form.js +30 -15
  10. package/lib/components/RichDescription.d.ts +1 -1
  11. package/lib/components/RichDescription.d.ts.map +1 -1
  12. package/lib/components/RichHelp.d.ts +1 -1
  13. package/lib/components/RichHelp.d.ts.map +1 -1
  14. package/lib/components/SchemaExamples.d.ts +1 -1
  15. package/lib/components/SchemaExamples.d.ts.map +1 -1
  16. package/lib/components/fields/ArrayField.d.ts +1 -1
  17. package/lib/components/fields/ArrayField.d.ts.map +1 -1
  18. package/lib/components/fields/BooleanField.d.ts +1 -1
  19. package/lib/components/fields/BooleanField.d.ts.map +1 -1
  20. package/lib/components/fields/CyclicSchemaField.d.ts +8 -0
  21. package/lib/components/fields/CyclicSchemaField.d.ts.map +1 -0
  22. package/lib/components/fields/CyclicSchemaField.js +21 -0
  23. package/lib/components/fields/FallbackField.d.ts +1 -1
  24. package/lib/components/fields/FallbackField.d.ts.map +1 -1
  25. package/lib/components/fields/LayoutGridField.d.ts +1 -1
  26. package/lib/components/fields/LayoutGridField.d.ts.map +1 -1
  27. package/lib/components/fields/LayoutHeaderField.d.ts +1 -1
  28. package/lib/components/fields/LayoutHeaderField.d.ts.map +1 -1
  29. package/lib/components/fields/LayoutMultiSchemaField.d.ts +1 -1
  30. package/lib/components/fields/LayoutMultiSchemaField.d.ts.map +1 -1
  31. package/lib/components/fields/MultiSchemaField.d.ts +1 -46
  32. package/lib/components/fields/MultiSchemaField.d.ts.map +1 -1
  33. package/lib/components/fields/MultiSchemaField.js +111 -135
  34. package/lib/components/fields/NumberField.d.ts +1 -1
  35. package/lib/components/fields/NumberField.d.ts.map +1 -1
  36. package/lib/components/fields/NumberField.js +26 -15
  37. package/lib/components/fields/ObjectField.d.ts +1 -1
  38. package/lib/components/fields/ObjectField.d.ts.map +1 -1
  39. package/lib/components/fields/ObjectField.js +20 -5
  40. package/lib/components/fields/OptionalDataControlsField.d.ts +1 -1
  41. package/lib/components/fields/OptionalDataControlsField.d.ts.map +1 -1
  42. package/lib/components/fields/SchemaField.d.ts +13 -7
  43. package/lib/components/fields/SchemaField.d.ts.map +1 -1
  44. package/lib/components/fields/SchemaField.js +37 -24
  45. package/lib/components/fields/StringField.d.ts +1 -1
  46. package/lib/components/fields/StringField.d.ts.map +1 -1
  47. package/lib/components/fields/index.d.ts.map +1 -1
  48. package/lib/components/fields/index.js +2 -0
  49. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts +1 -1
  50. package/lib/components/templates/ArrayFieldDescriptionTemplate.d.ts.map +1 -1
  51. package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts +1 -1
  52. package/lib/components/templates/ArrayFieldItemButtonsTemplate.d.ts.map +1 -1
  53. package/lib/components/templates/ArrayFieldItemTemplate.d.ts +1 -1
  54. package/lib/components/templates/ArrayFieldItemTemplate.d.ts.map +1 -1
  55. package/lib/components/templates/ArrayFieldTemplate.d.ts +1 -1
  56. package/lib/components/templates/ArrayFieldTemplate.d.ts.map +1 -1
  57. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts +1 -1
  58. package/lib/components/templates/ArrayFieldTitleTemplate.d.ts.map +1 -1
  59. package/lib/components/templates/BaseInputTemplate.d.ts +1 -1
  60. package/lib/components/templates/BaseInputTemplate.d.ts.map +1 -1
  61. package/lib/components/templates/BaseInputTemplate.js +2 -2
  62. package/lib/components/templates/ButtonTemplates/AddButton.d.ts +1 -1
  63. package/lib/components/templates/ButtonTemplates/AddButton.d.ts.map +1 -1
  64. package/lib/components/templates/ButtonTemplates/IconButton.d.ts +6 -6
  65. package/lib/components/templates/ButtonTemplates/IconButton.d.ts.map +1 -1
  66. package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts +1 -1
  67. package/lib/components/templates/ButtonTemplates/SubmitButton.d.ts.map +1 -1
  68. package/lib/components/templates/CyclicSchemaExpandTemplate.d.ts +7 -0
  69. package/lib/components/templates/CyclicSchemaExpandTemplate.d.ts.map +1 -0
  70. package/lib/components/templates/CyclicSchemaExpandTemplate.js +12 -0
  71. package/lib/components/templates/DescriptionField.d.ts +1 -1
  72. package/lib/components/templates/DescriptionField.d.ts.map +1 -1
  73. package/lib/components/templates/ErrorList.d.ts +1 -1
  74. package/lib/components/templates/ErrorList.d.ts.map +1 -1
  75. package/lib/components/templates/FallbackFieldTemplate.d.ts +1 -1
  76. package/lib/components/templates/FallbackFieldTemplate.d.ts.map +1 -1
  77. package/lib/components/templates/FieldErrorTemplate.d.ts +1 -1
  78. package/lib/components/templates/FieldErrorTemplate.d.ts.map +1 -1
  79. package/lib/components/templates/FieldHelpTemplate.d.ts +1 -1
  80. package/lib/components/templates/FieldHelpTemplate.d.ts.map +1 -1
  81. package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts +1 -1
  82. package/lib/components/templates/FieldTemplate/FieldTemplate.d.ts.map +1 -1
  83. package/lib/components/templates/FieldTemplate/Label.d.ts +1 -1
  84. package/lib/components/templates/FieldTemplate/Label.d.ts.map +1 -1
  85. package/lib/components/templates/GridTemplate.d.ts +1 -1
  86. package/lib/components/templates/GridTemplate.d.ts.map +1 -1
  87. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts +1 -1
  88. package/lib/components/templates/MultiSchemaFieldTemplate.d.ts.map +1 -1
  89. package/lib/components/templates/ObjectFieldTemplate.d.ts +1 -1
  90. package/lib/components/templates/ObjectFieldTemplate.d.ts.map +1 -1
  91. package/lib/components/templates/OptionalDataControlsTemplate.d.ts +1 -1
  92. package/lib/components/templates/OptionalDataControlsTemplate.d.ts.map +1 -1
  93. package/lib/components/templates/TitleField.d.ts +1 -1
  94. package/lib/components/templates/TitleField.d.ts.map +1 -1
  95. package/lib/components/templates/UnsupportedField.d.ts +1 -1
  96. package/lib/components/templates/UnsupportedField.d.ts.map +1 -1
  97. package/lib/components/templates/UnsupportedField.js +1 -1
  98. package/lib/components/templates/WrapIfAdditionalTemplate.d.ts +1 -1
  99. package/lib/components/templates/WrapIfAdditionalTemplate.d.ts.map +1 -1
  100. package/lib/components/templates/index.d.ts.map +1 -1
  101. package/lib/components/templates/index.js +2 -0
  102. package/lib/components/widgets/AltDateTimeWidget.d.ts +1 -1
  103. package/lib/components/widgets/AltDateTimeWidget.d.ts.map +1 -1
  104. package/lib/components/widgets/AltDateWidget.d.ts +1 -1
  105. package/lib/components/widgets/AltDateWidget.d.ts.map +1 -1
  106. package/lib/components/widgets/CheckboxWidget.d.ts +1 -1
  107. package/lib/components/widgets/CheckboxWidget.d.ts.map +1 -1
  108. package/lib/components/widgets/CheckboxesWidget.d.ts +1 -1
  109. package/lib/components/widgets/CheckboxesWidget.d.ts.map +1 -1
  110. package/lib/components/widgets/CheckboxesWidget.js +2 -2
  111. package/lib/components/widgets/ColorWidget.d.ts +1 -1
  112. package/lib/components/widgets/ColorWidget.d.ts.map +1 -1
  113. package/lib/components/widgets/DateTimeWidget.d.ts +1 -1
  114. package/lib/components/widgets/DateTimeWidget.d.ts.map +1 -1
  115. package/lib/components/widgets/DateWidget.d.ts +1 -1
  116. package/lib/components/widgets/DateWidget.d.ts.map +1 -1
  117. package/lib/components/widgets/EmailWidget.d.ts +1 -1
  118. package/lib/components/widgets/EmailWidget.d.ts.map +1 -1
  119. package/lib/components/widgets/FileWidget.d.ts +1 -1
  120. package/lib/components/widgets/FileWidget.d.ts.map +1 -1
  121. package/lib/components/widgets/HiddenWidget.d.ts +1 -1
  122. package/lib/components/widgets/HiddenWidget.d.ts.map +1 -1
  123. package/lib/components/widgets/PasswordWidget.d.ts +1 -1
  124. package/lib/components/widgets/PasswordWidget.d.ts.map +1 -1
  125. package/lib/components/widgets/RadioWidget.d.ts +1 -1
  126. package/lib/components/widgets/RadioWidget.d.ts.map +1 -1
  127. package/lib/components/widgets/RadioWidget.js +2 -2
  128. package/lib/components/widgets/RangeWidget.d.ts +1 -1
  129. package/lib/components/widgets/RangeWidget.d.ts.map +1 -1
  130. package/lib/components/widgets/RatingWidget.d.ts +1 -1
  131. package/lib/components/widgets/RatingWidget.d.ts.map +1 -1
  132. package/lib/components/widgets/SelectWidget.d.ts +1 -1
  133. package/lib/components/widgets/SelectWidget.d.ts.map +1 -1
  134. package/lib/components/widgets/SelectWidget.js +9 -8
  135. package/lib/components/widgets/TextWidget.d.ts +1 -1
  136. package/lib/components/widgets/TextWidget.d.ts.map +1 -1
  137. package/lib/components/widgets/TextareaWidget.d.ts +1 -1
  138. package/lib/components/widgets/TextareaWidget.d.ts.map +1 -1
  139. package/lib/components/widgets/TextareaWidget.js +3 -3
  140. package/lib/components/widgets/TimeWidget.d.ts +1 -1
  141. package/lib/components/widgets/TimeWidget.d.ts.map +1 -1
  142. package/lib/components/widgets/URLWidget.d.ts +1 -1
  143. package/lib/components/widgets/URLWidget.d.ts.map +1 -1
  144. package/lib/components/widgets/UpDownWidget.d.ts +1 -1
  145. package/lib/components/widgets/UpDownWidget.d.ts.map +1 -1
  146. package/lib/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +28 -27
  148. package/src/components/Form.tsx +34 -15
  149. package/src/components/fields/CyclicSchemaField.tsx +40 -0
  150. package/src/components/fields/MultiSchemaField.tsx +201 -230
  151. package/src/components/fields/NumberField.tsx +30 -16
  152. package/src/components/fields/ObjectField.tsx +29 -5
  153. package/src/components/fields/SchemaField.tsx +46 -34
  154. package/src/components/fields/index.ts +2 -0
  155. package/src/components/templates/BaseInputTemplate.tsx +2 -5
  156. package/src/components/templates/CyclicSchemaExpandTemplate.tsx +31 -0
  157. package/src/components/templates/UnsupportedField.tsx +1 -1
  158. package/src/components/templates/index.ts +2 -0
  159. package/src/components/widgets/CheckboxesWidget.tsx +2 -2
  160. package/src/components/widgets/RadioWidget.tsx +2 -2
  161. package/src/components/widgets/SelectWidget.tsx +45 -30
  162. package/src/components/widgets/TextareaWidget.tsx +3 -3
package/dist/core.umd.js CHANGED
@@ -898,6 +898,33 @@
898
898
  );
899
899
  }
900
900
  var BooleanField_default = BooleanField;
901
+ function CyclicSchemaField(props) {
902
+ const [expanded, setExpanded] = react.useState(false);
903
+ const { name, registry, schema, uiSchema, fieldPathId } = props;
904
+ const { globalUiOptions } = registry;
905
+ const uiOptions = utils.getUiOptions(uiSchema, globalUiOptions);
906
+ const CyclicSchemaExpandTemplate2 = utils.getTemplate(
907
+ "CyclicSchemaExpandTemplate",
908
+ registry,
909
+ uiOptions
910
+ );
911
+ if (!expanded) {
912
+ return /* @__PURE__ */ jsxRuntime.jsx(
913
+ CyclicSchemaExpandTemplate2,
914
+ {
915
+ registry,
916
+ schema,
917
+ uiSchema,
918
+ name,
919
+ fieldPathId,
920
+ onExpand: () => setExpanded(true)
921
+ }
922
+ );
923
+ }
924
+ const { fields: fields2 } = registry;
925
+ const { SchemaField: SchemaField2 } = fields2;
926
+ return /* @__PURE__ */ jsxRuntime.jsx(SchemaField2, { ...props, schema: { ...schema, [utils.RJSF_REF_CYCLE_KEY]: false } });
927
+ }
901
928
  function getFallbackTypeSelectionSchema(title) {
902
929
  return {
903
930
  type: "string",
@@ -1523,217 +1550,179 @@
1523
1550
  }
1524
1551
  );
1525
1552
  }
1526
- var AnyOfField = class extends react.Component {
1527
- /** Flag to skip the formData-change-driven option recalculation when the user just selected an option.
1528
- * Set to true in the setState callback of onOptionChange (after onChange is called), consumed and reset in
1529
- * componentDidUpdate. This prevents the matching-option recalculation from overriding a user's explicit choice
1530
- * when getDefaultFormState populates undefined properties that make deepEquals see a false formData change.
1531
- */
1532
- skipNextOptionRecalculation = false;
1533
- /** Constructs an `AnyOfField` with the given `props` to initialize the initially selected option in state
1534
- *
1535
- * @param props - The `FieldProps` for this template
1536
- */
1537
- constructor(props) {
1538
- super(props);
1539
- const {
1540
- formData,
1541
- options,
1542
- registry: { schemaUtils }
1543
- } = this.props;
1544
- const retrievedOptions = options.map((opt) => schemaUtils.retrieveSchema(opt, formData));
1545
- this.state = {
1546
- retrievedOptions,
1547
- selectedOption: this.getMatchingOption(0, formData, retrievedOptions)
1548
- };
1549
- }
1550
- /** React lifecycle method that is called when the props and/or state for this component is updated. It recomputes the
1551
- * currently selected option based on the overall `formData`
1552
- *
1553
- * @param prevProps - The previous `FieldProps` for this template
1554
- * @param prevState - The previous `AnyOfFieldState` for this template
1555
- */
1556
- componentDidUpdate(prevProps, prevState) {
1557
- const { formData, options, fieldPathId } = this.props;
1558
- const { selectedOption } = this.state;
1559
- let newState = this.state;
1560
- if (!utils.deepEquals(prevProps.options, options)) {
1561
- const {
1562
- registry: { schemaUtils }
1563
- } = this.props;
1564
- const retrievedOptions = options.map((opt) => schemaUtils.retrieveSchema(opt, formData));
1565
- newState = { selectedOption, retrievedOptions };
1553
+ function AnyOfField(props) {
1554
+ const {
1555
+ name,
1556
+ disabled = false,
1557
+ errorSchema = {},
1558
+ formData,
1559
+ fieldPathId,
1560
+ onBlur,
1561
+ onChange,
1562
+ onFocus,
1563
+ options,
1564
+ readonly,
1565
+ registry,
1566
+ required = false,
1567
+ schema,
1568
+ uiSchema
1569
+ } = props;
1570
+ const { schemaUtils } = registry;
1571
+ const formDataHash = utils.hashObject(formData ?? null);
1572
+ const retrievedOptions = react.useMemo(
1573
+ () => options.map((opt) => schemaUtils.retrieveSchema(opt, formData)),
1574
+ // oxlint-disable-next-line react-hooks/exhaustive-deps -- formDataHash is the value-stable proxy for formData
1575
+ [options, schemaUtils, formDataHash]
1576
+ );
1577
+ const [selectedOption, setSelectedOption] = react.useState(() => {
1578
+ const discriminator = utils.getDiscriminatorFieldFromSchema(schema);
1579
+ return schemaUtils.getClosestMatchingOption(formData, retrievedOptions, 0, discriminator);
1580
+ });
1581
+ const skipNextOptionRecalculation = react.useRef(false);
1582
+ const prevFormDataRef = react.useRef(formData);
1583
+ const prevFieldIdRef = react.useRef(fieldPathId.$id);
1584
+ react.useEffect(() => {
1585
+ const prevFormData = prevFormDataRef.current;
1586
+ const prevFieldId = prevFieldIdRef.current;
1587
+ prevFormDataRef.current = formData;
1588
+ prevFieldIdRef.current = fieldPathId.$id;
1589
+ if (!utils.deepEquals(formData, prevFormData) && fieldPathId.$id === prevFieldId) {
1590
+ if (skipNextOptionRecalculation.current) {
1591
+ skipNextOptionRecalculation.current = false;
1592
+ return;
1593
+ }
1594
+ const discriminator = utils.getDiscriminatorFieldFromSchema(schema);
1595
+ const matchingOption = schemaUtils.getClosestMatchingOption(
1596
+ formData,
1597
+ retrievedOptions,
1598
+ selectedOption,
1599
+ discriminator
1600
+ );
1601
+ if (matchingOption !== selectedOption) {
1602
+ setSelectedOption(matchingOption);
1603
+ }
1566
1604
  }
1567
- if (!utils.deepEquals(formData, prevProps.formData) && fieldPathId.$id === prevProps.fieldPathId.$id) {
1568
- if (this.skipNextOptionRecalculation) {
1569
- this.skipNextOptionRecalculation = false;
1570
- } else {
1571
- const { retrievedOptions } = newState;
1572
- const matchingOption = this.getMatchingOption(selectedOption, formData, retrievedOptions);
1573
- if (prevState && matchingOption !== selectedOption) {
1574
- newState = { selectedOption: matchingOption, retrievedOptions };
1575
- }
1605
+ });
1606
+ const fieldId = `${fieldPathId.$id}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`;
1607
+ const onOptionChange = react.useCallback(
1608
+ (option2) => {
1609
+ if (disabled || readonly) {
1610
+ return;
1611
+ }
1612
+ const intOption = option2 !== void 0 ? parseInt(option2, 10) : -1;
1613
+ if (intOption === selectedOption) {
1614
+ return;
1576
1615
  }
1616
+ const newOption = intOption >= 0 ? retrievedOptions[intOption] : void 0;
1617
+ const oldOption = selectedOption >= 0 ? retrievedOptions[selectedOption] : void 0;
1618
+ let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData);
1619
+ if (newOption) {
1620
+ newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
1621
+ }
1622
+ setSelectedOption(intOption);
1623
+ skipNextOptionRecalculation.current = true;
1624
+ onChange(newFormData, fieldPathId.path, void 0, fieldId);
1625
+ },
1626
+ // setSelectedOption is stable (guaranteed by useState); skipNextOptionRecalculation is a ref
1627
+ [selectedOption, retrievedOptions, disabled, readonly, schemaUtils, formData, fieldPathId, onChange, fieldId]
1628
+ );
1629
+ const { widgets: widgets2, fields: fields2, translateString, globalUiOptions } = registry;
1630
+ const { SchemaField: SchemaFieldComponent } = fields2;
1631
+ const MultiSchemaFieldTemplate2 = utils.getTemplate(
1632
+ "MultiSchemaFieldTemplate",
1633
+ registry,
1634
+ globalUiOptions
1635
+ );
1636
+ const isOptionalRender = utils.shouldRenderOptionalField(registry, schema, required, uiSchema);
1637
+ const hasFormData = utils.isFormDataAvailable(formData);
1638
+ const {
1639
+ widget = "select",
1640
+ placeholder,
1641
+ autofocus,
1642
+ autocomplete,
1643
+ title = schema.title,
1644
+ ...uiOptions
1645
+ } = utils.getUiOptions(uiSchema, globalUiOptions);
1646
+ const Widget = utils.getWidget({ type: "number" }, widget, widgets2);
1647
+ const rawErrors = get(errorSchema, utils.ERRORS_KEY, []);
1648
+ const fieldErrorSchema = omit3(errorSchema, [utils.ERRORS_KEY]);
1649
+ const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
1650
+ const option = selectedOption >= 0 ? retrievedOptions[selectedOption] || null : null;
1651
+ let optionSchema;
1652
+ if (option) {
1653
+ const { required: schemaRequired, type: schemaType } = schema;
1654
+ const parentProps = {};
1655
+ if (schemaRequired) {
1656
+ parentProps.required = schemaRequired;
1577
1657
  }
1578
- if (newState !== this.state) {
1579
- this.setState(newState);
1658
+ if (schemaType !== void 0 && !("type" in option)) {
1659
+ parentProps.type = schemaType;
1580
1660
  }
1661
+ optionSchema = Object.keys(parentProps).length > 0 ? utils.mergeSchemas(parentProps, option) : option;
1581
1662
  }
1582
- /** Determines the best matching option for the given `formData` and `options`.
1583
- *
1584
- * @param formData - The new formData
1585
- * @param options - The list of options to choose from
1586
- * @return - The index of the `option` that best matches the `formData`
1587
- */
1588
- getMatchingOption(selectedOption, formData, options) {
1589
- const {
1590
- schema,
1591
- registry: { schemaUtils }
1592
- } = this.props;
1593
- const discriminator = utils.getDiscriminatorFieldFromSchema(schema);
1594
- const option = schemaUtils.getClosestMatchingOption(formData, options, selectedOption, discriminator);
1595
- return option;
1596
- }
1597
- /** Callback handler to remember what the currently selected option is. In addition to that the `formData` is updated
1598
- * to remove properties that are not part of the newly selected option schema, and then the updated data is passed to
1599
- * the `onChange` handler.
1600
- *
1601
- * @param option - The new option value being selected
1602
- */
1603
- onOptionChange = (option) => {
1604
- const { selectedOption, retrievedOptions } = this.state;
1605
- const { disabled = false, formData, onChange, readonly = false, registry, fieldPathId } = this.props;
1606
- if (disabled || readonly) {
1607
- return;
1608
- }
1609
- const { schemaUtils } = registry;
1610
- const intOption = option !== void 0 ? parseInt(option, 10) : -1;
1611
- if (intOption === selectedOption) {
1612
- return;
1663
+ let optionsUiSchema = [];
1664
+ if (utils.ONE_OF_KEY in schema && uiSchema && utils.ONE_OF_KEY in uiSchema) {
1665
+ if (Array.isArray(uiSchema[utils.ONE_OF_KEY])) {
1666
+ optionsUiSchema = uiSchema[utils.ONE_OF_KEY];
1667
+ } else {
1668
+ console.warn(`uiSchema.oneOf is not an array for "${title || name}"`);
1613
1669
  }
1614
- const newOption = intOption >= 0 ? retrievedOptions[intOption] : void 0;
1615
- const oldOption = selectedOption >= 0 ? retrievedOptions[selectedOption] : void 0;
1616
- let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData);
1617
- if (newOption) {
1618
- newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, "excludeObjectChildren");
1670
+ } else if (utils.ANY_OF_KEY in schema && uiSchema && utils.ANY_OF_KEY in uiSchema) {
1671
+ if (Array.isArray(uiSchema[utils.ANY_OF_KEY])) {
1672
+ optionsUiSchema = uiSchema[utils.ANY_OF_KEY];
1673
+ } else {
1674
+ console.warn(`uiSchema.anyOf is not an array for "${title || name}"`);
1619
1675
  }
1620
- this.setState({ selectedOption: intOption }, () => {
1621
- this.skipNextOptionRecalculation = true;
1622
- onChange(newFormData, fieldPathId.path, void 0, this.getFieldId());
1623
- });
1624
- };
1625
- getFieldId() {
1626
- const { fieldPathId, schema } = this.props;
1627
- return `${fieldPathId.$id}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`;
1628
1676
  }
1629
- /** Renders the `AnyOfField` selector along with a `SchemaField` for the value of the `formData`
1630
- */
1631
- render() {
1632
- const {
1633
- name,
1634
- disabled = false,
1635
- errorSchema = {},
1636
- formData,
1677
+ let optionUiSchema = uiSchema;
1678
+ if (selectedOption >= 0 && optionsUiSchema.length > selectedOption) {
1679
+ optionUiSchema = optionsUiSchema[selectedOption];
1680
+ }
1681
+ const translateEnum = title ? utils.TranslatableString.TitleOptionPrefix : utils.TranslatableString.OptionPrefix;
1682
+ const translateParams = title ? [title] : [];
1683
+ const enumOptions = retrievedOptions.map((opt, index) => {
1684
+ const { title: uiTitle = opt.title } = utils.getUiOptions(optionsUiSchema[index]);
1685
+ return {
1686
+ label: uiTitle || translateString(translateEnum, translateParams.concat(String(index + 1))),
1687
+ value: index
1688
+ };
1689
+ });
1690
+ const selector = !isOptionalRender || hasFormData ? /* @__PURE__ */ jsxRuntime.jsx(
1691
+ Widget,
1692
+ {
1693
+ id: fieldId,
1694
+ name: `${name}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`,
1695
+ schema: { type: "number", default: 0 },
1696
+ onChange: onOptionChange,
1637
1697
  onBlur,
1638
1698
  onFocus,
1639
- readonly,
1640
- required = false,
1641
- registry,
1642
- schema,
1643
- uiSchema
1644
- } = this.props;
1645
- const { widgets: widgets2, fields: fields2, translateString, globalUiOptions, schemaUtils } = registry;
1646
- const { SchemaField: SchemaFieldComponent } = fields2;
1647
- const MultiSchemaFieldTemplate2 = utils.getTemplate(
1648
- "MultiSchemaFieldTemplate",
1699
+ disabled: disabled || isEmpty(enumOptions),
1700
+ multiple: false,
1701
+ rawErrors,
1702
+ errorSchema: fieldErrorSchema,
1703
+ value: selectedOption >= 0 ? selectedOption : void 0,
1704
+ options: { enumOptions, ...uiOptions },
1649
1705
  registry,
1650
- globalUiOptions
1651
- );
1652
- const isOptionalRender = utils.shouldRenderOptionalField(registry, schema, required, uiSchema);
1653
- const hasFormData = utils.isFormDataAvailable(formData);
1654
- const { selectedOption, retrievedOptions } = this.state;
1655
- const {
1656
- widget = "select",
1657
1706
  placeholder,
1658
- autofocus,
1659
1707
  autocomplete,
1660
- title = schema.title,
1661
- ...uiOptions
1662
- } = utils.getUiOptions(uiSchema, globalUiOptions);
1663
- const Widget = utils.getWidget({ type: "number" }, widget, widgets2);
1664
- const rawErrors = get(errorSchema, utils.ERRORS_KEY, []);
1665
- const fieldErrorSchema = omit3(errorSchema, [utils.ERRORS_KEY]);
1666
- const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
1667
- const option = selectedOption >= 0 ? retrievedOptions[selectedOption] || null : null;
1668
- let optionSchema;
1669
- if (option) {
1670
- const { required: schemaRequired } = schema;
1671
- optionSchema = schemaRequired ? utils.mergeSchemas({ required: schemaRequired }, option) : option;
1672
- }
1673
- let optionsUiSchema = [];
1674
- if (utils.ONE_OF_KEY in schema && uiSchema && utils.ONE_OF_KEY in uiSchema) {
1675
- if (Array.isArray(uiSchema[utils.ONE_OF_KEY])) {
1676
- optionsUiSchema = uiSchema[utils.ONE_OF_KEY];
1677
- } else {
1678
- console.warn(`uiSchema.oneOf is not an array for "${title || name}"`);
1679
- }
1680
- } else if (utils.ANY_OF_KEY in schema && uiSchema && utils.ANY_OF_KEY in uiSchema) {
1681
- if (Array.isArray(uiSchema[utils.ANY_OF_KEY])) {
1682
- optionsUiSchema = uiSchema[utils.ANY_OF_KEY];
1683
- } else {
1684
- console.warn(`uiSchema.anyOf is not an array for "${title || name}"`);
1685
- }
1708
+ autofocus,
1709
+ label: title ?? name,
1710
+ hideLabel: !displayLabel,
1711
+ readonly
1686
1712
  }
1687
- let optionUiSchema = uiSchema;
1688
- if (selectedOption >= 0 && optionsUiSchema.length > selectedOption) {
1689
- optionUiSchema = optionsUiSchema[selectedOption];
1713
+ ) : void 0;
1714
+ const optionsSchemaField = optionSchema && optionSchema.type !== "null" && /* @__PURE__ */ jsxRuntime.jsx(SchemaFieldComponent, { ...props, schema: optionSchema, uiSchema: optionUiSchema }) || null;
1715
+ return /* @__PURE__ */ jsxRuntime.jsx(
1716
+ MultiSchemaFieldTemplate2,
1717
+ {
1718
+ schema,
1719
+ registry,
1720
+ uiSchema,
1721
+ selector,
1722
+ optionSchemaField: optionsSchemaField
1690
1723
  }
1691
- const translateEnum = title ? utils.TranslatableString.TitleOptionPrefix : utils.TranslatableString.OptionPrefix;
1692
- const translateParams = title ? [title] : [];
1693
- const enumOptions = retrievedOptions.map((opt, index) => {
1694
- const { title: uiTitle = opt.title } = utils.getUiOptions(optionsUiSchema[index]);
1695
- return {
1696
- label: uiTitle || translateString(translateEnum, translateParams.concat(String(index + 1))),
1697
- value: index
1698
- };
1699
- });
1700
- const selector = !isOptionalRender || hasFormData ? /* @__PURE__ */ jsxRuntime.jsx(
1701
- Widget,
1702
- {
1703
- id: this.getFieldId(),
1704
- name: `${name}${schema.oneOf ? "__oneof_select" : "__anyof_select"}`,
1705
- schema: { type: "number", default: 0 },
1706
- onChange: this.onOptionChange,
1707
- onBlur,
1708
- onFocus,
1709
- disabled: disabled || isEmpty(enumOptions),
1710
- multiple: false,
1711
- rawErrors,
1712
- errorSchema: fieldErrorSchema,
1713
- value: selectedOption >= 0 ? selectedOption : void 0,
1714
- options: { enumOptions, ...uiOptions },
1715
- registry,
1716
- placeholder,
1717
- autocomplete,
1718
- autofocus,
1719
- label: title ?? name,
1720
- hideLabel: !displayLabel,
1721
- readonly
1722
- }
1723
- ) : void 0;
1724
- const optionsSchemaField = optionSchema && optionSchema.type !== "null" && /* @__PURE__ */ jsxRuntime.jsx(SchemaFieldComponent, { ...this.props, schema: optionSchema, uiSchema: optionUiSchema }) || null;
1725
- return /* @__PURE__ */ jsxRuntime.jsx(
1726
- MultiSchemaFieldTemplate2,
1727
- {
1728
- schema,
1729
- registry,
1730
- uiSchema,
1731
- selector,
1732
- optionSchemaField: optionsSchemaField
1733
- }
1734
- );
1735
- }
1736
- };
1724
+ );
1725
+ }
1737
1726
  var MultiSchemaField_default = AnyOfField;
1738
1727
  function NullField(props) {
1739
1728
  const { formData, onChange, fieldPathId } = props;
@@ -1751,23 +1740,37 @@
1751
1740
  const { registry, onChange, formData, value: initialValue } = props;
1752
1741
  const [lastValue, setLastValue] = react.useState(initialValue);
1753
1742
  const { StringField: StringField2 } = registry.fields;
1743
+ const separator = utils.getDecimalSeparator();
1744
+ const escapedSeparator = separator === "." ? "\\." : separator;
1754
1745
  let value = formData;
1755
1746
  const handleChange = react.useCallback(
1756
1747
  (newValue, path, errorSchema, id) => {
1757
1748
  setLastValue(newValue);
1758
- const normalizedValue = `${newValue}`.startsWith(".") ? `0${newValue}` : newValue;
1759
- const processed = typeof normalizedValue === "string" && normalizedValue.match(trailingCharMatcherWithPrefix) ? utils.asNumber(normalizedValue.replace(trailingCharMatcher, "")) : utils.asNumber(normalizedValue);
1749
+ const standardValue = typeof newValue === "string" ? newValue.replace(separator, ".") : newValue;
1750
+ const normalizedValue = `${standardValue}`.startsWith(".") ? `0${standardValue}` : standardValue;
1751
+ const processed = typeof normalizedValue === "string" && trailingCharMatcherWithPrefix.exec(normalizedValue) ? utils.asNumber(normalizedValue.replace(trailingCharMatcher, "")) : utils.asNumber(normalizedValue);
1760
1752
  onChange(processed, path, errorSchema, id);
1761
1753
  },
1762
- [onChange]
1754
+ [onChange, separator]
1763
1755
  );
1764
1756
  if (typeof lastValue === "string" && typeof value === "number") {
1765
- const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
1757
+ const re = new RegExp(`^(${String(value).replace(".", escapedSeparator)})?${escapedSeparator}?0*$`);
1766
1758
  if (lastValue.match(re)) {
1767
1759
  value = lastValue;
1768
1760
  }
1769
1761
  }
1770
- return /* @__PURE__ */ jsxRuntime.jsx(StringField2, { ...props, formData: value, onChange: handleChange });
1762
+ let displayValue = value;
1763
+ if (typeof value === "number" && separator !== ".") {
1764
+ const { schema, uiSchema } = props;
1765
+ const { schemaUtils } = registry;
1766
+ const enumOptions = schemaUtils.isSelect(schema) ? utils.optionsList(schema, uiSchema) : void 0;
1767
+ const defaultWidget = enumOptions ? "select" : "text";
1768
+ const { widget = defaultWidget } = utils.getUiOptions(uiSchema);
1769
+ if (widget !== "radio" && widget !== "select" && widget !== "hidden") {
1770
+ displayValue = String(value).replace(".", separator);
1771
+ }
1772
+ }
1773
+ return /* @__PURE__ */ jsxRuntime.jsx(StringField2, { ...props, formData: displayValue, onChange: handleChange });
1771
1774
  }
1772
1775
  var NumberField_default = NumberField;
1773
1776
 
@@ -1794,6 +1797,12 @@
1794
1797
  return translateString(utils.TranslatableString.NewStringDefault);
1795
1798
  }
1796
1799
  }
1800
+ function isAdditionalPropertySchema(schema) {
1801
+ return Boolean(schema?.[utils.ADDITIONAL_PROPERTY_FLAG]);
1802
+ }
1803
+ function getAdditionalPropertyOrder(schemaProperties) {
1804
+ return Object.keys(schemaProperties).filter((property) => isAdditionalPropertySchema(schemaProperties[property]));
1805
+ }
1797
1806
  function ObjectFieldPropertyFn(props) {
1798
1807
  const {
1799
1808
  fieldPathId,
@@ -1903,9 +1912,16 @@
1903
1912
  [schemaUtils, rawSchema, formData]
1904
1913
  );
1905
1914
  const uiOptions = react.useMemo(() => utils.getUiOptions(uiSchema, globalUiOptions), [uiSchema, globalUiOptions]);
1906
- const { properties: schemaProperties = {} } = schema;
1915
+ const schemaProperties = react.useMemo(() => schema.properties ?? {}, [schema.properties]);
1907
1916
  const childFieldPathId = props.childFieldPathId ?? fieldPathId;
1908
1917
  const lastRenamedProperty = react.useRef({ previousKey: "", currentKey: void 0 });
1918
+ const [additionalPropertyOrder, setAdditionalPropertyOrder] = react.useState(
1919
+ () => getAdditionalPropertyOrder(schemaProperties)
1920
+ );
1921
+ const definedPropertyOrder = react.useMemo(() => {
1922
+ const additionalPropertySet = new Set(getAdditionalPropertyOrder(schemaProperties));
1923
+ return Object.keys(schemaProperties).filter((property) => !additionalPropertySet.has(property));
1924
+ }, [schemaProperties]);
1909
1925
  const templateTitle = uiOptions.title ?? schema.title ?? title ?? name;
1910
1926
  const description = uiOptions.description ?? schema.description;
1911
1927
  const renderOptionalField = utils.shouldRenderOptionalField(registry, schema, required, uiSchema);
@@ -1945,7 +1961,7 @@
1945
1961
  apSchema = schemaUtils.retrieveSchema({ [utils.REF_KEY]: apSchema[utils.REF_KEY] }, formData);
1946
1962
  type = apSchema.type;
1947
1963
  constValue = apSchema.const;
1948
- defaultValue = apSchema.default;
1964
+ defaultValue = schemaUtils.getDefaultFormState(apSchema, defaultValue);
1949
1965
  }
1950
1966
  if (!type && (utils.ANY_OF_KEY in apSchema || utils.ONE_OF_KEY in apSchema)) {
1951
1967
  type = "object";
@@ -1958,6 +1974,7 @@
1958
1974
  lastRenamedProperty.current.currentKey = newKey;
1959
1975
  lastRenamedProperty.current.previousKey = getAvailableKey(newKey, newFormData);
1960
1976
  }
1977
+ setAdditionalPropertyOrder((order) => [...order, newKey]);
1961
1978
  onChange(newFormData, childFieldPathId.path);
1962
1979
  }, [formData, onChange, translateString, schemaUtils, childFieldPathId, getAvailableKey, schema]);
1963
1980
  const handleKeyRename = react.useCallback(
@@ -1979,6 +1996,7 @@
1979
1996
  lastRenamedProperty.current.previousKey = oldKey;
1980
1997
  }
1981
1998
  lastRenamedProperty.current.currentKey = actualNewKey;
1999
+ setAdditionalPropertyOrder((order) => order.map((property) => property === oldKey ? actualNewKey : property));
1982
2000
  onChange(renamedObj, childFieldPathId.path);
1983
2001
  }
1984
2002
  },
@@ -1986,6 +2004,7 @@
1986
2004
  );
1987
2005
  const handleRemoveProperty = react.useCallback(
1988
2006
  (key) => {
2007
+ setAdditionalPropertyOrder((order) => order.filter((property) => property !== key));
1989
2008
  onChange(ADDITIONAL_PROPERTY_KEY_REMOVE, [...childFieldPathId.path, key]);
1990
2009
  },
1991
2010
  [onChange, childFieldPathId]
@@ -1998,8 +2017,11 @@
1998
2017
  }, []);
1999
2018
  if (!renderOptionalField || hasFormData) {
2000
2019
  try {
2001
- const properties = Object.keys(schemaProperties);
2002
- orderedProperties = utils.orderProperties(properties, uiOptions.order);
2020
+ const definedPropertySet = new Set(definedPropertyOrder);
2021
+ const currentAdditionalProperties = additionalPropertyOrder.filter(
2022
+ (property) => Object.hasOwn(schemaProperties, property) && !definedPropertySet.has(property)
2023
+ );
2024
+ orderedProperties = utils.orderProperties([...definedPropertyOrder, ...currentAdditionalProperties], uiOptions.order);
2003
2025
  } catch (err) {
2004
2026
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2005
2027
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rjsf-config-error", style: { color: "red" }, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Markdown, { options: { disableParsingRawHTML: true }, children: translateString(utils.TranslatableString.InvalidObjectField, [name || "root", err.message]) }) }),
@@ -2014,7 +2036,7 @@
2014
2036
  title: uiOptions.label === false ? "" : templateTitle,
2015
2037
  description: uiOptions.label === false ? void 0 : description,
2016
2038
  properties: orderedProperties.map((propertyName) => {
2017
- const addedByAdditionalProperties = has(schema, [utils.PROPERTIES_KEY, propertyName, utils.ADDITIONAL_PROPERTY_FLAG]);
2039
+ const addedByAdditionalProperties = isAdditionalPropertySchema(schema.properties?.[propertyName]);
2018
2040
  const fieldUiSchema = addedByAdditionalProperties ? uiSchema.additionalProperties : uiSchema[propertyName];
2019
2041
  const hidden = utils.getUiOptions(fieldUiSchema).widget === "hidden";
2020
2042
  const content = /* @__PURE__ */ jsxRuntime.jsx(
@@ -2131,7 +2153,7 @@
2131
2153
  };
2132
2154
  function getFieldComponent(schema, uiOptions, registry) {
2133
2155
  const { field } = uiOptions;
2134
- const { fields: fields2 } = registry;
2156
+ const { fields: fields2, schemaUtils } = registry;
2135
2157
  if (typeof field === "function") {
2136
2158
  return field;
2137
2159
  }
@@ -2145,7 +2167,7 @@
2145
2167
  if (schemaId && schemaId in fields2) {
2146
2168
  componentName = schemaId;
2147
2169
  }
2148
- if (!componentName && (schema.anyOf || schema.oneOf)) {
2170
+ if ((schema.anyOf || schema.oneOf) && !schemaUtils.isSelect(schema) && componentName !== "ObjectField") {
2149
2171
  return () => null;
2150
2172
  }
2151
2173
  return componentName in fields2 ? fields2[componentName] : fields2.FallbackField;
@@ -2167,7 +2189,18 @@
2167
2189
  wasPropertyKeyModified = false
2168
2190
  } = props;
2169
2191
  const { schemaUtils, globalFormOptions, globalUiOptions, fields: fields2 } = registry;
2170
- const { AnyOfField: _AnyOfField, OneOfField: _OneOfField } = fields2;
2192
+ const { AnyOfField: _AnyOfField, OneOfField: _OneOfField, CyclicSchemaField: CyclicSchemaField2 } = fields2;
2193
+ const fieldId = fieldPathId[utils.ID_KEY];
2194
+ const handleFieldComponentChange = react.useCallback(
2195
+ (newFormData, path, newErrorSchema, id2) => {
2196
+ const theId = id2 || fieldId;
2197
+ return onChange(newFormData, path, newErrorSchema, theId);
2198
+ },
2199
+ [fieldId, onChange]
2200
+ );
2201
+ if (_schema[utils.RJSF_REF_CYCLE_KEY]) {
2202
+ return /* @__PURE__ */ jsxRuntime.jsx(CyclicSchemaField2, { ...props });
2203
+ }
2171
2204
  const uiSchema = utils.resolveUiSchema(_schema, _uiSchema, registry);
2172
2205
  const uiOptions = utils.getUiOptions(uiSchema, globalUiOptions);
2173
2206
  const FieldTemplate2 = utils.getTemplate("FieldTemplate", registry, uiOptions);
@@ -2179,14 +2212,6 @@
2179
2212
  const FieldHelpTemplate2 = utils.getTemplate("FieldHelpTemplate", registry, uiOptions);
2180
2213
  const FieldErrorTemplate2 = utils.getTemplate("FieldErrorTemplate", registry, uiOptions);
2181
2214
  const schema = schemaUtils.retrieveSchema(_schema, formData);
2182
- const fieldId = fieldPathId[utils.ID_KEY];
2183
- const handleFieldComponentChange = react.useCallback(
2184
- (newFormData, path, newErrorSchema, id2) => {
2185
- const theId = id2 || fieldId;
2186
- return onChange(newFormData, path, newErrorSchema, theId);
2187
- },
2188
- [fieldId, onChange]
2189
- );
2190
2215
  const FieldComponent = getFieldComponent(schema, uiOptions, registry);
2191
2216
  const isDeprecated = Boolean(schema.deprecated);
2192
2217
  const deprecatedHandling = isDeprecated ? uiOptions.deprecatedHandling ?? "label" : void 0;
@@ -2348,18 +2373,16 @@
2348
2373
  )
2349
2374
  ] }) });
2350
2375
  }
2351
- var SchemaField = class extends react.Component {
2352
- shouldComponentUpdate(nextProps) {
2353
- const {
2354
- registry: { globalFormOptions }
2355
- } = this.props;
2356
- const { experimental_componentUpdateStrategy = "customDeep" } = globalFormOptions;
2357
- return utils.shouldRender(this, nextProps, this.state, experimental_componentUpdateStrategy);
2376
+ var SchemaField = react.memo(SchemaFieldRender, (prevProps, nextProps) => {
2377
+ const { experimental_componentUpdateStrategy = "customDeep" } = nextProps.registry.globalFormOptions;
2378
+ if (experimental_componentUpdateStrategy === "always") {
2379
+ return false;
2358
2380
  }
2359
- render() {
2360
- return /* @__PURE__ */ jsxRuntime.jsx(SchemaFieldRender, { ...this.props });
2381
+ if (experimental_componentUpdateStrategy === "shallow") {
2382
+ return utils.shallowEquals(prevProps, nextProps);
2361
2383
  }
2362
- };
2384
+ return utils.deepEquals(prevProps, nextProps);
2385
+ });
2363
2386
  var SchemaField_default = SchemaField;
2364
2387
  function StringField(props) {
2365
2388
  const {
@@ -2430,6 +2453,7 @@
2430
2453
  ArrayField,
2431
2454
  // ArrayField falls back to SchemaField if ArraySchemaField is not defined, which it isn't by default
2432
2455
  BooleanField: BooleanField_default,
2456
+ CyclicSchemaField,
2433
2457
  FallbackField,
2434
2458
  LayoutGridField,
2435
2459
  LayoutHeaderField,
@@ -2705,12 +2729,9 @@
2705
2729
  ({ target: { value: newValue } }) => onChange(newValue === "" ? options.emptyValue : newValue),
2706
2730
  [onChange, options]
2707
2731
  );
2708
- const handleBlur = react.useCallback(
2709
- ({ target }) => onBlur(id, target && target.value),
2710
- [onBlur, id]
2711
- );
2732
+ const handleBlur = react.useCallback(({ target }) => onBlur(id, target?.value), [onBlur, id]);
2712
2733
  const handleFocus = react.useCallback(
2713
- ({ target }) => onFocus(id, target && target.value),
2734
+ ({ target }) => onFocus(id, target?.value),
2714
2735
  [onFocus, id]
2715
2736
  );
2716
2737
  const handleClear = react.useCallback(
@@ -2852,6 +2873,27 @@
2852
2873
  };
2853
2874
  }
2854
2875
  var ButtonTemplates_default = buttonTemplates;
2876
+ function CyclicSchemaExpandTemplate(props) {
2877
+ const { name, fieldPathId, registry, onExpand } = props;
2878
+ const { translateString } = registry;
2879
+ const buttonId5 = `${fieldPathId[utils.ID_KEY]}-button`;
2880
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem" }, children: [
2881
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-danger", children: translateString(utils.TranslatableString.CycleDetected, [name]) }),
2882
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2883
+ /* @__PURE__ */ jsxRuntime.jsx(
2884
+ "button",
2885
+ {
2886
+ id: buttonId5,
2887
+ type: "button",
2888
+ className: "btn btn-sm btn-warning",
2889
+ onClick: () => onExpand(fieldPathId[utils.ID_KEY]),
2890
+ children: translateString(utils.TranslatableString.ExpandButton)
2891
+ }
2892
+ ),
2893
+ " "
2894
+ ] })
2895
+ ] });
2896
+ }
2855
2897
  var TEST_IDS = utils.getTestIds();
2856
2898
  function RichDescription({ description, registry, uiSchema = {} }) {
2857
2899
  const { globalUiOptions } = registry;
@@ -3089,7 +3131,7 @@
3089
3131
  const { translateString } = registry;
3090
3132
  let translateEnum = utils.TranslatableString.UnsupportedField;
3091
3133
  const translateParams = [];
3092
- if (fieldPathId && fieldPathId.$id) {
3134
+ if (fieldPathId?.$id) {
3093
3135
  translateEnum = utils.TranslatableString.UnsupportedFieldWithId;
3094
3136
  translateParams.push(fieldPathId.$id);
3095
3137
  }
@@ -3179,6 +3221,7 @@
3179
3221
  ArrayFieldTitleTemplate,
3180
3222
  ButtonTemplates: ButtonTemplates_default(),
3181
3223
  BaseInputTemplate,
3224
+ CyclicSchemaExpandTemplate,
3182
3225
  DescriptionFieldTemplate: DescriptionField,
3183
3226
  ErrorListTemplate: ErrorList,
3184
3227
  FallbackFieldTemplate,
@@ -3247,11 +3290,11 @@
3247
3290
  const optionValueFormat = utils.getOptionValueFormat(options);
3248
3291
  const checkboxesValues = Array.isArray(value) ? value : [value];
3249
3292
  const handleBlur = react.useCallback(
3250
- ({ target }) => onBlur(id, utils.enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)),
3293
+ ({ target }) => onBlur(id, utils.enumOptionValueDecoder(target?.value, enumOptions, optionValueFormat, emptyValue)),
3251
3294
  [onBlur, id, enumOptions, emptyValue, optionValueFormat]
3252
3295
  );
3253
3296
  const handleFocus = react.useCallback(
3254
- ({ target }) => onFocus(id, utils.enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)),
3297
+ ({ target }) => onFocus(id, utils.enumOptionValueDecoder(target?.value, enumOptions, optionValueFormat, emptyValue)),
3255
3298
  [onFocus, id, enumOptions, emptyValue, optionValueFormat]
3256
3299
  );
3257
3300
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
@@ -3495,11 +3538,11 @@
3495
3538
  const { enumOptions, enumDisabled, inline, emptyValue } = options;
3496
3539
  const optionValueFormat = utils.getOptionValueFormat(options);
3497
3540
  const handleBlur = react.useCallback(
3498
- ({ target }) => onBlur(id, utils.enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)),
3541
+ ({ target }) => onBlur(id, utils.enumOptionValueDecoder(target?.value, enumOptions, optionValueFormat, emptyValue)),
3499
3542
  [onBlur, enumOptions, emptyValue, id, optionValueFormat]
3500
3543
  );
3501
3544
  const handleFocus = react.useCallback(
3502
- ({ target }) => onFocus(id, utils.enumOptionValueDecoder(target && target.value, enumOptions, optionValueFormat, emptyValue)),
3545
+ ({ target }) => onFocus(id, utils.enumOptionValueDecoder(target?.value, enumOptions, optionValueFormat, emptyValue)),
3503
3546
  [onFocus, enumOptions, emptyValue, id, optionValueFormat]
3504
3547
  );
3505
3548
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "field-radio-group", id, role: "radiogroup", children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
@@ -3664,7 +3707,9 @@
3664
3707
  onBlur,
3665
3708
  onFocus,
3666
3709
  placeholder,
3667
- htmlName
3710
+ htmlName,
3711
+ registry,
3712
+ uiSchema
3668
3713
  }) {
3669
3714
  const { enumOptions, enumDisabled, emptyValue: optEmptyVal } = options;
3670
3715
  const emptyValue = multiple ? [] : "";
@@ -3692,8 +3737,19 @@
3692
3737
  );
3693
3738
  const selectValue = utils.enumOptionSelectedValue(value, enumOptions, multiple, optionValueFormat, emptyValue);
3694
3739
  const showPlaceholderOption = !multiple && schema.default === void 0;
3695
- return (
3696
- // oxlint-disable-next-line jsx-a11y/no-autofocus
3740
+ utils.logUnsupportedDefaultForEnum(id, schema, enumOptions, multiple);
3741
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3742
+ /* @__PURE__ */ jsxRuntime.jsx(
3743
+ utils.SelectedOptionDescription,
3744
+ {
3745
+ id,
3746
+ multiple,
3747
+ options,
3748
+ registry,
3749
+ uiSchema,
3750
+ value
3751
+ }
3752
+ ),
3697
3753
  /* @__PURE__ */ jsxRuntime.jsxs(
3698
3754
  "select",
3699
3755
  {
@@ -3726,12 +3782,12 @@
3726
3782
  ]
3727
3783
  }
3728
3784
  )
3729
- );
3785
+ ] });
3730
3786
  }
3731
3787
  var SelectWidget_default = SelectWidget;
3732
3788
  function TextareaWidget({
3733
3789
  id,
3734
- options = {},
3790
+ options,
3735
3791
  placeholder,
3736
3792
  value,
3737
3793
  required,
@@ -3748,11 +3804,11 @@
3748
3804
  [onChange, options.emptyValue]
3749
3805
  );
3750
3806
  const handleBlur = react.useCallback(
3751
- ({ target }) => onBlur(id, target && target.value),
3807
+ ({ target }) => onBlur(id, target?.value),
3752
3808
  [onBlur, id]
3753
3809
  );
3754
3810
  const handleFocus = react.useCallback(
3755
- ({ target }) => onFocus(id, target && target.value),
3811
+ ({ target }) => onFocus(id, target?.value),
3756
3812
  [id, onFocus]
3757
3813
  );
3758
3814
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -4154,14 +4210,15 @@
4154
4210
  const schemaUtils = altSchemaUtils || this.state.schemaUtils;
4155
4211
  const { customValidate, transformErrors, uiSchema } = this.props;
4156
4212
  const validationSchema = retrievedSchema ?? schema;
4157
- return schemaUtils.getValidator().validateFormData(formData, validationSchema, customValidate, transformErrors, uiSchema);
4213
+ const validationFormData = formData ? JSON.parse(JSON.stringify(formData)) : void 0;
4214
+ return schemaUtils.getValidator().validateFormData(validationFormData, validationSchema, customValidate, transformErrors, uiSchema);
4158
4215
  }
4159
4216
  /** Renders any errors contained in the `state` in using the `ErrorList`, if not disabled by `showErrorList`. */
4160
4217
  renderErrors(registry) {
4161
4218
  const { errors, errorSchema, schema, uiSchema } = this.state;
4162
4219
  const options = utils.getUiOptions(uiSchema);
4163
4220
  const ErrorListTemplate = utils.getTemplate("ErrorListTemplate", registry, options);
4164
- if (errors && errors.length) {
4221
+ if (errors?.length) {
4165
4222
  return /* @__PURE__ */ jsxRuntime.jsx(
4166
4223
  ErrorListTemplate,
4167
4224
  {
@@ -4308,10 +4365,10 @@
4308
4365
  const wasPreviouslyNull = oldFormData === null || oldFormData === void 0;
4309
4366
  const inputForDefaults = hasOnlyUndefinedValues && wasPreviouslyNull ? void 0 : formData;
4310
4367
  if (utils.isObject(formData) || Array.isArray(formData)) {
4368
+ let plainLeafWasCleared = false;
4311
4369
  if (newValue === ADDITIONAL_PROPERTY_KEY_REMOVE) {
4312
4370
  _unset(formData, path);
4313
4371
  } else if (!isRootPath) {
4314
- let unsetPath = false;
4315
4372
  let valueForPath = newValue;
4316
4373
  if (newValue === void 0) {
4317
4374
  const lastSegment = path[path.length - 1];
@@ -4322,12 +4379,12 @@
4322
4379
  const leaf = field;
4323
4380
  const isOneOfOrAnyOfLeaf = leaf && (utils.ONE_OF_KEY in leaf || utils.ANY_OF_KEY in leaf);
4324
4381
  if (!isOneOfOrAnyOfLeaf && leaf !== void 0) {
4325
- unsetPath = true;
4382
+ plainLeafWasCleared = true;
4326
4383
  }
4327
4384
  }
4328
4385
  }
4329
- if (unsetPath) {
4330
- _unset(formData, path);
4386
+ if (plainLeafWasCleared) {
4387
+ set(formData, path, void 0);
4331
4388
  } else {
4332
4389
  set(formData, path, valueForPath);
4333
4390
  }
@@ -4344,6 +4401,9 @@
4344
4401
  );
4345
4402
  formData = newState.formData;
4346
4403
  retrievedSchema = newState.retrievedSchema;
4404
+ if (plainLeafWasCleared && formData) {
4405
+ set(formData, path, void 0);
4406
+ }
4347
4407
  }
4348
4408
  const mustValidate = !noValidate && (liveValidate === true || liveValidate === "onChange");
4349
4409
  let state = { formData, retrievedSchema };
@@ -4443,7 +4503,7 @@
4443
4503
  initialDefaultsGenerated: false,
4444
4504
  customErrors: void 0
4445
4505
  };
4446
- this.setState(state, () => onChange && onChange(toIChangeEvent({ ...this.state, ...state })));
4506
+ this.setState(state, () => onChange?.(toIChangeEvent({ ...this.state, ...state })));
4447
4507
  };
4448
4508
  /** Callback function to handle when a field on the form is blurred. Calls the `onBlur` callback for the `Form` if it
4449
4509
  * was provided. Also runs any live validation and/or live omit operations if the flags indicate they should happen
@@ -4620,7 +4680,7 @@
4620
4680
  if (!field) {
4621
4681
  field = this.formElement.current.querySelector(`input[id^="${elementId}"], button[id^="${elementId}"]`);
4622
4682
  }
4623
- if (field && field.length) {
4683
+ if (field?.length) {
4624
4684
  field = field[0];
4625
4685
  }
4626
4686
  if (field) {