@qoretechnologies/reqraft 0.10.45-pr.95.gc02205d → 0.10.45

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 (144) hide show
  1. package/.claude/CLAUDE.md +12 -0
  2. package/.tasks/INDEX.md +1 -0
  3. package/.tasks/TEMPLATE_TOKEN_GRAMMAR.md +72 -0
  4. package/dist/components/composer/Composer.d.ts.map +1 -1
  5. package/dist/components/composer/Composer.js +5 -1
  6. package/dist/components/composer/Composer.js.map +1 -1
  7. package/dist/components/form/engine/CompactRow.d.ts +20 -1
  8. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  9. package/dist/components/form/engine/CompactRow.js +279 -41
  10. package/dist/components/form/engine/CompactRow.js.map +1 -1
  11. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  12. package/dist/components/form/engine/CompactToolbar.js +72 -72
  13. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  14. package/dist/components/form/engine/FormEngine.d.ts +48 -1
  15. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  16. package/dist/components/form/engine/FormEngine.js +203 -98
  17. package/dist/components/form/engine/FormEngine.js.map +1 -1
  18. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
  19. package/dist/components/form/engine/_structuredData/SchemaDataView.js +55 -13
  20. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
  21. package/dist/components/form/engine/_structuredData/structuredData.d.ts +15 -0
  22. package/dist/components/form/engine/_structuredData/structuredData.d.ts.map +1 -1
  23. package/dist/components/form/engine/_structuredData/structuredData.js +22 -1
  24. package/dist/components/form/engine/_structuredData/structuredData.js.map +1 -1
  25. package/dist/components/form/engine/compactRowStyles.d.ts +2 -0
  26. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  27. package/dist/components/form/engine/compactRowStyles.js +21 -4
  28. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  29. package/dist/components/form/engine/compactToolbarContext.d.ts +8 -0
  30. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  31. package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
  32. package/dist/components/form/engine/readFirst.d.ts +24 -0
  33. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  34. package/dist/components/form/engine/readFirst.js +84 -6
  35. package/dist/components/form/engine/readFirst.js.map +1 -1
  36. package/dist/components/form/fields/Field.d.ts.map +1 -1
  37. package/dist/components/form/fields/Field.js +1 -1
  38. package/dist/components/form/fields/Field.js.map +1 -1
  39. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +12 -2
  40. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  41. package/dist/components/form/fields/allowed-values/AllowedValues.js +16 -6
  42. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  43. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  44. package/dist/components/form/fields/auto/AutoFormField.js +64 -14
  45. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  46. package/dist/components/form/fields/long-string/LongString.d.ts +9 -1
  47. package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
  48. package/dist/components/form/fields/long-string/LongString.js +25 -4
  49. package/dist/components/form/fields/long-string/LongString.js.map +1 -1
  50. package/dist/components/form/fields/template/ExampleValueModal.d.ts +29 -0
  51. package/dist/components/form/fields/template/ExampleValueModal.d.ts.map +1 -0
  52. package/dist/components/form/fields/template/ExampleValueModal.js +122 -0
  53. package/dist/components/form/fields/template/ExampleValueModal.js.map +1 -0
  54. package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
  55. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -3
  56. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
  57. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  58. package/dist/components/form/fields/template/TemplateField.js +35 -6
  59. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  60. package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts +2 -0
  61. package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts.map +1 -0
  62. package/dist/components/form/fields/template/__fixtures__/longExampleValue.js +9 -0
  63. package/dist/components/form/fields/template/__fixtures__/longExampleValue.js.map +1 -0
  64. package/dist/components/form/index.d.ts +1 -0
  65. package/dist/components/form/index.d.ts.map +1 -1
  66. package/dist/components/form/index.js +1 -0
  67. package/dist/components/form/index.js.map +1 -1
  68. package/dist/components/searchFilterBar/SearchFilterBar.d.ts +12 -1
  69. package/dist/components/searchFilterBar/SearchFilterBar.d.ts.map +1 -1
  70. package/dist/components/searchFilterBar/SearchFilterBar.js +2 -2
  71. package/dist/components/searchFilterBar/SearchFilterBar.js.map +1 -1
  72. package/dist/components/ticketThread/TicketThread.d.ts.map +1 -1
  73. package/dist/components/ticketThread/TicketThread.js +1 -1
  74. package/dist/components/ticketThread/TicketThread.js.map +1 -1
  75. package/dist/helpers/common.d.ts +8 -1
  76. package/dist/helpers/common.d.ts.map +1 -1
  77. package/dist/helpers/common.js +9 -1
  78. package/dist/helpers/common.js.map +1 -1
  79. package/dist/helpers/optionUiTypes.d.ts +30 -0
  80. package/dist/helpers/optionUiTypes.d.ts.map +1 -0
  81. package/dist/helpers/optionUiTypes.js +156 -0
  82. package/dist/helpers/optionUiTypes.js.map +1 -0
  83. package/dist/helpers/options.d.ts +19 -0
  84. package/dist/helpers/options.d.ts.map +1 -1
  85. package/dist/helpers/options.js +25 -1
  86. package/dist/helpers/options.js.map +1 -1
  87. package/dist/helpers/providerValue.d.ts +68 -0
  88. package/dist/helpers/providerValue.d.ts.map +1 -0
  89. package/dist/helpers/providerValue.js +50 -0
  90. package/dist/helpers/providerValue.js.map +1 -0
  91. package/dist/helpers/singleLineString.d.ts +37 -0
  92. package/dist/helpers/singleLineString.d.ts.map +1 -0
  93. package/dist/helpers/singleLineString.js +66 -0
  94. package/dist/helpers/singleLineString.js.map +1 -0
  95. package/dist/helpers/templates.d.ts +100 -0
  96. package/dist/helpers/templates.d.ts.map +1 -1
  97. package/dist/helpers/templates.js +237 -4
  98. package/dist/helpers/templates.js.map +1 -1
  99. package/dist/helpers/validations.d.ts +103 -2
  100. package/dist/helpers/validations.d.ts.map +1 -1
  101. package/dist/helpers/validations.js +858 -91
  102. package/dist/helpers/validations.js.map +1 -1
  103. package/dist/index.d.ts +1 -1
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +2 -1
  106. package/dist/index.js.map +1 -1
  107. package/package.json +1 -1
  108. package/src/components/composer/Composer.tsx +7 -3
  109. package/src/components/form/engine/CompactRow.tsx +391 -29
  110. package/src/components/form/engine/CompactToolbar.tsx +105 -98
  111. package/src/components/form/engine/FormEngine.stories.tsx +863 -12
  112. package/src/components/form/engine/FormEngine.tsx +231 -68
  113. package/src/components/form/engine/_structuredData/SchemaDataView.stories.tsx +104 -0
  114. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +158 -101
  115. package/src/components/form/engine/_structuredData/structuredData.ts +20 -0
  116. package/src/components/form/engine/compactRowStyles.ts +38 -1
  117. package/src/components/form/engine/compactToolbarContext.ts +8 -0
  118. package/src/components/form/engine/readFirst.ts +125 -35
  119. package/src/components/form/fields/Field.tsx +3 -1
  120. package/src/components/form/fields/allowed-values/AllowedValues.tsx +24 -2
  121. package/src/components/form/fields/array/ArrayAutoField.stories.tsx +81 -0
  122. package/src/components/form/fields/auto/AutoFormField.stories.tsx +47 -1
  123. package/src/components/form/fields/auto/AutoFormField.tsx +73 -11
  124. package/src/components/form/fields/long-string/LongString.tsx +46 -5
  125. package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +5 -0
  126. package/src/components/form/fields/template/ExampleValueModal.stories.tsx +114 -0
  127. package/src/components/form/fields/template/ExampleValueModal.tsx +99 -0
  128. package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +8 -4
  129. package/src/components/form/fields/template/TemplateField.stories.tsx +314 -1
  130. package/src/components/form/fields/template/TemplateField.tsx +47 -8
  131. package/src/components/form/fields/template/__fixtures__/longExampleValue.ts +7 -0
  132. package/src/components/form/index.tsx +1 -0
  133. package/src/components/searchFilterBar/SearchFilterBar.stories.tsx +62 -0
  134. package/src/components/searchFilterBar/SearchFilterBar.tsx +13 -0
  135. package/src/components/ticketThread/TicketThread.tsx +7 -0
  136. package/src/helpers/common.ts +11 -1
  137. package/src/helpers/optionUiTypes.ts +161 -0
  138. package/src/helpers/options.ts +23 -0
  139. package/src/helpers/providerValue.ts +125 -0
  140. package/src/helpers/singleLineString.ts +61 -0
  141. package/src/helpers/templates.ts +272 -3
  142. package/src/helpers/validations.ts +1177 -109
  143. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +23 -2
  144. package/src/index.tsx +1 -0
