@qoretechnologies/reqraft 0.10.38 → 0.10.39-pr.95.g3503e91

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 (102) hide show
  1. package/.claude/CLAUDE.md +12 -0
  2. package/dist/components/codeSize/index.d.ts +37 -0
  3. package/dist/components/codeSize/index.d.ts.map +1 -0
  4. package/dist/components/codeSize/index.js +87 -0
  5. package/dist/components/codeSize/index.js.map +1 -0
  6. package/dist/components/form/engine/CompactRow.d.ts +20 -1
  7. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  8. package/dist/components/form/engine/CompactRow.js +357 -30
  9. package/dist/components/form/engine/CompactRow.js.map +1 -1
  10. package/dist/components/form/engine/FormEngine.d.ts +24 -1
  11. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  12. package/dist/components/form/engine/FormEngine.js +179 -39
  13. package/dist/components/form/engine/FormEngine.js.map +1 -1
  14. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts +37 -0
  15. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -0
  16. package/dist/components/form/engine/_structuredData/SchemaDataView.js +335 -0
  17. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -0
  18. package/dist/components/form/engine/compactRowStyles.d.ts +13 -0
  19. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  20. package/dist/components/form/engine/compactRowStyles.js +30 -5
  21. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  22. package/dist/components/form/engine/readFirst.d.ts +73 -1
  23. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  24. package/dist/components/form/engine/readFirst.js +175 -5
  25. package/dist/components/form/engine/readFirst.js.map +1 -1
  26. package/dist/components/form/fields/Field.d.ts.map +1 -1
  27. package/dist/components/form/fields/Field.js +1 -1
  28. package/dist/components/form/fields/Field.js.map +1 -1
  29. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +12 -2
  30. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  31. package/dist/components/form/fields/allowed-values/AllowedValues.js +16 -6
  32. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  33. package/dist/components/form/fields/array/ArrayAuto.d.ts.map +1 -1
  34. package/dist/components/form/fields/array/ArrayAuto.js +51 -21
  35. package/dist/components/form/fields/array/ArrayAuto.js.map +1 -1
  36. package/dist/components/form/fields/array/ArrayAutoField.d.ts.map +1 -1
  37. package/dist/components/form/fields/array/ArrayAutoField.js +42 -25
  38. package/dist/components/form/fields/array/ArrayAutoField.js.map +1 -1
  39. package/dist/components/form/fields/auto/AutoFormField.d.ts +4 -0
  40. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  41. package/dist/components/form/fields/auto/AutoFormField.js +29 -4
  42. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  43. package/dist/components/form/fields/long-string/LongString.d.ts +9 -1
  44. package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
  45. package/dist/components/form/fields/long-string/LongString.js +25 -4
  46. package/dist/components/form/fields/long-string/LongString.js.map +1 -1
  47. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  48. package/dist/components/form/fields/template/TemplateField.js +12 -2
  49. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  50. package/dist/helpers/common.d.ts +8 -1
  51. package/dist/helpers/common.d.ts.map +1 -1
  52. package/dist/helpers/common.js +9 -1
  53. package/dist/helpers/common.js.map +1 -1
  54. package/dist/helpers/optionUiTypes.d.ts +30 -0
  55. package/dist/helpers/optionUiTypes.d.ts.map +1 -0
  56. package/dist/helpers/optionUiTypes.js +148 -0
  57. package/dist/helpers/optionUiTypes.js.map +1 -0
  58. package/dist/helpers/options.d.ts +19 -0
  59. package/dist/helpers/options.d.ts.map +1 -1
  60. package/dist/helpers/options.js +25 -1
  61. package/dist/helpers/options.js.map +1 -1
  62. package/dist/helpers/providerValue.d.ts +68 -0
  63. package/dist/helpers/providerValue.d.ts.map +1 -0
  64. package/dist/helpers/providerValue.js +50 -0
  65. package/dist/helpers/providerValue.js.map +1 -0
  66. package/dist/helpers/singleLineString.d.ts +37 -0
  67. package/dist/helpers/singleLineString.d.ts.map +1 -0
  68. package/dist/helpers/singleLineString.js +66 -0
  69. package/dist/helpers/singleLineString.js.map +1 -0
  70. package/dist/helpers/validations.d.ts +85 -2
  71. package/dist/helpers/validations.d.ts.map +1 -1
  72. package/dist/helpers/validations.js +802 -76
  73. package/dist/helpers/validations.js.map +1 -1
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +1 -0
  77. package/dist/index.js.map +1 -1
  78. package/package.json +1 -1
  79. package/src/components/codeSize/index.tsx +79 -0
  80. package/src/components/form/engine/CompactRow.tsx +436 -31
  81. package/src/components/form/engine/FormEngine.stories.tsx +802 -15
  82. package/src/components/form/engine/FormEngine.tsx +180 -13
  83. package/src/components/form/engine/_structuredData/SchemaDataView.stories.tsx +233 -0
  84. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +630 -0
  85. package/src/components/form/engine/compactRowStyles.ts +44 -2
  86. package/src/components/form/engine/readFirst.ts +201 -5
  87. package/src/components/form/fields/Field.tsx +3 -1
  88. package/src/components/form/fields/allowed-values/AllowedValues.tsx +24 -2
  89. package/src/components/form/fields/array/ArrayAuto.tsx +35 -4
  90. package/src/components/form/fields/array/ArrayAutoField.stories.tsx +134 -0
  91. package/src/components/form/fields/array/ArrayAutoField.tsx +22 -4
  92. package/src/components/form/fields/auto/AutoFormField.tsx +30 -1
  93. package/src/components/form/fields/long-string/LongString.tsx +46 -5
  94. package/src/components/form/fields/template/TemplateField.tsx +16 -1
  95. package/src/helpers/common.ts +11 -1
  96. package/src/helpers/optionUiTypes.ts +153 -0
  97. package/src/helpers/options.ts +23 -0
  98. package/src/helpers/providerValue.ts +125 -0
  99. package/src/helpers/singleLineString.ts +61 -0
  100. package/src/helpers/validations.ts +1105 -80
  101. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +23 -2
  102. package/src/index.tsx +1 -0
