@getodk/xforms-engine 0.2.0 → 0.4.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 (292) hide show
  1. package/dist/client/BaseNode.d.ts +69 -4
  2. package/dist/client/EngineConfig.d.ts +0 -1
  3. package/dist/client/GroupNode.d.ts +4 -3
  4. package/dist/client/ModelValueNode.d.ts +36 -0
  5. package/dist/client/NodeAppearances.d.ts +1 -2
  6. package/dist/client/NoteNode.d.ts +52 -0
  7. package/dist/client/RootNode.d.ts +4 -3
  8. package/dist/client/SelectNode.d.ts +6 -5
  9. package/dist/client/StringNode.d.ts +6 -5
  10. package/dist/client/SubtreeNode.d.ts +3 -2
  11. package/dist/client/TextRange.d.ts +85 -3
  12. package/dist/client/TriggerNode.d.ts +25 -0
  13. package/dist/client/constants.d.ts +8 -0
  14. package/dist/client/hierarchy.d.ts +19 -10
  15. package/dist/client/index.d.ts +0 -1
  16. package/dist/client/node-types.d.ts +3 -1
  17. package/dist/client/{RepeatRangeNode.d.ts → repeat/BaseRepeatRangeNode.d.ts} +18 -18
  18. package/dist/client/{RepeatInstanceNode.d.ts → repeat/RepeatInstanceNode.d.ts} +9 -9
  19. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +18 -0
  20. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +19 -0
  21. package/dist/client/unsupported/RangeNode.d.ts +9 -0
  22. package/dist/client/unsupported/RankNode.d.ts +9 -0
  23. package/dist/client/unsupported/UnsupportedControlNode.d.ts +32 -0
  24. package/dist/client/unsupported/UploadNode.d.ts +9 -0
  25. package/dist/client/validation.d.ts +162 -0
  26. package/dist/index.d.ts +14 -6
  27. package/dist/index.js +39696 -36151
  28. package/dist/index.js.map +1 -1
  29. package/dist/instance/Group.d.ts +3 -2
  30. package/dist/instance/ModelValue.d.ts +39 -0
  31. package/dist/instance/Note.d.ts +41 -0
  32. package/dist/instance/Root.d.ts +5 -4
  33. package/dist/instance/SelectField.d.ts +11 -6
  34. package/dist/instance/StringField.d.ts +12 -7
  35. package/dist/instance/Subtree.d.ts +2 -1
  36. package/dist/instance/TriggerControl.d.ts +40 -0
  37. package/dist/instance/abstract/DescendantNode.d.ts +8 -10
  38. package/dist/instance/abstract/InstanceNode.d.ts +3 -2
  39. package/dist/instance/abstract/UnsupportedControl.d.ts +46 -0
  40. package/dist/instance/children.d.ts +0 -1
  41. package/dist/instance/hierarchy.d.ts +15 -6
  42. package/dist/instance/index.d.ts +0 -1
  43. package/dist/instance/internal-api/EvaluationContext.d.ts +0 -1
  44. package/dist/instance/internal-api/InstanceConfig.d.ts +0 -1
  45. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -1
  46. package/dist/instance/internal-api/TranslationContext.d.ts +0 -1
  47. package/dist/instance/internal-api/ValidationContext.d.ts +28 -0
  48. package/dist/instance/internal-api/ValueContext.d.ts +3 -4
  49. package/dist/instance/{RepeatRange.d.ts → repeat/BaseRepeatRange.d.ts} +46 -46
  50. package/dist/instance/{RepeatInstance.d.ts → repeat/RepeatInstance.d.ts} +13 -13
  51. package/dist/instance/repeat/RepeatRangeControlled.d.ts +15 -0
  52. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +34 -0
  53. package/dist/instance/resource.d.ts +0 -1
  54. package/dist/instance/text/TextChunk.d.ts +0 -1
  55. package/dist/instance/text/TextRange.d.ts +4 -5
  56. package/dist/instance/unsupported/RangeControl.d.ts +4 -0
  57. package/dist/instance/unsupported/RankControl.d.ts +4 -0
  58. package/dist/instance/unsupported/UploadControl.d.ts +4 -0
  59. package/dist/lib/TokenListParser.d.ts +3 -3
  60. package/dist/lib/dom/query.d.ts +1 -2
  61. package/dist/lib/reactivity/createChildrenState.d.ts +0 -1
  62. package/dist/lib/reactivity/createComputedExpression.d.ts +7 -3
  63. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +4 -0
  64. package/dist/lib/reactivity/createSelectItems.d.ts +0 -1
  65. package/dist/lib/reactivity/createValueState.d.ts +0 -1
  66. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +0 -1
  67. package/dist/lib/reactivity/node-state/createClientState.d.ts +0 -1
  68. package/dist/lib/reactivity/node-state/createCurrentState.d.ts +0 -1
  69. package/dist/lib/reactivity/node-state/createEngineState.d.ts +0 -1
  70. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +1 -2
  71. package/dist/lib/reactivity/node-state/createSpecifiedPropertyDescriptor.d.ts +0 -1
  72. package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +1 -2
  73. package/dist/lib/reactivity/node-state/representations.d.ts +0 -1
  74. package/dist/lib/reactivity/scope.d.ts +0 -1
  75. package/dist/lib/reactivity/text/createFieldHint.d.ts +3 -4
  76. package/dist/lib/reactivity/text/createNodeLabel.d.ts +3 -4
  77. package/dist/lib/reactivity/text/createNoteText.d.ts +24 -0
  78. package/dist/lib/reactivity/text/createTextRange.d.ts +5 -8
  79. package/dist/lib/reactivity/types.d.ts +0 -1
  80. package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +8 -0
  81. package/dist/lib/reactivity/validation/createValidation.d.ts +17 -0
  82. package/dist/{XFormDOM.d.ts → parse/XFormDOM.d.ts} +1 -2
  83. package/dist/{XFormDataType.d.ts → parse/XFormDataType.d.ts} +2 -4
  84. package/dist/{XFormDefinition.d.ts → parse/XFormDefinition.d.ts} +2 -3
  85. package/dist/{body → parse/body}/BodyDefinition.d.ts +15 -10
  86. package/dist/{body → parse/body}/BodyElementDefinition.d.ts +8 -7
  87. package/dist/{body → parse/body}/RepeatElementDefinition.d.ts +4 -5
  88. package/dist/{body → parse/body}/UnsupportedBodyElementDefinition.d.ts +0 -1
  89. package/dist/{body → parse/body}/appearance/inputAppearanceParser.d.ts +1 -2
  90. package/dist/{body → parse/body}/appearance/selectAppearanceParser.d.ts +1 -2
  91. package/dist/{body → parse/body}/appearance/structureElementAppearanceParser.d.ts +1 -2
  92. package/dist/parse/body/appearance/unknownAppearanceParser.d.ts +3 -0
  93. package/dist/{body → parse/body}/control/ControlDefinition.d.ts +3 -4
  94. package/dist/{body → parse/body}/control/InputDefinition.d.ts +1 -2
  95. package/dist/parse/body/control/RangeControlDefinition.d.ts +11 -0
  96. package/dist/parse/body/control/RankControlDefinition.d.ts +11 -0
  97. package/dist/parse/body/control/TriggerControlDefinition.d.ts +11 -0
  98. package/dist/parse/body/control/UploadControlDefinition.d.ts +11 -0
  99. package/dist/{body → parse/body}/control/select/ItemDefinition.d.ts +3 -4
  100. package/dist/{body → parse/body}/control/select/ItemsetDefinition.d.ts +7 -7
  101. package/dist/{body → parse/body}/control/select/ItemsetNodesetContext.d.ts +2 -3
  102. package/dist/{body → parse/body}/control/select/SelectDefinition.d.ts +3 -12
  103. package/dist/{body → parse/body}/group/BaseGroupDefinition.d.ts +3 -5
  104. package/dist/{body → parse/body}/group/LogicalGroupDefinition.d.ts +0 -1
  105. package/dist/{body → parse/body}/group/PresentationGroupDefinition.d.ts +1 -2
  106. package/dist/{body → parse/body}/group/StructuralGroupDefinition.d.ts +0 -1
  107. package/dist/{model/BindComputation.d.ts → parse/expression/BindComputationExpression.d.ts} +5 -6
  108. package/dist/{body/control/select → parse/expression}/ItemsetNodesetExpression.d.ts +2 -3
  109. package/dist/{body/control/select → parse/expression}/ItemsetValueExpression.d.ts +2 -3
  110. package/dist/parse/expression/RepeatCountControlExpression.d.ts +18 -0
  111. package/dist/parse/expression/TextLiteralExpression.d.ts +9 -0
  112. package/dist/parse/expression/TextOutputExpression.d.ts +7 -0
  113. package/dist/parse/expression/TextReferenceExpression.d.ts +7 -0
  114. package/dist/parse/expression/TextTranslationExpression.d.ts +8 -0
  115. package/dist/{expression → parse/expression/abstract}/DependencyContext.d.ts +0 -1
  116. package/dist/{expression → parse/expression/abstract}/DependentExpression.d.ts +13 -10
  117. package/dist/parse/expression/abstract/TextChunkExpression.d.ts +17 -0
  118. package/dist/parse/model/BindDefinition.d.ts +39 -0
  119. package/dist/{model → parse/model}/BindElement.d.ts +1 -0
  120. package/dist/{model → parse/model}/DescendentNodeDefinition.d.ts +0 -1
  121. package/dist/{model/ValueNodeDefinition.d.ts → parse/model/LeafNodeDefinition.d.ts} +3 -4
  122. package/dist/{model → parse/model}/ModelBindMap.d.ts +0 -1
  123. package/dist/{model → parse/model}/ModelDefinition.d.ts +1 -2
  124. package/dist/{model → parse/model}/NodeDefinition.d.ts +8 -9
  125. package/dist/parse/model/NoteNodeDefinition.d.ts +30 -0
  126. package/dist/{model → parse/model}/RepeatInstanceDefinition.d.ts +3 -4
  127. package/dist/{model → parse/model}/RepeatRangeDefinition.d.ts +14 -5
  128. package/dist/{model → parse/model}/RepeatTemplateDefinition.d.ts +2 -3
  129. package/dist/{model → parse/model}/RootDefinition.d.ts +2 -3
  130. package/dist/{model → parse/model}/SubtreeDefinition.d.ts +1 -2
  131. package/dist/parse/text/HintDefinition.d.ts +8 -0
  132. package/dist/parse/text/ItemLabelDefinition.d.ts +8 -0
  133. package/dist/parse/text/ItemsetLabelDefinition.d.ts +12 -0
  134. package/dist/parse/text/LabelDefinition.d.ts +14 -0
  135. package/dist/parse/text/MessageDefinition.d.ts +14 -0
  136. package/dist/parse/text/abstract/TextElementDefinition.d.ts +22 -0
  137. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +34 -0
  138. package/dist/parse/xpath/dependency-analysis.d.ts +40 -0
  139. package/dist/parse/xpath/path-resolution.d.ts +69 -0
  140. package/dist/parse/xpath/predicate-analysis.d.ts +29 -0
  141. package/dist/parse/xpath/reference-parsing.d.ts +17 -0
  142. package/dist/parse/xpath/semantic-analysis.d.ts +97 -0
  143. package/dist/parse/xpath/syntax-traversal.d.ts +68 -0
  144. package/dist/solid.js +8745 -5186
  145. package/dist/solid.js.map +1 -1
  146. package/package.json +15 -16
  147. package/src/client/BaseNode.ts +74 -8
  148. package/src/client/GroupNode.ts +4 -2
  149. package/src/client/ModelValueNode.ts +40 -0
  150. package/src/client/NodeAppearances.ts +1 -1
  151. package/src/client/NoteNode.ts +74 -0
  152. package/src/client/README.md +1 -0
  153. package/src/client/RootNode.ts +4 -2
  154. package/src/client/SelectNode.ts +6 -4
  155. package/src/client/StringNode.ts +6 -4
  156. package/src/client/SubtreeNode.ts +3 -1
  157. package/src/client/TextRange.ts +98 -2
  158. package/src/client/TriggerNode.ts +29 -0
  159. package/src/client/constants.ts +10 -0
  160. package/src/client/hierarchy.ts +43 -15
  161. package/src/client/node-types.ts +17 -2
  162. package/src/client/{RepeatRangeNode.ts → repeat/BaseRepeatRangeNode.ts} +18 -19
  163. package/src/client/{RepeatInstanceNode.ts → repeat/RepeatInstanceNode.ts} +10 -8
  164. package/src/client/repeat/RepeatRangeControlledNode.ts +20 -0
  165. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +21 -0
  166. package/src/client/unsupported/RangeNode.ts +14 -0
  167. package/src/client/unsupported/RankNode.ts +14 -0
  168. package/src/client/unsupported/UnsupportedControlNode.ts +40 -0
  169. package/src/client/unsupported/UploadNode.ts +14 -0
  170. package/src/client/validation.ts +199 -0
  171. package/src/index.ts +21 -9
  172. package/src/instance/Group.ts +10 -4
  173. package/src/instance/ModelValue.ts +104 -0
  174. package/src/instance/Note.ts +142 -0
  175. package/src/instance/Root.ts +16 -6
  176. package/src/instance/SelectField.ts +29 -7
  177. package/src/instance/StringField.ts +36 -10
  178. package/src/instance/Subtree.ts +9 -3
  179. package/src/instance/TriggerControl.ts +134 -0
  180. package/src/instance/abstract/DescendantNode.ts +9 -10
  181. package/src/instance/abstract/InstanceNode.ts +29 -7
  182. package/src/instance/abstract/UnsupportedControl.ts +151 -0
  183. package/src/instance/children.ts +113 -16
  184. package/src/instance/hierarchy.ts +42 -5
  185. package/src/instance/index.ts +1 -1
  186. package/src/instance/internal-api/EvaluationContext.ts +1 -1
  187. package/src/instance/internal-api/ValidationContext.ts +32 -0
  188. package/src/instance/internal-api/ValueContext.ts +3 -3
  189. package/src/instance/{RepeatRange.ts → repeat/BaseRepeatRange.ts} +114 -99
  190. package/src/instance/{RepeatInstance.ts → repeat/RepeatInstance.ts} +27 -22
  191. package/src/instance/repeat/RepeatRangeControlled.ts +82 -0
  192. package/src/instance/repeat/RepeatRangeUncontrolled.ts +67 -0
  193. package/src/instance/text/TextRange.ts +10 -4
  194. package/src/instance/unsupported/RangeControl.ts +5 -0
  195. package/src/instance/unsupported/RankControl.ts +5 -0
  196. package/src/instance/unsupported/UploadControl.ts +5 -0
  197. package/src/lib/TokenListParser.ts +11 -7
  198. package/src/lib/dom/query.ts +1 -1
  199. package/src/lib/reactivity/createComputedExpression.ts +25 -27
  200. package/src/lib/reactivity/createNoteReadonlyThunk.ts +33 -0
  201. package/src/lib/reactivity/createSelectItems.ts +23 -16
  202. package/src/lib/reactivity/createValueState.ts +3 -3
  203. package/src/lib/reactivity/node-state/createSharedNodeState.ts +1 -1
  204. package/src/lib/reactivity/node-state/createSpecifiedState.ts +1 -1
  205. package/src/lib/reactivity/text/createFieldHint.ts +9 -7
  206. package/src/lib/reactivity/text/createNodeLabel.ts +8 -6
  207. package/src/lib/reactivity/text/createNoteText.ts +72 -0
  208. package/src/lib/reactivity/text/createTextRange.ts +17 -90
  209. package/src/lib/reactivity/validation/createAggregatedViolations.ts +75 -0
  210. package/src/lib/reactivity/validation/createValidation.ts +196 -0
  211. package/src/{XFormDataType.ts → parse/XFormDataType.ts} +1 -3
  212. package/src/{XFormDefinition.ts → parse/XFormDefinition.ts} +2 -2
  213. package/src/{body → parse/body}/BodyDefinition.ts +44 -27
  214. package/src/{body → parse/body}/BodyElementDefinition.ts +13 -6
  215. package/src/{body → parse/body}/RepeatElementDefinition.ts +10 -20
  216. package/src/{body → parse/body}/appearance/inputAppearanceParser.ts +1 -1
  217. package/src/{body → parse/body}/appearance/selectAppearanceParser.ts +1 -1
  218. package/src/{body → parse/body}/appearance/structureElementAppearanceParser.ts +1 -1
  219. package/src/parse/body/appearance/unknownAppearanceParser.ts +5 -0
  220. package/src/{body → parse/body}/control/ControlDefinition.ts +5 -4
  221. package/src/parse/body/control/RangeControlDefinition.ts +26 -0
  222. package/src/parse/body/control/RankControlDefinition.ts +27 -0
  223. package/src/parse/body/control/TriggerControlDefinition.ts +26 -0
  224. package/src/parse/body/control/UploadControlDefinition.ts +26 -0
  225. package/src/{body → parse/body}/control/select/ItemDefinition.ts +4 -4
  226. package/src/parse/body/control/select/ItemsetDefinition.ts +53 -0
  227. package/src/{body → parse/body}/control/select/ItemsetNodesetContext.ts +2 -2
  228. package/src/{body → parse/body}/control/select/SelectDefinition.ts +3 -11
  229. package/src/{body → parse/body}/group/BaseGroupDefinition.ts +11 -21
  230. package/src/{body → parse/body}/group/PresentationGroupDefinition.ts +1 -1
  231. package/src/{model/BindComputation.ts → parse/expression/BindComputationExpression.ts} +8 -12
  232. package/src/parse/expression/ItemsetNodesetExpression.ts +8 -0
  233. package/src/{body/control/select → parse/expression}/ItemsetValueExpression.ts +2 -2
  234. package/src/parse/expression/RepeatCountControlExpression.ts +44 -0
  235. package/src/parse/expression/TextLiteralExpression.ts +19 -0
  236. package/src/parse/expression/TextOutputExpression.ts +25 -0
  237. package/src/parse/expression/TextReferenceExpression.ts +14 -0
  238. package/src/parse/expression/TextTranslationExpression.ts +38 -0
  239. package/src/{expression → parse/expression/abstract}/DependentExpression.ts +46 -28
  240. package/src/parse/expression/abstract/TextChunkExpression.ts +38 -0
  241. package/src/{model → parse/model}/BindDefinition.ts +30 -27
  242. package/src/{model → parse/model}/BindElement.ts +1 -0
  243. package/src/{model/ValueNodeDefinition.ts → parse/model/LeafNodeDefinition.ts} +4 -4
  244. package/src/{model → parse/model}/ModelBindMap.ts +4 -0
  245. package/src/{model → parse/model}/NodeDefinition.ts +12 -12
  246. package/src/parse/model/NoteNodeDefinition.ts +70 -0
  247. package/src/{model → parse/model}/RepeatInstanceDefinition.ts +2 -2
  248. package/src/parse/model/RepeatRangeDefinition.ts +94 -0
  249. package/src/{model → parse/model}/RootDefinition.ts +8 -4
  250. package/src/parse/text/HintDefinition.ts +25 -0
  251. package/src/parse/text/ItemLabelDefinition.ts +25 -0
  252. package/src/parse/text/ItemsetLabelDefinition.ts +44 -0
  253. package/src/parse/text/LabelDefinition.ts +61 -0
  254. package/src/parse/text/MessageDefinition.ts +49 -0
  255. package/src/parse/text/abstract/TextElementDefinition.ts +71 -0
  256. package/src/parse/text/abstract/TextRangeDefinition.ts +70 -0
  257. package/src/parse/xpath/dependency-analysis.ts +105 -0
  258. package/src/parse/xpath/path-resolution.ts +475 -0
  259. package/src/parse/xpath/predicate-analysis.ts +61 -0
  260. package/src/parse/xpath/reference-parsing.ts +90 -0
  261. package/src/parse/xpath/semantic-analysis.ts +466 -0
  262. package/src/parse/xpath/syntax-traversal.ts +129 -0
  263. package/dist/body/text/HintDefinition.d.ts +0 -11
  264. package/dist/body/text/LabelDefinition.d.ts +0 -22
  265. package/dist/body/text/TextElementDefinition.d.ts +0 -33
  266. package/dist/body/text/TextElementOutputPart.d.ts +0 -13
  267. package/dist/body/text/TextElementPart.d.ts +0 -13
  268. package/dist/body/text/TextElementReferencePart.d.ts +0 -7
  269. package/dist/body/text/TextElementStaticPart.d.ts +0 -7
  270. package/dist/lib/xpath/analysis.d.ts +0 -23
  271. package/dist/model/BindDefinition.d.ts +0 -32
  272. package/src/body/control/select/ItemsetDefinition.ts +0 -36
  273. package/src/body/control/select/ItemsetNodesetExpression.ts +0 -8
  274. package/src/body/text/HintDefinition.ts +0 -26
  275. package/src/body/text/LabelDefinition.ts +0 -68
  276. package/src/body/text/TextElementDefinition.ts +0 -97
  277. package/src/body/text/TextElementOutputPart.ts +0 -27
  278. package/src/body/text/TextElementPart.ts +0 -31
  279. package/src/body/text/TextElementReferencePart.ts +0 -21
  280. package/src/body/text/TextElementStaticPart.ts +0 -26
  281. package/src/lib/xpath/analysis.ts +0 -241
  282. package/src/model/RepeatRangeDefinition.ts +0 -53
  283. package/src/{XFormDOM.ts → parse/XFormDOM.ts} +0 -0
  284. package/src/{body → parse/body}/UnsupportedBodyElementDefinition.ts +0 -0
  285. package/src/{body → parse/body}/control/InputDefinition.ts +1 -1
  286. /package/src/{body → parse/body}/group/LogicalGroupDefinition.ts +0 -0
  287. /package/src/{body → parse/body}/group/StructuralGroupDefinition.ts +0 -0
  288. /package/src/{expression → parse/expression/abstract}/DependencyContext.ts +0 -0
  289. /package/src/{model → parse/model}/DescendentNodeDefinition.ts +0 -0
  290. /package/src/{model → parse/model}/ModelDefinition.ts +0 -0
  291. /package/src/{model → parse/model}/RepeatTemplateDefinition.ts +0 -0
  292. /package/src/{model → parse/model}/SubtreeDefinition.ts +0 -0
