@qoretechnologies/reqraft 0.10.65 → 0.10.66-pr.145.g124fc92

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 (161) hide show
  1. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  2. package/dist/components/form/engine/CompactRow.js +130 -25
  3. package/dist/components/form/engine/CompactRow.js.map +1 -1
  4. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  5. package/dist/components/form/engine/CompactToolbar.js +78 -15
  6. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  7. package/dist/components/form/engine/FormEngine.d.ts +48 -1
  8. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  9. package/dist/components/form/engine/FormEngine.js +260 -99
  10. package/dist/components/form/engine/FormEngine.js.map +1 -1
  11. package/dist/components/form/engine/OptionFieldMessages.d.ts +18 -2
  12. package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
  13. package/dist/components/form/engine/OptionFieldMessages.js +22 -3
  14. package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
  15. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
  16. package/dist/components/form/engine/_structuredData/SchemaDataView.js +27 -1
  17. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
  18. package/dist/components/form/engine/compactRowContext.d.ts +5 -0
  19. package/dist/components/form/engine/compactRowContext.d.ts.map +1 -1
  20. package/dist/components/form/engine/compactRowContext.js.map +1 -1
  21. package/dist/components/form/engine/compactRowStyles.d.ts +12 -0
  22. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  23. package/dist/components/form/engine/compactRowStyles.js +72 -39
  24. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  25. package/dist/components/form/engine/compactToolbarContext.d.ts +3 -0
  26. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  27. package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
  28. package/dist/components/form/engine/formAppearance.d.ts +48 -0
  29. package/dist/components/form/engine/formAppearance.d.ts.map +1 -0
  30. package/dist/components/form/engine/formAppearance.js +50 -0
  31. package/dist/components/form/engine/formAppearance.js.map +1 -0
  32. package/dist/components/form/engine/readFirst.d.ts +14 -2
  33. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  34. package/dist/components/form/engine/readFirst.js +6 -2
  35. package/dist/components/form/engine/readFirst.js.map +1 -1
  36. package/dist/components/form/engine/rowFocus.d.ts +9 -1
  37. package/dist/components/form/engine/rowFocus.d.ts.map +1 -1
  38. package/dist/components/form/engine/rowFocus.js +17 -5
  39. package/dist/components/form/engine/rowFocus.js.map +1 -1
  40. package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
  41. package/dist/components/form/expressions/renderExpressionToText.js +21 -0
  42. package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
  43. package/dist/components/form/fields/ChoiceGroupHeading.d.ts +21 -0
  44. package/dist/components/form/fields/ChoiceGroupHeading.d.ts.map +1 -0
  45. package/dist/components/form/fields/ChoiceGroupHeading.js +33 -0
  46. package/dist/components/form/fields/ChoiceGroupHeading.js.map +1 -0
  47. package/dist/components/form/fields/Field.d.ts.map +1 -1
  48. package/dist/components/form/fields/Field.js +13 -11
  49. package/dist/components/form/fields/Field.js.map +1 -1
  50. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  51. package/dist/components/form/fields/allowed-values/AllowedValues.js +20 -7
  52. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  53. package/dist/components/form/fields/allowed-values/savedValues.d.ts +30 -0
  54. package/dist/components/form/fields/allowed-values/savedValues.d.ts.map +1 -0
  55. package/dist/components/form/fields/allowed-values/savedValues.js +18 -0
  56. package/dist/components/form/fields/allowed-values/savedValues.js.map +1 -0
  57. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  58. package/dist/components/form/fields/auto/AutoFormField.js +18 -8
  59. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  60. package/dist/components/form/fields/long-string/LongString.d.ts +7 -1
  61. package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
  62. package/dist/components/form/fields/long-string/LongString.js +9 -5
  63. package/dist/components/form/fields/long-string/LongString.js.map +1 -1
  64. package/dist/components/form/fields/multi-select/MultiSelectFormField.d.ts.map +1 -1
  65. package/dist/components/form/fields/multi-select/MultiSelectFormField.js +6 -5
  66. package/dist/components/form/fields/multi-select/MultiSelectFormField.js.map +1 -1
  67. package/dist/components/form/fields/number/Number.d.ts +4 -1
  68. package/dist/components/form/fields/number/Number.d.ts.map +1 -1
  69. package/dist/components/form/fields/number/Number.js +13 -5
  70. package/dist/components/form/fields/number/Number.js.map +1 -1
  71. package/dist/components/form/fields/radio-group/RadioGroup.d.ts.map +1 -1
  72. package/dist/components/form/fields/radio-group/RadioGroup.js +13 -7
  73. package/dist/components/form/fields/radio-group/RadioGroup.js.map +1 -1
  74. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  75. package/dist/components/form/fields/template/TemplateField.js +71 -42
  76. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  77. package/dist/components/form/index.d.ts +2 -0
  78. package/dist/components/form/index.d.ts.map +1 -1
  79. package/dist/components/form/index.js +2 -0
  80. package/dist/components/form/index.js.map +1 -1
  81. package/dist/components/imageLightbox/ImageLightbox.d.ts.map +1 -1
  82. package/dist/components/imageLightbox/ImageLightbox.js +2 -0
  83. package/dist/components/imageLightbox/ImageLightbox.js.map +1 -1
  84. package/dist/components/supportTicket/InterfaceReferenceTags.d.ts +3 -2
  85. package/dist/components/supportTicket/InterfaceReferenceTags.d.ts.map +1 -1
  86. package/dist/components/supportTicket/InterfaceReferenceTags.js.map +1 -1
  87. package/dist/components/supportTicket/ReferencePicker.d.ts +2 -1
  88. package/dist/components/supportTicket/ReferencePicker.d.ts.map +1 -1
  89. package/dist/components/supportTicket/ReferencePicker.js +19 -13
  90. package/dist/components/supportTicket/ReferencePicker.js.map +1 -1
  91. package/dist/components/supportTicket/TicketHeader.d.ts.map +1 -1
  92. package/dist/components/supportTicket/TicketHeader.js +4 -1
  93. package/dist/components/supportTicket/TicketHeader.js.map +1 -1
  94. package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -1
  95. package/dist/components/supportTicket/TicketReplyBox.js +29 -10
  96. package/dist/components/supportTicket/TicketReplyBox.js.map +1 -1
  97. package/dist/components/supportTicket/useLoadedImages.d.ts +10 -0
  98. package/dist/components/supportTicket/useLoadedImages.d.ts.map +1 -1
  99. package/dist/components/supportTicket/useLoadedImages.js +63 -1
  100. package/dist/components/supportTicket/useLoadedImages.js.map +1 -1
  101. package/dist/components/ticketReferences/TicketReferences.d.ts.map +1 -1
  102. package/dist/components/ticketReferences/TicketReferences.js +6 -2
  103. package/dist/components/ticketReferences/TicketReferences.js.map +1 -1
  104. package/dist/components/ticketThread/TicketThread.d.ts.map +1 -1
  105. package/dist/components/ticketThread/TicketThread.js +10 -16
  106. package/dist/components/ticketThread/TicketThread.js.map +1 -1
  107. package/dist/helpers/allowedValues.d.ts +12 -0
  108. package/dist/helpers/allowedValues.d.ts.map +1 -1
  109. package/dist/helpers/allowedValues.js +20 -1
  110. package/dist/helpers/allowedValues.js.map +1 -1
  111. package/dist/helpers/fieldDescription.d.ts +16 -0
  112. package/dist/helpers/fieldDescription.d.ts.map +1 -0
  113. package/dist/helpers/fieldDescription.js +40 -0
  114. package/dist/helpers/fieldDescription.js.map +1 -0
  115. package/dist/helpers/singleLineString.d.ts.map +1 -1
  116. package/dist/helpers/singleLineString.js +1 -0
  117. package/dist/helpers/singleLineString.js.map +1 -1
  118. package/package.json +1 -1
  119. package/src/components/form/engine/CompactRow.tsx +143 -23
  120. package/src/components/form/engine/CompactToolbar.tsx +85 -16
  121. package/src/components/form/engine/FormEngine.stories.tsx +25 -13
  122. package/src/components/form/engine/FormEngine.tsx +367 -81
  123. package/src/components/form/engine/FormEngineAppearance.stories.tsx +540 -0
  124. package/src/components/form/engine/FormEngineStickyHeaders.stories.tsx +5 -1
  125. package/src/components/form/engine/OptionFieldMessages.tsx +73 -2
  126. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +17 -4
  127. package/src/components/form/engine/compactRowContext.ts +5 -0
  128. package/src/components/form/engine/compactRowStyles.ts +218 -38
  129. package/src/components/form/engine/compactToolbarContext.ts +3 -0
  130. package/src/components/form/engine/formAppearance.ts +78 -0
  131. package/src/components/form/engine/readFirst.ts +16 -3
  132. package/src/components/form/engine/rowFocus.ts +17 -6
  133. package/src/components/form/expressions/renderExpressionToText.ts +15 -0
  134. package/src/components/form/fields/ChoiceGroupHeading.tsx +38 -0
  135. package/src/components/form/fields/Field.tsx +11 -9
  136. package/src/components/form/fields/allowed-values/AllowedValues.tsx +21 -9
  137. package/src/components/form/fields/allowed-values/savedValues.ts +41 -0
  138. package/src/components/form/fields/auto/AutoFormField.tsx +17 -4
  139. package/src/components/form/fields/long-string/LongString.stories.tsx +27 -0
  140. package/src/components/form/fields/long-string/LongString.tsx +14 -3
  141. package/src/components/form/fields/multi-select/MultiSelectFormField.tsx +5 -4
  142. package/src/components/form/fields/number/Number.tsx +19 -4
  143. package/src/components/form/fields/radio-group/RadioGroup.tsx +13 -7
  144. package/src/components/form/fields/template/TemplateField.tsx +32 -4
  145. package/src/components/form/index.tsx +2 -0
  146. package/src/components/imageLightbox/ImageLightbox.tsx +2 -0
  147. package/src/components/supportTicket/InterfaceReferenceTags.tsx +3 -2
  148. package/src/components/supportTicket/ReferencePicker.stories.tsx +0 -4
  149. package/src/components/supportTicket/ReferencePicker.tsx +22 -12
  150. package/src/components/supportTicket/TicketConversation.stories.tsx +0 -1
  151. package/src/components/supportTicket/TicketHeader.tsx +2 -1
  152. package/src/components/supportTicket/TicketReplyBox.stories.tsx +24 -21
  153. package/src/components/supportTicket/TicketReplyBox.tsx +27 -5
  154. package/src/components/supportTicket/useLoadedImages.ts +20 -0
  155. package/src/components/ticketReferences/TicketReferences.stories.tsx +26 -0
  156. package/src/components/ticketReferences/TicketReferences.tsx +12 -4
  157. package/src/components/ticketThread/TicketThread.stories.tsx +71 -2
  158. package/src/components/ticketThread/TicketThread.tsx +15 -28
  159. package/src/helpers/allowedValues.ts +19 -0
  160. package/src/helpers/fieldDescription.ts +39 -0
  161. package/src/helpers/singleLineString.ts +1 -0
