@aehrc/smart-forms-renderer 1.2.11 → 1.2.13

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 (302) hide show
  1. package/lib/components/FormComponents/AttachmentItem/AttachmentItem.js +2 -2
  2. package/lib/components/FormComponents/AttachmentItem/AttachmentItem.js.map +1 -1
  3. package/lib/components/FormComponents/BooleanItem/BooleanItem.js +2 -2
  4. package/lib/components/FormComponents/BooleanItem/BooleanItem.js.map +1 -1
  5. package/lib/components/FormComponents/ChoiceItems/CheckboxOptionList.js +2 -1
  6. package/lib/components/FormComponents/ChoiceItems/CheckboxOptionList.js.map +1 -1
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.d.ts +1 -0
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js +3 -2
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js.map +1 -1
  10. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.js +5 -6
  11. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.js.map +1 -1
  12. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js +2 -2
  13. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js.map +1 -1
  14. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js +2 -2
  15. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js.map +1 -1
  16. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +2 -2
  17. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
  18. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +2 -2
  19. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
  20. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioSingle.d.ts +2 -1
  21. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +61 -3
  22. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
  23. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +2 -2
  24. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
  25. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js +5 -2
  26. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js.map +1 -1
  27. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.js +2 -2
  28. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.js.map +1 -1
  29. package/lib/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.js +2 -2
  30. package/lib/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.js.map +1 -1
  31. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomDateTimeItem.js +2 -2
  32. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomDateTimeItem.js.map +1 -1
  33. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.js +3 -3
  34. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.js.map +1 -1
  35. package/lib/components/FormComponents/DecimalItem/DecimalItem.js +2 -2
  36. package/lib/components/FormComponents/DecimalItem/DecimalItem.js.map +1 -1
  37. package/lib/components/FormComponents/GroupItem/GroupItemView.js +1 -1
  38. package/lib/components/FormComponents/GroupItem/GroupItemView.js.map +1 -1
  39. package/lib/components/FormComponents/IntegerItem/IntegerItem.js +2 -2
  40. package/lib/components/FormComponents/IntegerItem/IntegerItem.js.map +1 -1
  41. package/lib/components/FormComponents/ItemParts/CheckboxSingle.d.ts +3 -1
  42. package/lib/components/FormComponents/ItemParts/CheckboxSingle.js +2 -2
  43. package/lib/components/FormComponents/ItemParts/CheckboxSingle.js.map +1 -1
  44. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.d.ts +7 -0
  45. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.js +26 -0
  46. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.js.map +1 -0
  47. package/lib/components/FormComponents/ItemParts/ItemLabel.js +1 -7
  48. package/lib/components/FormComponents/ItemParts/ItemLabel.js.map +1 -1
  49. package/lib/components/FormComponents/ItemParts/ItemLabelText.d.ts +8 -0
  50. package/lib/components/FormComponents/ItemParts/ItemLabelText.js +63 -0
  51. package/lib/components/FormComponents/ItemParts/ItemLabelText.js.map +1 -0
  52. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.d.ts +8 -0
  53. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js +53 -0
  54. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js.map +1 -0
  55. package/lib/components/FormComponents/ItemParts/ItemTextSwitcher copy.d.ts +7 -0
  56. package/lib/components/FormComponents/ItemParts/ItemTextSwitcher copy.js +39 -0
  57. package/lib/components/FormComponents/ItemParts/ItemTextSwitcher copy.js.map +1 -0
  58. package/lib/components/FormComponents/ItemParts/ItemTextSwitcher.js +3 -19
  59. package/lib/components/FormComponents/ItemParts/ItemTextSwitcher.js.map +1 -1
  60. package/lib/components/FormComponents/ItemParts/RadioOptionList.js +2 -1
  61. package/lib/components/FormComponents/ItemParts/RadioOptionList.js.map +1 -1
  62. package/lib/components/FormComponents/ItemParts/StyledText.d.ts +8 -0
  63. package/lib/components/FormComponents/ItemParts/StyledText.js +30 -0
  64. package/lib/components/FormComponents/ItemParts/StyledText.js.map +1 -0
  65. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.d.ts +1 -0
  66. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js +3 -2
  67. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js.map +1 -1
  68. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js +5 -5
  69. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js.map +1 -1
  70. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js +2 -2
  71. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js.map +1 -1
  72. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.js +2 -2
  73. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.js.map +1 -1
  74. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js +2 -2
  75. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js.map +1 -1
  76. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.js +2 -2
  77. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.js.map +1 -1
  78. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.d.ts +1 -0
  79. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js +71 -4
  80. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js.map +1 -1
  81. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.js +5 -6
  82. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.js.map +1 -1
  83. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.d.ts +1 -0
  84. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js +3 -2
  85. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js.map +1 -1
  86. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.js +5 -6
  87. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.js.map +1 -1
  88. package/lib/components/FormComponents/QuantityItem/QuantityItem.js +2 -2
  89. package/lib/components/FormComponents/QuantityItem/QuantityItem.js.map +1 -1
  90. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.d.ts +10 -0
  91. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.js +30 -0
  92. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.js.map +1 -0
  93. package/lib/components/FormComponents/SliderItem/Slider.styles.d.ts +1 -1
  94. package/lib/components/FormComponents/SliderItem/SliderItem.js +2 -2
  95. package/lib/components/FormComponents/SliderItem/SliderItem.js.map +1 -1
  96. package/lib/components/FormComponents/StringItem/StringItem.js +2 -2
  97. package/lib/components/FormComponents/StringItem/StringItem.js.map +1 -1
  98. package/lib/components/FormComponents/TextItem/TextItem.js +2 -2
  99. package/lib/components/FormComponents/TextItem/TextItem.js.map +1 -1
  100. package/lib/components/FormComponents/TimeItem/TimeItem.js +2 -2
  101. package/lib/components/FormComponents/TimeItem/TimeItem.js.map +1 -1
  102. package/lib/components/FormComponents/UrlItem/UrlItem.js +2 -2
  103. package/lib/components/FormComponents/UrlItem/UrlItem.js.map +1 -1
  104. package/lib/components/Iconify/Iconify.d.ts +10 -0
  105. package/lib/components/Iconify/Iconify.js +26 -0
  106. package/lib/components/Iconify/Iconify.js.map +1 -0
  107. package/lib/components/Renderer/FormBodyPage.d.ts +9 -0
  108. package/lib/components/Renderer/FormBodyPage.js +43 -0
  109. package/lib/components/Renderer/FormBodyPage.js.map +1 -0
  110. package/lib/components/Renderer/FormTitle.d.ts +7 -0
  111. package/lib/components/Renderer/FormTitle.js +30 -0
  112. package/lib/components/Renderer/FormTitle.js.map +1 -0
  113. package/lib/components/Renderer/FormTopLevelPage.d.ts +9 -0
  114. package/lib/components/Renderer/FormTopLevelPage.js +29 -0
  115. package/lib/components/Renderer/FormTopLevelPage.js.map +1 -0
  116. package/lib/hooks/useBooleanCalculatedExpression.d.ts +12 -0
  117. package/lib/hooks/useBooleanCalculatedExpression.js +52 -0
  118. package/lib/hooks/useBooleanCalculatedExpression.js.map +1 -0
  119. package/lib/hooks/useCalculatedExpressionAnimating.d.ts +1 -0
  120. package/lib/hooks/useCalculatedExpressionAnimating.js +18 -0
  121. package/lib/hooks/useCalculatedExpressionAnimating.js.map +1 -0
  122. package/lib/hooks/useCalculatedExpressionUpdated.d.ts +1 -1
  123. package/lib/hooks/useCalculatedExpressionUpdated.js +18 -9
  124. package/lib/hooks/useCalculatedExpressionUpdated.js.map +1 -1
  125. package/lib/hooks/useDecimalCalculatedExpression.d.ts +13 -0
  126. package/lib/hooks/useDecimalCalculatedExpression.js +58 -0
  127. package/lib/hooks/useDecimalCalculatedExpression.js.map +1 -0
  128. package/lib/hooks/useInitialiseGroupTable.d.ts +4 -0
  129. package/lib/hooks/useInitialiseGroupTable.js +36 -0
  130. package/lib/hooks/useInitialiseGroupTable.js.map +1 -0
  131. package/lib/hooks/useIntegerCalculatedExpression.d.ts +12 -0
  132. package/lib/hooks/useIntegerCalculatedExpression.js +55 -0
  133. package/lib/hooks/useIntegerCalculatedExpression.js.map +1 -0
  134. package/lib/hooks/useNumberInput.d.ts +3 -0
  135. package/lib/hooks/useNumberInput.js +31 -0
  136. package/lib/hooks/useNumberInput.js.map +1 -0
  137. package/lib/hooks/useParseXhtml.d.ts +2 -2
  138. package/lib/hooks/useParseXhtml.js +5 -5
  139. package/lib/hooks/useParseXhtml.js.map +1 -1
  140. package/lib/hooks/useRepeatAnswers.d.ts +4 -0
  141. package/lib/hooks/useRepeatAnswers.js +34 -0
  142. package/lib/hooks/useRepeatAnswers.js.map +1 -0
  143. package/lib/hooks/useRepeatGroups.d.ts +4 -0
  144. package/lib/hooks/useRepeatGroups.js +34 -0
  145. package/lib/hooks/useRepeatGroups.js.map +1 -0
  146. package/lib/hooks/useShowFeedback.d.ts +11 -0
  147. package/lib/hooks/useShowFeedback.js +33 -0
  148. package/lib/hooks/useShowFeedback.js.map +1 -0
  149. package/lib/hooks/useStringCalculatedExpression.d.ts +14 -0
  150. package/lib/hooks/useStringCalculatedExpression.js +69 -0
  151. package/lib/hooks/useStringCalculatedExpression.js.map +1 -0
  152. package/lib/hooks/useStringInput.d.ts +3 -0
  153. package/lib/hooks/useStringInput.js +31 -0
  154. package/lib/hooks/useStringInput.js.map +1 -0
  155. package/lib/interfaces/itemPath.interface.d.ts +31 -0
  156. package/lib/interfaces/itemPath.interface.js +2 -0
  157. package/lib/interfaces/itemPath.interface.js.map +1 -0
  158. package/lib/interfaces/repeatItem.interface.d.ts +5 -0
  159. package/lib/interfaces/repeatItem.interface.js +2 -0
  160. package/lib/interfaces/repeatItem.interface.js.map +1 -0
  161. package/lib/stores/questionnaireStore.js +15 -2
  162. package/lib/stores/questionnaireStore.js.map +1 -1
  163. package/lib/stores/rendererStylingStore.d.ts +144 -0
  164. package/lib/stores/rendererStylingStore.js +68 -0
  165. package/lib/stores/rendererStylingStore.js.map +1 -0
  166. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.d.ts +30 -0
  167. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.js +46 -0
  168. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.js.map +1 -0
  169. package/lib/stories/storybookWrappers/index.d.ts +2 -0
  170. package/lib/stories/storybookWrappers/index.js +18 -0
  171. package/lib/stories/storybookWrappers/index.js.map +1 -0
  172. package/lib/stories/testUtils.d.ts +23 -0
  173. package/lib/stories/testUtils.js +249 -0
  174. package/lib/stories/testUtils.js.map +1 -0
  175. package/lib/theme/Theme.d.ts +44 -0
  176. package/lib/theme/Theme.js +45 -0
  177. package/lib/theme/Theme.js.map +1 -0
  178. package/lib/theme/customGlobalStyles.d.ts +2 -0
  179. package/lib/theme/customGlobalStyles.js +61 -0
  180. package/lib/theme/customGlobalStyles.js.map +1 -0
  181. package/lib/theme/overrides/Accordion.d.ts +14 -0
  182. package/lib/theme/overrides/Accordion.js +32 -0
  183. package/lib/theme/overrides/Accordion.js.map +1 -0
  184. package/lib/theme/overrides/Autocomplete.d.ts +10 -0
  185. package/lib/theme/overrides/Autocomplete.js +28 -0
  186. package/lib/theme/overrides/Autocomplete.js.map +1 -0
  187. package/lib/theme/overrides/Button.d.ts +33 -0
  188. package/lib/theme/overrides/Button.js +52 -0
  189. package/lib/theme/overrides/Button.js.map +1 -0
  190. package/lib/theme/overrides/Card.d.ts +35 -0
  191. package/lib/theme/overrides/Card.js +49 -0
  192. package/lib/theme/overrides/Card.js.map +1 -0
  193. package/lib/theme/overrides/Input.d.ts +64 -0
  194. package/lib/theme/overrides/Input.js +81 -0
  195. package/lib/theme/overrides/Input.js.map +1 -0
  196. package/lib/theme/overrides/Overrides.d.ts +3 -0
  197. package/lib/theme/overrides/Overrides.js +29 -0
  198. package/lib/theme/overrides/Overrides.js.map +1 -0
  199. package/lib/theme/overrides/Paper.d.ts +12 -0
  200. package/lib/theme/overrides/Paper.js +31 -0
  201. package/lib/theme/overrides/Paper.js.map +1 -0
  202. package/lib/theme/overrides/SpeedDial.d.ts +16 -0
  203. package/lib/theme/overrides/SpeedDial.js +34 -0
  204. package/lib/theme/overrides/SpeedDial.js.map +1 -0
  205. package/lib/theme/overrides/Table.d.ts +12 -0
  206. package/lib/theme/overrides/Table.js +30 -0
  207. package/lib/theme/overrides/Table.js.map +1 -0
  208. package/lib/theme/palette.d.ts +27 -0
  209. package/lib/theme/palette.js +67 -0
  210. package/lib/theme/palette.js.map +1 -0
  211. package/lib/theme/shadows.d.ts +2 -0
  212. package/lib/theme/shadows.js +52 -0
  213. package/lib/theme/shadows.js.map +1 -0
  214. package/lib/utils/answerExpression.d.ts +18 -0
  215. package/lib/utils/answerExpression.js +133 -0
  216. package/lib/utils/answerExpression.js.map +1 -0
  217. package/lib/utils/calculatedExpression.js +1 -5
  218. package/lib/utils/calculatedExpression.js.map +1 -1
  219. package/lib/utils/dayjsExtend.d.ts +1 -0
  220. package/lib/utils/dayjsExtend.js +22 -0
  221. package/lib/utils/dayjsExtend.js.map +1 -0
  222. package/lib/utils/dynamicValueSet.d.ts +5 -0
  223. package/lib/utils/dynamicValueSet.js +96 -0
  224. package/lib/utils/dynamicValueSet.js.map +1 -0
  225. package/lib/utils/extensions.d.ts +2 -2
  226. package/lib/utils/extensions.js +2 -2
  227. package/lib/utils/extensions.js.map +1 -1
  228. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.d.ts +14 -0
  229. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.js +639 -0
  230. package/lib/utils/fhirpathAsyncUtils/fhirpath-async.js.map +1 -0
  231. package/lib/utils/fhirpathAsyncUtils/outcome-utils.d.ts +3 -0
  232. package/lib/utils/fhirpathAsyncUtils/outcome-utils.js +41 -0
  233. package/lib/utils/fhirpathAsyncUtils/outcome-utils.js.map +1 -0
  234. package/lib/utils/itemControl.d.ts +97 -0
  235. package/lib/utils/itemControl.js +336 -0
  236. package/lib/utils/itemControl.js.map +1 -0
  237. package/lib/utils/itemPath.d.ts +57 -0
  238. package/lib/utils/itemPath.js +75 -0
  239. package/lib/utils/itemPath.js.map +1 -0
  240. package/lib/utils/manageForm.js +5 -4
  241. package/lib/utils/manageForm.js.map +1 -1
  242. package/lib/utils/qrItem.d.ts +6 -0
  243. package/lib/utils/qrItem.js +11 -0
  244. package/lib/utils/qrItem.js.map +1 -1
  245. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.d.ts +2 -0
  246. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.js +43 -0
  247. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.js.map +1 -0
  248. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.d.ts +3 -0
  249. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js +101 -0
  250. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js.map +1 -0
  251. package/lib/utils/validateQuestionnaire.d.ts +66 -0
  252. package/lib/utils/validateQuestionnaire.js +559 -0
  253. package/lib/utils/validateQuestionnaire.js.map +1 -0
  254. package/package.json +2 -2
  255. package/src/components/FormComponents/AttachmentItem/AttachmentItem.tsx +2 -2
  256. package/src/components/FormComponents/BooleanItem/BooleanItem.tsx +2 -2
  257. package/src/components/FormComponents/ChoiceItems/CheckboxOptionList.tsx +5 -1
  258. package/src/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.tsx +5 -0
  259. package/src/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.tsx +6 -4
  260. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.tsx +2 -2
  261. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.tsx +2 -2
  262. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +2 -2
  263. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +2 -2
  264. package/src/components/FormComponents/ChoiceItems/ChoiceRadioSingle.tsx +1 -1
  265. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +93 -4
  266. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +2 -2
  267. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.tsx +4 -2
  268. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.tsx +2 -2
  269. package/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.tsx +2 -2
  270. package/src/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomDateTimeItem.tsx +2 -2
  271. package/src/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.tsx +3 -1
  272. package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +2 -2
  273. package/src/components/FormComponents/GroupItem/GroupItemView.tsx +1 -1
  274. package/src/components/FormComponents/IntegerItem/IntegerItem.tsx +2 -2
  275. package/src/components/FormComponents/ItemParts/CheckboxSingle.tsx +4 -2
  276. package/src/components/FormComponents/ItemParts/ItemLabel.tsx +1 -8
  277. package/src/components/FormComponents/ItemParts/ItemTextSwitcher.tsx +3 -25
  278. package/src/components/FormComponents/ItemParts/RadioOptionList.tsx +4 -1
  279. package/src/components/FormComponents/ItemParts/StyledText.tsx +46 -0
  280. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.tsx +4 -0
  281. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.tsx +6 -3
  282. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.tsx +2 -2
  283. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerValueSetItem.tsx +2 -2
  284. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.tsx +2 -2
  285. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetItem.tsx +2 -2
  286. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.tsx +86 -3
  287. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.tsx +6 -4
  288. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.tsx +4 -0
  289. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.tsx +6 -4
  290. package/src/components/FormComponents/QuantityItem/QuantityItem.tsx +2 -2
  291. package/src/components/FormComponents/SliderItem/SliderItem.tsx +2 -2
  292. package/src/components/FormComponents/StringItem/StringItem.tsx +2 -2
  293. package/src/components/FormComponents/TextItem/TextItem.tsx +2 -2
  294. package/src/components/FormComponents/TimeItem/TimeItem.tsx +2 -2
  295. package/src/components/FormComponents/UrlItem/UrlItem.tsx +2 -2
  296. package/src/hooks/useCalculatedExpressionUpdated.ts +25 -11
  297. package/src/hooks/useParseXhtml.tsx +9 -6
  298. package/src/stores/questionnaireStore.ts +23 -0
  299. package/src/utils/calculatedExpression.ts +1 -5
  300. package/src/utils/extensions.ts +9 -3
  301. package/src/utils/manageForm.ts +10 -9
  302. package/src/utils/qrItem.ts +12 -0
