ngx-t-forms-types 0.0.30 → 0.0.33
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/dist/interfaces/Form/formSubmissionHandleInterface.d.ts +6 -0
- package/dist/interfaces/FormBuilder/DefaultEelement.js +76 -0
- package/dist/interfaces/FormBuilder/DefaultInputConfigInterface.d.ts +13 -0
- package/dist/interfaces/FormBuilder/FormInputKeys.d.ts +6 -0
- package/dist/interfaces/FormBuilder/FormInputKeys.js +6 -0
- package/dist/interfaces/FormBuilder/inputConfig/ElementEditConfig.js +188 -3
- package/dist/interfaces/formInput/APIDataFetchingConfigurationInterface.d.ts +34 -0
- package/dist/interfaces/formInput/BasicFormInputInterface.d.ts +1 -0
- package/dist/interfaces/formInput/BasicFormInputInterface.js +1 -0
- package/dist/interfaces/formInput/IMscoaAccount.d.ts +19 -3
- package/dist/interfaces/formInput/ISelectInputInterface.d.ts +12 -0
- package/dist/interfaces/formInput/MultipleInterface.d.ts +10 -0
- package/dist/interfaces/formInput/WorkflowDocumentPicker.d.ts +2 -0
- package/dist/schemas/FormInputSchema.js +41 -2
- package/dist/schemas/MatOptionsSchema.js +7 -0
- package/dist/schemas/MscoaConfigSchema.js +1 -0
- package/dist/schemas/index.d.ts +2 -1
- package/dist/schemas/index.js +2 -1
- package/dist/skillet/authoring-rules.d.ts +41 -0
- package/dist/skillet/authoring-rules.js +61 -0
- package/dist/skillet/extra-members.d.ts +143 -0
- package/dist/skillet/extra-members.js +79 -0
- package/dist/skillet/form.d.ts +170 -0
- package/dist/skillet/form.js +139 -0
- package/dist/skillet/index.d.ts +43 -0
- package/dist/skillet/index.js +46 -0
- package/dist/skillet/input-members.d.ts +375 -0
- package/dist/skillet/input-members.js +186 -0
- package/dist/skillet/internal/coupling.d.ts +63 -0
- package/dist/skillet/internal/coupling.js +69 -0
- package/dist/skillet/internal/editor-guidance.d.ts +64 -0
- package/dist/skillet/internal/editor-guidance.js +291 -0
- package/dist/skillet/members/calculated-field.d.ts +155 -0
- package/dist/skillet/members/calculated-field.js +105 -0
- package/dist/skillet/members/conditional.d.ts +69 -0
- package/dist/skillet/members/conditional.js +16 -0
- package/dist/skillet/members/document-picker.d.ts +182 -0
- package/dist/skillet/members/document-picker.js +111 -0
- package/dist/skillet/members/mat-options.d.ts +187 -0
- package/dist/skillet/members/mat-options.js +92 -0
- package/dist/skillet/members/mscoa.d.ts +182 -0
- package/dist/skillet/members/mscoa.js +129 -0
- package/dist/skillet/members/pagination.d.ts +59 -0
- package/dist/skillet/members/pagination.js +16 -0
- package/dist/skillet/members/table.d.ts +178 -0
- package/dist/skillet/members/table.js +105 -0
- package/dist/skillet/members/validators.d.ts +197 -0
- package/dist/skillet/members/validators.js +74 -0
- package/dist/skillet/members/value.d.ts +154 -0
- package/dist/skillet/members/value.js +97 -0
- package/dist/skillet/shared-types.d.ts +57 -0
- package/dist/skillet/shared-types.js +69 -0
- package/dist/skillet/tests/house-rules.spec.d.ts +1 -0
- package/dist/skillet/tests/house-rules.spec.js +162 -0
- package/dist/skillet/tests/skillet-coupling.spec.d.ts +1 -0
- package/dist/skillet/tests/skillet-coupling.spec.js +191 -0
- package/dist/skillet/tests/variant-assembly.spec.d.ts +1 -0
- package/dist/skillet/tests/variant-assembly.spec.js +643 -0
- package/dist/skillet/variants.d.ts +138 -0
- package/dist/skillet/variants.js +536 -0
- package/dist/skillet/workflow-context.d.ts +95 -0
- package/dist/skillet/workflow-context.js +128 -0
- package/package.json +78 -60
|
@@ -5,6 +5,8 @@ import { IBasicFormInput } from "./BasicFormInputInterface.js";
|
|
|
5
5
|
export interface IWorkflowDocumentPicker extends IBasicFormInput {
|
|
6
6
|
workflowPickerConfig: IWorkflowDocumentPickerConfig;
|
|
7
7
|
[AllFormInputPrimaryKeys.AllowMultipleSelection]: boolean;
|
|
8
|
+
/** @see ISelectInputInterface.selectUpto */
|
|
9
|
+
selectUpto?: number;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Document-picker configuration.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Joi from 'joi';
|
|
2
|
-
import { AllFormInputPrimaryKeys, SpecialElementKeys } from '../interfaces/FormBuilder/index.js';
|
|
3
|
-
import { AdjudicationSteps, AutocapitalizeOptions, ElementTypes, InputDataTypes, InputPipeTypes, InputTypes } from '../interfaces/formInput/index.js';
|
|
2
|
+
import { AllFormInputPrimaryKeys, FormInputKeys, SpecialElementKeys } from '../interfaces/FormBuilder/index.js';
|
|
3
|
+
import { AdjudicationSteps, AutocapitalizeOptions, AutocompleteOptions, ElementTypes, InputDataTypes, InputPipeTypes, InputTypes } from '../interfaces/formInput/index.js';
|
|
4
4
|
// import { InputFileType } from '../interfaces/formInput/FileUploadInputInterface.js';
|
|
5
5
|
// import { LabelPosition } from '../interfaces/formInput/ToggleInputInterface.js';
|
|
6
6
|
// import { MscoaInputConfigSchema } from './MscoaConfigSchema.js';
|
|
@@ -49,6 +49,45 @@ export const baseFormColumnInputsSchema = Joi.object({
|
|
|
49
49
|
[AllFormInputPrimaryKeys.Max]: Joi.alternatives().try(Joi.number(), Joi.string(), Joi.date()).optional(),
|
|
50
50
|
[AllFormInputPrimaryKeys.MinLength]: Joi.alternatives().try(Joi.number(), Joi.string()).optional(),
|
|
51
51
|
[AllFormInputPrimaryKeys.MaxLength]: Joi.alternatives().try(Joi.number(), Joi.string()).optional(),
|
|
52
|
+
[FormInputKeys.Pattern]: Joi.string().allow('').optional(),
|
|
53
|
+
// --- presentation members declared on IBasicFormInput ----------------------
|
|
54
|
+
//
|
|
55
|
+
// These were declared on the interfaces and listed in DefaultInputConfig, but
|
|
56
|
+
// never here — and because Joi rejects unknown keys, a column carrying one
|
|
57
|
+
// failed the WHOLE form with '"Slides > Columns > Placeholder" is not
|
|
58
|
+
// allowed'. Empty strings are allowed throughout: the settings panel writes
|
|
59
|
+
// '' when an author clears a text row, and rejecting that made clearing a
|
|
60
|
+
// prefix a validation error.
|
|
61
|
+
[FormInputKeys.Placeholder]: Joi.string().allow('').optional(),
|
|
62
|
+
[FormInputKeys.Autocomplete]: Joi.string().valid(...Object.values(AutocompleteOptions)).optional(),
|
|
63
|
+
[FormInputKeys.Disabled]: Joi.boolean().optional(),
|
|
64
|
+
[FormInputKeys.PrefixText]: Joi.string().allow('').optional(),
|
|
65
|
+
[FormInputKeys.SuffixText]: Joi.string().allow('').optional(),
|
|
66
|
+
[FormInputKeys.PrefixIcon]: Joi.string().allow('').optional(),
|
|
67
|
+
[FormInputKeys.SuffixIcon]: Joi.string().allow('').optional(),
|
|
68
|
+
// Only meaningful alongside allowMultipleSelection; a single-selection
|
|
69
|
+
// control is already capped at one. `min(1)` because "select up to zero" is
|
|
70
|
+
// not a limit, it is a disabled control.
|
|
71
|
+
[FormInputKeys.SelectUpto]: Joi.number().integer().min(1).optional(),
|
|
72
|
+
// formControlNames of columns inside a multipleInput group to total.
|
|
73
|
+
[FormInputKeys.ShowTotalsOf]: Joi.array().items(Joi.string()).optional(),
|
|
74
|
+
// --- matrix table ---------------------------------------------------------
|
|
75
|
+
//
|
|
76
|
+
// Declared by IMatrixInput and accepted here so a stored form carrying either
|
|
77
|
+
// still validates. No element offers them: ElementTypes.MatrixTable is
|
|
78
|
+
// commented out of the enum, so nothing can currently be built with one.
|
|
79
|
+
//
|
|
80
|
+
// `columnsConfig` is keyed by column name and typed
|
|
81
|
+
// `TableColumnConfigInterface | any`, so its values are only checked to be
|
|
82
|
+
// objects — constraining them further here would reject the `any` half the
|
|
83
|
+
// interface explicitly permits.
|
|
84
|
+
[FormInputKeys.MatrixTableConfig]: Joi.object({
|
|
85
|
+
dataSource: Joi.string().required()
|
|
86
|
+
}).optional(),
|
|
87
|
+
[FormInputKeys.TableConfig]: Joi.object({
|
|
88
|
+
displayedColumnsInOrder: Joi.array().items(Joi.string()).required(),
|
|
89
|
+
columnsConfig: Joi.object().pattern(Joi.string(), Joi.object()).required()
|
|
90
|
+
}).optional(),
|
|
52
91
|
[AllFormInputPrimaryKeys.LinkedSegmentId]: Joi.string().optional(),
|
|
53
92
|
[AllFormInputPrimaryKeys.MscoaConfig]: MscoaInputConfigSchema.optional(),
|
|
54
93
|
[AllFormInputPrimaryKeys.SystemDefault]: Joi.boolean().optional(),
|
|
@@ -59,6 +59,13 @@ const APIDataFetchingConfigurationSchema = Joi.object({
|
|
|
59
59
|
capturedQuery: queryTemplateSchema.optional(),
|
|
60
60
|
// The endpoint's Postman description, verbatim; display-only (Docs tab).
|
|
61
61
|
capturedDocs: Joi.string().allow('').optional(),
|
|
62
|
+
// Opt-out of the automatic read-only lock on a value the tower owns. On a
|
|
63
|
+
// SCALAR it is gap-filling on an 'api' slot: a manually entered value stands
|
|
64
|
+
// whenever the fetch contributes nothing. On a COMPLEX value (the input
|
|
65
|
+
// declares dataType 'object' or 'array') it is also offered on a 'local'
|
|
66
|
+
// slot, and the tower re-merges each new derived value over the live one as a
|
|
67
|
+
// delta instead of replacing it. Only meaningful on a value slot.
|
|
68
|
+
allowManualValueEntry: Joi.boolean().optional(),
|
|
62
69
|
backEndConfig: Joi.object({
|
|
63
70
|
// Optional: a 'template'-mode fetch shapes its body from payloadTemplate and
|
|
64
71
|
// carries no mapping; GET fetches never had one. Readers default it to [].
|
|
@@ -16,6 +16,7 @@ export const DualCashExclusionRuleSchema = Joi.object({
|
|
|
16
16
|
id: Joi.string().optional(),
|
|
17
17
|
pattern: Joi.string().required(),
|
|
18
18
|
flags: Joi.string().allow('').optional(),
|
|
19
|
+
matchField: Joi.string().allow('').optional(),
|
|
19
20
|
segment: Joi.string().allow('').optional(),
|
|
20
21
|
description: Joi.string().allow('').optional()
|
|
21
22
|
});
|
package/dist/schemas/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateCalculatedFieldRules } from "./CalculatedFieldRulesSchema.js";
|
|
2
2
|
import { formColumnInputsSchema, validateFormColumnInputs, validateFormColumnInputsWithRequired } from "./FormInputSchema.js";
|
|
3
3
|
import { DatabaseFormSchema, FormSchema, validateApiDataFetchingConfiguration, validateForm, validateFormSlide } from "./FormSchema.js";
|
|
4
|
-
|
|
4
|
+
import { MscoaInputConfigSchema, validateMscoaInputConfig } from "./MscoaConfigSchema.js";
|
|
5
|
+
export { FormSchema, DatabaseFormSchema, formColumnInputsSchema, validateCalculatedFieldRules, validateFormColumnInputs, validateFormSlide, validateFormColumnInputsWithRequired, validateForm, validateApiDataFetchingConfiguration, MscoaInputConfigSchema, validateMscoaInputConfig };
|
package/dist/schemas/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateCalculatedFieldRules } from "./CalculatedFieldRulesSchema.js";
|
|
2
2
|
import { formColumnInputsSchema, validateFormColumnInputs, validateFormColumnInputsWithRequired } from "./FormInputSchema.js";
|
|
3
3
|
import { DatabaseFormSchema, FormSchema, validateApiDataFetchingConfiguration, validateForm, validateFormSlide } from "./FormSchema.js";
|
|
4
|
-
|
|
4
|
+
import { MscoaInputConfigSchema, validateMscoaInputConfig } from "./MscoaConfigSchema.js";
|
|
5
|
+
export { FormSchema, DatabaseFormSchema, formColumnInputsSchema, validateCalculatedFieldRules, validateFormColumnInputs, validateFormSlide, validateFormColumnInputsWithRequired, validateForm, validateApiDataFetchingConfiguration, MscoaInputConfigSchema, validateMscoaInputConfig };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form-wide authoring rules from the Form Creation Guide, stated once.
|
|
3
|
+
*
|
|
4
|
+
* ## Why these are not on the members they concern
|
|
5
|
+
*
|
|
6
|
+
* Hashbrown names every hoisted `$defs` entry by camel-casing the node's
|
|
7
|
+
* DESCRIPTION, and every `$ref` repeats that name in full. A member shared by
|
|
8
|
+
* every element — `label`, `formControlName`, `colSize` — is referenced once
|
|
9
|
+
* per element per nesting level, so each character of its description is paid
|
|
10
|
+
* around forty times in the full column schema. Measured before this split,
|
|
11
|
+
* `$ref` names were 58% of the full schema and 44% of the common one, and the
|
|
12
|
+
* seven most-shared members accounted for most of that.
|
|
13
|
+
*
|
|
14
|
+
* So a shared member's description carries its definition and the one rule
|
|
15
|
+
* that has to be read at that member, and the guidance that applies across the
|
|
16
|
+
* form is stated here, on the root, which is emitted exactly once. The
|
|
17
|
+
* sentences are the guide's — see `doc/features/skillet-internals.md`, "Where
|
|
18
|
+
* the prose comes from" — and they are the ones a model needs before it writes
|
|
19
|
+
* any field rather than while it writes one.
|
|
20
|
+
*
|
|
21
|
+
* `createFormDraftSchema()` composes these into the form's description. A
|
|
22
|
+
* caller using `createColumnSchema()` on its own has no root to carry them and
|
|
23
|
+
* should put {@link describeAuthoringRules} in the system prompt instead.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* The shape of a control name: lowerCamelCase, letters and digits only.
|
|
27
|
+
*
|
|
28
|
+
* Narrower than the engine, which also allows underscores — narrower is the
|
|
29
|
+
* permitted direction, and one convention is easier to follow than two.
|
|
30
|
+
* Exported so a test can hold the reserved-names rule to it: a reserved name
|
|
31
|
+
* the pattern would accept must be named in the rules, and one it rejects
|
|
32
|
+
* need not be.
|
|
33
|
+
*/
|
|
34
|
+
export declare const CONTROL_NAME_PATTERN = "^[a-z][a-zA-Z0-9]*$";
|
|
35
|
+
/**
|
|
36
|
+
* The rules, one sentence group each, in the order the guide states them:
|
|
37
|
+
* naming, words, types, what the engine reads, layout, error timing.
|
|
38
|
+
*/
|
|
39
|
+
export declare const AUTHORING_RULES: readonly string[];
|
|
40
|
+
/** The rules as one paragraph, for a form description or a system prompt. */
|
|
41
|
+
export declare function describeAuthoringRules(): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { RESERVED_CONTROL_NAMES } from './workflow-context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Form-wide authoring rules from the Form Creation Guide, stated once.
|
|
4
|
+
*
|
|
5
|
+
* ## Why these are not on the members they concern
|
|
6
|
+
*
|
|
7
|
+
* Hashbrown names every hoisted `$defs` entry by camel-casing the node's
|
|
8
|
+
* DESCRIPTION, and every `$ref` repeats that name in full. A member shared by
|
|
9
|
+
* every element — `label`, `formControlName`, `colSize` — is referenced once
|
|
10
|
+
* per element per nesting level, so each character of its description is paid
|
|
11
|
+
* around forty times in the full column schema. Measured before this split,
|
|
12
|
+
* `$ref` names were 58% of the full schema and 44% of the common one, and the
|
|
13
|
+
* seven most-shared members accounted for most of that.
|
|
14
|
+
*
|
|
15
|
+
* So a shared member's description carries its definition and the one rule
|
|
16
|
+
* that has to be read at that member, and the guidance that applies across the
|
|
17
|
+
* form is stated here, on the root, which is emitted exactly once. The
|
|
18
|
+
* sentences are the guide's — see `doc/features/skillet-internals.md`, "Where
|
|
19
|
+
* the prose comes from" — and they are the ones a model needs before it writes
|
|
20
|
+
* any field rather than while it writes one.
|
|
21
|
+
*
|
|
22
|
+
* `createFormDraftSchema()` composes these into the form's description. A
|
|
23
|
+
* caller using `createColumnSchema()` on its own has no root to carry them and
|
|
24
|
+
* should put {@link describeAuthoringRules} in the system prompt instead.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* The shape of a control name: lowerCamelCase, letters and digits only.
|
|
28
|
+
*
|
|
29
|
+
* Narrower than the engine, which also allows underscores — narrower is the
|
|
30
|
+
* permitted direction, and one convention is easier to follow than two.
|
|
31
|
+
* Exported so a test can hold the reserved-names rule to it: a reserved name
|
|
32
|
+
* the pattern would accept must be named in the rules, and one it rejects
|
|
33
|
+
* need not be.
|
|
34
|
+
*/
|
|
35
|
+
export const CONTROL_NAME_PATTERN = '^[a-z][a-zA-Z0-9]*$';
|
|
36
|
+
/**
|
|
37
|
+
* The reserved names the pattern alone does not stop.
|
|
38
|
+
*
|
|
39
|
+
* `_id` and the `SYSTEM_*` inputs fail the pattern and need no mention;
|
|
40
|
+
* `reference`, `status` and `data` pass it, so the rule has to carry them.
|
|
41
|
+
* Filtered at evaluation rather than listed by hand, so the sentence says
|
|
42
|
+
* exactly what the pattern leaves open — no more, which would be noise, and no
|
|
43
|
+
* less, which would be a hole.
|
|
44
|
+
*/
|
|
45
|
+
const RESERVED_WELL_FORMED_NAMES = RESERVED_CONTROL_NAMES.filter((name) => new RegExp(CONTROL_NAME_PATTERN).test(name));
|
|
46
|
+
/**
|
|
47
|
+
* The rules, one sentence group each, in the order the guide states them:
|
|
48
|
+
* naming, words, types, what the engine reads, layout, error timing.
|
|
49
|
+
*/
|
|
50
|
+
export const AUTHORING_RULES = [
|
|
51
|
+
`Control names are unique across the whole form and across every other form of the same workflow unless the same answer is deliberately carried forward, never change once the form is live, and are never one of the names the transaction document already owns: ${RESERVED_WELL_FORMED_NAMES.join(', ')}.`,
|
|
52
|
+
"A label never explains — that is the hint's job. Required fields are marked automatically, so add '(optional)' to the label of a field that is not required. A hint gives the format ('As it appears on your ID document, 13 digits'), the source ('Top right of the invoice, starts with INV') or the reason for asking something sensitive ('Used only to send delivery updates by SMS'); every field that could be misunderstood gets one.",
|
|
53
|
+
'Set type and dataType to the data. A number is never left as text: the engine compares strictly, so a number stored as text never equals a number. A phone number is type tel with dataType string.',
|
|
54
|
+
'A review decision toggle, a date the engine schedules on and any value a decision gate reads are always required and never conditionally hidden.',
|
|
55
|
+
'Related short values share one row (start and end as 6 and 6; quantity, unit price and line total as 4, 4 and 4); a textarea, an item list, a picker, an uploader or a signature never shares a row; the same kind of field keeps the same width all the way down a slide.',
|
|
56
|
+
'Errors are shown only after the user has left a field, so onlySetTempErrorOnTouch is true on nearly every field.',
|
|
57
|
+
];
|
|
58
|
+
/** The rules as one paragraph, for a form description or a system prompt. */
|
|
59
|
+
export function describeAuthoringRules() {
|
|
60
|
+
return AUTHORING_RULES.join(' ');
|
|
61
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { s } from '@hashbrownai/core';
|
|
2
|
+
import type { FormColumnInputs } from '../interfaces/Form/index.js';
|
|
3
|
+
import { FormInputKeys, SpecialElementKeys } from '../interfaces/FormBuilder/FormInputKeys.js';
|
|
4
|
+
import { AssertNever } from './internal/coupling.js';
|
|
5
|
+
import { type TableConfigDraft } from './members/table.js';
|
|
6
|
+
/**
|
|
7
|
+
* The members an element can carry that `AllFormInputPrimaryKeys` does not
|
|
8
|
+
* declare.
|
|
9
|
+
*
|
|
10
|
+
* `DefaultInputConfig[element].properties` is typed
|
|
11
|
+
* `Array<FormInputKeys | SpecialElementKeys | AllFormInputPrimaryKeys>`, and it
|
|
12
|
+
* uses all three. Keying the main registry on `AllFormInputPrimaryKeys` alone
|
|
13
|
+
* left fourteen keys unresolvable at assembly time, including `pattern` and
|
|
14
|
+
* `placeholder` — properties too ordinary for a form generator to do without.
|
|
15
|
+
*
|
|
16
|
+
* ## `properties` is not a property list
|
|
17
|
+
*
|
|
18
|
+
* It is the list of ROWS the settings panel shows for that element, which is a
|
|
19
|
+
* superset of what the input stores. `matOptionsApiCall` and
|
|
20
|
+
* `showAllMcoaSegments` open editors; they are not keys on a form input and no
|
|
21
|
+
* interface declares them. Those are recorded in {@link EDITOR_ONLY_KEYS} and
|
|
22
|
+
* skipped during assembly — absent by intent, not by oversight.
|
|
23
|
+
*
|
|
24
|
+
* Enum membership does not decide this, which is worth stating because it looks
|
|
25
|
+
* like it should: `multipleInputAvailableOperations` sits in
|
|
26
|
+
* `SpecialElementKeys` beside the editor directives, yet `IMultiple` really
|
|
27
|
+
* does declare it. The test that settles it is whether an interface declares
|
|
28
|
+
* the key, so that is the test used.
|
|
29
|
+
*/
|
|
30
|
+
/** The type an extra member must produce, read off the real interface. */
|
|
31
|
+
type MemberValue<K extends string> = K extends keyof FormColumnInputs ? NonNullable<FormColumnInputs[K]> : unknown;
|
|
32
|
+
/**
|
|
33
|
+
* Keys that open an editor rather than store a value. They appear in
|
|
34
|
+
* `properties` and must never appear in a generation schema.
|
|
35
|
+
*/
|
|
36
|
+
export declare const EDITOR_ONLY_KEYS: readonly [SpecialElementKeys.FormValueFromInputSelector, SpecialElementKeys.FormInputSelector, SpecialElementKeys.MatOptionsApiCall, SpecialElementKeys.MatOptionsRequiredInputs, SpecialElementKeys.MatOptionsApiValueAccessRules, SpecialElementKeys.DefaultCalculatedFieldRules, SpecialElementKeys.MatOptionsItemType, SpecialElementKeys.MatOptionsSelectionOptions, SpecialElementKeys.DefaultValuePipe, SpecialElementKeys.DefaultCurrencySelect, SpecialElementKeys.DefaultDecimalNumberInput, SpecialElementKeys.Default, SpecialElementKeys.ShowAllMcoaSegments];
|
|
37
|
+
/**
|
|
38
|
+
* Extra members still to be modelled.
|
|
39
|
+
*
|
|
40
|
+
* The four date bounds are all typed `Date`. A model emits JSON, so the best it
|
|
41
|
+
* can produce is an ISO string, which is not assignable to `Date` — they need
|
|
42
|
+
* the same draft-and-expand treatment as `matOptions` rather than a quiet
|
|
43
|
+
* mistyping. `tableConfig` and `matrixTableConfig` are nested configuration
|
|
44
|
+
* objects awaiting their own modules.
|
|
45
|
+
*/
|
|
46
|
+
export declare const PENDING_EXTRA_MEMBERS: readonly [FormInputKeys.StartMinDate, FormInputKeys.StartMaxDate, FormInputKeys.EndMinDate, FormInputKeys.EndMaxDate];
|
|
47
|
+
/**
|
|
48
|
+
* Extra members whose schema produces an AUTHORING DRAFT rather than the stored
|
|
49
|
+
* shape — the same category `DRAFT_INPUT_MEMBERS` defines in
|
|
50
|
+
* `input-members.ts`, for keys that live in the other two enums.
|
|
51
|
+
*
|
|
52
|
+
* `tableConfig` is the only one. Its `columnsConfig` is keyed by column name —
|
|
53
|
+
* an index signature, which Skillet has no node for — so the model emits an
|
|
54
|
+
* ARRAY of columns each carrying its own key, and the application folds that
|
|
55
|
+
* into the record. See `members/table.ts`.
|
|
56
|
+
*/
|
|
57
|
+
export declare const DRAFT_EXTRA_MEMBERS: readonly [FormInputKeys.TableConfig];
|
|
58
|
+
/** The draft each drafted extra member is held to. */
|
|
59
|
+
interface ExtraMemberDrafts {
|
|
60
|
+
[FormInputKeys.TableConfig]: TableConfigDraft;
|
|
61
|
+
}
|
|
62
|
+
export declare const extraDraftMemberSchemas: {
|
|
63
|
+
tableConfig: s.ObjectType<{
|
|
64
|
+
displayedColumnsInOrder: s.ArrayType<s.StringType>;
|
|
65
|
+
columns: s.ArrayType<s.ObjectType<{
|
|
66
|
+
key: s.StringType;
|
|
67
|
+
type: s.EnumType<["caluculated", "property", "checkBox", "primaryKey"]>;
|
|
68
|
+
property: s.StringType;
|
|
69
|
+
label: s.StringType;
|
|
70
|
+
inEdit: s.BooleanType;
|
|
71
|
+
checkUpto: s.StringType;
|
|
72
|
+
calculatedFieldRules: s.ObjectType<{
|
|
73
|
+
formula: s.StringType;
|
|
74
|
+
variables: s.ArrayType<import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
|
|
75
|
+
bindingType: "field";
|
|
76
|
+
variable: string;
|
|
77
|
+
label: string;
|
|
78
|
+
formControlName: string;
|
|
79
|
+
} | {
|
|
80
|
+
bindingType: "listAggregate";
|
|
81
|
+
variable: string;
|
|
82
|
+
label: string;
|
|
83
|
+
formControlName: string;
|
|
84
|
+
parentInputFormControl: string;
|
|
85
|
+
function: import("..").CalculationFunctions;
|
|
86
|
+
applyFunctionToCol: string;
|
|
87
|
+
applyFunctionToLabel: string | null;
|
|
88
|
+
filterValuesByCol: string | null;
|
|
89
|
+
filterValuesByThisColLabel: string | null;
|
|
90
|
+
tableCell: boolean | null;
|
|
91
|
+
}>>;
|
|
92
|
+
decimalPlaces: import("@hashbrownai/core/src/schema/base").SchemaForUnion<number | null>;
|
|
93
|
+
roundingMode: import("@hashbrownai/core/src/schema/base").SchemaForUnion<"FLOOR" | "CEIL" | "ROUND" | null>;
|
|
94
|
+
getFormulaFromAFormInput: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
95
|
+
formControlWithFormula: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
96
|
+
}>;
|
|
97
|
+
reductionFunction: import("@hashbrownai/core/src/schema/base").SchemaForUnion<"sum" | null>;
|
|
98
|
+
colorScale: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
99
|
+
}>>;
|
|
100
|
+
}>;
|
|
101
|
+
};
|
|
102
|
+
export declare const extraInputMemberSchemas: {
|
|
103
|
+
pattern: s.StringType;
|
|
104
|
+
placeholder: s.StringType;
|
|
105
|
+
autocomplete: s.EnumType<import("..").AutocompleteOptions[]>;
|
|
106
|
+
disabled: s.BooleanType;
|
|
107
|
+
prefixText: s.StringType;
|
|
108
|
+
suffixText: s.StringType;
|
|
109
|
+
prefixIcon: s.StringType;
|
|
110
|
+
suffixIcon: s.StringType;
|
|
111
|
+
selectUpto: s.IntegerType;
|
|
112
|
+
showTotalsOf: s.ArrayType<s.StringType>;
|
|
113
|
+
multipleInputAvailableOperations: s.ArrayType<s.EnumType<import("..").MultipleInputAvailableOperations[]>>;
|
|
114
|
+
matrixTableConfig: s.ObjectType<{
|
|
115
|
+
dataSource: s.StringType;
|
|
116
|
+
}>;
|
|
117
|
+
};
|
|
118
|
+
export type ExtraMemberKey = keyof typeof extraInputMemberSchemas;
|
|
119
|
+
type EditorOnlyKey = (typeof EDITOR_ONLY_KEYS)[number];
|
|
120
|
+
type PendingExtraKey = (typeof PENDING_EXTRA_MEMBERS)[number];
|
|
121
|
+
type DraftExtraKey = (typeof DRAFT_EXTRA_MEMBERS)[number];
|
|
122
|
+
/**
|
|
123
|
+
* Every `FormInputKeys` and `SpecialElementKeys` member is accounted for —
|
|
124
|
+
* modelled, deferred, declared editor-only, or already covered by the primary
|
|
125
|
+
* registry because both enums spell the same key.
|
|
126
|
+
*/
|
|
127
|
+
export type _EveryExtraKeyClassified = AssertNever<Exclude<FormInputKeys | SpecialElementKeys, ExtraMemberKey | EditorOnlyKey | PendingExtraKey | DraftExtraKey | FormInputKeys.Accept | FormInputKeys.ConditionalInputConfig | FormInputKeys.GroupBy>>;
|
|
128
|
+
/** Every extra node produces a value its interface member can hold. */
|
|
129
|
+
export type _NoExtraValueDrift = AssertNever<{
|
|
130
|
+
[K in ExtraMemberKey]: [
|
|
131
|
+
s.Infer<(typeof extraInputMemberSchemas)[K]>
|
|
132
|
+
] extends [MemberValue<K>] ? never : K;
|
|
133
|
+
}[ExtraMemberKey]>;
|
|
134
|
+
/** Every drafted extra node produces the draft it declares. */
|
|
135
|
+
export type _NoExtraDraftDrift = AssertNever<{
|
|
136
|
+
[K in DraftExtraKey]: [
|
|
137
|
+
s.Infer<(typeof extraDraftMemberSchemas)[K]>
|
|
138
|
+
] extends [ExtraMemberDrafts[K]] ? never : K;
|
|
139
|
+
}[DraftExtraKey]>;
|
|
140
|
+
/** Runtime key lists, derived from the enums. */
|
|
141
|
+
export declare const ALL_FORM_INPUT_KEYS: FormInputKeys[];
|
|
142
|
+
export declare const ALL_SPECIAL_ELEMENT_KEYS: SpecialElementKeys[];
|
|
143
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { s } from '@hashbrownai/core';
|
|
2
|
+
import { FormInputKeys, SpecialElementKeys, } from '../interfaces/FormBuilder/FormInputKeys.js';
|
|
3
|
+
import { enumValues } from './internal/coupling.js';
|
|
4
|
+
import { describe } from './internal/editor-guidance.js';
|
|
5
|
+
import { autocompleteSchema, multipleInputOperationSchema } from './shared-types.js';
|
|
6
|
+
import { matrixTableConfigSchema, tableConfigSchema, } from './members/table.js';
|
|
7
|
+
/**
|
|
8
|
+
* Keys that open an editor rather than store a value. They appear in
|
|
9
|
+
* `properties` and must never appear in a generation schema.
|
|
10
|
+
*/
|
|
11
|
+
export const EDITOR_ONLY_KEYS = [
|
|
12
|
+
SpecialElementKeys.FormValueFromInputSelector,
|
|
13
|
+
SpecialElementKeys.FormInputSelector,
|
|
14
|
+
SpecialElementKeys.MatOptionsApiCall,
|
|
15
|
+
SpecialElementKeys.MatOptionsRequiredInputs,
|
|
16
|
+
SpecialElementKeys.MatOptionsApiValueAccessRules,
|
|
17
|
+
SpecialElementKeys.DefaultCalculatedFieldRules,
|
|
18
|
+
SpecialElementKeys.MatOptionsItemType,
|
|
19
|
+
SpecialElementKeys.MatOptionsSelectionOptions,
|
|
20
|
+
SpecialElementKeys.DefaultValuePipe,
|
|
21
|
+
SpecialElementKeys.DefaultCurrencySelect,
|
|
22
|
+
SpecialElementKeys.DefaultDecimalNumberInput,
|
|
23
|
+
SpecialElementKeys.Default,
|
|
24
|
+
SpecialElementKeys.ShowAllMcoaSegments,
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Extra members still to be modelled.
|
|
28
|
+
*
|
|
29
|
+
* The four date bounds are all typed `Date`. A model emits JSON, so the best it
|
|
30
|
+
* can produce is an ISO string, which is not assignable to `Date` — they need
|
|
31
|
+
* the same draft-and-expand treatment as `matOptions` rather than a quiet
|
|
32
|
+
* mistyping. `tableConfig` and `matrixTableConfig` are nested configuration
|
|
33
|
+
* objects awaiting their own modules.
|
|
34
|
+
*/
|
|
35
|
+
export const PENDING_EXTRA_MEMBERS = [
|
|
36
|
+
FormInputKeys.StartMinDate,
|
|
37
|
+
FormInputKeys.StartMaxDate,
|
|
38
|
+
FormInputKeys.EndMinDate,
|
|
39
|
+
FormInputKeys.EndMaxDate,
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Extra members whose schema produces an AUTHORING DRAFT rather than the stored
|
|
43
|
+
* shape — the same category `DRAFT_INPUT_MEMBERS` defines in
|
|
44
|
+
* `input-members.ts`, for keys that live in the other two enums.
|
|
45
|
+
*
|
|
46
|
+
* `tableConfig` is the only one. Its `columnsConfig` is keyed by column name —
|
|
47
|
+
* an index signature, which Skillet has no node for — so the model emits an
|
|
48
|
+
* ARRAY of columns each carrying its own key, and the application folds that
|
|
49
|
+
* into the record. See `members/table.ts`.
|
|
50
|
+
*/
|
|
51
|
+
export const DRAFT_EXTRA_MEMBERS = [FormInputKeys.TableConfig];
|
|
52
|
+
export const extraDraftMemberSchemas = {
|
|
53
|
+
[FormInputKeys.TableConfig]: tableConfigSchema,
|
|
54
|
+
};
|
|
55
|
+
export const extraInputMemberSchemas = {
|
|
56
|
+
[FormInputKeys.Pattern]: s.string(describe("A regular expression the typed value must match, as a JavaScript pattern without delimiters. Only for a code with a fixed shape that nothing looks up, such as an ID number or an order reference; never on a lookup key such as a supplier number, where the endpoint's error is the check.", FormInputKeys.Pattern)),
|
|
57
|
+
// Each authored sentence below is the DEFINITION only. The advice that goes
|
|
58
|
+
// with it — give an example, turn autofill off for one-time values, when a
|
|
59
|
+
// selection cap applies at all — is written once, on the editor row, and
|
|
60
|
+
// composed in by `describe()`. Saying it in both places produced descriptions
|
|
61
|
+
// that made the same point twice in slightly different words.
|
|
62
|
+
[FormInputKeys.Placeholder]: s.string(describe('Ghost text shown inside the field while it is empty. Prefer none: it disappears as the user types and screen readers may skip it, so anything that matters belongs in the hint.', FormInputKeys.Placeholder)),
|
|
63
|
+
[FormInputKeys.Autocomplete]: autocompleteSchema,
|
|
64
|
+
[FormInputKeys.Disabled]: s.boolean(describe('Whether the control is rendered but cannot be interacted with.', FormInputKeys.Disabled)),
|
|
65
|
+
[FormInputKeys.PrefixText]: s.string(describe('Short static text shown before the field, for example a currency symbol. It stops the user typing the unit into the box.', FormInputKeys.PrefixText)),
|
|
66
|
+
[FormInputKeys.SuffixText]: s.string(describe('Short static text shown after the field, for example a unit such as kg or %. It stops the user typing the unit into the box.', FormInputKeys.SuffixText)),
|
|
67
|
+
[FormInputKeys.PrefixIcon]: s.string(describe('Name of the Material icon shown before the field.', FormInputKeys.PrefixIcon)),
|
|
68
|
+
[FormInputKeys.SuffixIcon]: s.string(describe('Name of the Material icon shown after the field.', FormInputKeys.SuffixIcon)),
|
|
69
|
+
// The applicability rule is the valuable half here: the editor row declares
|
|
70
|
+
// `allowMultipleSelection === true`, and Skillet cannot express that
|
|
71
|
+
// structurally, so it arrives as the sentence a model actually needs.
|
|
72
|
+
[FormInputKeys.SelectUpto]: s.integer(describe('The most options the user may choose at once.', FormInputKeys.SelectUpto), { minimum: 1 }),
|
|
73
|
+
[FormInputKeys.ShowTotalsOf]: s.array(describe("The formControlNames of columns inside this list whose values are summed and shown as a total. For the user's eyes only: a total used anywhere else must also be a calculated field on the form itself.", FormInputKeys.ShowTotalsOf), s.string('A formControlName inside this list to total.')),
|
|
74
|
+
[SpecialElementKeys.MultipleInputAvailableOperations]: s.array(describe("Which operations the user may perform on the rows of this repeatable group: usually 'add', 'remove' and 'update'; add 'lockEditOnFormSubmit' when rows must not change once submitted.", SpecialElementKeys.MultipleInputAvailableOperations), multipleInputOperationSchema),
|
|
75
|
+
[FormInputKeys.MatrixTableConfig]: matrixTableConfigSchema,
|
|
76
|
+
};
|
|
77
|
+
/** Runtime key lists, derived from the enums. */
|
|
78
|
+
export const ALL_FORM_INPUT_KEYS = enumValues(FormInputKeys);
|
|
79
|
+
export const ALL_SPECIAL_ELEMENT_KEYS = enumValues(SpecialElementKeys);
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { s } from '@hashbrownai/core';
|
|
2
|
+
import { type AssertNever } from './internal/coupling.js';
|
|
3
|
+
import { type AvailableApiEndpoint } from './members/mat-options.js';
|
|
4
|
+
import { type ColumnSchemaOptions } from './variants.js';
|
|
5
|
+
import { type WorkflowStepContext } from './workflow-context.js';
|
|
6
|
+
/**
|
|
7
|
+
* The whole-form schema: slides of columns, plus how the form submits.
|
|
8
|
+
*
|
|
9
|
+
* ## This produces a draft, and it cannot not
|
|
10
|
+
*
|
|
11
|
+
* `FormSchema` requires `submissionHandle.submissionAPI` — an array of at least
|
|
12
|
+
* one full `APIDataFetchingConfiguration`, complete with `_id`, `httpEndPoint`
|
|
13
|
+
* and `httpMethod`. It is the same problem `matOptions` has, except mandatory:
|
|
14
|
+
* there is no valid form without it, and no model can author it from a prompt.
|
|
15
|
+
* `FormSlide.sectionId` is the same story on a smaller scale — an identifier
|
|
16
|
+
* the builder assigns, which a model can only fabricate.
|
|
17
|
+
*
|
|
18
|
+
* So a generated form is a {@link FormDraft}. The application supplies section
|
|
19
|
+
* ids and expands the chosen endpoint ids into stored configurations, and only
|
|
20
|
+
* then does `validateForm()` have something it can pass. Any pipeline built on
|
|
21
|
+
* this needs that expansion step; there is no arrangement of the schema that
|
|
22
|
+
* removes it.
|
|
23
|
+
*
|
|
24
|
+
* ## Streaming
|
|
25
|
+
*
|
|
26
|
+
* `streaming: true` switches the slide and column arrays to their streaming
|
|
27
|
+
* variants, so a client parses each slide as it arrives instead of waiting for
|
|
28
|
+
* the closing brace of a large form. It changes nothing about the data — only
|
|
29
|
+
* when a consumer can first see it.
|
|
30
|
+
*/
|
|
31
|
+
export interface SubmissionHandleDraft {
|
|
32
|
+
submissionAPI: string[];
|
|
33
|
+
/**
|
|
34
|
+
* The pre-submit gate, as an endpoint id, expanded into
|
|
35
|
+
* `FormSubmissionHandleInterface.canSubmitAPI`.
|
|
36
|
+
*
|
|
37
|
+
* Absent — not empty — on most drafts, and on every draft generated without
|
|
38
|
+
* `FormSchemaOptions.canSubmitEndpoints`: the key is only put to the model
|
|
39
|
+
* when the caller has gate endpoints to offer, and a hand-built form carries
|
|
40
|
+
* no `canSubmitAPI` key either, so a schema that always emitted one would
|
|
41
|
+
* make every generated form differ from an authored one over a member the
|
|
42
|
+
* form does not use.
|
|
43
|
+
*/
|
|
44
|
+
canSubmitAPI?: string[];
|
|
45
|
+
submissionMessage: string | null;
|
|
46
|
+
}
|
|
47
|
+
export interface FormDraft {
|
|
48
|
+
formTitle: string;
|
|
49
|
+
/**
|
|
50
|
+
* Columns are typed loosely on purpose. The per-element variants are
|
|
51
|
+
* assembled at runtime from `DefaultInputConfig`, whose property arrays are
|
|
52
|
+
* `string[]` rather than const tuples, so there is no literal type for
|
|
53
|
+
* `s.Infer` to reconstruct. The compiler cannot describe these; the schema
|
|
54
|
+
* and `validateForm()` still constrain them.
|
|
55
|
+
*/
|
|
56
|
+
slides: {
|
|
57
|
+
label: string;
|
|
58
|
+
columns: unknown[];
|
|
59
|
+
}[];
|
|
60
|
+
submissionHandle: SubmissionHandleDraft;
|
|
61
|
+
}
|
|
62
|
+
export interface FormSchemaOptions extends ColumnSchemaOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Endpoints the form may submit to. As with `matOptions`, an empty list means
|
|
65
|
+
* the model is not asked to choose one — it emits an empty `submissionAPI`
|
|
66
|
+
* and the application fills it in.
|
|
67
|
+
*/
|
|
68
|
+
submissionEndpoints?: readonly AvailableApiEndpoint[];
|
|
69
|
+
/**
|
|
70
|
+
* Endpoints that may gate submission — called with the form data, and their
|
|
71
|
+
* answer decides whether the submission proceeds.
|
|
72
|
+
*
|
|
73
|
+
* Unlike {@link submissionEndpoints} this one is genuinely optional at the
|
|
74
|
+
* schema level: `canSubmitAPI` is optional on
|
|
75
|
+
* `FormSubmissionHandleInterface` and most forms have no pre-submit check, so
|
|
76
|
+
* an empty list here removes the key from the schema entirely rather than
|
|
77
|
+
* degrading it to an empty array. That follows `matOptions`, where a source
|
|
78
|
+
* with no candidates is not offered at all — the alternative is asking a
|
|
79
|
+
* model to pick an endpoint out of an empty list, which it answers by
|
|
80
|
+
* inventing one.
|
|
81
|
+
*/
|
|
82
|
+
canSubmitEndpoints?: readonly AvailableApiEndpoint[];
|
|
83
|
+
/**
|
|
84
|
+
* The workflow step this form serves, and the control names the workflow
|
|
85
|
+
* already fixes. See {@link WorkflowStepContext}: none of it is knowable
|
|
86
|
+
* from a prompt, and all of it decides what the form must contain.
|
|
87
|
+
*/
|
|
88
|
+
step?: WorkflowStepContext;
|
|
89
|
+
/** Parse slides and columns incrementally as they stream in. */
|
|
90
|
+
streaming?: boolean;
|
|
91
|
+
}
|
|
92
|
+
declare function submissionHandleSchema(endpoints: readonly AvailableApiEndpoint[], canSubmitEndpoints: readonly AvailableApiEndpoint[]): s.ObjectType<{
|
|
93
|
+
submissionAPI: s.ArrayType<s.StringType | s.EnumType<string[]>>;
|
|
94
|
+
canSubmitAPI: s.ArrayType<s.EnumType<string[]>>;
|
|
95
|
+
submissionMessage: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
96
|
+
}> | s.ObjectType<{
|
|
97
|
+
submissionAPI: s.ArrayType<s.StringType | s.EnumType<string[]>>;
|
|
98
|
+
submissionMessage: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
99
|
+
}>;
|
|
100
|
+
/** The submission-handle node, whichever endpoints the factory was given. */
|
|
101
|
+
type SubmissionHandleSchema = ReturnType<typeof submissionHandleSchema>;
|
|
102
|
+
/**
|
|
103
|
+
* The submission handle produces the draft it declares.
|
|
104
|
+
*
|
|
105
|
+
* The same check the per-member modules run on themselves, applied to the one
|
|
106
|
+
* nested object this file owns. It earns its keep on the `canSubmitAPI` branch
|
|
107
|
+
* in particular: that key exists only when the caller supplies
|
|
108
|
+
* `canSubmitEndpoints`, so the node's inferred type is a UNION of the two
|
|
109
|
+
* shapes, and a member added to either branch without a matching member on
|
|
110
|
+
* {@link SubmissionHandleDraft} fails here rather than at the application's
|
|
111
|
+
* expansion step.
|
|
112
|
+
*/
|
|
113
|
+
export type _NoSubmissionHandleDraftDrift = AssertNever<[
|
|
114
|
+
s.Infer<SubmissionHandleSchema>
|
|
115
|
+
] extends [SubmissionHandleDraft] ? never : 'submissionHandle'>;
|
|
116
|
+
/**
|
|
117
|
+
* Builds the form-draft schema.
|
|
118
|
+
*
|
|
119
|
+
* @param options which elements and data sources to offer, which endpoints the
|
|
120
|
+
* form may submit to and which may gate that submission, and whether to
|
|
121
|
+
* stream.
|
|
122
|
+
*/
|
|
123
|
+
export declare function createFormDraftSchema(options?: FormSchemaOptions): s.ObjectType<{
|
|
124
|
+
formTitle: s.StringType;
|
|
125
|
+
slides: s.ArrayType<s.ObjectType<{
|
|
126
|
+
label: s.StringType;
|
|
127
|
+
columns: s.ArrayType<s.HashbrownType<unknown>>;
|
|
128
|
+
}>>;
|
|
129
|
+
submissionHandle: s.ObjectType<{
|
|
130
|
+
submissionAPI: s.ArrayType<s.StringType | s.EnumType<string[]>>;
|
|
131
|
+
canSubmitAPI: s.ArrayType<s.EnumType<string[]>>;
|
|
132
|
+
submissionMessage: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
133
|
+
}> | s.ObjectType<{
|
|
134
|
+
submissionAPI: s.ArrayType<s.StringType | s.EnumType<string[]>>;
|
|
135
|
+
submissionMessage: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
136
|
+
}>;
|
|
137
|
+
}>;
|
|
138
|
+
/**
|
|
139
|
+
* Members of a generated draft the application must supply before the form is
|
|
140
|
+
* valid. Listed so the expansion step has something to check itself against.
|
|
141
|
+
*
|
|
142
|
+
* The per-member lists are pulled in rather than restated, so a module that
|
|
143
|
+
* takes on a new obligation adds it here by existing. Each entry is prefixed
|
|
144
|
+
* with the column path it hangs off, since the modules describe their own
|
|
145
|
+
* shape and do not know where in a form they sit.
|
|
146
|
+
*
|
|
147
|
+
* A module's own entries must therefore start at the MEMBER it owns —
|
|
148
|
+
* `validators[].id`, not `id` — because everything before that is added here
|
|
149
|
+
* and everything after is the module's to state. A list that skips its member
|
|
150
|
+
* name yields a path with a hole in it, which is worse than no list: it reads
|
|
151
|
+
* as authoritative and points nowhere.
|
|
152
|
+
*
|
|
153
|
+
* Three entries are not from any module and are worth reading twice:
|
|
154
|
+
*
|
|
155
|
+
* - `isCalculatedField` is derived, not authored — see `calculatedFieldSplit`
|
|
156
|
+
* in `variants.ts`. It is required by the interface on EVERY column, so
|
|
157
|
+
* expansion must set it on plain columns too, not only calculated ones.
|
|
158
|
+
* - `onlySetTempErrorOnTouch` is required by the interface but optional in the
|
|
159
|
+
* schema (offered on every value-capturing element through the always-shown
|
|
160
|
+
* editor rows), so a model may leave it null. Expansion then sets it, and the
|
|
161
|
+
* guide's house rule says what to: true, so errors appear only after the
|
|
162
|
+
* user leaves a field. The builder's own element templates default it to
|
|
163
|
+
* false; the guide is explicit that this is the wrong default for nearly
|
|
164
|
+
* every field.
|
|
165
|
+
* - the nulls. Skillet has no optional, so every unset member arrives as an
|
|
166
|
+
* explicit `null`, and Joi rejects `null` for a typed optional key. Stripping
|
|
167
|
+
* them is not tidying; a draft that keeps them fails validation.
|
|
168
|
+
*/
|
|
169
|
+
export declare const DRAFT_COMPLETION_REQUIRED: readonly ["slides[].sectionId", "slides[].columns[].id", "slides[].columns[].sectionId", "slides[].columns[].isCalculatedField (derived: calculatedFieldRules != null)", "slides[].columns[].onlySetTempErrorOnTouch (required by the interface and offered as optional; when the model leaves it null the application sets true)", "submissionHandle.submissionAPI[] (endpoint id expanded to its configuration)", "submissionHandle.canSubmitAPI[] (endpoint id expanded to its configuration; the key is present only when canSubmitEndpoints were offered, and an empty array is dropped)", ...string[], "every member emitted as null is stripped before validation"];
|
|
170
|
+
export {};
|