@@ -107,6 +107,7 @@ var typeChoices_1 = require("./typeChoices");
107
107
  var optionActions_1 = require("./optionActions");
108
108
  var rendererTypes_1 = require("./rendererTypes");
109
109
  var revealRow_1 = require("./revealRow");
110
+ var rowFocus_1 = require("./rowFocus");
110
111
  var emittedValues_1 = require("../fields/emittedValues");
111
112
  var lodash_1 = require("lodash");
112
113
  var map_1 = __importDefault(require("lodash/map"));
@@ -115,6 +116,8 @@ var size_1 = __importDefault(require("lodash/size"));
115
116
  var react_2 = __importStar(require("react"));
116
117
  var react_use_1 = require("react-use");
117
118
  var styled_components_1 = __importStar(require("styled-components"));
119
+ var allowedValues_1 = require("../../../helpers/allowedValues");
120
+ var fieldDescription_1 = require("../../../helpers/fieldDescription");
118
121
  var common_1 = require("../../../helpers/common");
119
122
  var options_1 = require("../../../helpers/options");
120
123
  var validations_1 = require("../../../helpers/validations");
@@ -136,6 +139,7 @@ var OptionFieldMessages_1 = require("./OptionFieldMessages");
136
139
  var optionsContext_1 = require("./optionsContext");
137
140
  var markdownRendererContext_1 = require("../../Description/markdownRendererContext");
138
141
  var OptionsHelpDialog_1 = require("./OptionsHelpDialog");
142
+ var formAppearance_1 = require("./formAppearance");
139
143
  var optionUiTypes_1 = require("../../../helpers/optionUiTypes");
140
144
  var readFirst_1 = require("./readFirst");
141
145
  /**
@@ -521,25 +525,28 @@ var FormEngineImpl = function (_a) {
521
525
  var name = _a.name, uniqueName = _a.uniqueName, value = _a.value, onChange = _a.onChange, onSingleOptionsChange = _a.onSingleOptionsChange, onDependableOptionChange = _a.onDependableOptionChange, placeholder = _a.placeholder, noValueString = _a.noValueString, // eslint-disable-line @typescript-eslint/no-unused-vars
522
526
  isValid = _a.isValid, // eslint-disable-line @typescript-eslint/no-unused-vars
523
527
  url = _a.url, customUrl = _a.customUrl, operatorsUrl = _a.operatorsUrl, onOptionsLoaded = _a.onOptionsLoaded, recordRequiresSearchOptions = _a.recordRequiresSearchOptions, readOnly = _a.readOnly, onReadOnlyActivate = _a.onReadOnlyActivate, _h = _a.allowTemplates, allowTemplates = _h === void 0 ? true : _h, interfaceContext = _a.interfaceContext, templateFieldProps = _a.templateFieldProps, forceDropdown = _a.forceDropdown, _j = _a.showTypeToggle, showTypeToggle = _j === void 0 ? true : _j, compact = _a.compact,
528
+ // Read through the context `FormEngine` provides (resolved there against an
529
+ // inherited appearance); destructured only to keep it out of `rest`.
530
+ _appearance = _a.appearance, // eslint-disable-line @typescript-eslint/no-unused-vars
524
531
  // Destructured only to keep it out of `rest` (and so off the DOM). The gutter
525
532
  // this prop documents was never implemented: it was passed to the wrap as
526
533
  // `$flush`, whose styled template had no interpolation slot, so it has always
527
534
  // been a no-op. Removing it from the API is a separate, breaking change —
528
535
  // every consumer passing it today already gets the flush layout by default.
529
536
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
530
- _k = _a.compactFlush,
537
+ _k = _a.compactFlush, // eslint-disable-line @typescript-eslint/no-unused-vars
531
538
  // Destructured only to keep it out of `rest` (and so off the DOM). The gutter
532
539
  // this prop documents was never implemented: it was passed to the wrap as
533
540
  // `$flush`, whose styled template had no interpolation slot, so it has always
534
541
  // been a no-op. Removing it from the API is a separate, breaking change —
535
542
  // every consumer passing it today already gets the flush layout by default.
536
543
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
537
- compactFlush = _k === void 0 ? false : _k, _l = _a.compactNested, compactNested = _l === void 0 ? false : _l, _m = _a.compactScroll, compactScroll = _m === void 0 ? 'host' : _m, compactPanelProps = _a.compactPanelProps, compactCollapsedGroupsProp = _a.compactCollapsedGroups, compactBoxLabels = _a.compactBoxLabels, _o = _a.compactStickyBoxHeaders, compactStickyBoxHeaders = _o === void 0 ? true : _o, _p = _a.compactStickyOffset, compactStickyOffset = _p === void 0 ? 0 : _p, _q = _a.compactToolbar, compactToolbar = _q === void 0 ? true : _q, _r = _a.commitMode, commitMode = _r === void 0 ? 'immediate' : _r, _s = _a.expandMode, expandMode = _s === void 0 ? 'single' : _s, onCommit = _a.onCommit, operatorsProp = _a.operators, groups = _a.groups, optionsLoader = _a.optionsLoader, onValidityChange = _a.onValidityChange, optionActions = _a.optionActions, _t = _a.optionActionsCollapse, optionActionsCollapse = _t === void 0 ? 'auto' : _t, componentOverrides = _a.componentOverrides, codePreviewRenderer = _a.codePreviewRenderer,
544
+ compactFlush = _k === void 0 ? false : _k, _l = _a.compactNested, compactNested = _l === void 0 ? false : _l, _m = _a.compactScroll, compactScroll = _m === void 0 ? 'host' : _m, compactPanelProps = _a.compactPanelProps, compactCollapsedGroupsProp = _a.compactCollapsedGroups, compactBoxLabels = _a.compactBoxLabels, _o = _a.revealRequired, revealRequired = _o === void 0 ? false : _o, focusAttentionRequest = _a.focusAttentionRequest, onAttentionChange = _a.onAttentionChange, _p = _a.compactStickyBoxHeaders, compactStickyBoxHeaders = _p === void 0 ? true : _p, _q = _a.compactStickyOffset, compactStickyOffset = _q === void 0 ? 0 : _q, _r = _a.compactToolbar, compactToolbar = _r === void 0 ? true : _r, _s = _a.commitMode, commitMode = _s === void 0 ? 'immediate' : _s, _t = _a.expandMode, expandMode = _t === void 0 ? 'single' : _t, onCommit = _a.onCommit, operatorsProp = _a.operators, groups = _a.groups, optionsLoader = _a.optionsLoader, onValidityChange = _a.onValidityChange, optionActions = _a.optionActions, _u = _a.optionActionsCollapse, optionActionsCollapse = _u === void 0 ? 'auto' : _u, componentOverrides = _a.componentOverrides, codePreviewRenderer = _a.codePreviewRenderer,
538
545
  // consumed by the wrapper below, which publishes it to every description this
539
546
  // form draws; destructured here only so it cannot reach `rest` and be spread
540
547
  // onto a DOM node
541
548
  _markdownRenderer = _a.markdownRenderer, // eslint-disable-line @typescript-eslint/no-unused-vars
542
- rendererOnlyUiTypes = _a.rendererOnlyUiTypes, templateAwareUiTypes = _a.templateAwareUiTypes, anyLikeUiTypes = _a.anyLikeUiTypes, inheritedFromParent = _a.inheritedFromParent, autoFocusFirstRequired = _a.autoFocusFirstRequired, expandFirstRequired = _a.expandFirstRequired, initialExpandedOptions = _a.initialExpandedOptions, maxFieldsShown = _a.maxFieldsShown, rest = __rest(_a, ["name", "uniqueName", "value", "onChange", "onSingleOptionsChange", "onDependableOptionChange", "placeholder", "noValueString", "isValid", "url", "customUrl", "operatorsUrl", "onOptionsLoaded", "recordRequiresSearchOptions", "readOnly", "onReadOnlyActivate", "allowTemplates", "interfaceContext", "templateFieldProps", "forceDropdown", "showTypeToggle", "compact", "compactFlush", "compactNested", "compactScroll", "compactPanelProps", "compactCollapsedGroups", "compactBoxLabels", "compactStickyBoxHeaders", "compactStickyOffset", "compactToolbar", "commitMode", "expandMode", "onCommit", "operators", "groups", "optionsLoader", "onValidityChange", "optionActions", "optionActionsCollapse", "componentOverrides", "codePreviewRenderer", "markdownRenderer", "rendererOnlyUiTypes", "templateAwareUiTypes", "anyLikeUiTypes", "inheritedFromParent", "autoFocusFirstRequired", "expandFirstRequired", "initialExpandedOptions", "maxFieldsShown"]);
549
+ rendererOnlyUiTypes = _a.rendererOnlyUiTypes, templateAwareUiTypes = _a.templateAwareUiTypes, anyLikeUiTypes = _a.anyLikeUiTypes, inheritedFromParent = _a.inheritedFromParent, autoFocusFirstRequired = _a.autoFocusFirstRequired, expandFirstRequired = _a.expandFirstRequired, initialExpandedOptions = _a.initialExpandedOptions, maxFieldsShown = _a.maxFieldsShown, rest = __rest(_a, ["name", "uniqueName", "value", "onChange", "onSingleOptionsChange", "onDependableOptionChange", "placeholder", "noValueString", "isValid", "url", "customUrl", "operatorsUrl", "onOptionsLoaded", "recordRequiresSearchOptions", "readOnly", "onReadOnlyActivate", "allowTemplates", "interfaceContext", "templateFieldProps", "forceDropdown", "showTypeToggle", "compact", "appearance", "compactFlush", "compactNested", "compactScroll", "compactPanelProps", "compactCollapsedGroups", "compactBoxLabels", "revealRequired", "focusAttentionRequest", "onAttentionChange", "compactStickyBoxHeaders", "compactStickyOffset", "compactToolbar", "commitMode", "expandMode", "onCommit", "operators", "groups", "optionsLoader", "onValidityChange", "optionActions", "optionActionsCollapse", "componentOverrides", "codePreviewRenderer", "markdownRenderer", "rendererOnlyUiTypes", "templateAwareUiTypes", "anyLikeUiTypes", "inheritedFromParent", "autoFocusFirstRequired", "expandFirstRequired", "initialExpandedOptions", "maxFieldsShown"]);
543
550
  // Built-ins + whatever the consumer declared for its own injected editors.
544
551
  var isRendererOnly = (0, react_2.useMemo)(function () { return (0, rendererTypes_1.createRendererOnlyUiTypeCheck)(rendererOnlyUiTypes); }, [JSON.stringify(rendererOnlyUiTypes)]);
545
552
  // Pointer CAPABILITY and viewport WIDTH are different questions and both
@@ -564,34 +571,50 @@ var FormEngineImpl = function (_a) {
564
571
  enters the component, so the header, the chips, the messages, the meter and
565
572
  the read-first summary cannot disagree about it: every one of them reads
566
573
  `options`, and none of them has to know the rule. */