@@ -93,11 +93,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
93
93
  return (mod && mod.__esModule) ? mod : { "default": mod };
94
94
  };
95
95
  Object.defineProperty(exports, "__esModule", { value: true });
96
- exports.CompactRow = void 0;
96
+ exports.CompactRow = exports.richtextItemText = void 0;
97
97
  var jsx_runtime_1 = require("react/jsx-runtime");
98
98
  var reqore_1 = require("@qoretechnologies/reqore");
99
99
  var optionActions_1 = require("./optionActions");
100
100
  var flatten_1 = __importDefault(require("lodash/flatten"));
101
+ var isEqual_1 = __importDefault(require("lodash/isEqual"));
101
102
  var size_1 = __importDefault(require("lodash/size"));
102
103
  var react_1 = __importStar(require("react"));
103
104
  var use_context_selector_1 = require("use-context-selector");
@@ -177,13 +178,40 @@ var MAX_INLINE_OPTION_ACTIONS = 2;
177
178
  // One read-first row: label | value | action collapsed; the real editor (the
178
179
  // classic renderOption) expanded. `hidden` = search-surfaced optional —
179
180
  // activating the row adds the field first.
181
+ /**
182
+ * The text inside a rich-text envelope, when a list item is one.
183
+ *
184
+ * An option like Gmail's `to` is `type: "list"`, `element_type: "string"`,
185
+ * `supports_templates: true`: each element is a plain string that may carry
186
+ * template tags, so its editor is a rich-text one and the element value arrives
187
+ * wrapped as `{type: "richtext", value: [{type: "paragraph", …}]}`.
188
+ *
189
+ * That envelope is a string in a coat, not structured data. The hash-list test
190
+ * unwraps `item.value`, found the Slate document — an object — and classed a
191
+ * list of email addresses as a list of hashes, so the row drew an expandable
192
+ * `type / children / text` tree instead of the address the operator typed.
193
+ */
194
+ var richtextItemText = function (item) {
195
+ return item && typeof item === 'object' && item.type === 'richtext' ?
196
+ (0, common_1.richtextToString)(item.value)
197
+ : undefined;
198
+ };
199
+ exports.richtextItemText = richtextItemText;
180
200
  exports.CompactRow = (0, react_1.memo)(function (_a) {
181
201
  var _b;
182
- var _c, _d, _e, _f, _g, _h, _j, _k;
183
- var optionName = _a.optionName, optionField = _a.optionField, _l = _a.hidden, hidden = _l === void 0 ? false : _l, _m = _a.clustered, clustered = _m === void 0 ? false : _m, _o = _a.clusterFirst, clusterFirst = _o === void 0 ? false : _o, _p = _a.clusterLast, clusterLast = _p === void 0 ? false : _p;
202
+ var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
203
+ var optionName = _a.optionName, optionField = _a.optionField, _o = _a.hidden, hidden = _o === void 0 ? false : _o, _p = _a.clustered, clustered = _p === void 0 ? false : _p, _q = _a.clusterFirst, clusterFirst = _q === void 0 ? false : _q, _r = _a.clusterLast, clusterLast = _r === void 0 ? false : _r, absorbedFields = _a.absorbedFields;
184
204
  var readOnly = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.readOnly; });
185
205
  var commitMode = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.commitMode; });
186
206
  var options = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.options; });
207
+ // An absorbed field keeps its own name — it is a different field, not a
208
+ // property of its host — so the label comes from its schema exactly as it
209
+ // would on its own row.
210
+ var getAbsorbedLabel = function (absorbedName) {
211
+ var _a;
212
+ return ((_a = options === null || options === void 0 ? void 0 : options[absorbedName]) === null || _a === void 0 ? void 0 : _a.display_name) ||
213
+ absorbedName;
214
+ };
187
215
  var codePreviewRenderer = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.codePreviewRenderer; });
188
216
  var markdownRenderer = (0, markdownRendererContext_1.useMarkdownRenderer)();
189
217
  var operators = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.operators; });
@@ -230,6 +258,26 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
230
258
  // renderer when it supplied one, reqraft's own otherwise.
231
259
  // Value-cell content: colour adds a swatch, file an icon + size; hash keeps
232
260
  // its "N fields" summary (sub-fields reveal beneath the row).
