@getodk/xforms-engine 0.2.0 → 0.3.0
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/body/BodyElementDefinition.d.ts +4 -3
- package/dist/body/RepeatElementDefinition.d.ts +2 -2
- package/dist/body/control/ControlDefinition.d.ts +2 -2
- package/dist/body/control/select/ItemDefinition.d.ts +2 -2
- package/dist/body/control/select/ItemsetDefinition.d.ts +5 -4
- package/dist/body/group/BaseGroupDefinition.d.ts +1 -1
- package/dist/body/group/PresentationGroupDefinition.d.ts +1 -1
- package/dist/client/BaseNode.d.ts +68 -2
- package/dist/client/GroupNode.d.ts +2 -0
- package/dist/client/ModelValueNode.d.ts +37 -0
- package/dist/client/NoteNode.d.ts +53 -0
- package/dist/client/RootNode.d.ts +2 -0
- package/dist/client/SelectNode.d.ts +5 -3
- package/dist/client/StringNode.d.ts +5 -3
- package/dist/client/SubtreeNode.d.ts +2 -0
- package/dist/client/TextRange.d.ts +85 -2
- package/dist/client/constants.d.ts +9 -0
- package/dist/client/hierarchy.d.ts +14 -9
- package/dist/client/node-types.d.ts +2 -1
- package/dist/client/{RepeatRangeNode.d.ts → repeat/BaseRepeatRangeNode.d.ts} +18 -17
- package/dist/client/{RepeatInstanceNode.d.ts → repeat/RepeatInstanceNode.d.ts} +9 -8
- package/dist/client/repeat/RepeatRangeControlledNode.d.ts +19 -0
- package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +20 -0
- package/dist/client/validation.d.ts +163 -0
- package/dist/expression/DependentExpression.d.ts +12 -8
- package/dist/index.d.ts +9 -4
- package/dist/index.js +2635 -678
- package/dist/index.js.map +1 -1
- package/dist/instance/Group.d.ts +3 -1
- package/dist/instance/ModelValue.d.ts +40 -0
- package/dist/instance/Note.d.ts +42 -0
- package/dist/instance/Root.d.ts +2 -0
- package/dist/instance/SelectField.d.ts +10 -4
- package/dist/instance/StringField.d.ts +11 -5
- package/dist/instance/Subtree.d.ts +2 -0
- package/dist/instance/abstract/DescendantNode.d.ts +5 -6
- package/dist/instance/abstract/InstanceNode.d.ts +2 -0
- package/dist/instance/hierarchy.d.ts +10 -5
- package/dist/instance/internal-api/ValidationContext.d.ts +21 -0
- package/dist/instance/{RepeatRange.d.ts → repeat/BaseRepeatRange.d.ts} +46 -45
- package/dist/instance/{RepeatInstance.d.ts → repeat/RepeatInstance.d.ts} +13 -12
- package/dist/instance/repeat/RepeatRangeControlled.d.ts +16 -0
- package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +35 -0
- package/dist/instance/text/TextRange.d.ts +4 -4
- package/dist/lib/reactivity/createComputedExpression.d.ts +6 -1
- package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +5 -0
- package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +1 -1
- package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +1 -1
- package/dist/lib/reactivity/text/createFieldHint.d.ts +3 -3
- package/dist/lib/reactivity/text/createNodeLabel.d.ts +2 -2
- package/dist/lib/reactivity/text/createNoteText.d.ts +25 -0
- package/dist/lib/reactivity/text/createTextRange.d.ts +5 -7
- package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +9 -0
- package/dist/lib/reactivity/validation/createValidation.d.ts +18 -0
- package/dist/model/BindDefinition.d.ts +4 -2
- package/dist/model/BindElement.d.ts +1 -0
- package/dist/model/{ValueNodeDefinition.d.ts → LeafNodeDefinition.d.ts} +2 -2
- package/dist/model/NodeDefinition.d.ts +8 -8
- package/dist/model/RepeatInstanceDefinition.d.ts +2 -2
- package/dist/model/RepeatRangeDefinition.d.ts +14 -4
- package/dist/parse/NoteNodeDefinition.d.ts +31 -0
- package/dist/parse/expression/RepeatCountControlExpression.d.ts +19 -0
- package/dist/parse/text/HintDefinition.d.ts +9 -0
- package/dist/parse/text/ItemLabelDefinition.d.ts +9 -0
- package/dist/parse/text/ItemsetLabelDefinition.d.ts +13 -0
- package/dist/parse/text/LabelDefinition.d.ts +15 -0
- package/dist/parse/text/MessageDefinition.d.ts +15 -0
- package/dist/parse/text/OutputChunkDefinition.d.ts +8 -0
- package/dist/parse/text/ReferenceChunkDefinition.d.ts +8 -0
- package/dist/parse/text/StaticTextChunkDefinition.d.ts +10 -0
- package/dist/parse/text/TranslationChunkDefinition.d.ts +9 -0
- package/dist/parse/text/abstract/TextChunkDefinition.d.ts +18 -0
- package/dist/parse/text/abstract/TextElementDefinition.d.ts +23 -0
- package/dist/parse/text/abstract/TextRangeDefinition.d.ts +35 -0
- package/dist/parse/xpath/dependency-analysis.d.ts +40 -0
- package/dist/parse/xpath/path-resolution.d.ts +70 -0
- package/dist/parse/xpath/predicate-analysis.d.ts +30 -0
- package/dist/parse/xpath/reference-parsing.d.ts +18 -0
- package/dist/parse/xpath/semantic-analysis.d.ts +98 -0
- package/dist/parse/xpath/syntax-traversal.d.ts +69 -0
- package/dist/solid.js +2636 -679
- package/dist/solid.js.map +1 -1
- package/package.json +14 -15
- package/src/body/BodyElementDefinition.ts +4 -3
- package/src/body/RepeatElementDefinition.ts +5 -17
- package/src/body/control/ControlDefinition.ts +4 -3
- package/src/body/control/select/ItemDefinition.ts +3 -3
- package/src/body/control/select/ItemsetDefinition.ts +29 -12
- package/src/body/control/select/ItemsetNodesetExpression.ts +1 -1
- package/src/body/group/BaseGroupDefinition.ts +3 -2
- package/src/body/group/PresentationGroupDefinition.ts +1 -1
- package/src/client/BaseNode.ts +73 -7
- package/src/client/GroupNode.ts +2 -0
- package/src/client/ModelValueNode.ts +40 -0
- package/src/client/NoteNode.ts +74 -0
- package/src/client/README.md +1 -0
- package/src/client/RootNode.ts +2 -0
- package/src/client/SelectNode.ts +5 -3
- package/src/client/StringNode.ts +5 -3
- package/src/client/SubtreeNode.ts +2 -0
- package/src/client/TextRange.ts +99 -2
- package/src/client/constants.ts +10 -0
- package/src/client/hierarchy.ts +30 -14
- package/src/client/node-types.ts +8 -1
- package/src/client/{RepeatRangeNode.ts → repeat/BaseRepeatRangeNode.ts} +18 -19
- package/src/client/{RepeatInstanceNode.ts → repeat/RepeatInstanceNode.ts} +10 -8
- package/src/client/repeat/RepeatRangeControlledNode.ts +20 -0
- package/src/client/repeat/RepeatRangeUncontrolledNode.ts +21 -0
- package/src/client/validation.ts +199 -0
- package/src/expression/DependentExpression.ts +45 -27
- package/src/index.ts +15 -8
- package/src/instance/Group.ts +10 -4
- package/src/instance/ModelValue.ts +104 -0
- package/src/instance/Note.ts +142 -0
- package/src/instance/Root.ts +9 -3
- package/src/instance/SelectField.ts +28 -6
- package/src/instance/StringField.ts +35 -9
- package/src/instance/Subtree.ts +9 -3
- package/src/instance/abstract/DescendantNode.ts +6 -7
- package/src/instance/abstract/InstanceNode.ts +20 -6
- package/src/instance/children.ts +42 -15
- package/src/instance/hierarchy.ts +21 -2
- package/src/instance/internal-api/ValidationContext.ts +23 -0
- package/src/instance/{RepeatRange.ts → repeat/BaseRepeatRange.ts} +114 -99
- package/src/instance/{RepeatInstance.ts → repeat/RepeatInstance.ts} +27 -22
- package/src/instance/repeat/RepeatRangeControlled.ts +82 -0
- package/src/instance/repeat/RepeatRangeUncontrolled.ts +67 -0
- package/src/instance/text/TextRange.ts +10 -4
- package/src/lib/reactivity/createComputedExpression.ts +22 -24
- package/src/lib/reactivity/createNoteReadonlyThunk.ts +33 -0
- package/src/lib/reactivity/createSelectItems.ts +21 -14
- package/src/lib/reactivity/node-state/createSharedNodeState.ts +1 -1
- package/src/lib/reactivity/text/createFieldHint.ts +9 -7
- package/src/lib/reactivity/text/createNodeLabel.ts +7 -5
- package/src/lib/reactivity/text/createNoteText.ts +72 -0
- package/src/lib/reactivity/text/createTextRange.ts +17 -90
- package/src/lib/reactivity/validation/createAggregatedViolations.ts +70 -0
- package/src/lib/reactivity/validation/createValidation.ts +196 -0
- package/src/model/BindComputation.ts +0 -4
- package/src/model/BindDefinition.ts +8 -6
- package/src/model/BindElement.ts +1 -0
- package/src/model/{ValueNodeDefinition.ts → LeafNodeDefinition.ts} +4 -4
- package/src/model/ModelBindMap.ts +4 -0
- package/src/model/NodeDefinition.ts +12 -12
- package/src/model/RepeatInstanceDefinition.ts +2 -2
- package/src/model/RepeatRangeDefinition.ts +49 -8
- package/src/model/RootDefinition.ts +7 -3
- package/src/parse/NoteNodeDefinition.ts +70 -0
- package/src/parse/TODO.md +3 -0
- package/src/parse/expression/RepeatCountControlExpression.ts +44 -0
- package/src/parse/text/HintDefinition.ts +25 -0
- package/src/parse/text/ItemLabelDefinition.ts +25 -0
- package/src/parse/text/ItemsetLabelDefinition.ts +44 -0
- package/src/parse/text/LabelDefinition.ts +61 -0
- package/src/parse/text/MessageDefinition.ts +49 -0
- package/src/parse/text/OutputChunkDefinition.ts +25 -0
- package/src/parse/text/ReferenceChunkDefinition.ts +14 -0
- package/src/parse/text/StaticTextChunkDefinition.ts +19 -0
- package/src/parse/text/TranslationChunkDefinition.ts +38 -0
- package/src/parse/text/abstract/TextChunkDefinition.ts +38 -0
- package/src/parse/text/abstract/TextElementDefinition.ts +71 -0
- package/src/parse/text/abstract/TextRangeDefinition.ts +70 -0
- package/src/parse/xpath/dependency-analysis.ts +105 -0
- package/src/parse/xpath/path-resolution.ts +475 -0
- package/src/parse/xpath/predicate-analysis.ts +61 -0
- package/src/parse/xpath/reference-parsing.ts +90 -0
- package/src/parse/xpath/semantic-analysis.ts +466 -0
- package/src/parse/xpath/syntax-traversal.ts +129 -0
- package/dist/body/text/HintDefinition.d.ts +0 -11
- package/dist/body/text/LabelDefinition.d.ts +0 -22
- package/dist/body/text/TextElementDefinition.d.ts +0 -33
- package/dist/body/text/TextElementOutputPart.d.ts +0 -13
- package/dist/body/text/TextElementPart.d.ts +0 -13
- package/dist/body/text/TextElementReferencePart.d.ts +0 -7
- package/dist/body/text/TextElementStaticPart.d.ts +0 -7
- package/dist/lib/xpath/analysis.d.ts +0 -23
- package/src/body/text/HintDefinition.ts +0 -26
- package/src/body/text/LabelDefinition.ts +0 -68
- package/src/body/text/TextElementDefinition.ts +0 -97
- package/src/body/text/TextElementOutputPart.ts +0 -27
- package/src/body/text/TextElementPart.ts +0 -31
- package/src/body/text/TextElementReferencePart.ts +0 -21
- package/src/body/text/TextElementStaticPart.ts +0 -26
- package/src/lib/xpath/analysis.ts +0 -241
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getodk/xforms-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "XForms engine for ODK Web Forms",
|
|
6
6
|
"type": "module",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
31
|
"engines": {
|
|
32
|
-
"node": "^18.20.
|
|
33
|
-
"yarn": "1.22.
|
|
32
|
+
"node": "^18.20.4 || ^20.15.1 || ^22.4.1",
|
|
33
|
+
"yarn": "1.22.22"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "npm-run-all -nl build:*",
|
|
@@ -54,26 +54,25 @@
|
|
|
54
54
|
"test:types": "tsc --project ./tsconfig.json --emitDeclarationOnly false --noEmit"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"solid-js": "^1.8.
|
|
57
|
+
"solid-js": "^1.8.18"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@babel/core": "^7.24.
|
|
61
|
-
"@getodk/tree-sitter-xpath": "0.1.
|
|
62
|
-
"@getodk/xpath": "0.
|
|
63
|
-
"@playwright/test": "^1.
|
|
64
|
-
"@vitest/browser": "^
|
|
60
|
+
"@babel/core": "^7.24.8",
|
|
61
|
+
"@getodk/tree-sitter-xpath": "0.1.2",
|
|
62
|
+
"@getodk/xpath": "0.2.0",
|
|
63
|
+
"@playwright/test": "^1.45.1",
|
|
64
|
+
"@vitest/browser": "^2.0.2",
|
|
65
65
|
"babel-plugin-transform-jsbi-to-bigint": "^1.4.0",
|
|
66
66
|
"http-server": "^14.1.1",
|
|
67
|
-
"jsdom": "^24.
|
|
68
|
-
"typedoc": "^0.
|
|
69
|
-
"
|
|
70
|
-
"vite": "^5.2.11",
|
|
67
|
+
"jsdom": "^24.1.0",
|
|
68
|
+
"typedoc": "^0.26.4",
|
|
69
|
+
"vite": "^5.3.3",
|
|
71
70
|
"vite-plugin-dts": "^3.9.1",
|
|
72
71
|
"vite-plugin-no-bundle": "^4.0.0",
|
|
73
|
-
"vitest": "^
|
|
72
|
+
"vitest": "^2.0.2"
|
|
74
73
|
},
|
|
75
74
|
"peerDependencies": {
|
|
76
|
-
"solid-js": "^1.8.
|
|
75
|
+
"solid-js": "^1.8.18"
|
|
77
76
|
},
|
|
78
77
|
"peerDependenciesMeta": {
|
|
79
78
|
"solid-js": {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { XFormDefinition } from '../XFormDefinition.ts';
|
|
2
2
|
import { DependencyContext } from '../expression/DependencyContext.ts';
|
|
3
|
+
import type { HintDefinition } from '../parse/text/HintDefinition.ts';
|
|
4
|
+
import type { ItemLabelDefinition } from '../parse/text/ItemLabelDefinition.ts';
|
|
5
|
+
import type { LabelDefinition } from '../parse/text/LabelDefinition.ts';
|
|
3
6
|
import type { BodyElementParentContext } from './BodyDefinition.ts';
|
|
4
|
-
import type { HintDefinition } from './text/HintDefinition.ts';
|
|
5
|
-
import type { LabelDefinition } from './text/LabelDefinition.ts';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* These category names roughly correspond to each of the ODK XForms spec's
|
|
@@ -22,7 +23,7 @@ export abstract class BodyElementDefinition<Type extends string> extends Depende
|
|
|
22
23
|
abstract readonly category: BodyElementCategory;
|
|
23
24
|
abstract readonly type: Type;
|
|
24
25
|
readonly hint: HintDefinition | null = null;
|
|
25
|
-
readonly label: LabelDefinition | null = null;
|
|
26
|
+
readonly label: ItemLabelDefinition | LabelDefinition | null = null;
|
|
26
27
|
|
|
27
28
|
readonly reference: string | null = null;
|
|
28
29
|
readonly parentReference: string | null;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { JAVAROSA_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
|
|
2
2
|
import type { XFormDefinition } from '../XFormDefinition.ts';
|
|
3
|
+
import { LabelDefinition } from '../parse/text/LabelDefinition.ts';
|
|
4
|
+
import { parseNodesetReference } from '../parse/xpath/reference-parsing.ts';
|
|
3
5
|
import type { BodyElementDefinitionArray, BodyElementParentContext } from './BodyDefinition.ts';
|
|
4
6
|
import { BodyDefinition } from './BodyDefinition.ts';
|
|
5
7
|
import { BodyElementDefinition } from './BodyElementDefinition.ts';
|
|
6
8
|
import type { StructureElementAppearanceDefinition } from './appearance/structureElementAppearanceParser.ts';
|
|
7
9
|
import { structureElementAppearanceParser } from './appearance/structureElementAppearanceParser.ts';
|
|
8
|
-
import { LabelDefinition } from './text/LabelDefinition.ts';
|
|
9
10
|
|
|
10
11
|
export class RepeatElementDefinition extends BodyElementDefinition<'repeat'> {
|
|
11
12
|
static override isCompatible(localName: string): boolean {
|
|
@@ -18,11 +19,8 @@ export class RepeatElementDefinition extends BodyElementDefinition<'repeat'> {
|
|
|
18
19
|
readonly appearances: StructureElementAppearanceDefinition;
|
|
19
20
|
override readonly label: LabelDefinition | null;
|
|
20
21
|
|
|
21
|
-
// TODO: this will fall into the growing category of non-`BindExpression`
|
|
22
|
-
// cases which have roughly the same design story.
|
|
23
22
|
readonly countExpression: string | null;
|
|
24
|
-
|
|
25
|
-
readonly isFixedCount: boolean;
|
|
23
|
+
readonly noAddRemoveExpression: string | null;
|
|
26
24
|
|
|
27
25
|
readonly children: BodyElementDefinitionArray;
|
|
28
26
|
|
|
@@ -31,7 +29,7 @@ export class RepeatElementDefinition extends BodyElementDefinition<'repeat'> {
|
|
|
31
29
|
|
|
32
30
|
this.label = LabelDefinition.forRepeatGroup(form, this);
|
|
33
31
|
|
|
34
|
-
const reference = element
|
|
32
|
+
const reference = parseNodesetReference(parent, element, 'nodeset');
|
|
35
33
|
|
|
36
34
|
if (reference == null) {
|
|
37
35
|
throw new Error('Invalid repeat: missing `nodeset` reference');
|
|
@@ -40,6 +38,7 @@ export class RepeatElementDefinition extends BodyElementDefinition<'repeat'> {
|
|
|
40
38
|
this.reference = reference;
|
|
41
39
|
this.appearances = structureElementAppearanceParser.parseFrom(element, 'appearance');
|
|
42
40
|
this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI, 'count');
|
|
41
|
+
this.noAddRemoveExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI, 'noAddRemove');
|
|
43
42
|
|
|
44
43
|
const childElements = Array.from(element.children).filter((childElement) => {
|
|
45
44
|
const { localName } = childElement;
|
|
@@ -49,17 +48,6 @@ export class RepeatElementDefinition extends BodyElementDefinition<'repeat'> {
|
|
|
49
48
|
const children = BodyDefinition.getChildElementDefinitions(form, this, element, childElements);
|
|
50
49
|
|
|
51
50
|
this.children = children;
|
|
52
|
-
|
|
53
|
-
// Spec says this can be either `true()` or `false()`. That said, it
|
|
54
|
-
// could also presumably be `true ( )` or whatever.
|
|
55
|
-
const noAddRemove =
|
|
56
|
-
element
|
|
57
|
-
.getAttributeNS(JAVAROSA_NAMESPACE_URI, 'noAddRemove')
|
|
58
|
-
?.trim()
|
|
59
|
-
.replaceAll(/\s+/g, '') ?? 'false()';
|
|
60
|
-
|
|
61
|
-
// TODO: **probably** safe to disregard anything else?
|
|
62
|
-
this.isFixedCount = noAddRemove === 'true()';
|
|
63
51
|
}
|
|
64
52
|
|
|
65
53
|
override toJSON() {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { XFormDefinition } from '../../XFormDefinition.ts';
|
|
2
2
|
import type { ParsedTokenList } from '../../lib/TokenListParser.ts';
|
|
3
|
+
import { HintDefinition } from '../../parse/text/HintDefinition.ts';
|
|
4
|
+
import { LabelDefinition } from '../../parse/text/LabelDefinition.ts';
|
|
5
|
+
import { parseNodesetReference } from '../../parse/xpath/reference-parsing.ts';
|
|
3
6
|
import type { BodyElementParentContext } from '../BodyDefinition.ts';
|
|
4
7
|
import { BodyElementDefinition } from '../BodyElementDefinition.ts';
|
|
5
|
-
import { HintDefinition } from '../text/HintDefinition.ts';
|
|
6
|
-
import { LabelDefinition } from '../text/LabelDefinition.ts';
|
|
7
8
|
|
|
8
9
|
// prettier-ignore
|
|
9
10
|
type ControlType =
|
|
@@ -30,7 +31,7 @@ export abstract class ControlDefinition<
|
|
|
30
31
|
constructor(form: XFormDefinition, parent: BodyElementParentContext, element: Element) {
|
|
31
32
|
super(form, parent, element);
|
|
32
33
|
|
|
33
|
-
const reference = element
|
|
34
|
+
const reference = parseNodesetReference(parent, element, 'ref');
|
|
34
35
|
|
|
35
36
|
if (reference == null) {
|
|
36
37
|
throw new Error(`Invalid control: missing ref attribute`);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { getValueElement, type ItemElement } from '../../../lib/dom/query.ts';
|
|
2
|
+
import { ItemLabelDefinition } from '../../../parse/text/ItemLabelDefinition.ts';
|
|
2
3
|
import type { XFormDefinition } from '../../../XFormDefinition.ts';
|
|
3
4
|
import { BodyElementDefinition } from '../../BodyElementDefinition.ts';
|
|
4
|
-
import { LabelDefinition } from '../../text/LabelDefinition.ts';
|
|
5
5
|
import type { AnySelectDefinition } from './SelectDefinition.ts';
|
|
6
6
|
|
|
7
7
|
export class ItemDefinition extends BodyElementDefinition<'item'> {
|
|
8
8
|
override readonly category = 'support';
|
|
9
9
|
override readonly type = 'item';
|
|
10
10
|
|
|
11
|
-
override readonly label:
|
|
11
|
+
override readonly label: ItemLabelDefinition | null;
|
|
12
12
|
readonly value: string;
|
|
13
13
|
|
|
14
14
|
constructor(
|
|
@@ -25,7 +25,7 @@ export class ItemDefinition extends BodyElementDefinition<'item'> {
|
|
|
25
25
|
|
|
26
26
|
super(form, parent, element);
|
|
27
27
|
|
|
28
|
-
this.label =
|
|
28
|
+
this.label = ItemLabelDefinition.from(form, this);
|
|
29
29
|
this.value = value;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { getValueElement, type ItemsetElement } from '../../../lib/dom/query.ts';
|
|
2
1
|
import type { XFormDefinition } from '../../../XFormDefinition.ts';
|
|
2
|
+
import { getValueElement, type ItemsetElement } from '../../../lib/dom/query.ts';
|
|
3
|
+
import { ItemsetLabelDefinition } from '../../../parse/text/ItemsetLabelDefinition.ts';
|
|
4
|
+
import { parseNodesetReference } from '../../../parse/xpath/reference-parsing.ts';
|
|
3
5
|
import { BodyElementDefinition } from '../../BodyElementDefinition.ts';
|
|
4
|
-
import { LabelDefinition } from '../../text/LabelDefinition.ts';
|
|
5
6
|
import { ItemsetNodesetExpression } from './ItemsetNodesetExpression.ts';
|
|
6
7
|
import { ItemsetValueExpression } from './ItemsetValueExpression.ts';
|
|
7
8
|
import type { AnySelectDefinition } from './SelectDefinition.ts';
|
|
@@ -11,26 +12,42 @@ export class ItemsetDefinition extends BodyElementDefinition<'itemset'> {
|
|
|
11
12
|
readonly type = 'itemset';
|
|
12
13
|
|
|
13
14
|
override readonly reference: string;
|
|
14
|
-
override readonly label:
|
|
15
|
+
override readonly label: ItemsetLabelDefinition | null;
|
|
15
16
|
|
|
16
17
|
readonly nodes: ItemsetNodesetExpression;
|
|
17
18
|
readonly value: ItemsetValueExpression;
|
|
18
19
|
|
|
19
|
-
constructor(
|
|
20
|
+
constructor(
|
|
21
|
+
form: XFormDefinition,
|
|
22
|
+
override readonly parent: AnySelectDefinition,
|
|
23
|
+
element: ItemsetElement
|
|
24
|
+
) {
|
|
25
|
+
super(form, parent, element);
|
|
26
|
+
|
|
27
|
+
const nodesetExpression = parseNodesetReference(parent, element, 'nodeset');
|
|
28
|
+
|
|
29
|
+
this.nodes = new ItemsetNodesetExpression(this, nodesetExpression);
|
|
30
|
+
this.reference = nodesetExpression;
|
|
31
|
+
|
|
20
32
|
const valueElement = getValueElement(element);
|
|
21
|
-
const valueExpression = valueElement?.getAttribute('ref');
|
|
22
33
|
|
|
23
|
-
if (
|
|
24
|
-
throw new Error(
|
|
34
|
+
if (valueElement == null) {
|
|
35
|
+
throw new Error('<itemset> has no <value>');
|
|
25
36
|
}
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
const valueExpression = parseNodesetReference(
|
|
39
|
+
{
|
|
40
|
+
reference: null,
|
|
41
|
+
},
|
|
42
|
+
valueElement,
|
|
43
|
+
'ref'
|
|
44
|
+
);
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
if (valueExpression == null) {
|
|
47
|
+
throw new Error(`<itemset> has no <value>`);
|
|
48
|
+
}
|
|
30
49
|
|
|
31
|
-
this.reference = nodesetExpression;
|
|
32
|
-
this.nodes = new ItemsetNodesetExpression(this, nodesetExpression);
|
|
33
50
|
this.value = new ItemsetValueExpression(this, valueExpression);
|
|
34
|
-
this.label =
|
|
51
|
+
this.label = ItemsetLabelDefinition.from(form, this);
|
|
35
52
|
}
|
|
36
53
|
}
|
|
@@ -3,6 +3,6 @@ import type { ItemsetDefinition } from './ItemsetDefinition.ts';
|
|
|
3
3
|
|
|
4
4
|
export class ItemsetNodesetExpression extends DependentExpression<'nodes'> {
|
|
5
5
|
constructor(itemset: ItemsetDefinition, nodesetExpression: string) {
|
|
6
|
-
super(itemset, 'nodes', nodesetExpression);
|
|
6
|
+
super(itemset.parent, 'nodes', nodesetExpression);
|
|
7
7
|
}
|
|
8
8
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { UpsertableMap } from '@getodk/common/lib/collections/UpsertableMap.ts';
|
|
2
2
|
import type { XFormDefinition } from '../../XFormDefinition.ts';
|
|
3
3
|
import { getLabelElement } from '../../lib/dom/query.ts';
|
|
4
|
+
import { LabelDefinition } from '../../parse/text/LabelDefinition.ts';
|
|
5
|
+
import { parseNodesetReference } from '../../parse/xpath/reference-parsing.ts';
|
|
4
6
|
import {
|
|
5
7
|
BodyDefinition,
|
|
6
8
|
type BodyElementDefinitionArray,
|
|
@@ -9,7 +11,6 @@ import {
|
|
|
9
11
|
import { BodyElementDefinition } from '../BodyElementDefinition.ts';
|
|
10
12
|
import type { StructureElementAppearanceDefinition } from '../appearance/structureElementAppearanceParser.ts';
|
|
11
13
|
import { structureElementAppearanceParser } from '../appearance/structureElementAppearanceParser.ts';
|
|
12
|
-
import { LabelDefinition } from '../text/LabelDefinition.ts';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* These type names are derived from **and expand upon** the language used in
|
|
@@ -81,7 +82,7 @@ export abstract class BaseGroupDefinition<
|
|
|
81
82
|
super(form, parent, element);
|
|
82
83
|
|
|
83
84
|
this.children = children ?? this.getChildren(element);
|
|
84
|
-
this.reference = element
|
|
85
|
+
this.reference = parseNodesetReference(parent, element, 'ref');
|
|
85
86
|
this.appearances = structureElementAppearanceParser.parseFrom(element, 'appearance');
|
|
86
87
|
this.label = LabelDefinition.forGroup(form, this);
|
|
87
88
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { XFormDefinition } from '../../XFormDefinition.ts';
|
|
2
|
+
import { LabelDefinition } from '../../parse/text/LabelDefinition.ts';
|
|
2
3
|
import type { BodyElementParentContext } from '../BodyDefinition.ts';
|
|
3
|
-
import { LabelDefinition } from '../text/LabelDefinition.ts';
|
|
4
4
|
import { BaseGroupDefinition } from './BaseGroupDefinition.ts';
|
|
5
5
|
|
|
6
6
|
export class PresentationGroupDefinition extends BaseGroupDefinition<'presentation-group'> {
|
package/src/client/BaseNode.ts
CHANGED
|
@@ -4,6 +4,11 @@ import type { NodeAppearances } from './NodeAppearances.ts';
|
|
|
4
4
|
import type { OpaqueReactiveObjectFactory } from './OpaqueReactiveObjectFactory.ts';
|
|
5
5
|
import type { TextRange } from './TextRange.ts';
|
|
6
6
|
import type { InstanceNodeType } from './node-types.ts';
|
|
7
|
+
import type {
|
|
8
|
+
AncestorNodeValidationState,
|
|
9
|
+
LeafNodeValidationState,
|
|
10
|
+
NodeValidationState,
|
|
11
|
+
} from './validation.ts';
|
|
7
12
|
|
|
8
13
|
export interface BaseNodeState {
|
|
9
14
|
/**
|
|
@@ -43,11 +48,17 @@ export interface BaseNodeState {
|
|
|
43
48
|
*/
|
|
44
49
|
get relevant(): boolean;
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Specifies whether the node must have a non-blank value to be valid (see
|
|
53
|
+
* {@link value} for details).
|
|
54
|
+
*
|
|
55
|
+
* @see {@link https://getodk.github.io/xforms-spec/#bind-attributes}
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*
|
|
59
|
+
* @todo What is the expected behavior of `required` expressions defined for
|
|
60
|
+
* non-leaf/value nodes?
|
|
61
|
+
*/
|
|
51
62
|
get required(): boolean;
|
|
52
63
|
|
|
53
64
|
/**
|
|
@@ -106,6 +117,14 @@ export interface BaseNodeState {
|
|
|
106
117
|
*
|
|
107
118
|
* Parent nodes, i.e. nodes which can contain {@link children}, do not store a
|
|
108
119
|
* value state. For those nodes, their value state should always be `null`.
|
|
120
|
+
*
|
|
121
|
+
* A node's value is considered "blank" when its primary instance state is an
|
|
122
|
+
* empty string, and it is considered "non-blank" otherwise. The engine may
|
|
123
|
+
* represent node values according to aspects of the node's definition (such
|
|
124
|
+
* as its defined data type, its associated control type if any). The node's
|
|
125
|
+
* value being blank or non-blank may contribute to satisfying conditions of
|
|
126
|
+
* the node's validity ({@link constraint}, {@link required}). Otherwise, it
|
|
127
|
+
* is an internal engine consideration.
|
|
109
128
|
*/
|
|
110
129
|
get value(): unknown;
|
|
111
130
|
}
|
|
@@ -181,8 +200,55 @@ export interface BaseNode {
|
|
|
181
200
|
readonly parent: BaseNode | null;
|
|
182
201
|
|
|
183
202
|
/**
|
|
184
|
-
* Each node provides a discrete object representing the stateful aspects of
|
|
185
|
-
* that node which will change over time. When a client provides a
|
|
203
|
+
* Each node provides a discrete object representing the stateful aspects\* of
|
|
204
|
+
* that node which will change over time. When a client provides a
|
|
205
|
+
* {@link OpaqueReactiveObjectFactory}, the engine will update the properties
|
|
206
|
+
* of this object as their respective states change, so a client can implement
|
|
207
|
+
* reactive updates that respond to changes as they occur.
|
|
208
|
+
*
|
|
209
|
+
* \* This includes state which is either client-/user-mutable, or state which
|
|
210
|
+
* is computed based on the core XForms computation model. Each node also
|
|
211
|
+
* exposes {@link validationState}, which reflects the validity of the
|
|
212
|
+
* node, or its descendants.
|
|
186
213
|
*/
|
|
187
214
|
readonly currentState: BaseNodeState;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Represents the validation state of a the node itself, or its descendants.
|
|
218
|
+
*
|
|
219
|
+
* @see {@link AncestorNodeValidationState} and
|
|
220
|
+
* {@link LeafNodeValidationState} for additional details.
|
|
221
|
+
*
|
|
222
|
+
* While filling a form (i.e. prior to submission), validation state can be
|
|
223
|
+
* viewed as computed metadata about the form state. The validation conditions
|
|
224
|
+
* and their violation messages produced by a node _may be computed on
|
|
225
|
+
* demand_. Clients should assume:
|
|
226
|
+
*
|
|
227
|
+
* 1. Validation state **will be current** when directly read by the client.
|
|
228
|
+
* Accessing validation state _may_ invoke engine computation of that state
|
|
229
|
+
* _at that time_.
|
|
230
|
+
*
|
|
231
|
+
* It **may** also be pre-computed by the engine so that direct reads are
|
|
232
|
+
* less computationally expensive, but such optimizations cannot be
|
|
233
|
+
* guaranteed by the engine at this time.
|
|
234
|
+
*
|
|
235
|
+
* 2. For clients providing an {@link OpaqueReactiveObjectFactory}, accessing
|
|
236
|
+
* validation state within a reactive context **will produce updates** to
|
|
237
|
+
* the validation state, as long as the client retains a subscription to
|
|
238
|
+
* that state.
|
|
239
|
+
*
|
|
240
|
+
* If it is possible to detect interruption of such client- reactive
|
|
241
|
+
* subscriptions, the engine _may defer computations_ until subsequent
|
|
242
|
+
* client read/re-subscription, in order to reduce unnecessary
|
|
243
|
+
* computational overhead. Again, such optimizations cannot be guaranteed
|
|
244
|
+
* by the engine at this time.
|
|
245
|
+
*
|
|
246
|
+
* @todo it's easier to conceive a reliable, general solution to optimizing
|
|
247
|
+
* the direct read case, than it is for the client-reactive case (largely
|
|
248
|
+
* because our solution for client reactivity is intentionally opaque). If it
|
|
249
|
+
* turns out that such optimizations are crucial for overall usability, the
|
|
250
|
+
* client-reactive case may best be served by additional APIs for reactive
|
|
251
|
+
* clients to explicitly pause and resume recomputation.
|
|
252
|
+
*/
|
|
253
|
+
readonly validationState: NodeValidationState;
|
|
188
254
|
}
|
package/src/client/GroupNode.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
|
4
4
|
import type { NodeAppearances } from './NodeAppearances.ts';
|
|
5
5
|
import type { RootNode } from './RootNode.ts';
|
|
6
6
|
import type { GeneralChildNode, GeneralParentNode } from './hierarchy.ts';
|
|
7
|
+
import type { AncestorNodeValidationState } from './validation.ts';
|
|
7
8
|
|
|
8
9
|
export interface GroupNodeState extends BaseNodeState {
|
|
9
10
|
get hint(): null;
|
|
@@ -34,4 +35,5 @@ export interface GroupNode extends BaseNode {
|
|
|
34
35
|
readonly root: RootNode;
|
|
35
36
|
readonly parent: GeneralParentNode;
|
|
36
37
|
readonly currentState: GroupNodeState;
|
|
38
|
+
readonly validationState: AncestorNodeValidationState;
|
|
37
39
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
2
|
+
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
3
|
+
import type { GeneralParentNode } from './hierarchy.ts';
|
|
4
|
+
import type { RootNode } from './RootNode.ts';
|
|
5
|
+
import type { LeafNodeValidationState } from './validation.ts';
|
|
6
|
+
|
|
7
|
+
export interface ModelValueNodeState extends BaseNodeState {
|
|
8
|
+
get label(): null;
|
|
9
|
+
get hint(): null;
|
|
10
|
+
get children(): null;
|
|
11
|
+
get valueOptions(): null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reflects the current value of a {@link ModelValueNode}. This value may be
|
|
15
|
+
* populated when a form is loaded, and it may be updated by certain
|
|
16
|
+
* computations defined by the form.
|
|
17
|
+
*/
|
|
18
|
+
get value(): string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ModelValueDefinition extends LeafNodeDefinition {
|
|
22
|
+
readonly bodyElement: null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A node which is:
|
|
27
|
+
*
|
|
28
|
+
* - model-only (i.e. it has no corresponding body element)
|
|
29
|
+
* - a leaf/value node (i.e. it has no element children; it may be defined in
|
|
30
|
+
* the form's `<model>` as either an {@link Element} or {@link Attr})
|
|
31
|
+
*/
|
|
32
|
+
export interface ModelValueNode extends BaseNode {
|
|
33
|
+
readonly nodeType: 'model-value';
|
|
34
|
+
readonly appearances: null;
|
|
35
|
+
readonly definition: ModelValueDefinition;
|
|
36
|
+
readonly root: RootNode;
|
|
37
|
+
readonly parent: GeneralParentNode;
|
|
38
|
+
readonly currentState: ModelValueNodeState;
|
|
39
|
+
readonly validationState: LeafNodeValidationState;
|
|
40
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { InputDefinition } from '../body/control/InputDefinition.ts';
|
|
2
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
3
|
+
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
4
|
+
import type { GeneralParentNode } from './hierarchy.ts';
|
|
5
|
+
import type { NodeAppearances } from './NodeAppearances.ts';
|
|
6
|
+
import type { RootNode } from './RootNode.ts';
|
|
7
|
+
import type { TextRange } from './TextRange.ts';
|
|
8
|
+
import type { LeafNodeValidationState } from './validation.ts';
|
|
9
|
+
|
|
10
|
+
export interface NoteNodeState extends BaseNodeState {
|
|
11
|
+
/**
|
|
12
|
+
* Note-specific specialization: a note will always have a non-null value in
|
|
13
|
+
* at least one of:
|
|
14
|
+
*
|
|
15
|
+
* - {@link label}
|
|
16
|
+
* - {@link hint}
|
|
17
|
+
*
|
|
18
|
+
* This is an alias to whichever is present, with precedent to {@link label}
|
|
19
|
+
* if both are present.
|
|
20
|
+
*/
|
|
21
|
+
// ^ @todo While it's possible to convey this at the type level, the resulting
|
|
22
|
+
// types would be far more complex than this, which is not ideal especially at
|
|
23
|
+
// the package (client) boundary. This alias is a concession that the simpler
|
|
24
|
+
// type is preferred, but that it is still important to convey to clients
|
|
25
|
+
// that at least one form-defined text value will always be available. Note:
|
|
26
|
+
// at least for a first pass, we won't guarantee that the resulting text is
|
|
27
|
+
// non-empty. (We'd probably need to accept an engine fallback to make that
|
|
28
|
+
// guarantee; otherwise we'd need to error on invalid state, potentially at
|
|
29
|
+
// arbitrary points in time.)
|
|
30
|
+
//
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
|
|
32
|
+
get noteText(): NonNullable<this['label'] | this['hint']>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A note will **always** be `readonly`.
|
|
36
|
+
*/
|
|
37
|
+
readonly readonly: true;
|
|
38
|
+
|
|
39
|
+
get label(): TextRange<'label', 'form'> | null;
|
|
40
|
+
get hint(): TextRange<'hint', 'form'> | null;
|
|
41
|
+
get children(): null;
|
|
42
|
+
get valueOptions(): null;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Reflects the readonly value of a {@link NoteNode}, or `null` if blank.
|
|
46
|
+
*/
|
|
47
|
+
// Note that being nullable is an intentional deviation from most other value
|
|
48
|
+
// node types, specifically to make a clear distinction between blank and
|
|
49
|
+
// non-blank values (as that has been a primary driver for prioritizing note
|
|
50
|
+
// functionality).
|
|
51
|
+
get value(): string | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface NoteDefinition extends LeafNodeDefinition {
|
|
55
|
+
readonly bodyElement: InputDefinition;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type NoteNodeAppearances = NodeAppearances<NoteDefinition>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A node which is:
|
|
62
|
+
*
|
|
63
|
+
* - associated with an input, with at least one text element (label or hint)
|
|
64
|
+
* - guaranteed to be {@link NoteNodeState.readonly | readonly}
|
|
65
|
+
*/
|
|
66
|
+
export interface NoteNode extends BaseNode {
|
|
67
|
+
readonly nodeType: 'note';
|
|
68
|
+
readonly appearances: NoteNodeAppearances;
|
|
69
|
+
readonly definition: NoteDefinition;
|
|
70
|
+
readonly root: RootNode;
|
|
71
|
+
readonly parent: GeneralParentNode;
|
|
72
|
+
readonly currentState: NoteNodeState;
|
|
73
|
+
readonly validationState: LeafNodeValidationState;
|
|
74
|
+
}
|
package/src/client/README.md
CHANGED
|
@@ -20,6 +20,7 @@ The interface is designed to:
|
|
|
20
20
|
- Facilitate loading any of a form's externally referenced resources, by means of a client-provided generic resource accessor[^2]
|
|
21
21
|
|
|
22
22
|
[^1]: This factory **may be** reactive, and for many clients that is the anticipated usage. But no assumptions are made by the engine about reactivity or any other implementation details beyond the factory's type definition.
|
|
23
|
+
|
|
23
24
|
[^2]: This accessor **may** access networked resources, and for many clients that is the anticipated usage. But no assumptions are made by the engine about the provenance of any resources it requests beyond the accessor's type definition.
|
|
24
25
|
|
|
25
26
|
### Non-goals
|
package/src/client/RootNode.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { RootDefinition } from '../model/RootDefinition.ts';
|
|
|
3
3
|
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
4
4
|
import type { ActiveLanguage, FormLanguage, FormLanguages } from './FormLanguage.ts';
|
|
5
5
|
import type { GeneralChildNode } from './hierarchy.ts';
|
|
6
|
+
import type { AncestorNodeValidationState } from './validation.ts';
|
|
6
7
|
|
|
7
8
|
export interface RootNodeState extends BaseNodeState {
|
|
8
9
|
/**
|
|
@@ -47,6 +48,7 @@ export interface RootNode extends BaseNode {
|
|
|
47
48
|
readonly root: RootNode;
|
|
48
49
|
readonly parent: null;
|
|
49
50
|
readonly currentState: RootNodeState;
|
|
51
|
+
readonly validationState: AncestorNodeValidationState;
|
|
50
52
|
|
|
51
53
|
/**
|
|
52
54
|
* @todo as with {@link RootNodeState.activeLanguage}, this is the most
|
package/src/client/SelectNode.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { AnySelectDefinition } from '../body/control/select/SelectDefinition.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
3
3
|
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
4
4
|
import type { NodeAppearances } from './NodeAppearances.ts';
|
|
5
5
|
import type { RootNode } from './RootNode.ts';
|
|
6
6
|
import type { StringNode } from './StringNode.ts';
|
|
7
7
|
import type { TextRange } from './TextRange.ts';
|
|
8
8
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
9
|
+
import type { LeafNodeValidationState } from './validation.ts';
|
|
9
10
|
|
|
10
11
|
export interface SelectItem {
|
|
11
12
|
get value(): string;
|
|
12
|
-
get label(): TextRange<'label'> | null;
|
|
13
|
+
get label(): TextRange<'item-label'> | null;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export interface SelectNodeState extends BaseNodeState {
|
|
@@ -35,7 +36,7 @@ export interface SelectNodeState extends BaseNodeState {
|
|
|
35
36
|
get value(): readonly SelectItem[];
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
export interface SelectDefinition extends
|
|
39
|
+
export interface SelectDefinition extends LeafNodeDefinition {
|
|
39
40
|
readonly bodyElement: AnySelectDefinition;
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -48,6 +49,7 @@ export interface SelectNode extends BaseNode {
|
|
|
48
49
|
readonly root: RootNode;
|
|
49
50
|
readonly parent: GeneralParentNode;
|
|
50
51
|
readonly currentState: SelectNodeState;
|
|
52
|
+
readonly validationState: LeafNodeValidationState;
|
|
51
53
|
|
|
52
54
|
/**
|
|
53
55
|
* For use by a client to update the selection of a select node where:
|
package/src/client/StringNode.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { InputDefinition } from '../body/control/InputDefinition.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
3
3
|
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
4
4
|
import type { NodeAppearances } from './NodeAppearances.ts';
|
|
5
5
|
import type { RootNode } from './RootNode.ts';
|
|
6
6
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
7
|
+
import type { LeafNodeValidationState } from './validation.ts';
|
|
7
8
|
|
|
8
9
|
export interface StringNodeState extends BaseNodeState {
|
|
9
10
|
get children(): null;
|
|
@@ -18,8 +19,8 @@ export interface StringNodeState extends BaseNodeState {
|
|
|
18
19
|
get value(): string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export interface StringDefinition extends
|
|
22
|
-
readonly bodyElement: InputDefinition
|
|
22
|
+
export interface StringDefinition extends LeafNodeDefinition {
|
|
23
|
+
readonly bodyElement: InputDefinition;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export type StringNodeAppearances = NodeAppearances<StringDefinition>;
|
|
@@ -38,6 +39,7 @@ export interface StringNode extends BaseNode {
|
|
|
38
39
|
readonly root: RootNode;
|
|
39
40
|
readonly parent: GeneralParentNode;
|
|
40
41
|
readonly currentState: StringNodeState;
|
|
42
|
+
readonly validationState: LeafNodeValidationState;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* For use by a client to update the value of a string node.
|
|
@@ -2,6 +2,7 @@ import type { SubtreeDefinition as BaseSubtreeDefinition } from '../model/Subtre
|
|
|
2
2
|
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
3
3
|
import type { RootNode } from './RootNode.ts';
|
|
4
4
|
import type { GeneralChildNode, GeneralParentNode } from './hierarchy.ts';
|
|
5
|
+
import type { AncestorNodeValidationState } from './validation.ts';
|
|
5
6
|
|
|
6
7
|
export interface SubtreeNodeState extends BaseNodeState {
|
|
7
8
|
get label(): null;
|
|
@@ -55,4 +56,5 @@ export interface SubtreeNode extends BaseNode {
|
|
|
55
56
|
readonly root: RootNode;
|
|
56
57
|
readonly parent: GeneralParentNode;
|
|
57
58
|
readonly currentState: SubtreeNodeState;
|
|
59
|
+
readonly validationState: AncestorNodeValidationState;
|
|
58
60
|
}
|