@getodk/xforms-engine 0.16.0 → 0.16.1
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/client/AttributeNode.d.ts +4 -3
- package/dist/index.js +272 -211
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +11 -23
- package/dist/instance/Group.d.ts +3 -0
- package/dist/instance/InputControl.d.ts +3 -0
- package/dist/instance/ModelValue.d.ts +4 -0
- package/dist/instance/Note.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +3 -0
- package/dist/instance/RangeControl.d.ts +4 -0
- package/dist/instance/RankControl.d.ts +5 -1
- package/dist/instance/Root.d.ts +3 -0
- package/dist/instance/SelectControl.d.ts +5 -1
- package/dist/instance/TriggerControl.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +3 -0
- package/dist/instance/abstract/DescendantNode.d.ts +5 -4
- package/dist/instance/abstract/InstanceNode.d.ts +4 -3
- package/dist/instance/hierarchy.d.ts +2 -1
- package/dist/instance/repeat/RepeatInstance.d.ts +2 -0
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +1 -1
- package/dist/integration/xpath/adapter/kind.d.ts +5 -3
- package/dist/integration/xpath/adapter/traversal.d.ts +3 -3
- package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +1 -0
- package/dist/parse/model/AttributeDefinition.d.ts +2 -0
- package/dist/solid.js +272 -211
- package/dist/solid.js.map +1 -1
- package/package.json +2 -2
- package/src/client/AttributeNode.ts +4 -3
- package/src/instance/Attribute.ts +38 -54
- package/src/instance/Group.ts +12 -4
- package/src/instance/InputControl.ts +12 -4
- package/src/instance/ModelValue.ts +13 -4
- package/src/instance/Note.ts +13 -4
- package/src/instance/PrimaryInstance.ts +12 -4
- package/src/instance/RangeControl.ts +13 -4
- package/src/instance/RankControl.ts +14 -5
- package/src/instance/Root.ts +12 -4
- package/src/instance/SelectControl.ts +14 -5
- package/src/instance/TriggerControl.ts +13 -4
- package/src/instance/UploadControl.ts +13 -3
- package/src/instance/abstract/DescendantNode.ts +4 -3
- package/src/instance/abstract/InstanceNode.ts +5 -3
- package/src/instance/attachments/buildAttributes.ts +5 -1
- package/src/instance/children/childrenInitOptions.ts +2 -1
- package/src/instance/hierarchy.ts +2 -0
- package/src/instance/repeat/RepeatInstance.ts +11 -3
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +1 -0
- package/src/integration/xpath/adapter/engineDOMAdapter.ts +2 -2
- package/src/integration/xpath/adapter/kind.ts +6 -1
- package/src/integration/xpath/adapter/names.ts +1 -0
- package/src/integration/xpath/adapter/traversal.ts +5 -6
- package/src/integration/xpath/static-dom/StaticAttribute.ts +1 -0
- package/src/lib/reactivity/createInstanceValueState.ts +29 -3
- package/src/parse/model/AttributeDefinition.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getodk/xforms-engine",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "XForms engine for ODK Web Forms",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@babel/core": "^7.28.5",
|
|
65
65
|
"@getodk/tree-sitter-xpath": "0.2.2",
|
|
66
|
-
"@getodk/xpath": "0.9.
|
|
66
|
+
"@getodk/xpath": "0.9.2",
|
|
67
67
|
"@playwright/test": "^1.57.0",
|
|
68
68
|
"@types/papaparse": "^5.5.0",
|
|
69
69
|
"@vitest/browser": "^3.2.4",
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Root } from '../instance/Root.ts';
|
|
2
2
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
3
|
+
import type { BaseNode, BaseNodeState } from './BaseNode.ts';
|
|
3
4
|
import type { OpaqueReactiveObjectFactory } from './OpaqueReactiveObjectFactory.ts';
|
|
4
5
|
import type { InstanceState } from './serialization/InstanceState.ts';
|
|
5
6
|
|
|
6
|
-
export interface AttributeNodeState {
|
|
7
|
+
export interface AttributeNodeState extends BaseNodeState {
|
|
7
8
|
get value(): string;
|
|
8
9
|
get relevant(): boolean;
|
|
9
10
|
}
|
|
@@ -11,7 +12,7 @@ export interface AttributeNodeState {
|
|
|
11
12
|
/**
|
|
12
13
|
* Base interface for common/shared aspects of attributes.
|
|
13
14
|
*/
|
|
14
|
-
export interface AttributeNode {
|
|
15
|
+
export interface AttributeNode extends BaseNode {
|
|
15
16
|
/**
|
|
16
17
|
* Specifies the node's general type. This can be useful for narrowing types,
|
|
17
18
|
* e.g. those of children.
|
|
@@ -31,7 +32,7 @@ export interface AttributeNode {
|
|
|
31
32
|
*/
|
|
32
33
|
readonly root: Root;
|
|
33
34
|
|
|
34
|
-
readonly
|
|
35
|
+
readonly parent: unknown;
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Each node provides a discrete object representing the stateful aspects of
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
2
2
|
import type { Accessor } from 'solid-js';
|
|
3
3
|
import type { AttributeNode } from '../client/AttributeNode.ts';
|
|
4
|
-
import type {
|
|
4
|
+
import type { InstanceState, NullValidationState } from '../client/index.ts';
|
|
5
5
|
import type { XFormsXPathAttribute } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
6
|
-
import type { EngineXPathEvaluator } from '../integration/xpath/EngineXPathEvaluator.ts';
|
|
7
6
|
import type { StaticAttribute } from '../integration/xpath/static-dom/StaticAttribute.ts';
|
|
8
7
|
import { createAttributeNodeInstanceState } from '../lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts';
|
|
9
8
|
import {
|
|
@@ -12,6 +11,10 @@ import {
|
|
|
12
11
|
type RuntimeValue,
|
|
13
12
|
} from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
13
|
import type { RuntimeValueSetter, RuntimeValueState } from '../lib/codecs/ValueCodec.ts';
|
|
14
|
+
import {
|
|
15
|
+
createAttributeState,
|
|
16
|
+
type AttributeState,
|
|
17
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
15
18
|
import { createInstanceValueState } from '../lib/reactivity/createInstanceValueState.ts';
|
|
16
19
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
20
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -19,31 +22,32 @@ import {
|
|
|
19
22
|
createSharedNodeState,
|
|
20
23
|
type SharedNodeState,
|
|
21
24
|
} from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
22
|
-
import type { ReactiveScope } from '../lib/reactivity/scope.ts';
|
|
23
25
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
24
26
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
25
|
-
import
|
|
27
|
+
import { DescendantNode, type DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
|
|
28
|
+
import type { AnyNode } from './hierarchy.ts';
|
|
26
29
|
import type { AttributeContext } from './internal-api/AttributeContext.ts';
|
|
27
|
-
import type { InstanceConfig } from './internal-api/InstanceConfig.ts';
|
|
28
30
|
import type { DecodeInstanceValue } from './internal-api/InstanceValueContext.ts';
|
|
29
31
|
import type { ClientReactiveSerializableAttributeNode } from './internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
|
|
30
|
-
import type { PrimaryInstance } from './PrimaryInstance.ts';
|
|
31
32
|
import type { Root } from './Root.ts';
|
|
32
33
|
|
|
33
|
-
export interface AttributeStateSpec {
|
|
34
|
+
export interface AttributeStateSpec extends DescendantNodeStateSpec<string> {
|
|
35
|
+
readonly children: null;
|
|
36
|
+
readonly attributes: Accessor<Attribute[]>;
|
|
34
37
|
readonly value: SimpleAtomicState<string>;
|
|
35
38
|
readonly instanceValue: Accessor<string>;
|
|
36
39
|
readonly relevant: Accessor<boolean>;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export class Attribute
|
|
43
|
+
extends DescendantNode<AttributeDefinition, AttributeStateSpec, AnyNode, null>
|
|
40
44
|
implements
|
|
41
45
|
AttributeNode,
|
|
42
46
|
ClientReactiveSerializableAttributeNode,
|
|
43
47
|
AttributeContext,
|
|
44
48
|
XFormsXPathAttribute
|
|
45
49
|
{
|
|
46
|
-
readonly [XPathNodeKindKey] = 'attribute';
|
|
50
|
+
override readonly [XPathNodeKindKey] = 'attribute';
|
|
47
51
|
|
|
48
52
|
protected readonly state: SharedNodeState<AttributeStateSpec>;
|
|
49
53
|
protected readonly engineState: EngineState<AttributeStateSpec>;
|
|
@@ -62,60 +66,30 @@ export class Attribute
|
|
|
62
66
|
protected readonly getInstanceValue: Accessor<string>;
|
|
63
67
|
protected readonly valueState: RuntimeValueState<RuntimeValue<'string'>>;
|
|
64
68
|
protected readonly setValueState: RuntimeValueSetter<RuntimeInputValue<'string'>>;
|
|
65
|
-
readonly
|
|
66
|
-
readonly getActiveLanguage: Accessor<ActiveLanguage>;
|
|
67
|
-
readonly contextNode: AnyNode;
|
|
68
|
-
readonly scope: ReactiveScope;
|
|
69
|
-
readonly rootDocument: PrimaryInstance;
|
|
70
|
-
readonly instanceConfig: InstanceConfig;
|
|
71
|
-
|
|
72
|
-
readonly root: Root;
|
|
69
|
+
readonly attributeState: AttributeState;
|
|
73
70
|
|
|
74
|
-
readonly
|
|
75
|
-
return this.owner.isRelevant();
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
readonly isAttached: Accessor<boolean> = () => {
|
|
71
|
+
override readonly isAttached: Accessor<boolean> = () => {
|
|
79
72
|
return this.owner.isAttached();
|
|
80
73
|
};
|
|
81
74
|
|
|
82
|
-
readonly
|
|
83
|
-
return true;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
readonly hasReadonlyAncestor: Accessor<boolean> = () => {
|
|
87
|
-
const { owner } = this;
|
|
88
|
-
return owner.hasReadonlyAncestor() || owner.isReadonly();
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
readonly hasNonRelevantAncestor: Accessor<boolean> = () => {
|
|
92
|
-
const { owner } = this;
|
|
93
|
-
return owner.hasNonRelevantAncestor() || !owner.isRelevant();
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
readonly contextReference = (): string => {
|
|
97
|
-
return this.owner.contextReference() + '/@' + this.definition.qualifiedName.getPrefixedName();
|
|
98
|
-
};
|
|
75
|
+
override readonly getXPathValue: () => string;
|
|
99
76
|
|
|
100
77
|
constructor(
|
|
101
78
|
readonly owner: AnyNode,
|
|
102
|
-
|
|
103
|
-
readonly instanceNode: StaticAttribute
|
|
79
|
+
definition: AttributeDefinition,
|
|
80
|
+
override readonly instanceNode: StaticAttribute
|
|
104
81
|
) {
|
|
105
|
-
const
|
|
82
|
+
const computeReference = () => {
|
|
83
|
+
return `${this.owner.contextReference()}/@${this.definition.qualifiedName.getPrefixedName()}`;
|
|
84
|
+
};
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
this.scope = owner.scope;
|
|
109
|
-
this.rootDocument = owner.rootDocument;
|
|
86
|
+
super(owner, instanceNode, definition, { computeReference });
|
|
110
87
|
|
|
111
|
-
|
|
112
|
-
this.instanceConfig = owner.instanceConfig;
|
|
88
|
+
const codec = getSharedValueCodec('string');
|
|
113
89
|
|
|
114
|
-
this.getActiveLanguage = owner.getActiveLanguage;
|
|
115
90
|
this.validationState = { violations: [] };
|
|
116
91
|
|
|
117
92
|
this.valueType = 'string';
|
|
118
|
-
this.evaluator = owner.evaluator;
|
|
119
93
|
this.decodeInstanceValue = codec.decodeInstanceValue;
|
|
120
94
|
|
|
121
95
|
const instanceValueState = createInstanceValueState(this);
|
|
@@ -134,6 +108,15 @@ export class Attribute
|
|
|
134
108
|
value: this.valueState,
|
|
135
109
|
instanceValue: this.getInstanceValue,
|
|
136
110
|
relevant: this.owner.isRelevant,
|
|
111
|
+
|
|
112
|
+
readonly: () => true,
|
|
113
|
+
reference: this.contextReference,
|
|
114
|
+
required: () => false,
|
|
115
|
+
children: null,
|
|
116
|
+
label: () => null,
|
|
117
|
+
hint: () => null,
|
|
118
|
+
attributes: () => [],
|
|
119
|
+
valueOptions: () => [],
|
|
137
120
|
},
|
|
138
121
|
this.instanceConfig
|
|
139
122
|
);
|
|
@@ -142,6 +125,11 @@ export class Attribute
|
|
|
142
125
|
this.engineState = state.engineState;
|
|
143
126
|
this.currentState = state.currentState;
|
|
144
127
|
this.instanceState = createAttributeNodeInstanceState(this);
|
|
128
|
+
this.attributeState = createAttributeState(this.scope);
|
|
129
|
+
|
|
130
|
+
this.getXPathValue = () => {
|
|
131
|
+
return this.getInstanceValue();
|
|
132
|
+
};
|
|
145
133
|
}
|
|
146
134
|
|
|
147
135
|
setValue(value: string): Root {
|
|
@@ -150,15 +138,11 @@ export class Attribute
|
|
|
150
138
|
return this.root;
|
|
151
139
|
}
|
|
152
140
|
|
|
153
|
-
|
|
141
|
+
override getAttributes(): readonly Attribute[] {
|
|
154
142
|
return [];
|
|
155
143
|
}
|
|
156
144
|
|
|
157
|
-
|
|
145
|
+
getChildren(): readonly [] {
|
|
158
146
|
return [];
|
|
159
147
|
}
|
|
160
|
-
|
|
161
|
-
getXPathValue(): string {
|
|
162
|
-
return '';
|
|
163
|
-
}
|
|
164
148
|
}
|
package/src/instance/Group.ts
CHANGED
|
@@ -8,7 +8,10 @@ import type { AncestorNodeValidationState } from '../client/validation.ts';
|
|
|
8
8
|
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
9
9
|
import type { StaticElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
10
10
|
import { createParentNodeInstanceState } from '../lib/client-reactivity/instance-state/createParentNodeInstanceState.ts';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
createAttributeState,
|
|
13
|
+
type AttributeState,
|
|
14
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
12
15
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
13
16
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
14
17
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -53,6 +56,7 @@ export class Group
|
|
|
53
56
|
// InstanceNode
|
|
54
57
|
protected readonly state: SharedNodeState<GroupStateSpec>;
|
|
55
58
|
protected override engineState: EngineState<GroupStateSpec>;
|
|
59
|
+
readonly attributeState: AttributeState;
|
|
56
60
|
|
|
57
61
|
// GroupNode
|
|
58
62
|
readonly nodeType = 'group';
|
|
@@ -72,7 +76,7 @@ export class Group
|
|
|
72
76
|
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
73
77
|
|
|
74
78
|
const childrenState = createChildrenState<Group, GeneralChildNode>(this);
|
|
75
|
-
|
|
79
|
+
this.attributeState = createAttributeState(this.scope);
|
|
76
80
|
|
|
77
81
|
this.childrenState = childrenState;
|
|
78
82
|
|
|
@@ -87,7 +91,7 @@ export class Group
|
|
|
87
91
|
label: createNodeLabel(this, definition),
|
|
88
92
|
hint: null,
|
|
89
93
|
children: childrenState.childIds,
|
|
90
|
-
attributes: attributeState.getAttributes,
|
|
94
|
+
attributes: this.attributeState.getAttributes,
|
|
91
95
|
valueOptions: null,
|
|
92
96
|
value: null,
|
|
93
97
|
},
|
|
@@ -103,7 +107,7 @@ export class Group
|
|
|
103
107
|
);
|
|
104
108
|
|
|
105
109
|
childrenState.setChildren(buildChildren(this));
|
|
106
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
110
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
107
111
|
this.validationState = createAggregatedViolations(this, this.instanceConfig);
|
|
108
112
|
this.instanceState = createParentNodeInstanceState(this);
|
|
109
113
|
}
|
|
@@ -111,4 +115,8 @@ export class Group
|
|
|
111
115
|
getChildren(): readonly GeneralChildNode[] {
|
|
112
116
|
return this.childrenState.getChildren();
|
|
113
117
|
}
|
|
118
|
+
|
|
119
|
+
override getAttributes(): readonly Attribute[] {
|
|
120
|
+
return this.attributeState.getAttributes();
|
|
121
|
+
}
|
|
114
122
|
}
|
|
@@ -13,7 +13,10 @@ import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPat
|
|
|
13
13
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
14
14
|
import type { RuntimeInputValue, RuntimeValue } from '../lib/codecs/getSharedValueCodec.ts';
|
|
15
15
|
import { getSharedValueCodec } from '../lib/codecs/getSharedValueCodec.ts';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
createAttributeState,
|
|
18
|
+
type AttributeState,
|
|
19
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
17
20
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
18
21
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
19
22
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -104,6 +107,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
104
107
|
// InstanceNode
|
|
105
108
|
protected readonly state: SharedNodeState<InputControlStateSpec<V>>;
|
|
106
109
|
protected readonly engineState: EngineState<InputControlStateSpec<V>>;
|
|
110
|
+
readonly attributeState: AttributeState;
|
|
107
111
|
|
|
108
112
|
// InputNode
|
|
109
113
|
readonly nodeType = 'input';
|
|
@@ -122,7 +126,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
122
126
|
|
|
123
127
|
this.appearances = definition.bodyElement.appearances;
|
|
124
128
|
this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
|
|
125
|
-
|
|
129
|
+
this.attributeState = createAttributeState(this.scope);
|
|
126
130
|
|
|
127
131
|
const state = createSharedNodeState(
|
|
128
132
|
this.scope,
|
|
@@ -135,7 +139,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
135
139
|
label: createNodeLabel(this, definition),
|
|
136
140
|
hint: createFieldHint(this, definition),
|
|
137
141
|
children: null,
|
|
138
|
-
attributes: attributeState.getAttributes,
|
|
142
|
+
attributes: this.attributeState.getAttributes,
|
|
139
143
|
valueOptions: null,
|
|
140
144
|
value: this.valueState,
|
|
141
145
|
instanceValue: this.getInstanceValue,
|
|
@@ -143,7 +147,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
143
147
|
this.instanceConfig
|
|
144
148
|
);
|
|
145
149
|
|
|
146
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
150
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
147
151
|
|
|
148
152
|
this.state = state;
|
|
149
153
|
this.engineState = state.engineState;
|
|
@@ -155,6 +159,10 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
155
159
|
|
|
156
160
|
return this.root;
|
|
157
161
|
}
|
|
162
|
+
|
|
163
|
+
override getAttributes(): readonly Attribute[] {
|
|
164
|
+
return this.attributeState.getAttributes();
|
|
165
|
+
}
|
|
158
166
|
}
|
|
159
167
|
|
|
160
168
|
export type AnyInputControl =
|
|
@@ -5,11 +5,15 @@ import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPat
|
|
|
5
5
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
6
6
|
import type { RuntimeInputValue, RuntimeValue } from '../lib/codecs/getSharedValueCodec.ts';
|
|
7
7
|
import { getSharedValueCodec } from '../lib/codecs/getSharedValueCodec.ts';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createAttributeState,
|
|
10
|
+
type AttributeState,
|
|
11
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
9
12
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
10
13
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
11
14
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
12
15
|
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
16
|
+
import type { Attribute } from './Attribute.ts';
|
|
13
17
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
14
18
|
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
15
19
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
@@ -51,6 +55,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
51
55
|
// InstanceNode
|
|
52
56
|
protected readonly state: SharedNodeState<ModelValueStateSpec<V>>;
|
|
53
57
|
protected readonly engineState: EngineState<ModelValueStateSpec<V>>;
|
|
58
|
+
readonly attributeState: AttributeState;
|
|
54
59
|
|
|
55
60
|
// ModelValueNode
|
|
56
61
|
readonly nodeType = 'model-value';
|
|
@@ -67,7 +72,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
67
72
|
|
|
68
73
|
super(parent, instanceNode, definition, codec);
|
|
69
74
|
|
|
70
|
-
|
|
75
|
+
this.attributeState = createAttributeState(this.scope);
|
|
71
76
|
|
|
72
77
|
const state = createSharedNodeState(
|
|
73
78
|
this.scope,
|
|
@@ -80,7 +85,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
80
85
|
label: null,
|
|
81
86
|
hint: null,
|
|
82
87
|
children: null,
|
|
83
|
-
attributes: attributeState.getAttributes,
|
|
88
|
+
attributes: this.attributeState.getAttributes,
|
|
84
89
|
valueOptions: null,
|
|
85
90
|
value: this.valueState,
|
|
86
91
|
instanceValue: this.getInstanceValue,
|
|
@@ -88,12 +93,16 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
88
93
|
this.instanceConfig
|
|
89
94
|
);
|
|
90
95
|
|
|
91
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
96
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
92
97
|
|
|
93
98
|
this.state = state;
|
|
94
99
|
this.engineState = state.engineState;
|
|
95
100
|
this.currentState = state.currentState;
|
|
96
101
|
}
|
|
102
|
+
|
|
103
|
+
override getAttributes(): readonly Attribute[] {
|
|
104
|
+
return this.attributeState.getAttributes();
|
|
105
|
+
}
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
export type AnyModelValue =
|
package/src/instance/Note.ts
CHANGED
|
@@ -8,7 +8,10 @@ import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPat
|
|
|
8
8
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
9
9
|
import { getNoteCodec } from '../lib/codecs/getNoteCodec.ts';
|
|
10
10
|
import type { NoteInputValue, NoteRuntimeValue } from '../lib/codecs/NoteCodec.ts';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
createAttributeState,
|
|
13
|
+
type AttributeState,
|
|
14
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
12
15
|
import { createNoteReadonlyThunk } from '../lib/reactivity/createNoteReadonlyThunk.ts';
|
|
13
16
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
14
17
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -20,6 +23,7 @@ import { createNoteText, type ComputedNoteText } from '../lib/reactivity/text/cr
|
|
|
20
23
|
import type { NoteNodeDefinition } from '../parse/model/NoteNodeDefinition.ts';
|
|
21
24
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
22
25
|
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
26
|
+
import type { Attribute } from './Attribute.ts';
|
|
23
27
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
24
28
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
25
29
|
import type { ClientReactiveSerializableValueNode } from './internal-api/serialization/ClientReactiveSerializableValueNode.ts';
|
|
@@ -48,6 +52,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
48
52
|
// InstanceNode
|
|
49
53
|
protected readonly state: SharedNodeState<NoteStateSpec<V>>;
|
|
50
54
|
protected readonly engineState: EngineState<NoteStateSpec<V>>;
|
|
55
|
+
readonly attributeState: AttributeState;
|
|
51
56
|
|
|
52
57
|
// NoteNode
|
|
53
58
|
readonly nodeType = 'note';
|
|
@@ -68,7 +73,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
68
73
|
|
|
69
74
|
const isReadonly = createNoteReadonlyThunk(this, definition);
|
|
70
75
|
const noteTextComputation = createNoteText(this, definition.noteTextDefinition);
|
|
71
|
-
|
|
76
|
+
this.attributeState = createAttributeState(this.scope);
|
|
72
77
|
|
|
73
78
|
let noteText: ComputedNoteText;
|
|
74
79
|
let label: Accessor<TextRange<'label', 'form'> | null>;
|
|
@@ -108,7 +113,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
108
113
|
noteText,
|
|
109
114
|
|
|
110
115
|
children: null,
|
|
111
|
-
attributes: attributeState.getAttributes,
|
|
116
|
+
attributes: this.attributeState.getAttributes,
|
|
112
117
|
valueOptions: null,
|
|
113
118
|
value: this.valueState,
|
|
114
119
|
instanceValue: this.getInstanceValue,
|
|
@@ -116,12 +121,16 @@ export class Note<V extends ValueType = ValueType>
|
|
|
116
121
|
this.instanceConfig
|
|
117
122
|
);
|
|
118
123
|
|
|
119
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
124
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
120
125
|
|
|
121
126
|
this.state = state;
|
|
122
127
|
this.engineState = state.engineState;
|
|
123
128
|
this.currentState = state.currentState;
|
|
124
129
|
}
|
|
130
|
+
|
|
131
|
+
override getAttributes(): readonly Attribute[] {
|
|
132
|
+
return this.attributeState.getAttributes();
|
|
133
|
+
}
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
export type AnyNote =
|
|
@@ -17,7 +17,10 @@ import { EngineXPathEvaluator } from '../integration/xpath/EngineXPathEvaluator.
|
|
|
17
17
|
import type { StaticDocument } from '../integration/xpath/static-dom/StaticDocument.ts';
|
|
18
18
|
import { createPrimaryInstanceState } from '../lib/client-reactivity/instance-state/createPrimaryInstanceState.ts';
|
|
19
19
|
import { prepareInstancePayload } from '../lib/client-reactivity/instance-state/prepareInstancePayload.ts';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
createAttributeState,
|
|
22
|
+
type AttributeState,
|
|
23
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
21
24
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
22
25
|
import { createTranslationState } from '../lib/reactivity/createTranslationState.ts';
|
|
23
26
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -125,6 +128,7 @@ export class PrimaryInstance<
|
|
|
125
128
|
// InstanceNode
|
|
126
129
|
protected readonly state: SharedNodeState<PrimaryInstanceStateSpec>;
|
|
127
130
|
protected readonly engineState: EngineState<PrimaryInstanceStateSpec>;
|
|
131
|
+
readonly attributeState: AttributeState;
|
|
128
132
|
|
|
129
133
|
override readonly instanceNode: StaticDocument;
|
|
130
134
|
readonly getChildren: Accessor<readonly Root[]>;
|
|
@@ -197,7 +201,7 @@ export class PrimaryInstance<
|
|
|
197
201
|
this.classes = definition.classes;
|
|
198
202
|
|
|
199
203
|
const childrenState = createChildrenState<this, Root>(this);
|
|
200
|
-
|
|
204
|
+
this.attributeState = createAttributeState(this.scope);
|
|
201
205
|
|
|
202
206
|
this.getChildren = childrenState.getChildren;
|
|
203
207
|
|
|
@@ -212,7 +216,7 @@ export class PrimaryInstance<
|
|
|
212
216
|
valueOptions: null,
|
|
213
217
|
value: null,
|
|
214
218
|
children: childrenState.childIds,
|
|
215
|
-
attributes: attributeState.getAttributes,
|
|
219
|
+
attributes: this.attributeState.getAttributes,
|
|
216
220
|
};
|
|
217
221
|
|
|
218
222
|
const state = createSharedNodeState(scope, stateSpec, config);
|
|
@@ -233,10 +237,14 @@ export class PrimaryInstance<
|
|
|
233
237
|
this.instanceState = createPrimaryInstanceState(this);
|
|
234
238
|
|
|
235
239
|
childrenState.setChildren([root]);
|
|
236
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
240
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
237
241
|
setIsAttached(true);
|
|
238
242
|
}
|
|
239
243
|
|
|
244
|
+
override getAttributes(): readonly Attribute[] {
|
|
245
|
+
return this.attributeState.getAttributes();
|
|
246
|
+
}
|
|
247
|
+
|
|
240
248
|
// PrimaryInstanceDocument
|
|
241
249
|
/**
|
|
242
250
|
* @todo Note that this method's signature is intentionally derived from
|
|
@@ -11,7 +11,10 @@ import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPat
|
|
|
11
11
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
12
12
|
import { RangeCodec } from '../lib/codecs/RangeCodec.ts';
|
|
13
13
|
import { getSharedValueCodec } from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createAttributeState,
|
|
16
|
+
type AttributeState,
|
|
17
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
15
18
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
16
19
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
17
20
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -23,6 +26,7 @@ import type {
|
|
|
23
26
|
RangeNodeDefinition,
|
|
24
27
|
RangeValueType,
|
|
25
28
|
} from '../parse/model/RangeNodeDefinition.ts';
|
|
29
|
+
import type { Attribute } from './Attribute.ts';
|
|
26
30
|
import type { Root } from './Root.ts';
|
|
27
31
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
28
32
|
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
@@ -66,6 +70,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
66
70
|
// InstanceNode
|
|
67
71
|
protected readonly state: SharedNodeState<RangeControlStateSpec<V>>;
|
|
68
72
|
protected readonly engineState: EngineState<RangeControlStateSpec<V>>;
|
|
73
|
+
readonly attributeState: AttributeState;
|
|
69
74
|
|
|
70
75
|
// RangeNode
|
|
71
76
|
readonly nodeType = 'range';
|
|
@@ -84,7 +89,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
84
89
|
super(parent, instanceNode, definition, codec);
|
|
85
90
|
|
|
86
91
|
this.appearances = definition.bodyElement.appearances;
|
|
87
|
-
|
|
92
|
+
this.attributeState = createAttributeState(this.scope);
|
|
88
93
|
|
|
89
94
|
const state = createSharedNodeState(
|
|
90
95
|
this.scope,
|
|
@@ -97,7 +102,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
97
102
|
label: createNodeLabel(this, definition),
|
|
98
103
|
hint: createFieldHint(this, definition),
|
|
99
104
|
children: null,
|
|
100
|
-
attributes: attributeState.getAttributes,
|
|
105
|
+
attributes: this.attributeState.getAttributes,
|
|
101
106
|
valueOptions: null,
|
|
102
107
|
value: this.valueState,
|
|
103
108
|
instanceValue: this.getInstanceValue,
|
|
@@ -105,7 +110,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
105
110
|
this.instanceConfig
|
|
106
111
|
);
|
|
107
112
|
|
|
108
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
113
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
109
114
|
|
|
110
115
|
this.state = state;
|
|
111
116
|
this.engineState = state.engineState;
|
|
@@ -117,6 +122,10 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
117
122
|
|
|
118
123
|
return this.root;
|
|
119
124
|
}
|
|
125
|
+
|
|
126
|
+
override getAttributes(): readonly Attribute[] {
|
|
127
|
+
return this.attributeState.getAttributes();
|
|
128
|
+
}
|
|
120
129
|
}
|
|
121
130
|
|
|
122
131
|
// prettier-ignore
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type XPathChoiceNode
|
|
1
|
+
import { XPathNodeKindKey, type XPathChoiceNode } from '@getodk/xpath';
|
|
2
2
|
import type { Accessor } from 'solid-js';
|
|
3
3
|
import { createMemo } from 'solid-js';
|
|
4
4
|
import type { RankDefinition, RankItem, RankNode, RankValueOptions } from '../client/RankNode.ts';
|
|
@@ -10,7 +10,10 @@ import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPat
|
|
|
10
10
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
11
11
|
import { sharedValueCodecs } from '../lib/codecs/getSharedValueCodec.ts';
|
|
12
12
|
import { MultipleValueItemCodec } from '../lib/codecs/items/MultipleValueItemCodec.ts';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
createAttributeState,
|
|
15
|
+
type AttributeState,
|
|
16
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
14
17
|
import { createItemCollection } from '../lib/reactivity/createItemCollection.ts';
|
|
15
18
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
16
19
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -20,6 +23,7 @@ import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
|
20
23
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
21
24
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
22
25
|
import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
|
|
26
|
+
import type { Attribute } from './Attribute.ts';
|
|
23
27
|
import type { Root } from './Root.ts';
|
|
24
28
|
import type { ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
25
29
|
import { ValueNode } from './abstract/ValueNode.ts';
|
|
@@ -96,6 +100,7 @@ export class RankControl
|
|
|
96
100
|
// InstanceNode
|
|
97
101
|
protected readonly state: SharedNodeState<RankControlStateSpec>;
|
|
98
102
|
protected readonly engineState: EngineState<RankControlStateSpec>;
|
|
103
|
+
readonly attributeState: AttributeState;
|
|
99
104
|
|
|
100
105
|
// RankNode
|
|
101
106
|
readonly nodeType = 'rank';
|
|
@@ -125,7 +130,7 @@ export class RankControl
|
|
|
125
130
|
const baseValueState = this.valueState;
|
|
126
131
|
const [baseGetValue, setValue] = baseValueState;
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
this.attributeState = createAttributeState(this.scope);
|
|
129
134
|
|
|
130
135
|
/**
|
|
131
136
|
* @ToDo As new value options become available, they're not yet in the
|
|
@@ -178,7 +183,7 @@ export class RankControl
|
|
|
178
183
|
label: createNodeLabel(this, definition),
|
|
179
184
|
hint: createFieldHint(this, definition),
|
|
180
185
|
children: null,
|
|
181
|
-
attributes: attributeState.getAttributes,
|
|
186
|
+
attributes: this.attributeState.getAttributes,
|
|
182
187
|
valueOptions,
|
|
183
188
|
value: valueState,
|
|
184
189
|
instanceValue: this.getInstanceValue,
|
|
@@ -186,13 +191,17 @@ export class RankControl
|
|
|
186
191
|
this.instanceConfig
|
|
187
192
|
);
|
|
188
193
|
|
|
189
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
194
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
190
195
|
|
|
191
196
|
this.state = state;
|
|
192
197
|
this.engineState = state.engineState;
|
|
193
198
|
this.currentState = state.currentState;
|
|
194
199
|
}
|
|
195
200
|
|
|
201
|
+
override getAttributes(): readonly Attribute[] {
|
|
202
|
+
return this.attributeState.getAttributes();
|
|
203
|
+
}
|
|
204
|
+
|
|
196
205
|
getValueLabel(value: string): TextRange<'item-label'> | null {
|
|
197
206
|
const valueOption = this.currentState.valueOptions.find((item) => item.value === value);
|
|
198
207
|
return valueOption?.label ?? null;
|