261
+ /**
262
+ * Flattens the line breaks in one prose segment of a richtext SUMMARY.
263
+ *
264
+ * The read-first row is a single line: every other value type reaches it
265
+ * through `whiteSpace: 'nowrap'`, which collapses newlines for free. The
266
+ * richtext branch is the only one that opts into `'pre'` — it has to, or the
267
+ * spaces that separate a word from the chip beside it are dropped — and `pre`
268
+ * also honours the newlines, which `nowrap` would have eaten.
269
+ *
270
+ * So a genuinely multi-line value (an alert rule's Gmail message body is five
271
+ * `\n`-separated lines) gave each segment after the first a blank first line.
272
+ * The wrapper centres its items, so a two-line-tall box centred against
273
+ * one-line chips put every word 12px below the chip beside it, and the row
274
+ * read as a staircase. Measured on supah: prose boxes 30px against 14px chips.
275
+ *
276
+ * A space, not nothing: consecutive prose segments are merged before they get
277
+ * here, so a value with a break and no chip between its lines would otherwise
278
+ * lose the word boundary entirely.
279
+ */
280
+ var collapseSummaryBreaks = function (text) { return text.replace(/\s*\r?\n\s*/g, ' '); };
233
281
  var renderReadFirstValue = function (field, schema, formatted) {
234
282
  var valueType = (0, readFirst_1.getValueType)(field, schema);
235
283
  var wrapStyle = {
@@ -268,7 +316,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
268
316
  // see `showCodePreview` below. Keeps the row height fixed while making
269
317
  // multi-line source readable without opening the full editor.
270
318
  if (valueType === 'code-editor' && typeof (field === null || field === void 0 ? void 0 : field.value) === 'string') {
271
- return (0, jsx_runtime_1.jsx)(codeSize_1.ReqraftCodeSizeTag, { code: field.value });
319
+ // An absorbed sibling has no row of its own, so a COLLAPSED host has to
320
+ // carry its value or it disappears from the form entirely when closed.
321
+ // It reads as a chip beside the size chip — "Qore · 62 lines" — which
322
+ // is the same summary the read-only interface pages already show.
323
+ return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { gapSize: 'tiny', verticalAlign: 'center', wrap: true, children: (absorbedFields !== null && absorbedFields !== void 0 ? absorbedFields : []).map(function (absorbedName) {
324
+ var _a;
325
+ var absorbedValue = (_a = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[absorbedName]) === null || _a === void 0 ? void 0 : _a.value;
326
+ if (absorbedValue === undefined || absorbedValue === null || absorbedValue === '') {
327
+ return null;
328
+ }
329
+ return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { className: 'options-readfirst-absorbed-tag', size: 'small', minimal: true, label: String(absorbedValue), tooltip: getAbsorbedLabel(absorbedName) }, absorbedName));
330
+ }) }));
272
331
  }
273
332
  // Markdown read summary: the row prints the value's prose (the markdown
274
333
  // markers are stripped by `formatOptionValue`), so a multi-line document
@@ -302,6 +361,14 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
302
361
  (0, templates_1.isValueTemplate)(field.value)) {
303
362
  return (0, jsx_runtime_1.jsx)(ReadOnlyTemplateTag_1.ReadOnlyTemplateTag, { value: field.value, templates: templates, size: 'small' });
304
363
  }
364
+ // A LIST whose elements are rich-text envelopes is a list of strings, so it
365
+ // reads as those strings. Without this the row fell through to the generic
366
+ // list summary and printed a bare count ("1 item") above the structured
367
+ // tree, never the address itself.
368
+ if (Array.isArray(field === null || field === void 0 ? void 0 : field.value) && field.value.some(function (item) { return (0, exports.richtextItemText)(item) !== undefined; })) {
369
+ var texts = field.value.map(function (item) { var _a; return (_a = (0, exports.richtextItemText)(item)) !== null && _a !== void 0 ? _a : String(item !== null && item !== void 0 ? item : ''); });
370
+ return (0, jsx_runtime_1.jsx)("span", { style: textStyle, children: texts.filter(function (text) { return text !== ''; }).join(', ') });
371
+ }
305
372
  // Richtext read-first summary: inline $-chips for embedded template tags
306
373
  // with the prose around them (the IDE intent scheme via getTemplateTagStyle),
307
374
  // kept lightweight instead of mounting the full editor — that lives in the
@@ -321,6 +388,33 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
321
388
  // size makes centring align the baselines too, at whatever font
322
389
  // size the consuming app uses.
323
390
  style: { fontSize: 'inherit' }, icon: 'ExchangeDollarLine', label: segment.text || segment.value, tooltip: segment.value }, (0, templates_1.getTemplateTagStyle)((_a = (templates ? (0, templates_1.findTemplate)(templates, segment.value || '') : undefined)) === null || _a === void 0 ? void 0 : _a.metadata)), index)
391
+ : (0, jsx_runtime_1.jsx)("span", { style: { whiteSpace: 'pre' }, children: collapseSummaryBreaks(segment.text) }, index);
392
+ }) }));
393
+ }
394
+ }
395
+ // An expression summarises to one line of text, and a template reference
396
+ // inside it printed as its own raw token — `$data:{…}` renders a value as
397
+ // code where a name belongs. Chip every reference here, on the richtext
398
+ // branch's pattern above, so the wrapper (`trim(`…`)`) still reads as the
399
+ // text it is while the reference reads as a name.
400
+ //
401
+ // Unconditionally: a surface with no catalogue (the Automation Hub
402
+ // template preview never fetches one) still shows the reference's own
403
+ // path, which is the point — a conditional chip is no chip at all
404
+ // exactly where the raw token looks worst.
405
+ if ((field === null || field === void 0 ? void 0 : field.is_expression) && formatted) {
406
+ var segments = (0, templates_1.splitTemplateTokens)(formatted);
407
+ var named = segments.map(function (segment) {
408
+ return segment.kind === 'token' ? __assign(__assign({}, segment), (0, templates_1.describeTemplateReference)(templates, segment.text)) : segment;
409
+ });
410
+ if (named.some(function (segment) { return segment.kind === 'token'; })) {
411
+ return ((0, jsx_runtime_1.jsx)("span", { style: __assign(__assign({}, wrapStyle), { gap: 4, overflow: 'hidden' }), children: named.map(function (segment, index) {
412
+ var _a;
413
+ return segment.kind === 'token' ?
414
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, __assign({ size: 'tiny',
415
+ // Inherit the row's font size so the chip shares a baseline
416
+ // with the text around it — see the richtext branch above.
417
+ style: { fontSize: 'inherit' }, icon: 'ExchangeDollarLine', label: segment.label, tooltip: segment.text }, (0, templates_1.getTemplateTagStyle)((_a = segment.item) === null || _a === void 0 ? void 0 : _a.metadata)), index)
324
418
  : (0, jsx_runtime_1.jsx)("span", { style: { whiteSpace: 'pre' }, children: segment.text }, index);
325
419
  }) }));
326
420
  }
