@qoretechnologies/reqraft 0.10.39-pr.99.gdbafa34 → 0.10.39

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 (110) 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 +365 -30
  9. package/dist/components/form/engine/CompactRow.js.map +1 -1
  10. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  11. package/dist/components/form/engine/CompactToolbar.js +6 -8
  12. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  13. package/dist/components/form/engine/FormEngine.d.ts +24 -45
  14. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  15. package/dist/components/form/engine/FormEngine.js +211 -84
  16. package/dist/components/form/engine/FormEngine.js.map +1 -1
  17. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts +37 -0
  18. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -0
  19. package/dist/components/form/engine/_structuredData/SchemaDataView.js +335 -0
  20. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -0
  21. package/dist/components/form/engine/compactRowStyles.d.ts +13 -0
  22. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  23. package/dist/components/form/engine/compactRowStyles.js +30 -5
  24. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  25. package/dist/components/form/engine/compactToolbarContext.d.ts +0 -8
  26. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  27. package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
  28. package/dist/components/form/engine/readFirst.d.ts +73 -1
  29. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  30. package/dist/components/form/engine/readFirst.js +175 -5
  31. package/dist/components/form/engine/readFirst.js.map +1 -1
  32. package/dist/components/form/fields/Field.d.ts.map +1 -1
  33. package/dist/components/form/fields/Field.js +1 -1
  34. package/dist/components/form/fields/Field.js.map +1 -1
  35. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +12 -2
  36. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  37. package/dist/components/form/fields/allowed-values/AllowedValues.js +16 -6
  38. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  39. package/dist/components/form/fields/array/ArrayAuto.d.ts.map +1 -1
  40. package/dist/components/form/fields/array/ArrayAuto.js +51 -21
  41. package/dist/components/form/fields/array/ArrayAuto.js.map +1 -1
  42. package/dist/components/form/fields/array/ArrayAutoField.d.ts.map +1 -1
  43. package/dist/components/form/fields/array/ArrayAutoField.js +42 -25
  44. package/dist/components/form/fields/array/ArrayAutoField.js.map +1 -1
  45. package/dist/components/form/fields/auto/AutoFormField.d.ts +4 -0
  46. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  47. package/dist/components/form/fields/auto/AutoFormField.js +29 -4
  48. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  49. package/dist/components/form/fields/long-string/LongString.d.ts +9 -1
  50. package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
  51. package/dist/components/form/fields/long-string/LongString.js +25 -4
  52. package/dist/components/form/fields/long-string/LongString.js.map +1 -1
  53. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  54. package/dist/components/form/fields/template/TemplateField.js +12 -2
  55. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  56. package/dist/helpers/common.d.ts +8 -1
  57. package/dist/helpers/common.d.ts.map +1 -1
  58. package/dist/helpers/common.js +9 -1
  59. package/dist/helpers/common.js.map +1 -1
  60. package/dist/helpers/optionUiTypes.d.ts +30 -0
  61. package/dist/helpers/optionUiTypes.d.ts.map +1 -0
  62. package/dist/helpers/optionUiTypes.js +148 -0
  63. package/dist/helpers/optionUiTypes.js.map +1 -0
  64. package/dist/helpers/options.d.ts +19 -0
  65. package/dist/helpers/options.d.ts.map +1 -1
  66. package/dist/helpers/options.js +25 -1
  67. package/dist/helpers/options.js.map +1 -1
  68. package/dist/helpers/providerValue.d.ts +68 -0
  69. package/dist/helpers/providerValue.d.ts.map +1 -0
  70. package/dist/helpers/providerValue.js +50 -0
  71. package/dist/helpers/providerValue.js.map +1 -0
  72. package/dist/helpers/singleLineString.d.ts +37 -0
  73. package/dist/helpers/singleLineString.d.ts.map +1 -0
  74. package/dist/helpers/singleLineString.js +66 -0
  75. package/dist/helpers/singleLineString.js.map +1 -0
  76. package/dist/helpers/validations.d.ts +85 -2
  77. package/dist/helpers/validations.d.ts.map +1 -1
  78. package/dist/helpers/validations.js +802 -76
  79. package/dist/helpers/validations.js.map +1 -1
  80. package/dist/index.d.ts +1 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +1 -0
  83. package/dist/index.js.map +1 -1
  84. package/package.json +1 -1
  85. package/src/components/codeSize/index.tsx +79 -0
  86. package/src/components/form/engine/CompactRow.tsx +450 -31
  87. package/src/components/form/engine/CompactToolbar.tsx +16 -21
  88. package/src/components/form/engine/FormEngine.stories.tsx +804 -17
  89. package/src/components/form/engine/FormEngine.tsx +207 -105
  90. package/src/components/form/engine/_structuredData/SchemaDataView.stories.tsx +233 -0
  91. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +630 -0
  92. package/src/components/form/engine/compactRowStyles.ts +44 -2
  93. package/src/components/form/engine/compactToolbarContext.ts +0 -8
  94. package/src/components/form/engine/readFirst.ts +201 -5
  95. package/src/components/form/fields/Field.tsx +3 -1
  96. package/src/components/form/fields/allowed-values/AllowedValues.tsx +24 -2
  97. package/src/components/form/fields/array/ArrayAuto.tsx +35 -4
  98. package/src/components/form/fields/array/ArrayAutoField.stories.tsx +134 -0
  99. package/src/components/form/fields/array/ArrayAutoField.tsx +22 -4
  100. package/src/components/form/fields/auto/AutoFormField.tsx +30 -1
  101. package/src/components/form/fields/long-string/LongString.tsx +46 -5
  102. package/src/components/form/fields/template/TemplateField.tsx +16 -1
  103. package/src/helpers/common.ts +11 -1
  104. package/src/helpers/optionUiTypes.ts +153 -0
  105. package/src/helpers/options.ts +23 -0
  106. package/src/helpers/providerValue.ts +125 -0
  107. package/src/helpers/singleLineString.ts +61 -0
  108. package/src/helpers/validations.ts +1105 -80
  109. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +23 -2
  110. 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,56 @@ 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 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;