@@ -33,6 +33,42 @@ var __importStar = (this && this.__importStar) || function (mod) {
33
33
  __setModuleDefault(result, mod);
34
34
  return result;
35
35
  };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
36
72
  var __rest = (this && this.__rest) || function (s, e) {
37
73
  var t = {};
38
74
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -57,11 +93,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
57
93
  return (mod && mod.__esModule) ? mod : { "default": mod };
58
94
  };
59
95
  Object.defineProperty(exports, "__esModule", { value: true });
60
- exports.CompactRow = void 0;
96
+ exports.CompactRow = exports.richtextItemText = void 0;
61
97
  var jsx_runtime_1 = require("react/jsx-runtime");
62
98
  var reqore_1 = require("@qoretechnologies/reqore");
63
99
  var optionActions_1 = require("./optionActions");
64
100
  var flatten_1 = __importDefault(require("lodash/flatten"));
101
+ var isEqual_1 = __importDefault(require("lodash/isEqual"));
65
102
  var size_1 = __importDefault(require("lodash/size"));
66
103
  var react_1 = __importStar(require("react"));
67
104
  var use_context_selector_1 = require("use-context-selector");
@@ -69,12 +106,15 @@ var validations_1 = require("../../../helpers/validations");
69
106
  var templates_1 = require("../../../helpers/templates");
70
107
  var common_1 = require("../../../helpers/common");
71
108
  var ReadOnlyTemplateTag_1 = require("../fields/template/ReadOnlyTemplateTag");
109
+ var codeSize_1 = require("../../codeSize");
72
110
  var Description_1 = require("../../Description");
73
111
  var markdownRendererContext_1 = require("../../Description/markdownRendererContext");