@@ -343,14 +437,14 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
343
437
  // hover-gated button is unreachable without a hover — and anything past the
344
438
  // inline cap overflows regardless, so a consumer injecting ten actions can
345
439
  // never push the row's value out of view.
346
- var _q = react_1.default.useMemo(function () {
440
+ var _s = react_1.default.useMemo(function () {
347
441
  return collapseOptionActions ?
348
442
  [[], injectedOptionActions]
349
443
  : [
350
444
  injectedOptionActions.slice(0, MAX_INLINE_OPTION_ACTIONS),
351
445
  injectedOptionActions.slice(MAX_INLINE_OPTION_ACTIONS),
352
446
  ];
353
- }, [collapseOptionActions, injectedOptionActions]), inlineOptionActions = _q[0], menuOptionActions = _q[1];
447
+ }, [collapseOptionActions, injectedOptionActions]), inlineOptionActions = _s[0], menuOptionActions = _s[1];
354
448
  var injectedOptionActionMenuItems = react_1.default.useMemo(function () {
355
449
  return menuOptionActions.map(function (action, index) {
356
450
  var _a, _b;
@@ -461,6 +555,38 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
461
555
  }, 60);
462
556
  return function () { return window.clearTimeout(id); };
463
557
  }, [isExpanded, optionName, autoFocusNameRef]);
558
+ // What the field held when it was opened — the baseline Cancel restores.
559
+ //
560
+ // Deliberately NOT `originalValue`, which is the whole form's load-time
561
+ // snapshot. That answers "undo every change ever made to this field", which
562
+ // is a different question from "forget what I just typed"; a Cancel sitting
563
+ // next to Done has to mean the second one, or it silently throws away edits
564
+ // the user made earlier and had already accepted.
565
+ //
566
+ // The dependency list is `isExpanded` alone on purpose: adding the value
567
+ // would re-take the snapshot on every keystroke, leaving nothing to cancel.
568
+ var editEntryValue = react_1.default.useRef(undefined);
569
+ react_1.default.useEffect(function () {
570
+ if (isExpanded) {
571
+ editEntryValue.current = { value: optionField === null || optionField === void 0 ? void 0 : optionField.value, type: optionField === null || optionField === void 0 ? void 0 : optionField.type };
572
+ }
573
+ else {
574
+ editEntryValue.current = undefined;
575
+ }
576
+ }, [isExpanded]);
577
+ // True while the open editor holds something other than what it opened with.
578
+ var editedSinceOpened = isExpanded &&
579
+ !!editEntryValue.current &&
580
+ !(0, isEqual_1.default)(editEntryValue.current.value, optionField === null || optionField === void 0 ? void 0 : optionField.value);
581
+ // Discard whatever was typed since the field was opened and close it. Used
582
+ // by both the Cancel button and Escape, so the two cannot diverge.
583
+ var cancelEdit = react_1.default.useCallback(function () {
584
+ var snapshot = editEntryValue.current;
585
+ if (snapshot && !(0, isEqual_1.default)(snapshot.value, optionField === null || optionField === void 0 ? void 0 : optionField.value)) {
586
+ handleValueChange(optionName, snapshot.value, snapshot.type);
587
+ }
588
+ toggleExpandedOption(optionName);
589
+ }, [handleValueChange, optionField === null || optionField === void 0 ? void 0 : optionField.value, optionName, toggleExpandedOption]);
464
590
  // The sub-schema describing this field's value, when it has one. A value the
465
591
  // form knows the shape of is previewed THROUGH that shape (see
466
592
  // `SchemaDataView`); only genuinely undescribed data falls through to the
@@ -478,7 +604,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
478
604
  // below an early return, so a hook placed there would run conditionally.
479
605
  var rawArgSchema = schema === null || schema === void 0 ? void 0 : schema.arg_schema;
480
606
  var argSchemaId = typeof rawArgSchema === 'string' ? rawArgSchema : undefined;
481
- var _r = react_1.default.useState(undefined), resolvedArgSchema = _r[0], setResolvedArgSchema = _r[1];
607
+ var _t = react_1.default.useState(undefined), resolvedArgSchema = _t[0], setResolvedArgSchema = _t[1];
482
608
  // Only worth a request when there is a described value to preview: a row whose
483
609
  // value is unset or scalar renders no inset, so fetching its schema would buy
484
610
  // a round trip per row and show nothing. `query` caches GETs, so rows sharing
@@ -514,6 +640,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
514
640
  }, [argSchemaId, valueLooksStructured]);
515
641
  var previewArgSchema = argSchemaId ? resolvedArgSchema : rawArgSchema;
516
642
  var previewWithSchema = react_1.default.useMemo(function () { return (0, SchemaDataView_1.canRenderWithSchema)(optionField === null || optionField === void 0 ? void 0 : optionField.value, previewArgSchema); }, [optionField === null || optionField === void 0 ? void 0 : optionField.value, previewArgSchema]);
643
+ // The form-load revert: back to the value the FORM was loaded with.
644
+ //
645
+ // In an open editor this is offered only when it would do something
646
+ // `cancelEditButton` does not — that is, when the field was already
647
+ // modified BEFORE it was opened, so "undo this edit" and "undo every edit"
648
+ // are different answers. On the usual path (open an untouched field, type,
649
+ // change your mind) the two are identical, and two buttons with the same
650
+ // effect and different names are worse than one.
651
+ //
652
+ // It is unconditional on the READ row, where it renders inline in the
653
+ // status-dot column — there is no edit in progress there to cancel, so the
654
+ // whole-field revert is the only undo that makes sense.
517
655
  var revertButton = changed ?