567
- var _u = (0, react_2.useState)((rest === null || rest === void 0 ? void 0 : rest.options) || undefined), servedOptions = _u[0], setOptions = _u[1];
574
+ var _v = (0, react_2.useState)((rest === null || rest === void 0 ? void 0 : rest.options) || undefined), servedOptions = _v[0], setOptions = _v[1];
568
575
  var options = (0, react_2.useMemo)(function () { return (0, options_1.resolveDegenerateRequiredGroups)(servedOptions); }, [servedOptions]);
569
576
  // optionsLoader lifecycle: loading feeds the skeleton gate, error the banner.
570
- var _v = (0, react_2.useState)(!!optionsLoader && !(rest === null || rest === void 0 ? void 0 : rest.options)), optionsLoading = _v[0], setOptionsLoading = _v[1];
571
- var _w = (0, react_2.useState)(), optionsError = _w[0], setOptionsError = _w[1];
577
+ var _w = (0, react_2.useState)(!!optionsLoader && !(rest === null || rest === void 0 ? void 0 : rest.options)), optionsLoading = _w[0], setOptionsLoading = _w[1];
578
+ var _x = (0, react_2.useState)(), optionsError = _x[0], setOptionsError = _x[1];
572
579
  // Operators: prop-provided (compact) or fetched via operatorsUrl (dpql,
573
580
  // ported from IDE Options) — the fetch overrides the seeded prop value.
574
- var _x = (0, react_2.useState)(operatorsProp), operators = _x[0], setOperators = _x[1];
581
+ var _y = (0, react_2.useState)(operatorsProp), operators = _y[0], setOperators = _y[1];
575
582
  // Remote-fetch loading (ported from IDE Options); only relevant when one of
576
583
  // the fetch urls is set — schema-as-props consumers never see the skeleton.
577
- var _y = (0, react_2.useState)(!!(url || customUrl || operatorsUrl)), loading = _y[0], setLoading = _y[1];
584
+ var _z = (0, react_2.useState)(!!(url || customUrl || operatorsUrl)), loading = _z[0], setLoading = _z[1];
578
585
  var confirmAction = (0, reqore_1.useReqoreProperty)('confirmAction');
579
586
  var theme = (0, reqore_1.useReqoreTheme)();
580
- var _z = (0, react_2.useState)(), focusedEditing = _z[0], setFocusedEditing = _z[1];
581
- var _0 = (0, react_2.useState)(false), showFieldTypes = _0[0], setShowFieldTypes = _0[1];
587
+ var calm = (0, formAppearance_1.useIsCalmForm)();
588
+ var _0 = (0, react_2.useState)(), focusedEditing = _0[0], setFocusedEditing = _0[1];
589
+ var _1 = (0, react_2.useState)(false), showFieldTypes = _1[0], setShowFieldTypes = _1[1];
582
590
  // Global toggle (toolbar ⓘ): reveal the short-description info panel on every
583
591
  // field that has a short_desc. Per-row ⓘ overrides still win over it.
584
592
  // Global field-info visibility, tri-state: `undefined` = default (critical
585
593
  // messages auto-open, the rest closed); `true` = show all; `false` = hide all
586
594
  // (even message fields). The toolbar ⓘ drives it.
587
- var _1 = (0, react_2.useState)(undefined), showAllDescriptions = _1[0], setShowAllDescriptions = _1[1];
588
- var _2 = (0, react_2.useState)(), showHelpForOption = _2[0], setShowHelpForOption = _2[1];
589
- var _3 = (0, react_2.useState)(false), showInvalidOptionsOnly = _3[0], setShowInvalidOptionsOnly = _3[1];
595
+ var _2 = (0, react_2.useState)(undefined), showAllDescriptions = _2[0], setShowAllDescriptions = _2[1];
596
+ var _3 = (0, react_2.useState)(), showHelpForOption = _3[0], setShowHelpForOption = _3[1];
597
+ var _4 = (0, react_2.useState)(false), showInvalidOptionsOnly = _4[0], setShowInvalidOptionsOnly = _4[1];
590
598
  // Which options are expanded into their editor (several can be open at once).
591
- var _4 = (0, react_2.useState)([]), expandedOptions = _4[0], setExpandedOptions = _4[1];
599
+ var _5 = (0, react_2.useState)([]), expandedOptions = _5[0], setExpandedOptions = _5[1];
600
+ // The fields the person has opened and left. An empty required field becomes a
601
+ // fault only then (or after a submit attempt, `revealRequired`): a form nobody has
602
+ // touched is not already wrong.
603
+ var _6 = (0, react_2.useState)([]), visitedOptions = _6[0], setVisitedOptions = _6[1];
604
+ var lastExpandedOptions = (0, react_2.useRef)([]);
605
+ (0, react_2.useEffect)(function () {
606
+ var left = lastExpandedOptions.current.filter(function (name) { return !expandedOptions.includes(name); });
607
+ lastExpandedOptions.current = expandedOptions;
608
+ if (left.length) {
609
+ setVisitedOptions(function (prev) {
610
+ var added = left.filter(function (name) { return !prev.includes(name); });
611
+ return added.length ? __spreadArray(__spreadArray([], prev, true), added, true) : prev;
612
+ });
613
+ }
614
+ }, [expandedOptions]);
592
615
  /** Status boxes whose "N more fields" control the reader has opened. Keyed by
593
616
  box so opening Optional does not also unfold Set. */
594
- var _5 = (0, react_2.useState)([]), expandedMoreBoxes = _5[0], setExpandedMoreBoxes = _5[1];
617
+ var _7 = (0, react_2.useState)([]), expandedMoreBoxes = _7[0], setExpandedMoreBoxes = _7[1];
595
618
  // --- Reveal a status box's content when it is opened ----------------------
596
619
  //
597
620
  // The status boxes stack, so the last one ("Optional", which holds every
