@getodk/xforms-engine 0.14.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.
Files changed (125) hide show
  1. package/dist/client/AttributeNode.d.ts +50 -0
  2. package/dist/client/BaseNode.d.ts +5 -0
  3. package/dist/client/form/FormInstanceConfig.d.ts +15 -0
  4. package/dist/client/index.d.ts +1 -0
  5. package/dist/client/node-types.d.ts +1 -1
  6. package/dist/client/validation.d.ts +7 -1
  7. package/dist/index.js +730 -294
  8. package/dist/index.js.map +1 -1
  9. package/dist/instance/Attribute.d.ts +64 -0
  10. package/dist/instance/Group.d.ts +2 -0
  11. package/dist/instance/InputControl.d.ts +2 -0
  12. package/dist/instance/PrimaryInstance.d.ts +2 -0
  13. package/dist/instance/Root.d.ts +2 -0
  14. package/dist/instance/UploadControl.d.ts +2 -0
  15. package/dist/instance/abstract/InstanceNode.d.ts +5 -2
  16. package/dist/instance/abstract/ValueNode.d.ts +2 -0
  17. package/dist/instance/attachments/buildAttributes.d.ts +7 -0
  18. package/dist/instance/internal-api/AttributeContext.d.ts +35 -0
  19. package/dist/instance/internal-api/InstanceConfig.d.ts +2 -0
  20. package/dist/instance/internal-api/InstanceValueContext.d.ts +6 -0
  21. package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +15 -0
  22. package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +2 -0
  23. package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +2 -2
  24. package/dist/instance/internal-api/serialization/ClientReactiveSerializableValueNode.d.ts +4 -0
  25. package/dist/instance/repeat/BaseRepeatRange.d.ts +5 -0
  26. package/dist/instance/repeat/RepeatInstance.d.ts +2 -2
  27. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +2 -2
  28. package/dist/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.d.ts +3 -0
  29. package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +0 -3
  30. package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +1 -1
  31. package/dist/lib/names/NamespaceDeclarationMap.d.ts +1 -1
  32. package/dist/lib/reactivity/createAttributeState.d.ts +16 -0
  33. package/dist/lib/reactivity/createInstanceValueState.d.ts +4 -1
  34. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +2 -2
  35. package/dist/lib/xml-serialization.d.ts +5 -9
  36. package/dist/parse/XFormDOM.d.ts +4 -1
  37. package/dist/parse/expression/ActionComputationExpression.d.ts +4 -0
  38. package/dist/parse/model/ActionDefinition.d.ts +15 -0
  39. package/dist/parse/model/AttributeDefinition.d.ts +24 -0
  40. package/dist/parse/model/{RootAttributeMap.d.ts → AttributeDefinitionMap.d.ts} +4 -10
  41. package/dist/parse/model/BindPreloadDefinition.d.ts +6 -10
  42. package/dist/parse/model/Event.d.ts +8 -0
  43. package/dist/parse/model/GroupDefinition.d.ts +4 -1
  44. package/dist/parse/model/LeafNodeDefinition.d.ts +5 -1
  45. package/dist/parse/model/ModelActionMap.d.ts +9 -0
  46. package/dist/parse/model/ModelDefinition.d.ts +8 -1
  47. package/dist/parse/model/NodeDefinition.d.ts +8 -3
  48. package/dist/parse/model/NoteNodeDefinition.d.ts +3 -2
  49. package/dist/parse/model/RangeNodeDefinition.d.ts +2 -1
  50. package/dist/parse/model/RepeatDefinition.d.ts +4 -1
  51. package/dist/parse/model/RootDefinition.d.ts +3 -2
  52. package/dist/solid.js +730 -294
  53. package/dist/solid.js.map +1 -1
  54. package/package.json +21 -17
  55. package/src/client/AttributeNode.ts +59 -0
  56. package/src/client/BaseNode.ts +6 -0
  57. package/src/client/form/FormInstanceConfig.ts +17 -0
  58. package/src/client/index.ts +1 -0
  59. package/src/client/node-types.ts +1 -0
  60. package/src/client/validation.ts +9 -1
  61. package/src/entrypoints/FormInstance.ts +1 -0
  62. package/src/instance/Attribute.ts +164 -0
  63. package/src/instance/Group.ts +7 -0
  64. package/src/instance/InputControl.ts +8 -0
  65. package/src/instance/ModelValue.ts +7 -0
  66. package/src/instance/Note.ts +6 -0
  67. package/src/instance/PrimaryInstance.ts +7 -0
  68. package/src/instance/RangeControl.ts +6 -0
  69. package/src/instance/RankControl.ts +7 -0
  70. package/src/instance/Root.ts +7 -0
  71. package/src/instance/SelectControl.ts +6 -0
  72. package/src/instance/TriggerControl.ts +6 -0
  73. package/src/instance/UploadControl.ts +5 -0
  74. package/src/instance/abstract/DescendantNode.ts +0 -1
  75. package/src/instance/abstract/InstanceNode.ts +4 -1
  76. package/src/instance/abstract/ValueNode.ts +2 -0
  77. package/src/instance/attachments/buildAttributes.ts +15 -0
  78. package/src/instance/children/normalizeChildInitOptions.ts +1 -1
  79. package/src/instance/internal-api/AttributeContext.ts +40 -0
  80. package/src/instance/internal-api/InstanceConfig.ts +6 -1
  81. package/src/instance/internal-api/InstanceValueContext.ts +6 -0
  82. package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +18 -0
  83. package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +2 -0
  84. package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +2 -3
  85. package/src/instance/internal-api/serialization/ClientReactiveSerializableValueNode.ts +4 -0
  86. package/src/instance/repeat/BaseRepeatRange.ts +14 -0
  87. package/src/instance/repeat/RepeatInstance.ts +5 -5
  88. package/src/integration/xpath/adapter/XFormsXPathNode.ts +3 -1
  89. package/src/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts +16 -0
  90. package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +5 -5
  91. package/src/lib/client-reactivity/instance-state/createRootInstanceState.ts +6 -9
  92. package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +5 -15
  93. package/src/lib/client-reactivity/instance-state/createValueNodeInstanceState.ts +2 -1
  94. package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +1 -0
  95. package/src/lib/codecs/NoteCodec.ts +1 -1
  96. package/src/lib/codecs/items/SingleValueItemCodec.ts +1 -3
  97. package/src/lib/names/NamespaceDeclarationMap.ts +1 -1
  98. package/src/lib/reactivity/createAttributeState.ts +51 -0
  99. package/src/lib/reactivity/createInstanceValueState.ts +152 -53
  100. package/src/lib/reactivity/node-state/createSharedNodeState.ts +2 -2
  101. package/src/lib/xml-serialization.ts +38 -34
  102. package/src/parse/XFormDOM.ts +9 -0
  103. package/src/parse/body/GroupElementDefinition.ts +1 -1
  104. package/src/parse/body/control/InputControlDefinition.ts +1 -1
  105. package/src/parse/expression/ActionComputationExpression.ts +12 -0
  106. package/src/parse/model/ActionDefinition.ts +70 -0
  107. package/src/parse/model/AttributeDefinition.ts +59 -0
  108. package/src/parse/model/{RootAttributeMap.ts → AttributeDefinitionMap.ts} +7 -13
  109. package/src/parse/model/BindDefinition.ts +1 -6
  110. package/src/parse/model/BindPreloadDefinition.ts +44 -12
  111. package/src/parse/model/Event.ts +9 -0
  112. package/src/parse/model/GroupDefinition.ts +6 -0
  113. package/src/parse/model/LeafNodeDefinition.ts +5 -0
  114. package/src/parse/model/ModelActionMap.ts +37 -0
  115. package/src/parse/model/ModelDefinition.ts +18 -3
  116. package/src/parse/model/NodeDefinition.ts +11 -3
  117. package/src/parse/model/NoteNodeDefinition.ts +5 -2
  118. package/src/parse/model/RangeNodeDefinition.ts +5 -2
  119. package/src/parse/model/RepeatDefinition.ts +8 -1
  120. package/src/parse/model/RootDefinition.ts +27 -9
  121. package/src/parse/model/nodeDefinitionMap.ts +1 -1
  122. package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +0 -22
  123. package/dist/parse/model/RootAttributeDefinition.d.ts +0 -21
  124. package/src/error/TemplatedNodeAttributeSerializationError.ts +0 -24
  125. package/src/parse/model/RootAttributeDefinition.ts +0 -44