518
656
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { className: 'options-readfirst-revert', size: 'small', flat: true, minimal: true, icon: 'HistoryLine', tooltip: 'Revert changes', onClick: function (e) {
519
657
  var _a, _b, _c, _d;
@@ -559,6 +697,27 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
559
697
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { className: 'options-readfirst-draft', label: 'Draft', intent: 'warning', icon: 'EditLine', size: 'tiny', minimal: true, fixed: true, flat: true, compact: true, effect: { uppercase: true, spaced: 1 } })
560
698
  : null;
561
699
  var isPassiveCloseAction = fixedAllowedValueOption || readOnly;
700
+ // Cancel — the counterpart to Done, and the answer to "how do I get out of
701
+ // here without keeping this". Done was the only way to leave an open field,
702
+ // so every way out committed: the check, clicking away, and Escape (which
703
+ // closed without discarding, so it committed too, silently).
704
+ //
705
+ // Shown only while there is something to discard. On an untouched field
706
+ // Cancel and Done would do exactly the same thing, and two buttons that
707
+ // differ in name but not in effect are worse than one.
708
+ //
709
+ // Not offered when the close action is passive (read-only, or a fixed
710
+ // choice) — nothing can have been typed, so there is nothing to cancel.
711
+ var cancelEditButton = !isPassiveCloseAction && editedSinceOpened ?
712
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { className: 'options-readfirst-cancel', size: 'small', flat: true, minimal: true, fixed: true, icon: 'CloseLine', intent: 'warning', "aria-label": 'Cancel edit', tooltip: 'Cancel edit \u2014 discard the changes made since this field was opened', onClick: function (event) {
713
+ event.stopPropagation();
714
+ cancelEdit();
715
+ } })
716
+ : null;
717
+ // See `revertButton` above for why this is conditional in the edit row.
718
+ var openedWithFormLoadValue = !editEntryValue.current ||
719
+ (0, isEqual_1.default)(editEntryValue.current.value, (_f = (_e = originalValue.current) === null || _e === void 0 ? void 0 : _e[optionName]) === null || _f === void 0 ? void 0 : _f.value);
720
+ var editRowRevertButton = openedWithFormLoadValue ? null : revertButton;
562
721
  var closeExpandedFieldButton = ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { className: 'options-readfirst-done', size: 'small', intent: !isPassiveCloseAction ? 'success' : undefined, flat: isPassiveCloseAction, minimal: isPassiveCloseAction, fixed: true, icon: isPassiveCloseAction ? 'CloseLine' : 'CheckLine', "aria-label": isPassiveCloseAction ? 'Close field' : 'Done', tooltip: isPassiveCloseAction ? 'Close field' : 'Done', onClick: function () { return toggleExpandedOption(optionName); } }));
563
722
  // Info tiers: Tier 1 (danger/warning + dependency hints) must be visible
564
723
  // without interaction; Tier 2 (info/success, default notes) sits behind ⓘ.
@@ -617,7 +776,12 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
617
776
  handleOptionLabelClick(optionName);
618
777
  } })
619
778
  : null;
620
- var renderInfoStrip = function (m, index) { return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { size: 'small', opaque: false, flat: true, intent: m.intent, title: m.title, children: m.content }, "".concat(m.content, "-").concat(index))); };
779
+ // The gap rides on the message itself rather than on the panel around it:
780
+ // the panel is a vertical ReqoreControlGroup, which owns its own layout and
781
+ // stacks children flush, and the class rule that used to carry a 4px gap
782
+ // never reached this element at all — which is why two messages read as one
783
+ // two-tone block with no space between them.
784
+ var renderInfoStrip = function (m, index) { return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { size: 'small', opaque: false, flat: true, intent: m.intent, title: m.title, style: { marginBottom: 8 }, children: m.content }, "".concat(m.content, "-").concat(index))); };
621
785
  var reasonColor = function (intent) {
622
786
  var _a;
623
787
  return intent === 'danger' ? cDanger
@@ -631,7 +795,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
631
795
  // wrapper AND the inline editor, so the rail/node/highlight persist across
632
796
  // view↔edit. The node is opaque (it masks the rail behind it); hovering any
633
797
  // member lights up the whole group via the shared highlight state.
634
- var clusterGroup = clustered ? (_e = schema === null || schema === void 0 ? void 0 : schema.required_groups) === null || _e === void 0 ? void 0 : _e[0] : undefined;
798
+ var clusterGroup = clustered ? (_g = schema === null || schema === void 0 ? void 0 : schema.required_groups) === null || _g === void 0 ? void 0 : _g[0] : undefined;
635
799
  var clusterMembers = clusterGroup ? requiredGroupsInfo.members[clusterGroup] || [] : [];
636
800
  // The group is fulfilled once any member is set — the whole rail then reads
637
801
  // success (not just the satisfying node).
@@ -672,16 +836,56 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
672
836
  },
673
837
  ]
674
838
  : []), true), injectedOptionActionMenuItems, true) }));
839
+ // The absorbed siblings' controls, rendered inside this row.
840
+ //
841
+ // Each keeps its own label so it is still identifiable — it is a different
842
+ // field, not a property of this one — but it sits inside this row's
843
+ // container, above the editor, so the pair reads as the single decision it
844
+ // is. `renderOption` is the same function the row uses for its own editor,
845
+ // so an absorbed field renders exactly as it would have on its own row.
846
+ var absorbedNodes = (absorbedFields === null || absorbedFields === void 0 ? void 0 : absorbedFields.length) ?
847
+ absorbedFields
848
+ .map(function (absorbedName) {
849
+ var absorbedField = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[absorbedName];
850
+ if (!absorbedField)
851
+ return null;
852
+ return (
853
+ // No label element of its own: the editor now heads itself with
854
+ // the field's name (see FieldAllowedValuesCheckGroup), so a label
855
+ // beside it printed the same word twice.
856
+ (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledAbsorbedField, { className: 'options-readfirst-absorbed', children: (0, jsx_runtime_1.jsx)("div", { style: { minWidth: 0, flex: 1 }, children: renderOption(absorbedName, absorbedField, 'small', true) }) }, absorbedName));
857
+ })
858
+ .filter(Boolean)
859
+ : null;
675
860
  // Declared here rather than beside the hash rows below: the `isExpanded`
676
861
  // branch returns before that point, and its editor needs to know whether it is
677
862
  // holding code.
678
863
  var valueType = (0, readFirst_1.getValueType)(optionField, schema);
