@qoretechnologies/reqraft 0.10.50 → 0.10.51-pr.115.g3e79f11
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/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
- package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
- package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
- package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/index.d.ts +4 -0
- package/dist/components/dpqlEditor/index.d.ts.map +1 -1
- package/dist/components/dpqlEditor/index.js +5 -1
- package/dist/components/dpqlEditor/index.js.map +1 -1
- package/dist/components/dpqlEditor/types.d.ts +29 -2
- package/dist/components/dpqlEditor/types.d.ts.map +1 -1
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
- package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
- package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
- package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +91 -12
- 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 +5 -2
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +107 -11
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +277 -51
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.d.ts +17 -2
- package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.js +61 -11
- package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js +7 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.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/readFirst.d.ts +19 -1
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +63 -10
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rendererTypes.d.ts +13 -0
- package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
- package/dist/components/form/engine/rendererTypes.js.map +1 -1
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +147 -18
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/expressions/dpqlMockLsp.d.ts +17 -0
- package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +1 -1
- package/dist/components/form/expressions/dpqlMockLsp.js +43 -8
- package/dist/components/form/expressions/dpqlMockLsp.js.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +14 -2
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +8 -1
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
- package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
- package/dist/components/form/fields/template/TemplateField.js +168 -2
- package/dist/components/form/fields/template/TemplateField.js.map +1 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +1 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js +24 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +1 -1
- package/dist/helpers/dpqlDetection.d.ts +58 -0
- package/dist/helpers/dpqlDetection.d.ts.map +1 -0
- package/dist/helpers/dpqlDetection.js +147 -0
- package/dist/helpers/dpqlDetection.js.map +1 -0
- package/dist/helpers/optionUiTypes.d.ts +1 -1
- package/dist/helpers/templates.d.ts +21 -0
- package/dist/helpers/templates.d.ts.map +1 -1
- package/dist/helpers/templates.js +28 -1
- package/dist/helpers/templates.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/fetch.d.ts +115 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +210 -44
- package/dist/utils/fetch.js.map +1 -1
- package/package.json +1 -1
- package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
- package/src/components/dpqlEditor/index.ts +4 -0
- package/src/components/dpqlEditor/types.ts +26 -2
- package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
- package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
- package/src/components/form/engine/CompactRow.tsx +112 -4
- package/src/components/form/engine/CompactToolbar.tsx +10 -3
- package/src/components/form/engine/FormEngine.stories.tsx +328 -6
- package/src/components/form/engine/FormEngine.tsx +319 -33
- package/src/components/form/engine/OptionFieldMessages.tsx +89 -11
- package/src/components/form/engine/_structuredData/SchemaDataView.tsx +11 -0
- package/src/components/form/engine/compactToolbarContext.ts +1 -1
- package/src/components/form/engine/readFirst.ts +70 -7
- package/src/components/form/engine/rendererTypes.ts +12 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +216 -29
- package/src/components/form/expressions/ExpressionField.tsx +194 -16
- package/src/components/form/expressions/dpqlMockLsp.ts +48 -0
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -2
- package/src/components/form/fields/auto/AutoFormField.tsx +7 -0
- package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
- package/src/components/form/fields/template/TemplateField.tsx +234 -1
- package/src/components/smartEditor/__fixtures__/mockLspServer.ts +25 -1
- package/src/helpers/dpqlDetection.ts +192 -0
- package/src/helpers/templates.ts +31 -0
- package/src/index.tsx +14 -1
- package/src/utils/fetch.ts +247 -21
|
@@ -97,7 +97,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
97
97
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
98
98
|
};
|
|
99
99
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
100
|
-
exports.FormEngine = exports.getTypeAndCanBeNull = exports.flattenOptions = exports.fixOptions = exports.OptionsContext = exports.hasRequiredOptions = exports.fixOperatorValue = exports.getType = void 0;
|
|
100
|
+
exports.FormEngine = exports.getTypeAndCanBeNull = exports.flattenOptions = exports.shouldEmitLocalValue = exports.agreementFromRebuild = exports.isMirrorOfValue = exports.fixOptions = exports.OptionsContext = exports.hasRequiredOptions = exports.getOptionFieldStorageType = exports.fixOperatorValue = exports.getType = void 0;
|
|
101
101
|
var react_1 = require("react");
|
|
102
102
|
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
103
103
|
var reqore_1 = require("@qoretechnologies/reqore");
|
|
@@ -231,14 +231,55 @@ var getOptionSchemaStorageType = function (option, isRendererOnly) {
|
|
|
231
231
|
: isRendererOnly(option === null || option === void 0 ? void 0 : option.ui_type) ? (option === null || option === void 0 ? void 0 : option.type) || (option === null || option === void 0 ? void 0 : option.ui_type)
|
|
232
232
|
: (option === null || option === void 0 ? void 0 : option.ui_type) || (option === null || option === void 0 ? void 0 : option.type)) || 'any');
|
|
233
233
|
};
|
|
234
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Whether an option currently holds an expression, in EITHER shape it comes in.
|
|
236
|
+
*
|
|
237
|
+
* At runtime the editor writes the flag onto the option itself
|
|
238
|
+
* (`{ type, is_expression: true, value }`), but a value loaded from a saved
|
|
239
|
+
* draft carries the envelope NESTED (`{ type, value: { is_expression: true,
|
|
240
|
+
* value } }`). Same thing, two shapes, and only the flat one was ever checked —
|
|
241
|
+
* so a freshly typed expression behaved while a reloaded one did not, which is
|
|
242
|
+
* exactly how this survived several fixes: every test used the runtime shape.
|
|
243
|
+
*/
|
|
244
|
+
var optionHoldsExpression = function (option) {
|
|
245
|
+
var _a;
|
|
246
|
+
var o = option;
|
|
247
|
+
return !!((o === null || o === void 0 ? void 0 : o.is_expression) || ((_a = o === null || o === void 0 ? void 0 : o.value) === null || _a === void 0 ? void 0 : _a.is_expression));
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Which type an option resolves to — the schema's, or the one stored on the
|
|
251
|
+
* value.
|
|
252
|
+
*
|
|
253
|
+
* Exported because this single decision is what every option field is rendered
|
|
254
|
+
* with, and what an expression's return type is checked against. It deserves
|
|
255
|
+
* to be assertable without standing up a form.
|
|
256
|
+
*/
|
|
257
|
+
var getOptionFieldStorageType = function (optionName, fieldType, schema, operators, operatorData, isRendererOnly,
|
|
258
|
+
/** Whether the stored value is an expression — see below. */
|
|
259
|
+
isExpression) {
|
|
235
260
|
if (isRendererOnly === void 0) { isRendererOnly = rendererTypes_1.isRendererOnlyUiType; }
|
|
236
261
|
var schemaOption = schema === null || schema === void 0 ? void 0 : schema[optionName];
|
|
237
|
-
|
|
262
|
+
/* A STORED type does not describe an expression.
|
|
263
|
+
|
|
264
|
+
An expression value is `{ is_expression: true, value: {...} }`, so the type
|
|
265
|
+
recorded beside it describes that envelope — `hash` — and not what the
|
|
266
|
+
field holds. Letting it win means the SCHEMA's declared type is ignored and
|
|
267
|
+
the wrong answer is handed to the expression editor as the return type to
|
|
268
|
+
check against: `1 + 2` on a field declared `"type": "auto"` came back
|
|
269
|
+
"The expression returns int, and this field holds hash". A literal `1` was
|
|
270
|
+
fine, because a literal is stored as a plain value whose type matches.
|
|
271
|
+
|
|
272
|
+
`auto`/`any` accept anything, which is exactly why nothing should be
|
|
273
|
+
checked against them; a concrete declared type still is. The schema is the
|
|
274
|
+
only party that knows what the field accepts. */
|
|
275
|
+
var storedType = !isExpression &&
|
|
276
|
+
fieldType &&
|
|
277
|
+
!(fieldType === (schemaOption === null || schemaOption === void 0 ? void 0 : schemaOption.ui_type) && isRendererOnly(fieldType)) ?
|
|
238
278
|
fieldType
|
|
239
279
|
: getOptionSchemaStorageType(schemaOption, isRendererOnly);
|
|
240
280
|
return (0, exports.getType)(storedType, operators, operatorData);
|
|
241
281
|
};
|
|
282
|
+
exports.getOptionFieldStorageType = getOptionFieldStorageType;
|
|
242
283
|
var hasRequiredOptions = function (options) {
|
|
243
284
|
if (options === void 0) { options = {}; }
|
|
244
285
|
return !!(0, lodash_1.findKey)(options, function (option) { return option.required; });
|
|
@@ -370,6 +411,64 @@ var normalizeEmptyFieldValues = function (fields) {
|
|
|
370
411
|
return acc;
|
|
371
412
|
}, {});
|
|
372
413
|
};
|
|
414
|
+
/**
|
|
415
|
+
* Does this rebuild say anything the parent does not already hold?
|
|
416
|
+
*
|
|
417
|
+
* `false` means the rebuild is a MIRROR: `fixOptions` found no default to
|
|
418
|
+
* materialise, so the result repeats the `value` the parent handed down. The
|
|
419
|
+
* compare is empty-normalized because `fixOptions` round-trips a required-empty
|
|
420
|
+
* field between `{ value: '' }` and no `value` key, and that cosmetic
|
|
421
|
+
* difference would otherwise read as new information forever.
|
|
422
|
+
*/
|
|
423
|
+
var isMirrorOfValue = function (fixedValue, value) { return (0, lodash_1.isEqual)(normalizeEmptyFieldValues(fixedValue), normalizeEmptyFieldValues(value)); };
|
|
424
|
+
exports.isMirrorOfValue = isMirrorOfValue;
|
|
425
|
+
/**
|
|
426
|
+
* What this rebuild lets the form agree with the parent on, if anything.
|
|
427
|
+
*
|
|
428
|
+
* Returns the rebuild when it mirrors `value`, and `undefined` when it
|
|
429
|
+
* contributed something the parent has yet to learn.
|
|
430
|
+
*
|
|
431
|
+
* Adopting the parent's value IS agreement, and saying so matters as much as
|
|
432
|
+
* staying quiet about it. The sync-down skips only when the parent echoed what
|
|
433
|
+
* this form last sent; if adopting a value never updates that record, it points
|
|
434
|
+
* at an older state forever, the skip can never fire again, and the form
|
|
435
|
+
* rebuilds on every single change. Holding the mirror back WITHOUT recording
|
|
436
|
+
* the agreement was measured making the starvation worse, not better — 8 s
|
|
437
|
+
* became a 45 s timeout — which is why the two belong together.
|
|
438
|
+
*/
|
|
439
|
+
var agreementFromRebuild = function (fixedValue, value) {
|
|
440
|
+
return (0, exports.isMirrorOfValue)(fixedValue, value) ? fixedValue : undefined;
|
|
441
|
+
};
|
|
442
|
+
exports.agreementFromRebuild = agreementFromRebuild;
|
|
443
|
+
/**
|
|
444
|
+
* Should the form report `localValue` to its parent as an answer?
|
|
445
|
+
*
|
|
446
|
+
* Extracted and pure because the situation it exists for cannot be reproduced
|
|
447
|
+
* through a rendered form: it needs the emit to be decided against a `value`
|
|
448
|
+
* NEWER than the `localValue` built from it, which only happens when two
|
|
449
|
+
* components' effects land in one React commit — and a test renderer flushes
|
|
450
|
+
* effects between updates, so the two never fall out of step. The states below
|
|
451
|
+
* were recorded from a live instrumented run instead, and this is what makes
|
|
452
|
+
* them assertable.
|
|
453
|
+
*
|
|
454
|
+
* Two ways the answer is no:
|
|
455
|
+
*
|
|
456
|
+
* 1. `localValue` is a mirror — a rebuild of the parent's own value that added
|
|
457
|
+
* nothing. Repeating it back is not an answer. **Checked first**, because
|
|
458
|
+
* the comparison in (2) reads whatever `value` has become by now, which,
|
|
459
|
+
* when a nested engine shares the parent value, is already that engine's
|
|
460
|
+
* newer write; comparing against it would find a difference this form never
|
|
461
|
+
* made and emit the older mirror over the newer write. That is the loop.
|
|
462
|
+
* 2. `localValue` already equals `value` — there is nothing to report.
|
|
463
|
+
*/
|
|
464
|
+
var shouldEmitLocalValue = function (_a) {
|
|
465
|
+
var localValue = _a.localValue, value = _a.value, mirroredValue = _a.mirroredValue;
|
|
466
|
+
if (mirroredValue !== undefined && (0, lodash_1.isEqual)(localValue, mirroredValue)) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
return !(0, lodash_1.isEqual)(localValue, value);
|
|
470
|
+
};
|
|
471
|
+
exports.shouldEmitLocalValue = shouldEmitLocalValue;
|
|
373
472
|
var flattenOptions = function (options) {
|
|
374
473
|
return (0, reduce_1.default)(options, function (newOptions, option, optionName) {
|
|
375
474
|
var _a;
|
|
@@ -415,12 +514,12 @@ var FormEngineImpl = function (_a) {
|
|
|
415
514
|
// been a no-op. Removing it from the API is a separate, breaking change —
|
|
416
515
|
// every consumer passing it today already gets the flush layout by default.
|
|
417
516
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
418
|
-
compactFlush = _l === void 0 ? false : _l, _m = _a.compactNested, compactNested = _m === void 0 ? false : _m, _o = _a.compactScroll, compactScroll = _o === void 0 ? 'host' : _o, compactPanelProps = _a.compactPanelProps,
|
|
517
|
+
compactFlush = _l === void 0 ? false : _l, _m = _a.compactNested, compactNested = _m === void 0 ? false : _m, _o = _a.compactScroll, compactScroll = _o === void 0 ? 'host' : _o, compactPanelProps = _a.compactPanelProps, compactCollapsedGroupsProp = _a.compactCollapsedGroups, compactBoxLabels = _a.compactBoxLabels, _p = _a.compactToolbar, compactToolbar = _p === void 0 ? true : _p, _q = _a.commitMode, commitMode = _q === void 0 ? 'immediate' : _q, _r = _a.expandMode, expandMode = _r === void 0 ? 'single' : _r, onCommit = _a.onCommit, operatorsProp = _a.operators, groups = _a.groups, optionsLoader = _a.optionsLoader, onValidityChange = _a.onValidityChange, optionActions = _a.optionActions, _s = _a.optionActionsCollapse, optionActionsCollapse = _s === void 0 ? 'auto' : _s, componentOverrides = _a.componentOverrides, codePreviewRenderer = _a.codePreviewRenderer,
|
|
419
518
|
// consumed by the wrapper below, which publishes it to every description this
|
|
420
519
|
// form draws; destructured here only so it cannot reach `rest` and be spread
|
|
421
520
|
// onto a DOM node
|
|
422
521
|
_markdownRenderer = _a.markdownRenderer, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
423
|
-
rendererOnlyUiTypes = _a.rendererOnlyUiTypes, inheritedFromParent = _a.inheritedFromParent, autoFocusFirstRequired = _a.autoFocusFirstRequired, expandFirstRequired = _a.expandFirstRequired, initialExpandedOptions = _a.initialExpandedOptions, maxFieldsShown = _a.maxFieldsShown, rest = __rest(_a, ["name", "uniqueName", "value", "onChange", "onSingleOptionsChange", "onDependableOptionChange", "placeholder", "noValueString", "isValid", "url", "customUrl", "operatorsUrl", "onOptionsLoaded", "recordRequiresSearchOptions", "readOnly", "allowTemplates", "interfaceContext", "templateFieldProps", "forceDropdown", "showTypeToggle", "compact", "compactFlush", "compactNested", "compactScroll", "compactPanelProps", "compactCollapsedGroups", "compactToolbar", "commitMode", "expandMode", "onCommit", "operators", "groups", "optionsLoader", "onValidityChange", "optionActions", "optionActionsCollapse", "componentOverrides", "codePreviewRenderer", "markdownRenderer", "rendererOnlyUiTypes", "inheritedFromParent", "autoFocusFirstRequired", "expandFirstRequired", "initialExpandedOptions", "maxFieldsShown"]);
|
|
522
|
+
rendererOnlyUiTypes = _a.rendererOnlyUiTypes, inheritedFromParent = _a.inheritedFromParent, autoFocusFirstRequired = _a.autoFocusFirstRequired, expandFirstRequired = _a.expandFirstRequired, initialExpandedOptions = _a.initialExpandedOptions, maxFieldsShown = _a.maxFieldsShown, rest = __rest(_a, ["name", "uniqueName", "value", "onChange", "onSingleOptionsChange", "onDependableOptionChange", "placeholder", "noValueString", "isValid", "url", "customUrl", "operatorsUrl", "onOptionsLoaded", "recordRequiresSearchOptions", "readOnly", "allowTemplates", "interfaceContext", "templateFieldProps", "forceDropdown", "showTypeToggle", "compact", "compactFlush", "compactNested", "compactScroll", "compactPanelProps", "compactCollapsedGroups", "compactBoxLabels", "compactToolbar", "commitMode", "expandMode", "onCommit", "operators", "groups", "optionsLoader", "onValidityChange", "optionActions", "optionActionsCollapse", "componentOverrides", "codePreviewRenderer", "markdownRenderer", "rendererOnlyUiTypes", "inheritedFromParent", "autoFocusFirstRequired", "expandFirstRequired", "initialExpandedOptions", "maxFieldsShown"]);
|
|
424
523
|
// Built-ins + whatever the consumer declared for its own injected editors.
|
|
425
524
|
var isRendererOnly = (0, react_2.useMemo)(function () { return (0, rendererTypes_1.createRendererOnlyUiTypeCheck)(rendererOnlyUiTypes); }, [JSON.stringify(rendererOnlyUiTypes)]);
|
|
426
525
|
// Pointer CAPABILITY and viewport WIDTH are different questions and both
|
|
@@ -438,33 +537,33 @@ var FormEngineImpl = function (_a) {
|
|
|
438
537
|
var collapseOptionActions = optionActionsCollapse === 'always' ? true
|
|
439
538
|
: optionActionsCollapse === 'never' ? false
|
|
440
539
|
: !isHoverCapable || !!isMobile;
|
|
441
|
-
var
|
|
540
|
+
var _t = (0, react_2.useState)((rest === null || rest === void 0 ? void 0 : rest.options) || undefined), options = _t[0], setOptions = _t[1];
|
|
442
541
|
// optionsLoader lifecycle: loading feeds the skeleton gate, error the banner.
|
|
443
|
-
var
|
|
444
|
-
var
|
|
542
|
+
var _u = (0, react_2.useState)(!!optionsLoader && !(rest === null || rest === void 0 ? void 0 : rest.options)), optionsLoading = _u[0], setOptionsLoading = _u[1];
|
|
543
|
+
var _v = (0, react_2.useState)(), optionsError = _v[0], setOptionsError = _v[1];
|
|
445
544
|
// Operators: prop-provided (compact) or fetched via operatorsUrl (dpql,
|
|
446
545
|
// ported from IDE Options) — the fetch overrides the seeded prop value.
|
|
447
|
-
var
|
|
546
|
+
var _w = (0, react_2.useState)(operatorsProp), operators = _w[0], setOperators = _w[1];
|
|
448
547
|
// Remote-fetch loading (ported from IDE Options); only relevant when one of
|
|
449
548
|
// the fetch urls is set — schema-as-props consumers never see the skeleton.
|
|
450
|
-
var
|
|
549
|
+
var _x = (0, react_2.useState)(!!(url || customUrl || operatorsUrl)), loading = _x[0], setLoading = _x[1];
|
|
451
550
|
var confirmAction = (0, reqore_1.useReqoreProperty)('confirmAction');
|
|
452
551
|
var theme = (0, reqore_1.useReqoreTheme)();
|
|
453
|
-
var
|
|
454
|
-
var
|
|
552
|
+
var _y = (0, react_2.useState)(), focusedEditing = _y[0], setFocusedEditing = _y[1];
|
|
553
|
+
var _z = (0, react_2.useState)(false), showFieldTypes = _z[0], setShowFieldTypes = _z[1];
|
|
455
554
|
// Global toggle (toolbar ⓘ): reveal the short-description info panel on every
|
|
456
555
|
// field that has a short_desc. Per-row ⓘ overrides still win over it.
|
|
457
556
|
// Global field-info visibility, tri-state: `undefined` = default (critical
|
|
458
557
|
// messages auto-open, the rest closed); `true` = show all; `false` = hide all
|
|
459
558
|
// (even message fields). The toolbar ⓘ drives it.
|
|
460
|
-
var
|
|
461
|
-
var
|
|
462
|
-
var
|
|
559
|
+
var _0 = (0, react_2.useState)(undefined), showAllDescriptions = _0[0], setShowAllDescriptions = _0[1];
|
|
560
|
+
var _1 = (0, react_2.useState)(), showHelpForOption = _1[0], setShowHelpForOption = _1[1];
|
|
561
|
+
var _2 = (0, react_2.useState)(false), showInvalidOptionsOnly = _2[0], setShowInvalidOptionsOnly = _2[1];
|
|
463
562
|
// Which options are expanded into their editor (several can be open at once).
|
|
464
|
-
var
|
|
563
|
+
var _3 = (0, react_2.useState)([]), expandedOptions = _3[0], setExpandedOptions = _3[1];
|
|
465
564
|
/** Status boxes whose "N more fields" control the reader has opened. Keyed by
|
|
466
565
|
box so opening Optional does not also unfold Set. */
|
|
467
|
-
var
|
|
566
|
+
var _4 = (0, react_2.useState)([]), expandedMoreBoxes = _4[0], setExpandedMoreBoxes = _4[1];
|
|
468
567
|
// --- Reveal a status box's content when it is opened ----------------------
|
|
469
568
|
//
|
|
470
569
|
// The status boxes stack, so the last one ("Optional", which holds every
|
|
@@ -480,7 +579,7 @@ var FormEngineImpl = function (_a) {
|
|
|
480
579
|
// box has not grown and there is nothing to scroll to. A layout effect runs
|
|
481
580
|
// after the DOM is updated and before paint, which makes the reveal
|
|
482
581
|
// deterministic instead of a guessed delay.
|
|
483
|
-
var
|
|
582
|
+
var _5 = (0, react_2.useState)(undefined), openedStatusBox = _5[0], setOpenedStatusBox = _5[1];
|
|
484
583
|
var statusBoxRefs = (0, react_2.useRef)({});
|
|
485
584
|
(0, react_2.useLayoutEffect)(function () {
|
|
486
585
|
var _a, _b;
|
|
@@ -511,13 +610,13 @@ var FormEngineImpl = function (_a) {
|
|
|
511
610
|
var settledBucket = (0, react_2.useRef)({});
|
|
512
611
|
// Measured form width (not viewport — the form lives in drawers/panels of
|
|
513
612
|
// arbitrary width) drives the stacked narrow layout.
|
|
514
|
-
var
|
|
613
|
+
var _6 = (0, react_use_1.useMeasure)(), compactWrapRef = _6[0], compactWrapWidth = _6[1].width;
|
|
515
614
|
// Own handle on the scroll wrap (useMeasure's ref is a callback, no `.current`)
|
|
516
615
|
// so the label-column measurement can publish its CSS var on the element. It's
|
|
517
616
|
// STATE, not a ref: the wrap mounts only after the loading-skeleton gate
|
|
518
617
|
// resolves, so the measurement effect must re-run when the node appears — a
|
|
519
618
|
// ref wouldn't retrigger it.
|
|
520
|
-
var
|
|
619
|
+
var _7 = (0, react_2.useState)(null), compactWrapNode = _7[0], setCompactWrapNode = _7[1];
|
|
521
620
|
// Ref mirror of the wrap node for callbacks that must not re-create when it
|
|
522
621
|
// mounts (flashOptions reads it inside a rAF).
|
|
523
622
|
var compactWrapNodeRef = (0, react_2.useRef)(null);
|
|
@@ -571,8 +670,8 @@ var FormEngineImpl = function (_a) {
|
|
|
571
670
|
var readRowHeights = (0, react_2.useRef)({});
|
|
572
671
|
// Required-groups linkage: hovering a group chip highlights every member row;
|
|
573
672
|
// clicking a sibling in the chip's popover scrolls to it and flashes it.
|
|
574
|
-
var
|
|
575
|
-
var
|
|
673
|
+
var _8 = (0, react_2.useState)([]), highlightedOptions = _8[0], setHighlightedOptions = _8[1];
|
|
674
|
+
var _9 = (0, react_2.useState)([]), flashedOptions = _9[0], setFlashedOptions = _9[1];
|
|
576
675
|
var flashTimeout = (0, react_2.useRef)();
|
|
577
676
|
var flashOptions = (0, react_2.useCallback)(function (optionNames, scrollToFirst) {
|
|
578
677
|
if (scrollToFirst === void 0) { scrollToFirst = false; }
|
|
@@ -621,28 +720,58 @@ var FormEngineImpl = function (_a) {
|
|
|
621
720
|
});
|
|
622
721
|
var compactNarrow = !!compactWrapWidth && compactWrapWidth < 480;
|
|
623
722
|
// Info panels auto-open on Tier-1 content; the per-row user override sticks.
|
|
624
|
-
var
|
|
723
|
+
var _10 = (0, react_2.useState)({}), infoPanelOverrides = _10[0], setInfoPanelOverrides = _10[1];
|
|
625
724
|
// Toolbar filters affect the listed rows only — the meter reflects the full set.
|
|
626
|
-
var
|
|
627
|
-
var
|
|
725
|
+
var _11 = (0, react_2.useState)(false), requiredOnly = _11[0], setRequiredOnly = _11[1];
|
|
726
|
+
var _12 = (0, react_2.useState)(''), compactQuery = _12[0], setCompactQuery = _12[1];
|
|
628
727
|
// Compact field sort (Fields menu → "Sort by"); 'schema' = declared order.
|
|
629
|
-
var
|
|
630
|
-
var
|
|
728
|
+
var _13 = (0, react_2.useState)('schema'), compactSort = _13[0], setCompactSort = _13[1];
|
|
729
|
+
var _14 = (0, react_2.useState)(function () { return ({
|
|
631
730
|
fields: (0, exports.fixOptions)(value, options || {}, undefined, isRendererOnly),
|
|
632
731
|
meta: undefined,
|
|
633
|
-
}); }), localValue =
|
|
732
|
+
}); }), localValue = _14[0], setLocalValue = _14[1];
|
|
634
733
|
var originalValue = (0, react_2.useRef)();
|
|
635
734
|
// Track the last value we emitted via onChange so we can skip re-applying fixOptions
|
|
636
735
|
// when the parent echoes it back as the new value prop (controlled component loop prevention)
|
|
637
736
|
var lastEmittedValue = (0, react_2.useRef)(value);
|
|
737
|
+
/**
|
|
738
|
+
* A `localValue` that is only a MIRROR of the incoming `value`, and so must
|
|
739
|
+
* never be emitted back as though this form had answered something.
|
|
740
|
+
*
|
|
741
|
+
* `localValue` is derived state: the sync-down effect below rebuilds it from
|
|
742
|
+
* the `value` prop. When that rebuild adds nothing (`fixOptions` had no
|
|
743
|
+
* default to materialise), the result says exactly what the parent already
|
|
744
|
+
* holds, and emitting it is not a change — it is this form repeating the
|
|
745
|
+
* parent's own words back at it.
|
|
746
|
+
*
|
|
747
|
+
* That repetition is harmless in a form that owns its state outright and
|
|
748
|
+
* fatal in one that shares a parent with a NESTED engine. The two write to
|
|
749
|
+
* the same parent value, so each sees the other's write arrive as an external
|
|
750
|
+
* change; `lastEmittedValue` is then always one step behind and its guard
|
|
751
|
+
* never fires. The engines alternate between two states forever, several
|
|
752
|
+
* times a second, and the newer write is repeatedly overwritten by the older
|
|
753
|
+
* one. Measured in the test editor: the row's summary flipped between two
|
|
754
|
+
* readings indefinitely and `setTimeout` was starved past a 45-second
|
|
755
|
+
* deadline.
|
|
756
|
+
*
|
|
757
|
+
* Only a mirror that CHANGES nothing is held back. A rebuild that restores a
|
|
758
|
+
* required or preselected field's default still emits, because that default
|
|
759
|
+
* is genuinely new information the parent has to be told about — which is the
|
|
760
|
+
* whole reason the sync-down runs `fixOptions` at all.
|
|
761
|
+
*/
|
|
762
|
+
var mirroredValue = (0, react_2.useRef)(undefined);
|
|
638
763
|
if (originalValue.current === undefined && (0, size_1.default)(value)) {
|
|
639
764
|
originalValue.current = localValue.fields;
|
|
640
765
|
}
|
|
641
766
|
var unavailableOptionsCount = (0, react_2.useRef)(0);
|
|
642
|
-
var
|
|
767
|
+
var _15 = (0, useQorusTypes_1.useQorusTypes)(), compactValue = _15.compactValue, typesLoading = _15.loading;
|
|
643
768
|
var templates = (0, useTemplates_1.useTemplates)(allowTemplates, rest.stringTemplates, interfaceContext);
|
|
644
769
|
(0, react_2.useEffect)(function () {
|
|
645
|
-
if ((0,
|
|
770
|
+
if (!(0, exports.shouldEmitLocalValue)({
|
|
771
|
+
localValue: localValue.fields,
|
|
772
|
+
value: value,
|
|
773
|
+
mirroredValue: mirroredValue.current,
|
|
774
|
+
})) {
|
|
646
775
|
return;
|
|
647
776
|
}
|
|
648
777
|
var toEmit = (0, size_1.default)(localValue.fields) ? localValue.fields : undefined;
|
|
@@ -822,16 +951,45 @@ var FormEngineImpl = function (_a) {
|
|
|
822
951
|
// Note: compare fixedValue against value, not localValue.fields — localValue may have been
|
|
823
952
|
// updated by nested FormEngine emissions, so comparing against it would never skip.
|
|
824
953
|
var normalizedValue = normalizeEmptyFieldValues(value);
|
|
954
|
+
/* What this rebuild lets us agree with the parent on — `undefined` when it
|
|
955
|
+
contributed something the parent has yet to learn. */
|
|
956
|
+
var agreed = (0, exports.agreementFromRebuild)(fixedValue, value);
|
|
825
957
|
if ((0, lodash_1.isEqual)(normalizedValue, normalizeEmptyFieldValues(lastEmittedValue.current)) &&
|
|
826
|
-
|
|
958
|
+
agreed !== undefined) {
|
|
827
959
|
return;
|
|
828
960
|
}
|
|
829
961
|
if (!originalValue.current && (0, size_1.default)(fixedValue)) {
|
|
830
962
|
originalValue.current = fixedValue;
|
|
831
963
|
}
|
|
964
|
+
/* Remember a mirror so the emit effect can tell one from an answer, and
|
|
965
|
+
record the agreement it represents. A rebuild that DID add something
|
|
966
|
+
leaves both alone — the parent has to learn about it. */
|
|
967
|
+
mirroredValue.current = agreed;
|
|
968
|
+
if (agreed !== undefined) {
|
|
969
|
+
lastEmittedValue.current = agreed;
|
|
970
|
+
}
|
|
832
971
|
setLocalValue === null || setLocalValue === void 0 ? void 0 : setLocalValue({ fields: fixedValue, meta: undefined });
|
|
833
972
|
}, [JSON.stringify(options), JSON.stringify(value), isRendererOnly]);
|
|
973
|
+
/**
|
|
974
|
+
* Fields the reader has actually edited in this instance.
|
|
975
|
+
*
|
|
976
|
+
* "This field is required" is an ERROR message, and an error is a report that
|
|
977
|
+
* something went wrong. Under a field nobody has been in yet it reports
|
|
978
|
+
* nothing — the form is empty because it is new — while the requirement is
|
|
979
|
+
* already stated by the asterisk, by the Needs-attention box the row sits in,
|
|
980
|
+
* and by the completion meter. A form whose first act is to accuse the reader
|
|
981
|
+
* of a mistake they have not made teaches them to discount its warnings.
|
|
982
|
+
*
|
|
983
|
+
* So the message waits for a touch. Being IN the field and leaving it empty
|
|
984
|
+
* is a real gap, and that one shows. A ref, not state: every edit re-renders
|
|
985
|
+
* anyway, so the following render reads the current set with no second pass.
|
|
986
|
+
*/
|
|
987
|
+
var touchedOptionsRef = (0, react_2.useRef)(new Set());
|
|
834
988
|
var handleValueChange = (0, react_2.useCallback)(function (optionName, val, _type, isFunction) {
|
|
989
|
+
// Every route into this handler is a person acting: typing, picking from a
|
|
990
|
+
// menu, clearing the value, adding an optional field. Marked here rather
|
|
991
|
+
// than inside the updater below, which React may invoke twice.
|
|
992
|
+
touchedOptionsRef.current.add(optionName);
|
|
835
993
|
setLocalValue(function (_a) {
|
|
836
994
|
var _b, _c;
|
|
837
995
|
var _d, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
@@ -1006,7 +1164,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1006
1164
|
return newValue;
|
|
1007
1165
|
}
|
|
1008
1166
|
var rendererType = (0, exports.getType)((options[optionName].ui_type || options[optionName].type), operators, option === null || option === void 0 ? void 0 : option.op);
|
|
1009
|
-
var storageType = getOptionFieldStorageType(optionName, option === null || option === void 0 ? void 0 : option.type, options, operators, option === null || option === void 0 ? void 0 : option.op, isRendererOnly);
|
|
1167
|
+
var storageType = (0, exports.getOptionFieldStorageType)(optionName, option === null || option === void 0 ? void 0 : option.type, options, operators, option === null || option === void 0 ? void 0 : option.op, isRendererOnly, optionHoldsExpression(option));
|
|
1010
1168
|
if (!(0, lodash_1.isPlainObject)(option)) {
|
|
1011
1169
|
return __assign(__assign({}, newValue), (_a = {}, _a[optionName] = {
|
|
1012
1170
|
type: storageType || rendererType,
|
|
@@ -1107,7 +1265,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1107
1265
|
var getValidityData = (0, react_2.useCallback)(function () {
|
|
1108
1266
|
var fields = (0, reduce_1.default)(availableOptions, function (result, option, optionName) {
|
|
1109
1267
|
var _a, _b;
|
|
1110
|
-
var type = getOptionFieldStorageType(optionName, option.type, options, operators, option.op, isRendererOnly);
|
|
1268
|
+
var type = (0, exports.getOptionFieldStorageType)(optionName, option.type, options, operators, option.op, isRendererOnly, optionHoldsExpression(option));
|
|
1111
1269
|
var optionValue = option.value;
|
|
1112
1270
|
var isRequired = (_a = options === null || options === void 0 ? void 0 : options[optionName]) === null || _a === void 0 ? void 0 : _a.required;
|
|
1113
1271
|
var hasRequiredGroups = !!((_b = options === null || options === void 0 ? void 0 : options[optionName]) === null || _b === void 0 ? void 0 : _b.required_groups);
|
|
@@ -1151,7 +1309,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1151
1309
|
return (0, reduce_1.default)(availableOptions, function (newValue, option, optionName) {
|
|
1152
1310
|
var _a;
|
|
1153
1311
|
if (showInvalidOptionsOnly &&
|
|
1154
|
-
isOptionValid(optionName, getOptionFieldStorageType(optionName, option.type, options, operators, option.op, isRendererOnly), option.value)) {
|
|
1312
|
+
isOptionValid(optionName, (0, exports.getOptionFieldStorageType)(optionName, option.type, options, operators, option.op, isRendererOnly, optionHoldsExpression(option)), option.value)) {
|
|
1155
1313
|
return newValue;
|
|
1156
1314
|
}
|
|
1157
1315
|
return __assign(__assign({}, newValue), (_a = {}, _a[optionName] = option, _a));
|
|
@@ -1185,7 +1343,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1185
1343
|
if (hidden)
|
|
1186
1344
|
return 'optional';
|
|
1187
1345
|
var schema = options === null || options === void 0 ? void 0 : options[name];
|
|
1188
|
-
var type = getOptionFieldStorageType(name, (_a = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _a === void 0 ? void 0 : _a.type, options, operators, (_b = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _b === void 0 ? void 0 : _b.op, isRendererOnly);
|
|
1346
|
+
var type = (0, exports.getOptionFieldStorageType)(name, (_a = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _a === void 0 ? void 0 : _a.type, options, operators, (_b = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _b === void 0 ? void 0 : _b.op, isRendererOnly, optionHoldsExpression(availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]));
|
|
1189
1347
|
var value = (_c = availableOptions === null || availableOptions === void 0 ? void 0 : availableOptions[name]) === null || _c === void 0 ? void 0 : _c.value;
|
|
1190
1348
|
// A schema-declared hash whose every entry is a materialised-but-unset
|
|
1191
1349
|
// field holds nothing, so it is not "set" — without this the row showed a
|
|
@@ -1307,11 +1465,16 @@ var FormEngineImpl = function (_a) {
|
|
|
1307
1465
|
if (!names.length) {
|
|
1308
1466
|
return;
|
|
1309
1467
|
}
|
|
1310
|
-
hasAppliedInitialExpansionRef.current = true;
|
|
1311
1468
|
var toExpand = initialExpandedOptions.filter(function (name) { return names.includes(name); });
|
|
1312
1469
|
if (!toExpand.length) {
|
|
1470
|
+
// Not "there is no such row" — "not YET". A server-driven schema arrives
|
|
1471
|
+
// in pieces, and the row the caller named can be in a later one (a test's
|
|
1472
|
+
// `cases` field materialises once its step-kind catalogue lands). Latching
|
|
1473
|
+
// here would spend the one shot on a form that did not yet contain the
|
|
1474
|
+
// field, and the address would never be applied at all.
|
|
1313
1475
|
return;
|
|
1314
1476
|
}
|
|
1477
|
+
hasAppliedInitialExpansionRef.current = true;
|
|
1315
1478
|
setExpandedOptions(function (prev) { return __spreadArray(__spreadArray([], prev, true), toExpand.filter(function (name) { return !prev.includes(name); }), true); });
|
|
1316
1479
|
}, [initialExpandedOptions, compact, availableOptions]);
|
|
1317
1480
|
// --- First-attention-field autofocus (opt-in) -----------------------------
|
|
@@ -1394,7 +1557,14 @@ var FormEngineImpl = function (_a) {
|
|
|
1394
1557
|
}
|
|
1395
1558
|
setExpandedOptions(function (prev) {
|
|
1396
1559
|
return prev.includes(target) ? prev
|
|
1397
|
-
: expandMode === 'multi' ? __spreadArray(__spreadArray([], prev, true), [target], false)
|
|
1560
|
+
: expandMode === 'multi' ? __spreadArray(__spreadArray([], prev, true), [target], false)
|
|
1561
|
+
// `expandMode: 'single'` is a rule about what a CLICK does: opening a
|
|
1562
|
+
// row closes the one the reader last opened. It is not a licence to
|
|
1563
|
+
// close a row the HOST named through `initialExpandedOptions`. That
|
|
1564
|
+
// is an address — a statement about what the page is FOR, made before
|
|
1565
|
+
// the reader did anything — and this scan is a convenience layered on
|
|
1566
|
+
// top of it. Keep the named rows; replace only what a click could.
|
|
1567
|
+
: __spreadArray(__spreadArray([], prev.filter(function (name) { return initialExpandedOptions === null || initialExpandedOptions === void 0 ? void 0 : initialExpandedOptions.includes(name); }), true), [target], false);
|
|
1398
1568
|
});
|
|
1399
1569
|
}
|
|
1400
1570
|
}, [
|
|
@@ -1407,10 +1577,13 @@ var FormEngineImpl = function (_a) {
|
|
|
1407
1577
|
dependencyLockedNames,
|
|
1408
1578
|
getOptionBucket,
|
|
1409
1579
|
expandMode,
|
|
1580
|
+
initialExpandedOptions,
|
|
1410
1581
|
]);
|
|
1411
1582
|
// Read-first completion summary (how many shown options have a value set),
|
|
1412
1583
|
// surfaced as a progress meter at the top of the compact form.
|
|
1413
|
-
var readFirstCompletion = (0, react_2.useMemo)(function () {
|
|
1584
|
+
var readFirstCompletion = (0, react_2.useMemo)(function () {
|
|
1585
|
+
return (0, readFirst_1.getReadFirstCompletion)(availableOptions, function (name) { return getOptionBucket(name) === 'attention'; });
|
|
1586
|
+
}, [JSON.stringify(availableOptions), getOptionBucket]);
|
|
1414
1587
|
var optionalFields = (0, react_2.useMemo)(function () {
|
|
1415
1588
|
return Object.keys(filteredOptions).map(function (option) {
|
|
1416
1589
|
var _a, _b, _c, _d, _f, _g;
|
|
@@ -1477,7 +1650,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1477
1650
|
// The info panel below the row keeps showing schema messages while editing —
|
|
1478
1651
|
// rendering them in the editor too would balloon a one-line edit.
|
|
1479
1652
|
suppressSchemaMessages) {
|
|
1480
|
-
var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
1653
|
+
var _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
1481
1654
|
var type = _a.type, other = __rest(_a, ["type"]);
|
|
1482
1655
|
var operatorParts = (0, common_1.fixOperatorValue)(other.op);
|
|
1483
1656
|
// The RENDERER type for this row — which editor mounts. Distinct from the
|
|
@@ -1494,11 +1667,28 @@ var FormEngineImpl = function (_a) {
|
|
|
1494
1667
|
var optionSchema = options === null || options === void 0 ? void 0 : options[optionName];
|
|
1495
1668
|
var schemaUiType = optionSchema === null || optionSchema === void 0 ? void 0 : optionSchema.ui_type;
|
|
1496
1669
|
var uiTypeIsAnyLike = schemaUiType === 'any' || schemaUiType === 'auto';
|
|
1670
|
+
/* An EXPRESSION's stored type is skipped in this chain.
|
|
1671
|
+
|
|
1672
|
+
The value is `{ is_expression: true, value: {...} }`, so the type saved
|
|
1673
|
+
beside it describes that envelope — `hash` — not what the field holds.
|
|
1674
|
+
With no `ui_type` to win first, that `hash` beat the schema's `auto`
|
|
1675
|
+
and was handed to the expression editor as the return type to check
|
|
1676
|
+
against: `1 + 2` on a field declared `auto` came back "This does not
|
|
1677
|
+
fit. The expression returns int, and this field holds hash". A literal
|
|
1678
|
+
`1` was fine, because a literal is stored as a plain value whose type
|
|
1679
|
+
matches.
|
|
1680
|
+
|
|
1681
|
+
Dropping the stored type here lets the schema decide, which is the
|
|
1682
|
+
only party that knows what the field accepts. This is the row
|
|
1683
|
+
renderer's OWN resolution and does not go through
|
|
1684
|
+
`getOptionFieldStorageType`, so guarding that one alone left this
|
|
1685
|
+
untouched. */
|
|
1686
|
+
var storedRowType = optionHoldsExpression(other) ? undefined : type;
|
|
1497
1687
|
var resolvedType = ((0, readFirst_1.isFixedCompactAllowedValueOption)(optionSchema) ?
|
|
1498
1688
|
getOptionSchemaStorageType(optionSchema, isRendererOnly)
|
|
1499
1689
|
: schemaUiType && !uiTypeIsAnyLike ? schemaUiType
|
|
1500
1690
|
: undefined) ||
|
|
1501
|
-
|
|
1691
|
+
storedRowType ||
|
|
1502
1692
|
schemaUiType ||
|
|
1503
1693
|
(optionSchema === null || optionSchema === void 0 ? void 0 : optionSchema.type) ||
|
|
1504
1694
|
'any';
|
|
@@ -1567,25 +1757,42 @@ var FormEngineImpl = function (_a) {
|
|
|
1567
1757
|
// control groups. The allowed-values renderer itself enforces the
|
|
1568
1758
|
// fixed catalogue and never exposes free-form entry.
|
|
1569
1759
|
allowCustomValues: (0, readFirst_1.isFixedCompactAllowedValueOption)(optionSchema) ||
|
|
1570
|
-
(((_g = options === null || options === void 0 ? void 0 : options[optionName]) === null || _g === void 0 ? void 0 : _g.supports_custom_values) !== false && resolvedType !== 'any'),
|
|
1760
|
+
(((_g = options === null || options === void 0 ? void 0 : options[optionName]) === null || _g === void 0 ? void 0 : _g.supports_custom_values) !== false && resolvedType !== 'any'),
|
|
1761
|
+
// A field may declare a template list OF ITS OWN, and when it does
|
|
1762
|
+
// that list is the one to offer. The engine-wide `stringTemplates`
|
|
1763
|
+
// are the form's shared vocabulary - config items, system properties
|
|
1764
|
+
// - and every field draws on the same set. A per-field list answers a
|
|
1765
|
+
// question only that field asks: a test assertion's `$.` references
|
|
1766
|
+
// are the values ITS case captured, and no other field in the form
|
|
1767
|
+
// should be offering them.
|
|
1768
|
+
//
|
|
1769
|
+
// Passing the engine's list unconditionally overwrote the schema's,
|
|
1770
|
+
// so a field that declared templates had none by the time it
|
|
1771
|
+
// rendered. On a typed field that only cost the picker; on an
|
|
1772
|
+
// ANY-LIKE one it changed the question, because `TemplateField`
|
|
1773
|
+
// opens on the template selector only when there is something to
|
|
1774
|
+
// pick and otherwise falls back to the type picker. An untyped field
|
|
1775
|
+
// therefore asked the author to choose `string`/`int`/`hash` before
|
|
1776
|
+
// it would let them name a value they had already captured.
|
|
1777
|
+
templates: (_h = optionSchema === null || optionSchema === void 0 ? void 0 : optionSchema.templates) !== null && _h !== void 0 ? _h : templates.value }, (0, exports.getTypeAndCanBeNull)(
|
|
1571
1778
|
// The RENDERER type picks the editor — the storage type lives on
|
|
1572
1779
|
// the value envelope. Passing storage here rendered a `richtext`
|
|
1573
1780
|
// field as a plain string input.
|
|
1574
|
-
resolvedType, (
|
|
1781
|
+
resolvedType, (_j = options === null || options === void 0 ? void 0 : options[optionName]) === null || _j === void 0 ? void 0 : _j.allowed_values, other.op), { ui_type: resolvedType, name: optionName, uniqueName: "".concat(uniqueName ? "".concat(uniqueName, ".") : "".concat(name ? "".concat(name, ".") : '')).concat(optionName), onChange:
|
|
1575
1782
|
// Identity-stable on purpose: the typed fields debounce on
|
|
1576
1783
|
// `[localValue, onChange]` — an inline lambda resets the pending emit
|
|
1577
1784
|
// every render and the typed value can starve.
|
|
1578
|
-
handleValueChange, key: optionName, arg_schema: (
|
|
1785
|
+
handleValueChange, key: optionName, arg_schema: (_k = options === null || options === void 0 ? void 0 : options[optionName]) === null || _k === void 0 ? void 0 : _k.arg_schema, noSoft: !!(rest === null || rest === void 0 ? void 0 : rest.options), value: other.value, isFunction: other.is_expression, isDefaultFunction: ((_l = options === null || options === void 0 ? void 0 : options[optionName]) === null || _l === void 0 ? void 0 : _l.default_view) === 'expression', sensitive: (_m = options === null || options === void 0 ? void 0 : options[optionName]) === null || _m === void 0 ? void 0 : _m.sensitive, default_value: (0, common_1.getDefaultValue)(options === null || options === void 0 ? void 0 : options[optionName]), isDefaultTemplate: ((_o = options === null || options === void 0 ? void 0 : options[optionName]) === null || _o === void 0 ? void 0 : _o.default_view) === 'template', allowed_values: (_p = options === null || options === void 0 ? void 0 : options[optionName]) === null || _p === void 0 ? void 0 : _p.allowed_values, allowed_values_creatable: (_q = options === null || options === void 0 ? void 0 : options[optionName]) === null || _q === void 0 ? void 0 : _q.allowed_values_creatable, disabled: ((_r = options === null || options === void 0 ? void 0 : options[optionName]) === null || _r === void 0 ? void 0 : _r.disabled) ||
|
|
1579
1786
|
(
|
|
1580
1787
|
// a system-owned field states that as `readonly`; only the older
|
|
1581
1788
|
// compat projection also sent `disabled`, so honouring only
|
|
1582
1789
|
// `disabled` rendered an editable control for a value the user
|
|
1583
1790
|
// cannot change (see CompactRow's `fieldReadonly`)
|
|
1584
|
-
(
|
|
1791
|
+
(_s = options === null || options === void 0 ? void 0 : options[optionName]) === null || _s === void 0 ? void 0 : _s.readonly) ||
|
|
1585
1792
|
readOnly ||
|
|
1586
|
-
!(0, validations_1.hasAllDependenciesFullfilled)((
|
|
1793
|
+
!(0, validations_1.hasAllDependenciesFullfilled)((_t = options === null || options === void 0 ? void 0 : options[optionName]) === null || _t === void 0 ? void 0 : _t.depends_on, availableOptions, options || {}), readOnly: readOnly, size: editorSize || rest.size, menuItems: ((_u = options === null || options === void 0 ? void 0 : options[optionName]) === null || _u === void 0 ? void 0 : _u.ui_type) === 'any' ?
|
|
1587
1794
|
getCustomMenuTemplateItems(optionName)
|
|
1588
|
-
: undefined }, templateFieldProps, { forceDropdown: effectiveForceDropdown })), (0, jsx_runtime_1.jsx)(OptionFieldMessages_1.OptionFieldMessages, { schema: options || {}, allOptions: availableOptions, name: optionName, option: __assign({ type: resolvedType }, other), getType: getTypeForOption }), operators && (0, size_1.default)(operators) && (0, size_1.default)(other.op) ?
|
|
1795
|
+
: undefined }, templateFieldProps, { forceDropdown: effectiveForceDropdown })), (0, jsx_runtime_1.jsx)(OptionFieldMessages_1.OptionFieldMessages, { schema: options || {}, allOptions: availableOptions, name: optionName, option: __assign({ type: resolvedType }, other), getType: getTypeForOption, untouched: !touchedOptionsRef.current.has(optionName) }), operators && (0, size_1.default)(operators) && (0, size_1.default)(other.op) ?
|
|
1589
1796
|
(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 ?
|
|
1590
1797
|
resolvedType === 'richtext' ?
|
|
1591
1798
|
(0, common_1.richtextToString)(other.value)
|
|
@@ -1807,6 +2014,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1807
2014
|
// removes it, and then the header carries just the consumer's own actions.
|
|
1808
2015
|
var compactHeaderActions = (0, react_2.useMemo)(function () { return __spreadArray(__spreadArray([], (compactToolbarParts ? [{ as: CompactToolbar_1.CompactToolbar, responsive: false }] : []), true), ((compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions) || []), true); }, [compactPanelProps === null || compactPanelProps === void 0 ? void 0 : compactPanelProps.actions, compactToolbarParts]);
|
|
1809
2016
|
var renderCompact = function () {
|
|
2017
|
+
var _a, _b, _c;
|
|
1810
2018
|
var headerBg = "".concat((0, colors_1.changeDarkness)((0, colors_1.getMainBackgroundColor)(theme), 0.02)).concat((0, colors_1.percentToHexAlpha)(88));
|
|
1811
2019
|
// Toolbar filters narrow the listed rows; the meter reflects the full set.
|
|
1812
2020
|
var query = compactQuery.trim().toLowerCase();
|
|
@@ -1899,7 +2107,7 @@ var FormEngineImpl = function (_a) {
|
|
|
1899
2107
|
var isUnset_1 = function (name) { var _a; return (0, readFirst_1.isOptionValueEmpty)((_a = shownOptions[name]) === null || _a === void 0 ? void 0 : _a.value); };
|
|
1900
2108
|
var isFieldInvalid_1 = function (name) {
|
|
1901
2109
|
var _a, _b, _c;
|
|
1902
|
-
return !isOptionValid(name, getOptionFieldStorageType(name, (_a = shownOptions[name]) === null || _a === void 0 ? void 0 : _a.type, options, operators, (_b = shownOptions[name]) === null || _b === void 0 ? void 0 : _b.op, isRendererOnly), (_c = shownOptions[name]) === null || _c === void 0 ? void 0 : _c.value);
|
|
2110
|
+
return !isOptionValid(name, (0, exports.getOptionFieldStorageType)(name, (_a = shownOptions[name]) === null || _a === void 0 ? void 0 : _a.type, options, operators, (_b = shownOptions[name]) === null || _b === void 0 ? void 0 : _b.op, isRendererOnly), (_c = shownOptions[name]) === null || _c === void 0 ? void 0 : _c.value);
|
|
1903
2111
|
};
|
|
1904
2112
|
var comparator_1 = function (a, b) {
|
|
1905
2113
|
switch (compactSort) {
|
|
@@ -1985,6 +2193,13 @@ var FormEngineImpl = function (_a) {
|
|
|
1985
2193
|
var bucketCount = function (b) {
|
|
1986
2194
|
return bucketGroups[b].reduce(function (n, g) { return n + buckets[b][g].length; }, 0);
|
|
1987
2195
|
};
|
|
2196
|
+
/* The default is to collapse the Optional box, and an explicit pass is
|
|
2197
|
+
what waives the "never collapse the sole box" escape below. Resolving it
|
|
2198
|
+
here rather than in the parameter list is what makes the two
|
|
2199
|
+
distinguishable — `['optional']` as a default and `['optional']` from a
|
|
2200
|
+
caller mean different things. */
|
|
2201
|
+
var compactCollapsedGroups = compactCollapsedGroupsProp !== null && compactCollapsedGroupsProp !== void 0 ? compactCollapsedGroupsProp : ['optional'];
|
|
2202
|
+
var collapsedGroupsRequested = compactCollapsedGroupsProp !== undefined;
|
|
1988
2203
|
// "Is the Optional box the whole form?" — when nothing needs attention and
|
|
1989
2204
|
// nothing is set, collapsing it leaves a card with no visible content at all.
|
|
1990
2205
|
var onlyOptionalRows = bucketCount('optional') > 0 && bucketCount('attention') === 0 && bucketCount('set') === 0;
|
|
@@ -2025,9 +2240,18 @@ var FormEngineImpl = function (_a) {
|
|
|
2025
2240
|
bucketGroups[boxKey].some(function (groupName) { return groupHasPreselectedRow(boxKey, groupName); });
|
|
2026
2241
|
};
|
|
2027
2242
|
var STATUS_BOXES = [
|
|
2028
|
-
{
|
|
2029
|
-
|
|
2030
|
-
|
|
2243
|
+
{
|
|
2244
|
+
key: 'attention',
|
|
2245
|
+
label: (_a = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.attention) !== null && _a !== void 0 ? _a : 'Needs attention',
|
|
2246
|
+
intent: 'warning',
|
|
2247
|
+
icon: 'ErrorWarningLine',
|
|
2248
|
+
},
|
|
2249
|
+
{ key: 'set', label: (_b = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.set) !== null && _b !== void 0 ? _b : 'Set', intent: 'success', icon: 'CheckLine' },
|
|
2250
|
+
{
|
|
2251
|
+
key: 'optional',
|
|
2252
|
+
label: (_c = compactBoxLabels === null || compactBoxLabels === void 0 ? void 0 : compactBoxLabels.optional) !== null && _c !== void 0 ? _c : 'Optional',
|
|
2253
|
+
icon: 'CheckboxBlankCircleLine',
|
|
2254
|
+
},
|
|
2031
2255
|
];
|
|
2032
2256
|
// Build the rows for one group: contiguous required-group members are pulled
|
|
2033
2257
|
// together at the first member's slot and rendered as a connected rail (flat
|
|
@@ -2130,7 +2354,9 @@ var FormEngineImpl = function (_a) {
|
|
|
2130
2354
|
var hasPreselectedRows = boxHasPreselectedRows(box.key);
|
|
2131
2355
|
var wouldCollapse = compactCollapsedGroups.includes(box.key) &&
|
|
2132
2356
|
!query &&
|
|
2133
|
-
!(box.key === 'optional' &&
|
|
2357
|
+
!(box.key === 'optional' &&
|
|
2358
|
+
onlyOptionalRows &&
|
|
2359
|
+
!collapsedGroupsRequested);
|
|
2134
2360
|
// Only a box that was opened SOLELY to reveal a preselected
|
|
2135
2361
|
// row splits its body; a box that renders open anyway shows
|
|
2136
2362
|
// all of its groups as before.
|