@@ -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,6 +178,7 @@ export class RankControl
174
178
  label: createNodeLabel(this, definition),
175
179
  hint: createFieldHint(this, definition),
176
180
  children: null,
181
+ attributes: attributeState.getAttributes,
177
182
  valueOptions,
178
183
  value: valueState,
179
184
  instanceValue: this.getInstanceValue,
@@ -181,6 +186,8 @@ export class RankControl
181
186
  this.instanceConfig
182
187
  );
183
188
 
189
+ attributeState.setAttributes(buildAttributes(this));
190
+
184
191
  this.state = state;
185
192
  this.engineState = state.engineState;
186
193
  this.currentState = state.currentState;
@@ -12,6 +12,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
15
16
  import type { ChildrenState } from '../lib/reactivity/createChildrenState.ts';
16
17
  import { createChildrenState } from '../lib/reactivity/createChildrenState.ts';
17
18
  import type { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
@@ -24,6 +25,8 @@ import { createAggregatedViolations } from '../lib/reactivity/validation/createA
24
25
  import type { BodyClassList } from '../parse/body/BodyDefinition.ts';
25
26
  import type { RootDefinition } from '../parse/model/RootDefinition.ts';
26
27
  import { DescendantNode } from './abstract/DescendantNode.ts';
28
+ import { buildAttributes } from './attachments/buildAttributes.ts';
29
+ import { Attribute } from './Attribute.ts';
27
30
  import { buildChildren } from './children/buildChildren.ts';
28
31
  import type { GeneralChildNode } from './hierarchy.ts';
29
32
  import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
@@ -39,6 +42,7 @@ interface RootStateSpec {
39
42
  readonly label: null;
40
43
  readonly hint: null;
41
44
  readonly children: Accessor<readonly FormNodeID[]>;
45
+ readonly attributes: Accessor<readonly Attribute[]>;
42
46
  readonly valueOptions: null;
43
47
  readonly value: null;
44
48
 
@@ -95,6 +99,7 @@ export class Root
95
99
  this.classes = parent.classes;
96
100
 
97
101
  const childrenState = createChildrenState<Root, GeneralChildNode>(this);
102
+ const attributeState = createAttributeState(this.scope);
98
103
 
99
104
  this.childrenState = childrenState;
100
105
  this.languages = parent.languages;
@@ -112,6 +117,7 @@ export class Root
112
117
  valueOptions: null,
113
118
  value: null,
114
119
  children: childrenState.childIds,
120
+ attributes: attributeState.getAttributes,
115
121
  },
116
122
  this.instanceConfig
117
123
  );