864
+ // How much source there is describes the FIELD, not its value, so the count
865
+ // sits under the field's name — the same rule `lineCountNote` already
866
+ // follows for a multi-line markdown value, and the same reason: the value
867
+ // column carries the value and nothing else. It renders on the read row and
868
+ // the open one alike, because "how much code is here?" is a question that
869
+ // outlives opening the editor.
870
+ //
871
+ // It is a plain monospaced note rather than a tag, and deliberately the same
872
+ // one `lineCountNote` renders: both answer "how big is this field's value?"
873
+ // in the same corner of the same column, so stating one as a chip and the
874
+ // other as text made two spellings of one idea.
875
+ var codeSizeNode = valueType === 'code-editor' &&
876
+ typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' &&
877
+ optionField.value !== '' ?
878
+ (function () {
879
+ var _a = (0, codeSize_1.describeCodeSize)(optionField.value), lines = _a.lines, chars = _a.chars;
880
+ return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { className: 'options-readfirst-label-code-size', size: 'tiny', effect: { opacity: 0.45, textAlign: 'left' }, style: { fontFamily: 'monospace' }, children: "".concat((0, codeSize_1.formatCodeChars)(chars), " ").concat((0, codeSize_1.formatCodeLines)(lines)) }));
881
+ })()
882
+ : null;
679
883
  if (isExpanded) {
680
884
  if (inlineEditable) {
681
885
  var collapse_1 = function () { return toggleExpandedOption(optionName); };
682
886
  var editingRow = ((0, jsx_runtime_1.jsxs)("div", __assign({ "data-field": optionName, className: 'readfirst-row readfirst-row-editing options-readfirst-inline options-readfirst-value', style: readRowHeights.current[optionName] ?
683
887
  { minHeight: readRowHeights.current[optionName] }
684
- : undefined }, clusterHoverProps, { children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledLabelBlock, { children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowLabel, { role: 'button', tabIndex: 0, "aria-label": "Collapse ".concat(label), title: (schema === null || schema === void 0 ? void 0 : schema.short_desc) || undefined, "$color": cKey, "$pointer": true, onClick: collapse_1, onKeyDown: function (event) {
888
+ : undefined }, clusterHoverProps, { children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledLabelBlock, { className: 'options-readfirst-label-block', children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowLabel, { role: 'button', tabIndex: 0, "aria-label": "Collapse ".concat(label), title: (schema === null || schema === void 0 ? void 0 : schema.short_desc) || undefined, "$color": cKey, "$pointer": true, onClick: collapse_1, onKeyDown: function (event) {
685
889
  if (event.key === 'Enter' || event.key === ' ') {
686
890
  event.preventDefault();
687
891
  collapse_1();
@@ -690,14 +894,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
690
894
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px' })
691
895
  : null, helpIcon] }), labelShortDesc ?
692
896
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledLabelDesc, { className: 'options-readfirst-label-desc', size: 'small', effect: { opacity: 0.55 }, children: labelShortDesc })
693
- : null] }), (0, jsx_runtime_1.jsxs)("div", { ref: editorRef, style: { minWidth: 0 }, onKeyDown: function (event) {
897
+ : null, codeSizeNode] }), (0, jsx_runtime_1.jsxs)("div", { ref: editorRef, style: { minWidth: 0 }, onKeyDown: function (event) {
694
898
  if (event.key === 'Escape') {
695
899
  event.stopPropagation();
696
- collapse_1();
900
+ // Escape discards. It used to call `collapse()`, which closed
901
+ // the field and KEPT whatever had been typed — the one
902
+ // keystroke every editor treats as "get me out of this
903
+ // without saving" was the quietest way to commit.
904
+ cancelEdit();
697
905
  }
698
- }, children: [valueType === 'code-editor' && typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' ?
699
- (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-editing-summary', children: (0, jsx_runtime_1.jsx)(codeSize_1.ReqraftCodeSizeTag, { code: optionField.value }) })
700
- : null, renderOption(optionName, optionField, 'small', true)] }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowActions, { children: [draftChip, revertButton, clearValueButton, inlineOptionActions.map(function (action, index) {
906
+ }, children: [panelMessages.length ?
907
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-info-panel', vertical: true, fluid: true, gapSize: 'normal', children: panelMessages.map(renderInfoStrip) })
908
+ : null, absorbedNodes, renderOption(optionName, optionField, 'small', true)] }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowActions, { children: [draftChip, editRowRevertButton, cancelEditButton, clearValueButton, inlineOptionActions.map(function (action, index) {
701
909
  return renderInjectedOptionAction(action, index);
702
910
  }), moreMenu, closeExpandedFieldButton] }), clusterNode] }), optionName));
703
911
  // ALWAYS wrap the editing row in the same StyledColumn so its parent stays
@@ -716,10 +924,10 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
716
924
  var cardBadges = schemaBadge !== undefined && schemaBadge !== null ?
717
925
  (Array.isArray(schemaBadge) ? schemaBadge : [schemaBadge])
718
926
  : [];
719
- var cardActions = ((_f = schema === null || schema === void 0 ? void 0 : schema.actions) === null || _f === void 0 ? void 0 : _f.filter(function (action) { return !!action && typeof action === 'object'; })) || [];
927
+ var cardActions = ((_h = schema === null || schema === void 0 ? void 0 : schema.actions) === null || _h === void 0 ? void 0 : _h.filter(function (action) { return !!action && typeof action === 'object'; })) || [];
720
928
  var cardTags = ((schema === null || schema === void 0 ? void 0 : schema.tags) || []);
721
929
  var schemaIntentColor = (schema === null || schema === void 0 ? void 0 : schema.intent) ?
722
- (_g = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _g === void 0 ? void 0 : _g[schema.intent]
930
+ (_j = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _j === void 0 ? void 0 : _j[schema.intent]
723
931
  : undefined;
724
932
  return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledEditCard, { "data-field": optionName, className: COMPACT_SINGLE_VALUE_TYPES.has(editType) ?
725
933
  'options-readfirst-card options-readfirst-card-single'
@@ -748,7 +956,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
748
956
  return renderInjectedOptionAction(action, index);
749
957
  }), hasValue && !readOnly ?
750
958
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { size: 'small', icon: 'DeleteBinLine', minimal: true, flat: true, fixed: true, intent: 'danger', className: 'options-readfirst-clear', "aria-label": 'Clear value', tooltip: 'Clear value', onClick: confirmClearValue })
751
- : null, moreMenu, closeExpandedFieldButton] })] }), (0, jsx_runtime_1.jsxs)(FocusedEditing_1.FocusedEditing, { isFullscreen: focusedEditing === optionName, onClose: function () { return setFocusedEditing(undefined); }, description: (schema === null || schema === void 0 ? void 0 : schema.display_name) || optionName, children: [focusedEditing === optionName ?
959
+ : null, moreMenu, closeExpandedFieldButton] })] }), absorbedNodes, (0, jsx_runtime_1.jsxs)(FocusedEditing_1.FocusedEditing, { isFullscreen: focusedEditing === optionName, onClose: function () { return setFocusedEditing(undefined); }, description: (schema === null || schema === void 0 ? void 0 : schema.display_name) || optionName, children: [focusedEditing === optionName ?
752
960
  (0, jsx_runtime_1.jsx)(Description_1.Description, { longDescription: schema === null || schema === void 0 ? void 0 : schema.desc, shortDescription: schema === null || schema === void 0 ? void 0 : schema.short_desc, longDescriptionShownByDefault: true })
753
961
  : null, renderOption(optionName, optionField)] })] }, optionName));
754
962
  }
