@getodk/xforms-engine 0.15.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 -6
- package/dist/client/BaseNode.d.ts +5 -0
- package/dist/client/form/FormInstanceConfig.d.ts +15 -0
- package/dist/index.js +654 -429
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +13 -19
- package/dist/instance/Group.d.ts +2 -1
- package/dist/instance/InputControl.d.ts +5 -0
- package/dist/instance/ModelValue.d.ts +4 -0
- package/dist/instance/Note.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +3 -2
- package/dist/instance/RangeControl.d.ts +4 -0
- package/dist/instance/RankControl.d.ts +5 -1
- package/dist/instance/Root.d.ts +2 -1
- package/dist/instance/SelectControl.d.ts +5 -1
- package/dist/instance/TriggerControl.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +3 -2
- package/dist/instance/abstract/DescendantNode.d.ts +5 -4
- package/dist/instance/abstract/InstanceNode.d.ts +6 -5
- package/dist/instance/abstract/ValueNode.d.ts +2 -1
- package/dist/instance/attachments/buildAttributes.d.ts +6 -2
- package/dist/instance/hierarchy.d.ts +2 -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/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/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 +5 -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 +654 -429
- package/dist/solid.js.map +1 -1
- package/package.json +21 -17
- package/src/client/AttributeNode.ts +4 -6
- 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 +43 -59
- package/src/instance/Group.ts +5 -6
- package/src/instance/InputControl.ts +16 -1
- package/src/instance/ModelValue.ts +16 -1
- package/src/instance/Note.ts +15 -1
- package/src/instance/PrimaryInstance.ts +8 -10
- package/src/instance/RangeControl.ts +15 -1
- package/src/instance/RankControl.ts +17 -2
- package/src/instance/Root.ts +5 -6
- package/src/instance/SelectControl.ts +16 -2
- package/src/instance/TriggerControl.ts +15 -1
- package/src/instance/UploadControl.ts +9 -8
- package/src/instance/abstract/DescendantNode.ts +4 -8
- package/src/instance/abstract/InstanceNode.ts +7 -5
- package/src/instance/abstract/ValueNode.ts +2 -1
- package/src/instance/attachments/buildAttributes.ts +15 -4
- package/src/instance/children/childrenInitOptions.ts +2 -1
- package/src/instance/children/normalizeChildInitOptions.ts +1 -1
- package/src/instance/hierarchy.ts +2 -2
- 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 +3 -4
- 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/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 +177 -52
- 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 +10 -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.1",
|
|
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.2",
|
|
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"
|
|
@@ -1,16 +1,18 @@
|
|
|
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;
|
|
9
|
+
get relevant(): boolean;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Base interface for common/shared aspects of attributes.
|
|
12
14
|
*/
|
|
13
|
-
export interface AttributeNode {
|
|
15
|
+
export interface AttributeNode extends BaseNode {
|
|
14
16
|
/**
|
|
15
17
|
* Specifies the node's general type. This can be useful for narrowing types,
|
|
16
18
|
* e.g. those of children.
|
|
@@ -30,10 +32,6 @@ export interface AttributeNode {
|
|
|
30
32
|
*/
|
|
31
33
|
readonly root: Root;
|
|
32
34
|
|
|
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
35
|
readonly parent: unknown;
|
|
38
36
|
|
|
39
37
|
/**
|
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,
|
|
@@ -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,7 +11,11 @@ import {
|
|
|
12
11
|
type RuntimeValue,
|
|
13
12
|
} from '../lib/codecs/getSharedValueCodec.ts';
|
|
14
13
|
import type { RuntimeValueSetter, RuntimeValueState } from '../lib/codecs/ValueCodec.ts';
|
|
15
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createAttributeState,
|
|
16
|
+
type AttributeState,
|
|
17
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
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';
|
|
18
21
|
import {
|
|
@@ -21,26 +24,23 @@ import {
|
|
|
21
24
|
} from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
22
25
|
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
23
26
|
import type { AttributeDefinition } from '../parse/model/AttributeDefinition.ts';
|
|
24
|
-
import type
|
|
25
|
-
import {
|
|
26
|
-
import type { AnyParentNode } from './hierarchy.ts';
|
|
27
|
+
import { DescendantNode, type DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
|
|
28
|
+
import type { AnyNode } from './hierarchy.ts';
|
|
27
29
|
import type { AttributeContext } from './internal-api/AttributeContext.ts';
|
|
28
30
|
import type { DecodeInstanceValue } from './internal-api/InstanceValueContext.ts';
|
|
29
31
|
import type { ClientReactiveSerializableAttributeNode } from './internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
|
|
30
32
|
import type { Root } from './Root.ts';
|
|
31
33
|
|
|
32
|
-
export interface AttributeStateSpec extends
|
|
34
|
+
export interface AttributeStateSpec extends DescendantNodeStateSpec<string> {
|
|
33
35
|
readonly children: null;
|
|
34
|
-
readonly attributes:
|
|
36
|
+
readonly attributes: Accessor<Attribute[]>;
|
|
35
37
|
readonly value: SimpleAtomicState<string>;
|
|
36
38
|
readonly instanceValue: Accessor<string>;
|
|
37
|
-
readonly
|
|
38
|
-
readonly hint: null;
|
|
39
|
-
readonly valueOptions: null;
|
|
39
|
+
readonly relevant: Accessor<boolean>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export class Attribute
|
|
43
|
-
extends
|
|
43
|
+
extends DescendantNode<AttributeDefinition, AttributeStateSpec, AnyNode, null>
|
|
44
44
|
implements
|
|
45
45
|
AttributeNode,
|
|
46
46
|
ClientReactiveSerializableAttributeNode,
|
|
@@ -55,7 +55,7 @@ export class Attribute
|
|
|
55
55
|
|
|
56
56
|
readonly nodeType = 'attribute';
|
|
57
57
|
readonly currentState: CurrentState<AttributeStateSpec>;
|
|
58
|
-
|
|
58
|
+
readonly instanceState: InstanceState;
|
|
59
59
|
|
|
60
60
|
readonly appearances = null;
|
|
61
61
|
readonly nodeOptions = null;
|
|
@@ -66,55 +66,33 @@ export class Attribute
|
|
|
66
66
|
protected readonly getInstanceValue: Accessor<string>;
|
|
67
67
|
protected readonly valueState: RuntimeValueState<RuntimeValue<'string'>>;
|
|
68
68
|
protected readonly setValueState: RuntimeValueSetter<RuntimeInputValue<'string'>>;
|
|
69
|
-
readonly
|
|
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
|
-
};
|
|
69
|
+
readonly attributeState: AttributeState;
|
|
85
70
|
|
|
86
|
-
readonly
|
|
87
|
-
|
|
88
|
-
return parent.hasReadonlyAncestor() || parent.isReadonly();
|
|
71
|
+
override readonly isAttached: Accessor<boolean> = () => {
|
|
72
|
+
return this.owner.isAttached();
|
|
89
73
|
};
|
|
90
74
|
|
|
91
|
-
readonly
|
|
92
|
-
const { parent } = this;
|
|
93
|
-
return parent.hasNonRelevantAncestor() || !parent.isRelevant();
|
|
94
|
-
};
|
|
75
|
+
override readonly getXPathValue: () => string;
|
|
95
76
|
|
|
96
77
|
constructor(
|
|
97
|
-
|
|
78
|
+
readonly owner: AnyNode,
|
|
98
79
|
definition: AttributeDefinition,
|
|
99
80
|
override readonly instanceNode: StaticAttribute
|
|
100
81
|
) {
|
|
101
|
-
const
|
|
82
|
+
const computeReference = () => {
|
|
83
|
+
return `${this.owner.contextReference()}/@${this.definition.qualifiedName.getPrefixedName()}`;
|
|
84
|
+
};
|
|
102
85
|
|
|
103
|
-
super(
|
|
104
|
-
scope: parent.scope,
|
|
105
|
-
computeReference: (): string => '@' + this.definition.qualifiedName.getPrefixedName(),
|
|
106
|
-
});
|
|
86
|
+
super(owner, instanceNode, definition, { computeReference });
|
|
107
87
|
|
|
108
|
-
|
|
88
|
+
const codec = getSharedValueCodec('string');
|
|
109
89
|
|
|
110
|
-
this.getActiveLanguage = parent.getActiveLanguage;
|
|
111
90
|
this.validationState = { violations: [] };
|
|
112
91
|
|
|
113
92
|
this.valueType = 'string';
|
|
114
|
-
this.evaluator = parent.evaluator;
|
|
115
93
|
this.decodeInstanceValue = codec.decodeInstanceValue;
|
|
116
94
|
|
|
117
|
-
const instanceValueState =
|
|
95
|
+
const instanceValueState = createInstanceValueState(this);
|
|
118
96
|
const valueState = codec.createRuntimeValueState(instanceValueState);
|
|
119
97
|
|
|
120
98
|
const [getInstanceValue] = instanceValueState;
|
|
@@ -122,26 +100,23 @@ export class Attribute
|
|
|
122
100
|
|
|
123
101
|
this.getInstanceValue = getInstanceValue;
|
|
124
102
|
this.setValueState = setValueState;
|
|
125
|
-
this.getXPathValue = () => {
|
|
126
|
-
return this.getInstanceValue();
|
|
127
|
-
};
|
|
128
103
|
this.valueState = valueState;
|
|
129
104
|
|
|
130
105
|
const state = createSharedNodeState(
|
|
131
|
-
|
|
106
|
+
owner.scope,
|
|
132
107
|
{
|
|
108
|
+
value: this.valueState,
|
|
109
|
+
instanceValue: this.getInstanceValue,
|
|
110
|
+
relevant: this.owner.isRelevant,
|
|
111
|
+
|
|
112
|
+
readonly: () => true,
|
|
133
113
|
reference: this.contextReference,
|
|
134
|
-
readonly: this.isReadonly,
|
|
135
|
-
relevant: this.isRelevant,
|
|
136
114
|
required: () => false,
|
|
137
|
-
|
|
138
|
-
label: null,
|
|
139
|
-
hint: null,
|
|
140
115
|
children: null,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
116
|
+
label: () => null,
|
|
117
|
+
hint: () => null,
|
|
118
|
+
attributes: () => [],
|
|
119
|
+
valueOptions: () => [],
|
|
145
120
|
},
|
|
146
121
|
this.instanceConfig
|
|
147
122
|
);
|
|
@@ -150,6 +125,11 @@ export class Attribute
|
|
|
150
125
|
this.engineState = state.engineState;
|
|
151
126
|
this.currentState = state.currentState;
|
|
152
127
|
this.instanceState = createAttributeNodeInstanceState(this);
|
|
128
|
+
this.attributeState = createAttributeState(this.scope);
|
|
129
|
+
|
|
130
|
+
this.getXPathValue = () => {
|
|
131
|
+
return this.getInstanceValue();
|
|
132
|
+
};
|
|
153
133
|
}
|
|
154
134
|
|
|
155
135
|
setValue(value: string): Root {
|
|
@@ -158,6 +138,10 @@ export class Attribute
|
|
|
158
138
|
return this.root;
|
|
159
139
|
}
|
|
160
140
|
|
|
141
|
+
override getAttributes(): readonly Attribute[] {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
|
|
161
145
|
getChildren(): readonly [] {
|
|
162
146
|
return [];
|
|
163
147
|
}
|
package/src/instance/Group.ts
CHANGED
|
@@ -50,13 +50,13 @@ export class Group
|
|
|
50
50
|
ClientReactiveSerializableParentNode<GeneralChildNode>
|
|
51
51
|
{
|
|
52
52
|
private readonly childrenState: ChildrenState<GeneralChildNode>;
|
|
53
|
-
private readonly attributeState: AttributeState;
|
|
54
53
|
|
|
55
54
|
override readonly [XPathNodeKindKey] = 'element';
|
|
56
55
|
|
|
57
56
|
// InstanceNode
|
|
58
57
|
protected readonly state: SharedNodeState<GroupStateSpec>;
|
|
59
58
|
protected override engineState: EngineState<GroupStateSpec>;
|
|
59
|
+
readonly attributeState: AttributeState;
|
|
60
60
|
|
|
61
61
|
// GroupNode
|
|
62
62
|
readonly nodeType = 'group';
|
|
@@ -76,10 +76,9 @@ export class Group
|
|
|
76
76
|
this.appearances = definition.bodyElement?.appearances ?? null;
|
|
77
77
|
|
|
78
78
|
const childrenState = createChildrenState<Group, GeneralChildNode>(this);
|
|
79
|
-
|
|
79
|
+
this.attributeState = createAttributeState(this.scope);
|
|
80
80
|
|
|
81
81
|
this.childrenState = childrenState;
|
|
82
|
-
this.attributeState = attributeState;
|
|
83
82
|
|
|
84
83
|
const state = createSharedNodeState(
|
|
85
84
|
this.scope,
|
|
@@ -92,7 +91,7 @@ export class Group
|
|
|
92
91
|
label: createNodeLabel(this, definition),
|
|
93
92
|
hint: null,
|
|
94
93
|
children: childrenState.childIds,
|
|
95
|
-
attributes: attributeState.getAttributes,
|
|
94
|
+
attributes: this.attributeState.getAttributes,
|
|
96
95
|
valueOptions: null,
|
|
97
96
|
value: null,
|
|
98
97
|
},
|
|
@@ -108,7 +107,7 @@ export class Group
|
|
|
108
107
|
);
|
|
109
108
|
|
|
110
109
|
childrenState.setChildren(buildChildren(this));
|
|
111
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
110
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
112
111
|
this.validationState = createAggregatedViolations(this, this.instanceConfig);
|
|
113
112
|
this.instanceState = createParentNodeInstanceState(this);
|
|
114
113
|
}
|
|
@@ -117,7 +116,7 @@ export class Group
|
|
|
117
116
|
return this.childrenState.getChildren();
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
getAttributes(): readonly Attribute[] {
|
|
119
|
+
override getAttributes(): readonly Attribute[] {
|
|
121
120
|
return this.attributeState.getAttributes();
|
|
122
121
|
}
|
|
123
122
|
}
|
|
@@ -13,6 +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 {
|
|
17
|
+
createAttributeState,
|
|
18
|
+
type AttributeState,
|
|
19
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
16
20
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
17
21
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
18
22
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -21,6 +25,8 @@ import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
|
21
25
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
22
26
|
import type { InputControlDefinition } from '../parse/body/control/InputControlDefinition.ts';
|
|
23
27
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
28
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
29
|
+
import type { Attribute } from './Attribute.ts';
|
|
24
30
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
25
31
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
26
32
|
import type { ClientReactiveSerializableValueNode } from './internal-api/serialization/ClientReactiveSerializableValueNode.ts';
|
|
@@ -69,6 +75,7 @@ const nodeOptionsFactoryByType: NodeOptionsFactoryByType = {
|
|
|
69
75
|
interface InputControlStateSpec<V extends ValueType> extends ValueNodeStateSpec<RuntimeValue<V>> {
|
|
70
76
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
71
77
|
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
78
|
+
readonly attributes: Accessor<readonly Attribute[]>;
|
|
72
79
|
readonly valueOptions: null;
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -100,6 +107,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
100
107
|
// InstanceNode
|
|
101
108
|
protected readonly state: SharedNodeState<InputControlStateSpec<V>>;
|
|
102
109
|
protected readonly engineState: EngineState<InputControlStateSpec<V>>;
|
|
110
|
+
readonly attributeState: AttributeState;
|
|
103
111
|
|
|
104
112
|
// InputNode
|
|
105
113
|
readonly nodeType = 'input';
|
|
@@ -118,6 +126,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
118
126
|
|
|
119
127
|
this.appearances = definition.bodyElement.appearances;
|
|
120
128
|
this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
|
|
129
|
+
this.attributeState = createAttributeState(this.scope);
|
|
121
130
|
|
|
122
131
|
const state = createSharedNodeState(
|
|
123
132
|
this.scope,
|
|
@@ -130,7 +139,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
130
139
|
label: createNodeLabel(this, definition),
|
|
131
140
|
hint: createFieldHint(this, definition),
|
|
132
141
|
children: null,
|
|
133
|
-
attributes:
|
|
142
|
+
attributes: this.attributeState.getAttributes,
|
|
134
143
|
valueOptions: null,
|
|
135
144
|
value: this.valueState,
|
|
136
145
|
instanceValue: this.getInstanceValue,
|
|
@@ -138,6 +147,8 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
138
147
|
this.instanceConfig
|
|
139
148
|
);
|
|
140
149
|
|
|
150
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
151
|
+
|
|
141
152
|
this.state = state;
|
|
142
153
|
this.engineState = state.engineState;
|
|
143
154
|
this.currentState = state.currentState;
|
|
@@ -148,6 +159,10 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
148
159
|
|
|
149
160
|
return this.root;
|
|
150
161
|
}
|
|
162
|
+
|
|
163
|
+
override getAttributes(): readonly Attribute[] {
|
|
164
|
+
return this.attributeState.getAttributes();
|
|
165
|
+
}
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
export type AnyInputControl =
|
|
@@ -5,11 +5,17 @@ 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 {
|
|
9
|
+
createAttributeState,
|
|
10
|
+
type AttributeState,
|
|
11
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
8
12
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
9
13
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
10
14
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
11
15
|
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
16
|
+
import type { Attribute } from './Attribute.ts';
|
|
12
17
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
18
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
13
19
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
14
20
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
15
21
|
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
@@ -49,6 +55,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
49
55
|
// InstanceNode
|
|
50
56
|
protected readonly state: SharedNodeState<ModelValueStateSpec<V>>;
|
|
51
57
|
protected readonly engineState: EngineState<ModelValueStateSpec<V>>;
|
|
58
|
+
readonly attributeState: AttributeState;
|
|
52
59
|
|
|
53
60
|
// ModelValueNode
|
|
54
61
|
readonly nodeType = 'model-value';
|
|
@@ -65,6 +72,8 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
65
72
|
|
|
66
73
|
super(parent, instanceNode, definition, codec);
|
|
67
74
|
|
|
75
|
+
this.attributeState = createAttributeState(this.scope);
|
|
76
|
+
|
|
68
77
|
const state = createSharedNodeState(
|
|
69
78
|
this.scope,
|
|
70
79
|
{
|
|
@@ -76,7 +85,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
76
85
|
label: null,
|
|
77
86
|
hint: null,
|
|
78
87
|
children: null,
|
|
79
|
-
attributes:
|
|
88
|
+
attributes: this.attributeState.getAttributes,
|
|
80
89
|
valueOptions: null,
|
|
81
90
|
value: this.valueState,
|
|
82
91
|
instanceValue: this.getInstanceValue,
|
|
@@ -84,10 +93,16 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
84
93
|
this.instanceConfig
|
|
85
94
|
);
|
|
86
95
|
|
|
96
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
97
|
+
|
|
87
98
|
this.state = state;
|
|
88
99
|
this.engineState = state.engineState;
|
|
89
100
|
this.currentState = state.currentState;
|
|
90
101
|
}
|
|
102
|
+
|
|
103
|
+
override getAttributes(): readonly Attribute[] {
|
|
104
|
+
return this.attributeState.getAttributes();
|
|
105
|
+
}
|
|
91
106
|
}
|
|
92
107
|
|
|
93
108
|
export type AnyModelValue =
|
package/src/instance/Note.ts
CHANGED
|
@@ -8,6 +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 {
|
|
12
|
+
createAttributeState,
|
|
13
|
+
type AttributeState,
|
|
14
|
+
} from '../lib/reactivity/createAttributeState.ts';
|
|
11
15
|
import { createNoteReadonlyThunk } from '../lib/reactivity/createNoteReadonlyThunk.ts';
|
|
12
16
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
13
17
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
@@ -18,6 +22,8 @@ import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
|
18
22
|
import { createNoteText, type ComputedNoteText } from '../lib/reactivity/text/createNoteText.ts';
|
|
19
23
|
import type { NoteNodeDefinition } from '../parse/model/NoteNodeDefinition.ts';
|
|
20
24
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
25
|
+
import { buildAttributes } from './attachments/buildAttributes.ts';
|
|
26
|
+
import type { Attribute } from './Attribute.ts';
|
|
21
27
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
22
28
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
23
29
|
import type { ClientReactiveSerializableValueNode } from './internal-api/serialization/ClientReactiveSerializableValueNode.ts';
|
|
@@ -46,6 +52,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
46
52
|
// InstanceNode
|
|
47
53
|
protected readonly state: SharedNodeState<NoteStateSpec<V>>;
|
|
48
54
|
protected readonly engineState: EngineState<NoteStateSpec<V>>;
|
|
55
|
+
readonly attributeState: AttributeState;
|
|
49
56
|
|
|
50
57
|
// NoteNode
|
|
51
58
|
readonly nodeType = 'note';
|
|
@@ -66,6 +73,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
66
73
|
|
|
67
74
|
const isReadonly = createNoteReadonlyThunk(this, definition);
|
|
68
75
|
const noteTextComputation = createNoteText(this, definition.noteTextDefinition);
|
|
76
|
+
this.attributeState = createAttributeState(this.scope);
|
|
69
77
|
|
|
70
78
|
let noteText: ComputedNoteText;
|
|
71
79
|
let label: Accessor<TextRange<'label', 'form'> | null>;
|
|
@@ -105,7 +113,7 @@ export class Note<V extends ValueType = ValueType>
|
|
|
105
113
|
noteText,
|
|
106
114
|
|
|
107
115
|
children: null,
|
|
108
|
-
attributes:
|
|
116
|
+
attributes: this.attributeState.getAttributes,
|
|
109
117
|
valueOptions: null,
|
|
110
118
|
value: this.valueState,
|
|
111
119
|
instanceValue: this.getInstanceValue,
|
|
@@ -113,10 +121,16 @@ export class Note<V extends ValueType = ValueType>
|
|
|
113
121
|
this.instanceConfig
|
|
114
122
|
);
|
|
115
123
|
|
|
124
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
125
|
+
|
|
116
126
|
this.state = state;
|
|
117
127
|
this.engineState = state.engineState;
|
|
118
128
|
this.currentState = state.currentState;
|
|
119
129
|
}
|
|
130
|
+
|
|
131
|
+
override getAttributes(): readonly Attribute[] {
|
|
132
|
+
return this.attributeState.getAttributes();
|
|
133
|
+
}
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
export type AnyNote =
|
|
@@ -128,6 +128,7 @@ export class PrimaryInstance<
|
|
|
128
128
|
// InstanceNode
|
|
129
129
|
protected readonly state: SharedNodeState<PrimaryInstanceStateSpec>;
|
|
130
130
|
protected readonly engineState: EngineState<PrimaryInstanceStateSpec>;
|
|
131
|
+
readonly attributeState: AttributeState;
|
|
131
132
|
|
|
132
133
|
override readonly instanceNode: StaticDocument;
|
|
133
134
|
readonly getChildren: Accessor<readonly Root[]>;
|
|
@@ -161,8 +162,6 @@ export class PrimaryInstance<
|
|
|
161
162
|
readonly evaluator: EngineXPathEvaluator;
|
|
162
163
|
override readonly contextNode = this;
|
|
163
164
|
|
|
164
|
-
private readonly attributeState: AttributeState;
|
|
165
|
-
|
|
166
165
|
constructor(options: PrimaryInstanceOptions<Mode>) {
|
|
167
166
|
const { mode, initialState, scope, model, secondaryInstances, config } = options;
|
|
168
167
|
const { instance: modelInstance } = model;
|
|
@@ -202,10 +201,9 @@ export class PrimaryInstance<
|
|
|
202
201
|
this.classes = definition.classes;
|
|
203
202
|
|
|
204
203
|
const childrenState = createChildrenState<this, Root>(this);
|
|
205
|
-
|
|
204
|
+
this.attributeState = createAttributeState(this.scope);
|
|
206
205
|
|
|
207
206
|
this.getChildren = childrenState.getChildren;
|
|
208
|
-
this.attributeState = attributeState;
|
|
209
207
|
|
|
210
208
|
const stateSpec: PrimaryInstanceStateSpec = {
|
|
211
209
|
activeLanguage: getActiveLanguage,
|
|
@@ -218,7 +216,7 @@ export class PrimaryInstance<
|
|
|
218
216
|
valueOptions: null,
|
|
219
217
|
value: null,
|
|
220
218
|
children: childrenState.childIds,
|
|
221
|
-
attributes: attributeState.getAttributes,
|
|
219
|
+
attributes: this.attributeState.getAttributes,
|
|
222
220
|
};
|
|
223
221
|
|
|
224
222
|
const state = createSharedNodeState(scope, stateSpec, config);
|
|
@@ -239,10 +237,14 @@ export class PrimaryInstance<
|
|
|
239
237
|
this.instanceState = createPrimaryInstanceState(this);
|
|
240
238
|
|
|
241
239
|
childrenState.setChildren([root]);
|
|
242
|
-
attributeState.setAttributes(buildAttributes(this));
|
|
240
|
+
this.attributeState.setAttributes(buildAttributes(this));
|
|
243
241
|
setIsAttached(true);
|
|
244
242
|
}
|
|
245
243
|
|
|
244
|
+
override getAttributes(): readonly Attribute[] {
|
|
245
|
+
return this.attributeState.getAttributes();
|
|
246
|
+
}
|
|
247
|
+
|
|
246
248
|
// PrimaryInstanceDocument
|
|
247
249
|
/**
|
|
248
250
|
* @todo Note that this method's signature is intentionally derived from
|
|
@@ -292,8 +294,4 @@ export class PrimaryInstance<
|
|
|
292
294
|
|
|
293
295
|
return Promise.resolve(result);
|
|
294
296
|
}
|
|
295
|
-
|
|
296
|
-
getAttributes(): readonly Attribute[] {
|
|
297
|
-
return this.attributeState.getAttributes();
|
|
298
|
-
}
|
|
299
297
|
}
|