@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
|
@@ -2,7 +2,8 @@ import { identity } from '@getodk/common/lib/identity.ts';
|
|
|
2
2
|
import type { Accessor } from 'solid-js';
|
|
3
3
|
import type { InputDefinition } from '../body/control/InputDefinition.ts';
|
|
4
4
|
import type { StringNode, StringNodeAppearances } from '../client/StringNode.ts';
|
|
5
|
-
import type { TextRange } from '../
|
|
5
|
+
import type { TextRange } from '../client/TextRange.ts';
|
|
6
|
+
import type { AnyViolation, LeafNodeValidationState } from '../client/validation.ts';
|
|
6
7
|
import { createValueState } from '../lib/reactivity/createValueState.ts';
|
|
7
8
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
8
9
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -11,17 +12,20 @@ import { createSharedNodeState } from '../lib/reactivity/node-state/createShared
|
|
|
11
12
|
import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
12
13
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
13
14
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
14
|
-
import type {
|
|
15
|
+
import type { SharedValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
16
|
+
import { createValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
17
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
15
18
|
import type { Root } from './Root.ts';
|
|
16
19
|
import type { DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
|
|
17
20
|
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
18
21
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
19
22
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
20
23
|
import type { SubscribableDependency } from './internal-api/SubscribableDependency.ts';
|
|
24
|
+
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
21
25
|
import type { ValueContext } from './internal-api/ValueContext.ts';
|
|
22
26
|
|
|
23
|
-
export interface StringFieldDefinition extends
|
|
24
|
-
readonly bodyElement: InputDefinition
|
|
27
|
+
export interface StringFieldDefinition extends LeafNodeDefinition {
|
|
28
|
+
readonly bodyElement: InputDefinition;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
interface StringFieldStateSpec extends DescendantNodeStateSpec<string> {
|
|
@@ -34,8 +38,14 @@ interface StringFieldStateSpec extends DescendantNodeStateSpec<string> {
|
|
|
34
38
|
|
|
35
39
|
export class StringField
|
|
36
40
|
extends DescendantNode<StringFieldDefinition, StringFieldStateSpec, null>
|
|
37
|
-
implements
|
|
41
|
+
implements
|
|
42
|
+
StringNode,
|
|
43
|
+
EvaluationContext,
|
|
44
|
+
SubscribableDependency,
|
|
45
|
+
ValidationContext,
|
|
46
|
+
ValueContext<string>
|
|
38
47
|
{
|
|
48
|
+
private readonly validation: SharedValidationState;
|
|
39
49
|
protected readonly state: SharedNodeState<StringFieldStateSpec>;
|
|
40
50
|
|
|
41
51
|
// InstanceNode
|
|
@@ -46,6 +56,10 @@ export class StringField
|
|
|
46
56
|
readonly appearances: StringNodeAppearances;
|
|
47
57
|
readonly currentState: CurrentState<StringFieldStateSpec>;
|
|
48
58
|
|
|
59
|
+
get validationState(): LeafNodeValidationState {
|
|
60
|
+
return this.validation.currentState;
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
// ValueContext
|
|
50
64
|
readonly encodeValue = identity<string>;
|
|
51
65
|
|
|
@@ -54,7 +68,11 @@ export class StringField
|
|
|
54
68
|
constructor(parent: GeneralParentNode, definition: StringFieldDefinition) {
|
|
55
69
|
super(parent, definition);
|
|
56
70
|
|
|
57
|
-
this.appearances =
|
|
71
|
+
this.appearances = definition.bodyElement.appearances;
|
|
72
|
+
|
|
73
|
+
const sharedStateOptions = {
|
|
74
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
75
|
+
};
|
|
58
76
|
|
|
59
77
|
const state = createSharedNodeState(
|
|
60
78
|
this.scope,
|
|
@@ -70,14 +88,22 @@ export class StringField
|
|
|
70
88
|
valueOptions: null,
|
|
71
89
|
value: createValueState(this),
|
|
72
90
|
},
|
|
73
|
-
|
|
74
|
-
clientStateFactory: this.engineConfig.stateFactory,
|
|
75
|
-
}
|
|
91
|
+
sharedStateOptions
|
|
76
92
|
);
|
|
77
93
|
|
|
78
94
|
this.state = state;
|
|
79
95
|
this.engineState = state.engineState;
|
|
80
96
|
this.currentState = state.currentState;
|
|
97
|
+
this.validation = createValidationState(this, sharedStateOptions);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getViolation(): AnyViolation | null {
|
|
101
|
+
return this.validation.engineState.violation;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ValidationContext
|
|
105
|
+
isBlank(): boolean {
|
|
106
|
+
return this.engineState.value === '';
|
|
81
107
|
}
|
|
82
108
|
|
|
83
109
|
// InstanceNode
|
package/src/instance/Subtree.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Accessor } from 'solid-js';
|
|
2
2
|
import type { SubtreeDefinition, SubtreeNode } from '../client/SubtreeNode.ts';
|
|
3
|
+
import type { AncestorNodeValidationState } from '../client/validation.ts';
|
|
3
4
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
4
5
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
5
6
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -8,6 +9,7 @@ import type { CurrentState } from '../lib/reactivity/node-state/createCurrentSta
|
|
|
8
9
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
9
10
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
10
11
|
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
12
|
+
import { createAggregatedViolations } from '../lib/reactivity/validation/createAggregatedViolations.ts';
|
|
11
13
|
import type { DescendantNodeSharedStateSpec } from './abstract/DescendantNode.ts';
|
|
12
14
|
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
13
15
|
import { buildChildren } from './children.ts';
|
|
@@ -38,6 +40,7 @@ export class Subtree
|
|
|
38
40
|
readonly nodeType = 'subtree';
|
|
39
41
|
readonly appearances = null;
|
|
40
42
|
readonly currentState: MaterializedChildren<CurrentState<SubtreeStateSpec>, GeneralChildNode>;
|
|
43
|
+
readonly validationState: AncestorNodeValidationState;
|
|
41
44
|
|
|
42
45
|
constructor(parent: GeneralParentNode, definition: SubtreeDefinition) {
|
|
43
46
|
super(parent, definition);
|
|
@@ -46,6 +49,10 @@ export class Subtree
|
|
|
46
49
|
|
|
47
50
|
this.childrenState = childrenState;
|
|
48
51
|
|
|
52
|
+
const sharedStateOptions = {
|
|
53
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
54
|
+
};
|
|
55
|
+
|
|
49
56
|
const state = createSharedNodeState(
|
|
50
57
|
this.scope,
|
|
51
58
|
{
|
|
@@ -60,9 +67,7 @@ export class Subtree
|
|
|
60
67
|
valueOptions: null,
|
|
61
68
|
value: null,
|
|
62
69
|
},
|
|
63
|
-
|
|
64
|
-
clientStateFactory: this.engineConfig.stateFactory,
|
|
65
|
-
}
|
|
70
|
+
sharedStateOptions
|
|
66
71
|
);
|
|
67
72
|
|
|
68
73
|
this.state = state;
|
|
@@ -74,6 +79,7 @@ export class Subtree
|
|
|
74
79
|
);
|
|
75
80
|
|
|
76
81
|
childrenState.setChildren(buildChildren(this));
|
|
82
|
+
this.validationState = createAggregatedViolations(this, sharedStateOptions);
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
getChildren(): readonly GeneralChildNode[] {
|
|
@@ -4,15 +4,14 @@ import type { BaseNode } from '../../client/BaseNode.ts';
|
|
|
4
4
|
import { createComputedExpression } from '../../lib/reactivity/createComputedExpression.ts';
|
|
5
5
|
import type { ReactiveScope } from '../../lib/reactivity/scope.ts';
|
|
6
6
|
import type { AnyDescendantNodeDefinition } from '../../model/DescendentNodeDefinition.ts';
|
|
7
|
+
import type { LeafNodeDefinition } from '../../model/LeafNodeDefinition.ts';
|
|
7
8
|
import type { AnyNodeDefinition } from '../../model/NodeDefinition.ts';
|
|
8
9
|
import type { RepeatInstanceDefinition } from '../../model/RepeatInstanceDefinition.ts';
|
|
9
|
-
import type {
|
|
10
|
-
import type { RepeatInstance } from '../RepeatInstance.ts';
|
|
11
|
-
import type { RepeatRange } from '../RepeatRange.ts';
|
|
12
|
-
import type { Root } from '../Root.ts';
|
|
13
|
-
import type { AnyChildNode, GeneralParentNode } from '../hierarchy.ts';
|
|
10
|
+
import type { AnyChildNode, GeneralParentNode, RepeatRange } from '../hierarchy.ts';
|
|
14
11
|
import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
|
|
15
12
|
import type { SubscribableDependency } from '../internal-api/SubscribableDependency.ts';
|
|
13
|
+
import type { RepeatInstance } from '../repeat/RepeatInstance.ts';
|
|
14
|
+
import type { Root } from '../Root.ts';
|
|
16
15
|
import type { InstanceNodeStateSpec } from './InstanceNode.ts';
|
|
17
16
|
import { InstanceNode } from './InstanceNode.ts';
|
|
18
17
|
|
|
@@ -37,7 +36,7 @@ export type DescendantNodeDefinition = Extract<
|
|
|
37
36
|
|
|
38
37
|
// prettier-ignore
|
|
39
38
|
export type DescendantNodeParent<Definition extends DescendantNodeDefinition> =
|
|
40
|
-
Definition extends
|
|
39
|
+
Definition extends LeafNodeDefinition
|
|
41
40
|
? GeneralParentNode
|
|
42
41
|
: Definition extends RepeatInstanceDefinition
|
|
43
42
|
? RepeatRange
|
|
@@ -96,7 +95,7 @@ export abstract class DescendantNode<
|
|
|
96
95
|
return this.isSelfRelevant();
|
|
97
96
|
};
|
|
98
97
|
|
|
99
|
-
|
|
98
|
+
readonly isRequired: Accessor<boolean>;
|
|
100
99
|
|
|
101
100
|
readonly root: Root;
|
|
102
101
|
readonly evaluator: XFormsXPathEvaluator;
|
|
@@ -3,6 +3,7 @@ import type { Accessor, Signal } from 'solid-js';
|
|
|
3
3
|
import type { BaseNode } from '../../client/BaseNode.ts';
|
|
4
4
|
import type { NodeAppearances } from '../../client/NodeAppearances.ts';
|
|
5
5
|
import type { InstanceNodeType } from '../../client/node-types.ts';
|
|
6
|
+
import type { NodeValidationState } from '../../client/validation.ts';
|
|
6
7
|
import type { TextRange } from '../../index.ts';
|
|
7
8
|
import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
8
9
|
import type { CurrentState } from '../../lib/reactivity/node-state/createCurrentState.ts';
|
|
@@ -117,6 +118,8 @@ export abstract class InstanceNode<
|
|
|
117
118
|
|
|
118
119
|
abstract readonly currentState: InstanceNodeCurrentState<Spec, Child>;
|
|
119
120
|
|
|
121
|
+
abstract readonly validationState: NodeValidationState;
|
|
122
|
+
|
|
120
123
|
// BaseNode: structural
|
|
121
124
|
abstract readonly root: Root;
|
|
122
125
|
|
|
@@ -230,11 +233,22 @@ export abstract class InstanceNode<
|
|
|
230
233
|
subscribe(): void {
|
|
231
234
|
const { engineState } = this;
|
|
232
235
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
// Note: a previous iteration of this default implementation guarded these
|
|
237
|
+
// reactive reads behind a relevance check. This caused timing issues for
|
|
238
|
+
// downstream computations referencing a node whose relevance changes.
|
|
239
|
+
//
|
|
240
|
+
// That original guard was intended to reduce excessive redundant
|
|
241
|
+
// computations, and so removing it is intended as a naive compromise of
|
|
242
|
+
// performance for obvious correctness improvements.
|
|
243
|
+
//
|
|
244
|
+
// This compromise, like many others, will be moot if/when we decide to
|
|
245
|
+
// decouple XPath evaluation from the browser/XML DOM: reactive
|
|
246
|
+
// subscriptions would be established by evaluation of the expressions
|
|
247
|
+
// themselves (as they traverse instance state and access values), rather
|
|
248
|
+
// than this safer/less focused approach.
|
|
249
|
+
engineState.reference;
|
|
250
|
+
engineState.relevant;
|
|
251
|
+
engineState.children;
|
|
252
|
+
engineState.value;
|
|
239
253
|
}
|
|
240
254
|
}
|
package/src/instance/children.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
|
|
2
2
|
import type { GroupDefinition } from '../client/GroupNode.ts';
|
|
3
3
|
import type { SubtreeDefinition } from '../client/SubtreeNode.ts';
|
|
4
|
+
import type { LeafNodeDefinition } from '../model/LeafNodeDefinition.ts';
|
|
4
5
|
import type { SubtreeDefinition as ModelSubtreeDefinition } from '../model/SubtreeDefinition.ts';
|
|
6
|
+
import { NoteNodeDefinition } from '../parse/NoteNodeDefinition.ts';
|
|
5
7
|
import { Group } from './Group.ts';
|
|
6
|
-
import {
|
|
8
|
+
import type { GeneralChildNode, GeneralParentNode } from './hierarchy.ts';
|
|
9
|
+
import { ModelValue, type ModelValueDefinition } from './ModelValue.ts';
|
|
10
|
+
import { Note } from './Note.ts';
|
|
11
|
+
import { RepeatRangeControlled } from './repeat/RepeatRangeControlled.ts';
|
|
12
|
+
import { RepeatRangeUncontrolled } from './repeat/RepeatRangeUncontrolled.ts';
|
|
7
13
|
import type { SelectFieldDefinition } from './SelectField.ts';
|
|
8
14
|
import { SelectField } from './SelectField.ts';
|
|
9
15
|
import type { StringFieldDefinition } from './StringField.ts';
|
|
10
16
|
import { StringField } from './StringField.ts';
|
|
11
17
|
import { Subtree } from './Subtree.ts';
|
|
12
|
-
import type { GeneralChildNode, GeneralParentNode } from './hierarchy.ts';
|
|
13
18
|
|
|
14
19
|
const isSubtreeDefinition = (
|
|
15
20
|
definition: ModelSubtreeDefinition
|
|
@@ -17,6 +22,22 @@ const isSubtreeDefinition = (
|
|
|
17
22
|
return definition.bodyElement == null;
|
|
18
23
|
};
|
|
19
24
|
|
|
25
|
+
type ControlNodeDefinition = SelectFieldDefinition | StringFieldDefinition;
|
|
26
|
+
|
|
27
|
+
type AnyLeafNodeDefinition = ControlNodeDefinition | ModelValueDefinition;
|
|
28
|
+
|
|
29
|
+
const isModelValueDefinition = (
|
|
30
|
+
definition: LeafNodeDefinition
|
|
31
|
+
): definition is ModelValueDefinition => {
|
|
32
|
+
return definition.bodyElement == null;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const isStringFieldDefinition = (
|
|
36
|
+
definition: ControlNodeDefinition
|
|
37
|
+
): definition is StringFieldDefinition => {
|
|
38
|
+
return definition.bodyElement.type === 'input';
|
|
39
|
+
};
|
|
40
|
+
|
|
20
41
|
export const buildChildren = (parent: GeneralParentNode): GeneralChildNode[] => {
|
|
21
42
|
const { children } = parent.definition;
|
|
22
43
|
|
|
@@ -34,24 +55,30 @@ export const buildChildren = (parent: GeneralParentNode): GeneralChildNode[] =>
|
|
|
34
55
|
}
|
|
35
56
|
|
|
36
57
|
case 'repeat-range': {
|
|
37
|
-
|
|
58
|
+
if (child.isControlled()) {
|
|
59
|
+
return new RepeatRangeControlled(parent, child);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return new RepeatRangeUncontrolled(parent, child);
|
|
38
63
|
}
|
|
39
64
|
|
|
40
|
-
case '
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
case 'select':
|
|
45
|
-
case 'select1':
|
|
46
|
-
return new SelectField(parent, child as SelectFieldDefinition);
|
|
65
|
+
case 'leaf-node': {
|
|
66
|
+
if (child instanceof NoteNodeDefinition) {
|
|
67
|
+
return new Note(parent, child);
|
|
68
|
+
}
|
|
47
69
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return new StringField(parent, child as StringFieldDefinition);
|
|
70
|
+
// More specific type helps with narrowing below
|
|
71
|
+
const leafChild: AnyLeafNodeDefinition = child;
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
|
|
73
|
+
if (isModelValueDefinition(leafChild)) {
|
|
74
|
+
return new ModelValue(parent, leafChild);
|
|
54
75
|
}
|
|
76
|
+
|
|
77
|
+
if (isStringFieldDefinition(leafChild)) {
|
|
78
|
+
return new StringField(parent, leafChild);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return new SelectField(parent, leafChild);
|
|
55
82
|
}
|
|
56
83
|
|
|
57
84
|
default: {
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { Group } from './Group.ts';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { ModelValue } from './ModelValue.ts';
|
|
3
|
+
import type { Note } from './Note.ts';
|
|
4
|
+
import type { RepeatInstance } from './repeat/RepeatInstance.ts';
|
|
5
|
+
import type { RepeatRangeControlled } from './repeat/RepeatRangeControlled.ts';
|
|
6
|
+
import type { RepeatRangeUncontrolled } from './repeat/RepeatRangeUncontrolled.ts';
|
|
4
7
|
import type { Root } from './Root.ts';
|
|
5
8
|
import type { SelectField } from './SelectField.ts';
|
|
6
9
|
import type { StringField } from './StringField.ts';
|
|
7
10
|
import type { Subtree } from './Subtree.ts';
|
|
8
11
|
|
|
12
|
+
export type RepeatRange = RepeatRangeControlled | RepeatRangeUncontrolled;
|
|
13
|
+
|
|
9
14
|
// prettier-ignore
|
|
10
15
|
export type AnyNode =
|
|
11
16
|
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
|
|
@@ -14,6 +19,8 @@ export type AnyNode =
|
|
|
14
19
|
| Subtree
|
|
15
20
|
| RepeatRange
|
|
16
21
|
| RepeatInstance
|
|
22
|
+
| Note
|
|
23
|
+
| ModelValue
|
|
17
24
|
| StringField
|
|
18
25
|
| SelectField;
|
|
19
26
|
|
|
@@ -41,6 +48,8 @@ export type AnyChildNode =
|
|
|
41
48
|
| Subtree
|
|
42
49
|
| RepeatRange
|
|
43
50
|
| RepeatInstance
|
|
51
|
+
| ModelValue
|
|
52
|
+
| Note
|
|
44
53
|
| StringField
|
|
45
54
|
| SelectField;
|
|
46
55
|
|
|
@@ -50,5 +59,15 @@ export type GeneralChildNode =
|
|
|
50
59
|
| Group
|
|
51
60
|
| Subtree
|
|
52
61
|
| RepeatRange
|
|
62
|
+
| ModelValue
|
|
63
|
+
| Note
|
|
64
|
+
| StringField
|
|
65
|
+
| SelectField;
|
|
66
|
+
|
|
67
|
+
// prettier-ignore
|
|
68
|
+
export type AnyValueNode =
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
|
|
70
|
+
| ModelValue
|
|
71
|
+
| Note
|
|
53
72
|
| StringField
|
|
54
73
|
| SelectField;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BindComputation } from '../../model/BindComputation.ts';
|
|
2
|
+
import type { MessageDefinition } from '../../parse/text/MessageDefinition.ts';
|
|
3
|
+
import type { EvaluationContext } from './EvaluationContext.ts';
|
|
4
|
+
import type { SubscribableDependency } from './SubscribableDependency.ts';
|
|
5
|
+
|
|
6
|
+
interface ValidationContextDefinitionBind {
|
|
7
|
+
readonly constraint: BindComputation<'constraint'>;
|
|
8
|
+
readonly constraintMsg: MessageDefinition<'constraintMsg'> | null;
|
|
9
|
+
readonly required: BindComputation<'required'>;
|
|
10
|
+
readonly requiredMsg: MessageDefinition<'requiredMsg'> | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ValidationContextDefinition {
|
|
14
|
+
readonly bind: ValidationContextDefinitionBind;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ValidationContext extends EvaluationContext, SubscribableDependency {
|
|
18
|
+
readonly definition: ValidationContextDefinition;
|
|
19
|
+
|
|
20
|
+
isRelevant(): boolean;
|
|
21
|
+
isRequired(): boolean;
|
|
22
|
+
isBlank(): boolean;
|
|
23
|
+
}
|