@@ -125,6 +131,7 @@ export class Root
125
131
  );
126
132
 
127
133
  childrenState.setChildren(buildChildren(this));
134
+ attributeState.setAttributes(buildAttributes(this));
128
135
  this.validationState = createAggregatedViolations(this, this.instanceConfig);
129
136
  this.instanceState = createRootInstanceState(this);
130
137
  }
@@ -14,6 +14,7 @@ import { SelectValueTypeError } from '../error/SelectValueTypeError.ts';
14
14
  import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
15
15
  import type { StaticLeafElement } from '../integration/xpath/static-dom/StaticElement.ts';
16
16
  import { getSelectCodec } from '../lib/codecs/getSelectCodec.ts';
17
+ import { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
17
18
  import { createItemCollection } from '../lib/reactivity/createItemCollection.ts';
18
19
  import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
19
20
  import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
@@ -26,6 +27,7 @@ import type { SelectType } from '../parse/body/control/SelectControlDefinition.t
26
27
  import type { Root } from './Root.ts';
27
28
  import type { ValueNodeStateSpec } from './abstract/ValueNode.ts';
28
29
  import { ValueNode } from './abstract/ValueNode.ts';
30
+ import { buildAttributes } from './attachments/buildAttributes.ts';
29
31
  import type { GeneralParentNode } from './hierarchy.ts';
30
32
  import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
31
33
  import type { ValidationContext } from './internal-api/ValidationContext.ts';
@@ -108,6 +110,7 @@ export class SelectControl
108
110
 
109
111
  this.appearances = definition.bodyElement.appearances;
110
112
  this.selectType = definition.bodyElement.type;
113
+ const attributeState = createAttributeState(this.scope);
111
114
 
112
115
  const valueOptions = createItemCollection(this);
113
116
 
@@ -153,6 +156,7 @@ export class SelectControl
153
156
  label: createNodeLabel(this, definition),
154
157
  hint: createFieldHint(this, definition),
155
158
  children: null,
159
+ attributes: attributeState.getAttributes,
156
160
  valueOptions,
157
161
  value: valueState,
158
162
  instanceValue: this.getInstanceValue,
@@ -161,6 +165,8 @@ export class SelectControl
161
165
  this.instanceConfig
162
166
  );
163
167
 
168
+ attributeState.setAttributes(buildAttributes(this));
169
+
164
170
  this.state = state;
165
171
  this.engineState = state.engineState;
166
172
  this.currentState = state.currentState;
@@ -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 type { TriggerInputValue, TriggerRuntimeValue } from '../lib/codecs/TriggerCodec.ts';
10
10
  import { TriggerCodec } from '../lib/codecs/TriggerCodec.ts';