@@ -37,6 +37,7 @@ import type {
37
37
  import type { AlertColor } from '@mui/material/Alert';
38
38
  import { useRendererConfigStore } from '../../../stores';
39
39
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
40
+ import ExpressionUpdateFadingIcon from '../ItemParts/ExpressionUpdateFadingIcon';
40
41
 
41
42
  interface OpenChoiceAutocompleteFieldProps
42
43
  extends PropsWithIsTabledAttribute,
@@ -49,6 +50,7 @@ interface OpenChoiceAutocompleteFieldProps
49
50
  loading: boolean;
50
51
  feedback: { message: string; color: AlertColor } | null;
51
52
  readOnly: boolean;
53
+ calcExpUpdated: boolean;
52
54
  onValueChange: (
53
55
  newValue: Coding | string | null,
54
56
  reason: AutocompleteChangeReason | string
@@ -64,6 +66,7 @@ function OpenChoiceAutocompleteField(props: OpenChoiceAutocompleteFieldProps) {
64
66
  loading,
65
67
  feedback,
66
68
  readOnly,
69
+ calcExpUpdated,
67
70
  isTabled,
68
71
  renderingExtensions,
69
72
  onValueChange
@@ -132,6 +135,7 @@ function OpenChoiceAutocompleteField(props: OpenChoiceAutocompleteFieldProps) {
132
135
  </Tooltip>
133
136
  </Fade>
134
137
  ) : null}
138
+ <ExpressionUpdateFadingIcon fadeIn={calcExpUpdated} disabled={readOnly} />
135
139
  {params.InputProps.endAdornment}
136
140
  <DisplayUnitText readOnly={readOnly}>{displayUnit}</DisplayUnitText>
137
141
  </>
@@ -35,6 +35,7 @@ import { createEmptyQrItem } from '../../../utils';
35
35
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
36
36
  import { useQuestionnaireStore } from '../../../stores';
37
37
  import { FullWidthFormComponentBox } from '../../Box.styles';
38
+ import { getQRItemId } from '../../../utils/qrItem';
38
39
 
39
40
  function OpenChoiceAutocompleteItem(props: BaseItemProps) {
40
41
  const {
@@ -45,13 +46,13 @@ function OpenChoiceAutocompleteItem(props: BaseItemProps) {
45
46
  renderingExtensions,
46
47
  feedbackFromParent,
47
48
  parentIsReadOnly,
48
- onQrItemChange
49
+ onQrItemChange,
50
+ calcExpUpdated
49
51
  } = props;
50
- // TODO no calcExpUpdated
51
52
 
52
53
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
53
54
 
54
- const answerKey = qrItem?.answer?.[0]?.id;
55
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
55
56
  const qrOpenChoice = qrItem ?? createEmptyQrItem(qItem, answerKey);
56
57
 
57
58
  // Init input value
@@ -175,6 +176,7 @@ function OpenChoiceAutocompleteItem(props: BaseItemProps) {
175
176
  loading={loading}
176
177
  feedback={feedback}
177
178
  readOnly={readOnly}
179
+ calcExpUpdated={calcExpUpdated}
178
180
  isTabled={isTabled}
179
181
  renderingExtensions={renderingExtensions}
180
182
  onValueChange={handleValueChange}
@@ -201,6 +203,7 @@ function OpenChoiceAutocompleteItem(props: BaseItemProps) {
201
203
  loading={loading}
202
204
  feedback={feedback}
203
205
  readOnly={readOnly}
206
+ calcExpUpdated={calcExpUpdated}
204
207
  isTabled={isTabled}
205
208
  renderingExtensions={renderingExtensions}
206
209
  onValueChange={handleValueChange}
@@ -27,7 +27,7 @@ import { updateChoiceCheckboxAnswers } from '../../../utils/choice';
27
27
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
28
28
  import { getOpenLabelText } from '../../../utils/extensions';
29
29
  import { updateOpenLabelAnswer } from '../../../utils/openChoice';
30
- import { createEmptyQrItem } from '../../../utils/qrItem';
30
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
31
31
  import { FullWidthFormComponentBox } from '../../Box.styles';
32
32
  import DisplayInstructions from '../DisplayItem/DisplayInstructions';
33
33
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
@@ -50,7 +50,7 @@ function OpenChoiceCheckboxAnswerOptionItem(props: BaseItemProps) {
50
50
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
51
51
 
52
52
  // Init input value
53
- const answerKey = qrItem?.answer?.[0]?.id;
53
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
54
54
  const qrOpenChoiceCheckbox = qrItem ?? createEmptyQrItem(qItem, answerKey);
55
55
  const answers = qrOpenChoiceCheckbox.answer ?? [];
56
56
 
@@ -28,7 +28,7 @@ import { convertCodingsToAnswerOptions, updateChoiceCheckboxAnswers } from '../.
28
28
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
29
29
  import { getOpenLabelText } from '../../../utils/extensions';
30
30
  import { updateOpenLabelAnswer } from '../../../utils/openChoice';
31
- import { createEmptyQrItem } from '../../../utils/qrItem';
31
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
32
32
  import { FullWidthFormComponentBox } from '../../Box.styles';
33
33
  import DisplayInstructions from '../DisplayItem/DisplayInstructions';
34
34
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
@@ -51,7 +51,7 @@ function OpenChoiceCheckboxAnswerValueSetItem(props: BaseItemProps) {
51
51
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
52
52
 
53
53
  // Init input value
54
- const answerKey = qrItem?.answer?.[0]?.id;
54
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
55
55
  const qrOpenChoiceCheckbox = qrItem ?? createEmptyQrItem(qItem, answerKey);
56
56
  const answers = qrOpenChoiceCheckbox.answer ?? [];
57
57
 
@@ -24,7 +24,7 @@ import { useQuestionnaireStore } from '../../../stores';
24
24
  import { findInAnswerOptions, getQrChoiceValue } from '../../../utils/choice';
25
25
  import { getOpenLabelText } from '../../../utils/extensions';
26
26
  import { getOldOpenLabelAnswer } from '../../../utils/openChoice';
27
- import { createEmptyQrItem } from '../../../utils/qrItem';
27
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
28
28
  import { FullWidthFormComponentBox } from '../../Box.styles';
29
29
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
30
30
  import ItemLabel from '../ItemParts/ItemLabel';
@@ -45,7 +45,7 @@ function OpenChoiceRadioAnswerOptionItem(props: BaseItemProps) {
45
45
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
46
46
 
47
47
  // Init answers
48
- const answerKey = qrItem?.answer?.[0]?.id;
48
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
49
49
  const qrOpenChoiceRadio = qrItem ?? createEmptyQrItem(qItem, answerKey);
50
50
  let valueRadio: string | null = getQrChoiceValue(qrOpenChoiceRadio, true);
51
51
  const answers = qrOpenChoiceRadio.answer ?? [];
@@ -29,7 +29,7 @@ import {
29
29
  } from '../../../utils/choice';
30
30
  import { getOpenLabelText } from '../../../utils/extensions';
31
31
  import { getOldOpenLabelAnswer } from '../../../utils/openChoice';
32
- import { createEmptyQrItem } from '../../../utils/qrItem';
32
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
33
33
  import { FullWidthFormComponentBox } from '../../Box.styles';
34
34
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
35
35
  import ItemLabel from '../ItemParts/ItemLabel';
@@ -50,7 +50,7 @@ function OpenChoiceRadioAnswerValueSetItem(props: BaseItemProps) {
50
50
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
51
51
 
52
52
  // Init answers
53
- const answerKey = qrItem?.answer?.[0]?.id;
53
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
54
54
  const qrOpenChoiceRadio = qrItem ?? createEmptyQrItem(qItem, answerKey);
55
55
  let valueRadio: string | null = getQrChoiceValue(qrOpenChoiceRadio, true);
56
56
  const answers = qrOpenChoiceRadio.answer ?? [];
@@ -29,6 +29,8 @@ import type {
29
29
  import { useRendererConfigStore } from '../../../stores';
30
30
  import { StyledRequiredTypography } from '../Item.styles';
31
31
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
32
+ import ExpressionUpdateFadingIcon from '../ItemParts/ExpressionUpdateFadingIcon';
33
+ import StyledText from '../ItemParts/StyledText';
32
34
 
33
35
  interface OpenChoiceSelectAnswerOptionFieldProps
34
36
  extends PropsWithIsTabledAttribute,
@@ -39,6 +41,7 @@ interface OpenChoiceSelectAnswerOptionFieldProps
39
41
  valueSelect: QuestionnaireItemAnswerOption | null;
40
42
  feedback: string;
41
43
  readOnly: boolean;
44
+ calcExpUpdated: boolean;
42
45
  onValueChange: (
43
46
  newValue: QuestionnaireItemAnswerOption | string | null,
44
47
  reason: AutocompleteChangeReason | string
@@ -52,6 +55,7 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
52
55
  valueSelect,
53
56
  feedback,
54
57
  readOnly,
58
+ calcExpUpdated,
55
59
  isTabled,
56
60
  renderingExtensions,
57
61
  onValueChange
@@ -62,6 +66,8 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
62
66
 
63
67
  const { displayUnit, displayPrompt, entryFormat } = renderingExtensions;
64
68
 
69
+ const [inputValue, setInputValue] = React.useState('');
70
+
65
71
  return (
66
72
  <>
67
73
  <Autocomplete
@@ -70,10 +76,42 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
70
76
  options={options}
71
77
  getOptionLabel={(option) => getAnswerOptionLabel(option)}
72
78
  onChange={(_, newValue, reason) => onValueChange(newValue, reason)}
73
- onInputChange={(_, newValue, reason) => onValueChange(newValue, reason)}
79
+ inputValue={inputValue}
80
+ onInputChange={(_, newInputValue, reason) => {
81
+ if (!inputValue && valueSelect && reason !== 'clear') {
82
+ // Convert current input value to be the current value plus additional input
83
+ onValueChange(null, 'clear');
84
+ setInputValue(getAnswerOptionLabel(valueSelect) + newInputValue);
85
+ } else {
86
+ setInputValue(newInputValue);
87
+ }
88
+ }}
89
+ onBlur={() => {
90
+ // Set value on blur if there is any current input
91
+ if (inputValue) {
92
+ onValueChange(inputValue, 'blur');
93
+ setInputValue(''); // Clear input after blur
94
+ }
95
+ }}
96
+ onKeyDown={(e) => {
97
+ if (e.key === 'Backspace') {
98
+ if (!inputValue && valueSelect) {
99
+ // Convert current selection to input value on backspace when input is empty
100
+ onValueChange(null, 'clear');
101
+ setInputValue(getAnswerOptionLabel(valueSelect));
102
+ }
103
+ }
104
+ }}
74
105
  freeSolo
75
106
  autoHighlight
76
- sx={{ maxWidth: !isTabled ? textFieldWidth : 3000, minWidth: 160, flexGrow: 1 }}
107
+ sx={{
108
+ maxWidth: !isTabled ? textFieldWidth : 3000,
109
+ minWidth: 160,
110
+ flexGrow: 1,
111
+ '& .MuiAutocomplete-tag': {
112
+ mx: 0
113
+ }
114
+ }}
77
115
  disabled={readOnly && readOnlyVisualStyle === 'disabled'}
78
116
  readOnly={readOnly && readOnlyVisualStyle === 'readonly'}
79
117
  size="small"
@@ -90,14 +128,59 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
90
128
  readOnly: readOnly && readOnlyVisualStyle === 'readonly',
91
129
  endAdornment: (
92
130
  <>
131
+ <ExpressionUpdateFadingIcon fadeIn={calcExpUpdated} disabled={readOnly} />
93
132
  {params.InputProps.endAdornment}
94
133
  <DisplayUnitText readOnly={readOnly}>{displayUnit}</DisplayUnitText>
95
134
  </>
96
- )
135
+ ),
136
+ sx: {
137
+ '&.MuiOutlinedInput-root.MuiInputBase-sizeSmall .MuiAutocomplete-input': {
138
+ paddingLeft: '0px'
139
+ }
140
+ }
97
141
  }
98
142
  }}
99
143
  />
100
144
  )}
145
+ renderOption={(optionProps, option) => {
146
+ const { key, ...rest } = optionProps;
147
+ return (
148
+ <li key={key} {...rest}>
149
+ <span>
150
+ {option.valueString ? (
151
+ <StyledText
152
+ textToDisplay={getAnswerOptionLabel(option)}
153
+ element={option._valueString}
154
+ />
155
+ ) : (
156
+ getAnswerOptionLabel(option)
157
+ )}
158
+ </span>
159
+ </li>
160
+ );
161
+ }}
162
+ renderValue={(value, getItemProps) => {
163
+ if (typeof value === 'string') return value;
164
+ const selectedOption =
165
+ typeof value !== 'string'
166
+ ? options.find((opt) => opt.valueString === value?.valueString)
167
+ : null;
168
+
169
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
170
+ const { onDelete, ...rest } = getItemProps();
171
+ return (
172
+ <span {...rest}>
173
+ {typeof value !== 'string' && value.valueString && selectedOption ? (
174
+ <StyledText
175
+ textToDisplay={getAnswerOptionLabel(value)}
176
+ element={selectedOption._valueString}
177
+ />
178
+ ) : (
179
+ getAnswerOptionLabel(value)
180
+ )}
181
+ </span>
182
+ );
183
+ }}
101
184
  />
102
185
 
103
186
  {feedback ? <StyledRequiredTypography>{feedback}</StyledRequiredTypography> : null}
@@ -21,7 +21,7 @@ import useReadOnly from '../../../hooks/useReadOnly';
21
21
  import useValidationFeedback from '../../../hooks/useValidationFeedback';
22
22
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
23
23
  import { useQuestionnaireStore } from '../../../stores';
24
- import { createEmptyQrItem } from '../../../utils/qrItem';
24
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
25
25
  import { FullWidthFormComponentBox } from '../../Box.styles';
26
26
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
27
27
  import ItemLabel from '../ItemParts/ItemLabel';
@@ -37,9 +37,9 @@ function OpenChoiceSelectAnswerOptionItem(props: BaseItemProps) {
37
37
  renderingExtensions,
38
38
  parentIsReadOnly,
39
39
  feedbackFromParent,
40
- onQrItemChange
40
+ onQrItemChange,
41
+ calcExpUpdated
41
42
  } = props;
42
- // TODO no calcExpUpdated
43
43
 
44
44
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
45
45
 
@@ -49,7 +49,7 @@ function OpenChoiceSelectAnswerOptionItem(props: BaseItemProps) {
49
49
  const feedback = useValidationFeedback(qItem, feedbackFromParent);
50
50
 
51
51
  // Init input value
52
- const answerKey = qrItem?.answer?.[0]?.id;
52
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
53
53
  const answerOptions = qItem.answerOption;
54
54
  if (!answerOptions) return null;
55
55
 
@@ -111,6 +111,7 @@ function OpenChoiceSelectAnswerOptionItem(props: BaseItemProps) {
111
111
  valueSelect={valueSelect}
112
112
  feedback={feedback}
113
113
  readOnly={readOnly}
114
+ calcExpUpdated={calcExpUpdated}
114
115
  isTabled={isTabled}
115
116
  renderingExtensions={renderingExtensions}
116
117
  onValueChange={handleValueChange}
@@ -135,6 +136,7 @@ function OpenChoiceSelectAnswerOptionItem(props: BaseItemProps) {
135
136
  valueSelect={valueSelect}
136
137
  feedback={feedback}
137
138
  readOnly={readOnly}
139
+ calcExpUpdated={calcExpUpdated}
138
140
  isTabled={isTabled}
139
141
  renderingExtensions={renderingExtensions}
140
142
  onValueChange={handleValueChange}
@@ -30,6 +30,7 @@ import type { TerminologyError } from '../../../hooks/useValueSetCodings';
30
30
  import { useRendererConfigStore } from '../../../stores';
31
31
  import { StyledRequiredTypography } from '../Item.styles';
32
32
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
33
+ import ExpressionUpdateFadingIcon from '../ItemParts/ExpressionUpdateFadingIcon';
33
34
 
34
35
  interface OpenChoiceSelectAnswerValueSetFieldProps
35
36
  extends PropsWithIsTabledAttribute,
@@ -41,6 +42,7 @@ interface OpenChoiceSelectAnswerValueSetFieldProps
41
42
  terminologyError: TerminologyError;
42
43
  feedback: string;
43
44
  readOnly: boolean;
45
+ calcExpUpdated: boolean;
44
46
  onValueChange: (
45
47
  newValue: Coding | string | null,
46
48
  reason: AutocompleteChangeReason | string
@@ -55,6 +57,7 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
55
57
  terminologyError,
56
58
  feedback,
57
59
  readOnly,
60
+ calcExpUpdated,
58
61
  isTabled,
59
62
  renderingExtensions,
60
63
  onValueChange
@@ -95,6 +98,7 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
95
98
  readOnly: readOnly && readOnlyVisualStyle === 'readonly',
96
99
  endAdornment: (
97
100
  <>
101
+ <ExpressionUpdateFadingIcon fadeIn={calcExpUpdated} disabled={readOnly} />
98
102
  {params.InputProps.endAdornment}
99
103
  <DisplayUnitText readOnly={readOnly}>{displayUnit}</DisplayUnitText>
100
104
  </>
@@ -22,7 +22,7 @@ import useValidationFeedback from '../../../hooks/useValidationFeedback';
22
22
  import useValueSetCodings from '../../../hooks/useValueSetCodings';
23
23
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
24
24
  import { useQuestionnaireStore } from '../../../stores';
25
- import { createEmptyQrItem } from '../../../utils/qrItem';
25
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
26
26
  import { FullWidthFormComponentBox } from '../../Box.styles';
27
27
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
28
28
  import ItemLabel from '../ItemParts/ItemLabel';
@@ -38,9 +38,9 @@ function OpenChoiceSelectAnswerValueSetItem(props: BaseItemProps) {
38
38
  renderingExtensions,
39
39
  parentIsReadOnly,
40
40
  feedbackFromParent,
41
- onQrItemChange
41
+ onQrItemChange,
42
+ calcExpUpdated
42
43
  } = props;
43
- // TODO no calcExpUpdated
44
44
 
45
45
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
46
46
 
@@ -50,7 +50,7 @@ function OpenChoiceSelectAnswerValueSetItem(props: BaseItemProps) {
50
50
  const feedback = useValidationFeedback(qItem, feedbackFromParent);
51
51
 
52
52
  // Init input value
53
- const answerKey = qrItem?.answer?.[0]?.id;
53
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
54
54
  const qrOpenChoice = qrItem ?? createEmptyQrItem(qItem, answerKey);
55
55
 
56
56
  let valueSelect: Coding | string | null = null;
@@ -131,6 +131,7 @@ function OpenChoiceSelectAnswerValueSetItem(props: BaseItemProps) {
131
131
  renderingExtensions={renderingExtensions}
132
132
  readOnly={readOnly}
133
133
  onValueChange={handleValueChange}
134
+ calcExpUpdated={calcExpUpdated}
134
135
  />
135
136
  );
136
137
  }
@@ -156,6 +157,7 @@ function OpenChoiceSelectAnswerValueSetItem(props: BaseItemProps) {
156
157
  renderingExtensions={renderingExtensions}
157
158
  readOnly={readOnly}
158
159
  onValueChange={handleValueChange}
160
+ calcExpUpdated={calcExpUpdated}
159
161
  />
160
162
  }
161
163
  />
@@ -25,7 +25,7 @@ import { useQuestionnaireStore } from '../../../stores';
25
25
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
26
26
  import { getDecimalPrecision } from '../../../utils/extensions';
27
27
  import { parseDecimalStringWithPrecision } from '../../../utils/parseInputs';
28
- import { createEmptyQrItem } from '../../../utils/qrItem';
28
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
29
29
  import Box from '@mui/material/Box';
30
30
  import QuantityField from './QuantityField';
31
31
  import {
@@ -71,7 +71,7 @@ function QuantityItem(props: BaseItemProps) {
71
71
  }
72
72
 
73
73
  // Init inputs
74
- const answerKey = qrItem?.answer?.[0]?.id;
74
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
75
75
  let valueQuantity: Quantity = {};
76
76
  let initialValueInput = '';
77
77
  let initialComparatorInput: Quantity['comparator'] | null = null;
@@ -17,7 +17,7 @@
17
17
 
18
18
  import React from 'react';
19
19
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
20
- import { createEmptyQrItem } from '../../../utils/qrItem';
20
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
21
21
  import { FullWidthFormComponentBox } from '../../Box.styles';
22
22
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
23
23
  import useReadOnly from '../../../hooks/useReadOnly';
@@ -46,7 +46,7 @@ function SliderItem(props: BaseItemProps) {
46
46
  const isInteracted = !!qrItem?.answer;
47
47
 
48
48
  // Init input value
49
- const answerKey = qrItem?.answer?.[0]?.id;
49
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
50
50
  let valueInteger = 0;
51
51
  if (qrItem?.answer) {
52
52
  if (qrItem?.answer[0].valueInteger) {
@@ -23,7 +23,7 @@ import useValidationFeedback from '../../../hooks/useValidationFeedback';
23
23
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
24
24
  import { useQuestionnaireStore } from '../../../stores';
25
25
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
26
- import { createEmptyQrItem } from '../../../utils/qrItem';
26
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
27
27
  import { FullWidthFormComponentBox } from '../../Box.styles';
28
28
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
29
29
  import ItemLabel from '../ItemParts/ItemLabel';
@@ -48,7 +48,7 @@ function StringItem(props: BaseItemProps) {
48
48
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
49
49
 
50
50
  // Init input value
51
- const answerKey = qrItem?.answer?.[0]?.id;
51
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
52
52
  const { initialInput } = readStringValue(qrItem);
53
53
 
54
54
  const [input, setInput] = useState(initialInput);
@@ -19,7 +19,7 @@ import { useCallback, useState } from 'react';
19
19
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
20
20
  import useValidationFeedback from '../../../hooks/useValidationFeedback';
21
21
  import debounce from 'lodash.debounce';
22
- import { createEmptyQrItem } from '../../../utils/qrItem';
22
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
23
23
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
24
24
  import { FullWidthFormComponentBox } from '../../Box.styles';
25
25
  import TextField from './TextField';
@@ -46,7 +46,7 @@ function TextItem(props: BaseItemProps) {
46
46
  const onFocusLinkId = useQuestionnaireStore.use.onFocusLinkId();
47
47
 
48
48
  // Init input value
49
- const answerKey = qrItem?.answer?.[0]?.id;
49
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
50
50
  const { initialInput } = readStringValue(qrItem);
51
51
 
52
52
  const [input, setInput] = useState(initialInput);
@@ -17,7 +17,7 @@
17
17
 
18
18
  import React from 'react';
19
19
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
20
- import { createEmptyQrItem } from '../../../utils/qrItem';
20
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
21
21
  import { FullWidthFormComponentBox } from '../../Box.styles';
22
22
  import TimeField from './TimeField';
23
23
  import type { Dayjs } from 'dayjs';
@@ -44,7 +44,7 @@ function TimeItem(props: BaseItemProps) {
44
44
  const { displayPrompt, entryFormat } = renderingExtensions;
45
45
 
46
46
  // Init input value
47
- const answerKey = qrItem?.answer?.[0]?.id;
47
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
48
48
  let timeString: string | null = null;
49
49
  if (qrItem?.answer && qrItem?.answer[0].valueTime) {
50
50
  timeString = qrItem.answer[0].valueTime;
@@ -19,7 +19,7 @@ import React, { useCallback, useState } from 'react';
19
19
  import type { BaseItemProps } from '../../../interfaces/renderProps.interface';
20
20
  import useValidationFeedback from '../../../hooks/useValidationFeedback';
21
21
  import debounce from 'lodash.debounce';
22
- import { createEmptyQrItem } from '../../../utils/qrItem';
22
+ import { createEmptyQrItem, getQRItemId } from '../../../utils/qrItem';
23
23
  import { DEBOUNCE_DURATION } from '../../../utils/debounce';
24
24
  import { FullWidthFormComponentBox } from '../../Box.styles';
25
25
  import UrlField from './UrlField';
@@ -46,7 +46,7 @@ function UrlItem(props: BaseItemProps) {
46
46
  const { displayUnit, displayPrompt, entryFormat } = renderingExtensions;
47
47
 
48
48
  // Init input value
49
- const answerKey = qrItem?.answer?.[0]?.id;
49
+ const answerKey = getQRItemId(qrItem?.answer?.[0]?.id);
50
50
  let valueUri = '';
51
51
  if (qrItem?.answer && qrItem?.answer[0].valueUri) {
52
52
  valueUri = qrItem.answer[0].valueUri;
@@ -6,27 +6,37 @@ import { useEffect, useRef, useState } from 'react';
6
6
  *
7
7
  * Ignores the initial mount (so it won't re-animate when the user switch between tabs).
8
8
  */
9
- export function useCalculatedExpressionUpdated(answerKey: string | undefined): boolean {
9
+ export function useCalculatedExpressionUpdated(
10
+ answerKey: string | undefined,
11
+ answerSnapshot?: string | undefined
12
+ ): boolean {
10
13
  const [animating, setAnimating] = useState(false);
11
14
  const previousAnswerKey = useRef<string | null>(null);
15
+ const previousAnswerSnapshot = useRef<string | null>(null);
12
16
  const mounted = useRef(false);
13
17
 
14
18
  useEffect(() => {
15
- // Skip the first render — just store the current key
19
+ // Skip the first render — just store the current key/snapshot
16
20
  if (!mounted.current) {
17
21
  mounted.current = true;
18
22
  previousAnswerKey.current = answerKey ?? null;
23
+ previousAnswerSnapshot.current = answerSnapshot ?? null;
19
24
  return;
20
25
  }
21
26
 
22
- // Answer key has changed, and it is a calculatedExpression
23
- if (
24
- answerKey &&
25
- answerKey !== previousAnswerKey.current &&
26
- // values generated via calculatedExpression will have "calculatedExpression" in their key e.g. obs-bmi-calculatedExpression-_Cye5_m-d4cjxZqY4-9XL
27
- answerKey.includes('calculatedExpression')
28
- ) {
29
- previousAnswerKey.current = answerKey;
27
+ // Determine whether the answer changed. If an answerSnapshot is provided we use
28
+ // that to detect value changes (useful when the answer id stays the same).
29
+ const changed =
30
+ answerSnapshot !== undefined
31
+ ? answerSnapshot !== previousAnswerSnapshot.current
32
+ : !!answerKey && answerKey !== previousAnswerKey.current;
33
+
34
+ const isCalculated = !!answerKey && answerKey.includes('calculatedExpression');
35
+
36
+ // Answer changed and it is a calculatedExpression
37
+ if (changed && isCalculated) {
38
+ previousAnswerKey.current = answerKey ?? null;
39
+ previousAnswerSnapshot.current = answerSnapshot ?? null;
30
40
  setAnimating(true);
31
41
 
32
42
  const timer = setTimeout(() => setAnimating(false), 700);
@@ -34,8 +44,12 @@ export function useCalculatedExpressionUpdated(answerKey: string | undefined): b
34
44
  return () => clearTimeout(timer);
35
45
  }
36
46
 
47
+ // Always advance the stored values so we don't re-fire due to transient undefined/null
48
+ previousAnswerKey.current = answerKey ?? null;
49
+ previousAnswerSnapshot.current = answerSnapshot ?? null;
50
+
37
51
  return undefined;
38
- }, [answerKey]);
52
+ }, [answerKey, answerSnapshot]);
39
53
 
40
54
  return animating;
41
55
  }
@@ -16,8 +16,8 @@
16
16
  */
17
17
 
18
18
  import React, { useMemo } from 'react';
19
- import { getXHtmlString } from '../utils/extensions';
20
- import type { QuestionnaireItem } from 'fhir/r4';
19
+ import { getXHtmlStringFromExtension } from '../utils/extensions';
20
+ import type { Element } from 'fhir/r4';
21
21
  import type { HTMLReactParserOptions } from 'html-react-parser';
22
22
  import { attributesToProps, default as htmlParse, domToReact } from 'html-react-parser';
23
23
  import type { Attributes } from 'html-react-parser/lib/attributes-to-props';
@@ -27,9 +27,12 @@ export interface ParsedXhtml {
27
27
  styles?: Record<string, string>;
28
28
  }
29
29
 
30
- export function useParseXhtml(qItem: QuestionnaireItem): ParsedXhtml | null {
30
+ export function useParseXhtml(
31
+ element: Element | undefined,
32
+ text: string | null | undefined
33
+ ): ParsedXhtml | null {
31
34
  return useMemo(() => {
32
- let xHtmlString = getXHtmlString(qItem);
35
+ let xHtmlString = getXHtmlStringFromExtension(element?.extension || []);
33
36
 
34
37
  if (xHtmlString === null || xHtmlString === '') {
35
38
  return null;
@@ -37,7 +40,7 @@ export function useParseXhtml(qItem: QuestionnaireItem): ParsedXhtml | null {
37
40
 
38
41
  // Replace <img with alt text - only if there are no alt tags
39
42
  if (!xHtmlString.includes('alt=') && !xHtmlString.includes('alt =')) {
40
- const altText = `<img alt='${qItem.text}'`;
43
+ const altText = `<img alt='${text}'`;
41
44
  xHtmlString = xHtmlString.replace('<img', altText);
42
45
  }
43
46
 
@@ -137,7 +140,7 @@ export function useParseXhtml(qItem: QuestionnaireItem): ParsedXhtml | null {
137
140
  content: parsedContent,
138
141
  styles: extractedStyles
139
142
  };
140
- }, [qItem]);
143
+ }, [element, text]);
141
144
  }
142
145
 
143
146
  export function getStylesFromClass(className: string): Record<string, string> | null {