74
112
  var FocusedEditing_1 = require("../../FocusedEditing");
75
113
  var compactRowContext_1 = require("./compactRowContext");
76
114
  var compactRowStyles_1 = require("./compactRowStyles");
77
115
  var OptionFieldMessages_1 = require("./OptionFieldMessages");
116
+ var SchemaDataView_1 = require("./_structuredData/SchemaDataView");
117
+ var fetch_1 = require("../../../utils/fetch");
78
118
  var readFirst_1 = require("./readFirst");
79
119
  var StructuredDataView_1 = require("./_structuredData/StructuredDataView");
80
120
  /**
@@ -138,13 +178,40 @@ var MAX_INLINE_OPTION_ACTIONS = 2;
138
178
  // One read-first row: label | value | action collapsed; the real editor (the
139
179
  // classic renderOption) expanded. `hidden` = search-surfaced optional —
140
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;
141
200
  exports.CompactRow = (0, react_1.memo)(function (_a) {
142
201
  var _b;
143
- var _c, _d, _e, _f, _g, _h, _j;
144
- var optionName = _a.optionName, optionField = _a.optionField, _k = _a.hidden, hidden = _k === void 0 ? false : _k, _l = _a.clustered, clustered = _l === void 0 ? false : _l, _m = _a.clusterFirst, clusterFirst = _m === void 0 ? false : _m, _o = _a.clusterLast, clusterLast = _o === void 0 ? false : _o;
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;
145
204
  var readOnly = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.readOnly; });
146
205
  var commitMode = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.commitMode; });
147
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
+ };
148
215
  var codePreviewRenderer = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.codePreviewRenderer; });
149
216
  var markdownRenderer = (0, markdownRendererContext_1.useMarkdownRenderer)();
150
217
  var operators = (0, use_context_selector_1.useContextSelector)(compactRowContext_1.CompactRowContext, function (v) { return v.operators; });
@@ -191,6 +258,26 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
191
258
  // renderer when it supplied one, reqraft's own otherwise.
192
259
  // Value-cell content: colour adds a swatch, file an icon + size; hash keeps
193
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, ' '); };
194
281
  var renderReadFirstValue = function (field, schema, formatted) {
195
282
  var valueType = (0, readFirst_1.getValueType)(field, schema);
196
283
  var wrapStyle = {
@@ -229,9 +316,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
229
316
  // see `showCodePreview` below. Keeps the row height fixed while making
230
317
  // multi-line source readable without opening the full editor.
231
318
  if (valueType === 'code-editor' && typeof (field === null || field === void 0 ? void 0 : field.value) === 'string') {
232
- var lines = field.value.split('\n').length;
233
- var chars = field.value.length;
234
- return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', minimal: true, intent: 'info', icon: 'CodeLine', label: "".concat(lines, " ").concat(lines === 1 ? 'line' : 'lines'), labelKey: "".concat(chars, " ").concat(chars === 1 ? 'char' : 'chars') }));
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
+ }) }));
235
331
  }
236
332
  // Markdown read summary: the row prints the value's prose (the markdown
237
333
  // markers are stripped by `formatOptionValue`), so a multi-line document
@@ -265,6 +361,14 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
265
361
  (0, templates_1.isValueTemplate)(field.value)) {
266
362
  return (0, jsx_runtime_1.jsx)(ReadOnlyTemplateTag_1.ReadOnlyTemplateTag, { value: field.value, templates: templates, size: 'small' });
267
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
+ }
268
372
  // Richtext read-first summary: inline $-chips for embedded template tags
269
373
  // with the prose around them (the IDE intent scheme via getTemplateTagStyle),
270
374
  // kept lightweight instead of mounting the full editor — that lives in the
@@ -284,7 +388,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
284
388
  // size makes centring align the baselines too, at whatever font
285
389
  // size the consuming app uses.
286
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)
287
- : (0, jsx_runtime_1.jsx)("span", { style: { whiteSpace: 'pre' }, children: segment.text }, index);
391
+ : (0, jsx_runtime_1.jsx)("span", { style: { whiteSpace: 'pre' }, children: collapseSummaryBreaks(segment.text) }, index);
288
392
  }) }));
289
393
  }
290
394
  }
@@ -333,14 +437,14 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
333
437
  // hover-gated button is unreachable without a hover — and anything past the
334
438
  // inline cap overflows regardless, so a consumer injecting ten actions can
335
439
  // never push the row's value out of view.
336
- var _p = react_1.default.useMemo(function () {
440
+ var _s = react_1.default.useMemo(function () {
337
441
  return collapseOptionActions ?
338
442
  [[], injectedOptionActions]
339
443
  : [
340
444
  injectedOptionActions.slice(0, MAX_INLINE_OPTION_ACTIONS),
341
445
  injectedOptionActions.slice(MAX_INLINE_OPTION_ACTIONS),
342
446
  ];
343
- }, [collapseOptionActions, injectedOptionActions]), inlineOptionActions = _p[0], menuOptionActions = _p[1];
447
+ }, [collapseOptionActions, injectedOptionActions]), inlineOptionActions = _s[0], menuOptionActions = _s[1];
344
448
  var injectedOptionActionMenuItems = react_1.default.useMemo(function () {
345
449
  return menuOptionActions.map(function (action, index) {
346
450
  var _a, _b;
@@ -451,6 +555,103 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
451
555
  }, 60);
452
556
  return function () { return window.clearTimeout(id); };
453
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]);
590
+ // The sub-schema describing this field's value, when it has one. A value the
591
+ // form knows the shape of is previewed THROUGH that shape (see
592
+ // `SchemaDataView`); only genuinely undescribed data falls through to the
593
+ // untyped data tree.
594
+ //
595
+ // The server does NOT inline that sub-schema. `encodeFieldsForUi()` registers
596
+ // it and sends an id string in its place, which the consumer fetches back —
597
+ // exactly what AutoFormField does to build the editor ("Some arg schemas are
598
+ // not provided as objects, but as strings so we need to fetch them"). A
599
+ // preview that understood only the inline object therefore fell through to
600
+ // the untyped tree for every field a real server describes: the schema view
601
+ // worked against hand-written story fixtures and nowhere else.
602
+ //
603
+ // Resolved here rather than beside the preview it feeds: the preview renders
604
+ // below an early return, so a hook placed there would run conditionally.
605
+ var rawArgSchema = schema === null || schema === void 0 ? void 0 : schema.arg_schema;
606
+ var argSchemaId = typeof rawArgSchema === 'string' ? rawArgSchema : undefined;
607
+ var _t = react_1.default.useState(undefined), resolvedArgSchema = _t[0], setResolvedArgSchema = _t[1];
608
+ // Only worth a request when there is a described value to preview: a row whose
609
+ // value is unset or scalar renders no inset, so fetching its schema would buy
610
+ // a round trip per row and show nothing. `query` caches GETs, so rows sharing
611
+ // an id (every row of one list) cost one request between them.
612
+ var valueLooksStructured = !!(optionField === null || optionField === void 0 ? void 0 : optionField.value) && typeof optionField.value === 'object';
613
+ react_1.default.useEffect(function () {
614
+ if (!argSchemaId || !valueLooksStructured) {
615
+ return undefined;
616
+ }
617
+ var cancelled = false;
618
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
619
+ var response;
620
+ return __generator(this, function (_a) {
621
+ switch (_a.label) {
622
+ case 0: return [4 /*yield*/, (0, fetch_1.query)({
623
+ url: "dataprovider/arg_schemas/".concat(argSchemaId),
624
+ method: 'GET',
625
+ })];
626
+ case 1:
627
+ response = _a.sent();
628
+ // A failed fetch is not an error state here: the preview simply stays the
629
+ // untyped tree, which is what it was before the schema view existed.
630
+ if (!cancelled && response.ok) {
631
+ setResolvedArgSchema(response.data);
632
+ }
633
+ return [2 /*return*/];
634
+ }
635
+ });
636
+ }); })();
637
+ return function () {
638
+ cancelled = true;
639
+ };
640
+ }, [argSchemaId, valueLooksStructured]);
641
+ var previewArgSchema = argSchemaId ? resolvedArgSchema : rawArgSchema;
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.
454
655
  var revertButton = changed ?