@@ -776,6 +984,9 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
776
984
  Array.isArray(optionField === null || optionField === void 0 ? void 0 : optionField.value) &&
777
985
  optionField.value.length > 0 &&
778
986
  optionField.value.some(function (item) {
987
+ if ((0, exports.richtextItemText)(item) !== undefined) {
988
+ return false;
989
+ }
779
990
  var inner = item && typeof item === 'object' && 'value' in item ?
780
991
  item.value
781
992
  : item;
@@ -791,6 +1002,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
791
1002
  valueType === 'code-editor' &&
792
1003
  typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' &&
793
1004
  optionField.value.length > 0;
1005
+ // A richtext value that renders as CHIPS is drawn in full by the row itself:
1006
+ // the chips are the value, and the reader is looking straight at it. The
1007
+ // native `title` below would then hover the raw source of the very thing the
1008
+ // chips replace ("[$fsminput:severity] $fsminput:alert_code") — and, because
1009
+ // each chip carries its own Reqore tooltip, hovering one fires BOTH: the chip
1010
+ // popover and the row's browser tooltip, in different places, saying almost
1011
+ // the same thing. Only the popover shows up in a screenshot, which is what
1012
+ // made the pair hard to report.
1013
+ var showsTemplateChips = !hidden &&
1014
+ valueType === 'richtext' &&
1015
+ Array.isArray(optionField === null || optionField === void 0 ? void 0 : optionField.value) &&
1016
+ (0, common_1.richtextToSegments)(optionField.value).some(function (segment) { return segment.kind === 'tag'; });
794
1017
  // Markdown reads the same way for the same reason: the row itself can only
795
1018
  // show a line of text, and for markdown that line is the SOURCE — the reader
796
1019
  // gets `## ` and `**` where the point of the value is what it looks like
@@ -824,32 +1047,42 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
824
1047
  var typeLabel = showFieldTypes ?
825
1048
  "<".concat((schema === null || schema === void 0 ? void 0 : schema.ui_type) || (schema === null || schema === void 0 ? void 0 : schema.type) || 'auto').concat((schema === null || schema === void 0 ? void 0 : schema.ui_element_type) ? "[".concat(schema.ui_element_type, "]") : '', ">")
826
1049
  : null;
827
- // Disabled rows (schema flag or unmet deps) can't open a lock + reason
828
- // renders instead. Form-level readOnly still opens in view mode (Close).
1050
+ // A `readonly` field is one the system ownsan assigned id, a recorded
1051
+ // provenance. The server states that on the field itself; only the older
1052
+ // compat projection also mapped it to `disabled`, so on this path the form
1053
+ // was handed `readonly` alone and rendered an editable control for a value
1054
+ // no answer of the user's can change.
1055
+ var fieldReadonly = !!(schema === null || schema === void 0 ? void 0 : schema.readonly);
1056
+ // Disabled rows (schema flag, readonly, or unmet deps) can't open — a lock +
1057
+ // reason renders instead. Form-level readOnly still opens in view mode (Close).
829
1058
  var fieldDisabled = !hidden &&
830
1059
  !readOnly &&
831
1060
  (!!(schema === null || schema === void 0 ? void 0 : schema.disabled) ||
1061
+ fieldReadonly ||
832
1062
  !(0, validations_1.hasAllDependenciesFullfilled)(schema === null || schema === void 0 ? void 0 : schema.depends_on, availableOptions, options || {}));
833
- var fieldDisabledReason = (schema === null || schema === void 0 ? void 0 : schema.disabled) ? 'This field is disabled' : 'Disabled — dependencies are not fulfilled';
1063
+ var fieldDisabledReason = (schema === null || schema === void 0 ? void 0 : schema.disabled) ? 'This field is disabled'
1064
+ : fieldReadonly ? 'Set by Qorus — not editable'
1065
+ : 'Disabled — dependencies are not fulfilled';
834
1066
  // Dependency contract: top-level entries must ALL hold; a nested array
835
- // means ANY of its entries; `name=value` requires that exact value.
836
- var dependencyEntries = fieldDisabled && !(schema === null || schema === void 0 ? void 0 : schema.disabled) ?
1067
+ // means ANY of its entries; `name=value` requires that exact value, and
1068
+ // `name!=value` requires any other answer. Parsed by the same helper the
1069
+ // predicate uses, so the lock cannot describe a rule the form does not apply.
1070
+ var dependencyEntries = fieldDisabled && !(schema === null || schema === void 0 ? void 0 : schema.disabled) && !fieldReadonly ?
837
1071
  ((schema === null || schema === void 0 ? void 0 : schema.depends_on) || [])
838
1072
  : [];
839
1073
  var describeDependency = function (dep) {
840
1074
  var _a, _b;
841
- var eqIndex = dep.indexOf('=');
842
- var depName = eqIndex === -1 ? dep : dep.slice(0, eqIndex);
843
- var expected = eqIndex === -1 ? undefined : dep.slice(eqIndex + 1);
1075
+ var _c = (0, validations_1.parseDependency)(dep), depName = _c.name, op = _c.op, expected = _c.value;
844
1076
  var depLabel = ((_a = options === null || options === void 0 ? void 0 : options[depName]) === null || _a === void 0 ? void 0 : _a.display_name) || depName;
845
1077
  var depValue = (_b = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[depName]) === null || _b === void 0 ? void 0 : _b.value;
846
1078
  return {
847
1079
  name: depName,
848
1080
  exists: !!(options === null || options === void 0 ? void 0 : options[depName]),
849
- label: expected === undefined ? depLabel : "".concat(depLabel, " = ").concat(expected),
850
- fulfilled: expected === undefined ?
851
- !(0, readFirst_1.isOptionValueEmpty)(depValue)
852
- : depValue != null && String(depValue) === expected,
1081
+ label: !op ? depLabel : "".concat(depLabel, " ").concat(op === '=' ? '=' : '≠', " ").concat(expected),
1082
+ fulfilled: !op ? !(0, readFirst_1.isOptionValueEmpty)(depValue)
1083
+ : depValue == null ? false
1084
+ : op === '=' ? String(depValue) === expected
1085
+ : String(depValue) !== expected,
853
1086
  };
854
1087
  };
855
1088
  var depHighlightNames = (0, flatten_1.default)(dependencyEntries)
@@ -899,7 +1132,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
899
1132
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: schema === null || schema === void 0 ? void 0 : schema.icon, image: schema === null || schema === void 0 ? void 0 : schema.image, size: '14px', className: 'options-readfirst-row-icon' })
900
1133
  : null;
901
1134
  var rowSchemaIntentColor = (schema === null || schema === void 0 ? void 0 : schema.intent) ?
