@getodk/xforms-engine 0.14.0 → 0.15.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/client/AttributeNode.d.ts +53 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/node-types.d.ts +1 -1
- package/dist/client/validation.d.ts +7 -1
- package/dist/index.js +436 -164
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +58 -0
- package/dist/instance/Group.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +4 -0
- package/dist/instance/Root.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +4 -0
- package/dist/instance/abstract/InstanceNode.d.ts +7 -4
- package/dist/instance/abstract/ValueNode.d.ts +1 -0
- package/dist/instance/attachments/buildAttributes.d.ts +3 -0
- package/dist/instance/hierarchy.d.ts +2 -1
- package/dist/instance/internal-api/AttributeContext.d.ts +29 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +16 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +2 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +2 -2
- package/dist/instance/repeat/BaseRepeatRange.d.ts +5 -0
- package/dist/instance/repeat/RepeatInstance.d.ts +4 -2
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +2 -2
- package/dist/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.d.ts +3 -0
- package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +0 -3
- package/dist/lib/names/NamespaceDeclarationMap.d.ts +1 -1
- package/dist/lib/reactivity/createAttributeState.d.ts +16 -0
- package/dist/lib/reactivity/createAttributeValueState.d.ts +15 -0
- package/dist/lib/xml-serialization.d.ts +5 -9
- package/dist/parse/XFormDOM.d.ts +1 -1
- package/dist/parse/model/AttributeDefinition.d.ts +22 -0
- package/dist/parse/model/{RootAttributeMap.d.ts → AttributeDefinitionMap.d.ts} +4 -10
- package/dist/parse/model/GroupDefinition.d.ts +4 -1
- package/dist/parse/model/LeafNodeDefinition.d.ts +1 -0
- package/dist/parse/model/NodeDefinition.d.ts +8 -3
- package/dist/parse/model/RepeatDefinition.d.ts +4 -1
- package/dist/parse/model/RootDefinition.d.ts +2 -2
- package/dist/solid.js +436 -164
- package/dist/solid.js.map +1 -1
- package/package.json +5 -5
- package/src/client/AttributeNode.ts +62 -0
- package/src/client/index.ts +1 -0
- package/src/client/node-types.ts +1 -0
- package/src/client/validation.ts +9 -1
- package/src/instance/Attribute.ts +164 -0
- package/src/instance/Group.ts +16 -0
- package/src/instance/InputControl.ts +1 -0
- package/src/instance/ModelValue.ts +1 -0
- package/src/instance/Note.ts +1 -0
- package/src/instance/PrimaryInstance.ts +17 -0
- package/src/instance/RangeControl.ts +1 -0
- package/src/instance/RankControl.ts +1 -0
- package/src/instance/Root.ts +16 -0
- package/src/instance/SelectControl.ts +1 -0
- package/src/instance/TriggerControl.ts +1 -0
- package/src/instance/UploadControl.ts +14 -0
- package/src/instance/abstract/DescendantNode.ts +5 -1
- package/src/instance/abstract/InstanceNode.ts +6 -3
- package/src/instance/abstract/ValueNode.ts +1 -0
- package/src/instance/attachments/buildAttributes.ts +8 -0
- package/src/instance/hierarchy.ts +3 -1
- package/src/instance/internal-api/AttributeContext.ts +34 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +19 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +2 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +2 -3
- package/src/instance/repeat/BaseRepeatRange.ts +14 -0
- package/src/instance/repeat/RepeatInstance.ts +14 -5
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +3 -1
- package/src/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts +16 -0
- package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +5 -5
- package/src/lib/client-reactivity/instance-state/createRootInstanceState.ts +6 -9
- package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +5 -15
- package/src/lib/names/NamespaceDeclarationMap.ts +1 -1
- package/src/lib/reactivity/createAttributeState.ts +51 -0
- package/src/lib/reactivity/createAttributeValueState.ts +189 -0
- package/src/lib/xml-serialization.ts +30 -34
- package/src/parse/model/AttributeDefinition.ts +58 -0
- package/src/parse/model/{RootAttributeMap.ts → AttributeDefinitionMap.ts} +7 -13
- package/src/parse/model/GroupDefinition.ts +6 -0
- package/src/parse/model/LeafNodeDefinition.ts +1 -0
- package/src/parse/model/NodeDefinition.ts +11 -3
- package/src/parse/model/RepeatDefinition.ts +8 -1
- package/src/parse/model/RootDefinition.ts +5 -5
- package/src/parse/model/nodeDefinitionMap.ts +1 -1
- package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +0 -22
- package/dist/parse/model/RootAttributeDefinition.d.ts +0 -21
- package/src/error/TemplatedNodeAttributeSerializationError.ts +0 -24
- package/src/parse/model/RootAttributeDefinition.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getodk/xforms-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "XForms engine for ODK Web Forms",
|
|
6
6
|
"type": "module",
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@babel/core": "^7.28.0",
|
|
65
|
-
"@getodk/tree-sitter-xpath": "0.2.
|
|
66
|
-
"@getodk/xpath": "0.
|
|
67
|
-
"@playwright/test": "^1.
|
|
65
|
+
"@getodk/tree-sitter-xpath": "0.2.1",
|
|
66
|
+
"@getodk/xpath": "0.9.0",
|
|
67
|
+
"@playwright/test": "^1.55.1",
|
|
68
68
|
"@types/papaparse": "^5.3.16",
|
|
69
69
|
"@vitest/browser": "^3.2.4",
|
|
70
70
|
"babel-plugin-transform-jsbi-to-bigint": "^1.4.2",
|
|
71
71
|
"http-server": "^14.1.1",
|
|
72
72
|
"jsdom": "^26.1.0",
|
|
73
73
|
"typedoc": "^0.28.7",
|
|
74
|
-
"vite": "^7.0.
|
|
74
|
+
"vite": "^7.0.8",
|
|
75
75
|
"vite-plugin-dts": "^4.5.4",
|
|
76
76
|
"vite-plugin-no-bundle": "^4.0.0",
|
|
77
77
|
"vitest": "^3.2.4"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Root } from '../instance/Root.ts';
|
|
2
|
+
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
3
|
+
import type { OpaqueReactiveObjectFactory } from './OpaqueReactiveObjectFactory.ts';
|
|
4
|
+
import type { InstanceState } from './serialization/InstanceState.ts';
|
|
5
|
+
|
|
6
|
+
export interface AttributeNodeState {
|
|
7
|
+
get value(): string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Base interface for common/shared aspects of attributes.
|
|
12
|
+
*/
|
|
13
|
+
export interface AttributeNode {
|
|
14
|
+
/**
|
|
15
|
+
* Specifies the node's general type. This can be useful for narrowing types,
|
|
16
|
+
* e.g. those of children.
|
|
17
|
+
*/
|
|
18
|
+
readonly nodeType: 'attribute';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Each node has a definition which specifies aspects of the node defined in
|
|
22
|
+
* the form. These aspects include (but are not limited to) the node's data
|
|
23
|
+
* type, its body presentation constraints (if any), its bound nodeset, and
|
|
24
|
+
* so on...
|
|
25
|
+
*/
|
|
26
|
+
readonly definition: AttributeDefinition;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Each node links back to the node representing the root of the form.
|
|
30
|
+
*/
|
|
31
|
+
readonly root: Root;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Each node links back to its parent, if any. All nodes have a parent except
|
|
35
|
+
* the form's {@link root}.
|
|
36
|
+
*/
|
|
37
|
+
readonly parent: unknown;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Each node provides a discrete object representing the stateful aspects of
|
|
41
|
+
* that node which will change over time. This includes state which is either
|
|
42
|
+
* client-/user-mutable, or state which is computed based on the core XForms
|
|
43
|
+
* computation model. Each node also exposes {@link validationState}, which
|
|
44
|
+
* reflects the validity of the node, or its descendants.
|
|
45
|
+
*
|
|
46
|
+
* When a client provides a {@link OpaqueReactiveObjectFactory}, the engine
|
|
47
|
+
* will update the properties of this object as their respective states
|
|
48
|
+
* change, so a client can implement reactive updates that respond to changes
|
|
49
|
+
* as they occur.
|
|
50
|
+
*/
|
|
51
|
+
readonly currentState: AttributeNodeState;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Represents the current instance state of the node.
|
|
55
|
+
*
|
|
56
|
+
* @see {@link InstanceState.instanceXML} for additional detail.
|
|
57
|
+
*/
|
|
58
|
+
readonly instanceState: InstanceState;
|
|
59
|
+
|
|
60
|
+
readonly appearances: null;
|
|
61
|
+
readonly nodeOptions: null;
|
|
62
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type * from './attachments/InstanceAttachmentMeta.ts';
|
|
2
2
|
export type * from './attachments/InstanceAttachmentsConfig.ts';
|
|
3
|
+
export type * from './AttributeNode.ts';
|
|
3
4
|
export type * from './constants.ts';
|
|
4
5
|
export * as constants from './constants.ts';
|
|
5
6
|
export type * from './form/CreateFormInstance.ts';
|
package/src/client/node-types.ts
CHANGED
package/src/client/validation.ts
CHANGED
|
@@ -193,7 +193,15 @@ export interface AncestorNodeValidationState {
|
|
|
193
193
|
get violations(): readonly DescendantNodeViolationReference[];
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Convenience interface for nodes that cannot be invalid.
|
|
198
|
+
*/
|
|
199
|
+
export interface NullValidationState {
|
|
200
|
+
get violations(): readonly [];
|
|
201
|
+
}
|
|
202
|
+
|
|
196
203
|
// prettier-ignore
|
|
197
204
|
export type NodeValidationState =
|
|
198
205
|
| AncestorNodeValidationState
|
|
199
|
-
| LeafNodeValidationState
|
|
206
|
+
| LeafNodeValidationState
|
|
207
|
+
| NullValidationState;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
import type { AttributeNode } from '../client/AttributeNode.ts';
|
|
4
|
+
import type { ActiveLanguage, InstanceState, NullValidationState } from '../client/index.ts';
|
|
5
|
+
import type { XFormsXPathAttribute } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
6
|
+
import type { EngineXPathEvaluator } from '../integration/xpath/EngineXPathEvaluator.ts';
|
|
7
|
+
import type { StaticAttribute } from '../integration/xpath/static-dom/StaticAttribute.ts';
|
|
8
|
+
import { createAttributeNodeInstanceState } from '../lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts';
|
|
9
|
+
import {
|
|
10
|
+
getSharedValueCodec,
|
|
11
|
+
type RuntimeInputValue,
|
|
12
|
+
type RuntimeValue,
|
|
13
|
+
} from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
|
+
import type { RuntimeValueSetter, RuntimeValueState } from '../lib/codecs/ValueCodec.ts';
|
|
15
|
+
import { createAttributeValueState } from '../lib/reactivity/createAttributeValueState.ts';
|
|
16
|
+
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
|
+
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
18
|
+
import {
|
|
19
|
+
createSharedNodeState,
|
|
20
|
+
type SharedNodeState,
|
|
21
|
+
} from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
22
|
+
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
23
|
+
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
24
|
+
import type { DescendantNodeSharedStateSpec } from './abstract/DescendantNode.ts';
|
|
25
|
+
import { InstanceNode } from './abstract/InstanceNode.ts';
|
|
26
|
+
import type { AnyParentNode } from './hierarchy.ts';
|
|
27
|
+
import type { AttributeContext } from './internal-api/AttributeContext.ts';
|
|
28
|
+
import type { DecodeInstanceValue } from './internal-api/InstanceValueContext.ts';
|
|
29
|
+
import type { ClientReactiveSerializableAttributeNode } from './internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
|
|
30
|
+
import type { Root } from './Root.ts';
|
|
31
|
+
|
|
32
|
+
export interface AttributeStateSpec extends DescendantNodeSharedStateSpec {
|
|
33
|
+
readonly children: null;
|
|
34
|
+
readonly attributes: null;
|
|
35
|
+
readonly value: SimpleAtomicState<string>;
|
|
36
|
+
readonly instanceValue: Accessor<string>;
|
|
37
|
+
readonly label: null;
|
|
38
|
+
readonly hint: null;
|
|
39
|
+
readonly valueOptions: null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class Attribute
|
|
43
|
+
extends InstanceNode<AttributeDefinition, AttributeStateSpec, AnyParentNode, null>
|
|
44
|
+
implements
|
|
45
|
+
AttributeNode,
|
|
46
|
+
ClientReactiveSerializableAttributeNode,
|
|
47
|
+
AttributeContext,
|
|
48
|
+
XFormsXPathAttribute
|
|
49
|
+
{
|
|
50
|
+
override readonly [XPathNodeKindKey] = 'attribute';
|
|
51
|
+
|
|
52
|
+
protected readonly state: SharedNodeState<AttributeStateSpec>;
|
|
53
|
+
protected readonly engineState: EngineState<AttributeStateSpec>;
|
|
54
|
+
readonly validationState: NullValidationState;
|
|
55
|
+
|
|
56
|
+
readonly nodeType = 'attribute';
|
|
57
|
+
readonly currentState: CurrentState<AttributeStateSpec>;
|
|
58
|
+
override readonly instanceState: InstanceState;
|
|
59
|
+
|
|
60
|
+
readonly appearances = null;
|
|
61
|
+
readonly nodeOptions = null;
|
|
62
|
+
|
|
63
|
+
readonly valueType: string;
|
|
64
|
+
readonly decodeInstanceValue: DecodeInstanceValue;
|
|
65
|
+
|
|
66
|
+
protected readonly getInstanceValue: Accessor<string>;
|
|
67
|
+
protected readonly valueState: RuntimeValueState<RuntimeValue<'string'>>;
|
|
68
|
+
protected readonly setValueState: RuntimeValueSetter<RuntimeInputValue<'string'>>;
|
|
69
|
+
readonly evaluator: EngineXPathEvaluator;
|
|
70
|
+
readonly getActiveLanguage: Accessor<ActiveLanguage>;
|
|
71
|
+
|
|
72
|
+
override readonly root: Root;
|
|
73
|
+
|
|
74
|
+
readonly isRelevant: Accessor<boolean> = () => {
|
|
75
|
+
return this.parent.isRelevant();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
readonly isAttached: Accessor<boolean> = () => {
|
|
79
|
+
return this.parent.isAttached();
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
readonly isReadonly: Accessor<boolean> = () => {
|
|
83
|
+
return true;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
readonly hasReadonlyAncestor: Accessor<boolean> = () => {
|
|
87
|
+
const { parent } = this;
|
|
88
|
+
return parent.hasReadonlyAncestor() || parent.isReadonly();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
readonly hasNonRelevantAncestor: Accessor<boolean> = () => {
|
|
92
|
+
const { parent } = this;
|
|
93
|
+
return parent.hasNonRelevantAncestor() || !parent.isRelevant();
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
constructor(
|
|
97
|
+
parent: AnyParentNode,
|
|
98
|
+
definition: AttributeDefinition,
|
|
99
|
+
override readonly instanceNode: StaticAttribute
|
|
100
|
+
) {
|
|
101
|
+
const codec = getSharedValueCodec('string');
|
|
102
|
+
|
|
103
|
+
super(parent.instanceConfig, parent, instanceNode, definition, {
|
|
104
|
+
scope: parent.scope,
|
|
105
|
+
computeReference: (): string => '@' + this.definition.qualifiedName.getPrefixedName(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
this.root = parent.root;
|
|
109
|
+
|
|
110
|
+
this.getActiveLanguage = parent.getActiveLanguage;
|
|
111
|
+
this.validationState = { violations: [] };
|
|
112
|
+
|
|
113
|
+
this.valueType = 'string';
|
|
114
|
+
this.evaluator = parent.evaluator;
|
|
115
|
+
this.decodeInstanceValue = codec.decodeInstanceValue;
|
|
116
|
+
|
|
117
|
+
const instanceValueState = createAttributeValueState(this);
|
|
118
|
+
const valueState = codec.createRuntimeValueState(instanceValueState);
|
|
119
|
+
|
|
120
|
+
const [getInstanceValue] = instanceValueState;
|
|
121
|
+
const [, setValueState] = valueState;
|
|
122
|
+
|
|
123
|
+
this.getInstanceValue = getInstanceValue;
|
|
124
|
+
this.setValueState = setValueState;
|
|
125
|
+
this.getXPathValue = () => {
|
|
126
|
+
return this.getInstanceValue();
|
|
127
|
+
};
|
|
128
|
+
this.valueState = valueState;
|
|
129
|
+
|
|
130
|
+
const state = createSharedNodeState(
|
|
131
|
+
this.scope,
|
|
132
|
+
{
|
|
133
|
+
reference: this.contextReference,
|
|
134
|
+
readonly: this.isReadonly,
|
|
135
|
+
relevant: this.isRelevant,
|
|
136
|
+
required: () => false,
|
|
137
|
+
|
|
138
|
+
label: null,
|
|
139
|
+
hint: null,
|
|
140
|
+
children: null,
|
|
141
|
+
valueOptions: null,
|
|
142
|
+
value: this.valueState,
|
|
143
|
+
instanceValue: this.getInstanceValue,
|
|
144
|
+
attributes: null,
|
|
145
|
+
},
|
|
146
|
+
this.instanceConfig
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
this.state = state;
|
|
150
|
+
this.engineState = state.engineState;
|
|
151
|
+
this.currentState = state.currentState;
|
|
152
|
+
this.instanceState = createAttributeNodeInstanceState(this);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
setValue(value: string): Root {
|
|
156
|
+
this.setValueState(value);
|
|
157
|
+
|
|
158
|
+
return this.root;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
getChildren(): readonly [] {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
}
|
package/src/instance/Group.ts
CHANGED
|
@@ -8,6 +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 {
|
|
12
|
+
createAttributeState,
|
|
13
|
+
type AttributeState,
|
|
14
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
11
15
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
12
16
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
13
17
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -20,6 +24,8 @@ import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
|
20
24
|
import { createAggregatedViolations } from '../lib/reactivity/validation/createAggregatedViolations.ts';
|
|
21
25
|
import type { DescendantNodeSharedStateSpec } from './abstract/DescendantNode.ts';
|
|
22
26
|
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
27
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
28
|
+
import { Attribute } from './Attribute.ts';
|
|
23
29
|
import { buildChildren } from './children/buildChildren.ts';
|
|
24
30
|
import type { GeneralChildNode, GeneralParentNode } from './hierarchy.ts';
|
|
25
31
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
@@ -30,6 +36,7 @@ interface GroupStateSpec extends DescendantNodeSharedStateSpec {
|
|
|
30
36
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
31
37
|
readonly hint: null;
|
|
32
38
|
readonly children: Accessor<readonly FormNodeID[]>;
|
|
39
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
33
40
|
readonly valueOptions: null;
|
|
34
41
|
readonly value: null;
|
|
35
42
|
}
|
|
@@ -43,6 +50,7 @@ export class Group
|
|
|
43
50
|
ClientReactiveSerializableParentNode<GeneralChildNode>
|
|
44
51
|
{
|
|
45
52
|
private readonly childrenState: ChildrenState<GeneralChildNode>;
|
|
53
|
+
private readonly attributeState: AttributeState;
|
|
46
54
|
|
|
47
55
|
override readonly [XPathNodeKindKey] = 'element';
|
|
48
56
|
|
|
@@ -68,8 +76,10 @@ export class Group
|
|
|
68
76
|
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
69
77
|
|
|
70
78
|
const childrenState = createChildrenState<Group, GeneralChildNode>(this);
|
|
79
|
+
const attributeState = createAttributeState(this.scope);
|
|
71
80
|
|
|
72
81
|
this.childrenState = childrenState;
|
|
82
|
+
this.attributeState = attributeState;
|
|
73
83
|
|
|
74
84
|
const state = createSharedNodeState(
|
|
75
85
|
this.scope,
|
|
@@ -82,6 +92,7 @@ export class Group
|
|
|
82
92
|
label: createNodeLabel(this, definition),
|
|
83
93
|
hint: null,
|
|
84
94
|
children: childrenState.childIds,
|
|
95
|
+
attributes: attributeState.getAttributes,
|
|
85
96
|
valueOptions: null,
|
|
86
97
|
value: null,
|
|
87
98
|
},
|
|
@@ -97,6 +108,7 @@ export class Group
|
|
|
97
108
|
);
|
|
98
109
|
|
|
99
110
|
childrenState.setChildren(buildChildren(this));
|
|
111
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
100
112
|
this.validationState = createAggregatedViolations(this, this.instanceConfig);
|
|
101
113
|
this.instanceState = createParentNodeInstanceState(this);
|
|
102
114
|
}
|
|
@@ -104,4 +116,8 @@ export class Group
|
|
|
104
116
|
getChildren(): readonly GeneralChildNode[] {
|
|
105
117
|
return this.childrenState.getChildren();
|
|
106
118
|
}
|
|
119
|
+
|
|
120
|
+
getAttributes(): readonly Attribute[] {
|
|
121
|
+
return this.attributeState.getAttributes();
|
|
122
|
+
}
|
|
107
123
|
}
|
|
@@ -130,6 +130,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
130
130
|
label: createNodeLabel(this, definition),
|
|
131
131
|
hint: createFieldHint(this, definition),
|
|
132
132
|
children: null,
|
|
133
|
+
attributes: null,
|
|
133
134
|
valueOptions: null,
|
|
134
135
|
value: this.valueState,
|
|
135
136
|
instanceValue: this.getInstanceValue,
|
package/src/instance/Note.ts
CHANGED
|
@@ -17,6 +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 {
|
|
21
|
+
createAttributeState,
|
|
22
|
+
type AttributeState,
|
|
23
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
20
24
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
21
25
|
import { createTranslationState } from '../lib/reactivity/createTranslationState.ts';
|
|
22
26
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -32,7 +36,9 @@ import type { ModelDefinition } from '../parse/model/ModelDefinition.ts';
|
|
|
32
36
|
import type { RootDefinition } from '../parse/model/RootDefinition.ts';
|
|
33
37
|
import type { SecondaryInstancesDefinition } from '../parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts';
|
|
34
38
|
import { InstanceNode } from './abstract/InstanceNode.ts';
|
|
39
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
35
40
|
import { InstanceAttachmentsState } from './attachments/InstanceAttachmentsState.ts';
|
|
41
|
+
import type { Attribute } from './Attribute.ts';
|
|
36
42
|
import type { InitialInstanceState } from './input/InitialInstanceState.ts';
|
|
37
43
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
38
44
|
import type { InstanceConfig } from './internal-api/InstanceConfig.ts';
|
|
@@ -71,6 +77,7 @@ interface PrimaryInstanceStateSpec {
|
|
|
71
77
|
readonly label: null;
|
|
72
78
|
readonly hint: null;
|
|
73
79
|
readonly children: Accessor<readonly FormNodeID[]>;
|
|
80
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
74
81
|
readonly valueOptions: null;
|
|
75
82
|
readonly value: null;
|
|
76
83
|
|
|
@@ -154,6 +161,8 @@ export class PrimaryInstance<
|
|
|
154
161
|
readonly evaluator: EngineXPathEvaluator;
|
|
155
162
|
override readonly contextNode = this;
|
|
156
163
|
|
|
164
|
+
private readonly attributeState: AttributeState;
|
|
165
|
+
|
|
157
166
|
constructor(options: PrimaryInstanceOptions<Mode>) {
|
|
158
167
|
const { mode, initialState, scope, model, secondaryInstances, config } = options;
|
|
159
168
|
const { instance: modelInstance } = model;
|
|
@@ -193,8 +202,10 @@ export class PrimaryInstance<
|
|
|
193
202
|
this.classes = definition.classes;
|
|
194
203
|
|
|
195
204
|
const childrenState = createChildrenState<this, Root>(this);
|
|
205
|
+
const attributeState = createAttributeState(this.scope);
|
|
196
206
|
|
|
197
207
|
this.getChildren = childrenState.getChildren;
|
|
208
|
+
this.attributeState = attributeState;
|
|
198
209
|
|
|
199
210
|
const stateSpec: PrimaryInstanceStateSpec = {
|
|
200
211
|
activeLanguage: getActiveLanguage,
|
|
@@ -207,6 +218,7 @@ export class PrimaryInstance<
|
|
|
207
218
|
valueOptions: null,
|
|
208
219
|
value: null,
|
|
209
220
|
children: childrenState.childIds,
|
|
221
|
+
attributes: attributeState.getAttributes,
|
|
210
222
|
};
|
|
211
223
|
|
|
212
224
|
const state = createSharedNodeState(scope, stateSpec, config);
|
|
@@ -227,6 +239,7 @@ export class PrimaryInstance<
|
|
|
227
239
|
this.instanceState = createPrimaryInstanceState(this);
|
|
228
240
|
|
|
229
241
|
childrenState.setChildren([root]);
|
|
242
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
230
243
|
setIsAttached(true);
|
|
231
244
|
}
|
|
232
245
|
|
|
@@ -279,4 +292,8 @@ export class PrimaryInstance<
|
|
|
279
292
|
|
|
280
293
|
return Promise.resolve(result);
|
|
281
294
|
}
|
|
295
|
+
|
|
296
|
+
getAttributes(): readonly Attribute[] {
|
|
297
|
+
return this.attributeState.getAttributes();
|
|
298
|
+
}
|
|
282
299
|
}
|
|
@@ -94,6 +94,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
94
94
|
label: createNodeLabel(this, definition),
|
|
95
95
|
hint: createFieldHint(this, definition),
|
|
96
96
|
children: null,
|
|
97
|
+
attributes: null,
|
|
97
98
|
valueOptions: null,
|
|
98
99
|
value: this.valueState,
|
|
99
100
|
instanceValue: this.getInstanceValue,
|
package/src/instance/Root.ts
CHANGED
|
@@ -12,6 +12,10 @@ import type { InstanceState } from '../client/serialization/InstanceState.ts';
|
|
|
12
12
|
import type { AncestorNodeValidationState } from '../client/validation.ts';
|
|
13
13
|
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
14
14
|
import { createRootInstanceState } from '../lib/client-reactivity/instance-state/createRootInstanceState.ts';
|
|
15
|
+
import {
|
|
16
|
+
createAttributeState,
|
|
17
|
+
type AttributeState,
|
|
18
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
15
19
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
16
20
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
17
21
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -24,6 +28,8 @@ import { createAggregatedViolations } from '../lib/reactivity/validation/createA
|
|
|
24
28
|
import type { BodyClassList } from '../parse/body/BodyDefinition.ts';
|
|
25
29
|
import type { RootDefinition } from '../parse/model/RootDefinition.ts';
|
|
26
30
|
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
31
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
32
|
+
import { Attribute } from './Attribute.ts';
|
|
27
33
|
import { buildChildren } from './children/buildChildren.ts';
|
|
28
34
|
import type { GeneralChildNode } from './hierarchy.ts';
|
|
29
35
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
@@ -39,6 +45,7 @@ interface RootStateSpec {
|
|
|
39
45
|
readonly label: null;
|
|
40
46
|
readonly hint: null;
|
|
41
47
|
readonly children: Accessor<readonly FormNodeID[]>;
|
|
48
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
42
49
|
readonly valueOptions: null;
|
|
43
50
|
readonly value: null;
|
|
44
51
|
|
|
@@ -56,6 +63,7 @@ export class Root
|
|
|
56
63
|
ClientReactiveSerializableParentNode<GeneralChildNode>
|
|
57
64
|
{
|
|
58
65
|
private readonly childrenState: ChildrenState<GeneralChildNode>;
|
|
66
|
+
private readonly attributeState: AttributeState;
|
|
59
67
|
|
|
60
68
|
// XFormsXPathElement
|
|
61
69
|
override readonly [XPathNodeKindKey] = 'element';
|
|
@@ -95,8 +103,10 @@ export class Root
|
|
|
95
103
|
this.classes = parent.classes;
|
|
96
104
|
|
|
97
105
|
const childrenState = createChildrenState<Root, GeneralChildNode>(this);
|
|
106
|
+
const attributeState = createAttributeState(this.scope);
|
|
98
107
|
|
|
99
108
|
this.childrenState = childrenState;
|
|
109
|
+
this.attributeState = attributeState;
|
|
100
110
|
this.languages = parent.languages;
|
|
101
111
|
|
|
102
112
|
const state = createSharedNodeState(
|
|
@@ -112,6 +122,7 @@ export class Root
|
|
|
112
122
|
valueOptions: null,
|
|
113
123
|
value: null,
|
|
114
124
|
children: childrenState.childIds,
|
|
125
|
+
attributes: attributeState.getAttributes,
|
|
115
126
|
},
|
|
116
127
|
this.instanceConfig
|
|
117
128
|
);
|
|
@@ -125,6 +136,7 @@ export class Root
|
|
|
125
136
|
);
|
|
126
137
|
|
|
127
138
|
childrenState.setChildren(buildChildren(this));
|
|
139
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
128
140
|
this.validationState = createAggregatedViolations(this, this.instanceConfig);
|
|
129
141
|
this.instanceState = createRootInstanceState(this);
|
|
130
142
|
}
|
|
@@ -133,6 +145,10 @@ export class Root
|
|
|
133
145
|
return this.childrenState.getChildren();
|
|
134
146
|
}
|
|
135
147
|
|
|
148
|
+
getAttributes(): readonly Attribute[] {
|
|
149
|
+
return this.attributeState.getAttributes();
|
|
150
|
+
}
|
|
151
|
+
|
|
136
152
|
// RootNode
|
|
137
153
|
setLanguage(language: FormLanguage): Root {
|
|
138
154
|
this.rootDocument.setLanguage(language);
|
|
@@ -100,6 +100,7 @@ export class TriggerControl
|
|
|
100
100
|
label: createNodeLabel(this, definition),
|
|
101
101
|
hint: createFieldHint(this, definition),
|
|
102
102
|
children: null,
|
|
103
|
+
attributes: null,
|
|
103
104
|
valueOptions: null,
|
|
104
105
|
value: this.valueState,
|
|
105
106
|
instanceValue: this.getInstanceValue,
|
|
@@ -9,6 +9,10 @@ import { UploadValueTypeError } from '../error/UploadValueTypeError.ts';
|
|
|
9
9
|
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
10
10
|
import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
|
|
11
11
|
import { createValueNodeInstanceState } from '../lib/client-reactivity/instance-state/createValueNodeInstanceState.ts';
|
|
12
|
+
import {
|
|
13
|
+
createAttributeState,
|
|
14
|
+
type AttributeState,
|
|
15
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
12
16
|
import { createInstanceAttachment } from '../lib/reactivity/createInstanceAttachment.ts';
|
|
13
17
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
14
18
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -20,6 +24,7 @@ import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
|
20
24
|
import type { SharedValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
21
25
|
import { createValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
22
26
|
import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
|
|
27
|
+
import type { Attribute } from './Attribute.ts';
|
|
23
28
|
import type { Root } from './Root.ts';
|
|
24
29
|
import type { DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
|
|
25
30
|
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
@@ -57,6 +62,7 @@ interface UploadControlStateSpec extends DescendantNodeStateSpec<InstanceAttachm
|
|
|
57
62
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
58
63
|
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
59
64
|
readonly children: null;
|
|
65
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
60
66
|
readonly valueOptions: null;
|
|
61
67
|
readonly value: SimpleAtomicState<InstanceAttachmentRuntimeValue>;
|
|
62
68
|
readonly instanceValue: Accessor<InstanceAttachmentFileName>;
|
|
@@ -95,6 +101,7 @@ export class UploadControl
|
|
|
95
101
|
|
|
96
102
|
private readonly validation: SharedValidationState;
|
|
97
103
|
private readonly instanceAttachment: InstanceAttachment;
|
|
104
|
+
private readonly attributeState: AttributeState;
|
|
98
105
|
|
|
99
106
|
// XFormsXPathElement
|
|
100
107
|
override readonly [XPathNodeKindKey] = 'element';
|
|
@@ -133,6 +140,8 @@ export class UploadControl
|
|
|
133
140
|
const instanceAttachment = createInstanceAttachment(this);
|
|
134
141
|
|
|
135
142
|
this.instanceAttachment = instanceAttachment;
|
|
143
|
+
const attributeState = createAttributeState(this.scope);
|
|
144
|
+
this.attributeState = attributeState;
|
|
136
145
|
this.decodeInstanceValue = instanceAttachment.decodeInstanceValue;
|
|
137
146
|
this.getXPathValue = instanceAttachment.getInstanceValue;
|
|
138
147
|
|
|
@@ -149,6 +158,7 @@ export class UploadControl
|
|
|
149
158
|
children: null,
|
|
150
159
|
valueOptions: null,
|
|
151
160
|
value: instanceAttachment.valueState,
|
|
161
|
+
attributes: attributeState.getAttributes,
|
|
152
162
|
instanceValue: instanceAttachment.getInstanceValue,
|
|
153
163
|
},
|
|
154
164
|
this.instanceConfig
|
|
@@ -181,4 +191,8 @@ export class UploadControl
|
|
|
181
191
|
|
|
182
192
|
return this.root;
|
|
183
193
|
}
|
|
194
|
+
|
|
195
|
+
getAttributes(): readonly Attribute[] {
|
|
196
|
+
return this.attributeState.getAttributes();
|
|
197
|
+
}
|
|
184
198
|
}
|