@getodk/xforms-engine 0.15.0 → 0.16.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 +2 -5
- package/dist/client/BaseNode.d.ts +5 -0
- package/dist/client/form/FormInstanceConfig.d.ts +15 -0
- package/dist/index.js +395 -231
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +17 -11
- package/dist/instance/Group.d.ts +0 -2
- package/dist/instance/InputControl.d.ts +2 -0
- package/dist/instance/PrimaryInstance.d.ts +0 -2
- package/dist/instance/Root.d.ts +0 -2
- package/dist/instance/UploadControl.d.ts +0 -2
- package/dist/instance/abstract/InstanceNode.d.ts +2 -2
- package/dist/instance/abstract/ValueNode.d.ts +2 -1
- package/dist/instance/attachments/buildAttributes.d.ts +6 -2
- package/dist/instance/hierarchy.d.ts +1 -2
- package/dist/instance/internal-api/AttributeContext.d.ts +6 -0
- package/dist/instance/internal-api/InstanceConfig.d.ts +2 -0
- package/dist/instance/internal-api/InstanceValueContext.d.ts +6 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +0 -1
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableValueNode.d.ts +4 -0
- package/dist/instance/repeat/RepeatInstance.d.ts +0 -2
- package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +1 -1
- package/dist/lib/reactivity/createInstanceValueState.d.ts +4 -1
- package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +2 -2
- package/dist/lib/xml-serialization.d.ts +1 -1
- package/dist/parse/XFormDOM.d.ts +3 -0
- package/dist/parse/expression/ActionComputationExpression.d.ts +4 -0
- package/dist/parse/model/ActionDefinition.d.ts +15 -0
- package/dist/parse/model/AttributeDefinition.d.ts +3 -1
- package/dist/parse/model/BindPreloadDefinition.d.ts +6 -10
- package/dist/parse/model/Event.d.ts +8 -0
- package/dist/parse/model/LeafNodeDefinition.d.ts +5 -2
- package/dist/parse/model/ModelActionMap.d.ts +9 -0
- package/dist/parse/model/ModelDefinition.d.ts +8 -1
- package/dist/parse/model/NoteNodeDefinition.d.ts +3 -2
- package/dist/parse/model/RangeNodeDefinition.d.ts +2 -1
- package/dist/parse/model/RootDefinition.d.ts +1 -0
- package/dist/solid.js +395 -231
- package/dist/solid.js.map +1 -1
- package/package.json +21 -17
- package/src/client/AttributeNode.ts +2 -5
- package/src/client/BaseNode.ts +6 -0
- package/src/client/form/FormInstanceConfig.ts +17 -0
- package/src/client/validation.ts +1 -1
- package/src/entrypoints/FormInstance.ts +1 -0
- package/src/instance/Attribute.ts +45 -45
- package/src/instance/Group.ts +1 -10
- package/src/instance/InputControl.ts +8 -1
- package/src/instance/ModelValue.ts +7 -1
- package/src/instance/Note.ts +6 -1
- package/src/instance/PrimaryInstance.ts +1 -11
- package/src/instance/RangeControl.ts +6 -1
- package/src/instance/RankControl.ts +7 -1
- package/src/instance/Root.ts +1 -10
- package/src/instance/SelectControl.ts +6 -1
- package/src/instance/TriggerControl.ts +6 -1
- package/src/instance/UploadControl.ts +1 -10
- package/src/instance/abstract/DescendantNode.ts +0 -5
- package/src/instance/abstract/InstanceNode.ts +2 -2
- package/src/instance/abstract/ValueNode.ts +2 -1
- package/src/instance/attachments/buildAttributes.ts +11 -4
- package/src/instance/children/normalizeChildInitOptions.ts +1 -1
- package/src/instance/hierarchy.ts +1 -3
- package/src/instance/internal-api/AttributeContext.ts +6 -0
- package/src/instance/internal-api/InstanceConfig.ts +6 -1
- package/src/instance/internal-api/InstanceValueContext.ts +6 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +0 -1
- package/src/instance/internal-api/serialization/ClientReactiveSerializableValueNode.ts +4 -0
- package/src/instance/repeat/RepeatInstance.ts +1 -10
- package/src/lib/client-reactivity/instance-state/createValueNodeInstanceState.ts +2 -1
- package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +1 -0
- package/src/lib/codecs/NoteCodec.ts +1 -1
- package/src/lib/codecs/items/SingleValueItemCodec.ts +1 -3
- package/src/lib/reactivity/createInstanceValueState.ts +152 -53
- package/src/lib/reactivity/node-state/createSharedNodeState.ts +2 -2
- package/src/lib/xml-serialization.ts +9 -1
- package/src/parse/XFormDOM.ts +9 -0
- package/src/parse/body/GroupElementDefinition.ts +1 -1
- package/src/parse/body/control/InputControlDefinition.ts +1 -1
- package/src/parse/expression/ActionComputationExpression.ts +12 -0
- package/src/parse/model/ActionDefinition.ts +70 -0
- package/src/parse/model/AttributeDefinition.ts +3 -2
- package/src/parse/model/AttributeDefinitionMap.ts +1 -1
- package/src/parse/model/BindDefinition.ts +1 -6
- package/src/parse/model/BindPreloadDefinition.ts +44 -12
- package/src/parse/model/Event.ts +9 -0
- package/src/parse/model/LeafNodeDefinition.ts +5 -1
- package/src/parse/model/ModelActionMap.ts +37 -0
- package/src/parse/model/ModelDefinition.ts +18 -3
- package/src/parse/model/NoteNodeDefinition.ts +5 -2
- package/src/parse/model/RangeNodeDefinition.ts +5 -2
- package/src/parse/model/RootDefinition.ts +22 -4
- package/dist/lib/reactivity/createAttributeValueState.d.ts +0 -15
- package/src/lib/reactivity/createAttributeValueState.ts +0 -189
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getodk/xforms-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "XForms engine for ODK Web Forms",
|
|
6
6
|
"type": "module",
|
|
@@ -29,20 +29,20 @@
|
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
31
|
"engines": {
|
|
32
|
-
"node": "^20.19.3 || ^22.12.0 || ^24.
|
|
33
|
-
"yarn": "
|
|
32
|
+
"node": "^20.19.3 || ^22.12.0 || ^24.11.0",
|
|
33
|
+
"yarn": "4.11.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
|
-
"build": "npm-run-all -nl build:*",
|
|
36
|
+
"build": "npm-run-all -nl 'build:*'",
|
|
37
37
|
"build:clean": "rimraf dist/",
|
|
38
38
|
"build:js": "vite build",
|
|
39
|
-
"build:solid": "
|
|
39
|
+
"build:solid": "VITE_BUILD_TARGET=solid vite build",
|
|
40
40
|
"dev": "vite",
|
|
41
|
-
"docs": "npm-run-all -nl docs:*",
|
|
41
|
+
"docs": "npm-run-all -nl 'docs:*'",
|
|
42
42
|
"docs:clean": "rimraf api-docs/",
|
|
43
43
|
"docs:api": "typedoc --readme none --out api-docs --entryPoints \"src/**/*\"",
|
|
44
44
|
"docs:serve": "http-server api-docs -o modules/client",
|
|
45
|
-
"test": "npm-run-all
|
|
45
|
+
"test": "npm-run-all -nl 'test-node:*' 'test-browser:*'",
|
|
46
46
|
"test-node:jsdom": "vitest run",
|
|
47
47
|
"test-browser:chromium": "BROWSER_NAME=chromium vitest run",
|
|
48
48
|
"test-browser:firefox": "BROWSER_NAME=firefox vitest run",
|
|
@@ -57,24 +57,28 @@
|
|
|
57
57
|
"bin-packer": "1.7.0",
|
|
58
58
|
"mdast-util-from-markdown": "^2.0.2",
|
|
59
59
|
"papaparse": "^5.5.3",
|
|
60
|
-
"solid-js": "^1.9.
|
|
60
|
+
"solid-js": "^1.9.10",
|
|
61
61
|
"temporal-polyfill": "^0.3.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@babel/core": "^7.28.
|
|
65
|
-
"@getodk/tree-sitter-xpath": "0.2.
|
|
66
|
-
"@getodk/xpath": "0.9.
|
|
67
|
-
"@playwright/test": "^1.
|
|
68
|
-
"@types/papaparse": "^5.
|
|
64
|
+
"@babel/core": "^7.28.5",
|
|
65
|
+
"@getodk/tree-sitter-xpath": "0.2.2",
|
|
66
|
+
"@getodk/xpath": "0.9.1",
|
|
67
|
+
"@playwright/test": "^1.57.0",
|
|
68
|
+
"@types/papaparse": "^5.5.0",
|
|
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
|
-
"jsdom": "^
|
|
73
|
-
"
|
|
74
|
-
"
|
|
72
|
+
"jsdom": "^27.2.0",
|
|
73
|
+
"npm-run-all2": "^8.0.4",
|
|
74
|
+
"rimraf": "^6.0.1",
|
|
75
|
+
"typedoc": "^0.28.14",
|
|
76
|
+
"typescript": "~5.9.3",
|
|
77
|
+
"vite": "^7.2.4",
|
|
75
78
|
"vite-plugin-dts": "^4.5.4",
|
|
76
79
|
"vite-plugin-no-bundle": "^4.0.0",
|
|
77
|
-
"vitest": "^3.2.4"
|
|
80
|
+
"vitest": "^3.2.4",
|
|
81
|
+
"web-tree-sitter": "0.24.5"
|
|
78
82
|
},
|
|
79
83
|
"peerDependencies": {
|
|
80
84
|
"solid-js": "^1.9.7"
|
|
@@ -5,6 +5,7 @@ import type { InstanceState } from './serialization/InstanceState.ts';
|
|
|
5
5
|
|
|
6
6
|
export interface AttributeNodeState {
|
|
7
7
|
get value(): string;
|
|
8
|
+
get relevant(): boolean;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -30,11 +31,7 @@ export interface AttributeNode {
|
|
|
30
31
|
*/
|
|
31
32
|
readonly root: Root;
|
|
32
33
|
|
|
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;
|
|
34
|
+
readonly owner: unknown;
|
|
38
35
|
|
|
39
36
|
/**
|
|
40
37
|
* Each node provides a discrete object representing the stateful aspects of
|
package/src/client/BaseNode.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Attribute } from '../instance/Attribute.ts';
|
|
1
2
|
import type { TokenListParser } from '../lib/TokenListParser.ts';
|
|
2
3
|
import type { AnyNodeDefinition } from '../parse/model/NodeDefinition.ts';
|
|
3
4
|
import type { NodeAppearances } from './NodeAppearances.ts';
|
|
@@ -129,6 +130,11 @@ export interface BaseNodeState {
|
|
|
129
130
|
* is an internal engine consideration.
|
|
130
131
|
*/
|
|
131
132
|
get value(): unknown;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Nodes can own attributes, which have a literal or reference value.
|
|
136
|
+
*/
|
|
137
|
+
get attributes(): readonly Attribute[];
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
/**
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import type { InstanceAttachmentsConfig } from '../attachments/InstanceAttachmentsConfig.ts';
|
|
2
2
|
import type { OpaqueReactiveObjectFactory } from '../OpaqueReactiveObjectFactory.ts';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @see https://getodk.github.io/xforms-spec/#preload-attributes
|
|
6
|
+
*/
|
|
7
|
+
export interface PreloadProperties {
|
|
8
|
+
/**
|
|
9
|
+
* The unique identifier for this device. If not provided, then an identifier will be
|
|
10
|
+
* generated during the first page load and stored in localstorage and reused for
|
|
11
|
+
* subsequent form loads.
|
|
12
|
+
*/
|
|
13
|
+
readonly deviceID?: string;
|
|
14
|
+
readonly email?: string;
|
|
15
|
+
readonly username?: string;
|
|
16
|
+
readonly phoneNumber?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
4
19
|
export interface FormInstanceConfig {
|
|
5
20
|
/**
|
|
6
21
|
* A client may specify a generic function for constructing stateful objects.
|
|
@@ -18,4 +33,6 @@ export interface FormInstanceConfig {
|
|
|
18
33
|
readonly stateFactory?: OpaqueReactiveObjectFactory;
|
|
19
34
|
|
|
20
35
|
readonly instanceAttachments?: InstanceAttachmentsConfig;
|
|
36
|
+
|
|
37
|
+
readonly preloadProperties?: PreloadProperties;
|
|
21
38
|
}
|
package/src/client/validation.ts
CHANGED
|
@@ -204,4 +204,4 @@ export interface NullValidationState {
|
|
|
204
204
|
export type NodeValidationState =
|
|
205
205
|
| AncestorNodeValidationState
|
|
206
206
|
| LeafNodeValidationState
|
|
207
|
-
| NullValidationState;
|
|
207
|
+
| NullValidationState; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
|
|
@@ -41,6 +41,7 @@ export class FormInstance<Mode extends FormInstanceInitializationMode>
|
|
|
41
41
|
const config: InstanceConfig = {
|
|
42
42
|
clientStateFactory: instanceConfig.stateFactory ?? identity,
|
|
43
43
|
computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null),
|
|
44
|
+
preloadProperties: instanceConfig.preloadProperties ?? {},
|
|
44
45
|
};
|
|
45
46
|
const primaryInstanceOptions: PrimaryInstanceOptions<Mode> = {
|
|
46
47
|
...options.instanceOptions,
|
|
@@ -12,42 +12,38 @@ import {
|
|
|
12
12
|
type RuntimeValue,
|
|
13
13
|
} from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
14
|
import type { RuntimeValueSetter, RuntimeValueState } from '../lib/codecs/ValueCodec.ts';
|
|
15
|
-
import {
|
|
15
|
+
import { createInstanceValueState } from '../lib/reactivity/createInstanceValueState.ts';
|
|
16
16
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
17
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
18
18
|
import {
|
|
19
19
|
createSharedNodeState,
|
|
20
20
|
type SharedNodeState,
|
|
21
21
|
} from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
22
|
+
import type { ReactiveScope } from '../lib/reactivity/scope.ts';
|
|
22
23
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
23
24
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
24
|
-
import type {
|
|
25
|
-
import { InstanceNode } from './abstract/InstanceNode.ts';
|
|
26
|
-
import type { AnyParentNode } from './hierarchy.ts';
|
|
25
|
+
import type { AnyChildNode, AnyNode } from './hierarchy.ts';
|
|
27
26
|
import type { AttributeContext } from './internal-api/AttributeContext.ts';
|
|
27
|
+
import type { InstanceConfig } from './internal-api/InstanceConfig.ts';
|
|
28
28
|
import type { DecodeInstanceValue } from './internal-api/InstanceValueContext.ts';
|
|
29
29
|
import type { ClientReactiveSerializableAttributeNode } from './internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
|
|
30
|
+
import type { PrimaryInstance } from './PrimaryInstance.ts';
|
|
30
31
|
import type { Root } from './Root.ts';
|
|
31
32
|
|
|
32
|
-
export interface AttributeStateSpec
|
|
33
|
-
readonly children: null;
|
|
34
|
-
readonly attributes: null;
|
|
33
|
+
export interface AttributeStateSpec {
|
|
35
34
|
readonly value: SimpleAtomicState<string>;
|
|
36
35
|
readonly instanceValue: Accessor<string>;
|
|
37
|
-
readonly
|
|
38
|
-
readonly hint: null;
|
|
39
|
-
readonly valueOptions: null;
|
|
36
|
+
readonly relevant: Accessor<boolean>;
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
export class Attribute
|
|
43
|
-
extends InstanceNode<AttributeDefinition, AttributeStateSpec, AnyParentNode, null>
|
|
44
40
|
implements
|
|
45
41
|
AttributeNode,
|
|
46
42
|
ClientReactiveSerializableAttributeNode,
|
|
47
43
|
AttributeContext,
|
|
48
44
|
XFormsXPathAttribute
|
|
49
45
|
{
|
|
50
|
-
|
|
46
|
+
readonly [XPathNodeKindKey] = 'attribute';
|
|
51
47
|
|
|
52
48
|
protected readonly state: SharedNodeState<AttributeStateSpec>;
|
|
53
49
|
protected readonly engineState: EngineState<AttributeStateSpec>;
|
|
@@ -55,7 +51,7 @@ export class Attribute
|
|
|
55
51
|
|
|
56
52
|
readonly nodeType = 'attribute';
|
|
57
53
|
readonly currentState: CurrentState<AttributeStateSpec>;
|
|
58
|
-
|
|
54
|
+
readonly instanceState: InstanceState;
|
|
59
55
|
|
|
60
56
|
readonly appearances = null;
|
|
61
57
|
readonly nodeOptions = null;
|
|
@@ -68,15 +64,19 @@ export class Attribute
|
|
|
68
64
|
protected readonly setValueState: RuntimeValueSetter<RuntimeInputValue<'string'>>;
|
|
69
65
|
readonly evaluator: EngineXPathEvaluator;
|
|
70
66
|
readonly getActiveLanguage: Accessor<ActiveLanguage>;
|
|
67
|
+
readonly contextNode: AnyNode;
|
|
68
|
+
readonly scope: ReactiveScope;
|
|
69
|
+
readonly rootDocument: PrimaryInstance;
|
|
70
|
+
readonly instanceConfig: InstanceConfig;
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
readonly root: Root;
|
|
73
73
|
|
|
74
74
|
readonly isRelevant: Accessor<boolean> = () => {
|
|
75
|
-
return this.
|
|
75
|
+
return this.owner.isRelevant();
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
readonly isAttached: Accessor<boolean> = () => {
|
|
79
|
-
return this.
|
|
79
|
+
return this.owner.isAttached();
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
readonly isReadonly: Accessor<boolean> = () => {
|
|
@@ -84,37 +84,41 @@ export class Attribute
|
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
readonly hasReadonlyAncestor: Accessor<boolean> = () => {
|
|
87
|
-
const {
|
|
88
|
-
return
|
|
87
|
+
const { owner } = this;
|
|
88
|
+
return owner.hasReadonlyAncestor() || owner.isReadonly();
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
readonly hasNonRelevantAncestor: Accessor<boolean> = () => {
|
|
92
|
-
const {
|
|
93
|
-
return
|
|
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();
|
|
94
98
|
};
|
|
95
99
|
|
|
96
100
|
constructor(
|
|
97
|
-
|
|
98
|
-
definition: AttributeDefinition,
|
|
99
|
-
|
|
101
|
+
readonly owner: AnyNode,
|
|
102
|
+
readonly definition: AttributeDefinition,
|
|
103
|
+
readonly instanceNode: StaticAttribute
|
|
100
104
|
) {
|
|
101
105
|
const codec = getSharedValueCodec('string');
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
+
this.contextNode = owner;
|
|
108
|
+
this.scope = owner.scope;
|
|
109
|
+
this.rootDocument = owner.rootDocument;
|
|
107
110
|
|
|
108
|
-
this.root =
|
|
111
|
+
this.root = owner.root;
|
|
112
|
+
this.instanceConfig = owner.instanceConfig;
|
|
109
113
|
|
|
110
|
-
this.getActiveLanguage =
|
|
114
|
+
this.getActiveLanguage = owner.getActiveLanguage;
|
|
111
115
|
this.validationState = { violations: [] };
|
|
112
116
|
|
|
113
117
|
this.valueType = 'string';
|
|
114
|
-
this.evaluator =
|
|
118
|
+
this.evaluator = owner.evaluator;
|
|
115
119
|
this.decodeInstanceValue = codec.decodeInstanceValue;
|
|
116
120
|
|
|
117
|
-
const instanceValueState =
|
|
121
|
+
const instanceValueState = createInstanceValueState(this);
|
|
118
122
|
const valueState = codec.createRuntimeValueState(instanceValueState);
|
|
119
123
|
|
|
120
124
|
const [getInstanceValue] = instanceValueState;
|
|
@@ -122,26 +126,14 @@ export class Attribute
|
|
|
122
126
|
|
|
123
127
|
this.getInstanceValue = getInstanceValue;
|
|
124
128
|
this.setValueState = setValueState;
|
|
125
|
-
this.getXPathValue = () => {
|
|
126
|
-
return this.getInstanceValue();
|
|
127
|
-
};
|
|
128
129
|
this.valueState = valueState;
|
|
129
130
|
|
|
130
131
|
const state = createSharedNodeState(
|
|
131
|
-
|
|
132
|
+
owner.scope,
|
|
132
133
|
{
|
|
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
134
|
value: this.valueState,
|
|
143
135
|
instanceValue: this.getInstanceValue,
|
|
144
|
-
|
|
136
|
+
relevant: this.owner.isRelevant,
|
|
145
137
|
},
|
|
146
138
|
this.instanceConfig
|
|
147
139
|
);
|
|
@@ -161,4 +153,12 @@ export class Attribute
|
|
|
161
153
|
getChildren(): readonly [] {
|
|
162
154
|
return [];
|
|
163
155
|
}
|
|
156
|
+
|
|
157
|
+
getXPathChildNodes(): readonly AnyChildNode[] {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
getXPathValue(): string {
|
|
162
|
+
return '';
|
|
163
|
+
}
|
|
164
164
|
}
|
package/src/instance/Group.ts
CHANGED
|
@@ -8,10 +8,7 @@ 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
|
+
import { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
15
12
|
import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
16
13
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
17
14
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -50,7 +47,6 @@ export class Group
|
|
|
50
47
|
ClientReactiveSerializableParentNode<GeneralChildNode>
|
|
51
48
|
{
|
|
52
49
|
private readonly childrenState: ChildrenState<GeneralChildNode>;
|
|
53
|
-
private readonly attributeState: AttributeState;
|
|
54
50
|
|
|
55
51
|
override readonly [XPathNodeKindKey] = 'element';
|
|
56
52
|
|
|
@@ -79,7 +75,6 @@ export class Group
|
|
|
79
75
|
const attributeState = createAttributeState(this.scope);
|
|
80
76
|
|
|
81
77
|
this.childrenState = childrenState;
|
|
82
|
-
this.attributeState = attributeState;
|
|
83
78
|
|
|
84
79
|
const state = createSharedNodeState(
|
|
85
80
|
this.scope,
|
|
@@ -116,8 +111,4 @@ export class Group
|
|
|
116
111
|
getChildren(): readonly GeneralChildNode[] {
|
|
117
112
|
return this.childrenState.getChildren();
|
|
118
113
|
}
|
|
119
|
-
|
|
120
|
-
getAttributes(): readonly Attribute[] {
|
|
121
|
-
return this.attributeState.getAttributes();
|
|
122
|
-
}
|
|
123
114
|
}
|
|
@@ -13,6 +13,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
16
17
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
18
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
18
19
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -21,6 +22,8 @@ import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
|
21
22
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
22
23
|
import type { InputControlDefinition } from '../parse/body/control/InputControlDefinition.ts';
|
|
23
24
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
25
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
26
|
+
import type { Attribute } from './Attribute.ts';
|
|
24
27
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
25
28
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
26
29
|
import type { ClientReactiveSerializableValueNode } from './internal-api/serialization/ClientReactiveSerializableValueNode.ts';
|
|
@@ -69,6 +72,7 @@ const nodeOptionsFactoryByType: NodeOptionsFactoryByType = {
|
|
|
69
72
|
interface InputControlStateSpec<V extends ValueType> extends ValueNodeStateSpec<RuntimeValue<V>> {
|
|
70
73
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
71
74
|
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
75
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
72
76
|
readonly valueOptions: null;
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -118,6 +122,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
118
122
|
|
|
119
123
|
this.appearances = definition.bodyElement.appearances;
|
|
120
124
|
this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
|
|
125
|
+
const attributeState = createAttributeState(this.scope);
|
|
121
126
|
|
|
122
127
|
const state = createSharedNodeState(
|
|
123
128
|
this.scope,
|
|
@@ -130,7 +135,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
130
135
|
label: createNodeLabel(this, definition),
|
|
131
136
|
hint: createFieldHint(this, definition),
|
|
132
137
|
children: null,
|
|
133
|
-
attributes:
|
|
138
|
+
attributes: attributeState.getAttributes,
|
|
134
139
|
valueOptions: null,
|
|
135
140
|
value: this.valueState,
|
|
136
141
|
instanceValue: this.getInstanceValue,
|
|
@@ -138,6 +143,8 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
138
143
|
this.instanceConfig
|
|
139
144
|
);
|
|
140
145
|
|
|
146
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
147
|
+
|
|
141
148
|
this.state = state;
|
|
142
149
|
this.engineState = state.engineState;
|
|
143
150
|
this.currentState = state.currentState;
|
|
@@ -5,11 +5,13 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
8
9
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
9
10
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
10
11
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
11
12
|
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
12
13
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
14
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
13
15
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
14
16
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
15
17
|
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
@@ -65,6 +67,8 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
65
67
|
|
|
66
68
|
super(parent, instanceNode, definition, codec);
|
|
67
69
|
|
|
70
|
+
const attributeState = createAttributeState(this.scope);
|
|
71
|
+
|
|
68
72
|
const state = createSharedNodeState(
|
|
69
73
|
this.scope,
|
|
70
74
|
{
|
|
@@ -76,7 +80,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
76
80
|
label: null,
|
|
77
81
|
hint: null,
|
|
78
82
|
children: null,
|
|
79
|
-
attributes:
|
|
83
|
+
attributes: attributeState.getAttributes,
|
|
80
84
|
valueOptions: null,
|
|
81
85
|
value: this.valueState,
|
|
82
86
|
instanceValue: this.getInstanceValue,
|
|
@@ -84,6 +88,8 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
84
88
|
this.instanceConfig
|
|
85
89
|
);
|
|
86
90
|
|
|
91
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
92
|
+
|
|
87
93
|
this.state = state;
|
|
88
94
|
this.engineState = state.engineState;
|
|
89
95
|
this.currentState = state.currentState;
|
package/src/instance/Note.ts
CHANGED
|
@@ -8,6 +8,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
11
12
|
import { createNoteReadonlyThunk } from '../lib/reactivity/createNoteReadonlyThunk.ts';
|
|
12
13
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
13
14
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -18,6 +19,7 @@ import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
|
18
19
|
import { createNoteText, type ComputedNoteText } from '../lib/reactivity/text/createNoteText.ts';
|
|
19
20
|
import type { NoteNodeDefinition } from '../parse/model/NoteNodeDefinition.ts';
|
|
20
21
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
22
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
21
23
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
22
24
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
23
25
|
import type { ClientReactiveSerializableValueNode } from './internal-api/serialization/ClientReactiveSerializableValueNode.ts';
|
|
@@ -66,6 +68,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
66
68
|
|
|
67
69
|
const isReadonly = createNoteReadonlyThunk(this, definition);
|
|
68
70
|
const noteTextComputation = createNoteText(this, definition.noteTextDefinition);
|
|
71
|
+
const attributeState = createAttributeState(this.scope);
|
|
69
72
|
|
|
70
73
|
let noteText: ComputedNoteText;
|
|
71
74
|
let label: Accessor<TextRange<'label', 'form'> | null>;
|
|
@@ -105,7 +108,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
105
108
|
noteText,
|
|
106
109
|
|
|
107
110
|
children: null,
|
|
108
|
-
attributes:
|
|
111
|
+
attributes: attributeState.getAttributes,
|
|
109
112
|
valueOptions: null,
|
|
110
113
|
value: this.valueState,
|
|
111
114
|
instanceValue: this.getInstanceValue,
|
|
@@ -113,6 +116,8 @@ export class Note<V extends ValueType = ValueType>
|
|
|
113
116
|
this.instanceConfig
|
|
114
117
|
);
|
|
115
118
|
|
|
119
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
120
|
+
|
|
116
121
|
this.state = state;
|
|
117
122
|
this.engineState = state.engineState;
|
|
118
123
|
this.currentState = state.currentState;
|
|
@@ -17,10 +17,7 @@ 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
|
+
import { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
24
21
|
import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
|
|
25
22
|
import { createTranslationState } from '../lib/reactivity/createTranslationState.ts';
|
|
26
23
|
import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
@@ -161,8 +158,6 @@ export class PrimaryInstance<
|
|
|
161
158
|
readonly evaluator: EngineXPathEvaluator;
|
|
162
159
|
override readonly contextNode = this;
|
|
163
160
|
|
|
164
|
-
private readonly attributeState: AttributeState;
|
|
165
|
-
|
|
166
161
|
constructor(options: PrimaryInstanceOptions<Mode>) {
|
|
167
162
|
const { mode, initialState, scope, model, secondaryInstances, config } = options;
|
|
168
163
|
const { instance: modelInstance } = model;
|
|
@@ -205,7 +200,6 @@ export class PrimaryInstance<
|
|
|
205
200
|
const attributeState = createAttributeState(this.scope);
|
|
206
201
|
|
|
207
202
|
this.getChildren = childrenState.getChildren;
|
|
208
|
-
this.attributeState = attributeState;
|
|
209
203
|
|
|
210
204
|
const stateSpec: PrimaryInstanceStateSpec = {
|
|
211
205
|
activeLanguage: getActiveLanguage,
|
|
@@ -292,8 +286,4 @@ export class PrimaryInstance<
|
|
|
292
286
|
|
|
293
287
|
return Promise.resolve(result);
|
|
294
288
|
}
|
|
295
|
-
|
|
296
|
-
getAttributes(): readonly Attribute[] {
|
|
297
|
-
return this.attributeState.getAttributes();
|
|
298
|
-
}
|
|
299
289
|
}
|
|
@@ -11,6 +11,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
14
15
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
15
16
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
16
17
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -24,6 +25,7 @@ import type {
|
|
|
24
25
|
} from '../parse/model/RangeNodeDefinition.ts';
|
|
25
26
|
import type { Root } from './Root.ts';
|
|
26
27
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
28
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
27
29
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
28
30
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
29
31
|
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
@@ -82,6 +84,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
82
84
|
super(parent, instanceNode, definition, codec);
|
|
83
85
|
|
|
84
86
|
this.appearances = definition.bodyElement.appearances;
|
|
87
|
+
const attributeState = createAttributeState(this.scope);
|
|
85
88
|
|
|
86
89
|
const state = createSharedNodeState(
|
|
87
90
|
this.scope,
|
|
@@ -94,7 +97,7 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
94
97
|
label: createNodeLabel(this, definition),
|
|
95
98
|
hint: createFieldHint(this, definition),
|
|
96
99
|
children: null,
|
|
97
|
-
attributes:
|
|
100
|
+
attributes: attributeState.getAttributes,
|
|
98
101
|
valueOptions: null,
|
|
99
102
|
value: this.valueState,
|
|
100
103
|
instanceValue: this.getInstanceValue,
|
|
@@ -102,6 +105,8 @@ export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
|
102
105
|
this.instanceConfig
|
|
103
106
|
);
|
|
104
107
|
|
|
108
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
109
|
+
|
|
105
110
|
this.state = state;
|
|
106
111
|
this.engineState = state.engineState;
|
|
107
112
|
this.currentState = state.currentState;
|
|
@@ -10,6 +10,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
|
|
13
14
|
import { createItemCollection } from '../lib/reactivity/createItemCollection.ts';
|
|
14
15
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
15
16
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -22,6 +23,7 @@ import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unkno
|
|
|
22
23
|
import type { Root } from './Root.ts';
|
|
23
24
|
import type { ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
24
25
|
import { ValueNode } from './abstract/ValueNode.ts';
|
|
26
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
25
27
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
26
28
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
27
29
|
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
@@ -123,6 +125,8 @@ export class RankControl
|
|
|
123
125
|
const baseValueState = this.valueState;
|
|
124
126
|
const [baseGetValue, setValue] = baseValueState;
|
|
125
127
|
|
|
128
|
+
const attributeState = createAttributeState(this.scope);
|
|
129
|
+
|
|
126
130
|
/**
|
|
127
131
|
* @ToDo As new value options become available, they're not yet in the
|
|
128
132
|
* `currentValues` state. This appends them. We intend to change this
|
|
@@ -174,7 +178,7 @@ export class RankControl
|
|
|
174
178
|
label: createNodeLabel(this, definition),
|
|
175
179
|
hint: createFieldHint(this, definition),
|
|
176
180
|
children: null,
|
|
177
|
-
attributes:
|
|
181
|
+
attributes: attributeState.getAttributes,
|
|
178
182
|
valueOptions,
|
|
179
183
|
value: valueState,
|
|
180
184
|
instanceValue: this.getInstanceValue,
|
|
@@ -182,6 +186,8 @@ export class RankControl
|
|
|
182
186
|
this.instanceConfig
|
|
183
187
|
);
|
|
184
188
|
|
|
189
|
+
attributeState.setAttributes(buildAttributes(this));
|
|
190
|
+
|
|
185
191
|
this.state = state;
|
|
186
192
|
this.engineState = state.engineState;
|
|
187
193
|
this.currentState = state.currentState;
|