@aehrc/smart-forms-renderer 0.13.1 → 0.14.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 (195) hide show
  1. package/lib/components/Box.styles.d.ts +0 -6
  2. package/lib/components/Box.styles.js +1 -29
  3. package/lib/components/Box.styles.js.map +1 -1
  4. package/lib/components/FormComponents/AttachmentItem/AttachmentField.d.ts +13 -0
  5. package/lib/components/FormComponents/AttachmentItem/AttachmentField.js +39 -0
  6. package/lib/components/FormComponents/AttachmentItem/AttachmentField.js.map +1 -0
  7. package/lib/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.d.ts +14 -0
  8. package/lib/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.js +34 -0
  9. package/lib/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.js.map +1 -0
  10. package/lib/components/FormComponents/AttachmentItem/AttachmentFileCollector.d.ts +8 -0
  11. package/lib/components/FormComponents/AttachmentItem/AttachmentFileCollector.js +61 -0
  12. package/lib/components/FormComponents/AttachmentItem/AttachmentFileCollector.js.map +1 -0
  13. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.d.ts +11 -0
  14. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.js +49 -0
  15. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.js.map +1 -0
  16. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.styles.d.ts +7 -0
  17. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.styles.js +30 -0
  18. package/lib/components/FormComponents/AttachmentItem/AttachmentFileDropBox.styles.js.map +1 -0
  19. package/lib/components/FormComponents/AttachmentItem/AttachmentItem.d.ts +14 -0
  20. package/lib/components/FormComponents/AttachmentItem/AttachmentItem.js +86 -0
  21. package/lib/components/FormComponents/AttachmentItem/AttachmentItem.js.map +1 -0
  22. package/lib/components/FormComponents/AttachmentItem/AttachmentUrlField.d.ts +10 -0
  23. package/lib/components/FormComponents/AttachmentItem/AttachmentUrlField.js +39 -0
  24. package/lib/components/FormComponents/AttachmentItem/AttachmentUrlField.js.map +1 -0
  25. package/lib/components/FormComponents/BooleanItem/BooleanItem.js +1 -3
  26. package/lib/components/FormComponents/BooleanItem/BooleanItem.js.map +1 -1
  27. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.d.ts +1 -1
  28. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js +2 -2
  29. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js.map +1 -1
  30. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.js +1 -3
  31. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.js.map +1 -1
  32. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js +2 -2
  33. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.js.map +1 -1
  34. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.d.ts +2 -1
  35. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js +6 -3
  36. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.js.map +1 -1
  37. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js +5 -5
  38. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.js.map +1 -1
  39. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js +1 -3
  40. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.js.map +1 -1
  41. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.d.ts +2 -1
  42. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +6 -3
  43. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  44. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js +4 -6
  45. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.js.map +1 -1
  46. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +2 -1
  47. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
  48. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js +1 -3
  49. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.js.map +1 -1
  50. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.d.ts +2 -1
  51. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js +8 -5
  52. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js.map +1 -1
  53. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.js +4 -6
  54. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.js.map +1 -1
  55. package/lib/components/FormComponents/CustomDateItem/CustomDateItem.js +2 -2
  56. package/lib/components/FormComponents/CustomDateItem/CustomDateItem.js.map +1 -1
  57. package/lib/components/FormComponents/DateItem/DateField.js +2 -1
  58. package/lib/components/FormComponents/DateItem/DateField.js.map +1 -1
  59. package/lib/components/FormComponents/DateItem/DateItem.js +2 -2
  60. package/lib/components/FormComponents/DateItem/DateItem.js.map +1 -1
  61. package/lib/components/FormComponents/DateTimeItem/DateTimeField.js +2 -1
  62. package/lib/components/FormComponents/DateTimeItem/DateTimeField.js.map +1 -1
  63. package/lib/components/FormComponents/DateTimeItem/DateTimeItem.js +2 -2
  64. package/lib/components/FormComponents/DateTimeItem/DateTimeItem.js.map +1 -1
  65. package/lib/components/FormComponents/DecimalItem/DecimalItem.js +2 -2
  66. package/lib/components/FormComponents/DecimalItem/DecimalItem.js.map +1 -1
  67. package/lib/components/FormComponents/IntegerItem/IntegerItem.js +2 -2
  68. package/lib/components/FormComponents/IntegerItem/IntegerItem.js.map +1 -1
  69. package/lib/components/FormComponents/ItemParts/ItemFieldGrid.d.ts +1 -3
  70. package/lib/components/FormComponents/ItemParts/ItemFieldGrid.js +9 -10
  71. package/lib/components/FormComponents/ItemParts/ItemFieldGrid.js.map +1 -1
  72. package/lib/components/FormComponents/ItemParts/ItemLabelText.js +1 -1
  73. package/lib/components/FormComponents/ItemParts/ItemLabelText.js.map +1 -1
  74. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js +20 -1
  75. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js.map +1 -1
  76. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js +2 -2
  77. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js.map +1 -1
  78. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js +1 -3
  79. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js.map +1 -1
  80. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js +2 -2
  81. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.js.map +1 -1
  82. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js +1 -3
  83. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.js.map +1 -1
  84. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js +2 -2
  85. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js.map +1 -1
  86. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.js +1 -3
  87. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.js.map +1 -1
  88. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.d.ts +2 -1
  89. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js +7 -4
  90. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js.map +1 -1
  91. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.js +4 -6
  92. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.js.map +1 -1
  93. package/lib/components/FormComponents/RepeatItem/RepeatItem.js +1 -3
  94. package/lib/components/FormComponents/RepeatItem/RepeatItem.js.map +1 -1
  95. package/lib/components/FormComponents/SingleItem/SingleItemSwitcher.js +28 -16
  96. package/lib/components/FormComponents/SingleItem/SingleItemSwitcher.js.map +1 -1
  97. package/lib/components/FormComponents/SliderItem/SliderField.js +2 -1
  98. package/lib/components/FormComponents/SliderItem/SliderField.js.map +1 -1
  99. package/lib/components/FormComponents/SliderItem/SliderItem.js +1 -3
  100. package/lib/components/FormComponents/SliderItem/SliderItem.js.map +1 -1
  101. package/lib/components/FormComponents/StringItem/StringItem.js +2 -2
  102. package/lib/components/FormComponents/StringItem/StringItem.js.map +1 -1
  103. package/lib/components/FormComponents/TextItem/TextItem.js +2 -2
  104. package/lib/components/FormComponents/TextItem/TextItem.js.map +1 -1
  105. package/lib/components/FormComponents/Textfield.styles.d.ts +1 -0
  106. package/lib/components/FormComponents/Textfield.styles.js +2 -1
  107. package/lib/components/FormComponents/Textfield.styles.js.map +1 -1
  108. package/lib/components/FormComponents/TimeItem/TimeField.js +2 -1
  109. package/lib/components/FormComponents/TimeItem/TimeField.js.map +1 -1
  110. package/lib/components/FormComponents/TimeItem/TimeItem.js +2 -2
  111. package/lib/components/FormComponents/TimeItem/TimeItem.js.map +1 -1
  112. package/lib/components/FormComponents/UrlItem/UrlItem.js +2 -2
  113. package/lib/components/FormComponents/UrlItem/UrlItem.js.map +1 -1
  114. package/lib/hooks/UseFileDrop.d.ts +10 -0
  115. package/lib/hooks/UseFileDrop.js +40 -0
  116. package/lib/hooks/UseFileDrop.js.map +1 -0
  117. package/lib/hooks/useAttachmentUrlValidation.d.ts +2 -0
  118. package/lib/{components/FormComponents/ItemParts/ItemExtensionLabels.js → hooks/useAttachmentUrlValidation.js} +9 -12
  119. package/lib/hooks/useAttachmentUrlValidation.js.map +1 -0
  120. package/lib/hooks/useRenderingExtensions.d.ts +1 -0
  121. package/lib/hooks/useRenderingExtensions.js +2 -1
  122. package/lib/hooks/useRenderingExtensions.js.map +1 -1
  123. package/lib/hooks/useValueSetCodings.d.ts +5 -1
  124. package/lib/hooks/useValueSetCodings.js +1 -1
  125. package/lib/hooks/useValueSetCodings.js.map +1 -1
  126. package/lib/setup-jest.js +1 -0
  127. package/lib/stories/MedicalHistoryTable.stories.js +45 -0
  128. package/lib/stories/SmartFormsRenderer.stories.js +117 -0
  129. package/lib/utils/fileUtils.d.ts +3 -0
  130. package/lib/utils/fileUtils.js +64 -0
  131. package/lib/utils/fileUtils.js.map +1 -0
  132. package/lib/utils/itemControl.d.ts +6 -0
  133. package/lib/utils/itemControl.js +15 -0
  134. package/lib/utils/itemControl.js.map +1 -1
  135. package/lib/utils/validateQuestionnaire.d.ts +3 -5
  136. package/lib/utils/validateQuestionnaire.js +8 -5
  137. package/lib/utils/validateQuestionnaire.js.map +1 -1
  138. package/package.json +3 -1
  139. package/src/components/Box.styles.ts +1 -31
  140. package/src/components/FormComponents/AttachmentItem/AttachmentField.tsx +96 -0
  141. package/src/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.tsx +87 -0
  142. package/src/components/FormComponents/AttachmentItem/AttachmentFileCollector.tsx +101 -0
  143. package/src/components/FormComponents/AttachmentItem/AttachmentFileDropBox.styles.ts +31 -0
  144. package/src/components/FormComponents/AttachmentItem/AttachmentFileDropBox.tsx +66 -0
  145. package/src/components/FormComponents/AttachmentItem/AttachmentItem.tsx +123 -0
  146. package/src/components/FormComponents/AttachmentItem/AttachmentUrlField.tsx +78 -0
  147. package/src/components/FormComponents/BooleanItem/BooleanItem.tsx +1 -7
  148. package/src/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.tsx +3 -3
  149. package/src/components/FormComponents/ChoiceItems/ChoiceAutocompleteItem.tsx +1 -7
  150. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerOptionItem.tsx +2 -6
  151. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetFields.tsx +6 -4
  152. package/src/components/FormComponents/ChoiceItems/ChoiceCheckboxAnswerValueSetItem.tsx +5 -9
  153. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionItem.tsx +1 -7
  154. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +7 -4
  155. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetItem.tsx +4 -10
  156. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +2 -1
  157. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionItem.tsx +1 -7
  158. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.tsx +9 -6
  159. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetItem.tsx +4 -10
  160. package/src/components/FormComponents/CustomDateItem/CustomDateItem.tsx +2 -7
  161. package/src/components/FormComponents/DateItem/DateField.tsx +2 -1
  162. package/src/components/FormComponents/DateItem/DateItem.tsx +2 -7
  163. package/src/components/FormComponents/DateTimeItem/DateTimeField.tsx +2 -1
  164. package/src/components/FormComponents/DateTimeItem/DateTimeItem.tsx +2 -7
  165. package/src/components/FormComponents/DecimalItem/DecimalItem.tsx +3 -15
  166. package/src/components/FormComponents/IntegerItem/IntegerItem.tsx +3 -15
  167. package/src/components/FormComponents/ItemParts/ItemFieldGrid.tsx +13 -16
  168. package/src/components/FormComponents/ItemParts/ItemLabelText.tsx +1 -1
  169. package/src/components/FormComponents/ItemParts/ItemLabelWrapper.tsx +30 -1
  170. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.tsx +2 -2
  171. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.tsx +1 -7
  172. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceCheckboxAnswerOptionItem.tsx +2 -6
  173. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionItem.tsx +1 -7
  174. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.tsx +2 -2
  175. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionItem.tsx +1 -7
  176. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.tsx +9 -6
  177. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetItem.tsx +4 -10
  178. package/src/components/FormComponents/RepeatItem/RepeatItem.tsx +1 -7
  179. package/src/components/FormComponents/SingleItem/SingleItemSwitcher.tsx +67 -31
  180. package/src/components/FormComponents/SliderItem/SliderField.tsx +2 -1
  181. package/src/components/FormComponents/SliderItem/SliderItem.tsx +1 -7
  182. package/src/components/FormComponents/StringItem/StringItem.tsx +3 -15
  183. package/src/components/FormComponents/TextItem/TextItem.tsx +3 -15
  184. package/src/components/FormComponents/Textfield.styles.ts +3 -1
  185. package/src/components/FormComponents/TimeItem/TimeField.tsx +2 -1
  186. package/src/components/FormComponents/TimeItem/TimeItem.tsx +2 -7
  187. package/src/components/FormComponents/UrlItem/UrlItem.tsx +3 -15
  188. package/src/hooks/UseFileDrop.ts +53 -0
  189. package/src/{components/FormComponents/ItemParts/ItemExtensionLabels.tsx → hooks/useAttachmentUrlValidation.ts} +7 -22
  190. package/src/hooks/useRenderingExtensions.ts +3 -0
  191. package/src/hooks/useValueSetCodings.ts +10 -2
  192. package/src/utils/fileUtils.ts +66 -0
  193. package/src/utils/itemControl.ts +16 -0
  194. package/src/utils/validateQuestionnaire.ts +17 -13
  195. package/lib/components/FormComponents/ItemParts/ItemExtensionLabels.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import Autocomplete from '@mui/material/Autocomplete';