455
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) {
456
657
  var _a, _b, _c, _d;
@@ -496,6 +697,27 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
496
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 } })
497
698
  : null;
498
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;
499
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); } }));
500
722
  // Info tiers: Tier 1 (danger/warning + dependency hints) must be visible
501
723
  // without interaction; Tier 2 (info/success, default notes) sits behind ⓘ.
@@ -554,7 +776,12 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
554
776
  handleOptionLabelClick(optionName);
555
777
  } })
556
778
  : null;
557
- 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))); };
558
785
  var reasonColor = function (intent) {
559
786
  var _a;
560
787
  return intent === 'danger' ? cDanger
@@ -568,7 +795,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
568
795
  // wrapper AND the inline editor, so the rail/node/highlight persist across
569
796
  // view↔edit. The node is opaque (it masks the rail behind it); hovering any
570
797
  // member lights up the whole group via the shared highlight state.
571
- 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;
572
799
  var clusterMembers = clusterGroup ? requiredGroupsInfo.members[clusterGroup] || [] : [];
573
800
  // The group is fulfilled once any member is set — the whole rail then reads
574
801
  // success (not just the satisfying node).
@@ -609,12 +836,48 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
609
836
  },
610
837
  ]
611
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;
860
+ // Declared here rather than beside the hash rows below: the `isExpanded`
861
+ // branch returns before that point, and its editor needs to know whether it is
862
+ // holding code.
863
+ var valueType = (0, readFirst_1.getValueType)(optionField, schema);
864
+ // How much source there is describes the FIELD, not its value, so the chip
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
+ var codeSizeNode = valueType === 'code-editor' &&
871
+ typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' &&
872
+ optionField.value !== '' ?
873
+ (0, jsx_runtime_1.jsx)(codeSize_1.ReqraftCodeSizeTag, { className: 'options-readfirst-label-code-size', code: optionField.value })
874
+ : null;
612
875
  if (isExpanded) {
613
876
  if (inlineEditable) {
614
877
  var collapse_1 = function () { return toggleExpandedOption(optionName); };
615
878
  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] ?
616
879
  { minHeight: readRowHeights.current[optionName] }
617
- : 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) {
880
+ : 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) {
618
881
  if (event.key === 'Enter' || event.key === ' ') {
619
882
  event.preventDefault();
620
883
  collapse_1();
@@ -623,12 +886,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
623
886
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px' })
624
887
  : null, helpIcon] }), labelShortDesc ?
