@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
package/dist/solid.js CHANGED
@@ -7556,7 +7556,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7556
7556
  epochMilliseconds: I$1,
7557
7557
  epochNanoseconds: v$1
7558
7558
  },
7559
- [wn$1, In$1, vn$1] = createSlotClass$1(N$1, j$1, {
7559
+ [wn$1, In$1] = createSlotClass$1(N$1, j$1, {
7560
7560
  ...gn$1,
7561
7561
  blank: y$1
7562
7562
  }, {
@@ -7641,7 +7641,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7641
7641
  from: (t, e) => En$1(toPlainDateTimeSlots$1(t, e)),
7642
7642
  compare: (t, e) => Yt$1(toPlainDateTimeSlots$1(t), toPlainDateTimeSlots$1(e))
7643
7643
  }),
7644
- [Ln$1, Vn$1, Jn$1] = createSlotClass$1(qt$1, Pt$1(kt$1, Mt$1), {
7644
+ [Ln$1, Vn$1] = createSlotClass$1(qt$1, Pt$1(kt$1, Mt$1), {
7645
7645
  ...Pn$1,
7646
7646
  ...Dn$1
7647
7647
  }, {
@@ -7660,7 +7660,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7660
7660
  }, {
7661
7661
  from: (t, e) => Vn$1(toPlainMonthDaySlots$1(t, e))
7662
7662
  }),
7663
- [kn$1, qn$1, Rn$1] = createSlotClass$1(Ut$1, Pt$1(Qt$1, Mt$1), {
7663
+ [kn$1, qn$1] = createSlotClass$1(Ut$1, Pt$1(Qt$1, Mt$1), {
7664
7664
  ...Pn$1,
7665
7665
  ...hn$1
7666
7666
  }, {
@@ -7684,7 +7684,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7684
7684
  from: (t, e) => qn$1(toPlainYearMonthSlots$1(t, e)),
7685
7685
  compare: (t, e) => te$1(toPlainYearMonthSlots$1(t), toPlainYearMonthSlots$1(e))
7686
7686
  }),
7687
- [xn$1, Wn$1, Gn$1] = createSlotClass$1(G$1, Pt$1(ue$1, Mt$1), {
7687
+ [xn$1, Wn$1] = createSlotClass$1(G$1, Pt$1(ue$1, Mt$1), {
7688
7688
  ...Pn$1,
7689
7689
  ...Tn$1
7690
7690
  }, {
@@ -7767,7 +7767,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7767
7767
  from: (t, e) => $n$1(toZonedDateTimeSlots$1(t, e)),
7768
7768
  compare: (t, e) => Be$1(toZonedDateTimeSlots$1(t), toZonedDateTimeSlots$1(e))
7769
7769
  }),
7770
- [Hn$1, Kn$1, Qn$1] = createSlotClass$1(Re$1, qe$1, On$1, {
7770
+ [Hn$1, Kn$1] = createSlotClass$1(Re$1, qe$1, On$1, {
7771
7771
  add: (t, e) => Kn$1(Ye$1(0, t, toDurationSlots$1(e))),
7772
7772
  subtract: (t, e) => Kn$1(Ye$1(1, t, toDurationSlots$1(e))),
7773
7773
  until: (t, e, n) => In$1(Ee$1(0, t, toInstantSlots$1(e), n)),
@@ -19301,6 +19301,12 @@ class XFormDOM {
19301
19301
  contextNode: model
19302
19302
  }
19303
19303
  );
19304
+ const setValues = evaluator.evaluateNodes(
19305
+ "./xf:setvalue[@event]",
19306
+ {
19307
+ contextNode: model
19308
+ }
19309
+ );
19304
19310
  const instances = evaluator.evaluateNodes("./xf:instance", {
19305
19311
  contextNode: model
19306
19312
  });
@@ -19336,6 +19342,7 @@ class XFormDOM {
19336
19342
  this.title = title;
19337
19343
  this.model = model;
19338
19344
  this.binds = binds;
19345
+ this.setValues = setValues;
19339
19346
  this.primaryInstance = primaryInstance;
19340
19347
  this.primaryInstanceRoot = primaryInstanceRoot;
19341
19348
  this.itextTranslationElements = itextTranslationElements;
@@ -19353,6 +19360,7 @@ class XFormDOM {
19353
19360
  title;
19354
19361
  model;
19355
19362
  binds;
19363
+ setValues;
19356
19364
  primaryInstance;
19357
19365
  primaryInstanceRoot;
19358
19366
  itextTranslationElements;
@@ -20193,6 +20201,27 @@ class ControlDefinition extends BodyElementDefinition {
20193
20201
  }
20194
20202
  }
20195
20203
 
20204
+ const parseToInteger = (value) => {
20205
+ if (value === null) {
20206
+ return null;
20207
+ }
20208
+ const parsed = Number(value);
20209
+ if (typeof value !== "string" || value.trim() === "" || !Number.isInteger(parsed)) {
20210
+ throw new Error(`Expected an integer, but got: ${value}`);
20211
+ }
20212
+ return parsed;
20213
+ };
20214
+ const parseToFloat = (value) => {
20215
+ if (value === null) {
20216
+ return null;
20217
+ }
20218
+ const parsed = Number(value);
20219
+ if (typeof value !== "string" || value.trim() === "" || Number.isNaN(parsed)) {
20220
+ throw new Error(`Expected a float, but got: ${value}`);
20221
+ }
20222
+ return parsed;
20223
+ };
20224
+
20196
20225
  const inputAppearanceParser = new TokenListParser([
20197
20226
  "multiline",
20198
20227
  "numbers",
@@ -20226,27 +20255,6 @@ const inputAppearanceParser = new TokenListParser([
20226
20255
  "masked"
20227
20256
  ]);
20228
20257
 
20229
- const parseToInteger = (value) => {
20230
- if (value === null) {
20231
- return null;
20232
- }
20233
- const parsed = Number(value);
20234
- if (typeof value !== "string" || value.trim() === "" || !Number.isInteger(parsed)) {
20235
- throw new Error(`Expected an integer, but got: ${value}`);
20236
- }
20237
- return parsed;
20238
- };
20239
- const parseToFloat = (value) => {
20240
- if (value === null) {
20241
- return null;
20242
- }
20243
- const parsed = Number(value);
20244
- if (typeof value !== "string" || value.trim() === "" || Number.isNaN(parsed)) {
20245
- throw new Error(`Expected a float, but got: ${value}`);
20246
- }
20247
- return parsed;
20248
- };
20249
-
20250
20258
  class InputControlDefinition extends ControlDefinition {
20251
20259
  static isCompatible(localName) {
20252
20260
  return localName === "input";
@@ -20623,8 +20631,8 @@ class GroupElementDefinition extends BodyElementDefinition {
20623
20631
  const childName = child.localName;
20624
20632
  return childName !== "label";
20625
20633
  });
20626
- this.children = this.body.getChildElementDefinitions(form, this, element, childElements);
20627
20634
  this.reference = parseNodesetReference(parent, element, "ref");
20635
+ this.children = this.body.getChildElementDefinitions(form, this, element, childElements);
20628
20636
  this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
20629
20637
  this.label = LabelDefinition.forGroup(form, this);
20630
20638
  }
@@ -21230,6 +21238,105 @@ class ItextTranslationsDefinition extends Map {
21230
21238
  }
21231
21239
  }
21232
21240
 
21241
+ class ActionComputationExpression extends DependentExpression {
21242
+ constructor(resultType, expression) {
21243
+ super(resultType, expression);
21244
+ }
21245
+ }
21246
+
21247
+ const XFORM_EVENT = {
21248
+ odkInstanceLoad: "odk-instance-load",
21249
+ odkInstanceFirstLoad: "odk-instance-first-load",
21250
+ odkNewRepeat: "odk-new-repeat",
21251
+ xformsRevalidate: "xforms-revalidate",
21252
+ xformsValueChanged: "xforms-value-changed"
21253
+ };
21254
+
21255
+ class ActionDefinition {
21256
+ constructor(model, element, source) {
21257
+ this.element = element;
21258
+ const ref = ActionDefinition.getRef(model, element);
21259
+ if (!ref) {
21260
+ throw new Error(
21261
+ 'Invalid setvalue element - you must define either "ref" or "bind" attribute'
21262
+ );
21263
+ }
21264
+ this.ref = ref;
21265
+ this.events = ActionDefinition.getEvents(element);
21266
+ const value = ActionDefinition.getValue(element);
21267
+ this.computation = new ActionComputationExpression("string", value);
21268
+ this.source = source;
21269
+ }
21270
+ static getRef(model, setValueElement) {
21271
+ if (setValueElement.hasAttribute("ref")) {
21272
+ return setValueElement.getAttribute("ref") ?? null;
21273
+ }
21274
+ if (setValueElement.hasAttribute("bind")) {
21275
+ const bindId = setValueElement.getAttribute("bind");
21276
+ const bindDefinition = Array.from(model.binds.values()).find((definition) => {
21277
+ return definition.bindElement.getAttribute("id") === bindId;
21278
+ });
21279
+ return bindDefinition?.nodeset ?? null;
21280
+ }
21281
+ return null;
21282
+ }
21283
+ static getValue(element) {
21284
+ if (element.hasAttribute("value")) {
21285
+ return element.getAttribute("value") || "''";
21286
+ }
21287
+ if (element.firstChild && isTextNode(element.firstChild)) {
21288
+ return `'${element.firstChild.nodeValue}'`;
21289
+ }
21290
+ return "''";
21291
+ }
21292
+ static isKnownEvent = (event) => {
21293
+ return Object.values(XFORM_EVENT).includes(event);
21294
+ };
21295
+ static getEvents(element) {
21296
+ const events = element.getAttribute("event")?.split(" ") ?? [];
21297
+ const unknownEvents = events.filter((event) => !this.isKnownEvent(event));
21298
+ if (unknownEvents.length) {
21299
+ throw new Error(
21300
+ `An action was registered for unsupported events: ${unknownEvents.join(", ")}`
21301
+ );
21302
+ }
21303
+ return events;
21304
+ }
21305
+ ref;
21306
+ events;
21307
+ computation;
21308
+ source;
21309
+ }
21310
+
21311
+ const REPEAT_REGEX = /(\[[^\]]*\])/gm;
21312
+ class ModelActionMap extends Map {
21313
+ static fromModel(model) {
21314
+ return new this(model);
21315
+ }
21316
+ static getKey(ref) {
21317
+ return ref.replace(REPEAT_REGEX, "");
21318
+ }
21319
+ constructor(model) {
21320
+ super(
21321
+ model.form.xformDOM.setValues.map((setValueElement) => {
21322
+ const action = new ActionDefinition(model, setValueElement);
21323
+ if (action.events.includes(XFORM_EVENT.odkNewRepeat)) {
21324
+ throw new Error('Model contains "setvalue" element with "odk-new-repeat" event');
21325
+ }
21326
+ const key = ModelActionMap.getKey(action.ref);
21327
+ return [key, action];
21328
+ })
21329
+ );
21330
+ }
21331
+ get(ref) {
21332
+ return super.get(ModelActionMap.getKey(ref));
21333
+ }
21334
+ add(action) {
21335
+ const key = ModelActionMap.getKey(action.ref);
21336
+ this.set(key, action);
21337
+ }
21338
+ }
21339
+
21233
21340
  const defaultBindComputationExpressions = {
21234
21341
  calculate: null,
21235
21342
  constraint: "true()",
@@ -21295,6 +21402,7 @@ class MessageDefinition extends TextRangeDefinition {
21295
21402
  chunks;
21296
21403
  }
21297
21404
 
21405
+ const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
21298
21406
  const getPreloadInput = (bindElement) => {
21299
21407
  const type = bindElement.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "preload");
21300
21408
  if (type == null) {
@@ -21319,9 +21427,38 @@ class BindPreloadDefinition {
21319
21427
  }
21320
21428
  type;
21321
21429
  parameter;
21430
+ event;
21431
+ getValue(context) {
21432
+ if (this.type === "uid") {
21433
+ return context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION);
21434
+ }
21435
+ if (this.type === "timestamp") {
21436
+ return context.evaluator.evaluateString("now()");
21437
+ }
21438
+ if (this.type === "date") {
21439
+ return context.evaluator.evaluateString("today()");
21440
+ }
21441
+ if (this.type === "property") {
21442
+ const properties = context.instanceConfig.preloadProperties;
21443
+ if (this.parameter === "deviceid") {
21444
+ return properties.deviceID;
21445
+ }
21446
+ if (this.parameter === "email") {
21447
+ return properties.email;
21448
+ }
21449
+ if (this.parameter === "phonenumber") {
21450
+ return properties.phoneNumber;
21451
+ }
21452
+ if (this.parameter === "username") {
21453
+ return properties.username;
21454
+ }
21455
+ }
21456
+ return;
21457
+ }
21322
21458
  constructor(input) {
21323
21459
  this.type = input.type;
21324
21460
  this.parameter = input.parameter;
21461
+ this.event = this.type === "timestamp" && this.parameter === "end" ? XFORM_EVENT.xformsRevalidate : XFORM_EVENT.odkInstanceFirstLoad;
21325
21462
  }
21326
21463
  }
21327
21464
 
@@ -21468,10 +21605,7 @@ class BindDefinition extends DependencyContext {
21468
21605
  // TODO: it is unclear whether this will need to be supported.
21469
21606
  // https://github.com/getodk/collect/issues/3758 mentions deprecation.
21470
21607
  saveIncomplete;
21471
- // TODO: these are deferred until prioritized
21472
- // readonly preload: string | null;
21473
- // readonly preloadParams: string | null;
21474
- // readonly 'max-pixels': string | null;
21608
+ // TODO: deferred until prioritized: readonly 'max-pixels': string | null;
21475
21609
  _parentBind;
21476
21610
  get parentBind() {
21477
21611
  let bind = this._parentBind;
@@ -21557,7 +21691,7 @@ const collectDefinitions = (result, definition) => {
21557
21691
  throw new ErrorProductionDesignPendingError();
21558
21692
  }
21559
21693
  result.set(nodeset, definition);
21560
- if (definition.type === "leaf-node") {
21694
+ if (definition.type === "leaf-node" || definition.type === "attribute") {
21561
21695
  return result;
21562
21696
  }
21563
21697
  for (const child of definition.children) {
@@ -21612,33 +21746,39 @@ const serializeElementNamespaceDeclarationXML = (namespaceDeclarations) => {
21612
21746
  });
21613
21747
  }).join("");
21614
21748
  };
21615
- const serializeElementAttributeXML = (attributes) => {
21616
- if (attributes == null) {
21617
- return "";
21618
- }
21619
- return attributes.map((attribute) => {
21620
- return attribute.serializeAttributeXML();
21621
- }).join("");
21622
- };
21623
- const serializeElementXML = (qualifiedName, children, options = {}) => {
21749
+ const serializeElementXML = (qualifiedName, children, attributes, namespaceDeclarations) => {
21624
21750
  const nodeName = qualifiedName.getPrefixedName(
21625
21751
  // options.namespaceDeclarations
21626
21752
  );
21627
- const namespaceDeclarations = serializeElementNamespaceDeclarationXML(
21628
- options.namespaceDeclarations
21629
- );
21630
- const attributes = serializeElementAttributeXML(options.attributes);
21631
- const prefix = `<${nodeName}${namespaceDeclarations}${attributes}`;
21753
+ const serializedNamespaceDeclarations = serializeElementNamespaceDeclarationXML(namespaceDeclarations);
21754
+ const prefix = `<${nodeName}${serializedNamespaceDeclarations}${attributes}`;
21632
21755
  if (children === "") {
21633
21756
  return `${prefix}/>`;
21634
21757
  }
21635
21758
  return `${prefix}>${children}</${nodeName}>`;
21636
21759
  };
21637
- const serializeParentElementXML = (qualifiedName, serializedChildren, options) => {
21638
- return serializeElementXML(qualifiedName, serializedChildren.join(""), options);
21760
+ const serializeAttributeXML = (qualifiedName, xmlValue) => {
21761
+ const nodeName = qualifiedName.getPrefixedName();
21762
+ return ` ${nodeName}="${xmlValue.normalize()}"`;
21763
+ };
21764
+ const serializeParentElementXML = (qualifiedName, children, attributes, namespaceDeclarations) => {
21765
+ const serializedChildren = children.map((child) => child.instanceState.instanceXML).join("");
21766
+ const serializedAttributes = attributes.map((attribute) => attribute.instanceState.instanceXML).join("");
21767
+ return serializeElementXML(
21768
+ qualifiedName,
21769
+ serializedChildren,
21770
+ serializedAttributes,
21771
+ namespaceDeclarations
21772
+ );
21639
21773
  };
21640
- const serializeLeafElementXML = (qualifiedName, xmlValue, options) => {
21641
- return serializeElementXML(qualifiedName, xmlValue.normalize(), options);
21774
+ const serializeLeafElementXML = (qualifiedName, xmlValue, attributes, namespaceDeclarations) => {
21775
+ const serializedAttributes = attributes?.map((attribute) => attribute.instanceState.instanceXML).join("") ?? "";
21776
+ return serializeElementXML(
21777
+ qualifiedName,
21778
+ xmlValue.normalize(),
21779
+ serializedAttributes,
21780
+ namespaceDeclarations
21781
+ );
21642
21782
  };
21643
21783
 
21644
21784
  class NamespaceDeclaration {
@@ -21867,6 +22007,60 @@ class NodeDefinition {
21867
22007
  nodeset;
21868
22008
  }
21869
22009
 
22010
+ class AttributeDefinition extends NodeDefinition {
22011
+ constructor(model, bind, template) {
22012
+ super(bind);
22013
+ this.model = model;
22014
+ this.template = template;
22015
+ const { value } = template;
22016
+ this.root = model.root;
22017
+ this.value = value;
22018
+ this.qualifiedName = template.qualifiedName;
22019
+ this.namespaceDeclarations = new NamespaceDeclarationMap(this);
22020
+ if (this.qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI$1) {
22021
+ this.serializedXML = "";
22022
+ } else {
22023
+ const xmlValue = escapeXMLText(this.value, true);
22024
+ this.serializedXML = serializeAttributeXML(this.qualifiedName, xmlValue);
22025
+ }
22026
+ }
22027
+ serializedXML;
22028
+ value;
22029
+ type = "attribute";
22030
+ namespaceDeclarations;
22031
+ bodyElement = null;
22032
+ root;
22033
+ isTranslated = false;
22034
+ parent = null;
22035
+ children = null;
22036
+ attributes = null;
22037
+ qualifiedName;
22038
+ serializeAttributeXML() {
22039
+ return this.serializedXML;
22040
+ }
22041
+ }
22042
+
22043
+ const isNonNamespaceAttribute = (attribute) => {
22044
+ return attribute.qualifiedName.namespaceURI?.href !== XMLNS_NAMESPACE_URI$1;
22045
+ };
22046
+ class AttributeDefinitionMap extends Map {
22047
+ static from(model, instanceNode) {
22048
+ const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
22049
+ const definitions = nonNamespaceAttributes.map((attribute) => {
22050
+ const bind = model.binds.getOrCreateBindDefinition(attribute.nodeset);
22051
+ return new AttributeDefinition(model, bind, attribute);
22052
+ });
22053
+ return new this(definitions);
22054
+ }
22055
+ constructor(definitions) {
22056
+ super(
22057
+ definitions.map((attribute) => {
22058
+ return [attribute.qualifiedName, attribute];
22059
+ })
22060
+ );
22061
+ }
22062
+ }
22063
+
21870
22064
  class DescendentNodeDefinition extends NodeDefinition {
21871
22065
  constructor(parent, bind, bodyElement) {
21872
22066
  super(bind);
@@ -21882,7 +22076,7 @@ class DescendentNodeDefinition extends NodeDefinition {
21882
22076
  }
21883
22077
 
21884
22078
  class GroupDefinition extends DescendentNodeDefinition {
21885
- constructor(parent, bind, bodyElement, template) {
22079
+ constructor(model, parent, bind, bodyElement, template) {
21886
22080
  if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat")) {
21887
22081
  throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
21888
22082
  }
@@ -21892,11 +22086,13 @@ class GroupDefinition extends DescendentNodeDefinition {
21892
22086
  this.qualifiedName = template.qualifiedName;
21893
22087
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
21894
22088
  this.children = root.buildSubtree(this, template);
22089
+ this.attributes = AttributeDefinitionMap.from(model, template);
21895
22090
  }
21896
22091
  type = "group";
21897
22092
  namespaceDeclarations;
21898
22093
  qualifiedName;
21899
22094
  children;
22095
+ attributes;
21900
22096
  toJSON() {
21901
22097
  const { parent, bodyElement, bind, root, ...rest } = this;
21902
22098
  return rest;
@@ -21904,21 +22100,24 @@ class GroupDefinition extends DescendentNodeDefinition {
21904
22100
  }
21905
22101
 
21906
22102
  class LeafNodeDefinition extends DescendentNodeDefinition {
21907
- constructor(parent, bind, bodyElement, template) {
22103
+ constructor(model, parent, bind, bodyElement, template) {
21908
22104
  if (bodyElement != null && bodyElement.category !== "control") {
21909
22105
  throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
21910
22106
  }
21911
22107
  super(parent, bind, bodyElement);
22108
+ this.model = model;
21912
22109
  this.template = template;
21913
22110
  this.valueType = bind.type.resolved;
21914
22111
  this.qualifiedName = template.qualifiedName;
21915
22112
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
22113
+ this.attributes = AttributeDefinitionMap.from(model, template);
21916
22114
  }
21917
22115
  type = "leaf-node";
21918
22116
  valueType;
21919
22117
  namespaceDeclarations;
21920
22118
  qualifiedName;
21921
22119
  children = null;
22120
+ attributes;
21922
22121
  toJSON() {
21923
22122
  const { bind, bodyElement, parent, root, ...rest } = this;
21924
22123
  return rest;
@@ -21929,13 +22128,13 @@ const isNoteBindDefinition = (bind) => {
21929
22128
  return bind.readonly.isConstantTruthyExpression();
21930
22129
  };
21931
22130
  class NoteNodeDefinition extends LeafNodeDefinition {
21932
- constructor(parent, bind, bodyElement, noteTextDefinition, template) {
21933
- super(parent, bind, bodyElement, template);
22131
+ constructor(model, parent, bind, bodyElement, noteTextDefinition, template) {
22132
+ super(model, parent, bind, bodyElement, template);
21934
22133
  this.bind = bind;
21935
22134
  this.bodyElement = bodyElement;
21936
22135
  this.noteTextDefinition = noteTextDefinition;
21937
22136
  }
21938
- static from(parent, bind, bodyElement, node) {
22137
+ static from(model, parent, bind, bodyElement, node) {
21939
22138
  if (!isNoteBindDefinition(bind) || bodyElement?.type !== "input") {
21940
22139
  return null;
21941
22140
  }
@@ -21944,7 +22143,7 @@ class NoteNodeDefinition extends LeafNodeDefinition {
21944
22143
  if (noteTextDefinition == null) {
21945
22144
  return null;
21946
22145
  }
21947
- return new this(parent, bind, bodyElement, noteTextDefinition, node);
22146
+ return new this(model, parent, bind, bodyElement, noteTextDefinition, node);
21948
22147
  }
21949
22148
  }
21950
22149
 
@@ -25575,7 +25774,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25575
25774
  }, gn = /*@__PURE__*/ g((t => e => e[t]), p.concat("sign")), pn = /*@__PURE__*/ g(((t, e) => t => t[w[e]]), O), On = {
25576
25775
  epochMilliseconds: I,
25577
25776
  epochNanoseconds: v
25578
- }, [wn, In, vn] = createSlotClass(N, j, {
25777
+ }, [wn, In] = createSlotClass(N, j, {
25579
25778
  ...gn,
25580
25779
  blank: y
25581
25780
  }, {
@@ -25649,7 +25848,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25649
25848
  }, {
25650
25849
  from: (t, e) => En(toPlainDateTimeSlots(t, e)),
25651
25850
  compare: (t, e) => Yt(toPlainDateTimeSlots(t), toPlainDateTimeSlots(e))
25652
- }), [Ln, Vn, Jn] = createSlotClass(qt, Pt(kt, Mt), {
25851
+ }), [Ln, Vn] = createSlotClass(qt, Pt(kt, Mt), {
25653
25852
  ...Pn,
25654
25853
  ...Dn
25655
25854
  }, {
@@ -25667,7 +25866,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25667
25866
  valueOf: neverValueOf
25668
25867
  }, {
25669
25868
  from: (t, e) => Vn(toPlainMonthDaySlots(t, e))
25670
- }), [kn, qn, Rn] = createSlotClass(Ut, Pt(Qt, Mt), {
25869
+ }), [kn, qn] = createSlotClass(Ut, Pt(Qt, Mt), {
25671
25870
  ...Pn,
25672
25871
  ...hn
25673
25872
  }, {
@@ -25690,7 +25889,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25690
25889
  }, {
25691
25890
  from: (t, e) => qn(toPlainYearMonthSlots(t, e)),
25692
25891
  compare: (t, e) => te(toPlainYearMonthSlots(t), toPlainYearMonthSlots(e))
25693
- }), [xn, Wn, Gn] = createSlotClass(G, Pt(ue, Mt), {
25892
+ }), [xn, Wn] = createSlotClass(G, Pt(ue, Mt), {
25694
25893
  ...Pn,
25695
25894
  ...Tn
25696
25895
  }, {
@@ -25766,7 +25965,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25766
25965
  }, {
25767
25966
  from: (t, e) => $n(toZonedDateTimeSlots(t, e)),
25768
25967
  compare: (t, e) => Be(toZonedDateTimeSlots(t), toZonedDateTimeSlots(e))
25769
- }), [Hn, Kn, Qn] = createSlotClass(Re, qe, On, {
25968
+ }), [Hn, Kn] = createSlotClass(Re, qe, On, {
25770
25969
  add: (t, e) => Kn(Ye(0, t, toDurationSlots(e))),
25771
25970
  subtract: (t, e) => Kn(Ye(1, t, toDurationSlots(e))),
25772
25971
  until: (t, e, n) => In(Ee(0, t, toInstantSlots(e), n)),
@@ -26155,15 +26354,15 @@ class RangeNodeBoundsDefinition {
26155
26354
  }
26156
26355
  }
26157
26356
  class RangeNodeDefinition extends LeafNodeDefinition {
26158
- constructor(parent, bind, bodyElement, node) {
26159
- super(parent, bind, bodyElement, node);
26357
+ constructor(model, parent, bind, bodyElement, node) {
26358
+ super(model, parent, bind, bodyElement, node);
26160
26359
  this.bind = bind;
26161
26360
  this.bodyElement = bodyElement;
26162
26361
  this.bounds = RangeNodeBoundsDefinition.from(bodyElement.bounds, bind);
26163
26362
  }
26164
- static from(parent, bind, bodyElement, node) {
26363
+ static from(model, parent, bind, bodyElement, node) {
26165
26364
  assertRangeBindDefinition(bind);
26166
- return new this(parent, bind, bodyElement, node);
26365
+ return new this(model, parent, bind, bodyElement, node);
26167
26366
  }
26168
26367
  bounds;
26169
26368
  }
@@ -26228,8 +26427,8 @@ const parseRepeatTemplateElement = (firstRepeatInstanceNode) => {
26228
26427
  return cloneStaticElementStructure(firstRepeatInstanceNode);
26229
26428
  };
26230
26429
  class RepeatDefinition extends DescendentNodeDefinition {
26231
- static from(parent, bind, bodyElement, instanceNodes) {
26232
- return new this(parent, bind, bodyElement, instanceNodes);
26430
+ static from(model, parent, bind, bodyElement, instanceNodes) {
26431
+ return new this(model, parent, bind, bodyElement, instanceNodes);
26233
26432
  }
26234
26433
  type = "repeat";
26235
26434
  children;
@@ -26237,7 +26436,8 @@ class RepeatDefinition extends DescendentNodeDefinition {
26237
26436
  template;
26238
26437
  namespaceDeclarations;
26239
26438
  qualifiedName;
26240
- constructor(parent, bind, bodyElement, instanceNodes) {
26439
+ attributes;
26440
+ constructor(model, parent, bind, bodyElement, instanceNodes) {
26241
26441
  super(parent, bind, bodyElement);
26242
26442
  const { root } = parent;
26243
26443
  const [instanceNode] = instanceNodes;
@@ -26248,6 +26448,7 @@ class RepeatDefinition extends DescendentNodeDefinition {
26248
26448
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
26249
26449
  this.children = root.buildSubtree(self, template);
26250
26450
  const initialCount = this.omitTemplate(instanceNodes).length;
26451
+ this.attributes = AttributeDefinitionMap.from(model, template);
26251
26452
  this.count = RepeatCountControlExpression.from(bodyElement, initialCount);
26252
26453
  }
26253
26454
  isControlled() {
@@ -26266,48 +26467,6 @@ class RepeatDefinition extends DescendentNodeDefinition {
26266
26467
  }
26267
26468
  }
26268
26469
 
26269
- class RootAttributeDefinition {
26270
- serializedXML;
26271
- parent;
26272
- qualifiedName;
26273
- value;
26274
- constructor(root, source) {
26275
- const { qualifiedName, value } = source;
26276
- this.parent = root;
26277
- this.qualifiedName = qualifiedName;
26278
- this.value = value;
26279
- if (qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI$1) {
26280
- this.serializedXML = "";
26281
- } else {
26282
- const nodeName = qualifiedName.getPrefixedName();
26283
- this.serializedXML = ` ${nodeName}="${escapeXMLText(value, true)}"`;
26284
- }
26285
- }
26286
- serializeAttributeXML() {
26287
- return this.serializedXML;
26288
- }
26289
- }
26290
-
26291
- const isNonNamespaceAttribute = (attribute) => {
26292
- return attribute.qualifiedName.namespaceURI?.href !== XMLNS_NAMESPACE_URI$1;
26293
- };
26294
- class RootAttributeMap extends Map {
26295
- static from(root, instanceNode) {
26296
- const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
26297
- const definitions = nonNamespaceAttributes.map((attribute) => {
26298
- return new RootAttributeDefinition(root, attribute);
26299
- });
26300
- return new this(definitions);
26301
- }
26302
- constructor(definitions) {
26303
- super(
26304
- definitions.map((attribute) => {
26305
- return [attribute.qualifiedName, attribute];
26306
- })
26307
- );
26308
- }
26309
- }
26310
-
26311
26470
  class RootDefinition extends NodeDefinition {
26312
26471
  constructor(form, model, submission, classes) {
26313
26472
  const template = model.instance.root;
@@ -26325,7 +26484,7 @@ class RootDefinition extends NodeDefinition {
26325
26484
  this.classes = classes;
26326
26485
  this.qualifiedName = qualifiedName;
26327
26486
  this.template = template;
26328
- this.attributes = RootAttributeMap.from(this, template);
26487
+ this.attributes = AttributeDefinitionMap.from(model, template);
26329
26488
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
26330
26489
  this.children = this.buildSubtree(this, template);
26331
26490
  }
@@ -26339,6 +26498,18 @@ class RootDefinition extends NodeDefinition {
26339
26498
  attributes;
26340
26499
  children;
26341
26500
  isTranslated = false;
26501
+ mapActions(bodyElement) {
26502
+ const source = bodyElement.reference;
26503
+ if (!source) {
26504
+ return;
26505
+ }
26506
+ for (const child of bodyElement.element.children) {
26507
+ if (child.nodeName === "setvalue") {
26508
+ const action = new ActionDefinition(this.model, child, source);
26509
+ this.model.actions.add(action);
26510
+ }
26511
+ }
26512
+ }
26342
26513
  buildSubtree(parent, node) {
26343
26514
  const { form, model } = this;
26344
26515
  const { body } = form;
@@ -26361,8 +26532,11 @@ class RootDefinition extends NodeDefinition {
26361
26532
  const bind = binds.getOrCreateBindDefinition(nodeset);
26362
26533
  const bodyElement = body.getBodyElement(nodeset);
26363
26534
  const [firstChild, ...restChildren] = children;
26535
+ if (bodyElement) {
26536
+ this.mapActions(bodyElement);
26537
+ }
26364
26538
  if (bodyElement?.type === "repeat") {
26365
- return RepeatDefinition.from(parent, bind, bodyElement, children);
26539
+ return RepeatDefinition.from(model, parent, bind, bodyElement, children);
26366
26540
  }
26367
26541
  if (restChildren.length) {
26368
26542
  throw new Error(`Unexpected: multiple elements for non-repeat nodeset: ${nodeset}`);
@@ -26370,11 +26544,11 @@ class RootDefinition extends NodeDefinition {
26370
26544
  const element = firstChild;
26371
26545
  if (element.isLeafElement()) {
26372
26546
  if (bodyElement?.type === "range") {
26373
- return RangeNodeDefinition.from(parent, bind, bodyElement, element);
26547
+ return RangeNodeDefinition.from(model, parent, bind, bodyElement, element);
26374
26548
  }
26375
- return NoteNodeDefinition.from(parent, bind, bodyElement, element) ?? new LeafNodeDefinition(parent, bind, bodyElement, element);
26549
+ return NoteNodeDefinition.from(model, parent, bind, bodyElement, element) ?? new LeafNodeDefinition(model, parent, bind, bodyElement, element);
26376
26550
  }
26377
- return new GroupDefinition(parent, bind, bodyElement, element);
26551
+ return new GroupDefinition(model, parent, bind, bodyElement, element);
26378
26552
  });
26379
26553
  }
26380
26554
  toJSON() {
@@ -26420,6 +26594,7 @@ class ModelDefinition {
26420
26594
  this.form = form;
26421
26595
  const submission = new SubmissionDefinition(form.xformDOM);
26422
26596
  this.binds = ModelBindMap.fromModel(this);
26597
+ this.actions = ModelActionMap.fromModel(this);
26423
26598
  this.instance = parseStaticDocumentFromDOMSubtree(form.xformDOM.primaryInstanceRoot, {
26424
26599
  nodesetPrefix: "/"
26425
26600
  });
@@ -26427,13 +26602,16 @@ class ModelDefinition {
26427
26602
  this.nodes = nodeDefinitionMap(this.root);
26428
26603
  this.itextTranslations = ItextTranslationsDefinition.from(form.xformDOM);
26429
26604
  this.itextChunks = generateItextChunks(form.xformDOM.itextTranslationElements);
26605
+ this.xformsRevalidateListeners = /* @__PURE__ */ new Map();
26430
26606
  }
26431
26607
  binds;
26608
+ actions;
26432
26609
  root;
26433
26610
  nodes;
26434
26611
  instance;
26435
26612
  itextTranslations;
26436
26613
  itextChunks;
26614
+ xformsRevalidateListeners;
26437
26615
  getNodeDefinition(nodeset) {
26438
26616
  const definition = this.nodes.get(nodeset);
26439
26617
  if (definition == null) {
@@ -26448,14 +26626,20 @@ class ModelDefinition {
26448
26626
  }
26449
26627
  return definition;
26450
26628
  }
26451
- toJSON() {
26452
- const { form, ...rest } = this;
26453
- return rest;
26629
+ registerXformsRevalidateListener(ref, listener) {
26630
+ this.xformsRevalidateListeners.set(ref, listener);
26631
+ }
26632
+ triggerXformsRevalidateListeners() {
26633
+ this.xformsRevalidateListeners.forEach((listener) => listener());
26454
26634
  }
26455
26635
  getTranslationChunks(itextId, activeLanguage) {
26456
26636
  const languageMap = this.itextChunks.get(activeLanguage.language);
26457
26637
  return languageMap?.get(itextId) ?? [];
26458
26638
  }
26639
+ toJSON() {
26640
+ const { form, ...rest } = this;
26641
+ return rest;
26642
+ }
26459
26643
  }
26460
26644
 
26461
26645
  class XFormDefinition {
@@ -28519,6 +28703,7 @@ const chunkedInstancePayload = (validation, submissionMeta, instanceFile, attach
28519
28703
  };
28520
28704
  };
28521
28705
  const prepareInstancePayload = (instanceRoot, options) => {
28706
+ instanceRoot.root.parent.model.triggerXformsRevalidateListeners();
28522
28707
  const validation = validateInstance(instanceRoot);
28523
28708
  const submissionMeta = instanceRoot.definition.submission;
28524
28709
  const instanceFile = new InstanceFile(instanceRoot);
@@ -28544,6 +28729,30 @@ const prepareInstancePayload = (instanceRoot, options) => {
28544
28729
  }
28545
28730
  };
28546
28731
 
28732
+ const createAttributeState = (scope) => {
28733
+ return scope.runTask(() => {
28734
+ const baseState = createSignal([]);
28735
+ const [getAttributes, baseSetAttributes] = baseState;
28736
+ const setAttributes = (valueOrSetterCallback) => {
28737
+ let setterCallback;
28738
+ if (typeof valueOrSetterCallback === "function") {
28739
+ setterCallback = valueOrSetterCallback;
28740
+ } else {
28741
+ setterCallback = (_) => valueOrSetterCallback;
28742
+ }
28743
+ return baseSetAttributes((prev) => {
28744
+ return setterCallback(prev);
28745
+ });
28746
+ };
28747
+ const attributes = [getAttributes, setAttributes];
28748
+ return {
28749
+ attributes,
28750
+ getAttributes,
28751
+ setAttributes
28752
+ };
28753
+ });
28754
+ };
28755
+
28547
28756
  const createChildrenState = (parent) => {
28548
28757
  return parent.scope.runTask(() => {
28549
28758
  const baseState = createSignal([]);
@@ -28856,83 +29065,16 @@ class InstanceNode {
28856
29065
  }
28857
29066
  }
28858
29067
 
28859
- class InstanceAttachmentsState extends Map {
28860
- constructor(sourceAttachments = null) {
28861
- super();
28862
- this.sourceAttachments = sourceAttachments;
28863
- }
28864
- getInitialFileValue(instanceNode) {
28865
- if (instanceNode == null) {
28866
- return null;
28867
- }
28868
- return this.sourceAttachments?.get(instanceNode.value) ?? null;
28869
- }
28870
- }
28871
-
28872
- const createRootInstanceState = (node) => {
29068
+ const createAttributeNodeInstanceState = (node) => {
29069
+ const { qualifiedName } = node.definition;
28873
29070
  return {
28874
29071
  get instanceXML() {
28875
- const { namespaceDeclarations, attributes } = node.definition;
28876
- const serializedChildren = node.currentState.children.map((child) => {
28877
- return child.instanceState.instanceXML;
28878
- });
28879
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren, {
28880
- namespaceDeclarations,
28881
- attributes: Array.from(attributes.values())
28882
- });
29072
+ const xmlValue = escapeXMLText(node.currentState.instanceValue, true);
29073
+ return serializeAttributeXML(qualifiedName, xmlValue);
28883
29074
  }
28884
29075
  };
28885
29076
  };
28886
29077
 
28887
- const violationReference = (node) => {
28888
- const violation = node.getViolation();
28889
- if (violation == null) {
28890
- return null;
28891
- }
28892
- const { nodeId } = node;
28893
- return {
28894
- nodeId,
28895
- get reference() {
28896
- return node.currentState.reference;
28897
- },
28898
- violation
28899
- };
28900
- };
28901
- const collectViolationReferences = (context) => {
28902
- return context.getChildren().flatMap((child) => {
28903
- switch (child.nodeType) {
28904
- case "model-value":
28905
- case "input":
28906
- case "note":
28907
- case "select":
28908
- case "range":
28909
- case "rank":
28910
- case "trigger":
28911
- case "upload": {
28912
- const reference = violationReference(child);
28913
- if (reference == null) {
28914
- return [];
28915
- }
28916
- return [reference];
28917
- }
28918
- default:
28919
- return collectViolationReferences(child);
28920
- }
28921
- });
28922
- };
28923
- const createAggregatedViolations = (context, options) => {
28924
- const { scope } = context;
28925
- return scope.runTask(() => {
28926
- const violations = createMemo(() => {
28927
- return collectViolationReferences(context);
28928
- });
28929
- const spec = { violations };
28930
- return createSharedNodeState(scope, spec, options).currentState;
28931
- });
28932
- };
28933
-
28934
- const XFORMS_XPATH_NODE_RANGE_KIND = "comment";
28935
-
28936
29078
  const expressionEvaluator = (evaluator, type, expression, options) => {
28937
29079
  switch (type) {
28938
29080
  case "boolean":
@@ -28990,6 +29132,347 @@ const createComputedExpression = (context, dependentExpression, options = {}) =>
28990
29132
  });
28991
29133
  };
28992
29134
 
29135
+ const REPEAT_INDEX_REGEX = /([^[]*)(\[[0-9]+\])/g;
29136
+ const isInstanceFirstLoad = (context) => {
29137
+ return context.rootDocument.initializationMode === "create";
29138
+ };
29139
+ const isAddingRepeatChild = (context) => {
29140
+ return context.rootDocument.isAttached();
29141
+ };
29142
+ const isEditInitialLoad = (context) => {
29143
+ return context.rootDocument.initializationMode === "edit";
29144
+ };
29145
+ const getInitialValue = (context) => {
29146
+ const sourceNode = context.instanceNode ?? context.definition.template;
29147
+ return context.decodeInstanceValue(sourceNode.value);
29148
+ };
29149
+ const createRelevantValueState = (context, baseValueState) => {
29150
+ return context.scope.runTask(() => {
29151
+ const [getRelevantValue, setValue] = baseValueState;
29152
+ const getValue = createMemo(() => {
29153
+ if (context.isRelevant()) {
29154
+ return getRelevantValue();
29155
+ }
29156
+ return "";
29157
+ });
29158
+ return [getValue, setValue];
29159
+ });
29160
+ };
29161
+ const guardDownstreamReadonlyWrites = (context, baseState) => {
29162
+ const { readonly } = context.definition.bind;
29163
+ if (readonly.isDefaultExpression) {
29164
+ return baseState;
29165
+ }
29166
+ const [getValue, baseSetValue] = baseState;
29167
+ const setValue = (value) => {
29168
+ if (context.isReadonly()) {
29169
+ const reference = untrack(() => context.contextReference());
29170
+ throw new Error(`Cannot write to readonly field: ${reference}`);
29171
+ }
29172
+ return baseSetValue(value);
29173
+ };
29174
+ return [getValue, setValue];
29175
+ };
29176
+ const isLoading = (context) => {
29177
+ return isInstanceFirstLoad(context) || isEditInitialLoad(context);
29178
+ };
29179
+ const setValueIfPreloadDefined = (context, setValue, preload) => {
29180
+ const value = preload.getValue(context);
29181
+ if (value) {
29182
+ setValue(value);
29183
+ }
29184
+ };
29185
+ const postloadValue = (context, setValue, preload) => {
29186
+ const ref = context.contextReference();
29187
+ context.definition.model.registerXformsRevalidateListener(ref, () => {
29188
+ setValueIfPreloadDefined(context, setValue, preload);
29189
+ });
29190
+ };
29191
+ const preloadValue = (context, setValue) => {
29192
+ const { preload } = context.definition.bind;
29193
+ if (!preload) {
29194
+ return;
29195
+ }
29196
+ if (preload.event === XFORM_EVENT.xformsRevalidate) {
29197
+ postloadValue(context, setValue, preload);
29198
+ return;
29199
+ }
29200
+ if (isLoading(context)) {
29201
+ setValueIfPreloadDefined(context, setValue, preload);
29202
+ }
29203
+ };
29204
+ const referencesCurrentNode = (context, ref) => {
29205
+ const nodes = context.evaluator.evaluateNodes(ref, {
29206
+ contextNode: context.contextNode
29207
+ });
29208
+ if (nodes.length > 1) {
29209
+ throw new Error(
29210
+ "You are trying to target a repeated field. Currently you may only target a field in a specific repeat instance. XPath nodeset has more than one node."
29211
+ );
29212
+ }
29213
+ return nodes.includes(context.contextNode);
29214
+ };
29215
+ const bindToRepeatInstance = (context, action) => {
29216
+ let source = action.source;
29217
+ let ref = action.ref;
29218
+ if (source) {
29219
+ const contextRef = context.contextReference();
29220
+ for (const part of contextRef.matchAll(REPEAT_INDEX_REGEX)) {
29221
+ const unbound = part[1] + "/";
29222
+ if (source.includes(unbound)) {
29223
+ const bound = part[0] + "/";
29224
+ source = source.replace(unbound, bound);
29225
+ ref = ref.replace(unbound, bound);
29226
+ }
29227
+ }
29228
+ }
29229
+ return { source, ref };
29230
+ };
29231
+ const createCalculation = (context, setRelevantValue, computation) => {
29232
+ const calculate = createComputedExpression(context, computation);
29233
+ createComputed(() => {
29234
+ if (context.isAttached() && context.isRelevant()) {
29235
+ const calculated = calculate();
29236
+ const value = context.decodeInstanceValue(calculated);
29237
+ setRelevantValue(value);
29238
+ }
29239
+ });
29240
+ };
29241
+ const createValueChangedCalculation = (context, setRelevantValue, action) => {
29242
+ const { source, ref } = bindToRepeatInstance(context, action);
29243
+ if (!source) {
29244
+ return;
29245
+ }
29246
+ let previous = "";
29247
+ const sourceElementExpression = new ActionComputationExpression("string", source);
29248
+ const calculateValueSource = createComputedExpression(context, sourceElementExpression);
29249
+ createComputed(() => {
29250
+ if (context.isAttached() && context.isRelevant()) {
29251
+ const valueSource = calculateValueSource();
29252
+ if (previous !== valueSource) {
29253
+ if (referencesCurrentNode(context, ref)) {
29254
+ const calc = context.evaluator.evaluateString(action.computation.expression, context);
29255
+ const value = context.decodeInstanceValue(calc);
29256
+ setRelevantValue(value);
29257
+ }
29258
+ }
29259
+ previous = valueSource;
29260
+ }
29261
+ });
29262
+ };
29263
+ const registerAction = (context, setValue, action) => {
29264
+ if (action.events.includes(XFORM_EVENT.odkInstanceFirstLoad)) {
29265
+ if (isInstanceFirstLoad(context)) {
29266
+ createCalculation(context, setValue, action.computation);
29267
+ }
29268
+ }
29269
+ if (action.events.includes(XFORM_EVENT.odkInstanceLoad)) {
29270
+ if (!isAddingRepeatChild(context)) {
29271
+ createCalculation(context, setValue, action.computation);
29272
+ }
29273
+ }
29274
+ if (action.events.includes(XFORM_EVENT.odkNewRepeat)) {
29275
+ if (isAddingRepeatChild(context)) {
29276
+ createCalculation(context, setValue, action.computation);
29277
+ }
29278
+ }
29279
+ if (action.events.includes(XFORM_EVENT.xformsValueChanged)) {
29280
+ createValueChangedCalculation(context, setValue, action);
29281
+ }
29282
+ };
29283
+ const createInstanceValueState = (context) => {
29284
+ return context.scope.runTask(() => {
29285
+ const initialValue = getInitialValue(context);
29286
+ const baseValueState = createSignal(initialValue);
29287
+ const relevantValueState = createRelevantValueState(context, baseValueState);
29288
+ const [, setValue] = relevantValueState;
29289
+ preloadValue(context, setValue);
29290
+ const { calculate } = context.definition.bind;
29291
+ if (calculate != null) {
29292
+ createCalculation(context, setValue, calculate);
29293
+ }
29294
+ const action = context.definition.model.actions.get(context.contextReference());
29295
+ if (action) {
29296
+ registerAction(context, setValue, action);
29297
+ }
29298
+ return guardDownstreamReadonlyWrites(context, relevantValueState);
29299
+ });
29300
+ };
29301
+
29302
+ class Attribute {
29303
+ constructor(owner, definition, instanceNode) {
29304
+ this.owner = owner;
29305
+ this.definition = definition;
29306
+ this.instanceNode = instanceNode;
29307
+ const codec = getSharedValueCodec("string");
29308
+ this.contextNode = owner;
29309
+ this.scope = owner.scope;
29310
+ this.rootDocument = owner.rootDocument;
29311
+ this.root = owner.root;
29312
+ this.instanceConfig = owner.instanceConfig;
29313
+ this.getActiveLanguage = owner.getActiveLanguage;
29314
+ this.validationState = { violations: [] };
29315
+ this.valueType = "string";
29316
+ this.evaluator = owner.evaluator;
29317
+ this.decodeInstanceValue = codec.decodeInstanceValue;
29318
+ const instanceValueState = createInstanceValueState(this);
29319
+ const valueState = codec.createRuntimeValueState(instanceValueState);
29320
+ const [getInstanceValue] = instanceValueState;
29321
+ const [, setValueState] = valueState;
29322
+ this.getInstanceValue = getInstanceValue;
29323
+ this.setValueState = setValueState;
29324
+ this.valueState = valueState;
29325
+ const state = createSharedNodeState(
29326
+ owner.scope,
29327
+ {
29328
+ value: this.valueState,
29329
+ instanceValue: this.getInstanceValue,
29330
+ relevant: this.owner.isRelevant
29331
+ },
29332
+ this.instanceConfig
29333
+ );
29334
+ this.state = state;
29335
+ this.engineState = state.engineState;
29336
+ this.currentState = state.currentState;
29337
+ this.instanceState = createAttributeNodeInstanceState(this);
29338
+ }
29339
+ [XPathNodeKindKey] = "attribute";
29340
+ state;
29341
+ engineState;
29342
+ validationState;
29343
+ nodeType = "attribute";
29344
+ currentState;
29345
+ instanceState;
29346
+ appearances = null;
29347
+ nodeOptions = null;
29348
+ valueType;
29349
+ decodeInstanceValue;
29350
+ getInstanceValue;
29351
+ valueState;
29352
+ setValueState;
29353
+ evaluator;
29354
+ getActiveLanguage;
29355
+ contextNode;
29356
+ scope;
29357
+ rootDocument;
29358
+ instanceConfig;
29359
+ root;
29360
+ isRelevant = () => {
29361
+ return this.owner.isRelevant();
29362
+ };
29363
+ isAttached = () => {
29364
+ return this.owner.isAttached();
29365
+ };
29366
+ isReadonly = () => {
29367
+ return true;
29368
+ };
29369
+ hasReadonlyAncestor = () => {
29370
+ const { owner } = this;
29371
+ return owner.hasReadonlyAncestor() || owner.isReadonly();
29372
+ };
29373
+ hasNonRelevantAncestor = () => {
29374
+ const { owner } = this;
29375
+ return owner.hasNonRelevantAncestor() || !owner.isRelevant();
29376
+ };
29377
+ contextReference = () => {
29378
+ return this.owner.contextReference() + "/@" + this.definition.qualifiedName.getPrefixedName();
29379
+ };
29380
+ setValue(value) {
29381
+ this.setValueState(value);
29382
+ return this.root;
29383
+ }
29384
+ getChildren() {
29385
+ return [];
29386
+ }
29387
+ getXPathChildNodes() {
29388
+ return [];
29389
+ }
29390
+ getXPathValue() {
29391
+ return "";
29392
+ }
29393
+ }
29394
+
29395
+ function buildAttributes(owner) {
29396
+ return Array.from(owner.definition.attributes.values()).map((attributeDefinition) => {
29397
+ return new Attribute(owner, attributeDefinition, attributeDefinition.template);
29398
+ });
29399
+ }
29400
+
29401
+ class InstanceAttachmentsState extends Map {
29402
+ constructor(sourceAttachments = null) {
29403
+ super();
29404
+ this.sourceAttachments = sourceAttachments;
29405
+ }
29406
+ getInitialFileValue(instanceNode) {
29407
+ if (instanceNode == null) {
29408
+ return null;
29409
+ }
29410
+ return this.sourceAttachments?.get(instanceNode.value) ?? null;
29411
+ }
29412
+ }
29413
+
29414
+ const createRootInstanceState = (node) => {
29415
+ return {
29416
+ get instanceXML() {
29417
+ return serializeParentElementXML(
29418
+ node.definition.qualifiedName,
29419
+ node.currentState.children,
29420
+ node.currentState.attributes,
29421
+ node.definition.namespaceDeclarations
29422
+ );
29423
+ }
29424
+ };
29425
+ };
29426
+
29427
+ const violationReference = (node) => {
29428
+ const violation = node.getViolation();
29429
+ if (violation == null) {
29430
+ return null;
29431
+ }
29432
+ const { nodeId } = node;
29433
+ return {
29434
+ nodeId,
29435
+ get reference() {
29436
+ return node.currentState.reference;
29437
+ },
29438
+ violation
29439
+ };
29440
+ };
29441
+ const collectViolationReferences = (context) => {
29442
+ return context.getChildren().flatMap((child) => {
29443
+ switch (child.nodeType) {
29444
+ case "model-value":
29445
+ case "input":
29446
+ case "note":
29447
+ case "select":
29448
+ case "range":
29449
+ case "rank":
29450
+ case "trigger":
29451
+ case "upload": {
29452
+ const reference = violationReference(child);
29453
+ if (reference == null) {
29454
+ return [];
29455
+ }
29456
+ return [reference];
29457
+ }
29458
+ default:
29459
+ return collectViolationReferences(child);
29460
+ }
29461
+ });
29462
+ };
29463
+ const createAggregatedViolations = (context, options) => {
29464
+ const { scope } = context;
29465
+ return scope.runTask(() => {
29466
+ const violations = createMemo(() => {
29467
+ return collectViolationReferences(context);
29468
+ });
29469
+ const spec = { violations };
29470
+ return createSharedNodeState(scope, spec, options).currentState;
29471
+ });
29472
+ };
29473
+
29474
+ const XFORMS_XPATH_NODE_RANGE_KIND = "comment";
29475
+
28993
29476
  class DescendantNode extends InstanceNode {
28994
29477
  constructor(parent, instanceNode, definition, options) {
28995
29478
  super(parent.instanceConfig, parent, instanceNode, definition, options);
@@ -29126,10 +29609,11 @@ const createParentNodeInstanceState = (node) => {
29126
29609
  if (!node.currentState.relevant) {
29127
29610
  return "";
29128
29611
  }
29129
- const serializedChildren = node.currentState.children.map((child) => {
29130
- return child.instanceState.instanceXML;
29131
- });
29132
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren);
29612
+ return serializeParentElementXML(
29613
+ node.definition.qualifiedName,
29614
+ node.currentState.children,
29615
+ node.currentState.attributes
29616
+ );
29133
29617
  }
29134
29618
  };
29135
29619
  };
@@ -39418,6 +39902,7 @@ class Group extends DescendantNode {
39418
39902
  super(parent, instanceNode, definition);
39419
39903
  this.appearances = definition.bodyElement?.appearances ?? null;
39420
39904
  const childrenState = createChildrenState(this);
39905
+ const attributeState = createAttributeState(this.scope);
39421
39906
  this.childrenState = childrenState;
39422
39907
  const state = createSharedNodeState(
39423
39908
  this.scope,
@@ -39429,6 +39914,7 @@ class Group extends DescendantNode {
39429
39914
  label: createNodeLabel(this, definition),
39430
39915
  hint: null,
39431
39916
  children: childrenState.childIds,
39917
+ attributes: attributeState.getAttributes,
39432
39918
  valueOptions: null,
39433
39919
  value: null
39434
39920
  },
@@ -39442,6 +39928,7 @@ class Group extends DescendantNode {
39442
39928
  childrenState
39443
39929
  );
39444
39930
  childrenState.setChildren(buildChildren(this));
39931
+ attributeState.setAttributes(buildAttributes(this));
39445
39932
  this.validationState = createAggregatedViolations(this, this.instanceConfig);
39446
39933
  this.instanceState = createParentNodeInstanceState(this);
39447
39934
  }
@@ -39466,92 +39953,12 @@ const createValueNodeInstanceState = (node) => {
39466
39953
  return "";
39467
39954
  }
39468
39955
  const xmlValue = escapeXMLText(node.currentState.instanceValue);
39469
- return serializeLeafElementXML(qualifiedName, xmlValue);
39956
+ const attributes = node.currentState.attributes;
39957
+ return serializeLeafElementXML(qualifiedName, xmlValue, attributes);
39470
39958
  }
39471
39959
  };
39472
39960
  };
39473
39961
 
39474
- const isInstanceFirstLoad = (context) => {
39475
- return context.rootDocument.initializationMode === "create";
39476
- };
39477
- const isEditInitialLoad = (context) => {
39478
- return context.rootDocument.initializationMode === "edit";
39479
- };
39480
- const getInitialValue = (context) => {
39481
- const sourceNode = context.instanceNode ?? context.definition.template;
39482
- return context.decodeInstanceValue(sourceNode.value);
39483
- };
39484
- const createRelevantValueState = (context, baseValueState) => {
39485
- return context.scope.runTask(() => {
39486
- const [getRelevantValue, setValue] = baseValueState;
39487
- const getValue = createMemo(() => {
39488
- if (context.isRelevant()) {
39489
- return getRelevantValue();
39490
- }
39491
- return "";
39492
- });
39493
- return [getValue, setValue];
39494
- });
39495
- };
39496
- const guardDownstreamReadonlyWrites = (context, baseState) => {
39497
- const { readonly } = context.definition.bind;
39498
- if (readonly.isDefaultExpression) {
39499
- return baseState;
39500
- }
39501
- const [getValue, baseSetValue] = baseState;
39502
- const setValue = (value) => {
39503
- if (context.isReadonly()) {
39504
- const reference = untrack(() => context.contextReference());
39505
- throw new Error(`Cannot write to readonly field: ${reference}`);
39506
- }
39507
- return baseSetValue(value);
39508
- };
39509
- return [getValue, setValue];
39510
- };
39511
- const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
39512
- const shouldPreloadUID = (context) => {
39513
- return isInstanceFirstLoad(context) || isEditInitialLoad(context);
39514
- };
39515
- const setPreloadUIDValue = (context, valueState) => {
39516
- const { preload } = context.definition.bind;
39517
- if (preload?.type !== "uid" || !shouldPreloadUID(context)) {
39518
- return;
39519
- }
39520
- const preloadUIDValue = context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION, {
39521
- contextNode: context.contextNode
39522
- });
39523
- const [, setValue] = valueState;
39524
- setValue(preloadUIDValue);
39525
- };
39526
- const createCalculation = (context, setRelevantValue, calculateDefinition) => {
39527
- context.scope.runTask(() => {
39528
- const calculate = createComputedExpression(context, calculateDefinition, {
39529
- defaultValue: ""
39530
- });
39531
- createComputed(() => {
39532
- if (context.isAttached() && context.isRelevant()) {
39533
- const calculated = calculate();
39534
- const value = context.decodeInstanceValue(calculated);
39535
- setRelevantValue(value);
39536
- }
39537
- });
39538
- });
39539
- };
39540
- const createInstanceValueState = (context) => {
39541
- return context.scope.runTask(() => {
39542
- const initialValue = getInitialValue(context);
39543
- const baseValueState = createSignal(initialValue);
39544
- const relevantValueState = createRelevantValueState(context, baseValueState);
39545
- setPreloadUIDValue(context, relevantValueState);
39546
- const { calculate } = context.definition.bind;
39547
- if (calculate != null) {
39548
- const [, setValue] = relevantValueState;
39549
- createCalculation(context, setValue, calculate);
39550
- }
39551
- return guardDownstreamReadonlyWrites(context, relevantValueState);
39552
- });
39553
- };
39554
-
39555
39962
  const engineViolationMessage = (context, role) => {
39556
39963
  const messageText = VALIDATION_TEXT[role];
39557
39964
  const chunk = new TextChunk(context, "literal", messageText);
@@ -39741,6 +40148,7 @@ class InputControl extends ValueNode {
39741
40148
  super(parent, instanceNode, definition, codec);
39742
40149
  this.appearances = definition.bodyElement.appearances;
39743
40150
  this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
40151
+ const attributeState = createAttributeState(this.scope);
39744
40152
  const state = createSharedNodeState(
39745
40153
  this.scope,
39746
40154
  {
@@ -39751,12 +40159,14 @@ class InputControl extends ValueNode {
39751
40159
  label: createNodeLabel(this, definition),
39752
40160
  hint: createFieldHint(this, definition),
39753
40161
  children: null,
40162
+ attributes: attributeState.getAttributes,
39754
40163
  valueOptions: null,
39755
40164
  value: this.valueState,
39756
40165
  instanceValue: this.getInstanceValue
39757
40166
  },
39758
40167
  this.instanceConfig
39759
40168
  );
40169
+ attributeState.setAttributes(buildAttributes(this));
39760
40170
  this.state = state;
39761
40171
  this.engineState = state.engineState;
39762
40172
  this.currentState = state.currentState;
@@ -39784,6 +40194,7 @@ class ModelValue extends ValueNode {
39784
40194
  constructor(parent, instanceNode, definition) {
39785
40195
  const codec = getSharedValueCodec(definition.valueType);
39786
40196
  super(parent, instanceNode, definition, codec);
40197
+ const attributeState = createAttributeState(this.scope);
39787
40198
  const state = createSharedNodeState(
39788
40199
  this.scope,
39789
40200
  {
@@ -39794,12 +40205,14 @@ class ModelValue extends ValueNode {
39794
40205
  label: null,
39795
40206
  hint: null,
39796
40207
  children: null,
40208
+ attributes: attributeState.getAttributes,
39797
40209
  valueOptions: null,
39798
40210
  value: this.valueState,
39799
40211
  instanceValue: this.getInstanceValue
39800
40212
  },
39801
40213
  this.instanceConfig
39802
40214
  );
40215
+ attributeState.setAttributes(buildAttributes(this));
39803
40216
  this.state = state;
39804
40217
  this.engineState = state.engineState;
39805
40218
  this.currentState = state.currentState;
@@ -39891,6 +40304,7 @@ class Note extends ValueNode {
39891
40304
  this.appearances = definition.bodyElement.appearances;
39892
40305
  const isReadonly = createNoteReadonlyThunk(this, definition);
39893
40306
  const noteTextComputation = createNoteText(this, definition.noteTextDefinition);
40307
+ const attributeState = createAttributeState(this.scope);
39894
40308
  let noteText;
39895
40309
  let label;
39896
40310
  let hint;
@@ -39921,12 +40335,14 @@ class Note extends ValueNode {
39921
40335
  hint,
39922
40336
  noteText,
39923
40337
  children: null,
40338
+ attributes: attributeState.getAttributes,
39924
40339
  valueOptions: null,
39925
40340
  value: this.valueState,
39926
40341
  instanceValue: this.getInstanceValue
39927
40342
  },
39928
40343
  this.instanceConfig
39929
40344
  );
40345
+ attributeState.setAttributes(buildAttributes(this));
39930
40346
  this.state = state;
39931
40347
  this.engineState = state.engineState;
39932
40348
  this.currentState = state.currentState;
@@ -39990,6 +40406,7 @@ class RangeControl extends ValueNode {
39990
40406
  const codec = new RangeCodec(baseCodec, definition);
39991
40407
  super(parent, instanceNode, definition, codec);
39992
40408
  this.appearances = definition.bodyElement.appearances;
40409
+ const attributeState = createAttributeState(this.scope);
39993
40410
  const state = createSharedNodeState(
39994
40411
  this.scope,
39995
40412
  {
@@ -40000,12 +40417,14 @@ class RangeControl extends ValueNode {
40000
40417
  label: createNodeLabel(this, definition),
40001
40418
  hint: createFieldHint(this, definition),
40002
40419
  children: null,
40420
+ attributes: attributeState.getAttributes,
40003
40421
  valueOptions: null,
40004
40422
  value: this.valueState,
40005
40423
  instanceValue: this.getInstanceValue
40006
40424
  },
40007
40425
  this.instanceConfig
40008
40426
  );
40427
+ attributeState.setAttributes(buildAttributes(this));
40009
40428
  this.state = state;
40010
40429
  this.engineState = state.engineState;
40011
40430
  this.currentState = state.currentState;
@@ -40223,6 +40642,7 @@ class RankControl extends ValueNode {
40223
40642
  this.mapOptionsByValue = mapOptionsByValue;
40224
40643
  const baseValueState = this.valueState;
40225
40644
  const [baseGetValue, setValue] = baseValueState;
40645
+ const attributeState = createAttributeState(this.scope);
40226
40646
  const getValue = this.scope.runTask(() => {
40227
40647
  return createMemo(() => {
40228
40648
  const options = valueOptions();
@@ -40257,12 +40677,14 @@ class RankControl extends ValueNode {
40257
40677
  label: createNodeLabel(this, definition),
40258
40678
  hint: createFieldHint(this, definition),
40259
40679
  children: null,
40680
+ attributes: attributeState.getAttributes,
40260
40681
  valueOptions,
40261
40682
  value: valueState,
40262
40683
  instanceValue: this.getInstanceValue
40263
40684
  },
40264
40685
  this.instanceConfig
40265
40686
  );
40687
+ attributeState.setAttributes(buildAttributes(this));
40266
40688
  this.state = state;
40267
40689
  this.engineState = state.engineState;
40268
40690
  this.currentState = state.currentState;
@@ -40318,26 +40740,17 @@ const createNodeRangeInstanceState = (node) => {
40318
40740
  };
40319
40741
  };
40320
40742
 
40321
- class TemplatedNodeAttributeSerializationError extends Error {
40322
- constructor() {
40323
- super("Template attribute omission not implemented");
40324
- }
40325
- }
40326
-
40327
40743
  const createTemplatedNodeInstanceState = (node) => {
40328
40744
  return {
40329
40745
  get instanceXML() {
40330
40746
  if (!node.currentState.relevant) {
40331
40747
  return "";
40332
40748
  }
40333
- const serializedChildren = node.currentState.children.map((child) => {
40334
- return child.instanceState.instanceXML;
40335
- });
40336
- const { attributes } = node.currentState;
40337
- if (attributes != null) {
40338
- throw new TemplatedNodeAttributeSerializationError();
40339
- }
40340
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren);
40749
+ return serializeParentElementXML(
40750
+ node.definition.qualifiedName,
40751
+ node.currentState.children,
40752
+ node.currentState.attributes
40753
+ );
40341
40754
  }
40342
40755
  };
40343
40756
  };
@@ -40358,6 +40771,7 @@ class RepeatInstance extends DescendantNode {
40358
40771
  this.parent = parent;
40359
40772
  this.appearances = definition.bodyElement.appearances;
40360
40773
  const childrenState = createChildrenState(this);
40774
+ const attributeState = createAttributeState(this.scope);
40361
40775
  this.childrenState = childrenState;
40362
40776
  this.currentIndex = currentIndex;
40363
40777
  const state = createSharedNodeState(
@@ -40370,7 +40784,7 @@ class RepeatInstance extends DescendantNode {
40370
40784
  // TODO: only-child <group><label>
40371
40785
  label: createNodeLabel(this, definition),
40372
40786
  hint: null,
40373
- attributes: null,
40787
+ attributes: attributeState.getAttributes,
40374
40788
  children: childrenState.childIds,
40375
40789
  valueOptions: null,
40376
40790
  value: null
@@ -40431,6 +40845,7 @@ class RepeatInstance extends DescendantNode {
40431
40845
 
40432
40846
  class BaseRepeatRange extends DescendantNode {
40433
40847
  childrenState;
40848
+ attributeState;
40434
40849
  /**
40435
40850
  * A repeat range doesn't have a corresponding primary instance element of its
40436
40851
  * own. It is represented in the following ways:
@@ -40470,7 +40885,9 @@ class BaseRepeatRange extends DescendantNode {
40470
40885
  super(parent, definition.template, definition);
40471
40886
  const repeatRange = this;
40472
40887
  const childrenState = createChildrenState(repeatRange);
40888
+ const attributeState = createAttributeState(this.scope);
40473
40889
  this.childrenState = childrenState;
40890
+ this.attributeState = attributeState;
40474
40891
  const state = createSharedNodeState(
40475
40892
  this.scope,
40476
40893
  {
@@ -40481,6 +40898,7 @@ class BaseRepeatRange extends DescendantNode {
40481
40898
  label: createNodeLabel(this, definition),
40482
40899
  hint: null,
40483
40900
  children: childrenState.childIds,
40901
+ attributes: attributeState.getAttributes,
40484
40902
  valueOptions: null,
40485
40903
  value: null
40486
40904
  },
@@ -40548,6 +40966,9 @@ class BaseRepeatRange extends DescendantNode {
40548
40966
  getChildren() {
40549
40967
  return this.childrenState.getChildren();
40550
40968
  }
40969
+ getAttributes() {
40970
+ return this.attributeState.getAttributes();
40971
+ }
40551
40972
  }
40552
40973
 
40553
40974
  class RepeatRangeControlled extends BaseRepeatRange {
@@ -40755,6 +41176,7 @@ class SelectControl extends ValueNode {
40755
41176
  super(parent, instanceNode, definition, codec);
40756
41177
  this.appearances = definition.bodyElement.appearances;
40757
41178
  this.selectType = definition.bodyElement.type;
41179
+ const attributeState = createAttributeState(this.scope);
40758
41180
  const valueOptions = createItemCollection(this);
40759
41181
  const isSelectWithImages = this.scope.runTask(() => {
40760
41182
  return createMemo(() => valueOptions().some((item) => !!item.label.imageSource));
@@ -40791,6 +41213,7 @@ class SelectControl extends ValueNode {
40791
41213
  label: createNodeLabel(this, definition),
40792
41214
  hint: createFieldHint(this, definition),
40793
41215
  children: null,
41216
+ attributes: attributeState.getAttributes,
40794
41217
  valueOptions,
40795
41218
  value: valueState,
40796
41219
  instanceValue: this.getInstanceValue,
@@ -40798,6 +41221,7 @@ class SelectControl extends ValueNode {
40798
41221
  },
40799
41222
  this.instanceConfig
40800
41223
  );
41224
+ attributeState.setAttributes(buildAttributes(this));
40801
41225
  this.state = state;
40802
41226
  this.engineState = state.engineState;
40803
41227
  this.currentState = state.currentState;
@@ -40916,6 +41340,7 @@ class TriggerControl extends ValueNode {
40916
41340
  constructor(parent, instanceNode, definition) {
40917
41341
  super(parent, instanceNode, definition, codec);
40918
41342
  this.appearances = definition.bodyElement.appearances;
41343
+ const attributeState = createAttributeState(this.scope);
40919
41344
  const state = createSharedNodeState(
40920
41345
  this.scope,
40921
41346
  {
@@ -40926,12 +41351,14 @@ class TriggerControl extends ValueNode {
40926
41351
  label: createNodeLabel(this, definition),
40927
41352
  hint: createFieldHint(this, definition),
40928
41353
  children: null,
41354
+ attributes: attributeState.getAttributes,
40929
41355
  valueOptions: null,
40930
41356
  value: this.valueState,
40931
41357
  instanceValue: this.getInstanceValue
40932
41358
  },
40933
41359
  this.instanceConfig
40934
41360
  );
41361
+ attributeState.setAttributes(buildAttributes(this));
40935
41362
  this.state = state;
40936
41363
  this.engineState = state.engineState;
40937
41364
  this.currentState = state.currentState;
@@ -41124,6 +41551,7 @@ class UploadControl extends DescendantNode {
41124
41551
  this.nodeOptions = definition.bodyElement.options;
41125
41552
  const instanceAttachment = createInstanceAttachment(this);
41126
41553
  this.instanceAttachment = instanceAttachment;
41554
+ const attributeState = createAttributeState(this.scope);
41127
41555
  this.decodeInstanceValue = instanceAttachment.decodeInstanceValue;
41128
41556
  this.getXPathValue = instanceAttachment.getInstanceValue;
41129
41557
  const state = createSharedNodeState(
@@ -41138,6 +41566,7 @@ class UploadControl extends DescendantNode {
41138
41566
  children: null,
41139
41567
  valueOptions: null,
41140
41568
  value: instanceAttachment.valueState,
41569
+ attributes: attributeState.getAttributes,
41141
41570
  instanceValue: instanceAttachment.getInstanceValue
41142
41571
  },
41143
41572
  this.instanceConfig
@@ -41273,7 +41702,7 @@ const buildMetaValueElement = (group, localName, value) => {
41273
41702
  const buildDeprecatedIDDefinition = (group, instanceNode) => {
41274
41703
  const nodeset = instanceNode.nodeset;
41275
41704
  const bind = group.model.binds.getOrCreateBindDefinition(nodeset);
41276
- return new LeafNodeDefinition(group.parent.definition, bind, null, instanceNode);
41705
+ return new LeafNodeDefinition(group.model, group.parent.definition, bind, null, instanceNode);
41277
41706
  };
41278
41707
  const buildDeprecatedID = (group, value) => {
41279
41708
  const instanceNode = buildMetaValueElement(group, DEPRECATED_ID_LOCAL_NAME, value);
@@ -41500,6 +41929,7 @@ class Root extends DescendantNode {
41500
41929
  });
41501
41930
  this.classes = parent.classes;
41502
41931
  const childrenState = createChildrenState(this);
41932
+ const attributeState = createAttributeState(this.scope);
41503
41933
  this.childrenState = childrenState;
41504
41934
  this.languages = parent.languages;
41505
41935
  const state = createSharedNodeState(
@@ -41514,7 +41944,8 @@ class Root extends DescendantNode {
41514
41944
  required: () => false,
41515
41945
  valueOptions: null,
41516
41946
  value: null,
41517
- children: childrenState.childIds
41947
+ children: childrenState.childIds,
41948
+ attributes: attributeState.getAttributes
41518
41949
  },
41519
41950
  this.instanceConfig
41520
41951
  );
@@ -41526,6 +41957,7 @@ class Root extends DescendantNode {
41526
41957
  childrenState
41527
41958
  );
41528
41959
  childrenState.setChildren(buildChildren(this));
41960
+ attributeState.setAttributes(buildAttributes(this));
41529
41961
  this.validationState = createAggregatedViolations(this, this.instanceConfig);
41530
41962
  this.instanceState = createRootInstanceState(this);
41531
41963
  }
@@ -41606,6 +42038,7 @@ class PrimaryInstance extends InstanceNode {
41606
42038
  this.evaluator = evaluator;
41607
42039
  this.classes = definition.classes;
41608
42040
  const childrenState = createChildrenState(this);
42041
+ const attributeState = createAttributeState(this.scope);
41609
42042
  this.getChildren = childrenState.getChildren;
41610
42043
  const stateSpec = {
41611
42044
  activeLanguage: getActiveLanguage,
@@ -41617,7 +42050,8 @@ class PrimaryInstance extends InstanceNode {
41617
42050
  required: false,
41618
42051
  valueOptions: null,
41619
42052
  value: null,
41620
- children: childrenState.childIds
42053
+ children: childrenState.childIds,
42054
+ attributes: attributeState.getAttributes
41621
42055
  };
41622
42056
  const state = createSharedNodeState(scope, stateSpec, config);
41623
42057
  this.state = state;
@@ -41632,6 +42066,7 @@ class PrimaryInstance extends InstanceNode {
41632
42066
  };
41633
42067
  this.instanceState = createPrimaryInstanceState(this);
41634
42068
  childrenState.setChildren([root]);
42069
+ attributeState.setAttributes(buildAttributes(this));
41635
42070
  setIsAttached(true);
41636
42071
  }
41637
42072
  // PrimaryInstanceDocument
@@ -41682,7 +42117,8 @@ class FormInstance {
41682
42117
  const { mode, initialState, instanceConfig } = options;
41683
42118
  const config = {
41684
42119
  clientStateFactory: instanceConfig.stateFactory ?? identity,
41685
- computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null)
42120
+ computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null),
42121
+ preloadProperties: instanceConfig.preloadProperties ?? {}
41686
42122
  };
41687
42123
  const primaryInstanceOptions = {
41688
42124
  ...options.instanceOptions,