@@ -11,16 +11,20 @@ type TokenListIterator<CanonicalToken extends string> = IterableIterator<
11
11
  PartiallyKnownString<CanonicalToken>
12
12
  >;
13
13
 
14
+ type PassthroughTokenList = Readonly<Record<string, boolean>>;
15
+
14
16
  /**
15
17
  * @see {@link TokenListParser}
16
18
  */
17
19
  // prettier-ignore
18
- export type TokenList<CanonicalToken extends string = string> = {
19
- readonly [Key in TokenListKey<CanonicalToken>]:
20
- Key extends SymbolIterator
21
- ? () => TokenListIterator<CanonicalToken>
22
- : boolean;
23
- };
20
+ export type TokenList<CanonicalToken extends string = string> =
21
+ & PassthroughTokenList
22
+ & {
23
+ readonly [Key in TokenListKey<CanonicalToken>]:
24
+ Key extends SymbolIterator
25
+ ? () => TokenListIterator<CanonicalToken>
26
+ : boolean;
27
+ };
24
28
 
25
29
  interface TokenListAlias<CanonicalToken extends string> {
26
30
  readonly fromAlias: string;
@@ -101,7 +105,7 @@ export class TokenListParser<
101
105
  private readonly aliases: ReadonlyMap<string, CanonicalToken>;
102
106
 
103
107
  constructor(
104
- readonly canonicalTokens: readonly CanonicalToken[],
108
+ readonly canonicalTokens: readonly CanonicalToken[] = [],
105
109
  options?: TokenListParserOptions<TokenAlias>
106
110
  ) {
107
111
  this.aliases = new Map(
@@ -3,7 +3,7 @@ import type {
3
3
  KnownAttributeLocalNamedElement,
4
4
  LocalNamedElement,
5
5
  } from '@getodk/common/types/dom.ts';
6
- import type { SelectElement } from '../../body/control/select/SelectDefinition';
6
+ import type { SelectElement } from '../../parse/body/control/select/SelectDefinition';
7
7
 
8
8
  const hintLookup = new ScopedElementLookup(':scope > hint', 'hint');
9
9
  const itemLookup = new ScopedElementLookup(':scope > item', 'item');
@@ -2,16 +2,18 @@ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
2
2
  import type { XFormsXPathEvaluator } from '@getodk/xpath';
3
3
  import type { Accessor } from 'solid-js';
4
4
  import { createMemo } from 'solid-js';
5
+ import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
6
+ import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
5
7
  import type {
6
8
  DependentExpression,
7
9
  DependentExpressionResultType,
8
- } from '../../expression/DependentExpression.ts';
9
- import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
10
- import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
10
+ } from '../../parse/expression/abstract/DependentExpression.ts';
11
+ import { isConstantExpression } from '../../parse/xpath/semantic-analysis.ts';
11
12
 
12
13
  interface ComputedExpressionResults {
13
14
  readonly boolean: boolean;
14
15
  readonly nodes: Node[];
16
+ readonly number: number;
15
17
  readonly string: string;
16
18
  }
17
19
 
@@ -44,6 +46,11 @@ const expressionEvaluator = <Type extends DependentExpressionResultType>(
44
46
  return evaluator.evaluateNodes(expression, options);
45
47
  }) as ExpressionEvaluator<Type>;
46
48
 
49
+ case 'number':
50
+ return (() => {
51
+ return evaluator.evaluateNumber(expression, options);
52
+ }) as ExpressionEvaluator<Type>;
53
+
47
54
  case 'string':
48
55
  return (() => {
49
56
  return evaluator.evaluateString(expression, options);
@@ -54,26 +61,19 @@ const expressionEvaluator = <Type extends DependentExpressionResultType>(
54
61
  }
55
62
  };
56
63
 
57
- /**
58
- * Determines if an XPath expression will always produce the same value.
59
- *
60
- * @todo There are quite a few more cases than this, and it also likely belongs
61
- * in another `lib` module.
62
- */
63
- const isConstantExpression = (expression: string): boolean => {
64
- const normalized = expression.replaceAll(/\s/g, '');
65
-
66
- return normalized === 'true()' || normalized === 'false()';
67
- };
68
-
69
64
  // prettier-ignore
70
65
  type ComputedExpression<Type extends DependentExpressionResultType> = Accessor<
71
66
  EvaluatedExpression<Type>
72
67
  >;
73
68
 
69
+ interface CreateComputedExpressionOptions {
70
+ readonly arbitraryDependencies?: readonly SubscribableDependency[];
71
+ }
72
+
74
73
  export const createComputedExpression = <Type extends DependentExpressionResultType>(
75
74
  context: EvaluationContext,
76
- dependentExpression: DependentExpression<Type>
75
+ dependentExpression: DependentExpression<Type>,
76
+ options: CreateComputedExpressionOptions = {}
77
77
  ): ComputedExpression<Type> => {
78
78
  const { contextNode, evaluator, root, scope } = context;
79
79
  const { expression, isTranslated, resultType } = dependentExpression;
@@ -85,26 +85,24 @@ export const createComputedExpression = <Type extends DependentExpressionResultT
85
85
  return createMemo(evaluateExpression);
86
86
  }
87
87
 
88
+ const { arbitraryDependencies = [] } = options;
89
+
88
90
  const getReferencedDependencies = createMemo(() => {
89
91
  return dependencyReferences.flatMap((reference) => {
90
92
  return context.getSubscribableDependenciesByReference(reference) ?? [];
91
93
  });
92
94
  });
93
95
 
94
- let getDependencies: Accessor<readonly SubscribableDependency[]>;
96
+ return createMemo(() => {
97
+ if (isTranslated) {
98
+ root.subscribe();
99
+ }
95
100
 
96
- if (isTranslated) {
97
- getDependencies = createMemo(() => {
98
- return [root, ...getReferencedDependencies()];
101
+ arbitraryDependencies.forEach((dependency) => {
102
+ dependency.subscribe();
99
103
  });
100
- } else {
101
- getDependencies = getReferencedDependencies;
102
- }
103
-
104
- return createMemo(() => {
105
- const dependencies = getDependencies();
106
104
 
107
- dependencies.forEach((dependency) => {
105
+ getReferencedDependencies().forEach((dependency) => {
108
106
  dependency.subscribe();
109
107
  });
110
108
 
@@ -0,0 +1,33 @@
1
+ import type { Accessor } from 'solid-js';
2
+ import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
3
+ import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
4
+ import { createComputedExpression } from './createComputedExpression.ts';
5
+
6
+ export const createNoteReadonlyThunk = (
7
+ context: EvaluationContext,
8
+ readonlyDefinition: BindComputationExpression<'readonly'>
9
+ ): Accessor<true> => {
10
+ if (!readonlyDefinition.isConstantTruthyExpression()) {
11
+ throw new Error('Expected a static readonly expression');
12
+ }
13
+
14
+ let result = true;
15
+
16
+ if (import.meta.env.DEV) {
17
+ const { expression } = readonlyDefinition;
18
+
19
+ if (readonlyDefinition.dependencyReferences.size > 0) {
20
+ throw new Error(`Expected expression ${expression} to have no dependencies`);
21
+ }
22
+
23
+ const computedExpression = createComputedExpression(context, readonlyDefinition);
24
+
25
+ result = computedExpression();
26
+
27
+ if (result !== true) {
28
+ throw new Error(`Expected expression ${readonlyDefinition.expression} to return true`);
29
+ }
30
+ }
31
+
32
+ return () => result;
33
+ };
@@ -2,8 +2,7 @@ import { UpsertableMap } from '@getodk/common/lib/collections/UpsertableMap.ts';
2
2
  import type { XFormsXPathEvaluator } from '@getodk/xpath';
3
3
  import type { Accessor } from 'solid-js';
4
4
  import { createMemo } from 'solid-js';
5
- import type { ItemDefinition } from '../../body/control/select/ItemDefinition.ts';
6
- import type { ItemsetDefinition } from '../../body/control/select/ItemsetDefinition.ts';
5
+ import type { TextRange as ClientTextRange } from '../../client/TextRange.ts';
7
6
  import type { SelectItem } from '../../index.ts';
8
7
  import type { SelectField } from '../../instance/SelectField.ts';
9
8
  import type {
@@ -11,20 +10,33 @@ import type {
11
10
  EvaluationContextRoot,
12
11
  } from '../../instance/internal-api/EvaluationContext.ts';
13
12
  import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
14
- import type { TextRange } from '../../instance/text/TextRange.ts';
13
+ import { TextChunk } from '../../instance/text/TextChunk.ts';
14
+ import { TextRange } from '../../instance/text/TextRange.ts';
15
+ import type { ItemDefinition } from '../../parse/body/control/select/ItemDefinition.ts';
16
+ import type { ItemsetDefinition } from '../../parse/body/control/select/ItemsetDefinition.ts';
15
17
  import { createComputedExpression } from './createComputedExpression.ts';
16
18
  import type { ReactiveScope } from './scope.ts';
17
19
  import { createTextRange } from './text/createTextRange.ts';
18
20
 
21
+ type DerivedItemLabel = ClientTextRange<'item-label', 'form-derived'>;
22
+
23
+ const derivedItemLabel = (context: EvaluationContext, value: string): DerivedItemLabel => {
24
+ const chunk = new TextChunk(context.root, 'literal', value);
25
+
26
+ return new TextRange('form-derived', 'item-label', [chunk]);
27
+ };
28
+
19
29
  const createSelectItemLabel = (
20
30
  context: EvaluationContext,
21
31
  definition: ItemDefinition
22
- ): Accessor<TextRange<'label'>> => {
32
+ ): Accessor<ClientTextRange<'item-label'>> => {
23
33
  const { label, value } = definition;
24
34
 
25
- return createTextRange(context, 'label', label, {
26
- fallbackValue: value,
27
- });
35
+ if (label == null) {
36
+ return () => derivedItemLabel(context, value);
37
+ }
38
+
39
+ return createTextRange(context, 'item-label', label);
28
40
  };
29
41
 
30
42
  const createTranslatedStaticSelectItems = (
@@ -73,25 +85,20 @@ const createSelectItemsetItemLabel = (
73
85
  context: EvaluationContext,
74
86
  definition: ItemsetDefinition,
75
87
  itemValue: Accessor<string>
76
- ): Accessor<TextRange<'label'>> => {
88
+ ): Accessor<ClientTextRange<'item-label'>> => {
77
89
  const { label } = definition;
78
90
 
79
91
  if (label == null) {
80
92
  return createMemo(() => {
81
- const value = itemValue();
82
- const staticValueLabel = createTextRange(context, 'label', label, {
83
- fallbackValue: value,
84
- });
85
-
86
- return staticValueLabel();
93
+ return derivedItemLabel(context, itemValue());
87
94
  });
88
95
  }
89
96
 
90
- return createTextRange(context, 'label', label);
97
+ return createTextRange(context, 'item-label', label);
91
98
  };
92
99
 
93
100
  interface ItemsetItem {
94
- label(): TextRange<'label'>;
101
+ label(): ClientTextRange<'item-label'>;
95
102
  value(): string;
96
103
  }
97
104
 
@@ -1,8 +1,8 @@
1
1
  import { createComputed, createMemo, createSignal, untrack } from 'solid-js';
2
- import type { DependentExpression } from '../../expression/DependentExpression.ts';
3
2
  import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
4
3
  import type { ValueContext } from '../../instance/internal-api/ValueContext.ts';
5
- import type { BindComputation } from '../../model/BindComputation.ts';
4
+ import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
5
+ import type { DependentExpression } from '../../parse/expression/abstract/DependentExpression.ts';
6
6
  import { createComputedExpression } from './createComputedExpression.ts';
7
7
  import type { SimpleAtomicState, SimpleAtomicStateSetter } from './types.ts';
8
8
 
@@ -209,7 +209,7 @@ const guardDownstreamReadonlyWrites = <RuntimeValue>(
209
209
  const createCalculation = <RuntimeValue>(
210
210
  context: ValueContext<RuntimeValue>,
211
211
  setValue: SimpleAtomicStateSetter<RuntimeValue>,
212
- calculateDefinition: BindComputation<'calculate'>
212
+ calculateDefinition: BindComputationExpression<'calculate'>
213
213
  ): void => {
214
214
  context.scope.runTask(() => {
215
215
  const calculate = createComputedExpression(context, calculateDefinition);
@@ -31,7 +31,7 @@ export interface SharedNodeState<Spec extends StateSpec> {
31
31
  readonly setProperty: SetEnginePropertyState<Spec>;
32
32
  }
33
33
 
34
- interface SharedNodeStateOptions<
34
+ export interface SharedNodeStateOptions<
35
35
  Factory extends OpaqueReactiveObjectFactory,
36
36
  Spec extends StateSpec,
37
37
  > {
@@ -80,7 +80,7 @@ export type ComputedPropertySpec<T> = Accessor<T>;
80
80
  /**
81
81
  * @see {@link StaticPropertySpec}
82
82
  */
83
- // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
83
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-explicit-any
84
84
  type NonStaticValue = Function | Signal<any> | SimpleAtomicState<any>;
85
85
 
86
86
  /**
@@ -1,16 +1,18 @@
1
1
  import { type Accessor } from 'solid-js';
2
+ import type { TextRange } from '../../../client/TextRange.ts';
2
3
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
3
- import { TextRange } from '../../../instance/text/TextRange.ts';
4
- import type { ValueNodeDefinition } from '../../../model/ValueNodeDefinition.ts';
4
+ import type { LeafNodeDefinition } from '../../../parse/model/LeafNodeDefinition.ts';
5
5
  import { createTextRange } from './createTextRange.ts';
6
6
 
7
7
  export const createFieldHint = (
8
8
  context: EvaluationContext,
9
- definition: ValueNodeDefinition
10
- ): Accessor<TextRange<'hint'> | null> => {
9
+ definition: LeafNodeDefinition
10
+ ): Accessor<TextRange<'hint', 'form'> | null> => {
11
11
  const hintDefinition = definition.bodyElement?.hint ?? null;
12
12
 
13
- return createTextRange(context, 'hint', hintDefinition, {
14
- fallbackValue: null,
15
- });
13
+ if (hintDefinition == null) {
14
+ return () => null;
15
+ }
16
+
17
+ return createTextRange(context, 'hint', hintDefinition);
16
18
  };
@@ -1,16 +1,18 @@
1
1
  import { type Accessor } from 'solid-js';
2
+ import type { TextRange } from '../../../client/TextRange.ts';
2
3
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
3
- import { TextRange } from '../../../instance/text/TextRange.ts';
4
- import type { AnyNodeDefinition } from '../../../model/NodeDefinition.ts';
4
+ import type { AnyNodeDefinition } from '../../../parse/model/NodeDefinition.ts';
5
5
  import { createTextRange } from './createTextRange.ts';
6
6
 
7
7
  export const createNodeLabel = (
8
8
  context: EvaluationContext,
9
9
  definition: AnyNodeDefinition
10
- ): Accessor<TextRange<'label'> | null> => {
10
+ ): Accessor<TextRange<'label', 'form'> | null> => {
11
11
  const labelDefinition = definition.bodyElement?.label ?? null;
12
12
 
13
- return createTextRange(context, 'label', labelDefinition, {
14
- fallbackValue: null,
15
- });
13
+ if (labelDefinition == null) {
14
+ return () => null;
15
+ }
16
+
17
+ return createTextRange(context, 'label', labelDefinition);
16
18
  };
@@ -0,0 +1,72 @@
1
+ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
2
+ import type { Accessor } from 'solid-js';
3
+ import type { TextRange } from '../../../client/TextRange.ts';
4
+ import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
5
+ import type { NoteTextDefinition } from '../../../parse/model/NoteNodeDefinition.ts';
6
+ import { createTextRange } from './createTextRange.ts';
7
+
8
+ // eslint-disable-next-line @typescript-eslint/sort-type-constituents
9
+ export type NoteTextRole = 'label' | 'hint';
10
+
11
+ export type ComputedNoteText<Role extends NoteTextRole = NoteTextRole> = Accessor<
12
+ TextRange<Role, 'form'>
13
+ >;
14
+
15
+ interface BaseNoteText {
16
+ readonly role: NoteTextRole;
17
+ readonly label: ComputedNoteText<'label'> | null;
18
+ readonly hint: ComputedNoteText<'hint'> | null;
19
+ }
20
+
21
+ interface LabelNoteText extends BaseNoteText {
22
+ readonly role: 'label';
23
+ readonly label: ComputedNoteText<'label'>;
24
+ readonly hint: null;
25
+ }
26
+
27
+ interface HintNoteText extends BaseNoteText {
28
+ readonly role: 'hint';
29
+ readonly label: null;
30
+ readonly hint: ComputedNoteText<'hint'>;
31
+ }
32
+
33
+ // prettier-ignore
34
+ export type NoteTextComputation =
35
+ // eslint-disable-next-line @typescript-eslint/sort-type-constituents
36
+ | LabelNoteText
37
+ | HintNoteText;
38
+
39
+ export const createNoteText = (
40
+ context: EvaluationContext,
41
+ noteTextDefinition: NoteTextDefinition
42
+ ): NoteTextComputation => {
43
+ const { scope } = context;
44
+ const { role } = noteTextDefinition;
45
+
46
+ return scope.runTask(() => {
47
+ switch (role) {
48
+ case 'label': {
49
+ const label = createTextRange(context, role, noteTextDefinition);
50
+
51
+ return {
52
+ role,
53
+ label,
54
+ hint: null,
55
+ };
56
+ }
57
+
58
+ case 'hint': {
59
+ const hint = createTextRange(context, role, noteTextDefinition);
60
+
61
+ return {
62
+ role,
63
+ label: null,
64
+ hint,
65
+ };
66
+ }
67
+
68
+ default:
69
+ throw new UnreachableError(noteTextDefinition);
70
+ }
71
+ });
72
+ };
@@ -1,23 +1,13 @@
1
- import type { CollectionValues } from '@getodk/common/types/collections/CollectionValues.ts';
2
- import { createMemo, type Accessor } from 'solid-js';
3
- import type {
4
- TextElementChild,
5
- TextElementDefinition,
6
- } from '../../../body/text/TextElementDefinition.ts';
7
- import type { TextElementReferencePart } from '../../../body/text/TextElementReferencePart.ts';
8
- import type { TextChunkSource } from '../../../client/TextRange.ts';
1
+ import type { Accessor } from 'solid-js';
2
+ import { createMemo } from 'solid-js';
3
+ import type { TextChunkSource, TextRole } from '../../../client/TextRange.ts';
9
4
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
10
5
  import { TextChunk } from '../../../instance/text/TextChunk.ts';
11
- import { TextRange, type TextRole } from '../../../instance/text/TextRange.ts';
6
+ import { TextRange } from '../../../instance/text/TextRange.ts';
7
+ import type { AnyTextChunkExpression } from '../../../parse/expression/abstract/TextChunkExpression.ts';
8
+ import type { TextRangeDefinition } from '../../../parse/text/abstract/TextRangeDefinition.ts';
12
9
  import { createComputedExpression } from '../createComputedExpression.ts';
13
10
 
14
- // prettier-ignore
15
- type TextSources =
16
- | readonly [TextElementReferencePart]
17
- | readonly TextElementChild[];
18
-
19
- type TextSource = CollectionValues<TextSources>;
20
-
21
11
  interface TextChunkComputation {
22
12
  readonly source: TextChunkSource;
23
13
  readonly getText: Accessor<string>;
@@ -25,21 +15,20 @@ interface TextChunkComputation {
25
15
 
26
16
  const createComputedTextChunk = (
27
17
  context: EvaluationContext,
28
- textSource: TextSource
18
+ textSource: AnyTextChunkExpression
29
19
  ): TextChunkComputation => {
30
- const { type } = textSource;
20
+ const { source } = textSource;
31
21
 
32
- if (type === 'static') {
22
+ if (source === 'literal') {
33
23
  const { stringValue } = textSource;
34
24
 
35
25
  return {
36
- source: type,
26
+ source,
37
27
  getText: () => stringValue,
38
28
  };
39
29
  }
40
30
 
41
31
  return context.scope.runTask(() => {
42
- const source: TextChunkSource = type === 'reference' ? 'itext' : type;
43
32
  const getText = createComputedExpression(context, textSource);
44
33
 
45
34
  return {
@@ -51,7 +40,7 @@ const createComputedTextChunk = (
51
40
 
52
41
  const createTextChunks = (
53
42
  context: EvaluationContext,
54
- textSources: TextSources
43
+ textSources: readonly AnyTextChunkExpression[]
55
44
  ): Accessor<readonly TextChunk[]> => {
56
45
  return context.scope.runTask(() => {
57
46
  const { root } = context;
@@ -67,45 +56,7 @@ const createTextChunks = (
67
56
  });
68
57
  };
69
58
 
70
- interface CreateTextRangeOptions<FallbackValue extends string | null> {
71
- readonly fallbackValue?: FallbackValue;
72
- }
73
-
74
- // prettier-ignore
75
- type ComputedTextRange<
76
- Role extends TextRole,
77
- Definition extends TextElementDefinition<Role> | null,
78
- FallbackValue extends string | null
79
- > = Accessor<
80
- Definition extends null
81
- ? FallbackValue extends null
82
- ? TextRange<Role> | null
83
- : TextRange<Role>
84
- : TextRange<Role>
85
- >;
86
-
87
- // prettier-ignore
88
- type FallbackTextRange<
89
- Role extends TextRole,
90
- FallbackValue extends string | null
91
- > =
92
- FallbackValue extends null
93
- ? TextRange<Role> | null
94
- : TextRange<Role>;
95
-
96
- const createFallbackTextRange = <Role extends TextRole, FallbackValue extends string | null>(
97
- context: EvaluationContext,
98
- role: Role,
99
- fallbackValue: FallbackValue
100
- ): FallbackTextRange<Role, FallbackValue> => {
101
- if (fallbackValue == null) {
102
- return null as FallbackTextRange<Role, FallbackValue>;
103
- }
104
-
105
- const staticChunk = new TextChunk(context.root, 'static', fallbackValue);
106
-
107
- return new TextRange(role, [staticChunk]);
108
- };
59
+ type ComputedFormTextRange<Role extends TextRole> = Accessor<TextRange<Role, 'form'>>;
109
60
 
110
61
  /**
111
62
  * Creates a text range (e.g. label or hint) from the provided definition,
@@ -116,40 +67,16 @@ const createFallbackTextRange = <Role extends TextRole, FallbackValue extends st
116
67
  *
117
68
  * @todo This does not yet handle itext translations **with** outputs!
118
69
  */
119
- export const createTextRange = <
120
- Role extends TextRole,
121
- Definition extends TextElementDefinition<Role> | null,
122
- FallbackValue extends string | null = null,
123
- >(
70
+ export const createTextRange = <Role extends TextRole>(
124
71
  context: EvaluationContext,
125
72
  role: Role,
126
- definition: Definition,
127
- options?: CreateTextRangeOptions<FallbackValue>
128
- ): ComputedTextRange<Role, Definition, FallbackValue> => {
73
+ definition: TextRangeDefinition<Role>
74
+ ): ComputedFormTextRange<Role> => {
129
75
  return context.scope.runTask(() => {
130
- if (definition == null) {
131
- const textRange = createFallbackTextRange(
132
- context,
133
- role,
134
- options?.fallbackValue ?? (null as FallbackValue)
135
- );
136
- const getTextRange = () => textRange;
137
-
138
- return getTextRange as ComputedTextRange<Role, Definition, FallbackValue>;
139
- }
140
-
141
- const { children, referenceExpression } = definition;
142
-
143
- let getTextChunks: Accessor<readonly TextChunk[]>;
144
-
145
- if (referenceExpression == null) {
146
- getTextChunks = createTextChunks(context, children);
147
- } else {
148
- getTextChunks = createTextChunks(context, [referenceExpression]);
149
- }
76
+ const getTextChunks = createTextChunks(context, definition.chunks);
150
77
 
151
78
  return createMemo(() => {
152
- return new TextRange(role, getTextChunks());
79
+ return new TextRange('form', role, getTextChunks());
153
80
  });
154
81
  });
155
82
  };
@@ -0,0 +1,75 @@
1
+ import { createMemo } from 'solid-js';
2
+ import type { OpaqueReactiveObjectFactory } from '../../../client/OpaqueReactiveObjectFactory.ts';
3
+ import type {
4
+ AncestorNodeValidationState,
5
+ DescendantNodeViolationReference,
6
+ } from '../../../client/validation.ts';
7
+ import type { AnyParentNode } from '../../../instance/hierarchy.ts';
8
+ import type { ValidationContext } from '../../../instance/internal-api/ValidationContext.ts';
9
+ import { createSharedNodeState } from '../node-state/createSharedNodeState.ts';
10
+
11
+ const violationReference = (node: ValidationContext): DescendantNodeViolationReference | null => {
12
+ const violation = node.getViolation();
13
+
14
+ if (violation == null) {
15
+ return null;
16
+ }
17
+
18
+ const { nodeId } = node;
19
+
20
+ return {
21
+ nodeId,
22
+ get reference() {
23
+ return node.currentState.reference;
24
+ },
25
+ violation,
26
+ };
27
+ };
28
+
29
+ const collectViolationReferences = (
30
+ context: AnyParentNode
31
+ ): readonly DescendantNodeViolationReference[] => {
32
+ return context.getChildren().flatMap((child) => {
33
+ switch (child.nodeType) {
34
+ case 'model-value':
35
+ case 'note':
36
+ case 'string':
37
+ case 'select':
38
+ case 'range':
39
+ case 'rank':
40
+ case 'trigger':
41
+ case 'upload': {
42
+ const reference = violationReference(child);
43
+
44
+ if (reference == null) {
45
+ return [];
46
+ }
47
+
48
+ return [reference];
49
+ }
50
+
51
+ default:
52
+ return collectViolationReferences(child);
53
+ }
54
+ });
55
+ };
56
+
57
+ interface AggregatedViolationsOptions {
58
+ readonly clientStateFactory: OpaqueReactiveObjectFactory<AncestorNodeValidationState>;
59
+ }
60
+
61
+ export const createAggregatedViolations = (
62
+ context: AnyParentNode,
63
+ options: AggregatedViolationsOptions
64
+ ): AncestorNodeValidationState => {
65
+ const { scope } = context;
66
+
67
+ return scope.runTask(() => {
68
+ const violations = createMemo(() => {
69
+ return collectViolationReferences(context);
70
+ });
71
+ const spec = { violations };
72
+
73
+ return createSharedNodeState(scope, spec, options).currentState;
74
+ });
75
+ };