@ebitex/forms-sdk 0.1.2 → 0.3.8
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/README.md +119 -0
- 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 +50 -0
- package/dist/nodes.js.map +1 -0
- package/dist/predicates.d.ts +35 -0
- package/dist/predicates.d.ts.map +1 -0
- package/dist/predicates.js +76 -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 +36 -6
- package/dist/react/EbitexForm.js.map +1 -1
- package/dist/types.d.ts +54 -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/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @ebitex/forms-sdk
|
|
2
|
+
|
|
3
|
+
Fetch and render [ebitex](https://ebitex.io) Forms in your own application.
|
|
4
|
+
|
|
5
|
+
Two entry points, split deliberately:
|
|
6
|
+
|
|
7
|
+
- **`@ebitex/forms-sdk`** — fetches a form definition and validates a submission against it. No
|
|
8
|
+
React dependency, so a server-only consumer never pulls one in.
|
|
9
|
+
- **`@ebitex/forms-sdk/react`** — the rendering components. Imports React as a `peerDependency`
|
|
10
|
+
(never bundled), so it never conflicts with your own app's copy.
|
|
11
|
+
|
|
12
|
+
Your organization's API key is **server-side only**. Fetch the form definition with
|
|
13
|
+
`createFormsClient` on your server or in a build step, then pass the result to `<EbitexForm>` —
|
|
14
|
+
which never receives the key itself, only the already-fetched definition.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm install @ebitex/forms-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
// Server-side (a route handler, a loader, a build step — never in a browser bundle)
|
|
26
|
+
import { createFormsClient } from '@ebitex/forms-sdk'
|
|
27
|
+
|
|
28
|
+
const client = createFormsClient({ apiKey: process.env.EBITEX_FORMS_API_KEY! })
|
|
29
|
+
const form = await client.getForm('contact-us')
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// Client-side — `form` is whatever getForm(...) returned above, passed down as a prop
|
|
34
|
+
import { EbitexForm } from '@ebitex/forms-sdk/react'
|
|
35
|
+
import '@ebitex/forms-sdk/styles.css'
|
|
36
|
+
|
|
37
|
+
function ContactPage({ form }: { form: SdkForm }) {
|
|
38
|
+
return <EbitexForm form={form} onSubmitted={() => console.log('done')} />
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`<EbitexForm>` posts directly to the form's own public `submissionUrl` — the same anonymous
|
|
43
|
+
endpoint ebitex's own hosted page and iframe embed use — so it never needs your API key either.
|
|
44
|
+
Multi-step forms save progress as the respondent advances.
|
|
45
|
+
|
|
46
|
+
## Rendering nodes yourself
|
|
47
|
+
|
|
48
|
+
If you're not using `<EbitexForm>` — building a custom renderer, or validating a submission
|
|
49
|
+
server-side without a browser involved — `collectDataFields`/`resolveVariant`/
|
|
50
|
+
`isFieldComparisonSatisfied`/`isAllOfSatisfied`/`isSatisfied` are the same evaluators it uses
|
|
51
|
+
internally, exported so a second, independently-written implementation never has a chance to drift
|
|
52
|
+
from the real one.
|
|
53
|
+
|
|
54
|
+
A form's content tree (`SdkForm.actions`, each `FormStep.nodes`) is `FormNode[]`: a `Fieldset` or
|
|
55
|
+
`Row` groups other nodes; a field type (`InputField`/`TextareaField`/`NumberField`/`ChoiceField`/
|
|
56
|
+
`ButtonField`) is a leaf; a `VariantNode` shows at most one of its `branches` (first whose `when`
|
|
57
|
+
is satisfied) or its `fallback`, based on the respondent's own answers so far.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
interface VariantNode {
|
|
61
|
+
nodeType: 'Variant'
|
|
62
|
+
branches: VariantBranch[]
|
|
63
|
+
/** Always an array — empty means "nothing" rather than `null`. */
|
|
64
|
+
fallback: FormNode[]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface VariantBranch {
|
|
68
|
+
when: VariantPredicate
|
|
69
|
+
/** May hold more than one node — not capped at one. */
|
|
70
|
+
nodes: FormNode[]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
type VariantPredicate = FieldComparisonPredicate | AllOfPredicate
|
|
74
|
+
|
|
75
|
+
interface FieldComparisonPredicate {
|
|
76
|
+
kind: 'FieldComparison'
|
|
77
|
+
field: string // a submissionKey answered *earlier* in the form
|
|
78
|
+
operator: 'Equals' | 'NotEquals' | 'IsEmpty' | 'IsNotEmpty'
|
|
79
|
+
value?: string // present for Equals/NotEquals, absent otherwise
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** AND-combination of two or more FieldComparisonPredicates — every one must be satisfied. */
|
|
83
|
+
interface AllOfPredicate {
|
|
84
|
+
kind: 'AllOf'
|
|
85
|
+
predicates: FieldComparisonPredicate[]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { resolveVariant, isSatisfied } from '@ebitex/forms-sdk'
|
|
91
|
+
|
|
92
|
+
// Which of a Variant's branches (or its fallback) the respondent currently sees, given their
|
|
93
|
+
// answers so far — returns that branch's/fallback's own node list, possibly empty.
|
|
94
|
+
const visibleNodes = resolveVariant(variantNode, currentAnswers)
|
|
95
|
+
|
|
96
|
+
// Evaluating one branch's own `when` directly, regardless of which predicate kind it is.
|
|
97
|
+
const branchApplies = isSatisfied(someBranch.when, currentAnswers)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
A field's answer is submitted under its own `submissionKey` — not necessarily its `name`: a field
|
|
101
|
+
placed by reference to one you've reused across forms is keyed by that shared field's own external
|
|
102
|
+
id instead. Always read/write `SubmissionData` by `submissionKey`.
|
|
103
|
+
|
|
104
|
+
## Validating a submission
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { validateSubmission } from '@ebitex/forms-sdk'
|
|
108
|
+
|
|
109
|
+
const errors = validateSubmission(form, submittedData, { requireAll: true })
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`<EbitexForm>` calls this itself for inline feedback before every request; the server is always the
|
|
113
|
+
final authority regardless — a client-side pass is for a good respondent experience, not enforcement.
|
|
114
|
+
|
|
115
|
+
## Versioning
|
|
116
|
+
|
|
117
|
+
This package's public wire shape mirrors ebitex's own Forms API responses directly (see
|
|
118
|
+
`SdkForm`/`FormNode` above) — a breaking shape change on the server ships as a new minor version
|
|
119
|
+
here (pre-1.0), not a patch. Pin a specific version if that matters to your build.
|
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 { isAllOfSatisfied, isFieldComparisonSatisfied, isSatisfied } from './predicates.js';
|
|
13
|
+
export { collectDataFields, isDataField, isFormField, resolveVariant } from './nodes.js';
|
|
14
|
+
export { type AllOfPredicate, 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, type VariantPredicate, } 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,gBAAgB,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE3F,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAExF,OAAO,EACL,KAAK,cAAc,EACnB,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,EAChB,KAAK,gBAAgB,GACtB,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 { isAllOfSatisfied, isFieldComparisonSatisfied, isSatisfied } 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,gBAAgB,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE3F,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAExF,OAAO,EAwBN,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 the chosen branch's/fallback's own node **list** (spec
|
|
10
|
+
* 113-variant-branch-refinements) — possibly empty, since a Variant may legitimately render nothing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveVariant(variant: VariantNode, data: SubmissionData): FormNode[];
|
|
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,EAAE,CAQrF;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,CAc5D"}
|
package/dist/nodes.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isSatisfied } 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 the chosen branch's/fallback's own node **list** (spec
|
|
14
|
+
* 113-variant-branch-refinements) — possibly empty, since a Variant may legitimately render nothing.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveVariant(variant, data) {
|
|
17
|
+
for (const branch of variant.branches) {
|
|
18
|
+
if (isSatisfied(branch.when, data)) {
|
|
19
|
+
return branch.nodes;
|
|
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
|
+
result.push(...collectDataFields(resolveVariant(node, data), data));
|
|
43
|
+
}
|
|
44
|
+
else if (isDataField(node)) {
|
|
45
|
+
result.push(node);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAY7C,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,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,KAAK,CAAA;QACrB,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,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;QACrE,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,35 @@
|
|
|
1
|
+
import type { AllOfPredicate, FieldComparisonPredicate, SubmissionData, VariantPredicate } 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
|
+
/**
|
|
24
|
+
* True when every predicate in `predicates` is satisfied (spec 113-variant-branch-refinements) —
|
|
25
|
+
* client-side port of `VariantResolver.IsSatisfied`'s `AllOfPredicate` case.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isAllOfSatisfied(predicate: AllOfPredicate, data: SubmissionData): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Dispatches a `Variant` branch's `when` to the right evaluator regardless of which of the two
|
|
30
|
+
* predicate kinds it is — what `resolveVariant` (`./nodes.js`) and `apps/forms-web`'s
|
|
31
|
+
* `resolvePublicVariant` call, so neither has to switch on `kind` itself. Client-side port of
|
|
32
|
+
* `VariantResolver.IsSatisfied`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isSatisfied(predicate: VariantPredicate, data: SubmissionData): boolean;
|
|
35
|
+
//# 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,cAAc,EAAE,wBAAwB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE5G;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,wBAAwB,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CA0B7G;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAEzF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAEtF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
/**
|
|
47
|
+
* True when every predicate in `predicates` is satisfied (spec 113-variant-branch-refinements) —
|
|
48
|
+
* client-side port of `VariantResolver.IsSatisfied`'s `AllOfPredicate` case.
|
|
49
|
+
*/
|
|
50
|
+
export function isAllOfSatisfied(predicate, data) {
|
|
51
|
+
return predicate.predicates.every((member) => isFieldComparisonSatisfied(member, data));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Dispatches a `Variant` branch's `when` to the right evaluator regardless of which of the two
|
|
55
|
+
* predicate kinds it is — what `resolveVariant` (`./nodes.js`) and `apps/forms-web`'s
|
|
56
|
+
* `resolvePublicVariant` call, so neither has to switch on `kind` itself. Client-side port of
|
|
57
|
+
* `VariantResolver.IsSatisfied`.
|
|
58
|
+
*/
|
|
59
|
+
export function isSatisfied(predicate, data) {
|
|
60
|
+
return predicate.kind === 'AllOf' ? isAllOfSatisfied(predicate, data) : isFieldComparisonSatisfied(predicate, data);
|
|
61
|
+
}
|
|
62
|
+
function isEmptyValue(value) {
|
|
63
|
+
if (typeof value === 'string')
|
|
64
|
+
return value.trim() === '';
|
|
65
|
+
if (Array.isArray(value))
|
|
66
|
+
return value.length === 0;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
function matchesValue(value, comparand) {
|
|
70
|
+
if (Array.isArray(value))
|
|
71
|
+
return value.some((item) => item === comparand);
|
|
72
|
+
if (typeof value === 'string')
|
|
73
|
+
return value === comparand;
|
|
74
|
+
return String(value) === comparand;
|
|
75
|
+
}
|
|
76
|
+
//# 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;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAyB,EAAE,IAAoB;IAC9E,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,0BAA0B,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;AACzF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,SAA2B,EAAE,IAAoB;IAC3E,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AACrH,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,13 @@ 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). The chosen
|
|
161
|
+
// branch's/fallback's own node list (spec 113-variant-branch-refinements) may be empty —
|
|
162
|
+
// NodeList over an empty array renders nothing, same as the old `null` case did.
|
|
163
|
+
return (_jsx(NodeList, { nodes: resolveVariant(node, data), baseId: baseId, data: data, errors: errors, disabled: disabled, fieldComponents: fieldComponents, onChange: onChange }, `variant-${index}`));
|
|
164
|
+
}
|
|
135
165
|
if (node.fieldType === 'Button') {
|
|
136
166
|
// Buttons inside a step's tree are the Form's own Actions, rendered by ActionButtons.
|
|
137
167
|
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":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -60,6 +60,36 @@ 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. A locale predicate is always decidable server-side (spec #109), so it's resolved away
|
|
67
|
+
* before serialization and never reaches the wire — a `Variant` node only survives serialization at
|
|
68
|
+
* all when it's governed by at least one `FieldComparisonPredicate`, alone or combined via
|
|
69
|
+
* `AllOfPredicate` (spec 113-variant-branch-refinements).
|
|
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
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* AND-combination of two or more `FieldComparisonPredicate`s on one branch (spec
|
|
83
|
+
* 113-variant-branch-refinements), e.g. `country = US AND shippingDiffers = yes`. Server-validated to
|
|
84
|
+
* contain only `FieldComparisonPredicate` members (no nesting, no `LocalePredicate`) and to have at
|
|
85
|
+
* least two — a well-formed response never sends a one-element `AllOfPredicate`.
|
|
86
|
+
*/
|
|
87
|
+
export interface AllOfPredicate {
|
|
88
|
+
kind: 'AllOf';
|
|
89
|
+
predicates: FieldComparisonPredicate[];
|
|
90
|
+
}
|
|
91
|
+
/** The only two predicate kinds a `Variant` branch's `when` can be on the wire — see `FieldComparisonPredicate`'s own remarks for why a `LocalePredicate` never reaches here. */
|
|
92
|
+
export type VariantPredicate = FieldComparisonPredicate | AllOfPredicate;
|
|
63
93
|
export interface FieldsetNode {
|
|
64
94
|
nodeType: 'Fieldset';
|
|
65
95
|
legend: string;
|
|
@@ -69,7 +99,30 @@ export interface RowNode {
|
|
|
69
99
|
nodeType: 'Row';
|
|
70
100
|
nodes: FormNode[];
|
|
71
101
|
}
|
|
72
|
-
|
|
102
|
+
/**
|
|
103
|
+
* One branch of a `Variant` (spec 111-conditional-fields): `nodes` is shown when `when` is satisfied
|
|
104
|
+
* against the respondent's current answers — see `resolveVariant` in `./nodes.js`. `nodes` is a list
|
|
105
|
+
* (spec 113-variant-branch-refinements), may be empty, matching `Fieldset`/`Row`'s own shape rather
|
|
106
|
+
* than a single required node.
|
|
107
|
+
*/
|
|
108
|
+
export interface VariantBranch {
|
|
109
|
+
when: VariantPredicate;
|
|
110
|
+
nodes: FormNode[];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A structural switch: at most one of `branches` (first match wins, in order) or `fallback` is what a
|
|
114
|
+
* respondent actually sees, decided live in the browser as they answer — see `resolveVariant` in
|
|
115
|
+
* `./nodes.js`, which both this SDK's `EbitexForm` and `apps/forms-web`'s `PublicFormRender` use so
|
|
116
|
+
* the decision can't drift between them. `fallback` is always an array (never `null`) — spec
|
|
117
|
+
* 113-variant-branch-refinements retyped it from a nullable single node to a list, an empty array
|
|
118
|
+
* replacing what `null` used to mean.
|
|
119
|
+
*/
|
|
120
|
+
export interface VariantNode {
|
|
121
|
+
nodeType: 'Variant';
|
|
122
|
+
branches: VariantBranch[];
|
|
123
|
+
fallback: FormNode[];
|
|
124
|
+
}
|
|
125
|
+
export type FormNode = FieldsetNode | RowNode | FormField | VariantNode;
|
|
73
126
|
export interface FormStep {
|
|
74
127
|
label: string;
|
|
75
128
|
nodes: FormNode[];
|
|
@@ -94,10 +147,5 @@ export interface SdkForm {
|
|
|
94
147
|
export type SubmissionData = Record<string, string | string[] | number | null>;
|
|
95
148
|
/** Field-level validation messages, keyed by `submissionKey`. Empty means valid. */
|
|
96
149
|
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
150
|
export {};
|
|
103
151
|
//# 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":"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"}
|
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;;AAwKH,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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"}
|