625
888
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledLabelDesc, { className: 'options-readfirst-label-desc', size: 'small', effect: { opacity: 0.55 }, children: labelShortDesc })
626
- : null] }), (0, jsx_runtime_1.jsx)("div", { ref: editorRef, style: { minWidth: 0 }, onKeyDown: function (event) {
889
+ : null, codeSizeNode] }), (0, jsx_runtime_1.jsxs)("div", { ref: editorRef, style: { minWidth: 0 }, onKeyDown: function (event) {
627
890
  if (event.key === 'Escape') {
628
891
  event.stopPropagation();
629
- collapse_1();
892
+ // Escape discards. It used to call `collapse()`, which closed
893
+ // the field and KEPT whatever had been typed — the one
894
+ // keystroke every editor treats as "get me out of this
895
+ // without saving" was the quietest way to commit.
896
+ cancelEdit();
630
897
  }
631
- }, children: renderOption(optionName, optionField, 'small', true) }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowActions, { children: [draftChip, revertButton, clearValueButton, inlineOptionActions.map(function (action, index) {
898
+ }, children: [panelMessages.length ?
899
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-info-panel', vertical: true, fluid: true, gapSize: 'normal', children: panelMessages.map(renderInfoStrip) })
900
+ : 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) {
632
901
  return renderInjectedOptionAction(action, index);
633
902
  }), moreMenu, closeExpandedFieldButton] }), clusterNode] }), optionName));