612
883
  if (isExpanded) {
613
884
  if (inlineEditable) {
614
885
  var collapse_1 = function () { return toggleExpandedOption(optionName); };
615
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] ?
616
887
  { 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) {
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) {
618
889
  if (event.key === 'Enter' || event.key === ' ') {
619
890
  event.preventDefault();
620
891
  collapse_1();
@@ -623,12 +894,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
623
894
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px' })
624
895
  : null, helpIcon] }), labelShortDesc ?
625
896
  (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) {
897
+ : null, codeSizeNode] }), (0, jsx_runtime_1.jsxs)("div", { ref: editorRef, style: { minWidth: 0 }, onKeyDown: function (event) {
627
898
  if (event.key === 'Escape') {
628
899
  event.stopPropagation();
629
- 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();
630
905
  }
631
- }, children: 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) {
632
909
  return renderInjectedOptionAction(action, index);
633
910
  }), moreMenu, closeExpandedFieldButton] }), clusterNode] }), optionName));
634
911
  // ALWAYS wrap the editing row in the same StyledColumn so its parent stays
@@ -647,10 +924,10 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
647
924
  var cardBadges = schemaBadge !== undefined && schemaBadge !== null ?
648
925
  (Array.isArray(schemaBadge) ? schemaBadge : [schemaBadge])
649
926
  : [];
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'; })) || [];
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'; })) || [];
651
928
  var cardTags = ((schema === null || schema === void 0 ? void 0 : schema.tags) || []);
652
929
  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]
