@qoretechnologies/reqraft 0.10.2 → 0.10.5
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.
- package/.claude/CLAUDE.md +5 -0
- package/design/COMPACT_ENGINE_REDESIGN.md +156 -0
- package/design/FORM_ENGINE_COMPACT_UX_PLAN.md +353 -0
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +158 -101
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
- package/dist/components/form/engine/CompactToolbar.js +122 -105
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +9 -1
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +272 -82
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/compactRowStyles.d.ts +6 -3
- package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +76 -49
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
- package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
- package/dist/components/form/engine/readFirst.d.ts +19 -0
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +22 -1
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/variants/VariantCalmTable.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantCalmTable.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantCalmTable.js +94 -0
- package/dist/components/form/engine/variants/VariantCalmTable.js.map +1 -0
- package/dist/components/form/engine/variants/VariantCards.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantCards.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantCards.js +80 -0
- package/dist/components/form/engine/variants/VariantCards.js.map +1 -0
- package/dist/components/form/engine/variants/VariantFocus.d.ts +7 -0
- package/dist/components/form/engine/variants/VariantFocus.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantFocus.js +138 -0
- package/dist/components/form/engine/variants/VariantFocus.js.map +1 -0
- package/dist/components/form/engine/variants/VariantMinimal.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantMinimal.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantMinimal.js +73 -0
- package/dist/components/form/engine/variants/VariantMinimal.js.map +1 -0
- package/dist/components/form/engine/variants/focusDemo.d.ts +13 -0
- package/dist/components/form/engine/variants/focusDemo.d.ts.map +1 -0
- package/dist/components/form/engine/variants/focusDemo.js +139 -0
- package/dist/components/form/engine/variants/focusDemo.js.map +1 -0
- package/dist/components/form/engine/variants/variantModel.d.ts +70 -0
- package/dist/components/form/engine/variants/variantModel.d.ts.map +1 -0
- package/dist/components/form/engine/variants/variantModel.js +133 -0
- package/dist/components/form/engine/variants/variantModel.js.map +1 -0
- package/dist/components/form/engine/variants/variantParts.d.ts +79 -0
- package/dist/components/form/engine/variants/variantParts.d.ts.map +1 -0
- package/dist/components/form/engine/variants/variantParts.js +191 -0
- package/dist/components/form/engine/variants/variantParts.js.map +1 -0
- package/dist/components/form/fields/auto/AutoFormField.d.ts +3 -0
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +5 -2
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/package.json +1 -1
- package/src/components/form/engine/CompactRow.tsx +273 -258
- package/src/components/form/engine/CompactToolbar.tsx +112 -85
- package/src/components/form/engine/FormEngine.stories.tsx +239 -115
- package/src/components/form/engine/FormEngine.tsx +332 -83
- package/src/components/form/engine/compactRowStyles.ts +221 -144
- package/src/components/form/engine/compactToolbarContext.ts +1 -0
- package/src/components/form/engine/readFirst.ts +35 -0
- package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +119 -0
- package/src/components/form/engine/variants/VariantCalmTable.tsx +242 -0
- package/src/components/form/engine/variants/VariantCards.tsx +212 -0
- package/src/components/form/engine/variants/VariantFocus.tsx +382 -0
- package/src/components/form/engine/variants/VariantMinimal.tsx +170 -0
- package/src/components/form/engine/variants/focusDemo.ts +145 -0
- package/src/components/form/engine/variants/variantModel.ts +216 -0
- package/src/components/form/engine/variants/variantParts.tsx +313 -0
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +9 -2
- package/src/components/form/fields/auto/AutoFormField.tsx +8 -0
|
@@ -297,40 +297,44 @@ var FormEngine = function (_a) {
|
|
|
297
297
|
var _b, _c, _d, _f, _g;
|
|
298
298
|
var name = _a.name, uniqueName = _a.uniqueName, value = _a.value, onChange = _a.onChange, onSingleOptionsChange = _a.onSingleOptionsChange, onDependableOptionChange = _a.onDependableOptionChange, placeholder = _a.placeholder, noValueString = _a.noValueString, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
299
299
|
isValid = _a.isValid, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
300
|
-
url = _a.url, customUrl = _a.customUrl, operatorsUrl = _a.operatorsUrl, onOptionsLoaded = _a.onOptionsLoaded, recordRequiresSearchOptions = _a.recordRequiresSearchOptions, readOnly = _a.readOnly, _h = _a.allowTemplates, allowTemplates = _h === void 0 ? true : _h, interfaceContext = _a.interfaceContext, templateFieldProps = _a.templateFieldProps, _j = _a.showTypeToggle, showTypeToggle = _j === void 0 ? true : _j, compact = _a.compact, _k = _a.compactFlush, compactFlush = _k === void 0 ? false : _k, _l = _a.commitMode, commitMode =
|
|
301
|
-
var
|
|
300
|
+
url = _a.url, customUrl = _a.customUrl, operatorsUrl = _a.operatorsUrl, onOptionsLoaded = _a.onOptionsLoaded, recordRequiresSearchOptions = _a.recordRequiresSearchOptions, readOnly = _a.readOnly, _h = _a.allowTemplates, allowTemplates = _h === void 0 ? true : _h, interfaceContext = _a.interfaceContext, templateFieldProps = _a.templateFieldProps, _j = _a.showTypeToggle, showTypeToggle = _j === void 0 ? true : _j, compact = _a.compact, _k = _a.compactFlush, compactFlush = _k === void 0 ? false : _k, _l = _a.compactNested, compactNested = _l === void 0 ? false : _l, _m = _a.commitMode, commitMode = _m === void 0 ? 'immediate' : _m, _o = _a.expandMode, expandMode = _o === void 0 ? 'single' : _o, onCommit = _a.onCommit, operatorsProp = _a.operators, groups = _a.groups, optionsLoader = _a.optionsLoader, onValidityChange = _a.onValidityChange, optionActions = _a.optionActions, componentOverrides = _a.componentOverrides, rest = __rest(_a, ["name", "uniqueName", "value", "onChange", "onSingleOptionsChange", "onDependableOptionChange", "placeholder", "noValueString", "isValid", "url", "customUrl", "operatorsUrl", "onOptionsLoaded", "recordRequiresSearchOptions", "readOnly", "allowTemplates", "interfaceContext", "templateFieldProps", "showTypeToggle", "compact", "compactFlush", "compactNested", "commitMode", "expandMode", "onCommit", "operators", "groups", "optionsLoader", "onValidityChange", "optionActions", "componentOverrides"]);
|
|
301
|
+
var _p = (0, react_2.useState)((rest === null || rest === void 0 ? void 0 : rest.options) || undefined), options = _p[0], setOptions = _p[1];
|
|
302
302
|
// optionsLoader lifecycle: loading feeds the skeleton gate, error the banner.
|
|
303
|
-
var
|
|
304
|
-
var
|
|
303
|
+
var _q = (0, react_2.useState)(!!optionsLoader && !(rest === null || rest === void 0 ? void 0 : rest.options)), optionsLoading = _q[0], setOptionsLoading = _q[1];
|
|
304
|
+
var _r = (0, react_2.useState)(), optionsError = _r[0], setOptionsError = _r[1];
|
|
305
305
|
// Operators: prop-provided (compact) or fetched via operatorsUrl (dpql,
|
|
306
306
|
// ported from IDE Options) — the fetch overrides the seeded prop value.
|
|
307
|
-
var
|
|
307
|
+
var _s = (0, react_2.useState)(operatorsProp), operators = _s[0], setOperators = _s[1];
|
|
308
308
|
// Remote-fetch loading (ported from IDE Options); only relevant when one of
|
|
309
309
|
// the fetch urls is set — schema-as-props consumers never see the skeleton.
|
|
310
|
-
var
|
|
310
|
+
var _t = (0, react_2.useState)(!!(url || customUrl || operatorsUrl)), loading = _t[0], setLoading = _t[1];
|
|
311
311
|
var confirmAction = (0, reqore_1.useReqoreProperty)('confirmAction');
|
|
312
312
|
var theme = (0, reqore_1.useReqoreTheme)();
|
|
313
|
-
var
|
|
314
|
-
var
|
|
313
|
+
var _u = (0, react_2.useState)(), focusedEditing = _u[0], setFocusedEditing = _u[1];
|
|
314
|
+
var _v = (0, react_2.useState)(false), showFieldTypes = _v[0], setShowFieldTypes = _v[1];
|
|
315
315
|
// Global toggle (toolbar ⓘ): reveal the short-description info panel on every
|
|
316
316
|
// field that has a short_desc. Per-row ⓘ overrides still win over it.
|
|
317
317
|
// Global field-info visibility, tri-state: `undefined` = default (critical
|
|
318
318
|
// messages auto-open, the rest closed); `true` = show all; `false` = hide all
|
|
319
319
|
// (even message fields). The toolbar ⓘ drives it.
|
|
320
|
-
var
|
|
321
|
-
var
|
|
322
|
-
var
|
|
320
|
+
var _w = (0, react_2.useState)(undefined), showAllDescriptions = _w[0], setShowAllDescriptions = _w[1];
|
|
321
|
+
var _x = (0, react_2.useState)(), showHelpForOption = _x[0], setShowHelpForOption = _x[1];
|
|
322
|
+
var _y = (0, react_2.useState)(false), showInvalidOptionsOnly = _y[0], setShowInvalidOptionsOnly = _y[1];
|
|
323
323
|
// Which options are expanded into their editor (several can be open at once).
|
|
324
|
-
var
|
|
324
|
+
var _z = (0, react_2.useState)([]), expandedOptions = _z[0], setExpandedOptions = _z[1];
|
|
325
|
+
// Remembers each row's last settled status box, so an actively-edited field
|
|
326
|
+
// stays put when its status flips (e.g. becomes valid) instead of jumping to
|
|
327
|
+
// another box mid-edit and stealing focus. Keyed by option name.
|
|
328
|
+
var settledBucket = (0, react_2.useRef)({});
|
|
325
329
|
// Measured form width (not viewport — the form lives in drawers/panels of
|
|
326
330
|
// arbitrary width) drives the stacked narrow layout.
|
|
327
|
-
var
|
|
331
|
+
var _0 = (0, react_use_1.useMeasure)(), compactWrapRef = _0[0], compactWrapWidth = _0[1].width;
|
|
328
332
|
// Own handle on the scroll wrap (useMeasure's ref is a callback, no `.current`)
|
|
329
333
|
// so the label-column measurement can publish its CSS var on the element. It's
|
|
330
334
|
// STATE, not a ref: the wrap mounts only after the loading-skeleton gate
|
|
331
335
|
// resolves, so the measurement effect must re-run when the node appears — a
|
|
332
336
|
// ref wouldn't retrigger it.
|
|
333
|
-
var
|
|
337
|
+
var _1 = (0, react_2.useState)(null), compactWrapNode = _1[0], setCompactWrapNode = _1[1];
|
|
334
338
|
var setCompactWrap = (0, react_2.useCallback)(function (node) {
|
|
335
339
|
compactWrapRef(node);
|
|
336
340
|
setCompactWrapNode(function (prev) { return (prev === node ? prev : node); });
|
|
@@ -367,15 +371,21 @@ var FormEngine = function (_a) {
|
|
|
367
371
|
var readRowHeights = (0, react_2.useRef)({});
|
|
368
372
|
// Required-groups linkage: hovering a group chip highlights every member row;
|
|
369
373
|
// clicking a sibling in the chip's popover scrolls to it and flashes it.
|
|
370
|
-
var
|
|
371
|
-
var
|
|
374
|
+
var _2 = (0, react_2.useState)([]), highlightedOptions = _2[0], setHighlightedOptions = _2[1];
|
|
375
|
+
var _3 = (0, react_2.useState)([]), flashedOptions = _3[0], setFlashedOptions = _3[1];
|
|
372
376
|
var flashTimeout = (0, react_2.useRef)();
|
|
373
377
|
var flashOptions = (0, react_2.useCallback)(function (optionNames, scrollToFirst) {
|
|
374
|
-
var _a;
|
|
375
378
|
if (scrollToFirst === void 0) { scrollToFirst = false; }
|
|
376
379
|
if (scrollToFirst && optionNames[0]) {
|
|
377
|
-
|
|
378
|
-
|
|
380
|
+
// Defer to the next frame: when this fires for a field that just changed
|
|
381
|
+
// panels, its row has only just re-mounted in the new box — scrolling in the
|
|
382
|
+
// same tick targets the stale (pre-move) layout, so the page doesn't budge.
|
|
383
|
+
// A rAF lets the new position settle first.
|
|
384
|
+
requestAnimationFrame(function () {
|
|
385
|
+
var _a;
|
|
386
|
+
(_a = document
|
|
387
|
+
.querySelector(".readfirst-row[data-field=\"".concat(optionNames[0], "\"]"))) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
|
388
|
+
});
|
|
379
389
|
}
|
|
380
390
|
setFlashedOptions(optionNames);
|
|
381
391
|
clearTimeout(flashTimeout.current);
|
|
@@ -383,18 +393,37 @@ var FormEngine = function (_a) {
|
|
|
383
393
|
}, []);
|
|
384
394
|
var flashOption = (0, react_2.useCallback)(function (optionName) { return flashOptions([optionName], true); }, [flashOptions]);
|
|
385
395
|
(0, react_2.useEffect)(function () { return function () { return clearTimeout(flashTimeout.current); }; }, []);
|
|
396
|
+
// Follow a field across panels: when its status bucket changes — e.g. you fill
|
|
397
|
+
// an optional field and it jumps to Set / Needs attention — scroll to its new
|
|
398
|
+
// row and flash it so it's easy to keep track of. `settledBucket` holds each
|
|
399
|
+
// field's current panel (frozen while the field is being edited, it re-buckets
|
|
400
|
+
// on collapse), so diffing it after every render catches the move the instant it
|
|
401
|
+
// lands in the new panel. Runs every render; the diff is cheap and only fires a
|
|
402
|
+
// scroll on an ACTUAL move of a non-expanded field.
|
|
403
|
+
var prevSettledBucket = (0, react_2.useRef)({});
|
|
404
|
+
(0, react_2.useEffect)(function () {
|
|
405
|
+
if (!compact)
|
|
406
|
+
return;
|
|
407
|
+
var cur = settledBucket.current;
|
|
408
|
+
var prev = prevSettledBucket.current;
|
|
409
|
+
var moved = Object.keys(cur).find(function (name) { return prev[name] && prev[name] !== cur[name] && !expandedOptions.includes(name); });
|
|
410
|
+
prevSettledBucket.current = __assign({}, cur);
|
|
411
|
+
if (moved) {
|
|
412
|
+
flashOptions([moved], true);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
386
415
|
var compactNarrow = !!compactWrapWidth && compactWrapWidth < 480;
|
|
387
416
|
// Info panels auto-open on Tier-1 content; the per-row user override sticks.
|
|
388
|
-
var
|
|
417
|
+
var _4 = (0, react_2.useState)({}), infoPanelOverrides = _4[0], setInfoPanelOverrides = _4[1];
|
|
389
418
|
// Toolbar filters affect the listed rows only — the meter reflects the full set.
|
|
390
|
-
var
|
|
391
|
-
var
|
|
419
|
+
var _5 = (0, react_2.useState)(false), requiredOnly = _5[0], setRequiredOnly = _5[1];
|
|
420
|
+
var _6 = (0, react_2.useState)(''), compactQuery = _6[0], setCompactQuery = _6[1];
|
|
392
421
|
// Compact field sort (Fields menu → "Sort by"); 'schema' = declared order.
|
|
393
|
-
var
|
|
394
|
-
var
|
|
422
|
+
var _7 = (0, react_2.useState)('schema'), compactSort = _7[0], setCompactSort = _7[1];
|
|
423
|
+
var _8 = (0, react_2.useState)(function () { return ({
|
|
395
424
|
fields: (0, exports.fixOptions)(value, options || {}),
|
|
396
425
|
meta: undefined,
|
|
397
|
-
}); }), localValue =
|
|
426
|
+
}); }), localValue = _8[0], setLocalValue = _8[1];
|
|
398
427
|
var originalValue = (0, react_2.useRef)();
|
|
399
428
|
// Track the last value we emitted via onChange so we can skip re-applying fixOptions
|
|
400
429
|
// when the parent echoes it back as the new value prop (controlled component loop prevention)
|
|
@@ -403,7 +432,7 @@ var FormEngine = function (_a) {
|
|
|
403
432
|
originalValue.current = localValue.fields;
|
|
404
433
|
}
|
|
405
434
|
var unavailableOptionsCount = (0, react_2.useRef)(0);
|
|
406
|
-
var
|
|
435
|
+
var _9 = (0, useQorusTypes_1.useQorusTypes)(), compactValue = _9.compactValue, typesLoading = _9.loading;
|
|
407
436
|
var templates = (0, useTemplates_1.useTemplates)(allowTemplates, rest.stringTemplates, interfaceContext);
|
|
408
437
|
(0, react_2.useEffect)(function () {
|
|
409
438
|
if ((0, lodash_1.isEqual)(localValue.fields, value)) {
|
|
@@ -726,6 +755,10 @@ var FormEngine = function (_a) {
|
|
|
726
755
|
meta: undefined,
|
|
727
756
|
};
|
|
728
757
|
});
|
|
758
|
+
// Collapse it too: a removed field drops back to the (collapsed) Optional box
|
|
759
|
+
// as a quiet addable row — if it was being edited, that editor must close
|
|
760
|
+
// rather than linger as an open editor for a field that's no longer added.
|
|
761
|
+
setExpandedOptions(function (prev) { return prev.filter(function (name) { return name !== optionName; }); });
|
|
729
762
|
}, []);
|
|
730
763
|
var handleAddOptionalFieldChange = (0, react_2.useCallback)(function (_name, optionName) {
|
|
731
764
|
var _a, _b, _c;
|
|
@@ -889,6 +922,67 @@ var FormEngine = function (_a) {
|
|
|
889
922
|
return __assign(__assign({}, newValue), (_a = {}, _a[optionName] = option, _a));
|
|
890
923
|
}, {});
|
|
891
924
|
}, [showInvalidOptionsOnly, JSON.stringify(availableOptions)]);
|
|
925
|
+
// Read-first STATUS / BOX for one option — lifted to component scope so the
|
|
926
|
+
// status boxes (renderCompact) and the header's "needs attention" count share
|
|
927
|
+
// exactly one definition. One-of group members travel together (bucket by the
|
|
928
|
+
// group's satisfaction); everything else by its own status.
|
|
929
|
+
var schemaMsgIntent = (0, react_2.useCallback)(function (name) {
|
|
930
|
+
var _a;
|
|
931
|
+
var msgs = (((_a = options === null || options === void 0 ? void 0 : options[name]) === null || _a === void 0 ? void 0 : _a.messages) || []);
|
|
932
|
+
if (msgs.some(function (m) { return m.intent === 'danger'; }))
|
|
933
|
+
return 'danger';
|
|
934
|
+
if (msgs.some(function (m) { return m.intent === 'warning'; }))
|
|
935
|
+
return 'warning';
|
|
936
|
+
return undefined;
|
|
937
|
+
}, [JSON.stringify(options)]);
|
|
938
|
+
var getOptionStatus = (0, react_2.useCallback)(function (name, hidden) {
|
|
939
|
+
var _a;
|
|
940
|
+
if (hidden === void 0) { hidden = false; }
|
|
941
|
+
if (hidden)
|
|
942
|
+
return 'optional';
|
|
943
|
+
var schema = options === null || options === void 0 ? void 0 : options[name];
|
|
944
|
+
var type = ((schema === null || schema === void 0 ? void 0 : schema.ui_type) || (schema === null || schema === void 0 ? void 0 : schema.type));
|
|
945
|
+
var value = (_a = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _a === void 0 ? void 0 : _a.value;
|
|
946
|
+
var empty = (0, readFirst_1.isOptionValueEmpty)(value);
|
|
947
|
+
var reqGroups = (schema === null || schema === void 0 ? void 0 : schema.required_groups) || [];
|
|
948
|
+
var required = !!((schema === null || schema === void 0 ? void 0 : schema.required) || reqGroups.length);
|
|
949
|
+
var covered = empty &&
|
|
950
|
+
reqGroups.some(function (g) {
|
|
951
|
+
var by = requiredGroupsInfo.satisfiedBy[g];
|
|
952
|
+
return !!by && by !== name;
|
|
953
|
+
});
|
|
954
|
+
var msgIntent = schemaMsgIntent(name);
|
|
955
|
+
var invalid = (!empty && !isOptionValid(name, type, value)) || msgIntent === 'danger';
|
|
956
|
+
return (0, readFirst_1.getReadFirstStatus)({
|
|
957
|
+
empty: empty,
|
|
958
|
+
required: required,
|
|
959
|
+
covered: covered,
|
|
960
|
+
invalid: invalid,
|
|
961
|
+
warned: msgIntent === 'warning',
|
|
962
|
+
});
|
|
963
|
+
}, [
|
|
964
|
+
JSON.stringify(options),
|
|
965
|
+
JSON.stringify(availableOptions),
|
|
966
|
+
isOptionValid,
|
|
967
|
+
requiredGroupsInfo,
|
|
968
|
+
schemaMsgIntent,
|
|
969
|
+
]);
|
|
970
|
+
var getOptionBucket = (0, react_2.useCallback)(function (name, hidden) {
|
|
971
|
+
var _a;
|
|
972
|
+
if (hidden === void 0) { hidden = false; }
|
|
973
|
+
if (!hidden) {
|
|
974
|
+
var reqGroups = ((_a = options === null || options === void 0 ? void 0 : options[name]) === null || _a === void 0 ? void 0 : _a.required_groups) || [];
|
|
975
|
+
if (reqGroups.length) {
|
|
976
|
+
return reqGroups.some(function (g) { return !requiredGroupsInfo.satisfiedBy[g]; }) ? 'attention' : 'set';
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return (0, readFirst_1.getReadFirstBucket)(getOptionStatus(name, hidden));
|
|
980
|
+
}, [JSON.stringify(options), requiredGroupsInfo, getOptionStatus]);
|
|
981
|
+
// How many fields are in the "Needs attention" box — drives the header link.
|
|
982
|
+
var readFirstAttentionCount = (0, react_2.useMemo)(function () {
|
|
983
|
+
return Object.keys(availableOptions || {}).filter(function (name) { return getOptionBucket(name) === 'attention'; })
|
|
984
|
+
.length;
|
|
985
|
+
}, [JSON.stringify(availableOptions), getOptionBucket]);
|
|
892
986
|
var getIntent = (0, react_2.useCallback)(
|
|
893
987
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
894
988
|
function (optName, type, optValue, _op) {
|
|
@@ -1011,13 +1105,27 @@ var FormEngine = function (_a) {
|
|
|
1011
1105
|
// The info panel below the row keeps showing schema messages while editing —
|
|
1012
1106
|
// rendering them in the editor too would balloon a one-line edit.
|
|
1013
1107
|
suppressSchemaMessages) {
|
|
1014
|
-
var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p
|
|
1108
|
+
var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
1015
1109
|
var type = _a.type, other = __rest(_a, ["type"]);
|
|
1016
1110
|
var operatorParts = (0, exports.fixOperatorValue)(other.op);
|
|
1017
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(
|
|
1018
|
-
var
|
|
1019
|
-
|
|
1020
|
-
|
|
1111
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(function () {
|
|
1112
|
+
var _a;
|
|
1113
|
+
var schemaMsgs = (suppressSchemaMessages ? [] : ((_a = options === null || options === void 0 ? void 0 : options[optionName]) === null || _a === void 0 ? void 0 : _a.messages) || []);
|
|
1114
|
+
if (!schemaMsgs.length)
|
|
1115
|
+
return null;
|
|
1116
|
+
var items = schemaMsgs.map(function (_a, index) {
|
|
1117
|
+
var intent = _a.intent, title = _a.title, content = _a.content;
|
|
1118
|
+
return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { intent: intent, title: title, opaque: false, size: 'small',
|
|
1119
|
+
// Compact: flat (no border) to match the read-row info panels;
|
|
1120
|
+
// classic forms keep the bordered, bottom-margined message.
|
|
1121
|
+
flat: compact || undefined, margin: compact ? undefined : 'bottom', children: content }, title || index));
|
|
1122
|
+
});
|
|
1123
|
+
// Compact: stack them in a 4px-gap panel so a field's messages look
|
|
1124
|
+
// identical whether the row is collapsed (read panel) or expanded.
|
|
1125
|
+
return compact ?
|
|
1126
|
+
(0, jsx_runtime_1.jsx)("div", { className: 'options-readfirst-info-panel', style: { display: 'flex', flexFlow: 'column', gap: 4, marginBottom: 8 }, children: items })
|
|
1127
|
+
: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: items });
|
|
1128
|
+
})(), operators && (0, size_1.default)(operators) ?
|
|
1021
1129
|
(0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { fill: true, wrap: true, className: 'operators', children: operatorParts.map(function (operator, index) {
|
|
1022
1130
|
var _a, _b;
|
|
1023
1131
|
return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsx)(Select_1.SelectFormField, { items: (0, map_1.default)(operators, function (op) { return (__assign(__assign({}, op), { value: op.name })); }), disabled: readOnly, value: operator && "".concat((_a = operators === null || operators === void 0 ? void 0 : operators[operator]) === null || _a === void 0 ? void 0 : _a.name), onChange: function (val) {
|
|
@@ -1033,18 +1141,21 @@ var FormEngine = function (_a) {
|
|
|
1033
1141
|
: null] }, index));
|
|
1034
1142
|
}) }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreVerticalSpacer, { height: 5 })] })
|
|
1035
1143
|
: null, (0, react_1.createElement)(TemplateField_1.TemplateField, __assign({ fluid: true }, options === null || options === void 0 ? void 0 : options[optionName], {
|
|
1144
|
+
// Propagate compact so an arg_schema field renders a COMPACT sub-form
|
|
1145
|
+
// (consistent with the parent) rather than the classic FormEngine.
|
|
1146
|
+
compact: compact,
|
|
1036
1147
|
// SEAM: forwarded through TemplateField's rest-spread to AutoFormField,
|
|
1037
1148
|
// which renders consumer-injected editors by field type/ui_type.
|
|
1038
|
-
componentOverrides: componentOverrides, allowTemplates: !!(allowTemplates && ((
|
|
1149
|
+
componentOverrides: componentOverrides, allowTemplates: !!(allowTemplates && ((_b = options === null || options === void 0 ? void 0 : options[optionName]) === null || _b === void 0 ? void 0 : _b.supports_templates)), allowFunctions: !!((_c = options === null || options === void 0 ? void 0 : options[optionName]) === null || _c === void 0 ? void 0 : _c.supports_expressions),
|
|
1039
1150
|
// reqraft: form-level expression fields get the Visual/Text shell
|
|
1040
1151
|
// (DPQL text mode); opt out per-form via `templateFieldProps`.
|
|
1041
|
-
allowTextExpressions: true, allowCustomValues: ((
|
|
1152
|
+
allowTextExpressions: true, allowCustomValues: ((_d = options === null || options === void 0 ? void 0 : options[optionName]) === null || _d === void 0 ? void 0 : _d.supports_custom_values) !== false && type !== 'any', templates: templates.value }, (0, exports.getTypeAndCanBeNull)(type, (_f = options === null || options === void 0 ? void 0 : options[optionName]) === null || _f === void 0 ? void 0 : _f.allowed_values, other.op), { ui_type: type, name: optionName, uniqueName: "".concat(uniqueName ? "".concat(uniqueName, ".") : "".concat(name ? "".concat(name, ".") : '')).concat(optionName), onChange:
|
|
1042
1153
|
// Identity-stable on purpose: the typed fields debounce on
|
|
1043
1154
|
// `[localValue, onChange]` — an inline lambda resets the pending emit
|
|
1044
1155
|
// every render and the typed value can starve.
|
|
1045
|
-
handleValueChange, key: optionName, arg_schema: (
|
|
1156
|
+
handleValueChange, key: optionName, arg_schema: (_g = options === null || options === void 0 ? void 0 : options[optionName]) === null || _g === void 0 ? void 0 : _g.arg_schema, noSoft: !!(rest === null || rest === void 0 ? void 0 : rest.options), value: other.value, isFunction: other.is_expression, isDefaultFunction: ((_h = options === null || options === void 0 ? void 0 : options[optionName]) === null || _h === void 0 ? void 0 : _h.default_view) === 'expression', sensitive: (_j = options === null || options === void 0 ? void 0 : options[optionName]) === null || _j === void 0 ? void 0 : _j.sensitive, default_value: (0, common_1.getDefaultValue)(options === null || options === void 0 ? void 0 : options[optionName]), isDefaultTemplate: ((_k = options === null || options === void 0 ? void 0 : options[optionName]) === null || _k === void 0 ? void 0 : _k.default_view) === 'template', allowed_values: (_l = options === null || options === void 0 ? void 0 : options[optionName]) === null || _l === void 0 ? void 0 : _l.allowed_values, disabled: ((_m = options === null || options === void 0 ? void 0 : options[optionName]) === null || _m === void 0 ? void 0 : _m.disabled) ||
|
|
1046
1157
|
readOnly ||
|
|
1047
|
-
!(0, validations_1.hasAllDependenciesFullfilled)((
|
|
1158
|
+
!(0, validations_1.hasAllDependenciesFullfilled)((_o = options === null || options === void 0 ? void 0 : options[optionName]) === null || _o === void 0 ? void 0 : _o.depends_on, availableOptions, options || {}), readOnly: readOnly, size: editorSize || rest.size, menuItems: ((_p = options === null || options === void 0 ? void 0 : options[optionName]) === null || _p === void 0 ? void 0 : _p.ui_type) === 'any' ?
|
|
1048
1159
|
getCustomMenuTemplateItems(optionName)
|
|
1049
1160
|
: undefined }, templateFieldProps)), (0, jsx_runtime_1.jsx)(OptionFieldMessages_1.OptionFieldMessages, { schema: options || {}, allOptions: availableOptions, name: optionName, option: __assign({ type: type }, other), getType: getTypeForOption }), operators && (0, size_1.default)(operators) && (0, size_1.default)(other.op) ?
|
|
1050
1161
|
(0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreVerticalSpacer, { height: 5 }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { size: 'small', children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreTagGroup, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', labelKey: 'WHERE', label: optionName }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', labelKey: 'IS', label: operatorParts.join(' ') }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', intent: 'info', label: other.value ?
|
|
@@ -1187,6 +1298,7 @@ var FormEngine = function (_a) {
|
|
|
1187
1298
|
var compactToolbarContextValue = (0, react_2.useMemo)(function () { return ({
|
|
1188
1299
|
readOnly: readOnly,
|
|
1189
1300
|
invalidCount: (0, size_1.default)(validityData.invalidFields),
|
|
1301
|
+
attentionCount: readFirstAttentionCount,
|
|
1190
1302
|
completion: readFirstCompletion,
|
|
1191
1303
|
showInvalidOnly: showInvalidOptionsOnly,
|
|
1192
1304
|
onToggleInvalidOnly: handleToggleInvalidOnly,
|
|
@@ -1211,6 +1323,7 @@ var FormEngine = function (_a) {
|
|
|
1211
1323
|
}); }, [
|
|
1212
1324
|
readOnly,
|
|
1213
1325
|
validityData,
|
|
1326
|
+
readFirstAttentionCount,
|
|
1214
1327
|
readFirstCompletion,
|
|
1215
1328
|
showInvalidOptionsOnly,
|
|
1216
1329
|
handleToggleInvalidOnly,
|
|
@@ -1265,15 +1378,18 @@ var FormEngine = function (_a) {
|
|
|
1265
1378
|
pushRow(optionName, false);
|
|
1266
1379
|
}
|
|
1267
1380
|
});
|
|
1268
|
-
//
|
|
1269
|
-
//
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1381
|
+
// Surface EVERY not-yet-added optional field as an addable (hidden) row, so
|
|
1382
|
+
// the whole schema is browsable inline — they all land in the Optional box
|
|
1383
|
+
// (hidden ⇒ 'optional' bucket) instead of being buried in the Fields menu.
|
|
1384
|
+
// Narrowed by the same filters as the listed rows (search query + required-
|
|
1385
|
+
// only). availableOptions (listed) and filteredOptions (these) are disjoint —
|
|
1386
|
+
// the former is built from fixedValue keys, the latter excludes them — so a
|
|
1387
|
+
// field is never both a listed and a hidden row.
|
|
1388
|
+
(0, lodash_1.forEach)(filteredOptions, function (_schema, optionName) {
|
|
1389
|
+
if (matchesFilters(optionName)) {
|
|
1390
|
+
pushRow(optionName, true);
|
|
1391
|
+
}
|
|
1392
|
+
});
|
|
1277
1393
|
// User sort (Fields menu → "Sort by"), applied WITHIN each group so the
|
|
1278
1394
|
// group sections and the required-group rails are preserved. Schema order is
|
|
1279
1395
|
// the default and the stable tiebreaker (Array.sort is stable, and each
|
|
@@ -1317,6 +1433,57 @@ var FormEngine = function (_a) {
|
|
|
1317
1433
|
return 1;
|
|
1318
1434
|
return groupOrder.indexOf(a) - groupOrder.indexOf(b);
|
|
1319
1435
|
});
|
|
1436
|
+
var buckets = {
|
|
1437
|
+
attention: {},
|
|
1438
|
+
set: {},
|
|
1439
|
+
optional: {},
|
|
1440
|
+
};
|
|
1441
|
+
var bucketGroups = { attention: [], set: [], optional: [] };
|
|
1442
|
+
// Freeze the box of any field currently being edited (or whose one-of group
|
|
1443
|
+
// has an edited member) to its last settled box — so finishing an edit that
|
|
1444
|
+
// flips its status doesn't remount it in another box and steal focus.
|
|
1445
|
+
var stableBucketOf = function (entry) {
|
|
1446
|
+
var _a;
|
|
1447
|
+
var fresh = getOptionBucket(entry.name, entry.hidden);
|
|
1448
|
+
var groupBeingEdited = !entry.hidden &&
|
|
1449
|
+
(((_a = options === null || options === void 0 ? void 0 : options[entry.name]) === null || _a === void 0 ? void 0 : _a.required_groups) || []).some(function (g) {
|
|
1450
|
+
return (requiredGroupsInfo.members[g] || []).some(function (m) { return expandedOptions.includes(m); });
|
|
1451
|
+
});
|
|
1452
|
+
if (!entry.hidden && (expandedOptions.includes(entry.name) || groupBeingEdited)) {
|
|
1453
|
+
var memo = settledBucket.current[entry.name];
|
|
1454
|
+
if (memo)
|
|
1455
|
+
return memo;
|
|
1456
|
+
}
|
|
1457
|
+
settledBucket.current[entry.name] = fresh;
|
|
1458
|
+
return fresh;
|
|
1459
|
+
};
|
|
1460
|
+
groupKeys.forEach(function (groupName) {
|
|
1461
|
+
grouped[groupName].forEach(function (entry) {
|
|
1462
|
+
var b = stableBucketOf(entry);
|
|
1463
|
+
if (!buckets[b][groupName]) {
|
|
1464
|
+
buckets[b][groupName] = [];
|
|
1465
|
+
bucketGroups[b].push(groupName);
|
|
1466
|
+
}
|
|
1467
|
+
buckets[b][groupName].push(entry);
|
|
1468
|
+
});
|
|
1469
|
+
});
|
|
1470
|
+
var bucketCount = function (b) {
|
|
1471
|
+
return bucketGroups[b].reduce(function (n, g) { return n + buckets[b][g].length; }, 0);
|
|
1472
|
+
};
|
|
1473
|
+
// 'general' / 'optional' are the SYNTHETIC fallback group keys getOptionGroup
|
|
1474
|
+
// assigns to fields with no explicit `group` — printing a "General"/"Optional"
|
|
1475
|
+
// sub-label for those is just noise, so suppress it. BUT a consumer may also
|
|
1476
|
+
// use 'general' as a REAL group (defining it in the `groups` prop and tagging
|
|
1477
|
+
// fields with `group: 'general'`); in that case it's a named group like any
|
|
1478
|
+
// other and DOES get its sub-label.
|
|
1479
|
+
var showGroupSubLabel = function (groupName) {
|
|
1480
|
+
return (groupName !== 'general' && groupName !== 'optional') || !!(groups === null || groups === void 0 ? void 0 : groups[groupName]);
|
|
1481
|
+
};
|
|
1482
|
+
var STATUS_BOXES = [
|
|
1483
|
+
{ key: 'attention', label: 'Needs attention', intent: 'warning', icon: 'ErrorWarningLine' },
|
|
1484
|
+
{ key: 'set', label: 'Set', intent: 'success', icon: 'CheckLine' },
|
|
1485
|
+
{ key: 'optional', label: 'Optional', icon: 'CheckboxBlankCircleLine' },
|
|
1486
|
+
];
|
|
1320
1487
|
// Build the rows for one group: contiguous required-group members are pulled
|
|
1321
1488
|
// together at the first member's slot and rendered as a connected rail (flat
|
|
1322
1489
|
// rows — no wrapper — so the value surface applies normally; the rail + nodes
|
|
@@ -1331,8 +1498,9 @@ var FormEngine = function (_a) {
|
|
|
1331
1498
|
}
|
|
1332
1499
|
: shownOptions[entry.name], hidden: entry.hidden, clustered: clustered, clusterFirst: clusterFirst, clusterLast: clusterLast }, entry.name));
|
|
1333
1500
|
};
|
|
1334
|
-
|
|
1335
|
-
|
|
1501
|
+
// (Clustering runs in narrow mode too now — the "One of the below is
|
|
1502
|
+
// required" box wraps the members regardless of width; it no longer relies
|
|
1503
|
+
// on a contiguous rail.)
|
|
1336
1504
|
var emitted = new Set();
|
|
1337
1505
|
var groupOf = function (name) { var _a, _b; return (_b = (_a = options === null || options === void 0 ? void 0 : options[name]) === null || _a === void 0 ? void 0 : _a.required_groups) === null || _b === void 0 ? void 0 : _b[0]; };
|
|
1338
1506
|
return names.map(function (entry) {
|
|
@@ -1345,51 +1513,73 @@ var FormEngine = function (_a) {
|
|
|
1345
1513
|
if (memberEntries.length < 2)
|
|
1346
1514
|
return renderRow(entry, false);
|
|
1347
1515
|
emitted.add(grp);
|
|
1348
|
-
|
|
1516
|
+
var railed = memberEntries.map(function (e, idx) {
|
|
1349
1517
|
return renderRow(e, true, idx === 0, idx === memberEntries.length - 1);
|
|
1350
1518
|
});
|
|
1519
|
+
// An UNMET one-of group gets the explicit "One of the below is required"
|
|
1520
|
+
// box (the Focus cluster). A met group needs no banner — the rail + the
|
|
1521
|
+
// "Covers"/"Covered by" chips already say which member satisfies it.
|
|
1522
|
+
if (requiredGroupsInfo.satisfiedBy[grp])
|
|
1523
|
+
return railed;
|
|
1524
|
+
return ((0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterBox, { className: 'options-readfirst-required-cluster', "$border": "".concat(cWarning, "33"), "$tint": "".concat(cWarning, "0d"), children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledRequiredClusterHeader, { "$color": cWarning, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'LinkM', size: '11px', style: { color: cWarning } }), "One of the below is required"] }), railed] }, grp));
|
|
1351
1525
|
});
|
|
1352
1526
|
};
|
|
1353
|
-
return ((0, jsx_runtime_1.jsx)(exports.OptionsContext.Provider, { value: { schema: options, value: availableOptions }, children: (0, jsx_runtime_1.jsx)(compactRowContext_1.CompactRowContext.Provider, { value: compactRowContextValue, children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreErrorBoundary, { children: [showHelpForOption && ((0, jsx_runtime_1.jsx)(OptionsHelpDialog_1.OptionsHelpDialog, { onClose: function () { return setShowHelpForOption(undefined); }, option: options[showHelpForOption] })), (0, jsx_runtime_1.jsx)(compactToolbarContext_1.CompactToolbarContext.Provider, { value: compactToolbarContextValue, children: (0, jsx_runtime_1.jsxs)(StyledCompactWrap, { ref: setCompactWrap, className: 'options-readfirst-scroll', "$flush": compactFlush, children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledCompactPanel
|
|
1527
|
+
return ((0, jsx_runtime_1.jsx)(exports.OptionsContext.Provider, { value: { schema: options, value: availableOptions }, children: (0, jsx_runtime_1.jsx)(compactRowContext_1.CompactRowContext.Provider, { value: compactRowContextValue, children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreErrorBoundary, { children: [showHelpForOption && ((0, jsx_runtime_1.jsx)(OptionsHelpDialog_1.OptionsHelpDialog, { onClose: function () { return setShowHelpForOption(undefined); }, option: options[showHelpForOption] })), (0, jsx_runtime_1.jsx)(compactToolbarContext_1.CompactToolbarContext.Provider, { value: compactToolbarContextValue, children: (0, jsx_runtime_1.jsxs)(StyledCompactWrap, { ref: setCompactWrap, className: 'options-readfirst-scroll', "$flush": compactFlush || compactNested, children: [(0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledCompactPanel
|
|
1528
|
+
// The top-level form scrolls, so its toolbar STICKS and carries a
|
|
1529
|
+
// dark blurred backdrop so content ghosts cleanly beneath it. A
|
|
1530
|
+
// nested (arg_schema) sub-form owns no scroll context — drop the
|
|
1531
|
+
// sticky, the backdrop, and the stacking context so its header is
|
|
1532
|
+
// transparent inside the parent's card.
|
|
1533
|
+
, { "$headerBg": compactNested ? 'transparent' : headerBg, "$nested": compactNested, flat: true,
|
|
1534
|
+
// No panel background: the form sits transparently on whatever
|
|
1535
|
+
// hosts it (page, drawer, or — for an arg_schema field — the
|
|
1536
|
+
// parent's edit card) instead of stacking its own dark surface.
|
|
1537
|
+
// The status boxes keep their own tints; the sticky toolbar keeps
|
|
1538
|
+
// its blurred header via the $headerBg override.
|
|
1539
|
+
transparent: true, stickyHeader: !compactNested, padded: false, actions: compactHeaderActions, contentStyle: {
|
|
1354
1540
|
display: 'flex',
|
|
1355
1541
|
flexFlow: 'column',
|
|
1356
1542
|
gap: '10px',
|
|
1357
|
-
|
|
1543
|
+
// Nested sub-form: no surrounding panel padding (it's flush in
|
|
1544
|
+
// the parent card); top-level keeps a small bottom gutter.
|
|
1545
|
+
padding: compactNested ? '0' : '0 0 12px',
|
|
1358
1546
|
}, children: [(0, size_1.default)(groupKeys) === 0 ?
|
|
1359
1547
|
(0, jsx_runtime_1.jsx)(reqore_1.ReqoreMessage, { flat: true, opaque: false, size: 'small', children: "No fields match the current filters." })
|
|
1360
|
-
: null,
|
|
1361
|
-
var
|
|
1362
|
-
var
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1548
|
+
: null, STATUS_BOXES.map(function (box) {
|
|
1549
|
+
var groupsInBox = bucketGroups[box.key];
|
|
1550
|
+
var count = bucketCount(box.key);
|
|
1551
|
+
if (!count)
|
|
1552
|
+
return null;
|
|
1553
|
+
var accent = box.key === 'attention' ? cWarning
|
|
1554
|
+
: box.key === 'set' ? cSuccess
|
|
1555
|
+
: cMuted;
|
|
1556
|
+
// The muted "Optional" box reads as a quieter, recessed
|
|
1557
|
+
// surface — a touch darker than the page rather than the
|
|
1558
|
+
// faint grey tint the accent would give.
|
|
1559
|
+
var boxBg = box.key === 'optional' ?
|
|
1560
|
+
(0, colors_1.changeDarkness)((0, colors_1.getMainBackgroundColor)(theme), 0.06)
|
|
1561
|
+
: undefined;
|
|
1562
|
+
return ((0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBox, { "$accent": accent, "$bg": boxBg, flat: true, minimal: true, collapseButtonProps: { flat: true, minimal: true, size: 'small' }, collapsible: true,
|
|
1563
|
+
// The Optional box now holds every not-yet-added field, so
|
|
1564
|
+
// it starts COLLAPSED to keep the form focused on what's in
|
|
1565
|
+
// use. But a SEARCH must surface matching addable fields —
|
|
1566
|
+
// and ReqorePanel unmounts collapsed content — so force it
|
|
1567
|
+
// open whenever a query is active. (isCollapsed is the
|
|
1568
|
+
// panel's controllable state; manual toggling still works
|
|
1569
|
+
// when no query is set.)
|
|
1570
|
+
isCollapsed: box.key === 'optional' && !query, label: (0, jsx_runtime_1.jsxs)(compactRowStyles_1.StyledGroupHeader, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { effect: { weight: 'bold' }, size: 'normal', children: box.label }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'small', minimal: true, compact: true, intent: box.intent, label: String(count) })] }), icon: box.icon, className: 'options-readfirst-group', padded: false, contentStyle: { padding: '4px 4px 6px' }, children: (0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledGroupBody, { "$divider": cDivider, "$hover": cHover, "$focus": cWarning, "$success": cSuccess, "$rowBg": cRowBg, "$lineColor": cGroupLine, className: compactNarrow ? 'readfirst-narrow' : undefined, children: groupsInBox.map(function (groupName) {
|
|
1571
|
+
var groupConfig = groups === null || groups === void 0 ? void 0 : groups[groupName];
|
|
1572
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [showGroupSubLabel(groupName) ?
|
|
1573
|
+
(0, jsx_runtime_1.jsx)(compactRowStyles_1.StyledStatusBoxGroupLabel, { children: (0, readFirst_1.getOptionGroupLabel)(groupName, groups) })
|
|
1574
|
+
: null, showGroupSubLabel(groupName) && (groupConfig === null || groupConfig === void 0 ? void 0 : groupConfig.subtitle) ?
|
|
1575
|
+
(0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { size: 'small', effect: { opacity: 0.6 }, style: {
|
|
1576
|
+
marginTop: 2,
|
|
1577
|
+
marginBottom: 8,
|
|
1578
|
+
marginLeft: compactRowStyles_1.GROUP_INDENT,
|
|
1579
|
+
paddingRight: 10,
|
|
1580
|
+
}, children: groupConfig.subtitle })
|
|
1581
|
+
: null, renderGroupRows(buckets[box.key][groupName])] }, groupName));
|
|
1582
|
+
}) }) }, box.key));
|
|
1393
1583
|
})] }), commitMode === 'batched' && !readOnly && dirtyOptionNames.length ?
|
|
1394
1584
|
(0, jsx_runtime_1.jsx)(StyledCommitDock, { "$bg": cBg, "$border": cDivider, children: (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { className: 'options-readfirst-commitbar', verticalAlign: 'center', wrap: true, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreTag, { size: 'tiny', minimal: true, flat: true, compact: true, effect: { uppercase: true, spaced: 1 }, intent: 'warning', icon: 'EditLine', label: "".concat(dirtyOptionNames.length, " unsaved change").concat(dirtyOptionNames.length === 1 ? '' : 's') }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { size: 'small', intent: 'success', icon: 'CheckLine', fixed: true, className: 'options-readfirst-save', disabled: !validityData.isValid, tooltip: validityData.isValid ?
|
|
1395
1585
|
'Apply the staged changes'
|