11
+ import { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
11
12
  import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
12
13
  import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
13
14
  import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
@@ -17,6 +18,7 @@ import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
17
18
  import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
18
19
  import type { Root } from './Root.ts';
19
20
  import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
21
+ import { buildAttributes } from './attachments/buildAttributes.ts';
20
22
  import type { GeneralParentNode } from './hierarchy.ts';
21
23
  import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
22
24
  import type { ValidationContext } from './internal-api/ValidationContext.ts';
@@ -88,6 +90,7 @@ export class TriggerControl
88
90
  super(parent, instanceNode, definition, codec);
89
91
 
90
92
  this.appearances = definition.bodyElement.appearances;
93
+ const attributeState = createAttributeState(this.scope);
91
94
 
92
95
  const state = createSharedNodeState(
93
96
  this.scope,
@@ -100,6 +103,7 @@ export class TriggerControl
100
103
  label: createNodeLabel(this, definition),
101
104
  hint: createFieldHint(this, definition),
102
105
  children: null,
106
+ attributes: attributeState.getAttributes,
103
107
  valueOptions: null,
104
108
  value: this.valueState,
105
109
  instanceValue: this.getInstanceValue,
@@ -107,6 +111,8 @@ export class TriggerControl
107
111
  this.instanceConfig
108
112
  );
109
113
 
114
+ attributeState.setAttributes(buildAttributes(this));
115
+
110
116
  this.state = state;
111
117
  this.engineState = state.engineState;
112
118
  this.currentState = state.currentState;
@@ -9,6 +9,7 @@ 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 { createAttributeState } from '../lib/reactivity/createAttributeState.ts';
12
13
  import { createInstanceAttachment } from '../lib/reactivity/createInstanceAttachment.ts';
13
14
  import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
14
15
  import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
@@ -20,6 +21,7 @@ import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
20
21
  import type { SharedValidationState } from '../lib/reactivity/validation/createValidation.ts';
21
22
  import { createValidationState } from '../lib/reactivity/validation/createValidation.ts';
22
23
  import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
24
+ import type { Attribute } from './Attribute.ts';
23
25
  import type { Root } from './Root.ts';
24
26
  import type { DescendantNodeStateSpec } from './abstract/DescendantNode.ts';
25
27
  import { DescendantNode } from './abstract/DescendantNode.ts';
@@ -57,6 +59,7 @@ interface UploadControlStateSpec extends DescendantNodeStateSpec<InstanceAttachm
57
59
  readonly label: Accessor<TextRange<'label'> | null>;
58
60
  readonly hint: Accessor<TextRange<'hint'> | null>;
59
61
  readonly children: null;
62
+ readonly attributes: Accessor<readonly Attribute[]>;
60
63
  readonly valueOptions: null;
61
64
  readonly value: SimpleAtomicState<InstanceAttachmentRuntimeValue>;
62
65
  readonly instanceValue: Accessor<InstanceAttachmentFileName>;
@@ -133,6 +136,7 @@ export class UploadControl
133
136
  const instanceAttachment = createInstanceAttachment(this);
134
137
 
135
138
  this.instanceAttachment = instanceAttachment;
139
+ const attributeState = createAttributeState(this.scope);
136
140
  this.decodeInstanceValue = instanceAttachment.decodeInstanceValue;
137
141
  this.getXPathValue = instanceAttachment.getInstanceValue;
138
142
 
@@ -149,6 +153,7 @@ export class UploadControl
149
153
  children: null,
150
154
  valueOptions: null,
151
155
  value: instanceAttachment.valueState,
156
+ attributes: attributeState.getAttributes,
152
157
  instanceValue: instanceAttachment.getInstanceValue,
153
158
  },
154
159
  this.instanceConfig
@@ -167,7 +167,6 @@ export abstract class DescendantNode<
167
167
  return true;
168
168
  }
169
169
  }
170
-
171
170
  return false;
172
171
  });
173
172
  });
@@ -13,6 +13,7 @@ import type {
13
13
  XFormsXPathPrimaryInstanceNodeKind,
14
14
  } from '../../integration/xpath/adapter/XFormsXPathNode.ts';
15
15
  import type { PrimaryInstanceXPathNode } from '../../integration/xpath/adapter/kind.ts';
16
+ import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
16
17
  import type { StaticDocument } from '../../integration/xpath/static-dom/StaticDocument.ts';
17
18
  import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
18
19
  import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
@@ -24,6 +25,7 @@ import { createReactiveScope } from '../../lib/reactivity/scope.ts';
24
25
  import type { SimpleAtomicState } from '../../lib/reactivity/types.ts';
25
26
  import { createUniqueId } from '../../lib/unique-id.ts';
26
27
  import type { AnyNodeDefinition } from '../../parse/model/NodeDefinition.ts';
28
+ import type { Attribute } from '../Attribute.ts';
27
29
  import type { PrimaryInstance } from '../PrimaryInstance.ts';
28
30
  import type { Root } from '../Root.ts';
29
31
  import type { AnyChildNode, AnyNode, AnyParentNode } from '../hierarchy.ts';
@@ -51,6 +53,7 @@ export interface InstanceNodeStateSpec<Value = never> {
51
53
  readonly label: Accessor<TextRange<'label'> | null> | null;
52
54
  readonly hint: Accessor<TextRange<'hint'> | null> | null;
53
55
  readonly children: Accessor<readonly FormNodeID[]> | null;
56
+ readonly attributes: Accessor<readonly Attribute[]> | null;
54
57
  readonly valueOptions: InstanceNodeValueOptionsStateSpec;
55
58
  readonly value: Signal<Value> | SimpleAtomicState<Value> | null;
56
59
  }