634
903
  // ALWAYS wrap the editing row in the same StyledColumn so its parent stays
@@ -647,10 +916,10 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
647
916
  var cardBadges = schemaBadge !== undefined && schemaBadge !== null ?
648
917
  (Array.isArray(schemaBadge) ? schemaBadge : [schemaBadge])
649
918
  : [];
650
- 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'; })) || [];
919
+ 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'; })) || [];
651
920
  var cardTags = ((schema === null || schema === void 0 ? void 0 : schema.tags) || []);
652
921
  var schemaIntentColor = (schema === null || schema === void 0 ? void 0 : schema.intent) ?
653
- (_g = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _g === void 0 ? void 0 : _g[schema.intent]
922
+ (_j = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _j === void 0 ? void 0 : _j[schema.intent]
654
923
  : undefined;
655
924
  return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledEditCard, { "data-field": optionName, className: COMPACT_SINGLE_VALUE_TYPES.has(editType) ?
656
925
  'options-readfirst-card options-readfirst-card-single'
@@ -679,7 +948,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
679
948
  return renderInjectedOptionAction(action, index);
680
949
  }), hasValue && !readOnly ?
681
950
  (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 })
682
- : 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 ?
951
+ : 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 ?
683
952
  (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 })
684
953
  : null, renderOption(optionName, optionField)] })] }, optionName));
685
954
  }
@@ -693,7 +962,6 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
693
962
  : []), true);
694
963
  // A hash row reveals its sub-fields as read-only sub-rows under a "view
695
964
  // more" disclosure; the row itself still expands the real editor on click.
696
- var valueType = (0, readFirst_1.getValueType)(optionField, schema);
697
965
  var hashEntries = (!hidden &&
698
966
  (valueType === 'hash' || valueType === 'free-hash') &&
699
967
  (schema === null || schema === void 0 ? void 0 : schema.ui_type) !== 'schema-definition') ?
@@ -708,6 +976,9 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
708
976
  Array.isArray(optionField === null || optionField === void 0 ? void 0 : optionField.value) &&
709
977
  optionField.value.length > 0 &&
