@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/index.js CHANGED
@@ -7899,7 +7899,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7899
7899
  epochMilliseconds: I$1,
7900
7900
  epochNanoseconds: v$1
7901
7901
  },
7902
- [wn$1, In$1, vn$1] = createSlotClass$1(N$1, j$1, {
7902
+ [wn$1, In$1] = createSlotClass$1(N$1, j$1, {
7903
7903
  ...gn$1,
7904
7904
  blank: y$1
7905
7905
  }, {
@@ -7984,7 +7984,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
7984
7984
  from: (t, e) => En$1(toPlainDateTimeSlots$1(t, e)),
7985
7985
  compare: (t, e) => Yt$1(toPlainDateTimeSlots$1(t), toPlainDateTimeSlots$1(e))
7986
7986
  }),
7987
- [Ln$1, Vn$1, Jn$1] = createSlotClass$1(qt$1, Pt$1(kt$1, Mt$1), {
7987
+ [Ln$1, Vn$1] = createSlotClass$1(qt$1, Pt$1(kt$1, Mt$1), {
7988
7988
  ...Pn$1,
7989
7989
  ...Dn$1
7990
7990
  }, {
@@ -8003,7 +8003,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
8003
8003
  }, {
8004
8004
  from: (t, e) => Vn$1(toPlainMonthDaySlots$1(t, e))
8005
8005
  }),
8006
- [kn$1, qn$1, Rn$1] = createSlotClass$1(Ut$1, Pt$1(Qt$1, Mt$1), {
8006
+ [kn$1, qn$1] = createSlotClass$1(Ut$1, Pt$1(Qt$1, Mt$1), {
8007
8007
  ...Pn$1,
8008
8008
  ...hn$1
8009
8009
  }, {
@@ -8027,7 +8027,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
8027
8027
  from: (t, e) => qn$1(toPlainYearMonthSlots$1(t, e)),
8028
8028
  compare: (t, e) => te$1(toPlainYearMonthSlots$1(t), toPlainYearMonthSlots$1(e))
8029
8029
  }),
8030
- [xn$1, Wn$1, Gn$1] = createSlotClass$1(G$1, Pt$1(ue$1, Mt$1), {
8030
+ [xn$1, Wn$1] = createSlotClass$1(G$1, Pt$1(ue$1, Mt$1), {
8031
8031
  ...Pn$1,
8032
8032
  ...Tn$1
8033
8033
  }, {
@@ -8110,7 +8110,7 @@ const sn$1 = /*@__PURE__*/new WeakMap(),
8110
8110
  from: (t, e) => $n$1(toZonedDateTimeSlots$1(t, e)),
8111
8111
  compare: (t, e) => Be$1(toZonedDateTimeSlots$1(t), toZonedDateTimeSlots$1(e))
8112
8112
  }),
8113
- [Hn$1, Kn$1, Qn$1] = createSlotClass$1(Re$1, qe$1, On$1, {
8113
+ [Hn$1, Kn$1] = createSlotClass$1(Re$1, qe$1, On$1, {
8114
8114
  add: (t, e) => Kn$1(Ye$1(0, t, toDurationSlots$1(e))),
8115
8115
  subtract: (t, e) => Kn$1(Ye$1(1, t, toDurationSlots$1(e))),
8116
8116
  until: (t, e, n) => In$1(Ee$1(0, t, toInstantSlots$1(e), n)),
@@ -19644,6 +19644,12 @@ class XFormDOM {
19644
19644
  contextNode: model
19645
19645
  }
19646
19646
  );
19647
+ const setValues = evaluator.evaluateNodes(
19648
+ "./xf:setvalue[@event]",
19649
+ {
19650
+ contextNode: model
19651
+ }
19652
+ );
19647
19653
  const instances = evaluator.evaluateNodes("./xf:instance", {
19648
19654
  contextNode: model
19649
19655
  });
@@ -19679,6 +19685,7 @@ class XFormDOM {
19679
19685
  this.title = title;
19680
19686
  this.model = model;
19681
19687
  this.binds = binds;
19688
+ this.setValues = setValues;
19682
19689
  this.primaryInstance = primaryInstance;
19683
19690
  this.primaryInstanceRoot = primaryInstanceRoot;
19684
19691
  this.itextTranslationElements = itextTranslationElements;
@@ -19696,6 +19703,7 @@ class XFormDOM {
19696
19703
  title;
19697
19704
  model;
19698
19705
  binds;
19706
+ setValues;
19699
19707
  primaryInstance;
19700
19708
  primaryInstanceRoot;
19701
19709
  itextTranslationElements;
@@ -20536,6 +20544,27 @@ class ControlDefinition extends BodyElementDefinition {
20536
20544
  }
20537
20545
  }
20538
20546
 
20547
+ const parseToInteger = (value) => {
20548
+ if (value === null) {
20549
+ return null;
20550
+ }
20551
+ const parsed = Number(value);
20552
+ if (typeof value !== "string" || value.trim() === "" || !Number.isInteger(parsed)) {
20553
+ throw new Error(`Expected an integer, but got: ${value}`);
20554
+ }
20555
+ return parsed;
20556
+ };
20557
+ const parseToFloat = (value) => {
20558
+ if (value === null) {
20559
+ return null;
20560
+ }
20561
+ const parsed = Number(value);
20562
+ if (typeof value !== "string" || value.trim() === "" || Number.isNaN(parsed)) {
20563
+ throw new Error(`Expected a float, but got: ${value}`);
20564
+ }
20565
+ return parsed;
20566
+ };
20567
+
20539
20568
  const inputAppearanceParser = new TokenListParser([
20540
20569
  "multiline",
20541
20570
  "numbers",
@@ -20569,27 +20598,6 @@ const inputAppearanceParser = new TokenListParser([
20569
20598
  "masked"
20570
20599
  ]);
20571
20600
 
20572
- const parseToInteger = (value) => {
20573
- if (value === null) {
20574
- return null;
20575
- }
20576
- const parsed = Number(value);
20577
- if (typeof value !== "string" || value.trim() === "" || !Number.isInteger(parsed)) {
20578
- throw new Error(`Expected an integer, but got: ${value}`);
20579
- }
20580
- return parsed;
20581
- };
20582
- const parseToFloat = (value) => {
20583
- if (value === null) {
20584
- return null;
20585
- }
20586
- const parsed = Number(value);
20587
- if (typeof value !== "string" || value.trim() === "" || Number.isNaN(parsed)) {
20588
- throw new Error(`Expected a float, but got: ${value}`);
20589
- }
20590
- return parsed;
20591
- };
20592
-
20593
20601
  class InputControlDefinition extends ControlDefinition {
20594
20602
  static isCompatible(localName) {
20595
20603
  return localName === "input";
@@ -20966,8 +20974,8 @@ class GroupElementDefinition extends BodyElementDefinition {
20966
20974
  const childName = child.localName;
20967
20975
  return childName !== "label";
20968
20976
  });
20969
- this.children = this.body.getChildElementDefinitions(form, this, element, childElements);
20970
20977
  this.reference = parseNodesetReference(parent, element, "ref");
20978
+ this.children = this.body.getChildElementDefinitions(form, this, element, childElements);
20971
20979
  this.appearances = structureElementAppearanceParser.parseFrom(element, "appearance");
20972
20980
  this.label = LabelDefinition.forGroup(form, this);
20973
20981
  }
@@ -21573,6 +21581,105 @@ class ItextTranslationsDefinition extends Map {
21573
21581
  }
21574
21582
  }
21575
21583
 
21584
+ class ActionComputationExpression extends DependentExpression {
21585
+ constructor(resultType, expression) {
21586
+ super(resultType, expression);
21587
+ }
21588
+ }
21589
+
21590
+ const XFORM_EVENT = {
21591
+ odkInstanceLoad: "odk-instance-load",
21592
+ odkInstanceFirstLoad: "odk-instance-first-load",
21593
+ odkNewRepeat: "odk-new-repeat",
21594
+ xformsRevalidate: "xforms-revalidate",
21595
+ xformsValueChanged: "xforms-value-changed"
21596
+ };
21597
+
21598
+ class ActionDefinition {
21599
+ constructor(model, element, source) {
21600
+ this.element = element;
21601
+ const ref = ActionDefinition.getRef(model, element);
21602
+ if (!ref) {
21603
+ throw new Error(
21604
+ 'Invalid setvalue element - you must define either "ref" or "bind" attribute'
21605
+ );
21606
+ }
21607
+ this.ref = ref;
21608
+ this.events = ActionDefinition.getEvents(element);
21609
+ const value = ActionDefinition.getValue(element);
21610
+ this.computation = new ActionComputationExpression("string", value);
21611
+ this.source = source;
21612
+ }
21613
+ static getRef(model, setValueElement) {
21614
+ if (setValueElement.hasAttribute("ref")) {
21615
+ return setValueElement.getAttribute("ref") ?? null;
21616
+ }
21617
+ if (setValueElement.hasAttribute("bind")) {
21618
+ const bindId = setValueElement.getAttribute("bind");
21619
+ const bindDefinition = Array.from(model.binds.values()).find((definition) => {
21620
+ return definition.bindElement.getAttribute("id") === bindId;
21621
+ });
21622
+ return bindDefinition?.nodeset ?? null;
21623
+ }
21624
+ return null;
21625
+ }
21626
+ static getValue(element) {
21627
+ if (element.hasAttribute("value")) {
21628
+ return element.getAttribute("value") || "''";
21629
+ }
21630
+ if (element.firstChild && isTextNode(element.firstChild)) {
21631
+ return `'${element.firstChild.nodeValue}'`;
21632
+ }
21633
+ return "''";
21634
+ }
21635
+ static isKnownEvent = (event) => {
21636
+ return Object.values(XFORM_EVENT).includes(event);
21637
+ };
21638
+ static getEvents(element) {
21639
+ const events = element.getAttribute("event")?.split(" ") ?? [];
21640
+ const unknownEvents = events.filter((event) => !this.isKnownEvent(event));
21641
+ if (unknownEvents.length) {
21642
+ throw new Error(
21643
+ `An action was registered for unsupported events: ${unknownEvents.join(", ")}`
21644
+ );
21645
+ }
21646
+ return events;
21647
+ }
21648
+ ref;
21649
+ events;
21650
+ computation;
21651
+ source;
21652
+ }
21653
+
21654
+ const REPEAT_REGEX = /(\[[^\]]*\])/gm;
21655
+ class ModelActionMap extends Map {
21656
+ static fromModel(model) {
21657
+ return new this(model);
21658
+ }
21659
+ static getKey(ref) {
21660
+ return ref.replace(REPEAT_REGEX, "");
21661
+ }
21662
+ constructor(model) {
21663
+ super(
21664
+ model.form.xformDOM.setValues.map((setValueElement) => {
21665
+ const action = new ActionDefinition(model, setValueElement);
21666
+ if (action.events.includes(XFORM_EVENT.odkNewRepeat)) {
21667
+ throw new Error('Model contains "setvalue" element with "odk-new-repeat" event');
21668
+ }
21669
+ const key = ModelActionMap.getKey(action.ref);
21670
+ return [key, action];
21671
+ })
21672
+ );
21673
+ }
21674
+ get(ref) {
21675
+ return super.get(ModelActionMap.getKey(ref));
21676
+ }
21677
+ add(action) {
21678
+ const key = ModelActionMap.getKey(action.ref);
21679
+ this.set(key, action);
21680
+ }
21681
+ }
21682
+
21576
21683
  const defaultBindComputationExpressions = {
21577
21684
  calculate: null,
21578
21685
  constraint: "true()",
@@ -21638,6 +21745,7 @@ class MessageDefinition extends TextRangeDefinition {
21638
21745
  chunks;
21639
21746
  }
21640
21747
 
21748
+ const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
21641
21749
  const getPreloadInput = (bindElement) => {
21642
21750
  const type = bindElement.getAttributeNS(JAVAROSA_NAMESPACE_URI$1, "preload");
21643
21751
  if (type == null) {
@@ -21662,9 +21770,38 @@ class BindPreloadDefinition {
21662
21770
  }
21663
21771
  type;
21664
21772
  parameter;
21773
+ event;
21774
+ getValue(context) {
21775
+ if (this.type === "uid") {
21776
+ return context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION);
21777
+ }
21778
+ if (this.type === "timestamp") {
21779
+ return context.evaluator.evaluateString("now()");
21780
+ }
21781
+ if (this.type === "date") {
21782
+ return context.evaluator.evaluateString("today()");
21783
+ }
21784
+ if (this.type === "property") {
21785
+ const properties = context.instanceConfig.preloadProperties;
21786
+ if (this.parameter === "deviceid") {
21787
+ return properties.deviceID;
21788
+ }
21789
+ if (this.parameter === "email") {
21790
+ return properties.email;
21791
+ }
21792
+ if (this.parameter === "phonenumber") {
21793
+ return properties.phoneNumber;
21794
+ }
21795
+ if (this.parameter === "username") {
21796
+ return properties.username;
21797
+ }
21798
+ }
21799
+ return;
21800
+ }
21665
21801
  constructor(input) {
21666
21802
  this.type = input.type;
21667
21803
  this.parameter = input.parameter;
21804
+ this.event = this.type === "timestamp" && this.parameter === "end" ? XFORM_EVENT.xformsRevalidate : XFORM_EVENT.odkInstanceFirstLoad;
21668
21805
  }
21669
21806
  }
21670
21807
 
@@ -21811,10 +21948,7 @@ class BindDefinition extends DependencyContext {
21811
21948
  // TODO: it is unclear whether this will need to be supported.
21812
21949
  // https://github.com/getodk/collect/issues/3758 mentions deprecation.
21813
21950
  saveIncomplete;
21814
- // TODO: these are deferred until prioritized
21815
- // readonly preload: string | null;
21816
- // readonly preloadParams: string | null;
21817
- // readonly 'max-pixels': string | null;
21951
+ // TODO: deferred until prioritized: readonly 'max-pixels': string | null;
21818
21952
  _parentBind;
21819
21953
  get parentBind() {
21820
21954
  let bind = this._parentBind;
@@ -21900,7 +22034,7 @@ const collectDefinitions = (result, definition) => {
21900
22034
  throw new ErrorProductionDesignPendingError();
21901
22035
  }
21902
22036
  result.set(nodeset, definition);
21903
- if (definition.type === "leaf-node") {
22037
+ if (definition.type === "leaf-node" || definition.type === "attribute") {
21904
22038
  return result;
21905
22039
  }
21906
22040
  for (const child of definition.children) {
@@ -21955,33 +22089,39 @@ const serializeElementNamespaceDeclarationXML = (namespaceDeclarations) => {
21955
22089
  });
21956
22090
  }).join("");
21957
22091
  };
21958
- const serializeElementAttributeXML = (attributes) => {
21959
- if (attributes == null) {
21960
- return "";
21961
- }
21962
- return attributes.map((attribute) => {
21963
- return attribute.serializeAttributeXML();
21964
- }).join("");
21965
- };
21966
- const serializeElementXML = (qualifiedName, children, options = {}) => {
22092
+ const serializeElementXML = (qualifiedName, children, attributes, namespaceDeclarations) => {
21967
22093
  const nodeName = qualifiedName.getPrefixedName(
21968
22094
  // options.namespaceDeclarations
21969
22095
  );
21970
- const namespaceDeclarations = serializeElementNamespaceDeclarationXML(
21971
- options.namespaceDeclarations
21972
- );
21973
- const attributes = serializeElementAttributeXML(options.attributes);
21974
- const prefix = `<${nodeName}${namespaceDeclarations}${attributes}`;
22096
+ const serializedNamespaceDeclarations = serializeElementNamespaceDeclarationXML(namespaceDeclarations);
22097
+ const prefix = `<${nodeName}${serializedNamespaceDeclarations}${attributes}`;
21975
22098
  if (children === "") {
21976
22099
  return `${prefix}/>`;
21977
22100
  }
21978
22101
  return `${prefix}>${children}</${nodeName}>`;
21979
22102
  };
21980
- const serializeParentElementXML = (qualifiedName, serializedChildren, options) => {
21981
- return serializeElementXML(qualifiedName, serializedChildren.join(""), options);
22103
+ const serializeAttributeXML = (qualifiedName, xmlValue) => {
22104
+ const nodeName = qualifiedName.getPrefixedName();
22105
+ return ` ${nodeName}="${xmlValue.normalize()}"`;
22106
+ };
22107
+ const serializeParentElementXML = (qualifiedName, children, attributes, namespaceDeclarations) => {
22108
+ const serializedChildren = children.map((child) => child.instanceState.instanceXML).join("");
22109
+ const serializedAttributes = attributes.map((attribute) => attribute.instanceState.instanceXML).join("");
22110
+ return serializeElementXML(
22111
+ qualifiedName,
22112
+ serializedChildren,
22113
+ serializedAttributes,
22114
+ namespaceDeclarations
22115
+ );
21982
22116
  };
21983
- const serializeLeafElementXML = (qualifiedName, xmlValue, options) => {
21984
- return serializeElementXML(qualifiedName, xmlValue.normalize(), options);
22117
+ const serializeLeafElementXML = (qualifiedName, xmlValue, attributes, namespaceDeclarations) => {
22118
+ const serializedAttributes = attributes?.map((attribute) => attribute.instanceState.instanceXML).join("") ?? "";
22119
+ return serializeElementXML(
22120
+ qualifiedName,
22121
+ xmlValue.normalize(),
22122
+ serializedAttributes,
22123
+ namespaceDeclarations
22124
+ );
21985
22125
  };
21986
22126
 
21987
22127
  class NamespaceDeclaration {
@@ -22210,6 +22350,60 @@ class NodeDefinition {
22210
22350
  nodeset;
22211
22351
  }
22212
22352
 
22353
+ class AttributeDefinition extends NodeDefinition {
22354
+ constructor(model, bind, template) {
22355
+ super(bind);
22356
+ this.model = model;
22357
+ this.template = template;
22358
+ const { value } = template;
22359
+ this.root = model.root;
22360
+ this.value = value;
22361
+ this.qualifiedName = template.qualifiedName;
22362
+ this.namespaceDeclarations = new NamespaceDeclarationMap(this);
22363
+ if (this.qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI$1) {
22364
+ this.serializedXML = "";
22365
+ } else {
22366
+ const xmlValue = escapeXMLText(this.value, true);
22367
+ this.serializedXML = serializeAttributeXML(this.qualifiedName, xmlValue);
22368
+ }
22369
+ }
22370
+ serializedXML;
22371
+ value;
22372
+ type = "attribute";
22373
+ namespaceDeclarations;
22374
+ bodyElement = null;
22375
+ root;
22376
+ isTranslated = false;
22377
+ parent = null;
22378
+ children = null;
22379
+ attributes = null;
22380
+ qualifiedName;
22381
+ serializeAttributeXML() {
22382
+ return this.serializedXML;
22383
+ }
22384
+ }
22385
+
22386
+ const isNonNamespaceAttribute = (attribute) => {
22387
+ return attribute.qualifiedName.namespaceURI?.href !== XMLNS_NAMESPACE_URI$1;
22388
+ };
22389
+ class AttributeDefinitionMap extends Map {
22390
+ static from(model, instanceNode) {
22391
+ const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
22392
+ const definitions = nonNamespaceAttributes.map((attribute) => {
22393
+ const bind = model.binds.getOrCreateBindDefinition(attribute.nodeset);
22394
+ return new AttributeDefinition(model, bind, attribute);
22395
+ });
22396
+ return new this(definitions);
22397
+ }
22398
+ constructor(definitions) {
22399
+ super(
22400
+ definitions.map((attribute) => {
22401
+ return [attribute.qualifiedName, attribute];
22402
+ })
22403
+ );
22404
+ }
22405
+ }
22406
+
22213
22407
  class DescendentNodeDefinition extends NodeDefinition {
22214
22408
  constructor(parent, bind, bodyElement) {
22215
22409
  super(bind);
@@ -22225,7 +22419,7 @@ class DescendentNodeDefinition extends NodeDefinition {
22225
22419
  }
22226
22420
 
22227
22421
  class GroupDefinition extends DescendentNodeDefinition {
22228
- constructor(parent, bind, bodyElement, template) {
22422
+ constructor(model, parent, bind, bodyElement, template) {
22229
22423
  if (bodyElement != null && (bodyElement.category !== "structure" || bodyElement.type === "repeat")) {
22230
22424
  throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
22231
22425
  }
@@ -22235,11 +22429,13 @@ class GroupDefinition extends DescendentNodeDefinition {
22235
22429
  this.qualifiedName = template.qualifiedName;
22236
22430
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
22237
22431
  this.children = root.buildSubtree(this, template);
22432
+ this.attributes = AttributeDefinitionMap.from(model, template);
22238
22433
  }
22239
22434
  type = "group";
22240
22435
  namespaceDeclarations;
22241
22436
  qualifiedName;
22242
22437
  children;
22438
+ attributes;
22243
22439
  toJSON() {
22244
22440
  const { parent, bodyElement, bind, root, ...rest } = this;
22245
22441
  return rest;
@@ -22247,21 +22443,24 @@ class GroupDefinition extends DescendentNodeDefinition {
22247
22443
  }
22248
22444
 
22249
22445
  class LeafNodeDefinition extends DescendentNodeDefinition {
22250
- constructor(parent, bind, bodyElement, template) {
22446
+ constructor(model, parent, bind, bodyElement, template) {
22251
22447
  if (bodyElement != null && bodyElement.category !== "control") {
22252
22448
  throw new Error(`Unexpected body element for nodeset ${bind.nodeset}`);
22253
22449
  }
22254
22450
  super(parent, bind, bodyElement);
22451
+ this.model = model;
22255
22452
  this.template = template;
22256
22453
  this.valueType = bind.type.resolved;
22257
22454
  this.qualifiedName = template.qualifiedName;
22258
22455
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
22456
+ this.attributes = AttributeDefinitionMap.from(model, template);
22259
22457
  }
22260
22458
  type = "leaf-node";
22261
22459
  valueType;
22262
22460
  namespaceDeclarations;
22263
22461
  qualifiedName;
22264
22462
  children = null;
22463
+ attributes;
22265
22464
  toJSON() {
22266
22465
  const { bind, bodyElement, parent, root, ...rest } = this;
22267
22466
  return rest;
@@ -22272,13 +22471,13 @@ const isNoteBindDefinition = (bind) => {
22272
22471
  return bind.readonly.isConstantTruthyExpression();
22273
22472
  };
22274
22473
  class NoteNodeDefinition extends LeafNodeDefinition {
22275
- constructor(parent, bind, bodyElement, noteTextDefinition, template) {
22276
- super(parent, bind, bodyElement, template);
22474
+ constructor(model, parent, bind, bodyElement, noteTextDefinition, template) {
22475
+ super(model, parent, bind, bodyElement, template);
22277
22476
  this.bind = bind;
22278
22477
  this.bodyElement = bodyElement;
22279
22478
  this.noteTextDefinition = noteTextDefinition;
22280
22479
  }
22281
- static from(parent, bind, bodyElement, node) {
22480
+ static from(model, parent, bind, bodyElement, node) {
22282
22481
  if (!isNoteBindDefinition(bind) || bodyElement?.type !== "input") {
22283
22482
  return null;
22284
22483
  }
@@ -22287,7 +22486,7 @@ class NoteNodeDefinition extends LeafNodeDefinition {
22287
22486
  if (noteTextDefinition == null) {
22288
22487
  return null;
22289
22488
  }
22290
- return new this(parent, bind, bodyElement, noteTextDefinition, node);
22489
+ return new this(model, parent, bind, bodyElement, noteTextDefinition, node);
22291
22490
  }
22292
22491
  }
22293
22492
 
@@ -25918,7 +26117,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25918
26117
  }, gn = /*@__PURE__*/ g((t => e => e[t]), p.concat("sign")), pn = /*@__PURE__*/ g(((t, e) => t => t[w[e]]), O), On = {
25919
26118
  epochMilliseconds: I,
25920
26119
  epochNanoseconds: v
25921
- }, [wn, In, vn] = createSlotClass(N, j, {
26120
+ }, [wn, In] = createSlotClass(N, j, {
25922
26121
  ...gn,
25923
26122
  blank: y
25924
26123
  }, {
@@ -25992,7 +26191,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
25992
26191
  }, {
25993
26192
  from: (t, e) => En(toPlainDateTimeSlots(t, e)),
25994
26193
  compare: (t, e) => Yt(toPlainDateTimeSlots(t), toPlainDateTimeSlots(e))
25995
- }), [Ln, Vn, Jn] = createSlotClass(qt, Pt(kt, Mt), {
26194
+ }), [Ln, Vn] = createSlotClass(qt, Pt(kt, Mt), {
25996
26195
  ...Pn,
25997
26196
  ...Dn
25998
26197
  }, {
@@ -26010,7 +26209,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
26010
26209
  valueOf: neverValueOf
26011
26210
  }, {
26012
26211
  from: (t, e) => Vn(toPlainMonthDaySlots(t, e))
26013
- }), [kn, qn, Rn] = createSlotClass(Ut, Pt(Qt, Mt), {
26212
+ }), [kn, qn] = createSlotClass(Ut, Pt(Qt, Mt), {
26014
26213
  ...Pn,
26015
26214
  ...hn
26016
26215
  }, {
@@ -26033,7 +26232,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
26033
26232
  }, {
26034
26233
  from: (t, e) => qn(toPlainYearMonthSlots(t, e)),
26035
26234
  compare: (t, e) => te(toPlainYearMonthSlots(t), toPlainYearMonthSlots(e))
26036
- }), [xn, Wn, Gn] = createSlotClass(G, Pt(ue, Mt), {
26235
+ }), [xn, Wn] = createSlotClass(G, Pt(ue, Mt), {
26037
26236
  ...Pn,
26038
26237
  ...Tn
26039
26238
  }, {
@@ -26109,7 +26308,7 @@ const sn = /*@__PURE__*/ new WeakMap, cn = /*@__PURE__*/ sn.get.bind(sn), un = /
26109
26308
  }, {
26110
26309
  from: (t, e) => $n(toZonedDateTimeSlots(t, e)),
26111
26310
  compare: (t, e) => Be(toZonedDateTimeSlots(t), toZonedDateTimeSlots(e))
26112
- }), [Hn, Kn, Qn] = createSlotClass(Re, qe, On, {
26311
+ }), [Hn, Kn] = createSlotClass(Re, qe, On, {
26113
26312
  add: (t, e) => Kn(Ye(0, t, toDurationSlots(e))),
26114
26313
  subtract: (t, e) => Kn(Ye(1, t, toDurationSlots(e))),
26115
26314
  until: (t, e, n) => In(Ee(0, t, toInstantSlots(e), n)),
@@ -26498,15 +26697,15 @@ class RangeNodeBoundsDefinition {
26498
26697
  }
26499
26698
  }
26500
26699
  class RangeNodeDefinition extends LeafNodeDefinition {
26501
- constructor(parent, bind, bodyElement, node) {
26502
- super(parent, bind, bodyElement, node);
26700
+ constructor(model, parent, bind, bodyElement, node) {
26701
+ super(model, parent, bind, bodyElement, node);
26503
26702
  this.bind = bind;
26504
26703
  this.bodyElement = bodyElement;
26505
26704
  this.bounds = RangeNodeBoundsDefinition.from(bodyElement.bounds, bind);
26506
26705
  }
26507
- static from(parent, bind, bodyElement, node) {
26706
+ static from(model, parent, bind, bodyElement, node) {
26508
26707
  assertRangeBindDefinition(bind);
26509
- return new this(parent, bind, bodyElement, node);
26708
+ return new this(model, parent, bind, bodyElement, node);
26510
26709
  }
26511
26710
  bounds;
26512
26711
  }
@@ -26571,8 +26770,8 @@ const parseRepeatTemplateElement = (firstRepeatInstanceNode) => {
26571
26770
  return cloneStaticElementStructure(firstRepeatInstanceNode);
26572
26771
  };
26573
26772
  class RepeatDefinition extends DescendentNodeDefinition {
26574
- static from(parent, bind, bodyElement, instanceNodes) {
26575
- return new this(parent, bind, bodyElement, instanceNodes);
26773
+ static from(model, parent, bind, bodyElement, instanceNodes) {
26774
+ return new this(model, parent, bind, bodyElement, instanceNodes);
26576
26775
  }
26577
26776
  type = "repeat";
26578
26777
  children;
@@ -26580,7 +26779,8 @@ class RepeatDefinition extends DescendentNodeDefinition {
26580
26779
  template;
26581
26780
  namespaceDeclarations;
26582
26781
  qualifiedName;
26583
- constructor(parent, bind, bodyElement, instanceNodes) {
26782
+ attributes;
26783
+ constructor(model, parent, bind, bodyElement, instanceNodes) {
26584
26784
  super(parent, bind, bodyElement);
26585
26785
  const { root } = parent;
26586
26786
  const [instanceNode] = instanceNodes;
@@ -26591,6 +26791,7 @@ class RepeatDefinition extends DescendentNodeDefinition {
26591
26791
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
26592
26792
  this.children = root.buildSubtree(self, template);
26593
26793
  const initialCount = this.omitTemplate(instanceNodes).length;
26794
+ this.attributes = AttributeDefinitionMap.from(model, template);
26594
26795
  this.count = RepeatCountControlExpression.from(bodyElement, initialCount);
26595
26796
  }
26596
26797
  isControlled() {
@@ -26609,48 +26810,6 @@ class RepeatDefinition extends DescendentNodeDefinition {
26609
26810
  }
26610
26811
  }
26611
26812
 
26612
- class RootAttributeDefinition {
26613
- serializedXML;
26614
- parent;
26615
- qualifiedName;
26616
- value;
26617
- constructor(root, source) {
26618
- const { qualifiedName, value } = source;
26619
- this.parent = root;
26620
- this.qualifiedName = qualifiedName;
26621
- this.value = value;
26622
- if (qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI$1) {
26623
- this.serializedXML = "";
26624
- } else {
26625
- const nodeName = qualifiedName.getPrefixedName();
26626
- this.serializedXML = ` ${nodeName}="${escapeXMLText(value, true)}"`;
26627
- }
26628
- }
26629
- serializeAttributeXML() {
26630
- return this.serializedXML;
26631
- }
26632
- }
26633
-
26634
- const isNonNamespaceAttribute = (attribute) => {
26635
- return attribute.qualifiedName.namespaceURI?.href !== XMLNS_NAMESPACE_URI$1;
26636
- };
26637
- class RootAttributeMap extends Map {
26638
- static from(root, instanceNode) {
26639
- const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
26640
- const definitions = nonNamespaceAttributes.map((attribute) => {
26641
- return new RootAttributeDefinition(root, attribute);
26642
- });
26643
- return new this(definitions);
26644
- }
26645
- constructor(definitions) {
26646
- super(
26647
- definitions.map((attribute) => {
26648
- return [attribute.qualifiedName, attribute];
26649
- })
26650
- );
26651
- }
26652
- }
26653
-
26654
26813
  class RootDefinition extends NodeDefinition {
26655
26814
  constructor(form, model, submission, classes) {
26656
26815
  const template = model.instance.root;
@@ -26668,7 +26827,7 @@ class RootDefinition extends NodeDefinition {
26668
26827
  this.classes = classes;
26669
26828
  this.qualifiedName = qualifiedName;
26670
26829
  this.template = template;
26671
- this.attributes = RootAttributeMap.from(this, template);
26830
+ this.attributes = AttributeDefinitionMap.from(model, template);
26672
26831
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
26673
26832
  this.children = this.buildSubtree(this, template);
26674
26833
  }
@@ -26682,6 +26841,18 @@ class RootDefinition extends NodeDefinition {
26682
26841
  attributes;
26683
26842
  children;
26684
26843
  isTranslated = false;
26844
+ mapActions(bodyElement) {
26845
+ const source = bodyElement.reference;
26846
+ if (!source) {
26847
+ return;
26848
+ }
26849
+ for (const child of bodyElement.element.children) {
26850
+ if (child.nodeName === "setvalue") {
26851
+ const action = new ActionDefinition(this.model, child, source);
26852
+ this.model.actions.add(action);
26853
+ }
26854
+ }
26855
+ }
26685
26856
  buildSubtree(parent, node) {
26686
26857
  const { form, model } = this;
26687
26858
  const { body } = form;
@@ -26704,8 +26875,11 @@ class RootDefinition extends NodeDefinition {
26704
26875
  const bind = binds.getOrCreateBindDefinition(nodeset);
26705
26876
  const bodyElement = body.getBodyElement(nodeset);
26706
26877
  const [firstChild, ...restChildren] = children;
26878
+ if (bodyElement) {
26879
+ this.mapActions(bodyElement);
26880
+ }
26707
26881
  if (bodyElement?.type === "repeat") {
26708
- return RepeatDefinition.from(parent, bind, bodyElement, children);
26882
+ return RepeatDefinition.from(model, parent, bind, bodyElement, children);
26709
26883
  }
26710
26884
  if (restChildren.length) {
26711
26885
  throw new Error(`Unexpected: multiple elements for non-repeat nodeset: ${nodeset}`);
@@ -26713,11 +26887,11 @@ class RootDefinition extends NodeDefinition {
26713
26887
  const element = firstChild;
26714
26888
  if (element.isLeafElement()) {
26715
26889
  if (bodyElement?.type === "range") {
26716
- return RangeNodeDefinition.from(parent, bind, bodyElement, element);
26890
+ return RangeNodeDefinition.from(model, parent, bind, bodyElement, element);
26717
26891
  }
26718
- return NoteNodeDefinition.from(parent, bind, bodyElement, element) ?? new LeafNodeDefinition(parent, bind, bodyElement, element);
26892
+ return NoteNodeDefinition.from(model, parent, bind, bodyElement, element) ?? new LeafNodeDefinition(model, parent, bind, bodyElement, element);
26719
26893
  }
26720
- return new GroupDefinition(parent, bind, bodyElement, element);
26894
+ return new GroupDefinition(model, parent, bind, bodyElement, element);
26721
26895
  });
26722
26896
  }
26723
26897
  toJSON() {
@@ -26763,6 +26937,7 @@ class ModelDefinition {
26763
26937
  this.form = form;
26764
26938
  const submission = new SubmissionDefinition(form.xformDOM);
26765
26939
  this.binds = ModelBindMap.fromModel(this);
26940
+ this.actions = ModelActionMap.fromModel(this);
26766
26941
  this.instance = parseStaticDocumentFromDOMSubtree(form.xformDOM.primaryInstanceRoot, {
26767
26942
  nodesetPrefix: "/"
26768
26943
  });
@@ -26770,13 +26945,16 @@ class ModelDefinition {
26770
26945
  this.nodes = nodeDefinitionMap(this.root);
26771
26946
  this.itextTranslations = ItextTranslationsDefinition.from(form.xformDOM);
26772
26947
  this.itextChunks = generateItextChunks(form.xformDOM.itextTranslationElements);
26948
+ this.xformsRevalidateListeners = /* @__PURE__ */ new Map();
26773
26949
  }
26774
26950
  binds;
26951
+ actions;
26775
26952
  root;
26776
26953
  nodes;
26777
26954
  instance;
26778
26955
  itextTranslations;
26779
26956
  itextChunks;
26957
+ xformsRevalidateListeners;
26780
26958
  getNodeDefinition(nodeset) {
26781
26959
  const definition = this.nodes.get(nodeset);
26782
26960
  if (definition == null) {
@@ -26791,14 +26969,20 @@ class ModelDefinition {
26791
26969
  }
26792
26970
  return definition;
26793
26971
  }
26794
- toJSON() {
26795
- const { form, ...rest } = this;
26796
- return rest;
26972
+ registerXformsRevalidateListener(ref, listener) {
26973
+ this.xformsRevalidateListeners.set(ref, listener);
26974
+ }
26975
+ triggerXformsRevalidateListeners() {
26976
+ this.xformsRevalidateListeners.forEach((listener) => listener());
26797
26977
  }
26798
26978
  getTranslationChunks(itextId, activeLanguage) {
26799
26979
  const languageMap = this.itextChunks.get(activeLanguage.language);
26800
26980
  return languageMap?.get(itextId) ?? [];
26801
26981
  }
26982
+ toJSON() {
26983
+ const { form, ...rest } = this;
26984
+ return rest;
26985
+ }
26802
26986
  }
26803
26987
 
26804
26988
  class XFormDefinition {
@@ -28862,6 +29046,7 @@ const chunkedInstancePayload = (validation, submissionMeta, instanceFile, attach
28862
29046
  };
28863
29047
  };
28864
29048
  const prepareInstancePayload = (instanceRoot, options) => {
29049
+ instanceRoot.root.parent.model.triggerXformsRevalidateListeners();
28865
29050
  const validation = validateInstance(instanceRoot);
28866
29051
  const submissionMeta = instanceRoot.definition.submission;
28867
29052
  const instanceFile = new InstanceFile(instanceRoot);
@@ -28887,6 +29072,30 @@ const prepareInstancePayload = (instanceRoot, options) => {
28887
29072
  }
28888
29073
  };
28889
29074
 
29075
+ const createAttributeState = (scope) => {
29076
+ return scope.runTask(() => {
29077
+ const baseState = createSignal([]);
29078
+ const [getAttributes, baseSetAttributes] = baseState;
29079
+ const setAttributes = (valueOrSetterCallback) => {
29080
+ let setterCallback;
29081
+ if (typeof valueOrSetterCallback === "function") {
29082
+ setterCallback = valueOrSetterCallback;
29083
+ } else {
29084
+ setterCallback = (_) => valueOrSetterCallback;
29085
+ }
29086
+ return baseSetAttributes((prev) => {
29087
+ return setterCallback(prev);
29088
+ });
29089
+ };
29090
+ const attributes = [getAttributes, setAttributes];
29091
+ return {
29092
+ attributes,
29093
+ getAttributes,
29094
+ setAttributes
29095
+ };
29096
+ });
29097
+ };
29098
+
28890
29099
  const createChildrenState = (parent) => {
28891
29100
  return parent.scope.runTask(() => {
28892
29101
  const baseState = createSignal([]);
@@ -29199,83 +29408,16 @@ class InstanceNode {
29199
29408
  }
29200
29409
  }
29201
29410
 
29202
- class InstanceAttachmentsState extends Map {
29203
- constructor(sourceAttachments = null) {
29204
- super();
29205
- this.sourceAttachments = sourceAttachments;
29206
- }
29207
- getInitialFileValue(instanceNode) {
29208
- if (instanceNode == null) {
29209
- return null;
29210
- }
29211
- return this.sourceAttachments?.get(instanceNode.value) ?? null;
29212
- }
29213
- }
29214
-
29215
- const createRootInstanceState = (node) => {
29411
+ const createAttributeNodeInstanceState = (node) => {
29412
+ const { qualifiedName } = node.definition;
29216
29413
  return {
29217
29414
  get instanceXML() {
29218
- const { namespaceDeclarations, attributes } = node.definition;
29219
- const serializedChildren = node.currentState.children.map((child) => {
29220
- return child.instanceState.instanceXML;
29221
- });
29222
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren, {
29223
- namespaceDeclarations,
29224
- attributes: Array.from(attributes.values())
29225
- });
29415
+ const xmlValue = escapeXMLText(node.currentState.instanceValue, true);
29416
+ return serializeAttributeXML(qualifiedName, xmlValue);
29226
29417
  }
29227
29418
  };
29228
29419
  };
29229
29420
 
29230
- const violationReference = (node) => {
29231
- const violation = node.getViolation();
29232
- if (violation == null) {
29233
- return null;
29234
- }
29235
- const { nodeId } = node;
29236
- return {
29237
- nodeId,
29238
- get reference() {
29239
- return node.currentState.reference;
29240
- },
29241
- violation
29242
- };
29243
- };
29244
- const collectViolationReferences = (context) => {
29245
- return context.getChildren().flatMap((child) => {
29246
- switch (child.nodeType) {
29247
- case "model-value":
29248
- case "input":
29249
- case "note":
29250
- case "select":
29251
- case "range":
29252
- case "rank":
29253
- case "trigger":
29254
- case "upload": {
29255
- const reference = violationReference(child);
29256
- if (reference == null) {
29257
- return [];
29258
- }
29259
- return [reference];
29260
- }
29261
- default:
29262
- return collectViolationReferences(child);
29263
- }
29264
- });
29265
- };
29266
- const createAggregatedViolations = (context, options) => {
29267
- const { scope } = context;
29268
- return scope.runTask(() => {
29269
- const violations = createMemo(() => {
29270
- return collectViolationReferences(context);
29271
- });
29272
- const spec = { violations };
29273
- return createSharedNodeState(scope, spec, options).currentState;
29274
- });
29275
- };
29276
-
29277
- const XFORMS_XPATH_NODE_RANGE_KIND = "comment";
29278
-
29279
29421
  const expressionEvaluator = (evaluator, type, expression, options) => {
29280
29422
  switch (type) {
29281
29423
  case "boolean":
@@ -29333,6 +29475,347 @@ const createComputedExpression = (context, dependentExpression, options = {}) =>
29333
29475
  });
29334
29476
  };
29335
29477
 
29478
+ const REPEAT_INDEX_REGEX = /([^[]*)(\[[0-9]+\])/g;
29479
+ const isInstanceFirstLoad = (context) => {
29480
+ return context.rootDocument.initializationMode === "create";
29481
+ };
29482
+ const isAddingRepeatChild = (context) => {
29483
+ return context.rootDocument.isAttached();
29484
+ };
29485
+ const isEditInitialLoad = (context) => {
29486
+ return context.rootDocument.initializationMode === "edit";
29487
+ };
29488
+ const getInitialValue = (context) => {
29489
+ const sourceNode = context.instanceNode ?? context.definition.template;
29490
+ return context.decodeInstanceValue(sourceNode.value);
29491
+ };
29492
+ const createRelevantValueState = (context, baseValueState) => {
29493
+ return context.scope.runTask(() => {
29494
+ const [getRelevantValue, setValue] = baseValueState;
29495
+ const getValue = createMemo(() => {
29496
+ if (context.isRelevant()) {
29497
+ return getRelevantValue();
29498
+ }
29499
+ return "";
29500
+ });
29501
+ return [getValue, setValue];
29502
+ });
29503
+ };
29504
+ const guardDownstreamReadonlyWrites = (context, baseState) => {
29505
+ const { readonly } = context.definition.bind;
29506
+ if (readonly.isDefaultExpression) {
29507
+ return baseState;
29508
+ }
29509
+ const [getValue, baseSetValue] = baseState;
29510
+ const setValue = (value) => {
29511
+ if (context.isReadonly()) {
29512
+ const reference = untrack(() => context.contextReference());
29513
+ throw new Error(`Cannot write to readonly field: ${reference}`);
29514
+ }
29515
+ return baseSetValue(value);
29516
+ };
29517
+ return [getValue, setValue];
29518
+ };
29519
+ const isLoading = (context) => {
29520
+ return isInstanceFirstLoad(context) || isEditInitialLoad(context);
29521
+ };
29522
+ const setValueIfPreloadDefined = (context, setValue, preload) => {
29523
+ const value = preload.getValue(context);
29524
+ if (value) {
29525
+ setValue(value);
29526
+ }
29527
+ };
29528
+ const postloadValue = (context, setValue, preload) => {
29529
+ const ref = context.contextReference();
29530
+ context.definition.model.registerXformsRevalidateListener(ref, () => {
29531
+ setValueIfPreloadDefined(context, setValue, preload);
29532
+ });
29533
+ };
29534
+ const preloadValue = (context, setValue) => {
29535
+ const { preload } = context.definition.bind;
29536
+ if (!preload) {
29537
+ return;
29538
+ }
29539
+ if (preload.event === XFORM_EVENT.xformsRevalidate) {
29540
+ postloadValue(context, setValue, preload);
29541
+ return;
29542
+ }
29543
+ if (isLoading(context)) {
29544
+ setValueIfPreloadDefined(context, setValue, preload);
29545
+ }
29546
+ };
29547
+ const referencesCurrentNode = (context, ref) => {
29548
+ const nodes = context.evaluator.evaluateNodes(ref, {
29549
+ contextNode: context.contextNode
29550
+ });
29551
+ if (nodes.length > 1) {
29552
+ throw new Error(
29553
+ "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."
29554
+ );
29555
+ }
29556
+ return nodes.includes(context.contextNode);
29557
+ };
29558
+ const bindToRepeatInstance = (context, action) => {
29559
+ let source = action.source;
29560
+ let ref = action.ref;
29561
+ if (source) {
29562
+ const contextRef = context.contextReference();
29563
+ for (const part of contextRef.matchAll(REPEAT_INDEX_REGEX)) {
29564
+ const unbound = part[1] + "/";
29565
+ if (source.includes(unbound)) {
29566
+ const bound = part[0] + "/";
29567
+ source = source.replace(unbound, bound);
29568
+ ref = ref.replace(unbound, bound);
29569
+ }
29570
+ }
29571
+ }
29572
+ return { source, ref };
29573
+ };
29574
+ const createCalculation = (context, setRelevantValue, computation) => {
29575
+ const calculate = createComputedExpression(context, computation);
29576
+ createComputed(() => {
29577
+ if (context.isAttached() && context.isRelevant()) {
29578
+ const calculated = calculate();
29579
+ const value = context.decodeInstanceValue(calculated);
29580
+ setRelevantValue(value);
29581
+ }
29582
+ });
29583
+ };
29584
+ const createValueChangedCalculation = (context, setRelevantValue, action) => {
29585
+ const { source, ref } = bindToRepeatInstance(context, action);
29586
+ if (!source) {
29587
+ return;
29588
+ }
29589
+ let previous = "";
29590
+ const sourceElementExpression = new ActionComputationExpression("string", source);
29591
+ const calculateValueSource = createComputedExpression(context, sourceElementExpression);
29592
+ createComputed(() => {
29593
+ if (context.isAttached() && context.isRelevant()) {
29594
+ const valueSource = calculateValueSource();
29595
+ if (previous !== valueSource) {
29596
+ if (referencesCurrentNode(context, ref)) {
29597
+ const calc = context.evaluator.evaluateString(action.computation.expression, context);
29598
+ const value = context.decodeInstanceValue(calc);
29599
+ setRelevantValue(value);
29600
+ }
29601
+ }
29602
+ previous = valueSource;
29603
+ }
29604
+ });
29605
+ };
29606
+ const registerAction = (context, setValue, action) => {
29607
+ if (action.events.includes(XFORM_EVENT.odkInstanceFirstLoad)) {
29608
+ if (isInstanceFirstLoad(context)) {
29609
+ createCalculation(context, setValue, action.computation);
29610
+ }
29611
+ }
29612
+ if (action.events.includes(XFORM_EVENT.odkInstanceLoad)) {
29613
+ if (!isAddingRepeatChild(context)) {
29614
+ createCalculation(context, setValue, action.computation);
29615
+ }
29616
+ }
29617
+ if (action.events.includes(XFORM_EVENT.odkNewRepeat)) {
29618
+ if (isAddingRepeatChild(context)) {
29619
+ createCalculation(context, setValue, action.computation);
29620
+ }
29621
+ }
29622
+ if (action.events.includes(XFORM_EVENT.xformsValueChanged)) {
29623
+ createValueChangedCalculation(context, setValue, action);
29624
+ }
29625
+ };
29626
+ const createInstanceValueState = (context) => {
29627
+ return context.scope.runTask(() => {
29628
+ const initialValue = getInitialValue(context);
29629
+ const baseValueState = createSignal(initialValue);
29630
+ const relevantValueState = createRelevantValueState(context, baseValueState);
29631
+ const [, setValue] = relevantValueState;
29632
+ preloadValue(context, setValue);
29633
+ const { calculate } = context.definition.bind;
29634
+ if (calculate != null) {
29635
+ createCalculation(context, setValue, calculate);
29636
+ }
29637
+ const action = context.definition.model.actions.get(context.contextReference());
29638
+ if (action) {
29639
+ registerAction(context, setValue, action);
29640
+ }
29641
+ return guardDownstreamReadonlyWrites(context, relevantValueState);
29642
+ });
29643
+ };
29644
+
29645
+ class Attribute {
29646
+ constructor(owner, definition, instanceNode) {
29647
+ this.owner = owner;
29648
+ this.definition = definition;
29649
+ this.instanceNode = instanceNode;
29650
+ const codec = getSharedValueCodec("string");
29651
+ this.contextNode = owner;
29652
+ this.scope = owner.scope;
29653
+ this.rootDocument = owner.rootDocument;
29654
+ this.root = owner.root;
29655
+ this.instanceConfig = owner.instanceConfig;
29656
+ this.getActiveLanguage = owner.getActiveLanguage;
29657
+ this.validationState = { violations: [] };
29658
+ this.valueType = "string";
29659
+ this.evaluator = owner.evaluator;
29660
+ this.decodeInstanceValue = codec.decodeInstanceValue;
29661
+ const instanceValueState = createInstanceValueState(this);
29662
+ const valueState = codec.createRuntimeValueState(instanceValueState);
29663
+ const [getInstanceValue] = instanceValueState;
29664
+ const [, setValueState] = valueState;
29665
+ this.getInstanceValue = getInstanceValue;
29666
+ this.setValueState = setValueState;
29667
+ this.valueState = valueState;
29668
+ const state = createSharedNodeState(
29669
+ owner.scope,
29670
+ {
29671
+ value: this.valueState,
29672
+ instanceValue: this.getInstanceValue,
29673
+ relevant: this.owner.isRelevant
29674
+ },
29675
+ this.instanceConfig
29676
+ );
29677
+ this.state = state;
29678
+ this.engineState = state.engineState;
29679
+ this.currentState = state.currentState;
29680
+ this.instanceState = createAttributeNodeInstanceState(this);
29681
+ }
29682
+ [XPathNodeKindKey] = "attribute";
29683
+ state;
29684
+ engineState;
29685
+ validationState;
29686
+ nodeType = "attribute";
29687
+ currentState;
29688
+ instanceState;
29689
+ appearances = null;
29690
+ nodeOptions = null;
29691
+ valueType;
29692
+ decodeInstanceValue;
29693
+ getInstanceValue;
29694
+ valueState;
29695
+ setValueState;
29696
+ evaluator;
29697
+ getActiveLanguage;
29698
+ contextNode;
29699
+ scope;
29700
+ rootDocument;
29701
+ instanceConfig;
29702
+ root;
29703
+ isRelevant = () => {
29704
+ return this.owner.isRelevant();
29705
+ };
29706
+ isAttached = () => {
29707
+ return this.owner.isAttached();
29708
+ };
29709
+ isReadonly = () => {
29710
+ return true;
29711
+ };
29712
+ hasReadonlyAncestor = () => {
29713
+ const { owner } = this;
29714
+ return owner.hasReadonlyAncestor() || owner.isReadonly();
29715
+ };
29716
+ hasNonRelevantAncestor = () => {
29717
+ const { owner } = this;
29718
+ return owner.hasNonRelevantAncestor() || !owner.isRelevant();
29719
+ };
29720
+ contextReference = () => {
29721
+ return this.owner.contextReference() + "/@" + this.definition.qualifiedName.getPrefixedName();
29722
+ };
29723
+ setValue(value) {
29724
+ this.setValueState(value);
29725
+ return this.root;
29726
+ }
29727
+ getChildren() {
29728
+ return [];
29729
+ }
29730
+ getXPathChildNodes() {
29731
+ return [];
29732
+ }
29733
+ getXPathValue() {
29734
+ return "";
29735
+ }
29736
+ }
29737
+
29738
+ function buildAttributes(owner) {
29739
+ return Array.from(owner.definition.attributes.values()).map((attributeDefinition) => {
29740
+ return new Attribute(owner, attributeDefinition, attributeDefinition.template);
29741
+ });
29742
+ }
29743
+
29744
+ class InstanceAttachmentsState extends Map {
29745
+ constructor(sourceAttachments = null) {
29746
+ super();
29747
+ this.sourceAttachments = sourceAttachments;
29748
+ }
29749
+ getInitialFileValue(instanceNode) {
29750
+ if (instanceNode == null) {
29751
+ return null;
29752
+ }
29753
+ return this.sourceAttachments?.get(instanceNode.value) ?? null;
29754
+ }
29755
+ }
29756
+
29757
+ const createRootInstanceState = (node) => {
29758
+ return {
29759
+ get instanceXML() {
29760
+ return serializeParentElementXML(
29761
+ node.definition.qualifiedName,
29762
+ node.currentState.children,
29763
+ node.currentState.attributes,
29764
+ node.definition.namespaceDeclarations
29765
+ );
29766
+ }
29767
+ };
29768
+ };
29769
+
29770
+ const violationReference = (node) => {
29771
+ const violation = node.getViolation();
29772
+ if (violation == null) {
29773
+ return null;
29774
+ }
29775
+ const { nodeId } = node;
29776
+ return {
29777
+ nodeId,
29778
+ get reference() {
29779
+ return node.currentState.reference;
29780
+ },
29781
+ violation
29782
+ };
29783
+ };
29784
+ const collectViolationReferences = (context) => {
29785
+ return context.getChildren().flatMap((child) => {
29786
+ switch (child.nodeType) {
29787
+ case "model-value":
29788
+ case "input":
29789
+ case "note":
29790
+ case "select":
29791
+ case "range":
29792
+ case "rank":
29793
+ case "trigger":
29794
+ case "upload": {
29795
+ const reference = violationReference(child);
29796
+ if (reference == null) {
29797
+ return [];
29798
+ }
29799
+ return [reference];
29800
+ }
29801
+ default:
29802
+ return collectViolationReferences(child);
29803
+ }
29804
+ });
29805
+ };
29806
+ const createAggregatedViolations = (context, options) => {
29807
+ const { scope } = context;
29808
+ return scope.runTask(() => {
29809
+ const violations = createMemo(() => {
29810
+ return collectViolationReferences(context);
29811
+ });
29812
+ const spec = { violations };
29813
+ return createSharedNodeState(scope, spec, options).currentState;
29814
+ });
29815
+ };
29816
+
29817
+ const XFORMS_XPATH_NODE_RANGE_KIND = "comment";
29818
+
29336
29819
  class DescendantNode extends InstanceNode {
29337
29820
  constructor(parent, instanceNode, definition, options) {
29338
29821
  super(parent.instanceConfig, parent, instanceNode, definition, options);
@@ -29469,10 +29952,11 @@ const createParentNodeInstanceState = (node) => {
29469
29952
  if (!node.currentState.relevant) {
29470
29953
  return "";
29471
29954
  }
29472
- const serializedChildren = node.currentState.children.map((child) => {
29473
- return child.instanceState.instanceXML;
29474
- });
29475
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren);
29955
+ return serializeParentElementXML(
29956
+ node.definition.qualifiedName,
29957
+ node.currentState.children,
29958
+ node.currentState.attributes
29959
+ );
29476
29960
  }
29477
29961
  };
29478
29962
  };
@@ -39761,6 +40245,7 @@ class Group extends DescendantNode {
39761
40245
  super(parent, instanceNode, definition);
39762
40246
  this.appearances = definition.bodyElement?.appearances ?? null;
39763
40247
  const childrenState = createChildrenState(this);
40248
+ const attributeState = createAttributeState(this.scope);
39764
40249
  this.childrenState = childrenState;
39765
40250
  const state = createSharedNodeState(
39766
40251
  this.scope,
@@ -39772,6 +40257,7 @@ class Group extends DescendantNode {
39772
40257
  label: createNodeLabel(this, definition),
39773
40258
  hint: null,
39774
40259
  children: childrenState.childIds,
40260
+ attributes: attributeState.getAttributes,
39775
40261
  valueOptions: null,
39776
40262
  value: null
39777
40263
  },
@@ -39785,6 +40271,7 @@ class Group extends DescendantNode {
39785
40271
  childrenState
39786
40272
  );
39787
40273
  childrenState.setChildren(buildChildren(this));
40274
+ attributeState.setAttributes(buildAttributes(this));
39788
40275
  this.validationState = createAggregatedViolations(this, this.instanceConfig);
39789
40276
  this.instanceState = createParentNodeInstanceState(this);
39790
40277
  }
@@ -39809,92 +40296,12 @@ const createValueNodeInstanceState = (node) => {
39809
40296
  return "";
39810
40297
  }
39811
40298
  const xmlValue = escapeXMLText(node.currentState.instanceValue);
39812
- return serializeLeafElementXML(qualifiedName, xmlValue);
40299
+ const attributes = node.currentState.attributes;
40300
+ return serializeLeafElementXML(qualifiedName, xmlValue, attributes);
39813
40301
  }
39814
40302
  };
39815
40303
  };
39816
40304
 
39817
- const isInstanceFirstLoad = (context) => {
39818
- return context.rootDocument.initializationMode === "create";
39819
- };
39820
- const isEditInitialLoad = (context) => {
39821
- return context.rootDocument.initializationMode === "edit";
39822
- };
39823
- const getInitialValue = (context) => {
39824
- const sourceNode = context.instanceNode ?? context.definition.template;
39825
- return context.decodeInstanceValue(sourceNode.value);
39826
- };
39827
- const createRelevantValueState = (context, baseValueState) => {
39828
- return context.scope.runTask(() => {
39829
- const [getRelevantValue, setValue] = baseValueState;
39830
- const getValue = createMemo(() => {
39831
- if (context.isRelevant()) {
39832
- return getRelevantValue();
39833
- }
39834
- return "";
39835
- });
39836
- return [getValue, setValue];
39837
- });
39838
- };
39839
- const guardDownstreamReadonlyWrites = (context, baseState) => {
39840
- const { readonly } = context.definition.bind;
39841
- if (readonly.isDefaultExpression) {
39842
- return baseState;
39843
- }
39844
- const [getValue, baseSetValue] = baseState;
39845
- const setValue = (value) => {
39846
- if (context.isReadonly()) {
39847
- const reference = untrack(() => context.contextReference());
39848
- throw new Error(`Cannot write to readonly field: ${reference}`);
39849
- }
39850
- return baseSetValue(value);
39851
- };
39852
- return [getValue, setValue];
39853
- };
39854
- const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
39855
- const shouldPreloadUID = (context) => {
39856
- return isInstanceFirstLoad(context) || isEditInitialLoad(context);
39857
- };
39858
- const setPreloadUIDValue = (context, valueState) => {
39859
- const { preload } = context.definition.bind;
39860
- if (preload?.type !== "uid" || !shouldPreloadUID(context)) {
39861
- return;
39862
- }
39863
- const preloadUIDValue = context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION, {
39864
- contextNode: context.contextNode
39865
- });
39866
- const [, setValue] = valueState;
39867
- setValue(preloadUIDValue);
39868
- };
39869
- const createCalculation = (context, setRelevantValue, calculateDefinition) => {
39870
- context.scope.runTask(() => {
39871
- const calculate = createComputedExpression(context, calculateDefinition, {
39872
- defaultValue: ""
39873
- });
39874
- createComputed(() => {
39875
- if (context.isAttached() && context.isRelevant()) {
39876
- const calculated = calculate();
39877
- const value = context.decodeInstanceValue(calculated);
39878
- setRelevantValue(value);
39879
- }
39880
- });
39881
- });
39882
- };
39883
- const createInstanceValueState = (context) => {
39884
- return context.scope.runTask(() => {
39885
- const initialValue = getInitialValue(context);
39886
- const baseValueState = createSignal(initialValue);
39887
- const relevantValueState = createRelevantValueState(context, baseValueState);
39888
- setPreloadUIDValue(context, relevantValueState);
39889
- const { calculate } = context.definition.bind;
39890
- if (calculate != null) {
39891
- const [, setValue] = relevantValueState;
39892
- createCalculation(context, setValue, calculate);
39893
- }
39894
- return guardDownstreamReadonlyWrites(context, relevantValueState);
39895
- });
39896
- };
39897
-
39898
40305
  const engineViolationMessage = (context, role) => {
39899
40306
  const messageText = VALIDATION_TEXT[role];
39900
40307
  const chunk = new TextChunk(context, "literal", messageText);
@@ -40084,6 +40491,7 @@ class InputControl extends ValueNode {
40084
40491
  super(parent, instanceNode, definition, codec);
40085
40492
  this.appearances = definition.bodyElement.appearances;
40086
40493
  this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
40494
+ const attributeState = createAttributeState(this.scope);
40087
40495
  const state = createSharedNodeState(
40088
40496
  this.scope,
40089
40497
  {
@@ -40094,12 +40502,14 @@ class InputControl extends ValueNode {
40094
40502
  label: createNodeLabel(this, definition),
40095
40503
  hint: createFieldHint(this, definition),
40096
40504
  children: null,
40505
+ attributes: attributeState.getAttributes,
40097
40506
  valueOptions: null,
40098
40507
  value: this.valueState,
40099
40508
  instanceValue: this.getInstanceValue
40100
40509
  },
40101
40510
  this.instanceConfig
40102
40511
  );
40512
+ attributeState.setAttributes(buildAttributes(this));
40103
40513
  this.state = state;
40104
40514
  this.engineState = state.engineState;
40105
40515
  this.currentState = state.currentState;
@@ -40127,6 +40537,7 @@ class ModelValue extends ValueNode {
40127
40537
  constructor(parent, instanceNode, definition) {
40128
40538
  const codec = getSharedValueCodec(definition.valueType);
40129
40539
  super(parent, instanceNode, definition, codec);
40540
+ const attributeState = createAttributeState(this.scope);
40130
40541
  const state = createSharedNodeState(
40131
40542
  this.scope,
40132
40543
  {
@@ -40137,12 +40548,14 @@ class ModelValue extends ValueNode {
40137
40548
  label: null,
40138
40549
  hint: null,
40139
40550
  children: null,
40551
+ attributes: attributeState.getAttributes,
40140
40552
  valueOptions: null,
40141
40553
  value: this.valueState,
40142
40554
  instanceValue: this.getInstanceValue
40143
40555
  },
40144
40556
  this.instanceConfig
40145
40557
  );
40558
+ attributeState.setAttributes(buildAttributes(this));
40146
40559
  this.state = state;
40147
40560
  this.engineState = state.engineState;
40148
40561
  this.currentState = state.currentState;
@@ -40234,6 +40647,7 @@ class Note extends ValueNode {
40234
40647
  this.appearances = definition.bodyElement.appearances;
40235
40648
  const isReadonly = createNoteReadonlyThunk(this, definition);
40236
40649
  const noteTextComputation = createNoteText(this, definition.noteTextDefinition);
40650
+ const attributeState = createAttributeState(this.scope);
40237
40651
  let noteText;
40238
40652
  let label;
40239
40653
  let hint;
@@ -40264,12 +40678,14 @@ class Note extends ValueNode {
40264
40678
  hint,
40265
40679
  noteText,
40266
40680
  children: null,
40681
+ attributes: attributeState.getAttributes,
40267
40682
  valueOptions: null,
40268
40683
  value: this.valueState,
40269
40684
  instanceValue: this.getInstanceValue
40270
40685
  },
40271
40686
  this.instanceConfig
40272
40687
  );
40688
+ attributeState.setAttributes(buildAttributes(this));
40273
40689
  this.state = state;
40274
40690
  this.engineState = state.engineState;
40275
40691
  this.currentState = state.currentState;
@@ -40333,6 +40749,7 @@ class RangeControl extends ValueNode {
40333
40749
  const codec = new RangeCodec(baseCodec, definition);
40334
40750
  super(parent, instanceNode, definition, codec);
40335
40751
  this.appearances = definition.bodyElement.appearances;
40752
+ const attributeState = createAttributeState(this.scope);
40336
40753
  const state = createSharedNodeState(
40337
40754
  this.scope,
40338
40755
  {
@@ -40343,12 +40760,14 @@ class RangeControl extends ValueNode {
40343
40760
  label: createNodeLabel(this, definition),
40344
40761
  hint: createFieldHint(this, definition),
40345
40762
  children: null,
40763
+ attributes: attributeState.getAttributes,
40346
40764
  valueOptions: null,
40347
40765
  value: this.valueState,
40348
40766
  instanceValue: this.getInstanceValue
40349
40767
  },
40350
40768
  this.instanceConfig
40351
40769
  );
40770
+ attributeState.setAttributes(buildAttributes(this));
40352
40771
  this.state = state;
40353
40772
  this.engineState = state.engineState;
40354
40773
  this.currentState = state.currentState;
@@ -40566,6 +40985,7 @@ class RankControl extends ValueNode {
40566
40985
  this.mapOptionsByValue = mapOptionsByValue;
40567
40986
  const baseValueState = this.valueState;
40568
40987
  const [baseGetValue, setValue] = baseValueState;
40988
+ const attributeState = createAttributeState(this.scope);
40569
40989
  const getValue = this.scope.runTask(() => {
40570
40990
  return createMemo(() => {
40571
40991
  const options = valueOptions();
@@ -40600,12 +41020,14 @@ class RankControl extends ValueNode {
40600
41020
  label: createNodeLabel(this, definition),
40601
41021
  hint: createFieldHint(this, definition),
40602
41022
  children: null,
41023
+ attributes: attributeState.getAttributes,
40603
41024
  valueOptions,
40604
41025
  value: valueState,
40605
41026
  instanceValue: this.getInstanceValue
40606
41027
  },
40607
41028
  this.instanceConfig
40608
41029
  );
41030
+ attributeState.setAttributes(buildAttributes(this));
40609
41031
  this.state = state;
40610
41032
  this.engineState = state.engineState;
40611
41033
  this.currentState = state.currentState;
@@ -40661,26 +41083,17 @@ const createNodeRangeInstanceState = (node) => {
40661
41083
  };
40662
41084
  };
40663
41085
 
40664
- class TemplatedNodeAttributeSerializationError extends Error {
40665
- constructor() {
40666
- super("Template attribute omission not implemented");
40667
- }
40668
- }
40669
-
40670
41086
  const createTemplatedNodeInstanceState = (node) => {
40671
41087
  return {
40672
41088
  get instanceXML() {
40673
41089
  if (!node.currentState.relevant) {
40674
41090
  return "";
40675
41091
  }
40676
- const serializedChildren = node.currentState.children.map((child) => {
40677
- return child.instanceState.instanceXML;
40678
- });
40679
- const { attributes } = node.currentState;
40680
- if (attributes != null) {
40681
- throw new TemplatedNodeAttributeSerializationError();
40682
- }
40683
- return serializeParentElementXML(node.definition.qualifiedName, serializedChildren);
41092
+ return serializeParentElementXML(
41093
+ node.definition.qualifiedName,
41094
+ node.currentState.children,
41095
+ node.currentState.attributes
41096
+ );
40684
41097
  }
40685
41098
  };
40686
41099
  };
@@ -40701,6 +41114,7 @@ class RepeatInstance extends DescendantNode {
40701
41114
  this.parent = parent;
40702
41115
  this.appearances = definition.bodyElement.appearances;
40703
41116
  const childrenState = createChildrenState(this);
41117
+ const attributeState = createAttributeState(this.scope);
40704
41118
  this.childrenState = childrenState;
40705
41119
  this.currentIndex = currentIndex;
40706
41120
  const state = createSharedNodeState(
@@ -40713,7 +41127,7 @@ class RepeatInstance extends DescendantNode {
40713
41127
  // TODO: only-child <group><label>
40714
41128
  label: createNodeLabel(this, definition),
40715
41129
  hint: null,
40716
- attributes: null,
41130
+ attributes: attributeState.getAttributes,
40717
41131
  children: childrenState.childIds,
40718
41132
  valueOptions: null,
40719
41133
  value: null
@@ -40774,6 +41188,7 @@ class RepeatInstance extends DescendantNode {
40774
41188
 
40775
41189
  class BaseRepeatRange extends DescendantNode {
40776
41190
  childrenState;
41191
+ attributeState;
40777
41192
  /**
40778
41193
  * A repeat range doesn't have a corresponding primary instance element of its
40779
41194
  * own. It is represented in the following ways:
@@ -40813,7 +41228,9 @@ class BaseRepeatRange extends DescendantNode {
40813
41228
  super(parent, definition.template, definition);
40814
41229
  const repeatRange = this;
40815
41230
  const childrenState = createChildrenState(repeatRange);
41231
+ const attributeState = createAttributeState(this.scope);
40816
41232
  this.childrenState = childrenState;
41233
+ this.attributeState = attributeState;
40817
41234
  const state = createSharedNodeState(
40818
41235
  this.scope,
40819
41236
  {
@@ -40824,6 +41241,7 @@ class BaseRepeatRange extends DescendantNode {
40824
41241
  label: createNodeLabel(this, definition),
40825
41242
  hint: null,
40826
41243
  children: childrenState.childIds,
41244
+ attributes: attributeState.getAttributes,
40827
41245
  valueOptions: null,
40828
41246
  value: null
40829
41247
  },
@@ -40891,6 +41309,9 @@ class BaseRepeatRange extends DescendantNode {
40891
41309
  getChildren() {
40892
41310
  return this.childrenState.getChildren();
40893
41311
  }
41312
+ getAttributes() {
41313
+ return this.attributeState.getAttributes();
41314
+ }
40894
41315
  }
40895
41316
 
40896
41317
  class RepeatRangeControlled extends BaseRepeatRange {
@@ -41098,6 +41519,7 @@ class SelectControl extends ValueNode {
41098
41519
  super(parent, instanceNode, definition, codec);
41099
41520
  this.appearances = definition.bodyElement.appearances;
41100
41521
  this.selectType = definition.bodyElement.type;
41522
+ const attributeState = createAttributeState(this.scope);
41101
41523
  const valueOptions = createItemCollection(this);
41102
41524
  const isSelectWithImages = this.scope.runTask(() => {
41103
41525
  return createMemo(() => valueOptions().some((item) => !!item.label.imageSource));
@@ -41134,6 +41556,7 @@ class SelectControl extends ValueNode {
41134
41556
  label: createNodeLabel(this, definition),
41135
41557
  hint: createFieldHint(this, definition),
41136
41558
  children: null,
41559
+ attributes: attributeState.getAttributes,
41137
41560
  valueOptions,
41138
41561
  value: valueState,
41139
41562
  instanceValue: this.getInstanceValue,
@@ -41141,6 +41564,7 @@ class SelectControl extends ValueNode {
41141
41564
  },
41142
41565
  this.instanceConfig
41143
41566
  );
41567
+ attributeState.setAttributes(buildAttributes(this));
41144
41568
  this.state = state;
41145
41569
  this.engineState = state.engineState;
41146
41570
  this.currentState = state.currentState;
@@ -41259,6 +41683,7 @@ class TriggerControl extends ValueNode {
41259
41683
  constructor(parent, instanceNode, definition) {
41260
41684
  super(parent, instanceNode, definition, codec);
41261
41685
  this.appearances = definition.bodyElement.appearances;
41686
+ const attributeState = createAttributeState(this.scope);
41262
41687
  const state = createSharedNodeState(
41263
41688
  this.scope,
41264
41689
  {
@@ -41269,12 +41694,14 @@ class TriggerControl extends ValueNode {
41269
41694
  label: createNodeLabel(this, definition),
41270
41695
  hint: createFieldHint(this, definition),
41271
41696
  children: null,
41697
+ attributes: attributeState.getAttributes,
41272
41698
  valueOptions: null,
41273
41699
  value: this.valueState,
41274
41700
  instanceValue: this.getInstanceValue
41275
41701
  },
41276
41702
  this.instanceConfig
41277
41703
  );
41704
+ attributeState.setAttributes(buildAttributes(this));
41278
41705
  this.state = state;
41279
41706
  this.engineState = state.engineState;
41280
41707
  this.currentState = state.currentState;
@@ -41467,6 +41894,7 @@ class UploadControl extends DescendantNode {
41467
41894
  this.nodeOptions = definition.bodyElement.options;
41468
41895
  const instanceAttachment = createInstanceAttachment(this);
41469
41896
  this.instanceAttachment = instanceAttachment;
41897
+ const attributeState = createAttributeState(this.scope);
41470
41898
  this.decodeInstanceValue = instanceAttachment.decodeInstanceValue;
41471
41899
  this.getXPathValue = instanceAttachment.getInstanceValue;
41472
41900
  const state = createSharedNodeState(
@@ -41481,6 +41909,7 @@ class UploadControl extends DescendantNode {
41481
41909
  children: null,
41482
41910
  valueOptions: null,
41483
41911
  value: instanceAttachment.valueState,
41912
+ attributes: attributeState.getAttributes,
41484
41913
  instanceValue: instanceAttachment.getInstanceValue
41485
41914
  },
41486
41915
  this.instanceConfig
@@ -41616,7 +42045,7 @@ const buildMetaValueElement = (group, localName, value) => {
41616
42045
  const buildDeprecatedIDDefinition = (group, instanceNode) => {
41617
42046
  const nodeset = instanceNode.nodeset;
41618
42047
  const bind = group.model.binds.getOrCreateBindDefinition(nodeset);
41619
- return new LeafNodeDefinition(group.parent.definition, bind, null, instanceNode);
42048
+ return new LeafNodeDefinition(group.model, group.parent.definition, bind, null, instanceNode);
41620
42049
  };
41621
42050
  const buildDeprecatedID = (group, value) => {
41622
42051
  const instanceNode = buildMetaValueElement(group, DEPRECATED_ID_LOCAL_NAME, value);
@@ -41843,6 +42272,7 @@ class Root extends DescendantNode {
41843
42272
  });
41844
42273
  this.classes = parent.classes;
41845
42274
  const childrenState = createChildrenState(this);
42275
+ const attributeState = createAttributeState(this.scope);
41846
42276
  this.childrenState = childrenState;
41847
42277
  this.languages = parent.languages;
41848
42278
  const state = createSharedNodeState(
@@ -41857,7 +42287,8 @@ class Root extends DescendantNode {
41857
42287
  required: () => false,
41858
42288
  valueOptions: null,
41859
42289
  value: null,
41860
- children: childrenState.childIds
42290
+ children: childrenState.childIds,
42291
+ attributes: attributeState.getAttributes
41861
42292
  },
41862
42293
  this.instanceConfig
41863
42294
  );
@@ -41869,6 +42300,7 @@ class Root extends DescendantNode {
41869
42300
  childrenState
41870
42301
  );
41871
42302
  childrenState.setChildren(buildChildren(this));
42303
+ attributeState.setAttributes(buildAttributes(this));
41872
42304
  this.validationState = createAggregatedViolations(this, this.instanceConfig);
41873
42305
  this.instanceState = createRootInstanceState(this);
41874
42306
  }
@@ -41949,6 +42381,7 @@ class PrimaryInstance extends InstanceNode {
41949
42381
  this.evaluator = evaluator;
41950
42382
  this.classes = definition.classes;
41951
42383
  const childrenState = createChildrenState(this);
42384
+ const attributeState = createAttributeState(this.scope);
41952
42385
  this.getChildren = childrenState.getChildren;
41953
42386
  const stateSpec = {
41954
42387
  activeLanguage: getActiveLanguage,
@@ -41960,7 +42393,8 @@ class PrimaryInstance extends InstanceNode {
41960
42393
  required: false,
41961
42394
  valueOptions: null,
41962
42395
  value: null,
41963
- children: childrenState.childIds
42396
+ children: childrenState.childIds,
42397
+ attributes: attributeState.getAttributes
41964
42398
  };
41965
42399
  const state = createSharedNodeState(scope, stateSpec, config);
41966
42400
  this.state = state;
@@ -41975,6 +42409,7 @@ class PrimaryInstance extends InstanceNode {
41975
42409
  };
41976
42410
  this.instanceState = createPrimaryInstanceState(this);
41977
42411
  childrenState.setChildren([root]);
42412
+ attributeState.setAttributes(buildAttributes(this));
41978
42413
  setIsAttached(true);
41979
42414
  }
41980
42415
  // PrimaryInstanceDocument
@@ -42025,7 +42460,8 @@ class FormInstance {
42025
42460
  const { mode, initialState, instanceConfig } = options;
42026
42461
  const config = {
42027
42462
  clientStateFactory: instanceConfig.stateFactory ?? identity,
42028
- computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null)
42463
+ computeAttachmentName: instanceConfig.instanceAttachments?.fileNameFactory ?? (() => null),
42464
+ preloadProperties: instanceConfig.preloadProperties ?? {}
42029
42465
  };
42030
42466
  const primaryInstanceOptions = {
42031
42467
  ...options.instanceOptions,