@@ -191,7 +194,7 @@ export abstract class InstanceNode<
191
194
  constructor(
192
195
  readonly instanceConfig: InstanceConfig,
193
196
  readonly parent: Parent,
194
- readonly instanceNode: StaticDocument | StaticElement | null,
197
+ readonly instanceNode: StaticAttribute | StaticDocument | StaticElement | null,
195
198
  readonly definition: Definition,
196
199
  options?: InstanceNodeOptions
197
200
  ) {
@@ -21,6 +21,7 @@ import type { SimpleAtomicState } from '../../lib/reactivity/types.ts';
21
21
  import type { SharedValidationState } from '../../lib/reactivity/validation/createValidation.ts';
22
22
  import { createValidationState } from '../../lib/reactivity/validation/createValidation.ts';
23
23
  import { LeafNodeDefinition } from '../../parse/model/LeafNodeDefinition.ts';
24
+ import type { Attribute } from '../Attribute.ts';
24
25
  import type { GeneralParentNode } from '../hierarchy.ts';
25
26
  import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
26
27
  import type {
@@ -36,6 +37,7 @@ export type ValueNodeDefinition<V extends ValueType> = LeafNodeDefinition<V>;
36
37
 
37
38
  export interface ValueNodeStateSpec<RuntimeValue> extends DescendantNodeStateSpec<RuntimeValue> {
38
39
  readonly children: null;
40
+ readonly attributes: Accessor<readonly Attribute[]>;
39
41
  readonly value: SimpleAtomicState<RuntimeValue>;
40
42
  readonly instanceValue: Accessor<string>;
41
43
  }
@@ -0,0 +1,15 @@
1
+ import { Attribute } from '../Attribute';
2
+ import type { AnyNode } from '../hierarchy.ts';
3
+ import type { InputControl } from '../InputControl.ts';
4
+ import type { ModelValue } from '../ModelValue.ts';
5
+ import type { Note } from '../Note.ts';
6
+ import type { RangeControl } from '../RangeControl.ts';
7
+
8
+ export function buildAttributes(
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ owner: AnyNode | InputControl<any> | ModelValue<any> | Note<any> | RangeControl<any>
11
+ ): Attribute[] {
12
+ return Array.from(owner.definition.attributes.values()).map((attributeDefinition) => {
13
+ return new Attribute(owner, attributeDefinition, attributeDefinition.template);
14
+ });
15
+ }
@@ -217,7 +217,7 @@ const buildDeprecatedIDDefinition = (
217
217
  const nodeset = instanceNode.nodeset;
218
218
  const bind = group.model.binds.getOrCreateBindDefinition(nodeset);
219
219
 
220
- return new LeafNodeDefinition(group.parent.definition, bind, null, instanceNode);
220
+ return new LeafNodeDefinition(group.model, group.parent.definition, bind, null, instanceNode);
221
221
  };
222
222
 
223
223
  const buildDeprecatedID = (
@@ -0,0 +1,40 @@
1
+ import type { Accessor } from 'solid-js';
2
+ import type { FormInstanceInitializationMode } from '../../client/index.ts';
3
+ import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
4
+ import type { ReactiveScope } from '../../lib/reactivity/scope.ts';
5
+ import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
6
+ import type { AnyBindPreloadDefinition } from '../../parse/model/BindPreloadDefinition.ts';
7
+ import type { ModelDefinition } from '../../parse/model/ModelDefinition.ts';
8
+ import type { EvaluationContext } from './EvaluationContext.ts';
9
+ import type { InstanceConfig } from './InstanceConfig.ts';
10
+
11
+ export interface InstanceAttributeContextDocument {
12
+ readonly initializationMode: FormInstanceInitializationMode;
13
+ readonly isAttached: Accessor<boolean>;
14
+ }
15
+
16
+ export type DecodeInstanceValue = (value: string) => string;
17
+
18
+ interface InstanceAttributeContextDefinitionBind {
19
+ readonly preload: AnyBindPreloadDefinition | null;
20
+ readonly calculate: BindComputationExpression<'calculate'> | null;
21
+ readonly readonly: BindComputationExpression<'readonly'>;
22
+ }
23
+
24
+ export interface InstanceAttributeContextDefinition {
25
+ readonly bind: InstanceAttributeContextDefinitionBind;
26
+ readonly template: StaticAttribute;
27
+ readonly model: ModelDefinition;
28
+ }
29
+
30
+ export interface AttributeContext extends EvaluationContext {
31
+ readonly scope: ReactiveScope;
32
+ readonly rootDocument: InstanceAttributeContextDocument;
33
+ readonly definition: InstanceAttributeContextDefinition;
34
+ readonly instanceNode: StaticAttribute;
35
+ readonly instanceConfig: InstanceConfig;
36
+ readonly decodeInstanceValue: DecodeInstanceValue;
37
+
38
+ isReadonly(): boolean;
39
+ isRelevant(): boolean;
40
+ }
@@ -1,5 +1,8 @@
1
1
  import type { InstanceAttachmentFileNameFactory } from '../../client/attachments/InstanceAttachmentsConfig.ts';
2
- import type { FormInstanceConfig } from '../../client/form/FormInstanceConfig.ts';
2
+ import type {
3
+ FormInstanceConfig,
4
+ PreloadProperties,
5
+ } from '../../client/form/FormInstanceConfig.ts';
3
6
  import type { OpaqueReactiveObjectFactory } from '../../client/OpaqueReactiveObjectFactory.ts';
4
7
 
5
8
  export interface InstanceConfig {
@@ -9,4 +12,6 @@ export interface InstanceConfig {
9
12
  readonly clientStateFactory: OpaqueReactiveObjectFactory;
10
13
 
11
14
  readonly computeAttachmentName: InstanceAttachmentFileNameFactory;
15
+
16
+ readonly preloadProperties: PreloadProperties;
12
17
  }
@@ -1,12 +1,16 @@
1
+ import type { Accessor } from 'solid-js';
1
2
  import type { FormInstanceInitializationMode } from '../../client/index.ts';
2
3
  import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
3
4
  import type { ReactiveScope } from '../../lib/reactivity/scope.ts';
4
5
  import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
5
6
  import type { AnyBindPreloadDefinition } from '../../parse/model/BindPreloadDefinition.ts';
7
+ import type { ModelDefinition } from '../../parse/model/ModelDefinition.ts';
6
8
  import type { EvaluationContext } from './EvaluationContext.ts';
9
+ import type { InstanceConfig } from './InstanceConfig.ts';
7
10
 
8
11
  export interface InstanceValueContextDocument {
9
12
  readonly initializationMode: FormInstanceInitializationMode;
13
+ readonly isAttached: Accessor<boolean>;
10
14
  }
11
15
 
12
16
  export type DecodeInstanceValue = (value: string) => string;
@@ -20,6 +24,7 @@ interface InstanceValueContextDefinitionBind {
20
24
  export interface InstanceValueContextDefinition {
21
25
  readonly bind: InstanceValueContextDefinitionBind;
22
26
  readonly template: StaticLeafElement;
27
+ readonly model: ModelDefinition;
23
28
  }
24
29
 
25
30
  export interface InstanceValueContext extends EvaluationContext {
@@ -27,6 +32,7 @@ export interface InstanceValueContext extends EvaluationContext {
27
32
  readonly rootDocument: InstanceValueContextDocument;
28
33
  readonly definition: InstanceValueContextDefinition;
29
34
  readonly instanceNode: StaticLeafElement | null;
35
+ readonly instanceConfig: InstanceConfig;
30
36
  readonly decodeInstanceValue: DecodeInstanceValue;
31
37
 
32
38
  isReadonly(): boolean;
@@ -0,0 +1,18 @@
1
+ import type { InstanceState } from '../../../client/serialization/InstanceState.ts';
2
+ import type { QualifiedName } from '../../../lib/names/QualifiedName.ts';
3
+
4
+ export type SerializedInstanceValue = string;
5
+
6
+ interface ClientReactiveSerializableAttributeNodeCurrentState {
7
+ get instanceValue(): SerializedInstanceValue;
8
+ }
9
+
10
+ interface ClientReactiveSerializableAttributeNodeDefinition {
11
+ readonly qualifiedName: QualifiedName;
12
+ }
13
+
14
+ export interface ClientReactiveSerializableAttributeNode {
15
+ readonly definition: ClientReactiveSerializableAttributeNodeDefinition;
16
+ readonly currentState: ClientReactiveSerializableAttributeNodeCurrentState;
17
+ readonly instanceState: InstanceState;
18
+ }
@@ -1,5 +1,6 @@
1
1
  import type { InstanceState } from '../../../client/serialization/InstanceState.ts';
2
2
  import type { QualifiedName } from '../../../lib/names/QualifiedName.ts';
3
+ import type { Attribute } from '../../Attribute.ts';
3
4
 
4
5
  export interface ClientReactiveSerializableChildNode {
5
6
  readonly instanceState: InstanceState;
@@ -10,6 +11,7 @@ export interface ClientReactiveSerializableParentNodeCurrentState<
10
11
  > {
11
12
  get relevant(): boolean;
12
13
  get children(): readonly Child[];
14
+ get attributes(): readonly Attribute[];
13
15
  }
14
16
 
15
17
  export interface ClientReactiveSerializableParentNodeDefinition {
@@ -1,5 +1,5 @@
1
- import type { TemplatedNodeAttributeSerializationError } from '../../../error/TemplatedNodeAttributeSerializationError.ts';
2
1
  import type { StaticElement } from '../../../integration/xpath/static-dom/StaticElement.ts';
2
+ import type { Attribute } from '../../Attribute.ts';
3
3
  import type { GeneralChildNode } from '../../hierarchy.ts';
4
4
  import type {
5
5
  ClientReactiveSerializableParentNode,
@@ -9,8 +9,7 @@ import type {
9
9
 
10
10
  export interface ClientReactiveSerializableTemplatedNodeCurrentState
11
11
  extends ClientReactiveSerializableParentNodeCurrentState<GeneralChildNode> {
12
- /** @see {@link TemplatedNodeAttributeSerializationError} */
13
- get attributes(): unknown;
12
+ get attributes(): readonly Attribute[];
14
13
  }
15
14
 
16
15
  export interface ClientReactiveSerializableTemplatedNodeDefinition
@@ -1,5 +1,7 @@
1
1
  import type { InstanceState } from '../../../client/serialization/InstanceState.ts';
2
2
  import type { QualifiedName } from '../../../lib/names/QualifiedName.ts';
3
+ import type { BindDefinition } from '../../../parse/model/BindDefinition.ts';
4
+ import type { Attribute } from '../../Attribute.ts';
3
5
  import type {
4
6
  ClientReactiveSerializableChildNode,
5
7
  ClientReactiveSerializableParentNode,
@@ -14,10 +16,12 @@ interface ClientReactiveSerializableValueNodeCurrentState {
14
16
  * @todo Consider moving into {@link InstanceState}
15
17
  */
16
18
  get instanceValue(): SerializedInstanceValue;
19
+ get attributes(): readonly Attribute[];
17
20
  }
18
21
 
19
22
  interface ClientReactiveSerializableValueNodeDefinition {
20
23
  readonly qualifiedName: QualifiedName;
24
+ readonly bind: BindDefinition;
21
25
  }
22
26
 
23
27
  export interface ClientReactiveSerializableValueNode {
@@ -17,6 +17,10 @@ import type {
17
17
  import { XFORMS_XPATH_NODE_RANGE_KIND } from '../../integration/xpath/adapter/XFormsXPathNode.ts';
18
18
  import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
19
19
  import { createNodeRangeInstanceState } from '../../lib/client-reactivity/instance-state/createNodeRangeInstanceState.ts';
20
+ import {
21
+ createAttributeState,
22
+ type AttributeState,
23
+ } from '../../lib/reactivity/createAttributeState.ts';
20
24
  import type { ChildrenState } from '../../lib/reactivity/createChildrenState.ts';
21
25
  import { createChildrenState } from '../../lib/reactivity/createChildrenState.ts';
22
26
  import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
@@ -32,6 +36,7 @@ import type {
32
36
  DescendantNodeSharedStateSpec,
33
37
  } from '../abstract/DescendantNode.ts';
34
38
  import { DescendantNode } from '../abstract/DescendantNode.ts';
39
+ import type { Attribute } from '../Attribute.ts';
35
40
  import type { GeneralParentNode, RepeatRange } from '../hierarchy.ts';
36
41
  import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
37
42
  import type { ClientReactiveSerializableParentNode } from '../internal-api/serialization/ClientReactiveSerializableParentNode.ts';
@@ -41,6 +46,7 @@ interface RepeatRangeStateSpec extends DescendantNodeSharedStateSpec {
41
46
  readonly hint: null;
42
47
  readonly label: Accessor<TextRange<'label'> | null>;
43
48
  readonly children: Accessor<readonly FormNodeID[]>;
49
+ readonly attributes: Accessor<readonly Attribute[]>;
44
50
  readonly valueOptions: null;
45
51
  readonly value: null;
46
52
  }
@@ -60,6 +66,7 @@ export abstract class BaseRepeatRange<Definition extends AnyRepeatDefinition>
60
66
  ClientReactiveSerializableParentNode<RepeatInstance>
61
67
  {
62
68
  protected readonly childrenState: ChildrenState<RepeatInstance>;
69
+ protected readonly attributeState: AttributeState;
63
70
 
64
71
  /**
65
72
  * A repeat range doesn't have a corresponding primary instance element of its
@@ -156,8 +163,10 @@ export abstract class BaseRepeatRange<Definition extends AnyRepeatDefinition>
156
163
  const repeatRange = this as AnyDescendantNode as RepeatRange;
157
164
 
158
165
  const childrenState = createChildrenState<RepeatRange, RepeatInstance>(repeatRange);
166
+ const attributeState = createAttributeState(this.scope);
159
167
 
160
168
  this.childrenState = childrenState;
169
+ this.attributeState = attributeState;
161
170
 
162
171
  const state = createSharedNodeState(
163
172
  this.scope,
@@ -170,6 +179,7 @@ export abstract class BaseRepeatRange<Definition extends AnyRepeatDefinition>
170
179
  label: createNodeLabel(this, definition),
171
180
  hint: null,
172
181
  children: childrenState.childIds,
182
+ attributes: attributeState.getAttributes,
173
183
  valueOptions: null,
174
184
  value: null,
175
185
  },
@@ -260,4 +270,8 @@ export abstract class BaseRepeatRange<Definition extends AnyRepeatDefinition>
260
270
  getChildren(): readonly RepeatInstance[] {
261
271
  return this.childrenState.getChildren();
262
272
  }
273
+
274
+ getAttributes(): readonly Attribute[] {
275
+ return this.attributeState.getAttributes();
276
+ }
263
277
  }
@@ -10,10 +10,10 @@ import type {
10
10
  import type { InstanceState } from '../../client/serialization/InstanceState.ts';
11
11
  import type { TextRange } from '../../client/TextRange.ts';
12
12
  import type { AncestorNodeValidationState } from '../../client/validation.ts';
13
- import type { TemplatedNodeAttributeSerializationError } from '../../error/TemplatedNodeAttributeSerializationError.ts';
14
13
  import type { XFormsXPathElement } from '../../integration/xpath/adapter/XFormsXPathNode.ts';
15
14
  import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
16
15
  import { createTemplatedNodeInstanceState } from '../../lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts';
16
+ import { createAttributeState } from '../../lib/reactivity/createAttributeState.ts';
17
17
  import type { ChildrenState } from '../../lib/reactivity/createChildrenState.ts';
18
18
  import { createChildrenState } from '../../lib/reactivity/createChildrenState.ts';
19
19
  import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
@@ -26,6 +26,7 @@ import { createNodeLabel } from '../../lib/reactivity/text/createNodeLabel.ts';
26
26
  import { createAggregatedViolations } from '../../lib/reactivity/validation/createAggregatedViolations.ts';
27
27
  import type { DescendantNodeSharedStateSpec } from '../abstract/DescendantNode.ts';
28
28
  import { DescendantNode } from '../abstract/DescendantNode.ts';
29
+ import type { Attribute } from '../Attribute.ts';
29
30
  import { buildChildren } from '../children/buildChildren.ts';
30
31
  import type { GeneralChildNode, RepeatRange } from '../hierarchy.ts';
31
32
  import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
@@ -35,9 +36,7 @@ interface RepeatInstanceStateSpec extends DescendantNodeSharedStateSpec {
35
36
  readonly label: Accessor<TextRange<'label'> | null>;
36
37
  readonly hint: null;
37
38
 
38
- /** @see {@link TemplatedNodeAttributeSerializationError} */
39
- readonly attributes: null;
40
-
39
+ readonly attributes: Accessor<readonly Attribute[]>;
41
40
  readonly children: Accessor<readonly FormNodeID[]>;
42
41
  readonly valueOptions: null;
43
42
  readonly value: null;
@@ -132,6 +131,7 @@ export class RepeatInstance
132
131
  this.appearances = definition.bodyElement.appearances;
133
132
 
134
133
  const childrenState = createChildrenState<RepeatInstance, GeneralChildNode>(this);
134
+ const attributeState = createAttributeState(this.scope);
135
135
 
136
136
  this.childrenState = childrenState;
137
137
  this.currentIndex = currentIndex;
@@ -147,7 +147,7 @@ export class RepeatInstance
147
147
  // TODO: only-child <group><label>
148
148
  label: createNodeLabel(this, definition),
149
149
  hint: null,
150
- attributes: null,
150
+ attributes: attributeState.getAttributes,
151
151
  children: childrenState.childIds,
152
152
  valueOptions: null,
153
153
  value: null,
@@ -97,7 +97,8 @@ export type XFormsXPathDescendantNodeKind =
97
97
  | XFormsXPathNodeRangeKind
98
98
  | XPathElementKind
99
99
  | XPathTextKind
100
- | XPathCommentKind;
100
+ | XPathCommentKind
101
+ | XPathAttributeKind;
101
102
 
102
103
  export interface XFormsXPathDescendantNode extends XFormsXPathNode {
103
104
  readonly [XPathNodeKindKey]: XFormsXPathDescendantNodeKind;
@@ -109,6 +110,7 @@ export type XFormsXPathPrimaryInstanceNodeKind =
109
110
  | XPathDocumentKind
110
111
  | XFormsXPathNodeRangeKind
111
112
  | XPathElementKind
113
+ | XPathAttributeKind
112
114
  | XPathTextKind;
113
115
 
114
116
  export interface XFormsXPathPrimaryInstanceNode extends XFormsXPathNode {
@@ -0,0 +1,16 @@
1
+ import type { InstanceState } from '../../../client/serialization/InstanceState.ts';
2
+ import type { ClientReactiveSerializableAttributeNode } from '../../../instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts';
3
+ import { escapeXMLText, serializeAttributeXML } from '../../xml-serialization.ts';
4
+
5
+ export const createAttributeNodeInstanceState = (
6
+ node: ClientReactiveSerializableAttributeNode
7
+ ): InstanceState => {
8
+ const { qualifiedName } = node.definition;
9
+
10
+ return {
11
+ get instanceXML() {
12
+ const xmlValue = escapeXMLText(node.currentState.instanceValue, true);
13
+ return serializeAttributeXML(qualifiedName, xmlValue);
14
+ },
15
+ };
16
+ };
@@ -12,11 +12,11 @@ export const createParentNodeInstanceState = (
12
12
  return '';
13
13
  }
14
14
 
15
- const serializedChildren = node.currentState.children.map((child) => {
16
- return child.instanceState.instanceXML;
17
- });
18
-
19
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren);
15
+ return serializeParentElementXML(
16
+ node.definition.qualifiedName,
17
+ node.currentState.children,
18
+ node.currentState.attributes
19
+ );
20
20
  },
21
21
  };
22
22
  };
@@ -5,15 +5,12 @@ import { serializeParentElementXML } from '../../xml-serialization.ts';
5
5
  export const createRootInstanceState = (node: Root): InstanceState => {
6
6
  return {
7
7
  get instanceXML() {
8
- const { namespaceDeclarations, attributes } = node.definition;
9
- const serializedChildren = node.currentState.children.map((child) => {
10
- return child.instanceState.instanceXML;
11
- });
12
-
13
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren, {
14
- namespaceDeclarations,
15
- attributes: Array.from(attributes.values()),
16
- });
8
+ return serializeParentElementXML(
9
+ node.definition.qualifiedName,
10
+ node.currentState.children,
11
+ node.currentState.attributes,
12
+ node.definition.namespaceDeclarations
13
+ );
17
14
  },
18
15
  };
19
16
  };