3
- import { StandardTextField } from '../Textfield.styles';
3
+ import { StandardTextField, TEXT_FIELD_WIDTH } from '../Textfield.styles';
4
4
  import Typography from '@mui/material/Typography';
5
5
  import type {
6
6
  PropsWithIsTabledAttribute,
@@ -8,6 +8,7 @@ import type {
8
8
  } from '../../../interfaces/renderProps.interface';
9
9
  import type { Coding, QuestionnaireItem } from 'fhir/r4';
10
10
  import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
11
+ import type { TerminologyError } from '../../../hooks/useValueSetCodings';
11
12
 
12
13
  interface OpenChoiceSelectAnswerValueSetFieldProps
13
14
  extends PropsWithIsTabledAttribute,
@@ -15,13 +16,14 @@ interface OpenChoiceSelectAnswerValueSetFieldProps
15
16
  qItem: QuestionnaireItem;
16
17
  options: Coding[];
17
18
  valueSelect: Coding | null;
18
- serverError: Error | null;
19
+ terminologyError: TerminologyError;
19
20
  readOnly: boolean;
20
21
  onValueChange: (newValue: Coding | string | null) => void;
21
22
  }
22
23
 
23
24
  function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueSetFieldProps) {
24
- const { qItem, options, valueSelect, serverError, readOnly, isTabled, onValueChange } = props;
25
+ const { qItem, options, valueSelect, terminologyError, readOnly, isTabled, onValueChange } =
26
+ props;
25
27
 
26
28
  const { displayUnit, displayPrompt, entryFormat } = useRenderingExtensions(qItem);
27
29
 
@@ -36,7 +38,7 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
36
38
  onInputChange={(_, newValue) => onValueChange(newValue)}
37
39
  freeSolo
38
40
  autoHighlight
39
- sx={{ maxWidth: !isTabled ? 280 : 3000, minWidth: 160, flexGrow: 1 }}
41
+ sx={{ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160, flexGrow: 1 }}
40
42
  disabled={readOnly}
41
43
  size="small"
42
44
  renderInput={(params) => (
@@ -57,9 +59,10 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
57
59
  />
58
60
  )}
59
61
  />
60
- {serverError ? (
62
+ {terminologyError.error ? (
61
63
  <Typography variant="subtitle2">
62
- There was an error fetching options from the terminology server.
64
+ There was an error fetching options from the terminology server for{' '}
65
+ {terminologyError.answerValueSet}
63
66
  </Typography>
64
67
  ) : null}
65
68
  </>
@@ -20,7 +20,6 @@ import type { Coding, QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/
20
20
  import { createEmptyQrItem } from '../../../utils/qrItem';
21
21
  import { FullWidthFormComponentBox } from '../../Box.styles';
22
22
  import useValueSetCodings from '../../../hooks/useValueSetCodings';
23
- import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
24
23
  import type {
25
24
  PropsWithIsRepeatedAttribute,
26
25
  PropsWithIsTabledAttribute,
@@ -44,7 +43,6 @@ function OpenChoiceSelectAnswerValueSetItem(props: OpenChoiceSelectAnswerValueSe
44
43
  const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
45
44
 
46
45
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
47
- const { displayInstructions, required } = useRenderingExtensions(qItem);
48
46
 
49
47
  // Init input value
50
48
  const qrOpenChoice = qrItem ?? createEmptyQrItem(qItem);
@@ -54,7 +52,7 @@ function OpenChoiceSelectAnswerValueSetItem(props: OpenChoiceSelectAnswerValueSe
54
52
  }
55
53
 
56
54
  // Get codings/options from valueSet
57
- const { codings, serverError } = useValueSetCodings(qItem);
55
+ const { codings, terminologyError } = useValueSetCodings(qItem);
58
56
 
59
57
  // Event handlers
60
58
  function handleValueChange(newValue: Coding | string | null) {
@@ -81,7 +79,7 @@ function OpenChoiceSelectAnswerValueSetItem(props: OpenChoiceSelectAnswerValueSe
81
79
  qItem={qItem}
82
80
  options={codings}
83
81
  valueSelect={valueSelect}
84
- serverError={serverError}
82
+ terminologyError={terminologyError}
85
83
  isTabled={isTabled}
86
84
  readOnly={readOnly}
87
85
  onValueChange={handleValueChange}
@@ -91,16 +89,12 @@ function OpenChoiceSelectAnswerValueSetItem(props: OpenChoiceSelectAnswerValueSe
91
89
 
92
90
  return (
93
91
  <FullWidthFormComponentBox>
94
- <ItemFieldGrid
95
- qItem={qItem}
96
- displayInstructions={displayInstructions}
97
- required={required}
98
- readOnly={readOnly}>
92
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
99
93
  <OpenChoiceSelectAnswerValueSetField
100
94
  qItem={qItem}
101
95
  options={codings}
102
96
  valueSelect={valueSelect}
103
- serverError={serverError}
97
+ terminologyError={terminologyError}
104
98
  isTabled={isTabled}
105
99
  readOnly={readOnly}
106
100
  onValueChange={handleValueChange}
@@ -23,7 +23,6 @@ import type {
23
23
  } from '../../../interfaces/renderProps.interface';
24
24
  import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
25
25
  import { nanoid } from 'nanoid';
26
- import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
27
26
  import { createEmptyQrItem } from '../../../utils/qrItem';
28
27
  import { FullWidthFormComponentBox } from '../../Box.styles';
29
28
  import AddItemButton from './AddItemButton';
@@ -46,7 +45,6 @@ function RepeatItem(props: RepeatItemProps) {
46
45
  const { qItem, qrItem, showMinimalView, parentIsReadOnly, onQrItemChange } = props;
47
46
 
48
47
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
49
- const { displayInstructions, required } = useRenderingExtensions(qItem);
50
48
 
51
49
  const initialRepeatAnswers = useInitialiseRepeatAnswers(qItem, qrItem);
52
50
 
@@ -119,11 +117,7 @@ function RepeatItem(props: RepeatItemProps) {
119
117
 
120
118
  return (
121
119
  <FullWidthFormComponentBox data-test="q-item-repeat-box">
122
- <ItemFieldGrid
123
- qItem={qItem}
124
- displayInstructions={displayInstructions}
125
- required={required}
126
- readOnly={readOnly}>
120
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
127
121
  <TransitionGroup>
128
122
  {repeatAnswers.map(({ nanoId, answer }, index) => {
129
123
  const repeatAnswerQrItem = createEmptyQrItem(qItem);
@@ -39,6 +39,7 @@ import CustomDateItem from '../CustomDateItem/CustomDateItem';
39
39
  import { isSpecificItemControl } from '../../../utils';
40
40
  import SliderItem from '../SliderItem/SliderItem';
41
41
  import IntegerItem from '../IntegerItem/IntegerItem';
42
+ import AttachmentItem from '../AttachmentItem/AttachmentItem';
42
43
 
43
44
  interface SingleItemSwitcherProps
44
45
  extends PropsWithQrItemChangeHandler,
@@ -55,9 +56,11 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
55
56
  props;
56
57
 
57
58
  switch (qItem.type) {
58
- case 'string':
59
+ case 'display':
60
+ return <DisplayItem qItem={qItem} />;
61
+ case 'boolean':
59
62
  return (
60
- <StringItem
63
+ <BooleanItem
61
64
  qItem={qItem}
62
65
  qrItem={qrItem}
63
66
  isRepeated={isRepeated}
@@ -66,9 +69,9 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
66
69
  onQrItemChange={onQrItemChange}
67
70
  />
68
71
  );
69
- case 'boolean':
72
+ case 'decimal':
70
73
  return (
71
- <BooleanItem
74
+ <DecimalItem
72
75
  qItem={qItem}
73
76
  qrItem={qrItem}
74
77
  isRepeated={isRepeated}
@@ -77,9 +80,22 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
77
80
  onQrItemChange={onQrItemChange}
78
81
  />
79
82
  );
80
- case 'time':
83
+ case 'integer':
84
+ if (isSpecificItemControl(qItem, 'slider')) {
85
+ return (
86
+ <SliderItem
87
+ qItem={qItem}
88
+ qrItem={qrItem}
89
+ isRepeated={isRepeated}
90
+ isTabled={isTabled}
91
+ parentIsReadOnly={parentIsReadOnly}
92
+ onQrItemChange={onQrItemChange}
93
+ />
94
+ );
95
+ }
96
+
81
97
  return (
82
- <TimeItem
98
+ <IntegerItem
83
99
  qItem={qItem}
84
100
  qrItem={qrItem}
85
101
  isRepeated={isRepeated}
@@ -110,34 +126,20 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
110
126
  onQrItemChange={onQrItemChange}
111
127
  />
112
128
  );
113
- case 'text':
129
+ case 'time':
114
130
  return (
115
- <TextItem
131
+ <TimeItem
116
132
  qItem={qItem}
117
133
  qrItem={qrItem}
118
134
  isRepeated={isRepeated}
135
+ isTabled={isTabled}
119
136
  parentIsReadOnly={parentIsReadOnly}
120
137
  onQrItemChange={onQrItemChange}
121
138
  />
122
139
  );
123
- case 'display':
124
- return <DisplayItem qItem={qItem} />;
125
- case 'integer':
126
- if (isSpecificItemControl(qItem, 'slider')) {
127
- return (
128
- <SliderItem
129
- qItem={qItem}
130
- qrItem={qrItem}
131
- isRepeated={isRepeated}
132
- isTabled={isTabled}
133
- parentIsReadOnly={parentIsReadOnly}
134
- onQrItemChange={onQrItemChange}
135
- />
136
- );
137
- }
138
-
140
+ case 'string':
139
141
  return (
140
- <IntegerItem
142
+ <StringItem
141
143
  qItem={qItem}
142
144
  qrItem={qrItem}
143
145
  isRepeated={isRepeated}
@@ -146,9 +148,19 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
146
148
  onQrItemChange={onQrItemChange}
147
149
  />
148
150
  );
149
- case 'decimal':
151
+ case 'text':
150
152
  return (
151
- <DecimalItem
153
+ <TextItem
154
+ qItem={qItem}
155
+ qrItem={qrItem}
156
+ isRepeated={isRepeated}
157
+ parentIsReadOnly={parentIsReadOnly}
158
+ onQrItemChange={onQrItemChange}
159
+ />
160
+ );
161
+ case 'url':
162
+ return (
163
+ <UrlItem
152
164
  qItem={qItem}
153
165
  qrItem={qrItem}
154
166
  isRepeated={isRepeated}
@@ -181,9 +193,33 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
181
193
  onQrItemChange={onQrItemChange}
182
194
  />
183
195
  );
184
- case 'url':
196
+ case 'attachment':
185
197
  return (
186
- <UrlItem
198
+ <AttachmentItem
199
+ qItem={qItem}
200
+ qrItem={qrItem}
201
+ isRepeated={isRepeated}
202
+ isTabled={isTabled}
203
+ parentIsReadOnly={parentIsReadOnly}
204
+ onQrItemChange={onQrItemChange}
205
+ />
206
+ );
207
+ case 'reference':
208
+ // FIXME reference item uses the same component as string item currently
209
+ return (
210
+ <StringItem
211
+ qItem={qItem}
212
+ qrItem={qrItem}
213
+ isRepeated={isRepeated}
214
+ isTabled={isTabled}
215
+ parentIsReadOnly={parentIsReadOnly}
216
+ onQrItemChange={onQrItemChange}
217
+ />
218
+ );
219
+ case 'quantity':
220
+ // FIXME quantity item uses the same component as decimal item currently
221
+ return (
222
+ <DecimalItem
187
223
  qItem={qItem}
188
224
  qrItem={qrItem}
189
225
  isRepeated={isRepeated}
@@ -195,8 +231,8 @@ function SingleItemSwitcher(props: SingleItemSwitcherProps) {
195
231
  default:
196
232
  return (
197
233
  <Typography>
198
- Item type not supported yet, or something has went wrong. If your questionnnaire is not a
199
- FHIR R4 resource, there might be issues rendering it.
234
+ Item type <b>{qItem.type}</b> not supported yet, or something has went wrong. If your
235
+ questionnnaire is not a FHIR R4 resource, there might be issues rendering it.
200
236
  </Typography>
201
237
  );
202
238
  }
@@ -22,6 +22,7 @@ import { getSliderMarks } from '../../../utils/slider';
22
22
  import Stack from '@mui/material/Stack';
23
23
  import SliderLabels from './SliderLabels';
24
24
  import SliderDisplayValue from './SliderDisplayValue';
25
+ import { TEXT_FIELD_WIDTH } from '../Textfield.styles';
25
26
 
26
27
  interface SliderFieldProps extends PropsWithIsTabledAttribute {
27
28
  linkId: string;
@@ -54,7 +55,7 @@ function SliderField(props: SliderFieldProps) {
54
55
  const sliderMarks = getSliderMarks(minValue, maxValue, minLabel, maxLabel, stepValue);
55
56
 
56
57
  const sliderSx = {
57
- maxWidth: !isTabled ? 280 : 3000,
58
+ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000,
58
59
  minWidth: 160
59
60
  };
60
61
 
@@ -23,7 +23,6 @@ import type {
23
23
  PropsWithQrItemChangeHandler
24
24
  } from '../../../interfaces/renderProps.interface';
25
25
  import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
26
- import useRenderingExtensions from '../../../hooks/useRenderingExtensions';
27
26
  import { createEmptyQrItem } from '../../../utils/qrItem';
28
27
  import { FullWidthFormComponentBox } from '../../Box.styles';
29
28
  import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
@@ -45,7 +44,6 @@ function SliderItem(props: SliderItemProps) {
45
44
  const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
46
45
 
47
46
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
48
- const { displayInstructions, required } = useRenderingExtensions(qItem);
49
47
  const { minValue, maxValue, stepValue, minLabel, maxLabel } = useSliderExtensions(qItem);
50
48
 
51
49
  const isInteracted = !!qrItem?.answer;
@@ -91,11 +89,7 @@ function SliderItem(props: SliderItemProps) {
91
89
 
92
90
  return (
93
91
  <FullWidthFormComponentBox data-test="q-item-slider-box">
94
- <ItemFieldGrid
95
- qItem={qItem}
96
- displayInstructions={displayInstructions}
97
- required={required}
98
- readOnly={readOnly}>
92
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
99
93
  <Box px={4}>
100
94
  <SliderField
101
95
  linkId={qItem.linkId}
@@ -47,16 +47,8 @@ function StringItem(props: StringItemProps) {
47
47
  const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
48
48
 
49
49
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
50
- const {
51
- displayUnit,
52
- displayPrompt,
53
- displayInstructions,
54
- entryFormat,
55
- required,
56
- regexValidation,
57
- minLength,
58
- maxLength
59
- } = useRenderingExtensions(qItem);
50
+ const { displayUnit, displayPrompt, entryFormat, regexValidation, minLength, maxLength } =
51
+ useRenderingExtensions(qItem);
60
52
 
61
53
  // Init input value
62
54
  let valueString = '';
@@ -115,11 +107,7 @@ function StringItem(props: StringItemProps) {
115
107
  }
116
108
  return (
117
109
  <FullWidthFormComponentBox data-test="q-item-string-box">
118
- <ItemFieldGrid
119
- qItem={qItem}
120
- displayInstructions={displayInstructions}
121
- required={required}
122
- readOnly={readOnly}>
110
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
123
111
  <StringField
124
112
  linkId={qItem.linkId}
125
113
  input={input}
@@ -46,16 +46,8 @@ function TextItem(props: TextItemProps) {
46
46
  const { qItem, qrItem, isRepeated, parentIsReadOnly, onQrItemChange } = props;
47
47
 
48
48
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
49
- const {
50
- displayUnit,
51
- displayPrompt,
52
- displayInstructions,
53
- entryFormat,
54
- required,
55
- regexValidation,
56
- minLength,
57
- maxLength
58
- } = useRenderingExtensions(qItem);
49
+ const { displayUnit, displayPrompt, entryFormat, regexValidation, minLength, maxLength } =
50
+ useRenderingExtensions(qItem);
59
51
 
60
52
  // Init input value
61
53
  let valueText = '';
@@ -113,11 +105,7 @@ function TextItem(props: TextItemProps) {
113
105
  }
114
106
  return (
115
107
  <FullWidthFormComponentBox data-test="q-item-text-box">
116
- <ItemFieldGrid
117
- qItem={qItem}
118
- displayInstructions={displayInstructions}
119
- required={required}
120
- readOnly={readOnly}>
108
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
121
109
  <TextField
122
110
  linkId={qItem.linkId}
123
111
  input={input}
@@ -18,12 +18,14 @@
18
18
  import { styled } from '@mui/material/styles';
19
19
  import TextField from '@mui/material/TextField';
20
20
 
21
+ export const TEXT_FIELD_WIDTH = 320;
22
+
21
23
  // Always use this accompanied by the TextField prop fullWidth
22
24
  export const StandardTextField = styled(TextField, {
23
25
  shouldForwardProp: (prop) => prop !== 'isTabled'
24
26
  })<{ isTabled: boolean }>(({ isTabled }) => ({
25
27
  // Set 280 as the standard width for a field
26
28
  // Set a theoretical infinite maxWidth if field is within a table to fill the table row
27
- maxWidth: !isTabled ? 280 : 3000,
29
+ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000,
28
30
  minWidth: 160
29
31
  }));
@@ -20,6 +20,7 @@ import type { PropsWithIsTabledAttribute } from '../../../interfaces/renderProps
20
20
  import type { Dayjs } from 'dayjs';
21
21
  import { LocalizationProvider, TimePicker as MuiTimePicker } from '@mui/x-date-pickers';
22
22
  import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
23
+ import { TEXT_FIELD_WIDTH } from '../Textfield.styles';
23
24
 
24
25
  interface TimeFieldProps extends PropsWithIsTabledAttribute {
25
26
  value: Dayjs | null;
@@ -39,7 +40,7 @@ function TimeField(props: TimeFieldProps) {
39
40
  value={value}
40
41
  disabled={readOnly}
41
42
  label={displayPrompt}
42
- sx={{ maxWidth: !isTabled ? 280 : 3000, minWidth: 160 }}
43
+ sx={{ maxWidth: !isTabled ? TEXT_FIELD_WIDTH : 3000, minWidth: 160 }}
43
44
  slotProps={{
44
45
  textField: {
45
46
  fullWidth: true
@@ -45,8 +45,7 @@ function TimeItem(props: TimeItemProps) {
45
45
  const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
46
46
 
47
47
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
48
- const { displayPrompt, displayInstructions, entryFormat, required } =
49
- useRenderingExtensions(qItem);
48
+ const { displayPrompt, entryFormat } = useRenderingExtensions(qItem);
50
49
 
51
50
  // Init input value
52
51
  let timeString: string | null = null;
@@ -80,11 +79,7 @@ function TimeItem(props: TimeItemProps) {
80
79
 
81
80
  return (
82
81
  <FullWidthFormComponentBox>
83
- <ItemFieldGrid
84
- qItem={qItem}
85
- displayInstructions={displayInstructions}
86
- required={required}
87
- readOnly={readOnly}>
82
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
88
83
  <TimeField
89
84
  value={timeDayJs}
90
85
  displayPrompt={displayPrompt}
@@ -45,16 +45,8 @@ function UrlItem(props: UrlItemProps) {
45
45
  const { qItem, qrItem, isRepeated, isTabled, parentIsReadOnly, onQrItemChange } = props;
46
46
 
47
47
  const readOnly = useReadOnly(qItem, parentIsReadOnly);
48
- const {
49
- displayUnit,
50
- displayPrompt,
51
- displayInstructions,
52
- entryFormat,
53
- required,
54
- regexValidation,
55
- minLength,
56
- maxLength
57
- } = useRenderingExtensions(qItem);
48
+ const { displayUnit, displayPrompt, entryFormat, regexValidation, minLength, maxLength } =
49
+ useRenderingExtensions(qItem);
58
50
 
59
51
  // Init input value
60
52
  let valueUri = '';
@@ -102,11 +94,7 @@ function UrlItem(props: UrlItemProps) {
102
94
  }
103
95
  return (
104
96
  <FullWidthFormComponentBox data-test="q-item-string-box">
105
- <ItemFieldGrid
106
- qItem={qItem}
107
- displayInstructions={displayInstructions}
108
- required={required}
109
- readOnly={readOnly}>
97
+ <ItemFieldGrid qItem={qItem} readOnly={readOnly}>
110
98
  <UrlField
111
99
  linkId={qItem.linkId}
112
100
  input={input}
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright 2024 Commonwealth Scientific and Industrial Research
3
+ * Organisation (CSIRO) ABN 41 687 119 230.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ import type { ConnectDropTarget, DropTargetMonitor } from 'react-dnd';
19
+ import { useDrop } from 'react-dnd';
20
+ import { NativeTypes } from 'react-dnd-html5-backend';
21
+
22
+ interface UseFileDrop {
23
+ canDrop: boolean;
24
+ isOver: boolean;
25
+ dropTarget: ConnectDropTarget;
26
+ }
27
+
28
+ function UseFileDrop(onDrop: (item: { files: any[] }) => void): UseFileDrop {
29
+ const [{ canDrop, isOver }, drop] = useDrop(
30
+ () => ({
31
+ accept: [NativeTypes.FILE],
32
+ drop(item: { files: any[] }) {
33
+ if (onDrop) {
34
+ onDrop(item);
35
+ }
36
+ },
37
+ canDrop() {
38
+ return true;
39
+ },
40
+ collect: (monitor: DropTargetMonitor) => {
41
+ return {
42
+ isOver: monitor.isOver(),
43
+ canDrop: monitor.canDrop()
44
+ };
45
+ }
46
+ }),
47
+ [onDrop]
48
+ );
49
+
50
+ return { canDrop, isOver, dropTarget: drop };
51
+ }
52
+
53
+ export default UseFileDrop;
@@ -15,28 +15,13 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- import React from 'react';
19
- import { ReadOnlyLabel, RequiredLabel } from '../../Box.styles';
20
- import Box from '@mui/material/Box';
21
-
22
- interface ItemExtensionLabelsProps {
23
- required: boolean;
24
- readOnly: boolean;
25
- }
26
-
27
- function ItemExtensionLabels(props: ItemExtensionLabelsProps) {
28
- const { required, readOnly } = props;
29
-
30
- if (!required && !readOnly) {
31
- return null;
18
+ function useAttachmentUrlValidation(url: string): boolean {
19
+ try {
20
+ new URL(url);
21
+ return true;
22
+ } catch (error) {
23
+ return false;
32
24
  }
33
-
34
- return (
35
- <Box display="flex" columnGap={0.5}>
36
- {required ? <RequiredLabel>Required</RequiredLabel> : null}
37
- {readOnly ? <ReadOnlyLabel>Read-only</ReadOnlyLabel> : null}
38
- </Box>
39
- );
40
25
  }
41
26
 
42
- export default ItemExtensionLabels;
27
+ export default useAttachmentUrlValidation;
@@ -17,6 +17,7 @@
17
17
 
18
18
  import {
19
19
  getRegexValidation,
20
+ getTextDisplayFlyover,
20
21
  getTextDisplayInstructions,
21
22
  getTextDisplayPrompt,
22
23
  getTextDisplayUnit
@@ -30,6 +31,7 @@ interface RenderingExtensions {
30
31
  displayUnit: string;
31
32
  displayPrompt: string;
32
33
  displayInstructions: string;
34
+ displayFlyover: string;
33
35
  readOnly: boolean;
34
36
  entryFormat: string;
35
37
  required: boolean;
@@ -44,6 +46,7 @@ function useRenderingExtensions(qItem: QuestionnaireItem): RenderingExtensions {
44
46
  displayUnit: getTextDisplayUnit(qItem),
45
47
  displayPrompt: getTextDisplayPrompt(qItem),
46
48
  displayInstructions: getTextDisplayInstructions(qItem),
49
+ displayFlyover: getTextDisplayFlyover(qItem),
47
50
  readOnly: !!qItem.readOnly,
48
51
  entryFormat: structuredDataCapture.getEntryFormat(qItem) ?? '',
49
52
  required: qItem.required ?? false,
@@ -28,7 +28,15 @@ import fhirpath from 'fhirpath';
28
28
  import fhirpath_r4_model from 'fhirpath/fhir-context/r4';
29
29
  import { useQuestionnaireStore, useSmartConfigStore, useTerminologyServerStore } from '../stores';
30
30
 
31
- function useValueSetCodings(qItem: QuestionnaireItem) {
31
+ export interface TerminologyError {
32
+ error: Error | null;
33
+ answerValueSet: string;
34
+ }
35
+
36
+ function useValueSetCodings(qItem: QuestionnaireItem): {
37
+ codings: Coding[];
38
+ terminologyError: TerminologyError;
39
+ } {
32
40
  const patient = useSmartConfigStore.use.patient();
33
41
  const user = useSmartConfigStore.use.user();
34
42
  const encounter = useSmartConfigStore.use.encounter();
@@ -145,7 +153,7 @@ function useValueSetCodings(qItem: QuestionnaireItem) {
145
153
  }
146
154
  }, [qItem]);
147
155
 
148
- return { codings, serverError };
156
+ return { codings, terminologyError: { error: serverError, answerValueSet: valueSetUrl ?? '' } };
149
157
  }
150
158
 
151
159
  export default useValueSetCodings;