930
+ (_j = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _j === void 0 ? void 0 : _j[schema.intent]
654
931
  : undefined;
655
932
  return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledEditCard, { "data-field": optionName, className: COMPACT_SINGLE_VALUE_TYPES.has(editType) ?
656
933
  'options-readfirst-card options-readfirst-card-single'
@@ -679,7 +956,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
679
956
  return renderInjectedOptionAction(action, index);
680
957
  }), hasValue && !readOnly ?
681
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 })
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 ?
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 ?
683
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 })
684
961
  : null, renderOption(optionName, optionField)] })] }, optionName));
685
962
  }
@@ -693,7 +970,6 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
693
970
  : []), true);
694
971
  // A hash row reveals its sub-fields as read-only sub-rows under a "view
695
972
  // more" disclosure; the row itself still expands the real editor on click.
696
- var valueType = (0, readFirst_1.getValueType)(optionField, schema);
697
973
  var hashEntries = (!hidden &&
698
974
  (valueType === 'hash' || valueType === 'free-hash') &&
699
975
  (schema === null || schema === void 0 ? void 0 : schema.ui_type) !== 'schema-definition') ?
@@ -708,6 +984,9 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
708
984
  Array.isArray(optionField === null || optionField === void 0 ? void 0 : optionField.value) &&
709
985
  optionField.value.length > 0 &&
710
986
  optionField.value.some(function (item) {
987
+ if ((0, exports.richtextItemText)(item) !== undefined) {
988
+ return false;
989
+ }
711
990
  var inner = item && typeof item === 'object' && 'value' in item ?
712
991
  item.value
713
992
  : item;
@@ -723,6 +1002,18 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
723
1002
  valueType === 'code-editor' &&
724
1003
  typeof (optionField === null || optionField === void 0 ? void 0 : optionField.value) === 'string' &&
725
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'; });
726
1017
  // Markdown reads the same way for the same reason: the row itself can only
727
1018
  // show a line of text, and for markdown that line is the SOURCE — the reader
728
1019
  // gets `## ` and `**` where the point of the value is what it looks like
@@ -831,7 +1122,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
831
1122
  (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
1123
  : null;
833
1124
  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]
1125
+ (_k = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _k === void 0 ? void 0 : _k[schema.intent]
835
1126
  : undefined;
836
1127
  var rowStripeColor = (showStripe ? intentColor : undefined) || rowSchemaIntentColor;
837
1128
  // Intent stripe on the block ROOT so it spans the field's whole territory:
@@ -846,7 +1137,7 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
846
1137
  // boxes — so the dot and the box can never disagree). Hidden (not-yet-added)
847
1138
  // and dependency-locked rows show no dot (the add/lock affordance speaks for
848
1139
  // 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;
1140
+ var cSuccess = (_l = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _l === void 0 ? void 0 : _l.success;
850
1141
  var rowStatus = (0, readFirst_1.getReadFirstStatus)({
851
1142
  empty: empty,
852
1143
  required: required,
@@ -864,40 +1155,84 @@ exports.CompactRow = (0, react_1.memo)(function (_a) {
864
1155
  event.preventDefault();
865
1156
  activate(event);
866
1157
  }
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 ?
1158
+ } }, 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
1159
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'Asterisk', color: 'danger', size: '10px', margin: 'left', marginSize: 'tiny' })
869
1160
  : null, helpIcon] }), typeLabel ?
870
1161
  (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'tiny', minimal: true, label: typeLabel, labelEffect: { opacity: 0.55 } })
871
1162
  : null] }), showLabelDesc ?
872
1163
  (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledLabelDesc, { className: 'options-readfirst-label-desc', size: 'small', effect: { opacity: 0.55 }, children: labelShortDesc })