710
978
  optionField.value.some(function (item) {
979
+ if ((0, exports.richtextItemText)(item) !== undefined) {
980
+ return false;
981
+ }
711
982
  var inner = item && typeof item === 'object' && 'value' in item ?
712
983
  item.value
713
984
  : item;
@@ -723,6 +994,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
723
994
  valueType === 'code-editor' &&
724
995
  typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' &&
725
996
  optionField.value.length > 0;
997
+ // A richtext value that renders as CHIPS is drawn in full by the row itself:
998
+ // the chips are the value, and the reader is looking straight at it. The
999
+ // native `title` below would then hover the raw source of the very thing the
1000
+ // chips replace ("[$fsminput:severity] $fsminput:alert_code") — and, because
1001
+ // each chip carries its own Reqore tooltip, hovering one fires BOTH: the chip
1002
+ // popover and the row's browser tooltip, in different places, saying almost
1003
+ // the same thing. Only the popover shows up in a screenshot, which is what
1004
+ // made the pair hard to report.
1005
+ var showsTemplateChips = !hidden &&
1006
+ valueType === 'richtext' &&
1007
+ Array.isArray(optionField === null || optionField === void 0 ? void 0 : optionField.value) &&
1008
+ (0, common_1.richtextToSegments)(optionField.value).some(function (segment) { return segment.kind === 'tag'; });
726
1009
  // Markdown reads the same way for the same reason: the row itself can only
727
1010
  // show a line of text, and for markdown that line is the SOURCE — the reader
728
1011
  // gets `## ` and `**` where the point of the value is what it looks like
@@ -831,7 +1114,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
831
1114
  (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' })
832
1115
  : null;
833
1116
  var rowSchemaIntentColor = (schema === null || schema === void 0 ? void 0 : schema.intent) ?
834
- (_h = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _h === void 0 ? void 0 : _h[schema.intent]
1117
+ (_k = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _k === void 0 ? void 0 : _k[schema.intent]
835
1118
  : undefined;
836
1119
  var rowStripeColor = (showStripe ? intentColor : undefined) || rowSchemaIntentColor;
837
1120
  // Intent stripe on the block ROOT so it spans the field's whole territory:
@@ -846,7 +1129,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
846
1129
  // boxes — so the dot and the box can never disagree). Hidden (not-yet-added)
847
1130
  // and dependency-locked rows show no dot (the add/lock affordance speaks for
848
1131
  // them). worstIntent already folds in schema + validation messages.
849
- var cSuccess = (_j = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _j === void 0 ? void 0 : _j.success;
1132
+ var cSuccess = (_l = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _l === void 0 ? void 0 : _l.success;
850
1133
  var rowStatus = (0, readFirst_1.getReadFirstStatus)({
851
1134
  empty: empty,
852
1135
  required: required,
@@ -864,40 +1147,84 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
864
1147
  event.preventDefault();
865
1148
  activate(event);
866
1149
  }
867
- } }, 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 ?
1150
+ } }, 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 ?
868
1151
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px', margin: 'left', marginSize: 'tiny' })
869
1152
  : null, helpIcon] }), typeLabel ?
870
1153
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'tiny', minimal: true, label: typeLabel, labelEffect: { opacity: 0.55 } })
871
1154
  : null] }), showLabelDesc ?
872
1155
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledLabelDesc, { className: 'options-readfirst-label-desc', size: 'small', effect: { opacity: 0.55 }, children: labelShortDesc })
873
- : null, lineCountNote ?
1156
+ : null, codeSizeNode, lineCountNote ?
874
1157
  (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 })
875
1158
  : null] }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowValue
876
1159
  // A code field draws its whole value in the preview below, with
877
1160
  // "Show more" for the rest, so a hover carrying the same text is
878
1161
  // noise -- and a native tooltip holding a few hundred lines is