902
- (_h = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _h === void 0 ? void 0 : _h[schema.intent]
1135
+ (_k = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _k === void 0 ? void 0 : _k[schema.intent]
903
1136
  : undefined;
904
1137
  var rowStripeColor = (showStripe ? intentColor : undefined) || rowSchemaIntentColor;
905
1138
  // Intent stripe on the block ROOT so it spans the field's whole territory:
@@ -914,7 +1147,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
914
1147
  // boxes — so the dot and the box can never disagree). Hidden (not-yet-added)
915
1148
  // and dependency-locked rows show no dot (the add/lock affordance speaks for
916
1149
  // them). worstIntent already folds in schema + validation messages.
917
- var cSuccess = (_j = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _j === void 0 ? void 0 : _j.success;
1150
+ var cSuccess = (_l = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _l === void 0 ? void 0 : _l.success;
918
1151
  var rowStatus = (0, readFirst_1.getReadFirstStatus)({
919
1152
  empty: empty,
920
1153
  required: required,
@@ -932,34 +1165,39 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
932
1165
  event.preventDefault();
933
1166
  activate(event);
934
1167
  }
935
- } }, clusterHoverProps, { children: [clusterNode, (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledLabelBlock, { children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowLabel, { title: (schema === null || schema === void 0 ? void 0 : schema.short_desc) || undefined, "$color": cKey, children: [rowChromeIcon, (0, jsx_runtime_1.jsxs)("span", { className: 'options-readfirst-label-text', style: { minWidth: 0 }, children: [label, required ?
1168
+ } }, clusterHoverProps, { children: [clusterNode, (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledLabelBlock, { className: 'options-readfirst-label-block', children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowLabel, { title: (schema === null || schema === void 0 ? void 0 : schema.short_desc) || undefined, "$color": cKey, children: [rowChromeIcon, (0, jsx_runtime_1.jsxs)("span", { className: 'options-readfirst-label-text', style: { minWidth: 0 }, children: [label, required ?
936
1169
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px', margin: 'left', marginSize: 'tiny' })
937
1170
  : null, helpIcon] }), typeLabel ?
938
1171
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'tiny', minimal: true, label: typeLabel, labelEffect: { opacity: 0.55 } })
939
1172
  : null] }), showLabelDesc ?
940
1173
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledLabelDesc, { className: 'options-readfirst-label-desc', size: 'small', effect: { opacity: 0.55 }, children: labelShortDesc })
941
- : null, lineCountNote ?
1174
+ : null, codeSizeNode, lineCountNote ?
942
1175
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { className: 'options-readfirst-label-lines', size: 'tiny', effect: { opacity: 0.45, textAlign: 'left' }, style: { fontFamily: 'monospace' }, children: lineCountNote })
943
1176
  : null] }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowValue
944
1177
  // A code field draws its whole value in the preview below, with
945
1178
  // "Show more" for the rest, so a hover carrying the same text is
946
1179
  // noise -- and a native tooltip holding a few hundred lines is
947
- // unreadable anyway. Every other value keeps its hover, which is the
948
- // only way to read one that the row had to truncate.
1180
+ // unreadable anyway. A chipped richtext value is the same case: the row
1181
+ // already draws it in full, and its chips carry their own tooltips.
1182
+ // Every other value keeps its hover, which is the only way to read one
1183
+ // that the row had to truncate.
949
1184
  , {
950
1185
  // A code field draws its whole value in the preview below, with
951
1186
  // "Show more" for the rest, so a hover carrying the same text is
952
1187
  // noise -- and a native tooltip holding a few hundred lines is
953
- // unreadable anyway. Every other value keeps its hover, which is the
954
- // only way to read one that the row had to truncate.
1188
+ // unreadable anyway. A chipped richtext value is the same case: the row
1189
+ // already draws it in full, and its chips carry their own tooltips.
1190
+ // Every other value keeps its hover, which is the only way to read one
1191
+ // that the row had to truncate.
955
1192
  title: (!empty &&
956
1193
  !hidden &&
957
1194
  !showCodePreview &&
958
1195
  !showMarkdownPreview &&
1196
+ !showsTemplateChips &&
959
1197
  typeof formatted === 'string') ?
960
1198
  formatted
961
- : undefined, "$color": empty || hidden ? "".concat(cMuted, "66") : cKey, "$empty": empty || hidden, children: [showMarkdownPreview || previewWithSchema ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'options-readfirst-valuetext', children: hidden || empty ? '—' : renderReadFirstValue(optionField, schema, formatted) })), valueReasons.map(function (m, i) { return ((0, jsx_runtime_1.jsx)("span", { className: 'options-readfirst-reason', style: { color: reasonColor(m.intent) }, children: m.content }, "".concat(m.content, "-").concat(i))); }), panelMessages.length ?
962
- (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-info-panel', children: panelMessages.map(renderInfoStrip) })
1199
+ : undefined, "$color": empty || hidden ? "".concat(cMuted, "66") : cKey, "$empty": empty || hidden, children: [showMarkdownPreview || (previewWithSchema && showStructuredPreview) ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'options-readfirst-valuetext', children: hidden || empty ? '—' : renderReadFirstValue(optionField, schema, formatted) })), valueReasons.map(function (m, i) { return ((0, jsx_runtime_1.jsx)("span", { className: 'options-readfirst-reason', style: { color: reasonColor(m.intent) }, children: m.content }, "".concat(m.content, "-").concat(i))); }), panelMessages.length ?
1200
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-info-panel', vertical: true, fluid: true, gapSize: 'normal', children: panelMessages.map(renderInfoStrip) })
963
1201
  : null, showStructuredPreview ?
964
1202
  // The inset lives inside the row now, so a click on a value chip would
965
1203
  // bubble to the row's onClick and fire activate() a SECOND time (the
@@ -1002,7 +1240,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
1002
1240
  // consumer that registers nothing — the heading is
1003
1241
  // accented either way, just in the theme's own colour
1004
1242
  // rather than one this library picked.
1005
- accent: ((_k = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _k === void 0 ? void 0 : _k.custom1) || cInfo,
1243
+ accent: ((_m = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _m === void 0 ? void 0 : _m.custom1) || cInfo,
1006
1244
  }, onItemClick: function () { return activate(); } })
1007
1245
  : (0, jsx_runtime_1.jsx)(StructuredDataView_1.StructuredDataView, { value: optionField === null || optionField === void 0 ? void 0 : optionField.value, collapsibleRoot: false, showTypes: showFieldTypes, defaultExpandDepth: 2, onItemClick: function () { return activate(); } }) }) }) })
1008
1246
  : null, showCodePreview ?