873
- : null, lineCountNote ?
1164
+ : null, codeSizeNode, lineCountNote ?
874
1165
  (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
1166
  : null] }), (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRowValue
876
1167
  // A code field draws its whole value in the preview below, with
877
1168
  // "Show more" for the rest, so a hover carrying the same text is
878
1169
  // 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.
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.
881
1174
  , {
882
1175
  // A code field draws its whole value in the preview below, with
883
1176
  // "Show more" for the rest, so a hover carrying the same text is
884
1177
  // 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.
1178
+ // unreadable anyway. A chipped richtext value is the same case: the row
1179
+ // already draws it in full, and its chips carry their own tooltips.
1180
+ // Every other value keeps its hover, which is the only way to read one
1181
+ // that the row had to truncate.
887
1182
  title: (!empty &&
888
1183
  !hidden &&
889
1184
  !showCodePreview &&
890
1185
  !showMarkdownPreview &&
1186
+ !showsTemplateChips &&
891
1187
  typeof formatted === 'string') ?
892
1188
  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) })
1189
+ : 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 ?
1190
+ (0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-info-panel', vertical: true, fluid: true, gapSize: 'normal', children: panelMessages.map(renderInfoStrip) })
895
1191
  : null, showStructuredPreview ?
896
1192
  // The inset lives inside the row now, so a click on a value chip would
897
1193
  // bubble to the row's onClick and fire activate() a SECOND time (the
898
1194
  // chip's onItemClick already calls it) — toggling the editor shut again.
899
1195
  // 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(); } }) }) }) })
1196
+ (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
1197
+ // The schema view spends more height per datum than a data tree
1198
+ // does — a labelled row rather than a packed chip — but there is
1199
+ // far less of it to read, so it gets enough room to show a
1200
+ // couple of complete items instead of fading out mid-row. A tree
1201
+ // of unknown depth keeps the tighter cap.
1202
+ , {
1203
+ // The schema view spends more height per datum than a data tree
1204
+ // does — a labelled row rather than a packed chip — but there is
1205
+ // far less of it to read, so it gets enough room to show a
1206
+ // couple of complete items instead of fading out mid-row. A tree
1207
+ // of unknown depth keeps the tighter cap.
1208
+ maxCollapsedHeight: previewWithSchema ? 140 : 96, buttonProps: { className: 'options-readfirst-viewmore' }, children: (0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-structured', children: previewWithSchema ?
1209
+ // The form already knows this value's shape, names and
1210
+ // choices, so the preview says it rather than making the
1211
+ // reader decode it: "Scheme Type — Default RBAC", not a data
1212
+ // tree announcing "Object · 1 field" over `type: default`.
1213
+ (0, jsx_runtime_1.jsx)(SchemaDataView_1.SchemaDataView, { value: optionField === null || optionField === void 0 ? void 0 : optionField.value, schema: previewArgSchema, showTypes: showFieldTypes, colors: {
1214
+ key: cKey,
1215
+ muted: cMuted,
1216
+ // Deliberately stronger than `cDivider`. That tier is for
1217
+ // decorative hairlines between rows, where being nearly
1218
+ // invisible is the point. This rule is load-bearing — it
1219
+ // is the only thing saying which fields belong to which
1220
+ // numbered item — so it gets the muted tier at partial
1221
+ // alpha: quiet, but actually visible.
1222
+ border: "".concat(cMuted, "66"),
1223
+ // The identity accent for each item's heading.
1224
+ //
1225
+ // `custom1` first: BRAND_DESIGN §1 says apps may register
1226
+ // their own named intents and reference them like the
1227
+ // built-ins, and that is where a product's own accent
1228
+ // lives (qorus-ide registers its brand purple there).
1229
+ // Falling back to `info` keeps this working for a
1230
+ // consumer that registers nothing — the heading is
1231
+ // accented either way, just in the theme's own colour
1232
+ // rather than one this library picked.
1233
+ accent: ((_m = theme === null || theme === void 0 ? void 0 : theme.intents) === null || _m === void 0 ? void 0 : _m.custom1) || cInfo,
1234
+ }, onItemClick: function () { return activate(); } })
1235
+ : (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
1236
  : null, showCodePreview ?
902
1237
  (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
1238
  codePreviewRenderer({