@ebitex/forms-sdk 0.1.2 → 0.2.6
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/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/nodes.d.ts +25 -0
- package/dist/nodes.d.ts.map +1 -0
- package/dist/nodes.js +53 -0
- package/dist/nodes.js.map +1 -0
- package/dist/predicates.d.ts +23 -0
- package/dist/predicates.d.ts.map +1 -0
- package/dist/predicates.js +60 -0
- package/dist/predicates.js.map +1 -0
- package/dist/react/EbitexForm.d.ts +1 -1
- package/dist/react/EbitexForm.d.ts.map +1 -1
- package/dist/react/EbitexForm.js +38 -6
- package/dist/react/EbitexForm.js.map +1 -1
- package/dist/types.d.ts +39 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -20
- package/dist/types.js.map +1 -1
- package/dist/validators.d.ts +10 -1
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +14 -3
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,5 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { createFormsClient, FormsApiError, type FormsClient, type FormsClientOptions, } from './client.js';
|
|
11
11
|
export { validateSubmission, type ValidateOptions } from './validators.js';
|
|
12
|
-
export {
|
|
12
|
+
export { isFieldComparisonSatisfied } from './predicates.js';
|
|
13
|
+
export { collectDataFields, isDataField, isFormField, resolveVariant } from './nodes.js';
|
|
14
|
+
export { type ButtonField, type ButtonType, type ChoiceField, type ChoiceOption, type ChoiceType, type FieldComparisonOperator, type FieldComparisonPredicate, type FieldsetNode, type FormField, type FormNode, type FormStep, type InputField, type InputVariant, type NumberField, type RowNode, type SdkForm, type SubmissionData, type TextareaField, type ValidationErrors, type VariantBranch, type VariantNode, } from './types.js';
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAExF,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -9,5 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { createFormsClient, FormsApiError, } from './client.js';
|
|
11
11
|
export { validateSubmission } from './validators.js';
|
|
12
|
-
export {
|
|
12
|
+
export { isFieldComparisonSatisfied } from './predicates.js';
|
|
13
|
+
export { collectDataFields, isDataField, isFormField, resolveVariant } from './nodes.js';
|
|
14
|
+
export {} from './types.js';
|
|
13
15
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,GAGd,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,kBAAkB,EAAwB,MAAM,iBAAiB,CAAA;AAE1E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,GAGd,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,kBAAkB,EAAwB,MAAM,iBAAiB,CAAA;AAE1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAExF,OAAO,EAsBN,MAAM,YAAY,CAAA"}
|
package/dist/nodes.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChoiceField, FormField, FormNode, InputField, NumberField, SubmissionData, TextareaField, VariantNode } from './types.js';
|
|
2
|
+
export declare function isFormField(node: FormNode): node is FormField;
|
|
3
|
+
/** Buttons are the one field shape carrying no answer, so they're excluded from data and validation. */
|
|
4
|
+
export declare function isDataField(node: FormNode): node is InputField | TextareaField | NumberField | ChoiceField;
|
|
5
|
+
/**
|
|
6
|
+
* Which of a `VariantNode`'s branches (or its `fallback`) the respondent currently sees, given their
|
|
7
|
+
* answers so far — first-match-wins, mirroring `Forms.Api`'s own `VariantResolver` selection order
|
|
8
|
+
* exactly (a residual Variant's retained branches are already in the server's own precedence order by
|
|
9
|
+
* construction). Returns `null` when nothing matches and there is no fallback — a Variant may
|
|
10
|
+
* legitimately render nothing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveVariant(variant: VariantNode, data: SubmissionData): FormNode | null;
|
|
13
|
+
/**
|
|
14
|
+
* Depth-first walk of a node tree, flattened to the data-carrying fields that are **currently
|
|
15
|
+
* visible** given `data` — a `Fieldset`/`Row` is walked through unconditionally, but a `Variant`
|
|
16
|
+
* contributes only its currently-selected branch's fields (spec 111-conditional-fields), so a field
|
|
17
|
+
* inside a branch that isn't shown never gets treated as present or required.
|
|
18
|
+
*
|
|
19
|
+
* `data` is required, not optional, deliberately: a caller that doesn't have the respondent's current
|
|
20
|
+
* answers yet has no correct default to fall back to (an empty object would make every `Variant`
|
|
21
|
+
* resolve as if nothing had been answered, which is only sometimes what a caller wants) — see
|
|
22
|
+
* `EbitexForm`'s and `PublicFormRender`'s own call sites for the two real ones this package has.
|
|
23
|
+
*/
|
|
24
|
+
export declare function collectDataFields(nodes: FormNode[], data: SubmissionData): (InputField | TextareaField | NumberField | ChoiceField)[];
|
|
25
|
+
//# sourceMappingURL=nodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACZ,MAAM,YAAY,CAAA;AAEnB,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,IAAI,SAAS,CAE7D;AAED,wGAAwG;AACxG,wBAAgB,WAAW,CACzB,IAAI,EAAE,QAAQ,GACb,IAAI,IAAI,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,GAAG,QAAQ,GAAG,IAAI,CAQ1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,EAAE,EACjB,IAAI,EAAE,cAAc,GACnB,CAAC,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC,EAAE,CAiB5D"}
|
package/dist/nodes.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isFieldComparisonSatisfied } from './predicates.js';
|
|
2
|
+
export function isFormField(node) {
|
|
3
|
+
return node.nodeType === 'Field';
|
|
4
|
+
}
|
|
5
|
+
/** Buttons are the one field shape carrying no answer, so they're excluded from data and validation. */
|
|
6
|
+
export function isDataField(node) {
|
|
7
|
+
return isFormField(node) && node.fieldType !== 'Button';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Which of a `VariantNode`'s branches (or its `fallback`) the respondent currently sees, given their
|
|
11
|
+
* answers so far — first-match-wins, mirroring `Forms.Api`'s own `VariantResolver` selection order
|
|
12
|
+
* exactly (a residual Variant's retained branches are already in the server's own precedence order by
|
|
13
|
+
* construction). Returns `null` when nothing matches and there is no fallback — a Variant may
|
|
14
|
+
* legitimately render nothing.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveVariant(variant, data) {
|
|
17
|
+
for (const branch of variant.branches) {
|
|
18
|
+
if (isFieldComparisonSatisfied(branch.when, data)) {
|
|
19
|
+
return branch.node;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return variant.fallback;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Depth-first walk of a node tree, flattened to the data-carrying fields that are **currently
|
|
26
|
+
* visible** given `data` — a `Fieldset`/`Row` is walked through unconditionally, but a `Variant`
|
|
27
|
+
* contributes only its currently-selected branch's fields (spec 111-conditional-fields), so a field
|
|
28
|
+
* inside a branch that isn't shown never gets treated as present or required.
|
|
29
|
+
*
|
|
30
|
+
* `data` is required, not optional, deliberately: a caller that doesn't have the respondent's current
|
|
31
|
+
* answers yet has no correct default to fall back to (an empty object would make every `Variant`
|
|
32
|
+
* resolve as if nothing had been answered, which is only sometimes what a caller wants) — see
|
|
33
|
+
* `EbitexForm`'s and `PublicFormRender`'s own call sites for the two real ones this package has.
|
|
34
|
+
*/
|
|
35
|
+
export function collectDataFields(nodes, data) {
|
|
36
|
+
const result = [];
|
|
37
|
+
for (const node of nodes) {
|
|
38
|
+
if (node.nodeType === 'Fieldset' || node.nodeType === 'Row') {
|
|
39
|
+
result.push(...collectDataFields(node.nodes, data));
|
|
40
|
+
}
|
|
41
|
+
else if (node.nodeType === 'Variant') {
|
|
42
|
+
const chosen = resolveVariant(node, data);
|
|
43
|
+
if (chosen !== null) {
|
|
44
|
+
result.push(...collectDataFields([chosen], data));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (isDataField(node)) {
|
|
48
|
+
result.push(node);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAY5D,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,OAAO,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAA;AAClC,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,WAAW,CACzB,IAAc;IAEd,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAA;AACzD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB,EAAE,IAAoB;IACvE,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,0BAA0B,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC,IAAI,CAAA;QACpB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,QAAQ,CAAA;AACzB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAiB,EACjB,IAAoB;IAEpB,MAAM,MAAM,GAA+D,EAAE,CAAA;IAE7E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;QACrD,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACzC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;YACnD,CAAC;QACH,CAAC;aAAM,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FieldComparisonPredicate, SubmissionData } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Client-side port of `Forms.Api`'s `VariantResolver.IsFieldComparisonSatisfied` — the single
|
|
4
|
+
* predicate evaluator this SDK's `EbitexForm` renderer and `apps/forms-web`'s `PublicFormRender`
|
|
5
|
+
* both import from here, so show/hide decisions can never drift between the two. Deliberately lives
|
|
6
|
+
* in this package rather than being duplicated in `apps/forms-web` — see
|
|
7
|
+
* `specs/features/111-conditional-fields/SPEC.md`'s Decision Log for why: there must be exactly one
|
|
8
|
+
* TypeScript implementation, and this package is the one that needs it regardless (an external
|
|
9
|
+
* consumer rendering nodes directly has the same problem), while `forms-sdk` staying dependency-free
|
|
10
|
+
* (spec #89) means depending on it adds nothing transitive to `forms-web`.
|
|
11
|
+
*
|
|
12
|
+
* Comparison is string-based against the submitted value's string form, matching the server exactly:
|
|
13
|
+
* no numeric-coercion table for either implementation to disagree on. A submitted array (a Checkbox
|
|
14
|
+
* answer) satisfies `Equals` when **any** element matches, and counts as empty only when it has zero
|
|
15
|
+
* elements. A missing/`null` answer behaves as "no answer" for every operator — the same rule that
|
|
16
|
+
* lets a hidden field's controlling condition collapse coherently through further conditions, since a
|
|
17
|
+
* respondent's browser never submits an answer for content it never showed.
|
|
18
|
+
*
|
|
19
|
+
* Verified against the **same** fixture file (`src/test/fixtures/field-comparison-cases.json`) the
|
|
20
|
+
* server's own `FieldComparisonPredicateParityTests` runs — see that file's own remarks.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isFieldComparisonSatisfied(predicate: FieldComparisonPredicate, data: SubmissionData): boolean;
|
|
23
|
+
//# sourceMappingURL=predicates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicates.d.ts","sourceRoot":"","sources":["../src/predicates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,wBAAwB,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CA0B7G"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side port of `Forms.Api`'s `VariantResolver.IsFieldComparisonSatisfied` — the single
|
|
3
|
+
* predicate evaluator this SDK's `EbitexForm` renderer and `apps/forms-web`'s `PublicFormRender`
|
|
4
|
+
* both import from here, so show/hide decisions can never drift between the two. Deliberately lives
|
|
5
|
+
* in this package rather than being duplicated in `apps/forms-web` — see
|
|
6
|
+
* `specs/features/111-conditional-fields/SPEC.md`'s Decision Log for why: there must be exactly one
|
|
7
|
+
* TypeScript implementation, and this package is the one that needs it regardless (an external
|
|
8
|
+
* consumer rendering nodes directly has the same problem), while `forms-sdk` staying dependency-free
|
|
9
|
+
* (spec #89) means depending on it adds nothing transitive to `forms-web`.
|
|
10
|
+
*
|
|
11
|
+
* Comparison is string-based against the submitted value's string form, matching the server exactly:
|
|
12
|
+
* no numeric-coercion table for either implementation to disagree on. A submitted array (a Checkbox
|
|
13
|
+
* answer) satisfies `Equals` when **any** element matches, and counts as empty only when it has zero
|
|
14
|
+
* elements. A missing/`null` answer behaves as "no answer" for every operator — the same rule that
|
|
15
|
+
* lets a hidden field's controlling condition collapse coherently through further conditions, since a
|
|
16
|
+
* respondent's browser never submits an answer for content it never showed.
|
|
17
|
+
*
|
|
18
|
+
* Verified against the **same** fixture file (`src/test/fixtures/field-comparison-cases.json`) the
|
|
19
|
+
* server's own `FieldComparisonPredicateParityTests` runs — see that file's own remarks.
|
|
20
|
+
*/
|
|
21
|
+
export function isFieldComparisonSatisfied(predicate, data) {
|
|
22
|
+
const value = data[predicate.field];
|
|
23
|
+
if (value === undefined || value === null) {
|
|
24
|
+
switch (predicate.operator) {
|
|
25
|
+
case 'IsEmpty':
|
|
26
|
+
return true;
|
|
27
|
+
case 'IsNotEmpty':
|
|
28
|
+
return false;
|
|
29
|
+
case 'Equals':
|
|
30
|
+
return false;
|
|
31
|
+
case 'NotEquals':
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
switch (predicate.operator) {
|
|
36
|
+
case 'IsEmpty':
|
|
37
|
+
return isEmptyValue(value);
|
|
38
|
+
case 'IsNotEmpty':
|
|
39
|
+
return !isEmptyValue(value);
|
|
40
|
+
case 'Equals':
|
|
41
|
+
return matchesValue(value, predicate.value);
|
|
42
|
+
case 'NotEquals':
|
|
43
|
+
return !matchesValue(value, predicate.value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function isEmptyValue(value) {
|
|
47
|
+
if (typeof value === 'string')
|
|
48
|
+
return value.trim() === '';
|
|
49
|
+
if (Array.isArray(value))
|
|
50
|
+
return value.length === 0;
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function matchesValue(value, comparand) {
|
|
54
|
+
if (Array.isArray(value))
|
|
55
|
+
return value.some((item) => item === comparand);
|
|
56
|
+
if (typeof value === 'string')
|
|
57
|
+
return value === comparand;
|
|
58
|
+
return String(value) === comparand;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=predicates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicates.js","sourceRoot":"","sources":["../src/predicates.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,0BAA0B,CAAC,SAAmC,EAAE,IAAoB;IAClG,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAEnC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,QAAQ,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3B,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAA;YACb,KAAK,YAAY;gBACf,OAAO,KAAK,CAAA;YACd,KAAK,QAAQ;gBACX,OAAO,KAAK,CAAA;YACd,KAAK,WAAW;gBACd,OAAO,IAAI,CAAA;QACf,CAAC;IACH,CAAC;IAED,QAAQ,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC3B,KAAK,SAAS;YACZ,OAAO,YAAY,CAAC,KAAK,CAAC,CAAA;QAC5B,KAAK,YAAY;YACf,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAC7B,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,KAAM,CAAC,CAAA;QAC9C,KAAK,WAAW;YACd,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,KAAM,CAAC,CAAA;IACjD,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAiC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAA;IACnD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAiC,EAAE,SAAiB;IACxE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,KAAK,SAAS,CAAA;IACzD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,CAAA;AACpC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CSSProperties } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { SdkForm, SubmissionData } from '../types.js';
|
|
3
3
|
import { type FieldComponents } from './fields.js';
|
|
4
4
|
export interface EbitexFormProps {
|
|
5
5
|
/** A form definition from `createFormsClient(...).getForm(...)`, fetched on your server. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EbitexForm.d.ts","sourceRoot":"","sources":["../../src/react/EbitexForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"EbitexForm.d.ts","sourceRoot":"","sources":["../../src/react/EbitexForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAEpE,OAAO,KAAK,EAAY,OAAO,EAAE,cAAc,EAAoB,MAAM,aAAa,CAAA;AAEtF,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAA;AAGpB,MAAM,WAAW,eAAe;IAC9B,4FAA4F;IAC5F,IAAI,EAAE,OAAO,CAAA;IAEb,kDAAkD;IAClD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAE5C,wGAAwG;IACxG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAElC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IAEjC,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,WAAW,EACX,OAAO,EACP,SAAS,EACT,KAAK,EACL,eAAe,EACf,KAAK,EAAE,aAAa,GACrB,EAAE,eAAe,sCA+MjB"}
|
package/dist/react/EbitexForm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useId, useMemo, useState } from 'react';
|
|
3
|
-
import { collectDataFields, } from '../
|
|
3
|
+
import { collectDataFields, resolveVariant } from '../nodes.js';
|
|
4
4
|
import { validateSubmission } from '../validators.js';
|
|
5
5
|
import { ChoiceFieldControl, InputFieldControl, NumberFieldControl, TextareaFieldControl, } from './fields.js';
|
|
6
6
|
import { getOrCreateVisitorId } from './visitorId.js';
|
|
@@ -40,19 +40,42 @@ export function EbitexForm({ form, onSubmitted, onError, className, style, field
|
|
|
40
40
|
* report errors for fields the respondent hasn't reached yet.
|
|
41
41
|
*/
|
|
42
42
|
function validateCurrentStep(requireAll) {
|
|
43
|
-
const stepKeys = new Set(collectDataFields(step.nodes)
|
|
43
|
+
const stepKeys = new Set(collectDataFields(step.nodes, data)
|
|
44
44
|
.map((field) => field.submissionKey)
|
|
45
45
|
.filter((key) => key !== undefined));
|
|
46
|
-
const all = validateSubmission(form,
|
|
46
|
+
const all = validateSubmission(form, visiblePayload(), { requireAll });
|
|
47
47
|
return Object.fromEntries(Object.entries(all).filter(([key]) => stepKeys.has(key)));
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* `data` as it should actually be sent — and validated — right now: every key belonging to a field
|
|
51
|
+
* that isn't currently *visible* (inside a `Variant` branch/fallback that isn't the one selected
|
|
52
|
+
* right now) is excluded, matching the server's own evaluation of what should have been shown
|
|
53
|
+
* (spec 111-conditional-fields). Answers aren't cleared from `data` itself when a field becomes
|
|
54
|
+
* hidden — only pruned here, at the moment of sending or validating — so toggling a controlling
|
|
55
|
+
* answer back and forth doesn't lose what the respondent already typed into a field that's
|
|
56
|
+
* temporarily out of view.
|
|
57
|
+
*
|
|
58
|
+
* **Validation must use this same pruned view, not raw `data`.** An earlier version of this
|
|
59
|
+
* component validated against raw `data` while sending the pruned view — a stale answer left behind
|
|
60
|
+
* in `data` after its field became hidden was then flagged as `"Unknown field."` by
|
|
61
|
+
* `validateSubmission` (which is itself correctly answers-aware) and blocked submission entirely,
|
|
62
|
+
* even though the value being blocked on would never actually have been sent. Found by a test that
|
|
63
|
+
* hid a field after answering it, then tried to submit — not by inspection.
|
|
64
|
+
*/
|
|
65
|
+
function visiblePayload() {
|
|
66
|
+
const allNodes = steps.flatMap((s) => s.nodes);
|
|
67
|
+
const visibleKeys = new Set(collectDataFields(allNodes, data)
|
|
68
|
+
.map((field) => field.submissionKey)
|
|
69
|
+
.filter((key) => key !== undefined));
|
|
70
|
+
return Object.fromEntries(Object.entries(data).filter(([key]) => visibleKeys.has(key)));
|
|
71
|
+
}
|
|
49
72
|
async function save(complete) {
|
|
50
73
|
setSubmitting(true);
|
|
51
74
|
try {
|
|
52
75
|
const response = await doFetch(form.submissionUrl, {
|
|
53
76
|
method: 'POST',
|
|
54
77
|
headers: { 'Content-Type': 'application/json' },
|
|
55
|
-
body: JSON.stringify({ visitor: visitorId, data, complete }),
|
|
78
|
+
body: JSON.stringify({ visitor: visitorId, data: visiblePayload(), complete }),
|
|
56
79
|
});
|
|
57
80
|
if (!response.ok) {
|
|
58
81
|
// The server is authoritative: a field-level rejection is surfaced inline rather than
|
|
@@ -88,7 +111,7 @@ export function EbitexForm({ form, onSubmitted, onError, className, style, field
|
|
|
88
111
|
}
|
|
89
112
|
}
|
|
90
113
|
async function submit() {
|
|
91
|
-
const allErrors = validateSubmission(form,
|
|
114
|
+
const allErrors = validateSubmission(form, visiblePayload(), { requireAll: true });
|
|
92
115
|
if (Object.keys(allErrors).length > 0) {
|
|
93
116
|
setErrors(allErrors);
|
|
94
117
|
return;
|
|
@@ -96,7 +119,7 @@ export function EbitexForm({ form, onSubmitted, onError, className, style, field
|
|
|
96
119
|
setErrors({});
|
|
97
120
|
if (await save(true)) {
|
|
98
121
|
setCompleted(true);
|
|
99
|
-
onSubmitted?.(
|
|
122
|
+
onSubmitted?.(visiblePayload());
|
|
100
123
|
}
|
|
101
124
|
}
|
|
102
125
|
function setValue(key, value) {
|
|
@@ -132,6 +155,15 @@ function NodeList({ nodes, baseId, data, errors, disabled, fieldComponents, onCh
|
|
|
132
155
|
// Horizontal on wide viewports, single column on narrow — see styles.css.
|
|
133
156
|
return (_jsx("div", { className: "ebitex-forms__row", children: _jsx(NodeList, { nodes: node.nodes, baseId: baseId, data: data, errors: errors, disabled: disabled, fieldComponents: fieldComponents, onChange: onChange }) }, `row-${index}`));
|
|
134
157
|
}
|
|
158
|
+
if (node.nodeType === 'Variant') {
|
|
159
|
+
// Re-evaluated on every render as `data` changes, so the visible branch updates live as
|
|
160
|
+
// the respondent answers the controlling field (spec 111-conditional-fields).
|
|
161
|
+
const chosen = resolveVariant(node, data);
|
|
162
|
+
if (chosen === null) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return (_jsx(NodeList, { nodes: [chosen], baseId: baseId, data: data, errors: errors, disabled: disabled, fieldComponents: fieldComponents, onChange: onChange }, `variant-${index}`));
|
|
166
|
+
}
|
|
135
167
|
if (node.fieldType === 'Button') {
|
|
136
168
|
// Buttons inside a step's tree are the Form's own Actions, rendered by ActionButtons.
|
|
137
169
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EbitexForm.js","sourceRoot":"","sources":["../../src/react/EbitexForm.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAsB,MAAM,OAAO,CAAA;AACpE,OAAO,
|
|
1
|
+
{"version":3,"file":"EbitexForm.js","sourceRoot":"","sources":["../../src/react/EbitexForm.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAsB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AA0BrD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,IAAI,EACJ,WAAW,EACX,OAAO,EACP,SAAS,EACT,KAAK,EACL,eAAe,EACf,KAAK,EAAE,aAAa,GACJ;IAChB,MAAM,MAAM,GAAG,KAAK,EAAE,CAAA;IACtB,MAAM,OAAO,GAAG,aAAa,IAAI,UAAU,CAAC,KAAK,CAAA;IAEjD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC7C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAiB,EAAE,CAAC,CAAA;IACpD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAmB,EAAE,CAAC,CAAA;IAC1D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IACxB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAA;IAC7B,MAAM,UAAU,GAAG,SAAS,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAEjD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAA;IAE3D,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,cAAK,SAAS,EAAE,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,YACrE,YAAG,SAAS,EAAC,wBAAwB,EAAC,IAAI,EAAC,QAAQ,gEAE/C,GACA,CACP,CAAA;IACH,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;OAGG;IACH,SAAS,mBAAmB,CAAC,UAAmB;QAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,iBAAiB,CAAC,IAAK,CAAC,KAAK,EAAE,IAAI,CAAC;aACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC;aACnC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CACrD,CAAA;QAED,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;QACtE,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,SAAS,cAAc;QACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC;aAC9B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC;aACnC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CACrD,CAAA;QAED,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACzF,CAAC;IAED,KAAK,UAAU,IAAI,CAAC,QAAiB;QACnC,aAAa,CAAC,IAAI,CAAC,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE;gBACjD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,CAAC;aAC/E,CAAC,CAAA;YAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,sFAAsF;gBACtF,iFAAiF;gBACjF,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAE7C,CAAA;gBAER,IAAI,IAAI,EAAE,KAAK,KAAK,mBAAmB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBACvD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;oBACtB,OAAO,KAAK,CAAA;gBACd,CAAC;gBAED,OAAO,EAAE,CAAC,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACxE,OAAO,KAAK,CAAA;YACd,CAAC;YAED,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;YAChB,OAAO,KAAK,CAAA;QACd,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,KAAK,UAAU,OAAO;QACpB,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,SAAS,CAAC,UAAU,CAAC,CAAA;YACrB,OAAM;QACR,CAAC;QAED,SAAS,CAAC,EAAE,CAAC,CAAA;QACb,sEAAsE;QACtE,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,YAAY,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;QAClF,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,SAAS,CAAC,SAAS,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;QAED,SAAS,CAAC,EAAE,CAAC,CAAA;QACb,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,CAAA;YAClB,WAAW,EAAE,CAAC,cAAc,EAAE,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAED,SAAS,QAAQ,CAAC,GAAW,EAAE,KAA6B;QAC1D,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW,CAAA;IAEhD,OAAO,CACL,eAAK,SAAS,EAAE,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,aAOpE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CACnB,aAAG,SAAS,EAAC,sBAAsB,EAAC,IAAI,EAAC,QAAQ,8BACjC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,6EAErC,CACL,CAAC,CAAC,CAAC,IAAI,EAER,gBACE,UAAU,QACV,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;oBAClB,KAAK,CAAC,cAAc,EAAE,CAAA;oBACtB,IAAI,UAAU,EAAE,CAAC;wBACf,KAAK,MAAM,EAAE,CAAA;oBACf,CAAC;yBAAM,CAAC;wBACN,KAAK,OAAO,EAAE,CAAA;oBAChB,CAAC;gBACH,CAAC,aAEA,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAClB,aAAG,SAAS,EAAC,8BAA8B,EAAC,IAAI,EAAC,QAAQ,sBACjD,SAAS,GAAG,CAAC,UAAM,KAAK,CAAC,MAAM,EACpC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAClC,CACL,CAAC,CAAC,CAAC,IAAI,EAER,KAAC,QAAQ,IACP,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,GAClB,EAEF,eAAK,SAAS,EAAC,uBAAuB,aACnC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CACf,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,sDAAsD,EAChE,QAAQ,EAAE,UAAU;gCACpB,yEAAyE;gCACzE,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,qBAG9C,CACV,CAAC,CAAC,CAAC,IAAI,EAEP,UAAU,CAAC,CAAC,CAAC,CACZ,KAAC,aAAa,IAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAC3D,CAAC,CAAC,CAAC,CACF,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,sBAAsB,EAAC,QAAQ,EAAE,QAAQ,qBAEhE,CACV,IACG,IACD,IACH,CACP,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,SAAS,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAA4C;IAClF,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAC1B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,CACA,CAAA;IAEpE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CACL,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,sBAAsB,EAAC,QAAQ,EAAE,QAAQ,uBAEhE,CACV,CAAA;IACH,CAAC;IAED,OAAO,CACL,4BACG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAC9B,iBAEE,IAAI,EAAE,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EACpG,SAAS,EAAE,cAAc,CACvB,sBAAsB,EACtB,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,SAAS,CAC/E,EACD,QAAQ,EAAE,QAAQ,YAEjB,MAAM,CAAC,KAAK,IARR,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,EAAE,CASxB,CACV,CAAC,GACD,CACJ,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,MAAM,EACN,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,eAAe,EACf,QAAQ,GAST;IACC,OAAO,CACL,4BACG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACjC,OAAO,CACL,oBAAU,SAAS,EAAC,wBAAwB,aAC1C,2BAAS,IAAI,CAAC,MAAM,GAAU,EAC9B,KAAC,QAAQ,IACP,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,GAClB,KAV8C,YAAY,KAAK,EAAE,CAW1D,CACZ,CAAA;YACH,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;gBAC5B,0EAA0E;gBAC1E,OAAO,CACL,cAAK,SAAS,EAAC,mBAAmB,YAChC,KAAC,QAAQ,IACP,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,GAClB,IAToC,OAAO,KAAK,EAAE,CAUhD,CACP,CAAA;YACH,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAChC,wFAAwF;gBACxF,8EAA8E;gBAC9E,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBACzC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;oBACpB,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,OAAO,CACL,KAAC,QAAQ,IAEP,KAAK,EAAE,CAAC,MAAM,CAAC,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,IAPb,WAAW,KAAK,EAAE,CAQvB,CACH,CAAA;YACH,CAAC;YAED,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAChC,sFAAsF;gBACtF,OAAO,IAAI,CAAA;YACb,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAA;YAC9B,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA;YAElC,MAAM,EAAE,GAAG,GAAG,MAAM,IAAI,GAAG,EAAE,CAAA;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;YACjC,MAAM,MAAM,GAAG;gBACb,EAAE;gBACF,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI;gBACxB,KAAK;gBACL,QAAQ;gBACR,QAAQ,EAAE,CAAC,KAA6B,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;aAClE,CAAA;YAED,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;gBACvB,KAAK,OAAO,CAAC,CAAC,CAAC;oBACb,MAAM,SAAS,GAAG,eAAe,EAAE,KAAK,IAAI,iBAAiB,CAAA;oBAC7D,OAAO,KAAC,SAAS,IAAW,KAAK,EAAE,IAAI,KAAM,MAAM,IAA5B,GAAG,CAA6B,CAAA;gBACzD,CAAC;gBACD,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,MAAM,SAAS,GAAG,eAAe,EAAE,QAAQ,IAAI,oBAAoB,CAAA;oBACnE,OAAO,KAAC,SAAS,IAAW,KAAK,EAAE,IAAI,KAAM,MAAM,IAA5B,GAAG,CAA6B,CAAA;gBACzD,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,SAAS,GAAG,eAAe,EAAE,MAAM,IAAI,kBAAkB,CAAA;oBAC/D,OAAO,KAAC,SAAS,IAAW,KAAK,EAAE,IAAI,KAAM,MAAM,IAA5B,GAAG,CAA6B,CAAA;gBACzD,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,SAAS,GAAG,eAAe,EAAE,MAAM,IAAI,kBAAkB,CAAA;oBAC/D,OAAO,KAAC,SAAS,IAAW,KAAK,EAAE,IAAI,KAAM,MAAM,IAA5B,GAAG,CAA6B,CAAA;gBACzD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,GACD,CACJ,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,GAAG,MAA8B;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACzC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -60,6 +60,24 @@ export interface ButtonField extends FieldBase {
|
|
|
60
60
|
buttonType: ButtonType;
|
|
61
61
|
}
|
|
62
62
|
export type FormField = InputField | TextareaField | NumberField | ChoiceField | ButtonField;
|
|
63
|
+
export type FieldComparisonOperator = 'Equals' | 'NotEquals' | 'IsEmpty' | 'IsNotEmpty';
|
|
64
|
+
/**
|
|
65
|
+
* A `Variant` branch's condition (spec 111-conditional-fields), comparing another field's submitted
|
|
66
|
+
* answer. This is the **only** predicate kind an SDK consumer will ever see: a locale predicate is
|
|
67
|
+
* always decidable server-side (spec #109), so it's resolved away before serialization and never
|
|
68
|
+
* reaches the wire — a `Variant` node only survives serialization at all when it's governed by at
|
|
69
|
+
* least one `FieldComparisonPredicate`.
|
|
70
|
+
*
|
|
71
|
+
* `field` names a submission key that appears earlier, in document order, than the `Variant` itself —
|
|
72
|
+
* enforced server-side at save time, so a well-formed response never asks you to evaluate a forward
|
|
73
|
+
* reference. `value` is present for `Equals`/`NotEquals`, absent for `IsEmpty`/`IsNotEmpty`.
|
|
74
|
+
*/
|
|
75
|
+
export interface FieldComparisonPredicate {
|
|
76
|
+
kind: 'FieldComparison';
|
|
77
|
+
field: string;
|
|
78
|
+
operator: FieldComparisonOperator;
|
|
79
|
+
value?: string;
|
|
80
|
+
}
|
|
63
81
|
export interface FieldsetNode {
|
|
64
82
|
nodeType: 'Fieldset';
|
|
65
83
|
legend: string;
|
|
@@ -69,7 +87,27 @@ export interface RowNode {
|
|
|
69
87
|
nodeType: 'Row';
|
|
70
88
|
nodes: FormNode[];
|
|
71
89
|
}
|
|
72
|
-
|
|
90
|
+
/**
|
|
91
|
+
* One branch of a `Variant` (spec 111-conditional-fields): `node` is shown when `when` is satisfied
|
|
92
|
+
* against the respondent's current answers — see `resolveVariant` in `./nodes.js`.
|
|
93
|
+
*/
|
|
94
|
+
export interface VariantBranch {
|
|
95
|
+
when: FieldComparisonPredicate;
|
|
96
|
+
node: FormNode;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* A structural switch: at most one of `branches` (first match wins, in order) or `fallback` is what a
|
|
100
|
+
* respondent actually sees, decided live in the browser as they answer — see `resolveVariant` in
|
|
101
|
+
* `./nodes.js`, which both this SDK's `EbitexForm` and `apps/forms-web`'s `PublicFormRender` use so
|
|
102
|
+
* the decision can't drift between them. `fallback` is `null`, not absent, when there genuinely is
|
|
103
|
+
* none — a Variant may legitimately render nothing.
|
|
104
|
+
*/
|
|
105
|
+
export interface VariantNode {
|
|
106
|
+
nodeType: 'Variant';
|
|
107
|
+
branches: VariantBranch[];
|
|
108
|
+
fallback: FormNode | null;
|
|
109
|
+
}
|
|
110
|
+
export type FormNode = FieldsetNode | RowNode | FormField | VariantNode;
|
|
73
111
|
export interface FormStep {
|
|
74
112
|
label: string;
|
|
75
113
|
nodes: FormNode[];
|
|
@@ -94,10 +132,5 @@ export interface SdkForm {
|
|
|
94
132
|
export type SubmissionData = Record<string, string | string[] | number | null>;
|
|
95
133
|
/** Field-level validation messages, keyed by `submissionKey`. Empty means valid. */
|
|
96
134
|
export type ValidationErrors = Record<string, string>;
|
|
97
|
-
export declare function isFormField(node: FormNode): node is FormField;
|
|
98
|
-
/** Buttons are the one field shape carrying no answer, so they're excluded from data and validation. */
|
|
99
|
-
export declare function isDataField(node: FormNode): node is InputField | TextareaField | NumberField | ChoiceField;
|
|
100
|
-
/** Depth-first walk of a node tree, flattened to the data-carrying fields only. */
|
|
101
|
-
export declare function collectDataFields(nodes: FormNode[]): (InputField | TextareaField | NumberField | ChoiceField)[];
|
|
102
135
|
export {};
|
|
103
136
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,CAAA;AAExE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,SAAS;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,YAAY,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,SAAS,EAAE,UAAU,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,qGAAqG;IACrG,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAA;AAE5F,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,UAAU,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,KAAK,CAAA;IACf,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,CAAA;AAExE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEtD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,SAAS;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,YAAY,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,SAAS,EAAE,UAAU,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,qGAAqG;IACrG,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAA;AAE5F,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAA;AAEvF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,iBAAiB,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,uBAAuB,CAAA;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,UAAU,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,KAAK,CAAA;IACf,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,wBAAwB,CAAA;IAC9B,IAAI,EAAE,QAAQ,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,SAAS,CAAA;IACnB,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAA;AAEvE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAA;IACvC;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAA;IACpB,OAAO,EAAE,QAAQ,EAAE,CAAA;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,qEAAqE;AACrE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,CAAA;AAE9E,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA"}
|
package/dist/types.js
CHANGED
|
@@ -5,24 +5,9 @@
|
|
|
5
5
|
* its resolved node tree through the same converter its persistence layer uses, so these types
|
|
6
6
|
* describe what genuinely arrives rather than what was intended to.
|
|
7
7
|
*/
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return isFormField(node) && node.fieldType !== 'Button';
|
|
14
|
-
}
|
|
15
|
-
/** Depth-first walk of a node tree, flattened to the data-carrying fields only. */
|
|
16
|
-
export function collectDataFields(nodes) {
|
|
17
|
-
const result = [];
|
|
18
|
-
for (const node of nodes) {
|
|
19
|
-
if (node.nodeType === 'Fieldset' || node.nodeType === 'Row') {
|
|
20
|
-
result.push(...collectDataFields(node.nodes));
|
|
21
|
-
}
|
|
22
|
-
else if (isDataField(node)) {
|
|
23
|
-
result.push(node);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
8
|
+
export {};
|
|
9
|
+
// `isFormField`/`isDataField`/`collectDataFields`/`resolveVariant` live in `./nodes.js`, not here —
|
|
10
|
+
// `resolveVariant` needs `isFieldComparisonSatisfied` from `./predicates.js`, which itself imports
|
|
11
|
+
// types from this file, so keeping tree-walking logic out of `types.ts` avoids a circular import
|
|
12
|
+
// between the two.
|
|
28
13
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;;AAuJH,oGAAoG;AACpG,mGAAmG;AACnG,iGAAiG;AACjG,mBAAmB"}
|
package/dist/validators.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SdkForm, SubmissionData, ValidationErrors } from './types.js';
|
|
2
2
|
export interface ValidateOptions {
|
|
3
3
|
/**
|
|
4
4
|
* `true` when finalizing a submission — every required field must be present and non-empty.
|
|
@@ -20,6 +20,15 @@ export interface ValidateOptions {
|
|
|
20
20
|
* Like the server's, this is a *basic* shape check by design — no email regex on an Email-variant
|
|
21
21
|
* input, for instance. It enforces the constraints a field definition actually declares, not
|
|
22
22
|
* stricter invented formats. Native browser validation still applies on top.
|
|
23
|
+
*
|
|
24
|
+
* **`collectDataFields` is answers-aware** (spec 111-conditional-fields): a field inside a `Variant`
|
|
25
|
+
* branch that isn't currently satisfied by `data` is simply absent from `fields` below, so it is
|
|
26
|
+
* never required and a value submitted for it is flagged the same as any other unrecognized key
|
|
27
|
+
* ("Unknown field."). That is a deliberate simplification from the server's own two-message
|
|
28
|
+
* distinction ("Unknown field." vs. "This field was not shown and cannot be submitted.") — the
|
|
29
|
+
* server remains authoritative for that nuance, and a respondent can't reach this case through this
|
|
30
|
+
* component's own UI anyway, since `EbitexForm` prunes a hidden field's answer from `data` the moment
|
|
31
|
+
* its controlling condition stops being satisfied (see that component's own `setValue`).
|
|
23
32
|
*/
|
|
24
33
|
export declare function validateSubmission(form: SdkForm, data: SubmissionData, options: ValidateOptions): ValidationErrors;
|
|
25
34
|
//# sourceMappingURL=validators.d.ts.map
|
package/dist/validators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE3E,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,eAAe,GACvB,gBAAgB,CAsClB"}
|
package/dist/validators.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { collectDataFields } from './
|
|
1
|
+
import { collectDataFields } from './nodes.js';
|
|
2
2
|
/**
|
|
3
3
|
* A client-side port of the server's own `SubmissionDataValidator`, for immediate feedback before a
|
|
4
4
|
* step advances or a form submits.
|
|
@@ -12,14 +12,25 @@ import { collectDataFields } from './types.js';
|
|
|
12
12
|
* Like the server's, this is a *basic* shape check by design — no email regex on an Email-variant
|
|
13
13
|
* input, for instance. It enforces the constraints a field definition actually declares, not
|
|
14
14
|
* stricter invented formats. Native browser validation still applies on top.
|
|
15
|
+
*
|
|
16
|
+
* **`collectDataFields` is answers-aware** (spec 111-conditional-fields): a field inside a `Variant`
|
|
17
|
+
* branch that isn't currently satisfied by `data` is simply absent from `fields` below, so it is
|
|
18
|
+
* never required and a value submitted for it is flagged the same as any other unrecognized key
|
|
19
|
+
* ("Unknown field."). That is a deliberate simplification from the server's own two-message
|
|
20
|
+
* distinction ("Unknown field." vs. "This field was not shown and cannot be submitted.") — the
|
|
21
|
+
* server remains authoritative for that nuance, and a respondent can't reach this case through this
|
|
22
|
+
* component's own UI anyway, since `EbitexForm` prunes a hidden field's answer from `data` the moment
|
|
23
|
+
* its controlling condition stops being satisfied (see that component's own `setValue`).
|
|
15
24
|
*/
|
|
16
25
|
export function validateSubmission(form, data, options) {
|
|
17
26
|
const errors = {};
|
|
18
|
-
const fields = new Map(collectDataFields(form.steps.flatMap((step) => step.nodes))
|
|
27
|
+
const fields = new Map(collectDataFields(form.steps.flatMap((step) => step.nodes), data)
|
|
19
28
|
.filter((field) => field.submissionKey !== undefined)
|
|
20
29
|
.map((field) => [field.submissionKey, field]));
|
|
21
30
|
// Unknown keys are errors, not ignored input — matching the server, which rejects them so
|
|
22
|
-
// arbitrary caller-supplied keys never accumulate in a column staff will later read.
|
|
31
|
+
// arbitrary caller-supplied keys never accumulate in a column staff will later read. A key
|
|
32
|
+
// belonging to a real but currently-hidden field falls in here too — see this function's own
|
|
33
|
+
// remarks on why that's an acceptable simplification client-side.
|
|
23
34
|
for (const key of Object.keys(data)) {
|
|
24
35
|
if (!fields.has(key)) {
|
|
25
36
|
errors[key] = 'Unknown field.';
|
package/dist/validators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"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"}
|