@@ -607,7 +630,7 @@ var FormEngineImpl = function (_a) {
607
630
  // box has not grown and there is nothing to scroll to. A layout effect runs
608
631
  // after the DOM is updated and before paint, which makes the reveal
609
632
  // deterministic instead of a guessed delay.
610
- var _6 = (0, react_2.useState)(undefined), openedStatusBox = _6[0], setOpenedStatusBox = _6[1];
633
+ var _8 = (0, react_2.useState)(undefined), openedStatusBox = _8[0], setOpenedStatusBox = _8[1];
611
634
  var statusBoxRefs = (0, react_2.useRef)({});
612
635
  (0, react_2.useLayoutEffect)(function () {
613
636
  var _a, _b;
@@ -638,13 +661,13 @@ var FormEngineImpl = function (_a) {
638
661
  var settledBucket = (0, react_2.useRef)({});
639
662
  // Measured form width (not viewport — the form lives in drawers/panels of
640
663
  // arbitrary width) drives the stacked narrow layout.
641
- var _7 = (0, react_use_1.useMeasure)(), compactWrapRef = _7[0], compactWrapWidth = _7[1].width;
664
+ var _9 = (0, react_use_1.useMeasure)(), compactWrapRef = _9[0], compactWrapWidth = _9[1].width;
642
665
  // Own handle on the scroll wrap (useMeasure's ref is a callback, no `.current`)
643
666
  // so the label-column measurement can publish its CSS var on the element. It's
644
667
  // STATE, not a ref: the wrap mounts only after the loading-skeleton gate
645
668
  // resolves, so the measurement effect must re-run when the node appears — a
646
669
  // ref wouldn't retrigger it.
647
- var _8 = (0, react_2.useState)(null), compactWrapNode = _8[0], setCompactWrapNode = _8[1];
670
+ var _10 = (0, react_2.useState)(null), compactWrapNode = _10[0], setCompactWrapNode = _10[1];
648
671
  // Ref mirror of the wrap node for callbacks that must not re-create when it
649
672
  // mounts (flashOptions reads it inside a rAF).
650
673
  var compactWrapNodeRef = (0, react_2.useRef)(null);
@@ -672,7 +695,7 @@ var FormEngineImpl = function (_a) {
672
695
  a search row and a field picker that each hide themselves when they have
673
696
  nothing to say, and what is left wraps differently at every form width.
674
697
  Zero when this form draws no toolbar at all. */
675
- var _9 = (0, react_2.useState)(0), compactToolbarHeight = _9[0], setCompactToolbarHeight = _9[1];
698
+ var _11 = (0, react_2.useState)(0), compactToolbarHeight = _11[0], setCompactToolbarHeight = _11[1];
676
699
  (0, react_2.useLayoutEffect)(function () {
677
700
  var wrap = compactWrapNode;
678
701
  if (!compact || !wrap || compactNested || !compactStickyBoxHeaders) {
@@ -757,8 +780,8 @@ var FormEngineImpl = function (_a) {
757
780
  var readRowHeights = (0, react_2.useRef)({});
758
781
  // Required-groups linkage: hovering a group chip highlights every member row;
759
782
  // clicking a sibling in the chip's popover scrolls to it and flashes it.
760
- var _10 = (0, react_2.useState)([]), highlightedOptions = _10[0], setHighlightedOptions = _10[1];
761
- var _11 = (0, react_2.useState)([]), flashedOptions = _11[0], setFlashedOptions = _11[1];
783
+ var _12 = (0, react_2.useState)([]), highlightedOptions = _12[0], setHighlightedOptions = _12[1];
784
+ var _13 = (0, react_2.useState)([]), flashedOptions = _13[0], setFlashedOptions = _13[1];
762
785
  var flashTimeout = (0, react_2.useRef)();
763
786
  var flashOptions = (0, react_2.useCallback)(function (optionNames, scrollToFirst) {
764
787
  if (scrollToFirst === void 0) { scrollToFirst = false; }
@@ -810,16 +833,16 @@ var FormEngineImpl = function (_a) {
810
833
  }
811
834
  });
812
835
  // Info panels auto-open on Tier-1 content; the per-row user override sticks.
813
- var _12 = (0, react_2.useState)({}), infoPanelOverrides = _12[0], setInfoPanelOverrides = _12[1];
836
+ var _14 = (0, react_2.useState)({}), infoPanelOverrides = _14[0], setInfoPanelOverrides = _14[1];
814
837
  // Toolbar filters affect the listed rows only — the meter reflects the full set.
815
- var _13 = (0, react_2.useState)(false), requiredOnly = _13[0], setRequiredOnly = _13[1];
816
- var _14 = (0, react_2.useState)(''), compactQuery = _14[0], setCompactQuery = _14[1];
838
+ var _15 = (0, react_2.useState)(false), requiredOnly = _15[0], setRequiredOnly = _15[1];
839
+ var _16 = (0, react_2.useState)(''), compactQuery = _16[0], setCompactQuery = _16[1];
817
840
  // Compact field sort (Fields menu → "Sort by"); 'schema' = declared order.
818
- var _15 = (0, react_2.useState)('schema'), compactSort = _15[0], setCompactSort = _15[1];
819
- var _16 = (0, react_2.useState)(function () { return ({
841
+ var _17 = (0, react_2.useState)('schema'), compactSort = _17[0], setCompactSort = _17[1];
842
+ var _18 = (0, react_2.useState)(function () { return ({
820
843
  fields: (0, exports.fixOptions)(value, options || {}, undefined, isRendererOnly),
821
844
  meta: undefined,
822
- }); }), localValue = _16[0], setLocalValue = _16[1];
845
+ }); }), localValue = _18[0], setLocalValue = _18[1];
823
846
  var originalValue = (0, react_2.useRef)();
824
847
  // Track the last value we emitted via onChange so we can skip re-applying fixOptions
825
848
  // when the parent echoes it back as the new value prop (controlled component loop prevention)
@@ -864,7 +887,7 @@ var FormEngineImpl = function (_a) {
864
887
  originalValue.current = localValue.fields;
865
888
  }
866
889
  var unavailableOptionsCount = (0, react_2.useRef)(0);
867
- var _17 = (0, useQorusTypes_1.useQorusTypes)(), compactValue = _17.compactValue, typesLoading = _17.loading;
890
+ var _19 = (0, useQorusTypes_1.useQorusTypes)(), compactValue = _19.compactValue, typesLoading = _19.loading;
868
891
  var templates = (0, useTemplates_1.useTemplates)(allowTemplates, rest.stringTemplates, interfaceContext);
869
892
  (0, react_2.useEffect)(function () {
870
893
  if (!(0, exports.shouldEmitLocalValue)({
@@ -1383,9 +1406,8 @@ var FormEngineImpl = function (_a) {
1383
1406
  var locked = [];
1384
1407
  (0, lodash_1.forEach)(options || {}, function (optionSchema, name) {
1385
1408
  (0, lodash_1.forEach)((optionSchema === null || optionSchema === void 0 ? void 0 : optionSchema.allowed_values) || [], function (allowedValue) {
1386
- var _a;
1387
1409
  if (!(0, OptionFieldMessages_1.getAllowedValueAvailability)(allowedValue, availableOptions, options || {}).available) {
1388
- locked.push("".concat(name, "\0").concat(JSON.stringify((_a = allowedValue === null || allowedValue === void 0 ? void 0 : allowedValue.value) === null || _a === void 0 ? void 0 : _a.value)));
1410
+ locked.push("".concat(name, "\0").concat(JSON.stringify((0, allowedValues_1.allowedValueOf)(allowedValue))));
1389
1411
  }
1390
1412
  });
1391
1413
  });
@@ -1523,6 +1545,11 @@ var FormEngineImpl = function (_a) {
1523
1545
  return (0, reduce_1.default)(availableOptions, function (newValue, option, optionName) {
1524
1546
  var _a;
1525
1547
  if (showInvalidOptionsOnly &&
1548
+ // An open row stays while the reader is in it, as its box does
1549
+ // (`stableBucketOf`): the first character typed into an empty required
1550
+ // field makes it valid, and hiding it then would pull the field out
1551
+ // from under the caret mid-word.
1552
+ !expandedOptions.includes(optionName) &&
1526
1553
  isOptionValid(optionName, (0, exports.getOptionFieldStorageType)(optionName, option.type, options, operators, option.op, isRendererOnly, optionHoldsExpression(option)), option.value)) {
1527
1554
  return newValue;
1528
1555
  }
@@ -1530,6 +1557,7 @@ var FormEngineImpl = function (_a) {
1530
1557
  }, {});
1531
1558
  }, [
1532
1559
  showInvalidOptionsOnly,
1560
+ expandedOptions,
1533
1561
  isRendererOnly,
1534
1562
  JSON.stringify(availableOptions),
1535
1563
  JSON.stringify(options),
@@ -1585,8 +1613,11 @@ var FormEngineImpl = function (_a) {
1585
1613
  covered: covered,
1586
1614
  invalid: invalid,
1587
1615
  warned: msgIntent === 'warning',
1616
+ visited: revealRequired || visitedOptions.includes(name),
1588
1617
  });
1589
1618
  }, [
1619
+ revealRequired,
1620
+ visitedOptions,
1590
1621
  isRendererOnly,
1591
1622
  JSON.stringify(options),
1592
1623
  JSON.stringify(availableOptions),
@@ -1615,6 +1646,21 @@ var FormEngineImpl = function (_a) {
1615
1646
  return Object.keys(availableOptions || {}).filter(function (name) { return getOptionBucket(name) === 'attention'; })
1616
1647
  .length;
1617
1648
  }, [JSON.stringify(availableOptions), getOptionBucket]);
1649
+ // How many of those are faults rather than only still to fill in (`pending`). Zero
1650
+ // on a new form, so its first box reads "To fill in" without amber.
1651
+ var readFirstAttentionFaultCount = (0, react_2.useMemo)(function () {
1652
+ return Object.keys(availableOptions || {}).filter(function (name) { return getOptionBucket(name) === 'attention' && getOptionStatus(name) !== 'pending'; }).length;
1653
+ }, [JSON.stringify(availableOptions), getOptionBucket, getOptionStatus]);
1654
+ // The same two numbers, to a host that draws its own submit control from them.
1655
+ var onAttentionChangeRef = (0, react_2.useRef)(onAttentionChange);
1656
+ onAttentionChangeRef.current = onAttentionChange;
1657
+ (0, react_2.useEffect)(function () {
1658
+ var _a;
1659
+ (_a = onAttentionChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onAttentionChangeRef, {
1660
+ count: readFirstAttentionCount,
1661
+ faults: readFirstAttentionFaultCount,
1662
+ });
1663
+ }, [readFirstAttentionCount, readFirstAttentionFaultCount]);
1618
1664
  var getIntent = (0, react_2.useCallback)(
1619
1665
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1620
1666
  function (optName, type, optValue, _op) {
@@ -1717,6 +1763,31 @@ var FormEngineImpl = function (_a) {
1717
1763
  // field update or an in-place schema reload will NOT re-grab focus; only a
1718
1764
  // genuine remount (a fresh instance) auto-focuses again, which is the intended
1719
1765
  // on-mount behaviour.
1766
+ // What the "first field to fix" scans read: the opener on arrival below and the
1767
+ // caret move on a submit attempt (`focusAttentionRequest`) pick the same field.
1768
+ var getAttentionFieldMeta = (0, react_2.useCallback)(function (fieldName) {
1769
+ var schema = options === null || options === void 0 ? void 0 : options[fieldName];
1770
+ if (!schema) {
1771
+ return undefined;
1772
+ }
1773
+ return {
1774
+ focusable: !readOnly &&
1775
+ !schema.disabled &&
1776
+ !schema.readonly &&
1777
+ !dependencyLockedNames.includes(fieldName),
1778
+ // Single source of truth: the same bucket the read-first status boxes
1779
+ // show, so a filled-but-invalid required row is a target too.
1780
+ needsAttention: getOptionBucket(fieldName) === 'attention',
1781
+ };
1782
+ }, [options, readOnly, dependencyLockedNames, getOptionBucket]);
1783
+ // Opening a row by name: `expandMode: 'single'` replaces only what a click could
1784
+ // (see the note in the opener below), never a row the host named.
1785
+ var openOption = (0, react_2.useCallback)(function (target) {
1786
+ return setExpandedOptions(function (prev) {
1787
+ return prev.includes(target) ? prev
1788
+ : expandMode === 'multi' ? __spreadArray(__spreadArray([], prev, true), [target], false) : __spreadArray(__spreadArray([], prev.filter(function (name) { return initialExpandedOptions === null || initialExpandedOptions === void 0 ? void 0 : initialExpandedOptions.includes(name); }), true), [target], false);
1789
+ });
1790
+ }, [expandMode, initialExpandedOptions]);
1720
1791
  var hasAutoFocusedRef = (0, react_2.useRef)(false);
1721
1792
  (0, react_2.useEffect)(function () {
1722
1793
  // Two decisions, one scan. Both open the row that needs attention;
@@ -1752,37 +1823,19 @@ var FormEngineImpl = function (_a) {
1752
1823
  if (wantsFocus && active && active !== document.body) {
1753
1824
  return;
1754
1825
  }
1755
- var target = (0, readFirst_1.getFirstAttentionOptionName)(orderedNames, function (fieldName) {
1756
- var schema = options[fieldName];
1757
- if (!schema) {
1758
- return undefined;
1759
- }
1760
- return {
1761
- focusable: !readOnly &&
1762
- !schema.disabled &&
1763
- !schema.readonly &&
1764
- !dependencyLockedNames.includes(fieldName),
1765
- // Single source of truth: the same bucket the read-first status boxes
1766
- // show, so a filled-but-invalid required row is a target too.
1767
- needsAttention: getOptionBucket(fieldName) === 'attention',
1768
- };
1769
- });
1826
+ var target = (0, readFirst_1.getFirstAttentionOptionName)(orderedNames, getAttentionFieldMeta);
1770
1827
  // Mark done even when nothing needs attention, so later value edits or an
1771
1828
  // in-place schema reload never re-scan or re-focus. Only a remount arms it
1772
1829
  // again.
1773
1830
  hasAutoFocusedRef.current = true;
1774
1831
  if (target) {
1775
- setExpandedOptions(function (prev) {
1776
- return prev.includes(target) ? prev
1777
- : expandMode === 'multi' ? __spreadArray(__spreadArray([], prev, true), [target], false)
1778
- // `expandMode: 'single'` is a rule about what a CLICK does: opening a
1779
- // row closes the one the reader last opened. It is not a licence to
1780
- // close a row the HOST named through `initialExpandedOptions`. That
1781
- // is an address — a statement about what the page is FOR, made before
1782
- // the reader did anything — and this scan is a convenience layered on
1783
- // top of it. Keep the named rows; replace only what a click could.
1784
- : __spreadArray(__spreadArray([], prev.filter(function (name) { return initialExpandedOptions === null || initialExpandedOptions === void 0 ? void 0 : initialExpandedOptions.includes(name); }), true), [target], false);
1785
- });
1832
+ // `expandMode: 'single'` is a rule about what a CLICK does: opening a row
1833
+ // closes the one the reader last opened. It is not a licence to close a row
1834
+ // the HOST named through `initialExpandedOptions`. That is an address — a
1835
+ // statement about what the page is FOR, made before the reader did anything
1836
+ // — and this scan is a convenience layered on top of it. `openOption` keeps
1837
+ // the named rows and replaces only what a click could.
1838
+ openOption(target);
1786
1839
  }
1787
1840
  }, [
1788
1841
  autoFocusFirstRequired,
@@ -1790,12 +1843,48 @@ var FormEngineImpl = function (_a) {
1790
1843
  compact,
1791
1844
  options,
1792
1845
  availableOptions,
1793
- readOnly,
1794
- dependencyLockedNames,
1795
- getOptionBucket,
1796
- expandMode,
1797
- initialExpandedOptions,
1846
+ getAttentionFieldMeta,
1847
+ openOption,
1798
1848
  ]);
1849
+ // A submit that could not go is answered with where to type: each new
1850
+ // `focusAttentionRequest` opens the first field that needs attention and puts the
1851
+ // caret in it. The host's submit button holds the caret at that moment, and an open
1852
+ // row never takes a caret held outside it (CompactRow), so the button lets go of it
1853
+ // here first; the person asked to submit, and this is the answer to that.
1854
+ var lastFocusRequest = (0, react_2.useRef)(focusAttentionRequest);
1855
+ (0, react_2.useEffect)(function () {
1856
+ var _a;
1857
+ if (focusAttentionRequest === lastFocusRequest.current) {
1858
+ return;
1859
+ }
1860
+ lastFocusRequest.current = focusAttentionRequest;
1861
+ if (!focusAttentionRequest || !compact || !options) {
1862
+ return;
1863
+ }
1864
+ var target = (0, readFirst_1.getFirstAttentionOptionName)(Object.keys(availableOptions), getAttentionFieldMeta);
1865
+ if (!target) {
1866
+ return;
1867
+ }
1868
+ var wrap = compactWrapNodeRef.current;
1869
+ var active = document.activeElement;
1870
+ if (active && active !== document.body && !(wrap === null || wrap === void 0 ? void 0 : wrap.contains(active))) {
1871
+ active.blur();
1872
+ }
1873
+ if (!expandedOptions.includes(target)) {
1874
+ // The row's own open effect reveals it and takes the caret.
1875
+ openOption(target);
1876
+ return;
1877
+ }
1878
+ // Already open (the field the form opened on arrival): its open effect has run,
1879
+ // so the caret goes to its control here.
1880
+ var row = wrap === null || wrap === void 0 ? void 0 : wrap.querySelector("[data-field=\"".concat(target, "\"]"));
1881
+ if (row) {
1882
+ (0, revealRow_1.revealRow)(row, 'auto');
1883
+ (_a = (0, rowFocus_1.findRowFocusTarget)(row.querySelector('.options-readfirst-row-editor'), {
1884
+ textEntryOnly: row.classList.contains('options-readfirst-card'),
1885
+ })) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
1886
+ }
1887
+ }, [focusAttentionRequest]);
1799
1888
  // Read-first completion summary (how many shown options have a value set),
1800
1889
  // surfaced as a progress meter at the top of the compact form.
1801
1890
  var readFirstCompletion = (0, react_2.useMemo)(function () {
@@ -2042,7 +2131,10 @@ var FormEngineImpl = function (_a) {
2042
2131
  readOnly ||
2043
2132
  !(0, validations_1.hasAllDependenciesFullfilled)((_v = options === null || options === void 0 ? void 0 : options[optionName]) === null || _v === void 0 ? void 0 : _v.depends_on, availableOptions, options || {}), readOnly: readOnly, size: editorSize || rest.size, menuItems: (0, typeChoices_1.offersTypeChoices)(options === null || options === void 0 ? void 0 : options[optionName], anyLikeUiTypes) ?
2044
2133
  getCustomMenuTemplateItems(optionName)
2045
- : undefined }, templateFieldProps, { forceDropdown: effectiveForceDropdown })), (0, jsx_runtime_1.jsx)(OptionFieldMessages_1.OptionFieldMessages, { schema: options || {}, allOptions: availableOptions, name: optionName, option: __assign({ type: resolvedType }, other), getType: getTypeForOption, isRendererOnly: isRendererOnly }), operators && (0, size_1.default)(operators) && (0, size_1.default)(other.op) ?
2134
+ : undefined }, templateFieldProps, { forceDropdown: effectiveForceDropdown })), (0, jsx_runtime_1.jsx)(OptionFieldMessages_1.OptionFieldMessages, { schema: options || {}, allOptions: availableOptions, name: optionName, option: __assign({ type: resolvedType }, other), getType: getTypeForOption, isRendererOnly: isRendererOnly,
2135
+ // Open is not left: a field the form opened for typing (the first empty
2136
+ // one, on a new form) says what it needs without already being wrong.
2137
+ requirementPending: !(revealRequired || visitedOptions.includes(optionName)) }), operators && (0, size_1.default)(operators) && (0, size_1.default)(other.op) ?
2046
2138
  (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreVerticalSpacer, { height: 5 }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { size: 'small', children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreTagGroup, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', labelKey: 'WHERE', label: optionName }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', labelKey: 'IS', label: operatorParts.join(' ') }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', intent: 'info', label: other.value ?
2047
2139
  resolvedType === 'richtext' ?
2048
2140
  (0, common_1.richtextToString)(other.value)
@@ -2074,6 +2166,8 @@ var FormEngineImpl = function (_a) {
2074
2166
  getTypeForOption,
2075
2167
  inheritedScopes,
2076
2168
  inheritedFromParent,
2169
+ revealRequired,
2170
+ visitedOptions,
2077
2171
  ]);
2078
2172
  // Compact (read-first) rendering.
2079
2173
  // Theme-derived colours so the flat-row layout adapts to light/dark/custom themes.
@@ -2096,6 +2190,10 @@ var FormEngineImpl = function (_a) {
2096
2190
  // The "N more fields" row's dashed edge. Well above the divider tint: this
2097
2191
  // one is an affordance the reader has to notice, not a hairline between rows.
2098
2192
  var cMoreBorder = "".concat(cText, "4d");
2193
+ // Calm: the section surface and its hairline, from the theme's panel (the
2194
+ // same surface and edge Reqore gives the section panels themselves).
2195
+ var cPanel = (0, formAppearance_1.getCalmPanelSurface)(theme);
2196
+ var cHairline = (0, formAppearance_1.getCalmPanelHairline)(theme);
2099
2197
  // The closure surface the extracted CompactRow reads through context. Refs and
2100
2198
  // setters are stable; the state/memo/handler fields change identity as they do
2101
2199
  // today, so a row re-renders exactly when its inputs do.
@@ -2112,6 +2210,8 @@ var FormEngineImpl = function (_a) {
2112
2210
  codePreviewRenderer: codePreviewRenderer,
2113
2211
  showAllDescriptions: showAllDescriptions,
2114
2212
  expandedOptions: expandedOptions,
2213
+ visitedOptions: visitedOptions,
2214
+ revealRequired: revealRequired,
2115
2215
  highlightedOptions: highlightedOptions,
2116
2216
  flashedOptions: flashedOptions,
2117
2217
  infoPanelOverrides: infoPanelOverrides,
@@ -2159,6 +2259,8 @@ var FormEngineImpl = function (_a) {
2159
2259
  codePreviewRenderer,
2160
2260
  showAllDescriptions,
2161
2261
  expandedOptions,
2262
+ visitedOptions,
2263
+ revealRequired,
2162
2264
  highlightedOptions,
2163
2265
  flashedOptions,
2164
2266
  infoPanelOverrides,
@@ -2207,6 +2309,7 @@ var FormEngineImpl = function (_a) {
2207
2309
  readOnly: readOnly,
2208
2310
  invalidCount: (0, size_1.default)(validityData.invalidFields),
2209
2311
  attentionCount: readFirstAttentionCount,
2312
+ attentionFaultCount: readFirstAttentionFaultCount,
2210
2313
  completion: readFirstCompletion,
2211
2314
  showInvalidOnly: showInvalidOptionsOnly,
2212
2315
  onToggleInvalidOnly: handleToggleInvalidOnly,
@@ -2253,6 +2356,7 @@ var FormEngineImpl = function (_a) {
2253
2356
  onReadOnlyActivate,
2254
2357
  validityData,
2255
2358
  readFirstAttentionCount,
2359
+ readFirstAttentionFaultCount,
2256
2360
  readFirstCompletion,
2257
2361
  showInvalidOptionsOnly,
2258
2362
  handleToggleInvalidOnly,
@@ -2282,7 +2386,7 @@ var FormEngineImpl = function (_a) {
2282
2386
  // removes it, and then the header carries just the consumer's own actions.
2283
2387
  var compactHeaderActions = (0, react_2.useMemo)(function () { return __spreadArray(__spreadArray([], (compactToolbarParts ? [{ as: CompactToolbar_1.CompactToolbar, responsive: false }] : []), true), ((compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions) || []), true); }, [compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions, compactToolbarParts]);
2284
2388
  var renderCompact = function () {
2285
- var _a, _b, _c, _d;
2389
+ var _a, _b, _c, _d, _f;
2286
2390
  var headerBg = "".concat((0, colors_1.changeDarkness)((0, colors_1.getMainBackgroundColor)(theme), 0.02)).concat((0, colors_1.percentToHexAlpha)(88));
2287
2391
  // Toolbar filters narrow the listed rows; the meter reflects the full set.
2288
2392
  var query = compactQuery.trim().toLowerCase();
@@ -2512,16 +2616,24 @@ var FormEngineImpl = function (_a) {
2512
2616
  var stickyBoxHeaders = compactStickyBoxHeaders && !compactNested;
2513
2617
  var boxStickyOffset = compactStickyOffset + compactToolbarHeight;
2514
2618
  var STATUS_BOXES = [
2515
- {
2516
- key: 'attention',
2517
- label: (_a = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.attention) !== null && _a !== void 0 ? _a : 'Needs attention',
2518
- intent: 'warning',
2519
- icon: 'ErrorWarningLine',
2520
- },
2521
- { key: 'set', label: (_b = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.set) !== null && _b !== void 0 ? _b : 'Set', intent: 'success', icon: 'CheckLine' },
2619
+ // The first box is amber only once something in it is a fault. On a new form it
2620
+ // holds the required fields still to fill in, which is not yet anything wrong.
2621
+ readFirstAttentionFaultCount ?
2622
+ {
2623
+ key: 'attention',
2624
+ label: (_a = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.attention) !== null && _a !== void 0 ? _a : 'Needs attention',
2625
+ intent: 'warning',
2626
+ icon: 'ErrorWarningLine',
2627
+ }
2628
+ : {
2629
+ key: 'attention',
2630
+ label: (_b = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.pending) !== null && _b !== void 0 ? _b : 'To fill in',
2631
+ icon: 'CheckboxBlankCircleLine',
2632
+ },
2633
+ { key: 'set', label: (_c = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.set) !== null && _c !== void 0 ? _c : 'Set', intent: 'success', icon: 'CheckLine' },
2522
2634
  {
2523
2635
  key: 'optional',
2524
- label: (_c = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.optional) !== null && _c !== void 0 ? _c : 'Optional',
2636
+ label: (_d = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.optional) !== null && _d !== void 0 ? _d : 'Optional',
2525
2637
  icon: 'CheckboxBlankCircleLine',
2526
2638
  },
2527
2639
  ];
@@ -2571,7 +2683,10 @@ var FormEngineImpl = function (_a) {
2571
2683
  // "Covers"/"Covered by" chips already say which member satisfies it.
2572
2684
  if (requiredGroupsInfo.satisfiedBy[grp])
2573
2685
  return railed;
2574
- return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterBox, { className: 'options-readfirst-required-cluster', "$border": "".concat(cWarning, "33"), "$tint": "".concat(cWarning, "0d"), children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterHeader, { "$color": cWarning, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'LinkM', size: '11px', style: { color: cWarning } }), "One of the below is required"] }), railed] }, grp));
2686
+ // Amber once someone has been to the group (or a submit was attempted); until
2687
+ // then it is still to fill in, in the quiet colour, like its members.
2688
+ var clusterColor = memberEntries.some(function (e) { return getOptionStatus(e.name) !== 'pending'; }) ? cWarning : cMuted;
2689
+ return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterBox, { className: 'options-readfirst-required-cluster', "$border": "".concat(clusterColor, "33"), "$tint": "".concat(clusterColor, "0d"), "$calm": calm, children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterHeader, { className: 'options-readfirst-required-cluster-header', "$color": clusterColor, "$calm": calm, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'LinkM', size: calm ? '13px' : '11px', style: { color: clusterColor } }), "One of the below is required"] }), railed] }, grp));
2575
2690
  });
2576
2691
  };
2577
2692
  // One schema group inside a status box: its thin sub-label, the group's
@@ -2590,14 +2705,18 @@ var FormEngineImpl = function (_a) {
2590
2705
  return null;
2591
2706
  }
2592
2707
  return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [showGroupSubLabel(groupName) ?
2593
- (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBoxGroupLabel, { children: (0, readFirst_1.getOptionGroupLabel)(groupName, groups) })
2708
+ (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBoxGroupLabel, { className: 'options-readfirst-group-label', "$calm": calm, "$color": cKey, children: (0, readFirst_1.getOptionGroupLabel)(groupName, groups) })
2594
2709
  : null, showGroupSubLabel(groupName) && (groupConfig === null || groupConfig === void 0 ? void 0 : groupConfig.subtitle) ?
2595
- (0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { size: 'small', effect: { opacity: 0.6 }, style: {
2596
- marginTop: 2,
2597
- marginBottom: 8,
2598
- marginLeft: compactRowStyles_1.GROUP_INDENT,
2599
- paddingRight: 10,
2600
- }, children: groupConfig.subtitle })
2710
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { className: 'options-readfirst-group-subtitle', size: 'small', effect: { opacity: 0.6 }, style: calm ?
2711
+ // Under the calm heading, at the rows' inset; the space below
2712
+ // it is the next row's own padding.
2713
+ { margin: 0, padding: "2px ".concat(compactRowStyles_1.CALM_SECTION_INSET, "px 4px") }
2714
+ : {
2715
+ marginTop: 2,
2716
+ marginBottom: 8,
2717
+ marginLeft: compactRowStyles_1.GROUP_INDENT,
2718
+ paddingRight: 10,
2719
+ }, children: groupConfig.subtitle })
2601
2720
  : null, renderGroupRows(rows)] }, groupName));
2602
2721
  };
2603
2722
  return ((0, jsx_runtime_1.jsx)(optionsContext_1.OptionsContext.Provider, { value: { schema: options, value: availableOptions }, children: (0, jsx_runtime_1.jsx)(compactRowContext_1.CompactRowContext.Provider, { value: compactRowContextValue, children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreErrorBoundary, { children: [showHelpForOption && ((0, jsx_runtime_1.jsx)(OptionsHelpDialog_1.OptionsHelpDialog, { onClose: function () { return setShowHelpForOption(undefined); }, option: options[showHelpForOption] })), (0, jsx_runtime_1.jsx)(compactToolbarContext_1.CompactToolbarContext.Provider, { value: compactToolbarContextValue, children: (0, jsx_runtime_1.jsxs)(StyledCompactWrap, { ref: setCompactWrap, className: 'options-readfirst-scroll', "$ownScroll": compactScroll === 'own' && !compactNested, children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledCompactPanel
@@ -2607,7 +2726,14 @@ var FormEngineImpl = function (_a) {
2607
2726
  , __assign({ "$tightHeader": !((compactToolbarParts === null || compactToolbarParts === void 0 ? void 0 : compactToolbarParts.search) && (0, size_1.default)(options) > 1), "$headerBg": compactNested ? 'transparent' : headerBg, "$nested": compactNested, "$stickyBoxes": compactStickyBoxHeaders && !compactNested, "$stackHeader": compactNarrow &&
2608
2727
  !!((compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.label) ||
2609
2728
  (compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.icon) ||
2610
- ((_d = compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions) === null || _d === void 0 ? void 0 : _d.length)), flat: true, raised: true, minimal: true,
2729
+ ((_f = compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions) === null || _f === void 0 ? void 0 : _f.length)), flat: true,
2730
+ // Calm: no surface and no lift at all. A theme that gives
2731
+ // panels a surface of their own (Reqore's `theme.panel`) would
2732
+ // otherwise paint this wrapper as a card around the section
2733
+ // cards inside it. Transparent and un-raised, Reqore also drops
2734
+ // the wrapper's horizontal padding, so the readiness line, the
2735
+ // search and the sections share one left edge with the host.
2736
+ raised: !calm, minimal: true, transparent: calm || undefined,
2611
2737
  // No panel background: the form sits transparently on whatever
2612
2738
  // hosts it (page, drawer, or — for an arg_schema field — the
2613
2739
  // parent's edit card) instead of stacking its own dark surface.
@@ -2661,7 +2787,7 @@ var FormEngineImpl = function (_a) {
2661
2787
  : 'No fields match the current filters.' })
2662
2788
  : null, readOnly ?
2663
2789
  bucketCount('set') ?
2664
- (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-read', style: { padding: '4px 4px 6px' }, children: (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledGroupBody, { "$divider": cDivider, "$hover": cHover, "$focus": cWarning, "$success": cSuccess, "$rowBg": cRowBg, "$lineColor": cGroupLine, "$moreBorder": cMoreBorder, className: compactNarrow ? 'readfirst-narrow' : undefined, children: bucketGroups.set.map(function (groupName) { return renderBoxGroup('set', groupName); }) }) })
2790
+ (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-read', style: { padding: calm ? 0 : '4px 4px 6px' }, children: (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledGroupBody, { "$calm": calm, "$hairline": cHairline, "$divider": cDivider, "$hover": cHover, "$focus": cWarning, "$success": cSuccess, "$rowBg": cRowBg, "$lineColor": cGroupLine, "$moreBorder": cMoreBorder, className: "readfirst-read-list".concat(compactNarrow ? ' readfirst-narrow' : ''), children: bucketGroups.set.map(function (groupName) { return renderBoxGroup('set', groupName); }) }) })
2665
2791
  : null
2666
2792
  : STATUS_BOXES.map(function (box) {
2667
2793
  var groupsInBox = bucketGroups[box.key];
@@ -2682,6 +2808,12 @@ var FormEngineImpl = function (_a) {
2682
2808
  // Group order is preserved so the visible rows read in the
2683
2809
  // same order they would if nothing were folded.
2684
2810
  var orderedRows = groupsInBox.flatMap(function (groupName) { return buckets[box.key][groupName] || []; });
2811
+ // The number in the box's header counts the rows whose value
2812
+ // belongs in it NOW. A field being edited keeps its box until it
2813
+ // is left (so it does not jump away under the caret), and it used
2814
+ // to keep its count too: a box read "To fill in 1" while its last
2815
+ // field already had a value and the host's submit read ready.
2816
+ var headerCount = readOnly ? count : (orderedRows.filter(function (entry) { return getOptionBucket(entry.name, entry.hidden) === box.key; }).length);
2685
2817
  // Optional's own rule first: a box opened solely to reveal
2686
2818
  // preselected rows offers those, not an arbitrary first-N.
2687
2819
  var candidateRows = splitForPreselected ? orderedRows.filter(isPreselectedRow) : orderedRows;
@@ -2706,23 +2838,32 @@ var FormEngineImpl = function (_a) {
2706
2838
  return (buckets[box.key][groupName] || []).some(function (entry) { return !shownRowSet.has(entry.name); });
2707
2839
  });
2708
2840
  var moreOpen = Boolean(query) || expandedMoreBoxes.includes(box.key);
2709
- var accent = box.key === 'attention' ? cWarning
2841
+ var accent = box.key === 'attention' && readFirstAttentionFaultCount ? cWarning
2710
2842
  : box.key === 'set' ? cSuccess
2711
2843
  : cMuted;
2712
2844
  // The muted "Optional" box reads as a quieter, recessed
2713
2845
  // surface — a touch darker than the page rather than the
2714
2846
  // faint grey tint the accent would give.
2715
- var boxBg = box.key === 'optional' ?
2847
+ // Calm: every box is the same panel — no recessed one.
2848
+ var boxBg = box.key === 'optional' && !calm ?
2716
2849
  (0, colors_1.changeDarkness)((0, colors_1.getMainBackgroundColor)(theme), 0.06)
2717
2850
  : undefined;
2718
- return ((0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBox, { "$accent": accent, "$bg": boxBg, "$surface": stickyBoxHeaders ? (0, colors_1.getMainBackgroundColor)(theme) : undefined, ref: function (node) {
2851
+ return ((0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBox, { "$accent": accent, "$bg": boxBg, "$calm": calm, "$surface": stickyBoxHeaders ?
2852
+ calm ? cPanel
2853
+ : (0, colors_1.getMainBackgroundColor)(theme)
2854
+ : undefined, ref: function (node) {
2719
2855
  statusBoxRefs.current[box.key] = node;
2720
2856
  },
2721
2857
  // Opening arms the reveal; collapsing disarms it, so a
2722
2858
  // close never scrolls.
2723
2859
  onCollapseChange: function (collapsed) {
2724
2860
  return setOpenedStatusBox(collapsed ? undefined : box.key);
2725
- }, flat: true, minimal: true,
2861
+ },
2862
+ // Calm: an ordinary panel — Reqore paints the theme's
2863
+ // panel surface and its hairline edge. The header stays
2864
+ // minimal (no surface or rule of its own); the first
2865
+ // row's hairline is the line under it.
2866
+ flat: !calm, minimal: true,
2726
2867
  /* The header stays on screen while its own box is
2727
2868
  being read — see `compactStickyBoxHeaders`. Sticky
2728
2869
  is bounded by its containing block, so the header
@@ -2754,7 +2895,17 @@ var FormEngineImpl = function (_a) {
2754
2895
  // the box reveals the preselected fields without also
2755
2896
  // dumping every not-yet-added optional field on the
2756
2897
  // author.
2757
- isCollapsed: wouldCollapse && !hasPreselectedRows, label: (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupHeader, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { effect: { weight: 'bold' }, size: 'normal', children: box.label }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', minimal: true, compact: true, intent: box.intent, label: String(count) })] }), icon: box.icon, className: 'options-readfirst-group', padded: false, contentStyle: { padding: '4px 4px 6px' }, children: (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupBody, { "$divider": cDivider, "$hover": cHover, "$focus": cWarning, "$success": cSuccess, "$rowBg": cRowBg, "$lineColor": cGroupLine, "$moreBorder": cMoreBorder, className: compactNarrow ? 'readfirst-narrow' : undefined, children: [shownGroups.map(function (groupName) {
2898
+ isCollapsed: wouldCollapse && !hasPreselectedRows, label: calm ?
2899
+ // One status dot and a word — and only where a
2900
+ // person is needed. The count is a quiet number.
2901
+ (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupHeader, { "$calm": true, children: [box.key === 'attention' && readFirstAttentionFaultCount ?
2902
+ (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusDot, { className: 'options-readfirst-group-dot', "$color": cWarning, "aria-hidden": true })
2903
+ : null, (0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { effect: { weight: 'bold' }, size: 'normal', children: box.label }), headerCount ?
2904
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreSpan, { className: 'options-readfirst-group-count', size: 'small', effect: { opacity: 0.65 }, children: headerCount })
2905
+ : null] })
2906
+ : (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupHeader, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { effect: { weight: 'bold' }, size: 'normal', children: box.label }), headerCount ?
2907
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', minimal: true, compact: true, intent: box.intent, label: String(headerCount) })
2908
+ : null] }), icon: calm ? undefined : box.icon, className: 'options-readfirst-group', padded: false, contentStyle: { padding: calm ? 0 : '4px 4px 6px' }, children: (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupBody, { "$calm": calm, "$hairline": cHairline, "$divider": cDivider, "$hover": cHover, "$focus": cWarning, "$success": cSuccess, "$rowBg": cRowBg, "$lineColor": cGroupLine, "$moreBorder": cMoreBorder, className: compactNarrow ? 'readfirst-narrow' : undefined, children: [shownGroups.map(function (groupName) {
2758
2909
  return renderBoxGroup(box.key, groupName, shownRowSet);
2759
2910
  }), deferredCount ?
2760
2911
  (0, jsx_runtime_1.jsxs)("button", { type: 'button', className: 'readfirst-row readfirst-more-row options-readfirst-more', "aria-expanded": moreOpen, onClick: function () {
@@ -2819,7 +2970,7 @@ var FormEngineImpl = function (_a) {
2819
2970
  : null, children, (0, size_1.default)(filteredOptions) >= 1 && !readOnly ?
2820
2971
  (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreVerticalSpacer, { height: 10 }), (0, jsx_runtime_1.jsx)(Select_1.SelectFormField, { items: optionalFields, onChange: function (val) { return handleAddOptionalFieldChange('options', val); }, placeholder: placeholder || 'More Options Available', minimal: true, icon: 'ListView', showDescription: false, fluid: true, size: rest.size })] })
2821
2972
  : null] })); }, sortButtonProps: { minimal: true }, showLayoutSwitch: false, style: { width: '100%' }, items: (0, map_1.default)(shownOptions, function (_a, optionName) {
2822
- var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
2973
+ var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
2823
2974
  var type = _a.type, other = __rest(_a, ["type"]);
2824
2975
  return ({
2825
2976
  label: ((_b = options[optionName]) === null || _b === void 0 ? void 0 : _b.display_name) || optionName,
@@ -2835,20 +2986,22 @@ var FormEngineImpl = function (_a) {
2835
2986
  cursor: 'help',
2836
2987
  }
2837
2988
  : undefined,
2838
- onClick: ((_f = options[optionName]) === null || _f === void 0 ? void 0 : _f.desc) ? function () { return handleOptionLabelClick(optionName); } : undefined,
2989
+ onClick: (0, fieldDescription_1.fieldHasLongDescription)(options[optionName]) ?
2990
+ function () { return handleOptionLabelClick(optionName); }
2991
+ : undefined,
2839
2992
  },
2840
- showLabelTooltip: !!((_g = options[optionName]) === null || _g === void 0 ? void 0 : _g.short_desc),
2993
+ showLabelTooltip: !!((_f = options[optionName]) === null || _f === void 0 ? void 0 : _f.short_desc),
2841
2994
  customLabelTooltip: {
2842
2995
  delay: 300,
2843
- content: ((0, jsx_runtime_1.jsx)(Description_1.Description, { longDescription: "".concat((_h = options[optionName]) === null || _h === void 0 ? void 0 : _h.short_desc).concat(((_j = options[optionName]) === null || _j === void 0 ? void 0 : _j.desc) ? '. Click to learn more.' : ''), margin: 'none' })),
2996
+ content: ((0, jsx_runtime_1.jsx)(Description_1.Description, { longDescription: "".concat((_g = options[optionName]) === null || _g === void 0 ? void 0 : _g.short_desc).concat((0, fieldDescription_1.fieldHasLongDescription)(options[optionName]) ? '. Click to learn more.' : ''), margin: 'none' })),
2844
2997
  },
2845
2998
  description: showFieldTypes ?
2846
- "<".concat(options[optionName].ui_type || options[optionName].type).concat(((_k = options[optionName]) === null || _k === void 0 ? void 0 : _k.ui_element_type) ? "[".concat(options[optionName].ui_element_type, "]") : '', "> ").concat(options[optionName].short_desc || '')
2999
+ "<".concat(options[optionName].ui_type || options[optionName].type).concat(((_h = options[optionName]) === null || _h === void 0 ? void 0 : _h.ui_element_type) ? "[".concat(options[optionName].ui_element_type, "]") : '', "> ").concat(options[optionName].short_desc || '')
2847
3000
  : options[optionName].short_desc || '',
2848
3001
  descriptionEffect: {
2849
3002
  textSize: '11px',
2850
3003
  opacity: 0.3,
2851
- underline: ((_l = options[optionName]) === null || _l === void 0 ? void 0 : _l.desc) ? 'underline dotted #878787' : undefined,
3004
+ underline: (0, fieldDescription_1.fieldHasLongDescription)(options[optionName]) ? 'underline dotted #878787' : undefined,
2852
3005
  },
2853
3006
  customTheme: {
2854
3007
  main: 'main:darken:1',
@@ -2885,7 +3038,7 @@ var FormEngineImpl = function (_a) {
2885
3038
  menu: [
2886
3039
  !readOnly &&
2887
3040
  type !== 'code-editor' &&
2888
- (((_m = options[optionName]) === null || _m === void 0 ? void 0 : _m.ui_type) || ((_o = options[optionName]) === null || _o === void 0 ? void 0 : _o.type)) !==
3041
+ (((_j = options[optionName]) === null || _j === void 0 ? void 0 : _j.ui_type) || ((_k = options[optionName]) === null || _k === void 0 ? void 0 : _k.type)) !==
2889
3042
  'code-editor' && {
2890
3043
  label: 'Focused editing',
2891
3044
  icon: 'FullscreenLine',
@@ -2905,15 +3058,15 @@ var FormEngineImpl = function (_a) {
2905
3058
  !readOnly &&
2906
3059
  other.value &&
2907
3060
  !(0, lodash_1.isEqual)(other.value, (0, common_1.getDefaultValue)(options[optionName])) &&
2908
- !(((_p = options[optionName]) === null || _p === void 0 ? void 0 : _p.disabled) || ((_q = options[optionName]) === null || _q === void 0 ? void 0 : _q.readonly)) && {
3061
+ !(((_l = options[optionName]) === null || _l === void 0 ? void 0 : _l.disabled) || ((_m = options[optionName]) === null || _m === void 0 ? void 0 : _m.readonly)) && {
2909
3062
  label: 'Remove value',
2910
3063
  icon: 'CloseLine',
2911
3064
  className: 'options-item-remove',
2912
3065
  onClick: function () { return handleValueChange(optionName, undefined); },
2913
3066
  },
2914
3067
  !readOnly &&
2915
- !((_r = options[optionName]) === null || _r === void 0 ? void 0 : _r.preselected) &&
2916
- !((_s = options[optionName]) === null || _s === void 0 ? void 0 : _s.required) && {
3068
+ !((_o = options[optionName]) === null || _o === void 0 ? void 0 : _o.preselected) &&
3069
+ !((_p = options[optionName]) === null || _p === void 0 ? void 0 : _p.required) && {
2917
3070
  label: 'Remove option',
2918
3071
  icon: 'DeleteBinLine',
2919
3072
  intent: 'danger',
@@ -2929,8 +3082,8 @@ var FormEngineImpl = function (_a) {
2929
3082
  },
2930
3083
  ],
2931
3084
  }),
2932
- content: ((0, jsx_runtime_1.jsxs)(FocusedEditing_1.FocusedEditing, { isFullscreen: focusedEditing === optionName, onClose: function () { return setFocusedEditing(undefined); }, description: (_t = options[optionName]) === null || _t === void 0 ? void 0 : _t.display_name, intent: getIntent(optionName, type, other.value, other.op), children: [focusedEditing === optionName ?
2933
- (0, jsx_runtime_1.jsx)(Description_1.Description, { longDescription: (_u = options[optionName]) === null || _u === void 0 ? void 0 : _u.desc, shortDescription: (_v = options[optionName]) === null || _v === void 0 ? void 0 : _v.short_desc, longDescriptionShownByDefault: true })
3085
+ content: ((0, jsx_runtime_1.jsxs)(FocusedEditing_1.FocusedEditing, { isFullscreen: focusedEditing === optionName, onClose: function () { return setFocusedEditing(undefined); }, description: (_q = options[optionName]) === null || _q === void 0 ? void 0 : _q.display_name, intent: getIntent(optionName, type, other.value, other.op), children: [focusedEditing === optionName ?
3086
+ (0, jsx_runtime_1.jsx)(Description_1.Description, { longDescription: (_r = options[optionName]) === null || _r === void 0 ? void 0 : _r.desc, shortDescription: (_s = options[optionName]) === null || _s === void 0 ? void 0 : _s.short_desc, longDescriptionShownByDefault: true })
2934
3087
  : null, renderOption(optionName, __assign({ type: type }, other))] })),
2935
3088
  });
2936
3089
  }), defaultZoom: 1, zoomable: false, actions: __spreadArray(__spreadArray([], (rest.actions || []).map(function (action) { return (__assign(__assign({}, action), { minimal: true })); }), true), [
@@ -2967,7 +3120,15 @@ var FormEngineImpl = function (_a) {
2967
3120
  * a child of the row it belongs to. Threading a renderer to each of them by
2968
3121
  * hand is how one of them gets missed.
2969
3122
  */
2970
- var FormEngine = function (props) { return ((0, jsx_runtime_1.jsx)(markdownRendererContext_1.MarkdownRendererContext.Provider, { value: props.markdownRenderer, children: (0, jsx_runtime_1.jsx)(FormEngineImpl, __assign({}, props)) })); };
3123
+ var FormEngine = function (props) {
3124
+ var _a;
3125
+ // The form's own `appearance` wins; without one it follows the form (or the
3126
+ // host's provider) it sits in, so a nested sub-form never changes look
3127
+ // halfway down its parent.
3128
+ var inherited = (0, formAppearance_1.useFormAppearance)();
3129
+ var appearance = (_a = props.appearance) !== null && _a !== void 0 ? _a : inherited;
3130
+ return ((0, jsx_runtime_1.jsx)(markdownRendererContext_1.MarkdownRendererContext.Provider, { value: props.markdownRenderer, children: (0, jsx_runtime_1.jsx)(formAppearance_1.FormAppearanceProvider, { value: appearance, children: (0, jsx_runtime_1.jsx)(FormEngineImpl, __assign({}, props)) }) }));
3131
+ };
2971
3132
  exports.FormEngine = FormEngine;
2972
3133
  exports.default = exports.FormEngine;
2973
3134
  var templateObject_1, templateObject_2, templateObject_3, templateObject_4;