879
- // unreadable anyway. Every other value keeps its hover, which is the
880
- // only way to read one that the row had to truncate.
1162
+ // unreadable anyway. A chipped richtext value is the same case: the row
1163
+ // already draws it in full, and its chips carry their own tooltips.
1164
+ // Every other value keeps its hover, which is the only way to read one
1165
+ // that the row had to truncate.
881
1166
  , {
882
1167
  // A code field draws its whole value in the preview below, with
883
1168
  // "Show more" for the rest, so a hover carrying the same text is
884
1169
  // noise -- and a native tooltip holding a few hundred lines is
885
- // unreadable anyway. Every other value keeps its hover, which is the
886
- // only way to read one that the row had to truncate.
1170
+ // unreadable anyway. A chipped richtext value is the same case: the row
1171
+ // already draws it in full, and its chips carry their own tooltips.
1172
+ // Every other value keeps its hover, which is the only way to read one
1173
+ // that the row had to truncate.
887
1174
  title: (!empty &&
888
1175
  !hidden &&
889
1176
  !showCodePreview &&
890
1177
  !showMarkdownPreview &&
1178
+ !showsTemplateChips &&
891
1179
  typeof formatted === 'string') ?
892
1180
  formatted
893
- : undefined, "$color": empty || hidden ? "".concat(cMuted, "66") : cKey, "$empty": empty || hidden, children: [showMarkdownPreview ? 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 ?
894
- (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-info-panel', children: panelMessages.map(renderInfoStrip) })
1181
+ : 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 ?
1182
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-info-panel', vertical: true, fluid: true, gapSize: 'normal', children: panelMessages.map(renderInfoStrip) })
895
1183
  : null, showStructuredPreview ?
896
1184
  // The inset lives inside the row now, so a click on a value chip would
897
1185
  // bubble to the row's onClick and fire activate() a SECOND time (the
898
1186
  // chip's onItemClick already calls it) — toggling the editor shut again.
899
1187
  // Stop the bubble here; the chip's own handler still opens the editor.
900
- (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledRowInset, { className: 'options-readfirst-inset', onClick: function (e) { return e.stopPropagation(); }, children: (0, jsx_runtime_1.jsx)(reqore_1.ReqoreCollapsibleContent, { maxCollapsedHeight: 96, buttonProps: { className: 'options-readfirst-viewmore' }, children: (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-structured', children: (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(); } }) }) }) })
1188
+ (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledRowInset, { className: 'options-readfirst-inset', onClick: function (e) { return e.stopPropagation(); }, children: (0, jsx_runtime_1.jsx)(reqore_1.ReqoreCollapsibleContent
1189
+ // The schema view spends more height per datum than a data tree
1190
+ // does — a labelled row rather than a packed chip — but there is
1191
+ // far less of it to read, so it gets enough room to show a
1192
+ // couple of complete items instead of fading out mid-row. A tree
1193
+ // of unknown depth keeps the tighter cap.
1194
+ , {
1195
+ // The schema view spends more height per datum than a data tree
1196
+ // does — a labelled row rather than a packed chip — but there is
1197
+ // far less of it to read, so it gets enough room to show a
1198
+ // couple of complete items instead of fading out mid-row. A tree
1199
+ // of unknown depth keeps the tighter cap.
1200
+ maxCollapsedHeight: previewWithSchema ? 140 : 96, buttonProps: { className: 'options-readfirst-viewmore' }, children: (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-structured', children: previewWithSchema ?
1201
+ // The form already knows this value's shape, names and
1202
+ // choices, so the preview says it rather than making the
1203
+ // reader decode it: "Scheme Type — Default RBAC", not a data
1204
+ // tree announcing "Object · 1 field" over `type: default`.
1205
+ (0, jsx_runtime_1.jsx)(SchemaDataView_1.SchemaDataView, { value: optionField === null || optionField === void 0 ? void 0 : optionField.value, schema: previewArgSchema, showTypes: showFieldTypes, colors: {
1206
+ key: cKey,
1207
+ muted: cMuted,
1208
+ // Deliberately stronger than `cDivider`. That tier is for
1209
+ // decorative hairlines between rows, where being nearly
1210
+ // invisible is the point. This rule is load-bearing — it
1211
+ // is the only thing saying which fields belong to which
1212
+ // numbered item — so it gets the muted tier at partial
1213
+ // alpha: quiet, but actually visible.
1214
+ border: "".concat(cMuted, "66"),
1215
+ // The identity accent for each item's heading.
1216
+ //
1217
+ // `custom1` first: BRAND_DESIGN §1 says apps may register
1218
+ // their own named intents and reference them like the
1219
+ // built-ins, and that is where a product's own accent
1220
+ // lives (qorus-ide registers its brand purple there).
1221
+ // Falling back to `info` keeps this working for a
1222
+ // consumer that registers nothing — the heading is
1223
+ // accented either way, just in the theme's own colour
1224
+ // rather than one this library picked.
1225
+ accent: ((_m = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _m === void 0 ? void 0 : _m.custom1) || cInfo,
1226
+ }, onItemClick: function () { return activate(); } })
1227
+ : (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(); } }) }) }) })
901
1228
  : null, showCodePreview ?
902
1229
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledRowInset, { className: 'options-readfirst-inset options-readfirst-code-inset', onClick: function (e) { return e.stopPropagation(); }, children: (0, jsx_runtime_1.jsx)(reqore_1.ReqoreCollapsibleContent, { maxCollapsedHeight: 96, buttonProps: { className: 'options-readfirst-viewmore' }, children: codePreviewRenderer ?
903
1230
  codePreviewRenderer({